Building Coder (Revit Secondary Development)-filter by using the "Solid Intersection" Mechanism

Source: Internet
Author: User

The temporary entity (Solid) created by the ry creation tool can be used for Geometric Feature filters.

Problem

I want to obtain all the beam with contact through programming, regardless of the connection status between them. The user selects a beam first, and then the program automatically selects all beam with recursive contact (I .e. cascading contact.

 

Jeremy


First, let's discuss the connection of these beams: You can use the Beam. LocationCurve. ElementsAtJoin attribute to obtain all beams connected to a specified endpoint of a Beam. Then, traverse the set of Beam beams, and continue to use the Beam. LocationCurve. ElementsAtJoin attribute for each Beam to obtain the set of new Beam connections in cascade mode. You can find a similar processing mechanism in the SDK routine TraverseSystem, which shows how to use the MEP Connection Manager in the pipeline system to traverse all the connected elements.


Then return to your needs: these beams are not in connection, but are only in contact with each other. We can use ElementIntersectsSolidFilter to detect all elements that overlap the region in a space area defined by the entity. This entity can come from the actual BIM model or be created temporarily and only exists in the memory.

To obtain the beam of all cascaded contact, we must create an entity and ElementIntersectsSolidFilter for each beam. If the contact you want is at any position (that is, not at the two ends of the beam), you should create a shape to stretch the entity according to the shape of the current beam, it then detects the beam that has any space intersection or close enough to the shape of the stretched entity. If you only care about the beam with an endpoint, you can simply create a sphere at the endpoint of the current beam.

This operation should be applied recursively to all the beam found. Of course, you must exclude the beam that has been processed, otherwise it will lead to an endless loop.

The implementation process is as follows:
1. Maintain the three beam lists

-Beam processed (processed beam table)
-Beam being processed (current beam table)
-Beam adjacent to the beam being processed (adjacent beam table)
2. Add a beam to the current beam table.

3. If the current beam table is not empty, repeat the following process:

-Add the current beam to the processed beam table
-Clear the adjacent beam table
-Add all beams in contact with the current beam to the adjacent beam table.
-Use the adjacent beam table found in the previous step as the new current beam table

In the following code, the code that detects all beam contacts with the specified beam is in method AddConnectedElements. This method first creates a sphere at the two ends of the beam, then creates a detector adjacent to the sphere-based space, and applies it to an ElementIntersectsSolidFilter. Execute the filter, delete the beam that has been processed from the filter result, and add the final result to the adjacent beam table.

[Csharp]
/// <Summary>
/// Obtain all elements adjacent to the element "e" (excluding processed elements)
/// </Summary>
Void AddElementsIntersectingSphereAt (
List <ElementId> neighbors,
XYZ p,
List <ElementId> visited,
Document doc)
{
Solid sphere = CreateSphereAt (doc. Application. Create, p, _ sphere_radius );
 
ElementIntersectsSolidFilter intersectSphere = new ElementIntersectsSolidFilter (sphere );
 
FilteredElementCollector collector = new FilteredElementCollector (doc)
. WhereElementIsCurveDriven () // You can process any element whose Location is LocationCurve.
. OfCategory (_ bic)
. Excluding (visited. Union <ElementId> (neighbors). ToList <ElementId> ())
. WherePasses (intersectSphere );
 
Neighbors. AddRange (collector. ToElementIds ());
}
 
/// <Summary>
/// Determine all neighbouring elements close
/// The two ends of the current element 'E ',
/// Skipping all previusly visited ones.
/// </Summary>
Void AddConnectedElements (
List <ElementId> neighbors,
Element e,
List <ElementId> visited)
{
Location loc = e. Location;
 
Debug. Print (string. Format ("current element {0} has location {1 }",
ElementDescription (e ),
Null = loc? "<Null>": loc. GetType (). Name ));
 
LocationCurve lc = loc as LocationCurve;
 
If (null! = Lc)
{
Document doc = e. Document;
 
Curve c = lc. Curve;
 
XYZ p = c. get_EndPoint (0 );
XYZ q = c. get_EndPoint (1 );
 
AddElementsIntersectingSphereAt (neighbors, p, visited, doc );
 
AddElementsIntersectingSphereAt (neighbors, q, visited, doc );
}
}

Note that the adjacent beam table and the processed beam table are both ElementId sets, rather than Element sets. Because. NET's comparison mechanism is not reliable in handling Revit elements. In addition, the ElementId set exactly matches
FilteredElementCollector's Exclude () method parameter requirements.

First, I tried to call the Exclude () method twice for the adjacent beam table and the processed beam table. However, if an empty set is returned for the first processing result, an exception is thrown when Exclude () is called when the empty set is closed. Of course, we can
Determine whether the set is empty before calling Exclude. However, the simpler method is to combine the adjacent beam table and the processed beam table into a beam table, and then call the Exclude () method at one time.

[Csharp]
Public Result Execute (
ExternalCommandData commandData,
Ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData. Application;
UIDocument uidoc = uiapp. ActiveUIDocument;
Application app = uiapp. Application;
CreationApp creapp = app. Create;
Document doc = uidoc. Document;
Selection sel = uidoc. Selection;
Reference r = null;

Try
{
R = sel. PickObject (ObjectType. Element, "Please select a beam ");
}
Catch (RvtOperationCanceledException)
{
Return Result. Cancelled;
}

// Initial Beam
Element start = doc. GetElement (r );

// Current beam table (we need to find their adjacent beam)
List <ElementId> current = new List <ElementId> ();

Current. Add (start. Id );

// Processed beam table
List <ElementId> visited = new List <ElementId> ();

// Adjacent beam table
List <ElementId> neighbors = new List <ElementId> ();

// Recursive call
While (0 <current. Count)
{
// Record the processed beam table
Visited. AddRange (current );

Neighbors. Clear ();

// Find the adjacent beam table of the current beam table (not processed)
Foreach (ElementId id in current)
{
Element e = doc. GetElement (id );
AddConnectedElements (neighbors, e, visited );
}

// After the current beam table is processed, find the adjacent beam table to become the current beam table for the next operation.
// Newly found become the next current ones

Current. Clear ();
Current. AddRange (neighbors );
}

Foreach (ElementId id in visited)
{
Uidoc. Selection. Elements. Add (doc. GetElement (id ));
}
Return Result. Succeeded;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.