Find Intersecting Elements

Right now I am sitting in the Tel Aviv Ben Gurion airport, which very friendlily provides free public wifi Internet access, unlike the also very friendly staff with an unfortunately less generous wifi policy in the Sheraton hotel we stayed at, who (try to) charge USD 20 per day for the same service.

Yesterday we looked at the

XML family usage report
from
Kevin Vandecar’s

filtering and optimisation
presentation
at the

AEC DevCamp
conference
in Boston in June, which formed the base of my

AU class CP234-2
on
the same topic.

I would like to present another of Kevin’s filtering examples, which I find rather neat and demonstrates one approach to find all element in close proximity to a selected one.
This frequently requested function is easy to implement, because the filtered element collector framework offers classes providing exactly the functionality we need for this:

  • The collector viewId constructor narrows down the selection to only viewable elements.
  • The BoundingBoxIntersectsFilter returns all elements that intersect a given bounding box.
  • An
    exclusion filter can be used to eliminate known elements to exclude, specifically:

    • The view itself, which often will have an intersecting bounding box.
    • The selected element.

Here is the short external command Execute mainline implementation putting this together:


[Transaction( TransactionMode.ReadOnly )]
[Regeneration( RegenerationOption.Manual )]
public class FilterEx2 : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string message,
    ElementSet elements )
  {
    UIApplication uiApp = commandData.Application;
    UIDocument uiDoc = uiApp.ActiveUIDocument;
    Application app = uiApp.Application;
    Document doc = uiDoc.Document;
 
    // Select something to use as base bounding box.
 
    Reference r = uiDoc.Selection.PickObject(
      ObjectType.Element );
 
    // Find the bounding box from the selected 
    // object and convert to outline.
 
    BoundingBoxXYZ bb = r.Element.get_BoundingBox(
      doc.ActiveView );
 
    Outline outline = new Outline( bb.Min, bb.Max );
 
    // Create a BoundingBoxIntersectsFilter to 
    // find everything intersecting the bounding 
    // box of the selected element.
 
    BoundingBoxIntersectsFilter bbfilter
      = new BoundingBoxIntersectsFilter( outline );
 
    // Use a view to construct the filter so we 
    // get only visible elements. For example, 
    // the analytical model will be found otherwise.
 
    FilteredElementCollector collector
      = new FilteredElementCollector(
        doc, doc.ActiveView.Id );
 
    // Lets also exclude the view itself (which 
    // often will have an intersecting bounding box), 
    // and also the element selected.
 
    ICollection<ElementId> idsExclude
      = new List<ElementId>();
 
    idsExclude.Add( r.Element.Id );
    // No need for this, BoundingBoxIntersectsFilter 
    // excludes all objects derived from View, as 
    // pointed out by Jim Jia below:
    //
    //idsExclude.Add( doc.ActiveView.Id );
 
    // Get the set of elements that pass the 
    // criteria. Note both filters are quick, 
    // so order is not so important.
 
    collector.Excluding( idsExclude )
      .WherePasses( bbfilter );
 
    // Generate a report to display in the dialog.
 
    int nCount = 0;
    string report = string.Empty;
    foreach( Element e in collector )
    {
      string name = e.Name;
 
      report += "nName = " + name
        + " Element Id: " + e.Id.ToString();
 
      nCount++;
    }
 
    Util.ShowTaskDialog(
      "Bounding Box + View + Exclusion Filter",
      "Found " + nCount.ToString()
      + " elements whose bounding box intersects",
      report );
 
    return Result.Succeeded;
  }
}

Running this in the StructuralUsage.rvt model, I select the following highlighted beam:

Beam intersecting various elements

This produces the following report of intersecting elements:

Report of intersecting elements


Comments

28 responses to “Find Intersecting Elements”

  1. idsExclude.Add( doc.ActiveView.Id );
    We don’t need to do this, the BoundingBoxIntersectsFilter will do this automatically,see the RevitAPI.chm remarks for this filter: “This filter excludes all objects derived from View and objects derived from ElementType”.

  2. Dear Jim,
    Hey, well spotted! Thank you for pointing this out!
    I modified the code above to reflect this. For an updated zip file containing the entire solution, please refer to
    http://thebuildingcoder.typepad.com/blog/2010/12/more-kevin-filtering-benchmarks.html
    Cheers, Jeremy.

  3. how to solve does not have ” Util.ShowTaskDialog” Order question.
    Thank~

  4. Dear James,
    What a fascinatingly cryptic question you created. Congratulations!
    Cheers, Jeremy.

  5. Asger petersen Avatar
    Asger petersen

    Hi Jeremy Tammik.
    I have a problem with line 115 “Util.ShowTaskDialog (”
    Error: The name ‘Util’ does not exist in the current context. You know why?
    thanks for your time :-)

  6. Dear Asger,
    As you can guess from the screen snapshot of the resulting message box, the ShowTaskDialog method is just a trivial wrapper for the Revit API TaskDialog class. The only thing it adds is to also list a truncated version the output to the Visual Studio debug output window. It is implemented like this:
    public static void ShowTaskDialog(
    string title,
    string info,
    string content )
    {
    string s = title + “: ” + info;
    if( 0 < content.Length )
    {
    Debug.Assert( 15 < content.Length,
    “expected at least 15 characters of content” );
    s += “: ” + content.Substring( 0, 15 ) + “…”;
    }
    Debug.Print( s );
    TaskDialog dialog = new TaskDialog( title );
    dialog.MainInstruction = info;
    dialog.MainContent = content;
    dialog.Show();
    }
    You can also grab the entire filtering sample application including the Util class from the AU class materials. It is all included there.
    Cheers, Jeremy.

  7. Asger petersen Avatar
    Asger petersen

    Hi Jeremy.
    Thanks for your quick response.
    Is possible only too select the objects that are 100% inside the BoundingBox??
    Cheers, Asger

  8. Dear Asger,
    Please have a look at the BoundingBoxIsInsideFilter class.
    Cheers and good luck, Jeremy.

  9. Asger petersen Avatar
    Asger petersen

    Hi Jeremy.
    Many thanks for “BoundingBoxIsInsideFilter” it was really useful
    I want to write to “comments” to all the selected object.
    I can only write to the “comments” on the bounding box,
    what I am missing?
    Parameter param = r.Element.get_Parameter(“comments”);
    String comments = “”;
    comments = param1.AsString();
    param.Set(“test”);

  10. Dear Asger,
    The bounding box has no parameters, so you cannot write to them.
    You can write to the parameters on the Revit database element.
    Other than that, and that the fact that you once say ‘param’ and once ‘param1’, your code looks fine to me.
    Cheers, Jeremy.

  11. Asger petersen Avatar
    Asger petersen

    Hi Jeremy.
    I read parameter “comments” from the bounding box / object and writes to objects inside the bounding box like this:
    //Get Comments from bounding box
    Parameter param1 = r.Element.get_Parameter(“Comments”);
    String comments = “”;
    comments = param1.AsString();
    and write to objects like this:
    Transaction trans = new Transaction(doc);
    trans.Start(“Lab”);
    e.get_Parameter(“Comments”).Set(comments);
    trans.Commit();
    But why can not I find columns inside the bounding box?

  12. Dear Asger,
    Your code for writing the comment string to the parameter value looks fine to me.
    I do not see what it has to do with finding columns inside a bounding box, though.
    The two issues sound pretty unrelated to me.
    Are you using the BoundingBoxIsInsideFilter?
    Have you checked what exact data the bounding boxes of the columns really have? Maybe they expand too far?
    Cheers, Jeremy.

  13. Asger petersen Avatar
    Asger petersen

    Hi Jeremy.
    yes I use BoundingBoxIsInsideFilter…..
    My bounding box is offset -240mm from Level 1 and Level 2 (Distance between level 3100mm)
    Column height is 1000mm.
    base offset Level 1: 0 mm.
    Top Offset level 2: -2100mm.
    I have found 2 ways to find columns on.
    1. If I change the top offset to: Level 1 1000mm, can I find the column inside the bounding box.
    2. If I use the “analytical model” parameter “Top vertical projection” and set it to “Top of Columns.” can I find the column inside the bounding box.
    why can not I find colomns without change the parameter?
    I have the same problems with stairs.
    Is there a way I can find all objects inside the bounding box?

  14. Dear Asger,
    It should be simple to test what is happening with the filter (to see if something’s wrong with the filter or not): just get the bounding box of the target element (element.get_BoundingBox(null)) and see if it mathematically lies within the target outline.
    Remember that BoundingBoxIsInsideFilter requires that the entire element outline be within the target volume, there can be no intersections with the boundaries.
    I suspect it will show that the bounding box for this column exceeds the limits in some way. The more interesting question then becomes: why is its bounding box shaped as it is, which we could investigate if a model is supplied.
    Cheers, Jeremy.

  15. Asger petersen Avatar
    Asger petersen

    Hi Jeremy.
    Thanks for your mail.
    Which email address should I send my test model to?
    Cheers, Asger

  16. Dear Asger,
    I’ll send you a mail to reply to, but I very much doubt that I will have any time to look at it, so I would suggest that you explore as much as possible yourself.
    Cheers, Jeremy.

  17. Hi Jimmy,
    I have been trying to develop some Room-Space-Checking function via REVIT API by fetching the room boundary points and draw an Outline based on those points to further use the BoundingBoxIntersectsFilter.
    However, there’s something I don’t know how to fix:
    start with initializing the Outline
    “Outline myOutLn = new Outline(new XYZ(10,10,10), new XYZ(1,1,1));”
    I found when putting the Outline into the BoundingBoxIntersectsFilter
    “BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(myOutLn);
    It results in an “Empty Outline” , after that we realize that each “x”,”y”,”z” of max point has to be larger than the “x”,”y”,”z” of the min point.
    However, when fetching the points from the room boundary, I ain’t sure that every “x”,”y”,”z” of min point is larger than the max point.
    Since I create the outline by the room boundary points, There’s no way to assure that every “x”,”y”,”z” of min point is larger than the max point.
    so I wonder if the “x”,”y”,”z” of the max point really need to be larger than the “x”,”y”,”z” of the min point? or if there is some other ways to create a legal outline for boundingboxfilter?
    thx a lot!!!!!
    Cheers, Kurt.

  18. Dear Kurt,
    If you look at the Revit API help file RevitAPI.chm entry on the Outline constructor, it says “Constructor that uses a minimum and maximum XYZ point to initialize the outline”.
    So I assume that you do indeed have to supply a min and a max point, and that the min point coordinates must be smaller than the max one’s.
    This is very easy to achieve!
    Simply compare the x, y and z values with each other as you collect them, and put the successively larger ones into the max point and the smaller ones into the min one.
    Cheers, Jeremy.

  19. Hello Jeremy,
    I have implemented the Intersecting code above and noticed that it does not work if we have an Analytical view! If that is the case, how do you change the view programmatically to be a regular 3D view?

  20. Dear Cosmas,
    I don’t know off-hand whether you can. But you can always create your own new 3D view to perform the operation. One of the SDK samples demonstrating the ray shooting method does just that somewhere.
    Cheers, Jeremy.

  21. Ari Monteiro Avatar
    Ari Monteiro

    Hello Jeremy,
    Can I use the BoundingBoxIntersectsFilter for interference checking envolving linked models?
    I tested this situation but no success at this point.
    I have architectural model with a structural model linked. So, I’m searching for interferences between wall and beams, for example.
    I saw the following posts:
    AVF Displays Intersections and Highlights Rooms
    http://thebuildingcoder.typepad.com/blog/2011/12/using-avf-to-display-intersections-and-highlight-rooms.html
    List Linked Elements
    http://thebuildingcoder.typepad.com/blog/2009/02/list-linked-elements.html
    I think them have a solution for my problem. Could you tell me if I am on right path?
    Thanks!
    Ari Monteiro

  22. Dear Ari Monteiro,
    Happy New Year to you!
    Yes, it sounds as if you may be on the right track.
    You just have to ensure that you instantiate the BoundingBoxIntersectsFilter with the correct document, i.e. the architectural document for architectural elements etc. Furthermore, you have to ensure that the results in the linked model are correctly transformed into the host model coordinate system.
    Good luck, and let us know how it goes.
    I am sure that other readers would love to see your solution, if you are willing to share it.
    Cheers, Jeremy.

  23. dear sir,,
    how to get thumbnail of .rfa file in windows form,if possible plz replay me
    thank u

  24. purvagupta2010@gmail.com Avatar
    purvagupta2010@gmail.com

    dEAR Jeremy
    When I try to find out for all the elements in view, their intersecting elements , how should i do that?
    I want to make a list with all the elements in a column, and their intersecting elements in the next column.
    But i am having problem in the bounding box intersection filter.
    I am getting zero intersecting elements, when i run the code.
    FilteredElementCollector collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
    BoundingBoxXYZ bb = elem.get_BoundingBox(null);
    Outline outline = new Outline(bb.Min, bb.Max);
    BoundingBoxIntersectsFilter bbfilter = new BoundingBoxIntersectsFilter(outline);
    collector1 = collector.WherePasses(bbfilter);
    ICollection intersectingElems = collector1.WhereElementIsNotElementType().ToElements();
    Am i missing something? As my Intersecting elems are zero when i debug.

  25. Dear Purvagupta,
    Here are a few more pointers:
    http://thebuildingcoder.typepad.com/blog/2012/10/element-intersection.html
    Cheers, Jeremy.

  26. Hello sir,thank yo so much for last time reply :)
    I am getting problem to get a real time view(like in case inserting door on a wall,after selecting the door, i am not getting the door view of moving along with the mouse cursor only getting cursor and if click on wall directly it will inserting.) before placing family inserting.
    my code is like this:
    public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
    ……….
    try
    {
    trans.Start();
    Family family = null;
    FamilySymbol symbol = null;
    if (doc.LoadFamily(@h4, out family))
    {
    foreach (FamilySymbol s in family.Symbols)
    {
    symbol = s;
    }
    View view = uidoc.ActiveView;
    Reference r = sel.PickObject(ObjectType.PointOnElement, “Select”);
    Element elem = doc.GetElement(r);
    Wall wall = elem as Wall;
    XYZ globalPoint = r.GlobalPoint;
    XYZ levelPoint = new XYZ(10, 10, 1);
    Wall wall = doc.GetElement(r) as Wall;
    FamilyInstance instance = doc.Create.NewFamilyInstance(levelPoint, symbol, wall,level,StructuralType.NonStructural);
    }
    trans.Commit();
    }
    catch (Exception)
    {
    }
    return Result.Succeeded;
    }

  27. hello sir,
    And also how to display the materials..(for example in door contains some materials, like glass,Door – Frame/Mullion ,i want to display only material glass from the door,or Door – Frame/Mullion..like this..,please replay soon as possible,
    thank you :)

Leave a Reply to Jim JiaCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading