pygel3d

PyGEL is a collection of classes and functions that expose features in the GEL library. The primary purpose of PyGEL (and GEL) is to be useful for geometry processing tasks. Especially tasks that involve 3D polygonal meshes, but there is also a graph component useful e.g. for skeletonization. The PyGEL package is called pygel3d and it contains five modules:

hmesh provides Manifold which is a class that represents polygonal meshes using the halfedge representation. hmesh also provides a slew of functions for manipulating polygonal meshes and the MeshDistance class which makes it simple to compute the distance to a triangle mesh.

graph contains the Graph class which is used for graphs: i.e. collections of vertices (in 3D) connected by edges. Unlike a Manifold, a Graph does not have to represent a surface. There are also some associated functions which may be useful: in particular, there is the LS_skeletonize function which computes a curve skeleton from a Graph and returns the result as a new Graph.

gl_display provides the Viewer class which makes it simple to visualize meshes and graphs.

jupyter_display makes it easy to use PyGEL in the context of a Jupyter Notebook. This module contains a function that allows you to create a widget for interactively visualizing a mesh or a graph in a Notebook. The feature is based on the Plotly library and it is possible to export the resulting notebooks to HTML while preserving the interactive 3D graphics in the notebook.

spatial contains the I3DTree class which is simply a kD-tree specialized for mapping 3D points to integers - typically indices. Of course, scipy.spatial has a more generic class, so this is perhaps not the most important part of PyGEL.

  1""" PyGEL is a collection of classes and functions that expose features in the
  2GEL library. The primary purpose of PyGEL (and GEL) is to be useful for geometry
  3processing tasks. Especially tasks that involve 3D polygonal meshes, but there is
  4also a graph component useful e.g. for skeletonization. The PyGEL package is called
  5pygel3d and it contains five modules:
  6
  7hmesh provides Manifold which is a class that represents polygonal meshes using the
  8halfedge representation. hmesh also provides a slew of functions for manipulating
  9polygonal meshes and the MeshDistance class which makes it simple to compute the
 10distance to a triangle mesh.
 11
 12graph contains the Graph class which is used for graphs: i.e. collections of
 13vertices (in 3D) connected by edges. Unlike a Manifold, a Graph does not have to
 14represent a surface. There are also some associated functions which may be useful:
 15in particular, there is the LS_skeletonize function which computes a curve skeleton
 16from a Graph and returns the result as a new Graph.
 17
 18gl_display provides the Viewer class which makes it simple to visualize meshes and
 19graphs.
 20
 21jupyter_display makes it easy to use PyGEL in the context of a Jupyter Notebook.
 22This module contains a function that allows you to create a widget for interactively
 23visualizing a mesh or a graph in a Notebook. The feature is based on the Plotly
 24library and it is possible to export the resulting notebooks to HTML while preserving
 25the interactive 3D graphics in the notebook.
 26
 27spatial contains the I3DTree class which is simply a kD-tree specialized for mapping
 283D points to integers - typically indices. Of course, scipy.spatial has a more
 29generic class, so this is perhaps not the most important part of PyGEL.
 30"""
 31__all__ = ["hmesh", "graph", "gl_display", "jupyter_display", "spatial"]
 32
 33import os
 34from sys import platform, prefix
 35import ctypes as ct
 36import numpy as np
 37from numpy.ctypeslib import ndpointer
 38
 39def _get_script_path():
 40    return os.path.dirname(__file__)
 41
 42def _get_lib_name():
 43    if platform == "darwin":
 44        return "libPyGEL.dylib"
 45    if platform == "win32":
 46        return "PyGEL.dll"
 47    return "libPyGEL.so"
 48
 49# Load PyGEL the Python GEL bridge library
 50lib_py_gel = ct.cdll.LoadLibrary(_get_script_path() + "/" + _get_lib_name())
 51
 52# An InvalidIndex is just a special integer value.
 53InvalidIndex = ct.c_size_t.in_dll(lib_py_gel, "InvalidIndex").value
 54
 55# The following many lines explitize the arguments and return types of the C API
 56
 57# IntVector
 58lib_py_gel.IntVector_new.restype = ct.c_void_p
 59lib_py_gel.IntVector_get.argtypes = (ct.c_void_p, ct.c_size_t)
 60lib_py_gel.IntVector_size.argtypes = (ct.c_void_p,)
 61lib_py_gel.IntVector_size.restype = ct.c_size_t
 62lib_py_gel.IntVector_delete.argtypes = (ct.c_void_p,)
 63
 64
 65# Vec3dVector
 66lib_py_gel.Vec3dVector_new.restype = ct.c_void_p
 67lib_py_gel.Vec3dVector_get.argtypes = (ct.c_void_p, ct.c_size_t)
 68lib_py_gel.Vec3dVector_get.restype = ct.POINTER(ct.c_double)
 69lib_py_gel.Vec3dVector_size.argtypes = (ct.c_void_p,)
 70lib_py_gel.Vec3dVector_size.restype = ct.c_size_t
 71lib_py_gel.Vec3dVector_delete.argtypes = (ct.c_void_p,)
 72
 73# I3DTree
 74lib_py_gel.I3DTree_new.restype = ct.c_void_p
 75lib_py_gel.I3DTree_delete.argtypes = (ct.c_void_p,)
 76lib_py_gel.I3DTree_insert.argtypes = (ct.c_void_p, ct.c_double, ct.c_double, ct.c_double, ct.c_size_t)
 77lib_py_gel.I3DTree_build.argtypes = (ct.c_void_p,)
 78lib_py_gel.I3DTree_closest_point.argtypes = (ct.c_void_p, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.POINTER(ct.c_double*3), ct.POINTER(ct.c_size_t))
 79lib_py_gel.I3DTree_in_sphere.argtypes = (ct.c_void_p, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_void_p,ct.c_void_p)
 80
 81# Manifold class
 82lib_py_gel.Manifold_from_triangles.argtypes = (ct.c_size_t,ct.c_size_t, ndpointer(np.float64, ndim=2, flags='C'), ndpointer(ct.c_int, ndim=2, flags='C'))
 83lib_py_gel.Manifold_from_triangles.restype = ct.c_void_p
 84lib_py_gel.Manifold_from_points.argtypes = (ct.c_size_t,ndpointer(np.float64, ndim=2, flags='C'), ndpointer(np.float64, shape=3),ndpointer(np.float64, shape=3))
 85lib_py_gel.Manifold_from_points.restype = ct.c_void_p
 86lib_py_gel.Manifold_new.restype = ct.c_void_p
 87lib_py_gel.Manifold_copy.restype = ct.c_void_p
 88lib_py_gel.Manifold_copy.argtypes = (ct.c_void_p,)
 89lib_py_gel.Manifold_merge.argtypes = (ct.c_void_p,ct.c_void_p)
 90lib_py_gel.Manifold_delete.argtypes = (ct.c_void_p,)
 91lib_py_gel.Manifold_positions.restype = ct.c_size_t
 92lib_py_gel.Manifold_positions.argtypes = (ct.c_void_p, ct.POINTER(ct.POINTER(ct.c_double)))
 93lib_py_gel.Manifold_no_allocated_vertices.restype = ct.c_size_t
 94lib_py_gel.Manifold_no_allocated_vertices.argtypes = (ct.c_void_p,)
 95lib_py_gel.Manifold_no_allocated_faces.restype = ct.c_size_t
 96lib_py_gel.Manifold_no_allocated_faces.argtypes = (ct.c_void_p,)
 97lib_py_gel.Manifold_no_allocated_halfedges.restype = ct.c_size_t
 98lib_py_gel.Manifold_no_allocated_halfedges.argtypes = (ct.c_void_p,)
 99lib_py_gel.Manifold_vertices.restype = ct.c_size_t
100lib_py_gel.Manifold_vertices.argtypes = (ct.c_void_p, ct.c_void_p)
101lib_py_gel.Manifold_faces.restype = ct.c_size_t
102lib_py_gel.Manifold_faces.argtypes = (ct.c_void_p, ct.c_void_p)
103lib_py_gel.Manifold_halfedges.restype = ct.c_size_t
104lib_py_gel.Manifold_halfedges.argtypes = (ct.c_void_p,ct.c_void_p)
105lib_py_gel.Manifold_circulate_vertex.restype = ct.c_size_t
106lib_py_gel.Manifold_circulate_vertex.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_char, ct.c_void_p)
107lib_py_gel.Manifold_circulate_face.restype = ct.c_size_t
108lib_py_gel.Manifold_circulate_face.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_char, ct.c_void_p)
109lib_py_gel.Manifold_add_face.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(np.float64, ndim=2, flags='C'))
110lib_py_gel.Manifold_remove_face.restype = ct.c_bool
111lib_py_gel.Manifold_remove_face.argtypes = (ct.c_void_p, ct.c_size_t)
112lib_py_gel.Manifold_remove_edge.restype = ct.c_bool
113lib_py_gel.Manifold_remove_edge.argtypes = (ct.c_void_p, ct.c_size_t)
114lib_py_gel.Manifold_remove_vertex.restype = ct.c_bool
115lib_py_gel.Manifold_remove_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
116lib_py_gel.Manifold_vertex_in_use.restype = ct.c_bool
117lib_py_gel.Manifold_vertex_in_use.argtypes = (ct.c_void_p,ct.c_size_t)
118lib_py_gel.Manifold_face_in_use.restype = ct.c_bool
119lib_py_gel.Manifold_face_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
120lib_py_gel.Manifold_halfedge_in_use.restype = ct.c_bool
121lib_py_gel.Manifold_halfedge_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
122lib_py_gel.Manifold_flip_edge.restype =  ct.c_bool
123lib_py_gel.Manifold_flip_edge.argtypes = (ct.c_void_p, ct.c_size_t)
124lib_py_gel.Manifold_collapse_edge.restype = ct.c_bool
125lib_py_gel.Manifold_collapse_edge.argtypes = (ct.c_void_p,ct.c_size_t,ct.c_bool)
126lib_py_gel.Manifold_split_face_by_edge.restype = ct.c_size_t
127lib_py_gel.Manifold_split_face_by_edge.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t,ct.c_size_t)
128lib_py_gel.Manifold_split_face_by_vertex.restype = ct.c_size_t
129lib_py_gel.Manifold_split_face_by_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
130lib_py_gel.Manifold_split_edge.restype = ct.c_size_t
131lib_py_gel.Manifold_split_edge.argtypes = (ct.c_void_p, ct.c_size_t)
132lib_py_gel.Manifold_stitch_boundary_edges.restype = ct.c_bool
133lib_py_gel.Manifold_stitch_boundary_edges.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t)
134lib_py_gel.Manifold_merge_faces.restype = ct.c_bool
135lib_py_gel.Manifold_merge_faces.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t)
136lib_py_gel.Manifold_close_hole.argtypes = (ct.c_void_p,ct.c_size_t)
137lib_py_gel.Manifold_cleanup.argtypes = (ct.c_void_p,)
138
139# Walker is a helper class assisting us in navigating a mesh.
140# Not directly expose in PyGEL3D
141lib_py_gel.Walker_next_halfedge.restype = ct.c_size_t
142lib_py_gel.Walker_next_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
143lib_py_gel.Walker_prev_halfedge.restype = ct.c_size_t
144lib_py_gel.Walker_prev_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
145lib_py_gel.Walker_opposite_halfedge.restype = ct.c_size_t
146lib_py_gel.Walker_opposite_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
147lib_py_gel.Walker_incident_face.restype = ct.c_size_t
148lib_py_gel.Walker_incident_face.argtypes = (ct.c_void_p, ct.c_size_t)
149lib_py_gel.Walker_incident_vertex.restype = ct.c_size_t
150lib_py_gel.Walker_incident_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
151
152# A list of helper functions
153lib_py_gel.is_halfedge_at_boundary.restype = ct.c_bool
154lib_py_gel.is_halfedge_at_boundary.argtypes = (ct.c_void_p, ct.c_size_t)
155lib_py_gel.is_vertex_at_boundary.restype = ct.c_bool
156lib_py_gel.is_vertex_at_boundary.argtypes = (ct.c_void_p, ct.c_size_t)
157lib_py_gel.length.restype = ct.c_double
158lib_py_gel.length.argtypes = (ct.c_void_p, ct.c_size_t)
159lib_py_gel.boundary_edge.restype = ct.c_bool
160lib_py_gel.boundary_edge.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
161lib_py_gel.valency.restype = ct.c_size_t
162lib_py_gel.valency.argtypes = (ct.c_void_p, ct.c_size_t)
163lib_py_gel.vertex_normal.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
164lib_py_gel.connected.restype = ct.c_bool
165lib_py_gel.connected.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
166lib_py_gel.no_edges.restype = ct.c_size_t
167lib_py_gel.no_edges.argtypes = (ct.c_void_p, ct.c_size_t)
168lib_py_gel.face_normal.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
169lib_py_gel.area.restype = ct.c_double
170lib_py_gel.area.argtypes = (ct.c_void_p, ct.c_size_t)
171lib_py_gel.perimeter.restype = ct.c_double
172lib_py_gel.perimeter.argtypes = (ct.c_void_p, ct.c_size_t)
173lib_py_gel.centre.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
174lib_py_gel.valid.restype = ct.c_bool
175lib_py_gel.valid.argtypes = (ct.c_void_p,)
176lib_py_gel.closed.restype = ct.c_bool
177lib_py_gel.closed.argtypes = (ct.c_void_p,)
178lib_py_gel.bbox.argtypes = (ct.c_void_p, ndpointer(dtype=np.float64, shape=(3,)),ndpointer(dtype=np.float64, shape=(3,)))
179lib_py_gel.bsphere.argtypes = (ct.c_void_p, ndpointer(dtype=np.float64, shape=(3,)), ct.POINTER(ct.c_double))
180lib_py_gel.stitch_mesh.argtypes = (ct.c_void_p,ct.c_double)
181lib_py_gel.stitch_mesh.restype = ct.c_int
182lib_py_gel.obj_save.argtypes = (ct.c_char_p, ct.c_void_p)
183lib_py_gel.off_save.argtypes = (ct.c_char_p, ct.c_void_p)
184lib_py_gel.x3d_save.argtypes = (ct.c_char_p, ct.c_void_p)
185lib_py_gel.obj_load.argtypes = (ct.c_char_p, ct.c_void_p)
186lib_py_gel.off_load.argtypes = (ct.c_char_p, ct.c_void_p)
187lib_py_gel.ply_load.argtypes = (ct.c_char_p, ct.c_void_p)
188lib_py_gel.x3d_load.argtypes = (ct.c_char_p, ct.c_void_p)
189lib_py_gel.remove_caps.argtypes = (ct.c_void_p, ct.c_float)
190lib_py_gel.remove_needles.argtypes = (ct.c_void_p, ct.c_float, ct.c_bool)
191lib_py_gel.close_holes.argtypes = (ct.c_void_p,ct.c_int)
192lib_py_gel.flip_orientation.argtypes = (ct.c_void_p,)
193lib_py_gel.merge_coincident_boundary_vertices.argtypes = (ct.c_void_p, ct.c_double)
194lib_py_gel.minimize_curvature.argtypes = (ct.c_void_p,ct.c_bool)
195lib_py_gel.minimize_dihedral_angle.argtypes = (ct.c_void_p, ct.c_int, ct.c_bool, ct.c_bool, ct.c_double)
196lib_py_gel.maximize_min_angle.argtypes = (ct.c_void_p,ct.c_float,ct.c_bool)
197lib_py_gel.optimize_valency.argtypes = (ct.c_void_p,ct.c_bool)
198lib_py_gel.randomize_mesh.argtypes = (ct.c_void_p,ct.c_int)
199lib_py_gel.quadric_simplify.argtypes = (ct.c_void_p,ct.c_double,ct.c_double,ct.c_double)
200lib_py_gel.average_edge_length.argtypes = (ct.c_void_p,)
201lib_py_gel.average_edge_length.restype = ct.c_float
202lib_py_gel.median_edge_length.argtypes = (ct.c_void_p,)
203lib_py_gel.median_edge_length.restype = ct.c_float
204lib_py_gel.refine_edges.argtypes = (ct.c_void_p,ct.c_float)
205lib_py_gel.refine_edges.restype = ct.c_int
206lib_py_gel.cc_split.argtypes = (ct.c_void_p,)
207lib_py_gel.loop_split.argtypes = (ct.c_void_p,)
208lib_py_gel.root3_subdivide.argtypes = (ct.c_void_p,)
209lib_py_gel.rootCC_subdivide.argtypes = (ct.c_void_p,)
210lib_py_gel.butterfly_subdivide.argtypes = (ct.c_void_p,)
211lib_py_gel.cc_smooth.argtypes = (ct.c_void_p,)
212lib_py_gel.volume_preserving_cc_smooth.argtypes = (ct.c_void_p,ct.c_int)
213lib_py_gel.regularize_quads.argtypes = (ct.c_void_p,ct.c_float,ct.c_float,ct.c_int)
214lib_py_gel.loop_smooth.argtypes = (ct.c_void_p,)
215lib_py_gel.ear_clip_triangulate.argtypes = (ct.c_void_p,)
216lib_py_gel.shortest_edge_triangulate.argtypes = (ct.c_void_p,)
217lib_py_gel.graph_to_feq.argtypes = (ct.c_void_p, ct.c_void_p, ndpointer(dtype=np.float64, ndim=1), ct.c_bool, ct.c_bool)
218lib_py_gel.graph_to_feq.restype = ct.c_void_p
219lib_py_gel.non_rigid_registration.argtypes = (ct.c_void_p, ct.c_void_p)
220lib_py_gel.taubin_smooth.argtypes = (ct.c_void_p, ct.c_int)
221lib_py_gel.laplacian_smooth.argtypes = (ct.c_void_p, ct.c_float, ct.c_int)
222lib_py_gel.anisotropic_smooth.argtypes = (ct.c_void_p, ct.c_float, ct.c_int)
223lib_py_gel.volumetric_isocontour.argtypes = (ct.c_void_p, ct.c_int, ct.c_int, ct.c_int, ndpointer(ndim=3, dtype=ct.c_float,flags='F'), ndpointer(dtype=ct.c_double,shape=(3,)), ndpointer(dtype=ct.c_double,shape=(3,)), ct.c_float, ct.c_bool, ct.c_bool, ct.c_bool )
224
225
226# MeshDistance allows us to compute the signed distance to a mesh
227lib_py_gel.MeshDistance_new.restype = ct.c_void_p
228lib_py_gel.MeshDistance_new.argtypes = (ct.c_void_p,)
229lib_py_gel.MeshDistance_signed_distance.argtypes = (ct.c_void_p,ct.c_int, ndpointer(dtype=ct.c_float,flags='C'),ndpointer(dtype=ct.c_float,flags='C',ndim=1),ct.c_float)
230lib_py_gel.MeshDistance_ray_inside_test.argtypes = (ct.c_void_p,ct.c_int, ndpointer(dtype=ct.c_float,flags='C'),ndpointer(dtype=ct.c_int,flags='C',ndim=1),ct.c_int)
231lib_py_gel.MeshDistance_ray_intersect.argtypes = (ct.c_void_p,ndpointer(dtype=ct.c_float,shape=3),ndpointer(dtype=ct.c_float,shape=3),ct.POINTER(ct.c_float))
232lib_py_gel.MeshDistance_ray_intersect.restype = ct.c_bool
233lib_py_gel.MeshDistance_delete.argtypes = (ct.c_void_p,)
234
235# The Graph class
236lib_py_gel.Graph_new.restype = ct.c_void_p
237lib_py_gel.Graph_copy.restype = ct.c_void_p
238lib_py_gel.Graph_copy.argtypes = (ct.c_void_p,)
239lib_py_gel.Graph_delete.argtypes = (ct.c_void_p,)
240lib_py_gel.Graph_clear.argtypes = (ct.c_void_p,)
241lib_py_gel.Graph_cleanup.argtypes = (ct.c_void_p,)
242lib_py_gel.Graph_nodes.argtypes = (ct.c_void_p, ct.c_void_p)
243lib_py_gel.Graph_nodes.restype = ct.c_size_t
244lib_py_gel.Graph_neighbors.restype = ct.c_size_t
245lib_py_gel.Graph_neighbors.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_void_p, ct.c_char)
246lib_py_gel.Graph_positions.argtypes = (ct.c_void_p,ct.POINTER(ct.POINTER(ct.c_double)))
247lib_py_gel.Graph_positions.restype = ct.c_size_t
248lib_py_gel.Graph_average_edge_length.argtypes = (ct.c_void_p,)
249lib_py_gel.Graph_average_edge_length.restype = ct.c_double
250lib_py_gel.Graph_add_node.argtypes = (ct.c_void_p, ndpointer(ct.c_double))
251lib_py_gel.Graph_add_node.restype = ct.c_size_t
252lib_py_gel.Graph_remove_node.argtypes = (ct.c_void_p, ct.c_size_t)
253lib_py_gel.Graph_node_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
254lib_py_gel.Graph_node_in_use.restype = ct.c_bool
255lib_py_gel.Graph_connect_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
256lib_py_gel.Graph_connect_nodes.restype = ct.c_size_t
257lib_py_gel.Graph_disconnect_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
258lib_py_gel.Graph_merge_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t, ct.c_bool)
259
260# Graph functions
261lib_py_gel.graph_from_mesh.argtypes = (ct.c_void_p, ct.c_void_p)
262lib_py_gel.graph_load.argtypes = (ct.c_void_p, ct.c_char_p)
263lib_py_gel.graph_load.restype = ct.c_void_p
264lib_py_gel.graph_save.argtypes = (ct.c_void_p, ct.c_char_p)
265lib_py_gel.graph_save.restype = ct.c_bool
266lib_py_gel.graph_to_mesh_cyl.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_float)
267lib_py_gel.graph_to_mesh_cyl.restype = ct.c_void_p
268lib_py_gel.graph_to_mesh_iso.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_float, ct.c_int)
269lib_py_gel.graph_to_mesh_iso.restype = ct.c_void_p
270lib_py_gel.graph_smooth.argtypes = (ct.c_void_p, ct.c_int, ct.c_float)
271lib_py_gel.graph_edge_contract.argtypes = (ct.c_void_p, ct.c_double)
272lib_py_gel.graph_prune.argtypes = (ct.c_void_p,)
273lib_py_gel.graph_saturate.argtypes = (ct.c_void_p, ct.c_int, ct.c_double, ct.c_double)
274lib_py_gel.graph_LS_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_bool)
275lib_py_gel.graph_MSLS_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int)
276lib_py_gel.graph_front_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int, ndpointer(dtype=np.float64,flags='C'), ct.c_int)
277lib_py_gel.graph_combined_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int, ndpointer(dtype=np.float64,flags='C'), ct.c_int)
278
279class IntVector:
280    """ Vector of integer values.
281    This is a simple class that implements iteration and index based
282    retrieval. Allocation happens in a call to libPyGEL. Since memory
283    is managed by the PyGEL library, the vector can be resized by library
284    functions. Generally not used directly by PyGEL3D users."""
285    def __init__(self):
286        self.obj = lib_py_gel.IntVector_new(0)
287    def __del__(self):
288        lib_py_gel.IntVector_delete(self.obj)
289    def __len__(self):
290        return int(lib_py_gel.IntVector_size(self.obj))
291    def __getitem__(self,key):
292        return lib_py_gel.IntVector_get(self.obj,key)
293    def __iter__(self):
294        n = lib_py_gel.IntVector_size(self.obj)
295        for i in range(0,n):
296            yield lib_py_gel.IntVector_get(self.obj, i)
297
298class Vec3dVector:
299    """ Vector of 3D vectors.
300    This is a simple class that implements iteration and index based
301    retrieval. Allocation happens in a call to libPyGEL. Since memory
302    is managed by the PyGEL library, the vector can be resized by library
303    functions. nerally not used directly by PyGEL3D users."""
304    def __init__(self):
305        self.obj = lib_py_gel.Vec3dVector_new(0)
306    def __del__(self):
307        lib_py_gel.Vec3dVector_delete(self.obj)
308    def __len__(self):
309        return int(lib_py_gel.Vec3dVector_size(self.obj))
310    def __getitem__(self,key):
311        return lib_py_gel.Vec3dVector_get(self.obj,key)
312    def __iter__(self):
313        n = lib_py_gel.Vec3dVector_size(self.obj)
314        for i in range(0,n):
315            data = lib_py_gel.Vec3dVector_get(self.obj, i)
316            yield [data[0], data[1], data[2]]