☰
绘制直线和多段线
2026/10/16 10:16:54 网站建设 项目流程

说明

  • Line(ZwSoft.ZwCAD.DatabaseServices.Line):纯粹两点直线实体,不支持线宽渐变、不能添加中间顶点,老管网部分标准会用到;
  • Polyline多段线:管网主流,支持线宽、拐点;
  • 新增枚举选项,用来控制管线实体类型:生成Line还是Polyline;
  • 在PipeGeomHelper增加CreatePipeLine工具方法;
  • 同时改造Line分支,通过配置切换生成Line / Polyline。

第一步:新增枚举(CommPipe命名空间)

namespace CommPipe { /// <summary> /// 管线绘制交互模式 /// </summary> public enum PipeDrawMode { /// <summary>拾取屏幕两点,直接画线</summary> PickScreenPoint, /// <summary>拾取图上两个管点块实体,提取插入点画线</summary> PickExistPointEntity } /// <summary> /// 管线实体类型:Line简单直线 / Polyline多段线 /// </summary> public enum PipeEntityKind { Line, Polyline } }

CodeDefine增加属性:

public PipeEntityKind PipeEntityKind { get; set; }

PipeGeomHelper 新增 CreatePipeLine 方法

/// <summary> /// 在模型空间创建简单Line直线实体 /// </summary> /// <param name="db">数据库</param> /// <param name="startPt">起点</param> /// <param name="endPt">终点</param> /// <param name="layerName">图层名</param> /// <returns>Line的ObjectId,失败返回Null</returns> public static ObjectId CreatePipeLine(Database db, Point3d startPt, Point3d endPt, string layerName) { if (db == null) return ObjectId.Null; try { using (var tr = db.TransactionManager.StartTransaction()) { ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId(db); BlockTableRecord ms = tr.GetObject(msId, OpenMode.ForWrite) as BlockTableRecord; if (ms == null) { tr.Abort(); return ObjectId.Null; } Line lineEnt = new Line(startPt, endPt); lineEnt.Layer = layerName ?? ""; ms.AppendEntity(lineEnt); tr.AddNewlyCreatedDBObject(lineEnt, true); tr.Commit(); return lineEnt.ObjectId; } } catch (Exception) { return ObjectId.Null; } }

原有CreatePipePolyline保留不动。

OnStartDrawElement 中 Line分支完整代码(同时支持Line/Polyline)

else if (curPipeType == CommPipe.PipeType.Line) { var layerDef = codeDefine.LayerInfo; string targetLayerName = layerDef.LayerKey; ZwSoft.ZwCAD.Colors.Color layerColor = LayerHelper.ParseRawColor(layerDef.ColorRaw); Point3d startPt = Point3d.Origin; Point3d endPt = Point3d.Origin; bool pickOk = false; // 根据配置选择绘制交互模式 if (codeDefine.LineDrawMode == CommPipe.PipeDrawMode.PickScreenPoint) { //模式A:拾取屏幕两点 PromptPointResult pt1 = ed.GetPoint("\n请拾取管线起点:"); if (pt1.Status != PromptStatus.OK) return; PromptPointResult pt2 = ed.GetPoint("\n请拾取管线终点:"); if (pt2.Status != PromptStatus.OK) return; startPt = pt1.Value; endPt = pt2.Value; pickOk = true; } else if (codeDefine.LineDrawMode == CommPipe.PipeDrawMode.PickExistPointEntity) { //模式B:拾取图上已存在管点块 if (!PipeGeomHelper.PickPipePointEntity(ed, "\n请拾取起始管点:", out startPt)) { ed.WriteMessage("\n拾取起始管点失败或用户取消"); return; } if (!PipeGeomHelper.PickPipePointEntity(ed, "\n请拾取终止管点:", out endPt)) { ed.WriteMessage("\n拾取终止管点失败或用户取消"); return; } pickOk = true; } if (!pickOk) { return; } //拾取完成之后,再确保图层存在 using (var trCheckLayer = db.TransactionManager.StartTransaction()) { if (!LayerHelper.IsLayerExists(trCheckLayer, db, targetLayerName)) { LayerHelper.EnsureLayerExist(trCheckLayer, db, targetLayerName, layerColor); } trCheckLayer.Commit(); } ObjectId pipeEntId = ObjectId.Null; if (codeDefine.PipeEntityKind == CommPipe.PipeEntityKind.Line) { // 创建原生Line直线 pipeEntId = PipeGeomHelper.CreatePipeLine(db, startPt, endPt, targetLayerName); } else { // 创建Polyline多段线 Point3dCollection pts = new Point3dCollection(); pts.Add(startPt); pts.Add(endPt); pipeEntId = PipeGeomHelper.CreatePipePolyline(db, pts, targetLayerName); } if (pipeEntId.IsNull) { ed.WriteMessage($"\n绘制管线【{codeDefine.Name}】失败"); return; } // Todo:给pipeEntId实体附加XData业务属性 // 如果是PickExistPointEntity模式,可把两个管点ObjectId写入XData做拓扑 ed.WriteMessage($"\n成功绘制管线【{codeDefine.Name}】"); }

关键点说明

  1. Line实体没有全局线宽属性,线宽要靠CAD图层线宽控制;而Polyline支持每段独立宽度;
  2. 两种实体都只做两点版本;后续如果要做多折管线,只能走Polyline;Line本身不支持多个顶点;
  3. 全部交互逻辑复用,只在最后创建实体时根据PipeEntityKind切换调用不同工具;
  4. 配置存到你的标准模板库,不同管线要素可以自由选:Line/Polyline、拾取屏幕点 / 拾取已有管点。

小提示:模式BPickExistPointEntity当前只判断是BlockReference;后续可以增强PickPipePointEntity,校验块名,防止拾取别的无关块。

如果你需要,我可以把PickPipePointEntity改成重载版本,同时输出拾取到的管点ObjectId,方便后面写拓扑XData。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询