Spaces:
Build error
Build error
Commit
·
faeda5e
1
Parent(s):
9b6fdf7
Upload 97 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- mesh-fix-MSVC_compilation/.gitattributes +5 -0
- mesh-fix-MSVC_compilation/.gitignore +10 -0
- mesh-fix-MSVC_compilation/CGAL_LICENSE.pdf +0 -0
- mesh-fix-MSVC_compilation/LICENSE.txt +30 -0
- mesh-fix-MSVC_compilation/MANIFEST.in +2 -0
- mesh-fix-MSVC_compilation/Makefile +48 -0
- mesh-fix-MSVC_compilation/README.md +110 -0
- mesh-fix-MSVC_compilation/data/unittest/cylinder.obj +38 -0
- mesh-fix-MSVC_compilation/data/unittest/cylinder_trans.obj +38 -0
- mesh-fix-MSVC_compilation/data/unittest/self_intersecting_cyl.obj +46 -0
- mesh-fix-MSVC_compilation/data/unittest/sphere.obj +1278 -0
- mesh-fix-MSVC_compilation/data/unittest/sphere.ply +1271 -0
- mesh-fix-MSVC_compilation/data/unittest/test_box.obj +50 -0
- mesh-fix-MSVC_compilation/data/unittest/test_box.ply +29 -0
- mesh-fix-MSVC_compilation/data/unittest/test_box.pp +11 -0
- mesh-fix-MSVC_compilation/data/unittest/test_box_le.ply +0 -0
- mesh-fix-MSVC_compilation/data/unittest/test_doublebox.obj +64 -0
- mesh-fix-MSVC_compilation/doc/Makefile +177 -0
- mesh-fix-MSVC_compilation/doc/make.bat +242 -0
- mesh-fix-MSVC_compilation/doc/source/conf.py +356 -0
- mesh-fix-MSVC_compilation/doc/source/index.rst +163 -0
- mesh-fix-MSVC_compilation/doc/source/pages/geometry.rst +29 -0
- mesh-fix-MSVC_compilation/doc/source/pages/mesh.rst +31 -0
- mesh-fix-MSVC_compilation/doc/source/pages/mesh_viewer.rst +11 -0
- mesh-fix-MSVC_compilation/mesh/CMakeLists.txt +114 -0
- mesh-fix-MSVC_compilation/mesh/__init__.py +20 -0
- mesh-fix-MSVC_compilation/mesh/arcball.py +247 -0
- mesh-fix-MSVC_compilation/mesh/cmake/python_helper.cmake +74 -0
- mesh-fix-MSVC_compilation/mesh/cmake/thirdparty.cmake +107 -0
- mesh-fix-MSVC_compilation/mesh/colors.py +790 -0
- mesh-fix-MSVC_compilation/mesh/errors.py +15 -0
- mesh-fix-MSVC_compilation/mesh/fonts.py +87 -0
- mesh-fix-MSVC_compilation/mesh/geometry/__init__.py +4 -0
- mesh-fix-MSVC_compilation/mesh/geometry/barycentric_coordinates_of_projection.py +49 -0
- mesh-fix-MSVC_compilation/mesh/geometry/cross_product.py +37 -0
- mesh-fix-MSVC_compilation/mesh/geometry/rodrigues.py +125 -0
- mesh-fix-MSVC_compilation/mesh/geometry/tri_normals.py +72 -0
- mesh-fix-MSVC_compilation/mesh/geometry/triangle_area.py +12 -0
- mesh-fix-MSVC_compilation/mesh/geometry/vert_normals.py +34 -0
- mesh-fix-MSVC_compilation/mesh/landmarks.py +102 -0
- mesh-fix-MSVC_compilation/mesh/lines.py +61 -0
- mesh-fix-MSVC_compilation/mesh/mesh.py +492 -0
- mesh-fix-MSVC_compilation/mesh/meshviewer.py +1238 -0
- mesh-fix-MSVC_compilation/mesh/processing.py +186 -0
- mesh-fix-MSVC_compilation/mesh/ressources/Arial.ttf +0 -0
- mesh-fix-MSVC_compilation/mesh/search.py +100 -0
- mesh-fix-MSVC_compilation/mesh/serialization/__init__.py +4 -0
- mesh-fix-MSVC_compilation/mesh/serialization/serialization.py +443 -0
- mesh-fix-MSVC_compilation/mesh/sphere.py +74 -0
- 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: */
|