From 6254667ba5286adb3a85e2437d61aac00f2efbb1 Mon Sep 17 00:00:00 2001 From: Chuong Ho Date: Thu, 22 Aug 2024 10:25:19 +0800 Subject: [PATCH] Add GetLocationGridLine --- OpenMEPRevit/ClassModel/GridItem.cs | 55 +++++++++ OpenMEPRevit/Element/Element.cs | 164 ++++++++++++++++++++++--- OpenMEPRevit/Element/ImportInstance.cs | 4 +- OpenMEPRevit/OpenMEPRevit.csproj | 4 +- 4 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 OpenMEPRevit/ClassModel/GridItem.cs diff --git a/OpenMEPRevit/ClassModel/GridItem.cs b/OpenMEPRevit/ClassModel/GridItem.cs new file mode 100644 index 0000000..bb62b38 --- /dev/null +++ b/OpenMEPRevit/ClassModel/GridItem.cs @@ -0,0 +1,55 @@ +using Autodesk.DesignScript.Runtime; +using Autodesk.Revit.DB; + +namespace OpenMEPRevit.ClassModel; + +[IsVisibleInDynamoLibrary(false)] +public class GridItem +{ + public Autodesk.Revit.DB.Grid Grid { get; set; } + + public bool IsHorizontal => Direction(Grid.Curve)!.IsAlmostEqualTo(XYZ.BasisX); + + public GridItem(Autodesk.Revit.DB.Grid grid) + { + Grid = grid; + } + + public double DistanceTo(XYZ? point) + { + Curve curve = this.Grid.Curve; + var plane = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), XYZ.Zero); + Curve newcurve = ProjectLineOnPlane(plane, curve); + XYZ p = ProjectPointOnPlane(plane, point); + // get distance curve to point + double distance = newcurve.Distance(p); + return distance; + } + + XYZ ProjectPointOnPlane(Autodesk.Revit.DB.Plane plane, XYZ? point) + { + var origin = plane.Origin; + var normal = plane.Normal; + var v = point - origin; + var d = normal.DotProduct(v); + return point - d * normal; + } + + Autodesk.Revit.DB.Curve ProjectLineOnPlane(Autodesk.Revit.DB.Plane plane, Autodesk.Revit.DB.Curve line) + { + var origin = plane.Origin; + var normal = plane.Normal; + var v = line.GetEndPoint(0) - origin; + var d = normal.DotProduct(v); + var p0 = line.GetEndPoint(0) - d * normal; + v = line.GetEndPoint(1) - origin; + d = normal.DotProduct(v); + var p1 = line.GetEndPoint(1) - d * normal; + return Autodesk.Revit.DB.Line.CreateBound(p0, p1); + } + XYZ? Direction(Autodesk.Revit.DB.Curve curve) + { + Line? line = curve as Line; + return line?.Direction; + } +} \ No newline at end of file diff --git a/OpenMEPRevit/Element/Element.cs b/OpenMEPRevit/Element/Element.cs index 1f3bb59..f8bac10 100644 --- a/OpenMEPRevit/Element/Element.cs +++ b/OpenMEPRevit/Element/Element.cs @@ -1,10 +1,14 @@ using Autodesk.DesignScript.Runtime; using Autodesk.Revit.DB; using Dynamo.Graph.Nodes; +using OpenMEPRevit.ClassModel; using OpenMEPRevit.Helpers; +using ProtoCore.Lang; +using Revit.Elements; using Revit.GeometryConversion; using RevitServices.Persistence; using RevitServices.Transactions; +using Grid = Autodesk.Revit.DB.Grid; using Level = Autodesk.Revit.DB.Level; using Point = Autodesk.DesignScript.Geometry.Point; @@ -37,10 +41,18 @@ private Element() { if (element == null) throw new ArgumentNullException(nameof(element)); + if (element.InternalElement is IndependentTag) + { + XYZ min = element.BoundingBox.MinPoint.ToXyz(); + XYZ max = element.BoundingBox.MaxPoint.ToXyz(); + return min.Add(max).Divide(2).ToPoint(); + } + if (element.InternalElement is Autodesk.Revit.DB.FabricationPart fabricationPart) { return fabricationPart.Origin.ToPoint(); } + if (element.InternalElement.Location is LocationPoint) { LocationPoint? lc = element.InternalElement.Location as LocationPoint; @@ -53,10 +65,122 @@ private Element() return lc?.Curve.Evaluate(0.5, false).ToPoint(); } - BoundingBoxXYZ bb = element.InternalElement.get_BoundingBox(null); + BoundingBoxXYZ? bb = element.InternalElement.get_BoundingBox(null); + if (bb == null) + { + return null; + } + return bb.Max.Add(bb.Min).Divide(0.5).ToPoint(); } + /// + /// Get the location of the element belong to the grid line with the closest distance + /// the location include the top, bottom, left, right grid line + /// + /// the elements + /// + [NodeCategory("Query")] + [MultiReturn("TopGrid", "BottomGrid", "LeftGrid", "RightGrid")] + public static Dictionary GetLocationGridLine(Revit.Elements.Element element) + { + var doc = DocumentManager.Instance.CurrentDBDocument; + List grids = GetGrids(doc); + XYZ? location = GetLocation(element)?.ToXyz(); + if (location == null) + { + return new Dictionary() + { + { "TopGrid", null }, + { "BottomGrid", null }, + { "LeftGrid", null }, + { "RightGrid", null } + }; + } + + Grid? topGrid = null; + Grid? bottomGrid = null; + Grid? leftGrid = null; + Grid? rightGrid = null; + + var xGrids = grids.Where(x => x.IsHorizontal).ToList(); + var yGrids = grids.Where(x => !x.IsHorizontal).ToList(); + // top + double locationY = location.Y; + double yDistance = double.MaxValue; + foreach (var item in xGrids) + { + double yCurrent = item.Grid.Curve.GetEndPoint(0).Y; + double distanceTo = item.DistanceTo(location); + if (yCurrent >= locationY && distanceTo <= yDistance) + { + yDistance = distanceTo; + topGrid = item.Grid; + } + } + + // bottom + yDistance = double.MaxValue; + foreach (var item in xGrids) + { + double yCurrent = item.Grid.Curve.GetEndPoint(0).Y; + double distanceTo = item.DistanceTo(location); + if (yCurrent <= locationY && distanceTo <= yDistance) + { + yDistance = distanceTo; + bottomGrid = item.Grid; + } + } + + // left + double locationX = location.X; + double xDistance = double.MaxValue; + foreach (var item in yGrids) + { + double xCurrent = item.Grid.Curve.GetEndPoint(0).X; + double distanceTo = item.DistanceTo(location); + if (xCurrent <= locationX && distanceTo <= xDistance) + { + xDistance = distanceTo; + leftGrid = item.Grid; + } + } + + // right + xDistance = double.MaxValue; + foreach (var item in yGrids) + { + double xCurrent = item.Grid.Curve.GetEndPoint(0).X; + double distanceTo = item.DistanceTo(location); + if (xCurrent >= locationX && distanceTo <= xDistance) + { + xDistance = distanceTo; + rightGrid = item.Grid; + } + } + + return new Dictionary() + { + { "TopGrid", topGrid?.ToDynamoType() }, + { "BottomGrid", bottomGrid?.ToDynamoType() }, + { "LeftGrid", leftGrid?.ToDynamoType() }, + { "RightGrid", rightGrid?.ToDynamoType() } + }; + } + + private static List GetGrids(Autodesk.Revit.DB.Document doc) + { + List gridItems = new List(); + FilteredElementCollector collector = new FilteredElementCollector(doc); + var grids = collector.OfClass(typeof(Grid)).Cast().ToList(); + foreach (Grid grid in grids) + { + gridItems.Add(new GridItem(grid)); + } + + return gridItems; + } + /// /// Returns the Document in which the Element resides /// @@ -71,8 +195,8 @@ private Element() { return new Dictionary { - {"Revit Document", element.InternalElement.Document}, - {"Dynamo Document", element.InternalElement.Document.ToDynamoType()} + { "Revit Document", element.InternalElement.Document }, + { "Dynamo Document", element.InternalElement.Document.ToDynamoType() } }; } @@ -95,7 +219,7 @@ private Element() TransactionManager.Instance.TransactionTaskDone(); return element; } - + /// /// Move the list collection of elements to new location /// @@ -106,17 +230,19 @@ private Element() /// ![](../OpenMEPPage/element/dyn/pic/Element.MoveElements.png) /// [NodeCategory("Action")] - public static List MoveElements(List elements, List newLocations) + public static List MoveElements(List elements, + List newLocations) { Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument; TransactionManager.Instance.EnsureInTransaction(doc); - if(elements.Count != newLocations.Count) + if (elements.Count != newLocations.Count) throw new Exception("The number of elements and new locations must be the same."); for (int i = 0; i < elements.Count; i++) { ElementTransformUtils.MoveElement(doc, elements[i].InternalElement.Id, newLocations[i].ToXyz().Subtract(GetLocation(elements[i]).ToXyz())); } + TransactionManager.Instance.TransactionTaskDone(); return elements; } @@ -141,11 +267,11 @@ private Element() TransactionManager.Instance.EnsureInTransaction(doc); double degree2Radian = angle * Math.PI / 180; ElementTransformUtils.RotateElement(doc, element.InternalElement.Id, - (Autodesk.Revit.DB.Line) lineAxis.ToRevitType(), degree2Radian); + (Autodesk.Revit.DB.Line)lineAxis.ToRevitType(), degree2Radian); TransactionManager.Instance.TransactionTaskDone(); return element; } - + /// /// Set Rotate multiple family instances /// This will be help save time when you have a lot of elements to rotate because just one transaction @@ -162,7 +288,7 @@ private Element() List lineAxis, List angles) { - if(elements.Count != lineAxis.Count) + if (elements.Count != lineAxis.Count) throw new Exception("The number of elements and line axis must be the same"); TransactionManager.Instance.ForceCloseTransaction(); Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument; @@ -171,8 +297,9 @@ private Element() { double degree2Radian = angles[i] * Math.PI / 180; ElementTransformUtils.RotateElement(doc, elements[i].InternalElement.Id, - (Autodesk.Revit.DB.Line) lineAxis[i].ToRevitType(), degree2Radian); + (Autodesk.Revit.DB.Line)lineAxis[i].ToRevitType(), degree2Radian); } + TransactionManager.Instance.TransactionTaskDone(); return elements; } @@ -192,11 +319,11 @@ private Element() List vectorAxis, List angles) { - if(elements.Count != vectorAxis.Count) + if (elements.Count != vectorAxis.Count) throw new Exception("The number of elements and vector axis must be the same"); Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument; TransactionManager.Instance.EnsureInTransaction(doc); - + for (int i = 0; i < elements.Count; i++) { double degree2Radian = angles[i] * Math.PI / 180; @@ -205,12 +332,13 @@ private Element() Autodesk.Revit.DB.Line line = Autodesk.Revit.DB.Line.CreateBound(location!.Add(vectorAxis[i].ToRevitType().Multiply(2)), location); ElementTransformUtils.RotateElement(doc, elements[i].InternalElement.Id, - (Autodesk.Revit.DB.Line) line, degree2Radian); + (Autodesk.Revit.DB.Line)line, degree2Radian); } + TransactionManager.Instance.TransactionTaskDone(); return elements; } - + /// /// Set Rotate of fitting By Vector /// @@ -235,7 +363,7 @@ private Element() Autodesk.Revit.DB.Line line = Autodesk.Revit.DB.Line.CreateBound(location!.Add(vectorAxis.ToRevitType().Multiply(2)), location); ElementTransformUtils.RotateElement(doc, element.InternalElement.Id, - (Autodesk.Revit.DB.Line) line, degree2Radian); + (Autodesk.Revit.DB.Line)line, degree2Radian); TransactionManager.Instance.TransactionTaskDone(); return element; } @@ -277,7 +405,6 @@ private Element() #else if (levelId.Value == -1) - #endif { // General get level method @@ -361,7 +488,7 @@ private Element() { if (element == null) throw new ArgumentNullException(nameof(element)); List connectors = ConnectorManager.Connector.GetConnectors(element); - if (connectors.Count==0) return null; + if (connectors.Count == 0) return null; dynamic? systemType = connectors.Select(x => ConnectorManager.Connector.SystemType(x)).FirstOrDefault(); return systemType; } @@ -383,7 +510,7 @@ private Element() if (connectors.Count == 0) return new List(); foreach (var connector in connectors) { - if(connector== null) continue; + if (connector == null) continue; ConnectorSet connectedConnectors = connector.AllRefs; foreach (Connector connectedConnector in connectedConnectors) { @@ -394,6 +521,7 @@ private Element() } } } + if (connectedElements.Count == 0) return new List(); return connectedElements.Select(x => x.ToDynamoType()).ToList(); } diff --git a/OpenMEPRevit/Element/ImportInstance.cs b/OpenMEPRevit/Element/ImportInstance.cs index b2acb43..078853b 100644 --- a/OpenMEPRevit/Element/ImportInstance.cs +++ b/OpenMEPRevit/Element/ImportInstance.cs @@ -30,8 +30,8 @@ private ImportInstance() { ElementId elementId = import.GetTypeId(); ElementType? elementType = import.Document.GetElement(elementId) as Autodesk.Revit.DB.ElementType; - IDictionary externalResourceReferences = elementType.GetExternalResourceReferences(); - foreach (KeyValuePair externalResourceReference in externalResourceReferences) + IDictionary? externalResourceReferences = elementType?.GetExternalResourceReferences(); + foreach (KeyValuePair externalResourceReference in externalResourceReferences!) { IDictionary information = externalResourceReference.Value.GetReferenceInformation(); foreach (KeyValuePair keyValuePair in information) diff --git a/OpenMEPRevit/OpenMEPRevit.csproj b/OpenMEPRevit/OpenMEPRevit.csproj index 4af7e2d..0c0852f 100644 --- a/OpenMEPRevit/OpenMEPRevit.csproj +++ b/OpenMEPRevit/OpenMEPRevit.csproj @@ -96,8 +96,8 @@ $(DefineConstants);R23 - 2.18 - 2.18 + 2.19 + 2.19 2024 net48 $(DefineConstants);R24