I’ve started a script to adapt a subd edge. The first hurdle I’ve come across is I’m going to need to operate on the subd with the mesh class, casting it with Rhino.Geometry.Mesh.CreateFromSubDControlNet() method.
From a first look, all the vertex/face ids and such will be completely different at this point. So I need to be able to obtain what the controlnet mesh AS a mesh class object ids of faces of what I selected in the subd were. That might not make sense. In short, how do I translate what I’ve selected on a SubD into something on the mesh. Is there something other than mesh closest point?
# SPIN EDGE V1
import Rhino
import Rhino.Geometry as rg
import rhinoscriptsyntax as rs
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select edge to orient")
go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.InnerLoop
#go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.EdgeCurve
go.GeometryFilter = Rhino.DocObjects.ObjectType.EdgeFilter
#go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge
go.Get()
objref = go.Object(0)
guid = objref.ObjectId
subd = rs.coercegeometry(guid)
print "subd:", subd
geo = objref.Geometry()
picked_edge_id = objref.GeometryComponentIndex.Index
picked_subd_edge = subd.Edges.Find(picked_edge_id)
if picked_subd_edge.FaceCount == 2:
face1 = picked_subd_edge.FaceAt(0)
face2 = picked_subd_edge.FaceAt(1)
else: print "Cannot rotate naked edge"
verts = [picked_subd_edge.VertexFrom.Id, picked_subd_edge.VertexTo.Id]
print "vertid_from:", verts [0], "vertid_to", verts [1]
face1_id, face2_id = face1.Id, face2.Id
print "face1:", face1_id, "face2:", face2_id
#print face1.ComponentIndex().Index, face2.ComponentIndex().Index
face1, face2 = subd.Faces.Find(face1_id), subd.Faces.Find(face2_id)
# convert to list comprehension
face1_verts = [face1.VertexAt(0).Id, face1.VertexAt(1).Id, face1.VertexAt(2).Id, face1.VertexAt(3).Id]
face2_verts = [face2.VertexAt(0).Id, face2.VertexAt(1).Id, face2.VertexAt(2).Id, face2.VertexAt(3).Id]
face2_verts.reverse()
print face1_verts, face2_verts
mesh = rg.Mesh.CreateFromSubDControlNet(subd)
meshfaces = mesh.Faces
#meshfacelist.DeleteFaces
#mesh topolyedge list class?
#GetEdgesForFace
#Get TopologyVertices
#MehFaceList.DeleteFaces
#MeshFaceList.Insert #insert a face at a defined index
#MeshFaceList.RemoveAt
#meshfacelist.SetFace # set a face at a specific index
#rg.MeshNgons.Create(meshvertexindexlist, faceindexlist)
# then get / access the mesh ngon
Below is my latest code, using closest point to go what feels like quite a long way round to getting underlying mesh faces from a selected subd edge. For the purpose of editing the subd net with the mesh class (since subd doesn’t really have anything to manipulate in that way).
# SPIN EDGE V1
import Rhino
import Rhino.Geometry as rg
import rhinoscriptsyntax as rs
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select edge to orient")
go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.InnerLoop
#go.GeometryAttributeFilter = Rhino.Input.Custom.GeometryAttributeFilter.EdgeCurve
go.GeometryFilter = Rhino.DocObjects.ObjectType.EdgeFilter
#go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge
go.Get()
objref = go.Object(0)
guid = objref.ObjectId
subd = rs.coercegeometry(guid)
print "subd:", subd
geo = objref.Geometry()
picked_edge_id = objref.GeometryComponentIndex.Index
picked_subd_edge = subd.Edges.Find(picked_edge_id)
if picked_subd_edge.FaceCount == 2:
face1 = picked_subd_edge.FaceAt(0)
face2 = picked_subd_edge.FaceAt(1)
else: print "Cannot rotate naked edge"
verts = [picked_subd_edge.VertexFrom.Id, picked_subd_edge.VertexTo.Id]
print "vertid_from:", verts [0], "vertid_to", verts [1]
face1_id, face2_id = face1.Id, face2.Id
print "face1:", face1_id, "face2:", face2_id
#print face1.ComponentIndex().Index, face2.ComponentIndex().Index
face1, face2 = subd.Faces.Find(face1_id), subd.Faces.Find(face2_id)
# convert to list comprehension
face1_verts = [face1.VertexAt(0).Id, face1.VertexAt(1).Id, face1.VertexAt(2).Id, face1.VertexAt(3).Id]
face2_verts = [face2.VertexAt(0).Id, face2.VertexAt(1).Id, face2.VertexAt(2).Id, face2.VertexAt(3).Id]
face2_verts.reverse()
print face1_verts, face2_verts
mesh = rg.Mesh.CreateFromSubDControlNet(subd)
meshfaces = mesh.Faces
meshverts = mesh.Vertices
meshverts.UseDoublePrecisionVertices = True
p3d = meshverts.ToPoint3dArray()
# verts [0], verts [1]
picked_mesh_indices = []
#probably need to make dictionary of vertex ids with distance to point1 or point2
for index, i in enumerate(p3d):
if i.DistanceTo(subd.Vertices.Find(verts [0]).ControlNetPoint) == 0:
picked_mesh_indices.append(index)
for index, i in enumerate(p3d):
if i.DistanceTo(subd.Vertices.Find(verts [1]).ControlNetPoint) == 0:
picked_mesh_indices.append(index)
print "Vertex Indices are", picked_mesh_indices
#now, find the two faces that share these verts?
all_assoc_faces = [ meshverts.GetVertexFaces(i) for i in picked_mesh_indices ]
face_verts = []
for i in all_assoc_faces:
for vert in i:
face_verts.append(vert)
myset = set(face_verts)
selected_faces = []
for i in myset:
if face_verts.count(i) > 1:
selected_faces.append(i)
print "Face Indices are", selected_faces
#meshfacelist.DeleteFaces
#mesh topolyedge list class?
#GetEdgesForFace
#Get TopologyVertices
#MehFaceList.DeleteFaces
#MeshFaceList.Insert #insert a face at a defined index
#MeshFaceList.RemoveAt
#meshfacelist.SetFace # set a face at a specific index
#rg.MeshNgons.Create(meshvertexindexlist, faceindexlist)
# then get / access the mesh ngon
# mesh.CopyFrom(subd) #? would this help? mimic other list?