Skip to content
On this page

画指北针

下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中画指北针的功能,该功能中用户点击画布确定指北针的位置,移动鼠标确定指针位置和文字标注位。

功能实现

  1. 实现自定义指北针类

为了方便后期管理与修改指北针设置,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现自定义指北针类。然后,我们可以利用 McDbMTextMcDbText 构造指针信息文本对象,将指针信息绘制在页面中。

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;
    }
};
  1. 注册自定义类信息
ts
new McDbTestCompass().rxInit();
  1. 编写方法,调用 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);

功能实践

实践效果如下:

  • 点击画指北针按钮,执行画指北针方法
  • 点击画布设置指北针位置
  • 移动鼠标设置指针方向,点击鼠标左键确定指向点
  • 成功绘制指北针