Civil 3d 纵断面标签添加(ai写的代码)
qq群友讨论如何添在纵断面图中添加纵断面标签。
经过搜索,
在au英文社区中找到了这个帖子,
Jeff_M给出了样例代码,
但不是很完整,
于是用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 }

浙公网安备 33010602011771号