BIMORPH NODES V2.2 ADDS HOLISTIC SUPPORT FOR LINKED-ELEMENT CLASH DETECTION WITH NEW LINK-ELEMENT NODES
Dear Dynamo aficionados
Bimorph nodes v2.2 is now available for download via the Dynamo Package Manager.
BimorphNodes v2.2 introduces the new LinkElement class nodes to Dynamo which are purpose-built for retrieving elements from linked Revit models. While this functionality has existed for some time in a number of other packages, what makes LinkElements unique are the range of additional properties and features they implement that solve a major limitation in the Revit API (and therefore Dynamo) concerning the location of linked elements within their host file.
The other significant update in v2.2, also related to this issue, is the addition of holistic support for linked element clash detection using any of the Bimorph Element and BoundingBox nodes. LinkElements serve a vital role in enabling this functionality, resulting in a range of nodes that are no longer impeded by the problems that arise from limitations in the Revit API.
BimorphNodes v2.2 overview:
- New LinkElement class nodes for rapid interop with elements from linked Revit models
- Element.IntersectsElement, Element.IntersectsSolid, BoundingBox.GetElementsInside and BoundingBox.GetElementsIntersect nodes provide holistic support for linked elements
- Clash detection codebase micro-optimised, resulting in 15-25% performance increase
- CurveFromCADLayers refactored with improved support for view-specific CAD links
- Curve.RemoveDuplicates 80% performance increase
- Built on the Revit 2017 API (support for Revit 2015 dropped)
- Efficiency enhancements and general stability improvements
New LinkElement Class Nodes
The new LinkElement class includes a range of methods and properties for retrieving and interacting with Elements from a linked Revit model (a Link Instance). What makes LinkElements unique are the way they handle the location of the element in coordinate space. There is a limitation in the Revit API which restricts any element derived from a Link Instance to its external files origin-to-origin location regardless of any transformations that may have been made to the Link Instance. LinkElements have been purpose-built to solve this limitation by performing operations on the linked element, such as geometry extraction, at its host location.
To create LinkElement instances use the LinkElement.OfCategory node:
Properties and metadata attached to the LinkElement instance can be accessed using the LinkElement property nodes. The Solids, Faces, Location and BoundingBox nodes return the resultant geometry at the LinkElements host location by default (not its origin-to-origin location):
There are also property nodes to access its associated Link Instance id, total transform and the embedded Dynamo Revit Element:
LinkElements Solve the Revit API Linked Element Transform Limitation
The linked element transform limitation manifests only in the Revit API context, which subsequently exposes a number of BimorphNodes to the problem. As mentioned, this limitation causes linked elements to default to their external files origin-to-origin position, even if the elements Link Instance has been transformed in the host document. The Revit projects most at risk of this problem are those where transformations have been applied to the Link Instance for coordination purposes, which is likely if Shared Coordinates are in use or if linked models have been manually moved to align with the main building model.
The problem is most pronounced when calling Revit API methods on a linked element where its relative location in the host file is required to yield a result. For example, the Revit API ElementQuickFilter and ElementSlowFilter class methods – which are used for clash detection in the BimorphNodes BoundingBox and Element nodes – produce erroneous results if element A vs B includes any linked elements which have been transformed. This is especially confusing to users since any linked Revit models which are moved to visually align with other links or live elements in the host file, are always positioned back at their respective origin-to-origin locations in the API context, causing the clash results to fail unexpectedly.
The following example illustrates the problem, showing the position of bounding boxes created in the API context from linked wall elements while its Link Instance is transformed. One would expect the bounding boxes to be drawn where the walls are positioned in the host model, but the Revit API limits them to the links origin-to-origin location:
LinkElements solve this limitation by handling linked elements at their host location (where you see it in Revit) and not the origin-to-origin location imposed by the Revit API:
Optimised for BimorphNodes Element and BoundingBox Nodes
LinkElements are optimised for use with BimorphNodes Element and BoundingBox nodes, firstly to ensure they remain ultra-efficient, and secondly to enable them to support linked elements regardless of any transformations made to their associated Link Instance in the host file.
However, the creation of the LinkElement class to enable this new functionality has had consequences; any custom code or package which collects elements from a linked Revit model (SpringNodes, Archi-lab, SteamNodes, etc) are no longer supported. The decision to drop support was due to:
There being no direct way to identify a linked elements Revit Link Instance through the API, which is critical as it stores the total transform (coordinate system) needed to locate the element at its host location. The Link Instance can be obtained indirectly by accessing the elements Document property, but this simple technique crippled performance, causing speed-of-execution to drop by more than 250%!
Moreover, even if this approach was adopted, it’s flawed as the available data provides no means to reliably identify a Link Instance if it has been linked multiple times in the same file
Settling for compromised functionality that would have prohibited unlimited support of Link Instances (it would have limited each link to 1 per document!) and crippled performance, was unacceptable, and this led to the development of the LinkElement class and the decision to make it exclusive.
The LinkElement class therefore plays a vital role in enabling the new linked element support in the Bimorph Element and BoundingBox nodes.
LinkElements Inherit Dynamo’s Element Class
To maximise functionality, LinkElements inherit from Dynamo’s Revit.Elements.Element class, meaning instances are compatible with all of Dynamo’s Element nodes and any other nodes that accept Elements as inputs.
There are some limitations with certain nodes in Dynamo’s Revit library that will not recognise LinkElements. For example, LinkElement Room’s are not compatible with the OOTB Room nodes, such as Room.Number. To resolve these issues, use the LinkElement.Element node to extract the wrapped Revit element (i.e. the Dynamo Revit Element) stored in the LinkElement and pass it into any nodes that are affected by this problem:
One drawback of extracting the Element is the loss of properties provided by the LinkElement. It means that any operations, such as geometry extraction, revert back to the linked elements origin-to-origin location. To manually resolve this issue, use the OOTB Geometry.Translate node and input the corresponding LinkElements TotalTransform as the ‘context coordinate system’. The ‘from coordinate system’ is always Identity:
HOLISTIC SUPPORT FOR LINKED-ELEMENT CLASH DETECTION
The Element.IntersectsElement, Element.IntersectsSolid, BoundingBox.GetElementsInside and BoundingBox.GetElementsIntersect have been updated with a new clash detective algorithm which enables holistic support for linked elements even if their Link Instances have been transformed or translated. It means that the limitation imposed on linked elements by the Revit API, which before the update impeded their functionality, is now fully resolved.
To enable this support the nodes depend on the new LinkElement class and leverage its properties to locate linked elements at their host locations. By utilising LinkElements, the nodes can be used to develop unique and highly versatile workflows that range from supporting linked elements from an unlimited number of Link Instances (ideal for large-scale residential schemes and master plans where multiple Link Instances are common), to linked element vs linked element clash detection, even if the elements derive from multiple Link Instances with different origin-to-origin locations (a problem which has no direct solution in the Revit API).
The nodes also implement a smart logic-tree which is designed to execute only the subroutines that are relevant to conditions of the intersection test being computed. The logic tree is central to minimising any performance overheads that arise from the new infrastructure, resulting in near-negligible compromises to speed-of-execution.
Summary of new features:
- Resolves the Revit API limitation imposed on linked elements
- Supports elements from an unlimited number of Link Instances
- Smart logic-tree minimises performance overheads of new functionality
How it Works
Providing the Element and BoundingBox nodes with holistic support for linked elements has not resulted in any changes to their inputs or outputs as all the updates have occurred internally. Therefore, using LinkElements with these nodes is no different to using Elements; simply collect the required linked elements using the LinkElement.OfCategory node, then provide the resultant LinkElement instances as inputs.
The following graph shows how to utilise LinkElements with the Element.IntersectsElement node to perform multi-category linked element clash detection, without being impeded by the Revit API limitations:
Utilising LinkElements with the BoundingBox.GetElementsIntersect node:
Are There Performance Impacts?
To enable holistic support for linked elements the codebase for the Element.Intersects nodes and BoundingBox nodes has grown significantly. The new infrastructure includes subroutines that are executed based on the conditions of the element input (ordinary Element, non-LinkElement, LinkElement or tranformed LinkElement) and include all the logic to resolve the limitations of linked elements imposed by the Revit API.
With more executable commands, it stands to reason that performance will be impacted. Yet, a key objective of BimorphNodes v2.2 was to resolve the linked element limitation and minimise the impacts on performance. Achieving this goal was made possible by:
- Creating of the LinkElement class, and optimising it for use with the BoubdingBox and Element.Intersects nodes
- Micro-optimising the codebase
- Building BimorphNodes on the Revit 2017 API
To answer the question then: there have been no noticeable impacts on performance, despite the new infrastructure. Speed-of-execution has actually got faster, resulting in at least a 15% increase in performance.
The following table shows the speed-of-execution improvements between v2.1 and v2.2 Element.IntersectsElement node. For the purposes of comparison, the Walls vs Ducts clash test conducted in BimorphNodes v2.1 to evaluate the performance of the Element.IntersectsElement node is used as the benchmark:
Performance Comparison Matrix
The following table shows the performance comparison between the various combinations of live Elements vs LinkElements controlled by the logic tree. The test conditions use the same Walls vs Ducts model mentioned in the ‘Performance Impacts’ section above:
Computation times shown in seconds. Walls (2,300) vs Ducts (2,160). Total Possible Clash Tests: 4,968,000 | Transformed LinkElements are moved, rotated and mirrored from their origin-to-origin location | Tested on: Windows 10, Revit 2018.2, Dynamo 1.3.2 and HP ZBook Intel i7-4710MQ 2.5GHz, 16GB DDR Memory, 256GB SSD
To support the transition to LinkElements, BimorphNodes BoundingBox and Element nodes include new exception handling to validate the list of elements input by the user. While this provides useful feedback if an invalid linked element is found, it reintroduces the performance impacts that led to the development of the LinkElement class in the first place (as the validation procedure must access each elements Document property to check if it is linked). To mitigate these impacts but still provide the advantages of element validation, a method of ‘validation sampling’ has been implemented.
Validation sampling selects a range of elements from the list at every interval using the equation: d / (5 + (0.01 * d)) where d = the count of items in the input list. Sampled elements are tested to verify if they are linked and where true, if they are instances of the LinkElement class. If any elements are linked but not LinkElements, the following exception is thrown:
Note that as a selection of elements are evaluated, there is potential non-valid linked elements can pass through the validation test if they are between the selection interval. However, the risks are negligible as the user would need to input a heterogeneous list interspersed with only a few invalid linked elements for this to occur. To eliminate the risk completely, always use LinkElements when your workflow requires them.
Mitigating ‘Dereferencing Non-Pointer’ Exceptions
There is known bug in Dynamo which throws a ‘dereferencing a non-pointer’ exception whenever a list of objects which contains either null or an empty list at index 0 (the start of the list) is input into any Query (property) node.
While most workflows are unlikely to be affected, it requires special mention since the Element.Intersects nodes are designed to output clash results via a 2D list (list of lists), where empty sub-lists indicate no clashes. Due to this behaviour, there is a higher probability that index 0 will be empty, making these nodes more susceptible to the bug.
As the Dynamo dev team have stated the bug is unlikely to be fixed by Dynamo v2.0, a simple workaround can be used in the interim by cleaning the list of empty sub-lists before passing it into any Query nodes using the OOTB List.IsEmpty and List.FilterByBoolMask. The following example shows a method for maintain the data-structure output by the Element.Intersects nodes after cleaning the list:
CAD.CurvesFromCADLayers Adds View-Specific CAD Instance Support
CurvesFromCADLayers includes new functionality to support curve conversion of any CAD link or import that is view-specific. In previous versions, curves from view-specific CAD instances would default to the sketch plane of the curve (typically the global XY plane at 0.0 elevation). In BimorphNodes v2.2 the node has been designed to translates curves to the sketch plane of the owner-view if the view is a plan, area plan or structural plan. All other view types do not have a sketch plane and remain unchanged in behaviour.
Curve.RemoveDuplicates Refactored and 80% More Efficient
Curve.RemoveDuplicates has been refactored to improve the codebase and provide an opportunity to enhance its performance. The result of the refactoring has reduced typical processing times by up to 80%.
LineStyle.Create Breaking Changes
Building BimorphNodes on the Revit 2017 API has enabled access to the Line Style’s pattern property. In v2.2, LineStyle.Create now node includes the Line Styles pattern as an input to utilise this new functionality. Note that line patterns are not supported in Revit 2016 and will be ignored, defaulting to the Solid pattern instead. In addition, the Solid line style can be selected as it is not classed as a LinePatternElement and is not listed in Dynamo’s OOTB Line Patterns node. To mitigate this limitation, leave the input unconnected and the Line Pattern will default to Solid.
There has also been a breaking change due to the removal of the run input and introduction of the line pattern input. Upgrading will cause the node inputs to change order but not update the wires (i.e. the function inputs) – we therefore suggest manually updating any graphs which utilise the LineStyle.Create node.
Element.IsElementSupported Improved Results
Element.IsElementSupported includes new updates to enable it to return more consistent results and evaluate elements that BimorphNodes Element and BoundingBox nodes do not support, such as linked elements. The inconsistencies were caused by the Revit API method in use where some elements would report as ‘supported’ but its Category would report as ‘unsupported’ by the Element.IsCategorySupported. Both results must be true otherwise the element is not supported. The Revit Development team suggested this was ‘normal’ behaviour, and to combine the results. Hence, both tests are now performed to yield a result.
The Element.IsCategorySupported has been depreciated as it no longer serves any purpose due to the updates made to the Element.IsElementSupported node. To avoid any disruption to graphs, the node is still included in BimorphNodes v2.2 but hidden from the library – we recommend manually replacing this node with IsElementSupported as it will be removed completely by v3.0.
Don’t forget to check out our BimorphNodes content pages and YouTube channel for user guides and extra content. New video content will be added in due course; be sure to subscribe to get notifications:
We’ve also recently moved the BimorphNodes dictionary to our new domain, Bimorph.com. Links for the old .co.uk domain automatically redirect, but we recommend updating any bookmarks and referring links to point to the new domain.
BIMORPH NODES V2.2 LIBRARY
List of BimorphNodes v2.2. Compatible with Revit 2016+ and Dynamo 1.2+: