要素线高程修改c#版
自己之前写过lisp版的,
居然全忘了,
上周五(2026年1月23日)用到这个功能,
让ai写程序,
写的乱七八糟,
达不到预期,
于是自己又写了c#程序(压根就没想到自己之前的lisp代码)
Civil 3d 要素线高程缩放 - david96007 - 博客园
因为时间仓促,
程序中的bug并没有被发现,
今天再次测试,
找到了bug,
让ai给修改了一下(lisp程序也完善了一下),
现在把完整代码贴在此,
万一哪一天ai搜索,
也能提供一点儿信息!
(代码未经测试)
public void MyCommand_TT() // This method can have any name { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = Application.DocumentManager.MdiActiveDocument.Database; // 创建选择过滤器,只允许选择要素线 TypedValue[] typval = new TypedValue[1]; typval[0] = new TypedValue((int)DxfCode.Start, "AECC_FEATURE_LINE"); SelectionFilter filter = new SelectionFilter(typval); // 提示用户选择要素线 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择要素线:"; pso.MessageForRemoval = "\n移除要素线:"; PromptSelectionResult psr = ed.GetSelection(pso, filter); if (psr.Status != PromptStatus.OK) return; // 新增:让用户输入缩放系数(替代固定的0.3048) PromptDoubleOptions pdo = new PromptDoubleOptions("\n请输入高程缩放系数 (默认0.3048):"); pdo.AllowNegative = false; // 禁止负数 pdo.AllowZero = false; // 禁止0 pdo.DefaultValue = 0.3048; // 默认值 PromptDoubleResult pdr = ed.GetDouble(pdo); if (pdr.Status != PromptStatus.OK) { ed.WriteMessage("\n输入无效,操作取消。"); return; } double factor = pdr.Value; // 使用用户输入的系数 // 定义缩放系数(可根据需要修改,或改为用户输入) int modifiedCount = 0; // ========== 核心修改:第一步 - 批量备份所有要素线的原始高程 ========== // 存储结构:Key=要素线ObjectId,Value=该要素线所有点的原始高程列表 Dictionary<ObjectId, List<double>> originalElevations = new Dictionary<ObjectId, List<double>>(); // 先开启只读事务,批量提取所有点的原始高程(避免联动修改影响) using (Transaction readTr = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in psr.Value.GetObjectIds()) { // 以只读方式打开要素线 FeatureLine fl = readTr.GetObject(id, OpenMode.ForRead) as FeatureLine; if (fl == null) continue; // 获取所有点(包含高程) var pts = fl.GetPoints(FeatureLinePointType.AllPoints); List<double> elevList = new List<double>(); // 计算有效点数(闭合要素线跳过最后一个点) int n = pts.Count; if (pts.Count > 0 && pts[0].DistanceTo(pts[n - 1]) < 1e-6) { n = n - 1; // 闭合要素线,最后一个点与第一个点重合,跳过 } // 备份前n个点的原始高程 for (int i = 0; i < n; i++) { elevList.Add(pts[i].Z); // 仅存储原始高程值 } // 将备份数据存入字典 originalElevations.Add(id, elevList); } readTr.Commit(); // 只读事务也需Commit释放资源 } // ========== 第二步 - 基于备份的原始高程批量修改 ========== using (Transaction writeTr = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in psr.Value.GetObjectIds()) { // 跳过无备份数据的要素线 if (!originalElevations.ContainsKey(id)) continue; // 以写方式打开要素线 FeatureLine fl = writeTr.GetObject(id, OpenMode.ForWrite) as FeatureLine; if (fl == null) continue; // 获取该要素线的原始高程备份 List<double> elevList = originalElevations[id]; int n = elevList.Count; // 遍历所有点,使用原始高程计算新值 for (int i = 0; i < n; i++) { // 基于原始高程计算新高程(仅乘一次系数,避免联动影响) double newElevation = elevList[i] * factor; // 设置新高程(即使点关联,也只按原始值修改一次) fl.SetPointElevation(i, newElevation); } modifiedCount++; } writeTr.Commit(); // 提交修改 } // 输出结果提示 ed.WriteMessage($"\n已成功修改 {modifiedCount} 条要素线的高程,所有点高程乘以系数 {factor}。"); }

浙公网安备 33010602011771号