feifeifeiliu commited on
Commit
faeda5e
·
1 Parent(s): 9b6fdf7

Upload 97 files

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-fix-MSVC_compilation/.gitattributes +5 -0
  2. mesh-fix-MSVC_compilation/.gitignore +10 -0
  3. mesh-fix-MSVC_compilation/CGAL_LICENSE.pdf +0 -0
  4. mesh-fix-MSVC_compilation/LICENSE.txt +30 -0
  5. mesh-fix-MSVC_compilation/MANIFEST.in +2 -0
  6. mesh-fix-MSVC_compilation/Makefile +48 -0
  7. mesh-fix-MSVC_compilation/README.md +110 -0
  8. mesh-fix-MSVC_compilation/data/unittest/cylinder.obj +38 -0
  9. mesh-fix-MSVC_compilation/data/unittest/cylinder_trans.obj +38 -0
  10. mesh-fix-MSVC_compilation/data/unittest/self_intersecting_cyl.obj +46 -0
  11. mesh-fix-MSVC_compilation/data/unittest/sphere.obj +1278 -0
  12. mesh-fix-MSVC_compilation/data/unittest/sphere.ply +1271 -0
  13. mesh-fix-MSVC_compilation/data/unittest/test_box.obj +50 -0
  14. mesh-fix-MSVC_compilation/data/unittest/test_box.ply +29 -0
  15. mesh-fix-MSVC_compilation/data/unittest/test_box.pp +11 -0
  16. mesh-fix-MSVC_compilation/data/unittest/test_box_le.ply +0 -0
  17. mesh-fix-MSVC_compilation/data/unittest/test_doublebox.obj +64 -0
  18. mesh-fix-MSVC_compilation/doc/Makefile +177 -0
  19. mesh-fix-MSVC_compilation/doc/make.bat +242 -0
  20. mesh-fix-MSVC_compilation/doc/source/conf.py +356 -0
  21. mesh-fix-MSVC_compilation/doc/source/index.rst +163 -0
  22. mesh-fix-MSVC_compilation/doc/source/pages/geometry.rst +29 -0
  23. mesh-fix-MSVC_compilation/doc/source/pages/mesh.rst +31 -0
  24. mesh-fix-MSVC_compilation/doc/source/pages/mesh_viewer.rst +11 -0
  25. mesh-fix-MSVC_compilation/mesh/CMakeLists.txt +114 -0
  26. mesh-fix-MSVC_compilation/mesh/__init__.py +20 -0
  27. mesh-fix-MSVC_compilation/mesh/arcball.py +247 -0
  28. mesh-fix-MSVC_compilation/mesh/cmake/python_helper.cmake +74 -0
  29. mesh-fix-MSVC_compilation/mesh/cmake/thirdparty.cmake +107 -0
  30. mesh-fix-MSVC_compilation/mesh/colors.py +790 -0
  31. mesh-fix-MSVC_compilation/mesh/errors.py +15 -0
  32. mesh-fix-MSVC_compilation/mesh/fonts.py +87 -0
  33. mesh-fix-MSVC_compilation/mesh/geometry/__init__.py +4 -0
  34. mesh-fix-MSVC_compilation/mesh/geometry/barycentric_coordinates_of_projection.py +49 -0
  35. mesh-fix-MSVC_compilation/mesh/geometry/cross_product.py +37 -0
  36. mesh-fix-MSVC_compilation/mesh/geometry/rodrigues.py +125 -0
  37. mesh-fix-MSVC_compilation/mesh/geometry/tri_normals.py +72 -0
  38. mesh-fix-MSVC_compilation/mesh/geometry/triangle_area.py +12 -0
  39. mesh-fix-MSVC_compilation/mesh/geometry/vert_normals.py +34 -0
  40. mesh-fix-MSVC_compilation/mesh/landmarks.py +102 -0
  41. mesh-fix-MSVC_compilation/mesh/lines.py +61 -0
  42. mesh-fix-MSVC_compilation/mesh/mesh.py +492 -0
  43. mesh-fix-MSVC_compilation/mesh/meshviewer.py +1238 -0
  44. mesh-fix-MSVC_compilation/mesh/processing.py +186 -0
  45. mesh-fix-MSVC_compilation/mesh/ressources/Arial.ttf +0 -0
  46. mesh-fix-MSVC_compilation/mesh/search.py +100 -0
  47. mesh-fix-MSVC_compilation/mesh/serialization/__init__.py +4 -0
  48. mesh-fix-MSVC_compilation/mesh/serialization/serialization.py +443 -0
  49. mesh-fix-MSVC_compilation/mesh/sphere.py +74 -0
  50. mesh-fix-MSVC_compilation/mesh/src/AABB_n_tree.h +355 -0
mesh-fix-MSVC_compilation/.gitattributes ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ /data/unittest/* text eol=lf
2
+ /data/unittest/*.obj text
3
+ /data/unittest/*.pp text
4
+ /data/unittest/sphere.ply text
5
+ /data/unittest/test_box.ply text
mesh-fix-MSVC_compilation/.gitignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ build/*
2
+ *.pyc
3
+ temporary_test
4
+ dist
5
+ MANIFEST
6
+ *.xml
7
+ *.egg-info
8
+ doc/build
9
+ .eggs
10
+ .idea
mesh-fix-MSVC_compilation/CGAL_LICENSE.pdf ADDED
Binary file (78.7 kB). View file
 
mesh-fix-MSVC_compilation/LICENSE.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/MANIFEST.in ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ recursive-include mesh/src *
2
+ recursive-include mesh/ressources *
mesh-fix-MSVC_compilation/Makefile ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Makefile for mesh package
2
+ package_name := mesh_package
3
+
4
+ all:
5
+ @echo "\033[0;36m----- [" ${package_name} "] Installing on the local virtual environment `which python`\033[0m"
6
+ @pip install --upgrade -r requirements.txt && pip list
7
+ @pip install --no-deps --install-option="--boost-location=$$BOOST_ROOT" --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_ROOT 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-fix-MSVC_compilation/README.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Perceiving Systems Mesh Package
2
+ ===============================
3
+
4
+ This package contains core functions for manipulating meshes and visualizing them.
5
+ It requires ``Python 3.5+`` and is supported on Linux and macOS operating systems.
6
+
7
+ The ``Mesh`` processing libraries support several of our projects such as
8
+ * [CoMA: Convolutional Mesh Encoders for Generating 3D Faces](http://coma.is.tue.mpg.de/)
9
+ * [FLAME: Learning a model of facial shape and expression from 4D scans](http://flame.is.tue.mpg.de/)
10
+ * [MANO: Modeling and Capturing Hands and Bodies Together](http://mano.is.tue.mpg.de/)
11
+ * [SMPL: A Skinned Multi-Person Linear Model](http://smpl.is.tue.mpg.de/)
12
+ * [VOCA: Voice Operated Character Animation](https://github.com/TimoBolkart/voca)
13
+ * [RingNet: 3D Face Shape and Expression Reconstruction from an Image](https://github.com/soubhiksanyal/RingNet)
14
+
15
+ Requirements
16
+ ------------
17
+
18
+ You first need to install the `Boost <http://www.boost.org>`_ libraries.
19
+ You can compile your own local version.
20
+
21
+ On Windows/MSVC, you must download and compile it yourself.
22
+
23
+ On Linux you can simply install it via:
24
+
25
+ ```
26
+ $ sudo apt-get install libboost-dev
27
+ ```
28
+
29
+ On macOS:
30
+
31
+ ```
32
+ $ brew install boost
33
+ ```
34
+
35
+ Installation
36
+ ------------
37
+
38
+ First, create a dedicated Python virtual environment and activate it:
39
+
40
+ ```
41
+ $ python3 -m venv --copies my_venv
42
+ $ source my_venv/bin/activate
43
+ ```
44
+
45
+ #### Linux/MacOS
46
+ You should then compile and install the ``psbody-mesh`` package using the Makefile.
47
+ If you are using the system-wide ``Boost`` libraries:
48
+
49
+ ```
50
+ $ make all
51
+ ```
52
+
53
+ or the libraries locally installed:
54
+
55
+ ```
56
+ $ BOOST_ROOT=/path/to/boost/libraries make all
57
+ ```
58
+
59
+ #### Windows
60
+ Since Makefile and the linux commands in it does not work on Windows, run the command below instead:
61
+ (remember to replace <path_to_your_boost> with your path to boost)
62
+ ```
63
+ pip install --no-deps --install-option="--boost-location=<path_to_your_boost>" --verbose --no-cache-dir .
64
+ ```
65
+
66
+ Note on MeshViewer: Windows users need a special version of PyOpenGL to use the MeshViewer, because the one automatically installed via PYPI does not include the required DLL.
67
+
68
+ please download the unofficial PyOpenGL wheel file from [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyopengl), uninstall the original version and install the new one by commands below:
69
+
70
+ ```
71
+ pip uninstall pyOpenGL
72
+ pip install <the-name-of-your-wheel-file>
73
+ ```
74
+
75
+ Testing
76
+ -------
77
+
78
+ To run the tests, simply do:
79
+
80
+ #### Linux/MacOS
81
+
82
+ ```
83
+ $ make tests
84
+ ```
85
+
86
+ #### Windows
87
+
88
+ ```
89
+ python -m unittest -v
90
+ ```
91
+
92
+ Documentation
93
+ -------------
94
+
95
+ A detailed documentation can be compiled using the Makefile:
96
+
97
+ ```
98
+ $ make documentation
99
+ ```
100
+
101
+ License
102
+ -------
103
+ Please refer for LICENSE.txt for using this software. The software is compiled using CGAL sources following the license in CGAL_LICENSE.pdf
104
+
105
+ Acknowledgments
106
+ ---------------
107
+
108
+ We thank the external contribution from the following people:
109
+ * [Kenneth Chaney](https://github.com/k-chaney) ([PR #5](https://github.com/MPI-IS/mesh/pull/5))
110
+ * [Dávid Komorowicz](https://github.com/Dawars) ([PR #8](https://github.com/MPI-IS/mesh/pull/8))
mesh-fix-MSVC_compilation/data/unittest/cylinder.obj ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/cylinder_trans.obj ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/self_intersecting_cyl.obj ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/sphere.obj ADDED
@@ -0,0 +1,1278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/sphere.ply ADDED
@@ -0,0 +1,1271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/test_box.obj ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/test_box.ply ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/test_box.pp ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/data/unittest/test_box_le.ply ADDED
Binary file (422 Bytes). View file
 
mesh-fix-MSVC_compilation/data/unittest/test_doublebox.obj ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/Makefile ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/make.bat ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/source/conf.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/source/index.rst ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ This package contains core functions for manipulating Meshes and visualizing them.
25
+ It requires ``Python 3.5+`` and is supported on Linux and macOS operating systems.
26
+
27
+
28
+ Getting started
29
+ ===============
30
+
31
+ Installation
32
+ ------------
33
+
34
+
35
+ There are several places where you can download the latest release of the ``psbody-mesh`` package:
36
+
37
+ * `Code Doc <https://code.is.localnet/series/3/8/>`_ , the internal documentation center of the MPI-IS
38
+ * `GitLab <https://gitlab.tuebingen.mpg.de/ps-body/mesh>`_, the internal repository used for development
39
+ * `GitHub <https://github.com/MPI-IS/mesh>`_ for the public release
40
+
41
+ ``Code Doc`` contains the wheel and source distributions, and the documentation of the **complete** package.
42
+
43
+ ``GitLab`` contains the source code of the **complete** package.
44
+
45
+ ``GitHub`` contains the source code of the public, **limited** package.
46
+
47
+
48
+ First, create a dedicated Python virtual environment and activate it:
49
+
50
+ .. code::
51
+
52
+ $ python3 -m venv --copies my_venv
53
+ $ source my_venv/bin/activate
54
+
55
+ The easiest way to install the ``psbody-mesh`` package is to use the wheel distribution:
56
+
57
+ .. code::
58
+
59
+ $ pip install psbody_mesh_*.whl
60
+
61
+ .. warning::
62
+
63
+ Make sure to use to wheel corresponding to your OS and your Python version.
64
+
65
+ You can also install the ``psbody-mesh`` package using the source distribution.
66
+ For this, you first need to install the `Boost <http://www.boost.org>`_ libraries.
67
+ You can compile your own local version or simply do:
68
+
69
+ .. code::
70
+
71
+ $ sudo apt-get install libboost-dev
72
+
73
+ and then install the ``psbody-mesh`` package:
74
+
75
+ .. code::
76
+
77
+ $ pip install psbody_mesh_*.tar.gz
78
+
79
+ As a last option, you can also compile and install the ``psbody-mesh`` package using the Makefile.
80
+ If you are using the system-wide ``Boost libraries``:
81
+
82
+ .. code::
83
+
84
+ $ make all
85
+
86
+ or the libraries locally installed:
87
+
88
+ .. code::
89
+
90
+ $ BOOST_ROOT=/path/to/boost/libraries make all
91
+
92
+ Testing
93
+ -------
94
+
95
+ To run the tests (only available in the **complete** package), simply do:
96
+
97
+ .. code::
98
+
99
+ $ make tests
100
+
101
+ Documentation
102
+ -------------
103
+
104
+ A detailed documentation can be compiled using the Makefile:
105
+
106
+ .. code::
107
+
108
+ $ make documentation
109
+
110
+ Loading a mesh
111
+ --------------
112
+
113
+ Loading a :py:class:`Mesh <psbody.mesh.mesh.Mesh>` class from a file is that easy:
114
+
115
+ .. code::
116
+
117
+ from psbody.mesh import Mesh
118
+ my_mesh = Mesh(filename='mesh_filename.ply')
119
+
120
+ Rendering a mesh
121
+ ----------------
122
+
123
+ From a previously loaded mesh ``my_mesh``, it is possible to visualize it inside an interactive window using the
124
+ :py:class:`MeshViewers <psbody.mesh.meshviewer.MeshViewers>` class:
125
+
126
+ .. code::
127
+
128
+ from psbody.mesh import MeshViewers
129
+
130
+ # creates a grid of 2x2 mesh viewers
131
+ mvs = MeshViewers(shape=[2, 2])
132
+
133
+ # sets the first (top-left) mesh to my_mesh
134
+ mvs[0][0].set_static_meshes([my_mesh])
135
+
136
+ Caching
137
+ -------
138
+
139
+ Some operations make use of caching for performance reasons. The default folder used for caching is
140
+
141
+ .. code::
142
+
143
+ ~/.psbody/mesh_package_cache
144
+
145
+
146
+ If you need to specify the cache folder, define the environment variable ``PSBODY_MESH_CACHE``
147
+ prior to any loading of the Mesh package:
148
+
149
+ .. code::
150
+
151
+ export PSBODY_MESH_CACHE="some/folder"
152
+ python
153
+ >> from psbody.mesh import Mesh
154
+ # now uses the specified cache
155
+
156
+
157
+
158
+ Indices and tables
159
+ ==================
160
+
161
+ * :ref:`genindex`
162
+ * :ref:`modindex`
163
+ * :ref:`search`
mesh-fix-MSVC_compilation/doc/source/pages/geometry.rst ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/source/pages/mesh.rst ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/doc/source/pages/mesh_viewer.rst ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Mesh viewer
2
+ ===========
3
+
4
+
5
+ Reference
6
+ ---------
7
+
8
+ .. automodule:: psbody.mesh.meshviewer
9
+ :members:
10
+ :undoc-members:
11
+
mesh-fix-MSVC_compilation/mesh/CMakeLists.txt ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # visibility
85
+ python_add_library(TARGET visibility SOURCES
86
+ src/py_visibility.cpp
87
+ src/visibility.cpp
88
+ )
89
+ target_include_directories(visibility PRIVATE
90
+ ${libcgalroot}/include
91
+ ${NUMPY_INCLUDE_PATH}
92
+ ${Boost_INCLUDE_DIRS})
93
+ set_property(TARGET visibility PROPERTY FOLDER "GeometryExt/")
94
+ target_compile_definitions(visibility PRIVATE
95
+ ${DEFINES_MESH_EXTENSIONS_WITH_CGAL_WITHOUT_LINK})
96
+
97
+
98
+ # serialization extensions
99
+
100
+ # plyutils
101
+ python_add_library(TARGET plyutils SOURCES
102
+ src/plyutils.h
103
+ src/plyutils.c
104
+ src/rply.h
105
+ src/rply.c)
106
+ set_property(TARGET plyutils PROPERTY FOLDER "SerializationExt/")
107
+
108
+ # loadobj
109
+ python_add_library(TARGET loadobj SOURCES src/py_loadobj.cpp)
110
+ target_include_directories(loadobj PRIVATE
111
+ ${NUMPY_INCLUDE_PATH}
112
+ ${Boost_INCLUDE_DIRS})
113
+ set_property(TARGET loadobj PROPERTY FOLDER "SerializationExt/")
114
+
mesh-fix-MSVC_compilation/mesh/__init__.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/arcball.py ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/cmake/python_helper.cmake ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/cmake/thirdparty.cmake ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/colors.py ADDED
@@ -0,0 +1,790 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/errors.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/fonts.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # encoding: utf-8
3
+
4
+ # Copyright (c) 2016 Max Planck Society. All rights reserved.
mesh-fix-MSVC_compilation/mesh/geometry/barycentric_coordinates_of_projection.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/cross_product.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/rodrigues.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/tri_normals.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/triangle_area.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/geometry/vert_normals.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/landmarks.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/lines.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/mesh.py ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/meshviewer.py ADDED
@@ -0,0 +1,1238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 backend used for visualization
12
+ 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 is usually performed
23
+ on a forked python process. In case OpenGL is not supported, a `DummyClass``
24
+ mesh viewer is returned.
25
+ * ``arguments=title nb_x_axis nb_y_axis width height`` a new window is created
26
+
27
+ .. autosummary::
28
+
29
+ MeshViewer
30
+ MeshViewers
31
+ MeshViewerLocal
32
+ test_for_opengl
33
+
34
+ """
35
+
36
+ import sys
37
+ import os.path
38
+ import time
39
+ import copy
40
+ import numpy as np
41
+ import traceback
42
+ from multiprocessing import freeze_support
43
+
44
+ import zmq
45
+ import re
46
+ import subprocess
47
+ import tempfile
48
+
49
+ # this is way too verbose, organize imports better
50
+ from OpenGL.GL import glPixelStorei, glMatrixMode, glHint, glTexParameterf, glDisableClientState
51
+ from OpenGL.GL import glBindTexture, glEnableClientState, glPointSize, glEnable
52
+ from OpenGL.GL import glColor3f, glDisable, glBegin, glEnd, glClearColor, glClearDepth
53
+ from OpenGL.GL import glNormalPointer, glLineWidth, glTexCoord2f, glTexCoordPointer
54
+ from OpenGL.GL import glViewport, glLightModeli, glLoadIdentity, glTranslatef, glPushMatrix
55
+ from OpenGL.GL import glLoadMatrixf, glPopMatrix, glMultMatrixf, glDrawElementsui, glTexEnvf, glGetDoublev
56
+ from OpenGL.GL import glGenTextures, glTexImage2D, glFrustum, glGenerateMipmap
57
+ from OpenGL.GL import glBlendFunc, glVertex3f, glVertexPointer, glVertexPointerf, glColorPointerf, glColorPointer
58
+ from OpenGL.GL import glGetFloatv, glGetIntegerv, glReadPixels
59
+ from OpenGL.GL import glClear, glFlush, glDepthFunc, glShadeModel
60
+ from OpenGL.GL import GL_TRUE, GL_FLOAT, GL_POINTS, GL_COLOR_ARRAY, GL_NORMAL_ARRAY, GL_LINE_SMOOTH, GL_MODELVIEW_MATRIX
61
+ from OpenGL.GL import GL_BLEND, GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_TEXTURE_MAG_FILTER, GL_SMOOTH
62
+ from OpenGL.GL import GL_TEXTURE_MIN_FILTER, GL_VIEWPORT, GL_LINEAR, GL_COLOR_MATERIAL, GL_LIGHT0, GL_NORMALIZE
63
+ from OpenGL.GL import GL_PROJECTION, GL_MODELVIEW, GL_VERTEX_SHADER, GL_LIGHTING, GL_TEXTURE_COORD_ARRAY
64
+ from OpenGL.GL import GL_TEXTURE_ENV, GL_TRIANGLES, GL_LINEAR_MIPMAP_LINEAR, GL_COLOR_CLEAR_VALUE
65
+ from OpenGL.GL import GL_FRAGMENT_SHADER, GL_NEAREST, GL_UNPACK_ALIGNMENT, GL_RGB, GL_BGR, GL_DECAL, GL_MODULATE
66
+ from OpenGL.GL import GL_UNSIGNED_BYTE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_QUADS, GL_POLYGON, GL_VERTEX_ARRAY, GL_DEPTH_COMPONENT
67
+ from OpenGL.GL import GL_LIGHT_MODEL_TWO_SIDE, GL_GENERATE_MIPMAP_HINT, GL_NICEST, GL_LINES, GL_PROJECTION_MATRIX
68
+ from OpenGL.GL import GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_LEQUAL, GL_DEPTH_TEST, GL_PERSPECTIVE_CORRECTION_HINT
69
+ from OpenGL.GL import shaders
70
+
71
+ from OpenGL.GLUT import glutInit, glutDisplayFunc, glutInitDisplayMode, glutInitWindowSize, glutGet, GLUT_WINDOW_WIDTH, GLUT_WINDOW_HEIGHT
72
+ from OpenGL.GLUT import glutMainLoop, glutPostRedisplay, glutInitWindowPosition, glutCreateWindow, glutTimerFunc, glutSetWindowTitle
73
+ from OpenGL.GLUT import glutReshapeFunc, glutKeyboardFunc, glutMouseFunc, glutMotionFunc, glutSwapBuffers
74
+ from OpenGL.GLUT import GLUT_RGBA, GLUT_DOUBLE, GLUT_ALPHA, GLUT_DEPTH
75
+ from OpenGL.GLUT import GLUT_LEFT_BUTTON, GLUT_DOWN, GLUT_UP, GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON
76
+ from OpenGL.GLU import gluPerspective, gluUnProject
77
+
78
+ import OpenGL.arrays.vbo
79
+
80
+ # if this file is processed/run as a python script/standalone, especially from the
81
+ # internal command
82
+ if __package__ is not None:
83
+ from .mesh import Mesh
84
+ from .geometry.tri_normals import TriNormals
85
+ from .arcball import ArcBallT, Matrix3fT, Matrix4fT, Point2fT, \
86
+ Matrix3fMulMatrix3f, Matrix3fSetRotationFromQuat4f, Matrix4fSetRotationFromMatrix3f
87
+
88
+ from .fonts import get_textureid_with_text
89
+
90
+ # this block is below the previous one to make my linter happy
91
+ if __package__ is None:
92
+ print("this file cannot be executed as a standalone python module")
93
+ print("python -m psbody.mesh.%s arguments" % (os.path.splitext(os.path.basename(__file__))[0]))
94
+ sys.exit(-1)
95
+
96
+
97
+ def _run_self(args, stdin=None, stdout=None, stderr=None):
98
+ """Executes this same script module with the given arguments (forking without subprocess dependencies)"""
99
+ return subprocess.Popen([sys.executable] +
100
+ ['-m'] + ['%s.%s' % (__package__, os.path.splitext(os.path.basename(__file__))[0])] +
101
+ args,
102
+ stdin=stdin,
103
+ stdout=stdout, # if stdout is not None else subprocess.PIPE,
104
+ stderr=stderr)
105
+
106
+
107
+ def _test_for_opengl():
108
+ try:
109
+ # from OpenGL.GLUT import glutInit
110
+ glutInit()
111
+ except Exception as e:
112
+ print(e, file=sys.stderr)
113
+ print('failure')
114
+ else:
115
+ print('success')
116
+
117
+
118
+ test_for_opengl_cached = None
119
+
120
+
121
+ def test_for_opengl():
122
+ """Tests if opengl is supported.
123
+
124
+ .. note:: the result of the test is cached
125
+
126
+ """
127
+
128
+ global test_for_opengl_cached
129
+ if test_for_opengl_cached is None:
130
+
131
+ with open(os.devnull) as dev_null, \
132
+ tempfile.TemporaryFile() as out, \
133
+ tempfile.TemporaryFile() as err:
134
+
135
+ p = _run_self(["TEST_FOR_OPENGL"],
136
+ stdin=dev_null,
137
+ stdout=out,
138
+ stderr=err)
139
+ p.wait()
140
+
141
+ out.seek(0)
142
+ err.seek(0)
143
+
144
+ line = ''.join(out.read().decode())
145
+ test_for_opengl_cached = 'success' in line
146
+ if not test_for_opengl_cached:
147
+ print('OpenGL test failed: ')
148
+ print('\tstdout:', line)
149
+ print('\tstderr:', '\n'.join(err.read().decode()))
150
+
151
+ return test_for_opengl_cached
152
+
153
+
154
+ class Dummy(object):
155
+
156
+ def __getattr__(self, name):
157
+ return Dummy()
158
+
159
+ def __call__(self, *args, **kwargs):
160
+ return Dummy()
161
+
162
+ def __getitem__(self, key):
163
+ return Dummy()
164
+
165
+ def __setitem__(self, key, value):
166
+ pass
167
+
168
+
169
+ def MeshViewer(titlebar='Mesh Viewer',
170
+ static_meshes=None,
171
+ static_lines=None,
172
+ uid=None,
173
+ autorecenter=True,
174
+ shape=(1, 1),
175
+ keepalive=False,
176
+ window_width=1280,
177
+ window_height=960,
178
+ snapshot_camera=None):
179
+ """Allows visual inspection of geometric primitives.
180
+
181
+ Write-only Attributes:
182
+
183
+ :param titlebar: string printed in the window titlebar
184
+ :param static_meshes: list of Mesh objects to be displayed
185
+ :param static_lines: list of Lines objects to be displayed
186
+
187
+ .. note:: `static_meshes` is meant for Meshes that are updated infrequently,
188
+ `and dynamic_meshes` is for Meshes that are updated frequently
189
+ (same for `dynamic_lines` vs. `static_lines`).
190
+ They may be treated differently for performance reasons.
191
+
192
+ """
193
+
194
+ if not test_for_opengl():
195
+ return Dummy()
196
+
197
+ mv = MeshViewerLocal(shape=(1, 1),
198
+ uid=uid,
199
+ titlebar=titlebar,
200
+ keepalive=keepalive,
201
+ window_width=window_width,
202
+ window_height=window_height)
203
+ result = mv.get_subwindows()[0][0]
204
+ result.snapshot_camera = snapshot_camera
205
+ if static_meshes:
206
+ result.static_meshes = static_meshes
207
+ if static_lines:
208
+ result.static_lines = static_lines
209
+ result.autorecenter = autorecenter
210
+
211
+ return result
212
+
213
+
214
+ def MeshViewers(shape=(1, 1),
215
+ titlebar="Mesh Viewers",
216
+ keepalive=False,
217
+ window_width=1280,
218
+ window_height=960):
219
+ """Allows subplot-style inspection of primitives in multiple subwindows.
220
+
221
+ :param shape: a tuple indicating the number of vertical and horizontal windows requested
222
+ :param titlebar: the title appearing on the created window
223
+
224
+
225
+ Returns: a list of lists of MeshViewer objects: one per window requested.
226
+ """
227
+
228
+ if not test_for_opengl():
229
+ return Dummy()
230
+
231
+ mv = MeshViewerLocal(shape=shape,
232
+ titlebar=titlebar,
233
+ uid=None,
234
+ keepalive=keepalive,
235
+ window_width=window_width,
236
+ window_height=window_height)
237
+ return mv.get_subwindows()
238
+
239
+
240
+ class MeshSubwindow(object):
241
+
242
+ def __init__(self, parent_window, which_window):
243
+ self.parent_window = parent_window
244
+ self.which_window = which_window
245
+
246
+ def set_dynamic_meshes(self, list_of_meshes, blocking=False):
247
+ self.parent_window.set_dynamic_meshes(list_of_meshes, blocking, self.which_window)
248
+
249
+ def set_static_meshes(self, list_of_meshes, blocking=False):
250
+ self.parent_window.set_static_meshes(list_of_meshes, blocking, self.which_window)
251
+
252
+ # list_of_model_names_and_parameters should be of form [{'name': scape_model_name, 'parameters': scape_model_parameters}]
253
+ # here scape_model_name is the filepath of the scape model.
254
+ def set_dynamic_models(self, list_of_model_names_and_parameters, blocking=False):
255
+ self.parent_window.set_dynamic_models(list_of_model_names_and_parameters, blocking, self.which_window)
256
+
257
+ def set_dynamic_lines(self, list_of_lines, blocking=False):
258
+ self.parent_window.set_dynamic_lines(list_of_lines, blocking, self.which_window)
259
+
260
+ def set_static_lines(self, list_of_lines, blocking=False):
261
+ self.parent_window.set_static_lines(list_of_lines, blocking=blocking, which_window=self.which_window)
262
+
263
+ def set_titlebar(self, titlebar, blocking=False):
264
+ self.parent_window.set_titlebar(titlebar, blocking, which_window=self.which_window)
265
+
266
+ def set_lighting_on(self, lighting_on, blocking=True):
267
+ self.parent_window.set_lighting_on(lighting_on, blocking=blocking, which_window=self.which_window)
268
+
269
+ def set_autorecenter(self, autorecenter, blocking=False):
270
+ self.parent_window.set_autorecenter(autorecenter, blocking=blocking, which_window=self.which_window)
271
+
272
+ def set_background_color(self, background_color, blocking=False):
273
+ self.parent_window.set_background_color(background_color, blocking=blocking, which_window=self.which_window)
274
+
275
+ def save_snapshot(self, path, blocking=False):
276
+ self.parent_window.save_snapshot(path, blocking=blocking, which_window=self.which_window)
277
+
278
+ def get_event(self):
279
+ return self.parent_window.get_event()
280
+
281
+ def get_keypress(self):
282
+ return self.parent_window.get_keypress()['key']
283
+
284
+ def get_mouseclick(self):
285
+ return self.parent_window.get_mouseclick()
286
+
287
+ def close(self):
288
+ self.parent_window.p.terminate()
289
+
290
+ background_color = property(fset=set_background_color, doc="Background color, as 3-element numpy array where 0 <= color <= 1.0.")
291
+ dynamic_meshes = property(fset=set_dynamic_meshes, doc="List of meshes for dynamic display.")
292
+ static_meshes = property(fset=set_static_meshes, doc="List of meshes for static display.")
293
+ dynamic_models = property(fset=set_dynamic_models, doc="List of model names and parameters for dynamic display.")
294
+ dynamic_lines = property(fset=set_dynamic_lines, doc="List of Lines for dynamic display.")
295
+ static_lines = property(fset=set_static_lines, doc="List of Lines for static display.")
296
+ titlebar = property(fset=set_titlebar, doc="Titlebar string.")
297
+ lighting_on = property(fset=set_lighting_on, doc="Titlebar string.")
298
+
299
+
300
+ class MeshViewerLocal(object):
301
+ """Proxy viewer instance for visual inspection of geometric primitives.
302
+
303
+ The lass forks another python process holding the display. It communicates
304
+ the commands with the remote instance seemlessly.
305
+
306
+ Write-only attributes:
307
+
308
+ :param titlebar: string printed in the window titlebar
309
+ :param dynamic_meshes: list of Mesh objects to be displayed
310
+ :param static_meshes: list of Mesh objects to be displayed
311
+ :param dynamic_lines: list of Lines objects to be displayed
312
+ :param static_lines: list of Lines objects to be displayed
313
+
314
+ .. note::
315
+
316
+ `static_meshes` is meant for Meshes that are
317
+ updated infrequently, and dynamic_meshes is for Meshes
318
+ that are updated frequently (same for dynamic_lines vs
319
+ static_lines). They may be treated differently for
320
+ performance reasons.
321
+
322
+ """
323
+
324
+ managed = {}
325
+
326
+ def __new__(cls, titlebar, uid, shape, keepalive, window_width, window_height):
327
+ assert(uid is None or isinstance(uid, str))
328
+
329
+ if uid == 'stack':
330
+ uid = ''.join(traceback.format_list(traceback.extract_stack()))
331
+ if uid and uid in MeshViewer.managed.keys():
332
+ return MeshViewer.managed[uid]
333
+
334
+ result = super(MeshViewerLocal, cls).__new__(cls)
335
+
336
+ result.client = zmq.Context.instance().socket(zmq.PUSH)
337
+ result.client.linger = 0
338
+
339
+ with open(os.devnull) as dev_null, \
340
+ tempfile.TemporaryFile() as err:
341
+
342
+ result.p = _run_self([titlebar, str(shape[0]), str(shape[1]), str(window_width), str(window_height)],
343
+ stdin=dev_null,
344
+ stdout=subprocess.PIPE,
345
+ stderr=err)
346
+
347
+ line = result.p.stdout.readline().decode()
348
+ result.p.stdout.close()
349
+ current_port = re.match('<PORT>(.*?)</PORT>', line)
350
+ if not current_port:
351
+ raise Exception("MeshViewer remote appears to have failed to launch")
352
+ current_port = int(current_port.group(1))
353
+ result.client.connect('tcp://127.0.0.1:%d' % (current_port))
354
+
355
+ if uid:
356
+ MeshViewerLocal.managed[uid] = result
357
+ result.shape = shape
358
+ result.keepalive = keepalive
359
+ return result
360
+
361
+ def get_subwindows(self):
362
+ return [[MeshSubwindow(parent_window=self, which_window=(r, c)) for c in range(self.shape[1])] for r in range(self.shape[0])]
363
+
364
+ @staticmethod
365
+ def _sanitize_meshes(list_of_meshes):
366
+ lm = []
367
+
368
+ # have to copy the meshes for now, because some contain CPython members,
369
+ # before pushing them on the queue
370
+ for m in list_of_meshes:
371
+ if hasattr(m, 'fc'):
372
+ lm.append(Mesh(v=m.v, f=m.f, fc=m.fc))
373
+ elif hasattr(m, 'vc'):
374
+ lm.append(Mesh(v=m.v, f=m.f, vc=m.vc))
375
+ else:
376
+ lm.append(Mesh(v=m.v, f=m.f if hasattr(m, 'f') else []))
377
+
378
+ if hasattr(m, 'vn'):
379
+ lm[-1].vn = m.vn
380
+ if hasattr(m, 'fn'):
381
+ lm[-1].fn = m.fn
382
+
383
+ if hasattr(m, 'v_to_text'):
384
+ lm[-1].v_to_text = m.v_to_text
385
+ if hasattr(m, 'texture_filepath') and hasattr(m, 'vt') and hasattr(m, 'ft'):
386
+ lm[-1].texture_filepath = m.texture_filepath
387
+ lm[-1].vt = m.vt
388
+ lm[-1].ft = m.ft
389
+
390
+ return lm
391
+
392
+ def _send_pyobj(self, label, obj, blocking, which_window):
393
+ if blocking:
394
+ context = zmq.Context.instance()
395
+ server = context.socket(zmq.PULL)
396
+ server.linger = 0
397
+ port = server.bind_to_random_port('tcp://127.0.0.1',
398
+ min_port=49152,
399
+ max_port=65535,
400
+ max_tries=100000)
401
+ # sending with blocking'
402
+ self.client.send_pyobj({'label': label,
403
+ 'obj': obj,
404
+ 'port': port,
405
+ 'which_window': which_window})
406
+ task_completion_time = server.recv_pyobj()
407
+ # task completion time was %.2fs in other process' % (task_completion_time,)
408
+ server.close()
409
+ else:
410
+ # sending nonblocking
411
+ self.client.send_pyobj({'label': label,
412
+ 'obj': obj,
413
+ 'which_window': which_window})
414
+
415
+ def set_dynamic_meshes(self, list_of_meshes, blocking=False, which_window=(0, 0)):
416
+ self._send_pyobj('dynamic_meshes', self._sanitize_meshes(list_of_meshes), blocking, which_window)
417
+
418
+ def set_static_meshes(self, list_of_meshes, blocking=False, which_window=(0, 0)):
419
+ self._send_pyobj('static_meshes', self._sanitize_meshes(list_of_meshes), blocking, which_window)
420
+
421
+ # list_of_model_names_and_parameters should be of form [{'name': scape_model_name, 'parameters': scape_model_parameters}]
422
+ # here scape_model_name is the filepath of the scape model.
423
+ def set_dynamic_models(self, list_of_model_names_and_parameters, blocking=False, which_window=(0, 0)):
424
+ self._send_pyobj('dynamic_models', list_of_model_names_and_parameters, blocking, which_window)
425
+
426
+ def set_dynamic_lines(self, list_of_lines, blocking=False, which_window=(0, 0)):
427
+ self._send_pyobj('dynamic_lines', list_of_lines, blocking, which_window)
428
+
429
+ def set_static_lines(self, list_of_lines, blocking=False, which_window=(0, 0)):
430
+ self._send_pyobj('static_lines', list_of_lines, blocking, which_window)
431
+
432
+ def set_titlebar(self, titlebar, blocking=False, which_window=(0, 0)):
433
+ self._send_pyobj('titlebar', titlebar, blocking, which_window)
434
+
435
+ def set_lighting_on(self, lighting_on, blocking=False, which_window=(0, 0)):
436
+ self._send_pyobj('lighting_on', lighting_on, blocking, which_window)
437
+
438
+ def set_autorecenter(self, autorecenter, blocking=False, which_window=(0, 0)):
439
+ self._send_pyobj('autorecenter', autorecenter, blocking, which_window)
440
+
441
+ def set_background_color(self, background_color, blocking=False, which_window=(0, 0)):
442
+ assert(isinstance(background_color, np.ndarray))
443
+ assert(background_color.size == 3)
444
+ self._send_pyobj('background_color', background_color.flatten(), blocking, which_window)
445
+
446
+ def get_keypress(self):
447
+ return self.get_ui_event('get_keypress')
448
+
449
+ def get_mouseclick(self):
450
+ """Returns a mouse click event.
451
+
452
+ .. note::
453
+
454
+ the call is blocking the caller until an event is received
455
+ """
456
+ return self.get_ui_event('get_mouseclick')
457
+
458
+ def get_event(self):
459
+ return self.get_ui_event('get_event')
460
+
461
+ def get_ui_event(self, event_id):
462
+ context = zmq.Context.instance()
463
+ server = context.socket(zmq.PULL)
464
+ server.linger = 0
465
+ port = server.bind_to_random_port('tcp://127.0.0.1',
466
+ min_port=49152,
467
+ max_port=65535,
468
+ max_tries=100000)
469
+ self._send_pyobj(event_id, port, blocking=True, which_window=(0, 0))
470
+ result = server.recv_pyobj()
471
+ server.close()
472
+ return result
473
+
474
+ background_color = property(fset=set_background_color,
475
+ doc="Background color, as 3-element numpy array where 0 <= color <= 1.0.")
476
+
477
+ dynamic_meshes = property(fset=set_dynamic_meshes,
478
+ doc="List of meshes for dynamic display.")
479
+ static_meshes = property(fset=set_static_meshes,
480
+ doc="List of meshes for static display.")
481
+ dynamic_models = property(fset=set_dynamic_models,
482
+ doc="List of model names and parameters for dynamic display.")
483
+
484
+ dynamic_lines = property(fset=set_dynamic_lines,
485
+ doc="List of Lines for dynamic display.")
486
+ static_lines = property(fset=set_static_lines,
487
+ doc="List of Lines for static display.")
488
+
489
+ titlebar = property(fset=set_titlebar,
490
+ doc="Titlebar string.")
491
+
492
+ def save_snapshot(self, path, blocking=False, which_window=(0, 0)):
493
+ """Saves a snapshot of the current window into the specified file
494
+
495
+ :param path: filename to which the current window content will be saved
496
+ """
497
+ self._send_pyobj('save_snapshot', path, blocking, which_window)
498
+
499
+ def __del__(self):
500
+ if not self.keepalive:
501
+ self.p.terminate()
502
+
503
+
504
+ class MeshViewerSingle(object):
505
+
506
+ def __init__(self, x1_pct, y1_pct, width_pct, height_pct):
507
+ assert(width_pct <= 1)
508
+ assert(height_pct <= 1)
509
+ self.dynamic_meshes = []
510
+ self.static_meshes = []
511
+ self.dynamic_models = []
512
+ self.dynamic_lines = []
513
+ self.static_lines = []
514
+ self.lighting_on = True
515
+ self.scape_models = {}
516
+ self.x1_pct = x1_pct
517
+ self.y1_pct = y1_pct
518
+ self.width_pct = width_pct
519
+ self.height_pct = height_pct
520
+ self.autorecenter = True
521
+
522
+ def get_dimensions(self):
523
+ d = {}
524
+ d['window_width'] = glutGet(GLUT_WINDOW_WIDTH)
525
+ d['window_height'] = glutGet(GLUT_WINDOW_HEIGHT)
526
+ d['subwindow_width'] = self.width_pct * d['window_width']
527
+ d['subwindow_height'] = self.height_pct * d['window_height']
528
+ d['subwindow_origin_x'] = self.x1_pct * d['window_width']
529
+ d['subwindow_origin_y'] = self.y1_pct * d['window_height']
530
+ return d
531
+
532
+ def on_draw(self, transform, want_camera=False):
533
+
534
+ d = self.get_dimensions()
535
+
536
+ glViewport(
537
+ int(d['subwindow_origin_x']),
538
+ int(d['subwindow_origin_y']),
539
+ int(d['subwindow_width']),
540
+ int(d['subwindow_height']))
541
+
542
+ glMatrixMode(GL_PROJECTION)
543
+ glLoadIdentity()
544
+
545
+ fov_degrees = 45.
546
+ near = 1.0
547
+ far = 100.
548
+ ratio = float(d['subwindow_width']) / float(d['subwindow_height'])
549
+ if d['subwindow_width'] < d['subwindow_height']:
550
+ xt = np.tan(fov_degrees * np.pi / 180. / 2.0) * near
551
+ yt = xt / ratio
552
+ glFrustum(-xt, xt, -yt, yt, near, far)
553
+ else:
554
+ gluPerspective(fov_degrees, ratio, near, far)
555
+
556
+ glMatrixMode(GL_MODELVIEW)
557
+ glLoadIdentity()
558
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
559
+
560
+ glTranslatef(0.0, 0.0, -6.0)
561
+ # glTranslatef(0.0,0.0,-3.5)
562
+
563
+ glPushMatrix()
564
+ glMultMatrixf(transform)
565
+ glColor3f(1.0, 0.75, 0.75)
566
+
567
+ if self.autorecenter:
568
+ camera = self.draw_primitives_recentered(want_camera=want_camera)
569
+ else:
570
+ if hasattr(self, 'current_center') and hasattr(self, 'current_scalefactor'):
571
+ camera = self.draw_primitives(scalefactor=self.current_scalefactor, center=self.current_center)
572
+ else:
573
+ camera = self.draw_primitives(want_camera=want_camera)
574
+
575
+ glPopMatrix()
576
+
577
+ if want_camera:
578
+ return camera
579
+
580
+ def draw_primitives_recentered(self, want_camera=False):
581
+ return self.draw_primitives(recenter=True, want_camera=want_camera)
582
+
583
+ @staticmethod
584
+ def set_shaders(m):
585
+ VERTEX_SHADER = shaders.compileShader("""void main() {
586
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
587
+ }""", GL_VERTEX_SHADER)
588
+ FRAGMENT_SHADER = shaders.compileShader("""void main() {
589
+ gl_FragColor = vec4( 0, 1, 0, 1 );
590
+ }""", GL_FRAGMENT_SHADER)
591
+ m.shaders = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)
592
+
593
+ @staticmethod
594
+ def set_texture(m):
595
+ texture_data = np.array(m.texture_image, dtype='int8')
596
+ m.textureID = glGenTextures(1)
597
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
598
+ glBindTexture(GL_TEXTURE_2D, m.textureID)
599
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_data.shape[1], texture_data.shape[0], 0, GL_BGR, GL_UNSIGNED_BYTE, texture_data.flatten())
600
+ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST) # must be GL_FASTEST, GL_NICEST or GL_DONT_CARE
601
+ glGenerateMipmap(GL_TEXTURE_2D)
602
+
603
+ @staticmethod
604
+ def draw_mesh(m, lighting_on):
605
+
606
+ # Supply vertices
607
+ glEnableClientState(GL_VERTEX_ARRAY)
608
+ m.vbo['v'].bind()
609
+ glVertexPointer(3, GL_FLOAT, 0, m.vbo['v'])
610
+ m.vbo['v'].unbind()
611
+
612
+ # Supply normals
613
+ if 'vn' in m.vbo.keys():
614
+ glEnableClientState(GL_NORMAL_ARRAY)
615
+ m.vbo['vn'].bind()
616
+ glNormalPointer(GL_FLOAT, 0, m.vbo['vn'])
617
+ m.vbo['vn'].unbind()
618
+ else:
619
+ glDisableClientState(GL_NORMAL_ARRAY)
620
+
621
+ # Supply colors
622
+ if 'vc' in m.vbo.keys():
623
+ glEnableClientState(GL_COLOR_ARRAY)
624
+ m.vbo['vc'].bind()
625
+ glColorPointer(3, GL_FLOAT, 0, m.vbo['vc'])
626
+ m.vbo['vc'].unbind()
627
+ else:
628
+ glDisableClientState(GL_COLOR_ARRAY)
629
+
630
+ if ('vt' in m.vbo.keys()) and hasattr(m, 'textureID'):
631
+ glEnable(GL_TEXTURE_2D)
632
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
633
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
634
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
635
+ glBindTexture(GL_TEXTURE_2D, m.textureID)
636
+
637
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY)
638
+ m.vbo['vt'].bind()
639
+ glTexCoordPointer(2, GL_FLOAT, 0, m.vbo['vt'])
640
+ m.vbo['vt'].unbind()
641
+ else:
642
+ glDisable(GL_TEXTURE_2D)
643
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY)
644
+
645
+ # Draw
646
+ if len(m.f) > 0:
647
+ # ie if it is triangulated
648
+ if lighting_on:
649
+ glEnable(GL_LIGHTING)
650
+ else:
651
+ glDisable(GL_LIGHTING)
652
+ glDrawElementsui(GL_TRIANGLES, np.arange(m.f.size, dtype=np.uint32))
653
+ else:
654
+ # not triangulated, so disable lighting
655
+ glDisable(GL_LIGHTING)
656
+ glPointSize(2)
657
+ glDrawElementsui(GL_POINTS, np.arange(len(m.v), dtype=np.uint32))
658
+ if hasattr(m, 'v_to_text'):
659
+
660
+ glEnable(GL_TEXTURE_2D)
661
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
662
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
663
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
664
+
665
+ # glEnable(GL_TEXTURE_GEN_S)
666
+ # glEnable(GL_TEXTURE_GEN_T)
667
+ # glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
668
+ # glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
669
+
670
+ bgcolor = np.array(glGetDoublev(GL_COLOR_CLEAR_VALUE))
671
+ fgcolor = 1. - bgcolor
672
+
673
+ from .lines import Lines
674
+ sc = float(np.max(np.max(m.v, axis=0) - np.min(m.v, axis=0))) / 10.
675
+
676
+ cur_mtx = np.linalg.pinv(glGetFloatv(GL_MODELVIEW_MATRIX).T)
677
+ xdir = cur_mtx[:3, 0]
678
+ ydir = cur_mtx[:3, 1]
679
+
680
+ glEnable(GL_LINE_SMOOTH)
681
+ glEnable(GL_BLEND)
682
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
683
+
684
+ for vidx, text in m.v_to_text.items():
685
+ pos0 = m.v[vidx].copy()
686
+ pos1 = m.v[vidx].copy()
687
+ if hasattr(m, 'vn'):
688
+ pos1 += m.vn[vidx] * sc
689
+ glLineWidth(5.0)
690
+ ln = Lines(v=np.vstack((pos0, pos1)), e=np.array([[0, 1]]))
691
+ glEnable(GL_LIGHTING)
692
+ glColor3f(1. - 0.8, 1. - 0.8, 1. - 1.00)
693
+ MeshViewerSingle.draw_lines(ln)
694
+
695
+ glDisable(GL_LIGHTING)
696
+
697
+ texture_id = get_textureid_with_text(text, bgcolor, fgcolor)
698
+ glBindTexture(GL_TEXTURE_2D, texture_id)
699
+
700
+ glPushMatrix()
701
+ glTranslatef(pos1[0], pos1[1], pos1[2])
702
+
703
+ dx = xdir * .10
704
+ dy = ydir * .10
705
+ if False:
706
+ glBegin(GL_QUADS)
707
+
708
+ glTexCoord2f(1., 0.)
709
+ glVertex3f(*(+dx + dy))
710
+
711
+ glTexCoord2f(1., 1.)
712
+ glVertex3f(*(+dx - dy))
713
+
714
+ glTexCoord2f(0., 1.)
715
+ glVertex3f(*(-dx - dy))
716
+
717
+ glTexCoord2f(0., 0.)
718
+ glVertex3f(*(-dx + dy))
719
+
720
+ # gluSphere(quadratic,0.05,32,32)
721
+ glEnd()
722
+ else:
723
+ glBegin(GL_POLYGON)
724
+
725
+ for r in np.arange(0, np.pi * 2., .01):
726
+ glTexCoord2f(np.cos(r) / 2. + .5, np.sin(r) / 2. + .5)
727
+ glVertex3f(*(dx * np.cos(r) + -dy * np.sin(r)))
728
+
729
+ glEnd()
730
+ glPopMatrix()
731
+
732
+ #
733
+ # glColor3f(bgcolor[0], bgcolor[1], bgcolor[2])
734
+ # glRasterPos3f(pos1[0], pos1[1], pos1[2])
735
+ # # print pos0
736
+ # # print pos1
737
+ #
738
+ #
739
+ # for t in text:
740
+ # GLUT.glutBitmapCharacter(GLUT.GLUT_BITMAP_HELVETICA_18, ord(t))
741
+
742
+ @staticmethod
743
+ def draw_lines(ls):
744
+ glDisableClientState(GL_NORMAL_ARRAY)
745
+ glEnableClientState(GL_VERTEX_ARRAY)
746
+ glLineWidth(3.0)
747
+ allpts = ls.v[ls.e.flatten()].astype(np.float32)
748
+ glVertexPointerf(allpts)
749
+ if hasattr(ls, 'vc') or hasattr(ls, 'ec'):
750
+ glEnableClientState(GL_COLOR_ARRAY)
751
+ if hasattr(ls, 'vc'):
752
+ glColorPointerf(ls.vc[ls.e.flatten()].astype(np.float32))
753
+ else:
754
+ clrs = np.ones((ls.e.shape[0] * 2, 3)) * np.repeat(ls.ec, 2, axis=0)
755
+ glColorPointerf(clrs)
756
+ else:
757
+ glDisableClientState(GL_COLOR_ARRAY)
758
+
759
+ glDisable(GL_LIGHTING)
760
+ glDrawElementsui(GL_LINES, np.arange(len(allpts), dtype=np.uint32))
761
+
762
+ def draw_primitives(self,
763
+ scalefactor=1.0,
764
+ center=[0.0, 0.0, 0.0],
765
+ recenter=False,
766
+ want_camera=False):
767
+
768
+ # measure the bounding box of all our primitives, so that we can
769
+ # recenter them in our field of view
770
+ if recenter:
771
+ all_meshes = self.static_meshes + self.dynamic_meshes
772
+ all_lines = self.static_lines + self.dynamic_lines
773
+
774
+ if (len(all_meshes) + len(all_lines)) == 0:
775
+ if want_camera:
776
+ return {'modelview_matrix': glGetDoublev(GL_MODELVIEW_MATRIX),
777
+ 'projection_matrix': glGetDoublev(GL_PROJECTION_MATRIX),
778
+ 'viewport': glGetIntegerv(GL_VIEWPORT)
779
+ }
780
+ else:
781
+ return None
782
+
783
+ for m in all_meshes:
784
+ m.v = m.v.reshape((-1, 3))
785
+
786
+ all_verts = np.concatenate(
787
+ [m.v[m.f.flatten() if len(m.f) > 0 else np.arange(len(m.v))] for m in all_meshes] +
788
+ [l.v[l.e.flatten()] for l in all_lines],
789
+ axis=0)
790
+
791
+ maximum = np.max(all_verts, axis=0)
792
+ minimum = np.min(all_verts, axis=0)
793
+ center = (maximum + minimum) / 2.
794
+ scalefactor = (maximum - minimum) / 4.
795
+ scalefactor = np.max(scalefactor)
796
+ else:
797
+ center = np.array(center)
798
+ # for mesh in self.dynamic_meshes :
799
+ # if mesh.f : mesh.reset_normals()
800
+ all_meshes = self.static_meshes + self.dynamic_meshes
801
+ all_lines = self.static_lines + self.dynamic_lines
802
+ self.current_center = center
803
+ self.current_scalefactor = scalefactor
804
+
805
+ glMatrixMode(GL_MODELVIEW)
806
+ glPushMatrix()
807
+ # uncomment to add a default rotation (useful when automatically snapshoting kinect data
808
+ # glRotate(220, 0.0, 1.0, 0.0)
809
+
810
+ tf = np.identity(4, 'f') / scalefactor
811
+ tf[:3, 3] = -center / scalefactor
812
+ tf[3, 3] = 1
813
+ cur_mtx = glGetFloatv(GL_MODELVIEW_MATRIX).T
814
+
815
+ glLoadMatrixf(cur_mtx.dot(tf).T)
816
+
817
+ if want_camera:
818
+ result = {'modelview_matrix': glGetDoublev(GL_MODELVIEW_MATRIX),
819
+ 'projection_matrix': glGetDoublev(GL_PROJECTION_MATRIX),
820
+ 'viewport': glGetIntegerv(GL_VIEWPORT)
821
+ }
822
+ else:
823
+ result = None
824
+
825
+ for m in all_meshes:
826
+ if not hasattr(m, 'vbo'):
827
+ # Precompute vertex vbo
828
+ fidxs = m.f.flatten() if len(m.f) > 0 else np.arange(len(m.v))
829
+ allpts = m.v[fidxs].astype(np.float32).flatten()
830
+ vbo = OpenGL.arrays.vbo.VBO(allpts)
831
+ m.vbo = {'v': vbo}
832
+
833
+ # Precompute normals vbo
834
+ if hasattr(m, 'vn'):
835
+ ns = m.vn.astype(np.float32)
836
+ ns = ns[m.f.flatten(), :]
837
+ m.vbo['vn'] = OpenGL.arrays.vbo.VBO(ns.flatten())
838
+ elif hasattr(m, 'f') and m.f.size > 0:
839
+ ns = TriNormals(m.v, m.f).reshape(-1, 3)
840
+ ns = np.tile(ns, (1, 3)).reshape(-1, 3).astype(np.float32)
841
+ m.vbo['vn'] = OpenGL.arrays.vbo.VBO(ns.flatten())
842
+
843
+ # Precompute texture vbo
844
+ if hasattr(m, 'ft') and (m.ft.size > 0):
845
+ ftidxs = m.ft.flatten()
846
+ data = m.vt[ftidxs].astype(np.float32)[:, 0:2]
847
+ data[:, 1] = 1.0 - 1.0 * data[:, 1]
848
+ m.vbo['vt'] = OpenGL.arrays.vbo.VBO(data)
849
+
850
+ # Precompute color vbo
851
+ if hasattr(m, 'vc'):
852
+ data = m.vc[fidxs].astype(np.float32)
853
+ m.vbo['vc'] = OpenGL.arrays.vbo.VBO(data)
854
+ elif hasattr(m, 'fc'):
855
+ data = np.tile(m.fc, (1, 3)).reshape(-1, 3).astype(np.float32)
856
+ m.vbo['vc'] = OpenGL.arrays.vbo.VBO(data)
857
+
858
+ for e in all_lines:
859
+ self.draw_lines(e)
860
+
861
+ for m in all_meshes:
862
+ if hasattr(m, 'texture_image') and not hasattr(m, 'textureID'):
863
+ self.set_texture(m)
864
+ self.draw_mesh(m, self.lighting_on)
865
+
866
+ glMatrixMode(GL_MODELVIEW)
867
+ glPopMatrix()
868
+
869
+ return result
870
+
871
+
872
+ class MeshViewerRemote(object):
873
+
874
+ def __init__(self,
875
+ titlebar='Mesh Viewer',
876
+ subwins_vert=1,
877
+ subwins_horz=1,
878
+ width=100,
879
+ height=100):
880
+
881
+ context = zmq.Context.instance()
882
+ self.server = context.socket(zmq.PULL)
883
+ self.server.linger = 0
884
+
885
+ # Find a port to use. The standard set of "private" ports is 49152 through 65535, as seen in...
886
+ # http://en.wikipedia.org/wiki/Port_(computer_networking)
887
+ port = self.server.bind_to_random_port('tcp://127.0.0.1',
888
+ min_port=49152,
889
+ max_port=65535,
890
+ max_tries=100000)
891
+
892
+ # Print out our port so that our client can connect to us with it. Flush stdout immediately; otherwise
893
+ # our client could wait forever.
894
+ print('<PORT>%d</PORT>\n' % (port,))
895
+ sys.stdout.flush()
896
+
897
+ self.arcball = ArcBallT(width, height)
898
+ self.transform = Matrix4fT()
899
+ self.lastrot = Matrix3fT()
900
+ self.thisrot = Matrix3fT()
901
+ self.isdragging = False
902
+ self.need_redraw = True
903
+
904
+ self.mesh_viewers = [[MeshViewerSingle(float(c) / (subwins_horz),
905
+ float(r) / (subwins_vert),
906
+ 1. / subwins_horz,
907
+ 1. / subwins_vert) for c in range(subwins_horz)] for r in range(subwins_vert)]
908
+
909
+ self.tm_for_fps = 0.
910
+ self.titlebar = titlebar
911
+ self.activate(width, height)
912
+
913
+ def snapshot(self, path):
914
+ """
915
+ Takes a snapshot of the meshviewer window and saves it to disc.
916
+
917
+ :param path: path to save the snapshot at.
918
+
919
+ .. note:: Requires the Pillow package to be installed.
920
+
921
+ """
922
+ from PIL import Image
923
+ from OpenGL.GLU import GLubyte
924
+
925
+ self.on_draw()
926
+
927
+ x = 0
928
+ y = 0
929
+ width = glutGet(GLUT_WINDOW_WIDTH)
930
+ height = glutGet(GLUT_WINDOW_HEIGHT)
931
+
932
+ data = (GLubyte * (3 * width * height))(0)
933
+ glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, data)
934
+ image = Image.frombytes(mode="RGB", size=(width, height), data=data)
935
+ image = image.transpose(Image.FLIP_TOP_BOTTOM)
936
+
937
+ # Save image to disk
938
+ image.save(path)
939
+
940
+ def activate(self, width, height):
941
+ glutInit(['mesh_viewer'])
942
+ glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
943
+ glutInitWindowSize(width, height)
944
+ glutInitWindowPosition(0, 0)
945
+ self.root_window_id = glutCreateWindow(self.titlebar)
946
+ glutDisplayFunc(self.on_draw)
947
+
948
+ glutTimerFunc(100, self.checkQueue, 0)
949
+ glutReshapeFunc(self.on_resize_window)
950
+
951
+ glutKeyboardFunc(self.on_keypress)
952
+ glutMouseFunc(self.on_click)
953
+ glutMotionFunc(self.on_drag)
954
+
955
+ # for r, lst in enumerate(self.mesh_viewers):
956
+ # for c, mv in enumerate(lst):
957
+ # mv.glut_window_id = glutCreateSubWindow(self.root_window_id, c*width/len(lst), r*height/len(self.mesh_viewers), width/len(lst), height/len(self.mesh_viewers))
958
+
959
+ glutDisplayFunc(self.on_draw)
960
+ self.init_opengl()
961
+
962
+ glutMainLoop() # won't return until process is killed
963
+
964
+ def on_drag(self, cursor_x, cursor_y):
965
+ """ Mouse cursor is moving
966
+ Glut calls this function (when mouse button is down)
967
+ and pases the mouse cursor postion in window coords as the mouse moves.
968
+ """
969
+ from .geometry.rodrigues import rodrigues
970
+ if (self.isdragging):
971
+ mouse_pt = Point2fT(cursor_x, cursor_y)
972
+ ThisQuat = self.arcball.drag(mouse_pt) # // Update End Vector And Get Rotation As Quaternion
973
+ self.thisrot = Matrix3fSetRotationFromQuat4f(ThisQuat) # // Convert Quaternion Into Matrix3fT
974
+ # Use correct Linear Algebra matrix multiplication C = A * B
975
+ self.thisrot = Matrix3fMulMatrix3f(self.lastrot, self.thisrot) # // Accumulate Last Rotation Into This One
976
+
977
+ # make sure it is a rotation
978
+ self.thisrot = rodrigues(rodrigues(self.thisrot)[0])[0]
979
+ self.transform = Matrix4fSetRotationFromMatrix3f(self.transform, self.thisrot) # // Set Our Final Transform's Rotation From This One
980
+ glutPostRedisplay()
981
+ return
982
+
983
+ # The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
984
+ def on_keypress(self, *args):
985
+ key = args[0]
986
+ if hasattr(self, 'event_port'):
987
+ self.keypress_port = self.event_port
988
+ del self.event_port
989
+ if hasattr(self, 'keypress_port'):
990
+ client = zmq.Context.instance().socket(zmq.PUSH)
991
+ client.connect('tcp://127.0.0.1:%d' % (self.keypress_port))
992
+ client.send_pyobj({'event_type': 'keyboard', 'key': key})
993
+ del self.keypress_port
994
+
995
+ def on_click(self, button, button_state, cursor_x, cursor_y):
996
+ """ Mouse button clicked.
997
+ Glut calls this function when a mouse button is
998
+ clicked or released.
999
+ """
1000
+
1001
+ self.isdragging = False
1002
+ # if (button == GLUT_RIGHT_BUTTON and button_state == GLUT_UP):
1003
+ # # Right button click
1004
+ # self.lastrot = Matrix3fSetIdentity (); # // Reset Rotation
1005
+ # self.thisrot = Matrix3fSetIdentity (); # // Reset Rotation
1006
+ # self.transform = Matrix4fSetRotationFromMatrix3f (self.transform, self.thisrot); # // Reset Rotation
1007
+ if (button == GLUT_LEFT_BUTTON and button_state == GLUT_UP):
1008
+ # Left button released
1009
+ self.lastrot = copy.copy(self.thisrot) # Set Last Static Rotation To Last Dynamic One
1010
+
1011
+ elif (button == GLUT_LEFT_BUTTON and button_state == GLUT_DOWN):
1012
+ # Left button clicked down
1013
+ self.lastrot = copy.copy(self.thisrot) # Set Last Static Rotation To Last Dynamic One
1014
+ self.isdragging = True # // Prepare For Dragging
1015
+ mouse_pt = Point2fT(cursor_x, cursor_y)
1016
+ self.arcball.click(mouse_pt) # Update Start Vector And Prepare For Dragging
1017
+
1018
+ elif (button == GLUT_RIGHT_BUTTON and button_state == GLUT_DOWN):
1019
+ # If a mouse click location was requested, return it to caller
1020
+ if hasattr(self, 'event_port'):
1021
+ self.mouseclick_port = self.event_port
1022
+ del self.event_port
1023
+ if hasattr(self, 'mouseclick_port'):
1024
+ self.send_mouseclick_to_caller(cursor_x, cursor_y)
1025
+
1026
+ elif (button == GLUT_MIDDLE_BUTTON and button_state == GLUT_DOWN):
1027
+ # If a mouse click location was requested, return it to caller
1028
+ if hasattr(self, 'event_port'):
1029
+ self.mouseclick_port = self.event_port
1030
+ del self.event_port
1031
+ if hasattr(self, 'mouseclick_port'):
1032
+ self.send_mouseclick_to_caller(cursor_x, cursor_y, button='middle')
1033
+
1034
+ glutPostRedisplay()
1035
+
1036
+ def send_mouseclick_to_caller(self,
1037
+ cursor_x,
1038
+ cursor_y,
1039
+ button='right'):
1040
+
1041
+ client = zmq.Context.instance().socket(zmq.PUSH)
1042
+ client.connect('tcp://127.0.0.1:%d' % (self.mouseclick_port))
1043
+ cameras = self.on_draw(want_cameras=True)
1044
+
1045
+ window_height = glutGet(GLUT_WINDOW_HEIGHT)
1046
+ depth_value = glReadPixels(cursor_x, window_height - cursor_y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)
1047
+
1048
+ pyobj = {
1049
+ 'event_type': 'mouse_click_%sbutton' % button,
1050
+ 'u': None, 'v': None,
1051
+ 'x': None, 'y': None, 'z': None,
1052
+ 'subwindow_row': None,
1053
+ 'subwindow_col': None
1054
+ }
1055
+
1056
+ for subwin_row, camera_list in enumerate(cameras):
1057
+ for subwin_col, camera in enumerate(camera_list):
1058
+
1059
+ # test for out-of-bounds
1060
+ if cursor_x < camera['viewport'][0]:
1061
+ continue
1062
+ if cursor_x > (camera['viewport'][0] + camera['viewport'][2]):
1063
+ continue
1064
+ if window_height - cursor_y < camera['viewport'][1]:
1065
+ continue
1066
+ if window_height - cursor_y > (camera['viewport'][1] + camera['viewport'][3]):
1067
+ continue
1068
+
1069
+ xx, yy, zz = gluUnProject(
1070
+ cursor_x, window_height - cursor_y, depth_value,
1071
+ camera['modelview_matrix'],
1072
+ camera['projection_matrix'],
1073
+ camera['viewport'])
1074
+
1075
+ pyobj = {
1076
+ 'event_type': 'mouse_click_%sbutton' % button,
1077
+ 'u': cursor_x - camera['viewport'][0], 'v': window_height - cursor_y - camera['viewport'][1],
1078
+ 'x': xx, 'y': yy, 'z': zz,
1079
+ 'which_subwindow': (subwin_row, subwin_col)
1080
+ }
1081
+
1082
+ client.send_pyobj(pyobj)
1083
+ del self.mouseclick_port
1084
+
1085
+ def on_draw(self, want_cameras=False):
1086
+ # sys.stderr.write('fps: %.2e\n' % (1. / (time.time() - self.tm_for_fps)))
1087
+ self.tm_for_fps = time.time()
1088
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
1089
+ cameras = []
1090
+ for mvl in self.mesh_viewers:
1091
+ cameras.append([])
1092
+ for mv in mvl:
1093
+ cameras[-1].append(mv.on_draw(self.transform, want_cameras))
1094
+ glFlush() # Flush The GL Rendering Pipeline
1095
+ glutSwapBuffers()
1096
+ self.need_redraw = False
1097
+ if want_cameras:
1098
+ return cameras
1099
+
1100
+ def on_resize_window(self, Width, Height):
1101
+ """Reshape The Window When It's Moved Or Resized"""
1102
+ self.arcball.setBounds(Width, Height) # //*NEW* Update mouse bounds for arcball
1103
+ return
1104
+
1105
+ def handle_request(self, request):
1106
+ label = request['label']
1107
+ obj = request['obj']
1108
+ w = request['which_window']
1109
+ mv = self.mesh_viewers[w[0]][w[1]]
1110
+
1111
+ # Handle each type of request.
1112
+ # Some requests require a redraw, and
1113
+ # some don't.
1114
+ if label == 'dynamic_meshes':
1115
+ mv.dynamic_meshes = obj
1116
+ self.need_redraw = True
1117
+ elif label == 'dynamic_models':
1118
+ mv.dynamic_models = obj
1119
+ self.need_redraw = True
1120
+ elif label == 'static_meshes':
1121
+ mv.static_meshes = obj
1122
+ self.need_redraw = True
1123
+ elif label == 'dynamic_lines':
1124
+ mv.dynamic_lines = obj
1125
+ self.need_redraw = True
1126
+ elif label == 'static_lines':
1127
+ mv.static_lines = obj
1128
+ self.need_redraw = True
1129
+ elif label == 'autorecenter':
1130
+ mv.autorecenter = obj
1131
+ self.need_redraw = True
1132
+ elif label == 'titlebar':
1133
+ assert(isinstance(obj, str))
1134
+ self.titlebar = obj
1135
+ glutSetWindowTitle(obj)
1136
+ elif label == 'lighting_on':
1137
+ mv.lighting_on = obj
1138
+ self.need_redraw = True
1139
+ elif label == 'background_color':
1140
+ glClearColor(obj[0], obj[1], obj[2], 1.0)
1141
+ self.need_redraw = True
1142
+ elif label == 'save_snapshot': # redraws for itself
1143
+ assert(isinstance(obj, str))
1144
+ self.snapshot(obj)
1145
+ elif label == 'get_keypress':
1146
+ self.keypress_port = obj
1147
+ elif label == 'get_mouseclick':
1148
+ self.mouseclick_port = obj
1149
+ elif label == 'get_event':
1150
+ self.event_port = obj
1151
+ else:
1152
+ return False # can't handle this request string
1153
+
1154
+ return True # handled the request string
1155
+
1156
+ def checkQueue(self, unused_timer_id):
1157
+ glutTimerFunc(20, self.checkQueue, 0)
1158
+
1159
+ # if True: # spinning
1160
+ # w_whole_window = glutGet(GLUT_WINDOW_WIDTH)
1161
+ # h_whole_window = glutGet(GLUT_WINDOW_HEIGHT)
1162
+ # center_x = w_whole_window/2
1163
+ # center_y = h_whole_window/2
1164
+ # self.on_click(GLUT_LEFT_BUTTON, GLUT_DOWN, center_x, center_y)
1165
+ # self.on_drag(center_x+2, center_y)
1166
+
1167
+ try:
1168
+ request = self.server.recv_pyobj(zmq.NOBLOCK)
1169
+ except zmq.ZMQError as e:
1170
+ if e.errno != zmq.EAGAIN:
1171
+ raise # something wrong besides empty queue
1172
+ return # empty queue, no problem
1173
+
1174
+ if not request:
1175
+ return
1176
+
1177
+ while (request):
1178
+ task_completion_time = time.time()
1179
+ if not self.handle_request(request):
1180
+ raise Exception('Unknown command string: %s' % (request['label']))
1181
+ task_completion_time = time.time() - task_completion_time
1182
+
1183
+ if 'port' in request: # caller wants confirmation
1184
+ port = request['port']
1185
+ client = zmq.Context.instance().socket(zmq.PUSH)
1186
+ client.connect('tcp://127.0.0.1:%d' % (port))
1187
+ client.send_pyobj(task_completion_time)
1188
+ try:
1189
+ request = self.server.recv_pyobj(zmq.NOBLOCK)
1190
+ except zmq.ZMQError as e:
1191
+ if e.errno != zmq.EAGAIN:
1192
+ raise
1193
+ request = None
1194
+
1195
+ if self.need_redraw:
1196
+ glutPostRedisplay()
1197
+
1198
+ def init_opengl(self):
1199
+ """A general OpenGL initialization function. Sets all of the initial parameters.
1200
+
1201
+ We call this right after our OpenGL window is created.
1202
+ """
1203
+
1204
+ glClearColor(0.0, 0.0, 0.0, 1.0) # This Will Clear The Background Color To Black
1205
+ glClearDepth(1.0) # Enables Clearing Of The Depth Buffer
1206
+ glDepthFunc(GL_LEQUAL) # The Type Of Depth Test To Do
1207
+ glEnable(GL_DEPTH_TEST) # Enables Depth Testing
1208
+ glShadeModel(GL_SMOOTH)
1209
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # Really Nice Perspective Calculations
1210
+
1211
+ glEnable(GL_LIGHT0)
1212
+ glEnable(GL_LIGHTING)
1213
+
1214
+ glEnable(GL_COLOR_MATERIAL)
1215
+ glEnable(GL_NORMALIZE) # important since we rescale the modelview matrix
1216
+
1217
+ return True
1218
+
1219
+
1220
+ if __name__ == '__main__':
1221
+
1222
+ # Windows specific: see http://docs.python.org/2/library/multiprocessing.html#multiprocessing.freeze_support
1223
+ freeze_support()
1224
+
1225
+ if len(sys.argv) == 2 and sys.argv[1] == 'TEST_FOR_OPENGL':
1226
+ _test_for_opengl()
1227
+
1228
+ elif len(sys.argv) > 2:
1229
+ m = MeshViewerRemote(titlebar=sys.argv[1],
1230
+ subwins_vert=int(sys.argv[2]),
1231
+ subwins_horz=int(sys.argv[3]),
1232
+ width=int(sys.argv[4]),
1233
+ height=int(sys.argv[5]))
1234
+
1235
+ else:
1236
+ print("#" * 10)
1237
+ print('Usage:')
1238
+ print("python -m %s.%s arguments" % (__package__, os.path.splitext(os.path.basename(__file__))[0]))
mesh-fix-MSVC_compilation/mesh/processing.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/ressources/Arial.ttf ADDED
Binary file (773 kB). View file
 
mesh-fix-MSVC_compilation/mesh/search.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/serialization/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # encoding: utf-8
3
+
4
+ # Copyright (c) 2016 Max Planck Society. All rights reserved.
mesh-fix-MSVC_compilation/mesh/serialization/serialization.py ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/sphere.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-fix-MSVC_compilation/mesh/src/AABB_n_tree.h ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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: */