diff --git a/Revit_Core_Adapter/CRUD/Read.cs b/Revit_Core_Adapter/CRUD/Read.cs index 52ee6d3fb..36cd14797 100644 --- a/Revit_Core_Adapter/CRUD/Read.cs +++ b/Revit_Core_Adapter/CRUD/Read.cs @@ -24,7 +24,6 @@ using BH.Engine.Adapters.Revit; using BH.Engine.Base; using BH.Engine.Geometry; -using BH.Engine.Graphics; using BH.oM.Adapter; using BH.oM.Adapters.Revit; using BH.oM.Adapters.Revit.Enums; @@ -87,7 +86,8 @@ protected override IEnumerable Read(IRequest request, ActionConfig } } - Dictionary requestsByLinks = request.SplitRequestTreeByLinks(this.Document); + // Split the request into separate requests per each link model + Dictionary requestsByLinks = request.SplitRequestTreeByLinks(this.Document); if (requestsByLinks == null) { BH.Engine.Base.Compute.RecordError($"Pull failed due to issues with the request containing {nameof(FilterByLink)}. Please try to restructure the used Request and try again."); @@ -96,12 +96,49 @@ protected override IEnumerable Read(IRequest request, ActionConfig RevitSettings settings = RevitSettings.DefaultIfNull(); + // Group links that hold the same document and have same transform + // Addresses the case when there is a nested link being loaded via more than one parent link + // Same document linked in multiple locations is being pulled per each location + // Performance is not affected by multiple converts of same elements thanks to refObjects + Dictionary<(Document, Transform), List> requestsByDocumentAndTransform = new Dictionary<(Document, Transform), List>(); + foreach (KeyValuePair requestByLink in requestsByLinks) + { + Document doc; + Transform transform = Transform.Identity; + if (requestByLink.Key.IntegerValue == -1) + doc = this.Document; + else + { + var linkInstance = this.Document.GetElement(requestByLink.Key) as RevitLinkInstance; + doc = linkInstance.GetLinkDocument(); + + Transform linkTransform = linkInstance.GetTotalTransform(); + if (!linkTransform.IsIdentity) + transform = linkTransform; + } + + (Document doc, Transform transform) tuple; + if (requestsByDocumentAndTransform.Keys.All(x => x.Item1.Title != doc.Title || !x.Item2.AlmostEqual(transform))) + { + tuple = (doc, transform); + requestsByDocumentAndTransform.Add(tuple, new List()); + } + else + tuple = requestsByDocumentAndTransform.Keys.First(x => x.Item1.Title == doc.Title && x.Item2.AlmostEqual(transform)); + + requestsByDocumentAndTransform[tuple].Add(requestByLink.Value); + } + + // Global refObjects help sharing the refObjects when pulling from same document linked in a few different locations (e.g. copy-pasted link) + // Thanks to sharing refObjects, an element is processed only once even if FromRevit is called against it multiple times + Dictionary>> globalRefObjects = new Dictionary>>(); List result = new List(); - foreach (KeyValuePair requestByLink in requestsByLinks) + foreach (var kvp in requestsByDocumentAndTransform) { - result.AddRange(Read(requestByLink.Key, requestByLink.Value, pullConfig, settings)); + result.AddRange(Read(kvp.Key.Item1, kvp.Key.Item2, kvp.Value, pullConfig, settings, globalRefObjects)); } + // Restore selection this.UIDocument.Selection.SetElementIds(selected); return result; @@ -112,7 +149,7 @@ protected override IEnumerable Read(IRequest request, ActionConfig /**** Public Methods ****/ /***************************************************/ - public static List Read(Document document, IRequest request, RevitPullConfig pullConfig = null, RevitSettings settings = null) + public static List Read(Document document, Transform transform, List requests, RevitPullConfig pullConfig = null, RevitSettings settings = null, Dictionary>> globalRefObjects = null) { if (document == null) { @@ -120,23 +157,18 @@ public static List Read(Document document, IRequest request, RevitP return new List(); } - if (request == null) - { - BH.Engine.Base.Compute.RecordError("BHoM objects could not be read because provided IRequest is null."); - return new List(); - } - pullConfig = pullConfig.DefaultIfNull(); settings = settings.DefaultIfNull(); + // Prefilter only elements from open worksets if requested IEnumerable worksetPrefilter = null; if (!pullConfig.IncludeClosedWorksets) worksetPrefilter = document.OpenWorksetsPrefilter(); - List elementIds = request.IElementIds(document, pullConfig.Discipline, settings, worksetPrefilter).RemoveGridSegmentIds(document)?.ToList(); - if (elementIds == null) - return new List(); + // Get elementIds from all requests + List elementIds = new LogicalOrRequest { Requests = requests }.ElementIds(document, pullConfig.Discipline, settings, worksetPrefilter).RemoveGridSegmentIds(document).ToList(); + // Get elementIds of nested elements if requested if (pullConfig.IncludeNestedElements) { List elemIds = new List(); @@ -153,12 +185,12 @@ public static List Read(Document document, IRequest request, RevitP elementIds.AddRange(elemIds); } - return Read(document, elementIds, pullConfig, settings); + return Read(document, transform, elementIds.ToList(), pullConfig, settings, globalRefObjects); } /***************************************************/ - public static List Read(Document document, List elementIds, RevitPullConfig pullConfig = null, RevitSettings settings = null) + public static List Read(Document document, Transform transform, List elementIds, RevitPullConfig pullConfig = null, RevitSettings settings = null, Dictionary>> globalRefObjects = null) { if (document == null) { @@ -175,14 +207,6 @@ public static List Read(Document document, List elementI pullConfig = pullConfig.DefaultIfNull(); settings = settings.DefaultIfNull(); - PullGeometryConfig geometryConfig = pullConfig.GeometryConfig; - if (geometryConfig == null) - geometryConfig = new PullGeometryConfig(); - - PullRepresentationConfig representationConfig = pullConfig.RepresentationConfig; - if (representationConfig == null) - representationConfig = new PullRepresentationConfig(); - Discipline discipline = pullConfig.Discipline; if (discipline == Discipline.Undefined) { @@ -190,93 +214,99 @@ public static List Read(Document document, List elementI discipline = Discipline.Physical; } - Options geometryOptions = BH.Revit.Engine.Core.Create.Options(ViewDetailLevel.Fine, geometryConfig.IncludeNonVisible, false); - Options meshOptions = BH.Revit.Engine.Core.Create.Options(geometryConfig.MeshDetailLevel.ViewDetailLevel(), geometryConfig.IncludeNonVisible, false); - Options renderMeshOptions = BH.Revit.Engine.Core.Create.Options(representationConfig.DetailLevel.ViewDetailLevel(), representationConfig.IncludeNonVisible, false); + // Set up refObjects + if (globalRefObjects == null) + globalRefObjects = new Dictionary>>(); + + if (!globalRefObjects.ContainsKey(document.Title)) + globalRefObjects.Add(document.Title, new Dictionary>()); + + Dictionary> refObjects = globalRefObjects[document.Title]; - Transform linkTransform = null; - TransformMatrix bHoMTransform = null; - if (document.IsLinked) + // Get the elements already processed for a given document + // Only relevant in case of same document linked in multiple locations + // Helps avoid getting same element processed multiple times + List result = new List(); + List remainingElementIds = new List(); + foreach (ElementId id in elementIds) { - linkTransform = document.LinkTransform(); - if (linkTransform?.IsIdentity == false) - bHoMTransform = linkTransform.FromRevit(); + var existing = refObjects.GetValues(id); + if (existing != null) + result.AddRange(existing); + else + remainingElementIds.Add(id); } - Dictionary> refObjects = new Dictionary>(); - // Extract panel geometry of walls, floors, slabs and roofs prior to running the converts (this is an optimisation aimed to reduce the number of view regenerations) if (!document.IsLinked) - document.CachePanelGeometry(elementIds, discipline, settings, refObjects); - - List result = new List(); - foreach (ElementId id in elementIds) + document.CachePanelGeometry(remainingElementIds, discipline, settings, refObjects); + + // Set up all geometry/representation configs + PullGeometryConfig geometryConfig = pullConfig.GeometryConfig; + if (geometryConfig == null) + geometryConfig = new PullGeometryConfig(); + + PullRepresentationConfig representationConfig = pullConfig.RepresentationConfig; + if (representationConfig == null) + representationConfig = new PullRepresentationConfig(); + + Options geometryOptions = BH.Revit.Engine.Core.Create.Options(ViewDetailLevel.Fine, geometryConfig.IncludeNonVisible, false); + Options meshOptions = BH.Revit.Engine.Core.Create.Options(geometryConfig.MeshDetailLevel.ViewDetailLevel(), geometryConfig.IncludeNonVisible, false); + Options renderMeshOptions = BH.Revit.Engine.Core.Create.Options(representationConfig.DetailLevel.ViewDetailLevel(), representationConfig.IncludeNonVisible, false); + + // Convert each element in coordinate system of the document that owns it + // Transformation from that document's coordinate system to the coordinate system of host document done further downstream + foreach (ElementId id in remainingElementIds) { Element element = document.GetElement(id); if (element == null) continue; - IEnumerable iBHoMObjects = Read(element, discipline, linkTransform, settings, refObjects); - - if (iBHoMObjects != null && iBHoMObjects.Any()) + IEnumerable converted = Read(element, discipline, settings, refObjects); + if (converted != null) { if (pullConfig.PullMaterialTakeOff) { - foreach (IBHoMObject iBHoMObject in iBHoMObjects) + foreach (IBHoMObject obj in converted) { oM.Physical.Materials.VolumetricMaterialTakeoff takeoff = element.VolumetricMaterialTakeoff(settings, refObjects); if (takeoff != null) - iBHoMObject.Fragments.AddOrReplace(takeoff); + obj.Fragments.AddOrReplace(takeoff); } } List edges = null; if (geometryConfig.PullEdges) - { edges = element.Curves(geometryOptions, settings, true).FromRevit(); - if (bHoMTransform != null) - edges = edges.Select(x => x?.ITransform(bHoMTransform)).ToList(); - } List surfaces = null; if (geometryConfig.PullSurfaces) - { surfaces = element.Faces(geometryOptions, settings).Select(x => x.IFromRevit()).ToList(); - if (bHoMTransform != null) - surfaces = surfaces.Select(x => x?.ITransform(bHoMTransform)).ToList(); - } List meshes = null; if (geometryConfig.PullMeshes) - { meshes = element.MeshedGeometry(meshOptions, settings); - if (bHoMTransform != null) - meshes = meshes.Select(x => x?.Transform(bHoMTransform)).ToList(); - } if (geometryConfig.PullEdges || geometryConfig.PullSurfaces || geometryConfig.PullMeshes) { RevitGeometry geometry = new RevitGeometry(edges, surfaces, meshes); - foreach (IBHoMObject iBHoMObject in iBHoMObjects) + foreach (IBHoMObject obj in converted) { - iBHoMObject.Fragments.AddOrReplace(geometry); + obj.Fragments.AddOrReplace(geometry); } } if (representationConfig.PullRenderMesh) { List renderMeshes = element.RenderMeshes(renderMeshOptions, settings); - if (bHoMTransform != null) - renderMeshes = renderMeshes.Select(x => x?.Transform(bHoMTransform)).ToList(); - RevitRepresentation representation = new RevitRepresentation(renderMeshes); - foreach (IBHoMObject iBHoMObject in iBHoMObjects) + foreach (IBHoMObject obj in converted) { - iBHoMObject.Fragments.AddOrReplace(representation); + obj.Fragments.AddOrReplace(representation); } } - result.AddRange(iBHoMObjects); + result.AddRange(converted); } } @@ -284,12 +314,13 @@ public static List Read(Document document, List elementI if (activePulls.Count(x => x) > 1) BH.Engine.Base.Compute.RecordWarning("Pull of more than one geometry/representation type has been specified in RevitPullConfig. Please consider this can be time consuming due to the amount of conversions."); - return result; + // Postprocess clones the output and transforms it to the coordinate system of the host model + return result.Select(x => x.IPostprocess(transform, settings)).Where(x => x != null).ToList(); } /***************************************************/ - public static List Read(Element element, Discipline discipline, Transform transform, RevitSettings settings = null, Dictionary> refObjects = null) + public static List Read(Element element, Discipline discipline, RevitSettings settings = null, Dictionary> refObjects = null) { if (element == null || !element.IsValidObject) return new List(); @@ -297,7 +328,7 @@ public static List Read(Element element, Discipline discipline, Tra List result = null; try { - result = element.IFromRevit(discipline, transform, settings, refObjects); + result = element.IFromRevit(discipline, settings, refObjects); } catch (Exception exception) { @@ -323,6 +354,3 @@ public static List Read(Element element, Discipline discipline, Tra /***************************************************/ } } - - - diff --git a/Revit_Core_Engine/Compute/SplitRequestTreeByLinks.cs b/Revit_Core_Engine/Compute/SplitRequestTreeByLinks.cs index 205357c7f..d025a8c96 100644 --- a/Revit_Core_Engine/Compute/SplitRequestTreeByLinks.cs +++ b/Revit_Core_Engine/Compute/SplitRequestTreeByLinks.cs @@ -42,11 +42,10 @@ public static partial class Compute [Description("Decomposes a tree created by a set of nested ILogicalRequests into a dictionary of Revit documents (both host and linked) and the IRequests relevant to them, which in total represents the same request as the original IRequest.")] [Input("request", "An IRequest to be split into a dictionary of Revit documents and the IRequests relevant to them.")] [Input("document", "Host document to be used as the basis of the splitting routine.")] - [Output("splitRequests", "A dictionary of Revit documents (both host and linked) and the IRequests relevant to them, which in total represents the same request as the input IRequest.")] - public static Dictionary SplitRequestTreeByLinks(this IRequest request, Document document) + [Output("splitRequests", "A dictionary of elementIds representing Revit documents (both host as -1 and linked as link Id) and the IRequests relevant to them, which in total represents the same request as the input IRequest.")] + public static Dictionary SplitRequestTreeByLinks(this IRequest request, Document document) { - - Dictionary requestsByLinks = new Dictionary(); + Dictionary requestsByLinks = new Dictionary(); List splitPerDoc = request.SplitRequestTreeByType(typeof(FilterByLink)); foreach (IRequest splitRequest in splitPerDoc) { @@ -62,7 +61,7 @@ public static Dictionary SplitRequestTreeByLinks(this IReque /**** Private Methods ****/ /***************************************************/ - private static bool TryOrganizeByLink(this IRequest request, Document document, Dictionary requestsByLinks) + private static bool TryOrganizeByLink(this IRequest request, Document document, Dictionary requestsByLinks) { if (request == null) return false; @@ -78,7 +77,7 @@ private static bool TryOrganizeByLink(this IRequest request, Document document, List linkRequests = request.AllRequestsOfType(typeof(FilterByLink)); if (linkRequests.Count == 0) { - requestsByLinks.AddRequestByLink(request, document); + requestsByLinks.AddRequestByLink(request, new ElementId(-1)); return true; } else if (linkRequests.Count == 1) @@ -86,29 +85,35 @@ private static bool TryOrganizeByLink(this IRequest request, Document document, FilterByLink linkRequest = (FilterByLink)linkRequests[0]; List linkInstanceIds = document.ElementIdsOfLinkInstances(linkRequest.LinkName, linkRequest.CaseSensitive); - if (linkInstanceIds.Count == 1) + if (linkInstanceIds.Count == 0) + { + BH.Engine.Base.Compute.RecordError($"Active Revit document does not contain links with neither name nor path nor ElementId equal to {linkRequest.LinkName}."); + return false; + } + else if (linkInstanceIds.Count > 1) + BH.Engine.Base.Compute.RecordWarning($"There is more than one link document named {linkRequest.LinkName} - elements will be pulled from all unique instances of the links." + + $"\nPlease use full link path or its ElementId instead of link name to pull specifically from a chosen instance."); + + foreach (ElementId linkInstanceId in linkInstanceIds) { request.RemoveSubRequest(linkRequest); request = request.SimplifyRequestTree(); - requestsByLinks.AddRequestByLink(request, ((RevitLinkInstance)document.GetElement(linkInstanceIds[0])).GetLinkDocument()); - return true; + requestsByLinks.AddRequestByLink(request, linkInstanceId); } - else if (linkInstanceIds.Count == 0) - BH.Engine.Base.Compute.RecordError($"Active Revit document does not contain links with neither name nor path nor ElementId equal to {linkRequest.LinkName}."); - else - BH.Engine.Base.Compute.RecordError($"There is more than one link document named {linkRequest.LinkName} - please use full link path or its ElementId instead of link name to pull."); - } - return false; + return true; + } + else + return false; } /***************************************************/ - private static void AddRequestByLink(this Dictionary requestsByLinks, IRequest request, Document document) + private static void AddRequestByLink(this Dictionary requestsByLinks, IRequest request, ElementId linkId) { - if (requestsByLinks.ContainsKey(document)) + if (requestsByLinks.ContainsKey(linkId)) { - IRequest requestByLink = requestsByLinks[document]; + IRequest requestByLink = requestsByLinks[linkId]; if (requestByLink is LogicalOrFilter) ((LogicalOrRequest)requestByLink).Requests.Add(request); else @@ -116,11 +121,11 @@ private static void AddRequestByLink(this Dictionary request LogicalOrRequest newHead = new LogicalOrRequest(); newHead.Requests.Add(requestByLink); newHead.Requests.Add(request); - requestsByLinks[document] = newHead; + requestsByLinks[linkId] = newHead; } } else - requestsByLinks[document] = request; + requestsByLinks[linkId] = request; } /***************************************************/ @@ -208,6 +213,3 @@ private static bool IsValidToOrganize(this IRequest request) /***************************************************/ } } - - - diff --git a/Revit_Core_Engine/Convert/FromRevit.cs b/Revit_Core_Engine/Convert/FromRevit.cs index a33531928..048187f62 100644 --- a/Revit_Core_Engine/Convert/FromRevit.cs +++ b/Revit_Core_Engine/Convert/FromRevit.cs @@ -41,16 +41,16 @@ public static partial class Convert /**** Interface Methods ****/ /***************************************************/ + [PreviousVersion("7.2", "BH.Revit.Engine.Core.Convert.IFromRevit(Autodesk.Revit.DB.Element, BH.oM.Adapters.Revit.Enums.Discipline, Autodesk.Revit.DB.Transform, BH.oM.Adapters.Revit.Settings.RevitSettings, System.Collections.Generic.Dictionary>)")] [Description("Interface method that tries to find a suitable FromRevit convert for any Revit Element.")] [Input("element", "Revit Element to be converted.")] [Input("discipline", "Engineering discipline based on the BHoM discipline classification.")] - [Input("transform", "Optional, a transform to apply to the converted object.")] [Input("settings", "Revit adapter settings to be used while performing the convert.")] [Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")] [Output("fromRevit", "Resulted BHoM object converted from a Revit Element.")] - public static List IFromRevit(this Element element, Discipline discipline, Transform transform = null, RevitSettings settings = null, Dictionary> refObjects = null) + public static List IFromRevit(this Element element, Discipline discipline, RevitSettings settings = null, Dictionary> refObjects = null) { - return FromRevit(element as dynamic, discipline, transform, settings, refObjects); + return FromRevit(element as dynamic, discipline, settings, refObjects); } /***************************************************/ @@ -71,14 +71,14 @@ public static IGeometry IFromRevit(this Location location) /**** Convert Revit elements to BHoM ****/ /***************************************************/ + [PreviousVersion("7.2", "BH.Revit.Engine.Core.Convert.FromRevit(Autodesk.Revit.DB.Analysis.EnergyAnalysisDetailModel, BH.oM.Adapters.Revit.Enums.Discipline, Autodesk.Revit.DB.Transform, BH.oM.Adapters.Revit.Settings.RevitSettings, System.Collections.Generic.Dictionary>)")] [Description("Converts a Revit EnergyAnalysisDetailModel to a BHoM object based on the requested engineering discipline.")] [Input("energyAnalysisModel", "Revit EnergyAnalysisDetailModel to be converted.")] [Input("discipline", "Engineering discipline based on the BHoM discipline classification.")] - [Input("transform", "Optional, a transform to apply to the converted object.")] [Input("settings", "Revit adapter settings to be used while performing the convert.")] [Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")] [Output("fromRevit", "Resulted BHoM object converted from a Revit EnergyAnalysisDetailModel.")] - public static List FromRevit(this EnergyAnalysisDetailModel energyAnalysisModel, Discipline discipline, Transform transform = null, RevitSettings settings = null, Dictionary> refObjects = null) + public static List FromRevit(this EnergyAnalysisDetailModel energyAnalysisModel, Discipline discipline, RevitSettings settings = null, Dictionary> refObjects = null) { if (energyAnalysisModel == null) { @@ -97,14 +97,14 @@ public static List FromRevit(this EnergyAnalysisDetailModel energyA /***************************************************/ + [PreviousVersion("7.2", "BH.Revit.Engine.Core.Convert.FromRevit(Autodesk.Revit.DB.AssemblyInstance, BH.oM.Adapters.Revit.Enums.Discipline, Autodesk.Revit.DB.Transform, BH.oM.Adapters.Revit.Settings.RevitSettings, System.Collections.Generic.Dictionary>)")] [Description("Converts a Revit AssemblyInstance to a BHoM object based on the requested engineering discipline.")] [Input("assemblyInstance", "Revit AssemblyInstance to be converted.")] [Input("discipline", "Engineering discipline based on the BHoM discipline classification.")] - [Input("transform", "Optional, a transform to apply to the converted object. Irrelevant in case of assembly instances.")] [Input("settings", "Revit adapter settings to be used while performing the convert.")] [Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")] [Output("fromRevit", "Resulted BHoM object converted from a Revit AssemblyInstance.")] - public static List FromRevit(this AssemblyInstance assemblyInstance, Discipline discipline, Transform transform = null, RevitSettings settings = null, Dictionary> refObjects = null) + public static List FromRevit(this AssemblyInstance assemblyInstance, Discipline discipline, RevitSettings settings = null, Dictionary> refObjects = null) { if (assemblyInstance == null) { @@ -114,7 +114,7 @@ public static List FromRevit(this AssemblyInstance assemblyInstance foreach (ElementId memberId in assemblyInstance.GetMemberIds()) { - assemblyInstance.Document.GetElement(memberId).IFromRevit(discipline, transform, settings, refObjects); + assemblyInstance.Document.GetElement(memberId).IFromRevit(discipline, settings, refObjects); } return new List { assemblyInstance.AssemblyFromRevit(settings, refObjects) }; @@ -122,14 +122,14 @@ public static List FromRevit(this AssemblyInstance assemblyInstance /***************************************************/ + [PreviousVersion("7.2", "BH.Revit.Engine.Core.Convert.FromRevit(Autodesk.Revit.DB.Element, BH.oM.Adapters.Revit.Enums.Discipline, Autodesk.Revit.DB.Transform, BH.oM.Adapters.Revit.Settings.RevitSettings, System.Collections.Generic.Dictionary>)")] [Description("Converts a Revit Element to a BHoM object based on the requested engineering discipline.")] [Input("element", "Revit EnergyAnalysisDetailModel to be converted.")] [Input("discipline", "Engineering discipline based on the BHoM discipline classification.")] - [Input("transform", "Optional, a transform to apply to the converted object.")] [Input("settings", "Revit adapter settings to be used while performing the convert.")] [Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")] [Output("fromRevit", "Resulted BHoM object converted from a Revit Element.")] - public static List FromRevit(this Element element, Discipline discipline, Transform transform = null, RevitSettings settings = null, Dictionary> refObjects = null) + public static List FromRevit(this Element element, Discipline discipline, RevitSettings settings = null, Dictionary> refObjects = null) { if (element == null) { @@ -159,12 +159,11 @@ public static List FromRevit(this Element element, Discipline disci List result = null; if (converted is IBHoMObject) - result = new List { ((IBHoMObject)converted).IPostprocess(transform, settings) }; + result = new List { ((IBHoMObject)converted) }; else if (converted is IEnumerable) { result = new List(((IEnumerable)converted) - .Where(x => x != null) - .Select(x => x.IPostprocess(transform, settings))); + .Where(x => x != null)); } return result; diff --git a/Revit_Core_Engine/Modify/Postprocess.cs b/Revit_Core_Engine/Modify/Postprocess.cs index 651c6753c..c71b2f12e 100644 --- a/Revit_Core_Engine/Modify/Postprocess.cs +++ b/Revit_Core_Engine/Modify/Postprocess.cs @@ -23,14 +23,19 @@ using Autodesk.Revit.DB; using BH.Engine.Adapters.Revit; using BH.Engine.Base; -using BH.Engine.Spatial; +using BH.Engine.Geometry; +using BH.Engine.Graphics; +using BH.oM.Adapters.Revit; using BH.oM.Adapters.Revit.Elements; using BH.oM.Adapters.Revit.Settings; using BH.oM.Base; +using BH.oM.Base.Attributes; using BH.oM.Dimensional; using BH.oM.Geometry; -using BH.oM.Base.Attributes; +using BH.oM.MEP.Fragments; +using BH.oM.Spatial.SettingOut; using System.ComponentModel; +using System.Linq; namespace BH.Revit.Engine.Core { @@ -71,7 +76,17 @@ public static IElement Postprocess(this IElement element, Transform transform, R settings = settings.DefaultIfNull(); if (transform?.IsIdentity == false) - element = element.ITransform(transform.FromRevit(), settings.DistanceTolerance); + { + TransformMatrix bhomTransform = transform.FromRevit(); + element = BH.Engine.Spatial.Modify.ITransform(element, bhomTransform, settings.DistanceTolerance); + + if (element is IBHoMObject) + { + IBHoMObject obj = (IBHoMObject)element; + obj.TransformGeometry(bhomTransform); + obj.TransformRepresentation(bhomTransform); + } + } return element; } @@ -94,7 +109,12 @@ public static IInstance Postprocess(this ModelInstance instance, Transform trans settings = settings.DefaultIfNull(); if (transform?.IsIdentity == false) - instance = instance.Transform(transform.FromRevit(), settings.DistanceTolerance) as ModelInstance; + { + TransformMatrix bhomTransform = transform.FromRevit(); + instance = instance.Transform(bhomTransform, settings.DistanceTolerance) as ModelInstance; + instance.TransformGeometry(bhomTransform); + instance.TransformRepresentation(bhomTransform); + } return instance; } @@ -118,16 +138,54 @@ public static BH.oM.Spatial.SettingOut.Level Postprocess(this BH.oM.Spatial.Sett { level = level.ShallowClone(); level.Elevation += transform.Origin.Z.ToSI(SpecTypeId.Length); + TransformMatrix bhomTransform = transform.FromRevit(); + level.TransformGeometry(bhomTransform); + level.TransformRepresentation(bhomTransform); } return level; } + /***************************************************/ + /**** Private methods ****/ + /***************************************************/ + + private static void TransformGeometry(this IBHoMObject obj, TransformMatrix transform) + { + RevitGeometry geometryFragment = obj.FindFragment(); + if (geometryFragment != null) + { + obj.Fragments.Remove(geometryFragment); + obj.Fragments.Add(new RevitGeometry + ( + geometryFragment.Edges?.Select(x => x.ITransform(transform)).ToList(), + geometryFragment.Surfaces?.Select(x => x.ITransform(transform)).ToList(), + geometryFragment.Meshes?.Select(x => x.Transform(transform)).ToList() + )); + } + } + + /***************************************************/ + + private static void TransformRepresentation(this IBHoMObject obj, TransformMatrix transform) + { + RevitRepresentation representationFragment = obj.FindFragment(); + if (representationFragment != null) + { + obj.Fragments.Remove(representationFragment); + obj.Fragments.Add(new RevitRepresentation + ( + representationFragment.RenderMeshes?.Select(x => x.Transform(transform)) + )); + } + } + + /***************************************************/ /**** Fallback methods ****/ /***************************************************/ - + private static IObject Postprocess(this IObject obj, Transform transform, RevitSettings settings) { return obj; @@ -136,7 +194,3 @@ private static IObject Postprocess(this IObject obj, Transform transform, RevitS /***************************************************/ } } - - - -