在线CAD绘制墙体(网页CAD开发室内设计软件)

本文涉及的产品
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
容器镜像服务 ACR,镜像仓库100个 不限时长
可观测监控 Prometheus 版,每月50GB免费额度
简介: 本文介绍了如何使用mxcad实现基础墙体功能,包括墙体的绘制、相交处理和更新。通过继承mxcad中的自定义实体`McDbCustomEntity`,封装计算墙体多段线的方法,并实现自定义墙体类`McDbTestWall`,以支持墙体的创建、移动和编辑。此外,还实现了墙体相交后的断点和拐点计算,确保墙体在与其他墙体相交时能够正确显示和更新。最后,通过监听夹点编辑和实体选择事件,实现了墙体的动态更新功能。在线示例demo地址:[https://demo.mxdraw3d.com:3000/mxcad/](https://demo.mxdraw3d.com:3000/mxcad/),展示墙体绘制效果

前言

室内平面图中墙体是最重要的图形之一,其中砖墙、混凝土墙、钢架墙、隔墙、隔热墙等类型的墙在设计图中均有不同的表现方式,墙体的用途一般可以分为一般墙、虚墙、卫生隔断、阳台挡板、矮墙等,根据不同的需求绘制对应的墙体能够增强建筑设计的专业性和准确性。下面我们将介绍如何使用mxcad实现基础墙体功能,并展示其实践运用效果。

下述的墙体功能为一个基于mxcad开发的demo示例,因此存在无法百分百适配用户实际使用需求的情况,用户可在下述源码的基础上基于mxcad实现二次开发一次来适配实际需求。

功能开发

mxcad 墙体功能的核心思想是通过继承 mxcad 中的自定义实体 McDbCustomEntity ,自己实现一个独立的墙体对象,以及通过监测墙体相交的变化实现自主计算墙体绘制的一系列逻辑。如果你对 mxcad 中的自定义实体还不熟悉,点击自定义实体开发文档链接了解自定义实体是什么,内部存在的方法以及如何通过该实体实现自定义的功能实体。

1.封装计算墙体对应的多段线方法
在计算墙体多段线的方法中,我们需要传入墙体开始点、墙体结束点和墙体宽度,如果目标墙体存在与其他墙体相交产生拐点的情况还需要传入目标墙体生成的拐点。为了方便后续与其他墙体之间的比对和计算,我们将返回墙体的四个断点(pt1,pt2,pt3,pt4)、整体多段线(pl)、以及所在的中心直线(line),参考代码:

   // 计算多段线相关数据
   const getPolyline = (startPoint: McGePoint3d, endPoint: McGePoint3d, width: number, turnPoints?: McGePoint3d[]): any => {
   
       const _startPoint = startPoint.clone();
       const _endPoint = endPoint.clone();
       if (startPoint.x > endPoint.x) {
   
           startPoint = _endPoint;
           endPoint = _startPoint;
       }
       const pl = new McDbPolyline();
       // 计算初始墙体四个端点  
       const v = endPoint.sub(startPoint).normalize().perpVector();
       let pt1 = startPoint.clone().addvec(v.clone().mult(width / 2));
       let pt2 = startPoint.clone().addvec(v.clone().negate().mult(width / 2));
       let pt3 = endPoint.clone().addvec(v.clone().negate().mult(width / 2));
       let pt4 = endPoint.clone().addvec(v.clone().mult(width / 2));
       const pointArr = {
   
           pt1Arr: [],
           pt2Arr: [],
           pt3Arr: [],
           pt4Arr: []
       }
       /**
        *有拐点则计算出墙体变换后的四个端点
        */
       if (turnPoints && turnPoints.length > 0) {
   
           turnPoints.forEach(pt => {
   
               const dist1 = pt.distanceTo(startPoint);
               const dist2 = pt.distanceTo(endPoint);
               if (dist1 < dist2) {
   
                   // 开始端
                   const _dist1 = pt.distanceTo(pt1);
                   const _dist2 = pt.distanceTo(pt2);
                   if (_dist1 < _dist2) {
   
                       // pt1 = pt;
                       pointArr.pt1Arr.push(pt)
                   } else {
   
                       // pt2 = pt;
                       pointArr.pt2Arr.push(pt)
                   }
               } else {
   
                   // 结束端
                   const _dist1 = pt.distanceTo(pt3);
                   const _dist2 = pt.distanceTo(pt4);
                   if (_dist1 < _dist2) {
   
                       // pt3 = pt;
                       pointArr.pt3Arr.push(pt)
                   } else {
   
                       // pt4 = pt;
                       pointArr.pt4Arr.push(pt);
                   }
               };
           });
        // 拐点变换后新的墙体端点      
           for (let i = 0; i < 4; i++) {
   
               if (pointArr[`pt${
     i + 1}Arr`].length !== 0) {
   
                   let dist = null;
                   let point = new McGePoint3d();
                   switch (i + 1) {
   
                       case 1:
                           point = pt4;
                           break;
                       case 2:
                           point = pt3;
                           break;
                       case 3:
                           point = pt2;
                           break;
                       case 4:
                           point = pt1;
                           break;
                   }
                   pointArr[`pt${
     i + 1}Arr`].forEach(pt => {
   
                       const _dist = pt.distanceTo(point);
                       if (!dist || _dist < dist) {
   
                           dist = _dist;
                           switch (i + 1) {
   
                               case 1:
                                   pt1 = pt;
                                   break;
                               case 2:
                                   pt2 = pt;
                                   break;
                               case 3:
                                   pt3 = pt;
                                   break;
                               case 4:
                                   pt4 = pt;
                                   break;
                           }
                       }
                   })
               }
           }
       } else {
   
           pl.addVertexAt(pt1);
           pl.addVertexAt(pt2);
           pl.addVertexAt(pt3);
           pl.addVertexAt(pt4);
       }
       pl.isClosed = true;
       const line = new McDbLine(startPoint, endPoint);
       return {
    pl, line, pt1, pt2, pt3, pt4 };
   }

2.实现自定义墙体类:McDbTestWall

   // 墙体类
   class McDbTestWall extends McDbCustomEntity {
   
       // 定义McDbTestWall内部的点对象
       // 墙体开始点
       private startPoint: McGePoint3d = new McGePoint3d();
       // 墙体夹点移动前结束点位置
       private _oldEndPoint: McGePoint3d = new McGePoint3d();
       // 墙体夹点移动前开始点位置
       private _oldStartPoint: McGePoint3d = new McGePoint3d();
       // 墙体结束点
       private endPoint: McGePoint3d = new McGePoint3d();
       // 墙体宽
       private _wallWidth: number = 30;
       // 墙体断点
       private _breakPoints: McGePoint3d[] = [];
       // 墙体拐点
       private _turnPoints: McGePoint3d[] = [];
       // 墙体相交点
       private _insterPoints: McGePoint3d[] = [];
       // 每一个断点组的长度记录
       private breakPtsCount: number[] = [];
       // 构造函数
       constructor(imp?: any) {
   
           super(imp);
       }
       // 创建函数
       public create(imp: any) {
   
           return new McDbTestWall(imp)
       }
       // 获取类名
       public getTypeName(): string {
   
           return "McDbTestWall";
       }
       //设置或获取墙体宽
       public set wallWidth(val: number) {
   
           this._wallWidth = val;
       }
       public get wallWidth(): number {
   
           return this._wallWidth;
       }
       //设置或获取墙体断点
       public set breakPoints(val: McGePoint3d[]) {
   
           this._breakPoints = val;
       }
       public get breakPoints(): McGePoint3d[] {
   
           return this._breakPoints;
       }
       //设置或获取墙体拐点
       public set turnPoints(val: McGePoint3d[]) {
   
           this._turnPoints = val;
       }
       public get turnPoints(): McGePoint3d[] {
   
           return this._turnPoints;
       }
       //设置或获取墙体相交点
       public set insterPoints(val: McGePoint3d[]) {
   
           this._insterPoints = val;
       }
       public get insterPoints(): McGePoint3d[] {
   
           return this._insterPoints;
       }
       //设置或获取墙体单次相交断点数
       public set breakPtsCounts(val: number[]) {
   
           this.breakPtsCount = val;
       }
       public get breakPtsCounts(): number[] {
   
           return this.breakPtsCount;
       }
       // 获取墙体移动前开始点
       public get oldStartPoint(): McGePoint3d {
   
           return this._oldStartPoint;
       }
       // 获取墙体移动前结束点
       public get oldEndPoint(): McGePoint3d {
   
           return this._oldEndPoint;
       }
       // 读取自定义实体数据
       public dwgInFields(filter: IMcDbDwgFiler): boolean {
   
           this.startPoint = filter.readPoint("startPoint").val;
           this.endPoint = filter.readPoint("endPoint").val;
           this._oldEndPoint = filter.readPoint("oldEndPoint").val;
           this._oldStartPoint = filter.readPoint("oldStartPoint").val;
           this._breakPoints = filter.readPoints("breakPoint").val;
           this._insterPoints = filter.readPoints("insterPoints").val;
           this._turnPoints = filter.readPoints("turnPoint").val;
           this._wallWidth = filter.readDouble("wallWidth").val;
           const _breakPtsCount = filter.readString("breakPtsCount").val;
           if (_breakPtsCount) {
   
               this.breakPtsCount = _breakPtsCount.split(',').map(Number);
           }
           return true;
       }
       // 写入自定义实体数据
       public dwgOutFields(filter: IMcDbDwgFiler): boolean {
   
           filter.writePoint("endPoint", this.endPoint);
           filter.writePoint("startPoint", this.startPoint);
           filter.writePoint("oldStartPoint", this._oldStartPoint);
           filter.writePoint("oldEndPoint", this._oldEndPoint);
           filter.writePoints("breakPoint", this._breakPoints);
           filter.writePoints("insterPoints", this._insterPoints);
           filter.writePoints("turnPoint", this._turnPoints);
           filter.writeDouble("wallWidth", this._wallWidth);
           if (this.breakPtsCount.length > 0) {
   
               filter.writeString("breakPtsCount", this.breakPtsCount.join(','));
           }
           return true;
       }

       // 移动自定义对象的夹点
       public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
   
           this.assertWrite();
           if (iIndex === 0) {
   
               this._oldStartPoint = this.startPoint.clone();
               this.startPoint.x += dXOffset;
               this.startPoint.y += dYOffset;
               this.startPoint.z += dZOffset;
           } else if (iIndex === 1) {
   
               this._oldEndPoint = this.endPoint.clone();
               this.endPoint.x += dXOffset;
               this.endPoint.y += dYOffset;
               this.endPoint.z += dZOffset;
           };
       };
       // 获取自定义对象的夹点
       public getGripPoints(): McGePoint3dArray {
   
           let ret = new McGePoint3dArray()
           ret.append(this.startPoint);
           ret.append(this.endPoint);
           return ret;
       };
       // 绘制实体
       public worldDraw(draw: MxCADWorldDraw): void {
   
           const {
    pl, pt1, pt2, pt3, pt4 } = getPolyline(this.startPoint.clone(), this.endPoint.clone(), this._wallWidth, this._turnPoints);
           const dol = 0.00001;
           if (this.turnPoints.length > 0 || this.breakPoints.length > 0) {
   
               // 有拐点,有断点
               const lineArr: McDbLine[] = [];
               const line1 = new McDbLine(pt1, pt4);
               const line2 = new McDbLine(pt2, pt3);
               lineArr.push(line2, line1)
               const dist1 = pt1.distanceTo(pt2);
               const dist2 = pt4.distanceTo(pt3);
               if (dist1 - this._wallWidth < 0.00001) {
   
                   const line3 = new McDbLine(pt2, pt1);
                   if (this._turnPoints.length > 0) {
   
                       let r = this._turnPoints.filter(pt => pt2.distanceTo(pt) < dol || pt1.distanceTo(pt) < dol);
                       if (r.length === 0) lineArr.push(line3)
                   } else {
   
                       lineArr.push(line3);
                   }
               }
               if (dist2 - this._wallWidth < 0.00001) {
   
                   const line4 = new McDbLine(pt3, pt4);
                   if (this._turnPoints.length > 0) {
   
                       let r = this._turnPoints.filter(pt => pt3.distanceTo(pt) < dol || pt4.distanceTo(pt) < dol);
                       if (r.length === 0) lineArr.push(line4)
                   } else {
   
                       lineArr.push(line4)
                   }
               };
               if (this.breakPoints.length > 0) {
   
                   /**
                    * 有断点
                    * 找出每一个断点所在的直线
                    * 以每一组断点去切割直线,再绘制切割好的直线
                    */
                   let count = 0;
                   const breakPlArr: McDbPolyline[] = []; // 存储每一组断点多段线
                   const breakPts = [];
                   this.breakPtsCount.forEach((item) => {
   
                       count += item;
                       const pl = new McDbPolyline()
                       if (count > 0) {
   
                           // 一组断点
                           const breakPoint = this.breakPoints.filter((pt, i) => i < count && i >= count - item);
                           breakPoint.forEach(pt => {
   
                               pl.addVertexAt(pt);
                           })
                           breakPts.push(breakPoint)
                       };
                       breakPlArr.push(pl);
                   });
                   lineArr.forEach((l) => {
   
                       // 直线上的断点集合
                       const plArr: McDbPolyline[] = []; // 直线上的断点连线
                       const r: McGePoint3d[] = []; // 直线上的断点集合
                       const _r: McGePoint3d[] = []; // 直线上的单断点集合
                       breakPts.forEach((item) => {
   
                           const points = item.filter(pt => {
   
                               const point = l.getClosestPointTo(pt, false).val;
                               const dist = point.distanceTo(pt);
                               return dist < dol
                           });
                           if (points.length > 0) {
   
                               r.push(...points)
                               if (points.length % 2 === 0) {
   
                                   points.forEach((pt, index) => {
   
                                       if (index % 2 == 0) {
   
                                           const pl = new McDbPolyline();
                                           pl.addVertexAt(pt);
                                           pl.addVertexAt(points[index + 1]);
                                           plArr.push(pl);
                                       }
                                   });
                               } else {
   
                                   _r.push(...points)
                               }
                           }
                       })
                       if (r.length > 0) {
   
                           // 直线上含有断点
                           l.splitCurves(r).forEach((obj) => {
   
                               const _line = obj.clone() as McDbLine;
                               const midPt = _line.startPoint.clone().addvec(_line.endPoint.sub(_line.startPoint).mult(1 / 2))
                               const res1 = r.filter(pt => _line.startPoint.distanceTo(pt) < dol);
                               const res2 = r.filter(pt => _line.endPoint.distanceTo(pt) < dol);
                               // 起始点只有一个是断点
                               if (res1.length === 0 || res2.length === 0) {
   
                                   if (_r.length === 0) {
   
                                       // 无单断点直接绘制
                                       draw.drawEntity(_line)
                                   } else {
   
                                       // 筛选出在切断后直线的单断点
                                       const singlePts = _r.filter(pt => _line.getDistAtPoint(pt).ret);//切割后线段上的单断点
                                       if (singlePts.length === 0) {
   
                                           // 若单断点不在这条直线上,则直接绘制
                                           draw.drawEntity(_line)
                                       } else {
   
                                           // 若单断点在这条直线上,则判断是否与对应的交点同向
                                           singlePts.forEach(pt => {
   
                                               if (breakPlArr.length > 0) {
   
                                                   const _plNum = breakPlArr.filter((pl, index) => {
   
                                                       if (pl.numVerts() === 2) {
   
                                                           return this.countLineToPl(pl, index, pt, midPt);
                                                       } else {
   
                                                           const num = pl.numVerts();
                                                           let flag = false;
                                                           for (let i = 0; i < num; i++) {
   
                                                               if (i % 2 == 0) {
   
                                                                   const _pl = new McDbPolyline();
                                                                   _pl.addVertexAt(pl.getPointAt(i).val);
                                                                   _pl.addVertexAt(pl.getPointAt(i + 1).val);
                                                                   _pl.trueColor = new McCmColor(255, 0, 0);
                                                                   const r = this.countLineToPl(_pl, index, pt, midPt)
                                                                   if (r) flag = true;
                                                               }
                                                           };
                                                           return flag
                                                       }

                                                   });
                                                   if (_plNum.length === singlePts.length) {
   
                                                       draw.drawEntity(_line)
                                                   }
                                               }
                                           })
                                       }

                                   }
                               }
                               // 起始点都是断点
                               if (res1.length !== 0 && res2.length !== 0) {
   
                                   const _r1 = plArr.filter((pl) => {
   
                                       const pt = pl.getClosestPointTo(midPt, false).val;
                                       return pt.distanceTo(midPt) < dol
                                   });
                                   if (_r1.length === 0) {
   
                                       draw.drawEntity(_line)
                                   }
                               }
                           })
                       } else {
   
                           // 线段上无断点
                           const length = l.getLength().val;
                           if (Math.abs(length - this._wallWidth) < dol) {
   
                               const midPt = l.getPointAtDist(l.getLength().val / 2).val;
                               const distArr = this.insterPoints.map(pt => pt.distanceTo(midPt));
                               const index = distArr.findIndex(element => element === Math.min(...distArr));
                               const pl = breakPlArr[index];
                               const insterPt = this._insterPoints[index];
                               const p = l.getClosestPointTo(insterPt, true).val;
                               if (p.distanceTo(insterPt) > dol) {
   
                                   const closePt = pl.getClosestPointTo(insterPt, true).val;
                                   const insterWallWidth = closePt.distanceTo(insterPt);
                                   const insterPtToLine = l.getClosestPointTo(insterPt, true).val.distanceTo(insterPt);
                                   if (insterPtToLine > insterWallWidth) {
   
                                       draw.drawEntity(l)
                                   } else {
   
                                       const midVec = midPt.sub(insterPt);
                                       const num = pl.numVerts();
                                       if (num === 2) {
   
                                           const vec = pl.getPointAt(0).val.sub(pl.getPointAt(1).val);
                                           const angle = Number((midVec.angleTo1(vec) * (180 / Math.PI)).toFixed(4));
                                           if (angle === 0 || angle === 180) {
   
                                               draw.drawEntity(l)
                                           }
                                       } else {
   
                                           let count = 0;
                                           for (let i = 0; i < num; i++) {
   
                                               if (i % 2 == 0) {
   
                                                   const _pl = new McDbPolyline();
                                                   _pl.addVertexAt(pl.getPointAt(i).val);
                                                   _pl.addVertexAt(pl.getPointAt(i + 1).val);
                                                   _pl.trueColor = new McCmColor(255, 0, 0);
                                                   const vec = _pl.getPointAt(0).val.sub(_pl.getPointAt(1).val);
                                                   const angle = Number((midVec.angleTo1(vec) * (180 / Math.PI)).toFixed(4));
                                                   if (angle === 0 || angle === 180) {
   
                                                       count += 1;
                                                   }
                                               }
                                           }
                                           if (count === num / 2) draw.drawEntity(l);
                                       }
                                   }
                               }

                           } else {
   
                               draw.drawEntity(l)
                           }
                       }
                   });
               } else {
   
                   // 无断点,全是拐点
                   lineArr.forEach((l, index) => {
   
                       if (index < 2) {
   
                           draw.drawEntity(l)
                       } else {
   
                           const length = l.getLength().val;
                           const r = this._turnPoints.filter(pt => pt.distanceTo(l.startPoint) < dol || pt.distanceTo(l.endPoint) < dol)
                           if (Math.abs(length - this._wallWidth) < dol && r.length === 0) {
   
                               draw.drawEntity(l)
                           }
                       }
                   })
               }
           }
           if (!this.breakPoints.length && !this.turnPoints.length) {
   
               draw.drawEntity(pl);
           }
           const line = new McDbLine(this.startPoint, this.endPoint)
           draw.drawOsnapEntity(line);
       }
       private countLineToPl(pl: McDbPolyline, index: number, pt: McGePoint3d, midPt: McGePoint3d): Boolean {
   
           const dol = 0.00001;
           const dist1 = pl.getPointAt(0).val.distanceTo(pt);
           const dist2 = pl.getPointAt(1).val.distanceTo(pt);
           const insterPt = this._insterPoints[index];
           if (dist1 < dol || dist2 < dol) {
   
               const _closePt = pl.getClosestPointTo(insterPt, true).val;
               const v = insterPt.sub(_closePt);
               const _v = midPt.sub(_closePt);
               let angle1 = v.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
               let angle2 = _v.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
               const angle = Math.abs(angle1 - angle2);
               if (Number((angle * (180 / Math.PI)).toFixed(4)) >= 90 && Number((angle * (180 / Math.PI)).toFixed(4)) <= 270) {
   
                   return true
               } else {
   
                   return false
               }
           } else {
   
               return false
           }
       }
       // 设置墙体起点
       public setStartPoint(pt: McGePoint3d) {
   
           this.startPoint = pt.clone()
           this._oldStartPoint = pt.clone()
       }
       // 获取墙体起点
       public getStartPoint(): McGePoint3d {
   
           return this.startPoint;
       }
       // 设置墙体结束点
       public setEndPoint(pt: McGePoint3d) {
   
           this.endPoint = pt.clone()
           this._oldEndPoint = pt.clone()
       }
       // 获取墙体结束点
       public getEndPoint(): McGePoint3d {
   
           return this.endPoint.clone();
       }
       // 增加墙体断点
       public addBreakPoints(pts: McGePoint3d[]) {
   
           this.breakPoints.push(...pts);
       }
       // 增加墙体交点
       public addInsterPoints(pts: McGePoint3d[]) {
   
           this._insterPoints.push(...pts);
       }
       // 增加墙体单次相交的断点数
       public addBreakPtsCount(val: number[]) {
   
           if (val.length > 0) {
   
               this.breakPtsCount.push(...val);
           }
       }
   };

3.计算墙体相交后的断点和拐点
计算与目标墙体相交的墙体,参考代码:

     //相交墙体集合
     const intersectingWalls: McObjectId[] = [];
     /**
      * startPoint:墙体开始点
      * endPoint:墙体结束点
      * wallWidth:墙体宽度
      */
     const {
    pt1, pt3, line } = getPolyline(startPoint, endPoint, wallWidth);
     const length = line.getLength().val;
     // 设置过滤器,过滤出自定义实体
     let filter = new MxCADResbuf();
     filter.AddString("McDbCustomEntity", 5020);
     const ss = new MxCADSelectionSet();
     ss.crossingSelect(pt1.x - length, pt1.y - length, pt3.x + length, pt3.y + length, filter);
     // 与其他墙体相交
     if (ss.count() !== 0) {
   
         ss.forEach(id => {
   
             const ent = id.getMcDbEntity();
             if ((ent as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                 intersectingWalls.push(id);
             }
         });
     }

根据相交墙体信息获取墙体断点与拐点,参考代码:

     // 处理相交墙体得到断点与拐点
     /**
      * this.startPoint:墙体开始点
      * this.endPoint:墙体结束点
      * this.wallWidth:墙体宽度
      * this.pointArr:断点集合
      * this.breakPtsCount:单次断点数集合
      * this.turnPointArr:拐点集合
      * this.insterPointArr:交点集合
      * this.dol:精度
      */
     function dealingWithWalls(wallObjIds: McObjectId[]) {
   
         const {
    pl, pt1, pt2, pt3, pt4, line } = getPolyline(this.startPoint, this.endPoint, this.wallWidth);
         if (wallObjIds.length != 0) {
   
             // 与新墙体有交点的墙体集合
             const wallArr = [];
             // 与其他墙体相交
             wallObjIds.forEach(id => {
   
                 const entity = id.getMcDbEntity();
                 if ((entity as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                     const wall = entity.clone() as McDbTestWall
                     const {
    pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line } = getPolyline(wall.getStartPoint(), wall.getEndPoint(), wall.wallWidth);
                     const _pointArr: McGePoint3d[] = [];
                     _pl.IntersectWith(pl, McDb.Intersect.kOnBothOperands).forEach(item => _pointArr.push(item));
                     if (_pointArr.length > 0) {
   
                         wallArr.push({
    id, wall, pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line, pointArr: _pointArr })
                     }
                 }
             });
             if (wallArr.length != 0) {
   
                 wallArr.forEach(item => {
   
                     const {
    id, wall, pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line, pointArr: _pointArr } = item;
                     /**
                          * 根据交点位置判断是否是拐点
                          * 中心相交的交点与比对中心线端点距离小于1/2墙宽的都是拐点
                          */
                     const insterPointArr = (line as McDbLine).IntersectWith(_line as McDbLine, McDb.Intersect.kExtendBoth);
                     if (insterPointArr.length() > 0) {
   
                         const insterPt = insterPointArr.at(0);
                         this.insterPointArr.push(insterPt);
                         const dist1 = insterPt.distanceTo(_line.startPoint);
                         const dist2 = insterPt.distanceTo(_line.endPoint);
                         const dist3 = insterPt.distanceTo(line.startPoint);
                         const dist4 = insterPt.distanceTo(line.endPoint);
                         let vec, _vec;
                         dist3 < dist4 ? vec = (line as McDbLine).endPoint.sub(insterPt).normalize() :
                         vec = (line as McDbLine).startPoint.sub(insterPt).normalize();
                         dist1 < dist2 ? _vec = (_line as McDbLine).endPoint.sub(insterPt).normalize() :
                         _vec = (_line as McDbLine).startPoint.sub(insterPt).normalize();
                         const angle1 = vec.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                         const angle2 = _vec.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                         if ((dist1 <= wall.wallWidth / 2 || dist2 <= wall.wallWidth / 2) &&
                             (dist3 <= this.wallWidth / 2 || dist4 <= this.wallWidth / 2)
                            ) {
   
                             // 绘制拐角
                             const turnArr = []
                             const line1 = new McDbLine(pt1, pt4);
                             const line2 = new McDbLine(pt2, pt3);
                             const _line1 = new McDbLine(_pt1, _pt4);
                             const _line2 = new McDbLine(_pt2, _pt3);
                             let line1ClosePt, line2ClosePt;
                             pt1.distanceTo(insterPt) < pt4.distanceTo(insterPt) ? line1ClosePt = pt1.clone() : line1ClosePt = pt4.clone();
                             pt2.distanceTo(insterPt) < pt3.distanceTo(insterPt) ? line2ClosePt = pt2.clone() : line2ClosePt = pt3.clone();
                             const lineInsterPts1 = line1.IntersectWith(_line1, McDb.Intersect.kExtendBoth)
                             const lineInsterPts2 = line1.IntersectWith(_line2, McDb.Intersect.kExtendBoth)
                             const lineInsterPts3 = line2.IntersectWith(_line1, McDb.Intersect.kExtendBoth)
                             const lineInsterPts4 = line2.IntersectWith(_line2, McDb.Intersect.kExtendBoth)
                             const _point1 = lineInsterPts1.length() > 0 ? lineInsterPts1.at(0) : line1ClosePt;
                             const _point2 = lineInsterPts2.length() > 0 ? lineInsterPts2.at(0) : line1ClosePt;
                             const _point3 = lineInsterPts3.length() > 0 ? lineInsterPts3.at(0) : line2ClosePt;
                             const _point4 = lineInsterPts4.length() > 0 ? lineInsterPts4.at(0) : line2ClosePt;
                             const inflectioPoints = [_point1, _point2, _point3, _point4];
                             const r = inflectioPoints.filter((pt) => {
   
                                 const v = pt.sub(insterPt);
                                 const angle3 = v.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                                 return this.isAngleBetween(angle3, angle1, angle2)
                             })
                             if (r.length) {
   
                                 turnArr.push(r[0])
                                 const point = r[0];
                                 const _r = inflectioPoints.filter((pt) => {
   
                                     const v = pt.sub(insterPt);
                                     const _v = point.sub(insterPt)
                                     const angle = v.angleTo2(_v, McGeVector3d.kNegateZAxis);
                                     return Math.abs(angle - Math.PI) < this.dol
                                 })
                                 if (_r.length) turnArr.push(_r[0])
                             }
                             this.turnPointArr.push(...turnArr);
                             this.breakPtsCount.push(0);
                             const _wall = wall.clone() as McDbTestWall;
                             _wall.turnPoints = [..._wall.turnPoints, ...turnArr];
                             _wall.addInsterPoints([insterPt]);
                             _wall.addBreakPtsCount([0]);
                             MxCpp.getCurrentMxCAD().drawEntity(_wall);
                             id.erase();
                         } else {
   
                             // 没有拐角直接根据断点绘制
                             this.pointArr.push(..._pointArr);
                             this.breakPtsCount.push(_pointArr.length);
                             const _wall = wall.clone() as McDbTestWall;
                             _wall.addBreakPoints(_pointArr);
                             _wall.addInsterPoints([insterPt]);
                             _wall.addBreakPtsCount([_pointArr.length]);
                             MxCpp.getCurrentMxCAD().drawEntity(_wall);
                             id.erase();
                         }
                     }

                 });
             }
         }
     }
     // 计算角度方向是否在指定角度范围内
     function isAngleBetween(angleRad: number, startRad: number, endRad: number) {
   
             let minRad, maxRad
             if (startRad - endRad > 0) {
   
                 minRad = endRad;
                 maxRad = startRad;
             } else {
   
                 minRad = startRad;
                 maxRad = endRad;
             }
             if (maxRad - minRad > Math.PI) {
   
                 return angleRad <= minRad || angleRad >= maxRad;
             } else {
   
                 return angleRad >= minRad && angleRad <= maxRad;
             }
         }

4.整合绘制墙体方法:MxdrawWalls

// 绘制墙体类
   class MxdrawWalls {
   
       // 墙体开始点
       private startPoint: McGePoint3d = new McGePoint3d();
       // 墙体结束点
       private endPoint: McGePoint3d = new McGePoint3d();
       // 墙体宽度
       private wallWidth: number = 10;
       // 断点集合
       private pointArr: McGePoint3d[] = [];
       // 拐点集合
       private turnPointArr: McGePoint3d[] = [];
       // 交点集合
       private insterPointArr: McGePoint3d[] = [];
       // 单次断点数集合
       private breakPtsCount: number[] = [];
       // 精度
       private dol = 0.00001;
       // 获取相交墙体
       public getIntersectingWalls(startPoint: McGePoint3d, endPoint: McGePoint3d, wallWidth: number): McObjectId[] {
   
           this.startPoint = startPoint.clone();
           this.endPoint = endPoint.clone();
           this.wallWidth = wallWidth;
           const intersectingWalls: McObjectId[] = [];
           const {
    pt1, pt3, line } = getPolyline(startPoint, endPoint, wallWidth);
           const length = line.getLength().val;
           // 设置过滤器,过滤出自定义实体
           let filter = new MxCADResbuf();
           filter.AddString("McDbCustomEntity", 5020);
           const ss = new MxCADSelectionSet();
           ss.crossingSelect(pt1.x - length, pt1.y - length, pt3.x + length, pt3.y + length, filter);
           // 与其他墙体相交
           if (ss.count() !== 0) {
   
               ss.forEach(id => {
   
                   const ent = id.getMcDbEntity();
                   if ((ent as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                       intersectingWalls.push(id);
                   }
               });
           }
           return intersectingWalls;
       }
       // 初始绘制墙体
       public drawWall(startPoint: McGePoint3d, endPoint: McGePoint3d, wallWidth: number): McObjectId {
   
           const wallObjIds = this.getIntersectingWalls(startPoint, endPoint, wallWidth);
           this.dealingWithWalls(wallObjIds);
           const wallId = this.draw();
           MxCpp.getCurrentMxCAD().updateDisplay();
           return wallId
       }
       private isAngleBetween(angleRad: number, startRad: number, endRad: number) {
   
           let minRad, maxRad
           if (startRad - endRad > 0) {
   
               minRad = endRad;
               maxRad = startRad;
           } else {
   
               minRad = startRad;
               maxRad = endRad;
           }
           if (maxRad - minRad > Math.PI) {
   
               return angleRad <= minRad || angleRad >= maxRad;
           } else {
   
               return angleRad >= minRad && angleRad <= maxRad;
           }
       }
       // 处理相交墙体得到断点与拐点
       private dealingWithWalls(wallObjIds: McObjectId[]) {
   
           const {
    pl, pt1, pt2, pt3, pt4, line } = getPolyline(this.startPoint, this.endPoint, this.wallWidth);
           if (wallObjIds.length != 0) {
   
               // 与新墙体有交点的墙体集合
               const wallArr = [];
               // 与其他墙体相交
               wallObjIds.forEach(id => {
   
                   const entity = id.getMcDbEntity();
                   if ((entity as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                       const wall = entity.clone() as McDbTestWall
                       const {
    pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line } = getPolyline(wall.getStartPoint(), wall.getEndPoint(), wall.wallWidth);
                       const _pointArr: McGePoint3d[] = [];
                       _pl.IntersectWith(pl, McDb.Intersect.kOnBothOperands).forEach(item => _pointArr.push(item));
                       if (_pointArr.length > 0) {
   
                           wallArr.push({
    id, wall, pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line, pointArr: _pointArr })
                       }
                   }
               });
               if (wallArr.length != 0) {
   
                   wallArr.forEach(item => {
   
                       const {
    id, wall, pl: _pl, pt1: _pt1, pt2: _pt2, pt3: _pt3, pt4: _pt4, line: _line, pointArr: _pointArr } = item;
                       /**
                        * 根据交点位置判断是否是拐点
                        * 中心相交的交点与比对中心线端点距离小于1/2墙宽的都是拐点
                        */
                       const insterPointArr = (line as McDbLine).IntersectWith(_line as McDbLine, McDb.Intersect.kExtendBoth);
                       if (insterPointArr.length() > 0) {
   
                           const insterPt = insterPointArr.at(0);
                           this.insterPointArr.push(insterPt);
                           const dist1 = insterPt.distanceTo(_line.startPoint);
                           const dist2 = insterPt.distanceTo(_line.endPoint);
                           const dist3 = insterPt.distanceTo(line.startPoint);
                           const dist4 = insterPt.distanceTo(line.endPoint);
                           let vec, _vec;
                           dist3 < dist4 ? vec = (line as McDbLine).endPoint.sub(insterPt).normalize() :
                               vec = (line as McDbLine).startPoint.sub(insterPt).normalize();
                           dist1 < dist2 ? _vec = (_line as McDbLine).endPoint.sub(insterPt).normalize() :
                               _vec = (_line as McDbLine).startPoint.sub(insterPt).normalize();
                           const angle1 = vec.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                           const angle2 = _vec.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                           if ((dist1 <= wall.wallWidth / 2 || dist2 <= wall.wallWidth / 2) &&
                               (dist3 <= this.wallWidth / 2 || dist4 <= this.wallWidth / 2)
                           ) {
   
                               // 绘制拐角
                               const turnArr = []
                               const line1 = new McDbLine(pt1, pt4);
                               const line2 = new McDbLine(pt2, pt3);
                               const _line1 = new McDbLine(_pt1, _pt4);
                               const _line2 = new McDbLine(_pt2, _pt3);
                               let line1ClosePt, line2ClosePt;
                               pt1.distanceTo(insterPt) < pt4.distanceTo(insterPt) ? line1ClosePt = pt1.clone() : line1ClosePt = pt4.clone();
                               pt2.distanceTo(insterPt) < pt3.distanceTo(insterPt) ? line2ClosePt = pt2.clone() : line2ClosePt = pt3.clone();
                               const lineInsterPts1 = line1.IntersectWith(_line1, McDb.Intersect.kExtendBoth)
                               const lineInsterPts2 = line1.IntersectWith(_line2, McDb.Intersect.kExtendBoth)
                               const lineInsterPts3 = line2.IntersectWith(_line1, McDb.Intersect.kExtendBoth)
                               const lineInsterPts4 = line2.IntersectWith(_line2, McDb.Intersect.kExtendBoth)
                               const _point1 = lineInsterPts1.length() > 0 ? lineInsterPts1.at(0) : line1ClosePt;
                               const _point2 = lineInsterPts2.length() > 0 ? lineInsterPts2.at(0) : line1ClosePt;
                               const _point3 = lineInsterPts3.length() > 0 ? lineInsterPts3.at(0) : line2ClosePt;
                               const _point4 = lineInsterPts4.length() > 0 ? lineInsterPts4.at(0) : line2ClosePt;
                               const inflectioPoints = [_point1, _point2, _point3, _point4];
                               const r = inflectioPoints.filter((pt) => {
   
                                   const v = pt.sub(insterPt);
                                   const angle3 = v.angleTo2(McGeVector3d.kXAxis, McGeVector3d.kNegateZAxis);
                                   return this.isAngleBetween(angle3, angle1, angle2)
                               })
                               if (r.length) {
   
                                   turnArr.push(r[0])
                                   const point = r[0];
                                   const _r = inflectioPoints.filter((pt) => {
   
                                       const v = pt.sub(insterPt);
                                       const _v = point.sub(insterPt)
                                       const angle = v.angleTo2(_v, McGeVector3d.kNegateZAxis);
                                       return Math.abs(angle - Math.PI) < this.dol
                                   })
                                   if (_r.length) turnArr.push(_r[0])
                               }
                               this.turnPointArr.push(...turnArr);
                               this.breakPtsCount.push(0);
                               const _wall = wall.clone() as McDbTestWall;
                               _wall.turnPoints = [..._wall.turnPoints, ...turnArr];
                               _wall.addInsterPoints([insterPt]);
                               _wall.addBreakPtsCount([0]);
                               MxCpp.getCurrentMxCAD().drawEntity(_wall);
                               id.erase();
                           } else {
   
                               // 没有拐角直接根据断点绘制
                               this.pointArr.push(..._pointArr);
                               this.breakPtsCount.push(_pointArr.length);
                               const _wall = wall.clone() as McDbTestWall;
                               _wall.addBreakPoints(_pointArr);
                               _wall.addInsterPoints([insterPt]);
                               _wall.addBreakPtsCount([_pointArr.length]);
                               MxCpp.getCurrentMxCAD().drawEntity(_wall);
                               id.erase();
                           }
                       }

                   });
               }
           }
       }
       // 绘制墙体
       private draw(): McObjectId {
   
           const mxcad = MxCpp.getCurrentMxCAD();
           const wall = new McDbTestWall();
           wall.setEndPoint(this.endPoint);
           wall.setStartPoint(this.startPoint);
           wall.wallWidth = this.wallWidth;
           if (this.pointArr && this.pointArr.length) {
   
               wall.addBreakPoints(this.pointArr)
           }
           wall.turnPoints = this.turnPointArr ? this.turnPointArr : [];
           if (this.insterPointArr && this.insterPointArr.length) {
   
               wall.addInsterPoints(this.insterPointArr)
           }
           if (this.breakPtsCount && this.breakPtsCount.length) {
   
               wall.addBreakPtsCount(this.breakPtsCount)
           }
           return mxcad.drawEntity(wall);
       }
      // 更新墙体
       public updateWall(wallId: McObjectId, isRedraw: Boolean) {
   
           const wall = wallId.getMcDbEntity() as McDbTestWall;
           if (wall.objectName === "McDbCustomEntity" && (wall as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
               const wallClone = wall.clone() as McDbTestWall;
               // 先修改移动前相交墙体里的断点和拐点
               const oldWallObjIds = this.getIntersectingWalls(wall.oldStartPoint, wall.oldEndPoint, wall.wallWidth);
               // 更新与墙体相交的墙
               oldWallObjIds.forEach(id => {
   
                   const _wall = (id.getMcDbEntity()) as McDbTestWall;
                   _wall.breakPoints = _wall.breakPoints.filter(pt => {
   
                       const r = wallClone.breakPoints.filter(point => point.distanceTo(pt) < this.dol);
                       return r.length === 0;
                   });
                   _wall.turnPoints = _wall.turnPoints.filter(pt => {
   
                       const r = wallClone.turnPoints.filter(point => point.distanceTo(pt) < this.dol);
                       return r.length === 0;
                   });
                   _wall.insterPoints = _wall.insterPoints.filter((pt, index) => {
   
                       const r = wallClone.insterPoints.filter(point => point.distanceTo(pt) < this.dol);
                       if (r.length === 0) {
   
                           return true
                       } else {
   
                           _wall.breakPtsCounts.splice(index, 1);
                       }
                   });
                   _wall.assertObjectModification(true);
               });
               // 是否重绘墙体,重新计算墙体点位
               if (isRedraw) {
   
                   wallId.erase();
                   setTimeout(() => {
   
                       this.drawWall(wall.getStartPoint(), wall.getEndPoint(), wall.wallWidth);
                   }, 0)
               };
           } else {
   
               return
           }
       }

5.调用 MxdrawWalls 绘制墙体

// 绘制墙体
   async function drawWall() {
   
       const getWallWidth = new MxCADUiPrDist();
       getWallWidth.setMessage(`\n${
     t('请设置墙体宽度')}:`);
       let wallWidth = await getWallWidth.go();
       if (!wallWidth) wallWidth = 30;
       while (true) {
   
           const getPoint1 = new MxCADUiPrPoint();
           getPoint1.setMessage(`\n${
     t('请设置墙体起点')}:`);
           const pt1 = await getPoint1.go();
           if (!pt1) break;

           const getDist = new MxCADUiPrDist();
           getDist.setBasePt(pt1);
           getDist.setMessage(`\n${
     t('请设置墙体长度')}:`);
           let pt2 = new McGePoint3d();
           getDist.setUserDraw((pt, pw) => {
   
               const v = pt1.sub(pt).normalize().perpVector().mult(wallWidth / 2);
               const line1 = new McDbLine(pt1.clone().addvec(v), pt.clone().addvec(v));
               pw.setColor(0x0000FF);
               pw.drawMcDbEntity(line1);

               const line2 = new McDbLine(pt1.clone().addvec(v.clone().negate()), pt.clone().addvec(v.clone().negate()));
               pw.setColor(0xFF0000);
               pw.drawMcDbEntity(line2);
               pt2 = pt.clone();
           });
           const dist = await getDist.go();
           if (!dist) break;
           const v = pt2.sub(pt1).normalize().mult(dist);
           const endPt = pt1.clone().addvec(v)
           const wall = new MxdrawWalls()
           wall.drawWall(pt1, endPt, wallWidth);
       }
   }

6.夹点编辑、实体删除情况处理
调用夹点编辑监听事件,监听墙体变化,当墙体位置发生改变则触发墙体更新方法,参考代码:

const mxcad: McObject = MxCpp.getCurrentMxCAD();
     // 监听wall夹点变化
     mxcad.mxdraw.on("objectGripEdit", (grips) => {
   
         grips.forEach((grip) => {
   
             const id = new McObjectId(grip.id, grip.type === "mxcad" ? McObjectIdType.kMxCAD : McObjectIdType.kMxDraw);
             if (id.isErase()) return;
             const wall = id.getMcDbEntity() as McDbTestWall;
             if(!wall) return;

             if (wall.objectName === "McDbCustomEntity" && (wall as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                 // 更新绘制wall
                 const newWall = new MxdrawWalls();
                 newWall.updateWall(id, true);
                 mxcad.clearMxCurrentSelect();
             };
         })
     })

调用实体选择监听事件,监听实体选择,若监听到选择的墙体被删除则触法墙体更新方法,参考代码:

     // 监听mxcad选择,若wall被删除则触发更新
     const oldSelectIds: McObjectId[] = [];
     mxcad.on("selectChange", (ids: McObjectId[]) => {
   
         if (ids.length > 0) {
   
             ids.forEach(id => {
   
                 const entity = id.getMcDbEntity();
                 if (entity && entity.objectName === "McDbCustomEntity" && (entity as McDbCustomEntity).getTypeName() === "McDbTestWall") {
   
                     oldSelectIds.push(id)
                 }
             })
         } else {
   
             setTimeout(()=>{
   
                 oldSelectIds.forEach(id => {
   
                     if (id.isErase()) {
   
                         const newWall = new MxdrawWalls();
                         newWall.updateWall(id, false);
                     }
                 });
                 oldSelectIds.length = 0;
             },0)
         }
     })

功能实践

在线示例demo地址:https://demo.mxdraw3d.com:3000/mxcad/
墙体绘制效果展示:
image-20241126100651820.png

相关文章
|
5天前
|
JavaScript C++
在线CAD绘制门和窗(网页CAD控件二开家装设计软件)
Mxcad 是一个基于 TypeScript 和 C++ 开发的网页 CAD 底层平台,提供丰富的开发接口,适用于快速构建与专业领域相关的网页 CAD 应用。本文以家装行业为例,详细介绍了如何使用 Mxcad 实现墙体、单开门和标准窗等实体,并实现这些实体之间的联动。 通过自定义实体类(如 `McDbTestStandardWindow` 和 `McDbTestSingleDoor`),可以轻松绘制标准窗和单开门,并支持用户交互设置尺寸和位置。这些实体能够自动识别并关联墙体,确保在靠近墙体时自动对齐和调整尺寸。同时,通过监听夹点编辑事件,实现了动态更新和联动效果。
|
2月前
|
存储 前端开发 搜索推荐
(前端直接编辑CAD)网页CAD二次开发中线型表的使用方法
在DWG数据库中,线型样式存储在线型样式表 `McDbLinetypeTable` 中,每个线型表记录对象 `McDbLinetypeTableRecord` 对应一种线型样式。本文介绍了如何获取、添加、遍历、删除和修改线型样式,并提供了绘制不同线型的示例代码,包括虚线、点划线和带文字的线型。通过在线示例demo,用户可以实践修改CAD图纸中的实体线型及其样式。
|
4月前
|
JavaScript 前端开发 API
在线三维CAD中创建一个三维管道模型(网页浏览编辑三维CAD)
本文介绍了如何使用mxcad3d创建三维管道模型。mxcad3d提供了丰富的API,使复杂的管道结构设计变得直观简便。首先需安装mxcad包并初始化项目。接着,通过编写JavaScript函数实现圆角方管的绘制,并将其添加到web界面中。点击绘制按钮即可生成管道模型并实时展示。这为网页CAD中的三维建模任务提供了强大支持。相关代码与项目可在[mxcad3d官方仓库](https://gitee.com/mxcadadox/mxcad_docs/tree/master/examples3D/Test3dPipe.7z)获取。
在线三维CAD中创建一个三维管道模型(网页浏览编辑三维CAD)
|
5月前
|
API 开发者
在线CAD实现图纸比较功能
MXCAD提供了一项实用的图纸比对功能,帮助设计师高效识别不同版本CAD图纸间的改动。用户只需几个简单步骤即可启动比对过程:打开MXCAD在线示例,上传目标图纸,选择“图纸比对”并加载待比对文件。系统会清晰标出所有差异,甚至支持实体定位以便更直观地查看变化细节。此外,MXCAD还开放了相关API,允许开发者根据具体需求进行定制化二次开发,如利用`McObject.loadDwgBackground()`方法加载背景图纸并通过`MxCompare`类获取差异数据等。关注“梦想云图网页CAD”公众号了解更多资讯。
在线CAD实现图纸比较功能
(在线编辑DWG)网页CAD二次开发实现多重引线功能
本章介绍如何使用 mxcad 插件在 CAD 图纸中实现箭头引注功能。用户可通过点击画布确定箭头起点和引线顶点,自定义箭头形状、上标和下标文字内容及位置,提高图纸的完整性和可读性。功能实现包括自定义箭头引注类、注册自定义类信息和调用自定义类。示例代码展示了详细的实现步骤,用户可根据需求进行二次开发。在线示例 demo 可供参考。
|
4月前
|
前端开发 API
(WEB前端编辑DWG)在线CAD如何实现图形识别功能
mxcad 提供的图形识别功能可帮助用户快速识别和提取 CAD 图纸中的各种图形,如直线、多段线、弧线、圆及图块,显著提升设计效率。此功能不仅适用于图形分类,还能进行数量统计和快速定位,减少手动操作。用户可通过 API 进行二次开发,自定义识别逻辑。具体步骤包括打开在线示例、选择识别功能、设置识别参数并开始识别。更多开发文档请关注公众号:梦想云图网页 CAD。
|
7月前
|
数据库
在线CAD二次开发块表(网页预览编辑cad插件)
网页CAD二次开发块表,在DWG数据库中,所有图块都存放在块表McDbBlockTable()中,块表中每一条记录称为图块记录对象McDbBlockTableRecord(),图块记录中存放着所有实体数据,用户可以通过改变图块的属性设置来修改其对应着的实体数据。
在线CAD二次开发块表(网页预览编辑cad插件)
|
5月前
|
开发框架 前端开发 JavaScript
网页CAD中二维CAD图转三维CAD的方法
本文介绍了一种将网页CAD中的二维图纸转换成三维模型的方法,特别聚焦于通过拉伸平面图形至一定高度来实现三维效果。文中利用了mxcad和mxcad3d两个框架,前者负责读取和解析二维CAD图纸,后者则基于这些数据构建三维模型。文章详细阐述了安装配置步骤及代码实现细节,包括创建项目、安装依赖、编写HTML与JavaScript代码等,并提供了完整的示例代码。最终实现了从二维图纸自动转换并展示三维模型的功能,同时添加了交互元素以方便用户操作。
网页CAD中二维CAD图转三维CAD的方法
|
5月前
【qt】平面CAD(计算机辅助设计 )项目 上
【qt】平面CAD(计算机辅助设计 )项目 上
60 0
|
8月前
|
开发工具 开发者
谷歌浏览器打开DWG图纸,实现圆转多边形功能(在线CAD开发教程)
本文介绍了如何使用在线CAD SDK实现圆转多边形功能。首先,需搭建绘图环境和添加命令行交互。接着,通过mxcad库,根据用户输入的边数实现两种转换方式:内接于圆(目标圆为多边形外接圆)和外切于圆(目标圆为多边形内切圆)。具体实现包括选中圆、获取边数、选择转换方式,然后根据用户选择绘制多边形。最终展示了转换效果。
谷歌浏览器打开DWG图纸,实现圆转多边形功能(在线CAD开发教程)