Skip to content
On this page

画对称轴

下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中画对称轴的功能,该功能中用户可设置对称轴长度,点击画布可确定对称轴的起始位置。

功能实现

  1. 实现自定义对称轴类

为了方便后期管理与修改对称轴设置,我们可以通过继承 McDbCustomEntity 自定义实体类来扩展实现自定义对称轴类。

ts
// 对称轴类
class McDbTestAxisOfSymmetry extends McDbCustomEntity {
    // 定义McDbTestAxisOfSymmetry内部的对象 
    // 对称轴开始点
    private startPoint: McGePoint3d = new McGePoint3d();
    // 对称轴结束点
    private endPoint: McGePoint3d = new McGePoint3d();
    // 对称轴标夹点
    private midPt: McGePoint3d = new McGePoint3d();
    private movePt: McGePoint3d = new McGePoint3d();
    private tPoint: McGePoint3d = new McGePoint3d();
    // 对称轴标长度
    private _axisLength: number = 0;

    // 构造函数
    constructor(imp?: any) {
        super(imp);
    }
    // 创建函数
    public create(imp: any) {
        return new McDbTestAxisOfSymmetry(imp)
    }
    // 获取类名
    public getTypeName(): string {
        return "McDbTestAxisOfSymmetry";
    }
    // 读取自定义实体数据
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
        this.startPoint = filter.readPoint("startPoint").val;
        this.endPoint = filter.readPoint("endPoint").val;
        this.midPt = filter.readPoint("midPt").val;
        this.movePt = filter.readPoint("movePt").val;
        this.tPoint = filter.readPoint("tPoint").val;
        this._axisLength = filter.readDouble("axisLength").val;
        return true;
    }
    // 写入自定义实体数据
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
        filter.writePoint("startPoint", this.startPoint);
        filter.writePoint("endPoint", this.endPoint);
        filter.writePoint("midPt", this.midPt);
        filter.writePoint("movePt", this.movePt);
        filter.writePoint("tPoint", this.tPoint);
        filter.writeDouble("axisLength", this._axisLength);
        return true;
    }

    // 移动自定义对象的夹点
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
        this.assertWrite();
        const l1 = this.startPoint.distanceTo(this.midPt)
        const l2 = this.movePt.distanceTo(this.midPt)
        const l3 = this.midPt.distanceTo(this.tPoint)
        if (iIndex === 0) {
            this.startPoint.x += dXOffset;
            this.startPoint.y += dYOffset;
            this.startPoint.z += dZOffset;
            // 重新计算夹点位置
            this.getMovePoints(l1, l2, l3);
        } else if (iIndex === 1) {
            this.endPoint.x += dXOffset;
            this.endPoint.y += dYOffset;
            this.endPoint.z += dZOffset;
            // 重新计算夹点位置
            this.getMovePoints(l1, l2, l3);
        } else if (iIndex === 2) {
            const _midPt = this.midPt.clone();
            _midPt.x += dXOffset;
            _midPt.y += dYOffset;
            _midPt.z += dZOffset;
            const line = new McDbLine(this.startPoint, this.endPoint);
            const res = line.getClosestPointTo(_midPt, false);
            const l = line.getLength()?.val / 2 - this.midPt.distanceTo(this.movePt)
            if (res.val && this.startPoint.distanceTo(res.val) <= l) {
                const x = res.val.x - this.midPt.x;
                const y = res.val.y - this.midPt.y;
                const z = res.val.z - this.midPt.z;
                this.midPt = res.val;
                this.movePt.x += x;
                this.movePt.y += y;
                this.movePt.z += z;
                this.tPoint.x += x;
                this.tPoint.y += y;
                this.tPoint.z += z;
            }
        } else if (iIndex === 3) {
            const _movePt = this.movePt.clone();
            _movePt.x += dXOffset;
            _movePt.y += dYOffset;
            _movePt.z += dZOffset;
            const line = new McDbLine(this.startPoint, this.endPoint);
            const res = line.getClosestPointTo(_movePt, false);
            const l = res.val?.distanceTo(this.startPoint)
            if (l <= line.getLength().val / 2) {
                this.movePt = res.val;
            }
        } else if (iIndex === 4) {
            const _tPoint = this.tPoint.clone();
            _tPoint.x += dXOffset;
            _tPoint.y += dYOffset;
            _tPoint.z += dZOffset;
            const line = new McDbLine(this.midPt, this.tPoint);
            const res = line.getClosestPointTo(_tPoint, true);
            this.tPoint = res.val;
        }
    };
    private getMovePoints(l1: number, l2: number, l3: number) {
        let startPt, endPt;
        if (this.startPoint.x < this.endPoint.x) {
            startPt = this.startPoint.clone();
            endPt = this.endPoint.clone();
        } else {
            startPt = this.endPoint.clone();
            endPt = this.startPoint.clone();
        }
        if (this.endPoint.distanceTo(this.startPoint) < (l1 + l2) * 2) {
            const v = this.endPoint.sub(this.startPoint).normalize();
            endPt = this.startPoint.addvec(v.clone().mult((l1 + l2) * 2));
        }
        const vec = endPt.sub(startPt).normalize();
        this.midPt = startPt.clone().addvec(vec.clone().mult(l1));
        this.movePt = this.midPt.clone().addvec(vec.clone().mult(l2));
        this.tPoint = this.midPt.clone().addvec(vec.clone().perpVector().mult(l3));
        this.endPoint = endPt;
        this.startPoint = startPt;
    }
    // 获取自定义对象的夹点
    public getGripPoints(): McGePoint3dArray {
        let ret = new McGePoint3dArray()
        ret.append(this.startPoint);
        ret.append(this.endPoint);
        ret.append(this.midPt);
        ret.append(this.movePt);
        ret.append(this.tPoint);
        return ret;
    };

    // 绘制实体 
    public worldDraw(draw: MxCADWorldDraw): void {
        if (!this._axisLength) this._axisLength = MxFun.screenCoordLong2Doc(10);
        this.drawAxiosIcon().forEach(entity => {
            draw.drawEntity(entity);
        })
        const pl = new McDbPolyline();
        pl.addVertexAt(this.startPoint);
        pl.addVertexAt(this.endPoint);
        draw.drawEntity(pl);
    }

    // 绘制对称轴标
    private drawAxiosIcon(): McDbEntity[] {
        let startPt, endPt;
        if (this.startPoint.x < this.endPoint.x) {
            startPt = this.startPoint.clone();
            endPt = this.endPoint.clone();
        } else {
            startPt = this.endPoint.clone();
            endPt = this.startPoint.clone();
        }
        if (this.midPt.distanceTo(this.movePt) == 0) {
            this.getMovePoints(this._axisLength / 2, this._axisLength * (5 / 8), this._axisLength);
        }
        const pt2 = this.midPt.clone().addvec(this.midPt.sub(this.tPoint));
        const line1 = new McDbLine(this.tPoint, pt2);
        const line2 = line1.clone() as McDbLine;
        line2.move(this.midPt, this.movePt);
        const _midPt = endPt.clone().subvec(this.midPt.sub(startPt));
        const line3 = line1.clone() as McDbLine;
        const line4 = line2.clone() as McDbLine;
        line3.move(this.movePt, _midPt);
        line4.move(this.movePt, _midPt);
        return [line1, line2, line3, line4]
    }

    // 设置对称轴开始点
    public setStartPoint(pt: McGePoint3d) {
        this.startPoint = pt.clone();
    }
    // 获取对称轴开始点
    public getStartPoint() {
        return this.startPoint;
    }
    // 设置对称轴结束点
    public setEndPoint(pt: McGePoint3d) {
        this.endPoint = pt.clone()
    }
    // 获取对称轴结束点
    public getEndPoint() {
        return this.endPoint;
    }
};
  1. 注册自定义类信息
ts
new McDbTestAxisOfSymmetry().rxInit();
  1. 编写方法,调用 McDbTestAxisOfSymmetry 自定义对称轴类实现引出标注功能
  • 设置对称轴起始点

调用 MxCADUiPrPoint 取点对象设置对称轴的起始点位置。

ts
// 构建对称轴对象
const axis = new McDbTestAxisOfSymmetry();
// 设置对称轴起点
const getPoint1 = new MxCADUiPrPoint();
getPoint1.setMessage('请设置对称轴起点:');
const pt1 = await getPoint1.go();
if (!pt1) return;
axis.setStartPoint(pt1);
// 设置对称轴结束点
const getPoint2 = new MxCADUiPrPoint();  
getPoint2.setMessage('请设置对称轴结束点:');
// 动态绘制对称轴
getPoint2.setUserDraw((pt, pw) => {
    const _axis = axis.clone() as McDbTestAxisOfSymmetry;
    _axis.setEndPoint(pt);
    pw.drawMcDbEntity(_axis);
});
const pt2 = await getPoint2.go();
if (!pt2) return;
axis.setEndPoint(pt2);
// 绘制实体
MxCpp.getCurrentMxCAD().drawEntity(axis);

功能实践

实践效果如下:

  • 点击画对称轴按钮,执行画对称轴方法
  • 点击鼠标左键设置对称轴起始点
  • 成功绘制折断线
  • 移动对称轴夹点可设置对称轴样式与位置