using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Nice3point.Revit.Toolkit.External; using System; using System.Collections; using System.Linq; namespace Szmedi.RvKits.DrawingTools; [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class MergeDimensionsCmd : ExternalCommand { public override void Execute() { MergeExecute(UiDocument); //Result = Result.Succeeded; } public void MergeExecute(UIDocument uidoc) { var doc = uidoc.Document; //视图中所有可见元素Id var list = ( from e in new FilteredElementCollector(doc, doc.ActiveView.Id).WhereElementIsNotElementType() select e.Id.IntegerValue ).ToList(); try { var selectedDims = uidoc.Selection .PickElementsByRectangle(new GenericFilter(), "请框选尺寸标注") .OfType() .ToList(); var dictionary = new Dictionary>(); foreach (Dimension dimension in selectedDims) { Line line = dimension.Curve as Line; if (line != null) { bool flag = false; foreach (var keyValuePair in dictionary) { bool flag3 = ( Math.Abs(keyValuePair.Key.Origin.DistanceTo(line.Origin)) < 0.0001 && Math.Abs(Math.Abs(keyValuePair.Key.Direction.DotProduct(line.Direction)) - 1.0) < 0.0001 ) || Math.Abs( Math.Abs( keyValuePair.Key.Direction.DotProduct(Line.CreateBound(keyValuePair.Key.Origin, line.Origin).Direction) ) - 1.0 ) < 0.0001; if (flag3) { flag = true; keyValuePair.Value.Add(dimension); break; } } if (!flag) { dictionary.Add(line, new List { dimension }); } } } doc.InvokeGroup(_ => { foreach (var keyValuePair in dictionary) { if (keyValuePair.Value.Count >= 1) { try { doc.Invoke(_ => { ReferenceArray referenceArray = new(); View view = keyValuePair.Value.First().View; DimensionType dimensionType = keyValuePair.Value.First().DimensionType; List dimsData = new(); foreach (Dimension dim in keyValuePair.Value) { if (dim.NumberOfSegments > 0) { dimsData.AddRange(from DimensionSegment segment in dim.Segments select new DimData(segment)); } else { dimsData.Add(new DimData(dim)); } foreach (Reference reference in dim.References) { bool flag8 = reference.ElementId != ElementId.InvalidElementId && !list.Contains(reference.ElementId.IntegerValue); if (!flag8 && reference.ElementId != ElementId.InvalidElementId) { if (doc.GetElement(reference.ElementId) is Grid grid) { referenceArray.Append(new Reference(grid)); } else { if (reference.ElementId == ElementId.InvalidElementId) { continue; } referenceArray.Append( doc.GetElement(reference.ElementId) is Level level ? new Reference(level) : reference ); } } } } Dimension dimension3 = doc.Create.NewDimension(view, keyValuePair.Key, referenceArray, dimensionType); if (dimension3 != null) { bool flag14 = TryRemoveZeroes(dimension3, out referenceArray); if (flag14) { Dimension dimension4 = doc.Create.NewDimension( view, keyValuePair.Key, referenceArray, dimensionType ); if (dimension4 != null) { doc.Delete(dimension3.Id); RestoreTextFields(dimension4, dimsData); } } else { RestoreTextFields(dimension3, dimsData); } doc.Delete((from d in keyValuePair.Value select d.Id).ToList()); } }); } catch (Exception) { // ignored } } } }); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { //break; } } public static bool TryRemoveZeroes(Dimension dimension, out ReferenceArray referenceArray) { referenceArray = new ReferenceArray(); Document document = dimension.Document; bool isEmpty = dimension.Segments.IsEmpty; bool result; if (isEmpty) { result = false; } else { for (int i = 0; i < dimension.NumberOfSegments; i++) { DimensionSegment dimensionSegment = dimension.Segments.get_Item(i); double? value = dimensionSegment.Value; bool flag = value != null && Math.Abs(value.Value) < 0.0001; if (!flag) { bool isEmpty2 = referenceArray.IsEmpty; if (isEmpty2) { var refer = dimension.References.get_Item(i); Element element = document.GetElement(refer); if (element is Grid or Level) { refer = new Reference(element); } referenceArray.Append(refer); } var refer1 = dimension.References.get_Item(i + 1); Element element1 = document.GetElement(refer1); if (element1 is Grid or Level) { refer1 = new Reference(element1); } referenceArray.Append(refer1); } } result = referenceArray.Size < dimension.References.Size; } return result; } private static void RestoreTextFields(Dimension dimension, IReadOnlyCollection dimsData) { IEnumerator enumerator = dimension.Segments.GetEnumerator(); while (enumerator.MoveNext()) { DimensionSegment segment = (DimensionSegment)enumerator.Current; DimData dimData = dimsData.FirstOrDefault( d => d.IsMatchValue(segment?.Value) && Math.Abs(d.Origin.DistanceTo(segment.Origin)) < 0.0001 ); if (dimData != null && segment != null) { segment.Prefix = dimData.Prefix; segment.Suffix = dimData.Suffix; segment.Above = dimData.Above; segment.Below = dimData.Below; segment.TextPosition = dimData.TextPosition; } } } } internal class DimData { public DimData(Dimension dimension) { Value = dimension.Value; Origin = dimension.Origin; TextPosition = dimension.TextPosition; Prefix = dimension.Prefix; Suffix = dimension.Suffix; Above = dimension.Above; Below = dimension.Below; } public DimData(DimensionSegment dimension) { Value = dimension.Value; Origin = dimension.Origin; TextPosition = dimension.TextPosition; Prefix = dimension.Prefix; Suffix = dimension.Suffix; Above = dimension.Above; Below = dimension.Below; } public double? Value { get; } public string Prefix { get; } public string Suffix { get; } public string Above { get; } public string Below { get; } public XYZ Origin { get; } public XYZ TextPosition { get; } public bool IsMatchValue(double? value) { bool flag = Value != null && value != null; bool result = flag ? Math.Abs(Value.Value - value.Value) < 0.0001 : Value == null && value == null; return result; } }