PyGEL3D 0.8.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygel3d/PyGEL.dll +0 -0
- pygel3d/__init__.py +389 -0
- pygel3d/experimental/__init__.py +1 -0
- pygel3d/experimental/hmesh.py +32 -0
- pygel3d/gl_display.py +127 -0
- pygel3d/graph.py +290 -0
- pygel3d/hmesh.py +1112 -0
- pygel3d/jupyter_display.py +91 -0
- pygel3d/spatial.py +40 -0
- pygel3d-0.8.0.dist-info/METADATA +159 -0
- pygel3d-0.8.0.dist-info/RECORD +14 -0
- pygel3d-0.8.0.dist-info/WHEEL +5 -0
- pygel3d-0.8.0.dist-info/licenses/LICENSE.md +27 -0
- pygel3d-0.8.0.dist-info/top_level.txt +1 -0
pygel3d/PyGEL.dll
ADDED
|
Binary file
|
pygel3d/__init__.py
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
""" PyGEL is a collection of classes and functions for geometry processing tasks.
|
|
2
|
+
Especially tasks that involve 3D polygonal meshes, but there is also a graph component
|
|
3
|
+
useful e.g. for skeletonization. The PyGEL package is called pygel3d and it contains
|
|
4
|
+
five modules:
|
|
5
|
+
|
|
6
|
+
hmesh provides Manifold which is a class that represents polygonal meshes using the
|
|
7
|
+
halfedge representation. hmesh also provides a slew of functions for manipulating
|
|
8
|
+
polygonal meshes and the MeshDistance class which makes it simple to compute the
|
|
9
|
+
distance to a triangle mesh.
|
|
10
|
+
|
|
11
|
+
graph contains the Graph class which is used for graphs: i.e. collections of
|
|
12
|
+
vertices (in 3D) connected by edges. Unlike a Manifold, a Graph does not have to
|
|
13
|
+
represent a surface. There are also some associated functions which may be useful:
|
|
14
|
+
in particular, there is the LS_skeleton function which computes a curve skeleton
|
|
15
|
+
from a Graph and returns the result as a new Graph.
|
|
16
|
+
|
|
17
|
+
gl_display provides the Viewer class which makes it simple to visualize meshes and
|
|
18
|
+
graphs.
|
|
19
|
+
|
|
20
|
+
jupyter_display makes it easy to use PyGEL in the context of a Jupyter Notebook.
|
|
21
|
+
This module contains a function that allows you to create a widget for interactively
|
|
22
|
+
visualizing a mesh or a graph in a Notebook. The feature is based on the Plotly
|
|
23
|
+
library and it is possible to export the resulting notebooks to HTML while preserving
|
|
24
|
+
the interactive 3D graphics in the notebook.
|
|
25
|
+
|
|
26
|
+
spatial contains the I3DTree class which is simply a kD-tree specialized for mapping
|
|
27
|
+
3D points to integers - typically indices. Of course, scipy.spatial has a more
|
|
28
|
+
generic class, so this is perhaps not the most important part of PyGEL.
|
|
29
|
+
|
|
30
|
+
PyGEL is based on the C++ GEL library and provides a Python interface for most but not
|
|
31
|
+
all of the functionality of GEL.
|
|
32
|
+
"""
|
|
33
|
+
def _read_version():
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
for parent in list(Path(__file__).resolve().parents)[:6]:
|
|
36
|
+
vf = parent / "VERSION"
|
|
37
|
+
if vf.is_file():
|
|
38
|
+
return vf.read_text(encoding="utf-8").strip()
|
|
39
|
+
try:
|
|
40
|
+
from importlib.metadata import version as _pkg_version
|
|
41
|
+
return _pkg_version("PyGEL3D")
|
|
42
|
+
except Exception:
|
|
43
|
+
return "0.0.0"
|
|
44
|
+
|
|
45
|
+
__version__ = _read_version()
|
|
46
|
+
|
|
47
|
+
__all__ = ["hmesh", "graph", "gl_display", "jupyter_display", "spatial", "experimental"]
|
|
48
|
+
|
|
49
|
+
import os
|
|
50
|
+
from sys import platform, prefix
|
|
51
|
+
import ctypes as ct
|
|
52
|
+
import numpy as np
|
|
53
|
+
from numpy.ctypeslib import ndpointer
|
|
54
|
+
|
|
55
|
+
def _get_script_path():
|
|
56
|
+
return os.path.dirname(__file__)
|
|
57
|
+
|
|
58
|
+
def _get_lib_name():
|
|
59
|
+
if platform == "darwin":
|
|
60
|
+
return "libPyGEL.dylib"
|
|
61
|
+
if platform == "win32":
|
|
62
|
+
return "PyGEL.dll"
|
|
63
|
+
return "libPyGEL.so"
|
|
64
|
+
|
|
65
|
+
def _load_library():
|
|
66
|
+
name = _get_lib_name()
|
|
67
|
+
path = os.path.join(_get_script_path(), name)
|
|
68
|
+
if not os.path.isfile(path):
|
|
69
|
+
raise ImportError(
|
|
70
|
+
f"pygel3d: native library {name} not found at {path}. "
|
|
71
|
+
"Reinstall from PyPI (`pip install --force-reinstall PyGEL3D`) "
|
|
72
|
+
"or build from source."
|
|
73
|
+
)
|
|
74
|
+
try:
|
|
75
|
+
return ct.cdll.LoadLibrary(path)
|
|
76
|
+
except OSError as exc:
|
|
77
|
+
hint = ""
|
|
78
|
+
if platform.startswith("linux"):
|
|
79
|
+
hint = (
|
|
80
|
+
" On Linux the library needs system OpenGL "
|
|
81
|
+
"(e.g. `sudo apt-get install libgl1`)."
|
|
82
|
+
)
|
|
83
|
+
raise ImportError(
|
|
84
|
+
f"pygel3d: failed to load {path}: {exc}.{hint}"
|
|
85
|
+
) from exc
|
|
86
|
+
|
|
87
|
+
# Load PyGEL the Python GEL bridge library
|
|
88
|
+
lib_py_gel = _load_library()
|
|
89
|
+
|
|
90
|
+
# An InvalidIndex is just a special integer value.
|
|
91
|
+
InvalidIndex = ct.c_size_t.in_dll(lib_py_gel, "InvalidIndex").value
|
|
92
|
+
|
|
93
|
+
# The following many lines explitize the arguments and return types of the C API
|
|
94
|
+
|
|
95
|
+
# IntVector
|
|
96
|
+
lib_py_gel.IntVector_new.restype = ct.c_void_p
|
|
97
|
+
lib_py_gel.IntVector_get.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
98
|
+
lib_py_gel.IntVector_size.argtypes = (ct.c_void_p,)
|
|
99
|
+
lib_py_gel.IntVector_size.restype = ct.c_size_t
|
|
100
|
+
lib_py_gel.IntVector_delete.argtypes = (ct.c_void_p,)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Vec3dVector
|
|
104
|
+
lib_py_gel.Vec3dVector_new.restype = ct.c_void_p
|
|
105
|
+
lib_py_gel.Vec3dVector_get.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
106
|
+
lib_py_gel.Vec3dVector_get.restype = ct.POINTER(ct.c_double)
|
|
107
|
+
lib_py_gel.Vec3dVector_size.argtypes = (ct.c_void_p,)
|
|
108
|
+
lib_py_gel.Vec3dVector_size.restype = ct.c_size_t
|
|
109
|
+
lib_py_gel.Vec3dVector_delete.argtypes = (ct.c_void_p,)
|
|
110
|
+
|
|
111
|
+
# I3DTree
|
|
112
|
+
lib_py_gel.I3DTree_new.restype = ct.c_void_p
|
|
113
|
+
lib_py_gel.I3DTree_delete.argtypes = (ct.c_void_p,)
|
|
114
|
+
lib_py_gel.I3DTree_insert.argtypes = (ct.c_void_p, ct.c_double, ct.c_double, ct.c_double, ct.c_size_t)
|
|
115
|
+
lib_py_gel.I3DTree_build.argtypes = (ct.c_void_p,)
|
|
116
|
+
lib_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))
|
|
117
|
+
lib_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)
|
|
118
|
+
|
|
119
|
+
# Manifold class
|
|
120
|
+
lib_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'))
|
|
121
|
+
lib_py_gel.Manifold_from_triangles.restype = ct.c_void_p
|
|
122
|
+
lib_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))
|
|
123
|
+
lib_py_gel.Manifold_from_points.restype = ct.c_void_p
|
|
124
|
+
lib_py_gel.Manifold_new.restype = ct.c_void_p
|
|
125
|
+
lib_py_gel.Manifold_copy.restype = ct.c_void_p
|
|
126
|
+
lib_py_gel.Manifold_copy.argtypes = (ct.c_void_p,)
|
|
127
|
+
lib_py_gel.Manifold_merge.argtypes = (ct.c_void_p,ct.c_void_p)
|
|
128
|
+
lib_py_gel.Manifold_delete.argtypes = (ct.c_void_p,)
|
|
129
|
+
lib_py_gel.Manifold_positions.restype = ct.c_size_t
|
|
130
|
+
lib_py_gel.Manifold_positions.argtypes = (ct.c_void_p, ct.POINTER(ct.POINTER(ct.c_double)))
|
|
131
|
+
lib_py_gel.Manifold_no_allocated_vertices.restype = ct.c_size_t
|
|
132
|
+
lib_py_gel.Manifold_no_allocated_vertices.argtypes = (ct.c_void_p,)
|
|
133
|
+
lib_py_gel.Manifold_no_allocated_faces.restype = ct.c_size_t
|
|
134
|
+
lib_py_gel.Manifold_no_allocated_faces.argtypes = (ct.c_void_p,)
|
|
135
|
+
lib_py_gel.Manifold_no_allocated_halfedges.restype = ct.c_size_t
|
|
136
|
+
lib_py_gel.Manifold_no_allocated_halfedges.argtypes = (ct.c_void_p,)
|
|
137
|
+
lib_py_gel.Manifold_vertices.restype = ct.c_size_t
|
|
138
|
+
lib_py_gel.Manifold_vertices.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
139
|
+
lib_py_gel.Manifold_faces.restype = ct.c_size_t
|
|
140
|
+
lib_py_gel.Manifold_faces.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
141
|
+
lib_py_gel.Manifold_halfedges.restype = ct.c_size_t
|
|
142
|
+
lib_py_gel.Manifold_halfedges.argtypes = (ct.c_void_p,ct.c_void_p)
|
|
143
|
+
lib_py_gel.Manifold_circulate_vertex.restype = ct.c_size_t
|
|
144
|
+
lib_py_gel.Manifold_circulate_vertex.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_char, ct.c_void_p)
|
|
145
|
+
lib_py_gel.Manifold_circulate_face.restype = ct.c_size_t
|
|
146
|
+
lib_py_gel.Manifold_circulate_face.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_char, ct.c_void_p)
|
|
147
|
+
lib_py_gel.Manifold_add_face.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(np.float64, ndim=2, flags='C'))
|
|
148
|
+
lib_py_gel.Manifold_remove_face.restype = ct.c_bool
|
|
149
|
+
lib_py_gel.Manifold_remove_face.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
150
|
+
lib_py_gel.Manifold_remove_edge.restype = ct.c_bool
|
|
151
|
+
lib_py_gel.Manifold_remove_edge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
152
|
+
lib_py_gel.Manifold_remove_vertex.restype = ct.c_bool
|
|
153
|
+
lib_py_gel.Manifold_remove_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
154
|
+
lib_py_gel.Manifold_vertex_in_use.restype = ct.c_bool
|
|
155
|
+
lib_py_gel.Manifold_vertex_in_use.argtypes = (ct.c_void_p,ct.c_size_t)
|
|
156
|
+
lib_py_gel.Manifold_face_in_use.restype = ct.c_bool
|
|
157
|
+
lib_py_gel.Manifold_face_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
158
|
+
lib_py_gel.Manifold_halfedge_in_use.restype = ct.c_bool
|
|
159
|
+
lib_py_gel.Manifold_halfedge_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
160
|
+
lib_py_gel.Manifold_flip_edge.restype = ct.c_bool
|
|
161
|
+
lib_py_gel.Manifold_flip_edge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
162
|
+
lib_py_gel.Manifold_collapse_edge.restype = ct.c_bool
|
|
163
|
+
lib_py_gel.Manifold_collapse_edge.argtypes = (ct.c_void_p,ct.c_size_t,ct.c_bool)
|
|
164
|
+
lib_py_gel.Manifold_split_face_by_edge.restype = ct.c_size_t
|
|
165
|
+
lib_py_gel.Manifold_split_face_by_edge.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t,ct.c_size_t)
|
|
166
|
+
lib_py_gel.Manifold_split_face_by_vertex.restype = ct.c_size_t
|
|
167
|
+
lib_py_gel.Manifold_split_face_by_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
168
|
+
lib_py_gel.Manifold_split_edge.restype = ct.c_size_t
|
|
169
|
+
lib_py_gel.Manifold_split_edge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
170
|
+
lib_py_gel.Manifold_stitch_boundary_edges.restype = ct.c_bool
|
|
171
|
+
lib_py_gel.Manifold_stitch_boundary_edges.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t)
|
|
172
|
+
lib_py_gel.Manifold_merge_faces.restype = ct.c_bool
|
|
173
|
+
lib_py_gel.Manifold_merge_faces.argtypes = (ct.c_void_p, ct.c_size_t,ct.c_size_t)
|
|
174
|
+
lib_py_gel.Manifold_close_hole.argtypes = (ct.c_void_p,ct.c_size_t)
|
|
175
|
+
lib_py_gel.Manifold_cleanup.argtypes = (ct.c_void_p,)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# Walker is a helper class assisting us in navigating a mesh.
|
|
179
|
+
# Not directly expose in PyGEL3D
|
|
180
|
+
lib_py_gel.Walker_next_halfedge.restype = ct.c_size_t
|
|
181
|
+
lib_py_gel.Walker_next_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
182
|
+
lib_py_gel.Walker_prev_halfedge.restype = ct.c_size_t
|
|
183
|
+
lib_py_gel.Walker_prev_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
184
|
+
lib_py_gel.Walker_opposite_halfedge.restype = ct.c_size_t
|
|
185
|
+
lib_py_gel.Walker_opposite_halfedge.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
186
|
+
lib_py_gel.Walker_incident_face.restype = ct.c_size_t
|
|
187
|
+
lib_py_gel.Walker_incident_face.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
188
|
+
lib_py_gel.Walker_incident_vertex.restype = ct.c_size_t
|
|
189
|
+
lib_py_gel.Walker_incident_vertex.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
190
|
+
|
|
191
|
+
# A list of helper functions
|
|
192
|
+
lib_py_gel.is_halfedge_at_boundary.restype = ct.c_bool
|
|
193
|
+
lib_py_gel.is_halfedge_at_boundary.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
194
|
+
lib_py_gel.is_vertex_at_boundary.restype = ct.c_bool
|
|
195
|
+
lib_py_gel.is_vertex_at_boundary.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
196
|
+
lib_py_gel.length.restype = ct.c_double
|
|
197
|
+
lib_py_gel.length.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
198
|
+
lib_py_gel.boundary_edge.restype = ct.c_bool
|
|
199
|
+
lib_py_gel.boundary_edge.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
|
|
200
|
+
lib_py_gel.valency.restype = ct.c_size_t
|
|
201
|
+
lib_py_gel.valency.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
202
|
+
lib_py_gel.vertex_normal.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
|
|
203
|
+
lib_py_gel.connected.restype = ct.c_bool
|
|
204
|
+
lib_py_gel.connected.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
|
|
205
|
+
lib_py_gel.no_edges.restype = ct.c_size_t
|
|
206
|
+
lib_py_gel.no_edges.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
207
|
+
lib_py_gel.face_normal.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
|
|
208
|
+
lib_py_gel.area.restype = ct.c_double
|
|
209
|
+
lib_py_gel.area.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
210
|
+
lib_py_gel.one_ring_area.restype = ct.c_double
|
|
211
|
+
lib_py_gel.one_ring_area.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
212
|
+
lib_py_gel.mixed_area.restype = ct.c_double
|
|
213
|
+
lib_py_gel.mixed_area.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
214
|
+
lib_py_gel.gaussian_curvature.restype = ct.c_double
|
|
215
|
+
lib_py_gel.gaussian_curvature.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
216
|
+
lib_py_gel.mean_curvature.restype = ct.c_double
|
|
217
|
+
lib_py_gel.mean_curvature.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
218
|
+
lib_py_gel.principal_curvatures.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(8,)))
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
lib_py_gel.total_area.restype = ct.c_double
|
|
222
|
+
lib_py_gel.total_area.argtypes = (ct.c_void_p,)
|
|
223
|
+
lib_py_gel.volume.restype = ct.c_double
|
|
224
|
+
lib_py_gel.volume.argtypes = (ct.c_void_p,)
|
|
225
|
+
lib_py_gel.perimeter.restype = ct.c_double
|
|
226
|
+
lib_py_gel.perimeter.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
227
|
+
lib_py_gel.centre.argtypes = (ct.c_void_p, ct.c_size_t, ndpointer(dtype=np.float64, shape=(3,)))
|
|
228
|
+
lib_py_gel.valid.restype = ct.c_bool
|
|
229
|
+
lib_py_gel.valid.argtypes = (ct.c_void_p,)
|
|
230
|
+
lib_py_gel.closed.restype = ct.c_bool
|
|
231
|
+
lib_py_gel.closed.argtypes = (ct.c_void_p,)
|
|
232
|
+
lib_py_gel.bbox.argtypes = (ct.c_void_p, ndpointer(dtype=np.float64, shape=(3,)),ndpointer(dtype=np.float64, shape=(3,)))
|
|
233
|
+
lib_py_gel.bsphere.argtypes = (ct.c_void_p, ndpointer(dtype=np.float64, shape=(3,)), ct.POINTER(ct.c_double))
|
|
234
|
+
lib_py_gel.stitch_mesh.argtypes = (ct.c_void_p,ct.c_double)
|
|
235
|
+
lib_py_gel.stitch_mesh.restype = ct.c_int
|
|
236
|
+
lib_py_gel.obj_save.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
237
|
+
lib_py_gel.off_save.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
238
|
+
lib_py_gel.x3d_save.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
239
|
+
lib_py_gel.obj_load.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
240
|
+
lib_py_gel.off_load.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
241
|
+
lib_py_gel.ply_load.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
242
|
+
lib_py_gel.x3d_load.argtypes = (ct.c_char_p, ct.c_void_p)
|
|
243
|
+
lib_py_gel.rsr_recon.argtypes = (ct.c_void_p, ndpointer(ndim=2, dtype=ct.c_double,flags='F'), ndpointer(ndim=2, dtype=ct.c_double,flags='F'), ct.c_int, ct.c_int, ct.c_bool, ct.c_int, ct.c_int, ct.c_double, ct.c_double, ct.c_int)
|
|
244
|
+
lib_py_gel.hrsr_recon.argtypes = (ct.c_void_p, ndpointer(ndim=2, dtype=ct.c_double,flags='F'), ndpointer(ndim=2, dtype=ct.c_double,flags='F'), ct.c_size_t, ct.c_size_t, ct.c_int, ct.c_bool, ct.c_int, ct.c_int, ct.c_double, ct.c_double, ct.c_int, ct.c_bool)
|
|
245
|
+
lib_py_gel.remove_caps.argtypes = (ct.c_void_p, ct.c_float)
|
|
246
|
+
lib_py_gel.remove_needles.argtypes = (ct.c_void_p, ct.c_float, ct.c_bool)
|
|
247
|
+
lib_py_gel.close_holes.argtypes = (ct.c_void_p,ct.c_int)
|
|
248
|
+
lib_py_gel.flip_orientation.argtypes = (ct.c_void_p,)
|
|
249
|
+
lib_py_gel.merge_coincident_boundary_vertices.argtypes = (ct.c_void_p, ct.c_double)
|
|
250
|
+
lib_py_gel.minimize_curvature.argtypes = (ct.c_void_p,ct.c_bool)
|
|
251
|
+
lib_py_gel.minimize_dihedral_angle.argtypes = (ct.c_void_p, ct.c_int, ct.c_bool, ct.c_bool, ct.c_double)
|
|
252
|
+
lib_py_gel.maximize_min_angle.argtypes = (ct.c_void_p,ct.c_float,ct.c_bool)
|
|
253
|
+
lib_py_gel.optimize_valency.argtypes = (ct.c_void_p,ct.c_bool)
|
|
254
|
+
lib_py_gel.randomize_mesh.argtypes = (ct.c_void_p,ct.c_int)
|
|
255
|
+
lib_py_gel.quadric_simplify.argtypes = (ct.c_void_p,ct.c_double,ct.c_double,ct.c_double)
|
|
256
|
+
lib_py_gel.average_edge_length.argtypes = (ct.c_void_p,)
|
|
257
|
+
lib_py_gel.average_edge_length.restype = ct.c_float
|
|
258
|
+
lib_py_gel.median_edge_length.argtypes = (ct.c_void_p,)
|
|
259
|
+
lib_py_gel.median_edge_length.restype = ct.c_float
|
|
260
|
+
lib_py_gel.refine_edges.argtypes = (ct.c_void_p,ct.c_float)
|
|
261
|
+
lib_py_gel.refine_edges.restype = ct.c_int
|
|
262
|
+
lib_py_gel.cc_split.argtypes = (ct.c_void_p,)
|
|
263
|
+
lib_py_gel.loop_split.argtypes = (ct.c_void_p,)
|
|
264
|
+
lib_py_gel.root3_subdivide.argtypes = (ct.c_void_p,)
|
|
265
|
+
lib_py_gel.rootCC_subdivide.argtypes = (ct.c_void_p,)
|
|
266
|
+
lib_py_gel.butterfly_subdivide.argtypes = (ct.c_void_p,)
|
|
267
|
+
lib_py_gel.cc_smooth.argtypes = (ct.c_void_p,)
|
|
268
|
+
lib_py_gel.volume_preserving_cc_smooth.argtypes = (ct.c_void_p,ct.c_int)
|
|
269
|
+
lib_py_gel.regularize_quads.argtypes = (ct.c_void_p,ct.c_float,ct.c_float,ct.c_int)
|
|
270
|
+
lib_py_gel.loop_smooth.argtypes = (ct.c_void_p,)
|
|
271
|
+
lib_py_gel.ear_clip_triangulate.argtypes = (ct.c_void_p,)
|
|
272
|
+
lib_py_gel.shortest_edge_triangulate.argtypes = (ct.c_void_p,)
|
|
273
|
+
lib_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)
|
|
274
|
+
lib_py_gel.graph_to_feq.restype = ct.c_void_p
|
|
275
|
+
lib_py_gel.non_rigid_registration.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
276
|
+
lib_py_gel.taubin_smooth.argtypes = (ct.c_void_p, ct.c_int)
|
|
277
|
+
lib_py_gel.laplacian_smooth.argtypes = (ct.c_void_p, ct.c_float, ct.c_int)
|
|
278
|
+
lib_py_gel.anisotropic_smooth.argtypes = (ct.c_void_p, ct.c_float, ct.c_int)
|
|
279
|
+
lib_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 )
|
|
280
|
+
lib_py_gel.extrude_faces.argtypes = (ct.c_void_p, ndpointer(dtype=ct.c_int, ndim=1), ct.c_int, ct.c_void_p)
|
|
281
|
+
lib_py_gel.kill_face_loop.argtypes = (ct.c_void_p,)
|
|
282
|
+
lib_py_gel.kill_degenerate_face_loops.argtypes = (ct.c_void_p,ct.c_double)
|
|
283
|
+
lib_py_gel.stable_marriage_registration.argtypes = (ct.c_void_p,ct.c_void_p)
|
|
284
|
+
lib_py_gel.stable_marriage_registration.restype = ct.c_int
|
|
285
|
+
lib_py_gel.connected_components.argtypes = (ct.c_void_p,)
|
|
286
|
+
lib_py_gel.connected_components.restype = ct.c_void_p
|
|
287
|
+
lib_py_gel.mesh_vec_size.argtypes = (ct.c_void_p,)
|
|
288
|
+
lib_py_gel.mesh_vec_size.restype = ct.c_size_t
|
|
289
|
+
lib_py_gel.mesh_vec_get.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
290
|
+
lib_py_gel.mesh_vec_get.restype = ct.c_void_p
|
|
291
|
+
lib_py_gel.mesh_vec_del.argtypes = (ct.c_void_p,)
|
|
292
|
+
lib_py_gel.count_boundary_curves.argtypes = (ct.c_void_p,)
|
|
293
|
+
lib_py_gel.count_boundary_curves.restype = ct.c_int
|
|
294
|
+
lib_py_gel.sphere_delaunay.argtypes = (ct.c_void_p, ndpointer(dtype=ct.c_double, flags='C'), ct.c_int)
|
|
295
|
+
lib_py_gel.sphere_delaunay.restype = ct.c_void_p
|
|
296
|
+
|
|
297
|
+
# MeshDistance allows us to compute the signed distance to a mesh
|
|
298
|
+
lib_py_gel.MeshDistance_new.restype = ct.c_void_p
|
|
299
|
+
lib_py_gel.MeshDistance_new.argtypes = (ct.c_void_p,)
|
|
300
|
+
lib_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)
|
|
301
|
+
lib_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)
|
|
302
|
+
lib_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))
|
|
303
|
+
lib_py_gel.MeshDistance_ray_intersect.restype = ct.c_bool
|
|
304
|
+
lib_py_gel.MeshDistance_delete.argtypes = (ct.c_void_p,)
|
|
305
|
+
|
|
306
|
+
# The Graph class
|
|
307
|
+
lib_py_gel.Graph_new.restype = ct.c_void_p
|
|
308
|
+
lib_py_gel.Graph_copy.restype = ct.c_void_p
|
|
309
|
+
lib_py_gel.Graph_copy.argtypes = (ct.c_void_p,)
|
|
310
|
+
lib_py_gel.Graph_delete.argtypes = (ct.c_void_p,)
|
|
311
|
+
lib_py_gel.Graph_clear.argtypes = (ct.c_void_p,)
|
|
312
|
+
lib_py_gel.Graph_cleanup.argtypes = (ct.c_void_p,)
|
|
313
|
+
lib_py_gel.Graph_nodes.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
314
|
+
lib_py_gel.Graph_nodes.restype = ct.c_size_t
|
|
315
|
+
lib_py_gel.Graph_neighbors.restype = ct.c_size_t
|
|
316
|
+
lib_py_gel.Graph_neighbors.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_void_p, ct.c_char)
|
|
317
|
+
lib_py_gel.Graph_positions.argtypes = (ct.c_void_p,ct.POINTER(ct.POINTER(ct.c_double)))
|
|
318
|
+
lib_py_gel.Graph_positions.restype = ct.c_size_t
|
|
319
|
+
lib_py_gel.Graph_average_edge_length.argtypes = (ct.c_void_p,)
|
|
320
|
+
lib_py_gel.Graph_average_edge_length.restype = ct.c_double
|
|
321
|
+
lib_py_gel.Graph_add_node.argtypes = (ct.c_void_p, ndpointer(ct.c_double))
|
|
322
|
+
lib_py_gel.Graph_add_node.restype = ct.c_size_t
|
|
323
|
+
lib_py_gel.Graph_remove_node.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
324
|
+
lib_py_gel.Graph_node_in_use.argtypes = (ct.c_void_p, ct.c_size_t)
|
|
325
|
+
lib_py_gel.Graph_node_in_use.restype = ct.c_bool
|
|
326
|
+
lib_py_gel.Graph_connect_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
|
|
327
|
+
lib_py_gel.Graph_connect_nodes.restype = ct.c_size_t
|
|
328
|
+
lib_py_gel.Graph_disconnect_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t)
|
|
329
|
+
lib_py_gel.Graph_merge_nodes.argtypes = (ct.c_void_p, ct.c_size_t, ct.c_size_t, ct.c_bool)
|
|
330
|
+
|
|
331
|
+
# Graph functions
|
|
332
|
+
lib_py_gel.graph_from_mesh.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
333
|
+
lib_py_gel.graph_load.argtypes = (ct.c_void_p, ct.c_char_p)
|
|
334
|
+
lib_py_gel.graph_load.restype = ct.c_void_p
|
|
335
|
+
lib_py_gel.graph_save.argtypes = (ct.c_void_p, ct.c_char_p)
|
|
336
|
+
lib_py_gel.graph_save.restype = ct.c_bool
|
|
337
|
+
lib_py_gel.graph_to_mesh_cyl.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_float)
|
|
338
|
+
lib_py_gel.graph_to_mesh_cyl.restype = ct.c_void_p
|
|
339
|
+
lib_py_gel.graph_to_mesh_iso.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_float, ct.c_int)
|
|
340
|
+
lib_py_gel.graph_to_mesh_iso.restype = ct.c_void_p
|
|
341
|
+
lib_py_gel.graph_smooth.argtypes = (ct.c_void_p, ct.c_int, ct.c_float)
|
|
342
|
+
lib_py_gel.graph_edge_contract.argtypes = (ct.c_void_p, ct.c_double)
|
|
343
|
+
lib_py_gel.graph_prune.argtypes = (ct.c_void_p,)
|
|
344
|
+
lib_py_gel.graph_saturate.argtypes = (ct.c_void_p, ct.c_int, ct.c_double, ct.c_double)
|
|
345
|
+
lib_py_gel.graph_LS_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_bool)
|
|
346
|
+
lib_py_gel.graph_MSLS_skeleton.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int)
|
|
347
|
+
lib_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)
|
|
348
|
+
lib_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)
|
|
349
|
+
lib_py_gel.graph_minimum_spanning_tree.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_int)
|
|
350
|
+
lib_py_gel.graph_close_chordless_cycles.argtypes = (ct.c_void_p, ct.c_int, ct.c_int, ct.c_double)
|
|
351
|
+
|
|
352
|
+
class IntVector:
|
|
353
|
+
""" Vector of integer values.
|
|
354
|
+
This is a simple class that implements iteration and index based
|
|
355
|
+
retrieval. Allocation happens in a call to libPyGEL. Since memory
|
|
356
|
+
is managed by the PyGEL library, the vector can be resized by library
|
|
357
|
+
functions. Not used directly by PyGEL3D users."""
|
|
358
|
+
def __init__(self):
|
|
359
|
+
self.obj = lib_py_gel.IntVector_new(0)
|
|
360
|
+
def __del__(self):
|
|
361
|
+
lib_py_gel.IntVector_delete(self.obj)
|
|
362
|
+
def __len__(self):
|
|
363
|
+
return int(lib_py_gel.IntVector_size(self.obj))
|
|
364
|
+
def __getitem__(self, key: int):
|
|
365
|
+
return lib_py_gel.IntVector_get(self.obj,key)
|
|
366
|
+
def __iter__(self):
|
|
367
|
+
n = lib_py_gel.IntVector_size(self.obj)
|
|
368
|
+
for i in range(0,n):
|
|
369
|
+
yield lib_py_gel.IntVector_get(self.obj, i)
|
|
370
|
+
|
|
371
|
+
class Vec3dVector:
|
|
372
|
+
""" Vector of 3D vectors.
|
|
373
|
+
This is a simple class that implements iteration and index based
|
|
374
|
+
retrieval. Allocation happens in a call to libPyGEL. Since memory
|
|
375
|
+
is managed by the PyGEL library, the vector can be resized by library
|
|
376
|
+
functions. Not used directly by PyGEL3D users."""
|
|
377
|
+
def __init__(self):
|
|
378
|
+
self.obj = lib_py_gel.Vec3dVector_new(0)
|
|
379
|
+
def __del__(self):
|
|
380
|
+
lib_py_gel.Vec3dVector_delete(self.obj)
|
|
381
|
+
def __len__(self):
|
|
382
|
+
return int(lib_py_gel.Vec3dVector_size(self.obj))
|
|
383
|
+
def __getitem__(self,key: int):
|
|
384
|
+
return lib_py_gel.Vec3dVector_get(self.obj,key)
|
|
385
|
+
def __iter__(self):
|
|
386
|
+
n = lib_py_gel.Vec3dVector_size(self.obj)
|
|
387
|
+
for i in range(0,n):
|
|
388
|
+
data = lib_py_gel.Vec3dVector_get(self.obj, i)
|
|
389
|
+
yield [data[0], data[1], data[2]]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__all__ = ["hmesh"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import ctypes as ct
|
|
3
|
+
from numpy.typing import ArrayLike
|
|
4
|
+
from pygel3d.hmesh import Manifold, _as_vec3_f
|
|
5
|
+
from pygel3d import lib_py_gel
|
|
6
|
+
|
|
7
|
+
def rsr_recon(verts: ArrayLike,
|
|
8
|
+
normals: ArrayLike=None,
|
|
9
|
+
use_Euclidean_distance: bool=False,
|
|
10
|
+
genus: int=-1,
|
|
11
|
+
k: int=70,
|
|
12
|
+
r: float=20,
|
|
13
|
+
theta: float=60,
|
|
14
|
+
n: int=50) -> Manifold:
|
|
15
|
+
""" RsR Reconstruction. The first argument, verts, is the point cloud. The next argument,
|
|
16
|
+
normals, are the normals associated with the vertices or empty list (default) if normals
|
|
17
|
+
need to be estimated during reconstruction. use_Euclidean_distance should be true if we
|
|
18
|
+
can use the Euclidean rather than projected distance. Set to true only for noise free
|
|
19
|
+
point clouds. genus is used to constrain the genus of the reconstructed object. genus
|
|
20
|
+
defaults to -1, meaning unknown genus. k is the number of nearest neighbors for each point,
|
|
21
|
+
r is the maximum distance to farthest neighbor measured in multiples of average distance,
|
|
22
|
+
theta is the threshold on angles between normals: two points are only connected if the angle
|
|
23
|
+
between their normals is less than theta. Finally, n is the threshold on the distance between
|
|
24
|
+
vertices that are connected by handle edges (check paper). For large n, it is harder for
|
|
25
|
+
the algorithm to add handles. """
|
|
26
|
+
m = Manifold()
|
|
27
|
+
verts_data, n_verts = _as_vec3_f(verts)
|
|
28
|
+
normal_data, n_normal = _as_vec3_f(normals)
|
|
29
|
+
|
|
30
|
+
lib_py_gel.rsr_recon_experimental(m.obj, verts_data, normal_data, n_verts, n_normal,
|
|
31
|
+
use_Euclidean_distance, genus, k, r, theta, n)
|
|
32
|
+
return m
|
pygel3d/gl_display.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
""" This modules provides an OpenGL based viewer for graphs and meshes """
|
|
2
|
+
|
|
3
|
+
from numpy.typing import ArrayLike
|
|
4
|
+
from typing import Self
|
|
5
|
+
from pygel3d import lib_py_gel
|
|
6
|
+
from pygel3d.hmesh import Manifold
|
|
7
|
+
from pygel3d.graph import Graph
|
|
8
|
+
import ctypes as ct
|
|
9
|
+
import numpy as np
|
|
10
|
+
from os import getcwd, chdir
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
lib_py_gel.GLManifoldViewer_new.restype = ct.c_void_p
|
|
14
|
+
lib_py_gel.GLManifoldViewer_clone_controller.argtypes = (ct.c_void_p, ct.c_void_p)
|
|
15
|
+
lib_py_gel.GLManifoldViewer_clone_controller.restype = None
|
|
16
|
+
lib_py_gel.GLManifoldViewer_delete.argtypes = (ct.c_void_p,)
|
|
17
|
+
lib_py_gel.GLManifoldViewer_display.argtypes = (ct.c_void_p,ct.c_void_p,ct.c_void_p,ct.c_char,ct.c_bool, ct.POINTER(ct.c_float*3), ct.POINTER(ct.c_double),ct.c_bool,ct.c_bool)
|
|
18
|
+
lib_py_gel.GLManifoldViewer_get_annotation_points.restype = ct.c_size_t
|
|
19
|
+
lib_py_gel.GLManifoldViewer_get_annotation_points.argtypes = (ct.c_void_p, ct.POINTER(ct.POINTER(ct.c_double)))
|
|
20
|
+
lib_py_gel.GLManifoldViewer_set_annotation_points.argtypes = (ct.c_void_p, ct.c_int, ct.POINTER(ct.c_double))
|
|
21
|
+
lib_py_gel.GLManifoldViewer_event_loop.argtypes = (ct.c_bool,)
|
|
22
|
+
class Viewer:
|
|
23
|
+
""" An OpenGL Viewer for Manifolds and Graphs. Having created an instance of this
|
|
24
|
+
class, call display to show a mesh or a graph. The display function is flexible,
|
|
25
|
+
allowing several types of interactive visualization. Each instance of this
|
|
26
|
+
class corresponds to a single window, but you can have several
|
|
27
|
+
GLManifoldViewer and hence also several windows showing different
|
|
28
|
+
visualizations. """
|
|
29
|
+
def __init__(self):
|
|
30
|
+
current_directory = getcwd()
|
|
31
|
+
self.obj = lib_py_gel.GLManifoldViewer_new()
|
|
32
|
+
chdir(current_directory) # Necessary because init_glfw changes cwd
|
|
33
|
+
def __del__(self):
|
|
34
|
+
lib_py_gel.GLManifoldViewer_delete(self.obj)
|
|
35
|
+
def clone_controller(self, other: Self):
|
|
36
|
+
""" Clone the controller from another GLManifoldViewer. This is useful if you
|
|
37
|
+
want to display a mesh in a different window but keep the same view controller.
|
|
38
|
+
"""
|
|
39
|
+
if isinstance(other, Viewer):
|
|
40
|
+
lib_py_gel.GLManifoldViewer_clone_controller(self.obj, other.obj)
|
|
41
|
+
else:
|
|
42
|
+
raise TypeError("Argument must be an instance of Viewer")
|
|
43
|
+
def display(self,
|
|
44
|
+
m: Manifold,
|
|
45
|
+
g: Graph=None,
|
|
46
|
+
mode: str='w',
|
|
47
|
+
smooth: bool=True,
|
|
48
|
+
bg_col: tuple[float, float, float]=(0.3,0.3,0.3),
|
|
49
|
+
data: ArrayLike|None=None,
|
|
50
|
+
reset_view: bool=False,
|
|
51
|
+
once: bool=False):
|
|
52
|
+
""" Display a mesh
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
---
|
|
56
|
+
- m : the Manifold mesh or Graph we want to show.
|
|
57
|
+
- g : the Graph we want to show. If you only want to show a graph, you
|
|
58
|
+
can simply pass the graph as m, so the g argument is relevant only if
|
|
59
|
+
you need to show both a Manifold _and_ a Graph.
|
|
60
|
+
- mode : a single character that determines how the mesh is visualized:
|
|
61
|
+
'w' - wireframe,
|
|
62
|
+
'i' - isophote,
|
|
63
|
+
'g' - glazed (try it and see),
|
|
64
|
+
's' - scalar field,
|
|
65
|
+
'l' - line field,
|
|
66
|
+
'n' - normal.
|
|
67
|
+
'x' - xray or ghost rendering. Useful to show Manifold on top of Graph
|
|
68
|
+
- smooth : if True we use vertex normals. Otherwise, face normals.
|
|
69
|
+
- bg_col : background color.
|
|
70
|
+
- data : per vertex data for visualization. scalar or vector field.
|
|
71
|
+
- reset_view : if False view is as left in the previous display call. If
|
|
72
|
+
True, the view is reset to the default.
|
|
73
|
+
- once : if True we immediately exit the event loop and return. However,
|
|
74
|
+
the window stays and if the event loop is called from this or any
|
|
75
|
+
other viewer, the window will still be responsive.
|
|
76
|
+
|
|
77
|
+
Interactive controls:
|
|
78
|
+
---
|
|
79
|
+
When a viewer window is displayed on the screen, you can naviagate with
|
|
80
|
+
the mouse: Left mouse button rotates, right mouse button is used for
|
|
81
|
+
zooming and (if shift is pressed) for panning. If you hold control, any
|
|
82
|
+
mouse button will pick a point on the 3D model. Up to 19 of these points
|
|
83
|
+
have unique colors. If you pick an already placed annotation point it
|
|
84
|
+
will be removed and can now be placed elsewhere. Hit space bar to clear
|
|
85
|
+
the annotation points. Hitting ESC exits the event loop causing control
|
|
86
|
+
to return to the script.
|
|
87
|
+
"""
|
|
88
|
+
data_ct = np.array(data,dtype=ct.c_double).ctypes
|
|
89
|
+
data_a = data_ct.data_as(ct.POINTER(ct.c_double))
|
|
90
|
+
bg_col_ct = np.array(bg_col,dtype=ct.c_float).ctypes
|
|
91
|
+
bg_col_a = bg_col_ct.data_as(ct.POINTER(ct.c_float*3))
|
|
92
|
+
if isinstance(m, Graph):
|
|
93
|
+
g = m
|
|
94
|
+
m = None
|
|
95
|
+
if isinstance(m,Manifold) and isinstance(g, Graph):
|
|
96
|
+
lib_py_gel.GLManifoldViewer_display(self.obj, m.obj, g.obj, ct.c_char(mode.encode('ascii')),smooth,bg_col_a,data_a,reset_view,once)
|
|
97
|
+
elif isinstance(m,Manifold):
|
|
98
|
+
lib_py_gel.GLManifoldViewer_display(self.obj, m.obj, 0, ct.c_char(mode.encode('ascii')),smooth,bg_col_a,data_a,reset_view,once)
|
|
99
|
+
elif isinstance(g,Graph):
|
|
100
|
+
lib_py_gel.GLManifoldViewer_display(self.obj, 0, g.obj, ct.c_char(mode.encode('ascii')),smooth,bg_col_a,data_a,reset_view,once)
|
|
101
|
+
|
|
102
|
+
def annotation_points(self) -> ArrayLike:
|
|
103
|
+
""" Retrieve a vector of annotation points. This vector is not a copy,
|
|
104
|
+
so any changes made to the points will be reflected in the viewer. """
|
|
105
|
+
pos = ct.POINTER(ct.c_double)()
|
|
106
|
+
n = lib_py_gel.GLManifoldViewer_get_annotation_points(self.obj, ct.byref(pos))
|
|
107
|
+
if n == 0:
|
|
108
|
+
return None
|
|
109
|
+
return np.ctypeslib.as_array(pos,(n,3))
|
|
110
|
+
def set_annotation_points(self, pts: ArrayLike):
|
|
111
|
+
""" Set the annotation points to the given list of points. The points
|
|
112
|
+
should be given as a flat list or array of size 3n where n is the
|
|
113
|
+
number of points. """
|
|
114
|
+
pts_ct = np.array(pts,dtype=ct.c_double).ctypes
|
|
115
|
+
if pts_ct.size % 3 != 0:
|
|
116
|
+
raise ValueError("Annotation points must be given as a flat array of size 3n")
|
|
117
|
+
n = int(pts_ct.size // 3)
|
|
118
|
+
pts_a = pts_ct.data_as(ct.POINTER(ct.c_double))
|
|
119
|
+
lib_py_gel.GLManifoldViewer_set_annotation_points(self.obj, n, pts_a)
|
|
120
|
+
@staticmethod
|
|
121
|
+
def event_loop():
|
|
122
|
+
""" Explicit call to the event loop. This function enters the event loop.
|
|
123
|
+
Call it if you want to turn on interactivity in the currently displayed
|
|
124
|
+
window."""
|
|
125
|
+
lib_py_gel.GLManifoldViewer_event_loop(False)
|
|
126
|
+
except AttributeError:
|
|
127
|
+
pass
|