Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

How to use the ElementIntersectsElementFilter from the RevitLinkInstance?

Anonymous

How to use the ElementIntersectsElementFilter from the RevitLinkInstance?

Anonymous
Not applicable

Dear All,

 

I need to get the MEP elements which from a linked file and intersect with some structural elements in current project.

 

I have try the ElementIntersectsElementFilter or the ElementIntersectsSolidFilter, if there is no transform between the RevitLinkInstance  and the current project. The filters are both works fine. But if the RevitLinkInstance be moved or rotated after importing, the calculation result of the filters are not correct.

 

So is that have any tricks can solve the case like that? For example,a method for pass a transform to the filter in the transaction. If no, please share a good algorithm to get the intersection result between two solid elements.

 

0 Likes
Reply
4,858 Views
11 Replies
Replies (11)

jeremytammik
Autodesk
Autodesk

Retrieve solids from the elements of interest and use SolidUtils.CreateTransformed on them:

 

https://apidocs.co/apps/revit/2019/22592761-f39c-4f53-d33b-6c21a4fa9d2d.htm

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Anonymous
Not applicable

Thanks a lot! You inspire me to develop with a new solution.

 

If there is a transform from the revitlinkinstance, the key point to use the ElementIntersectsSolidFilter correctly is transform the element in current project in same coordinate with the elements in the linked file project.

 

 

            Solid solid = getSolidFromElement(elm);
            foreach (RevitLinkedInstance ins in this._linkedInstaces)
            {
                Transform transform = ins.getTransform();
                if (transform.AlmostEqual(Transform.CreateTranslation(new
                 XYZ(0, 0, 0)) == false)
                {
                    solid = SolidUtils.CreateTransformed(solid, transform.Inverse);
                }
                FilteredElementCollector elmCol = new FilteredElementCollector(ins.getLinkedDocument());
                ElementIntersectsSolidFilter filter = new ElementIntersectsSolidFilter(solid);
                List<ElementId> resultsList = elmCol.WherePasses(filter).ToElementIds().ToList();

            }

 

 

0 Likes

jeremytammik
Autodesk
Autodesk

Congratulations on implementing such a very nice solution!

 

Could you please share your code for `getSolidFromElement` and `getTransform`, so we can see the complete details?

 

Thank you very much!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

jeremytammik
Autodesk
Autodesk

I cleaned up your code snippet to look like this:

 

    /// <summary>
    /// Collect the element ids of all elements in the 
    /// linked documents intersecting the given element.
    /// </summary>
    /// <param name="e">Target element</param>
    /// <param name="links">Linked documents</param>
    /// <param name="ids">Return intersecting element ids</param>
    /// <returns>Number of intersecting elements found</returns>
    int GetIntersectingLinkedElementIds( 
      Element e,
      IList<RevitLinkInstance> links,
      List<ElementId> ids )
    {
      int count = ids.Count();
      Solid solid = getSolidFromElement( e );

      foreach( RevitLinkInstance i in links )
      {
        Transform transform = i.getTransform();
        if( !transform.AlmostEqual( Transform.Identity) )
        {
          solid = SolidUtils.CreateTransformed( 
            solid, transform.Inverse );
        }
        ElementIntersectsSolidFilter filter 
          = new ElementIntersectsSolidFilter( solid );

        FilteredElementCollector intersecting 
          = new FilteredElementCollector( i.getLinkedDocument() )
            .WherePasses( filter );

        ids.AddRange( intersecting.ToElementIds() );
      }
      return ids.Count - count;
    }

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

c_hanschen
Advocate
Advocate

Hello!

 

First of all @jeremytammik and @Anonymous , thanks for sharing your code!

 

I'm trying to get it work, but my code returns no elements.

 

Here is my code in VB.net:

(I had to translate it to VB.net and need elements in return, not element id's)

 

Public Function GetIntersectingLinkedElements(MyElementCurrentDocument As Element, links As List(Of RevitLinkInstance)) As List(Of Element)

Dim IntersectingLinkedElements As New List(Of Element) 'construct empty list of elements
Dim sb As New StringBuilder() 'debug information
Dim MyListOfSolids As List(Of Solid) = GetAllSolidsOfElement(MyElementCurrentDocument) 'get all solids of the element

sb.AppendLine("Solids: " & MyListOfSolids.Count.ToString)
sb.AppendLine("Number of links: " & links.Count.ToString)

For Each MySolid As Solid In MyListOfSolids

For Each MyRevitLinkInstance As RevitLinkInstance In links

Dim MyTransform As Transform = MyRevitLinkInstance.GetTransform()

If MyTransform.AlmostEqual(Transform.Identity) = False Then MySolid = SolidUtils.CreateTransformed(MySolid, MyTransform.Inverse) 'transform my element to match the linked document

Dim filter As New ElementIntersectsSolidFilter(MySolid)
Dim intersecting As FilteredElementCollector = New FilteredElementCollector(MyRevitLinkInstance.Document).WherePasses(filter)

IntersectingLinkedElements.AddRange(intersecting.ToElements())

Next

Next

sb.AppendLine("IntersectingElements: " & IntersectingLinkedElements.Count.ToString)

MsgBox(sb.ToString())

Return IntersectingLinkedElements

End Function

 

It return 8 solids (that's correct) and 3 linkeddocuments (Also correct) but returns no elements at all.

 

what am i doing wrong? Any help would be appreciated!

 

Please take a look at the image (attachment) for easier reading of the code.

 

Many Thanks!

 

Chris

The Netherlands

0 Likes

c_hanschen
Advocate
Advocate

Sometimes it's like rubber-ducking, after sending my post I found the problem.

 

Were the code is:

MyRevitLinkInstance.Document

It should be:

MyRevitLinkInstance.GetLinkDocument

 

Maybe some VB.net user like my post anyway 😁

 

Chris

c_hanschen
Advocate
Advocate

@Anonymous , will you share your code from  `getSolidFromElement`

 

The function seems to work, but return wrong elements (not the elements that are intersecting).

maybe it is in the way you get your solids that is different than my way.

 

Thanks.

 

Chris

The Netherlands

 

0 Likes

c_hanschen
Advocate
Advocate

@jeremytammik and @Anonymous 

Thanks for all the info on this topic, it really helped, works great, but;

 

I managed to get it work really well, in basic you have to follow 3 steps to use the ElementIntersectsElementFilter :

- Get the Solid

- Transform the Solid by the Transform of the Instance

- Transform the Solid again if in a link by the transform of the LinkInstance.

By Following these 3 steps you can find all kind of intersections: model-model, model-link and link-model.

 

So far, so good, the ElementIntersectsElementFilter works really simple and great.

BUT, Why is it so slow? On a medium size model with a couple of links, it takes up to more than a second to find the intersecting element(s). That does not sound like much, but when clashing a 1000 instances, it takes 15 minutes!
(In my case, 5000 should not be a problem and should not take up to an hour or more)

When you compare this to Navisworks, it finds thousands of clashes in a second!

 

So i'm really impressed by the simple use of ElementIntersectsElementFilter, but is there a quicker way to find clashes through models? 

 

Thanks again,

 

Chris Hanschen

LKSVDD architecten 

The Netherlands

 

 

 

0 Likes

jeremy_tammik
Autodesk
Autodesk

The intersection filter is a slow filter. Therefore, you must expect the kind of performance you describe. However, this performance can be tremendously optimised by using quick filters first. You must never run a slow filter on hundreds of elements, let alone thousands. Use quick filters to eliminate 99% of all candidate elements, and use slow filters when only a handful remain. For instance, you can use the bounding box intersection filter first to eliminate the vast majority of elements, and then follow up on it with an intersection filter for fine-tuned handling of the last remaining few. People are using such algorithms to filter and perform interference checking with hundreds of thousands of elements.  Check out the discussion on slow and quick filters:

  

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open

c_hanschen
Advocate
Advocate

@jeremytammik , thanks again for your reply!

 

The combination of the bounding box intersection filter and the intersection filter works great!

 

Is there an way to combine this with a 'view' filter, working on linked file(s) with a view in the main model?

off course you can start your collector with New FilteredElementCollector(Mydoc, MyViewID), but is there a way this works with a linked model (MyDoc = RevitLinkInstance) and a view in the current model?

 

Thanks again!

 

Chris Hanschen

LKSVDD architecten

The Netherlands

0 Likes

jeremy_tammik
Autodesk
Autodesk

Very glad to hear that the combination works well. Yes, of course, you can combine any number of filters together very flexibly. Personally, I created some complex combinations for MEP elements, connectors, and structural elements. Check out The Building Coder topic group on filtered element collectors for those and many more examples:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.9

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open