diff --git a/Revit_Core_Engine/Objects/Active2dViewVisibilityContext.cs b/Revit_Core_Engine/Objects/Active2dViewVisibilityContext.cs new file mode 100644 index 000000000..2b532815c --- /dev/null +++ b/Revit_Core_Engine/Objects/Active2dViewVisibilityContext.cs @@ -0,0 +1,109 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using Autodesk.Revit.DB; +using System.ComponentModel; + +#if (!REVIT2018 && !REVIT2019) +namespace BH.Revit.Engine.Core +{ + [Description("Class used to extract elements visible in the active view of the host document if that view is of 2d type. See " + nameof(Query.ElementIdsByVisibleInActiveView) + " for usage example.")] + public class Active2dViewVisibilityContext : ActiveViewVisibilityContext, IExportContext2D + { + /***************************************************/ + /**** Constructor ****/ + /***************************************************/ + + [Description("hostDocument refers to the document that owns the active view. targetDocument can take three values:" + + "\n- same as hostDocument - visible elements of the host document are then collected" + + "\n- document linked in the host document - elements of that linked document visible in the active view of the host document are then collected" + + "\n- null - all elements of all documents, host and links, are then collected")] + public Active2dViewVisibilityContext(Document hostDocument, Document targetDocument) : base(hostDocument, targetDocument) + { + } + + + /***************************************************/ + /**** Public methods ****/ + /***************************************************/ + + public RenderNodeAction OnElementBegin2D(ElementNode node) + { + return base.OnElementBegin(node.ElementId); + } + + /***************************************************/ + + public void OnElementEnd2D(ElementNode node) + { + } + + /***************************************************/ + + public RenderNodeAction OnFaceEdge2D(FaceEdgeNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public RenderNodeAction OnFaceSilhouette2D(FaceSilhouetteNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public RenderNodeAction OnCurve(CurveNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public RenderNodeAction OnPolyline(PolylineNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public void OnLineSegment(LineSegment segment) + { + } + + /***************************************************/ + + public void OnPolylineSegments(PolylineSegments segments) + { + } + + /***************************************************/ + + public void OnText(TextNode node) + { + } + + /***************************************************/ + } +} +#endif \ No newline at end of file diff --git a/Revit_Core_Engine/Objects/ActiveViewVisibilityContext.cs b/Revit_Core_Engine/Objects/ActiveViewVisibilityContext.cs new file mode 100644 index 000000000..6008c0f8e --- /dev/null +++ b/Revit_Core_Engine/Objects/ActiveViewVisibilityContext.cs @@ -0,0 +1,224 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using Autodesk.Revit.DB; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace BH.Revit.Engine.Core +{ + [Description("Class used to extract elements visible in the active view of the host document if that view is of 3d type. See " + nameof(Query.ElementIdsByVisibleInActiveView) + " for usage example.")] + public class ActiveViewVisibilityContext : IExportContext + { + /***************************************************/ + /**** Constructor ****/ + /***************************************************/ + + [Description("hostDocument refers to the document that owns the active view. targetDocument can take three values:" + + "\n- same as hostDocument - visible elements of the host document are then collected" + + "\n- document linked in the host document - elements of that linked document visible in the active view of the host document are then collected" + + "\n- null - all elements of all documents, host and links, are then collected")] + public ActiveViewVisibilityContext(Document hostDocument, Document targetDocument) + { + m_HostDocument = hostDocument; + m_TargetDocument = targetDocument; + m_Documents.Push(hostDocument); + m_DocumentLookup[hostDocument.PathName] = hostDocument; + m_Elements.Add(hostDocument.PathName, new HashSet()); + } + + + /***************************************************/ + /**** Public methods ****/ + /***************************************************/ + + [Description("Returns ids of all elements visible in the active view of the host document. The ids are grouped by document they belong to.")] + public Dictionary> GetAllElementsVisibleInActiveView() + { + if (m_TargetDocument != null) + { + BH.Engine.Base.Compute.RecordError($"The context has been processed with a single target document. Please run again making sure that the target document parameter in the context constructor is null."); + return null; + } + else + return m_DocumentLookup.ToDictionary(x => x.Value, x => m_Elements[x.Key]); + } + + /***************************************************/ + + [Description("Returns ids of given target document's elements visible in the active view of the host document.")] + public HashSet GetElementsVisibleInActiveView(Document targetDocument) + { + HashSet result = null; + if (!m_Elements.TryGetValue(targetDocument?.PathName, out result)) + BH.Engine.Base.Compute.RecordError($"Document {targetDocument.Title} has not been processed in the context. Please run again making sure the document is passed as target document in the context constructor or the target document parameter is null."); + + return result; + } + + /***************************************************/ + + public void Finish() + { + } + + /***************************************************/ + + public bool IsCanceled() + { + return false; + } + + /***************************************************/ + + public RenderNodeAction OnElementBegin(ElementId elementId) + { + Document doc = m_Documents.Peek(); + m_Elements[doc.PathName].Add(elementId); + + Element element = doc.GetElement(elementId); + if (element is RevitLinkInstance) + { + RevitLinkInstance linkInstance = (RevitLinkInstance)element; + if (m_TargetDocument == null || m_TargetDocument.PathName == linkInstance.GetLinkDocument().PathName) + { + m_DocumentLookup[linkInstance.Document.PathName] = linkInstance.Document; + return RenderNodeAction.Proceed; + } + } + + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public void OnElementEnd(ElementId elementId) + { + } + + /***************************************************/ + + public RenderNodeAction OnFaceBegin(FaceNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public void OnFaceEnd(FaceNode node) + { + } + + /***************************************************/ + + public RenderNodeAction OnInstanceBegin(InstanceNode node) + { + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public void OnInstanceEnd(InstanceNode node) + { + } + + /***************************************************/ + + public void OnLight(LightNode node) + { + } + + /***************************************************/ + + public RenderNodeAction OnLinkBegin(LinkNode node) + { + Document doc = node.GetDocument(); + m_Documents.Push(doc); + if (!m_Elements.ContainsKey(doc.PathName)) + m_Elements[doc.PathName] = new HashSet(); + + return RenderNodeAction.Proceed; + } + + /***************************************************/ + + public void OnLinkEnd(LinkNode node) + { + m_Documents.Pop(); + } + + /***************************************************/ + + public void OnMaterial(MaterialNode node) + { + } + + /***************************************************/ + + public void OnPolymesh(PolymeshTopology node) + { + } + + /***************************************************/ + + public void OnRPC(RPCNode node) + { + } + + /***************************************************/ + + public RenderNodeAction OnViewBegin(ViewNode node) + { + if (node.ViewId == m_HostDocument.ActiveView.Id) + return RenderNodeAction.Proceed; + else + return RenderNodeAction.Skip; + } + + /***************************************************/ + + public void OnViewEnd(ElementId elementId) + { + } + + /***************************************************/ + + public bool Start() + { + return true; + } + + + /***************************************************/ + /**** Private fields ****/ + /***************************************************/ + + private Document m_HostDocument; + private Document m_TargetDocument; + private Stack m_Documents = new Stack(); + private Dictionary m_DocumentLookup = new Dictionary(); + private Dictionary> m_Elements = new Dictionary>(); + + /***************************************************/ + } +} diff --git a/Revit_Core_Engine/Query/ElementIds/ElementIds.cs b/Revit_Core_Engine/Query/ElementIds/ElementIds.cs index a97f1fec0..336fdd201 100644 --- a/Revit_Core_Engine/Query/ElementIds/ElementIds.cs +++ b/Revit_Core_Engine/Query/ElementIds/ElementIds.cs @@ -320,6 +320,20 @@ public static IEnumerable ElementIds(this FilterByVisibleInView reque /***************************************************/ + [Description("Finds the ElementIds of all elements within the Revit document that pass the filtering criteria set in the given FilterByVisibleInActiveView request.")] + [Input("request", "FilterByVisibleInActiveView request containing the filtering criteria, against which the elements in the Revit document are checked.")] + [Input("document", "Revit Document queried for the filtered elements.")] + [Input("discipline", "Engineering discipline based on the BHoM discipline classification.")] + [Input("settings", "Revit adapter settings to be used while evaluating the elements against the filtering criteria.")] + [Input("ids", "Optional, allows narrowing the search: if not null, the output will be an intersection of this collection and ElementIds filtered by the query.")] + [Output("elementIds", "Collection of filtered Revit ElementIds.")] + public static IEnumerable ElementIds(this FilterByVisibleInActiveView request, Document document, Discipline discipline = Discipline.Undefined, RevitSettings settings = null, IEnumerable ids = null) + { + return document.ElementIdsByVisibleInActiveView(ids); + } + + /***************************************************/ + [Description("Finds the ElementIds of all elements within the Revit document that pass the filtering criteria set in the given FilterViewByName request.")] [Input("request", "FilterViewByName request containing the filtering criteria, against which the elements in the Revit document are checked.")] [Input("document", "Revit Document queried for the filtered elements.")] diff --git a/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInActiveView.cs b/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInActiveView.cs new file mode 100644 index 000000000..0496930ff --- /dev/null +++ b/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInActiveView.cs @@ -0,0 +1,92 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using Autodesk.Revit.DB; +using BH.oM.Base.Attributes; +using System.Collections.Generic; +using System.ComponentModel; + +namespace BH.Revit.Engine.Core +{ + public static partial class Query + { + /***************************************************/ + /**** Public methods ****/ + /***************************************************/ + + [Description("Filters ElementIds of elements that are visible in active view of the host document. If the input document is a linked document, its elements visible in the active view of the host document will be returned.")] + [Input("document", "Revit document to be processed (can be a linked document).")] + [Input("ids", "Optional, allows narrowing the search: if not null, the output will be an intersection of this collection and ElementIds filtered by the query.")] + [Output("elementIds", "Collection of filtered ElementIds.")] + public static IEnumerable ElementIdsByVisibleInActiveView(this Document document, IEnumerable ids = null) + { + if (document == null) + return null; + + Document hostDocument = document.IsLinked ? document.HostDocument() : document; + + ActiveViewVisibilityContext context; + if (hostDocument.ActiveView is View3D) + context = new ActiveViewVisibilityContext(hostDocument, document); + else + { +#if (REVIT2018 || REVIT2019) + BH.Engine.Base.Compute.RecordError($"Querying visible elements from the active view failed because only 3d views are supported in Revit 2019 or older. In later versions also 2d views can be queried."); + return null; +#else + context = new Active2dViewVisibilityContext(hostDocument, document); +#endif + } + + CustomExporter exporter = new CustomExporter(hostDocument, context); + exporter.IncludeGeometricObjects = false; + exporter.ShouldStopOnError = false; + +#if (!REVIT2018 && !REVIT2019) + exporter.Export2DIncludingAnnotationObjects = true; +#endif + + try + { + exporter.Export(new List { hostDocument.ActiveView.Id }); + } + catch (Autodesk.Revit.Exceptions.ArgumentException ex) + { + if (ex.ParamName == "viewIds") + { + BH.Engine.Base.Compute.RecordError($"Visible elements could not be queried from the active view because views of type {hostDocument.ActiveView.ViewType} are not queryable in this version of Revit."); + return null; + } + else + throw; + } + + HashSet result = context.GetElementsVisibleInActiveView(document); + if (ids != null) + result.IntersectWith(ids); + + return result; + } + + /***************************************************/ + } +} diff --git a/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInView.cs b/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInView.cs index 873c5d83b..46848ec7d 100644 --- a/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInView.cs +++ b/Revit_Core_Engine/Query/ElementIds/ElementIdsByVisibleInView.cs @@ -35,7 +35,7 @@ public static partial class Query /**** Public methods ****/ /***************************************************/ - [Description("Filters ElementIds of elements that are visible in a view.")] + [Description("Filters ElementIds of elements that are visible in a view. Works only for querying the document that owns the view under the input viewId.")] [Input("document", "Revit document to be processed.")] [Input("viewId", "ElementId of the Revit view in which the filtered elements are visible.")] [Input("ids", "Optional, allows narrowing the search: if not null, the output will be an intersection of this collection and ElementIds filtered by the query.")] @@ -68,4 +68,3 @@ public static IEnumerable ElementIdsByVisibleInView(this Document doc /***************************************************/ } } - diff --git a/Revit_Core_Engine/Revit_Core_Engine.csproj b/Revit_Core_Engine/Revit_Core_Engine.csproj index dd4eed7b5..61124b3d1 100644 --- a/Revit_Core_Engine/Revit_Core_Engine.csproj +++ b/Revit_Core_Engine/Revit_Core_Engine.csproj @@ -423,6 +423,8 @@ + + @@ -435,6 +437,7 @@ + diff --git a/Revit_oM/Requests/FilterByVisibleInActiveView.cs b/Revit_oM/Requests/FilterByVisibleInActiveView.cs new file mode 100644 index 000000000..1882e0deb --- /dev/null +++ b/Revit_oM/Requests/FilterByVisibleInActiveView.cs @@ -0,0 +1,40 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Data.Requests; +using System.ComponentModel; + +namespace BH.oM.Adapters.Revit.Requests +{ + [Description("IRequest that filters elements visible in active view of the host Revit document. Combine with " + nameof(FilterByLink) + " to query linked documents for elements visible in active view of the host document.")] + public class FilterByVisibleInActiveView : IRequest + { + /***************************************************/ + /**** Properties ****/ + /***************************************************/ + + + /***************************************************/ + } +} + + diff --git a/Revit_oM/Requests/FilterByVisibleInView.cs b/Revit_oM/Requests/FilterByVisibleInView.cs index c97726613..81a25aa51 100644 --- a/Revit_oM/Requests/FilterByVisibleInView.cs +++ b/Revit_oM/Requests/FilterByVisibleInView.cs @@ -25,7 +25,7 @@ namespace BH.oM.Adapters.Revit.Requests { - [Description("IRequest that filters all elements visible in a given Revit view.")] + [Description("IRequest that filters all elements visible in a given Revit view. Works only for querying the host document (will not return valid results if combined with " + nameof(FilterByLink) + ").")] public class FilterByVisibleInView : IRequest { /***************************************************/ diff --git a/Revit_oM/Revit_oM.csproj b/Revit_oM/Revit_oM.csproj index 4ceea9a5a..a649b130a 100644 --- a/Revit_oM/Revit_oM.csproj +++ b/Revit_oM/Revit_oM.csproj @@ -124,6 +124,7 @@ +