Construct Mesh GHPython

Hello everyone,

I have trouble constructing a mesh in Python.

import Rhino.Geometry as rg
vertices = []
faces = []
for i in range(len(iMeshes)):
    vertices.append(rg.Mesh.Vertices.GetValue(iMeshes[i]))
for i in range(len(iMeshes)):
    faces.append(rg.Mesh.Faces.GetValue(iMeshes[i]))

Var 1

for i in range(len(iMeshes)):
    tempMesh = rg.Mesh()
    tempMesh.Faces.AddFace(faces[i])

=> Runtime error (ArgumentTypeException): expected MeshFace, got MeshFaceList

Var2

for i in range(len(iMeshes)):
    tempMesh = rg.Mesh()
    for j in faces[i]:
        tempMesh.Faces.AddFace(faces[i][j])

=> Runtime error (ArgumentTypeException): expected int, got MeshFace

In Var1 I get an error that MeshFace is expected, but if I give him MeshFace in Var2 he wants an integer.
Can someone tell me where the error is? Went threw all documentation I could found, but looks like I don’t see it.

181028_python_help.gh (3.8 KB)

Thank you very much.

So, the first section is not necesary. You don’t need to write the for loop to create the vertices list.
instead:

Vertices = iMesh.Vertices
Faces = iMesh.Faces

That alone would give the list of vertices and faces for one mesh, because you have a list of mesh you may do something like this.

vertices = []
faces = []
for i in range(len(iMeshes)):
    vertices.append(rg.Mesh[i].Vertices)

First Error: is because you’re faces list is no really a faces list, is a list of FacesList (nested list), so the Mesh.Faces.AddFace() is not going to work.

Second Error: AddFace uses indexes of the vertices point to construct a new face that then adds to the list of faces. because you’re faces list is not really a faces list.
So the j value on the second for loop is not an integer so you can’t use it as an indexer for a list.

for j in faces[i]: 
    tempMesh.Faces.AddFace(faces[i][j]) # j is not an integer so can't use it as an indexer_


AddFace(self: MeshFaceList, vertex1: int, vertex2: int, vertex3: int, vertex4: int) -- Quads 
AddFace(self: MeshFaceList, vertex1: int, vertex2: int, vertex3: int) -- Triangles
AddFace(self: MeshFaceList, face: MeshFace) -- Adding MeshFace

I personally wouldn’t do this, it over-complicates everything, is easier to write a function for one mesh and then applied the function to the list of meshes. Try this one:

import Rhino.Geometry as rg

def newMesh(iMesh):
    tempMesh = rg.Mesh()
    tempMesh.Faces.AddFaces(iMesh.Faces)
    tempMesh.Vertices.AddVertices(iMesh.Vertices)
    return tempMesh

newMeshesList = []
for i in range(0,len(iMeshes)):
    newMeshesList.append(newMesh(iMeshes[i]))

a = newMeshesList

181028_python_revision.gh (4.7 KB)

1 Like

Hi @Antonio_Cersosimo, thank you very much for your explanation.

Another question if it’s ok for you:

for i in range(meshCount):
    tempMesh = rg.Mesh()
    tempMesh.Faces.AddFaces(faces[i])
    tempMesh.Vertices.AddVertices(newVertices[i])
    newMeshes.append(tempMesh)

Solves my problem with the faces. My problem is, that the vertices I changed is a nested Point3d list now. Do I need to translate it to a Rhino.Geometry.Collections.MeshVertexList like I got from “deconstructing”. How would I do that?

Full script attached if it helps. Hope it’s not too messy. Hopefully the question can be answered while looking at the last two for-loops. (there’s an error somewhere in the nested loops which transforms the vertices, but can’t figure it out atm. Constructing the meshes should work)

181029_python_help.gh (12.6 KB)

Best regards
Tim

Well, this one was quite tricky and I didn’t really understand what you were trying to calculate at the end, but it’s working. I found two extra problems that are relate to the C# class definition in Rhinocommon. I was able to solve the script in two ways the second solution is more efficient than the other.

First one: Because you’re are using MeshVertexList you cannot get the length of the list in the Python way so you need to use the C# syntax for it. Mainly because IronPython doesn’t have the proper implementation for it.

for l in range(len(vertices[k])): # Python
    tempIndex = 0
for l in range(vertices[k].Count): // C#
    tempIndex = 0

Second One: Comes from this Error

Runtime error (ArgumentTypeException): Multiple targets could match: AddVertices(IEnumerable[Point3f]), AddVertices(IEnumerable[Point3d])
Traceback:
line 62, in script

This Error is because Python doesn’t require a type for the list initialization (Duck typing).
So again, MeshVertexList.AddVertices is a C# method that needs the type to be able to choose between the Point3f or Point3d.

#List initialization in both languages
tempPts = []  # Python
List<Point3d> tempPts = new List<Point3d>// C#
# Solution 2
tempPts = System.Collections.Generic.List[rg.Point3d]()

So, the reason why we need to get the list from the System.Collections is because that’s were the .Net List class that both IronPython and C# use, but the advantage is that you can specified the type like in C#. There is a Third Possible Solution but only for Rhino 6, something like this.

tempMesh.Vertices.UseDoublePrecisionVertices = True
tempMesh.Vertices.AddVertices(newVertices[i])

So, I don’t recommend you to use MeshVertexList or any other Geometry.Collection classes a lot in the script they are very messy to work with, an are only useful at the end of the mesh constructor but not through out the script.
Extra, there is Closest Point method that can make the calculation a lot quicker.

181029_python_revision2.gh (10.3 KB)

Thank you very much! I will have a look at it as soon I‘m home.

@wim what are you changing the whole time? :smiley:

Tim, we try to keep track of which threads we need to track - what you are seeing is just a consequence of that system. Ideally, that system is completely transparent to the audience but at this point, it’s not…
Just (try to) ignore it.

Yeah, no problem. I think David already told me but looks like I forgot about it. Sorry :see_no_evil: