Skip to content
On this page

星形

下面我们将介绍如何利用 mxcad 插件实现在CAD图纸中绘制星形的功能,该功能中用户自主设定星星的形状、大小与绘制位置。

功能实现

  1. 设置星形中心点、内半径以及顶点数

我们可以调用 MxCADUiPrPoint 取点对象来动态选择星形的中心点,即确定星形的绘制位置,调用 MxCADUiPrInt 根据用户输入的整型数字来确定星形的顶点数,然后再调用 MxCADUiPrDist 设置星形的内半径。

ts
const starVert = new MxCADUiPrInt()
starVert.setMessage("请输入星形顶点数:")
const starNum = await starVert.go()
if (!starNum) return;

const getCenter = new MxCADUiPrPoint()
getCenter.setMessage("指定星形中心点:")
const center = await getCenter.go()
if (!center) return;

const getRadius1 = new MxCADUiPrDist();
// 将星形中心点设置为基点
getRadius1.setBasePt(center);
getRadius1.setMessage('请设置星形的内半径:')
const rVal = await getRadius1.go();
if (!rVal) return;
const radius1 = getRadius1.value();
  1. 设置星形外半径并动态绘制星形

参考上述步骤中我们获取内半径的方法,可以再次调用 MxCADUiPrDist 设置星形的外半径。我们在星形内外半径即圆心所在位置可以得到星形的内接圆和外切圆,再根据上述步骤中我们获取到的星形顶点数调用 McDbCircle.getPointAtDist() 方法分别在内接圆与外接圆上取点,最后调用 McDbPolyline 多段线连接两个圆上取到的端点即可成功绘制星形。

ts
// 星形端点数组
let pointsArr: McGePoint3d[] = []
//获取外半径
const getRadius2 = new MxCADUiPrDist();
// 将星形中心点设置为基点
getRadius2.setBasePt(center);
getRadius2.setMessage('指定星形的外半径:');
// 动态绘制星形
getRadius2.setUserDraw((pt, pw) => {
    let circle2 = new McDbCircle(center.x, center.y, center.z, pt.distanceTo(center));
    let length1 = circle1.getLength();
    let length2 = circle2.getLength();
    if (!length1 || !length2) return;
    // 间隔取点
    let pointArr: McGePoint3d[] = [];
    for (let i = 0; i < starNum * 2; i++) {
        let point1 = circle1.getPointAtDist(length1.val / (starNum * 2) * i);
        if (!point1.ret) return
        let point2 = circle2.getPointAtDist(length2.val / (starNum * 2) * i);
        if (!point2.ret) return
        if (i % 2 === 0) {
            pointArr.push(point1.val)
        } else {
            pointArr.push(point2.val)
        }
    }
    let pl = new McDbPolyline();
    pointArr.forEach(pt => {
        pl.addVertexAt(pt)
    })
    pl.isClosed = true
    pw.drawMcDbEntity(pl)
    pointsArr = [...pointArr]
})
const rVal2 = await getRadius2.go()
if (!rVal2) return;
// 多段线连点绘制星形
let mxcad = MxCpp.getCurrentMxCAD();
let pl = new McDbPolyline();
pointsArr.forEach(pt => {
    pl.addVertexAt(pt)
})
pl.isClosed = true;
mxcad.drawEntity(pl)

功能扩展

  1. 实现自定义星形类

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

ts
// 自定义星形类
class McDbTestStart extends McDbCustomEntity {
    // 定义McDbTestStart内部的点对象 
    // 星形中心点
    private center: McGePoint3d = new McGePoint3d();
    // 星形内半径
    private radius1: number;
    // 星形外半径
    private radius2: number;
    // 星形顶点数
    private vertNum: number;
    // 构造函数
    constructor(imp?: any) {
        super(imp);
    }
    // 创建函数
    public create(imp: any) {
        return new McDbTestStart(imp)
    }
    // 获取类名
    public getTypeName(): string {
        return "McDbTestStart";
    }
    //设置或获取内半径
    public set starRadius1(val: number) {
        this.radius1 = val;
    }
    public get starRadius1(): number {
        return this.radius1;
    }
    //设置或获取外半径
    public set starRadius2(val: number) {
        this.radius2 = val;
    }
    public get starRadius2(): number {
        return this.radius2;
    }
    //设置或获取顶点数
    public set starVertNum(val: number) {
        this.vertNum = val;
    }
    public get starVertNum(): number {
        return this.vertNum;
    }
    // 读取自定义实体数据center、radius1、 radius2
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
        this.center = filter.readPoint("center").val;
        this.radius1 = filter.readDouble("radius1").val;
        this.radius2 = filter.readDouble("radius2").val;
        this.vertNum = filter.readLong("vertNum").val;
        return true;
    }
    // 写入自定义实体数据center、radius1、 radius2
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
        filter.writePoint("center", this.center);
        filter.writeDouble("radius1", this.radius1);
        filter.writeDouble("radius2", this.radius2);
        filter.writeLong("vertNum", this.vertNum);
        return true;
    }

    // 移动自定义对象的夹点
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
        this.assertWrite();
        this.center.x += dXOffset;
        this.center.y += dYOffset;
        this.center.z += dZOffset;
    };
    // 获取自定义对象的夹点
    public getGripPoints(): McGePoint3dArray {
        let ret = new McGePoint3dArray()
        ret.append(this.center);
        return ret;
    };
    // 绘制实体
    public worldDraw(draw: MxCADWorldDraw): void {
        const circle1 = new McDbCircle();
        circle1.center = this.center;
        circle1.radius = this.radius1;

        const circle2 = new McDbCircle();
        circle2.center = this.center;
        circle2.radius = this.radius2;

        let length1 = circle1.getLength().val;
        let length2 = circle2.getLength().val;
        if (!length1 || !length2) return;
        
        let pointArr: McGePoint3d[] = [];
        for (let i = 0; i < this.vertNum * 2; i++) {
            let point1 = circle1.getPointAtDist(length1 / (this.vertNum * 2) * i);
            if (!point1.ret) return
            let point2 = circle2.getPointAtDist(length2 / (this.vertNum * 2) * i);
            if (!point2.ret) return
            if (i % 2 === 0) {
                pointArr.push(point1.val)
            } else {
                pointArr.push(point2.val)
            }
        }
        let pl = new McDbPolyline();
        pointArr.forEach(pt => {
            pl.addVertexAt(pt)
        })
        pl.isClosed = true;
        draw.drawEntity(pl);
    }
    // 设置星形中心点
    public setCenter(pt: McGePoint3d) {
        this.assertWrite();
        this.center = pt.clone();
    }
    // 获取星形中心点
    public getCenter() {
        return this.center;
    }
}

功能实践

实践效果如下:

  • 点击星形按钮,执行绘制星形方法
  • 根据命令行提示步骤完成设置星形顶点数
  • 设置星形中心点,内半径
  • 然后设置星形外半径,动态绘制星形
  • 确定外半径值,成功绘制星形