using Autodesk.Revit.DB; using Autodesk.Revit.UI.Selection; using Nice3point.Revit.Toolkit.External; using System; 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 DimensionElemCmd : ExternalCommand { public override void Execute() { using Transaction transaction = new(Document, "标注对象"); try { while (true) { transaction.Start(); Reference refer = UiDocument.Selection.PickObject(ObjectType.Element, "请选择要标注的对象"); Element e = UiDocument.Document.GetElement(refer); CreateDimensionsByFaces(Document, e); transaction.Commit(); } } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { if (transaction.GetStatus() == TransactionStatus.Started) { transaction.RollBack(); } } catch (Exception ex) { ErrorMessage = ex.Message; if (transaction.GetStatus() == TransactionStatus.Started) { transaction.RollBack(); } } } private List GetElementFaces(Element elem) { List faces = new(); Options option = new() { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine, IncludeNonVisibleObjects = true }; GeometryElement geometry = elem.get_Geometry(option); foreach (GeometryObject geomObj in geometry) { GeometryInstance geomInstance = geomObj as GeometryInstance; if (geomInstance != null) { bool usesSymbolGeometry = elem is FamilyInstance && !(elem as FamilyInstance).HasModifiedGeometry(); GeometryElement instanceGeometry = usesSymbolGeometry ? geomInstance.GetSymbolGeometry() : geomInstance.GetInstanceGeometry(); foreach (GeometryObject instObj in instanceGeometry) { Solid instSolid = instObj as Solid; if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0 || instSolid.Volume < 0.0001) { continue; } foreach (Face face in instSolid.Faces) { faces.Add(face); } } } Solid solid = geomObj as Solid; if (solid != null) { if (solid.Faces.Size == 0 || solid.Edges.Size == 0 || solid.Volume < 0.0001) { continue; } foreach (Face face in solid.Faces) { faces.Add(face); } } } return faces; } private void CreateDimensionsByFace(Document Document, Face face) { List lines = new(); if (face.EdgeLoops.Size > 0) { foreach (CurveLoop loop in face.GetEdgesAsCurveLoops()) { foreach (Curve curve in loop) { if (curve is Line) { lines.Add(curve as Line); } } } } foreach (Line line in lines) { ReferenceArray array = new(); array.Append(line.GetEndPointReference(0)); array.Append(line.GetEndPointReference(1)); Document.Create.NewDimension(Document.ActiveView, line, array); } //List l1 = new List(); //List> l2 = new List>(); //GetParallLineGroups(lines, lines.FirstOrDefault(), l1, l2); //foreach (List list in l2) //{ // if (list.Count <= 1) // { // continue; // } // ReferenceArray array = new ReferenceArray(); // var p1 = list.FirstOrDefault().Evaluate(0.5, true); // var result = list.LastOrDefault().Project(p1); // var p2 = result.XYZPoint; // Line l = Line.CreateBound(p1, p2); // foreach (Line line in list) // { // array.Append(line.GetEndPointReference(0)); // } // doc.Create.NewDimension(doc.ActiveView, l, array); //} } private void CreateDimensionsByFaces(Document Document, Element e) { List elementFaces = GetElementFaces(e); if (e is Wall w) { IEnumerable elementIds = w.FindInserts(true, false, false, false) .Where(id => Document.GetElement(id) is Opening); foreach (var id in elementIds) { var opening = Document.GetElement(id); elementFaces.AddRange(GetElementFaces(opening)); } } Location loc = e.Location; var bounding = e.get_BoundingBox(Document.ActiveView); //if (loc == null) //{ // MessageBox.Show("元素无法被标注"); // return; //} //if (loc is LocationCurve) //{ // p = (loc as LocationCurve).Curve.GetEndPoint(0); //} //else if (loc is LocationPoint) //{ // p = (loc as LocationPoint).Point; //} List> groups = new(); GetParallFaces(elementFaces, groups); foreach (List faces in groups) { XYZ p = bounding.Min; if (faces.Count <= 1) { continue; } var face = faces[0]; var face1 = faces[faces.Count - 1]; ReferenceArray array = new(); foreach (var f in faces) { if (f.Reference == null) { //var elementIds = e.GetGeneratingElementIds(f); //var openingId = elementIds.FirstOrDefault(); //var opening = doc.GetElement(openingId) as Opening; //var fa = opening.GetGeometryObjectFromReference(f.Reference); //if (fa != f) //{ // array.Append(fa.Reference); //} continue; } array.Append(f.Reference); } try { Line line = null; if (face is not null and PlanarFace) { var pf = face as PlanarFace; var direction = pf.FaceNormal; if (direction.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero)) { p += direction * 2; } else { p += direction.CrossProduct(XYZ.BasisZ) * 2; } line = Line.CreateUnbound(p, direction); } Document.Create.NewDimension(Document.ActiveView, line, array); } catch (Exception) { } } } private void GetParallFaces(List faces, List> groups) { var firstface = faces.FirstOrDefault(); faces = faces.FindAll(face => face is PlanarFace); List group = new() { firstface }; groups.Add(group); PlanarFace pf = firstface as PlanarFace; faces.Remove(firstface); for (var i = faces.Count - 1; i >= 0; i--) { if (faces[i] is not PlanarFace) { continue; } var tempFace = faces[i] as PlanarFace; if (tempFace.FaceNormal.CrossProduct(pf.FaceNormal).IsAlmostEqualTo(XYZ.Zero)) { group.Add(tempFace); faces.Remove(tempFace); //GetParallFaces(faces, tempFace, ZoomRBGroup, groups); } } if (faces.Count >= 1) { GetParallFaces(faces, groups); } } private void GetParallLineGroups(List lines, List> groups) { var firstLine = lines.FirstOrDefault(); lines = lines.FindAll(curve => curve is Line); List group = new() { firstLine }; groups.Add(group); Line pf = firstLine as Line; lines.Remove(firstLine); for (var i = 0; i < lines.Count; i++) { if (lines[i] is not Line) { continue; } var tempLine = lines[i] as Line; if (tempLine.Direction.CrossProduct(pf.Direction).IsAlmostEqualTo(XYZ.Zero)) { group.Add(tempLine); lines.Remove(tempLine); //GetParallFaces(faces, tempFace, ZoomRBGroup, groups); } } if (lines.Count >= 1) { GetParallLineGroups(lines, groups); } } } }