feifeifeiliu commited on
Commit
b80cc22
·
1 Parent(s): 44dc438

Delete mesh-master

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. mesh-master/.gitignore +0 -12
  2. mesh-master/CGAL_LICENSE.pdf +0 -0
  3. mesh-master/LICENSE.txt +0 -30
  4. mesh-master/MANIFEST.in +0 -2
  5. mesh-master/Makefile +0 -48
  6. mesh-master/README.md +0 -156
  7. mesh-master/bin/meshviewer +0 -379
  8. mesh-master/data/unittest/cylinder.obj +0 -38
  9. mesh-master/data/unittest/cylinder_trans.obj +0 -38
  10. mesh-master/data/unittest/self_intersecting_cyl.obj +0 -46
  11. mesh-master/data/unittest/sphere.obj +0 -1278
  12. mesh-master/data/unittest/sphere.ply +0 -1271
  13. mesh-master/data/unittest/test_box.obj +0 -50
  14. mesh-master/data/unittest/test_box.ply +0 -29
  15. mesh-master/data/unittest/test_box.pp +0 -11
  16. mesh-master/data/unittest/test_box_le.ply +0 -0
  17. mesh-master/data/unittest/test_doublebox.obj +0 -64
  18. mesh-master/doc/Makefile +0 -177
  19. mesh-master/doc/make.bat +0 -242
  20. mesh-master/doc/source/conf.py +0 -356
  21. mesh-master/doc/source/index.rst +0 -193
  22. mesh-master/doc/source/pages/geometry.rst +0 -29
  23. mesh-master/doc/source/pages/mesh.rst +0 -31
  24. mesh-master/doc/source/pages/mesh_viewer.rst +0 -11
  25. mesh-master/mesh/CMakeLists.txt +0 -99
  26. mesh-master/mesh/__init__.py +0 -20
  27. mesh-master/mesh/arcball.py +0 -247
  28. mesh-master/mesh/cmake/python_helper.cmake +0 -74
  29. mesh-master/mesh/cmake/thirdparty.cmake +0 -107
  30. mesh-master/mesh/colors.py +0 -790
  31. mesh-master/mesh/errors.py +0 -15
  32. mesh-master/mesh/fonts.py +0 -87
  33. mesh-master/mesh/geometry/__init__.py +0 -4
  34. mesh-master/mesh/geometry/barycentric_coordinates_of_projection.py +0 -49
  35. mesh-master/mesh/geometry/cross_product.py +0 -37
  36. mesh-master/mesh/geometry/rodrigues.py +0 -125
  37. mesh-master/mesh/geometry/tri_normals.py +0 -72
  38. mesh-master/mesh/geometry/triangle_area.py +0 -12
  39. mesh-master/mesh/geometry/vert_normals.py +0 -34
  40. mesh-master/mesh/landmarks.py +0 -102
  41. mesh-master/mesh/lines.py +0 -61
  42. mesh-master/mesh/mesh.py +0 -492
  43. mesh-master/mesh/meshviewer.py +0 -1274
  44. mesh-master/mesh/processing.py +0 -186
  45. mesh-master/mesh/ressources/Arial.ttf +0 -0
  46. mesh-master/mesh/search.py +0 -100
  47. mesh-master/mesh/serialization/__init__.py +0 -4
  48. mesh-master/mesh/serialization/serialization.py +0 -443
  49. mesh-master/mesh/sphere.py +0 -74
  50. mesh-master/mesh/src/AABB_n_tree.h +0 -355
mesh-master/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- build/*
2
- _build
3
- *.pyc
4
- temporary_test
5
- dist
6
- MANIFEST
7
- *.xml
8
- *.egg-info
9
- doc/build
10
- .eggs
11
- .idea
12
- .noseids
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/CGAL_LICENSE.pdf DELETED
Binary file (78.7 kB)
 
mesh-master/LICENSE.txt DELETED
@@ -1,30 +0,0 @@
1
-
2
- Max-Planck grants you a non-exclusive, non-transferable, free of charge right to
3
- use the *psbody-mesh package* on computers owned, leased or otherwise controlled
4
- by you and/or your organization for the sole purpose of performing non-commercial
5
- scientific research.
6
-
7
- Any other use, in particular any use for commercial purposes, is prohibited.
8
- This includes, without limitation, incorporation in a commercial product, use in
9
- a commercial service, or production of other artifacts for commercial purposes
10
- including, for example, web services, movies, television programs, or video
11
- games. The Model may not be reproduced, modified and/or made available in any
12
- form to any third party without MPG’s prior written permission. By using the
13
- Model, you agree not to reverse engineer it.
14
-
15
- You expressly acknowledge and agree that the Model is provided “AS IS”, may
16
- contain errors, and that any use of the Model is at your sole risk. MAX PLANCK
17
- MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE DATA, NEITHER
18
- EXPRESS NOR IMPLIED, AND THE ABSENCE OF ANY LEGAL OR ACTUAL DEFECTS, WHETHER
19
- DISCOVERABLE OR NOT. Specifically, and not to limit the foregoing, Max-Planck
20
- makes no representations or warranties (i) regarding the merchantability or
21
- fitness for a particular purpose of the Model, (ii) that the use of the Model
22
- will not infringe any patents, copyrights or other intellectual property rights
23
- of a third party, and (iii) that the use of the Model will not cause any damage
24
- of any kind to you or a third party.
25
-
26
- Under no circumstances shall Max-Planck be liable for any incidental, special,
27
- indirect or consequential damages arising out of or relating to this license,
28
- including but not limited to, any lost profits, business interruption, loss of
29
- programs or other data, or all other commercial damages or losses, even if
30
- advised of the possibility thereof.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/MANIFEST.in DELETED
@@ -1,2 +0,0 @@
1
- recursive-include mesh/src *
2
- recursive-include mesh/ressources *
 
 
 
mesh-master/Makefile DELETED
@@ -1,48 +0,0 @@
1
- # Makefile for mesh package
2
- package_name := mesh_package
3
-
4
- all:
5
- @echo "\033[0;36m----- [" ${package_name} "] Installing with the interpreter `which python` (version `python --version | cut -d' ' -f2`)\033[0m"
6
- @pip install --upgrade -r requirements.txt && pip list
7
- @pip install --no-deps --install-option="--boost-location=$$BOOST_INCLUDE_DIRS" --verbose --no-cache-dir .
8
-
9
- import_tests:
10
- @echo "\033[0;33m----- [" ${package_name} "] Performing import tests\033[0m"
11
- @PSBODY_MESH_CACHE=`mktemp -d -t mesh_package.XXXXXXXXXX` python -c "from psbody.mesh.mesh import Mesh"
12
- @python -c "from psbody.mesh.meshviewer import MeshViewers"
13
- @echo "\033[0;33m----- [" ${package_name} "] OK import tests\033[0m"
14
-
15
- unit_tests:
16
- @if test "$(USE_NOSE)" = "" ; then \
17
- echo "\033[0;33m----- [" ${package_name} "] Running tests using unittest, no report file\033[0m" ; \
18
- PSBODY_MESH_CACHE=`mktemp -d -t mesh_package.XXXXXXXXXX` python -m unittest -v ; \
19
- else \
20
- echo "\033[0;33m----- [" ${package_name} "] Running tests using nosetests\033[0m" ; \
21
- pip install nose ; \
22
- PSBODY_MESH_CACHE=`mktemp -d -t mesh_package.XXXXXXXXXX` nosetests -v --with-xunit; \
23
- fi ;
24
-
25
- tests: import_tests unit_tests
26
-
27
- # Creating source distribution
28
- sdist:
29
- @echo "\033[0;33m----- [" ${package_name} "] Creating the source distribution\033[0m"
30
- @python setup.py sdist
31
-
32
- # Creating wheel distribution
33
- wheel:
34
- @echo "\033[0;33m----- [" ${package_name} "] Creating the wheel distribution\033[0m"
35
- @pip install wheel
36
- @python setup.py --verbose build_ext --boost-location=$$BOOST_INCLUDE_DIRS bdist_wheel
37
-
38
- # Build documentation
39
- documentation:
40
- @echo "\033[0;33m----- [" ${package_name} "] Building Sphinx documentation\033[0m"
41
- @pip install -U sphinx sphinx_bootstrap_theme
42
- @cd doc && make html
43
-
44
- clean:
45
- @rm -rf build
46
- @rm -rf dist
47
- @rm -rf psbody_mesh.egg-info
48
- @rm -rf *.xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/README.md DELETED
@@ -1,156 +0,0 @@
1
- [![Build Status](
2
- https://raw.githubusercontent.com/MPI-IS-BambooAgent/sw_badges/master/badges/plans/ps-body-mesh/tag.svg?sanitize=true)](
3
- https://atlas.is.localnet/bamboo/browse/PS-FMP/latest)
4
-
5
- Perceiving Systems Mesh Package
6
- ===============================
7
-
8
- This package contains core functions for manipulating meshes and
9
- visualizing them. It requires ``Python 3.5+`` and is supported on
10
- Linux and macOS operating systems.
11
-
12
- The ``Mesh`` processing libraries support several of our projects such as
13
- * [CoMA: Convolutional Mesh Encoders for Generating 3D Faces](http://coma.is.tue.mpg.de/)
14
- * [FLAME: Learning a model of facial shape and expression from 4D scans](http://flame.is.tue.mpg.de/)
15
- * [MANO: Modeling and Capturing Hands and Bodies Together](http://mano.is.tue.mpg.de/)
16
- * [SMPL: A Skinned Multi-Person Linear Model](http://smpl.is.tue.mpg.de/)
17
- * [VOCA: Voice Operated Character Animation](https://github.com/TimoBolkart/voca)
18
- * [RingNet: 3D Face Shape and Expression Reconstruction from an Image](https://github.com/soubhiksanyal/RingNet)
19
- * [Expressive Body Capture: 3D Hands, Face, and Body from a Single Image](https://smpl-x.is.tue.mpg.de/)
20
-
21
- Requirements
22
- ------------
23
-
24
- You first need to install the `Boost <http://www.boost.org>`_
25
- libraries. You can compile your own local version or simply do on
26
- Linux
27
-
28
- ```
29
- $ sudo apt-get install libboost-dev
30
- ```
31
-
32
- or on macOS
33
-
34
- ```
35
- $ brew install boost
36
- ```
37
-
38
- Installation
39
- ------------
40
-
41
- First, create a dedicated Python virtual environment and activate it:
42
-
43
- ```
44
- $ python3 -m venv --copies my_venv
45
- $ source my_venv/bin/activate
46
- ```
47
-
48
- You should then compile and install the ``psbody-mesh`` package easily
49
- using the Makefile:
50
-
51
- ```
52
- $ BOOST_INCLUDE_DIRS=/path/to/boost/include make all
53
- ```
54
-
55
- Testing
56
- -------
57
-
58
- To run the tests, simply do:
59
-
60
- ```
61
- $ make tests
62
- ```
63
-
64
- Documentation
65
- -------------
66
-
67
- A detailed documentation can be compiled using the Makefile:
68
-
69
- ```
70
- $ make documentation
71
- ```
72
-
73
- Viewing the Meshes
74
- ------------------
75
-
76
- Starting from version 0.4 meshviewer ships with `meshviewer` -- a
77
- program that allows you to display polygonal meshes produced by `mesh`
78
- package.
79
-
80
- ### Viewing a mesh on a local machine
81
-
82
- The most straightforward use-case is viewing the mesh on the same
83
- machine where it is stored. To do this simply run
84
-
85
- ```
86
- $ meshviewer view sphere.obj
87
- ```
88
-
89
- This will create an interactive window with your mesh rendering. You
90
- can render more than one mesh in the same window by passing several
91
- paths to `view` command
92
-
93
- ```
94
- $ meshviewer view sphere.obj cylinder.obj
95
- ```
96
-
97
- This will arrange the subplots horizontally in a row. If you want a
98
- grid arrangement, you can specify the grid parameters explicitly
99
-
100
- ```
101
- $ meshviewer view -nx 2 -ny 2 *.obj
102
- ```
103
-
104
- ### Viewing a mesh from a remote machine
105
-
106
- It is also possible to view a mesh stored on a remote machine. To do
107
- this you need mesh to be installed on both the local and the remote
108
- machines. You start by opening an empty viewer window listening on a
109
- network port
110
-
111
- ```
112
- (local) $ meshviewer open --port 3000
113
- ```
114
-
115
- To stream a shape to this viewer you have to either pick a port that
116
- is visible from the remote machine or by manually exposing the port
117
- when connecting. For example, through SSH port forwarding
118
-
119
- ```
120
- (local) $ ssh -R 3000:127.0.0.1:3000 user@host
121
- ```
122
-
123
- Then on a remote machine you use `view` command pointing to the
124
- locally forwarded port
125
-
126
- ```
127
- (remote) $ meshviewer view -p 3000 sphere.obj
128
- ```
129
-
130
- This should display the remote mesh on your local viewer. In case it
131
- does not it might be caused by the network connection being closed
132
- before the mesh could be sent. To work around this one can try
133
- increasing the timeout up to 1 second
134
-
135
- ```
136
- (remote) $ meshviewer view -p 3000 --timeout 1 sphere.obj
137
- ```
138
-
139
- To take a snapshot you should locally run a `snap` command
140
-
141
- ```
142
- (local) $ meshviewer snap -p 3000 sphere.png
143
- ```
144
-
145
- License
146
- -------
147
-
148
- Please refer for LICENSE.txt for using this software. The software is
149
- compiled using CGAL sources following the license in CGAL_LICENSE.pdf
150
-
151
- Acknowledgments
152
- ---------------
153
-
154
- We thank the external contribution from the following people:
155
- * [Kenneth Chaney](https://github.com/k-chaney) ([PR #5](https://github.com/MPI-IS/mesh/pull/5))
156
- * [Dávid Komorowicz](https://github.com/Dawars) ([PR #8](https://github.com/MPI-IS/mesh/pull/8))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/bin/meshviewer DELETED
@@ -1,379 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
-
4
- import textwrap
5
-
6
- __doc__ = textwrap.dedent(
7
- """
8
- `meshviewer` is a program that allows you to display polygonal
9
- meshes produced by `mesh` package.
10
-
11
- Viewing a mesh on a local machine
12
- ---------------------------------
13
-
14
- The most straightforward use-case is viewing the mesh on the same
15
- machine where it is stored. To do this simply run
16
-
17
- ```
18
- $ meshviewer view sphere.obj
19
- ```
20
-
21
- This will create an interactive window with your mesh rendering.
22
- You can render more than one mesh in the same window by passing
23
- several paths to `view` command
24
-
25
- ```
26
- $ meshviewer view sphere.obj cylinder.obj
27
- ```
28
-
29
- This will arrange the subplots horizontally in a row. If you want
30
- a grid arrangement, you can specify the grid parameters explicitly
31
-
32
- ```
33
- $ meshviewer view -nx 2 -ny 2 *.obj
34
- ```
35
-
36
- Viewing a mesh from a remote machine
37
- ------------------------------------
38
-
39
- It is also possible to view a mesh stored on a remote machine. To
40
- do this you need mesh to be installed on both the local and the
41
- remote machines. You start by opening an empty viewer window
42
- listening on a network port
43
-
44
- ```
45
- (local) $ meshviewer open --port 3000
46
- ```
47
-
48
- To stream a shape to this viewer you have to either pick a port
49
- that is visible from the remote machine or by manually exposing
50
- the port when connecting. For example, through SSH port
51
- forwarding
52
-
53
- ```
54
- (local) $ ssh -R 3000:127.0.0.1:3000 user@host
55
- ```
56
-
57
- Then on a remote machine you use `view` command pointing to the
58
- locally forwarded port
59
-
60
- ```
61
- (remote) $ meshviewer view -p 3000 sphere.obj
62
- ```
63
-
64
- This should display the remote mesh on your local viewer. In case it
65
- does not it might be caused by the network connection being closed
66
- before the mesh could be sent. To work around this one can try
67
- increasing the timeout up to 1 second
68
-
69
- ```
70
- (remote) $ meshviewer view -p 3000 --timeout 1 sphere.obj
71
- ```
72
-
73
- To take a snapshot you should locally run a `snap` command
74
-
75
- ```
76
- (local) $ meshviewer snap -p 3000 sphere.png
77
- ```
78
- """)
79
-
80
-
81
- import argparse
82
- import logging
83
- import sys
84
- import time
85
-
86
- from psbody.mesh.mesh import Mesh
87
- from psbody.mesh.meshviewer import (
88
- MESH_VIEWER_DEFAULT_TITLE,
89
- MESH_VIEWER_DEFAULT_SHAPE,
90
- MESH_VIEWER_DEFAULT_WIDTH,
91
- MESH_VIEWER_DEFAULT_HEIGHT,
92
- ZMQ_HOST,
93
- MeshViewerLocal,
94
- MeshViewerRemote)
95
-
96
-
97
- logging.basicConfig(level=logging.INFO)
98
-
99
-
100
- parser_root = argparse.ArgumentParser(
101
- add_help=False,
102
- description="View the polygonal meshes, locally and across the network",
103
- epilog=__doc__,
104
- formatter_class=argparse.RawTextHelpFormatter)
105
-
106
- subparsers = parser_root.add_subparsers(dest="command")
107
- subparsers.required = True
108
-
109
- parser_open = subparsers.add_parser("open", add_help=False)
110
- parser_open.add_argument(
111
- "-p", "--port",
112
- help="local port to listen for incoming commands",
113
- type=int)
114
-
115
- parser_view = subparsers.add_parser("view", add_help=False)
116
- parser_view.add_argument(
117
- "-h", "--host",
118
- help="remote host",
119
- metavar="HOSTNAME",
120
- type=str)
121
- parser_view.add_argument(
122
- "-p", "--port",
123
- help="remote port",
124
- type=int)
125
- parser_view.add_argument(
126
- "-ix", "--subwindow-index-horizontal",
127
- help="horizontal index of the target subwindow",
128
- metavar="INDEX",
129
- type=int)
130
- parser_view.add_argument(
131
- "-iy", "--subwindow-index-vertical",
132
- help="vertical index of the target subwindow",
133
- metavar="INDEX",
134
- type=int)
135
- parser_view.add_argument(
136
- "--timeout",
137
- help="wait for some time after sending the mesh to let it render",
138
- metavar="SECONDS",
139
- type=float,
140
- default=0.5)
141
- parser_view.add_argument(
142
- "filename",
143
- help="path to the mesh file",
144
- type=str,
145
- nargs="+")
146
-
147
- for parser in parser_open, parser_view:
148
- window_options = parser.add_argument_group("window options")
149
- window_options.add_argument(
150
- "-t", "--title",
151
- help="window title",
152
- type=str)
153
- window_options.add_argument(
154
- "-ww", "-wx", "--window-width",
155
- help="window width in pixels",
156
- metavar="PIXELS",
157
- type=int)
158
- window_options.add_argument(
159
- "-wh", "-wy", "--window-height",
160
- help="window height in pixels",
161
- metavar="PIXELS",
162
- type=int)
163
- window_options.add_argument(
164
- "-nx", "--subwindow-number-horizontal",
165
- help="number of horizontal subwindows",
166
- metavar="NUMBER",
167
- type=int)
168
- window_options.add_argument(
169
- "-ny", "--subwindow-number-vertical",
170
- help="number of vertical subwindows",
171
- metavar="NUMBER",
172
- type=int)
173
-
174
- parser_snap = subparsers.add_parser("snap", add_help=False)
175
- parser_snap.add_argument(
176
- "-h", "--host",
177
- help="remote host",
178
- type=str)
179
- parser_snap.add_argument(
180
- "-p", "--port",
181
- help="remote port",
182
- type=int,
183
- required=True)
184
- parser_snap.add_argument(
185
- "filename",
186
- help="path to the output snapshot",
187
- type=str)
188
-
189
-
190
- for p in parser_root, parser_open, parser_view, parser_snap:
191
- p.add_argument("--help", action="help")
192
-
193
-
194
- def dispatch_command(args):
195
- """
196
- Performs a sanity check of the passed arguments and then
197
- dispatches the appropriate command.
198
- """
199
-
200
- if args.command == "open":
201
- start_server(args)
202
- return
203
-
204
- if not args.port:
205
- client = start_local_client(args)
206
- else:
207
- client = start_remote_client(args)
208
-
209
- if args.command == "snap":
210
- take_snapshot(client, args)
211
-
212
- if args.command == "view":
213
- if args.port is not None:
214
- # Below is a list of contradicting settings: it futile to
215
- # try to change the parameters of a mesh viewer already
216
- # running on a remote machine.
217
- if args.title is not None:
218
- logging.warning(
219
- "--title is ignored when working with remote viewer")
220
-
221
- if args.window_width is not None:
222
- logging.warning(
223
- "--window-width is ignored when working with remote viewer")
224
-
225
- if args.window_height is not None:
226
- logging.warning(
227
- "--window-height is ignored when working with remote viewer")
228
-
229
- if args.subwindow_number_horizontal is not None:
230
- logging.warning(
231
- "--subwindow-number-horizontal is ignored when working "
232
- "with remote viewer")
233
-
234
- if args.subwindow_number_vertical is not None:
235
- logging.warning(
236
- "--subwindow-number-vertical is ignored when working "
237
- "with remote viewer")
238
-
239
- # This one is a bit different: while it should be
240
- # technically possible to stream the mesh in a specific
241
- # subwindow, we currently don't support that.
242
- if (
243
- args.subwindow_index_horizontal is not None or
244
- args.subwindow_index_vertical is not None
245
- ):
246
- logging.warning(
247
- "unfortunately, drawing to a specific subwindow is not "
248
- "supported when working with remote viewer and the first "
249
- "subwindow is going to be used instead")
250
-
251
- if (
252
- args.subwindow_index_horizontal is not None and
253
- args.subwindow_index_vertical is None
254
- ) or (
255
- args.subwindow_index_horizontal is None and
256
- args.subwindow_index_vertical is not None
257
- ):
258
- logging.fatal(
259
- "you have to specify both horizontal "
260
- "and vertical subwindow incides")
261
- return
262
-
263
- if (
264
- args.subwindow_index_horizontal is not None and
265
- args.subwindow_index_vertical is not None
266
- ):
267
- display_single_subwindow(client, args)
268
- else:
269
- display_multi_subwindows(client, args)
270
-
271
- # Basically, wait for send_pyobj() to actually send everything
272
- # before terminating.
273
- time.sleep(args.timeout)
274
-
275
-
276
- def start_server(args):
277
- """
278
- Starts a meshviewer window on a local machine.
279
-
280
- This function opens a mesh viewer window that listens for command
281
- on a given port.
282
- """
283
- server = MeshViewerRemote(
284
- titlebar=args.title or MESH_VIEWER_DEFAULT_TITLE,
285
- subwins_vert=args.subwindow_number_vertical or MESH_VIEWER_DEFAULT_SHAPE[1],
286
- subwins_horz=args.subwindow_number_horizontal or MESH_VIEWER_DEFAULT_SHAPE[0],
287
- width=args.window_width or MESH_VIEWER_DEFAULT_WIDTH,
288
- height=args.window_height or MESH_VIEWER_DEFAULT_HEIGHT,
289
- port=args.port)
290
- return server
291
-
292
-
293
- def start_local_client(args):
294
- """
295
- Starts a local meshviewer not connected to anywhere.
296
-
297
- This function internally opens a mesh viewer window listening on a
298
- random port.
299
- """
300
- client = MeshViewerLocal(
301
- titlebar=args.title or MESH_VIEWER_DEFAULT_TITLE,
302
- window_width=args.window_width or MESH_VIEWER_DEFAULT_WIDTH,
303
- window_height=args.window_height or MESH_VIEWER_DEFAULT_HEIGHT,
304
- shape=(
305
- args.subwindow_number_vertical or 1,
306
- args.subwindow_number_horizontal or len(args.filename),
307
- ),
308
- keepalive=True)
309
- return client
310
-
311
-
312
- def start_remote_client(args):
313
- """
314
- Starts a meshviewer client connected to a remote machine.
315
-
316
- This function does not create a new window, but is necessary to
317
- stream the mesh to a remote viewer.
318
- """
319
- client = MeshViewerLocal(
320
- host=args.host or ZMQ_HOST,
321
- port=args.port)
322
- return client
323
-
324
-
325
- def display_single_subwindow(client, args):
326
- """
327
- Displays a single mesh in a given subwindow.
328
- """
329
- ix = args.subwindow_index_horizontal
330
- iy = args.subwindow_index_vertical
331
-
332
- try:
333
- subwindow = client.get_subwindows()[iy][ix]
334
- except IndexError:
335
- logging.fatal(
336
- "cannot find subwindow ({}, {}). "
337
- "The current viewer shape is {}x{} subwindows, "
338
- "indexing is zero-based."
339
- .format(ix, iy, *client.shape))
340
- return
341
-
342
- meshes = [Mesh(filename=filename) for filename in args.filename]
343
- subwindow.set_static_meshes(meshes)
344
-
345
-
346
- def display_multi_subwindows(client, args):
347
- """
348
- Displays a list of meshes. One mesh per subwindow.
349
- """
350
- grid = client.get_subwindows()
351
-
352
- subwindows = [
353
- subwindow
354
- for row in grid
355
- for subwindow in row
356
- ]
357
-
358
- if len(subwindows) < len(args.filename):
359
- logging.warning(
360
- "cannot display {0} meshes in {1} subwindows. "
361
- "Taking the first {1}.".format(
362
- len(args.filename), len(subwindows)))
363
-
364
- for subwindow, filename in zip(subwindows, args.filename):
365
- mesh = Mesh(filename=filename)
366
- subwindow.set_static_meshes([mesh])
367
-
368
-
369
- def take_snapshot(client, args):
370
- """
371
- Take snapshot and dump it into a file.
372
- """
373
- client.save_snapshot(args.filename)
374
-
375
-
376
- if __name__ == "__main__":
377
- args = parser_root.parse_args()
378
- dispatch_command(args)
379
- sys.exit(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/cylinder.obj DELETED
@@ -1,38 +0,0 @@
1
- # Blender v2.61 (sub 0) OBJ File: ''
2
- # www.blender.org
3
- g Cylinder
4
- v 0.000000 -1.000000 -1.000000
5
- v 0.000000 -1.000000 1.000000
6
- v -0.382683 -1.000000 0.923880
7
- v -0.707107 -1.000000 0.707107
8
- v -0.923880 -1.000000 0.382684
9
- v -1.000000 -1.000000 -0.000000
10
- v -0.923879 -1.000000 -0.382684
11
- v -0.707107 -1.000000 -0.707107
12
- v -0.382683 -1.000000 -0.923880
13
- v 0.000001 1.000000 -1.000000
14
- v -0.000002 1.000000 1.000000
15
- v -0.382685 1.000000 0.923879
16
- v -0.707108 1.000000 0.707105
17
- v -0.923880 1.000000 0.382681
18
- v -1.000000 1.000000 -0.000003
19
- v -0.923878 1.000000 -0.382686
20
- v -0.707105 1.000000 -0.707109
21
- v -0.382681 1.000000 -0.923881
22
- s off
23
- f 10 1 18
24
- f 1 9 18
25
- f 8 17 9
26
- f 17 18 9
27
- f 7 16 8
28
- f 16 17 8
29
- f 6 15 7
30
- f 15 16 7
31
- f 5 14 6
32
- f 14 15 6
33
- f 4 13 5
34
- f 13 14 5
35
- f 3 12 4
36
- f 12 13 4
37
- f 2 11 3
38
- f 11 12 3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/cylinder_trans.obj DELETED
@@ -1,38 +0,0 @@
1
- # Blender v2.61 (sub 0) OBJ File: ''
2
- # www.blender.org
3
- g Cylinder
4
- v 1.057678 -1.000000 -1.000000
5
- v 1.057678 -1.000000 1.000000
6
- v 0.674994 -1.000000 0.923880
7
- v 0.350571 -1.000000 0.707107
8
- v 0.133798 -1.000000 0.382684
9
- v 0.057678 -1.000000 -0.000000
10
- v 0.133798 -1.000000 -0.382684
11
- v 0.350571 -1.000000 -0.707107
12
- v 0.674995 -1.000000 -0.923880
13
- v 1.057678 1.000000 -1.000000
14
- v 1.057676 1.000000 1.000000
15
- v 0.674992 1.000000 0.923879
16
- v 0.350569 1.000000 0.707105
17
- v 0.133797 1.000000 0.382681
18
- v 0.057678 1.000000 -0.000003
19
- v 0.133799 1.000000 -0.382686
20
- v 0.350573 1.000000 -0.707109
21
- v 0.674997 1.000000 -0.923881
22
- s off
23
- f 10 1 18
24
- f 1 9 18
25
- f 8 17 9
26
- f 17 18 9
27
- f 7 16 8
28
- f 16 17 8
29
- f 6 15 7
30
- f 15 16 7
31
- f 5 14 6
32
- f 14 15 6
33
- f 4 13 5
34
- f 13 14 5
35
- f 3 12 4
36
- f 12 13 4
37
- f 2 11 3
38
- f 11 12 3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/self_intersecting_cyl.obj DELETED
@@ -1,46 +0,0 @@
1
- # Blender v2.61 (sub 0) OBJ File: ''
2
- # www.blender.org
3
- g Plane
4
- v 0.000000 -0.500000 -1.000000
5
- v 0.707107 -0.500000 -0.707107
6
- v 1.000000 -0.500000 0.000000
7
- v 0.707107 -0.500000 0.707107
8
- v -0.000000 -0.500000 1.000000
9
- v -0.707107 -0.500000 0.707107
10
- v -1.000000 -0.500000 -0.000000
11
- v -0.707107 -0.500000 -0.707107
12
- v -0.000000 0.500000 -1.000000
13
- v 0.707106 0.500000 -0.707107
14
- v 1.000000 0.500000 -0.000001
15
- v 0.707107 0.500000 0.707107
16
- v -0.000000 0.500000 1.000000
17
- v -0.707107 0.500000 0.707107
18
- v -1.000000 0.500000 -0.000001
19
- v -0.707106 0.500000 -0.707107
20
- v 0.000000 -0.500000 0.000000
21
- v 0.000000 -0.835754 0.000000
22
- s off
23
- f 17 1 2
24
- f 18 10 9
25
- f 17 2 3
26
- f 18 11 10
27
- f 17 3 4
28
- f 18 12 11
29
- f 17 4 5
30
- f 18 13 12
31
- f 17 5 6
32
- f 18 14 13
33
- f 17 6 7
34
- f 18 15 14
35
- f 17 7 8
36
- f 18 16 15
37
- f 8 1 17
38
- f 18 9 16
39
- f 1 9 10 2
40
- f 2 10 11 3
41
- f 3 11 12 4
42
- f 4 12 13 5
43
- f 5 13 14 6
44
- f 6 14 15 7
45
- f 7 15 16 8
46
- f 9 1 8 16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/sphere.obj DELETED
@@ -1,1278 +0,0 @@
1
- ####
2
- #
3
- # OBJ File Generated by Meshlab
4
- #
5
- ####
6
- # Object sphere.obj
7
- #
8
- # Vertices: 422
9
- # Faces: 840
10
- #
11
- ####
12
- v 0.000000 0.000000 -127.000000
13
- v 5.000000 25.000000 -125.000000
14
- v 10.000000 24.000000 -125.000000
15
- v 15.000000 21.000000 -125.000000
16
- v 19.000000 17.000000 -125.000000
17
- v 22.000000 13.000000 -125.000000
18
- v 25.000000 8.000000 -125.000000
19
- v 26.000000 2.000000 -125.000000
20
- v 26.000000 -3.000000 -125.000000
21
- v 25.000000 -9.000000 -125.000000
22
- v 22.000000 -14.000000 -125.000000
23
- v 19.000000 -18.000000 -125.000000
24
- v 15.000000 -22.000000 -125.000000
25
- v 10.000000 -25.000000 -125.000000
26
- v 5.000000 -26.000000 -125.000000
27
- v 0.000000 -27.000000 -125.000000
28
- v -6.000000 -26.000000 -125.000000
29
- v -11.000000 -25.000000 -125.000000
30
- v -16.000000 -22.000000 -125.000000
31
- v -20.000000 -18.000000 -125.000000
32
- v -23.000000 -14.000000 -125.000000
33
- v -26.000000 -9.000000 -125.000000
34
- v -27.000000 -3.000000 -125.000000
35
- v -27.000000 2.000000 -125.000000
36
- v -26.000000 8.000000 -125.000000
37
- v -23.000000 13.000000 -125.000000
38
- v -20.000000 17.000000 -125.000000
39
- v -16.000000 21.000000 -125.000000
40
- v -11.000000 24.000000 -125.000000
41
- v -6.000000 25.000000 -125.000000
42
- v -1.000000 26.000000 -125.000000
43
- v 10.000000 50.000000 -117.000000
44
- v 21.000000 47.000000 -117.000000
45
- v 30.000000 41.000000 -117.000000
46
- v 38.000000 34.000000 -117.000000
47
- v 44.000000 25.000000 -117.000000
48
- v 49.000000 15.000000 -117.000000
49
- v 51.000000 5.000000 -117.000000
50
- v 51.000000 -6.000000 -117.000000
51
- v 49.000000 -16.000000 -117.000000
52
- v 44.000000 -26.000000 -117.000000
53
- v 38.000000 -35.000000 -117.000000
54
- v 30.000000 -42.000000 -117.000000
55
- v 21.000000 -48.000000 -117.000000
56
- v 10.000000 -51.000000 -117.000000
57
- v 0.000000 -52.000000 -117.000000
58
- v -11.000000 -51.000000 -117.000000
59
- v -22.000000 -48.000000 -117.000000
60
- v -31.000000 -42.000000 -117.000000
61
- v -39.000000 -35.000000 -117.000000
62
- v -45.000000 -26.000000 -117.000000
63
- v -50.000000 -16.000000 -117.000000
64
- v -52.000000 -6.000000 -117.000000
65
- v -52.000000 5.000000 -117.000000
66
- v -50.000000 15.000000 -117.000000
67
- v -45.000000 25.000000 -117.000000
68
- v -39.000000 34.000000 -117.000000
69
- v -31.000000 41.000000 -117.000000
70
- v -22.000000 47.000000 -117.000000
71
- v -11.000000 50.000000 -117.000000
72
- v -1.000000 51.000000 -117.000000
73
- v 15.000000 73.000000 -103.000000
74
- v 30.000000 68.000000 -103.000000
75
- v 43.000000 60.000000 -103.000000
76
- v 55.000000 49.000000 -103.000000
77
- v 64.000000 37.000000 -103.000000
78
- v 70.000000 23.000000 -103.000000
79
- v 74.000000 7.000000 -103.000000
80
- v 74.000000 -8.000000 -103.000000
81
- v 70.000000 -24.000000 -103.000000
82
- v 64.000000 -38.000000 -103.000000
83
- v 55.000000 -50.000000 -103.000000
84
- v 43.000000 -61.000000 -103.000000
85
- v 30.000000 -69.000000 -103.000000
86
- v 15.000000 -74.000000 -103.000000
87
- v 0.000000 -75.000000 -103.000000
88
- v -16.000000 -74.000000 -103.000000
89
- v -31.000000 -69.000000 -103.000000
90
- v -44.000000 -61.000000 -103.000000
91
- v -56.000000 -50.000000 -103.000000
92
- v -65.000000 -38.000000 -103.000000
93
- v -71.000000 -24.000000 -103.000000
94
- v -75.000000 -8.000000 -103.000000
95
- v -75.000000 7.000000 -103.000000
96
- v -71.000000 23.000000 -103.000000
97
- v -65.000000 37.000000 -103.000000
98
- v -56.000000 49.000000 -103.000000
99
- v -44.000000 60.000000 -103.000000
100
- v -31.000000 68.000000 -103.000000
101
- v -16.000000 73.000000 -103.000000
102
- v -1.000000 74.000000 -103.000000
103
- v 19.000000 92.000000 -85.000000
104
- v 38.000000 86.000000 -85.000000
105
- v 55.000000 76.000000 -85.000000
106
- v 70.000000 63.000000 -85.000000
107
- v 81.000000 47.000000 -85.000000
108
- v 89.000000 29.000000 -85.000000
109
- v 93.000000 9.000000 -85.000000
110
- v 93.000000 -10.000000 -85.000000
111
- v 89.000000 -30.000000 -85.000000
112
- v 81.000000 -48.000000 -85.000000
113
- v 70.000000 -64.000000 -85.000000
114
- v 55.000000 -77.000000 -85.000000
115
- v 38.000000 -87.000000 -85.000000
116
- v 19.000000 -93.000000 -85.000000
117
- v 0.000000 -95.000000 -85.000000
118
- v -20.000000 -93.000000 -85.000000
119
- v -39.000000 -87.000000 -85.000000
120
- v -56.000000 -77.000000 -85.000000
121
- v -71.000000 -64.000000 -85.000000
122
- v -82.000000 -48.000000 -85.000000
123
- v -90.000000 -30.000000 -85.000000
124
- v -94.000000 -10.000000 -85.000000
125
- v -94.000000 9.000000 -85.000000
126
- v -90.000000 29.000000 -85.000000
127
- v -82.000000 47.000000 -85.000000
128
- v -71.000000 63.000000 -85.000000
129
- v -56.000000 76.000000 -85.000000
130
- v -39.000000 86.000000 -85.000000
131
- v -20.000000 92.000000 -85.000000
132
- v -1.000000 94.000000 -85.000000
133
- v 22.000000 107.000000 -64.000000
134
- v 44.000000 100.000000 -64.000000
135
- v 64.000000 88.000000 -64.000000
136
- v 81.000000 73.000000 -64.000000
137
- v 95.000000 54.000000 -64.000000
138
- v 104.000000 33.000000 -64.000000
139
- v 109.000000 11.000000 -64.000000
140
- v 109.000000 -12.000000 -64.000000
141
- v 104.000000 -34.000000 -64.000000
142
- v 95.000000 -55.000000 -64.000000
143
- v 81.000000 -74.000000 -64.000000
144
- v 64.000000 -89.000000 -64.000000
145
- v 44.000000 -101.000000 -64.000000
146
- v 22.000000 -108.000000 -64.000000
147
- v 0.000000 -110.000000 -64.000000
148
- v -23.000000 -108.000000 -64.000000
149
- v -45.000000 -101.000000 -64.000000
150
- v -65.000000 -89.000000 -64.000000
151
- v -82.000000 -74.000000 -64.000000
152
- v -96.000000 -55.000000 -64.000000
153
- v -105.000000 -34.000000 -64.000000
154
- v -110.000000 -12.000000 -64.000000
155
- v -110.000000 11.000000 -64.000000
156
- v -105.000000 33.000000 -64.000000
157
- v -96.000000 54.000000 -64.000000
158
- v -82.000000 73.000000 -64.000000
159
- v -65.000000 88.000000 -64.000000
160
- v -45.000000 100.000000 -64.000000
161
- v -23.000000 107.000000 -64.000000
162
- v -1.000000 109.000000 -64.000000
163
- v 25.000000 118.000000 -40.000000
164
- v 49.000000 110.000000 -40.000000
165
- v 70.000000 97.000000 -40.000000
166
- v 89.000000 80.000000 -40.000000
167
- v 104.000000 60.000000 -40.000000
168
- v 114.000000 37.000000 -40.000000
169
- v 120.000000 12.000000 -40.000000
170
- v 120.000000 -13.000000 -40.000000
171
- v 114.000000 -38.000000 -40.000000
172
- v 104.000000 -61.000000 -40.000000
173
- v 89.000000 -81.000000 -40.000000
174
- v 70.000000 -98.000000 -40.000000
175
- v 49.000000 -111.000000 -40.000000
176
- v 25.000000 -119.000000 -40.000000
177
- v 0.000000 -121.000000 -40.000000
178
- v -26.000000 -119.000000 -40.000000
179
- v -50.000000 -111.000000 -40.000000
180
- v -71.000000 -98.000000 -40.000000
181
- v -90.000000 -81.000000 -40.000000
182
- v -105.000000 -61.000000 -40.000000
183
- v -115.000000 -38.000000 -40.000000
184
- v -121.000000 -13.000000 -40.000000
185
- v -121.000000 12.000000 -40.000000
186
- v -115.000000 37.000000 -40.000000
187
- v -105.000000 60.000000 -40.000000
188
- v -90.000000 80.000000 -40.000000
189
- v -71.000000 97.000000 -40.000000
190
- v -50.000000 110.000000 -40.000000
191
- v -26.000000 118.000000 -40.000000
192
- v -1.000000 120.000000 -40.000000
193
- v 26.000000 123.000000 -14.000000
194
- v 51.000000 115.000000 -14.000000
195
- v 74.000000 102.000000 -14.000000
196
- v 93.000000 84.000000 -14.000000
197
- v 109.000000 63.000000 -14.000000
198
- v 120.000000 39.000000 -14.000000
199
- v 125.000000 13.000000 -14.000000
200
- v 125.000000 -14.000000 -14.000000
201
- v 120.000000 -40.000000 -14.000000
202
- v 109.000000 -64.000000 -14.000000
203
- v 93.000000 -85.000000 -14.000000
204
- v 74.000000 -103.000000 -14.000000
205
- v 51.000000 -116.000000 -14.000000
206
- v 26.000000 -124.000000 -14.000000
207
- v 0.000000 -127.000000 -14.000000
208
- v -27.000000 -124.000000 -14.000000
209
- v -52.000000 -116.000000 -14.000000
210
- v -75.000000 -103.000000 -14.000000
211
- v -94.000000 -85.000000 -14.000000
212
- v -110.000000 -64.000000 -14.000000
213
- v -121.000000 -40.000000 -14.000000
214
- v -126.000000 -14.000000 -14.000000
215
- v -126.000000 13.000000 -14.000000
216
- v -121.000000 39.000000 -14.000000
217
- v -110.000000 63.000000 -14.000000
218
- v -94.000000 84.000000 -14.000000
219
- v -75.000000 102.000000 -14.000000
220
- v -52.000000 115.000000 -14.000000
221
- v -27.000000 123.000000 -14.000000
222
- v -1.000000 126.000000 -14.000000
223
- v 26.000000 123.000000 13.000000
224
- v 51.000000 115.000000 13.000000
225
- v 74.000000 102.000000 13.000000
226
- v 93.000000 84.000000 13.000000
227
- v 109.000000 63.000000 13.000000
228
- v 120.000000 39.000000 13.000000
229
- v 125.000000 13.000000 13.000000
230
- v 125.000000 -14.000000 13.000000
231
- v 120.000000 -40.000000 13.000000
232
- v 109.000000 -64.000000 13.000000
233
- v 93.000000 -85.000000 13.000000
234
- v 74.000000 -103.000000 13.000000
235
- v 51.000000 -116.000000 13.000000
236
- v 26.000000 -124.000000 13.000000
237
- v 0.000000 -127.000000 13.000000
238
- v -27.000000 -124.000000 13.000000
239
- v -52.000000 -116.000000 13.000000
240
- v -75.000000 -103.000000 13.000000
241
- v -94.000000 -85.000000 13.000000
242
- v -110.000000 -64.000000 13.000000
243
- v -121.000000 -40.000000 13.000000
244
- v -126.000000 -14.000000 13.000000
245
- v -126.000000 13.000000 13.000000
246
- v -121.000000 39.000000 13.000000
247
- v -110.000000 63.000000 13.000000
248
- v -94.000000 84.000000 13.000000
249
- v -75.000000 102.000000 13.000000
250
- v -52.000000 115.000000 13.000000
251
- v -27.000000 123.000000 13.000000
252
- v -1.000000 126.000000 13.000000
253
- v 25.000000 118.000000 39.000000
254
- v 49.000000 110.000000 39.000000
255
- v 70.000000 97.000000 39.000000
256
- v 89.000000 80.000000 39.000000
257
- v 104.000000 60.000000 39.000000
258
- v 114.000000 37.000000 39.000000
259
- v 120.000000 12.000000 39.000000
260
- v 120.000000 -13.000000 39.000000
261
- v 114.000000 -38.000000 39.000000
262
- v 104.000000 -61.000000 39.000000
263
- v 89.000000 -81.000000 39.000000
264
- v 70.000000 -98.000000 39.000000
265
- v 49.000000 -111.000000 39.000000
266
- v 25.000000 -119.000000 39.000000
267
- v 0.000000 -121.000000 39.000000
268
- v -26.000000 -119.000000 39.000000
269
- v -50.000000 -111.000000 39.000000
270
- v -71.000000 -98.000000 39.000000
271
- v -90.000000 -81.000000 39.000000
272
- v -105.000000 -61.000000 39.000000
273
- v -115.000000 -38.000000 39.000000
274
- v -121.000000 -13.000000 39.000000
275
- v -121.000000 12.000000 39.000000
276
- v -115.000000 37.000000 39.000000
277
- v -105.000000 60.000000 39.000000
278
- v -90.000000 80.000000 39.000000
279
- v -71.000000 97.000000 39.000000
280
- v -50.000000 110.000000 39.000000
281
- v -26.000000 118.000000 39.000000
282
- v -1.000000 120.000000 39.000000
283
- v 22.000000 107.000000 63.000000
284
- v 44.000000 100.000000 63.000000
285
- v 64.000000 88.000000 63.000000
286
- v 81.000000 73.000000 63.000000
287
- v 95.000000 54.000000 63.000000
288
- v 104.000000 33.000000 63.000000
289
- v 109.000000 11.000000 63.000000
290
- v 109.000000 -12.000000 63.000000
291
- v 104.000000 -34.000000 63.000000
292
- v 95.000000 -55.000000 63.000000
293
- v 81.000000 -74.000000 63.000000
294
- v 64.000000 -89.000000 63.000000
295
- v 44.000000 -101.000000 63.000000
296
- v 22.000000 -108.000000 63.000000
297
- v 0.000000 -110.000000 63.000000
298
- v -23.000000 -108.000000 63.000000
299
- v -45.000000 -101.000000 63.000000
300
- v -65.000000 -89.000000 63.000000
301
- v -82.000000 -74.000000 63.000000
302
- v -96.000000 -55.000000 63.000000
303
- v -105.000000 -34.000000 63.000000
304
- v -110.000000 -12.000000 63.000000
305
- v -110.000000 11.000000 63.000000
306
- v -105.000000 33.000000 63.000000
307
- v -96.000000 54.000000 63.000000
308
- v -82.000000 73.000000 63.000000
309
- v -65.000000 88.000000 63.000000
310
- v -45.000000 100.000000 63.000000
311
- v -23.000000 107.000000 63.000000
312
- v -1.000000 109.000000 63.000000
313
- v 19.000000 92.000000 84.000000
314
- v 38.000000 86.000000 84.000000
315
- v 55.000000 76.000000 84.000000
316
- v 70.000000 63.000000 84.000000
317
- v 81.000000 47.000000 84.000000
318
- v 89.000000 29.000000 84.000000
319
- v 93.000000 9.000000 84.000000
320
- v 93.000000 -10.000000 84.000000
321
- v 89.000000 -30.000000 84.000000
322
- v 81.000000 -48.000000 84.000000
323
- v 70.000000 -64.000000 84.000000
324
- v 55.000000 -77.000000 84.000000
325
- v 38.000000 -87.000000 84.000000
326
- v 19.000000 -93.000000 84.000000
327
- v 0.000000 -95.000000 84.000000
328
- v -20.000000 -93.000000 84.000000
329
- v -39.000000 -87.000000 84.000000
330
- v -56.000000 -77.000000 84.000000
331
- v -71.000000 -64.000000 84.000000
332
- v -82.000000 -48.000000 84.000000
333
- v -90.000000 -30.000000 84.000000
334
- v -94.000000 -10.000000 84.000000
335
- v -94.000000 9.000000 84.000000
336
- v -90.000000 29.000000 84.000000
337
- v -82.000000 47.000000 84.000000
338
- v -71.000000 63.000000 84.000000
339
- v -56.000000 76.000000 84.000000
340
- v -39.000000 86.000000 84.000000
341
- v -20.000000 92.000000 84.000000
342
- v -1.000000 94.000000 84.000000
343
- v 15.000000 73.000000 102.000000
344
- v 30.000000 68.000000 102.000000
345
- v 43.000000 60.000000 102.000000
346
- v 55.000000 49.000000 102.000000
347
- v 64.000000 37.000000 102.000000
348
- v 70.000000 23.000000 102.000000
349
- v 74.000000 7.000000 102.000000
350
- v 74.000000 -8.000000 102.000000
351
- v 70.000000 -24.000000 102.000000
352
- v 64.000000 -38.000000 102.000000
353
- v 55.000000 -50.000000 102.000000
354
- v 43.000000 -61.000000 102.000000
355
- v 30.000000 -69.000000 102.000000
356
- v 15.000000 -74.000000 102.000000
357
- v 0.000000 -75.000000 102.000000
358
- v -16.000000 -74.000000 102.000000
359
- v -31.000000 -69.000000 102.000000
360
- v -44.000000 -61.000000 102.000000
361
- v -56.000000 -50.000000 102.000000
362
- v -65.000000 -38.000000 102.000000
363
- v -71.000000 -24.000000 102.000000
364
- v -75.000000 -8.000000 102.000000
365
- v -75.000000 7.000000 102.000000
366
- v -71.000000 23.000000 102.000000
367
- v -65.000000 37.000000 102.000000
368
- v -56.000000 49.000000 102.000000
369
- v -44.000000 60.000000 102.000000
370
- v -31.000000 68.000000 102.000000
371
- v -16.000000 73.000000 102.000000
372
- v -1.000000 74.000000 102.000000
373
- v 10.000000 50.000000 116.000000
374
- v 21.000000 47.000000 116.000000
375
- v 30.000000 41.000000 116.000000
376
- v 38.000000 34.000000 116.000000
377
- v 44.000000 25.000000 116.000000
378
- v 49.000000 15.000000 116.000000
379
- v 51.000000 5.000000 116.000000
380
- v 51.000000 -6.000000 116.000000
381
- v 49.000000 -16.000000 116.000000
382
- v 44.000000 -26.000000 116.000000
383
- v 38.000000 -35.000000 116.000000
384
- v 30.000000 -42.000000 116.000000
385
- v 21.000000 -48.000000 116.000000
386
- v 10.000000 -51.000000 116.000000
387
- v 0.000000 -52.000000 116.000000
388
- v -11.000000 -51.000000 116.000000
389
- v -22.000000 -48.000000 116.000000
390
- v -31.000000 -42.000000 116.000000
391
- v -39.000000 -35.000000 116.000000
392
- v -45.000000 -26.000000 116.000000
393
- v -50.000000 -16.000000 116.000000
394
- v -52.000000 -6.000000 116.000000
395
- v -52.000000 5.000000 116.000000
396
- v -50.000000 15.000000 116.000000
397
- v -45.000000 25.000000 116.000000
398
- v -39.000000 34.000000 116.000000
399
- v -31.000000 41.000000 116.000000
400
- v -22.000000 47.000000 116.000000
401
- v -11.000000 50.000000 116.000000
402
- v -1.000000 51.000000 116.000000
403
- v 5.000000 25.000000 124.000000
404
- v 10.000000 24.000000 124.000000
405
- v 15.000000 21.000000 124.000000
406
- v 19.000000 17.000000 124.000000
407
- v 22.000000 13.000000 124.000000
408
- v 25.000000 8.000000 124.000000
409
- v 26.000000 2.000000 124.000000
410
- v 26.000000 -3.000000 124.000000
411
- v 25.000000 -9.000000 124.000000
412
- v 22.000000 -14.000000 124.000000
413
- v 19.000000 -18.000000 124.000000
414
- v 15.000000 -22.000000 124.000000
415
- v 10.000000 -25.000000 124.000000
416
- v 5.000000 -26.000000 124.000000
417
- v 0.000000 -27.000000 124.000000
418
- v -6.000000 -26.000000 124.000000
419
- v -11.000000 -25.000000 124.000000
420
- v -16.000000 -22.000000 124.000000
421
- v -20.000000 -18.000000 124.000000
422
- v -23.000000 -14.000000 124.000000
423
- v -26.000000 -9.000000 124.000000
424
- v -27.000000 -3.000000 124.000000
425
- v -27.000000 2.000000 124.000000
426
- v -26.000000 8.000000 124.000000
427
- v -23.000000 13.000000 124.000000
428
- v -20.000000 17.000000 124.000000
429
- v -16.000000 21.000000 124.000000
430
- v -11.000000 24.000000 124.000000
431
- v -6.000000 25.000000 124.000000
432
- v -1.000000 26.000000 124.000000
433
- v 0.000000 0.000000 127.000000
434
- # 422 vertices, 0 vertices normals
435
-
436
- f 1 2 3
437
- f 1 3 4
438
- f 1 4 5
439
- f 1 5 6
440
- f 1 6 7
441
- f 1 7 8
442
- f 1 8 9
443
- f 1 9 10
444
- f 1 10 11
445
- f 1 11 12
446
- f 1 12 13
447
- f 1 13 14
448
- f 1 14 15
449
- f 1 15 16
450
- f 1 16 17
451
- f 1 17 18
452
- f 1 18 19
453
- f 1 19 20
454
- f 1 20 21
455
- f 1 21 22
456
- f 1 22 23
457
- f 1 23 24
458
- f 1 24 25
459
- f 1 25 26
460
- f 1 26 27
461
- f 1 27 28
462
- f 1 28 29
463
- f 1 29 30
464
- f 1 30 31
465
- f 1 31 2
466
- f 2 33 3
467
- f 33 2 32
468
- f 3 34 4
469
- f 34 3 33
470
- f 4 35 5
471
- f 35 4 34
472
- f 5 36 6
473
- f 36 5 35
474
- f 6 37 7
475
- f 37 6 36
476
- f 7 38 8
477
- f 38 7 37
478
- f 8 39 9
479
- f 39 8 38
480
- f 9 40 10
481
- f 40 9 39
482
- f 10 41 11
483
- f 41 10 40
484
- f 11 42 12
485
- f 42 11 41
486
- f 12 43 13
487
- f 43 12 42
488
- f 13 44 14
489
- f 44 13 43
490
- f 14 45 15
491
- f 45 14 44
492
- f 15 46 16
493
- f 46 15 45
494
- f 16 47 17
495
- f 47 16 46
496
- f 17 48 18
497
- f 48 17 47
498
- f 18 49 19
499
- f 49 18 48
500
- f 19 50 20
501
- f 50 19 49
502
- f 20 51 21
503
- f 51 20 50
504
- f 21 52 22
505
- f 52 21 51
506
- f 22 53 23
507
- f 53 22 52
508
- f 23 54 24
509
- f 54 23 53
510
- f 24 55 25
511
- f 55 24 54
512
- f 25 56 26
513
- f 56 25 55
514
- f 26 57 27
515
- f 57 26 56
516
- f 27 58 28
517
- f 58 27 57
518
- f 28 59 29
519
- f 59 28 58
520
- f 29 60 30
521
- f 60 29 59
522
- f 30 61 31
523
- f 61 30 60
524
- f 31 32 2
525
- f 32 31 61
526
- f 32 63 33
527
- f 63 32 62
528
- f 33 64 34
529
- f 64 33 63
530
- f 34 65 35
531
- f 65 34 64
532
- f 35 66 36
533
- f 66 35 65
534
- f 36 67 37
535
- f 67 36 66
536
- f 37 68 38
537
- f 68 37 67
538
- f 38 69 39
539
- f 69 38 68
540
- f 39 70 40
541
- f 70 39 69
542
- f 40 71 41
543
- f 71 40 70
544
- f 41 72 42
545
- f 72 41 71
546
- f 42 73 43
547
- f 73 42 72
548
- f 43 74 44
549
- f 74 43 73
550
- f 44 75 45
551
- f 75 44 74
552
- f 45 76 46
553
- f 76 45 75
554
- f 46 77 47
555
- f 77 46 76
556
- f 47 78 48
557
- f 78 47 77
558
- f 48 79 49
559
- f 79 48 78
560
- f 49 80 50
561
- f 80 49 79
562
- f 50 81 51
563
- f 81 50 80
564
- f 51 82 52
565
- f 82 51 81
566
- f 52 83 53
567
- f 83 52 82
568
- f 53 84 54
569
- f 84 53 83
570
- f 54 85 55
571
- f 85 54 84
572
- f 55 86 56
573
- f 86 55 85
574
- f 56 87 57
575
- f 87 56 86
576
- f 57 88 58
577
- f 88 57 87
578
- f 58 89 59
579
- f 89 58 88
580
- f 59 90 60
581
- f 90 59 89
582
- f 60 91 61
583
- f 91 60 90
584
- f 61 62 32
585
- f 62 61 91
586
- f 62 93 63
587
- f 93 62 92
588
- f 63 94 64
589
- f 94 63 93
590
- f 64 95 65
591
- f 95 64 94
592
- f 65 96 66
593
- f 96 65 95
594
- f 66 97 67
595
- f 97 66 96
596
- f 67 98 68
597
- f 98 67 97
598
- f 68 99 69
599
- f 99 68 98
600
- f 69 100 70
601
- f 100 69 99
602
- f 70 101 71
603
- f 101 70 100
604
- f 71 102 72
605
- f 102 71 101
606
- f 72 103 73
607
- f 103 72 102
608
- f 73 104 74
609
- f 104 73 103
610
- f 74 105 75
611
- f 105 74 104
612
- f 75 106 76
613
- f 106 75 105
614
- f 76 107 77
615
- f 107 76 106
616
- f 77 108 78
617
- f 108 77 107
618
- f 78 109 79
619
- f 109 78 108
620
- f 79 110 80
621
- f 110 79 109
622
- f 80 111 81
623
- f 111 80 110
624
- f 81 112 82
625
- f 112 81 111
626
- f 82 113 83
627
- f 113 82 112
628
- f 83 114 84
629
- f 114 83 113
630
- f 84 115 85
631
- f 115 84 114
632
- f 85 116 86
633
- f 116 85 115
634
- f 86 117 87
635
- f 117 86 116
636
- f 87 118 88
637
- f 118 87 117
638
- f 88 119 89
639
- f 119 88 118
640
- f 89 120 90
641
- f 120 89 119
642
- f 90 121 91
643
- f 121 90 120
644
- f 91 92 62
645
- f 92 91 121
646
- f 92 123 93
647
- f 123 92 122
648
- f 93 124 94
649
- f 124 93 123
650
- f 94 125 95
651
- f 125 94 124
652
- f 95 126 96
653
- f 126 95 125
654
- f 96 127 97
655
- f 127 96 126
656
- f 97 128 98
657
- f 128 97 127
658
- f 98 129 99
659
- f 129 98 128
660
- f 99 130 100
661
- f 130 99 129
662
- f 100 131 101
663
- f 131 100 130
664
- f 101 132 102
665
- f 132 101 131
666
- f 102 133 103
667
- f 133 102 132
668
- f 103 134 104
669
- f 134 103 133
670
- f 104 135 105
671
- f 135 104 134
672
- f 105 136 106
673
- f 136 105 135
674
- f 106 137 107
675
- f 137 106 136
676
- f 107 138 108
677
- f 138 107 137
678
- f 108 139 109
679
- f 139 108 138
680
- f 109 140 110
681
- f 140 109 139
682
- f 110 141 111
683
- f 141 110 140
684
- f 111 142 112
685
- f 142 111 141
686
- f 112 143 113
687
- f 143 112 142
688
- f 113 144 114
689
- f 144 113 143
690
- f 114 145 115
691
- f 145 114 144
692
- f 115 146 116
693
- f 146 115 145
694
- f 116 147 117
695
- f 147 116 146
696
- f 117 148 118
697
- f 148 117 147
698
- f 118 149 119
699
- f 149 118 148
700
- f 119 150 120
701
- f 150 119 149
702
- f 120 151 121
703
- f 151 120 150
704
- f 121 122 92
705
- f 122 121 151
706
- f 122 153 123
707
- f 153 122 152
708
- f 123 154 124
709
- f 154 123 153
710
- f 124 155 125
711
- f 155 124 154
712
- f 125 156 126
713
- f 156 125 155
714
- f 126 157 127
715
- f 157 126 156
716
- f 127 158 128
717
- f 158 127 157
718
- f 128 159 129
719
- f 159 128 158
720
- f 129 160 130
721
- f 160 129 159
722
- f 130 161 131
723
- f 161 130 160
724
- f 131 162 132
725
- f 162 131 161
726
- f 132 163 133
727
- f 163 132 162
728
- f 133 164 134
729
- f 164 133 163
730
- f 134 165 135
731
- f 165 134 164
732
- f 135 166 136
733
- f 166 135 165
734
- f 136 167 137
735
- f 167 136 166
736
- f 137 168 138
737
- f 168 137 167
738
- f 138 169 139
739
- f 169 138 168
740
- f 139 170 140
741
- f 170 139 169
742
- f 140 171 141
743
- f 171 140 170
744
- f 141 172 142
745
- f 172 141 171
746
- f 142 173 143
747
- f 173 142 172
748
- f 143 174 144
749
- f 174 143 173
750
- f 144 175 145
751
- f 175 144 174
752
- f 145 176 146
753
- f 176 145 175
754
- f 146 177 147
755
- f 177 146 176
756
- f 147 178 148
757
- f 178 147 177
758
- f 148 179 149
759
- f 179 148 178
760
- f 149 180 150
761
- f 180 149 179
762
- f 150 181 151
763
- f 181 150 180
764
- f 151 152 122
765
- f 152 151 181
766
- f 152 183 153
767
- f 183 152 182
768
- f 153 184 154
769
- f 184 153 183
770
- f 154 185 155
771
- f 185 154 184
772
- f 155 186 156
773
- f 186 155 185
774
- f 156 187 157
775
- f 187 156 186
776
- f 157 188 158
777
- f 188 157 187
778
- f 158 189 159
779
- f 189 158 188
780
- f 159 190 160
781
- f 190 159 189
782
- f 160 191 161
783
- f 191 160 190
784
- f 161 192 162
785
- f 192 161 191
786
- f 162 193 163
787
- f 193 162 192
788
- f 163 194 164
789
- f 194 163 193
790
- f 164 195 165
791
- f 195 164 194
792
- f 165 196 166
793
- f 196 165 195
794
- f 166 197 167
795
- f 197 166 196
796
- f 167 198 168
797
- f 198 167 197
798
- f 168 199 169
799
- f 199 168 198
800
- f 169 200 170
801
- f 200 169 199
802
- f 170 201 171
803
- f 201 170 200
804
- f 171 202 172
805
- f 202 171 201
806
- f 172 203 173
807
- f 203 172 202
808
- f 173 204 174
809
- f 204 173 203
810
- f 174 205 175
811
- f 205 174 204
812
- f 175 206 176
813
- f 206 175 205
814
- f 176 207 177
815
- f 207 176 206
816
- f 177 208 178
817
- f 208 177 207
818
- f 178 209 179
819
- f 209 178 208
820
- f 179 210 180
821
- f 210 179 209
822
- f 180 211 181
823
- f 211 180 210
824
- f 181 182 152
825
- f 182 181 211
826
- f 182 213 183
827
- f 213 182 212
828
- f 183 214 184
829
- f 214 183 213
830
- f 184 215 185
831
- f 215 184 214
832
- f 185 216 186
833
- f 216 185 215
834
- f 186 217 187
835
- f 217 186 216
836
- f 187 218 188
837
- f 218 187 217
838
- f 188 219 189
839
- f 219 188 218
840
- f 189 220 190
841
- f 220 189 219
842
- f 190 221 191
843
- f 221 190 220
844
- f 191 222 192
845
- f 222 191 221
846
- f 192 223 193
847
- f 223 192 222
848
- f 193 224 194
849
- f 224 193 223
850
- f 194 225 195
851
- f 225 194 224
852
- f 195 226 196
853
- f 226 195 225
854
- f 196 227 197
855
- f 227 196 226
856
- f 197 228 198
857
- f 228 197 227
858
- f 198 229 199
859
- f 229 198 228
860
- f 199 230 200
861
- f 230 199 229
862
- f 200 231 201
863
- f 231 200 230
864
- f 201 232 202
865
- f 232 201 231
866
- f 202 233 203
867
- f 233 202 232
868
- f 203 234 204
869
- f 234 203 233
870
- f 204 235 205
871
- f 235 204 234
872
- f 205 236 206
873
- f 236 205 235
874
- f 206 237 207
875
- f 237 206 236
876
- f 207 238 208
877
- f 238 207 237
878
- f 208 239 209
879
- f 239 208 238
880
- f 209 240 210
881
- f 240 209 239
882
- f 210 241 211
883
- f 241 210 240
884
- f 211 212 182
885
- f 212 211 241
886
- f 212 243 213
887
- f 243 212 242
888
- f 213 244 214
889
- f 244 213 243
890
- f 214 245 215
891
- f 245 214 244
892
- f 215 246 216
893
- f 246 215 245
894
- f 216 247 217
895
- f 247 216 246
896
- f 217 248 218
897
- f 248 217 247
898
- f 218 249 219
899
- f 249 218 248
900
- f 219 250 220
901
- f 250 219 249
902
- f 220 251 221
903
- f 251 220 250
904
- f 221 252 222
905
- f 252 221 251
906
- f 222 253 223
907
- f 253 222 252
908
- f 223 254 224
909
- f 254 223 253
910
- f 224 255 225
911
- f 255 224 254
912
- f 225 256 226
913
- f 256 225 255
914
- f 226 257 227
915
- f 257 226 256
916
- f 227 258 228
917
- f 258 227 257
918
- f 228 259 229
919
- f 259 228 258
920
- f 229 260 230
921
- f 260 229 259
922
- f 230 261 231
923
- f 261 230 260
924
- f 231 262 232
925
- f 262 231 261
926
- f 232 263 233
927
- f 263 232 262
928
- f 233 264 234
929
- f 264 233 263
930
- f 234 265 235
931
- f 265 234 264
932
- f 235 266 236
933
- f 266 235 265
934
- f 236 267 237
935
- f 267 236 266
936
- f 237 268 238
937
- f 268 237 267
938
- f 238 269 239
939
- f 269 238 268
940
- f 239 270 240
941
- f 270 239 269
942
- f 240 271 241
943
- f 271 240 270
944
- f 241 242 212
945
- f 242 241 271
946
- f 242 273 243
947
- f 273 242 272
948
- f 243 274 244
949
- f 274 243 273
950
- f 244 275 245
951
- f 275 244 274
952
- f 245 276 246
953
- f 276 245 275
954
- f 246 277 247
955
- f 277 246 276
956
- f 247 278 248
957
- f 278 247 277
958
- f 248 279 249
959
- f 279 248 278
960
- f 249 280 250
961
- f 280 249 279
962
- f 250 281 251
963
- f 281 250 280
964
- f 251 282 252
965
- f 282 251 281
966
- f 252 283 253
967
- f 283 252 282
968
- f 253 284 254
969
- f 284 253 283
970
- f 254 285 255
971
- f 285 254 284
972
- f 255 286 256
973
- f 286 255 285
974
- f 256 287 257
975
- f 287 256 286
976
- f 257 288 258
977
- f 288 257 287
978
- f 258 289 259
979
- f 289 258 288
980
- f 259 290 260
981
- f 290 259 289
982
- f 260 291 261
983
- f 291 260 290
984
- f 261 292 262
985
- f 292 261 291
986
- f 262 293 263
987
- f 293 262 292
988
- f 263 294 264
989
- f 294 263 293
990
- f 264 295 265
991
- f 295 264 294
992
- f 265 296 266
993
- f 296 265 295
994
- f 266 297 267
995
- f 297 266 296
996
- f 267 298 268
997
- f 298 267 297
998
- f 268 299 269
999
- f 299 268 298
1000
- f 269 300 270
1001
- f 300 269 299
1002
- f 270 301 271
1003
- f 301 270 300
1004
- f 271 272 242
1005
- f 272 271 301
1006
- f 272 303 273
1007
- f 303 272 302
1008
- f 273 304 274
1009
- f 304 273 303
1010
- f 274 305 275
1011
- f 305 274 304
1012
- f 275 306 276
1013
- f 306 275 305
1014
- f 276 307 277
1015
- f 307 276 306
1016
- f 277 308 278
1017
- f 308 277 307
1018
- f 278 309 279
1019
- f 309 278 308
1020
- f 279 310 280
1021
- f 310 279 309
1022
- f 280 311 281
1023
- f 311 280 310
1024
- f 281 312 282
1025
- f 312 281 311
1026
- f 282 313 283
1027
- f 313 282 312
1028
- f 283 314 284
1029
- f 314 283 313
1030
- f 284 315 285
1031
- f 315 284 314
1032
- f 285 316 286
1033
- f 316 285 315
1034
- f 286 317 287
1035
- f 317 286 316
1036
- f 287 318 288
1037
- f 318 287 317
1038
- f 288 319 289
1039
- f 319 288 318
1040
- f 289 320 290
1041
- f 320 289 319
1042
- f 290 321 291
1043
- f 321 290 320
1044
- f 291 322 292
1045
- f 322 291 321
1046
- f 292 323 293
1047
- f 323 292 322
1048
- f 293 324 294
1049
- f 324 293 323
1050
- f 294 325 295
1051
- f 325 294 324
1052
- f 295 326 296
1053
- f 326 295 325
1054
- f 296 327 297
1055
- f 327 296 326
1056
- f 297 328 298
1057
- f 328 297 327
1058
- f 298 329 299
1059
- f 329 298 328
1060
- f 299 330 300
1061
- f 330 299 329
1062
- f 300 331 301
1063
- f 331 300 330
1064
- f 301 302 272
1065
- f 302 301 331
1066
- f 302 333 303
1067
- f 333 302 332
1068
- f 303 334 304
1069
- f 334 303 333
1070
- f 304 335 305
1071
- f 335 304 334
1072
- f 305 336 306
1073
- f 336 305 335
1074
- f 306 337 307
1075
- f 337 306 336
1076
- f 307 338 308
1077
- f 338 307 337
1078
- f 308 339 309
1079
- f 339 308 338
1080
- f 309 340 310
1081
- f 340 309 339
1082
- f 310 341 311
1083
- f 341 310 340
1084
- f 311 342 312
1085
- f 342 311 341
1086
- f 312 343 313
1087
- f 343 312 342
1088
- f 313 344 314
1089
- f 344 313 343
1090
- f 314 345 315
1091
- f 345 314 344
1092
- f 315 346 316
1093
- f 346 315 345
1094
- f 316 347 317
1095
- f 347 316 346
1096
- f 317 348 318
1097
- f 348 317 347
1098
- f 318 349 319
1099
- f 349 318 348
1100
- f 319 350 320
1101
- f 350 319 349
1102
- f 320 351 321
1103
- f 351 320 350
1104
- f 321 352 322
1105
- f 352 321 351
1106
- f 322 353 323
1107
- f 353 322 352
1108
- f 323 354 324
1109
- f 354 323 353
1110
- f 324 355 325
1111
- f 355 324 354
1112
- f 325 356 326
1113
- f 356 325 355
1114
- f 326 357 327
1115
- f 357 326 356
1116
- f 327 358 328
1117
- f 358 327 357
1118
- f 328 359 329
1119
- f 359 328 358
1120
- f 329 360 330
1121
- f 360 329 359
1122
- f 330 361 331
1123
- f 361 330 360
1124
- f 331 332 302
1125
- f 332 331 361
1126
- f 332 363 333
1127
- f 363 332 362
1128
- f 333 364 334
1129
- f 364 333 363
1130
- f 334 365 335
1131
- f 365 334 364
1132
- f 335 366 336
1133
- f 366 335 365
1134
- f 336 367 337
1135
- f 367 336 366
1136
- f 337 368 338
1137
- f 368 337 367
1138
- f 338 369 339
1139
- f 369 338 368
1140
- f 339 370 340
1141
- f 370 339 369
1142
- f 340 371 341
1143
- f 371 340 370
1144
- f 341 372 342
1145
- f 372 341 371
1146
- f 342 373 343
1147
- f 373 342 372
1148
- f 343 374 344
1149
- f 374 343 373
1150
- f 344 375 345
1151
- f 375 344 374
1152
- f 345 376 346
1153
- f 376 345 375
1154
- f 346 377 347
1155
- f 377 346 376
1156
- f 347 378 348
1157
- f 378 347 377
1158
- f 348 379 349
1159
- f 379 348 378
1160
- f 349 380 350
1161
- f 380 349 379
1162
- f 350 381 351
1163
- f 381 350 380
1164
- f 351 382 352
1165
- f 382 351 381
1166
- f 352 383 353
1167
- f 383 352 382
1168
- f 353 384 354
1169
- f 384 353 383
1170
- f 354 385 355
1171
- f 385 354 384
1172
- f 355 386 356
1173
- f 386 355 385
1174
- f 356 387 357
1175
- f 387 356 386
1176
- f 357 388 358
1177
- f 388 357 387
1178
- f 358 389 359
1179
- f 389 358 388
1180
- f 359 390 360
1181
- f 390 359 389
1182
- f 360 391 361
1183
- f 391 360 390
1184
- f 361 362 332
1185
- f 362 361 391
1186
- f 362 393 363
1187
- f 393 362 392
1188
- f 363 394 364
1189
- f 394 363 393
1190
- f 364 395 365
1191
- f 395 364 394
1192
- f 365 396 366
1193
- f 396 365 395
1194
- f 366 397 367
1195
- f 397 366 396
1196
- f 367 398 368
1197
- f 398 367 397
1198
- f 368 399 369
1199
- f 399 368 398
1200
- f 369 400 370
1201
- f 400 369 399
1202
- f 370 401 371
1203
- f 401 370 400
1204
- f 371 402 372
1205
- f 402 371 401
1206
- f 372 403 373
1207
- f 403 372 402
1208
- f 373 404 374
1209
- f 404 373 403
1210
- f 374 405 375
1211
- f 405 374 404
1212
- f 375 406 376
1213
- f 406 375 405
1214
- f 376 407 377
1215
- f 407 376 406
1216
- f 377 408 378
1217
- f 408 377 407
1218
- f 378 409 379
1219
- f 409 378 408
1220
- f 379 410 380
1221
- f 410 379 409
1222
- f 380 411 381
1223
- f 411 380 410
1224
- f 381 412 382
1225
- f 412 381 411
1226
- f 382 413 383
1227
- f 413 382 412
1228
- f 383 414 384
1229
- f 414 383 413
1230
- f 384 415 385
1231
- f 415 384 414
1232
- f 385 416 386
1233
- f 416 385 415
1234
- f 386 417 387
1235
- f 417 386 416
1236
- f 387 418 388
1237
- f 418 387 417
1238
- f 388 419 389
1239
- f 419 388 418
1240
- f 389 420 390
1241
- f 420 389 419
1242
- f 390 421 391
1243
- f 421 390 420
1244
- f 391 392 362
1245
- f 392 391 421
1246
- f 392 422 393
1247
- f 393 422 394
1248
- f 394 422 395
1249
- f 395 422 396
1250
- f 396 422 397
1251
- f 397 422 398
1252
- f 398 422 399
1253
- f 399 422 400
1254
- f 400 422 401
1255
- f 401 422 402
1256
- f 402 422 403
1257
- f 403 422 404
1258
- f 404 422 405
1259
- f 405 422 406
1260
- f 406 422 407
1261
- f 407 422 408
1262
- f 408 422 409
1263
- f 409 422 410
1264
- f 410 422 411
1265
- f 411 422 412
1266
- f 412 422 413
1267
- f 413 422 414
1268
- f 414 422 415
1269
- f 415 422 416
1270
- f 416 422 417
1271
- f 417 422 418
1272
- f 418 422 419
1273
- f 419 422 420
1274
- f 420 422 421
1275
- f 421 422 392
1276
- # 840 faces, 0 coords texture
1277
-
1278
- # End of File
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/sphere.ply DELETED
@@ -1,1271 +0,0 @@
1
- ply
2
- format ascii 1.0
3
- element vertex 422
4
- property float x
5
- property float y
6
- property float z
7
- element face 840
8
- property list uchar int vertex_indices
9
- end_header
10
- 0 0 -127
11
- 5 25 -125
12
- 10 24 -125
13
- 15 21 -125
14
- 19 17 -125
15
- 22 13 -125
16
- 25 8 -125
17
- 26 2 -125
18
- 26 -3 -125
19
- 25 -9 -125
20
- 22 -14 -125
21
- 19 -18 -125
22
- 15 -22 -125
23
- 10 -25 -125
24
- 5 -26 -125
25
- 0 -27 -125
26
- -6 -26 -125
27
- -11 -25 -125
28
- -16 -22 -125
29
- -20 -18 -125
30
- -23 -14 -125
31
- -26 -9 -125
32
- -27 -3 -125
33
- -27 2 -125
34
- -26 8 -125
35
- -23 13 -125
36
- -20 17 -125
37
- -16 21 -125
38
- -11 24 -125
39
- -6 25 -125
40
- -1 26 -125
41
- 10 50 -117
42
- 21 47 -117
43
- 30 41 -117
44
- 38 34 -117
45
- 44 25 -117
46
- 49 15 -117
47
- 51 5 -117
48
- 51 -6 -117
49
- 49 -16 -117
50
- 44 -26 -117
51
- 38 -35 -117
52
- 30 -42 -117
53
- 21 -48 -117
54
- 10 -51 -117
55
- 0 -52 -117
56
- -11 -51 -117
57
- -22 -48 -117
58
- -31 -42 -117
59
- -39 -35 -117
60
- -45 -26 -117
61
- -50 -16 -117
62
- -52 -6 -117
63
- -52 5 -117
64
- -50 15 -117
65
- -45 25 -117
66
- -39 34 -117
67
- -31 41 -117
68
- -22 47 -117
69
- -11 50 -117
70
- -1 51 -117
71
- 15 73 -103
72
- 30 68 -103
73
- 43 60 -103
74
- 55 49 -103
75
- 64 37 -103
76
- 70 23 -103
77
- 74 7 -103
78
- 74 -8 -103
79
- 70 -24 -103
80
- 64 -38 -103
81
- 55 -50 -103
82
- 43 -61 -103
83
- 30 -69 -103
84
- 15 -74 -103
85
- 0 -75 -103
86
- -16 -74 -103
87
- -31 -69 -103
88
- -44 -61 -103
89
- -56 -50 -103
90
- -65 -38 -103
91
- -71 -24 -103
92
- -75 -8 -103
93
- -75 7 -103
94
- -71 23 -103
95
- -65 37 -103
96
- -56 49 -103
97
- -44 60 -103
98
- -31 68 -103
99
- -16 73 -103
100
- -1 74 -103
101
- 19 92 -85
102
- 38 86 -85
103
- 55 76 -85
104
- 70 63 -85
105
- 81 47 -85
106
- 89 29 -85
107
- 93 9 -85
108
- 93 -10 -85
109
- 89 -30 -85
110
- 81 -48 -85
111
- 70 -64 -85
112
- 55 -77 -85
113
- 38 -87 -85
114
- 19 -93 -85
115
- 0 -95 -85
116
- -20 -93 -85
117
- -39 -87 -85
118
- -56 -77 -85
119
- -71 -64 -85
120
- -82 -48 -85
121
- -90 -30 -85
122
- -94 -10 -85
123
- -94 9 -85
124
- -90 29 -85
125
- -82 47 -85
126
- -71 63 -85
127
- -56 76 -85
128
- -39 86 -85
129
- -20 92 -85
130
- -1 94 -85
131
- 22 107 -64
132
- 44 100 -64
133
- 64 88 -64
134
- 81 73 -64
135
- 95 54 -64
136
- 104 33 -64
137
- 109 11 -64
138
- 109 -12 -64
139
- 104 -34 -64
140
- 95 -55 -64
141
- 81 -74 -64
142
- 64 -89 -64
143
- 44 -101 -64
144
- 22 -108 -64
145
- 0 -110 -64
146
- -23 -108 -64
147
- -45 -101 -64
148
- -65 -89 -64
149
- -82 -74 -64
150
- -96 -55 -64
151
- -105 -34 -64
152
- -110 -12 -64
153
- -110 11 -64
154
- -105 33 -64
155
- -96 54 -64
156
- -82 73 -64
157
- -65 88 -64
158
- -45 100 -64
159
- -23 107 -64
160
- -1 109 -64
161
- 25 118 -40
162
- 49 110 -40
163
- 70 97 -40
164
- 89 80 -40
165
- 104 60 -40
166
- 114 37 -40
167
- 120 12 -40
168
- 120 -13 -40
169
- 114 -38 -40
170
- 104 -61 -40
171
- 89 -81 -40
172
- 70 -98 -40
173
- 49 -111 -40
174
- 25 -119 -40
175
- 0 -121 -40
176
- -26 -119 -40
177
- -50 -111 -40
178
- -71 -98 -40
179
- -90 -81 -40
180
- -105 -61 -40
181
- -115 -38 -40
182
- -121 -13 -40
183
- -121 12 -40
184
- -115 37 -40
185
- -105 60 -40
186
- -90 80 -40
187
- -71 97 -40
188
- -50 110 -40
189
- -26 118 -40
190
- -1 120 -40
191
- 26 123 -14
192
- 51 115 -14
193
- 74 102 -14
194
- 93 84 -14
195
- 109 63 -14
196
- 120 39 -14
197
- 125 13 -14
198
- 125 -14 -14
199
- 120 -40 -14
200
- 109 -64 -14
201
- 93 -85 -14
202
- 74 -103 -14
203
- 51 -116 -14
204
- 26 -124 -14
205
- 0 -127 -14
206
- -27 -124 -14
207
- -52 -116 -14
208
- -75 -103 -14
209
- -94 -85 -14
210
- -110 -64 -14
211
- -121 -40 -14
212
- -126 -14 -14
213
- -126 13 -14
214
- -121 39 -14
215
- -110 63 -14
216
- -94 84 -14
217
- -75 102 -14
218
- -52 115 -14
219
- -27 123 -14
220
- -1 126 -14
221
- 26 123 13
222
- 51 115 13
223
- 74 102 13
224
- 93 84 13
225
- 109 63 13
226
- 120 39 13
227
- 125 13 13
228
- 125 -14 13
229
- 120 -40 13
230
- 109 -64 13
231
- 93 -85 13
232
- 74 -103 13
233
- 51 -116 13
234
- 26 -124 13
235
- 0 -127 13
236
- -27 -124 13
237
- -52 -116 13
238
- -75 -103 13
239
- -94 -85 13
240
- -110 -64 13
241
- -121 -40 13
242
- -126 -14 13
243
- -126 13 13
244
- -121 39 13
245
- -110 63 13
246
- -94 84 13
247
- -75 102 13
248
- -52 115 13
249
- -27 123 13
250
- -1 126 13
251
- 25 118 39
252
- 49 110 39
253
- 70 97 39
254
- 89 80 39
255
- 104 60 39
256
- 114 37 39
257
- 120 12 39
258
- 120 -13 39
259
- 114 -38 39
260
- 104 -61 39
261
- 89 -81 39
262
- 70 -98 39
263
- 49 -111 39
264
- 25 -119 39
265
- 0 -121 39
266
- -26 -119 39
267
- -50 -111 39
268
- -71 -98 39
269
- -90 -81 39
270
- -105 -61 39
271
- -115 -38 39
272
- -121 -13 39
273
- -121 12 39
274
- -115 37 39
275
- -105 60 39
276
- -90 80 39
277
- -71 97 39
278
- -50 110 39
279
- -26 118 39
280
- -1 120 39
281
- 22 107 63
282
- 44 100 63
283
- 64 88 63
284
- 81 73 63
285
- 95 54 63
286
- 104 33 63
287
- 109 11 63
288
- 109 -12 63
289
- 104 -34 63
290
- 95 -55 63
291
- 81 -74 63
292
- 64 -89 63
293
- 44 -101 63
294
- 22 -108 63
295
- 0 -110 63
296
- -23 -108 63
297
- -45 -101 63
298
- -65 -89 63
299
- -82 -74 63
300
- -96 -55 63
301
- -105 -34 63
302
- -110 -12 63
303
- -110 11 63
304
- -105 33 63
305
- -96 54 63
306
- -82 73 63
307
- -65 88 63
308
- -45 100 63
309
- -23 107 63
310
- -1 109 63
311
- 19 92 84
312
- 38 86 84
313
- 55 76 84
314
- 70 63 84
315
- 81 47 84
316
- 89 29 84
317
- 93 9 84
318
- 93 -10 84
319
- 89 -30 84
320
- 81 -48 84
321
- 70 -64 84
322
- 55 -77 84
323
- 38 -87 84
324
- 19 -93 84
325
- 0 -95 84
326
- -20 -93 84
327
- -39 -87 84
328
- -56 -77 84
329
- -71 -64 84
330
- -82 -48 84
331
- -90 -30 84
332
- -94 -10 84
333
- -94 9 84
334
- -90 29 84
335
- -82 47 84
336
- -71 63 84
337
- -56 76 84
338
- -39 86 84
339
- -20 92 84
340
- -1 94 84
341
- 15 73 102
342
- 30 68 102
343
- 43 60 102
344
- 55 49 102
345
- 64 37 102
346
- 70 23 102
347
- 74 7 102
348
- 74 -8 102
349
- 70 -24 102
350
- 64 -38 102
351
- 55 -50 102
352
- 43 -61 102
353
- 30 -69 102
354
- 15 -74 102
355
- 0 -75 102
356
- -16 -74 102
357
- -31 -69 102
358
- -44 -61 102
359
- -56 -50 102
360
- -65 -38 102
361
- -71 -24 102
362
- -75 -8 102
363
- -75 7 102
364
- -71 23 102
365
- -65 37 102
366
- -56 49 102
367
- -44 60 102
368
- -31 68 102
369
- -16 73 102
370
- -1 74 102
371
- 10 50 116
372
- 21 47 116
373
- 30 41 116
374
- 38 34 116
375
- 44 25 116
376
- 49 15 116
377
- 51 5 116
378
- 51 -6 116
379
- 49 -16 116
380
- 44 -26 116
381
- 38 -35 116
382
- 30 -42 116
383
- 21 -48 116
384
- 10 -51 116
385
- 0 -52 116
386
- -11 -51 116
387
- -22 -48 116
388
- -31 -42 116
389
- -39 -35 116
390
- -45 -26 116
391
- -50 -16 116
392
- -52 -6 116
393
- -52 5 116
394
- -50 15 116
395
- -45 25 116
396
- -39 34 116
397
- -31 41 116
398
- -22 47 116
399
- -11 50 116
400
- -1 51 116
401
- 5 25 124
402
- 10 24 124
403
- 15 21 124
404
- 19 17 124
405
- 22 13 124
406
- 25 8 124
407
- 26 2 124
408
- 26 -3 124
409
- 25 -9 124
410
- 22 -14 124
411
- 19 -18 124
412
- 15 -22 124
413
- 10 -25 124
414
- 5 -26 124
415
- 0 -27 124
416
- -6 -26 124
417
- -11 -25 124
418
- -16 -22 124
419
- -20 -18 124
420
- -23 -14 124
421
- -26 -9 124
422
- -27 -3 124
423
- -27 2 124
424
- -26 8 124
425
- -23 13 124
426
- -20 17 124
427
- -16 21 124
428
- -11 24 124
429
- -6 25 124
430
- -1 26 124
431
- 0 0 127
432
- 3 0 1 2
433
- 3 0 2 3
434
- 3 0 3 4
435
- 3 0 4 5
436
- 3 0 5 6
437
- 3 0 6 7
438
- 3 0 7 8
439
- 3 0 8 9
440
- 3 0 9 10
441
- 3 0 10 11
442
- 3 0 11 12
443
- 3 0 12 13
444
- 3 0 13 14
445
- 3 0 14 15
446
- 3 0 15 16
447
- 3 0 16 17
448
- 3 0 17 18
449
- 3 0 18 19
450
- 3 0 19 20
451
- 3 0 20 21
452
- 3 0 21 22
453
- 3 0 22 23
454
- 3 0 23 24
455
- 3 0 24 25
456
- 3 0 25 26
457
- 3 0 26 27
458
- 3 0 27 28
459
- 3 0 28 29
460
- 3 0 29 30
461
- 3 0 30 1
462
- 3 1 32 2
463
- 3 32 1 31
464
- 3 2 33 3
465
- 3 33 2 32
466
- 3 3 34 4
467
- 3 34 3 33
468
- 3 4 35 5
469
- 3 35 4 34
470
- 3 5 36 6
471
- 3 36 5 35
472
- 3 6 37 7
473
- 3 37 6 36
474
- 3 7 38 8
475
- 3 38 7 37
476
- 3 8 39 9
477
- 3 39 8 38
478
- 3 9 40 10
479
- 3 40 9 39
480
- 3 10 41 11
481
- 3 41 10 40
482
- 3 11 42 12
483
- 3 42 11 41
484
- 3 12 43 13
485
- 3 43 12 42
486
- 3 13 44 14
487
- 3 44 13 43
488
- 3 14 45 15
489
- 3 45 14 44
490
- 3 15 46 16
491
- 3 46 15 45
492
- 3 16 47 17
493
- 3 47 16 46
494
- 3 17 48 18
495
- 3 48 17 47
496
- 3 18 49 19
497
- 3 49 18 48
498
- 3 19 50 20
499
- 3 50 19 49
500
- 3 20 51 21
501
- 3 51 20 50
502
- 3 21 52 22
503
- 3 52 21 51
504
- 3 22 53 23
505
- 3 53 22 52
506
- 3 23 54 24
507
- 3 54 23 53
508
- 3 24 55 25
509
- 3 55 24 54
510
- 3 25 56 26
511
- 3 56 25 55
512
- 3 26 57 27
513
- 3 57 26 56
514
- 3 27 58 28
515
- 3 58 27 57
516
- 3 28 59 29
517
- 3 59 28 58
518
- 3 29 60 30
519
- 3 60 29 59
520
- 3 30 31 1
521
- 3 31 30 60
522
- 3 31 62 32
523
- 3 62 31 61
524
- 3 32 63 33
525
- 3 63 32 62
526
- 3 33 64 34
527
- 3 64 33 63
528
- 3 34 65 35
529
- 3 65 34 64
530
- 3 35 66 36
531
- 3 66 35 65
532
- 3 36 67 37
533
- 3 67 36 66
534
- 3 37 68 38
535
- 3 68 37 67
536
- 3 38 69 39
537
- 3 69 38 68
538
- 3 39 70 40
539
- 3 70 39 69
540
- 3 40 71 41
541
- 3 71 40 70
542
- 3 41 72 42
543
- 3 72 41 71
544
- 3 42 73 43
545
- 3 73 42 72
546
- 3 43 74 44
547
- 3 74 43 73
548
- 3 44 75 45
549
- 3 75 44 74
550
- 3 45 76 46
551
- 3 76 45 75
552
- 3 46 77 47
553
- 3 77 46 76
554
- 3 47 78 48
555
- 3 78 47 77
556
- 3 48 79 49
557
- 3 79 48 78
558
- 3 49 80 50
559
- 3 80 49 79
560
- 3 50 81 51
561
- 3 81 50 80
562
- 3 51 82 52
563
- 3 82 51 81
564
- 3 52 83 53
565
- 3 83 52 82
566
- 3 53 84 54
567
- 3 84 53 83
568
- 3 54 85 55
569
- 3 85 54 84
570
- 3 55 86 56
571
- 3 86 55 85
572
- 3 56 87 57
573
- 3 87 56 86
574
- 3 57 88 58
575
- 3 88 57 87
576
- 3 58 89 59
577
- 3 89 58 88
578
- 3 59 90 60
579
- 3 90 59 89
580
- 3 60 61 31
581
- 3 61 60 90
582
- 3 61 92 62
583
- 3 92 61 91
584
- 3 62 93 63
585
- 3 93 62 92
586
- 3 63 94 64
587
- 3 94 63 93
588
- 3 64 95 65
589
- 3 95 64 94
590
- 3 65 96 66
591
- 3 96 65 95
592
- 3 66 97 67
593
- 3 97 66 96
594
- 3 67 98 68
595
- 3 98 67 97
596
- 3 68 99 69
597
- 3 99 68 98
598
- 3 69 100 70
599
- 3 100 69 99
600
- 3 70 101 71
601
- 3 101 70 100
602
- 3 71 102 72
603
- 3 102 71 101
604
- 3 72 103 73
605
- 3 103 72 102
606
- 3 73 104 74
607
- 3 104 73 103
608
- 3 74 105 75
609
- 3 105 74 104
610
- 3 75 106 76
611
- 3 106 75 105
612
- 3 76 107 77
613
- 3 107 76 106
614
- 3 77 108 78
615
- 3 108 77 107
616
- 3 78 109 79
617
- 3 109 78 108
618
- 3 79 110 80
619
- 3 110 79 109
620
- 3 80 111 81
621
- 3 111 80 110
622
- 3 81 112 82
623
- 3 112 81 111
624
- 3 82 113 83
625
- 3 113 82 112
626
- 3 83 114 84
627
- 3 114 83 113
628
- 3 84 115 85
629
- 3 115 84 114
630
- 3 85 116 86
631
- 3 116 85 115
632
- 3 86 117 87
633
- 3 117 86 116
634
- 3 87 118 88
635
- 3 118 87 117
636
- 3 88 119 89
637
- 3 119 88 118
638
- 3 89 120 90
639
- 3 120 89 119
640
- 3 90 91 61
641
- 3 91 90 120
642
- 3 91 122 92
643
- 3 122 91 121
644
- 3 92 123 93
645
- 3 123 92 122
646
- 3 93 124 94
647
- 3 124 93 123
648
- 3 94 125 95
649
- 3 125 94 124
650
- 3 95 126 96
651
- 3 126 95 125
652
- 3 96 127 97
653
- 3 127 96 126
654
- 3 97 128 98
655
- 3 128 97 127
656
- 3 98 129 99
657
- 3 129 98 128
658
- 3 99 130 100
659
- 3 130 99 129
660
- 3 100 131 101
661
- 3 131 100 130
662
- 3 101 132 102
663
- 3 132 101 131
664
- 3 102 133 103
665
- 3 133 102 132
666
- 3 103 134 104
667
- 3 134 103 133
668
- 3 104 135 105
669
- 3 135 104 134
670
- 3 105 136 106
671
- 3 136 105 135
672
- 3 106 137 107
673
- 3 137 106 136
674
- 3 107 138 108
675
- 3 138 107 137
676
- 3 108 139 109
677
- 3 139 108 138
678
- 3 109 140 110
679
- 3 140 109 139
680
- 3 110 141 111
681
- 3 141 110 140
682
- 3 111 142 112
683
- 3 142 111 141
684
- 3 112 143 113
685
- 3 143 112 142
686
- 3 113 144 114
687
- 3 144 113 143
688
- 3 114 145 115
689
- 3 145 114 144
690
- 3 115 146 116
691
- 3 146 115 145
692
- 3 116 147 117
693
- 3 147 116 146
694
- 3 117 148 118
695
- 3 148 117 147
696
- 3 118 149 119
697
- 3 149 118 148
698
- 3 119 150 120
699
- 3 150 119 149
700
- 3 120 121 91
701
- 3 121 120 150
702
- 3 121 152 122
703
- 3 152 121 151
704
- 3 122 153 123
705
- 3 153 122 152
706
- 3 123 154 124
707
- 3 154 123 153
708
- 3 124 155 125
709
- 3 155 124 154
710
- 3 125 156 126
711
- 3 156 125 155
712
- 3 126 157 127
713
- 3 157 126 156
714
- 3 127 158 128
715
- 3 158 127 157
716
- 3 128 159 129
717
- 3 159 128 158
718
- 3 129 160 130
719
- 3 160 129 159
720
- 3 130 161 131
721
- 3 161 130 160
722
- 3 131 162 132
723
- 3 162 131 161
724
- 3 132 163 133
725
- 3 163 132 162
726
- 3 133 164 134
727
- 3 164 133 163
728
- 3 134 165 135
729
- 3 165 134 164
730
- 3 135 166 136
731
- 3 166 135 165
732
- 3 136 167 137
733
- 3 167 136 166
734
- 3 137 168 138
735
- 3 168 137 167
736
- 3 138 169 139
737
- 3 169 138 168
738
- 3 139 170 140
739
- 3 170 139 169
740
- 3 140 171 141
741
- 3 171 140 170
742
- 3 141 172 142
743
- 3 172 141 171
744
- 3 142 173 143
745
- 3 173 142 172
746
- 3 143 174 144
747
- 3 174 143 173
748
- 3 144 175 145
749
- 3 175 144 174
750
- 3 145 176 146
751
- 3 176 145 175
752
- 3 146 177 147
753
- 3 177 146 176
754
- 3 147 178 148
755
- 3 178 147 177
756
- 3 148 179 149
757
- 3 179 148 178
758
- 3 149 180 150
759
- 3 180 149 179
760
- 3 150 151 121
761
- 3 151 150 180
762
- 3 151 182 152
763
- 3 182 151 181
764
- 3 152 183 153
765
- 3 183 152 182
766
- 3 153 184 154
767
- 3 184 153 183
768
- 3 154 185 155
769
- 3 185 154 184
770
- 3 155 186 156
771
- 3 186 155 185
772
- 3 156 187 157
773
- 3 187 156 186
774
- 3 157 188 158
775
- 3 188 157 187
776
- 3 158 189 159
777
- 3 189 158 188
778
- 3 159 190 160
779
- 3 190 159 189
780
- 3 160 191 161
781
- 3 191 160 190
782
- 3 161 192 162
783
- 3 192 161 191
784
- 3 162 193 163
785
- 3 193 162 192
786
- 3 163 194 164
787
- 3 194 163 193
788
- 3 164 195 165
789
- 3 195 164 194
790
- 3 165 196 166
791
- 3 196 165 195
792
- 3 166 197 167
793
- 3 197 166 196
794
- 3 167 198 168
795
- 3 198 167 197
796
- 3 168 199 169
797
- 3 199 168 198
798
- 3 169 200 170
799
- 3 200 169 199
800
- 3 170 201 171
801
- 3 201 170 200
802
- 3 171 202 172
803
- 3 202 171 201
804
- 3 172 203 173
805
- 3 203 172 202
806
- 3 173 204 174
807
- 3 204 173 203
808
- 3 174 205 175
809
- 3 205 174 204
810
- 3 175 206 176
811
- 3 206 175 205
812
- 3 176 207 177
813
- 3 207 176 206
814
- 3 177 208 178
815
- 3 208 177 207
816
- 3 178 209 179
817
- 3 209 178 208
818
- 3 179 210 180
819
- 3 210 179 209
820
- 3 180 181 151
821
- 3 181 180 210
822
- 3 181 212 182
823
- 3 212 181 211
824
- 3 182 213 183
825
- 3 213 182 212
826
- 3 183 214 184
827
- 3 214 183 213
828
- 3 184 215 185
829
- 3 215 184 214
830
- 3 185 216 186
831
- 3 216 185 215
832
- 3 186 217 187
833
- 3 217 186 216
834
- 3 187 218 188
835
- 3 218 187 217
836
- 3 188 219 189
837
- 3 219 188 218
838
- 3 189 220 190
839
- 3 220 189 219
840
- 3 190 221 191
841
- 3 221 190 220
842
- 3 191 222 192
843
- 3 222 191 221
844
- 3 192 223 193
845
- 3 223 192 222
846
- 3 193 224 194
847
- 3 224 193 223
848
- 3 194 225 195
849
- 3 225 194 224
850
- 3 195 226 196
851
- 3 226 195 225
852
- 3 196 227 197
853
- 3 227 196 226
854
- 3 197 228 198
855
- 3 228 197 227
856
- 3 198 229 199
857
- 3 229 198 228
858
- 3 199 230 200
859
- 3 230 199 229
860
- 3 200 231 201
861
- 3 231 200 230
862
- 3 201 232 202
863
- 3 232 201 231
864
- 3 202 233 203
865
- 3 233 202 232
866
- 3 203 234 204
867
- 3 234 203 233
868
- 3 204 235 205
869
- 3 235 204 234
870
- 3 205 236 206
871
- 3 236 205 235
872
- 3 206 237 207
873
- 3 237 206 236
874
- 3 207 238 208
875
- 3 238 207 237
876
- 3 208 239 209
877
- 3 239 208 238
878
- 3 209 240 210
879
- 3 240 209 239
880
- 3 210 211 181
881
- 3 211 210 240
882
- 3 211 242 212
883
- 3 242 211 241
884
- 3 212 243 213
885
- 3 243 212 242
886
- 3 213 244 214
887
- 3 244 213 243
888
- 3 214 245 215
889
- 3 245 214 244
890
- 3 215 246 216
891
- 3 246 215 245
892
- 3 216 247 217
893
- 3 247 216 246
894
- 3 217 248 218
895
- 3 248 217 247
896
- 3 218 249 219
897
- 3 249 218 248
898
- 3 219 250 220
899
- 3 250 219 249
900
- 3 220 251 221
901
- 3 251 220 250
902
- 3 221 252 222
903
- 3 252 221 251
904
- 3 222 253 223
905
- 3 253 222 252
906
- 3 223 254 224
907
- 3 254 223 253
908
- 3 224 255 225
909
- 3 255 224 254
910
- 3 225 256 226
911
- 3 256 225 255
912
- 3 226 257 227
913
- 3 257 226 256
914
- 3 227 258 228
915
- 3 258 227 257
916
- 3 228 259 229
917
- 3 259 228 258
918
- 3 229 260 230
919
- 3 260 229 259
920
- 3 230 261 231
921
- 3 261 230 260
922
- 3 231 262 232
923
- 3 262 231 261
924
- 3 232 263 233
925
- 3 263 232 262
926
- 3 233 264 234
927
- 3 264 233 263
928
- 3 234 265 235
929
- 3 265 234 264
930
- 3 235 266 236
931
- 3 266 235 265
932
- 3 236 267 237
933
- 3 267 236 266
934
- 3 237 268 238
935
- 3 268 237 267
936
- 3 238 269 239
937
- 3 269 238 268
938
- 3 239 270 240
939
- 3 270 239 269
940
- 3 240 241 211
941
- 3 241 240 270
942
- 3 241 272 242
943
- 3 272 241 271
944
- 3 242 273 243
945
- 3 273 242 272
946
- 3 243 274 244
947
- 3 274 243 273
948
- 3 244 275 245
949
- 3 275 244 274
950
- 3 245 276 246
951
- 3 276 245 275
952
- 3 246 277 247
953
- 3 277 246 276
954
- 3 247 278 248
955
- 3 278 247 277
956
- 3 248 279 249
957
- 3 279 248 278
958
- 3 249 280 250
959
- 3 280 249 279
960
- 3 250 281 251
961
- 3 281 250 280
962
- 3 251 282 252
963
- 3 282 251 281
964
- 3 252 283 253
965
- 3 283 252 282
966
- 3 253 284 254
967
- 3 284 253 283
968
- 3 254 285 255
969
- 3 285 254 284
970
- 3 255 286 256
971
- 3 286 255 285
972
- 3 256 287 257
973
- 3 287 256 286
974
- 3 257 288 258
975
- 3 288 257 287
976
- 3 258 289 259
977
- 3 289 258 288
978
- 3 259 290 260
979
- 3 290 259 289
980
- 3 260 291 261
981
- 3 291 260 290
982
- 3 261 292 262
983
- 3 292 261 291
984
- 3 262 293 263
985
- 3 293 262 292
986
- 3 263 294 264
987
- 3 294 263 293
988
- 3 264 295 265
989
- 3 295 264 294
990
- 3 265 296 266
991
- 3 296 265 295
992
- 3 266 297 267
993
- 3 297 266 296
994
- 3 267 298 268
995
- 3 298 267 297
996
- 3 268 299 269
997
- 3 299 268 298
998
- 3 269 300 270
999
- 3 300 269 299
1000
- 3 270 271 241
1001
- 3 271 270 300
1002
- 3 271 302 272
1003
- 3 302 271 301
1004
- 3 272 303 273
1005
- 3 303 272 302
1006
- 3 273 304 274
1007
- 3 304 273 303
1008
- 3 274 305 275
1009
- 3 305 274 304
1010
- 3 275 306 276
1011
- 3 306 275 305
1012
- 3 276 307 277
1013
- 3 307 276 306
1014
- 3 277 308 278
1015
- 3 308 277 307
1016
- 3 278 309 279
1017
- 3 309 278 308
1018
- 3 279 310 280
1019
- 3 310 279 309
1020
- 3 280 311 281
1021
- 3 311 280 310
1022
- 3 281 312 282
1023
- 3 312 281 311
1024
- 3 282 313 283
1025
- 3 313 282 312
1026
- 3 283 314 284
1027
- 3 314 283 313
1028
- 3 284 315 285
1029
- 3 315 284 314
1030
- 3 285 316 286
1031
- 3 316 285 315
1032
- 3 286 317 287
1033
- 3 317 286 316
1034
- 3 287 318 288
1035
- 3 318 287 317
1036
- 3 288 319 289
1037
- 3 319 288 318
1038
- 3 289 320 290
1039
- 3 320 289 319
1040
- 3 290 321 291
1041
- 3 321 290 320
1042
- 3 291 322 292
1043
- 3 322 291 321
1044
- 3 292 323 293
1045
- 3 323 292 322
1046
- 3 293 324 294
1047
- 3 324 293 323
1048
- 3 294 325 295
1049
- 3 325 294 324
1050
- 3 295 326 296
1051
- 3 326 295 325
1052
- 3 296 327 297
1053
- 3 327 296 326
1054
- 3 297 328 298
1055
- 3 328 297 327
1056
- 3 298 329 299
1057
- 3 329 298 328
1058
- 3 299 330 300
1059
- 3 330 299 329
1060
- 3 300 301 271
1061
- 3 301 300 330
1062
- 3 301 332 302
1063
- 3 332 301 331
1064
- 3 302 333 303
1065
- 3 333 302 332
1066
- 3 303 334 304
1067
- 3 334 303 333
1068
- 3 304 335 305
1069
- 3 335 304 334
1070
- 3 305 336 306
1071
- 3 336 305 335
1072
- 3 306 337 307
1073
- 3 337 306 336
1074
- 3 307 338 308
1075
- 3 338 307 337
1076
- 3 308 339 309
1077
- 3 339 308 338
1078
- 3 309 340 310
1079
- 3 340 309 339
1080
- 3 310 341 311
1081
- 3 341 310 340
1082
- 3 311 342 312
1083
- 3 342 311 341
1084
- 3 312 343 313
1085
- 3 343 312 342
1086
- 3 313 344 314
1087
- 3 344 313 343
1088
- 3 314 345 315
1089
- 3 345 314 344
1090
- 3 315 346 316
1091
- 3 346 315 345
1092
- 3 316 347 317
1093
- 3 347 316 346
1094
- 3 317 348 318
1095
- 3 348 317 347
1096
- 3 318 349 319
1097
- 3 349 318 348
1098
- 3 319 350 320
1099
- 3 350 319 349
1100
- 3 320 351 321
1101
- 3 351 320 350
1102
- 3 321 352 322
1103
- 3 352 321 351
1104
- 3 322 353 323
1105
- 3 353 322 352
1106
- 3 323 354 324
1107
- 3 354 323 353
1108
- 3 324 355 325
1109
- 3 355 324 354
1110
- 3 325 356 326
1111
- 3 356 325 355
1112
- 3 326 357 327
1113
- 3 357 326 356
1114
- 3 327 358 328
1115
- 3 358 327 357
1116
- 3 328 359 329
1117
- 3 359 328 358
1118
- 3 329 360 330
1119
- 3 360 329 359
1120
- 3 330 331 301
1121
- 3 331 330 360
1122
- 3 331 362 332
1123
- 3 362 331 361
1124
- 3 332 363 333
1125
- 3 363 332 362
1126
- 3 333 364 334
1127
- 3 364 333 363
1128
- 3 334 365 335
1129
- 3 365 334 364
1130
- 3 335 366 336
1131
- 3 366 335 365
1132
- 3 336 367 337
1133
- 3 367 336 366
1134
- 3 337 368 338
1135
- 3 368 337 367
1136
- 3 338 369 339
1137
- 3 369 338 368
1138
- 3 339 370 340
1139
- 3 370 339 369
1140
- 3 340 371 341
1141
- 3 371 340 370
1142
- 3 341 372 342
1143
- 3 372 341 371
1144
- 3 342 373 343
1145
- 3 373 342 372
1146
- 3 343 374 344
1147
- 3 374 343 373
1148
- 3 344 375 345
1149
- 3 375 344 374
1150
- 3 345 376 346
1151
- 3 376 345 375
1152
- 3 346 377 347
1153
- 3 377 346 376
1154
- 3 347 378 348
1155
- 3 378 347 377
1156
- 3 348 379 349
1157
- 3 379 348 378
1158
- 3 349 380 350
1159
- 3 380 349 379
1160
- 3 350 381 351
1161
- 3 381 350 380
1162
- 3 351 382 352
1163
- 3 382 351 381
1164
- 3 352 383 353
1165
- 3 383 352 382
1166
- 3 353 384 354
1167
- 3 384 353 383
1168
- 3 354 385 355
1169
- 3 385 354 384
1170
- 3 355 386 356
1171
- 3 386 355 385
1172
- 3 356 387 357
1173
- 3 387 356 386
1174
- 3 357 388 358
1175
- 3 388 357 387
1176
- 3 358 389 359
1177
- 3 389 358 388
1178
- 3 359 390 360
1179
- 3 390 359 389
1180
- 3 360 361 331
1181
- 3 361 360 390
1182
- 3 361 392 362
1183
- 3 392 361 391
1184
- 3 362 393 363
1185
- 3 393 362 392
1186
- 3 363 394 364
1187
- 3 394 363 393
1188
- 3 364 395 365
1189
- 3 395 364 394
1190
- 3 365 396 366
1191
- 3 396 365 395
1192
- 3 366 397 367
1193
- 3 397 366 396
1194
- 3 367 398 368
1195
- 3 398 367 397
1196
- 3 368 399 369
1197
- 3 399 368 398
1198
- 3 369 400 370
1199
- 3 400 369 399
1200
- 3 370 401 371
1201
- 3 401 370 400
1202
- 3 371 402 372
1203
- 3 402 371 401
1204
- 3 372 403 373
1205
- 3 403 372 402
1206
- 3 373 404 374
1207
- 3 404 373 403
1208
- 3 374 405 375
1209
- 3 405 374 404
1210
- 3 375 406 376
1211
- 3 406 375 405
1212
- 3 376 407 377
1213
- 3 407 376 406
1214
- 3 377 408 378
1215
- 3 408 377 407
1216
- 3 378 409 379
1217
- 3 409 378 408
1218
- 3 379 410 380
1219
- 3 410 379 409
1220
- 3 380 411 381
1221
- 3 411 380 410
1222
- 3 381 412 382
1223
- 3 412 381 411
1224
- 3 382 413 383
1225
- 3 413 382 412
1226
- 3 383 414 384
1227
- 3 414 383 413
1228
- 3 384 415 385
1229
- 3 415 384 414
1230
- 3 385 416 386
1231
- 3 416 385 415
1232
- 3 386 417 387
1233
- 3 417 386 416
1234
- 3 387 418 388
1235
- 3 418 387 417
1236
- 3 388 419 389
1237
- 3 419 388 418
1238
- 3 389 420 390
1239
- 3 420 389 419
1240
- 3 390 391 361
1241
- 3 391 390 420
1242
- 3 391 421 392
1243
- 3 392 421 393
1244
- 3 393 421 394
1245
- 3 394 421 395
1246
- 3 395 421 396
1247
- 3 396 421 397
1248
- 3 397 421 398
1249
- 3 398 421 399
1250
- 3 399 421 400
1251
- 3 400 421 401
1252
- 3 401 421 402
1253
- 3 402 421 403
1254
- 3 403 421 404
1255
- 3 404 421 405
1256
- 3 405 421 406
1257
- 3 406 421 407
1258
- 3 407 421 408
1259
- 3 408 421 409
1260
- 3 409 421 410
1261
- 3 410 421 411
1262
- 3 411 421 412
1263
- 3 412 421 413
1264
- 3 413 421 414
1265
- 3 414 421 415
1266
- 3 415 421 416
1267
- 3 416 421 417
1268
- 3 417 421 418
1269
- 3 418 421 419
1270
- 3 419 421 420
1271
- 3 420 421 391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/test_box.obj DELETED
@@ -1,50 +0,0 @@
1
- ####
2
- #
3
- # OBJ File Generated by Meshlab
4
- #
5
- ####
6
- # Object test_box.obj
7
- #
8
- # Vertices: 8
9
- # Faces: 12
10
- #
11
- ####
12
- vn 0.577350 0.577350 0.577350
13
- #landmark pospospos
14
- v 0.500000 0.500000 0.500000
15
- vn -0.333333 0.666667 0.666667
16
- v -0.500000 0.500000 0.500000
17
- vn 0.666667 -0.333333 0.666667
18
- v 0.500000 -0.500000 0.500000
19
- vn -0.666667 -0.666667 0.333333
20
- v -0.500000 -0.500000 0.500000
21
- vn 0.666667 0.666667 -0.333333
22
- v 0.500000 0.500000 -0.500000
23
- vn -0.666667 0.333333 -0.666667
24
- v -0.500000 0.500000 -0.500000
25
- vn 0.333333 -0.666667 -0.666667
26
- v 0.500000 -0.500000 -0.500000
27
- vn -0.577350 -0.577350 -0.577350
28
- #landmark negnegneg
29
- v -0.500000 -0.500000 -0.500000
30
- # 8 vertices, 0 vertices normals
31
-
32
- g a
33
- f 1//1 2//2 3//3
34
- f 4//4 3//3 2//2
35
- f 1//1 3//3 5//5
36
- f 7//7 5//5 3//3
37
- f 1//1 5//5 2//2
38
- f 6//6 2//2 5//5
39
- g b
40
- f 8//8 6//6 7//7
41
- g c
42
- f 5//5 7//7 6//6
43
- f 8//8 7//7 4//4
44
- f 3//3 4//4 7//7
45
- g b
46
- f 8//8 4//4 6//6
47
- f 2//2 6//6 4//4
48
- # 12 faces, 0 coords texture
49
-
50
- # End of File
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/test_box.ply DELETED
@@ -1,29 +0,0 @@
1
- ply
2
- format ascii 1.0
3
- element vertex 8
4
- property float x
5
- property float y
6
- property float z
7
- element face 12
8
- property list uchar int vertex_indices
9
- end_header
10
- 0.5 0.5 0.5
11
- -0.5 0.5 0.5
12
- 0.5 -0.5 0.5
13
- -0.5 -0.5 0.5
14
- 0.5 0.5 -0.5
15
- -0.5 0.5 -0.5
16
- 0.5 -0.5 -0.5
17
- -0.5 -0.5 -0.5
18
- 3 0 1 2
19
- 3 3 2 1
20
- 3 0 2 4
21
- 3 6 4 2
22
- 3 0 4 1
23
- 3 5 1 4
24
- 3 7 5 6
25
- 3 4 6 5
26
- 3 7 6 3
27
- 3 2 3 6
28
- 3 7 3 5
29
- 3 1 5 3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/test_box.pp DELETED
@@ -1,11 +0,0 @@
1
- <!DOCTYPE PickedPoints>
2
- <PickedPoints>
3
- <DocumentData>
4
- <DateTime time="23:00:01" date="2012-04-10"/>
5
- <User name="javier"/>
6
- <DataFileName name="test_box.ply"/>
7
- <templateName name=".pickPointsTemplate.pptpl"/>
8
- </DocumentData>
9
- <point x="0.5" y="0.5" z="0.5" active="1" name="pospospos"/>
10
- <point x="-0.5" y="-0.5" z="-0.5" active="1" name="negnegneg"/>
11
- </PickedPoints>
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/data/unittest/test_box_le.ply DELETED
Binary file (422 Bytes)
 
mesh-master/data/unittest/test_doublebox.obj DELETED
@@ -1,64 +0,0 @@
1
- ####
2
- #
3
- # OBJ File
4
- #
5
- ####
6
- # Object test_doublebox.obj
7
- #
8
- # Vertices: 12
9
- # Faces: 20
10
- #
11
- ####
12
- vn 0.577350 0.577350 0.577350
13
- v 0.500000 0.500000 0.500000
14
- vn -0.333333 0.666667 0.666667
15
- v -0.500000 0.500000 0.500000
16
- vn 0.666667 -0.333333 0.666667
17
- v 0.500000 -0.500000 0.500000
18
- vn -0.666667 -0.666667 0.333333
19
- v -0.500000 -0.500000 0.500000
20
- vn 0.666667 0.666667 -0.333333
21
- v 0.500000 0.500000 -0.500000
22
- vn -0.666667 0.333333 -0.666667
23
- v -0.500000 0.500000 -0.500000
24
- vn 0.333333 -0.666667 -0.666667
25
- v 0.500000 -0.500000 -0.500000
26
- vn -0.577350 -0.577350 -0.577350
27
- v -0.500000 -0.500000 -0.500000
28
-
29
- vn 0.577350 0.577350 0.577350
30
- v 0.500000 0.500000 1.500000
31
- vn -0.333333 0.666667 0.666667
32
- v -0.500000 0.500000 1.500000
33
- vn 0.666667 -0.333333 0.666667
34
- v 0.500000 -0.500000 1.500000
35
- vn -0.666667 -0.666667 0.333333
36
- v -0.500000 -0.500000 1.500000
37
- # 12 vertices, 0 vertices normals
38
-
39
- g box1
40
- f 1//1 3//3 5//5
41
- f 7//7 5//5 3//3
42
- f 1//1 5//5 2//2
43
- f 6//6 2//2 5//5
44
- f 8//8 6//6 7//7
45
- f 5//5 7//7 6//6
46
- f 8//8 7//7 4//4
47
- f 3//3 4//4 7//7
48
- f 8//8 4//4 6//6
49
- f 2//2 6//6 4//4
50
- g box2
51
- f 9//9 10//10 11//11
52
- f 12//12 11//11 10//10
53
- f 9//9 11//11 1//1
54
- f 3//3 1//1 11//11
55
- f 9//9 1//1 10//10
56
- f 2//2 10//10 1//1
57
- f 4//4 3//3 12//12
58
- f 11//11 12//12 3//3
59
- f 4//4 12//12 2//2
60
- f 10//10 2//2 12//12
61
-
62
- # 20 faces, 0 coords texture
63
-
64
- # End of File
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/Makefile DELETED
@@ -1,177 +0,0 @@
1
- # Makefile for Sphinx documentation
2
- #
3
-
4
- # You can set these variables from the command line.
5
- SPHINXOPTS =
6
- SPHINXBUILD = sphinx-build
7
- PAPER =
8
- BUILDDIR = build
9
-
10
- # User-friendly check for sphinx-build
11
- ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12
- $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13
- endif
14
-
15
- # Internal variables.
16
- PAPEROPT_a4 = -D latex_paper_size=a4
17
- PAPEROPT_letter = -D latex_paper_size=letter
18
- ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
19
- # the i18n builder cannot share the environment and doctrees with the others
20
- I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
21
-
22
- .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23
-
24
- help:
25
- @echo "Please use \`make <target>' where <target> is one of"
26
- @echo " html to make standalone HTML files"
27
- @echo " dirhtml to make HTML files named index.html in directories"
28
- @echo " singlehtml to make a single large HTML file"
29
- @echo " pickle to make pickle files"
30
- @echo " json to make JSON files"
31
- @echo " htmlhelp to make HTML files and a HTML help project"
32
- @echo " qthelp to make HTML files and a qthelp project"
33
- @echo " devhelp to make HTML files and a Devhelp project"
34
- @echo " epub to make an epub"
35
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
37
- @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38
- @echo " text to make text files"
39
- @echo " man to make manual pages"
40
- @echo " texinfo to make Texinfo files"
41
- @echo " info to make Texinfo files and run them through makeinfo"
42
- @echo " gettext to make PO message catalogs"
43
- @echo " changes to make an overview of all changed/added/deprecated items"
44
- @echo " xml to make Docutils-native XML files"
45
- @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46
- @echo " linkcheck to check all external links for integrity"
47
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48
-
49
- clean:
50
- rm -rf $(BUILDDIR)/*
51
-
52
- html:
53
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54
- @echo
55
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56
-
57
- dirhtml:
58
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59
- @echo
60
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61
-
62
- singlehtml:
63
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64
- @echo
65
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66
-
67
- pickle:
68
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69
- @echo
70
- @echo "Build finished; now you can process the pickle files."
71
-
72
- json:
73
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74
- @echo
75
- @echo "Build finished; now you can process the JSON files."
76
-
77
- htmlhelp:
78
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79
- @echo
80
- @echo "Build finished; now you can run HTML Help Workshop with the" \
81
- ".hhp project file in $(BUILDDIR)/htmlhelp."
82
-
83
- qthelp:
84
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85
- @echo
86
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PSBodyMeshPackage.qhcp"
89
- @echo "To view the help file:"
90
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PSBodyMeshPackage.qhc"
91
-
92
- devhelp:
93
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94
- @echo
95
- @echo "Build finished."
96
- @echo "To view the help file:"
97
- @echo "# mkdir -p $$HOME/.local/share/devhelp/PSBodyMeshPackage"
98
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PSBodyMeshPackage"
99
- @echo "# devhelp"
100
-
101
- epub:
102
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103
- @echo
104
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105
-
106
- latex:
107
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108
- @echo
109
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
111
- "(use \`make latexpdf' here to do that automatically)."
112
-
113
- latexpdf:
114
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115
- @echo "Running LaTeX files through pdflatex..."
116
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
117
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118
-
119
- latexpdfja:
120
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121
- @echo "Running LaTeX files through platex and dvipdfmx..."
122
- $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124
-
125
- text:
126
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127
- @echo
128
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
129
-
130
- man:
131
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132
- @echo
133
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134
-
135
- texinfo:
136
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137
- @echo
138
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139
- @echo "Run \`make' in that directory to run these through makeinfo" \
140
- "(use \`make info' here to do that automatically)."
141
-
142
- info:
143
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144
- @echo "Running Texinfo files through makeinfo..."
145
- make -C $(BUILDDIR)/texinfo info
146
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147
-
148
- gettext:
149
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150
- @echo
151
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152
-
153
- changes:
154
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155
- @echo
156
- @echo "The overview file is in $(BUILDDIR)/changes."
157
-
158
- linkcheck:
159
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160
- @echo
161
- @echo "Link check complete; look for any errors in the above output " \
162
- "or in $(BUILDDIR)/linkcheck/output.txt."
163
-
164
- doctest:
165
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166
- @echo "Testing of doctests in the sources finished, look at the " \
167
- "results in $(BUILDDIR)/doctest/output.txt."
168
-
169
- xml:
170
- $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171
- @echo
172
- @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173
-
174
- pseudoxml:
175
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176
- @echo
177
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/make.bat DELETED
@@ -1,242 +0,0 @@
1
- @ECHO OFF
2
-
3
- REM Command file for Sphinx documentation
4
-
5
- if "%SPHINXBUILD%" == "" (
6
- set SPHINXBUILD=sphinx-build
7
- )
8
- set BUILDDIR=build
9
- set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
10
- set I18NSPHINXOPTS=%SPHINXOPTS% source
11
- if NOT "%PAPER%" == "" (
12
- set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13
- set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14
- )
15
-
16
- if "%1" == "" goto help
17
-
18
- if "%1" == "help" (
19
- :help
20
- echo.Please use `make ^<target^>` where ^<target^> is one of
21
- echo. html to make standalone HTML files
22
- echo. dirhtml to make HTML files named index.html in directories
23
- echo. singlehtml to make a single large HTML file
24
- echo. pickle to make pickle files
25
- echo. json to make JSON files
26
- echo. htmlhelp to make HTML files and a HTML help project
27
- echo. qthelp to make HTML files and a qthelp project
28
- echo. devhelp to make HTML files and a Devhelp project
29
- echo. epub to make an epub
30
- echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
31
- echo. text to make text files
32
- echo. man to make manual pages
33
- echo. texinfo to make Texinfo files
34
- echo. gettext to make PO message catalogs
35
- echo. changes to make an overview over all changed/added/deprecated items
36
- echo. xml to make Docutils-native XML files
37
- echo. pseudoxml to make pseudoxml-XML files for display purposes
38
- echo. linkcheck to check all external links for integrity
39
- echo. doctest to run all doctests embedded in the documentation if enabled
40
- goto end
41
- )
42
-
43
- if "%1" == "clean" (
44
- for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
45
- del /q /s %BUILDDIR%\*
46
- goto end
47
- )
48
-
49
-
50
- %SPHINXBUILD% 2> nul
51
- if errorlevel 9009 (
52
- echo.
53
- echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
54
- echo.installed, then set the SPHINXBUILD environment variable to point
55
- echo.to the full path of the 'sphinx-build' executable. Alternatively you
56
- echo.may add the Sphinx directory to PATH.
57
- echo.
58
- echo.If you don't have Sphinx installed, grab it from
59
- echo.http://sphinx-doc.org/
60
- exit /b 1
61
- )
62
-
63
- if "%1" == "html" (
64
- %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
65
- if errorlevel 1 exit /b 1
66
- echo.
67
- echo.Build finished. The HTML pages are in %BUILDDIR%/html.
68
- goto end
69
- )
70
-
71
- if "%1" == "dirhtml" (
72
- %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
73
- if errorlevel 1 exit /b 1
74
- echo.
75
- echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
76
- goto end
77
- )
78
-
79
- if "%1" == "singlehtml" (
80
- %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
81
- if errorlevel 1 exit /b 1
82
- echo.
83
- echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
84
- goto end
85
- )
86
-
87
- if "%1" == "pickle" (
88
- %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
89
- if errorlevel 1 exit /b 1
90
- echo.
91
- echo.Build finished; now you can process the pickle files.
92
- goto end
93
- )
94
-
95
- if "%1" == "json" (
96
- %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
97
- if errorlevel 1 exit /b 1
98
- echo.
99
- echo.Build finished; now you can process the JSON files.
100
- goto end
101
- )
102
-
103
- if "%1" == "htmlhelp" (
104
- %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
105
- if errorlevel 1 exit /b 1
106
- echo.
107
- echo.Build finished; now you can run HTML Help Workshop with the ^
108
- .hhp project file in %BUILDDIR%/htmlhelp.
109
- goto end
110
- )
111
-
112
- if "%1" == "qthelp" (
113
- %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
114
- if errorlevel 1 exit /b 1
115
- echo.
116
- echo.Build finished; now you can run "qcollectiongenerator" with the ^
117
- .qhcp project file in %BUILDDIR%/qthelp, like this:
118
- echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PSBodyMeshPackage.qhcp
119
- echo.To view the help file:
120
- echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PSBodyMeshPackage.ghc
121
- goto end
122
- )
123
-
124
- if "%1" == "devhelp" (
125
- %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
126
- if errorlevel 1 exit /b 1
127
- echo.
128
- echo.Build finished.
129
- goto end
130
- )
131
-
132
- if "%1" == "epub" (
133
- %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
134
- if errorlevel 1 exit /b 1
135
- echo.
136
- echo.Build finished. The epub file is in %BUILDDIR%/epub.
137
- goto end
138
- )
139
-
140
- if "%1" == "latex" (
141
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
142
- if errorlevel 1 exit /b 1
143
- echo.
144
- echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
145
- goto end
146
- )
147
-
148
- if "%1" == "latexpdf" (
149
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
150
- cd %BUILDDIR%/latex
151
- make all-pdf
152
- cd %BUILDDIR%/..
153
- echo.
154
- echo.Build finished; the PDF files are in %BUILDDIR%/latex.
155
- goto end
156
- )
157
-
158
- if "%1" == "latexpdfja" (
159
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
160
- cd %BUILDDIR%/latex
161
- make all-pdf-ja
162
- cd %BUILDDIR%/..
163
- echo.
164
- echo.Build finished; the PDF files are in %BUILDDIR%/latex.
165
- goto end
166
- )
167
-
168
- if "%1" == "text" (
169
- %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
170
- if errorlevel 1 exit /b 1
171
- echo.
172
- echo.Build finished. The text files are in %BUILDDIR%/text.
173
- goto end
174
- )
175
-
176
- if "%1" == "man" (
177
- %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
178
- if errorlevel 1 exit /b 1
179
- echo.
180
- echo.Build finished. The manual pages are in %BUILDDIR%/man.
181
- goto end
182
- )
183
-
184
- if "%1" == "texinfo" (
185
- %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
186
- if errorlevel 1 exit /b 1
187
- echo.
188
- echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
189
- goto end
190
- )
191
-
192
- if "%1" == "gettext" (
193
- %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
194
- if errorlevel 1 exit /b 1
195
- echo.
196
- echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
197
- goto end
198
- )
199
-
200
- if "%1" == "changes" (
201
- %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
202
- if errorlevel 1 exit /b 1
203
- echo.
204
- echo.The overview file is in %BUILDDIR%/changes.
205
- goto end
206
- )
207
-
208
- if "%1" == "linkcheck" (
209
- %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
210
- if errorlevel 1 exit /b 1
211
- echo.
212
- echo.Link check complete; look for any errors in the above output ^
213
- or in %BUILDDIR%/linkcheck/output.txt.
214
- goto end
215
- )
216
-
217
- if "%1" == "doctest" (
218
- %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
219
- if errorlevel 1 exit /b 1
220
- echo.
221
- echo.Testing of doctests in the sources finished, look at the ^
222
- results in %BUILDDIR%/doctest/output.txt.
223
- goto end
224
- )
225
-
226
- if "%1" == "xml" (
227
- %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
228
- if errorlevel 1 exit /b 1
229
- echo.
230
- echo.Build finished. The XML files are in %BUILDDIR%/xml.
231
- goto end
232
- )
233
-
234
- if "%1" == "pseudoxml" (
235
- %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
236
- if errorlevel 1 exit /b 1
237
- echo.
238
- echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
239
- goto end
240
- )
241
-
242
- :end
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/source/conf.py DELETED
@@ -1,356 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # PSBody Mesh Package documentation build configuration file, created by
4
- # sphinx-quickstart on Wed Mar 23 07:26:06 2016.
5
- #
6
- # This file is execfile()d with the current directory set to its
7
- # containing dir.
8
- #
9
- # Note that not all possible configuration values are present in this
10
- # autogenerated file.
11
- #
12
- # All configuration values have a default; values that are commented out
13
- # serve to show the default.
14
-
15
- import sys
16
- import os
17
- import sphinx_bootstrap_theme
18
-
19
- root_source_folder = os.path.abspath(
20
- os.path.join(os.path.dirname(__file__),
21
- os.pardir,
22
- os.pardir))
23
- sys.path.insert(0, root_source_folder)
24
-
25
- from mesh.version import __version__
26
-
27
- print(root_source_folder)
28
- print("version {}".format(__version__))
29
-
30
- # If extensions (or modules to document with autodoc) are in another directory,
31
- # add these directories to sys.path here. If the directory is relative to the
32
- # documentation root, use os.path.abspath to make it absolute, like shown here.
33
- # sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)))
34
-
35
- # -- General configuration ------------------------------------------------
36
-
37
- # If your documentation needs a minimal Sphinx version, state it here.
38
- #needs_sphinx = '1.0'
39
-
40
- # Add any Sphinx extension module names here, as strings. They can be
41
- # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
42
- # ones.
43
- extensions = [
44
- 'sphinx.ext.autodoc',
45
- 'sphinx.ext.intersphinx',
46
- 'sphinx.ext.todo',
47
- 'sphinx.ext.coverage',
48
- 'sphinx.ext.mathjax',
49
- 'sphinx.ext.ifconfig',
50
- 'sphinx.ext.viewcode',
51
- 'sphinx.ext.autosummary',
52
- ]
53
-
54
- autoclass_content = 'both'
55
-
56
- # Add any paths that contain templates here, relative to this directory.
57
- templates_path = ['_templates']
58
-
59
- # The suffix of source filenames.
60
- source_suffix = '.rst'
61
-
62
- # The encoding of source files.
63
- #source_encoding = 'utf-8-sig'
64
-
65
- # The master toctree document.
66
- master_doc = 'index'
67
-
68
- # General information about the project.
69
- project = u'PSBody Mesh Package'
70
- copyright = u'2016, Max Planck Institute for Intelligent Systems, PSBody group'
71
-
72
- # The version info for the project you're documenting, acts as replacement for
73
- # |version| and |release|, also used in various other places throughout the
74
- # built documents.
75
-
76
- # The short X.Y version
77
- version = __version__
78
- # The full version, including alpha/beta/rc tags
79
- release = __version__
80
-
81
- # The language for content autogenerated by Sphinx. Refer to documentation
82
- # for a list of supported languages.
83
- #language = None
84
-
85
- # There are two options for replacing |today|: either, you set today to some
86
- # non-false value, then it is used:
87
- #today = ''
88
- # Else, today_fmt is used as the format for a strftime call.
89
- #today_fmt = '%B %d, %Y'
90
-
91
- # List of patterns, relative to source directory, that match files and
92
- # directories to ignore when looking for source files.
93
- exclude_patterns = []
94
-
95
- # The reST default role (used for this markup: `text`) to use for all
96
- # documents.
97
- #default_role = None
98
-
99
- # If true, '()' will be appended to :func: etc. cross-reference text.
100
- #add_function_parentheses = True
101
-
102
- # If true, the current module name will be prepended to all description
103
- # unit titles (such as .. function::).
104
- #add_module_names = True
105
-
106
- # If true, sectionauthor and moduleauthor directives will be shown in the
107
- # output. They are ignored by default.
108
- #show_authors = False
109
-
110
- # The name of the Pygments (syntax highlighting) style to use.
111
- pygments_style = 'sphinx'
112
-
113
- # A list of ignored prefixes for module index sorting.
114
- #modindex_common_prefix = []
115
-
116
- # If true, keep warnings as "system message" paragraphs in the built documents.
117
- #keep_warnings = False
118
-
119
-
120
- # -- Options for HTML output ----------------------------------------------
121
-
122
- # The theme to use for HTML and HTML Help pages. See the documentation for
123
- # a list of builtin themes.
124
- html_theme = 'bootstrap'
125
- html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
126
-
127
- # Theme options are theme-specific and customize the look and feel of a theme
128
- # further. For a list of options available for each theme, see the
129
- # documentation.
130
- #html_theme_options = {}
131
-
132
- # Add any paths that contain custom themes here, relative to this directory.
133
- #html_theme_path = []
134
-
135
- # The name for this set of Sphinx documents. If None, it defaults to
136
- # "<project> v<release> documentation".
137
- #html_title = None
138
-
139
- # A shorter title for the navigation bar. Default is the same as html_title.
140
- #html_short_title = None
141
-
142
- # The name of an image file (relative to this directory) to place at the top
143
- # of the sidebar.
144
- #html_logo = None
145
-
146
- # The name of an image file (within the static path) to use as favicon of the
147
- # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
148
- # pixels large.
149
- #html_favicon = None
150
-
151
- # Add any paths that contain custom static files (such as style sheets) here,
152
- # relative to this directory. They are copied after the builtin static files,
153
- # so a file named "default.css" will overwrite the builtin "default.css".
154
- html_static_path = ['_static']
155
-
156
- # Add any extra paths that contain custom files (such as robots.txt or
157
- # .htaccess) here, relative to this directory. These files are copied
158
- # directly to the root of the documentation.
159
- #html_extra_path = []
160
-
161
- # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
162
- # using the given strftime format.
163
- #html_last_updated_fmt = '%b %d, %Y'
164
-
165
- # If true, SmartyPants will be used to convert quotes and dashes to
166
- # typographically correct entities.
167
- #html_use_smartypants = True
168
-
169
- # Custom sidebar templates, maps document names to template names.
170
- #html_sidebars = {}
171
-
172
- # Additional templates that should be rendered to pages, maps page names to
173
- # template names.
174
- #html_additional_pages = {}
175
-
176
- # If false, no module index is generated.
177
- #html_domain_indices = True
178
-
179
- # If false, no index is generated.
180
- #html_use_index = True
181
-
182
- # If true, the index is split into individual pages for each letter.
183
- #html_split_index = False
184
-
185
- # If true, links to the reST sources are added to the pages.
186
- #html_show_sourcelink = True
187
-
188
- # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
189
- #html_show_sphinx = True
190
-
191
- # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
192
- #html_show_copyright = True
193
-
194
- # If true, an OpenSearch description file will be output, and all pages will
195
- # contain a <link> tag referring to it. The value of this option must be the
196
- # base URL from which the finished HTML is served.
197
- #html_use_opensearch = ''
198
-
199
- # This is the file name suffix for HTML files (e.g. ".xhtml").
200
- #html_file_suffix = None
201
-
202
- # Output file base name for HTML help builder.
203
- htmlhelp_basename = 'PSBodyMeshPackagedoc'
204
-
205
-
206
- # -- Options for LaTeX output ---------------------------------------------
207
-
208
- latex_elements = {
209
- # The paper size ('letterpaper' or 'a4paper').
210
- #'papersize': 'letterpaper',
211
-
212
- # The font size ('10pt', '11pt' or '12pt').
213
- #'pointsize': '10pt',
214
-
215
- # Additional stuff for the LaTeX preamble.
216
- #'preamble': '',
217
- }
218
-
219
- # Grouping the document tree into LaTeX files. List of tuples
220
- # (source start file, target name, title,
221
- # author, documentclass [howto, manual, or own class]).
222
- latex_documents = [
223
- ('index', 'PSBodyMeshPackage.tex', u'PSBody Mesh Package Documentation',
224
- u'Max Planck Institute for Intelligent Systems, PSBody group', 'manual'),
225
- ]
226
-
227
- # The name of an image file (relative to this directory) to place at the top of
228
- # the title page.
229
- #latex_logo = None
230
-
231
- # For "manual" documents, if this is true, then toplevel headings are parts,
232
- # not chapters.
233
- #latex_use_parts = False
234
-
235
- # If true, show page references after internal links.
236
- #latex_show_pagerefs = False
237
-
238
- # If true, show URL addresses after external links.
239
- #latex_show_urls = False
240
-
241
- # Documents to append as an appendix to all manuals.
242
- #latex_appendices = []
243
-
244
- # If false, no module index is generated.
245
- #latex_domain_indices = True
246
-
247
-
248
- # -- Options for manual page output ---------------------------------------
249
-
250
- # One entry per manual page. List of tuples
251
- # (source start file, name, description, authors, manual section).
252
- man_pages = [
253
- ('index', 'psbodymeshpackage', u'PSBody Mesh Package Documentation',
254
- [u'Max Planck Institute for Intelligent Systems, PSBody group'], 1)
255
- ]
256
-
257
- # If true, show URL addresses after external links.
258
- #man_show_urls = False
259
-
260
-
261
- # -- Options for Texinfo output -------------------------------------------
262
-
263
- # Grouping the document tree into Texinfo files. List of tuples
264
- # (source start file, target name, title, author,
265
- # dir menu entry, description, category)
266
- texinfo_documents = [
267
- ('index', 'PSBodyMeshPackage', u'PSBody Mesh Package Documentation',
268
- u'Max Planck Institute for Intelligent Systems, PSBody group', 'PSBodyMeshPackage', 'One line description of project.',
269
- 'Miscellaneous'),
270
- ]
271
-
272
- # Documents to append as an appendix to all manuals.
273
- #texinfo_appendices = []
274
-
275
- # If false, no module index is generated.
276
- #texinfo_domain_indices = True
277
-
278
- # How to display URL addresses: 'footnote', 'no', or 'inline'.
279
- #texinfo_show_urls = 'footnote'
280
-
281
- # If true, do not generate a @detailmenu in the "Top" node's menu.
282
- #texinfo_no_detailmenu = False
283
-
284
-
285
- # -- Options for Epub output ----------------------------------------------
286
-
287
- # Bibliographic Dublin Core info.
288
- epub_title = u'PSBody Mesh Package'
289
- epub_author = u'Max Planck Institute for Intelligent Systems, PSBody group'
290
- epub_publisher = u'Max Planck Institute for Intelligent Systems, PSBody group'
291
- epub_copyright = u'2016, Max Planck Institute for Intelligent Systems, PSBody group'
292
-
293
- # The basename for the epub file. It defaults to the project name.
294
- #epub_basename = u'PSBody Mesh Package'
295
-
296
- # The HTML theme for the epub output. Since the default themes are not optimized
297
- # for small screen space, using the same theme for HTML and epub output is
298
- # usually not wise. This defaults to 'epub', a theme designed to save visual
299
- # space.
300
- #epub_theme = 'epub'
301
-
302
- # The language of the text. It defaults to the language option
303
- # or en if the language is not set.
304
- #epub_language = ''
305
-
306
- # The scheme of the identifier. Typical schemes are ISBN or URL.
307
- #epub_scheme = ''
308
-
309
- # The unique identifier of the text. This can be a ISBN number
310
- # or the project homepage.
311
- #epub_identifier = ''
312
-
313
- # A unique identification for the text.
314
- #epub_uid = ''
315
-
316
- # A tuple containing the cover image and cover page html template filenames.
317
- #epub_cover = ()
318
-
319
- # A sequence of (type, uri, title) tuples for the guide element of content.opf.
320
- #epub_guide = ()
321
-
322
- # HTML files that should be inserted before the pages created by sphinx.
323
- # The format is a list of tuples containing the path and title.
324
- #epub_pre_files = []
325
-
326
- # HTML files shat should be inserted after the pages created by sphinx.
327
- # The format is a list of tuples containing the path and title.
328
- #epub_post_files = []
329
-
330
- # A list of files that should not be packed into the epub file.
331
- epub_exclude_files = ['search.html']
332
-
333
- # The depth of the table of contents in toc.ncx.
334
- #epub_tocdepth = 3
335
-
336
- # Allow duplicate toc entries.
337
- #epub_tocdup = True
338
-
339
- # Choose between 'default' and 'includehidden'.
340
- #epub_tocscope = 'default'
341
-
342
- # Fix unsupported image types using the PIL.
343
- #epub_fix_images = False
344
-
345
- # Scale large images.
346
- #epub_max_image_width = 0
347
-
348
- # How to display URL addresses: 'footnote', 'no', or 'inline'.
349
- #epub_show_urls = 'inline'
350
-
351
- # If false, no index is generated.
352
- #epub_use_index = True
353
-
354
-
355
- # Example configuration for intersphinx: refer to the Python standard library.
356
- intersphinx_mapping = {'http://docs.python.org/': None}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/source/index.rst DELETED
@@ -1,193 +0,0 @@
1
- .. PSBody Mesh Package documentation master file, created by
2
- sphinx-quickstart on Wed Mar 23 07:26:06 2016.
3
- You can adapt this file completely to your liking, but it should at least
4
- contain the root `toctree` directive.
5
-
6
- Welcome to PSBody Mesh Package's documentation!
7
- ===============================================
8
-
9
- This is the documentation of the Mesh package of the Body Group, Max Planck Institute
10
- for Intelligent Systems, Tübingen, Germany.
11
-
12
- Contents:
13
-
14
- .. toctree::
15
- :maxdepth: 2
16
-
17
- Mesh<pages/mesh>
18
- Mesh Viewer<pages/mesh_viewer>
19
- Geometry<pages/geometry>
20
-
21
-
22
- What is this package about?
23
- ===========================
24
-
25
- This package contains core functions for manipulating Meshes and visualizing them.
26
- It requires ``Python 3.5+`` and is supported on Linux and macOS operating systems.
27
-
28
- Getting started
29
- ===============
30
-
31
- Installation
32
- ------------
33
-
34
- You can download the latest release of the ``psbody-mesh`` package
35
- from the projects `GitHub repository <https://github.com/MPI-IS/mesh>`_.
36
- To install, first you should create a dedicated Python virtual
37
- environment and activate it:
38
-
39
- .. code::
40
-
41
- $ python3 -m venv --copies my_venv
42
- $ source my_venv/bin/activate
43
-
44
- To compile the binary extensions you will need to install the `Boost
45
- <http://www.boost.org>`_ libraries. You can compile your own local
46
- version or simply do:
47
-
48
- .. code::
49
-
50
- $ sudo apt-get install libboost-dev
51
-
52
- and then compile and install the ``psbody-mesh`` package using the
53
- Makefile. If you are using the system-wide ``Boost libraries``:
54
-
55
- .. code::
56
-
57
- $ make all
58
-
59
- or the libraries locally installed:
60
-
61
- .. code::
62
-
63
- $ BOOST_INCLUDE_DIRS=/path/to/boost/include make all
64
-
65
- Testing
66
- -------
67
-
68
- To run the tests simply do:
69
-
70
- .. code::
71
-
72
- $ make tests
73
-
74
- Documentation
75
- -------------
76
-
77
- A detailed documentation can be compiled using the Makefile:
78
-
79
- .. code::
80
-
81
- $ make documentation
82
-
83
- Loading a mesh
84
- --------------
85
-
86
- Loading a :py:class:`Mesh <psbody.mesh.mesh.Mesh>` class from a file is that easy:
87
-
88
- .. code::
89
-
90
- from psbody.mesh import Mesh
91
- my_mesh = Mesh(filename='mesh_filename.ply')
92
-
93
- Rendering a mesh
94
- ----------------
95
-
96
- From a previously loaded mesh ``my_mesh``, it is possible to visualize it inside an interactive window using the
97
- :py:class:`MeshViewers <psbody.mesh.meshviewer.MeshViewers>` class:
98
-
99
- .. code::
100
-
101
- from psbody.mesh import MeshViewers
102
-
103
- # creates a grid of 2x2 mesh viewers
104
- mvs = MeshViewers(shape=[2, 2])
105
-
106
- # sets the first (top-left) mesh to my_mesh
107
- mvs[0][0].set_static_meshes([my_mesh])
108
-
109
- Caching
110
- -------
111
-
112
- Some operations make use of caching for performance reasons. The default folder used for caching is
113
-
114
- .. code::
115
-
116
- ~/.psbody/mesh_package_cache
117
-
118
-
119
- If you need to specify the cache folder, define the environment variable ``PSBODY_MESH_CACHE``
120
- prior to any loading of the Mesh package:
121
-
122
- .. code::
123
-
124
- export PSBODY_MESH_CACHE="some/folder"
125
- python
126
- >> from psbody.mesh import Mesh
127
- # now uses the specified cache
128
-
129
- Mesh Viewer
130
- -----------
131
-
132
- ``meshviewer`` is a program that allows you to display polygonal meshes produced by ``mesh`` package.
133
-
134
- Viewing a mesh on a local machine
135
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
136
-
137
- The most straightforward use-case is viewing the mesh on the same machine where it is stored. To do this simply run
138
-
139
- .. code::
140
-
141
- $ meshviewer view sphere.obj
142
-
143
- This will create an interactive window with your mesh rendering. You can render more than one mesh in the same window by passing several paths to ``view`` command
144
-
145
- .. code::
146
-
147
- $ meshviewer view sphere.obj cylinder.obj
148
-
149
- This will arrange the subplots horizontally in a row. If you want a grid arrangement, you can specify the grid parameters explicitly
150
-
151
- .. code::
152
-
153
- $ meshviewer view -nx 2 -ny 2 *.obj
154
-
155
- Viewing a mesh from a remote machine
156
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
157
-
158
- It is also possible to view a mesh stored on a remote machine. To do this you need mesh to be installed on both the local and the remote machines. You start by opening an empty viewer window listening on a network port
159
-
160
- .. code::
161
-
162
- (local) $ meshviewer open --port 3000
163
-
164
- To stream a shape to this viewer you have to either pick a port that is visible from the remote machine or by manually exposing the port when connecting. For example, through SSH port forwarding
165
-
166
- .. code::
167
-
168
- (local) $ ssh -R 3000:127.0.0.1:3000 user@host
169
-
170
- Then on a remote machine you use ``view`` command pointing to the locally forwarded port
171
-
172
- .. code::
173
-
174
- (remote) $ meshviewer view -p 3000 sphere.obj
175
-
176
- This should display the remote mesh on your local viewer. In case it does not it might be caused by the network connection being closed before the mesh could be sent. To work around this one can try increasing the timeout up to 1 second
177
-
178
- .. code::
179
-
180
- (remote) $ meshviewer view -p 3000 --timeout 1 sphere.obj
181
-
182
- To take a snapshot you should locally run a `snap` command
183
-
184
- .. code::
185
-
186
- (local) $ meshviewer snap -p 3000 sphere.png
187
-
188
- Indices and tables
189
- ==================
190
-
191
- * :ref:`genindex`
192
- * :ref:`modindex`
193
- * :ref:`search`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/source/pages/geometry.rst DELETED
@@ -1,29 +0,0 @@
1
- Geometry
2
- ========
3
-
4
- The geometry subpackage contains some utilities on the geometric entities.
5
-
6
- .. autosummary::
7
-
8
- psbody.mesh.geometry.triangle_area.triangle_area
9
- psbody.mesh.geometry.rodrigues.rodrigues
10
- psbody.mesh.geometry.barycentric_coordinates_of_projection.barycentric_coordinates_of_projection
11
- psbody.mesh.geometry.cross_product.CrossProduct
12
-
13
-
14
- Reference
15
- ---------
16
-
17
- .. automodule:: psbody.mesh.geometry.triangle_area
18
- :members:
19
-
20
- .. automodule:: psbody.mesh.geometry.rodrigues
21
- :members:
22
-
23
- .. automodule:: psbody.mesh.geometry.barycentric_coordinates_of_projection
24
- :members:
25
-
26
- .. automodule:: psbody.mesh.geometry.cross_product
27
- :members:
28
-
29
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/source/pages/mesh.rst DELETED
@@ -1,31 +0,0 @@
1
- Mesh
2
- ====
3
-
4
- The :py:class:`Mesh <psbody.mesh.mesh.Mesh>` class is the core class of the Mesh package.
5
-
6
- Loading and Saving a mesh
7
- -------------------------
8
-
9
- The entry point for loading a mesh is :py:func:`Mesh.load_from_file <psbody.mesh.mesh.Mesh.load_from_file>`.
10
-
11
- Supported file formats:
12
-
13
- * ply
14
- * obj
15
-
16
- Querying meshes
17
- ---------------
18
- Meshes contain functions to query their content efficiently.
19
-
20
- Transforming meshes
21
- -------------------
22
-
23
-
24
- Reference
25
- ---------
26
-
27
- .. automodule:: psbody.mesh.mesh
28
- :members:
29
- :undoc-members:
30
-
31
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/doc/source/pages/mesh_viewer.rst DELETED
@@ -1,11 +0,0 @@
1
- Mesh viewer
2
- ===========
3
-
4
-
5
- Reference
6
- ---------
7
-
8
- .. automodule:: psbody.mesh.meshviewer
9
- :members:
10
- :undoc-members:
11
-
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/CMakeLists.txt DELETED
@@ -1,99 +0,0 @@
1
- # Copyright 2016, Max Planck Society.
2
- # Not licensed
3
- # author Raffi Enficiaud
4
-
5
- cmake_minimum_required (VERSION 2.8.12)
6
- set_property(GLOBAL PROPERTY USE_FOLDERS ON)
7
-
8
- enable_testing()
9
-
10
- project(Mesh)
11
-
12
- add_custom_target(cmake_files SOURCES
13
- cmake/python_helper.cmake
14
- cmake/thirdparty.cmake
15
- src/hijack_python_headers.hpp)
16
-
17
- include(cmake/thirdparty.cmake)
18
- include(cmake/python_helper.cmake)
19
-
20
-
21
- include_directories(${PYTHON_INCLUDE_PATH})
22
-
23
- set(MESHPYTHON_SRC
24
- __init__.py
25
- mesh.py
26
- meshviewer.py
27
- colors.py
28
- search.py
29
- )
30
-
31
- # for convenience
32
- add_custom_target(MeshPython SOURCES ${MESHPYTHON_SRC})
33
-
34
-
35
-
36
-
37
- # aabb_normals
38
- # CGAL_NDEBUG removes calls to logging, warning and error functions that would need
39
- # a link to the CGAL libraries
40
- # CGAL_HAS_NO_THREADS removes the thread safety of the AABB tree with the advantage
41
- # of removing the dependency to boost::thread (and indirectly boost::system compiled library)
42
- # MESH_CGAL_AVOID_COMPILED_VERSION is a define of our own in order to hack a remaining
43
- # log of error without the need to include CGAL generated libraries
44
- # CGAL_NO_AUTOLINK_CGA prevents autolinking on Visual
45
-
46
- set(DEFINES_MESH_EXTENSIONS_WITH_CGAL_WITHOUT_LINK
47
- -DCGAL_NDEBUG=1
48
- -DMESH_CGAL_AVOID_COMPILED_VERSION=1
49
- -DCGAL_HAS_NO_THREADS=1
50
- -DCGAL_NO_AUTOLINK_CGAL=1)
51
-
52
- python_add_library(TARGET aabb_normals SOURCES
53
- src/cgal_error_emulation.hpp
54
- src/AABB_n_tree.h
55
- src/aabb_normals.cpp)
56
- set_property(TARGET aabb_normals PROPERTY FOLDER "GeometryExt/")
57
- target_include_directories(aabb_normals PRIVATE
58
- ${libcgalroot}/include
59
- ${NUMPY_INCLUDE_PATH}
60
- ${Boost_INCLUDE_DIRS})
61
- target_compile_definitions(aabb_normals PRIVATE
62
- ${DEFINES_MESH_EXTENSIONS_WITH_CGAL_WITHOUT_LINK})
63
-
64
-
65
- # spatial search
66
- python_add_library(TARGET spatialsearch SOURCES
67
- src/cgal_error_emulation.hpp
68
- src/nearest_point_triangle_3.h
69
- src/nearest_triangle_normals.hpp
70
- src/nearest_triangle.hpp
71
-
72
- src/spatialsearchmodule.cpp
73
- )
74
- set_property(TARGET spatialsearch PROPERTY FOLDER "GeometryExt/")
75
- target_include_directories(spatialsearch PRIVATE
76
- ${libcgalroot}/include
77
- ${NUMPY_INCLUDE_PATH}
78
- ${Boost_INCLUDE_DIRS})
79
- target_compile_definitions(spatialsearch PRIVATE
80
- ${DEFINES_MESH_EXTENSIONS_WITH_CGAL_WITHOUT_LINK})
81
-
82
-
83
-
84
- # serialization extensions
85
-
86
- # plyutils
87
- python_add_library(TARGET plyutils SOURCES
88
- src/plyutils.h
89
- src/plyutils.c
90
- src/rply.h
91
- src/rply.c)
92
- set_property(TARGET plyutils PROPERTY FOLDER "SerializationExt/")
93
-
94
- # loadobj
95
- python_add_library(TARGET loadobj SOURCES src/py_loadobj.cpp)
96
- target_include_directories(loadobj PRIVATE
97
- ${NUMPY_INCLUDE_PATH}
98
- ${Boost_INCLUDE_DIRS})
99
- set_property(TARGET loadobj PROPERTY FOLDER "SerializationExt/")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/__init__.py DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
-
6
- import os
7
- from os.path import abspath, dirname, expanduser, join
8
-
9
- from .mesh import Mesh
10
- from .meshviewer import MeshViewer, MeshViewers
11
-
12
- texture_path = abspath(join(dirname(__file__), '..', 'data', 'template', 'texture_coordinates'))
13
-
14
- if 'PSBODY_MESH_CACHE' in os.environ:
15
- mesh_package_cache_folder = expanduser(os.environ['PSBODY_MESH_CACHE'])
16
- else:
17
- mesh_package_cache_folder = expanduser('~/.psbody/mesh_package_cache')
18
-
19
- if not os.path.exists(mesh_package_cache_folder):
20
- os.makedirs(mesh_package_cache_folder)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/arcball.py DELETED
@@ -1,247 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
4
-
5
- """
6
- Math utilities, vector, matrix types and ArcBall quaternion rotation class
7
- ==========================================================================
8
-
9
- """
10
-
11
- import numpy as Numeric
12
- import copy
13
- from math import sqrt
14
-
15
- # //assuming IEEE-754(GLfloat), which i believe has max precision of 7 bits
16
- Epsilon = 1.0e-5
17
-
18
-
19
- class ArcBallT(object):
20
- def __init__(self, NewWidth, NewHeight):
21
- self.m_StVec = Vector3fT()
22
- self.m_EnVec = Vector3fT()
23
- self.m_AdjustWidth = 1.0
24
- self.m_AdjustHeight = 1.0
25
- self.setBounds(NewWidth, NewHeight)
26
-
27
- def __str__(self):
28
- str_rep = ""
29
- str_rep += "StVec = " + str(self.m_StVec)
30
- str_rep += "\nEnVec = " + str(self.m_EnVec)
31
- str_rep += "\n scale coords %f %f" % (self.m_AdjustWidth, self.m_AdjustHeight)
32
- return str_rep
33
-
34
- def setBounds(self, NewWidth, NewHeight):
35
- # //Set new bounds
36
- assert (NewWidth > 1.0 and NewHeight > 1.0), "Invalid width or height for bounds."
37
- # //Set adjustment factor for width/height
38
- self.m_AdjustWidth = 1.0 / ((NewWidth - 1.0) * 0.5)
39
- self.m_AdjustHeight = 1.0 / ((NewHeight - 1.0) * 0.5)
40
-
41
- def _mapToSphere(self, NewPt):
42
- # Given a new window coordinate, will modify NewVec in place
43
- X = 0
44
- Y = 1
45
- Z = 2
46
-
47
- NewVec = Vector3fT()
48
- # //Copy paramter into temp point
49
- TempPt = copy.copy(NewPt)
50
- # //Adjust point coords and scale down to range of [-1 ... 1]
51
- TempPt[X] = (NewPt[X] * self.m_AdjustWidth) - 1.0
52
- TempPt[Y] = 1.0 - (NewPt[Y] * self.m_AdjustHeight)
53
- # //Compute the square of the length of the vector to the point from the center
54
- length = Numeric.sum(Numeric.dot(TempPt, TempPt))
55
- # //If the point is mapped outside of the sphere... (length > radius squared)
56
- if (length > 1.0):
57
- # //Compute a normalizing factor (radius / sqrt(length))
58
- norm = 1.0 / sqrt(length)
59
-
60
- # //Return the "normalized" vector, a point on the sphere
61
- NewVec[X] = TempPt[X] * norm
62
- NewVec[Y] = TempPt[Y] * norm
63
- NewVec[Z] = 0.0
64
- else: # //Else it's on the inside
65
- # //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
66
- NewVec[X] = TempPt[X]
67
- NewVec[Y] = TempPt[Y]
68
- NewVec[Z] = sqrt(1.0 - length)
69
-
70
- return NewVec
71
-
72
- def click(self, NewPt):
73
- # Mouse down (Point2fT
74
- self.m_StVec = self._mapToSphere(NewPt)
75
- return
76
-
77
- def drag(self, NewPt):
78
- # Mouse drag, calculate rotation (Point2fT Quat4fT)
79
- """ drag (Point2fT mouse_coord) -> new_quaternion_rotation_vec
80
- """
81
- X = 0
82
- Y = 1
83
- Z = 2
84
- W = 3
85
-
86
- self.m_EnVec = self._mapToSphere(NewPt)
87
-
88
- # //Compute the vector perpendicular to the begin and end vectors
89
- # Perp = Vector3fT ()
90
- Perp = Vector3fCross(self.m_StVec, self.m_EnVec)
91
-
92
- NewRot = Quat4fT()
93
- # Compute the length of the perpendicular vector
94
- if (Vector3fLength(Perp) > Epsilon):
95
- # if its non-zero
96
- # We're ok, so return the perpendicular vector as the transform after all
97
- NewRot[X] = Perp[X]
98
- NewRot[Y] = Perp[Y]
99
- NewRot[Z] = Perp[Z]
100
- # //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
101
- NewRot[W] = Vector3fDot(self.m_StVec, self.m_EnVec)
102
- else:
103
- # if its zero
104
- # The begin and end vectors coincide, so return a quaternion of zero matrix (no rotation)
105
- NewRot[X] = NewRot[Y] = NewRot[Z] = NewRot[W] = 0.0
106
-
107
- return NewRot
108
-
109
-
110
- def Matrix4fT():
111
- return Numeric.identity(4, 'f')
112
-
113
-
114
- def Matrix3fT():
115
- return Numeric.identity(3, 'f')
116
-
117
-
118
- def Quat4fT():
119
- return Numeric.zeros(4, 'f')
120
-
121
-
122
- def Vector3fT():
123
- return Numeric.zeros(3, 'f')
124
-
125
-
126
- def Point2fT(x=0.0, y=0.0):
127
- pt = Numeric.zeros(2, 'f')
128
- pt[0] = x
129
- pt[1] = y
130
- return pt
131
-
132
-
133
- def Vector3fDot(u, v):
134
- # Dot product of two 3f vectors
135
- dotprod = Numeric.dot(u, v)
136
- return dotprod
137
-
138
-
139
- def Vector3fCross(u, v):
140
- # Cross product of two 3f vectors
141
- X = 0
142
- Y = 1
143
- Z = 2
144
- cross = Numeric.zeros(3, 'f')
145
- cross[X] = (u[Y] * v[Z]) - (u[Z] * v[Y])
146
- cross[Y] = (u[Z] * v[X]) - (u[X] * v[Z])
147
- cross[Z] = (u[X] * v[Y]) - (u[Y] * v[X])
148
- return cross
149
-
150
-
151
- def Vector3fLength(u):
152
- mag_squared = Numeric.sum(Numeric.dot(u, u))
153
- mag = sqrt(mag_squared)
154
- return mag
155
-
156
-
157
- def Matrix3fSetIdentity():
158
- return Numeric.identity(3, 'f')
159
-
160
-
161
- def Matrix3fMulMatrix3f(matrix_a, matrix_b):
162
- return matrix_a.dot(matrix_b)
163
-
164
-
165
- def Matrix4fSVD(NewObj):
166
- X = 0
167
- Y = 1
168
- Z = 2
169
- s = sqrt(((NewObj[X][X] * NewObj[X][X]) + (NewObj[X][Y] * NewObj[X][Y]) + (NewObj[X][Z] * NewObj[X][Z]) +
170
- (NewObj[Y][X] * NewObj[Y][X]) + (NewObj[Y][Y] * NewObj[Y][Y]) + (NewObj[Y][Z] * NewObj[Y][Z]) +
171
- (NewObj[Z][X] * NewObj[Z][X]) + (NewObj[Z][Y] * NewObj[Z][Y]) + (NewObj[Z][Z] * NewObj[Z][Z])) / 3.0)
172
- return s
173
-
174
-
175
- def Matrix4fSetRotationScaleFromMatrix3f(NewObj, three_by_three_matrix):
176
- """Modifies NewObj in-place by replacing its upper 3x3 portion from the
177
- passed in 3x3 matrix.
178
-
179
- :param NewObj: a `Matrix4fT`
180
- """
181
- NewObj[0:3, 0:3] = three_by_three_matrix
182
- return NewObj
183
-
184
-
185
- def Matrix4fSetRotationFromMatrix3f(NewObj, three_by_three_matrix):
186
- """
187
- Sets the rotational component (upper 3x3) of this matrix to the matrix
188
- values in the T precision Matrix3d argument; the other elements of
189
- this matrix are unchanged; a singular value decomposition is performed
190
- on this object's upper 3x3 matrix to factor out the scale, then this
191
- object's upper 3x3 matrix components are replaced by the passed rotation
192
- components, and then the scale is reapplied to the rotational
193
- components.
194
-
195
- :param three_by_three_matrix: T precision 3x3 matrix
196
- """
197
- scale = Matrix4fSVD(NewObj)
198
-
199
- NewObj = Matrix4fSetRotationScaleFromMatrix3f(NewObj, three_by_three_matrix)
200
- scaled_NewObj = NewObj * scale # Matrix4fMulRotationScale(NewObj, scale);
201
- return scaled_NewObj
202
-
203
-
204
- def Matrix3fSetRotationFromQuat4f(q1):
205
- """Converts the H quaternion q1 into a new equivalent 3x3 rotation matrix."""
206
- X = 0
207
- Y = 1
208
- Z = 2
209
- W = 3
210
-
211
- NewObj = Matrix3fT()
212
- n = Numeric.sum(Numeric.dot(q1, q1))
213
- s = 0.0
214
- if (n > 0.0):
215
- s = 2.0 / n
216
-
217
- xs = q1[X] * s
218
- ys = q1[Y] * s
219
- zs = q1[Z] * s
220
-
221
- wx = q1[W] * xs
222
- wy = q1[W] * ys
223
- wz = q1[W] * zs
224
-
225
- xx = q1[X] * xs
226
- xy = q1[X] * ys
227
- xz = q1[X] * zs
228
-
229
- yy = q1[Y] * ys
230
- yz = q1[Y] * zs
231
- zz = q1[Z] * zs
232
-
233
- # This math all comes about by way of algebra, complex math, and trig identities.
234
- # See Lengyel pages 88-92
235
- NewObj[X][X] = 1.0 - (yy + zz)
236
- NewObj[Y][X] = xy - wz
237
- NewObj[Z][X] = xz + wy
238
-
239
- NewObj[X][Y] = xy + wz
240
- NewObj[Y][Y] = 1.0 - (xx + zz)
241
- NewObj[Z][Y] = yz - wx
242
-
243
- NewObj[X][Z] = xz - wy
244
- NewObj[Y][Z] = yz + wx
245
- NewObj[Z][Z] = 1.0 - (xx + yy)
246
-
247
- return NewObj
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/cmake/python_helper.cmake DELETED
@@ -1,74 +0,0 @@
1
- # Copyright 2016, Max Planck Society.
2
- # Not licensed
3
- # author Raffi Enficiaud
4
-
5
- # helper file containing commands easing the declaration of python modules
6
-
7
- include(CMakeParseArguments)
8
-
9
-
10
- #.rst:
11
- # .. command:: python_add_library
12
- #
13
- # Adds a shared library that is meant to be a python extension module.
14
- # The added library links to python library and has the proper extension.
15
- #
16
- # ::
17
- #
18
- # python_add_library(
19
- # TARGET targetname
20
- # SOURCES source_list)
21
- #
22
- # ``targetname`` name of the python extension
23
- # ``source_list`` list of source files for this target.
24
- #
25
- function(python_add_library)
26
-
27
- if("${PYTHON_MODULES_EXTENSIONS}" STREQUAL "")
28
- if("${PYTHON_VERSION}" VERSION_GREATER "2.5")
29
- if(UNIX OR MINGW)
30
- set(PYTHON_MODULES_EXTENSIONS_TEMP ".so")
31
- else()
32
- set(PYTHON_MODULES_EXTENSIONS_TEMP ".pyd")
33
- endif()
34
- else()
35
- if(APPLE)
36
- set(PYTHON_MODULES_EXTENSIONS_TEMP ".so")
37
- else()
38
- set(PYTHON_MODULES_EXTENSIONS_TEMP ${CMAKE_SHARED_LIBRARY_SUFFIX})
39
- endif()
40
- endif()
41
- set(PYTHON_MODULES_EXTENSIONS ${PYTHON_MODULES_EXTENSIONS_TEMP} CACHE STRING "Python modules extension for the current platform")
42
- endif()
43
-
44
-
45
- set(options )
46
- set(oneValueArgs TARGET)
47
- set(multiValueArgs SOURCES)
48
- cmake_parse_arguments(local_python_add_cmd "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
49
-
50
- if("${local_python_add_cmd_TARGET}" STREQUAL "")
51
- message(FATAL_ERROR "python_add_library: the TARGET should be specified")
52
- endif()
53
-
54
- if("${local_python_add_cmd_SOURCES}" STREQUAL "")
55
- message(FATAL_ERROR "python_add_library: at least one source file should be specified")
56
- endif()
57
-
58
- add_library(${local_python_add_cmd_TARGET} SHARED
59
- src/hijack_python_headers.hpp # by default
60
- "${local_python_add_cmd_SOURCES}")
61
- target_include_directories(${local_python_add_cmd_TARGET} PRIVATE ${PYTHON_INCLUDE_PATH})
62
- target_link_libraries(${local_python_add_cmd_TARGET} ${PYTHON_LIBRARY}) # PYTHON_LIBRARIES may contain the debug version of python, which we do not want
63
- set_target_properties(${local_python_add_cmd_TARGET}
64
- PROPERTIES SUFFIX ${PYTHON_MODULES_EXTENSIONS}
65
- PREFIX "")
66
-
67
- if(FALSE)
68
- set_target_properties(${local_python_add_cmd_TARGET}
69
- PROPERTIES
70
- OUTPUT_NAME_DEBUG ${local_python_add_cmd_TARGET}_d
71
- )
72
- endif()
73
-
74
- endfunction(python_add_library)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/cmake/thirdparty.cmake DELETED
@@ -1,107 +0,0 @@
1
- # Copyright 2016, Max Planck Society.
2
- # Not licensed
3
- # author Raffi Enficiaud
4
-
5
- # this file contains all the necessary to link against thirdparty libraries
6
-
7
- # location of the stored thirdparty archives
8
- set(thirdparty_dir ${CMAKE_SOURCE_DIR}/thirdparty)
9
-
10
- # the location where the archives will be deflated, to avoid pollution
11
- # of the source tree
12
- set(thirdparties_deflate_directory ${CMAKE_BINARY_DIR}/external_libs_deflate)
13
- if(NOT EXISTS ${thirdparties_deflate_directory})
14
- file(MAKE_DIRECTORY ${thirdparties_deflate_directory})
15
- endif()
16
-
17
- # this module may be used to find system installed libraries on Linux
18
- if(UNIX AND NOT APPLE)
19
- find_package(PkgConfig)
20
- endif()
21
-
22
-
23
- # Python libraries, required
24
- find_package(PythonLibs REQUIRED)
25
- find_package(PythonInterp REQUIRED)
26
-
27
- # numpy
28
- execute_process(
29
- COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.get_include()"
30
- OUTPUT_VARIABLE NUMPY_INCLUDE_PATH
31
- ERROR_VARIABLE NUMPY_ERROR
32
- OUTPUT_STRIP_TRAILING_WHITESPACE
33
- )
34
- if(NOT (NUMPY_ERROR STREQUAL "") OR (NUMPY_INCLUDE_PATH STREQUAL ""))
35
- message(FATAL_ERROR "[numpy] the following error occured: ${NUMPY_ERROR} - Consider setting PYTHON_ROOT in the environment")
36
- endif()
37
- message(STATUS "[numpy] found headers in ${NUMPY_INCLUDE_PATH}")
38
-
39
-
40
- # cgal
41
- set(CGAL_MAJOR_VERSION 4)
42
- set(CGAL_MINOR_VERSION 7)
43
- set(CGAL_VERSION ${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION})
44
- set(LIBCGAL CGAL-${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION})
45
- set(libcgalroot ${thirdparties_deflate_directory}/${LIBCGAL})
46
-
47
- if(NOT EXISTS ${libcgalroot})
48
- message(STATUS "Untarring ${LIBCGAL}")
49
- execute_process(
50
- COMMAND ${CMAKE_COMMAND} -E tar xzf ${thirdparty_dir}/${LIBCGAL}.tar.gz
51
- WORKING_DIRECTORY ${thirdparties_deflate_directory})
52
- endif()
53
-
54
- if(NOT EXISTS ${libcgalroot}/include/CGAL/compiler_config.h)
55
- message(STATUS "[CGAL] creating empty configuration file for header only compilation")
56
- file(WRITE
57
- ${libcgalroot}/include/CGAL/compiler_config.h
58
- "// automatically generated by mesh cmake")
59
- endif()
60
-
61
-
62
-
63
- # boost (needed by CGAL)
64
- if(NOT BOOST_ROOT)
65
- message(STATUS "[BOOST] Boost root not configured, taking the system boost version")
66
- set(MESH_BOOST_FROM_SYSTEM TRUE)
67
- else()
68
- message(STATUS "[BOOST] Boost root directory set to ${BOOST_ROOT}")
69
- set(MESH_BOOST_FROM_SYSTEM FALSE)
70
- endif()
71
-
72
- if(UNIX AND NOT APPLE AND NOT MESH_BOOST_FROM_SYSTEM)
73
- message(WARNING "[BOOST] you are setting a different boost than the one provided by the system. This option should be taken with care.")
74
- endif()
75
-
76
- set(Boost_ADDITIONAL_VERSIONS
77
- "1.54" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57.0" "1.58" "1.58.0" "1.59" "1.59.0"
78
- "1.60" "1.60.0" "1.61" "1.61.0")
79
-
80
-
81
- add_definitions(-DBOOST_ALL_NO_LIB) # disable auto link
82
- set(Boost_USE_STATIC_LIBS OFF) # linking with static library version (not used because of the header only)
83
- if(NOT Boost_USE_STATIC_LIBS)
84
- # link against dynamic libraries
85
- add_definitions(-DBOOST_ALL_DYN_LINK)
86
- endif()
87
-
88
- # if we are using the system version, we do not want to have the exact version embedded in the rpath/ldd
89
- if(MESH_BOOST_FROM_SYSTEM)
90
- set(Boost_REALPATH OFF)
91
- else()
92
- set(Boost_REALPATH ON)
93
- endif()
94
-
95
- set(Boost_USE_MULTITHREADED ON)
96
- set(Boost_DEBUG ON)
97
- set(Boost_DETAILED_FAILURE_MSG ON)
98
- if(DEFINED BOOST_ROOT)
99
- set(Boost_NO_SYSTEM_PATHS ON)
100
- else()
101
- set(Boost_NO_SYSTEM_PATHS OFF)
102
- endif()
103
- set(Boost_NO_BOOST_CMAKE ON)
104
-
105
- # only the header locations
106
- find_package(Boost 1.59)
107
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/colors.py DELETED
@@ -1,790 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
4
- # Created by Matthew Loper on 2012-05-12.
5
-
6
- """
7
- Colors utilities
8
- ================
9
-
10
-
11
- """
12
-
13
- import re
14
- import numpy as np
15
-
16
-
17
- def main():
18
- """Generates code for name_to_rgb dict, assuming an rgb.txt file available (in X11 format)."""
19
- with open('rgb.txt') as fp:
20
-
21
- line = fp.readline()
22
- while line:
23
- reg = re.match('\s*(\d+)\s*(\d+)\s*(\d+)\s*(\w.*\w).*', line)
24
- if reg:
25
- r = int(reg.group(1)) / 255.
26
- g = int(reg.group(2)) / 255.
27
- b = int(reg.group(3)) / 255.
28
- d = reg.group(4)
29
- print("'%s': np.array([%.2f, %.2f, %.2f])," % (d, r, g, b))
30
- line = fp.readline()
31
-
32
-
33
- name_to_rgb = {
34
- 'snow': np.array([1.00, 0.98, 0.98]),
35
- 'ghost white': np.array([0.97, 0.97, 1.00]),
36
- 'GhostWhite': np.array([0.97, 0.97, 1.00]),
37
- 'white smoke': np.array([0.96, 0.96, 0.96]),
38
- 'WhiteSmoke': np.array([0.96, 0.96, 0.96]),
39
- 'gainsboro': np.array([0.86, 0.86, 0.86]),
40
- 'floral white': np.array([1.00, 0.98, 0.94]),
41
- 'FloralWhite': np.array([1.00, 0.98, 0.94]),
42
- 'old lace': np.array([0.99, 0.96, 0.90]),
43
- 'OldLace': np.array([0.99, 0.96, 0.90]),
44
- 'linen': np.array([0.98, 0.94, 0.90]),
45
- 'antique white': np.array([0.98, 0.92, 0.84]),
46
- 'AntiqueWhite': np.array([0.98, 0.92, 0.84]),
47
- 'papaya whip': np.array([1.00, 0.94, 0.84]),
48
- 'PapayaWhip': np.array([1.00, 0.94, 0.84]),
49
- 'blanched almond': np.array([1.00, 0.92, 0.80]),
50
- 'BlanchedAlmond': np.array([1.00, 0.92, 0.80]),
51
- 'bisque': np.array([1.00, 0.89, 0.77]),
52
- 'peach puff': np.array([1.00, 0.85, 0.73]),
53
- 'PeachPuff': np.array([1.00, 0.85, 0.73]),
54
- 'navajo white': np.array([1.00, 0.87, 0.68]),
55
- 'NavajoWhite': np.array([1.00, 0.87, 0.68]),
56
- 'moccasin': np.array([1.00, 0.89, 0.71]),
57
- 'cornsilk': np.array([1.00, 0.97, 0.86]),
58
- 'ivory': np.array([1.00, 1.00, 0.94]),
59
- 'lemon chiffon': np.array([1.00, 0.98, 0.80]),
60
- 'LemonChiffon': np.array([1.00, 0.98, 0.80]),
61
- 'seashell': np.array([1.00, 0.96, 0.93]),
62
- 'honeydew': np.array([0.94, 1.00, 0.94]),
63
- 'mint cream': np.array([0.96, 1.00, 0.98]),
64
- 'MintCream': np.array([0.96, 1.00, 0.98]),
65
- 'azure': np.array([0.94, 1.00, 1.00]),
66
- 'alice blue': np.array([0.94, 0.97, 1.00]),
67
- 'AliceBlue': np.array([0.94, 0.97, 1.00]),
68
- 'lavender': np.array([0.90, 0.90, 0.98]),
69
- 'lavender blush': np.array([1.00, 0.94, 0.96]),
70
- 'LavenderBlush': np.array([1.00, 0.94, 0.96]),
71
- 'misty rose': np.array([1.00, 0.89, 0.88]),
72
- 'MistyRose': np.array([1.00, 0.89, 0.88]),
73
- 'white': np.array([1.00, 1.00, 1.00]),
74
- 'black': np.array([0.00, 0.00, 0.00]),
75
- 'dark slate gray': np.array([0.18, 0.31, 0.31]),
76
- 'DarkSlateGray': np.array([0.18, 0.31, 0.31]),
77
- 'dark slate grey': np.array([0.18, 0.31, 0.31]),
78
- 'DarkSlateGrey': np.array([0.18, 0.31, 0.31]),
79
- 'dim gray': np.array([0.41, 0.41, 0.41]),
80
- 'DimGray': np.array([0.41, 0.41, 0.41]),
81
- 'dim grey': np.array([0.41, 0.41, 0.41]),
82
- 'DimGrey': np.array([0.41, 0.41, 0.41]),
83
- 'slate gray': np.array([0.44, 0.50, 0.56]),
84
- 'SlateGray': np.array([0.44, 0.50, 0.56]),
85
- 'slate grey': np.array([0.44, 0.50, 0.56]),
86
- 'SlateGrey': np.array([0.44, 0.50, 0.56]),
87
- 'light slate gray': np.array([0.47, 0.53, 0.60]),
88
- 'LightSlateGray': np.array([0.47, 0.53, 0.60]),
89
- 'light slate grey': np.array([0.47, 0.53, 0.60]),
90
- 'LightSlateGrey': np.array([0.47, 0.53, 0.60]),
91
- 'gray': np.array([0.75, 0.75, 0.75]),
92
- 'grey': np.array([0.75, 0.75, 0.75]),
93
- 'light grey': np.array([0.83, 0.83, 0.83]),
94
- 'LightGrey': np.array([0.83, 0.83, 0.83]),
95
- 'light gray': np.array([0.83, 0.83, 0.83]),
96
- 'LightGray': np.array([0.83, 0.83, 0.83]),
97
- 'midnight blue': np.array([0.10, 0.10, 0.44]),
98
- 'MidnightBlue': np.array([0.10, 0.10, 0.44]),
99
- 'navy': np.array([0.00, 0.00, 0.50]),
100
- 'navy blue': np.array([0.00, 0.00, 0.50]),
101
- 'NavyBlue': np.array([0.00, 0.00, 0.50]),
102
- 'cornflower blue': np.array([0.39, 0.58, 0.93]),
103
- 'CornflowerBlue': np.array([0.39, 0.58, 0.93]),
104
- 'dark slate blue': np.array([0.28, 0.24, 0.55]),
105
- 'DarkSlateBlue': np.array([0.28, 0.24, 0.55]),
106
- 'slate blue': np.array([0.42, 0.35, 0.80]),
107
- 'SlateBlue': np.array([0.42, 0.35, 0.80]),
108
- 'medium slate blue': np.array([0.48, 0.41, 0.93]),
109
- 'MediumSlateBlue': np.array([0.48, 0.41, 0.93]),
110
- 'light slate blue': np.array([0.52, 0.44, 1.00]),
111
- 'LightSlateBlue': np.array([0.52, 0.44, 1.00]),
112
- 'medium blue': np.array([0.00, 0.00, 0.80]),
113
- 'MediumBlue': np.array([0.00, 0.00, 0.80]),
114
- 'royal blue': np.array([0.25, 0.41, 0.88]),
115
- 'RoyalBlue': np.array([0.25, 0.41, 0.88]),
116
- 'blue': np.array([0.00, 0.00, 1.00]),
117
- 'dodger blue': np.array([0.12, 0.56, 1.00]),
118
- 'DodgerBlue': np.array([0.12, 0.56, 1.00]),
119
- 'deep sky blue': np.array([0.00, 0.75, 1.00]),
120
- 'DeepSkyBlue': np.array([0.00, 0.75, 1.00]),
121
- 'sky blue': np.array([0.53, 0.81, 0.92]),
122
- 'SkyBlue': np.array([0.53, 0.81, 0.92]),
123
- 'light sky blue': np.array([0.53, 0.81, 0.98]),
124
- 'LightSkyBlue': np.array([0.53, 0.81, 0.98]),
125
- 'steel blue': np.array([0.27, 0.51, 0.71]),
126
- 'SteelBlue': np.array([0.27, 0.51, 0.71]),
127
- 'light steel blue': np.array([0.69, 0.77, 0.87]),
128
- 'LightSteelBlue': np.array([0.69, 0.77, 0.87]),
129
- 'light blue': np.array([0.68, 0.85, 0.90]),
130
- 'LightBlue': np.array([0.68, 0.85, 0.90]),
131
- 'powder blue': np.array([0.69, 0.88, 0.90]),
132
- 'PowderBlue': np.array([0.69, 0.88, 0.90]),
133
- 'pale turquoise': np.array([0.69, 0.93, 0.93]),
134
- 'PaleTurquoise': np.array([0.69, 0.93, 0.93]),
135
- 'dark turquoise': np.array([0.00, 0.81, 0.82]),
136
- 'DarkTurquoise': np.array([0.00, 0.81, 0.82]),
137
- 'medium turquoise': np.array([0.28, 0.82, 0.80]),
138
- 'MediumTurquoise': np.array([0.28, 0.82, 0.80]),
139
- 'turquoise': np.array([0.25, 0.88, 0.82]),
140
- 'cyan': np.array([0.00, 1.00, 1.00]),
141
- 'light cyan': np.array([0.88, 1.00, 1.00]),
142
- 'LightCyan': np.array([0.88, 1.00, 1.00]),
143
- 'cadet blue': np.array([0.37, 0.62, 0.63]),
144
- 'CadetBlue': np.array([0.37, 0.62, 0.63]),
145
- 'medium aquamarine': np.array([0.40, 0.80, 0.67]),
146
- 'MediumAquamarine': np.array([0.40, 0.80, 0.67]),
147
- 'aquamarine': np.array([0.50, 1.00, 0.83]),
148
- 'dark green': np.array([0.00, 0.39, 0.00]),
149
- 'DarkGreen': np.array([0.00, 0.39, 0.00]),
150
- 'dark olive green': np.array([0.33, 0.42, 0.18]),
151
- 'DarkOliveGreen': np.array([0.33, 0.42, 0.18]),
152
- 'dark sea green': np.array([0.56, 0.74, 0.56]),
153
- 'DarkSeaGreen': np.array([0.56, 0.74, 0.56]),
154
- 'sea green': np.array([0.18, 0.55, 0.34]),
155
- 'SeaGreen': np.array([0.18, 0.55, 0.34]),
156
- 'medium sea green': np.array([0.24, 0.70, 0.44]),
157
- 'MediumSeaGreen': np.array([0.24, 0.70, 0.44]),
158
- 'light sea green': np.array([0.13, 0.70, 0.67]),
159
- 'LightSeaGreen': np.array([0.13, 0.70, 0.67]),
160
- 'pale green': np.array([0.60, 0.98, 0.60]),
161
- 'PaleGreen': np.array([0.60, 0.98, 0.60]),
162
- 'spring green': np.array([0.00, 1.00, 0.50]),
163
- 'SpringGreen': np.array([0.00, 1.00, 0.50]),
164
- 'lawn green': np.array([0.49, 0.99, 0.00]),
165
- 'LawnGreen': np.array([0.49, 0.99, 0.00]),
166
- 'green': np.array([0.00, 1.00, 0.00]),
167
- 'chartreuse': np.array([0.50, 1.00, 0.00]),
168
- 'medium spring green': np.array([0.00, 0.98, 0.60]),
169
- 'MediumSpringGreen': np.array([0.00, 0.98, 0.60]),
170
- 'green yellow': np.array([0.68, 1.00, 0.18]),
171
- 'GreenYellow': np.array([0.68, 1.00, 0.18]),
172
- 'lime green': np.array([0.20, 0.80, 0.20]),
173
- 'LimeGreen': np.array([0.20, 0.80, 0.20]),
174
- 'yellow green': np.array([0.60, 0.80, 0.20]),
175
- 'YellowGreen': np.array([0.60, 0.80, 0.20]),
176
- 'forest green': np.array([0.13, 0.55, 0.13]),
177
- 'ForestGreen': np.array([0.13, 0.55, 0.13]),
178
- 'olive drab': np.array([0.42, 0.56, 0.14]),
179
- 'OliveDrab': np.array([0.42, 0.56, 0.14]),
180
- 'dark khaki': np.array([0.74, 0.72, 0.42]),
181
- 'DarkKhaki': np.array([0.74, 0.72, 0.42]),
182
- 'khaki': np.array([0.94, 0.90, 0.55]),
183
- 'pale goldenrod': np.array([0.93, 0.91, 0.67]),
184
- 'PaleGoldenrod': np.array([0.93, 0.91, 0.67]),
185
- 'light goldenrod yellow': np.array([0.98, 0.98, 0.82]),
186
- 'LightGoldenrodYellow': np.array([0.98, 0.98, 0.82]),
187
- 'light yellow': np.array([1.00, 1.00, 0.88]),
188
- 'LightYellow': np.array([1.00, 1.00, 0.88]),
189
- 'yellow': np.array([1.00, 1.00, 0.00]),
190
- 'gold': np.array([1.00, 0.84, 0.00]),
191
- 'light goldenrod': np.array([0.93, 0.87, 0.51]),
192
- 'LightGoldenrod': np.array([0.93, 0.87, 0.51]),
193
- 'goldenrod': np.array([0.85, 0.65, 0.13]),
194
- 'dark goldenrod': np.array([0.72, 0.53, 0.04]),
195
- 'DarkGoldenrod': np.array([0.72, 0.53, 0.04]),
196
- 'rosy brown': np.array([0.74, 0.56, 0.56]),
197
- 'RosyBrown': np.array([0.74, 0.56, 0.56]),
198
- 'indian red': np.array([0.80, 0.36, 0.36]),
199
- 'IndianRed': np.array([0.80, 0.36, 0.36]),
200
- 'saddle brown': np.array([0.55, 0.27, 0.07]),
201
- 'SaddleBrown': np.array([0.55, 0.27, 0.07]),
202
- 'sienna': np.array([0.63, 0.32, 0.18]),
203
- 'peru': np.array([0.80, 0.52, 0.25]),
204
- 'burlywood': np.array([0.87, 0.72, 0.53]),
205
- 'beige': np.array([0.96, 0.96, 0.86]),
206
- 'wheat': np.array([0.96, 0.87, 0.70]),
207
- 'sandy brown': np.array([0.96, 0.64, 0.38]),
208
- 'SandyBrown': np.array([0.96, 0.64, 0.38]),
209
- 'tan': np.array([0.82, 0.71, 0.55]),
210
- 'chocolate': np.array([0.82, 0.41, 0.12]),
211
- 'firebrick': np.array([0.70, 0.13, 0.13]),
212
- 'brown': np.array([0.65, 0.16, 0.16]),
213
- 'dark salmon': np.array([0.91, 0.59, 0.48]),
214
- 'DarkSalmon': np.array([0.91, 0.59, 0.48]),
215
- 'salmon': np.array([0.98, 0.50, 0.45]),
216
- 'light salmon': np.array([1.00, 0.63, 0.48]),
217
- 'LightSalmon': np.array([1.00, 0.63, 0.48]),
218
- 'orange': np.array([1.00, 0.65, 0.00]),
219
- 'dark orange': np.array([1.00, 0.55, 0.00]),
220
- 'DarkOrange': np.array([1.00, 0.55, 0.00]),
221
- 'coral': np.array([1.00, 0.50, 0.31]),
222
- 'light coral': np.array([0.94, 0.50, 0.50]),
223
- 'LightCoral': np.array([0.94, 0.50, 0.50]),
224
- 'tomato': np.array([1.00, 0.39, 0.28]),
225
- 'orange red': np.array([1.00, 0.27, 0.00]),
226
- 'OrangeRed': np.array([1.00, 0.27, 0.00]),
227
- 'red': np.array([1.00, 0.00, 0.00]),
228
- 'hot pink': np.array([1.00, 0.41, 0.71]),
229
- 'HotPink': np.array([1.00, 0.41, 0.71]),
230
- 'deep pink': np.array([1.00, 0.08, 0.58]),
231
- 'DeepPink': np.array([1.00, 0.08, 0.58]),
232
- 'pink': np.array([1.00, 0.75, 0.80]),
233
- 'light pink': np.array([1.00, 0.71, 0.76]),
234
- 'LightPink': np.array([1.00, 0.71, 0.76]),
235
- 'pale violet red': np.array([0.86, 0.44, 0.58]),
236
- 'PaleVioletRed': np.array([0.86, 0.44, 0.58]),
237
- 'maroon': np.array([0.69, 0.19, 0.38]),
238
- 'medium violet red': np.array([0.78, 0.08, 0.52]),
239
- 'MediumVioletRed': np.array([0.78, 0.08, 0.52]),
240
- 'violet red': np.array([0.82, 0.13, 0.56]),
241
- 'VioletRed': np.array([0.82, 0.13, 0.56]),
242
- 'magenta': np.array([1.00, 0.00, 1.00]),
243
- 'violet': np.array([0.93, 0.51, 0.93]),
244
- 'plum': np.array([0.87, 0.63, 0.87]),
245
- 'orchid': np.array([0.85, 0.44, 0.84]),
246
- 'medium orchid': np.array([0.73, 0.33, 0.83]),
247
- 'MediumOrchid': np.array([0.73, 0.33, 0.83]),
248
- 'dark orchid': np.array([0.60, 0.20, 0.80]),
249
- 'DarkOrchid': np.array([0.60, 0.20, 0.80]),
250
- 'dark violet': np.array([0.58, 0.00, 0.83]),
251
- 'DarkViolet': np.array([0.58, 0.00, 0.83]),
252
- 'blue violet': np.array([0.54, 0.17, 0.89]),
253
- 'BlueViolet': np.array([0.54, 0.17, 0.89]),
254
- 'purple': np.array([0.63, 0.13, 0.94]),
255
- 'medium purple': np.array([0.58, 0.44, 0.86]),
256
- 'MediumPurple': np.array([0.58, 0.44, 0.86]),
257
- 'thistle': np.array([0.85, 0.75, 0.85]),
258
- 'snow1': np.array([1.00, 0.98, 0.98]),
259
- 'snow2': np.array([0.93, 0.91, 0.91]),
260
- 'snow3': np.array([0.80, 0.79, 0.79]),
261
- 'snow4': np.array([0.55, 0.54, 0.54]),
262
- 'seashell1': np.array([1.00, 0.96, 0.93]),
263
- 'seashell2': np.array([0.93, 0.90, 0.87]),
264
- 'seashell3': np.array([0.80, 0.77, 0.75]),
265
- 'seashell4': np.array([0.55, 0.53, 0.51]),
266
- 'AntiqueWhite1': np.array([1.00, 0.94, 0.86]),
267
- 'AntiqueWhite2': np.array([0.93, 0.87, 0.80]),
268
- 'AntiqueWhite3': np.array([0.80, 0.75, 0.69]),
269
- 'AntiqueWhite4': np.array([0.55, 0.51, 0.47]),
270
- 'bisque1': np.array([1.00, 0.89, 0.77]),
271
- 'bisque2': np.array([0.93, 0.84, 0.72]),
272
- 'bisque3': np.array([0.80, 0.72, 0.62]),
273
- 'bisque4': np.array([0.55, 0.49, 0.42]),
274
- 'PeachPuff1': np.array([1.00, 0.85, 0.73]),
275
- 'PeachPuff2': np.array([0.93, 0.80, 0.68]),
276
- 'PeachPuff3': np.array([0.80, 0.69, 0.58]),
277
- 'PeachPuff4': np.array([0.55, 0.47, 0.40]),
278
- 'NavajoWhite1': np.array([1.00, 0.87, 0.68]),
279
- 'NavajoWhite2': np.array([0.93, 0.81, 0.63]),
280
- 'NavajoWhite3': np.array([0.80, 0.70, 0.55]),
281
- 'NavajoWhite4': np.array([0.55, 0.47, 0.37]),
282
- 'LemonChiffon1': np.array([1.00, 0.98, 0.80]),
283
- 'LemonChiffon2': np.array([0.93, 0.91, 0.75]),
284
- 'LemonChiffon3': np.array([0.80, 0.79, 0.65]),
285
- 'LemonChiffon4': np.array([0.55, 0.54, 0.44]),
286
- 'cornsilk1': np.array([1.00, 0.97, 0.86]),
287
- 'cornsilk2': np.array([0.93, 0.91, 0.80]),
288
- 'cornsilk3': np.array([0.80, 0.78, 0.69]),
289
- 'cornsilk4': np.array([0.55, 0.53, 0.47]),
290
- 'ivory1': np.array([1.00, 1.00, 0.94]),
291
- 'ivory2': np.array([0.93, 0.93, 0.88]),
292
- 'ivory3': np.array([0.80, 0.80, 0.76]),
293
- 'ivory4': np.array([0.55, 0.55, 0.51]),
294
- 'honeydew1': np.array([0.94, 1.00, 0.94]),
295
- 'honeydew2': np.array([0.88, 0.93, 0.88]),
296
- 'honeydew3': np.array([0.76, 0.80, 0.76]),
297
- 'honeydew4': np.array([0.51, 0.55, 0.51]),
298
- 'LavenderBlush1': np.array([1.00, 0.94, 0.96]),
299
- 'LavenderBlush2': np.array([0.93, 0.88, 0.90]),
300
- 'LavenderBlush3': np.array([0.80, 0.76, 0.77]),
301
- 'LavenderBlush4': np.array([0.55, 0.51, 0.53]),
302
- 'MistyRose1': np.array([1.00, 0.89, 0.88]),
303
- 'MistyRose2': np.array([0.93, 0.84, 0.82]),
304
- 'MistyRose3': np.array([0.80, 0.72, 0.71]),
305
- 'MistyRose4': np.array([0.55, 0.49, 0.48]),
306
- 'azure1': np.array([0.94, 1.00, 1.00]),
307
- 'azure2': np.array([0.88, 0.93, 0.93]),
308
- 'azure3': np.array([0.76, 0.80, 0.80]),
309
- 'azure4': np.array([0.51, 0.55, 0.55]),
310
- 'SlateBlue1': np.array([0.51, 0.44, 1.00]),
311
- 'SlateBlue2': np.array([0.48, 0.40, 0.93]),
312
- 'SlateBlue3': np.array([0.41, 0.35, 0.80]),
313
- 'SlateBlue4': np.array([0.28, 0.24, 0.55]),
314
- 'RoyalBlue1': np.array([0.28, 0.46, 1.00]),
315
- 'RoyalBlue2': np.array([0.26, 0.43, 0.93]),
316
- 'RoyalBlue3': np.array([0.23, 0.37, 0.80]),
317
- 'RoyalBlue4': np.array([0.15, 0.25, 0.55]),
318
- 'blue1': np.array([0.00, 0.00, 1.00]),
319
- 'blue2': np.array([0.00, 0.00, 0.93]),
320
- 'blue3': np.array([0.00, 0.00, 0.80]),
321
- 'blue4': np.array([0.00, 0.00, 0.55]),
322
- 'DodgerBlue1': np.array([0.12, 0.56, 1.00]),
323
- 'DodgerBlue2': np.array([0.11, 0.53, 0.93]),
324
- 'DodgerBlue3': np.array([0.09, 0.45, 0.80]),
325
- 'DodgerBlue4': np.array([0.06, 0.31, 0.55]),
326
- 'SteelBlue1': np.array([0.39, 0.72, 1.00]),
327
- 'SteelBlue2': np.array([0.36, 0.67, 0.93]),
328
- 'SteelBlue3': np.array([0.31, 0.58, 0.80]),
329
- 'SteelBlue4': np.array([0.21, 0.39, 0.55]),
330
- 'DeepSkyBlue1': np.array([0.00, 0.75, 1.00]),
331
- 'DeepSkyBlue2': np.array([0.00, 0.70, 0.93]),
332
- 'DeepSkyBlue3': np.array([0.00, 0.60, 0.80]),
333
- 'DeepSkyBlue4': np.array([0.00, 0.41, 0.55]),
334
- 'SkyBlue1': np.array([0.53, 0.81, 1.00]),
335
- 'SkyBlue2': np.array([0.49, 0.75, 0.93]),
336
- 'SkyBlue3': np.array([0.42, 0.65, 0.80]),
337
- 'SkyBlue4': np.array([0.29, 0.44, 0.55]),
338
- 'LightSkyBlue1': np.array([0.69, 0.89, 1.00]),
339
- 'LightSkyBlue2': np.array([0.64, 0.83, 0.93]),
340
- 'LightSkyBlue3': np.array([0.55, 0.71, 0.80]),
341
- 'LightSkyBlue4': np.array([0.38, 0.48, 0.55]),
342
- 'SlateGray1': np.array([0.78, 0.89, 1.00]),
343
- 'SlateGray2': np.array([0.73, 0.83, 0.93]),
344
- 'SlateGray3': np.array([0.62, 0.71, 0.80]),
345
- 'SlateGray4': np.array([0.42, 0.48, 0.55]),
346
- 'LightSteelBlue1': np.array([0.79, 0.88, 1.00]),
347
- 'LightSteelBlue2': np.array([0.74, 0.82, 0.93]),
348
- 'LightSteelBlue3': np.array([0.64, 0.71, 0.80]),
349
- 'LightSteelBlue4': np.array([0.43, 0.48, 0.55]),
350
- 'LightBlue1': np.array([0.75, 0.94, 1.00]),
351
- 'LightBlue2': np.array([0.70, 0.87, 0.93]),
352
- 'LightBlue3': np.array([0.60, 0.75, 0.80]),
353
- 'LightBlue4': np.array([0.41, 0.51, 0.55]),
354
- 'LightCyan1': np.array([0.88, 1.00, 1.00]),
355
- 'LightCyan2': np.array([0.82, 0.93, 0.93]),
356
- 'LightCyan3': np.array([0.71, 0.80, 0.80]),
357
- 'LightCyan4': np.array([0.48, 0.55, 0.55]),
358
- 'PaleTurquoise1': np.array([0.73, 1.00, 1.00]),
359
- 'PaleTurquoise2': np.array([0.68, 0.93, 0.93]),
360
- 'PaleTurquoise3': np.array([0.59, 0.80, 0.80]),
361
- 'PaleTurquoise4': np.array([0.40, 0.55, 0.55]),
362
- 'CadetBlue1': np.array([0.60, 0.96, 1.00]),
363
- 'CadetBlue2': np.array([0.56, 0.90, 0.93]),
364
- 'CadetBlue3': np.array([0.48, 0.77, 0.80]),
365
- 'CadetBlue4': np.array([0.33, 0.53, 0.55]),
366
- 'turquoise1': np.array([0.00, 0.96, 1.00]),
367
- 'turquoise2': np.array([0.00, 0.90, 0.93]),
368
- 'turquoise3': np.array([0.00, 0.77, 0.80]),
369
- 'turquoise4': np.array([0.00, 0.53, 0.55]),
370
- 'cyan1': np.array([0.00, 1.00, 1.00]),
371
- 'cyan2': np.array([0.00, 0.93, 0.93]),
372
- 'cyan3': np.array([0.00, 0.80, 0.80]),
373
- 'cyan4': np.array([0.00, 0.55, 0.55]),
374
- 'DarkSlateGray1': np.array([0.59, 1.00, 1.00]),
375
- 'DarkSlateGray2': np.array([0.55, 0.93, 0.93]),
376
- 'DarkSlateGray3': np.array([0.47, 0.80, 0.80]),
377
- 'DarkSlateGray4': np.array([0.32, 0.55, 0.55]),
378
- 'aquamarine1': np.array([0.50, 1.00, 0.83]),
379
- 'aquamarine2': np.array([0.46, 0.93, 0.78]),
380
- 'aquamarine3': np.array([0.40, 0.80, 0.67]),
381
- 'aquamarine4': np.array([0.27, 0.55, 0.45]),
382
- 'DarkSeaGreen1': np.array([0.76, 1.00, 0.76]),
383
- 'DarkSeaGreen2': np.array([0.71, 0.93, 0.71]),
384
- 'DarkSeaGreen3': np.array([0.61, 0.80, 0.61]),
385
- 'DarkSeaGreen4': np.array([0.41, 0.55, 0.41]),
386
- 'SeaGreen1': np.array([0.33, 1.00, 0.62]),
387
- 'SeaGreen2': np.array([0.31, 0.93, 0.58]),
388
- 'SeaGreen3': np.array([0.26, 0.80, 0.50]),
389
- 'SeaGreen4': np.array([0.18, 0.55, 0.34]),
390
- 'PaleGreen1': np.array([0.60, 1.00, 0.60]),
391
- 'PaleGreen2': np.array([0.56, 0.93, 0.56]),
392
- 'PaleGreen3': np.array([0.49, 0.80, 0.49]),
393
- 'PaleGreen4': np.array([0.33, 0.55, 0.33]),
394
- 'SpringGreen1': np.array([0.00, 1.00, 0.50]),
395
- 'SpringGreen2': np.array([0.00, 0.93, 0.46]),
396
- 'SpringGreen3': np.array([0.00, 0.80, 0.40]),
397
- 'SpringGreen4': np.array([0.00, 0.55, 0.27]),
398
- 'green1': np.array([0.00, 1.00, 0.00]),
399
- 'green2': np.array([0.00, 0.93, 0.00]),
400
- 'green3': np.array([0.00, 0.80, 0.00]),
401
- 'green4': np.array([0.00, 0.55, 0.00]),
402
- 'chartreuse1': np.array([0.50, 1.00, 0.00]),
403
- 'chartreuse2': np.array([0.46, 0.93, 0.00]),
404
- 'chartreuse3': np.array([0.40, 0.80, 0.00]),
405
- 'chartreuse4': np.array([0.27, 0.55, 0.00]),
406
- 'OliveDrab1': np.array([0.75, 1.00, 0.24]),
407
- 'OliveDrab2': np.array([0.70, 0.93, 0.23]),
408
- 'OliveDrab3': np.array([0.60, 0.80, 0.20]),
409
- 'OliveDrab4': np.array([0.41, 0.55, 0.13]),
410
- 'DarkOliveGreen1': np.array([0.79, 1.00, 0.44]),
411
- 'DarkOliveGreen2': np.array([0.74, 0.93, 0.41]),
412
- 'DarkOliveGreen3': np.array([0.64, 0.80, 0.35]),
413
- 'DarkOliveGreen4': np.array([0.43, 0.55, 0.24]),
414
- 'khaki1': np.array([1.00, 0.96, 0.56]),
415
- 'khaki2': np.array([0.93, 0.90, 0.52]),
416
- 'khaki3': np.array([0.80, 0.78, 0.45]),
417
- 'khaki4': np.array([0.55, 0.53, 0.31]),
418
- 'LightGoldenrod1': np.array([1.00, 0.93, 0.55]),
419
- 'LightGoldenrod2': np.array([0.93, 0.86, 0.51]),
420
- 'LightGoldenrod3': np.array([0.80, 0.75, 0.44]),
421
- 'LightGoldenrod4': np.array([0.55, 0.51, 0.30]),
422
- 'LightYellow1': np.array([1.00, 1.00, 0.88]),
423
- 'LightYellow2': np.array([0.93, 0.93, 0.82]),
424
- 'LightYellow3': np.array([0.80, 0.80, 0.71]),
425
- 'LightYellow4': np.array([0.55, 0.55, 0.48]),
426
- 'yellow1': np.array([1.00, 1.00, 0.00]),
427
- 'yellow2': np.array([0.93, 0.93, 0.00]),
428
- 'yellow3': np.array([0.80, 0.80, 0.00]),
429
- 'yellow4': np.array([0.55, 0.55, 0.00]),
430
- 'gold1': np.array([1.00, 0.84, 0.00]),
431
- 'gold2': np.array([0.93, 0.79, 0.00]),
432
- 'gold3': np.array([0.80, 0.68, 0.00]),
433
- 'gold4': np.array([0.55, 0.46, 0.00]),
434
- 'goldenrod1': np.array([1.00, 0.76, 0.15]),
435
- 'goldenrod2': np.array([0.93, 0.71, 0.13]),
436
- 'goldenrod3': np.array([0.80, 0.61, 0.11]),
437
- 'goldenrod4': np.array([0.55, 0.41, 0.08]),
438
- 'DarkGoldenrod1': np.array([1.00, 0.73, 0.06]),
439
- 'DarkGoldenrod2': np.array([0.93, 0.68, 0.05]),
440
- 'DarkGoldenrod3': np.array([0.80, 0.58, 0.05]),
441
- 'DarkGoldenrod4': np.array([0.55, 0.40, 0.03]),
442
- 'RosyBrown1': np.array([1.00, 0.76, 0.76]),
443
- 'RosyBrown2': np.array([0.93, 0.71, 0.71]),
444
- 'RosyBrown3': np.array([0.80, 0.61, 0.61]),
445
- 'RosyBrown4': np.array([0.55, 0.41, 0.41]),
446
- 'IndianRed1': np.array([1.00, 0.42, 0.42]),
447
- 'IndianRed2': np.array([0.93, 0.39, 0.39]),
448
- 'IndianRed3': np.array([0.80, 0.33, 0.33]),
449
- 'IndianRed4': np.array([0.55, 0.23, 0.23]),
450
- 'sienna1': np.array([1.00, 0.51, 0.28]),
451
- 'sienna2': np.array([0.93, 0.47, 0.26]),
452
- 'sienna3': np.array([0.80, 0.41, 0.22]),
453
- 'sienna4': np.array([0.55, 0.28, 0.15]),
454
- 'burlywood1': np.array([1.00, 0.83, 0.61]),
455
- 'burlywood2': np.array([0.93, 0.77, 0.57]),
456
- 'burlywood3': np.array([0.80, 0.67, 0.49]),
457
- 'burlywood4': np.array([0.55, 0.45, 0.33]),
458
- 'wheat1': np.array([1.00, 0.91, 0.73]),
459
- 'wheat2': np.array([0.93, 0.85, 0.68]),
460
- 'wheat3': np.array([0.80, 0.73, 0.59]),
461
- 'wheat4': np.array([0.55, 0.49, 0.40]),
462
- 'tan1': np.array([1.00, 0.65, 0.31]),
463
- 'tan2': np.array([0.93, 0.60, 0.29]),
464
- 'tan3': np.array([0.80, 0.52, 0.25]),
465
- 'tan4': np.array([0.55, 0.35, 0.17]),
466
- 'chocolate1': np.array([1.00, 0.50, 0.14]),
467
- 'chocolate2': np.array([0.93, 0.46, 0.13]),
468
- 'chocolate3': np.array([0.80, 0.40, 0.11]),
469
- 'chocolate4': np.array([0.55, 0.27, 0.07]),
470
- 'firebrick1': np.array([1.00, 0.19, 0.19]),
471
- 'firebrick2': np.array([0.93, 0.17, 0.17]),
472
- 'firebrick3': np.array([0.80, 0.15, 0.15]),
473
- 'firebrick4': np.array([0.55, 0.10, 0.10]),
474
- 'brown1': np.array([1.00, 0.25, 0.25]),
475
- 'brown2': np.array([0.93, 0.23, 0.23]),
476
- 'brown3': np.array([0.80, 0.20, 0.20]),
477
- 'brown4': np.array([0.55, 0.14, 0.14]),
478
- 'salmon1': np.array([1.00, 0.55, 0.41]),
479
- 'salmon2': np.array([0.93, 0.51, 0.38]),
480
- 'salmon3': np.array([0.80, 0.44, 0.33]),
481
- 'salmon4': np.array([0.55, 0.30, 0.22]),
482
- 'LightSalmon1': np.array([1.00, 0.63, 0.48]),
483
- 'LightSalmon2': np.array([0.93, 0.58, 0.45]),
484
- 'LightSalmon3': np.array([0.80, 0.51, 0.38]),
485
- 'LightSalmon4': np.array([0.55, 0.34, 0.26]),
486
- 'orange1': np.array([1.00, 0.65, 0.00]),
487
- 'orange2': np.array([0.93, 0.60, 0.00]),
488
- 'orange3': np.array([0.80, 0.52, 0.00]),
489
- 'orange4': np.array([0.55, 0.35, 0.00]),
490
- 'DarkOrange1': np.array([1.00, 0.50, 0.00]),
491
- 'DarkOrange2': np.array([0.93, 0.46, 0.00]),
492
- 'DarkOrange3': np.array([0.80, 0.40, 0.00]),
493
- 'DarkOrange4': np.array([0.55, 0.27, 0.00]),
494
- 'coral1': np.array([1.00, 0.45, 0.34]),
495
- 'coral2': np.array([0.93, 0.42, 0.31]),
496
- 'coral3': np.array([0.80, 0.36, 0.27]),
497
- 'coral4': np.array([0.55, 0.24, 0.18]),
498
- 'tomato1': np.array([1.00, 0.39, 0.28]),
499
- 'tomato2': np.array([0.93, 0.36, 0.26]),
500
- 'tomato3': np.array([0.80, 0.31, 0.22]),
501
- 'tomato4': np.array([0.55, 0.21, 0.15]),
502
- 'OrangeRed1': np.array([1.00, 0.27, 0.00]),
503
- 'OrangeRed2': np.array([0.93, 0.25, 0.00]),
504
- 'OrangeRed3': np.array([0.80, 0.22, 0.00]),
505
- 'OrangeRed4': np.array([0.55, 0.15, 0.00]),
506
- 'red1': np.array([1.00, 0.00, 0.00]),
507
- 'red2': np.array([0.93, 0.00, 0.00]),
508
- 'red3': np.array([0.80, 0.00, 0.00]),
509
- 'red4': np.array([0.55, 0.00, 0.00]),
510
- 'DeepPink1': np.array([1.00, 0.08, 0.58]),
511
- 'DeepPink2': np.array([0.93, 0.07, 0.54]),
512
- 'DeepPink3': np.array([0.80, 0.06, 0.46]),
513
- 'DeepPink4': np.array([0.55, 0.04, 0.31]),
514
- 'HotPink1': np.array([1.00, 0.43, 0.71]),
515
- 'HotPink2': np.array([0.93, 0.42, 0.65]),
516
- 'HotPink3': np.array([0.80, 0.38, 0.56]),
517
- 'HotPink4': np.array([0.55, 0.23, 0.38]),
518
- 'pink1': np.array([1.00, 0.71, 0.77]),
519
- 'pink2': np.array([0.93, 0.66, 0.72]),
520
- 'pink3': np.array([0.80, 0.57, 0.62]),
521
- 'pink4': np.array([0.55, 0.39, 0.42]),
522
- 'LightPink1': np.array([1.00, 0.68, 0.73]),
523
- 'LightPink2': np.array([0.93, 0.64, 0.68]),
524
- 'LightPink3': np.array([0.80, 0.55, 0.58]),
525
- 'LightPink4': np.array([0.55, 0.37, 0.40]),
526
- 'PaleVioletRed1': np.array([1.00, 0.51, 0.67]),
527
- 'PaleVioletRed2': np.array([0.93, 0.47, 0.62]),
528
- 'PaleVioletRed3': np.array([0.80, 0.41, 0.54]),
529
- 'PaleVioletRed4': np.array([0.55, 0.28, 0.36]),
530
- 'maroon1': np.array([1.00, 0.20, 0.70]),
531
- 'maroon2': np.array([0.93, 0.19, 0.65]),
532
- 'maroon3': np.array([0.80, 0.16, 0.56]),
533
- 'maroon4': np.array([0.55, 0.11, 0.38]),
534
- 'VioletRed1': np.array([1.00, 0.24, 0.59]),
535
- 'VioletRed2': np.array([0.93, 0.23, 0.55]),
536
- 'VioletRed3': np.array([0.80, 0.20, 0.47]),
537
- 'VioletRed4': np.array([0.55, 0.13, 0.32]),
538
- 'magenta1': np.array([1.00, 0.00, 1.00]),
539
- 'magenta2': np.array([0.93, 0.00, 0.93]),
540
- 'magenta3': np.array([0.80, 0.00, 0.80]),
541
- 'magenta4': np.array([0.55, 0.00, 0.55]),
542
- 'orchid1': np.array([1.00, 0.51, 0.98]),
543
- 'orchid2': np.array([0.93, 0.48, 0.91]),
544
- 'orchid3': np.array([0.80, 0.41, 0.79]),
545
- 'orchid4': np.array([0.55, 0.28, 0.54]),
546
- 'plum1': np.array([1.00, 0.73, 1.00]),
547
- 'plum2': np.array([0.93, 0.68, 0.93]),
548
- 'plum3': np.array([0.80, 0.59, 0.80]),
549
- 'plum4': np.array([0.55, 0.40, 0.55]),
550
- 'MediumOrchid1': np.array([0.88, 0.40, 1.00]),
551
- 'MediumOrchid2': np.array([0.82, 0.37, 0.93]),
552
- 'MediumOrchid3': np.array([0.71, 0.32, 0.80]),
553
- 'MediumOrchid4': np.array([0.48, 0.22, 0.55]),
554
- 'DarkOrchid1': np.array([0.75, 0.24, 1.00]),
555
- 'DarkOrchid2': np.array([0.70, 0.23, 0.93]),
556
- 'DarkOrchid3': np.array([0.60, 0.20, 0.80]),
557
- 'DarkOrchid4': np.array([0.41, 0.13, 0.55]),
558
- 'purple1': np.array([0.61, 0.19, 1.00]),
559
- 'purple2': np.array([0.57, 0.17, 0.93]),
560
- 'purple3': np.array([0.49, 0.15, 0.80]),
561
- 'purple4': np.array([0.33, 0.10, 0.55]),
562
- 'MediumPurple1': np.array([0.67, 0.51, 1.00]),
563
- 'MediumPurple2': np.array([0.62, 0.47, 0.93]),
564
- 'MediumPurple3': np.array([0.54, 0.41, 0.80]),
565
- 'MediumPurple4': np.array([0.36, 0.28, 0.55]),
566
- 'thistle1': np.array([1.00, 0.88, 1.00]),
567
- 'thistle2': np.array([0.93, 0.82, 0.93]),
568
- 'thistle3': np.array([0.80, 0.71, 0.80]),
569
- 'thistle4': np.array([0.55, 0.48, 0.55]),
570
- 'gray0': np.array([0.00, 0.00, 0.00]),
571
- 'grey0': np.array([0.00, 0.00, 0.00]),
572
- 'gray1': np.array([0.01, 0.01, 0.01]),
573
- 'grey1': np.array([0.01, 0.01, 0.01]),
574
- 'gray2': np.array([0.02, 0.02, 0.02]),
575
- 'grey2': np.array([0.02, 0.02, 0.02]),
576
- 'gray3': np.array([0.03, 0.03, 0.03]),
577
- 'grey3': np.array([0.03, 0.03, 0.03]),
578
- 'gray4': np.array([0.04, 0.04, 0.04]),
579
- 'grey4': np.array([0.04, 0.04, 0.04]),
580
- 'gray5': np.array([0.05, 0.05, 0.05]),
581
- 'grey5': np.array([0.05, 0.05, 0.05]),
582
- 'gray6': np.array([0.06, 0.06, 0.06]),
583
- 'grey6': np.array([0.06, 0.06, 0.06]),
584
- 'gray7': np.array([0.07, 0.07, 0.07]),
585
- 'grey7': np.array([0.07, 0.07, 0.07]),
586
- 'gray8': np.array([0.08, 0.08, 0.08]),
587
- 'grey8': np.array([0.08, 0.08, 0.08]),
588
- 'gray9': np.array([0.09, 0.09, 0.09]),
589
- 'grey9': np.array([0.09, 0.09, 0.09]),
590
- 'gray10': np.array([0.10, 0.10, 0.10]),
591
- 'grey10': np.array([0.10, 0.10, 0.10]),
592
- 'gray11': np.array([0.11, 0.11, 0.11]),
593
- 'grey11': np.array([0.11, 0.11, 0.11]),
594
- 'gray12': np.array([0.12, 0.12, 0.12]),
595
- 'grey12': np.array([0.12, 0.12, 0.12]),
596
- 'gray13': np.array([0.13, 0.13, 0.13]),
597
- 'grey13': np.array([0.13, 0.13, 0.13]),
598
- 'gray14': np.array([0.14, 0.14, 0.14]),
599
- 'grey14': np.array([0.14, 0.14, 0.14]),
600
- 'gray15': np.array([0.15, 0.15, 0.15]),
601
- 'grey15': np.array([0.15, 0.15, 0.15]),
602
- 'gray16': np.array([0.16, 0.16, 0.16]),
603
- 'grey16': np.array([0.16, 0.16, 0.16]),
604
- 'gray17': np.array([0.17, 0.17, 0.17]),
605
- 'grey17': np.array([0.17, 0.17, 0.17]),
606
- 'gray18': np.array([0.18, 0.18, 0.18]),
607
- 'grey18': np.array([0.18, 0.18, 0.18]),
608
- 'gray19': np.array([0.19, 0.19, 0.19]),
609
- 'grey19': np.array([0.19, 0.19, 0.19]),
610
- 'gray20': np.array([0.20, 0.20, 0.20]),
611
- 'grey20': np.array([0.20, 0.20, 0.20]),
612
- 'gray21': np.array([0.21, 0.21, 0.21]),
613
- 'grey21': np.array([0.21, 0.21, 0.21]),
614
- 'gray22': np.array([0.22, 0.22, 0.22]),
615
- 'grey22': np.array([0.22, 0.22, 0.22]),
616
- 'gray23': np.array([0.23, 0.23, 0.23]),
617
- 'grey23': np.array([0.23, 0.23, 0.23]),
618
- 'gray24': np.array([0.24, 0.24, 0.24]),
619
- 'grey24': np.array([0.24, 0.24, 0.24]),
620
- 'gray25': np.array([0.25, 0.25, 0.25]),
621
- 'grey25': np.array([0.25, 0.25, 0.25]),
622
- 'gray26': np.array([0.26, 0.26, 0.26]),
623
- 'grey26': np.array([0.26, 0.26, 0.26]),
624
- 'gray27': np.array([0.27, 0.27, 0.27]),
625
- 'grey27': np.array([0.27, 0.27, 0.27]),
626
- 'gray28': np.array([0.28, 0.28, 0.28]),
627
- 'grey28': np.array([0.28, 0.28, 0.28]),
628
- 'gray29': np.array([0.29, 0.29, 0.29]),
629
- 'grey29': np.array([0.29, 0.29, 0.29]),
630
- 'gray30': np.array([0.30, 0.30, 0.30]),
631
- 'grey30': np.array([0.30, 0.30, 0.30]),
632
- 'gray31': np.array([0.31, 0.31, 0.31]),
633
- 'grey31': np.array([0.31, 0.31, 0.31]),
634
- 'gray32': np.array([0.32, 0.32, 0.32]),
635
- 'grey32': np.array([0.32, 0.32, 0.32]),
636
- 'gray33': np.array([0.33, 0.33, 0.33]),
637
- 'grey33': np.array([0.33, 0.33, 0.33]),
638
- 'gray34': np.array([0.34, 0.34, 0.34]),
639
- 'grey34': np.array([0.34, 0.34, 0.34]),
640
- 'gray35': np.array([0.35, 0.35, 0.35]),
641
- 'grey35': np.array([0.35, 0.35, 0.35]),
642
- 'gray36': np.array([0.36, 0.36, 0.36]),
643
- 'grey36': np.array([0.36, 0.36, 0.36]),
644
- 'gray37': np.array([0.37, 0.37, 0.37]),
645
- 'grey37': np.array([0.37, 0.37, 0.37]),
646
- 'gray38': np.array([0.38, 0.38, 0.38]),
647
- 'grey38': np.array([0.38, 0.38, 0.38]),
648
- 'gray39': np.array([0.39, 0.39, 0.39]),
649
- 'grey39': np.array([0.39, 0.39, 0.39]),
650
- 'gray40': np.array([0.40, 0.40, 0.40]),
651
- 'grey40': np.array([0.40, 0.40, 0.40]),
652
- 'gray41': np.array([0.41, 0.41, 0.41]),
653
- 'grey41': np.array([0.41, 0.41, 0.41]),
654
- 'gray42': np.array([0.42, 0.42, 0.42]),
655
- 'grey42': np.array([0.42, 0.42, 0.42]),
656
- 'gray43': np.array([0.43, 0.43, 0.43]),
657
- 'grey43': np.array([0.43, 0.43, 0.43]),
658
- 'gray44': np.array([0.44, 0.44, 0.44]),
659
- 'grey44': np.array([0.44, 0.44, 0.44]),
660
- 'gray45': np.array([0.45, 0.45, 0.45]),
661
- 'grey45': np.array([0.45, 0.45, 0.45]),
662
- 'gray46': np.array([0.46, 0.46, 0.46]),
663
- 'grey46': np.array([0.46, 0.46, 0.46]),
664
- 'gray47': np.array([0.47, 0.47, 0.47]),
665
- 'grey47': np.array([0.47, 0.47, 0.47]),
666
- 'gray48': np.array([0.48, 0.48, 0.48]),
667
- 'grey48': np.array([0.48, 0.48, 0.48]),
668
- 'gray49': np.array([0.49, 0.49, 0.49]),
669
- 'grey49': np.array([0.49, 0.49, 0.49]),
670
- 'gray50': np.array([0.50, 0.50, 0.50]),
671
- 'grey50': np.array([0.50, 0.50, 0.50]),
672
- 'gray51': np.array([0.51, 0.51, 0.51]),
673
- 'grey51': np.array([0.51, 0.51, 0.51]),
674
- 'gray52': np.array([0.52, 0.52, 0.52]),
675
- 'grey52': np.array([0.52, 0.52, 0.52]),
676
- 'gray53': np.array([0.53, 0.53, 0.53]),
677
- 'grey53': np.array([0.53, 0.53, 0.53]),
678
- 'gray54': np.array([0.54, 0.54, 0.54]),
679
- 'grey54': np.array([0.54, 0.54, 0.54]),
680
- 'gray55': np.array([0.55, 0.55, 0.55]),
681
- 'grey55': np.array([0.55, 0.55, 0.55]),
682
- 'gray56': np.array([0.56, 0.56, 0.56]),
683
- 'grey56': np.array([0.56, 0.56, 0.56]),
684
- 'gray57': np.array([0.57, 0.57, 0.57]),
685
- 'grey57': np.array([0.57, 0.57, 0.57]),
686
- 'gray58': np.array([0.58, 0.58, 0.58]),
687
- 'grey58': np.array([0.58, 0.58, 0.58]),
688
- 'gray59': np.array([0.59, 0.59, 0.59]),
689
- 'grey59': np.array([0.59, 0.59, 0.59]),
690
- 'gray60': np.array([0.60, 0.60, 0.60]),
691
- 'grey60': np.array([0.60, 0.60, 0.60]),
692
- 'gray61': np.array([0.61, 0.61, 0.61]),
693
- 'grey61': np.array([0.61, 0.61, 0.61]),
694
- 'gray62': np.array([0.62, 0.62, 0.62]),
695
- 'grey62': np.array([0.62, 0.62, 0.62]),
696
- 'gray63': np.array([0.63, 0.63, 0.63]),
697
- 'grey63': np.array([0.63, 0.63, 0.63]),
698
- 'gray64': np.array([0.64, 0.64, 0.64]),
699
- 'grey64': np.array([0.64, 0.64, 0.64]),
700
- 'gray65': np.array([0.65, 0.65, 0.65]),
701
- 'grey65': np.array([0.65, 0.65, 0.65]),
702
- 'gray66': np.array([0.66, 0.66, 0.66]),
703
- 'grey66': np.array([0.66, 0.66, 0.66]),
704
- 'gray67': np.array([0.67, 0.67, 0.67]),
705
- 'grey67': np.array([0.67, 0.67, 0.67]),
706
- 'gray68': np.array([0.68, 0.68, 0.68]),
707
- 'grey68': np.array([0.68, 0.68, 0.68]),
708
- 'gray69': np.array([0.69, 0.69, 0.69]),
709
- 'grey69': np.array([0.69, 0.69, 0.69]),
710
- 'gray70': np.array([0.70, 0.70, 0.70]),
711
- 'grey70': np.array([0.70, 0.70, 0.70]),
712
- 'gray71': np.array([0.71, 0.71, 0.71]),
713
- 'grey71': np.array([0.71, 0.71, 0.71]),
714
- 'gray72': np.array([0.72, 0.72, 0.72]),
715
- 'grey72': np.array([0.72, 0.72, 0.72]),
716
- 'gray73': np.array([0.73, 0.73, 0.73]),
717
- 'grey73': np.array([0.73, 0.73, 0.73]),
718
- 'gray74': np.array([0.74, 0.74, 0.74]),
719
- 'grey74': np.array([0.74, 0.74, 0.74]),
720
- 'gray75': np.array([0.75, 0.75, 0.75]),
721
- 'grey75': np.array([0.75, 0.75, 0.75]),
722
- 'gray76': np.array([0.76, 0.76, 0.76]),
723
- 'grey76': np.array([0.76, 0.76, 0.76]),
724
- 'gray77': np.array([0.77, 0.77, 0.77]),
725
- 'grey77': np.array([0.77, 0.77, 0.77]),
726
- 'gray78': np.array([0.78, 0.78, 0.78]),
727
- 'grey78': np.array([0.78, 0.78, 0.78]),
728
- 'gray79': np.array([0.79, 0.79, 0.79]),
729
- 'grey79': np.array([0.79, 0.79, 0.79]),
730
- 'gray80': np.array([0.80, 0.80, 0.80]),
731
- 'grey80': np.array([0.80, 0.80, 0.80]),
732
- 'gray81': np.array([0.81, 0.81, 0.81]),
733
- 'grey81': np.array([0.81, 0.81, 0.81]),
734
- 'gray82': np.array([0.82, 0.82, 0.82]),
735
- 'grey82': np.array([0.82, 0.82, 0.82]),
736
- 'gray83': np.array([0.83, 0.83, 0.83]),
737
- 'grey83': np.array([0.83, 0.83, 0.83]),
738
- 'gray84': np.array([0.84, 0.84, 0.84]),
739
- 'grey84': np.array([0.84, 0.84, 0.84]),
740
- 'gray85': np.array([0.85, 0.85, 0.85]),
741
- 'grey85': np.array([0.85, 0.85, 0.85]),
742
- 'gray86': np.array([0.86, 0.86, 0.86]),
743
- 'grey86': np.array([0.86, 0.86, 0.86]),
744
- 'gray87': np.array([0.87, 0.87, 0.87]),
745
- 'grey87': np.array([0.87, 0.87, 0.87]),
746
- 'gray88': np.array([0.88, 0.88, 0.88]),
747
- 'grey88': np.array([0.88, 0.88, 0.88]),
748
- 'gray89': np.array([0.89, 0.89, 0.89]),
749
- 'grey89': np.array([0.89, 0.89, 0.89]),
750
- 'gray90': np.array([0.90, 0.90, 0.90]),
751
- 'grey90': np.array([0.90, 0.90, 0.90]),
752
- 'gray91': np.array([0.91, 0.91, 0.91]),
753
- 'grey91': np.array([0.91, 0.91, 0.91]),
754
- 'gray92': np.array([0.92, 0.92, 0.92]),
755
- 'grey92': np.array([0.92, 0.92, 0.92]),
756
- 'gray93': np.array([0.93, 0.93, 0.93]),
757
- 'grey93': np.array([0.93, 0.93, 0.93]),
758
- 'gray94': np.array([0.94, 0.94, 0.94]),
759
- 'grey94': np.array([0.94, 0.94, 0.94]),
760
- 'gray95': np.array([0.95, 0.95, 0.95]),
761
- 'grey95': np.array([0.95, 0.95, 0.95]),
762
- 'gray96': np.array([0.96, 0.96, 0.96]),
763
- 'grey96': np.array([0.96, 0.96, 0.96]),
764
- 'gray97': np.array([0.97, 0.97, 0.97]),
765
- 'grey97': np.array([0.97, 0.97, 0.97]),
766
- 'gray98': np.array([0.98, 0.98, 0.98]),
767
- 'grey98': np.array([0.98, 0.98, 0.98]),
768
- 'gray99': np.array([0.99, 0.99, 0.99]),
769
- 'grey99': np.array([0.99, 0.99, 0.99]),
770
- 'gray100': np.array([1.00, 1.00, 1.00]),
771
- 'grey100': np.array([1.00, 1.00, 1.00]),
772
- 'dark grey': np.array([0.66, 0.66, 0.66]),
773
- 'DarkGrey': np.array([0.66, 0.66, 0.66]),
774
- 'dark gray': np.array([0.66, 0.66, 0.66]),
775
- 'DarkGray': np.array([0.66, 0.66, 0.66]),
776
- 'dark blue': np.array([0.00, 0.00, 0.55]),
777
- 'DarkBlue': np.array([0.00, 0.00, 0.55]),
778
- 'dark cyan': np.array([0.00, 0.55, 0.55]),
779
- 'DarkCyan': np.array([0.00, 0.55, 0.55]),
780
- 'dark magenta': np.array([0.55, 0.00, 0.55]),
781
- 'DarkMagenta': np.array([0.55, 0.00, 0.55]),
782
- 'dark red': np.array([0.55, 0.00, 0.00]),
783
- 'DarkRed': np.array([0.55, 0.00, 0.00]),
784
- 'light green': np.array([0.56, 0.93, 0.56]),
785
- 'LightGreen': np.array([0.56, 0.93, 0.56])
786
- }
787
-
788
-
789
- if __name__ == '__main__':
790
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/errors.py DELETED
@@ -1,15 +0,0 @@
1
- # Copyright (c) 2017 Max Planck Society. All rights reserved.
2
-
3
- """
4
- Error heirarchy for Mesh class
5
- """
6
-
7
-
8
- class MeshError(Exception):
9
- """Base error class for Mesh-related errors"""
10
- pass
11
-
12
-
13
- class SerializationError(MeshError):
14
- """Mesh reading or writing errors"""
15
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/fonts.py DELETED
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
4
-
5
- import os
6
- import numpy as np
7
- from OpenGL.GL import glPixelStorei, \
8
- glGenTextures, \
9
- glBindTexture, \
10
- glGenerateMipmap, \
11
- glHint, \
12
- glTexImage2D
13
- from OpenGL.GL import GL_UNPACK_ALIGNMENT, \
14
- GL_TEXTURE_2D, \
15
- GL_RGB, \
16
- GL_BGR, \
17
- GL_GENERATE_MIPMAP_HINT, \
18
- GL_NICEST, \
19
- GL_UNSIGNED_BYTE
20
-
21
-
22
- def get_image_with_text(text, fgcolor, bgcolor):
23
- if not hasattr(get_image_with_text, 'cache'):
24
- get_image_with_text.cache = {}
25
-
26
- import zlib
27
- uid = str(zlib.crc32(text)) + str(zlib.crc32(np.array(fgcolor))) + str(zlib.crc32(np.array(bgcolor)))
28
- if uid not in get_image_with_text.cache:
29
- from PIL import ImageFont
30
- from PIL import Image
31
- from PIL import ImageDraw
32
-
33
- font = ImageFont.truetype("/Library/Fonts/Courier New.ttf", 30)
34
-
35
- imsize = (256, 256)
36
-
37
- bgarray = np.asarray(np.zeros((imsize[0], imsize[1], 3)), np.uint8)
38
- bgarray[:, :, 0] += bgcolor[0]
39
- bgarray[:, :, 1] += bgcolor[1]
40
- bgarray[:, :, 2] += bgcolor[2]
41
- img = Image.fromarray(bgarray)
42
- draw = ImageDraw.Draw(img)
43
- w, h = draw.textsize(text, font=font)
44
- text_pos = ((imsize[0] - w) / 2, (imsize[1] - h) / 2)
45
- draw.text(text_pos, text, fill=fgcolor, font=font)
46
- get_image_with_text.cache[uid] = np.array(img.getdata()).reshape(img.size[0], img.size[1], 3) * 255
47
- return get_image_with_text.cache[uid]
48
-
49
-
50
- def get_textureid_with_text(text, fgcolor, bgcolor):
51
- if not hasattr(get_textureid_with_text, 'cache'):
52
- get_textureid_with_text.cache = {}
53
-
54
- import zlib
55
- uid = str(zlib.crc32(text)) + str(zlib.crc32(np.array(fgcolor))) + str(zlib.crc32(np.array(bgcolor)))
56
- if uid not in get_textureid_with_text.cache:
57
- from PIL import ImageFont
58
- from PIL import Image
59
- from PIL import ImageDraw
60
-
61
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
62
- "ressources",
63
- "Arial.ttf"),
64
- 100)
65
-
66
- imsize = (128, 128)
67
-
68
- bgarray = np.asarray(np.zeros((imsize[0], imsize[1], 3)), np.uint8)
69
- bgarray[:, :, 0] += bgcolor[0]
70
- bgarray[:, :, 1] += bgcolor[1]
71
- bgarray[:, :, 2] += bgcolor[2]
72
- img = Image.fromarray(bgarray)
73
- draw = ImageDraw.Draw(img)
74
- w, h = draw.textsize(text, font=font)
75
- text_pos = ((imsize[0] - w) / 2, (imsize[1] - h) / 2)
76
- draw.text(text_pos, text, fill=tuple(np.asarray(fgcolor, np.uint8)), font=font)
77
- texture_data = np.asarray(np.array(img.getdata()).reshape(img.size[0], img.size[1], 3) * 255, np.uint8)
78
-
79
- textureID = glGenTextures(1)
80
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
81
- glBindTexture(GL_TEXTURE_2D, textureID)
82
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_data.shape[1], texture_data.shape[0], 0, GL_BGR, GL_UNSIGNED_BYTE, texture_data.flatten())
83
- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST) # must be GL_FASTEST, GL_NICEST or GL_DONT_CARE
84
- glGenerateMipmap(GL_TEXTURE_2D)
85
- get_textureid_with_text.cache[uid] = textureID
86
-
87
- return get_textureid_with_text.cache[uid]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/__init__.py DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2016 Max Planck Society. All rights reserved.
 
 
 
 
 
mesh-master/mesh/geometry/barycentric_coordinates_of_projection.py DELETED
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
-
6
- from numpy import cross, sum, isscalar, spacing, vstack
7
-
8
-
9
- def barycentric_coordinates_of_projection(p, q, u, v):
10
- """Given a point, gives projected coords of that point to a triangle
11
- in barycentric coordinates.
12
-
13
- See
14
-
15
- **Heidrich**, Computing the Barycentric Coordinates of a Projected Point, JGT 05
16
- at http://www.cs.ubc.ca/~heidrich/Papers/JGT.05.pdf
17
-
18
- :param p: point to project
19
- :param q: a vertex of the triangle to project into
20
- :param u,v: edges of the the triangle such that it has vertices ``q``, ``q+u``, ``q+v``
21
-
22
- :returns: barycentric coordinates of ``p``'s projection in triangle defined by ``q``, ``u``, ``v``
23
- vectorized so ``p``, ``q``, ``u``, ``v`` can all be ``3xN``
24
- """
25
-
26
- p = p.T
27
- q = q.T
28
- u = u.T
29
- v = v.T
30
-
31
- n = cross(u, v, axis=0)
32
- s = sum(n * n, axis=0)
33
-
34
- # If the triangle edges are collinear, cross-product is zero,
35
- # which makes "s" 0, which gives us divide by zero. So we
36
- # make the arbitrary choice to set s to epsv (=numpy.spacing(1)),
37
- # the closest thing to zero
38
- if isscalar(s):
39
- s = s if s else spacing(1)
40
- else:
41
- s[s == 0] = spacing(1)
42
-
43
- oneOver4ASquared = 1.0 / s
44
- w = p - q
45
- b2 = sum(cross(u, w, axis=0) * n, axis=0) * oneOver4ASquared
46
- b1 = sum(cross(w, v, axis=0) * n, axis=0) * oneOver4ASquared
47
- b = vstack((1 - b1 - b2, b1, b2))
48
-
49
- return b.T
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/cross_product.py DELETED
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2012-07-20.
6
-
7
- import numpy as np
8
-
9
-
10
- def CrossProduct(a, b):
11
- """Computes the cross product of 2 vectors"""
12
- a = a.reshape(-1, 3)
13
- b = b.reshape(-1, 3)
14
-
15
- a1 = a[:, 0]
16
- a2 = a[:, 1]
17
- a3 = a[:, 2]
18
-
19
- Ax = np.zeros((len(a1), 3, 3))
20
- Ax[:, 0, 1] = -a3
21
- Ax[:, 0, 2] = +a2
22
- Ax[:, 1, 0] = +a3
23
- Ax[:, 1, 2] = -a1
24
- Ax[:, 2, 0] = -a2
25
- Ax[:, 2, 1] = +a1
26
-
27
- return _call_einsum_matvec(Ax, b)
28
-
29
-
30
- def _call_einsum_matvec(m, righthand):
31
- r = righthand.reshape(m.shape[0], 3)
32
- return np.einsum('ijk,ik->ij', m, r).flatten()
33
-
34
-
35
- def _call_einsum_matmat(m, righthand):
36
- r = righthand.reshape(m.shape[0], 3, -1)
37
- return np.einsum('ijk,ikm->ijm', m, r).reshape(-1, r.shape[2])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/rodrigues.py DELETED
@@ -1,125 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2012-07-22.
6
-
7
- import numpy as np
8
-
9
-
10
- def rodrigues(r, calculate_jacobian=True):
11
- """Computes the Rodrigues transform and its derivative
12
-
13
- :param r: either a 3-vector representing the rotation parameter, or a full rotation matrix
14
- :param calculate_jacobian: indicates if the Jacobian of the transform is also required
15
- :returns: If `calculate_jacobian` is `True`, the Jacobian is given as the second element of the returned tuple.
16
- """
17
-
18
- r = np.array(r, dtype=np.double)
19
- eps = np.finfo(np.double).eps
20
-
21
- if np.all(r.shape == (3, 1)) or np.all(r.shape == (1, 3)) or np.all(r.shape == (3,)):
22
- r = r.flatten()
23
- theta = np.linalg.norm(r)
24
- if theta < eps:
25
- r_out = np.eye(3)
26
- if calculate_jacobian:
27
- jac = np.zeros((3, 9))
28
- jac[0, 5] = jac[1, 6] = jac[2, 1] = -1
29
- jac[0, 7] = jac[1, 2] = jac[2, 3] = 1
30
-
31
- else:
32
- c = np.cos(theta)
33
- s = np.sin(theta)
34
- c1 = 1. - c
35
- itheta = 1.0 if theta == 0.0 else 1.0 / theta
36
- r *= itheta
37
- I = np.eye(3)
38
- rrt = np.array([r * r[0], r * r[1], r * r[2]])
39
- _r_x_ = np.array([[0, -r[2], r[1]], [r[2], 0, -r[0]], [-r[1], r[0], 0]])
40
- r_out = c * I + c1 * rrt + s * _r_x_
41
- if calculate_jacobian:
42
- drrt = np.array([[r[0] + r[0], r[1], r[2], r[1], 0, 0, r[2], 0, 0],
43
- [0, r[0], 0, r[0], r[1] + r[1], r[2], 0, r[2], 0],
44
- [0, 0, r[0], 0, 0, r[1], r[0], r[1], r[2] + r[2]]])
45
- d_r_x_ = np.array([[0, 0, 0, 0, 0, -1, 0, 1, 0],
46
- [0, 0, 1, 0, 0, 0, -1, 0, 0],
47
- [0, -1, 0, 1, 0, 0, 0, 0, 0]])
48
- I = np.array([I.flatten(), I.flatten(), I.flatten()])
49
- ri = np.array([[r[0]], [r[1]], [r[2]]])
50
- a0 = -s * ri
51
- a1 = (s - 2 * c1 * itheta) * ri
52
- a2 = np.ones((3, 1)) * c1 * itheta
53
- a3 = (c - s * itheta) * ri
54
- a4 = np.ones((3, 1)) * s * itheta
55
- jac = a0 * I + a1 * rrt.flatten() + a2 * drrt + a3 * _r_x_.flatten() + a4 * d_r_x_
56
- elif np.all(r.shape == (3, 3)):
57
- u, d, v = np.linalg.svd(r)
58
- r = np.dot(u, v)
59
- rx = r[2, 1] - r[1, 2]
60
- ry = r[0, 2] - r[2, 0]
61
- rz = r[1, 0] - r[0, 1]
62
- s = np.linalg.norm(np.array([rx, ry, rz])) * np.sqrt(0.25)
63
- c = np.clip((np.sum(np.diag(r)) - 1) * 0.5, -1, 1)
64
- theta = np.arccos(c)
65
- if s < 1e-5:
66
- if c > 0:
67
- r_out = np.zeros((3, 1))
68
- else:
69
- rx, ry, rz = np.clip(np.sqrt((np.diag(r) + 1) * 0.5), 0, np.inf)
70
- if r[0, 1] < 0:
71
- ry = -ry
72
- if r[0, 2] < 0:
73
- rz = -rz
74
- if np.abs(rx) < np.abs(ry) and np.abs(rx) < np.abs(rz) and ((r[1, 2] > 0) != (ry * rz > 0)):
75
- rz = -rz
76
-
77
- r_out = np.array([[rx, ry, rz]]).T
78
- theta /= np.linalg.norm(r_out)
79
- r_out *= theta
80
- if calculate_jacobian:
81
- jac = np.zeros((9, 3))
82
- if c > 0:
83
- jac[1, 2] = jac[5, 0] = jac[6, 1] = -0.5
84
- jac[2, 1] = jac[3, 2] = jac[7, 0] = 0.5
85
- else:
86
- vth = 1.0 / (2.0 * s)
87
- if calculate_jacobian:
88
- dtheta_dtr = -1. / s
89
- dvth_dtheta = -vth * c / s
90
- d1 = 0.5 * dvth_dtheta * dtheta_dtr
91
- d2 = 0.5 * dtheta_dtr
92
- dvardR = np.array([
93
- [0, 0, 0, 0, 0, 1, 0, -1, 0],
94
- [0, 0, -1, 0, 0, 0, 1, 0, 0],
95
- [0, 1, 0, -1, 0, 0, 0, 0, 0],
96
- [d1, 0, 0, 0, d1, 0, 0, 0, d1],
97
- [d2, 0, 0, 0, d2, 0, 0, 0, d2]])
98
- dvar2dvar = np.array([
99
- [vth, 0, 0, rx, 0],
100
- [0, vth, 0, ry, 0],
101
- [0, 0, vth, rz, 0],
102
- [0, 0, 0, 0, 1]])
103
- domegadvar2 = np.array([
104
- [theta, 0, 0, rx * vth],
105
- [0, theta, 0, ry * vth],
106
- [0, 0, theta, rz * vth]])
107
- jac = np.dot(np.dot(domegadvar2, dvar2dvar), dvardR)
108
- for ii in range(3):
109
- jac[ii] = jac[ii].reshape((3, 3)).T.flatten()
110
- jac = jac.T
111
- vth *= theta
112
- r_out = np.array([[rx, ry, rz]]).T * vth
113
- else:
114
- raise Exception("rodrigues: input matrix must be 1x3, 3x1 or 3x3.")
115
- if calculate_jacobian:
116
- return r_out, jac
117
- else:
118
- return r_out
119
-
120
-
121
- def rodrigues2rotmat(r):
122
- # R = np.zeros((3, 3))
123
- r_skew = np.array([[0, -r[2], r[1]], [r[2], 0, -r[0]], [-r[1], r[0], 0]])
124
- theta = np.linalg.norm(r)
125
- return np.identity(3) + np.sin(theta) * r_skew + (1 - np.cos(theta)) * r_skew.dot(r_skew)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/tri_normals.py DELETED
@@ -1,72 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2012-07-22.
6
-
7
-
8
- """
9
- tri_normals.py
10
-
11
- """
12
-
13
- from ..utils import col
14
- from .cross_product import CrossProduct
15
-
16
- import numpy as np
17
-
18
-
19
- def TriNormals(v, f):
20
- return NormalizedNx3(TriNormalsScaled(v, f))
21
-
22
-
23
- def TriNormalsScaled(v, f):
24
- return CrossProduct(TriEdges(v, f, 1, 0), TriEdges(v, f, 2, 0))
25
-
26
-
27
- def NormalizedNx3(v):
28
- ss = np.sum(v.reshape(-1, 3) ** 2, axis=1)
29
- ss[ss == 0] = 1
30
- s = np.sqrt(ss)
31
-
32
- return (v.reshape(-1, 3) / col(s)).flatten()
33
-
34
-
35
- def TriEdges(v, f, cplus, cminus):
36
- assert(cplus >= 0 and cplus <= 2 and cminus >= 0 and cminus <= 2)
37
- return _edges_for(v, f, cplus, cminus)
38
-
39
-
40
- def _edges_for(v, f, cplus, cminus):
41
- return (
42
- v.reshape(-1, 3)[f[:, cplus], :] -
43
- v.reshape(-1, 3)[f[:, cminus], :]).ravel()
44
-
45
-
46
- def TriToScaledNormal(x, tri):
47
-
48
- v = x.reshape(-1, 3)
49
-
50
- def v_xyz(iV):
51
- return v[tri[:, iV], :]
52
-
53
- return np.cross(v_xyz(1) - v_xyz(0), v_xyz(2) - v_xyz(0))
54
-
55
-
56
- def _bsxfun(oper, a, b):
57
- if a.shape[0] == b.shape[0] or a.shape[1] == b.shape[1]:
58
- return oper(a, b)
59
- elif min(a.shape) == 1 and min(b.shape) == 1:
60
- if a.shape[0] == 1:
61
- return oper(np.tile(a, (b.shape[0], 1)), b)
62
- else:
63
- return oper(np.tile(a, (1, b.shape[1], b)))
64
- else:
65
- raise '_bsxfun failure'
66
-
67
-
68
- def NormalizeRows(x):
69
-
70
- s = (np.sqrt(np.sum(x ** 2, axis=1))).flatten()
71
- s[s == 0] = 1
72
- return _bsxfun(np.divide, x, col(s))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/triangle_area.py DELETED
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
-
6
- from .tri_normals import TriToScaledNormal
7
- import numpy as np
8
-
9
-
10
- def triangle_area(v, f):
11
- """Computes the area associated to a set of triangles"""
12
- return (np.sqrt(np.sum(TriToScaledNormal(v, f) ** 2, axis=1)) / 2.).flatten()
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/geometry/vert_normals.py DELETED
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2013-03-12.
6
-
7
-
8
- import scipy.sparse as sp
9
- import numpy as np
10
- from .tri_normals import NormalizedNx3, TriNormalsScaled
11
- from ..utils import col
12
-
13
-
14
- def MatVecMult(mtx, vec):
15
- return mtx.dot(col(vec)).flatten()
16
-
17
-
18
- def VertNormals(v, f):
19
- return NormalizedNx3(VertNormalsScaled(v, f))
20
-
21
-
22
- def VertNormalsScaled(v, f):
23
- IS = f.flatten()
24
- JS = np.array([range(f.shape[0])] * 3).T.flatten()
25
- data = np.ones(len(JS))
26
-
27
- IS = np.concatenate((IS * 3, IS * 3 + 1, IS * 3 + 2))
28
- JS = np.concatenate((JS * 3, JS * 3 + 1, JS * 3 + 2)) # is this right?
29
- data = np.concatenate((data, data, data))
30
-
31
- faces_by_vertex = sp.csc_matrix((data, (IS, JS)), shape=(v.size, f.size))
32
-
33
- # faces_by_vertex should be 3 x wider...?
34
- return NormalizedNx3(MatVecMult(faces_by_vertex, TriNormalsScaled(v, f)))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/landmarks.py DELETED
@@ -1,102 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
4
- # Created by Matthew Loper on 2013-02-20.
5
-
6
-
7
- import numpy as np
8
-
9
- """
10
- landmarks.py
11
-
12
- """
13
-
14
-
15
- def landm_xyz_linear_transform(self, ordering=None):
16
- from .utils import col, sparse
17
-
18
- landmark_order = ordering if ordering else self.landm_names
19
- # construct a sparse matrix that converts between the landmark pts and all vertices, with height (# landmarks * 3) and width (# vertices * 3)
20
- if hasattr(self, 'landm_regressors'):
21
- landmark_coefficients = np.hstack([self.landm_regressors[name][1] for name in landmark_order])
22
- landmark_indices = np.hstack([self.landm_regressors[name][0] for name in landmark_order])
23
- column_indices = np.hstack([col(3 * landmark_indices + i) for i in range(3)]).flatten()
24
- row_indices = np.hstack([[3 * index, 3 * index + 1, 3 * index + 2] * len(self.landm_regressors[landmark_order[index]][0]) for index in np.arange(len(landmark_order))])
25
- values = np.hstack([col(landmark_coefficients) for i in range(3)]).flatten()
26
- return sparse(row_indices, column_indices, values, 3 * len(landmark_order), 3 * self.v.shape[0])
27
- elif hasattr(self, 'landm'):
28
- landmark_indices = np.array([self.landm[name] for name in landmark_order])
29
- column_indices = np.hstack(([col(3 * landmark_indices + i) for i in range(3)])).flatten()
30
- row_indices = np.arange(3 * len(landmark_order))
31
- return sparse(row_indices, column_indices, np.ones(len(column_indices)), 3 * len(landmark_order), 3 * self.v.shape[0])
32
- else:
33
- return np.zeros((0, 0))
34
-
35
-
36
- @property
37
- def landm_xyz(self, ordering=None):
38
- landmark_order = ordering if ordering else self.landm_names
39
- landmark_vertex_locations = (self.landm_xyz_linear_transform(landmark_order) * self.v.flatten()).reshape(-1, 3) if landmark_order else np.zeros((0, 0))
40
- if landmark_order:
41
- return dict([(landmark_order[i], xyz) for i, xyz in enumerate(landmark_vertex_locations)])
42
- return {}
43
-
44
-
45
- def recompute_landmark_indices(self, landmark_fname=None, safe_mode=True):
46
- filtered_landmarks = dict(
47
- filter(
48
- lambda e, : e[1] != [0.0, 0.0, 0.0],
49
- self.landm_raw_xyz.items()
50
- ) if (landmark_fname and safe_mode) else self.landm_raw_xyz.items())
51
- if len(filtered_landmarks) != len(self.landm_raw_xyz):
52
- print("WARNING: %d landmarks in file %s are positioned at (0.0, 0.0, 0.0) and were ignored" % (len(self.landm_raw_xyz) - len(filtered_landmarks), landmark_fname))
53
-
54
- self.landm = {}
55
- self.landm_regressors = {}
56
- if filtered_landmarks:
57
- landmark_names = list(filtered_landmarks.keys())
58
- closest_vertices, _ = self.closest_vertices(np.array(list(filtered_landmarks.values())))
59
- self.landm = dict(zip(landmark_names, closest_vertices))
60
- if len(self.f):
61
- face_indices, closest_points = self.closest_faces_and_points(np.array(list(filtered_landmarks.values())))
62
- vertex_indices, coefficients = self.barycentric_coordinates_for_points(closest_points, face_indices)
63
- self.landm_regressors = dict([(name, (vertex_indices[i], coefficients[i])) for i, name in enumerate(landmark_names)])
64
- else:
65
- self.landm_regressors = dict([(name, (np.array([closest_vertices[i]]), np.array([1.0]))) for i, name in enumerate(landmark_names)])
66
-
67
-
68
- def set_landmarks_from_xyz(self, landm_raw_xyz):
69
- self.landm_raw_xyz = landm_raw_xyz if hasattr(landm_raw_xyz, 'keys') else dict((str(i), l) for i, l in enumerate(landm_raw_xyz))
70
- self.recompute_landmark_indices()
71
-
72
-
73
- def is_vertex(x):
74
- return hasattr(x, "__len__") and len(x) == 3
75
-
76
-
77
- def is_index(x):
78
- return isinstance(x, (int, np.int32, np.int64))
79
-
80
-
81
- def set_landmarks_from_raw(self, landmarks):
82
- '''
83
- can accept:
84
- {'name1': [float, float, float], 'name2': [float, float, float], ...}
85
- {'name1': np.array([float, float, float]), 'name2': np.array([float, float, float]), ...}
86
- [[float,float,float],[float,float,float], ...]
87
- np.array([[float,float,float],[float,float,float], ...])
88
- [np.array([float,float,float]),np.array([float,float,float]), ...]
89
- {'name1': int, 'name2': int, ...}
90
- [int,int,int]
91
- np.array([int,int,int])
92
- '''
93
- landmarks = landmarks if hasattr(landmarks, 'keys') else dict((str(i), l) for i, l in enumerate(landmarks))
94
-
95
- if all(is_vertex(x) for x in landmarks.values()):
96
- landmarks = dict((i, np.array(l)) for i, l in landmarks.items())
97
- self.set_landmarks_from_xyz(landmarks)
98
- elif all(is_index(x) for x in landmarks.values()):
99
- self.landm = landmarks
100
- self.recompute_landmark_xyz()
101
- else:
102
- raise Exception("Can't parse landmarks")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/lines.py DELETED
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
4
-
5
- import numpy as np
6
- from . import colors
7
-
8
-
9
- class Lines(object):
10
- """Collection of 3D lines
11
-
12
- Attributes:
13
- v: Vx3 array of vertices
14
- e: Ex2 array of edges
15
- """
16
-
17
- def __init__(self, v, e, vc=None, ec=None):
18
-
19
- self.v = np.array(v)
20
- self.e = np.array(e)
21
-
22
- if vc is not None:
23
- self.set_vertex_colors(vc)
24
-
25
- if ec is not None:
26
- self.set_edge_colors(ec)
27
-
28
- def colors_like(self, color, arr):
29
- from .utils import row, col
30
- if isinstance(color, str):
31
- color = colors.name_to_rgb[color]
32
- elif isinstance(color, list):
33
- color = np.array(color)
34
-
35
- if color.shape == (arr.shape[0],):
36
- def jet(v):
37
- fourValue = 4 * v
38
- red = min(fourValue - 1.5, -fourValue + 4.5)
39
- green = min(fourValue - 0.5, -fourValue + 3.5)
40
- blue = min(fourValue + 0.5, -fourValue + 2.5)
41
- result = np.array([red, green, blue])
42
- result[result > 1.0] = 1.0
43
- result[result < 0.0] = 0.0
44
- return row(result)
45
- color = col(color)
46
- color = np.concatenate([jet(color[i]) for i in xrange(color.size)], axis=0)
47
-
48
- return np.ones((arr.shape[0], 3)) * color
49
-
50
- def set_vertex_colors(self, vc):
51
- self.vc = self.colors_like(vc, self.v)
52
-
53
- def set_edge_colors(self, ec):
54
- self.ec = self.colors_like(ec, self.e)
55
-
56
- def write_obj(self, filename):
57
- with open(filename, 'w') as fi:
58
- for r in self.v:
59
- fi.write('v %f %f %f\n' % (r[0], r[1], r[2]))
60
- for e in self.e:
61
- fi.write('l %d %d\n' % (e[0] + 1, e[1] + 1))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/mesh.py DELETED
@@ -1,492 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
5
-
6
- """
7
- Mesh module
8
- -----------
9
-
10
- """
11
-
12
-
13
- import os
14
- from functools import reduce
15
-
16
- import numpy as np
17
-
18
- from . import colors
19
- from . import search
20
-
21
- try:
22
- from .serialization import serialization
23
- except ImportError:
24
- pass
25
-
26
- from . import landmarks
27
- from . import texture
28
- from . import processing
29
-
30
-
31
- __all__ = ["Mesh"]
32
-
33
-
34
- class Mesh(object):
35
- """3d Triangulated Mesh class
36
-
37
- Attributes:
38
- v: Vx3 array of vertices
39
- f: Fx3 array of faces
40
-
41
- Optional attributes:
42
- fc: Fx3 array of face colors
43
- vc: Vx3 array of vertex colors
44
- vn: Vx3 array of vertex normals
45
- segm: dictionary of part names to triangle indices
46
-
47
- """
48
- def __init__(self,
49
- v=None,
50
- f=None,
51
- segm=None,
52
- filename=None,
53
- ppfilename=None,
54
- lmrkfilename=None,
55
- basename=None,
56
- vc=None,
57
- fc=None,
58
- vscale=None,
59
- landmarks=None):
60
- """
61
- :param v: vertices
62
- :param f: faces
63
- :param filename: a filename from which a mesh is loaded
64
- """
65
-
66
- if filename is not None:
67
- self.load_from_file(filename)
68
- if hasattr(self, 'f'):
69
- self.f = np.require(self.f, dtype=np.uint32)
70
- self.v = np.require(self.v, dtype=np.float64)
71
- self.filename = filename
72
- if vscale is not None:
73
- self.v *= vscale
74
- if v is not None:
75
- self.v = np.array(v, dtype=np.float64)
76
- if vscale is not None:
77
- self.v *= vscale
78
- if f is not None:
79
- self.f = np.require(f, dtype=np.uint32)
80
-
81
- self.basename = basename
82
- if self.basename is None and filename is not None:
83
- self.basename = os.path.splitext(os.path.basename(filename))[0]
84
-
85
- if segm is not None:
86
- self.segm = segm
87
- if landmarks is not None:
88
- self.set_landmark_indices_from_any(landmarks)
89
- if ppfilename is not None:
90
- self.set_landmark_indices_from_ppfile(ppfilename)
91
- if lmrkfilename is not None:
92
- self.set_landmark_indices_from_lmrkfile(lmrkfilename)
93
-
94
- if vc is not None:
95
- self.set_vertex_colors(vc)
96
-
97
- if fc is not None:
98
- self.set_face_colors(fc)
99
-
100
- def __del__(self):
101
- if hasattr(self, 'textureID'):
102
- from OpenGL.GL import glDeleteTextures
103
- glDeleteTextures([self.textureID])
104
-
105
- def edges_as_lines(self, copy_vertices=False):
106
- from .lines import Lines
107
- edges = self.f[:, [0, 1, 1, 2, 2, 0]].flatten().reshape(-1, 2)
108
- verts = self.v.copy() if copy_vertices else self.v
109
- return Lines(v=verts, e=edges)
110
-
111
- def show(self, mv=None, meshes=[], lines=[]):
112
- from .meshviewer import MeshViewer
113
- from .utils import row
114
-
115
- if mv is None:
116
- mv = MeshViewer(keepalive=True)
117
-
118
- if hasattr(self, 'landm'):
119
- from .sphere import Sphere
120
- sphere = Sphere(np.zeros((3)), 1.).to_mesh()
121
- scalefactor = 1e-2 * np.max(np.max(self.v) - np.min(self.v)) / np.max(np.max(sphere.v) - np.min(sphere.v))
122
- sphere.v = sphere.v * scalefactor
123
- spheres = [Mesh(vc='SteelBlue', f=sphere.f, v=sphere.v + row(np.array(self.landm_raw_xyz[k]))) for k in self.landm.keys()]
124
- mv.set_dynamic_meshes([self] + spheres + meshes, blocking=True)
125
- else:
126
- mv.set_dynamic_meshes([self] + meshes, blocking=True)
127
- mv.set_dynamic_lines(lines)
128
- return mv
129
-
130
- def colors_like(self, color, arr=None):
131
- from .utils import row, col
132
-
133
- if arr is None:
134
- arr = np.zeros(self.v.shape)
135
-
136
- # if arr is single-dim, reshape it
137
- if arr.ndim == 1 or arr.shape[1] == 1:
138
- arr = arr.reshape(-1, 3)
139
-
140
- if isinstance(color, str):
141
- color = colors.name_to_rgb[color]
142
- elif isinstance(color, list):
143
- color = np.array(color)
144
-
145
- if color.shape[0] == arr.shape[0] and color.shape[0] == color.size:
146
- def jet(v):
147
- fourValue = 4 * v
148
- red = min(fourValue - 1.5, -fourValue + 4.5)
149
- green = min(fourValue - 0.5, -fourValue + 3.5)
150
- blue = min(fourValue + 0.5, -fourValue + 2.5)
151
- result = np.array([red, green, blue])
152
- result[result > 1.0] = 1.0
153
- result[result < 0.0] = 0.0
154
- return row(result)
155
- color = col(color)
156
- color = np.concatenate([jet(color[i]) for i in range(color.size)], axis=0)
157
-
158
- return np.ones_like(arr) * color
159
-
160
- def set_vertex_colors(self, vc, vertex_indices=None):
161
- if vertex_indices is not None:
162
- self.vc[vertex_indices] = self.colors_like(vc, self.v[vertex_indices])
163
- else:
164
- self.vc = self.colors_like(vc, self.v)
165
- return self
166
-
167
- def set_vertex_colors_from_weights(self, weights, scale_to_range_1=True, color=True):
168
- # from numpy import ones_like
169
- if weights is None:
170
- return self
171
- if scale_to_range_1:
172
- weights = weights - np.min(weights)
173
- weights = (1.0 - 0.0) * weights / np.max(weights) + 0.0
174
- if color:
175
- from matplotlib import cm
176
- self.vc = cm.jet(weights)[:, :3]
177
- else:
178
- self.vc = np.tile(np.reshape(weights, (len(weights), 1)), (1, 3)) # *ones_like(self.v)
179
- return self
180
-
181
- def scale_vertex_colors(self, weights, w_min=0.0, w_max=1.0):
182
- if weights is None:
183
- return self
184
- weights = weights - np.min(weights)
185
- weights = (w_max - w_min) * weights / np.max(weights) + w_min
186
- self.vc = (weights * self.vc.T).T if weights is not None else self.vc
187
- return self
188
-
189
- def set_face_colors(self, fc):
190
- self.fc = self.colors_like(fc, self.f)
191
- return self
192
-
193
- def faces_by_vertex(self, as_sparse_matrix=False):
194
- import scipy.sparse as sp
195
- if not as_sparse_matrix:
196
- faces_by_vertex = [[] for i in range(len(self.v))]
197
- for i, face in enumerate(self.f):
198
- faces_by_vertex[face[0]].append(i)
199
- faces_by_vertex[face[1]].append(i)
200
- faces_by_vertex[face[2]].append(i)
201
- else:
202
- row = self.f.flatten()
203
- col = np.array([range(self.f.shape[0])] * 3).T.flatten()
204
- data = np.ones(len(col))
205
- faces_by_vertex = sp.csr_matrix((data, (row, col)), shape=(self.v.shape[0], self.f.shape[0]))
206
- return faces_by_vertex
207
-
208
- def estimate_vertex_normals(self, face_to_verts_sparse_matrix=None):
209
- from .geometry.tri_normals import TriNormalsScaled
210
-
211
- face_normals = TriNormalsScaled(self.v, self.f).reshape(-1, 3)
212
- ftov = face_to_verts_sparse_matrix if face_to_verts_sparse_matrix else self.faces_by_vertex(as_sparse_matrix=True)
213
- non_scaled_normals = ftov * face_normals
214
- norms = (np.sum(non_scaled_normals ** 2.0, axis=1) ** 0.5).T
215
- norms[norms == 0] = 1.0
216
- return (non_scaled_normals.T / norms).T
217
-
218
- def barycentric_coordinates_for_points(self, points, face_indices):
219
- from .geometry.barycentric_coordinates_of_projection import barycentric_coordinates_of_projection
220
- vertex_indices = self.f[face_indices.flatten(), :]
221
- tri_vertices = np.array([self.v[vertex_indices[:, 0]], self.v[vertex_indices[:, 1]], self.v[vertex_indices[:, 2]]])
222
- return vertex_indices, barycentric_coordinates_of_projection(points, tri_vertices[0, :], tri_vertices[1, :] - tri_vertices[0, :], tri_vertices[2, :] - tri_vertices[0, :])
223
-
224
- def transfer_segm(self, mesh, exclude_empty_parts=True):
225
- self.segm = {}
226
- if hasattr(mesh, 'segm'):
227
- face_centers = np.array([self.v[face, :].mean(axis=0) for face in self.f])
228
- (closest_faces, closest_points) = mesh.closest_faces_and_points(face_centers)
229
- mesh_parts_by_face = mesh.parts_by_face()
230
- parts_by_face = [mesh_parts_by_face[face] for face in closest_faces.flatten()]
231
- self.segm = dict([(part, []) for part in mesh.segm.keys()])
232
- for face, part in enumerate(parts_by_face):
233
- self.segm[part].append(face)
234
- for part in self.segm.keys():
235
- self.segm[part].sort()
236
- if exclude_empty_parts and not self.segm[part]:
237
- del self.segm[part]
238
-
239
- @property
240
- def verts_by_segm(self):
241
- return dict((segment, sorted(set(self.f[indices].flatten()))) for segment, indices in self.segm.items())
242
-
243
- def parts_by_face(self):
244
- segments_by_face = [''] * len(self.f)
245
- for part in self.segm.keys():
246
- for face in self.segm[part]:
247
- segments_by_face[face] = part
248
- return segments_by_face
249
-
250
- def verts_in_common(self, segments):
251
- """
252
- returns array of all vertex indices common to each segment in segments"""
253
- return sorted(reduce(lambda s0, s1: s0.intersection(s1),
254
- [set(self.verts_by_segm[segm]) for segm in segments]))
255
- # # indices of vertices in the faces of the first segment
256
- # indices = self.verts_by_segm[segments[0]]
257
- # for segment in segments[1:] :
258
- # indices = sorted([index for index in self.verts_by_segm[segment] if index in indices]) # Intersect current segment with current indices
259
- # return sorted(set(indices))
260
-
261
- @property
262
- def joint_names(self):
263
- return self.joint_regressors.keys()
264
-
265
- @property
266
- def joint_xyz(self):
267
- joint_locations = {}
268
- for name in self.joint_names:
269
- joint_locations[name] = self.joint_regressors[name]['offset'] + \
270
- np.sum(self.v[self.joint_regressors[name]['v_indices']].T * self.joint_regressors[name]['coeff'], axis=1)
271
- return joint_locations
272
-
273
- # creates joint_regressors from a list of joint names and a per joint list of vertex indices (e.g. a ring of vertices)
274
- # For the regression coefficients, all vertices for a given joint are given equal weight
275
- def set_joints(self, joint_names, vertex_indices):
276
- self.joint_regressors = {}
277
- for name, indices in zip(joint_names, vertex_indices):
278
- self.joint_regressors[name] = {'v_indices': indices,
279
- 'coeff': [1.0 / len(indices)] * len(indices),
280
- 'offset': np.array([0., 0., 0.])}
281
-
282
- def vertex_visibility(self, camera, normal_threshold=None, omni_directional_camera=False, binary_visiblity=True):
283
-
284
- vis, n_dot_cam = self.vertex_visibility_and_normals(camera, omni_directional_camera)
285
-
286
- if normal_threshold is not None:
287
- vis = np.logical_and(vis, n_dot_cam > normal_threshold)
288
-
289
- return np.squeeze(vis) if binary_visiblity else np.squeeze(vis * n_dot_cam)
290
-
291
- def vertex_visibility_and_normals(self, camera, omni_directional_camera=False):
292
- from .visibility import visibility_compute
293
- arguments = {'v': self.v,
294
- 'f': self.f,
295
- 'cams': np.array([camera.origin.flatten()])}
296
-
297
- if not omni_directional_camera:
298
- arguments['sensors'] = np.array([camera.sensor_axis.flatten()])
299
-
300
- arguments['n'] = self.vn if hasattr(self, 'vn') else self.estimate_vertex_normals()
301
-
302
- return(visibility_compute(**arguments))
303
-
304
- def visibile_mesh(self, camera=[0.0, 0.0, 0.0]):
305
- vis = self.vertex_visibility(camera)
306
- faces_to_keep = filter(lambda face: vis[face[0]] * vis[face[1]] * vis[face[2]], self.f)
307
- vertex_indices_to_keep = np.nonzero(vis)[0]
308
- vertices_to_keep = self.v[vertex_indices_to_keep]
309
- old_to_new_indices = np.zeros(len(vis))
310
- old_to_new_indices[vertex_indices_to_keep] = range(len(vertex_indices_to_keep))
311
- return Mesh(v=vertices_to_keep, f=np.array([old_to_new_indices[face] for face in faces_to_keep]))
312
-
313
- def estimate_circumference(self, plane_normal, plane_distance, partNamesAllowed=None, want_edges=False):
314
- raise Exception('estimate_circumference function has moved to body.mesh.metrics.circumferences')
315
-
316
- # ######################################################
317
- # Processing
318
- def reset_normals(self, face_to_verts_sparse_matrix=None, reset_face_normals=False):
319
- return processing.reset_normals(self, face_to_verts_sparse_matrix, reset_face_normals)
320
-
321
- def reset_face_normals(self):
322
- return processing.reset_face_normals(self)
323
-
324
- def uniquified_mesh(self):
325
- """This function returns a copy of the mesh in which vertices are copied such that
326
- each vertex appears in only one face, and hence has only one texture"""
327
- return processing.uniquified_mesh(self)
328
-
329
- def keep_vertices(self, keep_list):
330
- return processing.keep_vertices(self, keep_list)
331
-
332
- def remove_vertices(self, v_list):
333
- return self.keep_vertices(np.setdiff1d(np.arange(self.v.shape[0]), v_list))
334
-
335
- def point_cloud(self):
336
- return Mesh(v=self.v, f=[], vc=self.vc) if hasattr(self, 'vc') else Mesh(v=self.v, f=[])
337
-
338
- def remove_faces(self, face_indices_to_remove):
339
- return processing.remove_faces(self, face_indices_to_remove)
340
-
341
- def scale_vertices(self, scale_factor):
342
- return processing.scale_vertices(self, scale_factor)
343
-
344
- def rotate_vertices(self, rotation):
345
- return processing.rotate_vertices(self, rotation)
346
-
347
- def translate_vertices(self, translation):
348
- return processing.translate_vertices(self, translation)
349
-
350
- def flip_faces(self):
351
- return processing.flip_faces(self)
352
-
353
- def simplified(self, factor=None, n_verts_desired=None):
354
- from .topology import qslim_decimator
355
- return qslim_decimator(self, factor, n_verts_desired)
356
-
357
- def subdivide_triangles(self):
358
- return processing.subdivide_triangles(self)
359
-
360
- def concatenate_mesh(self, mesh):
361
- return processing.concatenate_mesh(self, mesh)
362
-
363
- # new_ordering specifies the new index of each vertex. If new_ordering[i] = j,
364
- # vertex i should now be the j^th vertex. As such, each entry in new_ordering should be unique.
365
- def reorder_vertices(self, new_ordering, new_normal_ordering=None):
366
- processing.reorder_vertices(self, new_ordering, new_normal_ordering)
367
-
368
- # ######################################################
369
- # Landmark methods
370
-
371
- @property
372
- def landm_names(self):
373
- names = []
374
- if hasattr(self, 'landm_regressors') or hasattr(self, 'landm'):
375
- names = self.landm_regressors.keys() if hasattr(self, 'landm_regressors') else self.landm.keys()
376
- return list(names)
377
-
378
- @property
379
- def landm_xyz(self, ordering=None):
380
- landmark_order = ordering if ordering else self.landm_names
381
- landmark_vertex_locations = (self.landm_xyz_linear_transform(landmark_order) * self.v.flatten()).reshape(-1, 3) if landmark_order else np.zeros((0, 0))
382
- return dict([(landmark_order[i], xyz) for i, xyz in enumerate(landmark_vertex_locations)]) if landmark_order else {}
383
-
384
- def set_landmarks_from_xyz(self, landm_raw_xyz):
385
- self.landm_raw_xyz = landm_raw_xyz if hasattr(landm_raw_xyz, 'keys') else dict((str(i), l) for i, l in enumerate(landm_raw_xyz))
386
- self.recompute_landmark_indices()
387
-
388
- def landm_xyz_linear_transform(self, ordering=None):
389
- return landmarks.landm_xyz_linear_transform(self, ordering)
390
-
391
- def recompute_landmark_xyz(self):
392
- self.landm_raw_xyz = dict((name, self.v[ind]) for name, ind in self.landm.items())
393
-
394
- def recompute_landmark_indices(self, landmark_fname=None, safe_mode=True):
395
- landmarks.recompute_landmark_indices(self, landmark_fname, safe_mode)
396
-
397
- def set_landmarks_from_regressors(self, regressors):
398
- self.landm_regressors = regressors
399
-
400
- def set_landmark_indices_from_any(self, landmark_file_or_values):
401
- serialization.set_landmark_indices_from_any(self, landmark_file_or_values)
402
-
403
- def set_landmarks_from_raw(self, landmark_file_or_values):
404
- landmarks.set_landmarks_from_raw(self, landmark_file_or_values)
405
-
406
- #######################################################
407
- # Texture methods
408
-
409
- @property
410
- def texture_image(self):
411
- if not hasattr(self, '_texture_image'):
412
- self.reload_texture_image()
413
- return self._texture_image
414
-
415
- def set_texture_image(self, path_to_texture):
416
- self.texture_filepath = path_to_texture
417
-
418
- def texture_coordinates_by_vertex(self):
419
- return texture.texture_coordinates_by_vertex(self)
420
-
421
- def reload_texture_image(self):
422
- texture.reload_texture_image(self)
423
-
424
- def transfer_texture(self, mesh_with_texture):
425
- texture.transfer_texture(self, mesh_with_texture)
426
-
427
- def load_texture(self, texture_version):
428
- texture.load_texture(self, texture_version)
429
-
430
- def texture_rgb(self, texture_coordinate):
431
- return texture.texture_rgb(self, texture_coordinate)
432
-
433
- def texture_rgb_vec(self, texture_coordinates):
434
- return texture.texture_rgb_vec(self, texture_coordinates)
435
-
436
- #######################################################
437
- # Search methods
438
-
439
- def compute_aabb_tree(self):
440
- return search.AabbTree(self)
441
-
442
- def compute_aabb_normals_tree(self):
443
- return search.AabbNormalsTree(self)
444
-
445
- def compute_closest_point_tree(self, use_cgal=False):
446
- return search.CGALClosestPointTree(self) if use_cgal else search.ClosestPointTree(self)
447
-
448
- def closest_vertices(self, vertices, use_cgal=False):
449
- return self.compute_closest_point_tree(use_cgal).nearest(vertices)
450
-
451
- def closest_points(self, vertices):
452
- return self.closest_faces_and_points(vertices)[1]
453
-
454
- def closest_faces_and_points(self, vertices):
455
- return self.compute_aabb_tree().nearest(vertices)
456
-
457
- #######################################################
458
- # Serialization methods
459
-
460
- def load_from_file(self, filename):
461
- serialization.load_from_file(self, filename)
462
-
463
- def load_from_ply(self, filename):
464
- serialization.load_from_ply(self, filename)
465
-
466
- def load_from_obj(self, filename):
467
- serialization.load_from_obj(self, filename)
468
-
469
- def write_json(self, filename, header="", footer="", name="", include_faces=True, texture_mode=True):
470
- serialization.write_json(self, filename, header, footer, name, include_faces, texture_mode)
471
-
472
- def write_three_json(self, filename, name=""):
473
- serialization.write_three_json(self, filename, name)
474
-
475
- def write_ply(self, filename, flip_faces=False, ascii=False, little_endian=True, comments=[]):
476
- serialization.write_ply(self, filename, flip_faces, ascii, little_endian, comments)
477
-
478
- def write_mtl(self, path, material_name, texture_name):
479
- """Serializes a material attributes file"""
480
- serialization.write_mtl(self, path, material_name, texture_name)
481
-
482
- def write_obj(self, filename, flip_faces=False, group=False, comments=None):
483
- serialization.write_obj(self, filename, flip_faces, group, comments)
484
-
485
- def load_from_obj_cpp(self, filename):
486
- serialization.load_from_obj_cpp(self, filename)
487
-
488
- def set_landmark_indices_from_ppfile(self, ppfilename):
489
- serialization.set_landmark_indices_from_ppfile(self, ppfilename)
490
-
491
- def set_landmark_indices_from_lmrkfile(self, lmrkfilename):
492
- serialization.set_landmark_indices_from_lmrkfile(self, lmrkfilename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/meshviewer.py DELETED
@@ -1,1274 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2012 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2012-05-11.
6
-
7
- """
8
- Mesh visualization and related classes
9
- --------------------------------------
10
-
11
- This module contains the core visualization tools for meshes. The
12
- backend used for visualization is OpenGL.
13
-
14
- The module itself can be run like the following
15
-
16
- .. code::
17
-
18
- python -m psbody.mesh.meshviewer arguments
19
-
20
- The following commands are used
21
-
22
- * ``arguments=TEST_FOR_OPENGL`` a basic OpenGL support is run. This
23
- is usually performed on a forked python process. In case OpenGL is
24
- not supported, a `DummyClass`` mesh viewer is returned.
25
-
26
- * ``arguments=title nb_x_axis nb_y_axis width height`` a new window is
27
- created
28
-
29
- .. autosummary::
30
-
31
- MeshViewer
32
- MeshViewers
33
- MeshViewerLocal
34
- test_for_opengl
35
- """
36
-
37
- import copy
38
- import logging
39
- import multiprocessing
40
- import os
41
- import re
42
- import subprocess
43
- import sys
44
- import tempfile
45
- import time
46
- import traceback
47
-
48
- import numpy as np
49
- from OpenGL import GL, GLU, GLUT
50
- from OpenGL.arrays.vbo import VBO
51
- from PIL import Image
52
- import zmq
53
-
54
- # if this file is processed/run as a python script/standalone, especially from the
55
- # internal command
56
- if __package__ is not None:
57
- from .arcball import (
58
- ArcBallT, Matrix3fT, Matrix4fT, Point2fT,
59
- Matrix3fMulMatrix3f, Matrix3fSetRotationFromQuat4f,
60
- Matrix4fSetRotationFromMatrix3f)
61
- from .geometry.tri_normals import TriNormals
62
- from .fonts import get_textureid_with_text
63
- from .mesh import Mesh
64
-
65
-
66
- # this block is below the previous one to make my linter happy
67
- if __package__ is None:
68
- print("this file cannot be executed as a standalone python module")
69
- print("python -m psbody.mesh.%s arguments" % (os.path.splitext(os.path.basename(__file__))[0]))
70
- sys.exit(-1)
71
-
72
-
73
- # Default transport and host are such that we can listen for incoming
74
- # network connections.
75
- ZMQ_TRANSPORT = "tcp"
76
- ZMQ_HOST = "0.0.0.0"
77
- # The dynamic port range.
78
- ZMQ_PORT_MIN = 49152
79
- ZMQ_PORT_MAX = 65535
80
-
81
- MESH_VIEWER_DEFAULT_TITLE = "Mesh Viewer"
82
- MESH_VIEWER_DEFAULT_SHAPE = (1, 1)
83
- MESH_VIEWER_DEFAULT_WIDTH = 1280
84
- MESH_VIEWER_DEFAULT_HEIGHT = 960
85
-
86
-
87
- def _run_self(args, stdin=None, stdout=None, stderr=None):
88
- """Executes this same script module with the given arguments (forking without subprocess dependencies)"""
89
- return subprocess.Popen([sys.executable] +
90
- ['-m'] + ['%s.%s' % (__package__, os.path.splitext(os.path.basename(__file__))[0])] +
91
- args,
92
- stdin=stdin,
93
- stdout=stdout, # if stdout is not None else subprocess.PIPE,
94
- stderr=stderr)
95
-
96
-
97
- def _test_for_opengl():
98
- try:
99
- # from OpenGL.GLUT import glutInit
100
- GLUT.glutInit()
101
- except Exception as e:
102
- print(e, file=sys.stderr)
103
- print('failure')
104
- else:
105
- print('success')
106
-
107
-
108
- test_for_opengl_cached = None
109
-
110
-
111
- def test_for_opengl():
112
- """Tests if opengl is supported.
113
-
114
- .. note:: the result of the test is cached
115
-
116
- """
117
-
118
- global test_for_opengl_cached
119
- if test_for_opengl_cached is None:
120
-
121
- with open(os.devnull) as dev_null, \
122
- tempfile.TemporaryFile() as out, \
123
- tempfile.TemporaryFile() as err:
124
-
125
- p = _run_self(["TEST_FOR_OPENGL"],
126
- stdin=dev_null,
127
- stdout=out,
128
- stderr=err)
129
- p.wait()
130
-
131
- out.seek(0)
132
- err.seek(0)
133
-
134
- line = ''.join(out.read().decode())
135
- test_for_opengl_cached = 'success' in line
136
- if not test_for_opengl_cached:
137
- print('OpenGL test failed: ')
138
- print('\tstdout:', line)
139
- print('\tstderr:', '\n'.join(err.read().decode()))
140
-
141
- return test_for_opengl_cached
142
-
143
-
144
- class Dummy:
145
-
146
- def __getattr__(self, name):
147
- return Dummy()
148
-
149
- def __call__(self, *args, **kwargs):
150
- return Dummy()
151
-
152
- def __getitem__(self, key):
153
- return Dummy()
154
-
155
- def __setitem__(self, key, value):
156
- pass
157
-
158
-
159
- def MeshViewer(titlebar='Mesh Viewer',
160
- static_meshes=None,
161
- static_lines=None,
162
- uid=None,
163
- autorecenter=True,
164
- shape=(1, 1),
165
- keepalive=True,
166
- window_width=1280,
167
- window_height=960,
168
- snapshot_camera=None):
169
- """Allows visual inspection of geometric primitives.
170
-
171
- Write-only Attributes:
172
-
173
- :param titlebar: string printed in the window titlebar
174
- :param static_meshes: list of Mesh objects to be displayed
175
- :param static_lines: list of Lines objects to be displayed
176
-
177
- .. note:: `static_meshes` is meant for Meshes that are updated infrequently,
178
- `and dynamic_meshes` is for Meshes that are updated frequently
179
- (same for `dynamic_lines` vs. `static_lines`).
180
- They may be treated differently for performance reasons.
181
-
182
- """
183
-
184
- if not test_for_opengl():
185
- return Dummy()
186
-
187
- mv = MeshViewerLocal(shape=(1, 1),
188
- uid=uid,
189
- titlebar=titlebar,
190
- keepalive=keepalive,
191
- window_width=window_width,
192
- window_height=window_height)
193
- result = mv.get_subwindows()[0][0]
194
- result.snapshot_camera = snapshot_camera
195
- if static_meshes:
196
- result.static_meshes = static_meshes
197
- if static_lines:
198
- result.static_lines = static_lines
199
- result.autorecenter = autorecenter
200
-
201
- return result
202
-
203
-
204
- def MeshViewers(shape=(1, 1),
205
- titlebar="Mesh Viewers",
206
- keepalive=True,
207
- window_width=1280,
208
- window_height=960):
209
- """Allows subplot-style inspection of primitives in multiple subwindows.
210
-
211
- :param shape: a tuple indicating the number of vertical and horizontal windows requested
212
- :param titlebar: the title appearing on the created window
213
-
214
-
215
- Returns: a list of lists of MeshViewer objects: one per window requested.
216
- """
217
-
218
- if not test_for_opengl():
219
- return Dummy()
220
-
221
- mv = MeshViewerLocal(shape=shape,
222
- titlebar=titlebar,
223
- uid=None,
224
- keepalive=keepalive,
225
- window_width=window_width,
226
- window_height=window_height)
227
- return mv.get_subwindows()
228
-
229
-
230
- class MeshSubwindow:
231
-
232
- def __init__(self, parent_window, which_window):
233
- self.parent_window = parent_window
234
- self.which_window = which_window
235
-
236
- def set_dynamic_meshes(self, list_of_meshes, blocking=False):
237
- self.parent_window.set_dynamic_meshes(list_of_meshes, blocking, self.which_window)
238
-
239
- def set_static_meshes(self, list_of_meshes, blocking=False):
240
- self.parent_window.set_static_meshes(list_of_meshes, blocking, self.which_window)
241
-
242
- # list_of_model_names_and_parameters should be of form [{'name': scape_model_name, 'parameters': scape_model_parameters}]
243
- # here scape_model_name is the filepath of the scape model.
244
- def set_dynamic_models(self, list_of_model_names_and_parameters, blocking=False):
245
- self.parent_window.set_dynamic_models(list_of_model_names_and_parameters, blocking, self.which_window)
246
-
247
- def set_dynamic_lines(self, list_of_lines, blocking=False):
248
- self.parent_window.set_dynamic_lines(list_of_lines, blocking, self.which_window)
249
-
250
- def set_static_lines(self, list_of_lines, blocking=False):
251
- self.parent_window.set_static_lines(list_of_lines, blocking=blocking, which_window=self.which_window)
252
-
253
- def set_titlebar(self, titlebar, blocking=False):
254
- self.parent_window.set_titlebar(titlebar, blocking, which_window=self.which_window)
255
-
256
- def set_lighting_on(self, lighting_on, blocking=True):
257
- self.parent_window.set_lighting_on(lighting_on, blocking=blocking, which_window=self.which_window)
258
-
259
- def set_autorecenter(self, autorecenter, blocking=False):
260
- self.parent_window.set_autorecenter(autorecenter, blocking=blocking, which_window=self.which_window)
261
-
262
- def set_background_color(self, background_color, blocking=False):
263
- self.parent_window.set_background_color(background_color, blocking=blocking, which_window=self.which_window)
264
-
265
- def save_snapshot(self, path, blocking=False):
266
- self.parent_window.save_snapshot(
267
- path, blocking=blocking, which_window=self.which_window)
268
-
269
- def get_event(self):
270
- return self.parent_window.get_event()
271
-
272
- def get_keypress(self):
273
- return self.parent_window.get_keypress()['key']
274
-
275
- def get_mouseclick(self):
276
- return self.parent_window.get_mouseclick()
277
-
278
- def close(self):
279
- self.parent_window.p.terminate()
280
-
281
- background_color = property(fset=set_background_color, doc="Background color, as 3-element numpy array where 0 <= color <= 1.0.")
282
- dynamic_meshes = property(fset=set_dynamic_meshes, doc="List of meshes for dynamic display.")
283
- static_meshes = property(fset=set_static_meshes, doc="List of meshes for static display.")
284
- dynamic_models = property(fset=set_dynamic_models, doc="List of model names and parameters for dynamic display.")
285
- dynamic_lines = property(fset=set_dynamic_lines, doc="List of Lines for dynamic display.")
286
- static_lines = property(fset=set_static_lines, doc="List of Lines for static display.")
287
- titlebar = property(fset=set_titlebar, doc="Titlebar string.")
288
- lighting_on = property(fset=set_lighting_on, doc="Titlebar string.")
289
-
290
-
291
- class MeshViewerSingle:
292
-
293
- def __init__(self, x1_pct, y1_pct, width_pct, height_pct):
294
- assert(width_pct <= 1)
295
- assert(height_pct <= 1)
296
- self.dynamic_meshes = []
297
- self.static_meshes = []
298
- self.dynamic_models = []
299
- self.dynamic_lines = []
300
- self.static_lines = []
301
- self.lighting_on = True
302
- self.scape_models = {}
303
- self.x1_pct = x1_pct
304
- self.y1_pct = y1_pct
305
- self.width_pct = width_pct
306
- self.height_pct = height_pct
307
- self.autorecenter = True
308
-
309
- def get_dimensions(self):
310
- d = {}
311
- d['window_width'] = GLUT.glutGet(GLUT.GLUT_WINDOW_WIDTH)
312
- d['window_height'] = GLUT.glutGet(GLUT.GLUT_WINDOW_HEIGHT)
313
- d['subwindow_width'] = self.width_pct * d['window_width']
314
- d['subwindow_height'] = self.height_pct * d['window_height']
315
- d['subwindow_origin_x'] = self.x1_pct * d['window_width']
316
- d['subwindow_origin_y'] = self.y1_pct * d['window_height']
317
- return d
318
-
319
- def on_draw(self, transform, want_camera=False):
320
-
321
- d = self.get_dimensions()
322
-
323
- GL.glViewport(
324
- int(d['subwindow_origin_x']),
325
- int(d['subwindow_origin_y']),
326
- int(d['subwindow_width']),
327
- int(d['subwindow_height']))
328
-
329
- GL.glMatrixMode(GL.GL_PROJECTION)
330
- GL.glLoadIdentity()
331
-
332
- fov_degrees = 45.
333
- near = 1.0
334
- far = 100.
335
- ratio = float(d['subwindow_width']) / float(d['subwindow_height'])
336
- if d['subwindow_width'] < d['subwindow_height']:
337
- xt = np.tan(fov_degrees * np.pi / 180. / 2.0) * near
338
- yt = xt / ratio
339
- GL.glFrustum(-xt, xt, -yt, yt, near, far)
340
- else:
341
- GLU.gluPerspective(fov_degrees, ratio, near, far)
342
-
343
- GL.glMatrixMode(GL.GL_MODELVIEW)
344
- GL.glLoadIdentity()
345
- GL.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE)
346
-
347
- GL.glTranslatef(0.0, 0.0, -6.0)
348
- # GL.glTranslatef(0.0,0.0,-3.5)
349
-
350
- GL.glPushMatrix()
351
- GL.glMultMatrixf(transform)
352
- GL.glColor3f(1.0, 0.75, 0.75)
353
-
354
- if self.autorecenter:
355
- camera = self.draw_primitives_recentered(want_camera=want_camera)
356
- else:
357
- if hasattr(self, 'current_center') and hasattr(self, 'current_scalefactor'):
358
- camera = self.draw_primitives(scalefactor=self.current_scalefactor, center=self.current_center)
359
- else:
360
- camera = self.draw_primitives(want_camera=want_camera)
361
-
362
- GL.glPopMatrix()
363
-
364
- if want_camera:
365
- return camera
366
-
367
- def draw_primitives_recentered(self, want_camera=False):
368
- return self.draw_primitives(recenter=True, want_camera=want_camera)
369
-
370
- @staticmethod
371
- def set_shaders(m):
372
- VERTEX_SHADER = GL.shaders.compileShader("""void main() {
373
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
374
- }""", GL.GL_VERTEX_SHADER)
375
- FRAGMENT_SHADER = GL.shaders.compileShader("""void main() {
376
- gl_FragColor = vec4( 0, 1, 0, 1 );
377
- }""", GL.GL_FRAGMENT_SHADER)
378
- m.shaders = GL.shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)
379
-
380
- @staticmethod
381
- def set_texture(m):
382
- texture_data = np.array(m.texture_image, dtype='int8')
383
- m.textureID = GL.glGenTextures(1)
384
- GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
385
- GL.glBindTexture(GL.GL_TEXTURE_2D, m.textureID)
386
- GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, texture_data.shape[1], texture_data.shape[0], 0, GL.GL_BGR, GL.GL_UNSIGNED_BYTE, texture_data.flatten())
387
- GL.glHint(GL.GL_GENERATE_MIPMAP_HINT, GL.GL_NICEST) # must be GL_FASTEST, GL.GL_NICEST or GL_DONT_CARE
388
- GL.glGenerateMipmap(GL.GL_TEXTURE_2D)
389
-
390
- @staticmethod
391
- def draw_mesh(m, lighting_on):
392
-
393
- # Supply vertices
394
- GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
395
- m.vbo['v'].bind()
396
- GL.glVertexPointer(3, GL.GL_FLOAT, 0, m.vbo['v'])
397
- m.vbo['v'].unbind()
398
-
399
- # Supply normals
400
- if 'vn' in m.vbo.keys():
401
- GL.glEnableClientState(GL.GL_NORMAL_ARRAY)
402
- m.vbo['vn'].bind()
403
- GL.glNormalPointer(GL.GL_FLOAT, 0, m.vbo['vn'])
404
- m.vbo['vn'].unbind()
405
- else:
406
- GL.glDisableClientState(GL.GL_NORMAL_ARRAY)
407
-
408
- # Supply colors
409
- if 'vc' in m.vbo.keys():
410
- GL.glEnableClientState(GL.GL_COLOR_ARRAY)
411
- m.vbo['vc'].bind()
412
- GL.glColorPointer(3, GL.GL_FLOAT, 0, m.vbo['vc'])
413
- m.vbo['vc'].unbind()
414
- else:
415
- GL.glDisableClientState(GL.GL_COLOR_ARRAY)
416
-
417
- if ('vt' in m.vbo.keys()) and hasattr(m, 'textureID'):
418
- GL.glEnable(GL.GL_TEXTURE_2D)
419
- GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST)
420
- GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST)
421
- GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE)
422
- GL.glBindTexture(GL.GL_TEXTURE_2D, m.textureID)
423
-
424
- GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY)
425
- m.vbo['vt'].bind()
426
- GL.glTexCoordPointer(2, GL.GL_FLOAT, 0, m.vbo['vt'])
427
- m.vbo['vt'].unbind()
428
- else:
429
- GL.glDisable(GL.GL_TEXTURE_2D)
430
- GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY)
431
-
432
- # Draw
433
- if len(m.f) > 0:
434
- # ie if it is triangulated
435
- if lighting_on:
436
- GL.glEnable(GL.GL_LIGHTING)
437
- else:
438
- GL.glDisable(GL.GL_LIGHTING)
439
- GL.glDrawElementsui(GL.GL_TRIANGLES, np.arange(m.f.size, dtype=np.uint32))
440
- else:
441
- # not triangulated, so disable lighting
442
- GL.glDisable(GL.GL_LIGHTING)
443
- GL.glPointSize(2)
444
- GL.glDrawElementsui(GL.GL_POINTS, np.arange(len(m.v), dtype=np.uint32))
445
- if hasattr(m, 'v_to_text'):
446
-
447
- GL.glEnable(GL.GL_TEXTURE_2D)
448
- GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
449
- GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR)
450
- GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL)
451
-
452
- bgcolor = np.array(GL.glGetDoublev(GL.GL_COLOR_CLEAR_VALUE))
453
- fgcolor = 1. - bgcolor
454
-
455
- from .lines import Lines
456
- sc = float(np.max(np.max(m.v, axis=0) - np.min(m.v, axis=0))) / 10.
457
-
458
- cur_mtx = np.linalg.pinv(GL.glGetFloatv(GL.GL_MODELVIEW_MATRIX).T)
459
- xdir = cur_mtx[:3, 0]
460
- ydir = cur_mtx[:3, 1]
461
-
462
- GL.glEnable(GL.GL_LINE_SMOOTH)
463
- GL.glEnable(GL.GL_BLEND)
464
- GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
465
-
466
- for vidx, text in m.v_to_text.items():
467
- pos0 = m.v[vidx].copy()
468
- pos1 = m.v[vidx].copy()
469
- if hasattr(m, 'vn'):
470
- pos1 += m.vn[vidx] * sc
471
- GL.glLineWidth(5.0)
472
- ln = Lines(v=np.vstack((pos0, pos1)), e=np.array([[0, 1]]))
473
- GL.glEnable(GL.GL_LIGHTING)
474
- GL.glColor3f(1. - 0.8, 1. - 0.8, 1. - 1.00)
475
- MeshViewerSingle.draw_lines(ln)
476
-
477
- GL.glDisable(GL.GL_LIGHTING)
478
-
479
- texture_id = get_textureid_with_text(text, bgcolor, fgcolor)
480
- GL.glBindTexture(GL.GL_TEXTURE_2D, texture_id)
481
-
482
- GL.glPushMatrix()
483
- GL.glTranslatef(pos1[0], pos1[1], pos1[2])
484
-
485
- dx = xdir * .10
486
- dy = ydir * .10
487
- if False:
488
- GL.glBegin(GL.GL_QUADS)
489
-
490
- GL.glTexCoord2f(1., 0.)
491
- GL.glVertex3f(*(+dx + dy))
492
-
493
- GL.glTexCoord2f(1., 1.)
494
- GL.glVertex3f(*(+dx - dy))
495
-
496
- GL.glTexCoord2f(0., 1.)
497
- GL.glVertex3f(*(-dx - dy))
498
-
499
- GL.glTexCoord2f(0., 0.)
500
- GL.glVertex3f(*(-dx + dy))
501
-
502
- # gluSphere(quadratic,0.05,32,32)
503
- GL.glEnd()
504
- else:
505
- GL.glBegin(GL.GL_POLYGON)
506
-
507
- for r in np.arange(0, np.pi * 2., .01):
508
- GL.glTexCoord2f(np.cos(r) / 2. + .5, np.sin(r) / 2. + .5)
509
- GL.glVertex3f(*(dx * np.cos(r) + -dy * np.sin(r)))
510
-
511
- GL.glEnd()
512
- GL.glPopMatrix()
513
-
514
-
515
- @staticmethod
516
- def draw_lines(ls):
517
- GL.glDisableClientState(GL.GL_NORMAL_ARRAY)
518
- GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
519
- GL.glLineWidth(3.0)
520
- allpts = ls.v[ls.e.flatten()].astype(np.float32)
521
- GL.glVertexPointerf(allpts)
522
- if hasattr(ls, 'vc') or hasattr(ls, 'ec'):
523
- GL.glEnableClientState(GL.GL_COLOR_ARRAY)
524
- if hasattr(ls, 'vc'):
525
- GL.glColorPointerf(ls.vc[ls.e.flatten()].astype(np.float32))
526
- else:
527
- clrs = np.ones((ls.e.shape[0] * 2, 3)) * np.repeat(ls.ec, 2, axis=0)
528
- GL.glColorPointerf(clrs)
529
- else:
530
- GL.glDisableClientState(GL.GL_COLOR_ARRAY)
531
-
532
- GL.glDisable(GL.GL_LIGHTING)
533
- GL.glDrawElementsui(GL.GL_LINES, np.arange(len(allpts), dtype=np.uint32))
534
-
535
- def draw_primitives(self,
536
- scalefactor=1.0,
537
- center=[0.0, 0.0, 0.0],
538
- recenter=False,
539
- want_camera=False):
540
-
541
- # measure the bounding box of all our primitives, so that we can
542
- # recenter them in our field of view
543
- if recenter:
544
- all_meshes = self.static_meshes + self.dynamic_meshes
545
- all_lines = self.static_lines + self.dynamic_lines
546
-
547
- if (len(all_meshes) + len(all_lines)) == 0:
548
- if want_camera:
549
- return {'modelview_matrix': GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX),
550
- 'projection_matrix': GL.glGetDoublev(GL.GL_PROJECTION_MATRIX),
551
- 'viewport': GL.glGetIntegerv(GL.GL_VIEWPORT)
552
- }
553
- else:
554
- return None
555
-
556
- for m in all_meshes:
557
- m.v = m.v.reshape((-1, 3))
558
-
559
- all_verts = np.concatenate(
560
- [m.v[m.f.flatten() if len(m.f) > 0 else np.arange(len(m.v))] for m in all_meshes] +
561
- [l.v[l.e.flatten()] for l in all_lines],
562
- axis=0)
563
-
564
- maximum = np.max(all_verts, axis=0)
565
- minimum = np.min(all_verts, axis=0)
566
- center = (maximum + minimum) / 2.
567
- scalefactor = (maximum - minimum) / 4.
568
- scalefactor = np.max(scalefactor)
569
- else:
570
- center = np.array(center)
571
- # for mesh in self.dynamic_meshes :
572
- # if mesh.f : mesh.reset_normals()
573
- all_meshes = self.static_meshes + self.dynamic_meshes
574
- all_lines = self.static_lines + self.dynamic_lines
575
- self.current_center = center
576
- self.current_scalefactor = scalefactor
577
-
578
- GL.glMatrixMode(GL.GL_MODELVIEW)
579
- GL.glPushMatrix()
580
- # uncomment to add a default rotation (useful when automatically snapshoting kinect data
581
- # glRotate(220, 0.0, 1.0, 0.0)
582
-
583
- tf = np.identity(4, 'f') / scalefactor
584
- tf[:3, 3] = -center / scalefactor
585
- tf[3, 3] = 1
586
- cur_mtx = GL.glGetFloatv(GL.GL_MODELVIEW_MATRIX).T
587
-
588
- GL.glLoadMatrixf(cur_mtx.dot(tf).T)
589
-
590
- if want_camera:
591
- result = {'modelview_matrix': GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX),
592
- 'projection_matrix': GL.glGetDoublev(GL.GL_PROJECTION_MATRIX),
593
- 'viewport': GL.glGetIntegerv(GL.GL_VIEWPORT)
594
- }
595
- else:
596
- result = None
597
-
598
- for m in all_meshes:
599
- if not hasattr(m, 'vbo'):
600
- # Precompute vertex vbo
601
- fidxs = m.f.flatten() if len(m.f) > 0 else np.arange(len(m.v))
602
- allpts = m.v[fidxs].astype(np.float32).flatten()
603
- vbo = VBO(allpts)
604
- m.vbo = {'v': vbo}
605
-
606
- # Precompute normals vbo
607
- if hasattr(m, 'vn'):
608
- ns = m.vn.astype(np.float32)
609
- ns = ns[m.f.flatten(), :]
610
- m.vbo['vn'] = VBO(ns.flatten())
611
- elif hasattr(m, 'f') and m.f.size > 0:
612
- ns = TriNormals(m.v, m.f).reshape(-1, 3)
613
- ns = np.tile(ns, (1, 3)).reshape(-1, 3).astype(np.float32)
614
- m.vbo['vn'] = VBO(ns.flatten())
615
-
616
- # Precompute texture vbo
617
- if hasattr(m, 'ft') and (m.ft.size > 0):
618
- ftidxs = m.ft.flatten()
619
- data = m.vt[ftidxs].astype(np.float32)[:, 0:2]
620
- data[:, 1] = 1.0 - 1.0 * data[:, 1]
621
- m.vbo['vt'] = VBO(data)
622
-
623
- # Precompute color vbo
624
- if hasattr(m, 'vc'):
625
- data = m.vc[fidxs].astype(np.float32)
626
- m.vbo['vc'] = VBO(data)
627
- elif hasattr(m, 'fc'):
628
- data = np.tile(m.fc, (1, 3)).reshape(-1, 3).astype(np.float32)
629
- m.vbo['vc'] = VBO(data)
630
-
631
- for e in all_lines:
632
- self.draw_lines(e)
633
-
634
- for m in all_meshes:
635
- if hasattr(m, 'texture_image') and not hasattr(m, 'textureID'):
636
- self.set_texture(m)
637
- self.draw_mesh(m, self.lighting_on)
638
-
639
- GL.glMatrixMode(GL.GL_MODELVIEW)
640
- GL.glPopMatrix()
641
-
642
- return result
643
-
644
-
645
- class MeshViewerLocal:
646
- """Proxy viewer instance for visual inspection of geometric primitives.
647
-
648
- The class forks another python process holding the display. It communicates
649
- the commands with the remote instance seamlessly.
650
-
651
- Write-only attributes:
652
-
653
- :param titlebar: string printed in the window titlebar
654
- :param dynamic_meshes: list of Mesh objects to be displayed
655
- :param static_meshes: list of Mesh objects to be displayed
656
- :param dynamic_lines: list of Lines objects to be displayed
657
- :param static_lines: list of Lines objects to be displayed
658
-
659
- .. note::
660
-
661
- `static_meshes` is meant for Meshes that are
662
- updated infrequently, and dynamic_meshes is for Meshes
663
- that are updated frequently (same for dynamic_lines vs
664
- static_lines). They may be treated differently for
665
- performance reasons.
666
-
667
- """
668
-
669
- managed = {}
670
-
671
- def __new__(
672
- cls,
673
- titlebar=MESH_VIEWER_DEFAULT_TITLE,
674
- uid=None,
675
- host=ZMQ_HOST,
676
- port=None,
677
- shape=MESH_VIEWER_DEFAULT_SHAPE,
678
- keepalive=False,
679
- window_width=MESH_VIEWER_DEFAULT_WIDTH,
680
- window_height=MESH_VIEWER_DEFAULT_HEIGHT
681
- ):
682
-
683
- assert(uid is None or isinstance(uid, str))
684
-
685
- if uid == 'stack':
686
- uid = ''.join(traceback.format_list(traceback.extract_stack()))
687
- if uid and uid in MeshViewer.managed.keys():
688
- return MeshViewer.managed[uid]
689
-
690
- viewer = super(MeshViewerLocal, cls).__new__(cls)
691
-
692
- viewer.remote_host = host
693
- viewer.remote_port = port
694
-
695
- viewer.client = zmq.Context.instance().socket(zmq.PUSH)
696
- viewer.client.linger = 0
697
-
698
- if viewer.remote_port:
699
- addr = "{}://{}:{}".format(
700
- ZMQ_TRANSPORT,
701
- viewer.remote_host,
702
- viewer.remote_port)
703
- viewer.client.connect(addr)
704
-
705
- # XXX: Proper shape querying over the network is not
706
- # possible as of now. This should be tackled during
707
- # refactoring in the future.
708
-
709
- # viewer.shape = viewer.get_window_shape()
710
- viewer.shape = (1, 1)
711
-
712
- return viewer
713
-
714
- with open(os.devnull) as dev_null, \
715
- tempfile.TemporaryFile() as err:
716
-
717
- viewer.p = _run_self([titlebar, str(shape[0]), str(shape[1]), str(window_width), str(window_height)],
718
- stdin=dev_null,
719
- stdout=subprocess.PIPE,
720
- stderr=err)
721
-
722
- line = viewer.p.stdout.readline().decode()
723
- viewer.p.stdout.close()
724
- current_port = re.match('<PORT>(.*?)</PORT>', line)
725
- if not current_port:
726
- raise Exception("MeshViewer remote appears to have failed to launch")
727
- current_port = int(current_port.group(1))
728
- viewer.client.connect('{}://{}:{}'.format(ZMQ_TRANSPORT, ZMQ_HOST, current_port))
729
-
730
- logging.info(
731
- "started remote viewer on port {}".format(current_port))
732
-
733
- if uid:
734
- MeshViewerLocal.managed[uid] = viewer
735
- viewer.shape = shape
736
- viewer.keepalive = keepalive
737
- return viewer
738
-
739
- def get_subwindows(self):
740
- return [[MeshSubwindow(parent_window=self, which_window=(r, c)) for c in range(self.shape[1])] for r in range(self.shape[0])]
741
-
742
- @staticmethod
743
- def _sanitize_meshes(list_of_meshes):
744
- lm = []
745
-
746
- # have to copy the meshes for now, because some contain CPython members,
747
- # before pushing them on the queue
748
- for m in list_of_meshes:
749
- if hasattr(m, 'fc'):
750
- lm.append(Mesh(v=m.v, f=m.f, fc=m.fc))
751
- elif hasattr(m, 'vc'):
752
- lm.append(Mesh(v=m.v, f=m.f, vc=m.vc))
753
- else:
754
- lm.append(Mesh(v=m.v, f=m.f if hasattr(m, 'f') else []))
755
-
756
- if hasattr(m, 'vn'):
757
- lm[-1].vn = m.vn
758
- if hasattr(m, 'fn'):
759
- lm[-1].fn = m.fn
760
-
761
- if hasattr(m, 'v_to_text'):
762
- lm[-1].v_to_text = m.v_to_text
763
- if hasattr(m, 'texture_filepath') and hasattr(m, 'vt') and hasattr(m, 'ft'):
764
- lm[-1].texture_filepath = m.texture_filepath
765
- lm[-1].vt = m.vt
766
- lm[-1].ft = m.ft
767
-
768
- return lm
769
-
770
- def _send_pyobj(self, label, obj, blocking, which_window):
771
- logging.debug("sending a request:")
772
- logging.debug("\tlabel = {!r}".format(label))
773
- logging.debug("\tobj = {!r}".format(obj))
774
- logging.debug("\tblocking = {!r}".format(blocking))
775
- logging.debug("\twhich_window = {!r}".format(which_window))
776
-
777
- if blocking:
778
- context = zmq.Context.instance()
779
- server = context.socket(zmq.PULL)
780
- server.linger = 0
781
- port = server.bind_to_random_port(
782
- "{}://{}".format(ZMQ_TRANSPORT, ZMQ_HOST),
783
- min_port=ZMQ_PORT_MIN,
784
- max_port=ZMQ_PORT_MAX,
785
- max_tries=100000)
786
-
787
- # sending with blocking'
788
- self.client.send_pyobj({
789
- 'label': label,
790
- 'obj': obj,
791
- 'port': port,
792
- 'which_window': which_window
793
- })
794
-
795
- task_completion_time = server.recv_pyobj()
796
- # task completion time was %.2fs in other process' % (task_completion_time,)
797
- server.close()
798
- else:
799
- # sending nonblocking
800
- res = self.client.send_pyobj({
801
- 'label': label,
802
- 'obj': obj,
803
- 'which_window': which_window
804
- })
805
-
806
- def _recv_pyobj(self, label, port=None):
807
- context = zmq.Context.instance()
808
- server = context.socket(zmq.PULL)
809
- server.linger = 0
810
-
811
- if not port:
812
- port = server.bind_to_random_port(
813
- "{}://{}".format(ZMQ_TRANSPORT, ZMQ_HOST),
814
- min_port=ZMQ_PORT_MIN,
815
- max_port=ZMQ_PORT_MAX,
816
- max_tries=100000)
817
-
818
- self._send_pyobj(label, port, blocking=True, which_window=(0, 0))
819
- result = server.recv_pyobj()
820
- server.close()
821
-
822
- return result
823
-
824
- def set_dynamic_meshes(self, list_of_meshes, blocking=False, which_window=(0, 0)):
825
- self._send_pyobj('dynamic_meshes', self._sanitize_meshes(list_of_meshes), blocking, which_window)
826
-
827
- def set_static_meshes(self, list_of_meshes, blocking=False, which_window=(0, 0)):
828
- self._send_pyobj('static_meshes', self._sanitize_meshes(list_of_meshes), blocking, which_window)
829
-
830
- # list_of_model_names_and_parameters should be of form [{'name': scape_model_name, 'parameters': scape_model_parameters}]
831
- # here scape_model_name is the filepath of the scape model.
832
- def set_dynamic_models(self, list_of_model_names_and_parameters, blocking=False, which_window=(0, 0)):
833
- self._send_pyobj('dynamic_models', list_of_model_names_and_parameters, blocking, which_window)
834
-
835
- def set_dynamic_lines(self, list_of_lines, blocking=False, which_window=(0, 0)):
836
- self._send_pyobj('dynamic_lines', list_of_lines, blocking, which_window)
837
-
838
- def set_static_lines(self, list_of_lines, blocking=False, which_window=(0, 0)):
839
- self._send_pyobj('static_lines', list_of_lines, blocking, which_window)
840
-
841
- def set_titlebar(self, titlebar, blocking=False, which_window=(0, 0)):
842
- self._send_pyobj('titlebar', titlebar, blocking, which_window)
843
-
844
- def set_lighting_on(self, lighting_on, blocking=False, which_window=(0, 0)):
845
- self._send_pyobj('lighting_on', lighting_on, blocking, which_window)
846
-
847
- def set_autorecenter(self, autorecenter, blocking=False, which_window=(0, 0)):
848
- self._send_pyobj('autorecenter', autorecenter, blocking, which_window)
849
-
850
- def set_background_color(self, background_color, blocking=False, which_window=(0, 0)):
851
- assert(isinstance(background_color, np.ndarray))
852
- assert(background_color.size == 3)
853
- self._send_pyobj('background_color', background_color.flatten(), blocking, which_window)
854
-
855
- def get_keypress(self):
856
- return self._recv_pyobj('get_keypress')
857
-
858
- def get_mouseclick(self):
859
- """Returns a mouse click event.
860
-
861
- .. note::
862
-
863
- the call is blocking the caller until an event is received
864
- """
865
- return self._recv_pyobj('get_mouseclick')
866
-
867
- def get_event(self):
868
- return self._recv_pyobj('get_event')
869
-
870
- def get_window_shape(self):
871
- response = self._recv_pyobj("get_window_shape")
872
- return response["shape"]
873
-
874
- background_color = property(fset=set_background_color,
875
- doc="Background color, as 3-element numpy array where 0 <= color <= 1.0.")
876
-
877
- dynamic_meshes = property(fset=set_dynamic_meshes,
878
- doc="List of meshes for dynamic display.")
879
- static_meshes = property(fset=set_static_meshes,
880
- doc="List of meshes for static display.")
881
- dynamic_models = property(fset=set_dynamic_models,
882
- doc="List of model names and parameters for dynamic display.")
883
-
884
- dynamic_lines = property(fset=set_dynamic_lines,
885
- doc="List of Lines for dynamic display.")
886
- static_lines = property(fset=set_static_lines,
887
- doc="List of Lines for static display.")
888
-
889
- titlebar = property(fset=set_titlebar,
890
- doc="Titlebar string.")
891
-
892
- def save_snapshot(self, path, blocking=False, which_window=(0, 0), wait_time=1):
893
- """Saves a snapshot of the current window into the specified file
894
-
895
- :param path: filename to which the current window content will be saved
896
- :param wait_time: waiting time to save snapshot. Increase it if the image is incomplete
897
- """
898
- print('Saving snapshot to %s, please wait...' % path)
899
- self._send_pyobj('save_snapshot', path, blocking, which_window)
900
- time.sleep(wait_time)
901
-
902
- def __del__(self):
903
- if hasattr(self, "p") and not self.keepalive:
904
- self.p.terminate()
905
-
906
-
907
- class MeshViewerRemote:
908
- def __init__(
909
- self,
910
- titlebar=MESH_VIEWER_DEFAULT_TITLE,
911
- subwins_vert=MESH_VIEWER_DEFAULT_SHAPE[1],
912
- subwins_horz=MESH_VIEWER_DEFAULT_SHAPE[0],
913
- width=MESH_VIEWER_DEFAULT_WIDTH,
914
- height=MESH_VIEWER_DEFAULT_HEIGHT,
915
- port=None
916
- ):
917
-
918
- context = zmq.Context.instance()
919
- self.server = context.socket(zmq.PULL)
920
- self.server.linger = 0
921
-
922
- if not port:
923
- self.port = self.server.bind_to_random_port(
924
- "{}://{}".format(ZMQ_TRANSPORT, ZMQ_HOST),
925
- min_port=ZMQ_PORT_MIN,
926
- max_port=ZMQ_PORT_MAX,
927
- max_tries=100000)
928
- else:
929
- self.server.bind(
930
- "{}://{}:{}".format(ZMQ_TRANSPORT, ZMQ_HOST, port))
931
- self.port = port
932
-
933
- logging.debug(
934
- "listening for incoming messages on port {}"
935
- .format(self.port))
936
-
937
- # Print out our port so that our client can connect to us with it. Flush stdout immediately; otherwise
938
- # our client could wait forever.
939
- print('<PORT>%d</PORT>\n' % (self.port,))
940
- sys.stdout.flush()
941
-
942
- self.arcball = ArcBallT(width, height)
943
- self.transform = Matrix4fT()
944
- self.lastrot = Matrix3fT()
945
- self.thisrot = Matrix3fT()
946
- self.isdragging = False
947
- self.need_redraw = True
948
-
949
- self.shape = (subwins_vert, subwins_horz)
950
- self.mesh_viewers = [
951
- [
952
- MeshViewerSingle(
953
- float(c) / (subwins_horz),
954
- float(r) / (subwins_vert),
955
- 1. / subwins_horz,
956
- 1. / subwins_vert)
957
- for c in range(subwins_horz)
958
- ]
959
- for r in range(subwins_vert)
960
- ]
961
-
962
- self.tm_for_fps = 0.
963
- self.titlebar = titlebar
964
- self.activate(width, height)
965
-
966
- def snapshot(self, path, wait_time=0.1):
967
- """
968
- Takes a snapshot of the meshviewer window and saves it to disc.
969
-
970
- :param path: path to save the snapshot at.
971
- :param wait_time: waiting time to save snapshot. Increase it if the image is incomplete
972
-
973
- .. note:: Requires the Pillow package to be installed.
974
- """
975
- self.on_draw()
976
- time.sleep(wait_time)
977
-
978
- width = GLUT.glutGet(GLUT.GLUT_WINDOW_WIDTH)
979
- height = GLUT.glutGet(GLUT.GLUT_WINDOW_HEIGHT)
980
-
981
- data = (GLU.GLubyte * (3 * width * height))(0)
982
- GL.glReadPixels(0, 0, width, height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, data)
983
- image = Image.frombytes(mode="RGB", size=(width, height), data=data)
984
- image = image.transpose(Image.FLIP_TOP_BOTTOM)
985
-
986
- # Save image to disk
987
- image.save(path)
988
-
989
- def activate(self, width, height):
990
- GLUT.glutInit(['mesh_viewer'])
991
- GLUT.glutInitDisplayMode(GLUT.GLUT_RGBA | GLUT.GLUT_DOUBLE | GLUT.GLUT_ALPHA | GLUT.GLUT_DEPTH)
992
- GLUT.glutInitWindowSize(width, height)
993
- GLUT.glutInitWindowPosition(0, 0)
994
- self.root_window_id = GLUT.glutCreateWindow(self.titlebar)
995
-
996
- GLUT.glutTimerFunc(100, self.checkQueue, 0)
997
- GLUT.glutReshapeFunc(self.on_resize_window)
998
-
999
- GLUT.glutKeyboardFunc(self.on_keypress)
1000
- GLUT.glutMouseFunc(self.on_click)
1001
- GLUT.glutMotionFunc(self.on_drag)
1002
- GLUT.glutDisplayFunc(self.on_draw)
1003
-
1004
- self.init_opengl()
1005
-
1006
- GLUT.glutMainLoop() # won't return until process is killed
1007
-
1008
- def on_drag(self, cursor_x, cursor_y):
1009
- """ Mouse cursor is moving
1010
- Glut calls this function (when mouse button is down)
1011
- and pases the mouse cursor postion in window coords as the mouse moves.
1012
- """
1013
- from .geometry.rodrigues import rodrigues
1014
- if (self.isdragging):
1015
- mouse_pt = Point2fT(cursor_x, cursor_y)
1016
- ThisQuat = self.arcball.drag(mouse_pt) # // Update End Vector And Get Rotation As Quaternion
1017
- self.thisrot = Matrix3fSetRotationFromQuat4f(ThisQuat) # // Convert Quaternion Into Matrix3fT
1018
- # Use correct Linear Algebra matrix multiplication C = A * B
1019
- self.thisrot = Matrix3fMulMatrix3f(self.lastrot, self.thisrot) # // Accumulate Last Rotation Into This One
1020
-
1021
- # make sure it is a rotation
1022
- self.thisrot = rodrigues(rodrigues(self.thisrot)[0])[0]
1023
- self.transform = Matrix4fSetRotationFromMatrix3f(self.transform, self.thisrot) # // Set Our Final Transform's Rotation From This One
1024
- GLUT.glutPostRedisplay()
1025
- return
1026
-
1027
- # The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
1028
- def on_keypress(self, *args):
1029
- key = args[0]
1030
- if hasattr(self, 'event_port'):
1031
- self.keypress_port = self.event_port
1032
- del self.event_port
1033
- if hasattr(self, 'keypress_port'):
1034
- client = zmq.Context.instance().socket(zmq.PUSH)
1035
- client.connect('{}://{}:{}'.format(ZMQ_TRANSPORT, ZMQ_HOST, self.keypress_port))
1036
- client.send_pyobj({'event_type': 'keyboard', 'key': key})
1037
- del self.keypress_port
1038
-
1039
- def on_click(self, button, button_state, cursor_x, cursor_y):
1040
- """ Mouse button clicked.
1041
- Glut calls this function when a mouse button is
1042
- clicked or released.
1043
- """
1044
-
1045
- self.isdragging = False
1046
-
1047
- if (button == GLUT.GLUT_LEFT_BUTTON and button_state == GLUT.GLUT_UP):
1048
- # Left button released
1049
- self.lastrot = copy.copy(self.thisrot) # Set Last Static Rotation To Last Dynamic One
1050
-
1051
- elif (button == GLUT.GLUT_LEFT_BUTTON and button_state == GLUT.GLUT_DOWN):
1052
- # Left button clicked down
1053
- self.lastrot = copy.copy(self.thisrot) # Set Last Static Rotation To Last Dynamic One
1054
- self.isdragging = True # // Prepare For Dragging
1055
- mouse_pt = Point2fT(cursor_x, cursor_y)
1056
- self.arcball.click(mouse_pt) # Update Start Vector And Prepare For Dragging
1057
-
1058
- elif (button == GLUT.GLUT_RIGHT_BUTTON and button_state == GLUT.GLUT_DOWN):
1059
- # If a mouse click location was requested, return it to caller
1060
- if hasattr(self, 'event_port'):
1061
- self.mouseclick_port = self.event_port
1062
- del self.event_port
1063
- if hasattr(self, 'mouseclick_port'):
1064
- self.send_mouseclick_to_caller(cursor_x, cursor_y)
1065
-
1066
- elif (button == GLUT.GLUT_MIDDLE_BUTTON and button_state == GLUT.GLUT_DOWN):
1067
- # If a mouse click location was requested, return it to caller
1068
- if hasattr(self, 'event_port'):
1069
- self.mouseclick_port = self.event_port
1070
- del self.event_port
1071
- if hasattr(self, 'mouseclick_port'):
1072
- self.send_mouseclick_to_caller(cursor_x, cursor_y, button='middle')
1073
-
1074
- GLUT.glutPostRedisplay()
1075
-
1076
- def send_mouseclick_to_caller(self, cursor_x, cursor_y, button='right'):
1077
-
1078
- client = zmq.Context.instance().socket(zmq.PUSH)
1079
- client.connect('{}://{}:{}'.format(ZMQ_TRANSPORT, ZMQ_HOST, self.mouseclick_port))
1080
- cameras = self.on_draw(want_cameras=True)
1081
-
1082
- window_height = GLUT.glutGet(GLUT.GLUT_WINDOW_HEIGHT)
1083
- depth_value = GL.glReadPixels(cursor_x, window_height - cursor_y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT)
1084
-
1085
- pyobj = {
1086
- 'event_type': 'mouse_click_%sbutton' % button,
1087
- 'u': None, 'v': None,
1088
- 'x': None, 'y': None, 'z': None,
1089
- 'subwindow_row': None,
1090
- 'subwindow_col': None
1091
- }
1092
-
1093
- for subwin_row, camera_list in enumerate(cameras):
1094
- for subwin_col, camera in enumerate(camera_list):
1095
-
1096
- # test for out-of-bounds
1097
- if cursor_x < camera['viewport'][0]:
1098
- continue
1099
- if cursor_x > (camera['viewport'][0] + camera['viewport'][2]):
1100
- continue
1101
- if window_height - cursor_y < camera['viewport'][1]:
1102
- continue
1103
- if window_height - cursor_y > (camera['viewport'][1] + camera['viewport'][3]):
1104
- continue
1105
-
1106
- xx, yy, zz = GLU.gluUnProject(
1107
- cursor_x, window_height - cursor_y, depth_value,
1108
- camera['modelview_matrix'],
1109
- camera['projection_matrix'],
1110
- camera['viewport'])
1111
-
1112
- pyobj = {
1113
- 'event_type': 'mouse_click_%sbutton' % button,
1114
- 'u': cursor_x - camera['viewport'][0], 'v': window_height - cursor_y - camera['viewport'][1],
1115
- 'x': xx, 'y': yy, 'z': zz,
1116
- 'which_subwindow': (subwin_row, subwin_col)
1117
- }
1118
-
1119
- client.send_pyobj(pyobj)
1120
- del self.mouseclick_port
1121
-
1122
- def on_draw(self, want_cameras=False):
1123
- # sys.stderr.write('fps: %.2e\n' % (1. / (time.time() - self.tm_for_fps)))
1124
- self.tm_for_fps = time.time()
1125
- GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
1126
- cameras = []
1127
- for mvl in self.mesh_viewers:
1128
- cameras.append([])
1129
- for mv in mvl:
1130
- cameras[-1].append(mv.on_draw(self.transform, want_cameras))
1131
- GL.glFlush() # Flush The GL Rendering Pipeline
1132
- GLUT.glutSwapBuffers()
1133
- self.need_redraw = False
1134
- if want_cameras:
1135
- return cameras
1136
-
1137
- def on_resize_window(self, Width, Height):
1138
- """Reshape The Window When It's Moved Or Resized"""
1139
- self.arcball.setBounds(Width, Height) # //*NEW* Update mouse bounds for arcball
1140
- return
1141
-
1142
- def send_window_shape(self, port):
1143
- client = zmq.Context.instance().socket(zmq.PUSH)
1144
- client.connect('{}://{}:{}'.format(ZMQ_TRANSPORT, ZMQ_HOST, port))
1145
- client.send_pyobj({
1146
- 'event_type': 'window_shape',
1147
- 'shape': self.shape
1148
- })
1149
-
1150
- def handle_request(self, request):
1151
- label = request['label']
1152
- obj = request['obj']
1153
- w = request['which_window']
1154
- mv = self.mesh_viewers[w[0]][w[1]]
1155
-
1156
- logging.debug("received a request: {}".format(request))
1157
-
1158
- # Handle each type of request.
1159
- # Some requests require a redraw, and
1160
- # some don't.
1161
- if label == 'dynamic_meshes':
1162
- mv.dynamic_meshes = obj
1163
- self.need_redraw = True
1164
- elif label == 'dynamic_models':
1165
- mv.dynamic_models = obj
1166
- self.need_redraw = True
1167
- elif label == 'static_meshes':
1168
- mv.static_meshes = obj
1169
- self.need_redraw = True
1170
- elif label == 'dynamic_lines':
1171
- mv.dynamic_lines = obj
1172
- self.need_redraw = True
1173
- elif label == 'static_lines':
1174
- mv.static_lines = obj
1175
- self.need_redraw = True
1176
- elif label == 'autorecenter':
1177
- mv.autorecenter = obj
1178
- self.need_redraw = True
1179
- elif label == 'titlebar':
1180
- assert(isinstance(obj, str))
1181
- self.titlebar = obj
1182
- GLUT.glutSetWindowTitle(obj)
1183
- elif label == 'lighting_on':
1184
- mv.lighting_on = obj
1185
- self.need_redraw = True
1186
- elif label == 'background_color':
1187
- GL.glClearColor(obj[0], obj[1], obj[2], 1.0)
1188
- self.need_redraw = True
1189
- elif label == 'save_snapshot': # redraws for itself
1190
- assert(isinstance(obj, str))
1191
- self.snapshot(obj)
1192
- elif label == 'get_keypress':
1193
- self.keypress_port = obj
1194
- elif label == 'get_mouseclick':
1195
- self.mouseclick_port = obj
1196
- elif label == 'get_event':
1197
- self.event_port = obj
1198
- elif label == 'get_window_shape':
1199
- self.send_window_shape(obj)
1200
- else:
1201
- return False # can't handle this request string
1202
-
1203
- return True # handled the request string
1204
-
1205
- def checkQueue(self, unused_timer_id):
1206
- GLUT.glutTimerFunc(20, self.checkQueue, 0)
1207
-
1208
- try:
1209
- request = self.server.recv_pyobj(zmq.NOBLOCK)
1210
- except zmq.ZMQError as e:
1211
- if e.errno != zmq.EAGAIN:
1212
- raise # something wrong besides empty queue
1213
- return # empty queue, no problem
1214
-
1215
- if not request:
1216
- return
1217
-
1218
- while (request):
1219
- task_completion_time = time.time()
1220
- if not self.handle_request(request):
1221
- raise Exception('Unknown command string: %s' % (request['label']))
1222
- task_completion_time = time.time() - task_completion_time
1223
-
1224
- if 'port' in request: # caller wants confirmation
1225
- port = request['port']
1226
- client = zmq.Context.instance().socket(zmq.PUSH)
1227
- client.connect('{}://{}:{}'.format(ZMQ_TRANSPORT, ZMQ_HOST, port))
1228
- client.send_pyobj(task_completion_time)
1229
- try:
1230
- request = self.server.recv_pyobj(zmq.NOBLOCK)
1231
- except zmq.ZMQError as e:
1232
- if e.errno != zmq.EAGAIN:
1233
- raise
1234
- request = None
1235
-
1236
- if self.need_redraw:
1237
- GLUT.glutPostRedisplay()
1238
-
1239
- def init_opengl(self):
1240
- """A general OpenGL initialization function. Sets all of the initial parameters.
1241
-
1242
- We call this right after our OpenGL window is created.
1243
- """
1244
-
1245
- GL.glClearColor(0.0, 0.0, 0.0, 1.0) # This Will Clear The Background Color To Black
1246
- GL.glClearDepth(1.0) # Enables Clearing Of The Depth Buffer
1247
- GL.glDepthFunc(GL.GL_LEQUAL) # The Type Of Depth Test To Do
1248
- GL.glEnable(GL.GL_DEPTH_TEST) # Enables Depth Testing
1249
- GL.glShadeModel(GL.GL_SMOOTH)
1250
- GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST) # Really Nice Perspective Calculations
1251
-
1252
- GL.glEnable(GL.GL_LIGHT0)
1253
- GL.glEnable(GL.GL_LIGHTING)
1254
-
1255
- GL.glEnable(GL.GL_COLOR_MATERIAL)
1256
- GL.glEnable(GL.GL_NORMALIZE) # important since we rescale the modelview matrix
1257
-
1258
- return True
1259
-
1260
-
1261
- if __name__ == '__main__':
1262
- if len(sys.argv) == 2 and sys.argv[1] == 'TEST_FOR_OPENGL':
1263
- _test_for_opengl()
1264
-
1265
- elif len(sys.argv) > 2:
1266
- m = MeshViewerRemote(titlebar=sys.argv[1],
1267
- subwins_vert=int(sys.argv[2]),
1268
- subwins_horz=int(sys.argv[3]),
1269
- width=int(sys.argv[4]),
1270
- height=int(sys.argv[5]))
1271
- else:
1272
- print("#" * 10)
1273
- print('Usage:')
1274
- print("python -m %s.%s arguments" % (__package__, os.path.splitext(os.path.basename(__file__))[0]))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/processing.py DELETED
@@ -1,186 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2013-02-20.
6
-
7
-
8
- """
9
- Mesh processing backend
10
- =======================
11
-
12
- """
13
-
14
- import numpy as np
15
-
16
-
17
- def reset_normals(self, face_to_verts_sparse_matrix=None, reset_face_normals=False):
18
- self.vn = self.estimate_vertex_normals(face_to_verts_sparse_matrix=None)
19
- if reset_face_normals:
20
- self.fn = self.f.copy()
21
- return self
22
-
23
-
24
- def reset_face_normals(self):
25
- if not hasattr(self, 'vn'):
26
- self.reset_normals()
27
- self.fn = self.f
28
- return self
29
-
30
-
31
- def uniquified_mesh(self):
32
- """This function returns a copy of the mesh in which vertices are copied such that
33
- each vertex appears in only one face, and hence has only one texture"""
34
- from mesh import Mesh
35
- new_mesh = Mesh(v=self.v[self.f.flatten()], f=np.array(range(len(self.f.flatten()))).reshape(-1, 3))
36
-
37
- if not hasattr(self, 'vn'):
38
- self.reset_normals()
39
- new_mesh.vn = self.vn[self.f.flatten()]
40
-
41
- if hasattr(self, 'vt'):
42
- new_mesh.vt = self.vt[self.ft.flatten()]
43
- new_mesh.ft = new_mesh.f.copy()
44
- return new_mesh
45
-
46
-
47
- def keep_vertices(self, keep_list):
48
- trans = dict((v, i) for i, v in enumerate(keep_list))
49
- trans_f = np.array([trans[v] if v in trans else -1 for row in self.f for v in row], dtype=np.uint32).reshape(-1, 3)
50
- if hasattr(self, 'vn') and self.vn.shape[0] == self.vn.shape[0]:
51
- self.vn = self.vn.reshape(-1, 3)[keep_list]
52
- if hasattr(self, 'vc') and self.vc.shape[0] == self.v.shape[0]:
53
- self.vc = self.vc.reshape(-1, 3)[keep_list]
54
- if hasattr(self, 'landm_raw_xyz'):
55
- self.recompute_landmark_indices()
56
-
57
- self.v = self.v.reshape(-1, 3)[keep_list]
58
- self.f = trans_f[(trans_f != np.uint32(-1)).all(axis=1)]
59
- return self
60
-
61
-
62
- def point_cloud(self):
63
- from .mesh import Mesh
64
- return Mesh(v=self.v, f=[], vc=self.vc) if hasattr(self, 'vc') else Mesh(v=self.v, f=[])
65
-
66
-
67
- def remove_faces(self, face_indices_to_remove):
68
-
69
- def arr_replace(arr_in, lookup_dict):
70
- arr_out = arr_in.copy()
71
- for k, v in lookup_dict.iteritems():
72
- arr_out[arr_in == k] = v
73
- return arr_out
74
-
75
- f = np.delete(self.f, face_indices_to_remove, 0)
76
- v2keep = np.unique(f)
77
- self.v = self.v[v2keep]
78
- self.f = arr_replace(f, dict((v, i) for i, v in enumerate(v2keep)))
79
-
80
- if hasattr(self, 'fc'):
81
- self.fc = np.delete(self.fc, face_indices_to_remove, 0)
82
- if hasattr(self, 'vn') and self.vn.shape[0] == self.vn.shape[0]:
83
- self.vn = self.vn.reshape(-1, 3)[v2keep]
84
- if hasattr(self, 'vc') and self.vc.shape[0] == self.v.shape[0]:
85
- self.vc = self.vc.reshape(-1, 3)[v2keep]
86
- if hasattr(self, 'landm_raw_xyz'):
87
- self.recompute_landmark_indices()
88
-
89
- if hasattr(self, 'ft'):
90
- ft = np.delete(self.ft, face_indices_to_remove, 0)
91
- vt2keep = np.unique(ft)
92
- self.vt = self.vt[vt2keep]
93
- self.ft = arr_replace(ft, dict((v, i) for i, v in enumerate(vt2keep)))
94
-
95
- return self
96
-
97
-
98
- def flip_faces(self):
99
- self.f = self.f.copy()
100
- for i in range(len(self.f)):
101
- self.f[i] = self.f[i][::-1]
102
- if hasattr(self, 'ft'):
103
- for i in range(len(self.f)):
104
- self.ft[i] = self.ft[i][::-1]
105
- return self
106
-
107
-
108
- def scale_vertices(self, scale_factor):
109
- self.v *= scale_factor
110
- return self
111
-
112
-
113
- def rotate_vertices(self, rotation_matrix):
114
- import cv2
115
- rotation_matrix = np.matrix(cv2.Rodrigues(np.array(rotation_matrix))[0] if (np.array(rotation_matrix).shape != (3, 3)) else rotation_matrix)
116
- self.v = np.array(self.v * rotation_matrix.T)
117
- return self
118
-
119
-
120
- def translate_vertices(self, translation):
121
- self.v += translation
122
- return self
123
-
124
-
125
- def subdivide_triangles(self):
126
- new_faces = []
127
- new_vertices = self.v.copy()
128
- for face in self.f:
129
- face_vertices = np.array([self.v[face[0], :], self.v[face[1], :], self.v[face[2], :]])
130
- new_vertex = np.mean(face_vertices, axis=0)
131
- new_vertices = np.vstack([new_vertices, new_vertex])
132
- new_vertex_index = len(new_vertices) - 1
133
- if len(new_faces):
134
- new_faces = np.vstack([new_faces, [face[0], face[1], new_vertex_index], [face[1], face[2], new_vertex_index], [face[2], face[0], new_vertex_index]])
135
- else:
136
- new_faces = np.array([[face[0], face[1], new_vertex_index], [face[1], face[2], new_vertex_index], [face[2], face[0], new_vertex_index]])
137
- self.v = new_vertices
138
- self.f = new_faces
139
-
140
- if hasattr(self, 'vt'):
141
- new_ft = []
142
- new_texture_coordinates = self.vt.copy()
143
- for face_texture in self.ft:
144
- face_texture_coordinates = np.array([self.vt[face_texture[0], :], self.vt[face_texture[1], :], self.vt[face_texture[2], :]])
145
- new_texture_coordinate = np.mean(face_texture_coordinates, axis=0)
146
- new_texture_coordinates = np.vstack([new_texture_coordinates, new_texture_coordinate])
147
- new_texture_index = len(new_texture_coordinates) - 1
148
- if len(new_ft):
149
- new_ft = np.vstack([new_ft, [face_texture[0], face_texture[1], new_texture_index], [face_texture[1], face_texture[2], new_texture_index], [face_texture[2], face_texture[0], new_texture_index]])
150
- else:
151
- new_ft = np.array([[face_texture[0], face_texture[1], new_texture_index], [face_texture[1], face_texture[2], new_texture_index], [face_texture[2], face_texture[0], new_texture_index]])
152
- self.vt = new_texture_coordinates
153
- self.ft = new_ft
154
- return self
155
-
156
-
157
- def concatenate_mesh(self, mesh):
158
- if len(self.v) == 0:
159
- self.f = mesh.f.copy()
160
- self.v = mesh.v.copy()
161
- self.vc = mesh.vc.copy() if hasattr(mesh, 'vc') else None
162
- elif len(mesh.v):
163
- self.f = np.concatenate([self.f, mesh.f.copy() + len(self.v)])
164
- self.v = np.concatenate([self.v, mesh.v])
165
- self.vc = np.concatenate([self.vc, mesh.vc]) if (hasattr(mesh, 'vc') and hasattr(self, 'vc')) else None
166
- return self
167
-
168
-
169
- # new_ordering specifies the new index of each vertex. If new_ordering[i] = j,
170
- # vertex i should now be the j^th vertex. As such, each entry in new_ordering should be unique.
171
- def reorder_vertices(self, new_ordering, new_normal_ordering=None):
172
- if new_normal_ordering is None:
173
- new_normal_ordering = new_ordering
174
- inverse_ordering = np.zeros(len(new_ordering), dtype=int)
175
- for i, j in enumerate(new_ordering):
176
- inverse_ordering[j] = i
177
- inverse_normal_ordering = np.zeros(len(new_normal_ordering), dtype=int)
178
- for i, j in enumerate(new_normal_ordering):
179
- inverse_normal_ordering[j] = i
180
- self.v = self.v[inverse_ordering]
181
- if hasattr(self, 'vn'):
182
- self.vn = self.vn[inverse_normal_ordering]
183
- for i in range(len(self.f)):
184
- self.f[i] = np.array([new_ordering[vertex_index] for vertex_index in self.f[i]])
185
- if hasattr(self, 'fn'):
186
- self.fn[i] = np.array([new_normal_ordering[normal_index] for normal_index in self.fn[i]])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/ressources/Arial.ttf DELETED
Binary file (773 kB)
 
mesh-master/mesh/search.py DELETED
@@ -1,100 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Created by Matthew Loper on 2013-02-20.
5
- # Copyright (c) 2013 MPI. All rights reserved.
6
-
7
- """
8
- Searching and lookup of geometric entities
9
- ==========================================
10
-
11
- """
12
-
13
-
14
- import numpy as np
15
-
16
- __all__ = ['AabbTree', 'AabbNormalsTree', 'ClosestPointTree', 'CGALClosestPointTree']
17
-
18
-
19
- class AabbTree(object):
20
- """Encapsulates an AABB (Axis Aligned Bounding Box) Tree"""
21
- def __init__(self, m):
22
- from . import spatialsearch
23
- # this shit return NULL
24
- self.cpp_handle = spatialsearch.aabbtree_compute(m.v.astype(np.float64).copy(order='C'), m.f.astype(np.uint32).copy(order='C'))
25
-
26
- def nearest(self, v_samples, nearest_part=False):
27
- "nearest_part tells you whether the closest point in triangle abc is in the interior (0), on an edge (ab:1,bc:2,ca:3), or a vertex (a:4,b:5,c:6)"
28
- from . import spatialsearch
29
- f_idxs, f_part, v = spatialsearch.aabbtree_nearest(self.cpp_handle, np.array(v_samples, dtype=np.float64, order='C'))
30
- return (f_idxs, f_part, v) if nearest_part else (f_idxs, v)
31
-
32
- def nearest_alongnormal(self, points, normals):
33
- from . import spatialsearch
34
- distances, f_idxs, v = spatialsearch.aabbtree_nearest_alongnormal(self.cpp_handle,
35
- points.astype(np.float64),
36
- normals.astype(np.float64))
37
- return (distances, f_idxs, v)
38
-
39
- def intersections_indices(self, q_v, q_f):
40
- '''
41
- Given a set of query vertices and faces, the function computes which intersect the mesh
42
- A list with the indices in q_f is returned
43
- @param q_v The query vertices (array of 3xN float values)
44
- @param q_f The query faces (array 3xF integer values)
45
- '''
46
- import spatialsearch
47
- return spatialsearch.aabbtree_intersections_indices(self.cpp_handle,
48
- q_v.astype(np.float64),
49
- q_f.astype(np.uint32))
50
-
51
-
52
- class ClosestPointTree(object):
53
- """Provides nearest neighbor search for a cloud of vertices (i.e. triangles are not used)"""
54
- def __init__(self, m):
55
- from scipy.spatial import KDTree
56
- self.v = m.v
57
- self.kdtree = KDTree(self.v)
58
-
59
- def nearest(self, v_samples):
60
- (distances, indices) = zip(*[self.kdtree.query(v) for v in v_samples])
61
- return (indices, distances)
62
-
63
- def nearest_vertices(self, v_samples):
64
- (distances, indices) = zip(*[self.kdtree.query(v) for v in v_samples])
65
- return self.v[indices]
66
-
67
-
68
- class CGALClosestPointTree(object):
69
- """Encapsulates an AABB (Axis Aligned Bounding Box) Tree """
70
- def __init__(self, m):
71
- from . import spatialsearch
72
- self.v = m.v
73
- n = m.v.shape[0]
74
- faces = np.vstack([np.array(range(n)), np.array(range(n)) + n, np.array(range(n)) + 2 * n]).T
75
- eps = 0.000000000001
76
- self.cpp_handle = spatialsearch.aabbtree_compute(np.vstack([m.v + eps * np.array([1.0, 0.0, 0.0]), m.v + eps * np.array([0.0, 1.0, 0.0]), m.v - eps * np.array([1.0, 1.0, 0.0])]).astype(np.float64).copy(order='C'), faces.astype(np.uint32).copy(order='C'))
77
-
78
- def nearest(self, v_samples):
79
- from . import spatialsearch
80
- f_idxs, f_part, v = spatialsearch.aabbtree_nearest(self.cpp_handle, np.array(v_samples, dtype=np.float64, order='C'))
81
- return (f_idxs.flatten(), (np.sum(((self.v[f_idxs.flatten()] - v_samples) ** 2.0), axis=1) ** 0.5).flatten())
82
-
83
- def nearest_vertices(self, v_samples):
84
- from . import spatialsearch
85
- f_idxs, f_part, v = spatialsearch.aabbtree_nearest(self.cpp_handle, np.array(v_samples, dtype=np.float64, order='C'))
86
- return self.v[f_idxs.flatten()]
87
-
88
-
89
- class AabbNormalsTree(object):
90
- def __init__(self, m):
91
- # the weight of the normals cosine is proportional to the std of the vertices
92
- # the best point can be translated up to 2*eps because of the normals
93
- from . import aabb_normals
94
- eps = 0.1 # np.std(m.v)#0
95
- self.tree_handle = aabb_normals.aabbtree_n_compute(m.v, m.f.astype(np.uint32).copy(), eps)
96
-
97
- def nearest(self, v_samples, n_samples):
98
- from . import aabb_normals
99
- closest_tri, closest_p = aabb_normals.aabbtree_n_nearest(self.tree_handle, v_samples, n_samples)
100
- return (closest_tri, closest_p)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/serialization/__init__.py DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2016 Max Planck Society. All rights reserved.
 
 
 
 
 
mesh-master/mesh/serialization/serialization.py DELETED
@@ -1,443 +0,0 @@
1
- #!/usr/bin/env python
2
- # encoding: utf-8
3
-
4
- # Copyright (c) 2013 Max Planck Society. All rights reserved.
5
- # Created by Matthew Loper on 2013-02-20.
6
-
7
- import re
8
- import os
9
- import sys
10
- import numpy as np
11
-
12
- from ..errors import SerializationError
13
-
14
- """
15
- serialization.py
16
-
17
-
18
- """
19
-
20
- __all__ = ['load_from_obj', 'load_from_obj_cpp', 'write_obj', 'write_mtl',
21
- 'write_json', 'write_three_json',
22
- 'set_landmark_indices_from_ppfile', 'set_landmark_indices_from_lmrkfile',
23
- 'load_from_ply', 'load_from_file']
24
-
25
- # import os.path
26
-
27
-
28
- def load_from_obj(self, filename):
29
- v = []
30
- f = []
31
- ft = []
32
- fn = []
33
- vt = []
34
- vn = []
35
- vc = []
36
- segm = dict()
37
- landm_raw_xyz = dict()
38
- currSegm = ''
39
- currLandm = ''
40
- with open(filename, 'r', buffering=2 ** 10) as fp:
41
- for line in fp:
42
- line = line.split()
43
- if len(line) > 0:
44
- if line[0] == 'v':
45
- v.append([float(x) for x in line[1:4]])
46
- if len(line) == 7:
47
- vc.append([float(x) for x in line[4:]])
48
- if currLandm:
49
- landm_raw_xyz[currLandm] = v[-1]
50
- currLandm = ''
51
- elif line[0] == 'vt':
52
- vt.append([float(x) for x in line[1:]])
53
- elif line[0] == 'vn':
54
- vn.append([float(x) for x in line[1:]])
55
- elif line[0] == 'f':
56
- faces = [x.split('/') for x in line[1:]]
57
- for iV in range(1, len(faces) - 1): # trivially triangulate faces
58
- f.append([int(faces[0][0]), int(faces[iV][0]), int(faces[iV + 1][0])])
59
- if (len(faces[0]) > 1) and faces[0][1]:
60
- ft.append([int(faces[0][1]), int(faces[iV][1]), int(faces[iV + 1][1])])
61
- if (len(faces[0]) > 2) and faces[0][2]:
62
- fn.append([int(faces[0][2]), int(faces[iV][2]), int(faces[iV + 1][2])])
63
- if currSegm:
64
- segm[currSegm].append(len(f) - 1)
65
- elif line[0] == 'g':
66
- currSegm = line[1]
67
- if currSegm not in segm.keys():
68
- segm[currSegm] = []
69
- elif line[0] == '#landmark':
70
- currLandm = line[1]
71
- elif line[0] == 'mtllib':
72
- self.materials_filepath = os.path.join(os.path.dirname(filename), line[1])
73
- self.materials_file = open(self.materials_filepath, 'r').readlines()
74
-
75
- self.v = np.array(v)
76
- self.f = np.array(f) - 1
77
- if vt:
78
- self.vt = np.array(vt)
79
- if vn:
80
- self.vn = np.array(vn)
81
- if vc:
82
- self.vc = np.array(vc)
83
- if ft:
84
- self.ft = np.array(ft) - 1
85
- if fn:
86
- self.fn = np.array(fn) - 1
87
- self.segm = segm
88
- self.landm_raw_xyz = landm_raw_xyz
89
- self.recompute_landmark_indices()
90
-
91
- if hasattr(self, 'materials_file'):
92
- for line in self.materials_file:
93
- if line and line.split() and line.split()[0] == 'map_Ka':
94
- self.texture_filepath = os.path.abspath(os.path.join(os.path.dirname(filename), line.split()[1]))
95
-
96
-
97
- def load_from_obj_cpp(self, filename):
98
- from .loadobj import loadobj
99
- if sys.version_info[:2] == (2, 6):
100
- from OrderedDict import OrderedDict
101
- else:
102
- from collections import OrderedDict
103
-
104
- v, vt, vn, f, ft, fn, mtl_path, landm, segm = loadobj(filename)
105
- if v.size != 0:
106
- self.v = v
107
- if f.size != 0:
108
- self.f = f
109
- if vn.size != 0:
110
- self.vn = vn
111
- if vt.size != 0:
112
- self.vt = vt
113
- if fn.size != 0:
114
- self.fn = fn
115
- if ft.size != 0:
116
- self.ft = ft
117
- if segm:
118
- self.segm = OrderedDict([(k, v if type(v) is list else v.tolist()) for k, v in segm.items()])
119
- if mtl_path:
120
- try:
121
- self.materials_filepath = os.path.join(os.path.dirname(filename), mtl_path.strip())
122
- self.materials_file = file(self.materials_filepath, 'r').readlines()
123
- except:
124
- self.materials_filepath = None
125
- if hasattr(self, 'materials_file'):
126
- for line in self.materials_file:
127
- if line and line.split() and line.split()[0] == 'map_Ka':
128
- self.texture_filepath = os.path.abspath(os.path.join(os.path.dirname(filename), line.split()[1]))
129
- if landm:
130
- self.landm = landm
131
- self.recompute_landmark_xyz()
132
-
133
-
134
- def write_obj(self, filename, flip_faces=False, group=False, comments=None):
135
- if os.path.dirname(filename) and not os.path.exists(os.path.dirname(filename)):
136
- os.makedirs(os.path.dirname(filename))
137
-
138
- ff = -1 if flip_faces else 1
139
-
140
- def write_face_to_obj_file(face_index, obj_file):
141
- vertex_indices = self.f[face_index][::ff] + 1
142
-
143
- if hasattr(self, 'ft'):
144
- texture_indices = self.ft[face_index][::ff] + 1
145
- if not hasattr(self, 'fn'):
146
- self.reset_face_normals()
147
- normal_indices = self.fn[face_index][::ff] + 1
148
- obj_file.write('f %d/%d/%d %d/%d/%d %d/%d/%d\n' % tuple(
149
- np.array([vertex_indices, texture_indices, normal_indices]).T.flatten()))
150
- elif hasattr(self, 'fn'):
151
- normal_indices = self.fn[face_index][::ff] + 1
152
- obj_file.write('f %d//%d %d//%d %d//%d\n' % tuple(np.array([vertex_indices, normal_indices]).T.flatten()))
153
- else:
154
- obj_file.write('f %d %d %d\n' % tuple(vertex_indices))
155
-
156
- with open(filename, 'w') as fi:
157
- if comments is not None:
158
- if isinstance(comments, str):
159
- comments = [comments]
160
- for comment in comments:
161
- for line in comment.split("\n"):
162
- fi.write("# %s\n" % line)
163
-
164
- if hasattr(self, 'texture_filepath'):
165
- outfolder = os.path.dirname(filename)
166
- outbase = os.path.splitext(os.path.basename(filename))[0]
167
- mtlpath = outbase + '.mtl'
168
- fi.write('mtllib %s\n' % mtlpath)
169
- from shutil import copyfile
170
- texture_name = outbase + os.path.splitext(self.texture_filepath)[1]
171
- if os.path.abspath(self.texture_filepath) != os.path.abspath(os.path.join(outfolder, texture_name)):
172
- copyfile(self.texture_filepath, os.path.join(outfolder, texture_name))
173
- self.write_mtl(os.path.join(outfolder, mtlpath), outbase, texture_name)
174
-
175
- for r in self.v:
176
- fi.write('v %f %f %f\n' % (r[0], r[1], r[2]))
177
-
178
- if hasattr(self, 'fn') and hasattr(self, 'vn'):
179
- for r in self.vn:
180
- fi.write('vn %f %f %f\n' % (r[0], r[1], r[2]))
181
-
182
- if hasattr(self, 'ft'):
183
- for r in self.vt:
184
- if len(r) == 3:
185
- fi.write('vt %f %f %f\n' % (r[0], r[1], r[2]))
186
- else:
187
- fi.write('vt %f %f\n' % (r[0], r[1]))
188
- if hasattr(self, 'segm') and self.segm and not group:
189
- for p in self.segm.keys():
190
- fi.write('g %s\n' % p)
191
- for face_index in self.segm[p]:
192
- write_face_to_obj_file(face_index, fi)
193
- else:
194
- if hasattr(self, 'f'):
195
- for face_index in range(len(self.f)):
196
- write_face_to_obj_file(face_index, fi)
197
-
198
-
199
- def write_mtl(self, path, material_name, texture_name):
200
- """Material attribute file serialization"""
201
- with open(path, 'w') as f:
202
- f.write('newmtl %s\n' % material_name)
203
- # copied from another obj, no idea about what it does
204
- f.write('ka 0.329412 0.223529 0.027451\n')
205
- f.write('kd 0.780392 0.568627 0.113725\n')
206
- f.write('ks 0.992157 0.941176 0.807843\n')
207
- f.write('illum 0\n')
208
- f.write('map_Ka %s\n' % texture_name)
209
- f.write('map_Kd %s\n' % texture_name)
210
- f.write('map_Ks %s\n' % texture_name)
211
-
212
-
213
- def write_ply(self, filename, flip_faces=False, ascii=False, little_endian=True, comments=[]):
214
- from psbody.mesh.serialization import plyutils
215
-
216
- if os.path.dirname(filename) and not os.path.exists(os.path.dirname(filename)):
217
- os.makedirs(os.path.dirname(filename))
218
-
219
- ff = -1 if flip_faces else 1
220
-
221
- if isinstance(comments, str):
222
- comments = [comments]
223
- comments = filter(lambda c: len(c) > 0, sum(map(lambda c: c.split("\n"), comments), []))
224
-
225
- plyutils.write(list([list(x) for x in self.v]),
226
- list([list(x[::ff]) for x in self.f] if hasattr(self, 'f') else []),
227
- list([list((x * 255).astype(int)) for x in ([] if not hasattr(self, 'vc') else self.vc)]),
228
- filename, ascii, little_endian, list(comments),
229
- list([list(x) for x in ([] if not hasattr(self, 'vn') else self.vn)]))
230
-
231
-
232
- def write_three_json(self, filename, name=""):
233
- import json
234
-
235
- if os.path.dirname(filename) and not os.path.exists(os.path.dirname(filename)):
236
- os.makedirs(os.path.dirname(filename))
237
-
238
- name = name if name else self.basename
239
- name = name if name else os.path.splitext(os.path.basename(filename))[0]
240
-
241
- metadata = {"formatVersion": 3.1,
242
- "sourceFile": "%s.obj" % name,
243
- "generatedBy": "korper",
244
- "vertices": len(self.v),
245
- "faces": len(self.f),
246
- "normals": len(self.vn),
247
- "colors": 0,
248
- "uvs": len(self.vt),
249
- "materials": 1
250
- }
251
- materials = [{"DbgColor": 15658734,
252
- "DbgIndex": 0,
253
- "DbgName": "defaultMat",
254
- "colorAmbient": [0.0, 0.0, 0.0],
255
- "colorDiffuse": [0.64, 0.64, 0.64],
256
- "colorSpecular": [0.5, 0.5, 0.5],
257
- "illumination": 2,
258
- "opticalDensity": 1.0,
259
- "specularCoef": 96.078431,
260
- "transparency": 1.0
261
- }]
262
-
263
- mesh_data = {"metadata": metadata,
264
- 'scale': 0.35,
265
- "materials": materials,
266
- "morphTargets": [],
267
- "morphColors": [],
268
- "colors": []}
269
- mesh_data["vertices"] = self.v.flatten().tolist()
270
- mesh_data["normals"] = self.vn.flatten().tolist()
271
- mesh_data["uvs"] = [np.array([[vt[0], vt[1]] for vt in self.vt]).flatten().tolist()]
272
- mesh_data["faces"] = np.array([[42, self.f[i][0], self.f[i][1], self.f[i][2], 0, self.ft[i][0], self.ft[i][1],
273
- self.ft[i][2], self.fn[i][0], self.fn[i][1], self.fn[i][2]] for i in
274
- range(len(self.f))]).flatten().tolist()
275
-
276
- json_or_js_file = open(filename, 'w')
277
- json_or_js_file.write(json.dumps(mesh_data, indent=4))
278
- json_or_js_file.close()
279
-
280
-
281
- def write_json(self, filename, header="", footer="", name="", include_faces=True, texture_mode=True):
282
- import json
283
-
284
- if os.path.dirname(filename) and not os.path.exists(os.path.dirname(filename)):
285
- os.makedirs(os.path.dirname(filename))
286
-
287
- name = name if name else self.basename
288
- name = name if name else os.path.splitext(os.path.basename(filename))[0]
289
-
290
- if texture_mode:
291
- vertex_texture_pairs = {}
292
- for face_index in range(len(self.f)):
293
- for i in [0, 1, 2]:
294
- v_index = self.f[face_index][i]
295
- t_index = self.ft[face_index][i]
296
- vertex_texture_pairs[(v_index, t_index)] = []
297
- for face_index in range(len(self.f)):
298
- for i in [0, 1, 2]:
299
- v_index = self.f[face_index][i]
300
- t_index = self.ft[face_index][i]
301
- vertex_texture_pairs[(v_index, t_index)].append((face_index, i))
302
- mesh_data = {'name': name,
303
- 'vertices': [],
304
- 'textures': []
305
- }
306
- for v_index, t_index, faces_entries in vertex_texture_pairs.items():
307
- mesh_data['vertices'].append()
308
-
309
- if include_faces:
310
- mesh_data['faces'] = list([[int(np.asscalar(i)) for i in list(x)] for x in self.f])
311
-
312
- else:
313
- mesh_data = {'name': name,
314
- 'vertices': list([list(x) for x in self.v])
315
- }
316
- if include_faces:
317
- mesh_data['faces'] = list([[int(np.asscalar(i)) for i in list(x)] for x in self.f])
318
-
319
- json_or_js_file = open(filename, 'w')
320
- if os.path.basename(filename).endswith('js'):
321
- json_or_js_file.write(header + '\nmesh = ') if header else json_or_js_file.write('var mesh = ')
322
- json_or_js_file.write(json.dumps(mesh_data, indent=4))
323
- json_or_js_file.write(footer)
324
- else:
325
- json_or_js_file.write(json.dumps(mesh_data, indent=4))
326
- json_or_js_file.close()
327
-
328
-
329
- def set_landmark_indices_from_ppfile(self, ppfilename):
330
- from xml.etree import ElementTree
331
- tree = ElementTree.parse(ppfilename)
332
-
333
- def get_xyz(e):
334
- try:
335
- return [float(e.attrib['x']), float(e.attrib['y']), float(e.attrib['z'])]
336
- except: # may happen if landmarks are just spaces
337
- return [0, 0, 0]
338
-
339
- self.landm_raw_xyz = dict((e.attrib['name'], get_xyz(e)) for e in tree.iter() if e.tag == 'point')
340
- self.recompute_landmark_indices(ppfilename)
341
-
342
-
343
- def set_landmark_indices_from_lmrkfile(self, lmrkfilename):
344
- with open(lmrkfilename, 'r') as lmrkfile:
345
- self.landm_raw_xyz = {}
346
-
347
- for line in lmrkfile.readlines():
348
- if not line.strip():
349
- continue
350
- command = line.split()[0]
351
- data = [float(x) for x in line.split()[1:]]
352
-
353
- if command == '_scale':
354
- selfscale_factor = np.matrix(data)
355
- elif command == '_translate':
356
- self.caesar_translation_vector = np.matrix(data)
357
- elif command == '_rotation':
358
- self.caesar_rotation_matrix = np.matrix(data).reshape(3, 3)
359
- else:
360
- self.landm_raw_xyz[command] = [data[1], data[2], data[0]]
361
- self.recompute_landmark_indices(lmrkfilename)
362
-
363
-
364
- def _is_lmrkfile(filename):
365
- is_lmrk = re.compile('^_scale\s[-\d\.]+\s+_translate(\s[-\d\.]+){3}\s+_rotation(\s[-\d\.]+){9}\s+')
366
- with open(filename) as f:
367
- data = f.read()
368
- res = is_lmrk.match(data)
369
- return res
370
-
371
-
372
- def set_landmark_indices_from_any(self, landmarks):
373
- '''
374
- Sets landmarks given any of:
375
- - ppfile
376
- - ldmk file
377
- - dict of {name:inds} (i.e. mesh.landm)
378
- - dict of {name:xyz} (i.e. mesh.landm_xyz)
379
- - pkl, json, yaml file containing either of the above dicts
380
- '''
381
- import json
382
- import pickle
383
-
384
- try:
385
- path_exists = os.path.exists(landmarks)
386
- except:
387
- path_exists = False
388
- if path_exists:
389
- if re.search(".ya{0,1}ml$", landmarks):
390
- import yaml
391
- with open(landmarks) as f:
392
- self.set_landmarks_from_raw(yaml.load(f, Loader=yaml.FullLoader))
393
- elif re.search(".json$", landmarks):
394
- with open(landmarks) as f:
395
- self.set_landmarks_from_raw(json.load(f))
396
- elif re.search(".pkl$", landmarks):
397
- with open(landmarks, "rb") as f:
398
- self.set_landmarks_from_raw(pickle.load(f))
399
- elif _is_lmrkfile(landmarks):
400
- self.set_landmark_indices_from_lmrkfile(landmarks)
401
- else:
402
- try:
403
- self.set_landmark_indices_from_ppfile(landmarks)
404
- except:
405
- raise Exception("Landmark file %s is of unknown format" % landmarks)
406
- else:
407
- self.set_landmarks_from_raw(landmarks)
408
-
409
-
410
- def load_from_file(self, filename, use_cpp=True):
411
- if re.search(".ply$", filename):
412
- self.load_from_ply(filename)
413
- elif re.search(".obj$", filename):
414
- # XXX experimental cpp obj loader, if problems, switch back to
415
- if use_cpp:
416
- self.load_from_obj_cpp(filename)
417
- else:
418
- self.load_from_obj(filename)
419
-
420
- elif re.search(".bsf$", filename):
421
- self.load_from_bsf(filename)
422
- else:
423
- raise NotImplementedError("Unknown mesh file format.")
424
-
425
-
426
- def load_from_ply(self, filename):
427
- from os.path import abspath, dirname, join
428
-
429
- test_data_folder = abspath(join(dirname(__file__), '..', 'data', 'unittest'))
430
-
431
- from psbody.mesh.serialization import plyutils
432
- try:
433
- res = plyutils.read(filename)
434
- except plyutils.error as e:
435
- raise SerializationError(e)
436
-
437
- self.v = np.array(res['pts']).T.copy()
438
- self.f = np.array(res['tri']).T.copy()
439
-
440
- if 'color' in res:
441
- self.set_vertex_colors(np.array(res['color']).T.copy() / 255)
442
- if 'normals' in res:
443
- self.vn = np.array(res['normals']).T.copy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/sphere.py DELETED
@@ -1,74 +0,0 @@
1
- import numpy as np
2
- from .mesh import Mesh
3
- from .colors import name_to_rgb
4
-
5
-
6
- __all__ = ['Sphere']
7
-
8
-
9
- class Sphere(object):
10
- def __init__(self, center, radius):
11
- if(center.flatten().shape != (3,)):
12
- raise Exception("Center should have size(1,3) instead of %s" % center.shape)
13
- self.center = center.flatten()
14
- self.radius = radius
15
-
16
- def __str__(self):
17
- return "%s:%s" % (self.center, self.radius)
18
-
19
- def to_mesh(self, color=name_to_rgb['red']):
20
- v = np.array([[0.0000, -1.000, 0.0000], [0.7236, -0.447, 0.5257],
21
- [-0.278, -0.447, 0.8506], [-0.894, -0.447, 0.0000],
22
- [-0.278, -0.447, -0.850], [0.7236, -0.447, -0.525],
23
- [0.2765, 0.4472, 0.8506], [-0.723, 0.4472, 0.5257],
24
- [-0.720, 0.4472, -0.525], [0.2763, 0.4472, -0.850],
25
- [0.8945, 0.4472, 0.0000], [0.0000, 1.0000, 0.0000],
26
- [-0.165, -0.850, 0.4999], [0.4253, -0.850, 0.3090],
27
- [0.2629, -0.525, 0.8090], [0.4253, -0.850, -0.309],
28
- [0.8508, -0.525, 0.0000], [-0.525, -0.850, 0.0000],
29
- [-0.688, -0.525, 0.4999], [-0.162, -0.850, -0.499],
30
- [-0.688, -0.525, -0.499], [0.2628, -0.525, -0.809],
31
- [0.9518, 0.0000, -0.309], [0.9510, 0.0000, 0.3090],
32
- [0.5876, 0.0000, 0.8090], [0.0000, 0.0000, 1.0000],
33
- [-0.588, 0.0000, 0.8090], [-0.951, 0.0000, 0.3090],
34
- [-0.955, 0.0000, -0.309], [-0.587, 0.0000, -0.809],
35
- [0.0000, 0.0000, -1.000], [0.5877, 0.0000, -0.809],
36
- [0.6889, 0.5257, 0.4999], [-0.262, 0.5257, 0.8090],
37
- [-0.854, 0.5257, 0.0000], [-0.262, 0.5257, -0.809],
38
- [0.6889, 0.5257, -0.499], [0.5257, 0.8506, 0.0000],
39
- [0.1626, 0.8506, 0.4999], [-0.425, 0.8506, 0.3090],
40
- [-0.422, 0.8506, -0.309], [0.1624, 0.8506, -0.499]])
41
-
42
- f = np.array([[15, 3, 13], [13, 14, 15], [2, 15, 14], [13, 1, 14], [17, 2, 14], [14, 16, 17],
43
- [6, 17, 16], [14, 1, 16], [19, 4, 18], [18, 13, 19], [3, 19, 13], [18, 1, 13],
44
- [21, 5, 20], [20, 18, 21], [4, 21, 18], [20, 1, 18], [22, 6, 16], [16, 20, 22],
45
- [5, 22, 20], [16, 1, 20], [24, 2, 17], [17, 23, 24], [11, 24, 23], [23, 17, 6],
46
- [26, 3, 15], [15, 25, 26], [7, 26, 25], [25, 15, 2], [28, 4, 19], [19, 27, 28],
47
- [8, 28, 27], [27, 19, 3], [30, 5, 21], [21, 29, 30], [9, 30, 29], [29, 21, 4],
48
- [32, 6, 22], [22, 31, 32], [10, 32, 31], [31, 22, 5], [33, 7, 25], [25, 24, 33],
49
- [11, 33, 24], [24, 25, 2], [34, 8, 27], [27, 26, 34], [7, 34, 26], [26, 27, 3],
50
- [35, 9, 29], [29, 28, 35], [8, 35, 28], [28, 29, 4], [36, 10, 31], [31, 30, 36],
51
- [9, 36, 30], [30, 31, 5], [37, 11, 23], [23, 32, 37], [10, 37, 32], [32, 23, 6],
52
- [39, 7, 33], [33, 38, 39], [12, 39, 38], [38, 33, 11], [40, 8, 34], [34, 39, 40],
53
- [12, 40, 39], [39, 34, 7], [41, 9, 35], [35, 40, 41], [12, 41, 40], [40, 35, 8],
54
- [42, 10, 36], [36, 41, 42], [12, 42, 41], [41, 36, 9], [38, 11, 37], [37, 42, 38],
55
- [12, 38, 42], [42, 37, 10]]) - 1
56
-
57
- return Mesh(v=v * self.radius + self.center, f=f, vc=np.tile(color, (v.shape[0], 1)))
58
-
59
- def has_inside(self, point):
60
- return np.linalg.norm(point - self.center) <= self.radius
61
-
62
- def intersects(self, sphere):
63
- return np.linalg.norm(sphere.center - self.center) < (self.radius + sphere.radius)
64
-
65
- def intersection_vol(self, sphere):
66
- if not self.intersects(sphere):
67
- return 0
68
- d = np.linalg.norm(sphere.center - self.center)
69
- R, r = (self.radius, sphere.radius) if (self.radius > sphere.radius) else (sphere.radius, self.radius)
70
- if R >= (d + r):
71
- return (4 * np.pi * (r ** 3)) / 3
72
-
73
- # http://mathworld.wolfram.com/Sphere-SphereIntersection.html
74
- return (np.pi * (R + r - d) ** 2 * (d ** 2 + 2 * d * r - 3 * r * r + 2 * d * R + 6 * r * R - 3 * R * R)) / (12 * d)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mesh-master/mesh/src/AABB_n_tree.h DELETED
@@ -1,355 +0,0 @@
1
- // Author(s) : Javier Romero
2
-
3
- #ifndef AABB_N_TREE_H
4
- #define AABB_N_TREE_H
5
-
6
- #include <vector>
7
-
8
- #define CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES 1
9
- #include <CGAL/AABB_tree.h>
10
- #include <CGAL/AABB_traits.h>
11
- #include <CGAL/internal/AABB_tree/nearest_point_triangle_3.h>
12
- #include <CGAL/Simple_cartesian.h>
13
- #include <CGAL/AABB_triangle_primitive.h>
14
-
15
- #include <CGAL/intersections.h>
16
- #include <CGAL/Bbox_3.h>
17
-
18
- #include <boost/cstdint.hpp>
19
- #include <boost/array.hpp>
20
-
21
-
22
- typedef CGAL::Simple_cartesian<double> K;
23
- using boost::uint32_t;
24
- using boost::uint64_t;
25
- using boost::array;
26
- using std::vector;
27
-
28
- typedef K::Point_3 Point;
29
- typedef K::Segment_3 Segment;
30
- typedef K::Triangle_3 Triangle;
31
- typedef K::Vector_3 Normal;
32
- typedef std::pair<Point,Normal> Point_Normal;
33
-
34
- typedef std::vector<Triangle>::iterator Iterator;
35
- typedef CGAL::AABB_triangle_primitive<K,Iterator> Primitive;
36
-
37
-
38
- namespace CGAL {
39
- template<typename FT>
40
- FT dist_point_normal(const Point_Normal& a, const Point_Normal& b, FT eps){
41
- return (sqrt(squared_distance(a.first, b.first)) + eps*(1 - a.second*b.second));
42
- }
43
-
44
- // Adaptation of nearest_point_3 to take into account normals
45
- // product with weight eps
46
- template<typename FT>
47
- Point_Normal nearest_pointnormal_3(const Point_Normal& origin,
48
- const Triangle& triangle,
49
- const Point_Normal& bound,
50
- const FT eps,
51
- const K& k){
52
- // compute normal penalties
53
- const FT dist_n_bound = eps*(1 - origin.second*bound.second);
54
- //const Normal tri_n = unit_normal(triangle[0],triangle[1],triangle[2]);
55
- Normal tri_n = triangle.supporting_plane().orthogonal_direction().vector();
56
- tri_n = tri_n / sqrt(tri_n.squared_length());
57
- const FT dist_n_triangle = eps*(1 - origin.second*tri_n);
58
-
59
- // Distance from origin to bound
60
- const FT dist_bound = sqrt(squared_distance(origin.first,bound.first)) + dist_n_bound;
61
-
62
- // since dist_n_triangle < dist_triangle
63
- if (dist_n_triangle > dist_bound)
64
- return bound;
65
-
66
- // Project origin on triangle supporting plane
67
- const Point_Normal proj = std::make_pair(triangle.supporting_plane().projection(origin.first), tri_n);
68
-
69
- const FT dist_proj = sqrt(squared_distance(origin.first,proj.first)) + dist_n_triangle;
70
-
71
- Point moved_point;
72
- // If point is projected outside, return bound
73
- if ( dist_proj > dist_bound)
74
- return bound;
75
- // If proj is inside triangle, total dist is dist_proj
76
- else if ( CGAL::internal::is_inside_triangle_3<K>(proj.first,triangle,moved_point,k) )
77
- return proj;
78
- // Else return the constructed point (nearest point of triangle from proj)
79
- // if it is closest to origin than bound
80
- else{
81
- const FT dist_moved = sqrt(squared_distance(origin.first, moved_point)) + dist_n_triangle;
82
- return (dist_moved > dist_bound) ? bound : std::make_pair(moved_point, tri_n);
83
- }
84
- }
85
-
86
- // extends AABB_Traits with classes handling points with normals
87
- template <typename GeomTraits, typename AABB_primitive>
88
- class AABB_n_traits:public AABB_traits<GeomTraits,AABB_primitive>{
89
-
90
- public:
91
-
92
- typedef Point_Normal PointNormal;
93
- typedef AABB_n_traits<GeomTraits, AABB_primitive> AT;
94
-
95
- class Do_intersect{
96
- public:
97
- template<typename Query>
98
- bool operator()(const Query& q, const CGAL::Bbox_3& bbox) const{
99
- return CGAL::do_intersect(q, bbox);
100
- }
101
-
102
- template<typename Query>
103
- bool operator()(const Query& q, const AABB_primitive& pr) const{
104
- return GeomTraits().do_intersect_3_object()(q, pr.datum());
105
- }
106
-
107
- bool operator()(const typename GeomTraits::Triangle_3& q, const AABB_primitive& pr) const{
108
-
109
- // if any point is the same, don't consider it'
110
- if(q[0] == pr.datum()[0] || q[0] == pr.datum()[1] ||q[0] == pr.datum()[2] ||
111
- q[1] == pr.datum()[0] || q[1] == pr.datum()[1] ||q[1] == pr.datum()[2] ||
112
- q[2] == pr.datum()[0] || q[2] == pr.datum()[1] ||q[2] == pr.datum()[2])
113
- return false;
114
- else
115
- return CGAL::do_intersect(q, pr.datum());
116
- }
117
- };
118
-
119
- class Closest_point {
120
- typedef typename AT::Point_3 Point;
121
- typedef typename AT::PointNormal PointNormal;
122
- typedef typename AT::Primitive Primitive;
123
- typedef typename AT::FT FT;
124
-
125
- public:
126
-
127
- // for intersection: return the closest point on
128
- // triangle pr or bound to pn
129
- PointNormal operator()(const PointNormal& pn, const Primitive& pr,
130
- const PointNormal& bound, FT eps) const {
131
- return nearest_pointnormal_3(pn, pr.datum(), bound, eps, K());
132
- }
133
-
134
- };
135
-
136
- class Compare_distance {
137
- typedef typename AT::Point_3 Point;
138
- typedef typename AT::PointNormal PointNormal;
139
- typedef typename AT::FT FT;
140
- typedef typename AT::Primitive Primitive;
141
- public:
142
-
143
- // create a sphere that contains all possible results
144
- // (all points closer than current result) and
145
- // check if pr intersects
146
- template <class Solid>
147
- CGAL::Comparison_result operator()(const PointNormal& p, const Solid& pr, const PointNormal& bound, FT eps) const
148
- {
149
- // d_q = ||q - p|| + eps(1 - n_q*n_p) > ||q-p||
150
- // d_q < d_b -> ||q-p|| < d_b
151
- // a sphere containing all q such that ||q-p|| < d_b
152
- // contains all q such that d_q < d_b
153
- FT safe_dist = dist_point_normal(p,bound,eps);
154
- return GeomTraits().do_intersect_3_object()
155
- (GeomTraits().construct_sphere_3_object()
156
- (p.first, safe_dist*safe_dist), pr)?
157
- CGAL::SMALLER : CGAL::LARGER;
158
- }
159
- };
160
-
161
- Closest_point closest_point_object() {return Closest_point();}
162
- Compare_distance compare_distance_object() {return Compare_distance();}
163
- Do_intersect do_intersect_object() {return Do_intersect();}
164
-
165
- };// end of AABB_n_traits
166
-
167
-
168
- /**
169
- * @class Do_intersect_noself_traits
170
- */
171
- template<typename AABBTraits, typename Query>
172
- class Do_intersect_noself_traits
173
- {
174
- typedef typename AABBTraits::FT FT;
175
- typedef typename AABBTraits::Point_3 Point;
176
- typedef typename AABBTraits::Primitive Primitive;
177
- typedef typename AABBTraits::Bounding_box Bounding_box;
178
- typedef typename AABBTraits::Primitive::Id Primitive_id;
179
- typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
180
- typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
181
- typedef ::CGAL::AABB_node<AABBTraits> Node;
182
- typedef typename ::CGAL::AABB_tree<AABBTraits>::size_type size_type;
183
-
184
- public:
185
- Do_intersect_noself_traits()
186
- : m_is_found(false)
187
- {}
188
-
189
- bool go_further() const { return !m_is_found; }
190
-
191
- void intersection(const Query& query, const Primitive& primitive)
192
- {
193
- if( AABBTraits().do_intersect_object()(query, primitive) )
194
- m_is_found = true;
195
- }
196
-
197
- bool do_intersect(const Query& query, const Node& node) const
198
- {
199
- return AABBTraits().do_intersect_object()(query, node.bbox());
200
- }
201
-
202
- bool is_intersection_found() const { return m_is_found; }
203
-
204
- private:
205
- bool m_is_found;
206
- };
207
-
208
- /**
209
- * @class Projection_n_traits
210
- */
211
- template <typename AABBTraits>
212
- class Projection_n_traits
213
- {
214
- typedef typename AABBTraits::FT FT;
215
- typedef typename AABBTraits::Point_3 Point;
216
- typedef typename AABBTraits::PointNormal PointNormal;
217
- typedef typename AABBTraits::Primitive Primitive;
218
- typedef typename AABBTraits::Bounding_box Bounding_box;
219
- typedef typename AABBTraits::Primitive::Id Primitive_id;
220
- typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
221
- typedef typename AABBTraits::Object_and_primitive_id Object_and_primitive_id;
222
- typedef ::CGAL::AABB_node<AABBTraits> Node;
223
-
224
- public:
225
- Projection_n_traits(const PointNormal& hint,
226
- const typename Primitive::Id& hint_primitive,
227
- const FT eps)
228
- : m_closest_point(hint), m_closest_primitive(hint_primitive), eps(eps) {}
229
-
230
- bool go_further() const { return true; }
231
-
232
- void intersection(const PointNormal& query, const Primitive& primitive)
233
- {
234
- PointNormal new_closest_point = AABBTraits().closest_point_object()
235
- (query, primitive, m_closest_point, eps);
236
- if(new_closest_point.first != m_closest_point.first)
237
- {
238
- m_closest_primitive = primitive.id();
239
- m_closest_point = new_closest_point; // this effectively shrinks the sphere
240
- }
241
- }
242
-
243
- bool do_intersect(const PointNormal& query, const Node& node) const
244
- {
245
- return AABBTraits().compare_distance_object()
246
- (query, node.bbox(), m_closest_point, eps) == CGAL::SMALLER;
247
- }
248
-
249
- Point closest_point() const { return m_closest_point.first; }
250
- Point_and_primitive_id closest_point_and_primitive() const
251
- {
252
- return Point_and_primitive_id(m_closest_point.first, m_closest_primitive);
253
- }
254
-
255
- private:
256
- PointNormal m_closest_point;
257
- typename Primitive::Id m_closest_primitive;
258
- const FT eps;
259
- };
260
-
261
- // Class that extends AABB tree with PointNormal Search
262
- template <typename AABBTraits>
263
- class AABB_n_tree:public AABB_tree<AABBTraits>{
264
- public:
265
- typedef typename AABBTraits::Point_3 Point;
266
- typedef typename AABBTraits::PointNormal PointNormal;
267
- typedef typename AABBTraits::Point_and_primitive_id Point_and_primitive_id;
268
-
269
- AABB_n_tree():AABB_tree<AABBTraits>(){}
270
-
271
- template<typename ConstPrimitiveIterator>
272
- AABB_n_tree(ConstPrimitiveIterator first, ConstPrimitiveIterator beyond,
273
- typename AABBTraits::FT eps):
274
- AABB_tree<AABBTraits>(first, beyond), eps(eps){}
275
-
276
- // XXX The hint is random; that is slow and could be closer (euclideanly) than the best point
277
- Point_and_primitive_id closest_point_and_primitive(const PointNormal& query) const{
278
- // return closest_point_and_primitive(query,best_hint(query.first));
279
- return closest_point_and_primitive(query,this->any_reference_point_and_id());
280
- }
281
-
282
- Point_and_primitive_id closest_point_and_primitive(const PointNormal& query,
283
- const Point_and_primitive_id& hint) const{
284
-
285
- Normal hint_n = (*hint.second).supporting_plane().orthogonal_direction().vector();
286
- PointNormal hint_pn = std::make_pair(hint.first, hint_n/sqrt(hint_n.squared_length()));
287
- // hint_pn = std::make_pair(Point(10000,10000,10000),Normal(0,0,1));
288
- Projection_n_traits<AABBTraits> projection_traits(hint_pn, hint.second, eps);
289
- this->traversal(query, projection_traits);
290
- return projection_traits.closest_point_and_primitive();
291
- }
292
-
293
- template<typename Query>
294
- bool do_intersect(const Query& query) const
295
- {
296
- //using namespace CGAL::internal::AABB_tree;
297
- Do_intersect_noself_traits<AABBTraits, Query> traversal_traits;
298
- this->traversal(query, traversal_traits);
299
- return traversal_traits.is_intersection_found();
300
- }
301
-
302
- typename AABBTraits::FT eps;
303
- };
304
- }
305
-
306
- typedef CGAL::AABB_n_traits<K, Primitive> AABB_n_triangle_traits;
307
- typedef AABB_n_triangle_traits::Point_and_primitive_id Point_and_Primitive_id;
308
- typedef CGAL::AABB_n_tree<AABB_n_triangle_traits> Tree;
309
-
310
- struct TreeAndTri {
311
- TreeAndTri(const array<uint32_t, 3>* p_mesh_tri,
312
- const array<double, 3>* p_mesh_points,
313
- const double eps,
314
- const size_t T,
315
- const size_t P)
316
- {
317
- std::vector<K::Point_3> mesh_points;
318
- mesh_points.reserve(P);
319
- for(size_t pp=0; pp<P; ++pp){
320
- mesh_points.push_back(K::Point_3(p_mesh_points[pp][0],
321
- p_mesh_points[pp][1],
322
- p_mesh_points[pp][2]));
323
- }
324
-
325
- triangles.reserve(T);
326
- for(size_t tt=0; tt<T; ++tt) {
327
- triangles.push_back(K::Triangle_3(mesh_points[p_mesh_tri[tt][0]],
328
- mesh_points[p_mesh_tri[tt][1]],
329
- mesh_points[p_mesh_tri[tt][2]]));
330
- }
331
-
332
- tree.eps = eps;
333
- tree.rebuild(triangles.begin(), triangles.end());
334
- // tree.accelerate_distance_queries();
335
- }
336
-
337
- vector<K::Triangle_3> triangles;
338
- Tree tree;
339
- };
340
-
341
- template<typename T>
342
- boost::uint64_t wrapPointer(T *ptr) {
343
- return reinterpret_cast<uint64_t>(ptr);
344
- }
345
- template<typename T>
346
- T* unwrapPointer(uint64_t ptr) {
347
- return reinterpret_cast<T*>(ptr);
348
- }
349
-
350
- #endif // AABB_N_TREE_H
351
-
352
- /***EMACS SETTINGS***/
353
- /* Local Variables: */
354
- /* tab-width: 2 */
355
- /* End: */