C#AutoCAD二次开发打断多段线

在 C# 中进行 AutoCAD 二次开发,实现点击多段线并在点击处打断 2 毫米的功能,核心步骤是:获取点击点、计算打断点、执行打断操作。

核心实现步骤与代码

  1. 定义命令与获取实体
    首先,需要定义一个 AutoCAD 命令,并让用户选择一条多段线。
csharp 复制代码
   using Autodesk.AutoCAD.ApplicationServices;
   using Autodesk.AutoCAD.DatabaseServices;
   using Autodesk.AutoCAD.EditorInput;
   using Autodesk.AutoCAD.Geometry;
   using Autodesk.AutoCAD.Runtime;

   [CommandMethod("BreakPolyline2mm")]
   public void BreakPolyline2mm()
   {
       Document doc = Application.DocumentManager.MdiActiveDocument;
       Database db = doc.Database;
       Editor ed = doc.Editor;

       // 1. 选择一条多段线
       PromptEntityOptions peo = new PromptEntityOptions("
请选择一条多段线: ");
       peo.SetRejectMessage("
请选择一条多段线。");
       peo.AddAllowedClass(typeof(Polyline), true);
       PromptEntityResult per = ed.GetEntity(peo);
       if (per.Status != PromptStatus.OK) return;

       // 2. 获取用户点击的点(在WCS坐标系下)
       Point3d pickedPoint = per.PickedPoint;
       using (Transaction tr = db.TransactionManager.StartTransaction())
       {
           // 打开选中的多段线 Polyline pline = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as Polyline;
           if (pline == null) return;

           // 3. 将点击点转换到多段线的模型空间(OCS)
           Point3d clickedPointOcs = pickedPoint.TransformBy(ed.CurrentUserCoordinateSystem.Inverse());

           // 4. 找到点击点所在的多段线线段及参数
           double paramAtPoint = pline.GetParameterAtPoint(clickedPointOcs);
           int segmentIndex = (int)Math.Floor(paramAtPoint); // 线段索引(从0开始)

           // 5. 计算距离点击点前后各1毫米(共2毫米)的两个打断点 // 获取线段起点和终点的参数 double startParam = segmentIndex;
           double endParam = segmentIndex + 1;

           // 计算线段在参数方向上的单位向量(用于偏移)
           Point3d startPoint = pline.GetPointAtParameter(startParam);
           Point3d endPoint = pline.GetPointAtParameter(endParam);
           Vector3d segmentDirection = (endPoint - startPoint).GetNormal();

           // 计算距离(假设绘图单位为毫米)
           double offsetDistance = 1.0; // 1毫米
           Point3d breakPoint1 = clickedPointOcs segmentDirection * offsetDistance;
           Point3d breakPoint2 = clickedPointOcs + segmentDirection * offsetDistance;

           // 6. 确保打断点在线段范围内(避免超出边界)
           // 计算两个打断点相对于线段起点的参数
           double param1 = pline.GetParameterAtPoint(breakPoint1);
           double param2 = pline.GetParameterAtPoint(breakPoint2);

           // 对参数进行排序,确保 param1 < param2 if (param1 > param2)
           {
               (param1, param2) = (param2, param1);
               (breakPoint1, breakPoint2) = (breakPoint2, breakPoint1);
           }

           // 7. 执行打断操作
           // 使用 BreakAtPoints 方法在两点处打断多段线 DBObjectCollection brokenSegments = pline.GetSplitCurves(new DoubleCollection { param1, param2 });
           if (brokenSegments.Count > 0)
           {
               BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
               // 删除原多段线 pline.Erase();
               // 添加打断后生成的新对象(可能是多段线或直线段)
               foreach (DBObject obj in brokenSegments)
               {
                   Entity newEntity = obj as Entity;
                   if (newEntity != null)
                   {
                       btr.AppendEntity(newEntity);
                       tr.AddNewlyCreatedDBObject(newEntity, true);
                   }
               }
           }

           tr.Commit();
       }
       ed.WriteMessage("
多段线已在点击处成功打断2毫米。");
   }
   ```

2.  **关键逻辑说明**
   *   **参数计算**:`GetParameterAtPoint` 方法用于获取点击点沿多段线的曲线参数,这对于精确定位至关重要。
   *   **打断点计算**:通过获取点击点所在线段的单位方向向量,向两侧各偏移 1 毫米,计算出两个打断点。
   *   **边界处理**:通过 `GetParameterAtPoint` 对计算出的打断点进行反向验证,确保其在线段范围内,并通过排序保证参数顺序正确。
   *   **执行打断**:`GetSplitCurves` 方法是核心,它接受一个参数集合,并在这些参数点处将曲线(多段线)分割。返回的集合包含分割后的新曲线对象。

### 注意事项与优化建议

| 事项 | 说明与建议 |
| :--- | :--- |
| **绘图单位** | 上述代码假设 1 个 AutoCAD 绘图单位代表 1 毫米。如果您的绘图单位是米、英寸等,需要调整 `offsetDistance` 变量的值(例如,对于米制,1毫米应为0.001)。 |
| **点击容差** | 用户点击可能不完全在线上。`GetParameterAtPoint` 方法本身有一定的容差。对于更精确的控制,可以先使用 `GetClosestPointTo` 方法将点击点投影到多段线上,再使用投影点进行计算。 |
| **复杂多段线** | 对于包含圆弧段的多段线,上述基于直线段方向向量的计算方法可能不精确。更通用的方法是使用 `GetPointAtDist` 和 `GetDistAtPoint` 方法,沿曲线路径进行距离计算。 |
| **事务处理** | 所有数据库操作(获取对象、修改、添加新对象)必须在事务 (`Transaction`) 内完成,这是 AutoCAD .NET API 的强制要求。 |
| **错误处理** | 生产代码中应增加 `try-catch` 块以处理可能的异常,例如参数计算错误或对象类型不匹配。 |

**优化后的打断点计算(适用于直线和圆弧段)**:
```csharp
// 替代上述第5步中的向量计算,使用沿曲线的距离进行计算
double distAtClickedPoint = pline.GetDistAtPoint(clickedPointOcs);
double dist1 = distAtClickedPoint - offsetDistance; // 向前1毫米
double dist2 = distAtClickedPoint + offsetDistance; // 向后1毫米

// 确保距离值有效(不小于0,不大于多段线总长)
dist1 = Math.Max(0, Math.Min(pline.Length, dist1));
dist2 = Math.Max(0, Math.Min(pline.Length, dist2));

// 获取打断点
Point3d breakPoint1 = pline.GetPointAtDist(dist1);
Point3d breakPoint2 = pline.GetPointAtDist(dist2);

// 获取对应的参数
double param1 = pline.GetParameterAtPoint(breakPoint1);
double param2 = pline.GetParameterAtPoint(breakPoint2);

此方法通过沿曲线的实际路径测量距离来计算打断点,对直线段和圆弧段都适用,是更健壮的解决方案。

相关推荐
-银雾鸢尾-2 小时前
C#中的万物之父——Object类
开发语言·c#
-银雾鸢尾-2 小时前
C#中的继承
开发语言·c#
-银雾鸢尾-15 小时前
里氏替换原则
开发语言·c#·里氏替换原则
-银雾鸢尾-19 小时前
C#中的索引器
开发语言·c#
en.en..19 小时前
冒泡排序与选择排序完整对比解析
开发语言·数据结构·算法·c#·排序算法
geovindu20 小时前
CSharp: Decorator Pattern
开发语言·后端·c#·装饰器模式·结构型模式
淡海水21 小时前
06-04-YooAsset源码-Unity加密解密服务
前端·unity·性能优化·c#·游戏引擎·yooasset
她说彩礼65万1 天前
C# yeild的使用
开发语言·c#