├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake └── FindLIBIGL.cmake ├── mesh ├── hemispherical.obj ├── mountain.obj ├── terrain_rough.obj ├── terrain_tri.obj └── terrain_yen.obj └── src ├── Viz.h ├── common.h ├── compute_surface_func.h ├── fermat3d.cpp ├── fermat3d_imp.h ├── isolines_ds.h └── isolines_util.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | *.un~ 31 | *.swo 32 | *.swp 33 | 34 | build/* 35 | fermat/* 36 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libigl"] 2 | path = libigl 3 | url = https://github.com/libigl/libigl.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(fermat3d) 3 | 4 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 5 | 6 | # libigl 7 | option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF) 8 | option(LIBIGL_WITH_ANTTWEAKBAR "Use AntTweakBar" OFF) 9 | option(LIBIGL_WITH_CGAL "Use CGAL" OFF) 10 | option(LIBIGL_WITH_COMISO "Use CoMiso" OFF) 11 | option(LIBIGL_WITH_CORK "Use Cork" OFF) 12 | option(LIBIGL_WITH_EMBREE "Use Embree" OFF) 13 | option(LIBIGL_WITH_LIM "Use LIM" OFF) 14 | option(LIBIGL_WITH_MATLAB "Use Matlab" OFF) 15 | option(LIBIGL_WITH_MOSEK "Use MOSEK" OFF) 16 | option(LIBIGL_WITH_OPENGL "Use OpenGL" ON) 17 | option(LIBIGL_WITH_OPENGL_GLFW "Use GLFW" ON) 18 | option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui" OFF) 19 | option(LIBIGL_WITH_PNG "Use PNG" OFF) 20 | option(LIBIGL_WITH_PYTHON "Use Python" OFF) 21 | option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF) 22 | option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF) 23 | option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" ON) 24 | option(LIBIGL_WITH_XML "Use XML" OFF) 25 | 26 | find_package(LIBIGL REQUIRED QUIET) 27 | 28 | # Add your project files 29 | file(GLOB SRCFILES src/*.cpp src/*.h) 30 | add_executable(${PROJECT_NAME}_bin ${SRCFILES}) 31 | target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl_glfw) 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License, version 2.0 2 | 3 | 1. Definitions 4 | 5 | 1.1. "Contributor" 6 | 7 | means each individual or legal entity that creates, contributes to the 8 | creation of, or owns Covered Software. 9 | 10 | 1.2. "Contributor Version" 11 | 12 | means the combination of the Contributions of others (if any) used by a 13 | Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | 17 | means Covered Software of a particular Contributor. 18 | 19 | 1.4. "Covered Software" 20 | 21 | means Source Code Form to which the initial Contributor has attached the 22 | notice in Exhibit A, the Executable Form of such Source Code Form, and 23 | Modifications of such Source Code Form, in each case including portions 24 | thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | a. that the initial Contributor has attached the notice described in 30 | Exhibit B to the Covered Software; or 31 | 32 | b. that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the terms of 34 | a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | 38 | means any form of the work other than Source Code Form. 39 | 40 | 1.7. "Larger Work" 41 | 42 | means a work that combines Covered Software with other material, in a 43 | separate file or files, that is not Covered Software. 44 | 45 | 1.8. "License" 46 | 47 | means this document. 48 | 49 | 1.9. "Licensable" 50 | 51 | means having the right to grant, to the maximum extent possible, whether 52 | at the time of the initial grant or subsequently, any and all of the 53 | rights conveyed by this License. 54 | 55 | 1.10. "Modifications" 56 | 57 | means any of the following: 58 | 59 | a. any file in Source Code Form that results from an addition to, 60 | deletion from, or modification of the contents of Covered Software; or 61 | 62 | b. any new file in Source Code Form that contains any Covered Software. 63 | 64 | 1.11. "Patent Claims" of a Contributor 65 | 66 | means any patent claim(s), including without limitation, method, 67 | process, and apparatus claims, in any patent Licensable by such 68 | Contributor that would be infringed, but for the grant of the License, 69 | by the making, using, selling, offering for sale, having made, import, 70 | or transfer of either its Contributions or its Contributor Version. 71 | 72 | 1.12. "Secondary License" 73 | 74 | means either the GNU General Public License, Version 2.0, the GNU Lesser 75 | General Public License, Version 2.1, the GNU Affero General Public 76 | License, Version 3.0, or any later versions of those licenses. 77 | 78 | 1.13. "Source Code Form" 79 | 80 | means the form of the work preferred for making modifications. 81 | 82 | 1.14. "You" (or "Your") 83 | 84 | means an individual or a legal entity exercising rights under this 85 | License. For legal entities, "You" includes any entity that controls, is 86 | controlled by, or is under common control with You. For purposes of this 87 | definition, "control" means (a) the power, direct or indirect, to cause 88 | the direction or management of such entity, whether by contract or 89 | otherwise, or (b) ownership of more than fifty percent (50%) of the 90 | outstanding shares or beneficial ownership of such entity. 91 | 92 | 93 | 2. License Grants and Conditions 94 | 95 | 2.1. Grants 96 | 97 | Each Contributor hereby grants You a world-wide, royalty-free, 98 | non-exclusive license: 99 | 100 | a. under intellectual property rights (other than patent or trademark) 101 | Licensable by such Contributor to use, reproduce, make available, 102 | modify, display, perform, distribute, and otherwise exploit its 103 | Contributions, either on an unmodified basis, with Modifications, or 104 | as part of a Larger Work; and 105 | 106 | b. under Patent Claims of such Contributor to make, use, sell, offer for 107 | sale, have made, import, and otherwise transfer either its 108 | Contributions or its Contributor Version. 109 | 110 | 2.2. Effective Date 111 | 112 | The licenses granted in Section 2.1 with respect to any Contribution 113 | become effective for each Contribution on the date the Contributor first 114 | distributes such Contribution. 115 | 116 | 2.3. Limitations on Grant Scope 117 | 118 | The licenses granted in this Section 2 are the only rights granted under 119 | this License. No additional rights or licenses will be implied from the 120 | distribution or licensing of Covered Software under this License. 121 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 122 | Contributor: 123 | 124 | a. for any code that a Contributor has removed from Covered Software; or 125 | 126 | b. for infringements caused by: (i) Your and any other third party's 127 | modifications of Covered Software, or (ii) the combination of its 128 | Contributions with other software (except as part of its Contributor 129 | Version); or 130 | 131 | c. under Patent Claims infringed by Covered Software in the absence of 132 | its Contributions. 133 | 134 | This License does not grant any rights in the trademarks, service marks, 135 | or logos of any Contributor (except as may be necessary to comply with 136 | the notice requirements in Section 3.4). 137 | 138 | 2.4. Subsequent Licenses 139 | 140 | No Contributor makes additional grants as a result of Your choice to 141 | distribute the Covered Software under a subsequent version of this 142 | License (see Section 10.2) or under the terms of a Secondary License (if 143 | permitted under the terms of Section 3.3). 144 | 145 | 2.5. Representation 146 | 147 | Each Contributor represents that the Contributor believes its 148 | Contributions are its original creation(s) or it has sufficient rights to 149 | grant the rights to its Contributions conveyed by this License. 150 | 151 | 2.6. Fair Use 152 | 153 | This License is not intended to limit any rights You have under 154 | applicable copyright doctrines of fair use, fair dealing, or other 155 | equivalents. 156 | 157 | 2.7. Conditions 158 | 159 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in 160 | Section 2.1. 161 | 162 | 163 | 3. Responsibilities 164 | 165 | 3.1. Distribution of Source Form 166 | 167 | All distribution of Covered Software in Source Code Form, including any 168 | Modifications that You create or to which You contribute, must be under 169 | the terms of this License. You must inform recipients that the Source 170 | Code Form of the Covered Software is governed by the terms of this 171 | License, and how they can obtain a copy of this License. You may not 172 | attempt to alter or restrict the recipients' rights in the Source Code 173 | Form. 174 | 175 | 3.2. Distribution of Executable Form 176 | 177 | If You distribute Covered Software in Executable Form then: 178 | 179 | a. such Covered Software must also be made available in Source Code Form, 180 | as described in Section 3.1, and You must inform recipients of the 181 | Executable Form how they can obtain a copy of such Source Code Form by 182 | reasonable means in a timely manner, at a charge no more than the cost 183 | of distribution to the recipient; and 184 | 185 | b. You may distribute such Executable Form under the terms of this 186 | License, or sublicense it under different terms, provided that the 187 | license for the Executable Form does not attempt to limit or alter the 188 | recipients' rights in the Source Code Form under this License. 189 | 190 | 3.3. Distribution of a Larger Work 191 | 192 | You may create and distribute a Larger Work under terms of Your choice, 193 | provided that You also comply with the requirements of this License for 194 | the Covered Software. If the Larger Work is a combination of Covered 195 | Software with a work governed by one or more Secondary Licenses, and the 196 | Covered Software is not Incompatible With Secondary Licenses, this 197 | License permits You to additionally distribute such Covered Software 198 | under the terms of such Secondary License(s), so that the recipient of 199 | the Larger Work may, at their option, further distribute the Covered 200 | Software under the terms of either this License or such Secondary 201 | License(s). 202 | 203 | 3.4. Notices 204 | 205 | You may not remove or alter the substance of any license notices 206 | (including copyright notices, patent notices, disclaimers of warranty, or 207 | limitations of liability) contained within the Source Code Form of the 208 | Covered Software, except that You may alter any license notices to the 209 | extent required to remedy known factual inaccuracies. 210 | 211 | 3.5. Application of Additional Terms 212 | 213 | You may choose to offer, and to charge a fee for, warranty, support, 214 | indemnity or liability obligations to one or more recipients of Covered 215 | Software. However, You may do so only on Your own behalf, and not on 216 | behalf of any Contributor. You must make it absolutely clear that any 217 | such warranty, support, indemnity, or liability obligation is offered by 218 | You alone, and You hereby agree to indemnify every Contributor for any 219 | liability incurred by such Contributor as a result of warranty, support, 220 | indemnity or liability terms You offer. You may include additional 221 | disclaimers of warranty and limitations of liability specific to any 222 | jurisdiction. 223 | 224 | 4. Inability to Comply Due to Statute or Regulation 225 | 226 | If it is impossible for You to comply with any of the terms of this License 227 | with respect to some or all of the Covered Software due to statute, 228 | judicial order, or regulation then You must: (a) comply with the terms of 229 | this License to the maximum extent possible; and (b) describe the 230 | limitations and the code they affect. Such description must be placed in a 231 | text file included with all distributions of the Covered Software under 232 | this License. Except to the extent prohibited by statute or regulation, 233 | such description must be sufficiently detailed for a recipient of ordinary 234 | skill to be able to understand it. 235 | 236 | 5. Termination 237 | 238 | 5.1. The rights granted under this License will terminate automatically if You 239 | fail to comply with any of its terms. However, if You become compliant, 240 | then the rights granted under this License from a particular Contributor 241 | are reinstated (a) provisionally, unless and until such Contributor 242 | explicitly and finally terminates Your grants, and (b) on an ongoing 243 | basis, if such Contributor fails to notify You of the non-compliance by 244 | some reasonable means prior to 60 days after You have come back into 245 | compliance. Moreover, Your grants from a particular Contributor are 246 | reinstated on an ongoing basis if such Contributor notifies You of the 247 | non-compliance by some reasonable means, this is the first time You have 248 | received notice of non-compliance with this License from such 249 | Contributor, and You become compliant prior to 30 days after Your receipt 250 | of the notice. 251 | 252 | 5.2. If You initiate litigation against any entity by asserting a patent 253 | infringement claim (excluding declaratory judgment actions, 254 | counter-claims, and cross-claims) alleging that a Contributor Version 255 | directly or indirectly infringes any patent, then the rights granted to 256 | You by any and all Contributors for the Covered Software under Section 257 | 2.1 of this License shall terminate. 258 | 259 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user 260 | license agreements (excluding distributors and resellers) which have been 261 | validly granted by You or Your distributors under this License prior to 262 | termination shall survive termination. 263 | 264 | 6. Disclaimer of Warranty 265 | 266 | Covered Software is provided under this License on an "as is" basis, 267 | without warranty of any kind, either expressed, implied, or statutory, 268 | including, without limitation, warranties that the Covered Software is free 269 | of defects, merchantable, fit for a particular purpose or non-infringing. 270 | The entire risk as to the quality and performance of the Covered Software 271 | is with You. Should any Covered Software prove defective in any respect, 272 | You (not any Contributor) assume the cost of any necessary servicing, 273 | repair, or correction. This disclaimer of warranty constitutes an essential 274 | part of this License. No use of any Covered Software is authorized under 275 | this License except under this disclaimer. 276 | 277 | 7. Limitation of Liability 278 | 279 | Under no circumstances and under no legal theory, whether tort (including 280 | negligence), contract, or otherwise, shall any Contributor, or anyone who 281 | distributes Covered Software as permitted above, be liable to You for any 282 | direct, indirect, special, incidental, or consequential damages of any 283 | character including, without limitation, damages for lost profits, loss of 284 | goodwill, work stoppage, computer failure or malfunction, or any and all 285 | other commercial damages or losses, even if such party shall have been 286 | informed of the possibility of such damages. This limitation of liability 287 | shall not apply to liability for death or personal injury resulting from 288 | such party's negligence to the extent applicable law prohibits such 289 | limitation. Some jurisdictions do not allow the exclusion or limitation of 290 | incidental or consequential damages, so this exclusion and limitation may 291 | not apply to You. 292 | 293 | 8. Litigation 294 | 295 | Any litigation relating to this License may be brought only in the courts 296 | of a jurisdiction where the defendant maintains its principal place of 297 | business and such litigation shall be governed by laws of that 298 | jurisdiction, without reference to its conflict-of-law provisions. Nothing 299 | in this Section shall prevent a party's ability to bring cross-claims or 300 | counter-claims. 301 | 302 | 9. Miscellaneous 303 | 304 | This License represents the complete agreement concerning the subject 305 | matter hereof. If any provision of this License is held to be 306 | unenforceable, such provision shall be reformed only to the extent 307 | necessary to make it enforceable. Any law or regulation which provides that 308 | the language of a contract shall be construed against the drafter shall not 309 | be used to construe this License against a Contributor. 310 | 311 | 312 | 10. Versions of the License 313 | 314 | 10.1. New Versions 315 | 316 | Mozilla Foundation is the license steward. Except as provided in Section 317 | 10.3, no one other than the license steward has the right to modify or 318 | publish new versions of this License. Each version will be given a 319 | distinguishing version number. 320 | 321 | 10.2. Effect of New Versions 322 | 323 | You may distribute the Covered Software under the terms of the version 324 | of the License under which You originally received the Covered Software, 325 | or under the terms of any subsequent version published by the license 326 | steward. 327 | 328 | 10.3. Modified Versions 329 | 330 | If you create software not governed by this License, and you want to 331 | create a new license for such software, you may create and use a 332 | modified version of this License if you rename the license and remove 333 | any references to the name of the license steward (except to note that 334 | such modified license differs from this License). 335 | 336 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 337 | Licenses If You choose to distribute Source Code Form that is 338 | Incompatible With Secondary Licenses under the terms of this version of 339 | the License, the notice described in Exhibit B of this License must be 340 | attached. 341 | 342 | Exhibit A - Source Code Form License Notice 343 | 344 | This Source Code Form is subject to the 345 | terms of the Mozilla Public License, v. 346 | 2.0. If a copy of the MPL was not 347 | distributed with this file, You can 348 | obtain one at 349 | http://mozilla.org/MPL/2.0/. 350 | 351 | If it is not possible or desirable to put the notice in a particular file, 352 | then You may include the notice in a location (such as a LICENSE file in a 353 | relevant directory) where a recipient would be likely to look for such a 354 | notice. 355 | 356 | You may add additional accurate notices of copyright ownership. 357 | 358 | Exhibit B - "Incompatible With Secondary Licenses" Notice 359 | 360 | This Source Code Form is "Incompatible 361 | With Secondary Licenses", as defined by 362 | the Mozilla Public License, v. 2.0. 363 | 364 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3D Fermat Spiral for [Husky](https://github.com/VccRobot/husky) 2 | 3 | 4 | ## Install: 5 | On Windows, Using Git command line (https://git-scm.com) 6 | 7 | git clone --recursive https://github.com/VccRobot/fermat3d.git 8 | 9 | 10 | ## Compile: 11 | 12 | Using CMake GUI on Windows, the project can be compiled following the standard cmake routine. First, create new directory inside where the repo is downloaded and name it `build`. Then in CMake GUI, set the `source code` to where this repo is downloaded and the `binaries` to the `build` directoy. Hit `Configure` and make sure to specify `Viusal Studio 15 2017` as the generator for this project, then hit `Generate`. This will create a `.sln` file under the `build` directory that you can open using Visual Studio 2017. 13 | 14 | ## Run: 15 | 16 | In Visual Studio, the project is named `fermat3d_bin`. Make sure to select this project and hit F5 on Release mode. After a while, you should see a window pop up with seperate fermat spirals constructed on a terrain mesh. 17 | 18 | ### Fixing Runtime Error: 19 | During the construction of isolines, libigl uses a very small number to detect the duplicated vertices. If you receive a run-time error, that means you need to increase this number. You can do this by going to 'fermat3d\libigl\include\igl\isolines.cpp' and change the number in line 106. On my machine, I changed it to 2.2204e-9. 20 | 21 | 22 | ## Understanding the Code: 23 | 24 | Constructing of the Connected Fermat Spiral follows the steps in [Connected Fermat Spirals for Layered Fabrication](https://www.cs.sfu.ca/~haoz/pubs/zhao_sig16_fermat.pdf). Instead of using the offsets contours from the boundary of the input shape, we use the isolines from the height function (compute_surface_func.h). The isolines are computed using Libigl. There a set of post-processing operations that needs to be done in order to prepare the isolines to construct the Fermat Spirals. The 25 | post-processing of the isolines includes 26 | 27 | - Removing zero length isolines 28 | - Creating separate spirallable regions 29 | 30 | All the operations related to isolines are implemented in isolines_ds.h and isolines_util.h. Since we are using the height function, this creates isolines with non-uniform spacing. The proper way is to compute the offset from the boundary of the input mesh based on the geodesic function as done in [DSCarver: decompose-and-spiral-carve for subtractive manufacturing](https://www.cs.sfu.ca/~haoz/pubs/zhao_sig18_cnc.pdf) and then use this to compute the isolines. 31 | 32 | After computing the isolines and recognizing the spirallable regions, we are ready to construct the Fermat spiral. For each spirallable regions, we create a single spiral and then convert it to Fermat spiral (fermat3d_imp.h). 33 | -------------------------------------------------------------------------------- /cmake/FindLIBIGL.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the LIBIGL library 2 | # Once done this will define 3 | # 4 | # LIBIGL_FOUND - system has LIBIGL 5 | # LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory 6 | if(LIBIGL_FOUND) 7 | return() 8 | endif() 9 | 10 | find_path(LIBIGL_INCLUDE_DIR igl/readOBJ.h 11 | HINTS 12 | ENV LIBIGL 13 | ENV LIBIGLROOT 14 | ENV LIBIGL_ROOT 15 | ENV LIBIGL_DIR 16 | PATHS 17 | ${CMAKE_SOURCE_DIR}/../.. 18 | ${CMAKE_SOURCE_DIR}/.. 19 | ${CMAKE_SOURCE_DIR} 20 | ${CMAKE_SOURCE_DIR}/libigl 21 | ${CMAKE_SOURCE_DIR}/../libigl 22 | ${CMAKE_SOURCE_DIR}/../../libigl 23 | /usr 24 | /usr/local 25 | /usr/local/igl/libigl 26 | PATH_SUFFIXES include 27 | ) 28 | 29 | include(FindPackageHandleStandardArgs) 30 | find_package_handle_standard_args(LIBIGL 31 | "\nlibigl not found --- You can download it using:\n\tgit clone --recursive https://github.com/libigl/libigl.git ${CMAKE_SOURCE_DIR}/../libigl" 32 | LIBIGL_INCLUDE_DIR) 33 | mark_as_advanced(LIBIGL_INCLUDE_DIR) 34 | 35 | list(APPEND CMAKE_MODULE_PATH "${LIBIGL_INCLUDE_DIR}/../shared/cmake") 36 | include(libigl) 37 | -------------------------------------------------------------------------------- /mesh/hemispherical.obj: -------------------------------------------------------------------------------- 1 | #### 2 | # 3 | # OBJ File Generated by Meshlab 4 | # 5 | #### 6 | # Object hemispherical.obj 7 | # 8 | # Vertices: 1321 9 | # Faces: 2560 10 | # 11 | #### 12 | v 0.000000 3.000000 0.000000 13 | v 0.197273 2.992821 -0.064098 14 | v 0.000000 2.992821 -0.207425 15 | v 0.393601 2.971317 -0.127889 16 | v 0.197451 2.981133 -0.271768 17 | v 0.000000 2.971317 -0.413857 18 | v 0.588046 2.935591 -0.191068 19 | v 0.395246 2.954741 -0.336576 20 | v 0.197965 2.954741 -0.479909 21 | v 0.000000 2.935591 -0.618308 22 | v 0.779676 2.885815 -0.253332 23 | v 0.589237 2.914271 -0.399778 24 | v 0.394966 2.923778 -0.543624 25 | v 0.198127 2.914271 -0.683936 26 | v 0.000000 2.885815 -0.819800 27 | v 0.967574 2.822227 -0.314384 28 | v 0.787982 2.856908 -0.466008 29 | v 0.595160 2.876071 -0.611556 30 | v 0.397710 2.876071 -0.755012 31 | v 0.199701 2.856908 -0.893420 32 | v 0.000000 2.822227 -1.017367 33 | v 1.150841 2.745130 -0.373931 34 | v 0.974591 2.787956 -0.526760 35 | v 0.792248 2.813355 -0.676296 36 | v 0.597282 2.822663 -0.822089 37 | v 0.398377 2.813355 -0.962460 38 | v 0.199813 2.787956 -1.089668 39 | v 0.000000 2.745130 -1.210066 40 | v 1.328600 2.654895 -0.431688 41 | v 1.157718 2.704736 -0.586593 42 | v 0.977787 2.738471 -0.738044 43 | v 0.792454 2.755381 -0.883116 44 | v 0.595012 2.755381 -1.026566 45 | v 0.399769 2.738471 -1.157999 46 | v 0.200128 2.704736 -1.282323 47 | v 0.000000 2.654895 -1.396973 48 | v 1.500000 2.551952 -0.487380 49 | v 1.333391 2.609142 -0.643773 50 | v 1.158562 2.650246 -0.796197 51 | v 0.976590 2.675010 -0.943713 52 | v 0.788597 2.683281 -1.085410 53 | v 0.595741 2.675010 -1.220416 54 | v 0.399213 2.650246 -1.347897 55 | v 0.200224 2.609142 -1.467067 56 | v 0.000000 2.551952 -1.577193 57 | v 1.664220 2.436796 -0.540738 58 | v 1.533615 2.479029 -0.708830 59 | v 1.362785 2.529101 -0.863980 60 | v 1.182409 2.563044 -1.016225 61 | v 0.997026 2.580088 -1.161501 62 | v 0.796555 2.580088 -1.307151 63 | v 0.601103 2.563044 -1.438568 64 | v 0.400570 2.529101 -1.563071 65 | v 0.200224 2.479029 -1.677595 66 | v 0.000000 2.436796 -1.749865 67 | v 1.820476 2.309976 -0.591508 68 | v 1.693538 2.356539 -0.760691 69 | v 1.557775 2.390821 -0.925910 70 | v 1.382645 2.432923 -1.081286 71 | v 1.198821 2.459728 -1.229864 72 | v 1.002420 2.468106 -1.379713 73 | v 0.799214 2.459728 -1.520196 74 | v 0.601103 2.432923 -1.649109 75 | v 0.399213 2.390821 -1.767654 76 | v 0.200128 2.356539 -1.845717 77 | v 0.000000 2.309976 -1.914161 78 | v 1.968017 2.172099 -0.639448 79 | v 1.846367 2.221441 -0.810017 80 | v 1.713421 2.260427 -0.977066 81 | v 1.572331 2.287874 -1.137281 82 | v 1.392640 2.323002 -1.290044 83 | v 1.202904 2.337823 -1.444854 84 | v 1.002420 2.337823 -1.590514 85 | v 0.796555 2.323002 -1.723125 86 | v 0.595741 2.287874 -1.846815 87 | v 0.399769 2.260427 -1.931490 88 | v 0.199813 2.221441 -2.006309 89 | v 0.000000 2.172099 -2.069296 90 | v 2.106139 2.023827 -0.684326 91 | v 1.988526 2.076747 -0.856089 92 | v 1.860719 2.119021 -1.023463 93 | v 1.723373 2.150433 -1.185591 94 | v 1.577193 2.170820 -1.341641 95 | v 1.392640 2.192729 -1.500831 96 | v 1.198821 2.200047 -1.650036 97 | v 0.997026 2.192729 -1.788262 98 | v 0.788597 2.170820 -1.914590 99 | v 0.595012 2.150433 -2.005393 100 | v 0.398377 2.119021 -2.085916 101 | v 0.199701 2.076747 -2.155746 102 | v 0.000000 2.023827 -2.214526 103 | v 2.234181 1.865868 -0.725929 104 | v 2.126908 1.915032 -0.899397 105 | v 2.002507 1.961521 -1.068831 106 | v 1.866875 1.997632 -1.234604 107 | v 1.723373 2.022127 -1.393193 108 | v 1.572331 2.040383 -1.537729 109 | v 1.382645 2.055168 -1.692507 110 | v 1.182409 2.055168 -1.837987 111 | v 0.976590 2.040383 -1.970560 112 | v 0.792454 2.022127 -2.069546 113 | v 0.597282 1.997632 -2.157017 114 | v 0.397710 1.961521 -2.234784 115 | v 0.198127 1.915032 -2.300738 116 | v 0.000000 1.865868 -2.349157 117 | v 2.351529 1.698978 -0.764058 118 | v 2.248161 1.750644 -0.938625 119 | v 2.133845 1.793785 -1.108620 120 | v 2.002507 1.833210 -1.276442 121 | v 1.860719 1.863068 -1.437603 122 | v 1.713421 1.884809 -1.584830 123 | v 1.557775 1.897367 -1.724336 124 | v 1.362785 1.903816 -1.875713 125 | v 1.158562 1.897367 -2.014382 126 | v 0.977787 1.884809 -2.119299 127 | v 0.792248 1.863068 -2.213892 128 | v 0.595160 1.833210 -2.298940 129 | v 0.394966 1.793785 -2.371990 130 | v 0.197965 1.750644 -2.428179 131 | v 0.000000 1.698978 -2.472544 132 | v 2.457622 1.523956 -0.798530 133 | v 2.359298 1.576280 -0.974194 134 | v 2.248161 1.622443 -1.146058 135 | v 2.126908 1.660874 -1.310634 136 | v 1.988526 1.694458 -1.474644 137 | v 1.846367 1.717960 -1.624666 138 | v 1.693538 1.734259 -1.767561 139 | v 1.533615 1.742652 -1.900313 140 | v 1.333391 1.742652 -2.045784 141 | v 1.157718 1.734259 -2.156857 142 | v 0.974591 1.717960 -2.258049 143 | v 0.787982 1.694458 -2.346890 144 | v 0.589237 1.660874 -2.427817 145 | v 0.395246 1.622443 -2.492280 146 | v 0.197451 1.576280 -2.544868 147 | v 0.000000 1.523956 -2.584097 148 | v 2.551952 1.341641 -0.829180 149 | v 2.457622 1.395761 -1.005955 150 | v 2.351529 1.443200 -1.177915 151 | v 2.234181 1.483732 -1.344237 152 | v 2.106139 1.517163 -1.504126 153 | v 1.968017 1.543332 -1.656815 154 | v 1.820476 1.562114 -1.801574 155 | v 1.664220 1.573419 -1.937711 156 | v 1.500000 1.577193 -2.064573 157 | v 1.328600 1.573419 -2.181553 158 | v 1.150841 1.562114 -2.288092 159 | v 0.967574 1.543332 -2.383679 160 | v 0.779676 1.517163 -2.467858 161 | v 0.588046 1.483732 -2.540225 162 | v 0.393601 1.443200 -2.600433 163 | v 0.197273 1.395761 -2.648195 164 | v 0.000000 1.341641 -2.683281 165 | v 0.121921 2.992821 0.167810 166 | v 0.243259 2.971317 0.334817 167 | v 0.319482 2.981133 0.103806 168 | v 0.363432 2.935591 0.500222 169 | v 0.442241 2.954741 0.271894 170 | v 0.517595 2.954741 0.039976 171 | v 0.481866 2.885815 0.663232 172 | v 0.562296 2.914271 0.436859 173 | v 0.639069 2.923778 0.207646 174 | v 0.711686 2.914271 -0.022918 175 | v 0.597994 2.822227 0.823068 176 | v 0.686700 2.856908 0.605411 177 | v 0.765539 2.876071 0.377050 178 | v 0.840958 2.876071 0.144933 179 | v 0.911403 2.856908 -0.086155 180 | v 0.711259 2.745130 0.978964 181 | v 0.802143 2.787956 0.764113 182 | v 0.888014 2.813355 0.544486 183 | v 0.966423 2.822663 0.314010 184 | v 1.038459 2.813355 0.081463 185 | v 1.098082 2.787956 -0.146692 186 | v 0.821120 2.654895 1.130175 187 | v 0.915637 2.704736 0.919789 188 | v 1.004075 2.738471 0.701862 189 | v 1.084775 2.755381 0.480770 190 | v 1.160191 2.755381 0.248664 191 | v 1.224858 2.738471 0.022362 192 | v 1.281404 2.704736 -0.205926 193 | v 0.927051 2.551952 1.275976 194 | v 1.024305 2.609142 1.069194 195 | v 1.115244 2.650246 0.855820 196 | v 1.199307 2.675010 0.637169 197 | v 1.275976 2.683281 0.414590 198 | v 1.344778 2.675010 0.189455 199 | v 1.405290 2.650246 -0.036849 200 | v 1.457137 2.609142 -0.262925 201 | v 1.028545 2.436796 1.415670 202 | v 1.148050 2.479029 1.239514 203 | v 1.242818 2.529101 1.029101 204 | v 1.331872 2.563044 0.810507 205 | v 1.412751 2.580088 0.589304 206 | v 1.489324 2.580088 0.353637 207 | v 1.553911 2.563044 0.127141 208 | v 1.610351 2.529101 -0.102050 209 | v 1.657361 2.479029 -0.327981 210 | v 1.125116 2.309976 1.548589 211 | v 1.246793 2.356539 1.375584 212 | v 1.361971 2.390821 1.195411 213 | v 1.455625 2.432923 0.980838 214 | v 1.540126 2.459728 0.760098 215 | v 1.621950 2.468106 0.527003 216 | v 1.692763 2.459728 0.290332 217 | v 1.754147 2.432923 0.062081 218 | v 1.804503 2.390821 -0.166561 219 | v 1.817225 2.356539 -0.380025 220 | v 1.216301 2.172099 1.674095 221 | v 1.340931 2.221441 1.505691 222 | v 1.458721 2.260427 1.327630 223 | v 1.567496 2.287874 1.143937 224 | v 1.657254 2.323002 0.925834 225 | v 1.745856 2.337823 0.697545 226 | v 1.822434 2.337823 0.461862 227 | v 1.884938 2.323002 0.225094 228 | v 1.940520 2.287874 -0.004113 229 | v 1.960492 2.260427 -0.216660 230 | v 1.969859 2.221441 -0.429950 231 | v 1.301666 2.023827 1.791589 232 | v 1.428677 2.076747 1.626654 233 | v 1.548365 2.119021 1.453381 234 | v 1.660115 2.150433 1.272658 235 | v 1.763356 2.170820 1.085410 236 | v 1.857725 2.192729 0.860697 237 | v 1.939733 2.200047 0.630258 238 | v 2.008836 2.192729 0.395625 239 | v 2.064573 2.170820 0.158359 240 | v 2.091111 2.150433 -0.053810 241 | v 2.106930 2.119021 -0.265704 242 | v 2.111948 2.076747 -0.476236 243 | v 1.380800 1.865868 1.900508 244 | v 1.512628 1.915032 1.744880 245 | v 1.635327 1.961521 1.574211 246 | v 1.751074 1.997632 1.393990 247 | v 1.857557 2.022127 1.208505 248 | v 1.948344 2.040383 1.020192 249 | v 2.036930 2.055168 0.791960 250 | v 2.113414 2.055168 0.556568 251 | v 2.175897 2.040383 0.319856 252 | v 2.213136 2.022127 0.114143 253 | v 2.236016 1.997632 -0.098506 254 | v 2.248305 1.961521 -0.312342 255 | v 2.249357 1.915032 -0.522537 256 | v 1.453325 1.698978 2.000330 257 | v 1.587405 1.750644 1.848077 258 | v 1.713755 1.793785 1.686825 259 | v 1.832778 1.833210 1.510055 260 | v 1.942236 1.863068 1.325405 261 | v 2.036739 1.884809 1.139820 262 | v 2.121320 1.897367 0.948683 263 | v 2.205033 1.903816 0.716459 264 | v 2.273806 1.897367 0.479380 265 | v 2.317726 1.884809 0.275031 266 | v 2.350355 1.863068 0.069342 267 | v 2.370337 1.833210 -0.144381 268 | v 2.377948 1.793785 -0.357350 269 | v 2.370510 1.750644 -0.562073 270 | v 1.518894 1.523956 2.090578 271 | v 1.655577 1.576280 1.942783 272 | v 1.784686 1.622443 1.783977 273 | v 1.903738 1.660874 1.617801 274 | v 2.016958 1.694458 1.435510 275 | v 2.115708 1.717960 1.253950 276 | v 2.204383 1.734259 1.064444 277 | v 2.281218 1.742652 0.871326 278 | v 2.357697 1.742652 0.635949 279 | v 2.409048 1.734259 0.434550 280 | v 2.448698 1.717960 0.229115 281 | v 2.475525 1.694458 0.024186 282 | v 2.491076 1.660874 -0.189839 283 | v 2.492437 1.622443 -0.394256 284 | v 2.481329 1.576280 -0.598621 285 | v 1.577193 1.341641 2.170820 286 | v 1.716167 1.395761 2.026481 287 | v 1.846926 1.443200 1.872441 288 | v 1.968845 1.483732 1.709440 289 | v 2.081342 1.517163 1.538257 290 | v 2.183876 1.543332 1.359712 291 | v 2.275957 1.562114 1.174658 292 | v 2.357145 1.573419 0.983982 293 | v 2.427051 1.577193 0.788597 294 | v 2.485340 1.573419 0.589437 295 | v 2.531734 1.562114 0.387456 296 | v 2.566011 1.543332 0.183620 297 | v 2.588005 1.517163 -0.021094 298 | v 2.597613 1.483732 -0.225708 299 | v 2.594788 1.443200 -0.429241 300 | v 2.579543 1.395761 -0.630720 301 | v -0.121921 2.992821 0.167810 302 | v -0.243259 2.971317 0.334817 303 | v 0.000000 2.981133 0.335923 304 | v -0.363432 2.935591 0.500222 305 | v -0.121926 2.954741 0.504615 306 | v 0.121926 2.954741 0.504615 307 | v -0.481866 2.885815 0.663232 308 | v -0.241719 2.914271 0.669772 309 | v 0.000000 2.923778 0.671956 310 | v 0.241719 2.914271 0.669772 311 | v -0.597994 2.822227 0.823068 312 | v -0.363578 2.856908 0.840173 313 | v -0.122031 2.876071 0.844585 314 | v 0.122031 2.876071 0.844585 315 | v 0.363578 2.856908 0.840173 316 | v -0.711259 2.745130 0.978964 317 | v -0.478839 2.787956 0.999008 318 | v -0.243426 2.813355 1.012807 319 | v 0.000000 2.822663 1.016157 320 | v 0.243426 2.813355 1.012807 321 | v 0.478839 2.787956 0.999008 322 | v -0.821120 2.654895 1.130175 323 | v -0.591823 2.704736 1.155053 324 | v -0.357235 2.738471 1.171819 325 | v -0.122026 2.755381 1.180249 326 | v 0.122026 2.755381 1.180249 327 | v 0.357235 2.738471 1.171819 328 | v 0.591823 2.704736 1.155053 329 | v -0.927051 2.551952 1.275976 330 | v -0.700336 2.609142 1.304571 331 | v -0.469303 2.650246 1.325123 332 | v -0.235377 2.675010 1.337505 333 | v 0.000000 2.683281 1.341641 334 | v 0.235377 2.675010 1.337505 335 | v 0.469303 2.650246 1.325123 336 | v 0.700336 2.609142 1.304571 337 | v -1.028545 2.436796 1.415670 338 | v -0.824081 2.479029 1.474892 339 | v -0.594682 2.529101 1.500000 340 | v -0.359266 2.563044 1.517146 341 | v -0.123898 2.580088 1.525711 342 | v 0.123898 2.580088 1.525711 343 | v 0.359266 2.563044 1.517146 344 | v 0.594682 2.529101 1.500000 345 | v 0.824081 2.479029 1.474892 346 | v -1.125116 2.309976 1.548589 347 | v -0.922978 2.356539 1.610849 348 | v -0.716031 2.390821 1.664714 349 | v -0.483019 2.432923 1.687477 350 | v -0.246971 2.459728 1.699630 351 | v 0.000000 2.468106 1.705419 352 | v 0.246971 2.459728 1.699630 353 | v 0.483019 2.432923 1.687477 354 | v 0.716031 2.390821 1.664714 355 | v 0.922978 2.356539 1.610849 356 | v -1.216301 2.172099 1.674095 357 | v -1.017627 2.221441 1.740585 358 | v -0.811881 2.260427 1.797587 359 | v -0.603566 2.287874 1.844273 360 | v -0.368401 2.323002 1.862241 361 | v -0.123906 2.337823 1.875961 362 | v 0.123906 2.337823 1.875961 363 | v 0.368401 2.323002 1.862241 364 | v 0.603566 2.287874 1.844273 365 | v 0.811881 2.260427 1.797587 366 | v 1.017627 2.221441 1.740585 367 | v -1.301666 2.023827 1.791589 368 | v -1.105555 2.076747 1.861417 369 | v -0.903777 2.119021 1.921702 370 | v -0.697366 2.150433 1.972136 371 | v -0.487380 2.170820 2.012461 372 | v -0.244503 2.192729 2.032771 373 | v 0.000000 2.200047 2.039557 374 | v 0.244503 2.192729 2.032771 375 | v 0.487380 2.170820 2.012461 376 | v 0.697366 2.150433 1.972136 377 | v 0.903777 2.119021 1.921702 378 | v 1.105555 2.076747 1.861417 379 | v -1.380800 1.865868 1.900508 380 | v -1.192052 1.915032 1.977793 381 | v -0.991820 1.961521 2.041746 382 | v -0.784651 1.997632 2.096137 383 | v -0.575340 2.022127 2.140090 384 | v -0.368188 2.040383 2.168242 385 | v -0.123753 2.055168 2.181965 386 | v 0.123753 2.055168 2.181965 387 | v 0.368188 2.040383 2.168242 388 | v 0.575340 2.022127 2.140090 389 | v 0.784651 1.997632 2.096137 390 | v 0.991820 1.961521 2.041746 391 | v 1.192052 1.915032 1.977793 392 | v -1.453325 1.698978 2.000330 393 | v -1.267091 1.750644 2.080799 394 | v -1.074686 1.793785 2.151135 395 | v -0.869788 1.833210 2.209708 396 | v -0.660351 1.863068 2.256748 397 | v -0.454647 1.884809 2.289278 398 | v -0.246727 1.897367 2.310655 399 | v 0.000000 1.903816 2.318509 400 | v 0.246727 1.897367 2.310655 401 | v 0.454647 1.884809 2.289278 402 | v 0.660351 1.863068 2.256748 403 | v 0.869788 1.833210 2.209708 404 | v 1.074686 1.793785 2.151135 405 | v 1.267091 1.750644 2.080799 406 | v -1.518894 1.523956 2.090578 407 | v -1.336095 1.576280 2.174901 408 | v -1.145165 1.622443 2.248616 409 | v -0.950333 1.660874 2.310490 410 | v -0.741977 1.694458 2.361838 411 | v -0.538788 1.717960 2.399650 412 | v -0.331155 1.734259 2.425424 413 | v -0.123745 1.742652 2.438822 414 | v 0.123745 1.742652 2.438822 415 | v 0.331155 1.734259 2.425424 416 | v 0.538788 1.717960 2.399650 417 | v 0.741977 1.694458 2.361838 418 | v 0.950333 1.660874 2.310490 419 | v 1.145165 1.622443 2.248616 420 | v 1.336095 1.576280 2.174901 421 | v -1.577193 1.341641 2.170820 422 | v -1.396973 1.395761 2.258389 423 | v -1.210066 1.443200 2.335147 424 | v -1.017367 1.483732 2.400729 425 | v -0.819800 1.517163 2.454821 426 | v -0.618308 1.543332 2.497163 427 | v -0.413857 1.562114 2.527553 428 | v -0.207425 1.573419 2.545845 429 | v 0.000000 1.577193 2.551952 430 | v 0.207425 1.573419 2.545845 431 | v 0.413857 1.562114 2.527553 432 | v 0.618308 1.543332 2.497163 433 | v 0.819800 1.517163 2.454821 434 | v 1.017367 1.483732 2.400729 435 | v 1.210066 1.443200 2.335147 436 | v 1.396973 1.395761 2.258389 437 | v -0.197273 2.992821 -0.064098 438 | v -0.393601 2.971317 -0.127889 439 | v -0.319482 2.981133 0.103806 440 | v -0.588046 2.935591 -0.191068 441 | v -0.517595 2.954741 0.039976 442 | v -0.442241 2.954741 0.271894 443 | v -0.779676 2.885815 -0.253332 444 | v -0.711686 2.914271 -0.022918 445 | v -0.639069 2.923778 0.207646 446 | v -0.562296 2.914271 0.436859 447 | v -0.967574 2.822227 -0.314384 448 | v -0.911403 2.856908 -0.086155 449 | v -0.840958 2.876071 0.144933 450 | v -0.765539 2.876071 0.377050 451 | v -0.686700 2.856908 0.605411 452 | v -1.150841 2.745130 -0.373931 453 | v -1.098082 2.787956 -0.146692 454 | v -1.038459 2.813355 0.081463 455 | v -0.966423 2.822663 0.314010 456 | v -0.888014 2.813355 0.544486 457 | v -0.802143 2.787956 0.764113 458 | v -1.328600 2.654895 -0.431688 459 | v -1.281404 2.704736 -0.205926 460 | v -1.224858 2.738471 0.022362 461 | v -1.160191 2.755381 0.248664 462 | v -1.084775 2.755381 0.480770 463 | v -1.004075 2.738471 0.701862 464 | v -0.915637 2.704736 0.919789 465 | v -1.500000 2.551952 -0.487380 466 | v -1.457137 2.609142 -0.262925 467 | v -1.405290 2.650246 -0.036849 468 | v -1.344778 2.675010 0.189455 469 | v -1.275976 2.683281 0.414590 470 | v -1.199307 2.675010 0.637169 471 | v -1.115244 2.650246 0.855820 472 | v -1.024305 2.609142 1.069194 473 | v -1.664220 2.436796 -0.540738 474 | v -1.657361 2.479029 -0.327981 475 | v -1.610351 2.529101 -0.102050 476 | v -1.553911 2.563044 0.127141 477 | v -1.489324 2.580088 0.353637 478 | v -1.412751 2.580088 0.589304 479 | v -1.331872 2.563044 0.810507 480 | v -1.242818 2.529101 1.029101 481 | v -1.148050 2.479029 1.239514 482 | v -1.820476 2.309976 -0.591508 483 | v -1.817225 2.356539 -0.380025 484 | v -1.804503 2.390821 -0.166561 485 | v -1.754147 2.432923 0.062081 486 | v -1.692763 2.459728 0.290332 487 | v -1.621950 2.468106 0.527003 488 | v -1.540126 2.459728 0.760098 489 | v -1.455625 2.432923 0.980838 490 | v -1.361971 2.390821 1.195411 491 | v -1.246793 2.356539 1.375584 492 | v -1.968017 2.172099 -0.639448 493 | v -1.969859 2.221441 -0.429950 494 | v -1.960492 2.260427 -0.216660 495 | v -1.940520 2.287874 -0.004113 496 | v -1.884938 2.323002 0.225094 497 | v -1.822434 2.337823 0.461862 498 | v -1.745856 2.337823 0.697545 499 | v -1.657254 2.323002 0.925834 500 | v -1.567496 2.287874 1.143937 501 | v -1.458721 2.260427 1.327630 502 | v -1.340931 2.221441 1.505691 503 | v -2.106139 2.023827 -0.684326 504 | v -2.111948 2.076747 -0.476236 505 | v -2.106930 2.119021 -0.265704 506 | v -2.091111 2.150433 -0.053810 507 | v -2.064573 2.170820 0.158359 508 | v -2.008836 2.192729 0.395625 509 | v -1.939733 2.200047 0.630258 510 | v -1.857725 2.192729 0.860697 511 | v -1.763356 2.170820 1.085410 512 | v -1.660115 2.150433 1.272658 513 | v -1.548365 2.119021 1.453381 514 | v -1.428677 2.076747 1.626654 515 | v -2.234181 1.865868 -0.725929 516 | v -2.249357 1.915032 -0.522537 517 | v -2.248305 1.961521 -0.312342 518 | v -2.236016 1.997632 -0.098506 519 | v -2.213136 2.022127 0.114143 520 | v -2.175897 2.040383 0.319856 521 | v -2.113414 2.055168 0.556568 522 | v -2.036930 2.055168 0.791960 523 | v -1.948344 2.040383 1.020192 524 | v -1.857557 2.022127 1.208505 525 | v -1.751074 1.997632 1.393990 526 | v -1.635327 1.961521 1.574211 527 | v -1.512628 1.915032 1.744880 528 | v -2.351529 1.698978 -0.764058 529 | v -2.370510 1.750644 -0.562073 530 | v -2.377948 1.793785 -0.357350 531 | v -2.370337 1.833210 -0.144381 532 | v -2.350355 1.863068 0.069342 533 | v -2.317726 1.884809 0.275031 534 | v -2.273806 1.897367 0.479380 535 | v -2.205033 1.903816 0.716459 536 | v -2.121320 1.897367 0.948683 537 | v -2.036739 1.884809 1.139820 538 | v -1.942236 1.863068 1.325405 539 | v -1.832778 1.833210 1.510055 540 | v -1.713755 1.793785 1.686825 541 | v -1.587405 1.750644 1.848077 542 | v -2.457622 1.523956 -0.798530 543 | v -2.481329 1.576280 -0.598621 544 | v -2.492437 1.622443 -0.394256 545 | v -2.491076 1.660874 -0.189839 546 | v -2.475525 1.694458 0.024186 547 | v -2.448698 1.717960 0.229115 548 | v -2.409048 1.734259 0.434550 549 | v -2.357697 1.742652 0.635949 550 | v -2.281218 1.742652 0.871326 551 | v -2.204383 1.734259 1.064444 552 | v -2.115708 1.717960 1.253950 553 | v -2.016958 1.694458 1.435510 554 | v -1.903738 1.660874 1.617801 555 | v -1.784686 1.622443 1.783977 556 | v -1.655577 1.576280 1.942783 557 | v -2.551952 1.341641 -0.829180 558 | v -2.579543 1.395761 -0.630720 559 | v -2.594788 1.443200 -0.429241 560 | v -2.597613 1.483732 -0.225708 561 | v -2.588005 1.517163 -0.021094 562 | v -2.566011 1.543332 0.183620 563 | v -2.531734 1.562114 0.387456 564 | v -2.485340 1.573419 0.589437 565 | v -2.427051 1.577193 0.788597 566 | v -2.357145 1.573419 0.983982 567 | v -2.275957 1.562114 1.174658 568 | v -2.183876 1.543332 1.359712 569 | v -2.081342 1.517163 1.538257 570 | v -1.968845 1.483732 1.709440 571 | v -1.846926 1.443200 1.872441 572 | v -1.716167 1.395761 2.026481 573 | v -0.197451 2.981133 -0.271768 574 | v -0.197965 2.954741 -0.479909 575 | v -0.395246 2.954741 -0.336576 576 | v -0.198127 2.914271 -0.683936 577 | v -0.394966 2.923778 -0.543624 578 | v -0.589237 2.914271 -0.399778 579 | v -0.199701 2.856908 -0.893420 580 | v -0.397710 2.876071 -0.755012 581 | v -0.595160 2.876071 -0.611556 582 | v -0.787982 2.856908 -0.466008 583 | v -0.199813 2.787956 -1.089668 584 | v -0.398377 2.813355 -0.962460 585 | v -0.597282 2.822663 -0.822089 586 | v -0.792248 2.813355 -0.676296 587 | v -0.974591 2.787956 -0.526760 588 | v -0.200128 2.704736 -1.282323 589 | v -0.399769 2.738471 -1.157999 590 | v -0.595012 2.755381 -1.026566 591 | v -0.792454 2.755381 -0.883116 592 | v -0.977787 2.738471 -0.738044 593 | v -1.157718 2.704736 -0.586593 594 | v -0.200224 2.609142 -1.467067 595 | v -0.399213 2.650246 -1.347897 596 | v -0.595741 2.675010 -1.220416 597 | v -0.788597 2.683281 -1.085410 598 | v -0.976590 2.675010 -0.943713 599 | v -1.158562 2.650246 -0.796197 600 | v -1.333391 2.609142 -0.643773 601 | v -0.200224 2.479029 -1.677595 602 | v -0.400570 2.529101 -1.563071 603 | v -0.601103 2.563044 -1.438568 604 | v -0.796555 2.580088 -1.307151 605 | v -0.997026 2.580088 -1.161501 606 | v -1.182409 2.563044 -1.016225 607 | v -1.362785 2.529101 -0.863980 608 | v -1.533615 2.479029 -0.708830 609 | v -0.200128 2.356539 -1.845717 610 | v -0.399213 2.390821 -1.767654 611 | v -0.601103 2.432923 -1.649109 612 | v -0.799214 2.459728 -1.520196 613 | v -1.002420 2.468106 -1.379713 614 | v -1.198821 2.459728 -1.229864 615 | v -1.382645 2.432923 -1.081286 616 | v -1.557775 2.390821 -0.925910 617 | v -1.693538 2.356539 -0.760691 618 | v -0.199813 2.221441 -2.006309 619 | v -0.399769 2.260427 -1.931490 620 | v -0.595741 2.287874 -1.846815 621 | v -0.796555 2.323002 -1.723125 622 | v -1.002420 2.337823 -1.590514 623 | v -1.202904 2.337823 -1.444854 624 | v -1.392640 2.323002 -1.290044 625 | v -1.572331 2.287874 -1.137281 626 | v -1.713421 2.260427 -0.977066 627 | v -1.846367 2.221441 -0.810017 628 | v -0.199701 2.076747 -2.155746 629 | v -0.398377 2.119021 -2.085916 630 | v -0.595012 2.150433 -2.005393 631 | v -0.788597 2.170820 -1.914590 632 | v -0.997026 2.192729 -1.788262 633 | v -1.198821 2.200047 -1.650036 634 | v -1.392640 2.192729 -1.500831 635 | v -1.577193 2.170820 -1.341641 636 | v -1.723373 2.150433 -1.185591 637 | v -1.860719 2.119021 -1.023463 638 | v -1.988526 2.076747 -0.856089 639 | v -0.198127 1.915032 -2.300738 640 | v -0.397710 1.961521 -2.234784 641 | v -0.597282 1.997632 -2.157017 642 | v -0.792454 2.022127 -2.069546 643 | v -0.976590 2.040383 -1.970560 644 | v -1.182409 2.055168 -1.837987 645 | v -1.382645 2.055168 -1.692507 646 | v -1.572331 2.040383 -1.537729 647 | v -1.723373 2.022127 -1.393193 648 | v -1.866875 1.997632 -1.234604 649 | v -2.002507 1.961521 -1.068831 650 | v -2.126908 1.915032 -0.899397 651 | v -0.197965 1.750644 -2.428179 652 | v -0.394966 1.793785 -2.371990 653 | v -0.595160 1.833210 -2.298940 654 | v -0.792248 1.863068 -2.213892 655 | v -0.977787 1.884809 -2.119299 656 | v -1.158562 1.897367 -2.014382 657 | v -1.362785 1.903816 -1.875713 658 | v -1.557775 1.897367 -1.724336 659 | v -1.713421 1.884809 -1.584830 660 | v -1.860719 1.863068 -1.437603 661 | v -2.002507 1.833210 -1.276442 662 | v -2.133845 1.793785 -1.108620 663 | v -2.248161 1.750644 -0.938625 664 | v -0.197451 1.576280 -2.544868 665 | v -0.395246 1.622443 -2.492280 666 | v -0.589237 1.660874 -2.427817 667 | v -0.787982 1.694458 -2.346890 668 | v -0.974591 1.717960 -2.258049 669 | v -1.157718 1.734259 -2.156857 670 | v -1.333391 1.742652 -2.045784 671 | v -1.533615 1.742652 -1.900313 672 | v -1.693538 1.734259 -1.767561 673 | v -1.846367 1.717960 -1.624666 674 | v -1.988526 1.694458 -1.474644 675 | v -2.126908 1.660874 -1.310634 676 | v -2.248161 1.622443 -1.146058 677 | v -2.359298 1.576280 -0.974194 678 | v -0.197273 1.395761 -2.648195 679 | v -0.393601 1.443200 -2.600433 680 | v -0.588046 1.483732 -2.540225 681 | v -0.779676 1.517163 -2.467858 682 | v -0.967574 1.543332 -2.383679 683 | v -1.150841 1.562114 -2.288092 684 | v -1.328600 1.573419 -2.181553 685 | v -1.500000 1.577193 -2.064573 686 | v -1.664220 1.573419 -1.937711 687 | v -1.820476 1.562114 -1.801574 688 | v -1.968017 1.543332 -1.656815 689 | v -2.106139 1.517163 -1.504126 690 | v -2.234181 1.483732 -1.344237 691 | v -2.351529 1.443200 -1.177915 692 | v -2.457622 1.395761 -1.005955 693 | v 0.121921 1.188336 -2.751907 694 | v 0.319482 1.240356 -2.712830 695 | v 0.243259 1.029344 -2.807361 696 | v 0.517595 1.285645 -2.660679 697 | v 0.442241 1.078212 -2.764396 698 | v 0.363432 0.865425 -2.849378 699 | v 0.711686 1.323800 -2.596354 700 | v 0.639069 1.121829 -2.707968 701 | v 0.562296 0.912563 -2.801973 702 | v 0.481866 0.697363 -2.877758 703 | v 0.911403 1.354708 -2.516766 704 | v 0.840958 1.156586 -2.637252 705 | v 0.765539 0.948974 -2.741058 706 | v 0.686700 0.736152 -2.826044 707 | v 0.597994 0.525964 -2.892363 708 | v 1.098082 1.378017 -2.428020 709 | v 1.038459 1.185308 -2.552773 710 | v 0.966423 0.981474 -2.665096 711 | v 0.888014 0.771168 -2.759843 712 | v 0.802143 0.563368 -2.835345 713 | v 0.711259 0.352048 -2.893125 714 | v 1.281404 1.393781 -2.327096 715 | v 1.224858 1.204681 -2.459363 716 | v 1.160191 1.009832 -2.575693 717 | v 1.084775 0.802230 -2.679494 718 | v 1.004075 0.596917 -2.763245 719 | v 0.915637 0.386911 -2.830531 720 | v 0.821120 0.176446 -2.880040 721 | v 1.457137 1.402011 -2.216105 722 | v 1.405290 1.218184 -2.353973 723 | v 1.344778 1.026847 -2.477328 724 | v 1.275976 0.829180 -2.585410 725 | v 1.199307 0.626400 -2.677552 726 | v 1.115244 0.419758 -2.753186 727 | v 1.024305 0.210528 -2.811846 728 | v 0.927051 0.000000 -2.853170 729 | v 1.657361 1.402011 -2.070633 730 | v 1.610351 1.222325 -2.216459 731 | v 1.553911 1.032510 -2.349316 732 | v 1.489324 0.837548 -2.465852 733 | v 1.412751 0.626761 -2.571246 734 | v 1.331872 0.421289 -2.654926 735 | v 1.242818 0.210592 -2.722325 736 | v 1.148050 0.000000 -2.771638 737 | v 1.817225 1.393781 -1.937800 738 | v 1.804503 1.218184 -2.063927 739 | v 1.754147 1.032510 -2.203835 740 | v 1.692763 0.840343 -2.329888 741 | v 1.621950 0.632404 -2.443224 742 | v 1.540126 0.420172 -2.539974 743 | v 1.455625 0.210748 -2.614717 744 | v 1.361971 0.000000 -2.673020 745 | v 1.969859 1.378017 -1.794638 746 | v 1.960492 1.204681 -1.924894 747 | v 1.940520 1.026847 -2.044497 748 | v 1.884938 0.837548 -2.178421 749 | v 1.822434 0.632404 -2.297564 750 | v 1.745856 0.421603 -2.402964 751 | v 1.657254 0.210787 -2.491802 752 | v 1.567496 0.000000 -2.557920 753 | v 2.111948 1.354708 -1.644520 754 | v 2.106930 1.185308 -1.776483 755 | v 2.091111 1.009832 -1.899341 756 | v 2.064573 0.829180 -2.012461 757 | v 2.008836 0.626761 -2.138165 758 | v 1.939733 0.420172 -2.249642 759 | v 1.857725 0.210787 -2.346152 760 | v 1.763356 0.000000 -2.427051 761 | v 2.249357 1.323800 -1.479171 762 | v 2.248305 1.156586 -1.614754 763 | v 2.236016 0.981474 -1.742683 764 | v 2.213136 0.802230 -1.859692 765 | v 2.175897 0.626400 -1.968018 766 | v 2.113414 0.421289 -2.087103 767 | v 2.036930 0.210748 -2.192373 768 | v 1.948344 0.000000 -2.281218 769 | v 2.370510 1.285645 -1.314457 770 | v 2.377948 1.121829 -1.444599 771 | v 2.370337 0.948974 -1.575104 772 | v 2.350355 0.771168 -1.697390 773 | v 2.317726 0.596917 -1.808821 774 | v 2.273806 0.419758 -1.911442 775 | v 2.205033 0.210592 -2.023235 776 | v 2.121320 0.000000 -2.121320 777 | v 2.481329 1.240356 -1.142156 778 | v 2.492437 1.078212 -1.274841 779 | v 2.491076 0.912563 -1.400632 780 | v 2.475525 0.736152 -1.526386 781 | v 2.448698 0.563368 -1.639053 782 | v 2.409048 0.386911 -1.745505 783 | v 2.357697 0.210528 -1.843080 784 | v 2.281218 0.000000 -1.948344 785 | v 2.579543 1.188336 -0.966340 786 | v 2.594788 1.029344 -1.098875 787 | v 2.597613 0.865425 -1.226151 788 | v 2.588005 0.697363 -1.347558 789 | v 2.566011 0.525964 -1.462515 790 | v 2.531734 0.352048 -1.570472 791 | v 2.485340 0.176446 -1.670913 792 | v 2.427051 0.000000 -1.763356 793 | v 2.654895 1.188336 -0.734432 794 | v 2.678780 1.240356 -0.534465 795 | v 2.745130 1.029344 -0.636169 796 | v 2.690402 1.285645 -0.329933 797 | v 2.765756 1.078212 -0.433649 798 | v 2.822227 0.865425 -0.534862 799 | v 2.689203 1.323800 -0.125464 800 | v 2.772914 1.121829 -0.229018 801 | v 2.838593 0.912563 -0.331082 802 | v 2.885815 0.697363 -0.430994 803 | v 2.675226 1.354708 0.089073 804 | v 2.768046 1.156586 -0.015157 805 | v 2.843465 0.948974 -0.118963 806 | v 2.899929 0.736152 -0.220205 807 | v 2.935591 0.525964 -0.325064 808 | v 2.648511 1.378017 0.294038 809 | v 2.748733 1.185308 0.198783 810 | v 2.833298 0.981474 0.095563 811 | v 2.899178 0.771168 -0.008287 812 | v 2.944449 0.563368 -0.113286 813 | v 2.971317 0.352048 -0.217577 814 | v 2.609176 1.393781 0.499576 815 | v 2.717495 1.204681 0.404924 816 | v 2.808149 1.009832 0.307475 817 | v 2.883564 0.802230 0.203673 818 | v 2.938279 0.596917 0.101042 819 | v 2.974943 0.386911 -0.003859 820 | v 2.992821 0.176446 -0.109050 821 | v 2.557920 1.402011 0.701005 822 | v 2.673020 1.218184 0.609092 823 | v 2.771638 1.026847 0.513424 824 | v 2.853170 0.829180 0.414590 825 | v 2.917110 0.626400 0.313200 826 | v 2.963065 0.419758 0.209879 827 | v 2.990752 0.210528 0.105264 828 | v 3.000000 0.000000 0.000000 829 | v 2.481442 1.402011 0.936383 830 | v 2.605603 1.222325 0.846612 831 | v 2.714517 1.032510 0.751879 832 | v 2.805391 0.837548 0.654441 833 | v 2.881964 0.626761 0.549048 834 | v 2.936556 0.421289 0.446268 835 | v 2.973137 0.210592 0.340745 836 | v 2.990752 0.000000 0.235377 837 | v 2.404511 1.393781 1.129470 838 | v 2.520534 1.218184 1.078396 839 | v 2.638034 1.032510 0.987270 840 | v 2.738947 0.840343 0.889938 841 | v 2.824854 0.632404 0.787568 842 | v 2.891584 0.420172 0.679852 843 | v 2.936556 0.210748 0.576390 844 | v 2.963065 0.000000 0.469303 845 | v 2.315522 1.378017 1.318874 846 | v 2.436508 1.204681 1.269713 847 | v 2.544086 1.026847 1.213760 848 | v 2.654280 0.837548 1.119514 849 | v 2.748276 0.632404 1.023252 850 | v 2.824854 0.421603 0.917851 851 | v 2.881964 0.210787 0.806133 852 | v 2.917110 0.000000 0.700336 853 | v 2.216659 1.354708 1.500397 854 | v 2.340613 1.185308 1.454846 855 | v 2.452569 1.009832 1.401836 856 | v 2.551952 0.829180 1.341641 857 | v 2.654280 0.626761 1.249787 858 | v 2.738947 0.420172 1.149618 859 | v 2.805391 0.210787 1.041800 860 | v 2.853170 0.000000 0.927051 861 | v 2.101865 1.323800 1.682176 862 | v 2.230487 1.156586 1.639279 863 | v 2.348357 0.981474 1.588058 864 | v 2.452569 0.802230 1.530141 865 | v 2.544086 0.626400 1.461250 866 | v 2.638034 0.421289 1.365026 867 | v 2.714517 0.210748 1.259755 868 | v 2.771638 0.000000 1.148050 869 | v 1.982651 1.285645 1.848300 870 | v 2.108721 1.121829 1.815157 871 | v 2.230487 0.948974 1.767590 872 | v 2.340613 0.771168 1.710798 873 | v 2.436508 0.596917 1.645332 874 | v 2.520534 0.419758 1.571850 875 | v 2.605603 0.210592 1.471897 876 | v 2.673020 0.000000 1.361971 877 | v 1.853028 1.240356 2.006939 878 | v 1.982651 1.078212 1.976501 879 | v 2.101865 0.912563 1.936335 880 | v 2.216659 0.736152 1.882685 881 | v 2.315522 0.563368 1.822355 882 | v 2.404511 0.386911 1.751750 883 | v 2.481442 0.210528 1.672760 884 | v 2.557920 0.000000 1.567496 885 | v 1.716167 1.188336 2.154676 886 | v 1.846926 1.029344 2.128219 887 | v 1.968845 0.865425 2.091576 888 | v 2.081342 0.697363 2.044921 889 | v 2.183876 0.525964 1.988479 890 | v 2.275957 0.352048 1.922520 891 | v 2.357145 0.176446 1.847359 892 | v 2.427051 0.000000 1.763356 893 | v 1.518894 1.188336 2.298003 894 | v 1.336095 1.240356 2.382513 895 | v 1.453325 1.029344 2.414187 896 | v 1.145165 1.285645 2.456769 897 | v 1.267091 1.078212 2.496386 898 | v 1.380800 0.865425 2.518816 899 | v 0.950333 1.323800 2.518814 900 | v 1.074686 1.121829 2.566427 901 | v 1.192052 0.912563 2.597353 902 | v 1.301666 0.697363 2.611389 903 | v 0.741977 1.354708 2.571816 904 | v 0.869788 1.156586 2.627884 905 | v 0.991820 0.948974 2.667535 906 | v 1.105555 0.736152 2.689950 907 | v 1.216301 0.525964 2.691463 908 | v 0.538788 1.378017 2.609746 909 | v 0.660351 1.185308 2.675627 910 | v 0.784651 0.981474 2.724157 911 | v 0.903777 0.771168 2.754721 912 | v 1.017627 0.563368 2.765331 913 | v 1.125116 0.352048 2.758655 914 | v 0.331155 1.393781 2.635851 915 | v 0.454647 1.204681 2.709620 916 | v 0.575340 1.009832 2.765723 917 | v 0.697366 0.802230 2.805371 918 | v 0.811881 0.596917 2.825693 919 | v 0.922978 0.386911 2.828146 920 | v 1.028545 0.176446 2.812643 921 | v 0.123745 1.402011 2.649349 922 | v 0.246727 1.218184 2.730412 923 | v 0.368188 1.026847 2.794642 924 | v 0.487380 0.829180 2.841641 925 | v 0.603566 0.626400 2.871120 926 | v 0.716031 0.419758 2.882899 927 | v 0.824081 0.210528 2.876903 928 | v 0.927051 0.000000 2.853170 929 | v -0.123745 1.402011 2.649349 930 | v 0.000000 1.222325 2.739694 931 | v 0.123753 1.032510 2.814002 932 | v 0.244503 0.837548 2.870319 933 | v 0.368401 0.626761 2.910576 934 | v 0.483019 0.421289 2.930735 935 | v 0.594682 0.210592 2.932917 936 | v 0.700336 0.000000 2.917110 937 | v -0.331155 1.393781 2.635851 938 | v -0.246727 1.218184 2.730412 939 | v -0.123753 1.032510 2.814002 940 | v 0.000000 0.840343 2.879900 941 | v 0.123906 0.632404 2.929968 942 | v 0.246971 0.420172 2.960145 943 | v 0.359266 0.210748 2.970945 944 | v 0.469303 0.000000 2.963065 945 | v -0.538788 1.378017 2.609746 946 | v -0.454647 1.204681 2.709620 947 | v -0.368188 1.026847 2.794642 948 | v -0.244503 0.837548 2.870319 949 | v -0.123906 0.632404 2.929968 950 | v 0.000000 0.421603 2.970227 951 | v 0.123898 0.210787 2.990020 952 | v 0.235377 0.000000 2.990752 953 | v -0.741977 1.354708 2.571816 954 | v -0.660351 1.185308 2.675627 955 | v -0.575340 1.009832 2.765723 956 | v -0.487380 0.829180 2.841641 957 | v -0.368401 0.626761 2.910576 958 | v -0.246971 0.420172 2.960145 959 | v -0.123898 0.210787 2.990020 960 | v 0.000000 0.000000 3.000000 961 | v -0.950333 1.323800 2.518814 962 | v -0.869788 1.156586 2.627884 963 | v -0.784651 0.981474 2.724157 964 | v -0.697366 0.802230 2.805371 965 | v -0.603566 0.626400 2.871120 966 | v -0.483019 0.421289 2.930735 967 | v -0.359266 0.210748 2.970945 968 | v -0.235377 0.000000 2.990752 969 | v -1.145165 1.285645 2.456769 970 | v -1.074686 1.121829 2.566427 971 | v -0.991820 0.948974 2.667535 972 | v -0.903777 0.771168 2.754721 973 | v -0.811881 0.596917 2.825693 974 | v -0.716031 0.419758 2.882899 975 | v -0.594682 0.210592 2.932917 976 | v -0.469303 0.000000 2.963065 977 | v -1.336095 1.240356 2.382513 978 | v -1.267091 1.078212 2.496386 979 | v -1.192052 0.912563 2.597353 980 | v -1.105555 0.736152 2.689950 981 | v -1.017627 0.563368 2.765331 982 | v -0.922978 0.386911 2.828146 983 | v -0.824081 0.210528 2.876903 984 | v -0.700336 0.000000 2.917110 985 | v -1.518894 1.188336 2.298003 986 | v -1.453325 1.029344 2.414187 987 | v -1.380800 0.865425 2.518816 988 | v -1.301666 0.697363 2.611389 989 | v -1.216301 0.525964 2.691463 990 | v -1.125116 0.352048 2.758655 991 | v -1.028545 0.176446 2.812643 992 | v -0.927051 0.000000 2.853170 993 | v -1.716167 1.188336 2.154676 994 | v -1.853028 1.240356 2.006939 995 | v -1.846926 1.029344 2.128219 996 | v -1.982651 1.285645 1.848300 997 | v -1.982651 1.078212 1.976501 998 | v -1.968845 0.865425 2.091576 999 | v -2.101865 1.323800 1.682176 1000 | v -2.108721 1.121829 1.815157 1001 | v -2.101865 0.912563 1.936335 1002 | v -2.081342 0.697363 2.044921 1003 | v -2.216659 1.354708 1.500397 1004 | v -2.230487 1.156586 1.639279 1005 | v -2.230487 0.948974 1.767590 1006 | v -2.216659 0.736152 1.882685 1007 | v -2.183876 0.525964 1.988479 1008 | v -2.315522 1.378017 1.318874 1009 | v -2.340613 1.185308 1.454846 1010 | v -2.348357 0.981474 1.588058 1011 | v -2.340613 0.771168 1.710798 1012 | v -2.315522 0.563368 1.822355 1013 | v -2.275957 0.352048 1.922520 1014 | v -2.404511 1.393781 1.129470 1015 | v -2.436508 1.204681 1.269713 1016 | v -2.452569 1.009832 1.401836 1017 | v -2.452569 0.802230 1.530141 1018 | v -2.436508 0.596917 1.645332 1019 | v -2.404511 0.386911 1.751750 1020 | v -2.357145 0.176446 1.847359 1021 | v -2.481442 1.402011 0.936383 1022 | v -2.520534 1.218184 1.078396 1023 | v -2.544086 1.026847 1.213760 1024 | v -2.551952 0.829180 1.341641 1025 | v -2.544086 0.626400 1.461250 1026 | v -2.520534 0.419758 1.571850 1027 | v -2.481442 0.210528 1.672760 1028 | v -2.427051 0.000000 1.763356 1029 | v -2.557920 1.402011 0.701005 1030 | v -2.605603 1.222325 0.846612 1031 | v -2.638034 1.032510 0.987270 1032 | v -2.654280 0.837548 1.119514 1033 | v -2.654280 0.626761 1.249787 1034 | v -2.638034 0.421289 1.365026 1035 | v -2.605603 0.210592 1.471897 1036 | v -2.557920 0.000000 1.567496 1037 | v -2.609176 1.393781 0.499576 1038 | v -2.673020 1.218184 0.609092 1039 | v -2.714517 1.032510 0.751879 1040 | v -2.738947 0.840343 0.889938 1041 | v -2.748276 0.632404 1.023252 1042 | v -2.738947 0.420172 1.149618 1043 | v -2.714517 0.210748 1.259755 1044 | v -2.673020 0.000000 1.361971 1045 | v -2.648511 1.378017 0.294038 1046 | v -2.717495 1.204681 0.404924 1047 | v -2.771638 1.026847 0.513424 1048 | v -2.805391 0.837548 0.654441 1049 | v -2.824854 0.632404 0.787568 1050 | v -2.824854 0.421603 0.917851 1051 | v -2.805391 0.210787 1.041800 1052 | v -2.771638 0.000000 1.148050 1053 | v -2.675226 1.354708 0.089073 1054 | v -2.748733 1.185308 0.198783 1055 | v -2.808149 1.009832 0.307475 1056 | v -2.853170 0.829180 0.414590 1057 | v -2.881964 0.626761 0.549048 1058 | v -2.891584 0.420172 0.679852 1059 | v -2.881964 0.210787 0.806133 1060 | v -2.853170 0.000000 0.927051 1061 | v -2.689203 1.323800 -0.125464 1062 | v -2.768046 1.156586 -0.015157 1063 | v -2.833298 0.981474 0.095563 1064 | v -2.883564 0.802230 0.203673 1065 | v -2.917110 0.626400 0.313200 1066 | v -2.936556 0.421289 0.446268 1067 | v -2.936556 0.210748 0.576390 1068 | v -2.917110 0.000000 0.700336 1069 | v -2.690402 1.285645 -0.329933 1070 | v -2.772914 1.121829 -0.229018 1071 | v -2.843465 0.948974 -0.118963 1072 | v -2.899178 0.771168 -0.008287 1073 | v -2.938279 0.596917 0.101042 1074 | v -2.963065 0.419758 0.209879 1075 | v -2.973137 0.210592 0.340745 1076 | v -2.963065 0.000000 0.469303 1077 | v -2.678780 1.240356 -0.534465 1078 | v -2.765756 1.078212 -0.433649 1079 | v -2.838593 0.912563 -0.331082 1080 | v -2.899929 0.736152 -0.220205 1081 | v -2.944449 0.563368 -0.113286 1082 | v -2.974943 0.386911 -0.003859 1083 | v -2.990752 0.210528 0.105264 1084 | v -2.990752 0.000000 0.235377 1085 | v -2.654895 1.188336 -0.734432 1086 | v -2.745130 1.029344 -0.636169 1087 | v -2.822227 0.865425 -0.534862 1088 | v -2.885815 0.697363 -0.430994 1089 | v -2.935591 0.525964 -0.325064 1090 | v -2.971317 0.352048 -0.217577 1091 | v -2.992821 0.176446 -0.109050 1092 | v -3.000000 0.000000 0.000000 1093 | v -2.579543 1.188336 -0.966340 1094 | v -2.481329 1.240356 -1.142156 1095 | v -2.594788 1.029344 -1.098875 1096 | v -2.370510 1.285645 -1.314457 1097 | v -2.492437 1.078212 -1.274841 1098 | v -2.597613 0.865425 -1.226151 1099 | v -2.249357 1.323800 -1.479171 1100 | v -2.377948 1.121829 -1.444599 1101 | v -2.491076 0.912563 -1.400632 1102 | v -2.588005 0.697363 -1.347558 1103 | v -2.111948 1.354708 -1.644520 1104 | v -2.248305 1.156586 -1.614754 1105 | v -2.370337 0.948974 -1.575104 1106 | v -2.475525 0.736152 -1.526386 1107 | v -2.566011 0.525964 -1.462515 1108 | v -1.969859 1.378017 -1.794638 1109 | v -2.106930 1.185308 -1.776483 1110 | v -2.236016 0.981474 -1.742683 1111 | v -2.350355 0.771168 -1.697390 1112 | v -2.448698 0.563368 -1.639053 1113 | v -2.531734 0.352048 -1.570472 1114 | v -1.817225 1.393781 -1.937800 1115 | v -1.960492 1.204681 -1.924894 1116 | v -2.091111 1.009832 -1.899341 1117 | v -2.213136 0.802230 -1.859692 1118 | v -2.317726 0.596917 -1.808821 1119 | v -2.409048 0.386911 -1.745505 1120 | v -2.485340 0.176446 -1.670913 1121 | v -1.657361 1.402011 -2.070633 1122 | v -1.804503 1.218184 -2.063927 1123 | v -1.940520 1.026847 -2.044497 1124 | v -2.064573 0.829180 -2.012461 1125 | v -2.175897 0.626400 -1.968018 1126 | v -2.273806 0.419758 -1.911442 1127 | v -2.357697 0.210528 -1.843080 1128 | v -2.427051 0.000000 -1.763356 1129 | v -1.457137 1.402011 -2.216105 1130 | v -1.610351 1.222325 -2.216459 1131 | v -1.754147 1.032510 -2.203835 1132 | v -1.884938 0.837548 -2.178421 1133 | v -2.008836 0.626761 -2.138165 1134 | v -2.113414 0.421289 -2.087103 1135 | v -2.205033 0.210592 -2.023235 1136 | v -2.281218 0.000000 -1.948344 1137 | v -1.281404 1.393781 -2.327096 1138 | v -1.405290 1.218184 -2.353973 1139 | v -1.553911 1.032510 -2.349316 1140 | v -1.692763 0.840343 -2.329888 1141 | v -1.822434 0.632404 -2.297564 1142 | v -1.939733 0.420172 -2.249642 1143 | v -2.036930 0.210748 -2.192373 1144 | v -2.121320 0.000000 -2.121320 1145 | v -1.098082 1.378017 -2.428020 1146 | v -1.224858 1.204681 -2.459363 1147 | v -1.344778 1.026847 -2.477328 1148 | v -1.489324 0.837548 -2.465852 1149 | v -1.621950 0.632404 -2.443224 1150 | v -1.745856 0.421603 -2.402964 1151 | v -1.857725 0.210787 -2.346152 1152 | v -1.948344 0.000000 -2.281218 1153 | v -0.911403 1.354708 -2.516766 1154 | v -1.038459 1.185308 -2.552773 1155 | v -1.160191 1.009832 -2.575693 1156 | v -1.275976 0.829180 -2.585410 1157 | v -1.412751 0.626761 -2.571246 1158 | v -1.540126 0.420172 -2.539974 1159 | v -1.657254 0.210787 -2.491802 1160 | v -1.763356 0.000000 -2.427051 1161 | v -0.711686 1.323800 -2.596354 1162 | v -0.840958 1.156586 -2.637252 1163 | v -0.966423 0.981474 -2.665096 1164 | v -1.084775 0.802230 -2.679494 1165 | v -1.199307 0.626400 -2.677552 1166 | v -1.331872 0.421289 -2.654926 1167 | v -1.455625 0.210748 -2.614717 1168 | v -1.567496 0.000000 -2.557920 1169 | v -0.517595 1.285645 -2.660679 1170 | v -0.639069 1.121829 -2.707968 1171 | v -0.765539 0.948974 -2.741058 1172 | v -0.888014 0.771168 -2.759843 1173 | v -1.004075 0.596917 -2.763245 1174 | v -1.115244 0.419758 -2.753186 1175 | v -1.242818 0.210592 -2.722325 1176 | v -1.361971 0.000000 -2.673020 1177 | v -0.319482 1.240356 -2.712830 1178 | v -0.442241 1.078212 -2.764396 1179 | v -0.562296 0.912563 -2.801973 1180 | v -0.686700 0.736152 -2.826044 1181 | v -0.802143 0.563368 -2.835345 1182 | v -0.915637 0.386911 -2.830531 1183 | v -1.024305 0.210528 -2.811846 1184 | v -1.148050 0.000000 -2.771638 1185 | v -0.121921 1.188336 -2.751907 1186 | v -0.243259 1.029344 -2.807361 1187 | v -0.363432 0.865425 -2.849378 1188 | v -0.481866 0.697363 -2.877758 1189 | v -0.597994 0.525964 -2.892363 1190 | v -0.711259 0.352048 -2.893125 1191 | v -0.821120 0.176446 -2.880040 1192 | v -0.927051 0.000000 -2.853170 1193 | v 2.990752 0.000000 -0.235377 1194 | v 2.963065 0.000000 -0.469303 1195 | v 2.974943 0.176484 -0.344338 1196 | v 2.917110 0.000000 -0.700336 1197 | v 2.938279 0.176574 -0.579086 1198 | v 2.944449 0.353272 -0.453229 1199 | v 2.853170 0.000000 -0.927051 1200 | v 2.883564 0.176597 -0.808622 1201 | v 2.899178 0.352289 -0.686047 1202 | v 2.899929 0.526175 -0.559956 1203 | v 2.771638 0.000000 -1.148050 1204 | v 2.808149 0.176597 -1.040728 1205 | v 2.833298 0.353454 -0.920594 1206 | v 2.843465 0.530798 -0.795587 1207 | v 2.838593 0.704240 -0.668157 1208 | v 2.673020 0.000000 -1.361971 1209 | v 2.717495 0.176574 -1.258587 1210 | v 2.748733 0.352289 -1.149070 1211 | v 2.768046 0.530798 -1.027704 1212 | v 2.772914 0.706537 -0.900974 1213 | v 2.765756 0.870059 -0.770448 1214 | v 2.557920 0.000000 -1.567496 1215 | v 2.609176 0.176484 -1.470052 1216 | v 2.648511 0.353272 -1.364034 1217 | v 2.675226 0.526175 -1.251522 1218 | v 2.689203 0.704240 -1.127933 1219 | v 2.690402 0.870059 -1.002365 1220 | v 2.678780 1.032744 -0.870388 1221 | v 1.148050 0.000000 2.771638 1222 | v 1.361971 0.000000 2.673020 1223 | v 1.246793 0.176484 2.722933 1224 | v 1.567496 0.000000 2.557920 1225 | v 1.458721 0.176574 2.615522 1226 | v 1.340931 0.353272 2.660283 1227 | v 1.763356 0.000000 2.427051 1228 | v 1.660115 0.176597 2.492555 1229 | v 1.548365 0.352289 2.545282 1230 | v 1.428677 0.526175 2.584961 1231 | v 1.948344 0.000000 2.281218 1232 | v 1.857557 0.176597 2.349105 1233 | v 1.751074 0.353454 2.410147 1234 | v 1.635327 0.530798 2.458447 1235 | v 1.512628 0.704240 2.493191 1236 | v 2.121320 0.000000 2.121320 1237 | v 2.036739 0.176574 2.195567 1238 | v 1.942236 0.352289 2.259118 1239 | v 1.832778 0.530798 2.314990 1240 | v 1.713755 0.706537 2.358781 1241 | v 1.587405 0.870059 2.392309 1242 | v 2.281218 0.000000 1.948344 1243 | v 2.204383 0.176484 2.027203 1244 | v 2.115708 0.353272 2.097374 1245 | v 2.016958 0.526175 2.157549 1246 | v 1.903738 0.704240 2.209033 1247 | v 1.784686 0.870059 2.248976 1248 | v 1.655577 1.032744 2.278707 1249 | v -2.281218 0.000000 1.948344 1250 | v -2.121320 0.000000 2.121320 1251 | v -2.204383 0.176484 2.027203 1252 | v -1.948344 0.000000 2.281218 1253 | v -2.036739 0.176574 2.195567 1254 | v -2.115708 0.353272 2.097374 1255 | v -1.763356 0.000000 2.427051 1256 | v -1.857557 0.176597 2.349105 1257 | v -1.942236 0.352289 2.259118 1258 | v -2.016958 0.526175 2.157549 1259 | v -1.567496 0.000000 2.557920 1260 | v -1.660115 0.176597 2.492555 1261 | v -1.751074 0.353454 2.410147 1262 | v -1.832778 0.530798 2.314990 1263 | v -1.903738 0.704240 2.209033 1264 | v -1.361971 0.000000 2.673020 1265 | v -1.458721 0.176574 2.615522 1266 | v -1.548365 0.352289 2.545282 1267 | v -1.635327 0.530798 2.458447 1268 | v -1.713755 0.706537 2.358781 1269 | v -1.784686 0.870059 2.248976 1270 | v -1.148050 0.000000 2.771638 1271 | v -1.246793 0.176484 2.722933 1272 | v -1.340931 0.353272 2.660283 1273 | v -1.428677 0.526175 2.584961 1274 | v -1.512628 0.704240 2.493191 1275 | v -1.587405 0.870059 2.392309 1276 | v -1.655577 1.032744 2.278707 1277 | v -2.557920 0.000000 -1.567496 1278 | v -2.673020 0.000000 -1.361971 1279 | v -2.609176 0.176484 -1.470052 1280 | v -2.771638 0.000000 -1.148050 1281 | v -2.717495 0.176574 -1.258587 1282 | v -2.648511 0.353272 -1.364034 1283 | v -2.853170 0.000000 -0.927051 1284 | v -2.808149 0.176597 -1.040728 1285 | v -2.748733 0.352289 -1.149070 1286 | v -2.675226 0.526175 -1.251522 1287 | v -2.917110 0.000000 -0.700336 1288 | v -2.883564 0.176597 -0.808622 1289 | v -2.833298 0.353454 -0.920594 1290 | v -2.768046 0.530798 -1.027704 1291 | v -2.689203 0.704240 -1.127933 1292 | v -2.963065 0.000000 -0.469303 1293 | v -2.938279 0.176574 -0.579086 1294 | v -2.899178 0.352289 -0.686047 1295 | v -2.843465 0.530798 -0.795587 1296 | v -2.772914 0.706537 -0.900974 1297 | v -2.690402 0.870059 -1.002365 1298 | v -2.990752 0.000000 -0.235377 1299 | v -2.974943 0.176484 -0.344338 1300 | v -2.944449 0.353272 -0.453229 1301 | v -2.899929 0.526175 -0.559956 1302 | v -2.838593 0.704240 -0.668157 1303 | v -2.765756 0.870059 -0.770448 1304 | v -2.678780 1.032744 -0.870388 1305 | v 0.700336 0.000000 -2.917110 1306 | v 0.469303 0.000000 -2.963065 1307 | v 0.591823 0.176484 -2.935745 1308 | v 0.235377 0.000000 -2.990752 1309 | v 0.357235 0.176574 -2.973416 1310 | v 0.478839 0.353272 -2.940393 1311 | v 0.000000 0.000000 -3.000000 1312 | v 0.122026 0.176597 -2.992311 1313 | v 0.243426 0.352289 -2.969282 1314 | v 0.363578 0.526175 -2.931033 1315 | v -0.235377 0.000000 -2.990752 1316 | v -0.122026 0.176597 -2.992311 1317 | v 0.000000 0.353454 -2.979105 1318 | v 0.122031 0.530798 -2.950146 1319 | v 0.241719 0.704240 -2.906135 1320 | v -0.469303 0.000000 -2.963065 1321 | v -0.357235 0.176574 -2.973416 1322 | v -0.243426 0.352289 -2.969282 1323 | v -0.122031 0.530798 -2.950146 1324 | v 0.000000 0.706537 -2.915614 1325 | v 0.121926 0.870059 -2.868472 1326 | v -0.700336 0.000000 -2.917110 1327 | v -0.591823 0.176484 -2.935745 1328 | v -0.478839 0.353272 -2.940393 1329 | v -0.363578 0.526175 -2.931033 1330 | v -0.241719 0.704240 -2.906135 1331 | v -0.121926 0.870059 -2.868472 1332 | v 0.000000 1.032744 -2.816636 1333 | # 1321 vertices, 0 vertices normals 1334 | 1335 | f 1 3 2 1336 | f 2 5 4 1337 | f 3 6 5 1338 | f 5 2 3 1339 | f 4 8 7 1340 | f 5 9 8 1341 | f 6 10 9 1342 | f 8 4 5 1343 | f 9 5 6 1344 | f 7 12 11 1345 | f 8 13 12 1346 | f 9 14 13 1347 | f 10 15 14 1348 | f 12 7 8 1349 | f 13 8 9 1350 | f 14 9 10 1351 | f 11 17 16 1352 | f 12 18 17 1353 | f 13 19 18 1354 | f 14 20 19 1355 | f 15 21 20 1356 | f 17 11 12 1357 | f 18 12 13 1358 | f 19 13 14 1359 | f 20 14 15 1360 | f 16 23 22 1361 | f 17 24 23 1362 | f 18 25 24 1363 | f 19 26 25 1364 | f 20 27 26 1365 | f 21 28 27 1366 | f 23 16 17 1367 | f 24 17 18 1368 | f 25 18 19 1369 | f 26 19 20 1370 | f 27 20 21 1371 | f 22 30 29 1372 | f 23 31 30 1373 | f 24 32 31 1374 | f 25 33 32 1375 | f 26 34 33 1376 | f 27 35 34 1377 | f 28 36 35 1378 | f 30 22 23 1379 | f 31 23 24 1380 | f 32 24 25 1381 | f 33 25 26 1382 | f 34 26 27 1383 | f 35 27 28 1384 | f 29 38 37 1385 | f 30 39 38 1386 | f 31 40 39 1387 | f 32 41 40 1388 | f 33 42 41 1389 | f 34 43 42 1390 | f 35 44 43 1391 | f 36 45 44 1392 | f 38 29 30 1393 | f 39 30 31 1394 | f 40 31 32 1395 | f 41 32 33 1396 | f 42 33 34 1397 | f 43 34 35 1398 | f 44 35 36 1399 | f 37 47 46 1400 | f 38 48 47 1401 | f 39 49 48 1402 | f 40 50 49 1403 | f 41 51 50 1404 | f 42 52 51 1405 | f 43 53 52 1406 | f 44 54 53 1407 | f 45 55 54 1408 | f 47 37 38 1409 | f 48 38 39 1410 | f 49 39 40 1411 | f 50 40 41 1412 | f 51 41 42 1413 | f 52 42 43 1414 | f 53 43 44 1415 | f 54 44 45 1416 | f 46 57 56 1417 | f 47 58 57 1418 | f 48 59 58 1419 | f 49 60 59 1420 | f 50 61 60 1421 | f 51 62 61 1422 | f 52 63 62 1423 | f 53 64 63 1424 | f 54 65 64 1425 | f 55 66 65 1426 | f 57 46 47 1427 | f 58 47 48 1428 | f 59 48 49 1429 | f 60 49 50 1430 | f 61 50 51 1431 | f 62 51 52 1432 | f 63 52 53 1433 | f 64 53 54 1434 | f 65 54 55 1435 | f 56 68 67 1436 | f 57 69 68 1437 | f 58 70 69 1438 | f 59 71 70 1439 | f 60 72 71 1440 | f 61 73 72 1441 | f 62 74 73 1442 | f 63 75 74 1443 | f 64 76 75 1444 | f 65 77 76 1445 | f 66 78 77 1446 | f 68 56 57 1447 | f 69 57 58 1448 | f 70 58 59 1449 | f 71 59 60 1450 | f 72 60 61 1451 | f 73 61 62 1452 | f 74 62 63 1453 | f 75 63 64 1454 | f 76 64 65 1455 | f 77 65 66 1456 | f 67 80 79 1457 | f 68 81 80 1458 | f 69 82 81 1459 | f 70 83 82 1460 | f 71 84 83 1461 | f 72 85 84 1462 | f 73 86 85 1463 | f 74 87 86 1464 | f 75 88 87 1465 | f 76 89 88 1466 | f 77 90 89 1467 | f 78 91 90 1468 | f 80 67 68 1469 | f 81 68 69 1470 | f 82 69 70 1471 | f 83 70 71 1472 | f 84 71 72 1473 | f 85 72 73 1474 | f 86 73 74 1475 | f 87 74 75 1476 | f 88 75 76 1477 | f 89 76 77 1478 | f 90 77 78 1479 | f 79 93 92 1480 | f 80 94 93 1481 | f 81 95 94 1482 | f 82 96 95 1483 | f 83 97 96 1484 | f 84 98 97 1485 | f 85 99 98 1486 | f 86 100 99 1487 | f 87 101 100 1488 | f 88 102 101 1489 | f 89 103 102 1490 | f 90 104 103 1491 | f 91 105 104 1492 | f 93 79 80 1493 | f 94 80 81 1494 | f 95 81 82 1495 | f 96 82 83 1496 | f 97 83 84 1497 | f 98 84 85 1498 | f 99 85 86 1499 | f 100 86 87 1500 | f 101 87 88 1501 | f 102 88 89 1502 | f 103 89 90 1503 | f 104 90 91 1504 | f 92 107 106 1505 | f 93 108 107 1506 | f 94 109 108 1507 | f 95 110 109 1508 | f 96 111 110 1509 | f 97 112 111 1510 | f 98 113 112 1511 | f 99 114 113 1512 | f 100 115 114 1513 | f 101 116 115 1514 | f 102 117 116 1515 | f 103 118 117 1516 | f 104 119 118 1517 | f 105 120 119 1518 | f 107 92 93 1519 | f 108 93 94 1520 | f 109 94 95 1521 | f 110 95 96 1522 | f 111 96 97 1523 | f 112 97 98 1524 | f 113 98 99 1525 | f 114 99 100 1526 | f 115 100 101 1527 | f 116 101 102 1528 | f 117 102 103 1529 | f 118 103 104 1530 | f 119 104 105 1531 | f 106 122 121 1532 | f 107 123 122 1533 | f 108 124 123 1534 | f 109 125 124 1535 | f 110 126 125 1536 | f 111 127 126 1537 | f 112 128 127 1538 | f 113 129 128 1539 | f 114 130 129 1540 | f 115 131 130 1541 | f 116 132 131 1542 | f 117 133 132 1543 | f 118 134 133 1544 | f 119 135 134 1545 | f 120 136 135 1546 | f 122 106 107 1547 | f 123 107 108 1548 | f 124 108 109 1549 | f 125 109 110 1550 | f 126 110 111 1551 | f 127 111 112 1552 | f 128 112 113 1553 | f 129 113 114 1554 | f 130 114 115 1555 | f 131 115 116 1556 | f 132 116 117 1557 | f 133 117 118 1558 | f 134 118 119 1559 | f 135 119 120 1560 | f 121 138 137 1561 | f 122 139 138 1562 | f 123 140 139 1563 | f 124 141 140 1564 | f 125 142 141 1565 | f 126 143 142 1566 | f 127 144 143 1567 | f 128 145 144 1568 | f 129 146 145 1569 | f 130 147 146 1570 | f 131 148 147 1571 | f 132 149 148 1572 | f 133 150 149 1573 | f 134 151 150 1574 | f 135 152 151 1575 | f 136 153 152 1576 | f 138 121 122 1577 | f 139 122 123 1578 | f 140 123 124 1579 | f 141 124 125 1580 | f 142 125 126 1581 | f 143 126 127 1582 | f 144 127 128 1583 | f 145 128 129 1584 | f 146 129 130 1585 | f 147 130 131 1586 | f 148 131 132 1587 | f 149 132 133 1588 | f 150 133 134 1589 | f 151 134 135 1590 | f 152 135 136 1591 | f 1 2 154 1592 | f 154 156 155 1593 | f 2 4 156 1594 | f 156 154 2 1595 | f 155 158 157 1596 | f 156 159 158 1597 | f 4 7 159 1598 | f 158 155 156 1599 | f 159 156 4 1600 | f 157 161 160 1601 | f 158 162 161 1602 | f 159 163 162 1603 | f 7 11 163 1604 | f 161 157 158 1605 | f 162 158 159 1606 | f 163 159 7 1607 | f 160 165 164 1608 | f 161 166 165 1609 | f 162 167 166 1610 | f 163 168 167 1611 | f 11 16 168 1612 | f 165 160 161 1613 | f 166 161 162 1614 | f 167 162 163 1615 | f 168 163 11 1616 | f 164 170 169 1617 | f 165 171 170 1618 | f 166 172 171 1619 | f 167 173 172 1620 | f 168 174 173 1621 | f 16 22 174 1622 | f 170 164 165 1623 | f 171 165 166 1624 | f 172 166 167 1625 | f 173 167 168 1626 | f 174 168 16 1627 | f 169 176 175 1628 | f 170 177 176 1629 | f 171 178 177 1630 | f 172 179 178 1631 | f 173 180 179 1632 | f 174 181 180 1633 | f 22 29 181 1634 | f 176 169 170 1635 | f 177 170 171 1636 | f 178 171 172 1637 | f 179 172 173 1638 | f 180 173 174 1639 | f 181 174 22 1640 | f 175 183 182 1641 | f 176 184 183 1642 | f 177 185 184 1643 | f 178 186 185 1644 | f 179 187 186 1645 | f 180 188 187 1646 | f 181 189 188 1647 | f 29 37 189 1648 | f 183 175 176 1649 | f 184 176 177 1650 | f 185 177 178 1651 | f 186 178 179 1652 | f 187 179 180 1653 | f 188 180 181 1654 | f 189 181 29 1655 | f 182 191 190 1656 | f 183 192 191 1657 | f 184 193 192 1658 | f 185 194 193 1659 | f 186 195 194 1660 | f 187 196 195 1661 | f 188 197 196 1662 | f 189 198 197 1663 | f 37 46 198 1664 | f 191 182 183 1665 | f 192 183 184 1666 | f 193 184 185 1667 | f 194 185 186 1668 | f 195 186 187 1669 | f 196 187 188 1670 | f 197 188 189 1671 | f 198 189 37 1672 | f 190 200 199 1673 | f 191 201 200 1674 | f 192 202 201 1675 | f 193 203 202 1676 | f 194 204 203 1677 | f 195 205 204 1678 | f 196 206 205 1679 | f 197 207 206 1680 | f 198 208 207 1681 | f 46 56 208 1682 | f 200 190 191 1683 | f 201 191 192 1684 | f 202 192 193 1685 | f 203 193 194 1686 | f 204 194 195 1687 | f 205 195 196 1688 | f 206 196 197 1689 | f 207 197 198 1690 | f 208 198 46 1691 | f 199 210 209 1692 | f 200 211 210 1693 | f 201 212 211 1694 | f 202 213 212 1695 | f 203 214 213 1696 | f 204 215 214 1697 | f 205 216 215 1698 | f 206 217 216 1699 | f 207 218 217 1700 | f 208 219 218 1701 | f 56 67 219 1702 | f 210 199 200 1703 | f 211 200 201 1704 | f 212 201 202 1705 | f 213 202 203 1706 | f 214 203 204 1707 | f 215 204 205 1708 | f 216 205 206 1709 | f 217 206 207 1710 | f 218 207 208 1711 | f 219 208 56 1712 | f 209 221 220 1713 | f 210 222 221 1714 | f 211 223 222 1715 | f 212 224 223 1716 | f 213 225 224 1717 | f 214 226 225 1718 | f 215 227 226 1719 | f 216 228 227 1720 | f 217 229 228 1721 | f 218 230 229 1722 | f 219 231 230 1723 | f 67 79 231 1724 | f 221 209 210 1725 | f 222 210 211 1726 | f 223 211 212 1727 | f 224 212 213 1728 | f 225 213 214 1729 | f 226 214 215 1730 | f 227 215 216 1731 | f 228 216 217 1732 | f 229 217 218 1733 | f 230 218 219 1734 | f 231 219 67 1735 | f 220 233 232 1736 | f 221 234 233 1737 | f 222 235 234 1738 | f 223 236 235 1739 | f 224 237 236 1740 | f 225 238 237 1741 | f 226 239 238 1742 | f 227 240 239 1743 | f 228 241 240 1744 | f 229 242 241 1745 | f 230 243 242 1746 | f 231 244 243 1747 | f 79 92 244 1748 | f 233 220 221 1749 | f 234 221 222 1750 | f 235 222 223 1751 | f 236 223 224 1752 | f 237 224 225 1753 | f 238 225 226 1754 | f 239 226 227 1755 | f 240 227 228 1756 | f 241 228 229 1757 | f 242 229 230 1758 | f 243 230 231 1759 | f 244 231 79 1760 | f 232 246 245 1761 | f 233 247 246 1762 | f 234 248 247 1763 | f 235 249 248 1764 | f 236 250 249 1765 | f 237 251 250 1766 | f 238 252 251 1767 | f 239 253 252 1768 | f 240 254 253 1769 | f 241 255 254 1770 | f 242 256 255 1771 | f 243 257 256 1772 | f 244 258 257 1773 | f 92 106 258 1774 | f 246 232 233 1775 | f 247 233 234 1776 | f 248 234 235 1777 | f 249 235 236 1778 | f 250 236 237 1779 | f 251 237 238 1780 | f 252 238 239 1781 | f 253 239 240 1782 | f 254 240 241 1783 | f 255 241 242 1784 | f 256 242 243 1785 | f 257 243 244 1786 | f 258 244 92 1787 | f 245 260 259 1788 | f 246 261 260 1789 | f 247 262 261 1790 | f 248 263 262 1791 | f 249 264 263 1792 | f 250 265 264 1793 | f 251 266 265 1794 | f 252 267 266 1795 | f 253 268 267 1796 | f 254 269 268 1797 | f 255 270 269 1798 | f 256 271 270 1799 | f 257 272 271 1800 | f 258 273 272 1801 | f 106 121 273 1802 | f 260 245 246 1803 | f 261 246 247 1804 | f 262 247 248 1805 | f 263 248 249 1806 | f 264 249 250 1807 | f 265 250 251 1808 | f 266 251 252 1809 | f 267 252 253 1810 | f 268 253 254 1811 | f 269 254 255 1812 | f 270 255 256 1813 | f 271 256 257 1814 | f 272 257 258 1815 | f 273 258 106 1816 | f 259 275 274 1817 | f 260 276 275 1818 | f 261 277 276 1819 | f 262 278 277 1820 | f 263 279 278 1821 | f 264 280 279 1822 | f 265 281 280 1823 | f 266 282 281 1824 | f 267 283 282 1825 | f 268 284 283 1826 | f 269 285 284 1827 | f 270 286 285 1828 | f 271 287 286 1829 | f 272 288 287 1830 | f 273 289 288 1831 | f 121 137 289 1832 | f 275 259 260 1833 | f 276 260 261 1834 | f 277 261 262 1835 | f 278 262 263 1836 | f 279 263 264 1837 | f 280 264 265 1838 | f 281 265 266 1839 | f 282 266 267 1840 | f 283 267 268 1841 | f 284 268 269 1842 | f 285 269 270 1843 | f 286 270 271 1844 | f 287 271 272 1845 | f 288 272 273 1846 | f 289 273 121 1847 | f 1 154 290 1848 | f 290 292 291 1849 | f 154 155 292 1850 | f 292 290 154 1851 | f 291 294 293 1852 | f 292 295 294 1853 | f 155 157 295 1854 | f 294 291 292 1855 | f 295 292 155 1856 | f 293 297 296 1857 | f 294 298 297 1858 | f 295 299 298 1859 | f 157 160 299 1860 | f 297 293 294 1861 | f 298 294 295 1862 | f 299 295 157 1863 | f 296 301 300 1864 | f 297 302 301 1865 | f 298 303 302 1866 | f 299 304 303 1867 | f 160 164 304 1868 | f 301 296 297 1869 | f 302 297 298 1870 | f 303 298 299 1871 | f 304 299 160 1872 | f 300 306 305 1873 | f 301 307 306 1874 | f 302 308 307 1875 | f 303 309 308 1876 | f 304 310 309 1877 | f 164 169 310 1878 | f 306 300 301 1879 | f 307 301 302 1880 | f 308 302 303 1881 | f 309 303 304 1882 | f 310 304 164 1883 | f 305 312 311 1884 | f 306 313 312 1885 | f 307 314 313 1886 | f 308 315 314 1887 | f 309 316 315 1888 | f 310 317 316 1889 | f 169 175 317 1890 | f 312 305 306 1891 | f 313 306 307 1892 | f 314 307 308 1893 | f 315 308 309 1894 | f 316 309 310 1895 | f 317 310 169 1896 | f 311 319 318 1897 | f 312 320 319 1898 | f 313 321 320 1899 | f 314 322 321 1900 | f 315 323 322 1901 | f 316 324 323 1902 | f 317 325 324 1903 | f 175 182 325 1904 | f 319 311 312 1905 | f 320 312 313 1906 | f 321 313 314 1907 | f 322 314 315 1908 | f 323 315 316 1909 | f 324 316 317 1910 | f 325 317 175 1911 | f 318 327 326 1912 | f 319 328 327 1913 | f 320 329 328 1914 | f 321 330 329 1915 | f 322 331 330 1916 | f 323 332 331 1917 | f 324 333 332 1918 | f 325 334 333 1919 | f 182 190 334 1920 | f 327 318 319 1921 | f 328 319 320 1922 | f 329 320 321 1923 | f 330 321 322 1924 | f 331 322 323 1925 | f 332 323 324 1926 | f 333 324 325 1927 | f 334 325 182 1928 | f 326 336 335 1929 | f 327 337 336 1930 | f 328 338 337 1931 | f 329 339 338 1932 | f 330 340 339 1933 | f 331 341 340 1934 | f 332 342 341 1935 | f 333 343 342 1936 | f 334 344 343 1937 | f 190 199 344 1938 | f 336 326 327 1939 | f 337 327 328 1940 | f 338 328 329 1941 | f 339 329 330 1942 | f 340 330 331 1943 | f 341 331 332 1944 | f 342 332 333 1945 | f 343 333 334 1946 | f 344 334 190 1947 | f 335 346 345 1948 | f 336 347 346 1949 | f 337 348 347 1950 | f 338 349 348 1951 | f 339 350 349 1952 | f 340 351 350 1953 | f 341 352 351 1954 | f 342 353 352 1955 | f 343 354 353 1956 | f 344 355 354 1957 | f 199 209 355 1958 | f 346 335 336 1959 | f 347 336 337 1960 | f 348 337 338 1961 | f 349 338 339 1962 | f 350 339 340 1963 | f 351 340 341 1964 | f 352 341 342 1965 | f 353 342 343 1966 | f 354 343 344 1967 | f 355 344 199 1968 | f 345 357 356 1969 | f 346 358 357 1970 | f 347 359 358 1971 | f 348 360 359 1972 | f 349 361 360 1973 | f 350 362 361 1974 | f 351 363 362 1975 | f 352 364 363 1976 | f 353 365 364 1977 | f 354 366 365 1978 | f 355 367 366 1979 | f 209 220 367 1980 | f 357 345 346 1981 | f 358 346 347 1982 | f 359 347 348 1983 | f 360 348 349 1984 | f 361 349 350 1985 | f 362 350 351 1986 | f 363 351 352 1987 | f 364 352 353 1988 | f 365 353 354 1989 | f 366 354 355 1990 | f 367 355 209 1991 | f 356 369 368 1992 | f 357 370 369 1993 | f 358 371 370 1994 | f 359 372 371 1995 | f 360 373 372 1996 | f 361 374 373 1997 | f 362 375 374 1998 | f 363 376 375 1999 | f 364 377 376 2000 | f 365 378 377 2001 | f 366 379 378 2002 | f 367 380 379 2003 | f 220 232 380 2004 | f 369 356 357 2005 | f 370 357 358 2006 | f 371 358 359 2007 | f 372 359 360 2008 | f 373 360 361 2009 | f 374 361 362 2010 | f 375 362 363 2011 | f 376 363 364 2012 | f 377 364 365 2013 | f 378 365 366 2014 | f 379 366 367 2015 | f 380 367 220 2016 | f 368 382 381 2017 | f 369 383 382 2018 | f 370 384 383 2019 | f 371 385 384 2020 | f 372 386 385 2021 | f 373 387 386 2022 | f 374 388 387 2023 | f 375 389 388 2024 | f 376 390 389 2025 | f 377 391 390 2026 | f 378 392 391 2027 | f 379 393 392 2028 | f 380 394 393 2029 | f 232 245 394 2030 | f 382 368 369 2031 | f 383 369 370 2032 | f 384 370 371 2033 | f 385 371 372 2034 | f 386 372 373 2035 | f 387 373 374 2036 | f 388 374 375 2037 | f 389 375 376 2038 | f 390 376 377 2039 | f 391 377 378 2040 | f 392 378 379 2041 | f 393 379 380 2042 | f 394 380 232 2043 | f 381 396 395 2044 | f 382 397 396 2045 | f 383 398 397 2046 | f 384 399 398 2047 | f 385 400 399 2048 | f 386 401 400 2049 | f 387 402 401 2050 | f 388 403 402 2051 | f 389 404 403 2052 | f 390 405 404 2053 | f 391 406 405 2054 | f 392 407 406 2055 | f 393 408 407 2056 | f 394 409 408 2057 | f 245 259 409 2058 | f 396 381 382 2059 | f 397 382 383 2060 | f 398 383 384 2061 | f 399 384 385 2062 | f 400 385 386 2063 | f 401 386 387 2064 | f 402 387 388 2065 | f 403 388 389 2066 | f 404 389 390 2067 | f 405 390 391 2068 | f 406 391 392 2069 | f 407 392 393 2070 | f 408 393 394 2071 | f 409 394 245 2072 | f 395 411 410 2073 | f 396 412 411 2074 | f 397 413 412 2075 | f 398 414 413 2076 | f 399 415 414 2077 | f 400 416 415 2078 | f 401 417 416 2079 | f 402 418 417 2080 | f 403 419 418 2081 | f 404 420 419 2082 | f 405 421 420 2083 | f 406 422 421 2084 | f 407 423 422 2085 | f 408 424 423 2086 | f 409 425 424 2087 | f 259 274 425 2088 | f 411 395 396 2089 | f 412 396 397 2090 | f 413 397 398 2091 | f 414 398 399 2092 | f 415 399 400 2093 | f 416 400 401 2094 | f 417 401 402 2095 | f 418 402 403 2096 | f 419 403 404 2097 | f 420 404 405 2098 | f 421 405 406 2099 | f 422 406 407 2100 | f 423 407 408 2101 | f 424 408 409 2102 | f 425 409 259 2103 | f 1 290 426 2104 | f 426 428 427 2105 | f 290 291 428 2106 | f 428 426 290 2107 | f 427 430 429 2108 | f 428 431 430 2109 | f 291 293 431 2110 | f 430 427 428 2111 | f 431 428 291 2112 | f 429 433 432 2113 | f 430 434 433 2114 | f 431 435 434 2115 | f 293 296 435 2116 | f 433 429 430 2117 | f 434 430 431 2118 | f 435 431 293 2119 | f 432 437 436 2120 | f 433 438 437 2121 | f 434 439 438 2122 | f 435 440 439 2123 | f 296 300 440 2124 | f 437 432 433 2125 | f 438 433 434 2126 | f 439 434 435 2127 | f 440 435 296 2128 | f 436 442 441 2129 | f 437 443 442 2130 | f 438 444 443 2131 | f 439 445 444 2132 | f 440 446 445 2133 | f 300 305 446 2134 | f 442 436 437 2135 | f 443 437 438 2136 | f 444 438 439 2137 | f 445 439 440 2138 | f 446 440 300 2139 | f 441 448 447 2140 | f 442 449 448 2141 | f 443 450 449 2142 | f 444 451 450 2143 | f 445 452 451 2144 | f 446 453 452 2145 | f 305 311 453 2146 | f 448 441 442 2147 | f 449 442 443 2148 | f 450 443 444 2149 | f 451 444 445 2150 | f 452 445 446 2151 | f 453 446 305 2152 | f 447 455 454 2153 | f 448 456 455 2154 | f 449 457 456 2155 | f 450 458 457 2156 | f 451 459 458 2157 | f 452 460 459 2158 | f 453 461 460 2159 | f 311 318 461 2160 | f 455 447 448 2161 | f 456 448 449 2162 | f 457 449 450 2163 | f 458 450 451 2164 | f 459 451 452 2165 | f 460 452 453 2166 | f 461 453 311 2167 | f 454 463 462 2168 | f 455 464 463 2169 | f 456 465 464 2170 | f 457 466 465 2171 | f 458 467 466 2172 | f 459 468 467 2173 | f 460 469 468 2174 | f 461 470 469 2175 | f 318 326 470 2176 | f 463 454 455 2177 | f 464 455 456 2178 | f 465 456 457 2179 | f 466 457 458 2180 | f 467 458 459 2181 | f 468 459 460 2182 | f 469 460 461 2183 | f 470 461 318 2184 | f 462 472 471 2185 | f 463 473 472 2186 | f 464 474 473 2187 | f 465 475 474 2188 | f 466 476 475 2189 | f 467 477 476 2190 | f 468 478 477 2191 | f 469 479 478 2192 | f 470 480 479 2193 | f 326 335 480 2194 | f 472 462 463 2195 | f 473 463 464 2196 | f 474 464 465 2197 | f 475 465 466 2198 | f 476 466 467 2199 | f 477 467 468 2200 | f 478 468 469 2201 | f 479 469 470 2202 | f 480 470 326 2203 | f 471 482 481 2204 | f 472 483 482 2205 | f 473 484 483 2206 | f 474 485 484 2207 | f 475 486 485 2208 | f 476 487 486 2209 | f 477 488 487 2210 | f 478 489 488 2211 | f 479 490 489 2212 | f 480 491 490 2213 | f 335 345 491 2214 | f 482 471 472 2215 | f 483 472 473 2216 | f 484 473 474 2217 | f 485 474 475 2218 | f 486 475 476 2219 | f 487 476 477 2220 | f 488 477 478 2221 | f 489 478 479 2222 | f 490 479 480 2223 | f 491 480 335 2224 | f 481 493 492 2225 | f 482 494 493 2226 | f 483 495 494 2227 | f 484 496 495 2228 | f 485 497 496 2229 | f 486 498 497 2230 | f 487 499 498 2231 | f 488 500 499 2232 | f 489 501 500 2233 | f 490 502 501 2234 | f 491 503 502 2235 | f 345 356 503 2236 | f 493 481 482 2237 | f 494 482 483 2238 | f 495 483 484 2239 | f 496 484 485 2240 | f 497 485 486 2241 | f 498 486 487 2242 | f 499 487 488 2243 | f 500 488 489 2244 | f 501 489 490 2245 | f 502 490 491 2246 | f 503 491 345 2247 | f 492 505 504 2248 | f 493 506 505 2249 | f 494 507 506 2250 | f 495 508 507 2251 | f 496 509 508 2252 | f 497 510 509 2253 | f 498 511 510 2254 | f 499 512 511 2255 | f 500 513 512 2256 | f 501 514 513 2257 | f 502 515 514 2258 | f 503 516 515 2259 | f 356 368 516 2260 | f 505 492 493 2261 | f 506 493 494 2262 | f 507 494 495 2263 | f 508 495 496 2264 | f 509 496 497 2265 | f 510 497 498 2266 | f 511 498 499 2267 | f 512 499 500 2268 | f 513 500 501 2269 | f 514 501 502 2270 | f 515 502 503 2271 | f 516 503 356 2272 | f 504 518 517 2273 | f 505 519 518 2274 | f 506 520 519 2275 | f 507 521 520 2276 | f 508 522 521 2277 | f 509 523 522 2278 | f 510 524 523 2279 | f 511 525 524 2280 | f 512 526 525 2281 | f 513 527 526 2282 | f 514 528 527 2283 | f 515 529 528 2284 | f 516 530 529 2285 | f 368 381 530 2286 | f 518 504 505 2287 | f 519 505 506 2288 | f 520 506 507 2289 | f 521 507 508 2290 | f 522 508 509 2291 | f 523 509 510 2292 | f 524 510 511 2293 | f 525 511 512 2294 | f 526 512 513 2295 | f 527 513 514 2296 | f 528 514 515 2297 | f 529 515 516 2298 | f 530 516 368 2299 | f 517 532 531 2300 | f 518 533 532 2301 | f 519 534 533 2302 | f 520 535 534 2303 | f 521 536 535 2304 | f 522 537 536 2305 | f 523 538 537 2306 | f 524 539 538 2307 | f 525 540 539 2308 | f 526 541 540 2309 | f 527 542 541 2310 | f 528 543 542 2311 | f 529 544 543 2312 | f 530 545 544 2313 | f 381 395 545 2314 | f 532 517 518 2315 | f 533 518 519 2316 | f 534 519 520 2317 | f 535 520 521 2318 | f 536 521 522 2319 | f 537 522 523 2320 | f 538 523 524 2321 | f 539 524 525 2322 | f 540 525 526 2323 | f 541 526 527 2324 | f 542 527 528 2325 | f 543 528 529 2326 | f 544 529 530 2327 | f 545 530 381 2328 | f 531 547 546 2329 | f 532 548 547 2330 | f 533 549 548 2331 | f 534 550 549 2332 | f 535 551 550 2333 | f 536 552 551 2334 | f 537 553 552 2335 | f 538 554 553 2336 | f 539 555 554 2337 | f 540 556 555 2338 | f 541 557 556 2339 | f 542 558 557 2340 | f 543 559 558 2341 | f 544 560 559 2342 | f 545 561 560 2343 | f 395 410 561 2344 | f 547 531 532 2345 | f 548 532 533 2346 | f 549 533 534 2347 | f 550 534 535 2348 | f 551 535 536 2349 | f 552 536 537 2350 | f 553 537 538 2351 | f 554 538 539 2352 | f 555 539 540 2353 | f 556 540 541 2354 | f 557 541 542 2355 | f 558 542 543 2356 | f 559 543 544 2357 | f 560 544 545 2358 | f 561 545 395 2359 | f 1 426 3 2360 | f 3 562 6 2361 | f 426 427 562 2362 | f 562 3 426 2363 | f 6 563 10 2364 | f 562 564 563 2365 | f 427 429 564 2366 | f 563 6 562 2367 | f 564 562 427 2368 | f 10 565 15 2369 | f 563 566 565 2370 | f 564 567 566 2371 | f 429 432 567 2372 | f 565 10 563 2373 | f 566 563 564 2374 | f 567 564 429 2375 | f 15 568 21 2376 | f 565 569 568 2377 | f 566 570 569 2378 | f 567 571 570 2379 | f 432 436 571 2380 | f 568 15 565 2381 | f 569 565 566 2382 | f 570 566 567 2383 | f 571 567 432 2384 | f 21 572 28 2385 | f 568 573 572 2386 | f 569 574 573 2387 | f 570 575 574 2388 | f 571 576 575 2389 | f 436 441 576 2390 | f 572 21 568 2391 | f 573 568 569 2392 | f 574 569 570 2393 | f 575 570 571 2394 | f 576 571 436 2395 | f 28 577 36 2396 | f 572 578 577 2397 | f 573 579 578 2398 | f 574 580 579 2399 | f 575 581 580 2400 | f 576 582 581 2401 | f 441 447 582 2402 | f 577 28 572 2403 | f 578 572 573 2404 | f 579 573 574 2405 | f 580 574 575 2406 | f 581 575 576 2407 | f 582 576 441 2408 | f 36 583 45 2409 | f 577 584 583 2410 | f 578 585 584 2411 | f 579 586 585 2412 | f 580 587 586 2413 | f 581 588 587 2414 | f 582 589 588 2415 | f 447 454 589 2416 | f 583 36 577 2417 | f 584 577 578 2418 | f 585 578 579 2419 | f 586 579 580 2420 | f 587 580 581 2421 | f 588 581 582 2422 | f 589 582 447 2423 | f 45 590 55 2424 | f 583 591 590 2425 | f 584 592 591 2426 | f 585 593 592 2427 | f 586 594 593 2428 | f 587 595 594 2429 | f 588 596 595 2430 | f 589 597 596 2431 | f 454 462 597 2432 | f 590 45 583 2433 | f 591 583 584 2434 | f 592 584 585 2435 | f 593 585 586 2436 | f 594 586 587 2437 | f 595 587 588 2438 | f 596 588 589 2439 | f 597 589 454 2440 | f 55 598 66 2441 | f 590 599 598 2442 | f 591 600 599 2443 | f 592 601 600 2444 | f 593 602 601 2445 | f 594 603 602 2446 | f 595 604 603 2447 | f 596 605 604 2448 | f 597 606 605 2449 | f 462 471 606 2450 | f 598 55 590 2451 | f 599 590 591 2452 | f 600 591 592 2453 | f 601 592 593 2454 | f 602 593 594 2455 | f 603 594 595 2456 | f 604 595 596 2457 | f 605 596 597 2458 | f 606 597 462 2459 | f 66 607 78 2460 | f 598 608 607 2461 | f 599 609 608 2462 | f 600 610 609 2463 | f 601 611 610 2464 | f 602 612 611 2465 | f 603 613 612 2466 | f 604 614 613 2467 | f 605 615 614 2468 | f 606 616 615 2469 | f 471 481 616 2470 | f 607 66 598 2471 | f 608 598 599 2472 | f 609 599 600 2473 | f 610 600 601 2474 | f 611 601 602 2475 | f 612 602 603 2476 | f 613 603 604 2477 | f 614 604 605 2478 | f 615 605 606 2479 | f 616 606 471 2480 | f 78 617 91 2481 | f 607 618 617 2482 | f 608 619 618 2483 | f 609 620 619 2484 | f 610 621 620 2485 | f 611 622 621 2486 | f 612 623 622 2487 | f 613 624 623 2488 | f 614 625 624 2489 | f 615 626 625 2490 | f 616 627 626 2491 | f 481 492 627 2492 | f 617 78 607 2493 | f 618 607 608 2494 | f 619 608 609 2495 | f 620 609 610 2496 | f 621 610 611 2497 | f 622 611 612 2498 | f 623 612 613 2499 | f 624 613 614 2500 | f 625 614 615 2501 | f 626 615 616 2502 | f 627 616 481 2503 | f 91 628 105 2504 | f 617 629 628 2505 | f 618 630 629 2506 | f 619 631 630 2507 | f 620 632 631 2508 | f 621 633 632 2509 | f 622 634 633 2510 | f 623 635 634 2511 | f 624 636 635 2512 | f 625 637 636 2513 | f 626 638 637 2514 | f 627 639 638 2515 | f 492 504 639 2516 | f 628 91 617 2517 | f 629 617 618 2518 | f 630 618 619 2519 | f 631 619 620 2520 | f 632 620 621 2521 | f 633 621 622 2522 | f 634 622 623 2523 | f 635 623 624 2524 | f 636 624 625 2525 | f 637 625 626 2526 | f 638 626 627 2527 | f 639 627 492 2528 | f 105 640 120 2529 | f 628 641 640 2530 | f 629 642 641 2531 | f 630 643 642 2532 | f 631 644 643 2533 | f 632 645 644 2534 | f 633 646 645 2535 | f 634 647 646 2536 | f 635 648 647 2537 | f 636 649 648 2538 | f 637 650 649 2539 | f 638 651 650 2540 | f 639 652 651 2541 | f 504 517 652 2542 | f 640 105 628 2543 | f 641 628 629 2544 | f 642 629 630 2545 | f 643 630 631 2546 | f 644 631 632 2547 | f 645 632 633 2548 | f 646 633 634 2549 | f 647 634 635 2550 | f 648 635 636 2551 | f 649 636 637 2552 | f 650 637 638 2553 | f 651 638 639 2554 | f 652 639 504 2555 | f 120 653 136 2556 | f 640 654 653 2557 | f 641 655 654 2558 | f 642 656 655 2559 | f 643 657 656 2560 | f 644 658 657 2561 | f 645 659 658 2562 | f 646 660 659 2563 | f 647 661 660 2564 | f 648 662 661 2565 | f 649 663 662 2566 | f 650 664 663 2567 | f 651 665 664 2568 | f 652 666 665 2569 | f 517 531 666 2570 | f 653 120 640 2571 | f 654 640 641 2572 | f 655 641 642 2573 | f 656 642 643 2574 | f 657 643 644 2575 | f 658 644 645 2576 | f 659 645 646 2577 | f 660 646 647 2578 | f 661 647 648 2579 | f 662 648 649 2580 | f 663 649 650 2581 | f 664 650 651 2582 | f 665 651 652 2583 | f 666 652 517 2584 | f 136 667 153 2585 | f 653 668 667 2586 | f 654 669 668 2587 | f 655 670 669 2588 | f 656 671 670 2589 | f 657 672 671 2590 | f 658 673 672 2591 | f 659 674 673 2592 | f 660 675 674 2593 | f 661 676 675 2594 | f 662 677 676 2595 | f 663 678 677 2596 | f 664 679 678 2597 | f 665 680 679 2598 | f 666 681 680 2599 | f 531 546 681 2600 | f 667 136 653 2601 | f 668 653 654 2602 | f 669 654 655 2603 | f 670 655 656 2604 | f 671 656 657 2605 | f 672 657 658 2606 | f 673 658 659 2607 | f 674 659 660 2608 | f 675 660 661 2609 | f 676 661 662 2610 | f 677 662 663 2611 | f 678 663 664 2612 | f 679 664 665 2613 | f 680 665 666 2614 | f 681 666 531 2615 | f 153 682 152 2616 | f 152 683 151 2617 | f 682 684 683 2618 | f 683 152 682 2619 | f 151 685 150 2620 | f 683 686 685 2621 | f 684 687 686 2622 | f 685 151 683 2623 | f 686 683 684 2624 | f 150 688 149 2625 | f 685 689 688 2626 | f 686 690 689 2627 | f 687 691 690 2628 | f 688 150 685 2629 | f 689 685 686 2630 | f 690 686 687 2631 | f 149 692 148 2632 | f 688 693 692 2633 | f 689 694 693 2634 | f 690 695 694 2635 | f 691 696 695 2636 | f 692 149 688 2637 | f 693 688 689 2638 | f 694 689 690 2639 | f 695 690 691 2640 | f 148 697 147 2641 | f 692 698 697 2642 | f 693 699 698 2643 | f 694 700 699 2644 | f 695 701 700 2645 | f 696 702 701 2646 | f 697 148 692 2647 | f 698 692 693 2648 | f 699 693 694 2649 | f 700 694 695 2650 | f 701 695 696 2651 | f 147 703 146 2652 | f 697 704 703 2653 | f 698 705 704 2654 | f 699 706 705 2655 | f 700 707 706 2656 | f 701 708 707 2657 | f 702 709 708 2658 | f 703 147 697 2659 | f 704 697 698 2660 | f 705 698 699 2661 | f 706 699 700 2662 | f 707 700 701 2663 | f 708 701 702 2664 | f 146 710 145 2665 | f 703 711 710 2666 | f 704 712 711 2667 | f 705 713 712 2668 | f 706 714 713 2669 | f 707 715 714 2670 | f 708 716 715 2671 | f 709 717 716 2672 | f 710 146 703 2673 | f 711 703 704 2674 | f 712 704 705 2675 | f 713 705 706 2676 | f 714 706 707 2677 | f 715 707 708 2678 | f 716 708 709 2679 | f 145 718 144 2680 | f 710 719 718 2681 | f 711 720 719 2682 | f 712 721 720 2683 | f 713 722 721 2684 | f 714 723 722 2685 | f 715 724 723 2686 | f 716 725 724 2687 | f 718 145 710 2688 | f 719 710 711 2689 | f 720 711 712 2690 | f 721 712 713 2691 | f 722 713 714 2692 | f 723 714 715 2693 | f 724 715 716 2694 | f 725 716 717 2695 | f 144 726 143 2696 | f 718 727 726 2697 | f 719 728 727 2698 | f 720 729 728 2699 | f 721 730 729 2700 | f 722 731 730 2701 | f 723 732 731 2702 | f 724 733 732 2703 | f 726 144 718 2704 | f 727 718 719 2705 | f 728 719 720 2706 | f 729 720 721 2707 | f 730 721 722 2708 | f 731 722 723 2709 | f 732 723 724 2710 | f 733 724 725 2711 | f 143 734 142 2712 | f 726 735 734 2713 | f 727 736 735 2714 | f 728 737 736 2715 | f 729 738 737 2716 | f 730 739 738 2717 | f 731 740 739 2718 | f 732 741 740 2719 | f 734 143 726 2720 | f 735 726 727 2721 | f 736 727 728 2722 | f 737 728 729 2723 | f 738 729 730 2724 | f 739 730 731 2725 | f 740 731 732 2726 | f 741 732 733 2727 | f 142 742 141 2728 | f 734 743 742 2729 | f 735 744 743 2730 | f 736 745 744 2731 | f 737 746 745 2732 | f 738 747 746 2733 | f 739 748 747 2734 | f 740 749 748 2735 | f 742 142 734 2736 | f 743 734 735 2737 | f 744 735 736 2738 | f 745 736 737 2739 | f 746 737 738 2740 | f 747 738 739 2741 | f 748 739 740 2742 | f 749 740 741 2743 | f 141 750 140 2744 | f 742 751 750 2745 | f 743 752 751 2746 | f 744 753 752 2747 | f 745 754 753 2748 | f 746 755 754 2749 | f 747 756 755 2750 | f 748 757 756 2751 | f 750 141 742 2752 | f 751 742 743 2753 | f 752 743 744 2754 | f 753 744 745 2755 | f 754 745 746 2756 | f 755 746 747 2757 | f 756 747 748 2758 | f 757 748 749 2759 | f 140 758 139 2760 | f 750 759 758 2761 | f 751 760 759 2762 | f 752 761 760 2763 | f 753 762 761 2764 | f 754 763 762 2765 | f 755 764 763 2766 | f 756 765 764 2767 | f 758 140 750 2768 | f 759 750 751 2769 | f 760 751 752 2770 | f 761 752 753 2771 | f 762 753 754 2772 | f 763 754 755 2773 | f 764 755 756 2774 | f 765 756 757 2775 | f 139 766 138 2776 | f 758 767 766 2777 | f 759 768 767 2778 | f 760 769 768 2779 | f 761 770 769 2780 | f 762 771 770 2781 | f 763 772 771 2782 | f 764 773 772 2783 | f 766 139 758 2784 | f 767 758 759 2785 | f 768 759 760 2786 | f 769 760 761 2787 | f 770 761 762 2788 | f 771 762 763 2789 | f 772 763 764 2790 | f 773 764 765 2791 | f 138 774 137 2792 | f 766 775 774 2793 | f 767 776 775 2794 | f 768 777 776 2795 | f 769 778 777 2796 | f 770 779 778 2797 | f 771 780 779 2798 | f 772 781 780 2799 | f 774 138 766 2800 | f 775 766 767 2801 | f 776 767 768 2802 | f 777 768 769 2803 | f 778 769 770 2804 | f 779 770 771 2805 | f 780 771 772 2806 | f 781 772 773 2807 | f 137 782 289 2808 | f 289 783 288 2809 | f 782 784 783 2810 | f 783 289 782 2811 | f 288 785 287 2812 | f 783 786 785 2813 | f 784 787 786 2814 | f 785 288 783 2815 | f 786 783 784 2816 | f 287 788 286 2817 | f 785 789 788 2818 | f 786 790 789 2819 | f 787 791 790 2820 | f 788 287 785 2821 | f 789 785 786 2822 | f 790 786 787 2823 | f 286 792 285 2824 | f 788 793 792 2825 | f 789 794 793 2826 | f 790 795 794 2827 | f 791 796 795 2828 | f 792 286 788 2829 | f 793 788 789 2830 | f 794 789 790 2831 | f 795 790 791 2832 | f 285 797 284 2833 | f 792 798 797 2834 | f 793 799 798 2835 | f 794 800 799 2836 | f 795 801 800 2837 | f 796 802 801 2838 | f 797 285 792 2839 | f 798 792 793 2840 | f 799 793 794 2841 | f 800 794 795 2842 | f 801 795 796 2843 | f 284 803 283 2844 | f 797 804 803 2845 | f 798 805 804 2846 | f 799 806 805 2847 | f 800 807 806 2848 | f 801 808 807 2849 | f 802 809 808 2850 | f 803 284 797 2851 | f 804 797 798 2852 | f 805 798 799 2853 | f 806 799 800 2854 | f 807 800 801 2855 | f 808 801 802 2856 | f 283 810 282 2857 | f 803 811 810 2858 | f 804 812 811 2859 | f 805 813 812 2860 | f 806 814 813 2861 | f 807 815 814 2862 | f 808 816 815 2863 | f 809 817 816 2864 | f 810 283 803 2865 | f 811 803 804 2866 | f 812 804 805 2867 | f 813 805 806 2868 | f 814 806 807 2869 | f 815 807 808 2870 | f 816 808 809 2871 | f 282 818 281 2872 | f 810 819 818 2873 | f 811 820 819 2874 | f 812 821 820 2875 | f 813 822 821 2876 | f 814 823 822 2877 | f 815 824 823 2878 | f 816 825 824 2879 | f 818 282 810 2880 | f 819 810 811 2881 | f 820 811 812 2882 | f 821 812 813 2883 | f 822 813 814 2884 | f 823 814 815 2885 | f 824 815 816 2886 | f 825 816 817 2887 | f 281 826 280 2888 | f 818 827 826 2889 | f 819 828 827 2890 | f 820 829 828 2891 | f 821 830 829 2892 | f 822 831 830 2893 | f 823 832 831 2894 | f 824 833 832 2895 | f 826 281 818 2896 | f 827 818 819 2897 | f 828 819 820 2898 | f 829 820 821 2899 | f 830 821 822 2900 | f 831 822 823 2901 | f 832 823 824 2902 | f 833 824 825 2903 | f 280 834 279 2904 | f 826 835 834 2905 | f 827 836 835 2906 | f 828 837 836 2907 | f 829 838 837 2908 | f 830 839 838 2909 | f 831 840 839 2910 | f 832 841 840 2911 | f 834 280 826 2912 | f 835 826 827 2913 | f 836 827 828 2914 | f 837 828 829 2915 | f 838 829 830 2916 | f 839 830 831 2917 | f 840 831 832 2918 | f 841 832 833 2919 | f 279 842 278 2920 | f 834 843 842 2921 | f 835 844 843 2922 | f 836 845 844 2923 | f 837 846 845 2924 | f 838 847 846 2925 | f 839 848 847 2926 | f 840 849 848 2927 | f 842 279 834 2928 | f 843 834 835 2929 | f 844 835 836 2930 | f 845 836 837 2931 | f 846 837 838 2932 | f 847 838 839 2933 | f 848 839 840 2934 | f 849 840 841 2935 | f 278 850 277 2936 | f 842 851 850 2937 | f 843 852 851 2938 | f 844 853 852 2939 | f 845 854 853 2940 | f 846 855 854 2941 | f 847 856 855 2942 | f 848 857 856 2943 | f 850 278 842 2944 | f 851 842 843 2945 | f 852 843 844 2946 | f 853 844 845 2947 | f 854 845 846 2948 | f 855 846 847 2949 | f 856 847 848 2950 | f 857 848 849 2951 | f 277 858 276 2952 | f 850 859 858 2953 | f 851 860 859 2954 | f 852 861 860 2955 | f 853 862 861 2956 | f 854 863 862 2957 | f 855 864 863 2958 | f 856 865 864 2959 | f 858 277 850 2960 | f 859 850 851 2961 | f 860 851 852 2962 | f 861 852 853 2963 | f 862 853 854 2964 | f 863 854 855 2965 | f 864 855 856 2966 | f 865 856 857 2967 | f 276 866 275 2968 | f 858 867 866 2969 | f 859 868 867 2970 | f 860 869 868 2971 | f 861 870 869 2972 | f 862 871 870 2973 | f 863 872 871 2974 | f 864 873 872 2975 | f 866 276 858 2976 | f 867 858 859 2977 | f 868 859 860 2978 | f 869 860 861 2979 | f 870 861 862 2980 | f 871 862 863 2981 | f 872 863 864 2982 | f 873 864 865 2983 | f 275 874 274 2984 | f 866 875 874 2985 | f 867 876 875 2986 | f 868 877 876 2987 | f 869 878 877 2988 | f 870 879 878 2989 | f 871 880 879 2990 | f 872 881 880 2991 | f 874 275 866 2992 | f 875 866 867 2993 | f 876 867 868 2994 | f 877 868 869 2995 | f 878 869 870 2996 | f 879 870 871 2997 | f 880 871 872 2998 | f 881 872 873 2999 | f 274 882 425 3000 | f 425 883 424 3001 | f 882 884 883 3002 | f 883 425 882 3003 | f 424 885 423 3004 | f 883 886 885 3005 | f 884 887 886 3006 | f 885 424 883 3007 | f 886 883 884 3008 | f 423 888 422 3009 | f 885 889 888 3010 | f 886 890 889 3011 | f 887 891 890 3012 | f 888 423 885 3013 | f 889 885 886 3014 | f 890 886 887 3015 | f 422 892 421 3016 | f 888 893 892 3017 | f 889 894 893 3018 | f 890 895 894 3019 | f 891 896 895 3020 | f 892 422 888 3021 | f 893 888 889 3022 | f 894 889 890 3023 | f 895 890 891 3024 | f 421 897 420 3025 | f 892 898 897 3026 | f 893 899 898 3027 | f 894 900 899 3028 | f 895 901 900 3029 | f 896 902 901 3030 | f 897 421 892 3031 | f 898 892 893 3032 | f 899 893 894 3033 | f 900 894 895 3034 | f 901 895 896 3035 | f 420 903 419 3036 | f 897 904 903 3037 | f 898 905 904 3038 | f 899 906 905 3039 | f 900 907 906 3040 | f 901 908 907 3041 | f 902 909 908 3042 | f 903 420 897 3043 | f 904 897 898 3044 | f 905 898 899 3045 | f 906 899 900 3046 | f 907 900 901 3047 | f 908 901 902 3048 | f 419 910 418 3049 | f 903 911 910 3050 | f 904 912 911 3051 | f 905 913 912 3052 | f 906 914 913 3053 | f 907 915 914 3054 | f 908 916 915 3055 | f 909 917 916 3056 | f 910 419 903 3057 | f 911 903 904 3058 | f 912 904 905 3059 | f 913 905 906 3060 | f 914 906 907 3061 | f 915 907 908 3062 | f 916 908 909 3063 | f 418 918 417 3064 | f 910 919 918 3065 | f 911 920 919 3066 | f 912 921 920 3067 | f 913 922 921 3068 | f 914 923 922 3069 | f 915 924 923 3070 | f 916 925 924 3071 | f 918 418 910 3072 | f 919 910 911 3073 | f 920 911 912 3074 | f 921 912 913 3075 | f 922 913 914 3076 | f 923 914 915 3077 | f 924 915 916 3078 | f 925 916 917 3079 | f 417 926 416 3080 | f 918 927 926 3081 | f 919 928 927 3082 | f 920 929 928 3083 | f 921 930 929 3084 | f 922 931 930 3085 | f 923 932 931 3086 | f 924 933 932 3087 | f 926 417 918 3088 | f 927 918 919 3089 | f 928 919 920 3090 | f 929 920 921 3091 | f 930 921 922 3092 | f 931 922 923 3093 | f 932 923 924 3094 | f 933 924 925 3095 | f 416 934 415 3096 | f 926 935 934 3097 | f 927 936 935 3098 | f 928 937 936 3099 | f 929 938 937 3100 | f 930 939 938 3101 | f 931 940 939 3102 | f 932 941 940 3103 | f 934 416 926 3104 | f 935 926 927 3105 | f 936 927 928 3106 | f 937 928 929 3107 | f 938 929 930 3108 | f 939 930 931 3109 | f 940 931 932 3110 | f 941 932 933 3111 | f 415 942 414 3112 | f 934 943 942 3113 | f 935 944 943 3114 | f 936 945 944 3115 | f 937 946 945 3116 | f 938 947 946 3117 | f 939 948 947 3118 | f 940 949 948 3119 | f 942 415 934 3120 | f 943 934 935 3121 | f 944 935 936 3122 | f 945 936 937 3123 | f 946 937 938 3124 | f 947 938 939 3125 | f 948 939 940 3126 | f 949 940 941 3127 | f 414 950 413 3128 | f 942 951 950 3129 | f 943 952 951 3130 | f 944 953 952 3131 | f 945 954 953 3132 | f 946 955 954 3133 | f 947 956 955 3134 | f 948 957 956 3135 | f 950 414 942 3136 | f 951 942 943 3137 | f 952 943 944 3138 | f 953 944 945 3139 | f 954 945 946 3140 | f 955 946 947 3141 | f 956 947 948 3142 | f 957 948 949 3143 | f 413 958 412 3144 | f 950 959 958 3145 | f 951 960 959 3146 | f 952 961 960 3147 | f 953 962 961 3148 | f 954 963 962 3149 | f 955 964 963 3150 | f 956 965 964 3151 | f 958 413 950 3152 | f 959 950 951 3153 | f 960 951 952 3154 | f 961 952 953 3155 | f 962 953 954 3156 | f 963 954 955 3157 | f 964 955 956 3158 | f 965 956 957 3159 | f 412 966 411 3160 | f 958 967 966 3161 | f 959 968 967 3162 | f 960 969 968 3163 | f 961 970 969 3164 | f 962 971 970 3165 | f 963 972 971 3166 | f 964 973 972 3167 | f 966 412 958 3168 | f 967 958 959 3169 | f 968 959 960 3170 | f 969 960 961 3171 | f 970 961 962 3172 | f 971 962 963 3173 | f 972 963 964 3174 | f 973 964 965 3175 | f 411 974 410 3176 | f 966 975 974 3177 | f 967 976 975 3178 | f 968 977 976 3179 | f 969 978 977 3180 | f 970 979 978 3181 | f 971 980 979 3182 | f 972 981 980 3183 | f 974 411 966 3184 | f 975 966 967 3185 | f 976 967 968 3186 | f 977 968 969 3187 | f 978 969 970 3188 | f 979 970 971 3189 | f 980 971 972 3190 | f 981 972 973 3191 | f 410 982 561 3192 | f 561 983 560 3193 | f 982 984 983 3194 | f 983 561 982 3195 | f 560 985 559 3196 | f 983 986 985 3197 | f 984 987 986 3198 | f 985 560 983 3199 | f 986 983 984 3200 | f 559 988 558 3201 | f 985 989 988 3202 | f 986 990 989 3203 | f 987 991 990 3204 | f 988 559 985 3205 | f 989 985 986 3206 | f 990 986 987 3207 | f 558 992 557 3208 | f 988 993 992 3209 | f 989 994 993 3210 | f 990 995 994 3211 | f 991 996 995 3212 | f 992 558 988 3213 | f 993 988 989 3214 | f 994 989 990 3215 | f 995 990 991 3216 | f 557 997 556 3217 | f 992 998 997 3218 | f 993 999 998 3219 | f 994 1000 999 3220 | f 995 1001 1000 3221 | f 996 1002 1001 3222 | f 997 557 992 3223 | f 998 992 993 3224 | f 999 993 994 3225 | f 1000 994 995 3226 | f 1001 995 996 3227 | f 556 1003 555 3228 | f 997 1004 1003 3229 | f 998 1005 1004 3230 | f 999 1006 1005 3231 | f 1000 1007 1006 3232 | f 1001 1008 1007 3233 | f 1002 1009 1008 3234 | f 1003 556 997 3235 | f 1004 997 998 3236 | f 1005 998 999 3237 | f 1006 999 1000 3238 | f 1007 1000 1001 3239 | f 1008 1001 1002 3240 | f 555 1010 554 3241 | f 1003 1011 1010 3242 | f 1004 1012 1011 3243 | f 1005 1013 1012 3244 | f 1006 1014 1013 3245 | f 1007 1015 1014 3246 | f 1008 1016 1015 3247 | f 1009 1017 1016 3248 | f 1010 555 1003 3249 | f 1011 1003 1004 3250 | f 1012 1004 1005 3251 | f 1013 1005 1006 3252 | f 1014 1006 1007 3253 | f 1015 1007 1008 3254 | f 1016 1008 1009 3255 | f 554 1018 553 3256 | f 1010 1019 1018 3257 | f 1011 1020 1019 3258 | f 1012 1021 1020 3259 | f 1013 1022 1021 3260 | f 1014 1023 1022 3261 | f 1015 1024 1023 3262 | f 1016 1025 1024 3263 | f 1018 554 1010 3264 | f 1019 1010 1011 3265 | f 1020 1011 1012 3266 | f 1021 1012 1013 3267 | f 1022 1013 1014 3268 | f 1023 1014 1015 3269 | f 1024 1015 1016 3270 | f 1025 1016 1017 3271 | f 553 1026 552 3272 | f 1018 1027 1026 3273 | f 1019 1028 1027 3274 | f 1020 1029 1028 3275 | f 1021 1030 1029 3276 | f 1022 1031 1030 3277 | f 1023 1032 1031 3278 | f 1024 1033 1032 3279 | f 1026 553 1018 3280 | f 1027 1018 1019 3281 | f 1028 1019 1020 3282 | f 1029 1020 1021 3283 | f 1030 1021 1022 3284 | f 1031 1022 1023 3285 | f 1032 1023 1024 3286 | f 1033 1024 1025 3287 | f 552 1034 551 3288 | f 1026 1035 1034 3289 | f 1027 1036 1035 3290 | f 1028 1037 1036 3291 | f 1029 1038 1037 3292 | f 1030 1039 1038 3293 | f 1031 1040 1039 3294 | f 1032 1041 1040 3295 | f 1034 552 1026 3296 | f 1035 1026 1027 3297 | f 1036 1027 1028 3298 | f 1037 1028 1029 3299 | f 1038 1029 1030 3300 | f 1039 1030 1031 3301 | f 1040 1031 1032 3302 | f 1041 1032 1033 3303 | f 551 1042 550 3304 | f 1034 1043 1042 3305 | f 1035 1044 1043 3306 | f 1036 1045 1044 3307 | f 1037 1046 1045 3308 | f 1038 1047 1046 3309 | f 1039 1048 1047 3310 | f 1040 1049 1048 3311 | f 1042 551 1034 3312 | f 1043 1034 1035 3313 | f 1044 1035 1036 3314 | f 1045 1036 1037 3315 | f 1046 1037 1038 3316 | f 1047 1038 1039 3317 | f 1048 1039 1040 3318 | f 1049 1040 1041 3319 | f 550 1050 549 3320 | f 1042 1051 1050 3321 | f 1043 1052 1051 3322 | f 1044 1053 1052 3323 | f 1045 1054 1053 3324 | f 1046 1055 1054 3325 | f 1047 1056 1055 3326 | f 1048 1057 1056 3327 | f 1050 550 1042 3328 | f 1051 1042 1043 3329 | f 1052 1043 1044 3330 | f 1053 1044 1045 3331 | f 1054 1045 1046 3332 | f 1055 1046 1047 3333 | f 1056 1047 1048 3334 | f 1057 1048 1049 3335 | f 549 1058 548 3336 | f 1050 1059 1058 3337 | f 1051 1060 1059 3338 | f 1052 1061 1060 3339 | f 1053 1062 1061 3340 | f 1054 1063 1062 3341 | f 1055 1064 1063 3342 | f 1056 1065 1064 3343 | f 1058 549 1050 3344 | f 1059 1050 1051 3345 | f 1060 1051 1052 3346 | f 1061 1052 1053 3347 | f 1062 1053 1054 3348 | f 1063 1054 1055 3349 | f 1064 1055 1056 3350 | f 1065 1056 1057 3351 | f 548 1066 547 3352 | f 1058 1067 1066 3353 | f 1059 1068 1067 3354 | f 1060 1069 1068 3355 | f 1061 1070 1069 3356 | f 1062 1071 1070 3357 | f 1063 1072 1071 3358 | f 1064 1073 1072 3359 | f 1066 548 1058 3360 | f 1067 1058 1059 3361 | f 1068 1059 1060 3362 | f 1069 1060 1061 3363 | f 1070 1061 1062 3364 | f 1071 1062 1063 3365 | f 1072 1063 1064 3366 | f 1073 1064 1065 3367 | f 547 1074 546 3368 | f 1066 1075 1074 3369 | f 1067 1076 1075 3370 | f 1068 1077 1076 3371 | f 1069 1078 1077 3372 | f 1070 1079 1078 3373 | f 1071 1080 1079 3374 | f 1072 1081 1080 3375 | f 1074 547 1066 3376 | f 1075 1066 1067 3377 | f 1076 1067 1068 3378 | f 1077 1068 1069 3379 | f 1078 1069 1070 3380 | f 1079 1070 1071 3381 | f 1080 1071 1072 3382 | f 1081 1072 1073 3383 | f 546 1082 681 3384 | f 681 1083 680 3385 | f 1082 1084 1083 3386 | f 1083 681 1082 3387 | f 680 1085 679 3388 | f 1083 1086 1085 3389 | f 1084 1087 1086 3390 | f 1085 680 1083 3391 | f 1086 1083 1084 3392 | f 679 1088 678 3393 | f 1085 1089 1088 3394 | f 1086 1090 1089 3395 | f 1087 1091 1090 3396 | f 1088 679 1085 3397 | f 1089 1085 1086 3398 | f 1090 1086 1087 3399 | f 678 1092 677 3400 | f 1088 1093 1092 3401 | f 1089 1094 1093 3402 | f 1090 1095 1094 3403 | f 1091 1096 1095 3404 | f 1092 678 1088 3405 | f 1093 1088 1089 3406 | f 1094 1089 1090 3407 | f 1095 1090 1091 3408 | f 677 1097 676 3409 | f 1092 1098 1097 3410 | f 1093 1099 1098 3411 | f 1094 1100 1099 3412 | f 1095 1101 1100 3413 | f 1096 1102 1101 3414 | f 1097 677 1092 3415 | f 1098 1092 1093 3416 | f 1099 1093 1094 3417 | f 1100 1094 1095 3418 | f 1101 1095 1096 3419 | f 676 1103 675 3420 | f 1097 1104 1103 3421 | f 1098 1105 1104 3422 | f 1099 1106 1105 3423 | f 1100 1107 1106 3424 | f 1101 1108 1107 3425 | f 1102 1109 1108 3426 | f 1103 676 1097 3427 | f 1104 1097 1098 3428 | f 1105 1098 1099 3429 | f 1106 1099 1100 3430 | f 1107 1100 1101 3431 | f 1108 1101 1102 3432 | f 675 1110 674 3433 | f 1103 1111 1110 3434 | f 1104 1112 1111 3435 | f 1105 1113 1112 3436 | f 1106 1114 1113 3437 | f 1107 1115 1114 3438 | f 1108 1116 1115 3439 | f 1109 1117 1116 3440 | f 1110 675 1103 3441 | f 1111 1103 1104 3442 | f 1112 1104 1105 3443 | f 1113 1105 1106 3444 | f 1114 1106 1107 3445 | f 1115 1107 1108 3446 | f 1116 1108 1109 3447 | f 674 1118 673 3448 | f 1110 1119 1118 3449 | f 1111 1120 1119 3450 | f 1112 1121 1120 3451 | f 1113 1122 1121 3452 | f 1114 1123 1122 3453 | f 1115 1124 1123 3454 | f 1116 1125 1124 3455 | f 1118 674 1110 3456 | f 1119 1110 1111 3457 | f 1120 1111 1112 3458 | f 1121 1112 1113 3459 | f 1122 1113 1114 3460 | f 1123 1114 1115 3461 | f 1124 1115 1116 3462 | f 1125 1116 1117 3463 | f 673 1126 672 3464 | f 1118 1127 1126 3465 | f 1119 1128 1127 3466 | f 1120 1129 1128 3467 | f 1121 1130 1129 3468 | f 1122 1131 1130 3469 | f 1123 1132 1131 3470 | f 1124 1133 1132 3471 | f 1126 673 1118 3472 | f 1127 1118 1119 3473 | f 1128 1119 1120 3474 | f 1129 1120 1121 3475 | f 1130 1121 1122 3476 | f 1131 1122 1123 3477 | f 1132 1123 1124 3478 | f 1133 1124 1125 3479 | f 672 1134 671 3480 | f 1126 1135 1134 3481 | f 1127 1136 1135 3482 | f 1128 1137 1136 3483 | f 1129 1138 1137 3484 | f 1130 1139 1138 3485 | f 1131 1140 1139 3486 | f 1132 1141 1140 3487 | f 1134 672 1126 3488 | f 1135 1126 1127 3489 | f 1136 1127 1128 3490 | f 1137 1128 1129 3491 | f 1138 1129 1130 3492 | f 1139 1130 1131 3493 | f 1140 1131 1132 3494 | f 1141 1132 1133 3495 | f 671 1142 670 3496 | f 1134 1143 1142 3497 | f 1135 1144 1143 3498 | f 1136 1145 1144 3499 | f 1137 1146 1145 3500 | f 1138 1147 1146 3501 | f 1139 1148 1147 3502 | f 1140 1149 1148 3503 | f 1142 671 1134 3504 | f 1143 1134 1135 3505 | f 1144 1135 1136 3506 | f 1145 1136 1137 3507 | f 1146 1137 1138 3508 | f 1147 1138 1139 3509 | f 1148 1139 1140 3510 | f 1149 1140 1141 3511 | f 670 1150 669 3512 | f 1142 1151 1150 3513 | f 1143 1152 1151 3514 | f 1144 1153 1152 3515 | f 1145 1154 1153 3516 | f 1146 1155 1154 3517 | f 1147 1156 1155 3518 | f 1148 1157 1156 3519 | f 1150 670 1142 3520 | f 1151 1142 1143 3521 | f 1152 1143 1144 3522 | f 1153 1144 1145 3523 | f 1154 1145 1146 3524 | f 1155 1146 1147 3525 | f 1156 1147 1148 3526 | f 1157 1148 1149 3527 | f 669 1158 668 3528 | f 1150 1159 1158 3529 | f 1151 1160 1159 3530 | f 1152 1161 1160 3531 | f 1153 1162 1161 3532 | f 1154 1163 1162 3533 | f 1155 1164 1163 3534 | f 1156 1165 1164 3535 | f 1158 669 1150 3536 | f 1159 1150 1151 3537 | f 1160 1151 1152 3538 | f 1161 1152 1153 3539 | f 1162 1153 1154 3540 | f 1163 1154 1155 3541 | f 1164 1155 1156 3542 | f 1165 1156 1157 3543 | f 668 1166 667 3544 | f 1158 1167 1166 3545 | f 1159 1168 1167 3546 | f 1160 1169 1168 3547 | f 1161 1170 1169 3548 | f 1162 1171 1170 3549 | f 1163 1172 1171 3550 | f 1164 1173 1172 3551 | f 1166 668 1158 3552 | f 1167 1158 1159 3553 | f 1168 1159 1160 3554 | f 1169 1160 1161 3555 | f 1170 1161 1162 3556 | f 1171 1162 1163 3557 | f 1172 1163 1164 3558 | f 1173 1164 1165 3559 | f 667 1174 153 3560 | f 1166 1175 1174 3561 | f 1167 1176 1175 3562 | f 1168 1177 1176 3563 | f 1169 1178 1177 3564 | f 1170 1179 1178 3565 | f 1171 1180 1179 3566 | f 1172 1181 1180 3567 | f 1174 667 1166 3568 | f 1175 1166 1167 3569 | f 1176 1167 1168 3570 | f 1177 1168 1169 3571 | f 1178 1169 1170 3572 | f 1179 1170 1171 3573 | f 1180 1171 1172 3574 | f 1181 1172 1173 3575 | f 817 809 1182 3576 | f 1182 1184 1183 3577 | f 809 802 1184 3578 | f 1184 1182 809 3579 | f 1183 1186 1185 3580 | f 1184 1187 1186 3581 | f 802 796 1187 3582 | f 1186 1183 1184 3583 | f 1187 1184 802 3584 | f 1185 1189 1188 3585 | f 1186 1190 1189 3586 | f 1187 1191 1190 3587 | f 796 791 1191 3588 | f 1189 1185 1186 3589 | f 1190 1186 1187 3590 | f 1191 1187 796 3591 | f 1188 1193 1192 3592 | f 1189 1194 1193 3593 | f 1190 1195 1194 3594 | f 1191 1196 1195 3595 | f 791 787 1196 3596 | f 1193 1188 1189 3597 | f 1194 1189 1190 3598 | f 1195 1190 1191 3599 | f 1196 1191 791 3600 | f 1192 1198 1197 3601 | f 1193 1199 1198 3602 | f 1194 1200 1199 3603 | f 1195 1201 1200 3604 | f 1196 1202 1201 3605 | f 787 784 1202 3606 | f 1198 1192 1193 3607 | f 1199 1193 1194 3608 | f 1200 1194 1195 3609 | f 1201 1195 1196 3610 | f 1202 1196 787 3611 | f 1197 1204 1203 3612 | f 1198 1205 1204 3613 | f 1199 1206 1205 3614 | f 1200 1207 1206 3615 | f 1201 1208 1207 3616 | f 1202 1209 1208 3617 | f 784 782 1209 3618 | f 1204 1197 1198 3619 | f 1205 1198 1199 3620 | f 1206 1199 1200 3621 | f 1207 1200 1201 3622 | f 1208 1201 1202 3623 | f 1209 1202 784 3624 | f 1203 780 781 3625 | f 1204 779 780 3626 | f 1205 778 779 3627 | f 1206 777 778 3628 | f 1207 776 777 3629 | f 1208 775 776 3630 | f 1209 774 775 3631 | f 782 137 774 3632 | f 780 1203 1204 3633 | f 779 1204 1205 3634 | f 778 1205 1206 3635 | f 777 1206 1207 3636 | f 776 1207 1208 3637 | f 775 1208 1209 3638 | f 774 1209 782 3639 | f 917 909 1210 3640 | f 1210 1212 1211 3641 | f 909 902 1212 3642 | f 1212 1210 909 3643 | f 1211 1214 1213 3644 | f 1212 1215 1214 3645 | f 902 896 1215 3646 | f 1214 1211 1212 3647 | f 1215 1212 902 3648 | f 1213 1217 1216 3649 | f 1214 1218 1217 3650 | f 1215 1219 1218 3651 | f 896 891 1219 3652 | f 1217 1213 1214 3653 | f 1218 1214 1215 3654 | f 1219 1215 896 3655 | f 1216 1221 1220 3656 | f 1217 1222 1221 3657 | f 1218 1223 1222 3658 | f 1219 1224 1223 3659 | f 891 887 1224 3660 | f 1221 1216 1217 3661 | f 1222 1217 1218 3662 | f 1223 1218 1219 3663 | f 1224 1219 891 3664 | f 1220 1226 1225 3665 | f 1221 1227 1226 3666 | f 1222 1228 1227 3667 | f 1223 1229 1228 3668 | f 1224 1230 1229 3669 | f 887 884 1230 3670 | f 1226 1220 1221 3671 | f 1227 1221 1222 3672 | f 1228 1222 1223 3673 | f 1229 1223 1224 3674 | f 1230 1224 887 3675 | f 1225 1232 1231 3676 | f 1226 1233 1232 3677 | f 1227 1234 1233 3678 | f 1228 1235 1234 3679 | f 1229 1236 1235 3680 | f 1230 1237 1236 3681 | f 884 882 1237 3682 | f 1232 1225 1226 3683 | f 1233 1226 1227 3684 | f 1234 1227 1228 3685 | f 1235 1228 1229 3686 | f 1236 1229 1230 3687 | f 1237 1230 884 3688 | f 1231 880 881 3689 | f 1232 879 880 3690 | f 1233 878 879 3691 | f 1234 877 878 3692 | f 1235 876 877 3693 | f 1236 875 876 3694 | f 1237 874 875 3695 | f 882 274 874 3696 | f 880 1231 1232 3697 | f 879 1232 1233 3698 | f 878 1233 1234 3699 | f 877 1234 1235 3700 | f 876 1235 1236 3701 | f 875 1236 1237 3702 | f 874 1237 882 3703 | f 1017 1009 1238 3704 | f 1238 1240 1239 3705 | f 1009 1002 1240 3706 | f 1240 1238 1009 3707 | f 1239 1242 1241 3708 | f 1240 1243 1242 3709 | f 1002 996 1243 3710 | f 1242 1239 1240 3711 | f 1243 1240 1002 3712 | f 1241 1245 1244 3713 | f 1242 1246 1245 3714 | f 1243 1247 1246 3715 | f 996 991 1247 3716 | f 1245 1241 1242 3717 | f 1246 1242 1243 3718 | f 1247 1243 996 3719 | f 1244 1249 1248 3720 | f 1245 1250 1249 3721 | f 1246 1251 1250 3722 | f 1247 1252 1251 3723 | f 991 987 1252 3724 | f 1249 1244 1245 3725 | f 1250 1245 1246 3726 | f 1251 1246 1247 3727 | f 1252 1247 991 3728 | f 1248 1254 1253 3729 | f 1249 1255 1254 3730 | f 1250 1256 1255 3731 | f 1251 1257 1256 3732 | f 1252 1258 1257 3733 | f 987 984 1258 3734 | f 1254 1248 1249 3735 | f 1255 1249 1250 3736 | f 1256 1250 1251 3737 | f 1257 1251 1252 3738 | f 1258 1252 987 3739 | f 1253 1260 1259 3740 | f 1254 1261 1260 3741 | f 1255 1262 1261 3742 | f 1256 1263 1262 3743 | f 1257 1264 1263 3744 | f 1258 1265 1264 3745 | f 984 982 1265 3746 | f 1260 1253 1254 3747 | f 1261 1254 1255 3748 | f 1262 1255 1256 3749 | f 1263 1256 1257 3750 | f 1264 1257 1258 3751 | f 1265 1258 984 3752 | f 1259 980 981 3753 | f 1260 979 980 3754 | f 1261 978 979 3755 | f 1262 977 978 3756 | f 1263 976 977 3757 | f 1264 975 976 3758 | f 1265 974 975 3759 | f 982 410 974 3760 | f 980 1259 1260 3761 | f 979 1260 1261 3762 | f 978 1261 1262 3763 | f 977 1262 1263 3764 | f 976 1263 1264 3765 | f 975 1264 1265 3766 | f 974 1265 982 3767 | f 1117 1109 1266 3768 | f 1266 1268 1267 3769 | f 1109 1102 1268 3770 | f 1268 1266 1109 3771 | f 1267 1270 1269 3772 | f 1268 1271 1270 3773 | f 1102 1096 1271 3774 | f 1270 1267 1268 3775 | f 1271 1268 1102 3776 | f 1269 1273 1272 3777 | f 1270 1274 1273 3778 | f 1271 1275 1274 3779 | f 1096 1091 1275 3780 | f 1273 1269 1270 3781 | f 1274 1270 1271 3782 | f 1275 1271 1096 3783 | f 1272 1277 1276 3784 | f 1273 1278 1277 3785 | f 1274 1279 1278 3786 | f 1275 1280 1279 3787 | f 1091 1087 1280 3788 | f 1277 1272 1273 3789 | f 1278 1273 1274 3790 | f 1279 1274 1275 3791 | f 1280 1275 1091 3792 | f 1276 1282 1281 3793 | f 1277 1283 1282 3794 | f 1278 1284 1283 3795 | f 1279 1285 1284 3796 | f 1280 1286 1285 3797 | f 1087 1084 1286 3798 | f 1282 1276 1277 3799 | f 1283 1277 1278 3800 | f 1284 1278 1279 3801 | f 1285 1279 1280 3802 | f 1286 1280 1087 3803 | f 1281 1288 1287 3804 | f 1282 1289 1288 3805 | f 1283 1290 1289 3806 | f 1284 1291 1290 3807 | f 1285 1292 1291 3808 | f 1286 1293 1292 3809 | f 1084 1082 1293 3810 | f 1288 1281 1282 3811 | f 1289 1282 1283 3812 | f 1290 1283 1284 3813 | f 1291 1284 1285 3814 | f 1292 1285 1286 3815 | f 1293 1286 1084 3816 | f 1287 1080 1081 3817 | f 1288 1079 1080 3818 | f 1289 1078 1079 3819 | f 1290 1077 1078 3820 | f 1291 1076 1077 3821 | f 1292 1075 1076 3822 | f 1293 1074 1075 3823 | f 1082 546 1074 3824 | f 1080 1287 1288 3825 | f 1079 1288 1289 3826 | f 1078 1289 1290 3827 | f 1077 1290 1291 3828 | f 1076 1291 1292 3829 | f 1075 1292 1293 3830 | f 1074 1293 1082 3831 | f 717 709 1294 3832 | f 1294 1296 1295 3833 | f 709 702 1296 3834 | f 1296 1294 709 3835 | f 1295 1298 1297 3836 | f 1296 1299 1298 3837 | f 702 696 1299 3838 | f 1298 1295 1296 3839 | f 1299 1296 702 3840 | f 1297 1301 1300 3841 | f 1298 1302 1301 3842 | f 1299 1303 1302 3843 | f 696 691 1303 3844 | f 1301 1297 1298 3845 | f 1302 1298 1299 3846 | f 1303 1299 696 3847 | f 1300 1305 1304 3848 | f 1301 1306 1305 3849 | f 1302 1307 1306 3850 | f 1303 1308 1307 3851 | f 691 687 1308 3852 | f 1305 1300 1301 3853 | f 1306 1301 1302 3854 | f 1307 1302 1303 3855 | f 1308 1303 691 3856 | f 1304 1310 1309 3857 | f 1305 1311 1310 3858 | f 1306 1312 1311 3859 | f 1307 1313 1312 3860 | f 1308 1314 1313 3861 | f 687 684 1314 3862 | f 1310 1304 1305 3863 | f 1311 1305 1306 3864 | f 1312 1306 1307 3865 | f 1313 1307 1308 3866 | f 1314 1308 687 3867 | f 1309 1316 1315 3868 | f 1310 1317 1316 3869 | f 1311 1318 1317 3870 | f 1312 1319 1318 3871 | f 1313 1320 1319 3872 | f 1314 1321 1320 3873 | f 684 682 1321 3874 | f 1316 1309 1310 3875 | f 1317 1310 1311 3876 | f 1318 1311 1312 3877 | f 1319 1312 1313 3878 | f 1320 1313 1314 3879 | f 1321 1314 684 3880 | f 1315 1180 1181 3881 | f 1316 1179 1180 3882 | f 1317 1178 1179 3883 | f 1318 1177 1178 3884 | f 1319 1176 1177 3885 | f 1320 1175 1176 3886 | f 1321 1174 1175 3887 | f 682 153 1174 3888 | f 1180 1315 1316 3889 | f 1179 1316 1317 3890 | f 1178 1317 1318 3891 | f 1177 1318 1319 3892 | f 1176 1319 1320 3893 | f 1175 1320 1321 3894 | f 1174 1321 682 3895 | # 2560 faces, 0 coords texture 3896 | 3897 | # End of File 3898 | -------------------------------------------------------------------------------- /src/Viz.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIZ_ 2 | #define _VIZ_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | 13 | 14 | //********************** reset_viewer() 15 | void reset_viewer(igl::opengl::glfw::Viewer&viewer, 16 | const Eigen::MatrixXd&V, const Eigen::MatrixXi&F, 17 | const Eigen::VectorXd&vertex_func , 18 | const bool is_colorize_vertex = true, 19 | const double line_width = 5.0) { 20 | 21 | //set the mesh by clearing any data that is currently present 22 | viewer.data().clear(); 23 | 24 | viewer.data().show_lines = false;//don't wanna show mesh edges s 25 | viewer.data().set_face_based(true); 26 | viewer.data().line_width = line_width; 27 | viewer.data().set_mesh(V, F); 28 | viewer.core.align_camera_center(V, F); 29 | 30 | if (is_colorize_vertex) { 31 | //colorize the mesh vertices with the function 32 | Eigen::MatrixXd func_colors; 33 | igl::jet(vertex_func, true, func_colors); 34 | viewer.data().set_colors(func_colors); 35 | } 36 | 37 | } 38 | //****************************************************************************** 39 | 40 | 41 | //********************** add_edge_to_viewer() 42 | void add_edge_to_viewer(igl::opengl::glfw::Viewer&viewer, 43 | const Eigen::MatrixXd&iso_value, 44 | const std::vector&iso_edges, 45 | const bool is_random_colors = true, 46 | const float r = 0.0f, const float g = 0.0f, const float b = 0.0f){ 47 | 48 | 49 | Eigen::VectorXd val(iso_edges.size()); 50 | Eigen::MatrixXd color; 51 | 52 | if (is_random_colors) { 53 | for (int i = 0; i < iso_edges.size(); i++) { 54 | Eigen::MatrixXd isoVV1(1, 3); 55 | igl::slice(iso_value, iso_edges.at(i).row(0).col(1), 56 | Eigen::RowVector3d(0, 1, 2), isoVV1); 57 | val(i) = isoVV1(1); 58 | } 59 | igl::colormap(igl::COLOR_MAP_TYPE_JET, val, true, color); 60 | } 61 | 62 | 63 | //pass the isolines edges 64 | for (int i = 0; i < iso_edges.size(); i++) { 65 | 66 | const size_t num_edges = iso_edges.at(i).rows(); 67 | 68 | Eigen::MatrixXd isoVV1(num_edges, 3), isoVV2(num_edges, 3); 69 | 70 | //source 71 | igl::slice(iso_value, iso_edges.at(i).col(0), 72 | Eigen::RowVector3d(0, 1, 2), isoVV1); 73 | //target 74 | igl::slice(iso_value, iso_edges.at(i).col(1), 75 | Eigen::RowVector3d(0, 1, 2), isoVV2); 76 | 77 | viewer.data().add_edges( 78 | isoVV1, 79 | isoVV2, 80 | (is_random_colors) ? 81 | Eigen::RowVector3d(color.row(i)) : Eigen::RowVector3d(r, g, b)); 82 | } 83 | } 84 | //****************************************************************************** 85 | 86 | //********************** add_edge_to_viewer() 87 | void add_colorful_edge_to_viewer(igl::opengl::glfw::Viewer&viewer, 88 | const Eigen::MatrixXd&iso_value, 89 | const std::vector&iso_edges) { 90 | 91 | //colorful edges with the edge id in each isoline 92 | 93 | for (int i = 0; i < iso_edges.size(); i++) { 94 | const size_t num_edges = iso_edges.at(i).rows(); 95 | 96 | Eigen::VectorXd val(num_edges); 97 | 98 | // val(0) = 1.0f;//big number (1/0) 99 | 100 | for (int e =0 ; e < num_edges; e++) { 101 | val(e) = double(e); 102 | } 103 | 104 | Eigen::MatrixXd color; 105 | igl::colormap(igl::COLOR_MAP_TYPE_JET, val, true, color); 106 | 107 | 108 | for (int e = 0; e < num_edges; e++) { 109 | Eigen::MatrixXd isoVV1(1, 3), isoVV2(1, 3); 110 | int v0(iso_edges.at(i)(e, 0)), v1(iso_edges.at(i)(e, 1)); 111 | 112 | isoVV1 = iso_value.row(v0); 113 | isoVV2 = iso_value.row(v1); 114 | 115 | 116 | viewer.data().add_edges(isoVV1, isoVV2, 117 | Eigen::RowVector3d(color.row(e))); 118 | } 119 | } 120 | } 121 | //****************************************************************************** 122 | 123 | 124 | //********************** add_edge_to_viewer() 125 | void add_edge_to_viewer(igl::opengl::glfw::Viewer&viewer, 126 | const std::vector&points, 127 | bool is_connected = true) { 128 | //use this to draw the spiral 129 | //each row in the points contains points that compose a contour 130 | //listed in order 131 | 132 | 133 | Eigen::MatrixXd contour_color = (Eigen::MatrixXd::Random(1, 3) + 134 | Eigen::MatrixXd::Constant(1, 3, 1.f)) / 2.0f; 135 | 136 | for (int i = 0; i < points.size(); i++) { 137 | 138 | for (int p = 0; p < points.at(i).rows() - 1; p++) { 139 | 140 | viewer.data().add_edges(points.at(i).row(p), 141 | points.at(i).row(p + 1), contour_color); 142 | } 143 | contour_color = (Eigen::MatrixXd::Random(1, 3) + 144 | Eigen::MatrixXd::Constant(1, 3, 1.f)) / 2.0f; 145 | if (is_connected) { 146 | //connect the last point in this conour witht the next one 147 | if (i < points.size() - 1) { 148 | viewer.data().add_edges(points.at(i).row(points.at(i).rows() - 1), 149 | points.at(i + 1).row(0), contour_color); 150 | } 151 | } 152 | } 153 | 154 | } 155 | //****************************************************************************** 156 | 157 | 158 | //********************** add_vertices_id_text_to_viewer() 159 | void add_vertices_id_text_to_viewer(igl::opengl::glfw::Viewer&viewer, 160 | const Eigen::MatrixXd&iso_value){ 161 | 162 | for (int i = 0; i < iso_value.rows(); i++) { 163 | std::stringstream st; 164 | st << i; 165 | viewer.data().add_label(iso_value.row(i), st.str()); 166 | } 167 | 168 | } 169 | //****************************************************************************** 170 | 171 | 172 | //**********************isolines_obj() 173 | void isolines_obj(Eigen::MatrixXd&iso_value, 174 | std::vector&iso_edges) { 175 | 176 | std::fstream file("isolines.obj", std::ios::out); 177 | file.precision(20); 178 | for (int i = 0; i < iso_value.rows(); i++) { 179 | file << "v " << iso_value(i, 0) << " " << iso_value(i, 1) << " " 180 | << iso_value(i, 2) << std::endl; 181 | } 182 | 183 | for (int i = 0; i < iso_edges.size(); i++) { 184 | 185 | const size_t num_edges = iso_edges.at(i).rows(); 186 | for (int j = 0; j < num_edges; j++) { 187 | int p0 = iso_edges.at(i)(j, 0); 188 | int p1 = iso_edges.at(i)(j, 1); 189 | file << "l " << p0 + 1 << " " << p1 + 1 << std::endl; 190 | 191 | } 192 | } 193 | } 194 | //****************************************************************************** 195 | 196 | 197 | //**********************spiral_obj() 198 | void spiral_obj(std::vector&points, bool is_connected = true) 199 | { 200 | std::fstream file("spirals.obj", std::ios::out); 201 | file.precision(20); 202 | 203 | int total_edges(0); 204 | for (int i = 0; i < points.size(); i++) { 205 | for (int j = 0; j < points.at(i).rows() - 1; j++) { 206 | file << "v " << points.at(i)(j, 0) << " " << points.at(i)(j, 1) 207 | << " " << points.at(i)(j, 2) << std::endl; 208 | file << "v " << points.at(i)(j + 1, 0) << " " 209 | << points.at(i)(j + 1, 1) 210 | << " " << points.at(i)(j + 1, 2) << std::endl; 211 | total_edges++; 212 | file << "l " << total_edges * 2 - 1 213 | << " " << total_edges * 2 << std::endl; 214 | } 215 | if (is_connected) { 216 | if (i < points.size() - 1) { 217 | file << "v " << points.at(i)(points.at(i).rows() - 1, 0) 218 | << " " << points.at(i)(points.at(i).rows() - 1, 1) 219 | << " " << points.at(i)(points.at(i).rows() - 1, 2) 220 | << std::endl; 221 | 222 | file << "v " << points.at(i + 1)(0, 0) 223 | << " " << points.at(i + 1)(0, 1) 224 | << " " << points.at(i + 1)(0, 2) 225 | << std::endl; 226 | 227 | total_edges++; 228 | file << "l " << total_edges * 2 - 1 229 | << " " << total_edges * 2 << std::endl; 230 | 231 | } 232 | } 233 | } 234 | 235 | } 236 | //****************************************************************************** 237 | 238 | #endif /*_VIZ_*/ 239 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMON_ 2 | #define _COMMON_ 3 | 4 | #ifndef MIN_NUM_POINT_PER_CONTOUR 5 | #define MIN_NUM_POINT_PER_CONTOUR 15 6 | #endif 7 | 8 | 9 | #define VIZ //define to enable visualization utilities 10 | 11 | 12 | //********************** dist() 13 | template 14 | T dist(T x1, T y1, T z1, T x2, T y2, T z2) 15 | { 16 | T dx, dy, dz; 17 | dx = x1 - x2; 18 | dy = y1 - y2; 19 | dz = z1 - z2; 20 | dx *= dx; 21 | dy *= dy; 22 | dz *= dz; 23 | 24 | return dx + dy + dz; 25 | } 26 | //****************************************************************************** 27 | 28 | 29 | #endif /*_COMMON_*/ 30 | -------------------------------------------------------------------------------- /src/compute_surface_func.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPUTE_SURFACE_FUNC_ 2 | #define _COMPUTE_SURFACE_FUNC_ 3 | 4 | #include 5 | enum FUNCTION { 6 | HEIGHT, 7 | GEODESIC 8 | }; 9 | 10 | void compute_surface_func(const Eigen::MatrixXd & V, 11 | const Eigen::MatrixXi & F, Eigen::VectorXd & vertex_func, 12 | FUNCTION my_func) { 13 | 14 | //compute per vertex function and store it in vertex_func 15 | 16 | 17 | if (my_func == HEIGHT) { 18 | //using the height value as the per-vertex function 19 | vertex_func = V.col(1); 20 | } 21 | else if (my_func == GEODESIC) { 22 | int l = 0; 23 | } 24 | 25 | 26 | 27 | 28 | 29 | 30 | } 31 | 32 | 33 | #endif /*_COMPUTE_SURFACE_FUNC_*/ 34 | -------------------------------------------------------------------------------- /src/fermat3d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "isolines_ds.h" 4 | #include "fermat3d_imp.h" 5 | #include "compute_surface_func.h" 6 | 7 | #ifdef VIZ 8 | 9 | #include 10 | #include "Viz.h" 11 | 12 | igl::opengl::glfw::Viewer viewer; 13 | #endif 14 | 15 | 16 | int main(int argc, char *argv[]){ 17 | 18 | //Load mesh 19 | //../mesh/terrain_yen 20 | //../mesh/hemispherical.obj 21 | //../mesh/terrain_rough.obj 22 | 23 | Eigen::MatrixXd V; 24 | Eigen::MatrixXi F; 25 | igl::readOBJ("../mesh/terrain_yen.obj", V, F); 26 | 27 | 28 | Eigen::VectorXd vertex_func; 29 | compute_surface_func(V, F, vertex_func,HEIGHT); 30 | 31 | 32 | #ifdef VIZ 33 | reset_viewer(viewer, V, F, vertex_func); 34 | #endif 35 | 36 | 37 | int num_contours = 100; 38 | IsolinesDS iso_lines(V, F, vertex_func, num_contours); 39 | 40 | double tol = 0.0003*sqrt(dist(V.col(0).maxCoeff(), V.col(1).maxCoeff(), 41 | V.col(2).maxCoeff(), V.col(0).minCoeff(), V.col(1).minCoeff(), 42 | V.col(2).minCoeff())); 43 | 44 | std::vector> fermat = 45 | fermat3d(&iso_lines, tol); 46 | 47 | #ifdef VIZ 48 | viewer.launch(); 49 | #endif 50 | 51 | 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/fermat3d_imp.h: -------------------------------------------------------------------------------- 1 | #ifndef _FERMAT3D_IMP_ 2 | #define _FERMAT3D_IMP_ 3 | 4 | #include "common.h" 5 | #include "isolines_ds.h" 6 | 7 | 8 | #ifdef VIZ 9 | #include "Viz.h" 10 | extern igl::opengl::glfw::Viewer viewer; 11 | #endif 12 | 13 | 14 | //********************** get_spiral3d_one_region() 15 | std::vector get_spiral3d_one_region(IsolinesDS * iso_lines, 16 | const int reg_id, 17 | const double tol) { 18 | 19 | const std::vector region_isoE = iso_lines->get_region(reg_id); 20 | 21 | //Generate a single spiral from a (spirallable) isolines in region_isoE 22 | //each row in region_isoE stores the points of single contours 23 | 24 | //Starting with the outer contour (indesx 0) we keep rerouting to form 25 | //the spiral 26 | 27 | std::vector spiral; 28 | 29 | int str_edge_id, end_edge_id; 30 | 31 | Eigen::VectorXd p_end; 32 | 33 | for (int i = 0; i < region_isoE.size(); i++) { 34 | const int num_edges = region_isoE.at(i).rows(); 35 | 36 | Eigen::MatrixXd contour(num_edges, 3); 37 | 38 | int direction; 39 | int p_str_id; 40 | 41 | 42 | if (i == 0) { 43 | //for the first contour, we can pick any vertex to be our starting 44 | //point 45 | str_edge_id = 0; 46 | p_str_id = region_isoE.at(i)(str_edge_id, 0); 47 | 48 | direction = 1; 49 | end_edge_id = num_edges - 1; 50 | } 51 | else { 52 | //For subsequent contours, we have to choose the right direction 53 | //so that the spiral can continue growing 54 | //Also we pick the next edge (not the edge that we projected 55 | //on it from previous isoline) 56 | 57 | //1) using distance 58 | int str_edge_id_p0, str_edge_id_p1; 59 | str_edge_id_p0 = region_isoE.at(i)(str_edge_id, 0); 60 | str_edge_id_p1 = region_isoE.at(i)(str_edge_id, 1); 61 | 62 | /*double dd0 = dist(isoV(p_str_id, 0), 63 | isoV(p_str_id, 1), 64 | isoV(p_str_id, 2), 65 | isoV(str_edge_id_p0, 0), 66 | isoV(str_edge_id_p0, 1), 67 | isoV(str_edge_id_p0, 2)); 68 | 69 | double dd1 = dist(isoV(p_str_id, 0), 70 | isoV(p_str_id, 1), 71 | isoV(p_str_id, 2), 72 | isoV(str_edge_id_p1, 0), 73 | isoV(str_edge_id_p1, 1), 74 | isoV(str_edge_id_p1, 2));*/ 75 | 76 | double dd0 = dist( 77 | iso_lines->get_coordinates(p_str_id)(0), 78 | iso_lines->get_coordinates(p_str_id)(1), 79 | iso_lines->get_coordinates(p_str_id)(2), 80 | iso_lines->get_coordinates(str_edge_id_p0)(0), 81 | iso_lines->get_coordinates(str_edge_id_p0)(1), 82 | iso_lines->get_coordinates(str_edge_id_p0)(2)); 83 | 84 | double dd1 = dist( 85 | iso_lines->get_coordinates(p_str_id)(0), 86 | iso_lines->get_coordinates(p_str_id)(1), 87 | iso_lines->get_coordinates(p_str_id)(2), 88 | iso_lines->get_coordinates(str_edge_id_p1)(0), 89 | iso_lines->get_coordinates(str_edge_id_p1)(1), 90 | iso_lines->get_coordinates(str_edge_id_p1)(2)); 91 | 92 | end_edge_id = str_edge_id; 93 | 94 | 95 | if (dd1 < dd0) { 96 | //set direction 97 | p_str_id = str_edge_id_p1; 98 | direction = 1; 99 | 100 | //get next edge 101 | str_edge_id = (str_edge_id == region_isoE.at(i).rows() - 1) 102 | ? 0 : str_edge_id + 1; 103 | } 104 | else { 105 | //set direction 106 | p_str_id = str_edge_id_p0; 107 | direction = -1; 108 | 109 | //get next edge 110 | str_edge_id = (str_edge_id == 0) ? 111 | region_isoE.at(i).rows() - 1 : str_edge_id - 1; 112 | } 113 | 114 | /* 115 | //2) using vectors 116 | Eigen::VectorXd p_proj = spiral.back().row( 117 | spiral.back().rows() - 1); 118 | 119 | Eigen::VectorXd va0 = isoV.row(str_edge_id_p0) - p_proj.transpose(); 120 | Eigen::VectorXd va1 = isoV.row(str_edge_id_p1) - p_proj.transpose(); 121 | Eigen::VectorXd vb; 122 | if (spiral.size() == 1) { 123 | vb = isoV.row(p_str_id) - p_end.transpose(); 124 | } 125 | else { 126 | Eigen::MatrixXd last_pt_prv_contour = 127 | spiral.at(spiral.size() - 2).row( 128 | spiral.at(spiral.size() - 2).rows() - 1); 129 | vb = isoV.row(p_str_id) - last_pt_prv_contour; 130 | } 131 | 132 | va0.normalize(); 133 | va1.normalize(); 134 | vb.normalize(); 135 | 136 | double dir0, dir1; 137 | dir0 = va0.dot(vb); 138 | dir1 = va1.dot(vb); 139 | 140 | //*** 141 | if (false) { 142 | add_edge_to_viewer(viewer, spiral,false); 143 | 144 | viewer.data().add_points(isoV.row(p_str_id), 145 | Eigen::RowVector3d(0.0, 0, 0.0)); 146 | 147 | viewer.data().add_points(p_proj.transpose(), 148 | Eigen::RowVector3d(1.0, 0, 1.0)); 149 | viewer.data().add_points(isoV.row(str_edge_id_p0), 150 | Eigen::RowVector3d(1.0, 0, 0.0)); 151 | viewer.data().add_points(isoV.row(str_edge_id_p1), 152 | Eigen::RowVector3d(0.0, 0, 1.0)); 153 | 154 | std::cout << isoV.row(str_edge_id_p0) << std::endl; 155 | std::cout << isoV.row(str_edge_id_p1) << std::endl; 156 | std::cout << p_proj.transpose() << std::endl; 157 | 158 | if (i == 1) { 159 | viewer.data().add_points( 160 | p_end.transpose(), 161 | Eigen::RowVector3d(0.0, 1.0, 0.0)); 162 | } 163 | else { 164 | viewer.data().add_points( 165 | spiral.at(spiral.size() - 2).row( 166 | spiral.at(spiral.size() - 2).rows() - 1), 167 | Eigen::RowVector3d(0.0, 1.0, 0.0)); 168 | } 169 | 170 | 171 | viewer.launch(); 172 | } 173 | 174 | 175 | if (dir0 *dir1 > 0.0000001) { 176 | std::cout << "Error::get_spiral3d() can not decide which" 177 | << "direction to take!!!" << std::endl; 178 | system("pause"); 179 | } 180 | 181 | end_edge_id = str_edge_id; 182 | 183 | if (dir1 > 0.0) { 184 | //set direction 185 | p_str_id = str_edge_id_p1; 186 | direction = 1; 187 | 188 | //get next edge 189 | str_edge_id = (str_edge_id == region_isoE.at(i).rows() - 1) 190 | ? 0 : str_edge_id + 1; 191 | } 192 | else { 193 | //set direction 194 | p_str_id = str_edge_id_p0; 195 | direction = -1; 196 | 197 | //get next edge 198 | str_edge_id = (str_edge_id == 0) ? 199 | region_isoE.at(i).rows() - 1 : str_edge_id - 1; 200 | } */ 201 | 202 | 203 | } 204 | 205 | //this is a guide point that we use such that if we get too close 206 | //to it, we re-route to the next isoline 207 | //p_end = 0.5*(isoV.row(region_isoE.at(i)(end_edge_id, 0)) + 208 | // isoV.row(region_isoE.at(i)(end_edge_id, 1))); 209 | 210 | p_end = 0.5*(iso_lines->get_coordinates(region_isoE.at(i)(end_edge_id, 0)) + 211 | iso_lines->get_coordinates(region_isoE.at(i)(end_edge_id, 1))); 212 | 213 | //** 214 | //viewer.data().add_edges(isoV.row(region_isoE.at(i)(end_edge_id, 0)), 215 | // isoV.row(region_isoE.at(i)(end_edge_id, 1)), 216 | // Eigen::RowVector3d(0.5, 1.0, 0.3)); 217 | 218 | 219 | int num_point_take_from_contour = 0; 220 | int ed = str_edge_id; 221 | 222 | while (true) { 223 | 224 | //The edge end points id 225 | int ed_p0(region_isoE.at(i)(ed, 0)), 226 | ed_p1(region_isoE.at(i)(ed, 1)); 227 | 228 | //if (direction < 0) { std::swap(ed_p0, ed_p1); } 229 | 230 | //Edge mid point 231 | //Eigen::VectorXd p_mid = 0.5*(isoV.row(ed_p0) + isoV.row(ed_p1)); 232 | 233 | Eigen::VectorXd p_mid = 0.5*( 234 | iso_lines->get_coordinates(ed_p0) + 235 | iso_lines->get_coordinates(ed_p1)); 236 | 237 | //The distance to last point 238 | double dd = dist(p_mid(0), p_mid(1), p_mid(2), 239 | p_end(0), p_end(1), p_end(2)); 240 | 241 | 242 | //If we are too close to the end point and have taken enough points 243 | //from this contour 244 | if (dd < tol && 245 | num_point_take_from_contour>MIN_NUM_POINT_PER_CONTOUR - 3) { 246 | 247 | if (i == region_isoE.size() - 1) { 248 | //if it is the las contour, we add the mid point and quit 249 | //since no projection needed 250 | contour.row(num_point_take_from_contour) = p_mid; 251 | num_point_take_from_contour++; 252 | break; 253 | } 254 | 255 | //We should reroute here by projecting to the nexxt isoline 256 | Eigen::VectorXd t(1), sqrD(1); 257 | int edge_p0(0), edge_p1(0); 258 | 259 | //project_point_to_isoline(p_mid, isoV, region_isoE.at(i + 1), 260 | // t, sqrD, edge_p0, edge_p1, str_edge_id); 261 | 262 | iso_lines->project_point_to_isoline(p_mid, 263 | region_isoE.at(i + 1), 264 | t, sqrD, edge_p0, edge_p1, str_edge_id); 265 | 266 | 267 | //str_edge_id for the next contour 268 | if (abs(sqrD(0, 0) - std::numeric_limits::max()) < 1) { 269 | std::cout << "Error:: get_spiral3d" << 270 | " Can not find intersection" << std::endl; 271 | system("pause"); 272 | } 273 | 274 | Eigen::VectorXd p_proj; 275 | p_proj.resize(3); 276 | 277 | //p_proj = isoV.row(edge_p0).transpose() 278 | // + t(0)*(isoV.row(edge_p1).transpose() - 279 | // isoV.row(edge_p0).transpose()); 280 | 281 | p_proj = iso_lines->get_coordinates(edge_p0).transpose() 282 | + t(0)*(iso_lines->get_coordinates(edge_p1).transpose() - 283 | iso_lines->get_coordinates(edge_p0).transpose()); 284 | 285 | 286 | contour.row(num_point_take_from_contour) = p_mid; 287 | contour.row(num_point_take_from_contour) = p_proj; 288 | num_point_take_from_contour += 2; 289 | 290 | //** 291 | /*if (false) { 292 | //viewer.data().add_points(p_mid.transpose(), 293 | // Eigen::RowVector3d(0.0, 0.0, 1.0)); 294 | //viewer.data().add_points(p_proj.transpose(), 295 | // Eigen::RowVector3d(1.0, 0.0, 1.0)); 296 | if (false) { 297 | add_edge_to_viewer(viewer, spiral, true); 298 | viewer.launch(); 299 | } 300 | } 301 | if (false) { 302 | viewer.launch(); 303 | }*/ 304 | 305 | break; 306 | } 307 | else { 308 | //Add the point to the contour 309 | contour.row(num_point_take_from_contour) = p_mid; 310 | num_point_take_from_contour++; 311 | } 312 | if (direction == 1) { 313 | ed = (ed == region_isoE.at(i).rows() - 1) ? 0 : ed + 1; 314 | } 315 | else { 316 | ed = (ed == 0) ? region_isoE.at(i).rows() - 1 : ed - 1; 317 | } 318 | } 319 | 320 | //only push to the spiral the true points 321 | spiral.push_back(contour.topRows(num_point_take_from_contour - 1)); 322 | 323 | } 324 | 325 | //add_edge_to_viewer(viewer, spiral, true); 326 | //viewer.launch(); 327 | 328 | return spiral; 329 | 330 | 331 | } 332 | //***************************************************************************** 333 | 334 | 335 | //********************** get_fermat3d_one_region() 336 | std::vector get_fermat3d_one_region(IsolinesDS * iso_lines, 337 | std::vector spiral, 338 | const double tol) { 339 | //construct fermat spiral from contour spiral 340 | //each row spiral is a seperate contour whose last point is connected 341 | //to the first point of the next contour 342 | int MAX_SIZE = 0; 343 | for (int i = 0; i < spiral.size(); i++) { 344 | MAX_SIZE += spiral.at(i).rows(); 345 | } 346 | 347 | Eigen::MatrixXd inward(MAX_SIZE, 3), outward(MAX_SIZE, 3); 348 | int num_inward_pts(0), num_outward_pts(0); 349 | 350 | int current_path_id = 0; 351 | int nxt_pt_id = 1; 352 | int END = 3; 353 | Eigen::MatrixXd p_in = spiral.at(0).row(0); 354 | Eigen::MatrixXd p_out = spiral.at(0).row(spiral.at(0).rows() - END); 355 | 356 | Eigen::MatrixXd nxt_pt; 357 | nxt_pt = p_in; 358 | 359 | #ifdef VIZ 360 | //** 361 | viewer.data().add_points(p_in, Eigen::RowVector3d(0.0, 0.0, 1.0)); 362 | viewer.data().add_points(p_out, Eigen::RowVector3d(1.0, 0.0, 0.0)); 363 | #endif 364 | 365 | Eigen::MatrixXd contour_end_pt = spiral.at(0).row( 366 | spiral.at(0).rows() - (END + 6)); 367 | 368 | //** 369 | //viewer.data().add_points(contour_end_pt, Eigen::RowVector3d(1.0, 0, 1.0)); 370 | 371 | //viewer.launch(); 372 | 373 | std::vector reroute_pt;//index of the rerouting points in the inward 374 | //link. used to construct the outward line 375 | 376 | inward.row(num_inward_pts) = nxt_pt; 377 | num_inward_pts++; 378 | 379 | int num_points_taken_from_path = 1; 380 | 381 | //did the inward link walked on the last contour 382 | bool walked_on_last_contour = false; 383 | while (true) { 384 | nxt_pt = spiral.at(current_path_id).row(nxt_pt_id); 385 | 386 | 387 | //The distance to last point 388 | double dd = dist(contour_end_pt(0), 389 | contour_end_pt(1), 390 | contour_end_pt(2), 391 | nxt_pt(0), nxt_pt(1), nxt_pt(2)); 392 | 393 | if (dd < tol && 394 | num_points_taken_from_path>MIN_NUM_POINT_PER_CONTOUR - 6) { 395 | 396 | //reroute 397 | inward.row(num_inward_pts) = nxt_pt; 398 | num_inward_pts++; 399 | num_points_taken_from_path++; 400 | inward.row(num_inward_pts) = contour_end_pt; 401 | num_inward_pts++; 402 | num_points_taken_from_path++; 403 | 404 | //** 405 | //viewer.data().add_points(nxt_pt, Eigen::RowVector3d(0, 0, 0)); 406 | //viewer.data().add_points(contour_end_pt, 407 | // Eigen::RowVector3d(1.0, 0.0, 1.0)); 408 | 409 | //index of reroute point 410 | if (current_path_id > 0) { 411 | reroute_pt.push_back(num_inward_pts - 1); 412 | //** 413 | //viewer.data().add_points(contour_end_pt, 414 | // Eigen::RowVector3d(0, 1.0, 1.0)); 415 | } 416 | 417 | if (current_path_id == spiral.size() - 1) { 418 | walked_on_last_contour = true; 419 | } 420 | 421 | //move to the next path 422 | if (current_path_id != spiral.size() - 1) { 423 | current_path_id++; 424 | num_points_taken_from_path = 0; 425 | } 426 | 427 | 428 | //reroute and prepare the next contour by projecting to the next 429 | //path 430 | Eigen::VectorXd t(1, 1), sqrD(1, 1); 431 | int seg_st(0), seg_end(0); 432 | 433 | //project_point_to_isoline(contour_end_pt.transpose(), 434 | // spiral.at(current_path_id), t, sqrD, seg_st, seg_end); 435 | 436 | iso_lines->project_point_to_isoline(contour_end_pt.transpose(), 437 | spiral.at(current_path_id), t, sqrD, seg_st, seg_end); 438 | 439 | 440 | if (abs(sqrD(0, 0) - std::numeric_limits::max()) < 1) { 441 | std::cout << "Error:: get_fermat3d" << 442 | " Can not find intersection (0)" << std::endl; 443 | 444 | //** 445 | //viewer.data().add_points(contour_end_pt, 446 | // Eigen::RowVector3d(0, 0, 1.0)); 447 | 448 | //std::vector fermat; 449 | //fermat.push_back(inward.topRows(num_inward_pts)); 450 | //add_edge_to_viewer(viewer, fermat, true); 451 | //viewer.launch(); 452 | system("pause"); 453 | } 454 | Eigen::VectorXd p_proj(3); 455 | 456 | p_proj = spiral.at(current_path_id).row(seg_st).transpose() 457 | + t(0)*(spiral.at(current_path_id).row(seg_end).transpose() - 458 | spiral.at(current_path_id).row(seg_st).transpose()); 459 | 460 | //add the projected point to the link 461 | inward.row(num_inward_pts) = p_proj; 462 | num_inward_pts++; 463 | num_points_taken_from_path++; 464 | 465 | 466 | //** 467 | //viewer.data().add_points(p_proj.transpose(), 468 | // Eigen::RowVector3d(0, 1.0, 0)); 469 | 470 | //the next id is the end of the segment we projected onto since 471 | // we are moving ahead 472 | nxt_pt_id = seg_end; 473 | 474 | 475 | if (current_path_id < spiral.size() - 1) { 476 | //get the contour_end_pt by moving a little backward from 477 | //the projected point and then project 478 | 479 | int end_id = seg_st; 480 | for (int hh = 0; hh < END + 10; hh++) { 481 | //we should not step into another path 482 | if (end_id == 0) { 483 | std::cout << "Should not get here. Fix by moving to" << 484 | " another path or just terminate" << std::endl; 485 | //std::vector fermat; 486 | //fermat.push_back(inward.topRows(num_inward_pts)); 487 | //add_edge_to_viewer(viewer, fermat, true); 488 | //viewer.launch(); 489 | 490 | system("pause"); 491 | } 492 | end_id--; 493 | //end_id = (end_id == 0) ? 494 | // spiral.at(current_path_id).rows() - 1 : end_id - 1; 495 | } 496 | 497 | //The point after moving a little backward from the project 498 | //point 499 | contour_end_pt = spiral.at(current_path_id).row(end_id); 500 | 501 | //** 502 | //viewer.data().add_points(contour_end_pt, 503 | // Eigen::RowVector3d(1.0, 0.0, 1.0)); 504 | 505 | //Now project to get the actual contour_end_pt 506 | Eigen::VectorXd t1(1, 1), sqrD1(1, 1); 507 | int st1(0), end1(0); 508 | 509 | //project_point_to_isoline(contour_end_pt.transpose(), 510 | // spiral.at(current_path_id + 1), t1, sqrD1, st1, end1); 511 | 512 | iso_lines->project_point_to_isoline(contour_end_pt.transpose(), 513 | spiral.at(current_path_id + 1), t1, sqrD1, st1, end1); 514 | 515 | 516 | if (abs(sqrD1(0, 0) - std::numeric_limits::max()) < 1){ 517 | std::cout << "Error:: get_fermat3d" << 518 | " Can not find porjection" << std::endl; 519 | //std::vector fermat; 520 | //fermat.push_back(inward.topRows(num_inward_pts)); 521 | //add_edge_to_viewer(viewer, fermat, true); 522 | //viewer.launch(); 523 | system("pause"); 524 | } 525 | contour_end_pt = (spiral.at( 526 | current_path_id + 1).row(st1).transpose() 527 | + t1(0)*(spiral.at( 528 | current_path_id + 1).row(end1).transpose() - 529 | spiral.at( 530 | current_path_id + 1).row(st1).transpose()) 531 | ).transpose(); 532 | 533 | //** 534 | //viewer.data().add_points(contour_end_pt, 535 | // Eigen::RowVector3d(1.0, 0.0, 1.0)); 536 | 537 | } 538 | else { 539 | //If we are near the end, we don't care much about 540 | //contour_end_pt but we add it to compute the distance to know 541 | //when should we stop 542 | 543 | //if walked_on_last_contour == true 544 | //in this case, we have reached the end, and thus the 545 | //outward link will start by projecting and walking 546 | //along path_id = spiral.size()-2 547 | //this happens when the number of contours is odd (but not 548 | //necessarily so) 549 | 550 | //if walked_on_last_contour == false 551 | //in this case, we still have one final path below the last 552 | //one that the inward link has reached. for that, the 553 | //outward link starts by walking along the path with 554 | //id = current_path_id (which the inward has not walked on 555 | //to yet) and we start with the seg_st because we are 556 | //moving in the opposite direction 557 | 558 | 559 | if (walked_on_last_contour) { 560 | //std::cout<<"Error:: get_fermat3d() Make the number of " 561 | // << "contours even to scape this."<project_point_to_isoline( 578 | spiral.at(current_path_id).row(seg_end).transpose(), 579 | spiral.at(current_path_id - 1), 580 | t2, sqrD2, seg_st, seg_end); 581 | 582 | 583 | if (abs(sqrD2(0, 0) 584 | - std::numeric_limits::max()) < 1) { 585 | std::cout << "Error:: get_fermat3d" << 586 | " Can not find intersection (1)" << std::endl; 587 | system("pause"); 588 | } 589 | current_path_id--; 590 | reroute_pt.pop_back(); 591 | } 592 | 593 | nxt_pt_id = seg_st; 594 | 595 | //** 596 | //viewer.data().add_points(spiral.at( 597 | // current_path_id).row(seg_st), 598 | // Eigen::RowVector3d(0.5, 0.25, 0.5)); 599 | 600 | /*viewer.data().add_points(spiral.at( 601 | current_path_id).row(seg_end), 602 | Eigen::RowVector3d(0, 0, 0.5));*/ 603 | 604 | //viewer.launch(); 605 | break; 606 | 607 | } 608 | 609 | 610 | //** 611 | //viewer.data().add_points(contour_end_pt, 612 | // Eigen::RowVector3d(0.5, 0.5, 0.5)); 613 | 614 | } 615 | else { 616 | inward.row(num_inward_pts) = nxt_pt; 617 | num_inward_pts++; 618 | num_points_taken_from_path++; 619 | 620 | 621 | //** 622 | //viewer.data().add_points(nxt_pt, Eigen::RowVector3d(0, 0, 0)); 623 | 624 | 625 | if (nxt_pt_id == spiral.at(current_path_id).rows() - 1) { 626 | //move to next conour 627 | if (current_path_id == spiral.size() - 1) { 628 | //this was the last one alreadt 629 | break; 630 | } 631 | 632 | current_path_id++; 633 | nxt_pt_id = 0; 634 | } 635 | else { 636 | nxt_pt_id++; 637 | } 638 | } 639 | } 640 | 641 | 642 | 643 | //outward link 644 | //follow the same logic but with going in the opposite direction 645 | if (reroute_pt.size() > 0) { 646 | contour_end_pt = inward.row(reroute_pt.back()); 647 | reroute_pt.pop_back(); 648 | } 649 | else { 650 | //if there is no enough rerouting points i.e, the inward linke is just 651 | //one path, the the outward is one path also ends at p_out 652 | contour_end_pt = p_out; 653 | } 654 | num_points_taken_from_path = 0; 655 | 656 | while (true) { 657 | nxt_pt = spiral.at(current_path_id).row(nxt_pt_id); 658 | 659 | //The distance to last point 660 | double dd = dist(contour_end_pt(0), 661 | contour_end_pt(1), 662 | contour_end_pt(2), 663 | nxt_pt(0), nxt_pt(1), nxt_pt(2)); 664 | if (dd < tol && 665 | num_points_taken_from_path > MIN_NUM_POINT_PER_CONTOUR - 3) { 666 | 667 | outward.row(num_outward_pts) = nxt_pt; 668 | num_outward_pts++; 669 | 670 | //** 671 | //viewer.data().add_points(outward.row(num_outward_pts - 1), 672 | // Eigen::RowVector3d(0.5, 0.5, 0.5)); 673 | 674 | //decrement the path id 675 | if (current_path_id > 1) { 676 | //we don't want reach path with id =0 because we know that this 677 | //path is already occupoed by the inward link 678 | current_path_id--; 679 | num_points_taken_from_path = 0; 680 | } 681 | else { 682 | //add the exit point and exit 683 | outward.row(num_outward_pts) = contour_end_pt; 684 | num_outward_pts++; 685 | break; 686 | } 687 | 688 | 689 | 690 | //reroute by projection on the current path (we already updated it) 691 | Eigen::VectorXd t(1, 1), sqrD(1, 1); 692 | int seg_st(0), seg_end(0); 693 | 694 | //project_point_to_isoline(nxt_pt.transpose(), 695 | // spiral.at(current_path_id), t, sqrD, seg_st, seg_end); 696 | 697 | iso_lines->project_point_to_isoline(nxt_pt.transpose(), 698 | spiral.at(current_path_id), t, sqrD, seg_st, seg_end); 699 | 700 | 701 | if (abs(sqrD(0, 0) - std::numeric_limits::max()) < 1) { 702 | std::cout << "Error:: get_fermat3d" << 703 | " Can not find intersection" << std::endl; 704 | system("pause"); 705 | } 706 | Eigen::VectorXd p_proj(3); 707 | 708 | p_proj = spiral.at(current_path_id).row(seg_st).transpose() 709 | + t(0)*(spiral.at(current_path_id).row(seg_end).transpose() - 710 | spiral.at(current_path_id).row(seg_st).transpose()); 711 | 712 | //add the projected point to the link 713 | outward.row(num_outward_pts) = p_proj; 714 | num_outward_pts++; 715 | num_points_taken_from_path++; 716 | 717 | //** 718 | //viewer.data().add_points(outward.row(num_outward_pts - 1), 719 | // Eigen::RowVector3d(0.1, 1.0, 1.0)); 720 | 721 | 722 | //the next id is the start of the segment since we are moving 723 | //in the opposite direction 724 | nxt_pt_id = seg_st; 725 | 726 | //update the contour_end_pt so we know where to stop next time 727 | if (reroute_pt.size() == 0) { 728 | contour_end_pt = p_out; 729 | } 730 | else { 731 | contour_end_pt = inward.row(reroute_pt.back()); 732 | reroute_pt.pop_back(); 733 | } 734 | } 735 | else { 736 | //if we are still far from the rerouting point, we add the next_pt 737 | //and decrement the point id (and the path if necessary) 738 | outward.row(num_outward_pts) = nxt_pt; 739 | num_outward_pts++; 740 | num_points_taken_from_path++; 741 | 742 | //** 743 | //viewer.data().add_points(outward.row(num_outward_pts - 1), 744 | // Eigen::RowVector3d(0.5, 0.5, 0.5)); 745 | 746 | if (nxt_pt_id == 0) { 747 | if (current_path_id == 0) { break; } 748 | current_path_id--; 749 | nxt_pt_id = spiral.at(current_path_id).rows() - 1; 750 | } 751 | else { 752 | nxt_pt_id--; 753 | } 754 | 755 | } 756 | } 757 | 758 | std::vector fermat; 759 | fermat.push_back(inward.topRows(num_inward_pts)); 760 | fermat.push_back(outward.topRows(num_outward_pts)); 761 | 762 | #ifdef VIZ 763 | add_edge_to_viewer(viewer, fermat, true); 764 | #endif 765 | 766 | //viewer.launch(); 767 | 768 | return fermat; 769 | 770 | 771 | } 772 | //***************************************************************************** 773 | 774 | 775 | //********************** fermat3d() 776 | std::vector> fermat3d( 777 | IsolinesDS * iso_lines, const double tol) { 778 | 779 | 780 | //Create the fermat spiral for a bunch of spirallable regions 781 | int num_regions = iso_lines->get_num_spiral_region(); 782 | 783 | //std::vector> spiral(num_regions); 784 | //for (int r = 0; r < num_regions; r++) { 785 | // spiral.at(r) = get_spiral3d_one_region(iso_lines, r, tol); 786 | //} 787 | std::vector> spiral; 788 | for (int r = 0; r < num_regions; r++) { 789 | if (iso_lines->get_num_contours(r) < 6) { continue; } 790 | spiral.push_back(get_spiral3d_one_region(iso_lines, r, tol)); 791 | } 792 | 793 | //std::vector> fermat(spiral.size()); 794 | //for (int s = 0; s < spiral.size(); s++) { 795 | // fermat.at(s) = get_fermat3d_one_region(iso_lines, spiral.at(s), tol); 796 | //} 797 | std::vector> fermat; 798 | for (int s = 0; s < spiral.size(); s++) { 799 | fermat.push_back(get_fermat3d_one_region(iso_lines,spiral.at(s), tol)); 800 | } 801 | 802 | return fermat; 803 | 804 | } 805 | //***************************************************************************** 806 | #endif /*_FERMAT3D_IMP_*/ 807 | -------------------------------------------------------------------------------- /src/isolines_ds.h: -------------------------------------------------------------------------------- 1 | #ifndef _ISOLINES_DS_ 2 | #define _ISOLINES_DS_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "common.h" 12 | 13 | 14 | #ifdef VIZ 15 | #include "Viz.h" 16 | extern igl::opengl::glfw::Viewer viewer; 17 | #endif 18 | 19 | 20 | 21 | class IsolinesDS 22 | { 23 | public: 24 | IsolinesDS() {}; 25 | 26 | //Populate the basic data structure that is used for further processing 27 | //of the isolines (isoV and isoE) 28 | IsolinesDS(Eigen::MatrixXd&V, Eigen::MatrixXi&F, 29 | Eigen::VectorXd& vertex_func, const int num_contours); 30 | 31 | //Find the projection of a point onto a single isoline (my_isoline) 32 | //whose the indeices of its edges can index isoV 33 | void project_point_to_isoline(const Eigen::VectorXd & point, 34 | const Eigen::MatrixXi & my_isoline, 35 | Eigen::VectorXd & t_min, 36 | Eigen::VectorXd & sqrD_min, 37 | int &edge_p0, int&edge_p1, int&edge_id); 38 | 39 | //Find the projection of a point onto a single path defined by a set of 40 | //points (given their xy coordinates) 41 | void project_point_to_isoline(const Eigen::VectorXd & point, 42 | const Eigen::MatrixXd & path, 43 | Eigen::VectorXd & t_min, 44 | Eigen::VectorXd & sqrD_min, 45 | int &edge_p0, int&edge_p1); 46 | 47 | //*** getter 48 | inline int get_num_spiral_region() { 49 | //return the number of spirallal regions 50 | return spiral_regions.size(); 51 | } 52 | 53 | inline int get_num_contours(int r) { 54 | //return the number of contours in region number r 55 | return spiral_regions.at(r).size(); 56 | } 57 | 58 | inline std::vector get_region(int id) { 59 | //return the region by its index 60 | return spiral_regions.at(id); 61 | } 62 | 63 | inline Eigen::MatrixXd get_coordinates(int v_id) { 64 | //return the vertex cooridnates. vertex here is an isoline vertex 65 | //not a mesh vertex 66 | return isoV.row(v_id); 67 | } 68 | 69 | 70 | ~IsolinesDS() {}; 71 | 72 | private: 73 | 74 | //******** VARIABLES *********// 75 | 76 | Eigen::MatrixXd V;//Mesh input vertices 77 | Eigen::MatrixXi F;//Mesh input faces 78 | Eigen::VectorXd vertex_func; //Function defined over the mesh 79 | 80 | Eigen::MatrixXd isoV;//isolines vertices 81 | Eigen::MatrixXi isoE;//isolines edges 82 | 83 | int num_contours; //number of contours used to get the isolines 84 | 85 | //groups the isolines by their isovalue 86 | std::vector isolines_groups; 87 | 88 | //groups of spirallable region 89 | //spiral_region[X][Y].row(Z) gives the end points of the Zth edges 90 | //of the Yth isolines in the Xth spirallable region 91 | std::vector> spiral_regions; 92 | 93 | 94 | 95 | //******** FUNCTIONS *********// 96 | 97 | //Get the isovalue of the vertex 98 | //vertex here is a vertex on the isolines not a mesh vertex 99 | auto isovalue(int vertex); 100 | 101 | //Populates isolines_groups 102 | void grouping_isolines(const bool is_sort_ascend = false); 103 | 104 | //Clean up the iso edge from edges that has the same start and end point 105 | void remove_zero_length_isoE_points(); 106 | 107 | 108 | //Find the spirallable region (grouping_isolines() should be called first) 109 | void spirallable_region(); 110 | 111 | //Find the one-sided Hausdorff distance between two isolines (source and 112 | //target) by picking NUM_SAMPLES of the source vertices and find their 113 | //projection on the target 114 | double isoline_isoline_min_distance(const Eigen::MatrixXi & source, 115 | const Eigen::MatrixXi & target, const int NUM_SAMPLES = 100); 116 | 117 | 118 | //Creating vertex edge data structure which gives for each vertex 119 | //what edges it is connected to. Vertex here is a vertex in the isolines 120 | //not a mesh vertex 121 | void create_vertex_edge(const Eigen::MatrixXi isoE, 122 | Eigen::MatrixXi & vertex_edge); 123 | 124 | //Building chains from edges (their vertices) have the same isovalue 125 | void create_chain_use_vertex_edge(const Eigen::MatrixXi & iso_edges, 126 | const Eigen::MatrixXi & vertex_edge, 127 | std::vector & chain_iso_edges); 128 | 129 | }; 130 | 131 | //********************** IsolinesDS::IsolinesDS() 132 | IsolinesDS::IsolinesDS(Eigen::MatrixXd&V, Eigen::MatrixXi&F, 133 | Eigen::VectorXd& vertex_func, const int num_contours) : 134 | V(V),F(F),vertex_func(vertex_func), num_contours(num_contours) { 135 | 136 | //Construct the isolines 137 | igl::isolines(V, F, vertex_func, num_contours, isoV, isoE); 138 | 139 | //clean up by removing the duplicated edges (edges with same start and end 140 | //point) 141 | remove_zero_length_isoE_points(); 142 | 143 | //group the isolines by their isovalue 144 | grouping_isolines(true); 145 | 146 | //Creating spirallable regions 147 | spirallable_region(); 148 | 149 | //for (int i = 0; i < spiral_regions.size(); i++) { 150 | // add_edge_to_viewer(viewer, isoV, spiral_regions.at(i), false, 151 | // double(rand()) / double(RAND_MAX), 152 | // double(rand()) / double(RAND_MAX), 153 | // double(rand()) / double(RAND_MAX)); 154 | //} 155 | //viewer.launch(); 156 | 157 | } 158 | //***************************************************************************** 159 | 160 | 161 | //********************** IsolinesDS::isovalue() 162 | auto IsolinesDS::isovalue(int vertex) { 163 | return isoV(vertex, 1); 164 | } 165 | //***************************************************************************** 166 | 167 | //********************** IsolinesDS::remove_zero_length_isoE_points() 168 | void IsolinesDS::remove_zero_length_isoE_points() { 169 | 170 | //some edges has the same start and end points 171 | //we remove such edges here 172 | 173 | Eigen::MatrixXi isoE_filtered; 174 | isoE_filtered.resize(isoE.rows(), isoE.cols()); 175 | int num_edges = 0; 176 | //remove edges with the same starting and end point 177 | for (int irow = 0; irow < isoE.rows(); irow++) { 178 | int ed_p0 = isoE(irow, 0); 179 | int ed_p1 = isoE(irow, 1); 180 | if (ed_p0 != ed_p1) { 181 | isoE_filtered.row(num_edges) = isoE.row(irow); 182 | num_edges++; 183 | } 184 | } 185 | //resize to fit 186 | isoE_filtered.conservativeResize(num_edges, isoE_filtered.cols()); 187 | isoE.swap(isoE_filtered); 188 | } 189 | //****************************************************************************** 190 | 191 | 192 | //********************** IsolinesDS::seperate_isolines() 193 | void IsolinesDS::grouping_isolines(const bool is_sort_ascend) { 194 | //populates seperate_isolines such that each row in this 195 | //vector is a single isoline with the same isovalue 196 | //set is_sort_ascend to true if you want the smallest value isoline to be 197 | //the first in the returned vector 198 | 199 | 200 | //record isoline values 201 | //TODO use hash function instead of vector 202 | std::vectorisoVal_seen; 203 | for (int i = 0; i < isoV.rows(); i++) { 204 | bool seen = false; 205 | for (int j = 0; j < isoVal_seen.size(); j++) { 206 | if (abs(isovalue(i) - isoVal_seen[j]) < 0.0001) { 207 | seen = true; 208 | break; 209 | } 210 | } 211 | if (!seen) { 212 | isoVal_seen.push_back(isovalue(i)); 213 | } 214 | } 215 | 216 | 217 | if (is_sort_ascend) { 218 | std::sort(isoVal_seen.begin(), isoVal_seen.end()); 219 | } 220 | else { 221 | std::sort(isoVal_seen.begin(), isoVal_seen.end(), std::greater<>()); 222 | } 223 | 224 | //the return vector 225 | std::vector < Eigen::MatrixXi> isoE_vec(isoVal_seen.size()); 226 | 227 | 228 | for (int e = 0; e < isoE.rows(); e++) { 229 | //start and end point of the edge 230 | int p1(isoE(e, 0)), p2(isoE(e, 1)); 231 | 232 | //the function value on the edge start and end point 233 | double v1(isovalue(p1)), v2(isovalue(p2)); 234 | 235 | assert(abs(v1 - v2) < 2.2204e-10 236 | && "the two end points of an edge should have the same value"); 237 | 238 | int iso_num = -1; 239 | //what the iso index 240 | //TODO use hash function 241 | for (int s = 0; s < isoVal_seen.size(); s++) { 242 | if (abs(v1 - isoVal_seen.at(s)) < 2.2204e-10) { 243 | iso_num = s; 244 | break; 245 | } 246 | } 247 | 248 | //if we have not seen it before 249 | if (iso_num < 0) { 250 | /*iso_num = isoVal_seen.size(); 251 | isoVal_seen.push_back(v1); 252 | 253 | Eigen::MatrixXi new_iso; 254 | isoE_vec.push_back(new_iso);*/ 255 | std::cout << "Error::group_isolines() can not find the " 256 | << "iso value index" << std::endl; 257 | system("pause"); 258 | } 259 | 260 | isoE_vec.at(iso_num).conservativeResize( 261 | isoE_vec.at(iso_num).rows() + 1, 2); 262 | isoE_vec.at(iso_num).row(isoE_vec.at(iso_num).rows() - 1) = 263 | isoE.row(e); 264 | 265 | } 266 | 267 | //remove the empty isoE_vec 268 | for (int i = isoE_vec.size() - 1; i >= 0; i--) { 269 | if (isoE_vec.at(i).rows() == 0) { 270 | isoE_vec.erase(isoE_vec.begin() + i); 271 | } 272 | 273 | } 274 | 275 | isolines_groups.clear(); 276 | isoE_vec.swap(isolines_groups); 277 | 278 | } 279 | //***************************************************************************** 280 | 281 | 282 | //********************** IsolinesDS::isoline_isoline_min_distance() 283 | double IsolinesDS::isoline_isoline_min_distance(const Eigen::MatrixXi & source, 284 | const Eigen::MatrixXi & target, const int NUM_SAMPLES) { 285 | //compute the min distance from the source isoline to the target isoline 286 | //by picking NUM_SAMPLES samples from the source and find the min distance 287 | //to the target isoline (by projection) 288 | 289 | std::vector indices(source.rows()); 290 | std::iota(indices.begin(), indices.end(), 0); 291 | 292 | double min_dist = std::numeric_limits::max(); 293 | 294 | if (source.rows() > NUM_SAMPLES) { 295 | unsigned seed = 296 | std::chrono::system_clock::now().time_since_epoch().count(); 297 | std::shuffle(indices.begin(), indices.end(), 298 | std::default_random_engine(seed)); 299 | } 300 | int sam_count = std::min(NUM_SAMPLES, int(source.rows())); 301 | 302 | for (int i = 0; i < sam_count; i++) { 303 | int pt_id = indices.at(i); 304 | 305 | Eigen::VectorXd t(1), sqrD(1); 306 | int edge_p0, edge_p1, edge_id; 307 | //project this point onto the target 308 | Eigen::VectorXd pt(3); 309 | pt = isoV.row(source(pt_id)); 310 | 311 | project_point_to_isoline(pt.transpose(), 312 | target, t, sqrD, edge_p0, edge_p1, edge_id); 313 | 314 | min_dist = std::min(min_dist, double(sqrD(0))); 315 | } 316 | 317 | return min_dist; 318 | } 319 | //***************************************************************************** 320 | 321 | 322 | //********************** IsolinesDS::project_point_to_isoline() 323 | void IsolinesDS::project_point_to_isoline(const Eigen::VectorXd & point, 324 | const Eigen::MatrixXi & my_isoline, 325 | Eigen::VectorXd & t_min, 326 | Eigen::VectorXd & sqrD_min, 327 | int &edge_p0, int&edge_p1, int&edge_id) { 328 | 329 | //a variant of point projection to isolines where the isoline is passed by 330 | //as a mesh (with line segments as mesh elements). the mesh elements are 331 | //stored in isoE and the vertices can be indexed from isoV 332 | 333 | sqrD_min(0) = std::numeric_limits::max(); 334 | 335 | for (int i = 0; i < my_isoline.rows(); i++) { 336 | //for each edge in the isoline 337 | 338 | //the end points of the edge 339 | int ed_p0(my_isoline(i, 0)), ed_p1(my_isoline(i, 1)); 340 | 341 | //For some reason the 3rd parameter in project_to_line_segment 342 | //can be isoV.row(ed_p1) so we need another matrix for it 343 | 344 | Eigen::MatrixXd dest(1, 3), source(1, 3), pt(1, 3); 345 | dest(0) = isoV(ed_p1, 0); 346 | dest(1) = isoV(ed_p1, 1); 347 | dest(2) = isoV(ed_p1, 2); 348 | 349 | source(0) = isoV(ed_p0, 0); 350 | source(1) = isoV(ed_p0, 1); 351 | source(2) = isoV(ed_p0, 2); 352 | 353 | pt(0) = point(0); 354 | pt(1) = point(1); 355 | pt(2) = point(2); 356 | 357 | Eigen::VectorXd t(1), sqrD(1); 358 | 359 | igl::project_to_line_segment(pt, source, dest, t, sqrD); 360 | 361 | if (t(0) > -0.000001 && t(0) < 1.0 - 0.000001 && 362 | sqrD_min(0) > sqrD(0)) { 363 | sqrD_min(0) = sqrD(0); 364 | t_min(0) = t(0); 365 | edge_p0 = ed_p0; 366 | edge_p1 = ed_p1; 367 | edge_id = i; 368 | } 369 | } 370 | } 371 | //***************************************************************************** 372 | 373 | 374 | //********************** IsolinesDS::project_point_to_isoline() 375 | void IsolinesDS::project_point_to_isoline(const Eigen::VectorXd & point, 376 | const Eigen::MatrixXd & path, 377 | Eigen::VectorXd & t_min, 378 | Eigen::VectorXd & sqrD_min, 379 | int &edge_p0, int&edge_p1) { 380 | 381 | //variant of project_point_to_isoline that takes a list 382 | //of points connected like a chain 383 | //note that path does not form a closed chain 384 | 385 | sqrD_min(0) = std::numeric_limits::max(); 386 | 387 | for (int i = 0; i < path.rows() - 1; i++) { 388 | //for each edge in the isoline 389 | 390 | //For some reason the 3rd parameter in project_to_line_segment 391 | //can be isoV.row(ed_p1) so we need another matrix for it 392 | 393 | Eigen::MatrixXd dest(1, 3), source(1, 3), pt(1, 3); 394 | dest(0) = path(i + 1, 0); 395 | dest(1) = path(i + 1, 1); 396 | dest(2) = path(i + 1, 2); 397 | 398 | source(0) = path(i, 0); 399 | source(1) = path(i, 1); 400 | source(2) = path(i, 2); 401 | 402 | pt(0) = point(0); 403 | pt(1) = point(1); 404 | pt(2) = point(2); 405 | 406 | Eigen::VectorXd t(1), sqrD(1); 407 | 408 | igl::project_to_line_segment(pt, source, dest, t, sqrD); 409 | 410 | if (t(0) > -0.000001 && t(0) < 1.0 - 0.000001 && 411 | sqrD_min(0) > sqrD(0)) { 412 | sqrD_min(0) = sqrD(0); 413 | t_min(0) = t(0); 414 | edge_p0 = i; 415 | edge_p1 = i + 1; 416 | } 417 | } 418 | } 419 | //***************************************************************************** 420 | 421 | 422 | //********************** create_vertex_edge() 423 | void IsolinesDS::create_vertex_edge(const Eigen::MatrixXi isoE, 424 | Eigen::MatrixXi & vertex_edge) { 425 | 426 | //Construct vertex-edge matrix 427 | vertex_edge = Eigen::MatrixXi::Constant(vertex_edge.rows(), 2, -1); 428 | 429 | for (int e = 0; e < isoE.rows(); e++) { 430 | int v0 = isoE(e, 0); 431 | int v1 = isoE(e, 1); 432 | 433 | if (vertex_edge(v0, 0) == -1) { vertex_edge(v0, 0) = e; } 434 | else if (vertex_edge(v0, 1) == -1) { vertex_edge(v0, 1) = e; } 435 | else { 436 | std::cout << "Error::multi_spirallable_region() " << 437 | "vertex [" << v0 << "] connected to more than two edges" 438 | << std::endl; 439 | system("pause"); 440 | } 441 | 442 | if (vertex_edge(v1, 0) == -1) { vertex_edge(v1, 0) = e; } 443 | else if (vertex_edge(v1, 1) == -1) { vertex_edge(v1, 1) = e; } 444 | else { 445 | std::cout << "Error::multi_spirallable_region() " << 446 | "vertex [" << v1 << "] connected to more than two edges" 447 | << std::endl; 448 | system("pause"); 449 | } 450 | } 451 | 452 | } 453 | //***************************************************************************** 454 | 455 | 456 | //********************** IsolinesDS::create_chain_use_vertex_edge() 457 | void IsolinesDS::create_chain_use_vertex_edge( 458 | const Eigen::MatrixXi & iso_edges, 459 | const Eigen::MatrixXi & vertex_edge, 460 | std::vector & chain_iso_edges) { 461 | 462 | //contour reorder by making sure that each contour is a single chain of 463 | //connected vertices (not just punch of seperate edges) 464 | //expected the contour to not have edges with same start and end point 465 | //i.e., execute remove_zero_length_isoE_points() 466 | 467 | //we use the vertex_edge data structure 468 | //iso_edges is a collection of edges whose vertices have the same iso value 469 | //these edges may belong to one or more spirallable regions 470 | //vertex_edge gives the two edges a vertex belongs to 471 | //chain_iso_edges is the returned vector where each row is a seperate 472 | //chain (belong to different spirallable region) and the index represent 473 | //edge in iso_edges 474 | 475 | 476 | int starting_edge(0), starting_v(iso_edges(0, 0)); 477 | //Edge id that is being processed 478 | int my_edge = starting_edge; 479 | 480 | //we stop when all edges are taken 481 | int num_edge_taken = 0; 482 | 483 | std::vector taken(iso_edges.rows(), false); 484 | std::vector taken_v(vertex_edge.rows(), false); 485 | 486 | while (num_edge_taken < iso_edges.rows()) { 487 | 488 | //The current chain we are building 489 | Eigen::MatrixXi my_chain(iso_edges.rows() - num_edge_taken + 1, 2); 490 | int num_edges_chain = 0; 491 | while (true) { 492 | 493 | //the start and end of the edge 494 | int v0 = iso_edges(my_edge, 0); 495 | int v1 = iso_edges(my_edge, 1); 496 | 497 | //add the edge (its vertices) to the chain 498 | my_chain.row(num_edges_chain) = iso_edges.row(my_edge); 499 | if (num_edges_chain > 1) { 500 | //make sure that the start point of this edge is the end 501 | //point of the previous edge 502 | if (my_chain(num_edges_chain, 0) != 503 | my_chain(num_edges_chain - 1, 1)) { 504 | std::swap(my_chain(num_edges_chain, 0), 505 | my_chain(num_edges_chain, 1)); 506 | } 507 | } 508 | num_edges_chain++; 509 | num_edge_taken++; 510 | 511 | //mark the edge as being taken 512 | taken.at(my_edge) = true; 513 | 514 | #if 1 515 | if (vertex_edge(v1, 0) != my_edge && 516 | vertex_edge(v1, 1) != my_edge) { 517 | std::cout << "Error::create_chain_use_vertex_edge() " 518 | << "the end vertex of an edge does not contain the edge\n" 519 | << " v0= " << v0 << " v1= " << v1 << " my_edge= " 520 | << my_edge << std::endl; 521 | system("pause"); 522 | } 523 | #endif 524 | //move to the next edge 525 | //my_edge = (vertex_edge(v1, 0) != my_edge) ? vertex_edge(v1, 0) : 526 | // vertex_edge(v1, 1); 527 | 528 | if ((v1 == starting_v || v0 == starting_v) && 529 | my_edge != starting_edge) { 530 | taken_v[v0] = taken_v[v1] = true; 531 | break; 532 | } 533 | 534 | 535 | int my_v = v1; 536 | if (taken_v[my_v]) { my_v = v0; } 537 | if (taken_v[my_v] && v1 != starting_v && v0 != starting_v) { 538 | std::cout << "Error::create_chain_use_vertex_edge()" 539 | << " both vertices of an edge are added!!!" << std::endl; 540 | system("pause"); 541 | } 542 | 543 | my_edge = (vertex_edge(my_v, 0) != my_edge) ? 544 | vertex_edge(my_v, 0) : vertex_edge(my_v, 1); 545 | 546 | //mark the taken vertices 547 | taken_v[v0] = taken_v[v1] = true; 548 | 549 | if (my_edge == starting_edge) { break; } 550 | } 551 | 552 | /* 553 | //Make sure that the edges are ordered in the same direction as other 554 | //chains. First compute the center mass of the chain and then check 555 | //the angle of the end points of the first edge 556 | Eigen::RowVector3d chain_center(3,0); 557 | for (int v = 0; v < my_chain.rows(); v++) { 558 | // chain_center += my_chain.row(v); 559 | } 560 | chain_center /= my_chain.rows(); 561 | 562 | //get angle between st0 - center - end0 563 | //where st0 and end0 are the start and end points of the first edge in 564 | //the chain 565 | double s1 = dist(isoV(my_chain(0, 1), 0), 566 | isoV(my_chain(0, 1), 1), isoV(my_chain(0, 1), 2), 567 | isoV(my_chain(0, 0), 0), 568 | isoV(my_chain(0, 0), 1), isoV(my_chain(0, 0), 2)); 569 | 570 | double s2 = dist(chain_center(0), chain_center(1), 571 | chain_center(2), isoV(my_chain(0, 1), 0), 572 | isoV(my_chain(0, 1), 1), isoV(my_chain(0, 1), 2)); 573 | 574 | double s3 = dist(chain_center(0), chain_center(1), 575 | chain_center(2), isoV(my_chain(0, 0), 0), 576 | isoV(my_chain(0, 0), 1), isoV(my_chain(0, 0), 2)); 577 | 578 | 579 | double angle = acos((s3 + s2 - s1) / (2.*sqrt(s3*s2))); 580 | */ 581 | 582 | //add the newly-created chain only if it is big enough 583 | if (num_edges_chain > MIN_NUM_POINT_PER_CONTOUR) { 584 | chain_iso_edges.push_back(my_chain.topRows(num_edges_chain)); 585 | 586 | } 587 | 588 | //if we have processed all the edges 589 | if (num_edge_taken >= iso_edges.rows()) { break; } 590 | 591 | //look for the next not-taken edge to be our starting edge 592 | starting_edge = -1; 593 | for (int i = 0; i < taken.size(); i++) { 594 | if (!taken.at(i)) { 595 | starting_edge = i; 596 | break; 597 | } 598 | } 599 | 600 | if (starting_edge < 0) { break; } 601 | my_edge = starting_edge; 602 | starting_v = iso_edges(starting_edge, 0); 603 | 604 | } 605 | } 606 | //***************************************************************************** 607 | 608 | //********************** spirallable_region() 609 | void IsolinesDS::spirallable_region() { 610 | 611 | //Isolate the isolines into spirallable regions. Each spirallable region 612 | //is set of isolines such that each isolines (its vertices) have a unique 613 | //values (different than another isoline in the same region) 614 | //Input: in each row in isolines_groups, we store the set of edges 615 | //that has the same iso value (they are not ordered or sorted in any way) 616 | 617 | //Output: spiral_regions[X][Y] where X is index for the spirallable region 618 | //Y is the contour index (betwee 0 and num_contours -1). 619 | //spiral_regions[X][Y] gives the edges as Eigen::MatrixXi of 620 | //contour Y in the spiralle region X 621 | 622 | //TODO filter out isolines with few points (less than 623 | //MIN_NUM_POINT_PER_CONTOUR) 624 | 625 | //We first sort the isolines such that each isolines form a connected 626 | //closed chain. Now we have one or more chain for the current processed 627 | //iso value. We then add the chain to the correct spirallable region 628 | 629 | 630 | //because the first one is the outer boundary edges 631 | // assert(!spiral_regions.at(0).empty()); 632 | int region_id = 1; 633 | int num_regions = 1; 634 | //vertex_edge data structure is build for each isoline (isoline whose 635 | //vertices has the same iso value) such that each vertex points to the 636 | //two edges it belongs to 637 | Eigen::MatrixXi vertex_edge(isoV.rows(), 2); 638 | 639 | //We keep track of the regions that we have last added new isolines to 640 | //because these are the regions that will grow further. 641 | std::vector last_region(1, 0); 642 | 643 | 644 | for (int i = 0; i < isolines_groups.size(); i++) { 645 | 646 | std::vector chains; 647 | 648 | create_vertex_edge(isolines_groups.at(i), vertex_edge); 649 | 650 | create_chain_use_vertex_edge(isolines_groups.at(i), vertex_edge, 651 | chains); 652 | 653 | if (chains.size() == 1 && 654 | (spiral_regions.size() == 0 || spiral_regions.size() == 1)) { 655 | //Special case 656 | //The first couple of isolines may not need checks. This is the case 657 | //of haveing one region and the chains are just one so it is always 658 | //added to the exisiting region (creating one spirallalbe region) 659 | if (spiral_regions.size() == 0) { 660 | std::vector ch; 661 | ch.push_back(chains.at(0)); 662 | spiral_regions.push_back(ch); 663 | } 664 | else { 665 | spiral_regions.at(0).push_back(chains.at(0)); 666 | } 667 | 668 | } 669 | else { 670 | //General case 671 | 672 | //For each chain, we store its distance to all the region that we 673 | //have updated last time along with 674 | //the min distance as pair (which is used later for sorting 675 | //to figure out the closest region / containing region of the chain) 676 | std::vector>> 677 | chain_dist_to_region; 678 | chain_dist_to_region.reserve(chains.size()); 679 | 680 | for (int c = 0; c < chains.size(); c++) { 681 | std::vector < std::pair> my_chain_distances; 682 | 683 | //find the min distance to all the regions that has been 684 | //updated or created last time 685 | for (int r = 0; r < last_region.size(); r++) { 686 | int reg = last_region.at(r); 687 | double min_dist = isoline_isoline_min_distance( 688 | chains.at(c), spiral_regions.at(reg).back()); 689 | 690 | my_chain_distances.push_back( 691 | std::make_pair(min_dist, reg)); 692 | 693 | } 694 | chain_dist_to_region.push_back(my_chain_distances); 695 | } 696 | 697 | 698 | std::vector> add_to_region(spiral_regions.size()); 699 | //Sort all the collected distances for each chain 700 | //from there we know which region the chain should be added to 701 | for (int c = 0; c < chains.size(); c++) { 702 | //sort key-value pairs 703 | std::sort(chain_dist_to_region.at(c).begin(), 704 | chain_dist_to_region.at(c).end()); 705 | 706 | int closest_region = chain_dist_to_region.at(c).front().second; 707 | 708 | //add that we are going to add this chain to that region 709 | add_to_region.at(closest_region).push_back(c); 710 | } 711 | 712 | std::vector current_region; 713 | 714 | //actually add the chain to the region only if we are going to 715 | //add only one chain to this region 716 | for (int r = 0; r < spiral_regions.size(); r++) { 717 | if (add_to_region.at(r).size() == 1) { 718 | int ch = add_to_region.at(r).front(); 719 | spiral_regions.at(r).push_back(chains.at(ch)); 720 | 721 | current_region.push_back(r); 722 | } 723 | } 724 | 725 | //if we found that we need to add more than one chain to the region 726 | //then we don't add them to these regions but instead open new 727 | //region using them 728 | for (int r = spiral_regions.size() - 1; r >= 0; r--) { 729 | if (add_to_region.at(r).size() > 1) { 730 | for (int c = 0; c < add_to_region.at(r).size(); c++) { 731 | 732 | int ch = add_to_region.at(r).at(c); 733 | 734 | std::vector mat_V; 735 | mat_V.push_back(chains.at(ch)); 736 | 737 | spiral_regions.push_back(mat_V); 738 | 739 | current_region.push_back(spiral_regions.size() - 1); 740 | } 741 | } 742 | } 743 | 744 | last_region.swap(current_region); 745 | 746 | } 747 | 748 | region_id++; 749 | } 750 | 751 | for (int i = 0; i < spiral_regions.size(); i++) { 752 | std::cout << "i= " << i << " --> " << 753 | spiral_regions.at(i).size() << std::endl; 754 | } 755 | 756 | #ifdef VIZ 757 | if (false) { 758 | reset_viewer(viewer, V, F, vertex_func); 759 | for (int c = 0; c < spiral_regions.size(); c++) { 760 | if (false) { 761 | //draw each region in a different color 762 | float r, g, b(0.0f); 763 | if (spiral_regions.at(c).size() > 1) { 764 | r = float(rand()) / float(RAND_MAX); 765 | g = float(rand()) / float(RAND_MAX); 766 | b = float(rand()) / float(RAND_MAX); 767 | } 768 | else { 769 | r = 0.0f; 770 | g = 0.0f; 771 | b = 0.0f; 772 | } 773 | add_edge_to_viewer(viewer, isoV, spiral_regions.at(c), false, 774 | r, g, b); 775 | } 776 | else { 777 | //draw each isoline in raincolor relevent to the increasing 778 | //order of its edges 779 | add_colorful_edge_to_viewer(viewer, isoV, 780 | spiral_regions.at(c)); 781 | } 782 | } 783 | viewer.launch(); 784 | } 785 | #endif 786 | 787 | } 788 | //***************************************************************************** 789 | 790 | #endif /*_ISOLINES_DS_*/ 791 | 792 | -------------------------------------------------------------------------------- /src/isolines_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _ISOLINES_HELPER_ 2 | #define _ISOLINES_HELPER_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "common.h" 10 | #include "Viz.h" 11 | 12 | 13 | extern igl::opengl::glfw::Viewer viewer; 14 | extern Eigen::MatrixXd V; 15 | extern Eigen::MatrixXi F; 16 | extern Eigen::VectorXd vertex_func; 17 | 18 | 19 | //********************** project_point_to_isoline()✔ 20 | void project_point_to_isoline(const Eigen::VectorXd & point, 21 | const Eigen::MatrixXd & isoV, 22 | const Eigen::MatrixXi & isoE, 23 | Eigen::VectorXd & t_min, 24 | Eigen::VectorXd & sqrD_min, 25 | int &edge_p0, int&edge_p1, int&edge_id) { 26 | 27 | //a variant of point projection to isolines where the isoline is passed by 28 | //as a mesh (with line segments as mesh elements). the mesh elements are 29 | //stored in isoE and the vertices can be indexed from isoV 30 | 31 | sqrD_min(0) = std::numeric_limits::max(); 32 | 33 | double min_dist = std::numeric_limits::max(); 34 | int pp; 35 | 36 | for (int i = 0; i < isoE.rows(); i++) { 37 | //for each edge in the isoline 38 | 39 | //the end points of the edge 40 | int ed_p0(isoE(i, 0)), ed_p1(isoE(i, 1)); 41 | 42 | //For some reason the 3rd parameter in project_to_line_segment 43 | //can be isoV.row(ed_p1) so we need another matrix for it 44 | 45 | Eigen::MatrixXd dest(1, 3), source(1,3), pt(1,3); 46 | dest(0) = isoV(ed_p1, 0); 47 | dest(1) = isoV(ed_p1, 1); 48 | dest(2) = isoV(ed_p1, 2); 49 | 50 | source(0) = isoV(ed_p0, 0); 51 | source(1) = isoV(ed_p0, 1); 52 | source(2) = isoV(ed_p0, 2); 53 | 54 | pt(0) = point(0); 55 | pt(1) = point(1); 56 | pt(2) = point(2); 57 | 58 | Eigen::VectorXd t(1), sqrD(1); 59 | 60 | igl::project_to_line_segment(pt, source, dest, t, sqrD); 61 | 62 | 63 | /*double dddd1 = dist(point(0), point(1), point(2), isoV(ed_p1, 0), 64 | isoV(ed_p1, 1), isoV(ed_p1, 2)); 65 | double dddd0 = dist(point(0), point(1), point(2), isoV(ed_p0, 0), 66 | isoV(ed_p0, 1), isoV(ed_p0, 2)); 67 | if (dddd1 < min_dist) { min_dist = dddd1; pp = ed_p1; } 68 | if (dddd0 < min_dist) { min_dist = dddd0; pp = ed_p0; }*/ 69 | 70 | 71 | 72 | if (t(0) > -0.000001 && t(0) < 1.0 - 0.000001 && 73 | sqrD_min(0) > sqrD(0)) { 74 | sqrD_min(0) = sqrD(0); 75 | t_min(0) = t(0); 76 | edge_p0 = ed_p0; 77 | edge_p1 = ed_p1; 78 | edge_id = i; 79 | } 80 | } 81 | 82 | /*std::cout << " pp=" << pp << " edge_p0= " << edge_p0 << " edge_p1= " 83 | << edge_p1 << std::endl; 84 | 85 | viewer.data().add_points(isoV.row(pp), 86 | Eigen::RowVector3d(1.0, 0.0, 1.0)); 87 | viewer.data().add_points(isoV.row(edge_p0), 88 | Eigen::RowVector3d(0.0, 0.0, 0.0)); 89 | viewer.data().add_points(isoV.row(edge_p1), 90 | Eigen::RowVector3d(0.0, 0.0, 0.0));*/ 91 | } 92 | //****************************************************************************** 93 | 94 | 95 | //********************** project_point_to_isoline()✔ 96 | void project_point_to_isoline(const Eigen::VectorXd & point, 97 | const Eigen::MatrixXd & path, 98 | Eigen::VectorXd & t_min, 99 | Eigen::VectorXd & sqrD_min, 100 | int &edge_p0, int&edge_p1) { 101 | 102 | //variant of project_point_to_isoline that takes a list 103 | //of points connected like a chain 104 | //note that path does not form a closed chain 105 | 106 | sqrD_min(0) = std::numeric_limits::max(); 107 | 108 | for (int i = 0; i < path.rows() - 1; i++) { 109 | //for each edge in the isoline 110 | 111 | //For some reason the 3rd parameter in project_to_line_segment 112 | //can be isoV.row(ed_p1) so we need another matrix for it 113 | 114 | Eigen::MatrixXd dest(1, 3), source(1, 3), pt(1, 3); 115 | dest(0) = path(i + 1, 0); 116 | dest(1) = path(i + 1, 1); 117 | dest(2) = path(i + 1, 2); 118 | 119 | source(0) = path(i, 0); 120 | source(1) = path(i, 1); 121 | source(2) = path(i, 2); 122 | 123 | pt(0) = point(0); 124 | pt(1) = point(1); 125 | pt(2) = point(2); 126 | 127 | Eigen::VectorXd t(1), sqrD(1); 128 | 129 | igl::project_to_line_segment(pt, source, dest, t, sqrD); 130 | 131 | if (t(0) > -0.000001 && t(0) < 1.0 - 0.000001 && 132 | sqrD_min(0) > sqrD(0)) { 133 | sqrD_min(0) = sqrD(0); 134 | t_min(0) = t(0); 135 | edge_p0 = i; 136 | edge_p1 = i + 1; 137 | } 138 | } 139 | } 140 | //****************************************************************************** 141 | 142 | 143 | //********************** isoline_isoline_min_distance()✔ 144 | double isoline_isoline_min_distance(const Eigen::MatrixXi & source, 145 | const Eigen::MatrixXi & target, 146 | const Eigen::MatrixXd & isoV) { 147 | //compute the min distance from the source isoline to the target isoline 148 | //by picking NUM_SAMPLES samples from the source and find the min distance 149 | //to the target isoline (by projection) 150 | 151 | const int NUM_SAMPLES = 100; 152 | 153 | std::vector indices(source.rows()); 154 | std::iota(indices.begin(), indices.end(), 0); 155 | 156 | double min_dist = std::numeric_limits::max(); 157 | 158 | if (source.rows() > NUM_SAMPLES) { 159 | unsigned seed = 160 | std::chrono::system_clock::now().time_since_epoch().count(); 161 | std::shuffle(indices.begin(), indices.end(), 162 | std::default_random_engine(seed)); 163 | } 164 | int sam_count = std::min(NUM_SAMPLES, int(source.rows())); 165 | 166 | for (int i = 0; i < sam_count; i++) { 167 | int pt_id = indices.at(i); 168 | 169 | Eigen::VectorXd t(1), sqrD(1); 170 | int edge_p0, edge_p1, edge_id; 171 | //project this point onto the target 172 | Eigen::VectorXd pt(3); 173 | pt = isoV.row(source(pt_id)); 174 | 175 | project_point_to_isoline(pt.transpose(), 176 | isoV, target, t, sqrD, edge_p0, edge_p1, edge_id); 177 | 178 | min_dist = std::min(min_dist, double(sqrD(0))); 179 | } 180 | 181 | return min_dist; 182 | 183 | } 184 | //****************************************************************************** 185 | 186 | 187 | //********************** sort_indexes()✔ 188 | template 189 | std::vector sort_indexes(const std::vector &v) { 190 | 191 | //https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes 192 | // initialize original index locations 193 | std::vector idx(v.size()); 194 | iota(idx.begin(), idx.end(), 0); 195 | 196 | // sort indexes based on comparing values in v 197 | std::sort(idx.begin(), idx.end(), 198 | [&v](size_t i1, size_t i2) {return v[i1] < v[i2]; }); 199 | 200 | return idx; 201 | } 202 | //****************************************************************************** 203 | 204 | 205 | //********************** remove_zero_length_isoE_points()✔ 206 | inline Eigen::MatrixXi remove_zero_length_isoE_points( 207 | const Eigen::MatrixXi & isoE) { 208 | 209 | //some edges has the same start and end points 210 | //we remove such edges here 211 | 212 | Eigen::MatrixXi isoE_filtered; 213 | isoE_filtered.resize(isoE.rows(), isoE.cols()); 214 | int num_edges = 0; 215 | //remove edges with the same starting and end point 216 | for (int irow = 0; irow < isoE.rows(); irow++) { 217 | int ed_p0 = isoE(irow, 0); 218 | int ed_p1 = isoE(irow, 1); 219 | if (ed_p0 != ed_p1) { 220 | isoE_filtered.row(num_edges) = isoE.row(irow); 221 | num_edges++; 222 | } 223 | } 224 | //resize to fit 225 | isoE_filtered.conservativeResize(num_edges, isoE_filtered.cols()); 226 | return isoE_filtered; 227 | } 228 | //****************************************************************************** 229 | 230 | 231 | //********************** group_isolines()✔ 232 | std::vector group_isolines(const Eigen::MatrixXd& isoV, 233 | const Eigen::MatrixXi& isoE, 234 | const Eigen::VectorXd& isoVal, 235 | const bool is_sort_ascend = false) { 236 | //reorder the isolines and return a vector such that each row in this 237 | //vector is a single isoline with constant value 238 | //set is_sort_ascend to true if you want the smallest value isoline to be 239 | //the first in the returned vector 240 | 241 | assert(isoV.rows() == isoVal.rows()); 242 | 243 | //record isoline values 244 | //TODO use hash function instead of vector 245 | std::vectorisoVal_seen; 246 | for (int i = 0; i < isoV.rows(); i++) { 247 | bool seen = false; 248 | for (int j = 0; j < isoVal_seen.size(); j++) { 249 | if (abs(isoVal(i) - isoVal_seen[j]) < 0.0001) { 250 | seen = true; 251 | break; 252 | } 253 | } 254 | if (!seen) { 255 | isoVal_seen.push_back(isoVal(i)); 256 | } 257 | } 258 | 259 | 260 | if (is_sort_ascend) { 261 | std::sort(isoVal_seen.begin(), isoVal_seen.end()); 262 | } 263 | else { 264 | std::sort(isoVal_seen.begin(), isoVal_seen.end(), std::greater<>()); 265 | } 266 | 267 | //the return vector 268 | std::vector < Eigen::MatrixXi> isoE_vec(isoVal_seen.size()); 269 | 270 | 271 | for (int e = 0; e < isoE.rows(); e++) { 272 | //start and end point of the edge 273 | int p1(isoE(e, 0)), p2(isoE(e, 1)); 274 | 275 | //the function value on the edge start and end point 276 | double v1(isoVal(p1)), v2(isoVal(p2)); 277 | 278 | assert(abs(v1 - v2) < 2.2204e-10 279 | && "the two end points of an edge should have the same value"); 280 | 281 | int iso_num = -1; 282 | //what the iso index 283 | //TODO use hash function 284 | for (int s = 0; s < isoVal_seen.size(); s++) { 285 | if (abs(v1 - isoVal_seen.at(s)) < 2.2204e-10) { 286 | iso_num = s; 287 | break; 288 | } 289 | } 290 | 291 | //if we have not seen it before 292 | if (iso_num < 0) { 293 | /*iso_num = isoVal_seen.size(); 294 | isoVal_seen.push_back(v1); 295 | 296 | Eigen::MatrixXi new_iso; 297 | isoE_vec.push_back(new_iso);*/ 298 | std::cout<<"Error::group_isolines() can not find the " 299 | << "iso value index"<= 0; i--) { 312 | if (isoE_vec.at(i).rows() == 0) { 313 | isoE_vec.erase(isoE_vec.begin() + i); 314 | } 315 | 316 | } 317 | 318 | return isoE_vec; 319 | 320 | } 321 | //****************************************************************************** 322 | 323 | 324 | //********************** create_chain()✔ 325 | void create_chain(std::vector&seperate_isoE, 326 | const Eigen::MatrixXd& isoV) { 327 | //contour reorder by making sure that each contour is a single chain of 328 | //connected vertices (not just punch of seperate edges) 329 | //expected the contour to not have edges with same start and end point 330 | //i.e., execute remove_zero_length_isoE_points() 331 | 332 | for (int cont = 0; cont < seperate_isoE.size(); cont++) { 333 | 334 | 335 | Eigen::MatrixXi new_cont; 336 | 337 | // std::cout << "\n\n \n " << seperate_isoE.at(cont) << std::endl; 338 | 339 | for (int ed_cur = 0; ed_cur < seperate_isoE.at(cont).rows() - 1; 340 | ed_cur++) { 341 | 342 | int ed_cur_p0 = seperate_isoE.at(cont)(ed_cur, 0); 343 | int ed_cur_p1 = seperate_isoE.at(cont)(ed_cur, 1); 344 | 345 | int ed_next_p0, ed_next_p1, ed_next; 346 | ed_next_p0 = ed_next_p1 = -1; 347 | 348 | for (int ed = ed_cur + 1; ed < seperate_isoE.at(cont).rows(); 349 | ed++) { 350 | 351 | if (ed == ed_cur) { continue; } 352 | 353 | int ed_p0 = seperate_isoE.at(cont)(ed, 0); 354 | int ed_p1 = seperate_isoE.at(cont)(ed, 1); 355 | 356 | if ((ed_p1 == ed_cur_p1 || ed_p0 == ed_cur_p1) 357 | || (ed_cur == 0 && 358 | (ed_p1 == ed_cur_p0 || ed_p0 == ed_cur_p0))) { 359 | if ((ed_next_p0 >= 0 || ed_next_p1 >= 0) && ed_cur != 0) { 360 | std::cout << "Error::create_chain() more than one" << 361 | "one edge to connect to" << std::endl; 362 | system("pause"); 363 | } 364 | ed_next_p0 = ed_p0; 365 | ed_next_p1 = ed_p1; 366 | ed_next = ed; 367 | } 368 | } 369 | 370 | if (ed_next_p0 < 0 || ed_next_p1 < 0) { 371 | // std::cout << "\n\n \n " << seperate_isoE.at(cont) << std::endl; 372 | std::cout << "Error::create_chain() can not find next edge" 373 | << std::endl; 374 | system("pause"); 375 | } 376 | 377 | 378 | seperate_isoE.at(cont).row(ed_next).swap( 379 | seperate_isoE.at(cont).row(ed_cur + 1)); 380 | 381 | 382 | if (seperate_isoE.at(cont)(ed_cur, 1) != 383 | seperate_isoE.at(cont)(ed_cur + 1, 0)) { 384 | //if the last point in the current edge does not match 385 | //the first point in the first point in the next edge, 386 | //then we need to find the common point (same_p) and put it 387 | //as first point in the next edge. 388 | //if this is does not fix the point, then we can flip the 389 | //current edge (mave the first point as last point) only if 390 | //this is the first edge 391 | 392 | int same_p, diff_p; 393 | if (seperate_isoE.at(cont)(ed_cur, 0) == 394 | seperate_isoE.at(cont)(ed_cur + 1, 0) || 395 | seperate_isoE.at(cont)(ed_cur, 1) == 396 | seperate_isoE.at(cont)(ed_cur + 1, 0)) { 397 | same_p = seperate_isoE.at(cont)(ed_cur + 1, 0); 398 | diff_p = seperate_isoE.at(cont)(ed_cur + 1, 1); 399 | } 400 | else { 401 | same_p = seperate_isoE.at(cont)(ed_cur + 1, 1); 402 | diff_p = seperate_isoE.at(cont)(ed_cur + 1, 0); 403 | } 404 | 405 | 406 | seperate_isoE.at(cont)(ed_cur + 1, 0) = same_p; 407 | seperate_isoE.at(cont)(ed_cur + 1, 1) = diff_p; 408 | 409 | if (seperate_isoE.at(cont)(ed_cur, 1) != 410 | seperate_isoE.at(cont)(ed_cur + 1, 0)) { 411 | if (ed_cur == 0) { 412 | //it is okay to flip the very first edge 413 | std::swap(seperate_isoE.at(cont)(ed_cur, 0), 414 | seperate_isoE.at(cont)(ed_cur, 1)); 415 | } 416 | else { 417 | std::cout << "Error::create_chain() can't find" 418 | " good order !!!" 419 | << std::endl; 420 | system("pause"); 421 | } 422 | } 423 | } 424 | } 425 | } 426 | } 427 | //****************************************************************************** 428 | 429 | 430 | //********************** create_vertex_edge()✔ 431 | void create_vertex_edge(const Eigen::MatrixXi isoE, 432 | Eigen::MatrixXi & vertex_edge) { 433 | 434 | //Construct vertex-edge matrix 435 | vertex_edge = Eigen::MatrixXi::Constant(vertex_edge.rows(), 2, -1); 436 | 437 | for (int e = 0; e < isoE.rows(); e++) { 438 | int v0 = isoE(e, 0); 439 | int v1 = isoE(e, 1); 440 | 441 | if (vertex_edge(v0, 0) == -1) { vertex_edge(v0, 0) = e; } 442 | else if (vertex_edge(v0, 1) == -1) { vertex_edge(v0, 1) = e; } 443 | else { 444 | std::cout << "Error::multi_spirallable_region() " << 445 | "vertex [" << v0 << "] connected to more than two edges" 446 | << std::endl; 447 | system("pause"); 448 | } 449 | 450 | if (vertex_edge(v1, 0) == -1) { vertex_edge(v1, 0) = e; } 451 | else if (vertex_edge(v1, 1) == -1) { vertex_edge(v1, 1) = e; } 452 | else { 453 | std::cout << "Error::multi_spirallable_region() " << 454 | "vertex [" << v1 << "] connected to more than two edges" 455 | << std::endl; 456 | system("pause"); 457 | } 458 | } 459 | 460 | } 461 | //****************************************************************************** 462 | 463 | 464 | //********************** create_chain_use_vertex_edge()✔ 465 | void create_chain_use_vertex_edge(const Eigen::MatrixXi & iso_edges, 466 | const Eigen::MatrixXi & vertex_edge, 467 | const Eigen::MatrixXd & isoV, 468 | std::vector & chain_iso_edges) { 469 | //A varaint of create_chain where we use the vertex_edge data structure 470 | //iso_edges is a collection of edges whose vertices have the same iso value 471 | //these edges may belong to one or more spirallable regions 472 | //vertex_edge gives the two edges a vertex belongs to 473 | //chain_iso_edges is the returned vector where each row is a seperate 474 | //chain (belong to different spirallable region) and the index represent 475 | //edge in iso_edges 476 | 477 | 478 | int starting_edge(0), starting_v(iso_edges(0, 0)); 479 | //Edge id that is being processed 480 | int my_edge = starting_edge; 481 | 482 | //we stop when all edges are taken 483 | int num_edge_taken = 0; 484 | 485 | std::vector taken(iso_edges.rows(), false); 486 | std::vector taken_v(vertex_edge.rows(), false); 487 | 488 | while (num_edge_taken < iso_edges.rows()) { 489 | 490 | //The current chain we are building 491 | Eigen::MatrixXi my_chain(iso_edges.rows()- num_edge_taken +1, 2); 492 | int num_edges_chain = 0; 493 | while (true) { 494 | 495 | //the start and end of the edge 496 | int v0 = iso_edges(my_edge, 0); 497 | int v1 = iso_edges(my_edge, 1); 498 | 499 | //add the edge (its vertices) to the chain 500 | my_chain.row(num_edges_chain) = iso_edges.row(my_edge); 501 | if (num_edges_chain > 1) { 502 | //make sure that the start point of this edge is the end 503 | //point of the previous edge 504 | if (my_chain(num_edges_chain, 0) != 505 | my_chain(num_edges_chain - 1, 1)) { 506 | std::swap(my_chain(num_edges_chain, 0), 507 | my_chain(num_edges_chain, 1)); 508 | } 509 | } 510 | num_edges_chain++; 511 | num_edge_taken++; 512 | 513 | //mark the edge as being taken 514 | taken.at(my_edge) = true; 515 | 516 | #if 1 517 | if (vertex_edge(v1, 0) != my_edge && 518 | vertex_edge(v1, 1) != my_edge) { 519 | std::cout << "Error::create_chain_use_vertex_edge() " 520 | << "the end vertex of an edge does not contain the edge\n" 521 | << " v0= " << v0 << " v1= " << v1 << " my_edge= " 522 | << my_edge << std::endl; 523 | system("pause"); 524 | } 525 | #endif 526 | //move to the next edge 527 | //my_edge = (vertex_edge(v1, 0) != my_edge) ? vertex_edge(v1, 0) : 528 | // vertex_edge(v1, 1); 529 | 530 | if ((v1 == starting_v || v0 == starting_v) && 531 | my_edge != starting_edge) { 532 | taken_v[v0] = taken_v[v1] = true; 533 | break; 534 | } 535 | 536 | 537 | int my_v = v1; 538 | if (taken_v[my_v]) { my_v = v0; } 539 | if (taken_v[my_v] && v1!= starting_v && v0!= starting_v) { 540 | std::cout<<"Error::create_chain_use_vertex_edge()" 541 | <<" both vertices of an edge are added!!!"< MIN_NUM_POINT_PER_CONTOUR) { 586 | chain_iso_edges.push_back(my_chain.topRows(num_edges_chain)); 587 | 588 | } 589 | 590 | //if we have processed all the edges 591 | if (num_edge_taken >= iso_edges.rows()) { break; } 592 | 593 | //look for the next not-taken edge to be our starting edge 594 | starting_edge = -1; 595 | for (int i = 0; i < taken.size(); i++) { 596 | if (!taken.at(i)) { 597 | starting_edge = i; 598 | break; 599 | } 600 | } 601 | 602 | if (starting_edge < 0) { break; } 603 | my_edge = starting_edge; 604 | starting_v = iso_edges(starting_edge, 0); 605 | 606 | } 607 | } 608 | //****************************************************************************** 609 | 610 | 611 | //********************** isolate_isolines()✔ 612 | void isolate_isolines(const std::vector&all_seperate_isoE, 613 | const Eigen::MatrixXd & isoV, 614 | std::vector >&isolate_isoE) { 615 | 616 | //Isolate the isolines into spirallable regions. Each spirallable region 617 | //is set of isolines such that each isolines (its vertices) have a unique 618 | //values (different than another isoline in the same region) 619 | //Input: in each row in all_seperate_isoE, we store the set of edges 620 | //that has the same iso value (they are not ordered or sorted in any way) 621 | 622 | //Output: isolate_isoE[X][Y] where X is index for the spirallable region 623 | //Y is the contour index (betwee 0 and num_contours -1). isolate_isoE[X][Y] 624 | //gives the edges as Eigen::MatrixXi of contour Y in the spiralle region X 625 | 626 | //TODO filter out isolines with few points (less than 627 | //MIN_NUM_POINT_PER_CONTOUR) 628 | 629 | //We first sort the isolines such that each isolines form a connected 630 | //closed chain. Now we have one or more chain for the current processed 631 | //iso value. We then add the chain to the correct spirallable region 632 | 633 | 634 | //because the first one is the outer boundary edges 635 | // assert(!isolate_isoE.at(0).empty()); 636 | int region_id = 1; 637 | int num_regions = 1; 638 | //vertex_edge data structure is build for each isoline (isoline whose 639 | //vertices has the same iso value) such that each vertex points to the 640 | //two edges it belongs to 641 | Eigen::MatrixXi vertex_edge(isoV.rows(), 2); 642 | 643 | //We keep track of the regions that we have last added new isolines to 644 | //because these are the regions that will grow further. 645 | std::vector last_region(1, 0); 646 | 647 | 648 | for (int i = 0; i < all_seperate_isoE.size(); i++) { 649 | 650 | std::vector chains; 651 | 652 | create_vertex_edge(all_seperate_isoE.at(i), vertex_edge); 653 | 654 | create_chain_use_vertex_edge(all_seperate_isoE.at(i), vertex_edge, 655 | isoV, chains); 656 | 657 | if (false) { 658 | reset_viewer(viewer, V, F, vertex_func); 659 | add_edge_to_viewer(viewer, isoV, chains); 660 | viewer.launch(); 661 | } 662 | 663 | if (chains.size() == 1 && 664 | (isolate_isoE.size() == 0 || isolate_isoE.size() == 1)) { 665 | //Special case 666 | //The first couple of isolines may not need checks. This is the case 667 | //of haveing one region and the chains are just one so it is always 668 | //added to the exisiting region (creating one spirallalbe region) 669 | if (isolate_isoE.size() == 0) { 670 | std::vector ch; 671 | ch.push_back(chains.at(0)); 672 | isolate_isoE.push_back(ch); 673 | } 674 | else { 675 | isolate_isoE.at(0).push_back(chains.at(0)); 676 | } 677 | 678 | } 679 | else { 680 | //General case 681 | 682 | //For each chain, we store its distance to all the region that we 683 | //have updated last time along with 684 | //the min distance as pair (which is used later for sorting 685 | //to figure out the closest region / containing region of the chain) 686 | std::vector>> 687 | chain_dist_to_region; 688 | chain_dist_to_region.reserve(chains.size()); 689 | 690 | for (int c = 0; c < chains.size(); c++) { 691 | std::vector < std::pair> my_chain_distances; 692 | 693 | //find the min distance to all the regions that has been 694 | //updated or created last time 695 | for (int r = 0; r < last_region.size(); r++) { 696 | int reg = last_region.at(r); 697 | double min_dist = isoline_isoline_min_distance( 698 | chains.at(c), isolate_isoE.at(reg).back(), isoV); 699 | 700 | my_chain_distances.push_back( 701 | std::make_pair(min_dist, reg)); 702 | 703 | } 704 | chain_dist_to_region.push_back(my_chain_distances); 705 | } 706 | 707 | 708 | std::vector> add_to_region(isolate_isoE.size()); 709 | //Sort all the collected distances for each chain 710 | //from there we know which region the chain should be added to 711 | for (int c = 0; c < chains.size(); c++) { 712 | //sort key-value pairs 713 | std::sort(chain_dist_to_region.at(c).begin(), 714 | chain_dist_to_region.at(c).end()); 715 | 716 | int closest_region = chain_dist_to_region.at(c).front().second; 717 | 718 | //add that we are going to add this chain to that region 719 | add_to_region.at(closest_region).push_back(c); 720 | } 721 | 722 | std::vector current_region; 723 | 724 | //actually add the chain to the region only if we are going to 725 | //add only one chain to this region 726 | for (int r = 0; r < isolate_isoE.size(); r++) { 727 | if (add_to_region.at(r).size() == 1) { 728 | int ch = add_to_region.at(r).front(); 729 | isolate_isoE.at(r).push_back(chains.at(ch)); 730 | 731 | current_region.push_back(r); 732 | } 733 | } 734 | 735 | //if we found that we need to add more than one chain to the region 736 | //then we don't add them to these regions but instead open new 737 | //region using them 738 | for (int r = isolate_isoE.size() - 1; r >= 0; r--) { 739 | if (add_to_region.at(r).size() > 1) { 740 | for (int c = 0; c < add_to_region.at(r).size(); c++) { 741 | 742 | int ch = add_to_region.at(r).at(c); 743 | 744 | std::vector mat_V; 745 | mat_V.push_back(chains.at(ch)); 746 | 747 | isolate_isoE.push_back(mat_V); 748 | 749 | current_region.push_back(isolate_isoE.size() - 1); 750 | } 751 | } 752 | } 753 | 754 | last_region.swap(current_region); 755 | 756 | } 757 | 758 | region_id++; 759 | } 760 | 761 | for (int i = 0; i < isolate_isoE.size(); i++) { 762 | std::cout << "i= " << i << " --> " << isolate_isoE.at(i).size() << std::endl; 763 | } 764 | 765 | 766 | if (false) { 767 | reset_viewer(viewer, V, F, vertex_func); 768 | for (int c = 0; c < isolate_isoE.size(); c++) { 769 | if (false) { 770 | //draw each region in a different color 771 | float r, g, b(0.0f); 772 | if (isolate_isoE.at(c).size() > 1) { 773 | r = float(rand()) / float(RAND_MAX); 774 | g = float(rand()) / float(RAND_MAX); 775 | b = float(rand()) / float(RAND_MAX); 776 | } 777 | else { 778 | r = 0.0f; 779 | g = 0.0f; 780 | b = 0.0f; 781 | } 782 | add_edge_to_viewer(viewer, isoV, isolate_isoE.at(c), false, 783 | r, g, b); 784 | } 785 | else { 786 | //draw each isoline in raincolor relevent to the increasing 787 | //order of its edges 788 | add_colorful_edge_to_viewer(viewer, isoV, isolate_isoE.at(c)); 789 | } 790 | } 791 | viewer.launch(); 792 | } 793 | 794 | } 795 | //****************************************************************************** 796 | #endif /*_ISOLINES_HELPER_*/ --------------------------------------------------------------------------------