CAD画图 发表于 2024-5-30 09:48:24

在线CAD(云CAD)实现自定义实体的详细方法

前言

自定义实体在CAD二次开发中使用的频率较高,本章节主要阐述网页CAD中使用自定义实体的方法,mxcad可以根据用户的具体需求来创建和管理自定义实体,可以通过从自定义实体类 McDbCustomEntity()中继承实体的名称、属性、方法,也可结合自身需求对自定义实体类中的属性或方法进行重写。

设置自定义实体

下面以自定义直线为例来介绍如何使用自定义实体,效果如图:


1. 定义自定义实体类继承McDbCustomEntity 类,代码如下:
<span style="background-color: white;">   class McDbTestLineCustomEntity extends McDbCustomEntity {
   private pt1: McGePoint3d = new McGePoint3d();
   private pt2: McGePoint3d = new McGePoint3d();
   constructor(imp?: any) {
       super(imp);
   }
   public create(imp: any) {
       return new McDbTestLineCustomEntity(imp)
   }
   public getTypeName(): string {
       return "McDbTestLineCustomEntity";
   }
   }</span>
2. 通过重写 dwgInFields()函数读取自定义实体数据,dwgOutFields()函数写入自定义实体数据(在从文件读取实体或把实体写入文件时,复制实体等地方都会调用这两个函数),代码如下:
<span style="background-color: white;">    public dwgInFields(filter: IMcDbDwgFiler): boolean {
       this.pt1 = filter.readPoint("pt1").val;
       this.pt2 = filter.readPoint("pt2").val;
       return true;
   }
   public dwgOutFields(filter: IMcDbDwgFiler): boolean {
       filter.writePoint("pt1", this.pt1);
       filter.writePoint("pt2", this.pt2);
       return true;
   }</span>
3. getGripPoints()方法是在点击这个渲染好的图形时提供一个操作点位,即返回自定义的编辑夹点,并在点击操作点移动的回调函数moveGripPointsAt()中处理夹点编辑结果,参考代码如下:<span style="background-color: white;">public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
       this.assertWrite();
       if (iIndex == 0) {
         this.pt1.x += dXOffset;
         this.pt1.y += dYOffset;
         this.pt1.z += dZOffset;
       }
       else if (iIndex == 1) {
         this.pt2.x += dXOffset;
         this.pt2.y += dYOffset;
         this.pt2.z += dZOffset;
       }
   };
   public getGripPoints(): McGePoint3dArray {
       let ret = new McGePoint3dArray()
       ret.append(this.pt1);
       ret.append(this.pt2);
       return ret;
   };</span>
4. 每次触发动态绘制worldDraw,就会将原本的实例对象删掉(同时也会删除渲染的three.js物体对象),通过create方法重新创建实例,参考代码如下:<span style="background-color: white;">   public worldDraw(draw: MxCADWorldDraw): void {
       let tmpline = new McDbLine(this.pt1, this.pt2);
       draw.drawEntity(tmpline);
   }</span>
5. 在程序启动的时候,调用rxInit函数,自定义实体的类型信息注册到系统中,参考代码如下:<span style="background-color: white;">    MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
      //McDbTestLineCustomEntity 自定义实体
      new McDbTestLineCustomEntity().rxInit();
    })</span>
完整代码如下:
<span style="background-color: white;">import { IMcDbDwgFiler, McDbCustomEntity, McDbLine, McGePoint3d, McGePoint3dArray, MxCADUiPrPoint, MxCADWorldDraw, MxCpp } from "mxcad";
export class McDbTestLineCustomEntity extends McDbCustomEntity {
    private pt1: McGePoint3d = new McGePoint3d();
    private pt2: McGePoint3d = new McGePoint3d();
    constructor(imp?: any) {
      super(imp);
    }
    public create(imp: any) {
      return new McDbTestLineCustomEntity(imp)
    }
    public getTypeName(): string {
      return "McDbTestLineCustomEntity";
    }
    public dwgInFields(filter: IMcDbDwgFiler): boolean {
      this.pt1 = filter.readPoint("pt1").val;
      this.pt2 = filter.readPoint("pt2").val;
      return true;
    }
    public dwgOutFields(filter: IMcDbDwgFiler): boolean {
      filter.writePoint("pt1", this.pt1);
      filter.writePoint("pt2", this.pt2);
      return true;
    }
    public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
      this.assertWrite();
      if (iIndex == 0) {
            this.pt1.x += dXOffset;
            this.pt1.y += dYOffset;
            this.pt1.z += dZOffset;
      }
      else if (iIndex == 1) {
            this.pt2.x += dXOffset;
            this.pt2.y += dYOffset;
            this.pt2.z += dZOffset;
      }
    };
    public getGripPoints(): McGePoint3dArray {
      let ret = new McGePoint3dArray()
      ret.append(this.pt1);
      ret.append(this.pt2);
      return ret;
    };
    public worldDraw(draw: MxCADWorldDraw): void {
      let tmpline = new McDbLine(this.pt1, this.pt2);
      draw.drawEntity(tmpline);
    }
    public setPoint1(pt1: McGePoint3d) {
      this.assertWrite();
      this.pt1 = pt1.clone();
    }
    public setPoint2(pt2: McGePoint3d) {
      this.assertWrite();
      this.pt2 = pt2.clone();
    }
    public getPoint1() {
      return this.pt1;
    }
    public getPoint2() {
      return this.pt2;
    }
}
export async function MxTest_DrawCustomEntity() {
    let mxcad = MxCpp.getCurrentMxCAD();
    const getPoint = new MxCADUiPrPoint();
    getPoint.setMessage("\n指定一点:");
    let pt1 = (await getPoint.go());
    if (!pt1) return;
    getPoint.setBasePt(pt1);
    getPoint.setUseBasePt(true);
    getPoint.setMessage("\n指定二点:");
    let pt2 = (await getPoint.go());
    if (!pt2) return;
    let myline = new McDbTestLineCustomEntity();
    myline.setPoint1(pt1);
    myline.setPoint2(pt2);
    mxcad.drawEntity(myline);
}</span>
实际演练

上面的代码是最简单的画直线的操作,更复杂点的自定义实体例子,可以打开在线DEMO查看,如下图:


首先我们自定义一条自带文本且两个端点以圆结束的直线,其中线段自带的文本可自定义设置,默显示认为线段长度,其实现方法如下:

1. 根据上述自定义实体的方法,我们通过继承 McDbCustomEntity 类来初始化我们的自定义实体,代码如下:
    篇幅限制,更多的内容请查询梦想CAD控件
DEMO源码下载地址

https://gitee.com/mxcadx/mxdraw-article/blob/master/%E7%BD%91%E9%A1%B5CAD%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%9E%E4%BD%93/demo.7z

chiouho 发表于 2025-1-6 14:46:23

谢谢楼主的分享
页: [1]
查看完整版本: 在线CAD(云CAD)实现自定义实体的详细方法