We are delighted to announce the release of BimorphNodes v2.2, which 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 now provide holistic support for linked elements
- Clash detection codebase micro-optimised, resulting in +15% performance increase
- CAD.CurveFromCADLayers refactored with improved support for view-specific CAD links
- Curve.RemoveDuplicates refactored resulting in +80% performance increase
- Built on the Revit 2017 API (Revit 2015 no longer supported)
- Efficiency enhancements and general stability improvements
New Link-Element Class Nodes
The new LinkElement nodes include 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 locate the linked element in the host file. This is significant as the Revit API has a limitation which restricts linked elements to their external files center-to-center location, regardless of any transformations made to them in the host file. LinkElements have been purpose-built to solve this limitation by performing operations, such as geometry extraction, at the linked elements host location.
LinkElement instances can be created using 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 respective geometry at its host location by default:
There are also property nodes to access its associated Link Instance id, total transform and the embedded Dynamo Revit Element:
Link-Elements 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 center-to-center position, regardless of any transformations made to their Link Instance 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 center-to-center 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 center-to-center location:
LinkElements on the other-hand solve the problem by handling linked elements at their host location (where you see it in Revit), and this new functionality forms the basis for enabling holistic linked element support in the BimorphNodes BoundingBox and Element nodes:
Optimised for Bimorph Nodes Element and Bounding-Box 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.
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 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 (in fact, it would have limited each link to just 1 per document) with 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.
Link-Elements 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, due to the inheritance tree. To resolve such issues, use the LinkElement.Element node to extract the wrapped Revit element (i.e. the Dynamo Revit Element):
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 center-to-center 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’ should always be the global 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 center-to-center 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 Element and BoundingBox codebase has grown significantly. The new infrastructure includes subroutines that execute based on the conditions of the elements input (ordinary Element, non-LinkElement, LinkElement or tranformed LinkElement) and include all the logic to resolve the linked element transform limitation.
With more subroutines to execute, it stands to reason that impacts on performance would be inevitable. However, a fundamental objective for BimorphNodes v2.2 was to add the new functionality without undermining the ultra-efficient performance achieved in v2.1. Hence, we implemented a range of measures to minimise potential performance impacts, which included:
- Creation of the LinkElement class, optimised for use with BimorphNodes
- Micro-optimisation of the codebase
- Building BimorphNodes on the newer Revit 2017 API
The result? Between a 15-90% performance increase compared to BimorphNodes v2.1!
The following table shows the performance improvements using the Element.IntersectsElement node. For the purposes of comparison, the Walls vs Ducts clash test conducted when BimorphNodes v2.1 was released is used as the benchmark:
Performance Comparison Matrix
The table below shows the performance comparisons of the various clash tests between live Elements vs LinkElements controlled by the logic tree. The test conditions use the same Walls vs Ducts model used in the ‘Performance Impacts’ benchmark 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 center-to-center 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 a 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 (set to @L2 lacing) and List.FilterByBoolMask.
The following example shows a method for maintaining the data-structure output by the Element.Intersects nodes after cleaning the list:
CAD.CurvesFromCADLayers Adds View-Specific CAD Instance Support
CAD.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 translate 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 will default to the curves sketch plane.
Curve.RemoveDuplicates Refactored and 80% More Efficient
Curve.RemoveDuplicates has been refactored to improve the codebase, resulting in up to an 80% performance increase.
LineStyle.Create Breaking Changes
Building BimorphNodes v2.2 on the Revit 2017 API has enabled access to the Line Style’s pattern property, so we’ve added it as an input to the LineStyle.Create node. Note that line patterns are not supported in Revit 2016 and default to the Solid pattern instead. In addition, the Solid line style cannot be selected as it is not classed as a LinePatternElement and is not listed in Dynamo’s OOTB Line Patterns node. To create Solid lines in 2017+, 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. 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.
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 in v2.2. Compatible with Revit 2016+ and Dynamo 1.2+. (click to enlarge):