Hello, coding masters.
I’m working on a script (with python) to get the thickness of a plate. My idea is to select the plate and return the thickness of it.
I tried many alternatives, but I did not get the result I want.
Any ideas,advices are wellcomed.
In the photo are types of plates.
one idea was to extract all the edges,and find the smallest common one
but it has issues
also is the easy alternative to select one edge that is the thickness, buuut, I want to make the operation just from one click
The problem if you may call it a problem is that Rhino is a surface modeller not a solid modeller. You can’t avoid running into issues because even if you deconstruct the polysurface you don’t know “by heart” which sub-surface will fall into the list as index 0 (or whatever index)
getting Brep edges and picking the smallest length might be the best workaround here
Are you importing this model from somewhere or is this created inside Rhino?
is created inside Rhino
or maybe is there a way to acces an object history, and extract info from there, for example if a surface is offseted, than I can dig into it’s history and find if it was offseted/extruded and get the value used
try this:
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
""""""
objs = [obj for obj in rs.AllObjects()if rs.IsObjectSelectable(obj) and rs.IsPolysurface(obj) and rs.IsObjectSolid(obj)]
print len(objs)
for obj in objs:
surfs = rs.ExplodePolysurfaces(obj)
curves = []
lengths = []
for surf in surfs:
curves += rs.DuplicateEdgeCurves(surf)
for crv in curves:
lengths.append(rs.CurveLength(crv))
lengths.sort()
thickness = lengths[0]
print "thickness is: {}".format(thickness)
rs.DeleteObjects(curves)
rs.DeleteObjects(surfs)
You may modify to display the name of the object or change it to pick just a single one
I modified the code to display the name of the solid:
import rhinoscriptsyntax as rs
objs = [obj for obj in rs.AllObjects()if rs.IsObjectSelectable(obj) and rs.IsPolysurface(obj) and rs.IsObjectSolid(obj)]
print len(objs)
for obj in objs:
object_name = rs.ObjectName(obj)
surfs = rs.ExplodePolysurfaces(obj)
#print len(surfs)
curves = []
lengths = []
for surf in surfs:
curves += rs.DuplicateEdgeCurves(surf)
for crv in curves:
lengths.append(rs.CurveLength(crv))
lengths.sort()
#print lengths
thickness = lengths[0]
print "Object {} thickness is: {}".format(object_name,thickness)
rs.DeleteObjects(curves)
rs.DeleteObjects(surfs)
Update: I cleaned it up a bit I had some leftovers
a sec to check it
it works and i ll add some scriptlines to avoid the lenghts[0] in case the plate has a edge which is smaller than the actual thickness
You will run into issues there
many thanks, Peychev!
i m thinking to offset all srfs with half of the thickness, and if two centroids of the offseted srfs are coincident,then that is the real thickness
that may work, but how do you know the direction of the offset?
A while ago I was testing to create clipping planes on the surfaces of exploded box. I had to flip some of them, the direction was inconsistent.
Perhaps you should modify my code not to explode but just get the subsurfaces. Although I do not know how would you deal with curved sub-surfaces.
Must be tested but I think you’ll have issues.
i think that the offset uses the normal of the surface, and if i choose to offset with -thickness/2, all the offsets will be made to the interiour of the plate
the forum doesn t leave me to post more replies :)) because i m on the first day on this forum.
so
i tested it and usualy the positive normal is outward the plate
but is the posibility that the centroids to be a shifted. for exmple,if you have a simple curved surface(like the one made with fillet) and then offset that surface with 10 ,tha distance from the centroids is smaller, measuring the distance from the instersection of the isocurves(u an v) from each surface might be a solution
it does but it could be outwards or inwards, you don’t know which one.
I’m thinking, there is one more way to measure this.
Getting the two sub-surfaces with largest areas and measure the distance between their centroids
Probably not the most efficient way but, here you go:
import rhinoscriptsyntax as rs
import operator
objs = [obj for obj in rs.AllObjects()if rs.IsObjectSelectable(obj) and rs.IsPolysurface(obj) and rs.IsObjectSolid(obj)]
#print len(objs)
for obj in objs:
object_name = rs.ObjectName(obj)
surfs = rs.ExplodePolysurfaces(obj)
#print len(surfs)
areas = []
idx_area_dict = {}
max_surfs_centroids = []
for surf in surfs:
areas.append(rs.Area(surf))
#areas.sort()
for i in range(len(surfs)):
k = i
v = float(str(int(areas[i])))
idx_area_dict[k] = v
#print idx_area_dict
max_area = max(idx_area_dict.iteritems(),key=operator.itemgetter(1))[1]
#print max_area
for i in range(len(areas)):
if float(str(int(areas[i]))) == max_area:
pt = rs.SurfaceAreaCentroid(surfs[i])[0]
max_surfs_centroids.append(pt)
#print max_surfs_centroids
if len(max_surfs_centroids) > 1:
thickness = round(rs.Distance(max_surfs_centroids[0],max_surfs_centroids[1]),2)
print "Object {} thickness is: {} mm".format(object_name,thickness)
#rs.DeleteObjects(curves)
rs.DeleteObjects(surfs)
I guess, not having read the whole thread, and if user interaction is allowed, I’d ask for a point on the brep - pick on a face, and send a ray or line into the brep normal to the face at that location until it hits another face, then measure back to the pick point.
-Pascal