Hi,

this is indeed the expected behavior, as OpenMesh requires the vertices of incident faces to be ordered in a consistent manner.

In OpenMesh an edge connecting the vertices v1 and v2 is represented by two halfedges pointing in opposite directions, i.e. one halfedge pointing from v1 to v2 and one pointing from v2 to v1. Each halfedge is associated with one face and the order of the vertices of that face has to be consistent with the halfedge direction.

You can think of it in terms of consistent normal orientation: For example, the first two triangles added to the mesh in your snippet are (7, 0, 9) and (9, 7, 6). These triangles share the edge connecting vertices 9 and 7, but their normals (defined by the order of their vertices) point in opposite directions.

This is why you should see an error message “PolyMeshT::add_face: complex edge”.

You can learn more about OpenMesh’s halfedge data structure here: https://www.openmesh.org/media/Documentations/OpenMesh-6.1-Documentation/a00016.html

Also, this stackoverflow post has some nice images: https://stackoverflow.com/questions/24205196/addfacecomplex-edge-error-in-openmesh

Best regards,
Alexander Dielen



On 10. Apr 2019, at 10:25, Marc Siggel <marc.siggel@biophys.mpg.de> wrote:

Hi,

I am new to OpenMesha and currently working with the python bindings to build a quick prototype of my code before moving to c++.
attached a simple icosahedron structure. I defined 12 vertices and 20 faces.
When using the vf circulator I experience that not all neighbouring face of a vertex are found. I also found that the number of faces is sensitive to the order of the vertex handles when defining a face.
when looking at the indices some are set to -1.
Is this expected behavior or am I missing something fundamental?

Please find the minimal example below.
Any help or comments would be greatly appreciated!

Best regards,
Marc Siggel



  import OpenMesh as om
  import numpy as np
   mesh = om.TriMesh()
   mesh_notebook = {}
   face_notebook = {}
   radius = 3.0/4.0/np.pi
   phi = 0.5*(1+np.sqrt(5))
   a = radius / np.sqrt(phi*np.sqrt(5))

   mesh_notebook[0,"handle"] = mesh.add_vertex([a*phi,0,a])
   mesh_notebook[1,"handle"] = mesh.add_vertex([a*phi,0,-a])
   mesh_notebook[2,"handle"] = mesh.add_vertex([-a*phi,0,-a])
   mesh_notebook[3,"handle"] = mesh.add_vertex([-a*phi,0,a])
   mesh_notebook[4,"handle"] = mesh.add_vertex([a,a*phi,0])
   mesh_notebook[5,"handle"] = mesh.add_vertex([-a,a*phi,0])
   mesh_notebook[6,"handle"] = mesh.add_vertex([-a,-a*phi,0])
   mesh_notebook[7,"handle"] = mesh.add_vertex([a,-a*phi,0])
   mesh_notebook[8,"handle"] = mesh.add_vertex([0,a,a*phi])
   mesh_notebook[9,"handle"] = mesh.add_vertex([0,-a,a*phi])
   mesh_notebook[10,"handle"] = mesh.add_vertex([0,-a,-a*phi])
   mesh_notebook[11,"handle"] = mesh.add_vertex([0,a,-a*phi])

   face_notebook[0,"handle"] = mesh.add_face(mesh_notebook[7,"handle"], mesh_notebook[0,"handle"], mesh_notebook[9,"handle"])
   face_notebook[1,"handle"] = mesh.add_face(mesh_notebook[9,"handle"], mesh_notebook[7,"handle"], mesh_notebook[6,"handle"])
   face_notebook[2,"handle"] = mesh.add_face(mesh_notebook[9,"handle"], mesh_notebook[6,"handle"], mesh_notebook[3,"handle"])
   face_notebook[3,"handle"] = mesh.add_face(mesh_notebook[7,"handle"], mesh_notebook[1,"handle"], mesh_notebook[10,"handle"])
   face_notebook[4,"handle"] = mesh.add_face(mesh_notebook[7,"handle"], mesh_notebook[10,"handle"], mesh_notebook[6,"handle"])
   face_notebook[5,"handle"] = mesh.add_face(mesh_notebook[10,"handle"], mesh_notebook[6,"handle"], mesh_notebook[2,"handle"])
   face_notebook[6,"handle"] = mesh.add_face(mesh_notebook[0,"handle"], mesh_notebook[1,"handle"], mesh_notebook[7,"handle"])
   face_notebook[7,"handle"] = mesh.add_face(mesh_notebook[6,"handle"], mesh_notebook[3,"handle"], mesh_notebook[2,"handle"])
   face_notebook[8,"handle"] = mesh.add_face(mesh_notebook[0,"handle"], mesh_notebook[4,"handle"], mesh_notebook[8,"handle"])
   face_notebook[9,"handle"] = mesh.add_face(mesh_notebook[8,"handle"], mesh_notebook[4,"handle"], mesh_notebook[5,"handle"])
   face_notebook[10,"handle"] = mesh.add_face(mesh_notebook[8,"handle"], mesh_notebook[3,"handle"], mesh_notebook[5,"handle"])
   face_notebook[11,"handle"] = mesh.add_face(mesh_notebook[1,"handle"], mesh_notebook[4,"handle"], mesh_notebook[11,"handle"])
   face_notebook[12,"handle"] = mesh.add_face(mesh_notebook[4,"handle"], mesh_notebook[5,"handle"], mesh_notebook[11,"handle"])
   face_notebook[13,"handle"] = mesh.add_face(mesh_notebook[5,"handle"], mesh_notebook[11,"handle"], mesh_notebook[2,"handle"])
   face_notebook[14,"handle"] = mesh.add_face(mesh_notebook[0,"handle"], mesh_notebook[1,"handle"], mesh_notebook[4,"handle"])
   face_notebook[15,"handle"] = mesh.add_face(mesh_notebook[3,"handle"], mesh_notebook[2,"handle"], mesh_notebook[5,"handle"])
   face_notebook[16,"handle"] = mesh.add_face(mesh_notebook[0,"handle"], mesh_notebook[8,"handle"], mesh_notebook[9,"handle"])
   face_notebook[17,"handle"] = mesh.add_face(mesh_notebook[9,"handle"], mesh_notebook[8,"handle"], mesh_notebook[3,"handle"])
   face_notebook[18,"handle"] = mesh.add_face(mesh_notebook[1,"handle"], mesh_notebook[10,"handle"], mesh_notebook[11,"handle"])
   face_notebook[19,"handle"] = mesh.add_face(mesh_notebook[2,"handle"], mesh_notebook[10,"handle"], mesh_notebook[11,"handle"])

   print(len(mesh.faces())) # should be 20
   for edge in mesh.vf(mesh_notebook[0,"handle"]):
       print(edge.idx()) # should be 5
   for j,i in face_notebook:
       print(face_notebook[j,i].idx()) # some are defined as -1 - default behavior?
_______________________________________________
OpenMesh mailing list -- openmesh@lists.rwth-aachen.de
To unsubscribe send an email to openmesh-leave@lists.rwth-aachen.de
https://lists.rwth-aachen.de/postorius/lists/openmesh.lists.rwth-aachen.de