Comparing geometry of Dynamo solids - collecting objects of the same shape


#1

Hi Guys!

I’m developing a project that automatically generates families of prefabricated segments on the basis of Revit project modeled in a traditional way (regular Revit walls, etc.).

In a nutshell: I import Revit geometry to Dynamo, divide it into modules based on a set of constraints, and then export these modules to separate Revit families for scheduling using FamilyInstance.ByGeometry from Spring Nodes.

I’m almost there with the basic framework, but I’m struggling with an issue, that should be one of the key features of this script: it happens in the process that I receive a number of identical modules, say, two segments of straight walls without openings and with the same length (see image). My current workflow turns these two segments into two separate families, which is pretty useless for scheduling.



Ideally, I would like to detect that two solids in my model are identical and eventually convert both of them to two instances of the same family which would allow to count them together in a schedule - as two instances of the same family instead of two separate beings.

One idea I can think of is to:

  1. Identify and list all different modules within the project
  2. Create families from them
  3. Place these families in appropriate locations

And whereas points 2 and 3 seem doable I cannot think of a method for comparing geometries of all the modules and grouping them. Could maybe anyone help me out with this?

Thanks in advance for any help.


#2

Here’s a random idea that is far from perfect (possible to fool it) but might work for most cases.
You have the solid, now get the faces and the edges (I assume you know how to do that since you’ve gotten this far).

Get the solid volume. Next get the area of all the faces and sort that list by size. Get a Count of the number of faces. Get the length of all of the edges and sort by length. Get a count of all the edges. - convert all of the lists into strings then add it all up into one massive string that represents the solid:

(VolumeString#FaceAreaStrings#FaceCountString#CurveLengthString#CurveCountString)

Now you should be able to compare and group strings. The chances of a non-similar solid having the same Volume, number of Faces, Face Areas, Number of Edges and Edge lengths is reeeaaaallllllyyyy small - possible, but not likely.

Elegant solution - no
Do-Able, yes.


#3


FindSimilarGeometry.dyn (19.1 KB)


#4

Hi Ben! That is in fact quite a complex approach, but it works :slight_smile: Thanks a lot for your time!


#5

Ben,
I would like to be able to pick an element and have your script find all other elements that match. Your script above gets me in the ballpark, but I am having issues using that as a filter. Any ideas or help would be greatly appreciated.
Thanks


#6

Get the Element Id of the selected element and the index of that element in your list of all elements to compare. After converting the parameters to a single string, get the string at the index of your element and use it to compare against all the other values in your list of strings.


#7

It’s simple string matching.

if you have a list such as: “Cat”,“Dog”,“Cow”,“Bird”,“Cat”,“Dog”,“Cow”,“Bird”,“Cat”,“Dog”,“Cow”,“Bird”

you would use the == node + a filter by bool mask node to find all matches for “Cat”.


#8

Thanks for the replies everyone!
Is there a way to filter two elements that are opposite hand of each other? Filtering if certain points were positive coordinates in one element and negative in the other.


#9

Given the methodology I suggested to the OP - opposite hand would make no difference since the volumes and areas and curve counts should all be identical.

That said - there is and API method for “Mirrored” Family instance testing.
http://www.revitapidocs.com/2017.1/20ab2f32-e3ca-8173-aac3-a03e998fd0ab.htm


#10

Thanks. I will look into that. I am not that savvy with Python, so getting the check mirrored code into a node may be a task for me. But a task possibly worth trying. I might be able to use the centroid coordinates to group the elements by.

Thanks again!


#11

#12

Hi @staylor,

Found this code (not my own).
If i’m correct it does a check if the elements are mirrored(true) or not(false).

import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

#input assigned to IN variable
element = list(UnwrapElement(IN[0]))

#output assigned to OUT variable
OUT = [ (True if elem.Mirrored else False) for elem in element ]

Kind regards,
Mark


#13

Mark,
Thanks for showing the python code! This will do the trick, but I need this to work on a sub-group level. Like I stated, I have virtually no experience with python to edit the above code to work with groups. Reason I assume this is the case. If I flatten a group of sub-list it works, but if I don’t then it errors out.

After testing, this will only work if the elements were mirrored using the mirror command. So if elements just happen to be opposite hand, it doesn’t recognize that.