Sort list of points derived from Solid3d clockwise with Python

Hello all,

I’m trying to create a Point3dCollection of the bottom vertices of a Solid3d. However, when I run this script:

      for id in boundary_id:				
             obj = t.GetObject(id, OpenMode.ForRead)
					#find half of the vertices of a solid
					if isinstance(obj, Solid3d):
						brep = Brep(obj)
						vertices = brep.Vertices
						points_XYZ = []
						for i in vertices:
							point_vertice = i.Point
							points_XYZ.append([point_vertice.X, point_vertice.Y, point_vertice.Z])
							points_XYZ.sort(key=lambda x: (x[2]))
							points = []
							for i in points_XYZ:
								point_a = Point3d(i[0],i[1],i[2])
								points.append(point_a)
																					
						pts = Point3dCollection()
						for k in points[0:(len(points)/2)]:
							pts.Add(k)
						pts.Add(points[0])
						boundary_p3dcol.append(pts)

I get the following result: it appears that brep.Vertices results in a unordered list of points

The order of the first list is indicated in red below:

What I want to achieve is the order marked with blue: the Point3Ds are sorted clockwise.
If the point are sorted clockwise a closed polygon can later on be created for bounding a volume surface.

for k in points[:2]: pts.Add(k)
pts.Add(points[3])
pts.Add(points[2])

Swapping the second and thirth index works fine for rectangular solids with the script below:

                for id in boundary_id:
					obj = t.GetObject(id, OpenMode.ForRead)
					#find half of the vertices of a solid
					if isinstance(obj, Solid3d):
						brep = Brep(obj)
						vertices = brep.Vertices
						points_XYZ = []
						for i in vertices:
							point_vertice = i.Point
							points_XYZ.append([point_vertice.X, point_vertice.Y, point_vertice.Z])
							points_XYZ.sort(key=lambda x: (x[2]))
							points = []
							for i in points_XYZ:
								point_a = Point3d(i[0],i[1],i[2])
								points.append(point_a)
						#grab half of list, other half are top vertices
						points_filtered = []
						points_filtered.append(points[0:(len(points)/2)])
						pts = Point3dCollection()
						for k in points_filtered:
							pts.Add(k[0])
							pts.Add(k[1])
							pts.Add(k[3])
							pts.Add(k[2])
							pts.Add(k[0])
						boundary_p3dcol.append(pts)

This is however not applicable if the solid is not rectangular (e.g. has 5 base vertices). How can the script function regardless the amount of points in the solid?

you should look at faces and then at the edge loops then rather than immediately go for the veritces.

1 Like