画指北针
下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中画指北针的功能,该功能中用户点击画布确定指北针的位置,移动鼠标确定指针位置和文字标注位。
功能实现
- 实现自定义指北针类
为了方便后期管理与修改指北针设置,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现自定义指北针类。然后,我们可以利用 McDbMText 或 McDbText 构造指针信息文本对象,将指针信息绘制在页面中。
ts
// 指北针类
class McDbTestCompass extends McDbCustomEntity {
// 定义McDbTestCompass内部的点对象
// 位置点
private compassPos: McGePoint3d = new McGePoint3d();
// 指针指向
private pointerPt: McGePoint3d = new McGePoint3d(this.compassPos.x, this.compassPos.y + this.campassRadius);
// 半径
private _campassRadius: number = MxFun.screenCoordLong2Doc(20);
// 字高
private height: number = this._campassRadius / 4;
// 文字位置
private textPos: McGePoint3d = new McGePoint3d();
// 构造函数
constructor(imp?: any) {
super(imp);
}
// 创建函数
public create(imp: any) {
return new McDbTestCompass(imp)
}
// 获取类名
public getTypeName(): string {
return "McDbTestCompass";
}
//设置或获取指针半径
public set campassRadius(val: number) {
this._campassRadius = val;
}
public get campassRadius(): number {
return this._campassRadius;
}
// 读取自定义实体数据
public dwgInFields(filter: IMcDbDwgFiler): boolean {
this.compassPos = filter.readPoint("compassPos").val;
this.pointerPt = filter.readPoint("pointerPt").val;
this.textPos = filter.readPoint("textPos").val;
this._campassRadius = filter.readDouble("campassRadius").val;
this.height = filter.readDouble("height").val;
return true;
}
// 写入自定义实体数据
public dwgOutFields(filter: IMcDbDwgFiler): boolean {
filter.writePoint("pointerPt", this.pointerPt);
filter.writePoint("compassPos", this.compassPos);
filter.writePoint("textPos", this.textPos);
filter.writeDouble("campassRadius", this._campassRadius);
filter.writeDouble("height", this.height);
return true;
}
// 移动自定义对象的夹点
public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
this.assertWrite();
const vec = this.pointerPt.sub(this.compassPos)
const circle = new McDbCircle(this.compassPos.x, this.compassPos.y, this.compassPos.y, this._campassRadius)
if (iIndex === 0) {
this.pointerPt.x += dXOffset;
this.pointerPt.y += dYOffset;
this.pointerPt.z += dZOffset;
this.pointerPt = circle.getClosestPointTo(this.pointerPt, false).val;
const _vec = this.pointerPt.sub(this.compassPos);
const v = this.textPos.sub(this.compassPos);
v.rotateBy(_vec.angleTo2(vec, McGeVector3d.kNegateZAxis));
this.textPos = this.compassPos.clone().addvec(v)
} else if (iIndex === 1) {
this.compassPos.x += dXOffset;
this.compassPos.y += dYOffset;
this.compassPos.z += dZOffset;
this.textPos.x += dXOffset;
this.textPos.y += dYOffset;
this.textPos.z += dZOffset;
this.pointerPt.x += dXOffset;
this.pointerPt.y += dYOffset;
this.pointerPt.z += dZOffset;
} else if (iIndex === 2) {
this.textPos.x += dXOffset;
this.textPos.y += dYOffset;
this.textPos.z += dZOffset;
}
};
// 获取自定义对象的夹点
public getGripPoints(): McGePoint3dArray {
let ret = new McGePoint3dArray()
ret.append(this.pointerPt);
ret.append(this.compassPos);
ret.append(this.textPos);
return ret;
};
// 绘制实体
public worldDraw(draw: MxCADWorldDraw): void {
// 绘制指针圆盘
const circle = new McDbCircle(this.compassPos.x, this.compassPos.y, this.compassPos.z, this.campassRadius);
draw.drawEntity(circle);
// 绘制指针
const vec = this.pointerPt.sub(this.compassPos).normalize().mult(this._campassRadius);
const pt1 = this.compassPos.clone().subvec(vec.rotateBy(Math.PI * (1 / 36)));
const pt2 = this.compassPos.clone().subvec(vec.rotateBy(Math.PI * 2 * (35 / 36)));
const solid = new McDbHatch();
solid.appendLoop(new McGePoint3dArray([pt1, pt2, this.pointerPt]));
draw.drawEntity(solid);
// 绘制指针文本
const text = new McDbText();
text.textString = '北';
text.height = this.height;
text.horizontalMode = McDb.TextHorzMode.kTextCenter;
text.position = text.alignmentPoint = this.textPos;
draw.drawEntity(text);
}
// 设置指北针位置
public setCompassPos(pt: McGePoint3d) {
this.compassPos = pt.clone()
}
// 获取指北针位置
public getCompassPos() {
return this.compassPos;
}
// 设置指向
public setPointerPt(pt: McGePoint3d) {
const circle = new McDbCircle(this.compassPos.x, this.compassPos.y, this.compassPos.z, this._campassRadius);
this.pointerPt = circle.getClosestPointTo(pt, false).val;
const vec = this.pointerPt.sub(this.compassPos).normalize();
this.textPos = this.pointerPt.clone().addvec(vec.mult(this._campassRadius/4))
}
// 获取指向
public getPointerPt() {
return this.pointerPt;
}
};
- 注册自定义类信息
ts
new McDbTestCompass().rxInit();
- 编写方法,调用 McDbTestCompass 自定义指北针类实现引出标注功能
- 设置指北针位置
我们可以利用 MxCADUiPrPoint() 取点对象设置指北针位置。
ts
// 设置指北针方向
const getPoint1 = new MxCADUiPrPoint();
getPoint1.setMessage('请设置指北针位置:');
const pt1 = await getPoint1.go();
if (!pt1) return;
compass.setCompassPos(pt1);
- 设置指针方向 调用 MxCADUiPrPoint 取点对象设置指北针指针指向点所在位置,若用户未设置指向点则默认设置指针指向Y轴正方向。
ts
// 构造指北针实体
const compass = new McDbTestCompass();
// 设置指针方向
const getPoint2 = new MxCADUiPrPoint();
getPoint2.setBasePt(pt1);
getPoint2.setMessage('请设置指北针方向:');
// 动态绘制指针
getPoint2.setUserDraw((pt, pw) => {
const _compass = compass.clone() as McDbTestCompass;
_compass.setPointerPt(pt);
pw.drawMcDbEntity(_compass);
// 绘制指针指向
const line = new McDbLine(pt1.x, pt1.y, pt1.z,pt.x,pt.y,pt.z);
pw.drawMcDbEntity(line);
});
let pt2 = await getPoint2.go();
// 设置默认指向
if(!pt2){
pt2 = pt1.clone().addvec(McGeVector3d.kYAxis.clone().mult(compass.campassRadius));
}
compass.setPointerPt(pt2);
// 绘制指针
MxCpp.getCurrentMxCAD().drawEntity(compass);
功能实践
实践效果如下:
- 点击画指北针按钮,执行画指北针方法
- 点击画布设置指北针位置
- 移动鼠标设置指针方向,点击鼠标左键确定指向点
- 成功绘制指北针