Hey everyone!
As the title says, I have 6 intersecting surfaces and I’m trying to extract the 12 unique intersecting lines.
I’ve tried using the node Geometry.Intersect but it also returns a surface and afterwards I haven’t been able to list the unique lines from this list.
This is the script I have so far:
WIP_Solid from intersecting surfaces.dyn (23.4 KB)
The end goal is to build a solid from these lines, so basically a solid from the intersecting surfaces.
Any help or suggestions are appreciated/weclome!
try cross product in lacing and use remove if not node for filter out…maybe 
@sovitek Thanks for the suggestion, but I’m getting 24 lines instead of 12, they are double but can’t seem to remove the duplicates…
yeah not sure…hahaha…then i need see the whole graphs but for duplicate items lines with unique items…then maybe string from object will work…not sure
and maybe with a math round node as well
if you have a small sample rvt you could share with only that situation, we can probably help
I think Geometry.Intersect will be giving you double because when you use cross lacing it looks at each of the 6 surfaces in order, and tells you which other surfaces they intersect with. So if there is an intersection with surface 0 and surface 1, the line will be created in both instances.
Unique items may not be removing the duplicates because it doesn’t work well with geometry as it can be too sensitive to floating point maths errors.
You could make a bounding box of the lines if your resulting shape would be a cuboid?
yeah or try prune duplicates…datashapes should have one there works for geometry…or a point by parameter, and use ootb point prune duplicates, with maybe some tolerance.but depends.
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
unique = []
uniqueStr = []
def toList(input):
if isinstance(input,list):
return input
else:
return [input]
def surfsol_ToSortedVertices(surfsol):
return ",".join(sorted([i.ToString() for i in surfsol.Vertices]))
def curve_ToSortedVertices(cv):
nbs = cv.ToNurbsCurve()
return ",".join(sorted([p.ToString() for p in nbs.ControlPoints()]))
def pt_ToSortedVertices(pt):
return pt.ToString()
g = toList(IN[0])
for geom in g:
try:
#solids and surfaces
if not (surfsol_ToSortedVertices(geom) in uniqueStr) :
uniqueStr.append(surfsol_ToSortedVertices(geom))
unique.append(geom)
except:
try:
#Curves and lines
if not (curve_ToSortedVertices(geom) in uniqueStr) :
uniqueStr.append(curve_ToSortedVertices(geom))
unique.append(geom)
except:
#Points
if not (pt_ToSortedVertices(geom) in uniqueStr) :
uniqueStr.append(pt_ToSortedVertices(geom))
unique.append(geom)
OUT = unique
The List.Combinations node is your go to here - this can provide all the possible pairs of surface interactions without duplication - so unless they are coplanar all results will be unique lines and the minimal number of operations
Hola amigos buenas!
@Laura_BIMChick i’ve analyzed what could be your situation, i’ve discovered that when you’re making the intersections you’re geting 2 times “same line” but is not the same line they are similar curves but in exaclty oposite directions, so i put a midle point in each curve and this new points will intersect presisly with the correspondant, this will helps you to filter, i let you an example, the solution of @Mike.Buttery it’s the best i think!! 
At scale I personally like to use List.DropItems followed by PolySurface.ByJoinedSurfaces, and then Geometry.Intersect.
The problem with List.Combinations is that it generates a list of 30 surfaces from the original list of six. In larger lists this will get to the point of consuming more memory than systems will have available at the intersect phase where most objects will be invalid.
List.DropItems with a range from 1 to the length of the list will give you ‘all the other untested items’ for any given item in a sequential list - your list will have 15 items in it in total here. You can drop the last list which should be empty using a value of -1for the count. Converting those into a PolySurface reduces it to five objects. Intersect your list of six with the list of five PolySurfaces with auto or shortest lacing and you should have a clean output of the six lines with the least amount of compute to manage.
brutish approach, only works if the surfaces are orthogonal:
My understanding is that C# (and therefore Dynamo) is object oriented, so a node is not creating new surfaces (consuming memory), just using pointers to the existing object in memory.
You could use list levels over generating a polysurface as well
A few things here.
Dynamo an nd most other visual programming isn’t quite the same as basic OOP as the ‘objects’ are recreated by each node, allowing for a ‘non-destructive’ method of object creation. This means the surface you get from a patch operation can be trimmed, thickened, translated, and transformed so you get five resulting geometries (the four actions and the original patch) without needing to first ‘duplicate’ the surface for each node. Many users learn this early on when they wonder why the translated geometry and the original both show up in the background preview.
I have had a few C# based package versions which are more akin to true OOP which makes things faster which seemed great at first. Make the thing once, modify the same thing with four coming off of it, then display any one of them and you get a ‘complete’ result. However this meant concurrent branching lead to race conditions and inconsistent results (imagine the four of those actions performed in opposite order - you can’t trim a surface after making it into a solid). If you look closely at Dynamo’s returned data you can see where this happens - Dictionary.SetValueAtKeys returns a new dictionary not a modification of the existing one.
The next thing to consider is the impact on storing the larger number of pointers (assuming the nodes in question are utilizing pointers and not new instances) for sequential operations. The sequential lists are almost always going to return a ‘new list’ rather than a reused one even if we have pointers, and those new lists need new chunks of memory to keep things in the right order.
Then we have the extra amount of items to display - N*N surfaces is a bigger hit even if they are pointers than N surfaces for both the textual representation (data preview) and the geometry display. Try adding the entire text of Hamlet (or similar text data) into a String node and see how Dynamo performs for the most direct comparison. Note when I have done this (about three times a year on average) Dynamo often crash out, or make me wish it did.
The final issue is in the number of tests. With PolySurfaces you only need to do the intersect action N-1 times. Without that you need to do it… ugh too early after vacation but I think it’s (N*(N-1))/2. With only six surfaces you’re doing 15 tests instead of 5. As the number of surfaces grows the number is tests follows suit in both methods - a list of 256 surfaces is 255 tests with the PolySurface method, while the lacing method is 32640 computationally expensive Boolean operations, all of which have to be stored in memory.
Thanks for the thoughtful and comprehensive reply. I have been stuck waiting for explosive data runs (usually before deadlines) and crossing my fingers it makes it through and my ram survives