首页 > 其他分享 >云CAD(在线编辑DWG的API)实现自定义实体的详细方法

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

时间:2024-05-31 10:22:24浏览次数:25  
标签:自定义 public API let DWG new pt2 pt1

前言

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

设置自定义实体

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

1. 定义自定义实体类继承McDbCustomEntity类,代码如下:

   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";
     }
   }

2.通过重写 dwgInFields() 函数读取自定义实体数据,dwgOutFields() 函数写入自定义实体数据(在从文件读取实体或把实体写入文件时,复制实体等地方都会调用这两个函数),代码如下:

     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;
     }

3. getGripPoints()方法是在点击这个渲染好的图形时提供一个操作点位,即返回自定义的编辑夹点,并在点击操作点移动的回调函数moveGripPointsAt()中处理夹点编辑结果,参考代码如下:

   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;
     };

4.每次触发动态绘制worldDraw 就会将原本的实例对象删掉(同时也会删除渲染的three.js物体对象),通过create方法重新创建实例,参考代码如下:

     public worldDraw(draw: MxCADWorldDraw): void {
       let tmpline = new McDbLine(this.pt1, this.pt2);
       draw.drawEntity(tmpline);
     }

5. 在程序启动的时候,调用rxInit函数,自定义实体的类型信息注册到系统中,参考代码如下:

    MxFun.on("mxcadApplicationCreatedMxCADObject", (param) => {
        //McDbTestLineCustomEntity 自定义实体
        new McDbTestLineCustomEntity().rxInit();
    })

完整代码如下:

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);
}

 实际演练

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

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

1. 根据上述自定义实体的方法,我们通过继承 McDbCustomEntity 类来初始化我们的自定义实体,代码如下:

   // 新创建 McDbLineText 类,继承McDbCustomEntity
   class McDbLineText extends McDbCustomEntity {
       //设置McDbLineText类中的两个直线端点 pt1、pt2
       //以及显示线段长度的文字_text和文字大小_textsize
       private pt1: McGePoint3d = new McGePoint3d();
       private pt2: McGePoint3d = new McGePoint3d();
       private _text: string = "";
       private _textsize: number = 10;
       //构造函数
       constructor(imp?: any) {
           super(imp);
       }
       //创建函数
       public create(imp: any) {
           return new McDbLineText(imp)
       }
       //获取类型
       public getTypeName(): string {
           return "McDbLineText";
       }
       //设置或获取文本值
       public set text(val: string) {
           this._text = val;
       }
       public get text(): string {
           return this._text;
       }
       //设置或获取文本大小
       public set textsize(val: number) {
           this._textsize = val;
       }
       public get textsize(): number {
           return this._textsize;
       }
       //读取自定义实体数据pt1、pt2、_text、_textsize
       public dwgInFields(filter: IMcDbDwgFiler): boolean {
           this.pt1 = filter.readPoint("pt1").val;
           this.pt2 = filter.readPoint("pt2").val;
           this._text = filter.readString("text").val;
           this._textsize = filter.readDouble("textsize").val;
           return true;
       }
       //写入自定义实体数据pt1、pt2、_text、_textsize
       public dwgOutFields(filter: IMcDbDwgFiler): boolean {
           filter.writePoint("pt1", this.pt1);
           filter.writePoint("pt2", this.pt2);
           filter.writeString("text", this._text);
           filter.writeDouble("textsize", this._textsize);
           return true;
       }
       //自定义同步函数,当其他对象与该对象相连时同步数据
       private fineLink(pt: McGePoint3d): any {
           let ret: any = {};
           let myId = this.getObjectID();
           let dSearch = this._textsize * 0.5;;
           let filter = new MxCADResbuf();
           filter.AddString("McDbCustomEntity", 5020);
           let ss = new MxCADSelectionSet();
           ss.crossingSelect(pt.x - dSearch, pt.y - dSearch, pt.x + dSearch, pt.y + dSearch, filter);
           ss.forEach((id) => {
               if (id == myId)
                   return;
               let ent = id.getMcDbEntity();
               if (!ent) return;
               if (ent instanceof McDbLineText) {
                   let line = (ent as McDbLineText);
                   let linkPoint = line.getPoint1();
                   let link_pos = 0;
                   // 得到直线与图块连接的端点坐标.
                  let dist = line.getPoint1().distanceTo(pt);
                   if (dist > line.getPoint2().distanceTo(pt)) {
                       dist = line.getPoint2().distanceTo(pt);
                       linkPoint = line.getPoint2();
                       link_pos = 1;
                   }
                   if (dist < dSearch) {
                      ret[id.id] = { link_point: linkPoint,link_pos:link_pos };
                   }
               }
           });
           return ret;
       }
       //处理夹点编辑效果
       public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
           this.assertWrite();
           let pt:McGePoint3d = this.pt1.clone();
           let new_pt:McGePoint3d = pt;
           if (iIndex == 0) {
               this.pt1.x += dXOffset;
               this.pt1.y += dYOffset;
               this.pt1.z += dZOffset;
               new_pt = this.pt1;
           }
           else if (iIndex == 1) {
               pt = this.pt2.clone();
               this.pt2.x += dXOffset;
               this.pt2.y += dYOffset;
               this.pt2.z += dZOffset;
               new_pt = this.pt2;
           }
           if (this.getObjectID().isValid()) {
               // 同步,与连接的其它对象。
               let linkobj = this.fineLink(pt)
               Object.keys(linkobj).forEach((id_val:any)=>{
                   let idFind = new McObjectId(id_val);
                   let lineFind = (idFind.getMcDbEntity() as McDbLineText);
                   if(linkobj[id_val].link_pos == 0){
                       lineFind.setPoint1(new_pt);
                   }
                   else{
                       lineFind.setPoint2(new_pt);
                   }
                 });
           }
       };
       //设置对象编辑点位
       public getGripPoints(): McGePoint3dArray {
           let ret = new McGePoint3dArray()
           ret.append(this.pt1);
           ret.append(this.pt2);
           return ret;
       };
       //动态绘制
       public worldDraw(draw: MxCADWorldDraw): void {
           let circle_r = this._textsize * 0.4;
           let vec2 = this.pt2.sub(this.pt1);
           vec2.normalize().mult(circle_r);
           let tmpline = new McDbLine(this.pt1.clone().addvec(vec2),
                                      this.pt2.clone().subvec(vec2));
           draw.drawEntity(tmpline);
           let vec = this.pt2.sub(this.pt1).mult(0.5);
           let midpt = this.pt1.clone().addvec(vec);
           if (vec.dotProduct(McGeVector3d.kXAxis) < 0) {
               vec.negate();
           }
           let ange = vec.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
           let str = this._text;
           if (str.length == 0) {
               str = this.pt1.distanceTo(this.pt2).toFixed(2);
           }
           vec.perpVector();
           if (vec.dotProduct(McGeVector3d.kYAxis) < 0) {
               vec.negate();
           }
           vec.normalize().mult(this._textsize * 0.2);
           let text = new McDbText();
           text.textString = str;
           text.position = midpt.clone().addvec(vec);
           text.alignmentPoint = midpt.clone().addvec(vec);
           text.rotation = ange;
           text.verticalMode = McDb.TextVertMode.kTextBottom;
           text.horizontalMode = McDb.TextHorzMode.kTextCenter;
           text.height = this._textsize;
           draw.drawEntity(text)
           let circle1 = new McDbCircle();
           circle1.center = this.pt1;
           circle1.radius = circle_r;
           draw.drawEntity(circle1);

           let circle2= new McDbCircle();
           circle2.center = this.pt2;
           circle2.radius = circle_r;
           draw.drawEntity(circle2);
       }
       // 设置pt1
       public setPoint1(pt1: McGePoint3d) {
           this.assertWrite();
           this.pt1 = pt1.clone();
       }
       // 设置pt2
       public setPoint2(pt2: McGePoint3d) {
           this.assertWrite();
           this.pt2 = pt2.clone();
       }
       // 获取pt1
       public getPoint1() {
           return this.pt1;
       }
       //获取pt2
       public getPoint2() {
           return this.pt2;
       }
   }

2.调用上述实现的自定义类 McDbLineText ,实现绘制函数。

2.1基础绘制:用户自定义直线两端点,代码如下:

//基础绘制函数
   function Mx_baseLineText(){
     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 McDbLineText();
     new McDbLineText().rxInit();
     myline.setPoint1(pt1);
     myline.setPoint2(pt2);
     myline.textsize = mxcad.mxdraw.screenCoordLong2Doc(10);
     mxcad.drawEntity(myline);
   }

其实现效果如下:

2.2端点联动:设置多条线段相连为一个整体,节点之间相互关联,代码如下:

 function Mx_testLineText(){
       let mxcad = MxCpp.getCurrentMxCAD();
       //设置联动端点
       let pt1 = new McGePoint3d(100,100,0);
       let pt2 = new McGePoint3d(200,150,0);
       let pt3 = new McGePoint3d(400,50,0);
       let pt4 = new McGePoint3d(600,60,0);
       let pt5 = new McGePoint3d(200,300,0);
       let textsize = 5;
       //第一条线
       let myline1 = new McDbLineText();
       myline1.setPoint1(pt1);
       myline1.setPoint2(pt2);
       myline1.textsize = textsize;
       myline1.text = "自定义文本";
       mxcad.drawEntity(myline1);
       //第二条线
       let myline2 = new McDbLineText();
       myline2.setPoint1(pt2);
       myline2.setPoint2(pt3);
       myline2.textsize = textsize;
       mxcad.drawEntity(myline2);
       //第三条线
       let myline3 = new McDbLineText();
       myline3.setPoint1(pt3);
       myline3.setPoint2(pt4);
       myline3.textsize = textsize;
       mxcad.drawEntity(myline3); 
       //第四条线
       let myline4 = new McDbLineText();
       myline4.setPoint1(pt2);
       myline4.setPoint2(pt5);
       myline4.textsize = textsize;
       mxcad.drawEntity(myline4);  
       //把所有的实体都放到当前显示视区
       mxcad.zoomW(new McGePoint3d(-300,-300,0),new McGePoint3d(650,500,0));
       //更新视区显示
       mxcad.updateDisplay();
   }

其实现效果如下:

 

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

 

标签:自定义,public,API,let,DWG,new,pt2,pt1
From: https://www.cnblogs.com/yzy0224/p/18223962

相关文章

  • 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)
     SpringDataJPA系列1、SpringBoot集成JPA及基本使用2、SpringDataJPACriteria查询、部分字段查询3、SpringDataJPA数据批量插入、批量更新真的用对了吗4、SpringDataJPA的一对一、LazyInitializationException异常、一对多、多对多操作5、SpringDataJPA自定义......
  • ISBN查询图书api接口
          基本说明:接口地址:http://data.isbn.work/openApi/getInfoByIsbn?isbn={isbn}&appKey={appkey}返回格式:json请求方式:get请求示例:http://data.isbn.work/openApi/getInfoByIsbn?isbn=9787531526445&appKey=ae1718d4587744b0b79f940fbef69e77+v 809137232请求参......
  • JavaDS-学习数据结构之如果从零开始手搓顺序表,顺带学习自定义异常怎么用!
    前言笔者开始学习数据结构了,虽然笔者已经会用了,不管是C++中的stl亦或是Java中的集合,为了算法比赛多少都突击过,但只知其然而不知其所以然,还是会限制发展的,因此,笔者写下这篇博客.内容是手搓一个顺序表.顺带加一点异常的使用,大伙看个乐子就好了.有错误直接私信喷我就......
  • asp.net web api 接口内调用多个远程接口优化
    提高查询速度的远程接口优化;[ApiController][Route("[controller]")]publicclassShippingCostController:ControllerBase{privatereadonlyShippingCostService_shippingCostService;publicShippingCostController(ShippingCostServiceshippingCostServ......
  • asp.net web api 接口控制并发研究(临时性方法)
    有一个业务场景,接口的业务逻辑非常复杂,对数据库的压力比较大,希望限制下接口的并发数量,研究了下:usingMicrosoft.AspNetCore.Mvc;usingSystem.Collections.Concurrent;usingSystem.Threading.Tasks;namespaceTestBingFa.Controllers{[ApiController][Route("[c......
  • 回顾与前瞻:百度权重API接口的发展之路
     百度权重API接口是一个用于网站关键词排名的预估工具,可以帮助网站主预测他们的网站在百度搜索结果中的排名情况,并给出一个0到9的评估等级。本文将回顾一下百度权重API接口的发展历程,并展望一下未来可能的发展方向。百度权重API接口最早是由爱站、站长工具等网站推出的,旨在帮......
  • QT事件触发顺序探讨:处理自定义事件与系统事件的冲突
    1.课题背景在项目开发过程中用到了纯按键的QT交互,我们通过自定义以下全局键盘事件类进行交互的实现:classKEYPRESSFILTER_EXPORTKeyPressFilter:publicQObject{Q_OBJECTpublic:staticKeyPressFilter*instance(){if(m_instance==nullptr){......
  • C#自定义事件的写法
    C#事件基于委托例1:只用于学习,理解事件底层原理,不推荐这么写;例2:系统用的就是该方式,例如按钮的Click事件;例3:最简略的写法,但是需要客户代码转换EventArgs;1、事件声明完整格式范例: 1//自定义事件参数,默认以EventArgs结尾,需要继承EventArgs类2publicclassMyEventArgs:......
  • 如何在 Firebase 云消息 HTTP V1 API 中创建群组?
    我目前正在从Firebase传统API迁移到适用于Firebase云消息(FCM)的HTTPV1API。虽然HTTPV1文档提供了向组发送消息的详细信息,但我却找不到任何有关如何使用HTTPV1API创建或管理组的信息。在传统API中,我们曾经使用/notification等端点创建通知组,并在这些组中管......
  • 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
     SpringDataJPA系列1、SpringBoot集成JPA及基本使用2、SpringDataJPACriteria查询、部分字段查询3、SpringDataJPA数据批量插入、批量更新真的用对了吗4、SpringDataJPA的一对一、LazyInitializationException异常、一对多、多对多操作5、SpringDataJPA自定......