欢迎来到我的博客
Civil 3D开发与应用,欢迎加入QQ群:484124761
AutoCAD开发,欢迎加入QQ群:193522571

Civil 3d 纵断面标签添加(ai写的代码)

qq群友讨论如何添在纵断面图中添加纵断面标签。

经过搜索,

在au英文社区中找到了这个帖子,

给出了样例代码,
但不是很完整,

于是用ai写了一段相对完成的代码,

分享到这里!

  1 using System;
  2 using System.Collections.Generic;
  3 using Autodesk.AutoCAD.ApplicationServices;
  4 using Autodesk.AutoCAD.DatabaseServices;
  5 using Autodesk.AutoCAD.EditorInput;
  6 using Autodesk.AutoCAD.Runtime;
  7 using Autodesk.Civil;
  8 using Autodesk.Civil.ApplicationServices;
  9 using Autodesk.Civil.DatabaseServices;
 10 using Autodesk.Civil.DatabaseServices.Styles;
 11 using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
 12 namespace Widgets
 13 {
 14     /// <summary>
 15     /// 纵断面图标签添加(简化版,无反射)。
 16     /// 参照 Autodesk 论坛 ProfileLabelSetStyle 方案:
 17     /// https://forums.autodesk.com/t5/civil-3d-customization-forum/add-profile-label-set-to-profile-in-3d-civil-using-vb-net-api/m-p/9408920
 18     /// </summary>
 19     public static class ProfileViewLabelsSimple
 20     {
 21         /// <summary>命令入口。</summary>
 22         public static void AddLabels()
 23         {
 24             AddLabelsInteractive();
 25         }
 26         /// <summary>
 27         /// 拾取纵断面图,按 ProfileLabelSetStyle 为各纵断面创建标签组。
 28         /// </summary>
 29         public static void AddLabelsInteractive()
 30         {
 31             Document doc = AcadApp.DocumentManager.MdiActiveDocument;
 32             Editor ed = doc.Editor;
 33             if (!TrySelectProfileView(ed, out ObjectId profileViewId))
 34                 return;
 35             PromptKeywordOptions pko = new PromptKeywordOptions(
 36                 "\n操作 [全部(A)/替换(R)/列表(E)]: ", "All Replace List");
 37             pko.Keywords.Default = "All";
 38             PromptResult pkr = ed.GetKeywords(pko);
 39             if (pkr.Status != PromptStatus.OK)
 40                 return;
 41             using (Transaction tr = doc.TransactionManager.StartTransaction())
 42             {
 43                 ProfileView profileView = tr.GetObject(profileViewId, OpenMode.ForRead) as ProfileView;
 44                 if (profileView == null)
 45                 {
 46                     ed.WriteMessage("\n无法读取纵断面图。");
 47                     return;
 48                 }
 49                 if (pkr.StringResult == "List")
 50                 {
 51                     ListExistingLabels(ed, tr, profileView);
 52                     tr.Commit();
 53                     return;
 54                 }
 55                 bool replaceExisting = pkr.StringResult == "Replace";
 56                 ObjectId labelSetStyleId = ResolveLabelSetStyleId(ed);
 57                 if (labelSetStyleId.IsNull)
 58                 {
 59                     ed.WriteMessage("\n未找到可用的 ProfileLabelSetStyle。");
 60                     return;
 61                 }
 62                 ProfileLabelSetStyle labelSetStyle =
 63                     tr.GetObject(labelSetStyleId, OpenMode.ForRead) as ProfileLabelSetStyle;
 64                 if (labelSetStyle == null)
 65                 {
 66                     ed.WriteMessage("\n无法读取 ProfileLabelSetStyle。");
 67                     return;
 68                 }
 69                 ed.WriteMessage($"\n使用标签集样式: {labelSetStyle.Name},共 {labelSetStyle.Count} 项。");
 70                 int created = ApplyLabelSetToProfileView(
 71                     tr, profileViewId, profileView, labelSetStyle, replaceExisting, ed);
 72                 tr.Commit();
 73                 ed.WriteMessage($"\n完成,新建标签组 {created} 个。");
 74             }
 75         }
 76         /// <summary>
 77         /// 遍历 GraphOverrides,为每个 ProfileOverride 应用标签集。
 78         /// </summary>
 79         public static int ApplyLabelSetToProfileView(
 80             Transaction tr,
 81             ObjectId profileViewId,
 82             ProfileView profileView,
 83             ProfileLabelSetStyle labelSetStyle,
 84             bool replaceExisting,
 85             Editor ed = null)
 86         {
 87             if (profileView == null || labelSetStyle == null)
 88                 return 0;
 89             ProfileOverrideCollection overrides = profileView.GraphOverrides;
 90             if (overrides == null || overrides.Count == 0)
 91             {
 92                 ed?.WriteMessage("\n纵断面图中没有纵断面(GraphOverrides 为空)。");
 93                 return 0;
 94             }
 95             ProfileViewStyle profileViewStyle = null;
 96             if (!profileView.StyleId.IsNull)
 97             {
 98                 profileViewStyle = tr.GetObject(profileView.StyleId, OpenMode.ForRead) as ProfileViewStyle;
 99             }
100             int created = 0;
101             foreach (ProfileOverride profileOverride in overrides)
102             {
103                 if (profileOverride == null || profileOverride.ProfileId.IsNull)
104                     continue;
105                 ObjectId profileId = profileOverride.ProfileId;
106                 Profile profile = tr.GetObject(profileId, OpenMode.ForRead) as Profile;
107                 string profileName = profile?.Name ?? profileOverride.ProfileName ?? profileId.ToString();
108                 ed?.WriteMessage($"\n纵断面 \"{profileName}\":");
109                 if (replaceExisting)
110                 {
111                     EraseExistingLabelGroups(tr, profileViewId, profileId, ed);
112                 }
113                 int count = ApplyLabelSetToProfile(
114                     tr, profileViewId, profileId, profileViewStyle, labelSetStyle, ed);
115                 created += count;
116                 ed?.WriteMessage($"  新建 {count} 个标签组。");
117             }
118             return created;
119         }
120         /// <summary>
121         /// 按标签集定义,为指定纵断面 + 纵断面图创建标签组。
122         /// </summary>
123         public static int ApplyLabelSetToProfile(
124             Transaction tr,
125             ObjectId profileViewId,
126             ObjectId profileId,
127             ProfileViewStyle profileViewStyle,
128             ProfileLabelSetStyle labelSetStyle,
129             Editor ed = null)
130         {
131             if (labelSetStyle == null || labelSetStyle.Count == 0)
132                 return 0;
133             int created = 0;
134             // 逆序遍历,与论坛示例一致,尽量保持 UI 中标签组顺序
135             for (int i = labelSetStyle.Count - 1; i >= 0; i--)
136             {
137                 ProfileLabelSetItem item = labelSetStyle[i];
138                 if (item == null)
139                     continue;
140                 ObjectId labelGroupId = CreateLabelGroupFromSetItem(
141                     tr, profileViewId, profileId, profileViewStyle, item);
142                 if (labelGroupId.IsNull)
143                 {
144                     ed?.WriteMessage($"\n  跳过 {item.LabelStyleType}(当前版本不支持或创建失败)。");
145                     continue;
146                 }
147                 ApplyLabelGroupOptions(tr, labelGroupId, item);
148                 created++;
149                 ed?.WriteMessage($"\n  已添加 {item.LabelStyleType}。");
150             }
151             return created;
152         }
153         public static void ListExistingLabels(Editor ed, Transaction tr, ProfileView profileView)
154         {
155             ProfileOverrideCollection overrides = profileView.GraphOverrides;
156             ed.WriteMessage($"\n纵断面图 \"{profileView.Name}\",GraphOverrides 数量: {overrides?.Count ?? 0}");
157             if (overrides == null)
158                 return;
159             foreach (ProfileOverride profileOverride in overrides)
160             {
161                 if (profileOverride == null)
162                     continue;
163                 ObjectIdCollection labelGroupIds = profileOverride.GetProfileLabelGroupIds();
164                 ed.WriteMessage($"\n  纵断面: {profileOverride.ProfileName}  标签组: {labelGroupIds?.Count ?? 0}");
165                 if (labelGroupIds == null)
166                     continue;
167                 foreach (ObjectId lgId in labelGroupIds)
168                 {
169                     if (lgId.IsNull || lgId.IsErased)
170                         continue;
171                     LabelGroup lg = tr.GetObject(lgId, OpenMode.ForRead) as LabelGroup;
172                     if (lg == null)
173                         continue;
174                     ed.WriteMessage(
175                         $"\n    - {lg.GetType().Name}  样式: {lg.StyleName}  子标签数: {lg.SubEntityCount}");
176                 }
177             }
178         }
179         private static void EraseExistingLabelGroups(
180             Transaction tr,
181             ObjectId profileViewId,
182             ObjectId profileId,
183             Editor ed)
184         {
185             RXClass labelGroupClass = ProfileLabelGroup.GetClass(typeof(ProfileLabelGroup));
186             ObjectIdCollection existingIds = ProfileLabelGroup.GetAvailableLabelGroupIds(
187                 labelGroupClass, profileViewId, profileId, true);
188             if (existingIds == null || existingIds.Count == 0)
189                 return;
190             foreach (ObjectId id in existingIds)
191             {
192                 if (id.IsNull || id.IsErased)
193                     continue;
194                 ProfileLabelGroup grp = tr.GetObject(id, OpenMode.ForWrite) as ProfileLabelGroup;
195                 grp?.Erase();
196             }
197             ed?.WriteMessage($"\n  已清除已有标签组 {existingIds.Count} 个。");
198         }
199         private static ObjectId CreateLabelGroupFromSetItem(
200             Transaction tr,
201             ObjectId profileViewId,
202             ObjectId profileId,
203             ProfileViewStyle profileViewStyle,
204             ProfileLabelSetItem item)
205         {
206             ObjectId styleId = item.LabelStyleId;
207             if (styleId.IsNull)
208                 return ObjectId.Null;
209             try
210             {
211                 switch (item.LabelStyleType)
212                 {
213                     case LabelStyleType.ProfileCrestCurve:
214                         return ProfileCrestCurveLabelGroup.Create(profileViewId, profileId, styleId);
215                     case LabelStyleType.ProfileSagCurve:
216                         return ProfileSagCurveLabelGroup.Create(profileViewId, profileId, styleId);
217                     // 论坛示例:ProfileGradeBreaks 使用 ProfilePVILabelGroup.Create
218                     case LabelStyleType.ProfileGradeBreaks:
219                         return ProfilePVILabelGroup.Create(profileViewId, profileId, styleId);
220                     case LabelStyleType.ProfileHorizontalGeometryPoint:
221                     {
222                         ObjectId labelGroupId = ProfileHorizontalGeometryPointLabelGroup.Create(
223                             profileViewId, profileId, styleId);
224                         if (labelGroupId.IsNull)
225                             return ObjectId.Null;
226                         ApplyHorizontalGeometryPointOptions(tr, labelGroupId, item);
227                         return labelGroupId;
228                     }
229                     case LabelStyleType.ProfileLine:
230                         return ProfileLineLabelGroup.Create(profileViewId, profileId, styleId);
231                     case LabelStyleType.ProfileMajorStation:
232                         if (profileViewStyle == null)
233                             return ObjectId.Null;
234                         return ProfileStationLabelGroup.CreateMajor(
235                             profileViewId,
236                             profileId,
237                             styleId,
238                             profileViewStyle.BottomAxis.MajorTickStyle.Interval);
239                     case LabelStyleType.ProfileMinorStation:
240                         if (profileViewStyle == null)
241                             return ObjectId.Null;
242                         return ProfileMinorStationLabelGroup.Create(
243                             profileViewId,
244                             styleId,
245                             profileViewStyle.BottomAxis.MinorTickStyle.Interval);
246                     default:
247                         return ObjectId.Null;
248                 }
249             }
250             catch
251             {
252                 return ObjectId.Null;
253             }
254         }
255         private static void ApplyHorizontalGeometryPointOptions(
256             Transaction tr,
257             ObjectId labelGroupId,
258             ProfileLabelSetItem item)
259         {
260             ProfileHorizontalGeometryPointLabelGroup group =
261                 tr.GetObject(labelGroupId, OpenMode.ForWrite) as ProfileHorizontalGeometryPointLabelGroup;
262             if (group == null)
263                 return;
264             var geometryPoints = group.GetGeometryPointsOptions();
265             Dictionary<AlignmentPointType, bool> labeledPoints = item.GetLabeledAlignmentGeometryPoints();
266             if (geometryPoints == null || labeledPoints == null)
267                 return;
268             geometryPoints.UnSelectAll();
269             foreach (KeyValuePair<AlignmentPointType, bool> pair in labeledPoints)
270             {
271                 if (!pair.Value)
272                     continue;
273                 geometryPoints[pair.Key].Selected = true;
274             }
275             group.SetGeometryPointsOptions(geometryPoints);
276         }
277         private static void ApplyLabelGroupOptions(
278             Transaction tr,
279             ObjectId labelGroupId,
280             ProfileLabelSetItem item)
281         {
282             try
283             {
284                 ProfileLabelGroup group = tr.GetObject(labelGroupId, OpenMode.ForWrite) as ProfileLabelGroup;
285                 if (group == null)
286                     return;
287                 group.DefaultDimensionAnchorOption =
288                     (DimensionAnchorOptionType)item.DimensionAnchorOption;
289                 group.DefaultDimensionAnchorValue = item.DimensionAnchorValue;
290             }
291             catch
292             {
293                 // 部分标签类型不支持锚点选项
294             }
295         }
296         private static ObjectId ResolveLabelSetStyleId(Editor ed)
297         {
298             PromptStringOptions pso = new PromptStringOptions("\nProfileLabelSetStyle 名称 [Standard]: ");
299             pso.AllowSpaces = true;
300             pso.UseDefaultValue = true;
301             pso.DefaultValue = "Standard";
302             PromptResult psr = ed.GetString(pso);
303             if (psr.Status != PromptStatus.OK)
304                 return ObjectId.Null;
305             string inputName = string.IsNullOrWhiteSpace(psr.StringResult) ? "Standard" : psr.StringResult.Trim();
306             CivilDocument civilDoc = CivilApplication.ActiveDocument;
307             if (civilDoc == null)
308                 return ObjectId.Null;
309             ProfileLabelSetStyleCollection styles = civilDoc.Styles.LabelSetStyles.ProfileLabelSetStyles;
310             if (styles == null)
311                 return ObjectId.Null;
312             string[] styleNames = { inputName, "Standard", "标准" };
313             foreach (string name in styleNames)
314             {
315                 try
316                 {
317                     ObjectId id = styles[name];
318                     if (!id.IsNull)
319                         return id;
320                 }
321                 catch
322                 {
323                     // 尝试下一个名称
324                 }
325             }
326             return ObjectId.Null;
327         }
328         private static bool TrySelectProfileView(Editor ed, out ObjectId profileViewId)
329         {
330             profileViewId = ObjectId.Null;
331             PromptEntityOptions peo = new PromptEntityOptions("\n选择纵断面图: ");
332             peo.SetRejectMessage("\n请选择 ProfileView");
333             peo.AddAllowedClass(typeof(ProfileView), true);
334             PromptEntityResult per = ed.GetEntity(peo);
335             if (per.Status != PromptStatus.OK)
336                 return false;
337             profileViewId = per.ObjectId;
338             return true;
339         }
340     }
341 }

 

posted @ 2026-06-04 10:16  david96007  阅读(23)  评论(0)    收藏  举报