Your options are limited it seems. You could extract the curves from the walls then perform an intersection using the Geometry.Intersect method from the ProtoGeometry library, although to implement this completely will result in a heavy process that will very quickly become inefficient and probably fail on big projects with lots of walls.
One idea that you might find a bit more efficient, but unfortunately seems to be buggy as hell (if you test this you’ll notice the apparent intersection yeilds inconsistent results), is the RevitAPI ReferenceIntersector filter class. In the example below, swap out the model curve with the wall location curve and only evaluate wall elements other than the one being tested (get pop()ing) to prevent duplicate results:
It could be rebuilt without the gap in dynamo with a variety of methods, but all of the light ones will fail under one circumstance or another (how was the wall built? Is the profile edited? Is the height inconsistent? etc…)
Might be simpler to unjoin the elements, build the geometry, and rejoin the elements. That said, how big is your dataset? Joining and unjoining isn’t a fast operation on large sets, and wall joins are inconsistent at best.
Better to keep it simple and avoid that mess too.
Try to use the element.location node to query the line for each wall, then build a solid geometry from that - offset them by a small number (say 0.01), start point and end point, some list management, polycuvre through points and then extrude. You can then run the Python test you had before but with a simplified geometry that mimics the wall geometry you had before.
The only issue I see with that is multi story walls - that element location node will place the line (and therefore your extrusion) at the level the wall is hosted to, so set the z values for all of them to a consistent point. Assuming you are doing this one level at a time, you can either use the level you are testing or the origin plane. If you are attempting all walls in a job at once then the list management gets dicey. Try the sample set first and lists setup can be reviewed from there.
I’d like to re-build the wall using just Revit API methods only (Python). I will try to solve the general case first and the look at what could make the workflow fail later. What Revit API methods would you use to re-build the solids?
I think I’ll try that as last resort.
I tried that. I can get the wall location lines, create lines and intersect them (just using Revit API). That works. But my goal is to sort them by finding out the intersecting volume.
In which case offset twice - once by Wall Thickness * 0.5 and once by Wall thickness * -0.5.
Build the polycurve and extrude by the wall height. Then intersect your geometries and go from there. Only issue will be if your walls have profile edits or shapes.
Out of curiosity, what is the need for the intersecting volumes?
None that I’m aware of. You could un-join, but it will be destructive, even if you perform the action in a sub-transaction and rollback to avoid the myriad of problems that can (will?) arise when attempting to re-join, I can still see this process failing. There’s also another issue with accessing the wall joins via the LocationCurve class: it only provides access to the ends of the curve meaning any junctions in-between the walls location curve cant be accessed!
If you need the volumes for the intersections, then it would be easiest to calculate this mathematically in my view. If the method of using the location curve intersections tells you which walls are intersecting, get both walls height and width, you could then calculate the total area of the intersection using trigonometry, then yield the intersecting volume from this information. Sounds complicated, and it is, however the alternatives are beset by pitfalls that would hinder the solution.
I’ve not tested the above so even that has no guarantee of working, however there is one other option you could try:
Extract the location curve of the target wall, including its width and height
Use this data to create a new solid
Get the bounding box of the solid and use the BoundingBoxIntersectsFilter to select any surrounding wall elements. This is a quick filter which will reduce the number of brute-force intersections on the solid object that will need to be performed
Extract the location curves of any walls selected from the quick filter
Use the SolidCurveIntersection filter to test which location curve intersect the solid. This will also solve any problems caused by multi-storey target walls intersecting smaller walls on single floors
Calculate the intersection volumes using your preferred method (i.e. new solid or mathematics)
To find intersecting walls, you could shoot a ray along the given wall’s location line, maybe raised above floor level by a foot or so, and ask it for intersections with other wall elements.
Here is a full-fledged example using the ReferenceIntersector to determine a point on a neighbouring, parallel wall to create dimensioning:
It uses the ReferenceIntersector class to determine points and geometry references to create dimensioning between the walls.
At that time, the method was called FindReferencesByDirection. It was later wrapped in the ReferenceIntersector class. The external command CmdDimensionWallsFindRefs demonstrating its use has been updated to use the new class and is available in The Building Coder samples on GitHub:
Hi @Jeremy_Tammik this is a sound approach and was my suggested solution in the early part of this thread, however I noticed it output inconsistent results and seemed buggy which lead to the more cumbersome ‘solid intersection’ approach. Are there limitations with the ReferenceIntersector class? For example, if walls are very obtuse to the ray, they seemed to be ignored. Only walls (or any other element) that were perpendicular or slightly rotated were picked up?
No, never. If you run into such a situation, please produce a simple, minimal, reproducible case for it and submit it to the development team for analysis.