本帖最后由 MxDraw 于 2024-5-31 10:42 编辑
前言自定义实体在CAD二次开发中使用的频率较高,本章节主要阐述网页CAD中使用自定义实体的方法,mxcad可以根据用户的具体需求来创建和管理自定义实体,可以通过从自定义实体类 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";
- }
- }
- 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;
- };
复制代码
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源码下载地址
|