diff --git a/.github/workflows/runtests.yml b/.github/workflows/runtests.yml index a9d5ef8..7b5bec7 100644 --- a/.github/workflows/runtests.yml +++ b/.github/workflows/runtests.yml @@ -20,7 +20,7 @@ jobs: conda-channels: anaconda, conda-forge - name: Install dependencies run: | - conda install -n=base pyembree numpy + conda install -n=base pyembree numpy cython source activate base pip install -U pip pip install -r requirements.txt diff --git a/data/sphere.obj b/data/sphere.obj new file mode 100644 index 0000000..96b02fc --- /dev/null +++ b/data/sphere.obj @@ -0,0 +1,2496 @@ +# Max2Obj Version 4.0 Mar 10th, 2001 +# +# object default to come ... +# +v 0.000000 19.737080 -0.000000 +v -0.000000 19.357838 -3.850513 +v -0.751198 19.357838 -3.776527 +v -1.473528 19.357838 -3.557410 +v -2.139230 19.357838 -3.201585 +v -2.722724 19.357838 -2.722724 +v -3.201585 19.357838 -2.139230 +v -3.557411 19.357838 -1.473527 +v -3.776527 19.357838 -0.751197 +v -3.850513 19.357838 0.000001 +v -3.776526 19.357838 0.751199 +v -3.557410 19.357838 1.473529 +v -3.201584 19.357838 2.139232 +v -2.722722 19.357838 2.722726 +v -2.139228 19.357838 3.201586 +v -1.473525 19.357838 3.557412 +v -0.751195 19.357838 3.776527 +v 0.000004 19.357838 3.850513 +v 0.751202 19.357838 3.776526 +v 1.473532 19.357838 3.557409 +v 2.139235 19.357838 3.201582 +v 2.722728 19.357838 2.722721 +v 3.201588 19.357838 2.139226 +v 3.557413 19.357838 1.473523 +v 3.776528 19.357838 0.751192 +v 3.850513 19.357838 -0.000006 +v 3.776525 19.357838 -0.751204 +v 3.557408 19.357838 -1.473534 +v 3.201581 19.357838 -2.139236 +v 2.722719 19.357838 -2.722729 +v 2.139224 19.357838 -3.201589 +v 1.473520 19.357838 -3.557414 +v 0.751190 19.357838 -3.776528 +v -0.000000 18.234684 -7.553053 +v -1.473528 18.234684 -7.407924 +v -2.890428 18.234684 -6.978112 +v -4.196251 18.234684 -6.280135 +v -5.340816 18.234684 -5.340816 +v -6.280135 18.234684 -4.196251 +v -6.978112 18.234684 -2.890427 +v -7.407924 18.234684 -1.473526 +v -7.553053 18.234684 0.000002 +v -7.407923 18.234684 1.473531 +v -6.978110 18.234684 2.890432 +v -6.280132 18.234684 4.196255 +v -5.340812 18.234684 5.340819 +v -4.196247 18.234684 6.280138 +v -2.890423 18.234684 6.978114 +v -1.473521 18.234684 7.407925 +v 0.000007 18.234684 7.553053 +v 1.473535 18.234684 7.407922 +v 2.890436 18.234684 6.978108 +v 4.196259 18.234684 6.280129 +v 5.340822 18.234684 5.340808 +v 6.280140 18.234684 4.196243 +v 6.978116 18.234684 2.890418 +v 7.407926 18.234684 1.473516 +v 7.553053 18.234684 -0.000012 +v 7.407921 18.234684 -1.473540 +v 6.978106 18.234684 -2.890441 +v 6.280127 18.234684 -4.196263 +v 5.340805 18.234684 -5.340826 +v 4.196239 18.234684 -6.280143 +v 2.890414 18.234684 -6.978117 +v 1.473512 18.234684 -7.407927 +v -0.000000 16.410782 -10.965334 +v -2.139230 16.410782 -10.754638 +v -4.196251 16.410782 -10.130648 +v -6.092012 16.410782 -9.117342 +v -7.753662 16.410782 -7.753662 +v -9.117343 16.410782 -6.092012 +v -10.130649 16.410782 -4.196250 +v -10.754639 16.410782 -2.139228 +v -10.965334 16.410782 0.000004 +v -10.754638 16.410782 2.139235 +v -10.130646 16.410782 4.196257 +v -9.117338 16.410782 6.092018 +v -7.753657 16.410782 7.753667 +v -6.092007 16.410782 9.117347 +v -4.196243 16.410782 10.130651 +v -2.139221 16.410782 10.754640 +v 0.000011 16.410782 10.965334 +v 2.139242 16.410782 10.754636 +v 4.196263 16.410782 10.130643 +v 6.092024 16.410782 9.117334 +v 7.753672 16.410782 7.753652 +v 9.117351 16.410782 6.092000 +v 10.130653 16.410782 4.196237 +v 10.754642 16.410782 2.139214 +v 10.965334 16.410782 -0.000018 +v 10.754635 16.410782 -2.139249 +v 10.130640 16.410782 -4.196270 +v 9.117331 16.410782 -6.092030 +v 7.753647 16.410782 -7.753677 +v 6.091995 16.410782 -9.117354 +v 4.196230 16.410782 -10.130656 +v 2.139207 16.410782 -10.754642 +v -0.000001 13.956223 -13.956223 +v -2.722724 13.956223 -13.688058 +v -5.340815 13.956223 -12.893869 +v -7.753661 13.956223 -11.604176 +v -9.868540 13.956223 -9.868540 +v -11.604177 13.956223 -7.753661 +v -12.893869 13.956223 -5.340813 +v -13.688059 13.956223 -2.722721 +v -13.956223 13.956223 0.000005 +v -13.688057 13.956223 2.722730 +v -12.893867 13.956223 5.340822 +v -11.604171 13.956223 7.753669 +v -9.868534 13.956223 9.868546 +v -7.753654 13.956223 11.604181 +v -5.340805 13.956223 12.893873 +v -2.722712 13.956223 13.688061 +v 0.000013 13.956223 13.956223 +v 2.722738 13.956223 13.688055 +v 5.340830 13.956223 12.893863 +v 7.753676 13.956223 11.604166 +v 9.868553 13.956223 9.868527 +v 11.604186 13.956223 7.753646 +v 12.893877 13.956223 5.340797 +v 13.688063 13.956223 2.722703 +v 13.956223 13.956223 -0.000022 +v 13.688054 13.956223 -2.722747 +v 12.893860 13.956223 -5.340838 +v 11.604161 13.956223 -7.753684 +v 9.868521 13.956223 -9.868559 +v 7.753639 13.956223 -11.604191 +v 5.340788 13.956223 -12.893880 +v 2.722694 13.956223 -13.688065 +v -0.000001 10.965333 -16.410782 +v -3.201585 10.965333 -16.095453 +v -6.280134 10.965333 -15.161586 +v -9.117341 10.965333 -13.645067 +v -11.604176 10.965333 -11.604176 +v -13.645067 10.965333 -9.117341 +v -15.161587 10.965333 -6.280132 +v -16.095455 10.965333 -3.201581 +v -16.410782 10.965333 0.000005 +v -16.095453 10.965333 3.201591 +v -15.161583 10.965333 6.280142 +v -13.645061 10.965333 9.117350 +v -11.604168 10.965333 11.604183 +v -9.117332 10.965333 13.645074 +v -6.280122 10.965333 15.161591 +v -3.201571 10.965333 16.095457 +v 0.000016 10.965333 16.410782 +v 3.201602 10.965333 16.095451 +v 6.280151 10.965333 15.161579 +v 9.117358 10.965333 13.645056 +v 11.604191 10.965333 11.604160 +v 13.645080 10.965333 9.117324 +v 15.161595 10.965333 6.280113 +v 16.095459 10.965333 3.201560 +v 16.410782 10.965333 -0.000026 +v 16.095448 10.965333 -3.201612 +v 15.161575 10.965333 -6.280161 +v 13.645050 10.965333 -9.117368 +v 11.604154 10.965333 -11.604198 +v 9.117315 10.965333 -13.645085 +v 6.280103 10.965333 -15.161599 +v 3.201550 10.965333 -16.095461 +v -0.000001 7.553053 -18.234684 +v -3.557410 7.553053 -17.884310 +v -6.978111 7.553053 -16.846651 +v -10.130647 7.553053 -15.161587 +v -12.893868 7.553053 -12.893868 +v -15.161587 7.553053 -10.130647 +v -16.846653 7.553053 -6.978108 +v -17.884310 7.553053 -3.557406 +v -18.234684 7.553053 0.000006 +v -17.884308 7.553053 3.557418 +v -16.846647 7.553053 6.978120 +v -15.161580 7.553053 10.130656 +v -12.893860 7.553053 12.893877 +v -10.130636 7.553053 15.161592 +v -6.978098 7.553053 16.846657 +v -3.557395 7.553053 17.884314 +v 0.000018 7.553053 18.234684 +v 3.557429 7.553053 17.884306 +v 6.978130 7.553053 16.846643 +v 10.130666 7.553053 15.161573 +v 12.893886 7.553053 12.893852 +v 15.161599 7.553053 10.130627 +v 16.846661 7.553053 6.978087 +v 17.884315 7.553053 3.557383 +v 18.234684 7.553053 -0.000029 +v 17.884304 7.553053 -3.557441 +v 16.846640 7.553053 -6.978141 +v 15.161567 7.553053 -10.130675 +v 12.893844 7.553053 -12.893893 +v 10.130617 7.553053 -15.161606 +v 6.978076 7.553053 -16.846666 +v 3.557372 7.553053 -17.884317 +v -0.000001 3.850514 -19.357838 +v -3.776527 3.850514 -18.985882 +v -7.407923 3.850514 -17.884310 +v -10.754637 3.850514 -16.095453 +v -13.688058 3.850514 -13.688058 +v -16.095453 3.850514 -10.754637 +v -17.884310 3.850514 -7.407920 +v -18.985882 3.850514 -3.776522 +v -19.357838 3.850514 0.000006 +v -18.985880 3.850514 3.776534 +v -17.884306 3.850514 7.407932 +v -16.095448 3.850514 10.754647 +v -13.688049 3.850514 13.688066 +v -10.754626 3.850514 16.095461 +v -7.407909 3.850514 17.884315 +v -3.776510 3.850514 18.985886 +v 0.000019 3.850514 19.357838 +v 3.776546 3.850514 18.985878 +v 7.407944 3.850514 17.884300 +v 10.754658 3.850514 16.095440 +v 13.688075 3.850514 13.688040 +v 16.095469 3.850514 10.754616 +v 17.884319 3.850514 7.407897 +v 18.985888 3.850514 3.776498 +v 19.357838 3.850514 -0.000031 +v 18.985876 3.850514 -3.776559 +v 17.884296 3.850514 -7.407955 +v 16.095434 3.850514 -10.754667 +v 13.688031 3.850514 -13.688085 +v 10.754605 3.850514 -16.095474 +v 7.407886 3.850514 -17.884325 +v 3.776485 3.850514 -18.985889 +v -0.000001 0.000001 -19.737080 +v -3.850513 0.000001 -19.357838 +v -7.553053 0.000001 -18.234684 +v -10.965333 0.000001 -16.410782 +v -13.956223 0.000001 -13.956223 +v -16.410784 0.000001 -10.965333 +v -18.234686 0.000001 -7.553051 +v -19.357838 0.000001 -3.850508 +v -19.737080 0.000001 0.000006 +v -19.357836 0.000001 3.850521 +v -18.234680 0.000001 7.553062 +v -16.410776 0.000001 10.965343 +v -13.956214 0.000001 13.956232 +v -10.965322 0.000001 16.410789 +v -7.553039 0.000001 18.234690 +v -3.850496 0.000001 19.357841 +v 0.000019 0.000001 19.737080 +v 3.850533 0.000001 19.357834 +v 7.553074 0.000001 18.234674 +v 10.965354 0.000001 16.410769 +v 13.956241 0.000001 13.956205 +v 16.410797 0.000001 10.965311 +v 18.234695 0.000001 7.553027 +v 19.357843 0.000001 3.850484 +v 19.737080 0.000001 -0.000032 +v 19.357830 0.000001 -3.850546 +v 18.234671 0.000001 -7.553085 +v 16.410761 0.000001 -10.965364 +v 13.956196 0.000001 -13.956249 +v 10.965301 0.000001 -16.410805 +v 7.553015 0.000001 -18.234699 +v 3.850471 0.000001 -19.357845 +v -0.000001 -3.850511 -19.357838 +v -3.776527 -3.850511 -18.985882 +v -7.407923 -3.850511 -17.884310 +v -10.754637 -3.850511 -16.095455 +v -13.688058 -3.850511 -13.688058 +v -16.095455 -3.850511 -10.754637 +v -17.884312 -3.850511 -7.407921 +v -18.985884 -3.850511 -3.776522 +v -19.357838 -3.850511 0.000006 +v -18.985880 -3.850511 3.776535 +v -17.884306 -3.850511 7.407932 +v -16.095448 -3.850511 10.754647 +v -13.688049 -3.850511 13.688067 +v -10.754626 -3.850511 16.095461 +v -7.407909 -3.850511 17.884315 +v -3.776510 -3.850511 18.985886 +v 0.000019 -3.850511 19.357838 +v 3.776547 -3.850511 18.985878 +v 7.407944 -3.850511 17.884302 +v 10.754658 -3.850511 16.095440 +v 13.688076 -3.850511 13.688041 +v 16.095469 -3.850511 10.754617 +v 17.884321 -3.850511 7.407898 +v 18.985888 -3.850511 3.776498 +v 19.357838 -3.850511 -0.000031 +v 18.985876 -3.850511 -3.776559 +v 17.884296 -3.850511 -7.407955 +v 16.095434 -3.850511 -10.754668 +v 13.688032 -3.850511 -13.688085 +v 10.754606 -3.850511 -16.095476 +v 7.407887 -3.850511 -17.884325 +v 3.776486 -3.850511 -18.985889 +v -0.000001 -7.553051 -18.234686 +v -3.557411 -7.553051 -17.884310 +v -6.978111 -7.553051 -16.846653 +v -10.130647 -7.553051 -15.161588 +v -12.893869 -7.553051 -12.893869 +v -15.161588 -7.553051 -10.130647 +v -16.846653 -7.553051 -6.978109 +v -17.884312 -7.553051 -3.557406 +v -18.234686 -7.553051 0.000006 +v -17.884310 -7.553051 3.557418 +v -16.846649 -7.553051 6.978120 +v -15.161581 -7.553051 10.130657 +v -12.893861 -7.553051 12.893878 +v -10.130637 -7.553051 15.161593 +v -6.978098 -7.553051 16.846659 +v -3.557395 -7.553051 17.884314 +v 0.000018 -7.553051 18.234686 +v 3.557429 -7.553051 17.884308 +v 6.978131 -7.553051 16.846645 +v 10.130667 -7.553051 15.161574 +v 12.893886 -7.553051 12.893853 +v 15.161600 -7.553051 10.130628 +v 16.846663 -7.553051 6.978087 +v 17.884315 -7.553051 3.557383 +v 18.234686 -7.553051 -0.000029 +v 17.884304 -7.553051 -3.557441 +v 16.846640 -7.553051 -6.978142 +v 15.161568 -7.553051 -10.130676 +v 12.893845 -7.553051 -12.893894 +v 10.130618 -7.553051 -15.161607 +v 6.978077 -7.553051 -16.846666 +v 3.557372 -7.553051 -17.884319 +v -0.000001 -10.965333 -16.410782 +v -3.201585 -10.965333 -16.095453 +v -6.280134 -10.965333 -15.161587 +v -9.117341 -10.965333 -13.645068 +v -11.604176 -10.965333 -11.604176 +v -13.645068 -10.965333 -9.117341 +v -15.161588 -10.965333 -6.280132 +v -16.095455 -10.965333 -3.201581 +v -16.410782 -10.965333 0.000005 +v -16.095453 -10.965333 3.201591 +v -15.161583 -10.965333 6.280142 +v -13.645062 -10.965333 9.117351 +v -11.604168 -10.965333 11.604183 +v -9.117332 -10.965333 13.645074 +v -6.280122 -10.965333 15.161592 +v -3.201571 -10.965333 16.095457 +v 0.000016 -10.965333 16.410782 +v 3.201602 -10.965333 16.095451 +v 6.280152 -10.965333 15.161579 +v 9.117359 -10.965333 13.645056 +v 11.604191 -10.965333 11.604161 +v 13.645080 -10.965333 9.117324 +v 15.161595 -10.965333 6.280113 +v 16.095459 -10.965333 3.201560 +v 16.410782 -10.965333 -0.000026 +v 16.095449 -10.965333 -3.201612 +v 15.161575 -10.965333 -6.280161 +v 13.645050 -10.965333 -9.117368 +v 11.604154 -10.965333 -11.604198 +v 9.117315 -10.965333 -13.645085 +v 6.280103 -10.965333 -15.161599 +v 3.201550 -10.965333 -16.095461 +v -0.000001 -13.956223 -13.956223 +v -2.722724 -13.956223 -13.688058 +v -5.340815 -13.956223 -12.893868 +v -7.753661 -13.956223 -11.604176 +v -9.868540 -13.956223 -9.868540 +v -11.604176 -13.956223 -7.753661 +v -12.893869 -13.956223 -5.340813 +v -13.688059 -13.956223 -2.722721 +v -13.956223 -13.956223 0.000005 +v -13.688057 -13.956223 2.722729 +v -12.893866 -13.956223 5.340821 +v -11.604171 -13.956223 7.753668 +v -9.868533 -13.956223 9.868546 +v -7.753654 -13.956223 11.604180 +v -5.340805 -13.956223 12.893873 +v -2.722712 -13.956223 13.688060 +v 0.000013 -13.956223 13.956223 +v 2.722738 -13.956223 13.688055 +v 5.340830 -13.956223 12.893863 +v 7.753676 -13.956223 11.604166 +v 9.868552 -13.956223 9.868527 +v 11.604186 -13.956223 7.753646 +v 12.893876 -13.956223 5.340796 +v 13.688062 -13.956223 2.722703 +v 13.956223 -13.956223 -0.000022 +v 13.688053 -13.956223 -2.722747 +v 12.893859 -13.956223 -5.340838 +v 11.604161 -13.956223 -7.753684 +v 9.868521 -13.956223 -9.868559 +v 7.753639 -13.956223 -11.604191 +v 5.340788 -13.956223 -12.893880 +v 2.722694 -13.956223 -13.688064 +v -0.000000 -16.410784 -10.965333 +v -2.139230 -16.410784 -10.754637 +v -4.196251 -16.410784 -10.130647 +v -6.092011 -16.410784 -9.117341 +v -7.753661 -16.410784 -7.753661 +v -9.117341 -16.410784 -6.092011 +v -10.130647 -16.410784 -4.196249 +v -10.754638 -16.410784 -2.139228 +v -10.965333 -16.410784 0.000004 +v -10.754636 -16.410784 2.139235 +v -10.130644 -16.410784 4.196256 +v -9.117337 -16.410784 6.092018 +v -7.753656 -16.410784 7.753666 +v -6.092006 -16.410784 9.117345 +v -4.196243 -16.410784 10.130650 +v -2.139221 -16.410784 10.754639 +v 0.000011 -16.410784 10.965333 +v 2.139241 -16.410784 10.754635 +v 4.196262 -16.410784 10.130642 +v 6.092023 -16.410784 9.117333 +v 7.753671 -16.410784 7.753651 +v 9.117349 -16.410784 6.092000 +v 10.130652 -16.410784 4.196237 +v 10.754640 -16.410784 2.139214 +v 10.965333 -16.410784 -0.000018 +v 10.754633 -16.410784 -2.139248 +v 10.130639 -16.410784 -4.196269 +v 9.117330 -16.410784 -6.092029 +v 7.753646 -16.410784 -7.753676 +v 6.091994 -16.410784 -9.117353 +v 4.196230 -16.410784 -10.130655 +v 2.139207 -16.410784 -10.754642 +v -0.000000 -18.234686 -7.553051 +v -1.473527 -18.234686 -7.407920 +v -2.890427 -18.234686 -6.978109 +v -4.196249 -18.234686 -6.280132 +v -5.340813 -18.234686 -5.340813 +v -6.280132 -18.234686 -4.196249 +v -6.978109 -18.234686 -2.890426 +v -7.407921 -18.234686 -1.473525 +v -7.553051 -18.234686 0.000002 +v -7.407920 -18.234686 1.473530 +v -6.978107 -18.234686 2.890431 +v -6.280129 -18.234686 4.196253 +v -5.340810 -18.234686 5.340816 +v -4.196245 -18.234686 6.280135 +v -2.890422 -18.234686 6.978111 +v -1.473521 -18.234686 7.407922 +v 0.000007 -18.234686 7.553051 +v 1.473535 -18.234686 7.407919 +v 2.890435 -18.234686 6.978106 +v 4.196258 -18.234686 6.280127 +v 5.340820 -18.234686 5.340806 +v 6.280138 -18.234686 4.196241 +v 6.978113 -18.234686 2.890417 +v 7.407923 -18.234686 1.473516 +v 7.553051 -18.234686 -0.000012 +v 7.407918 -18.234686 -1.473539 +v 6.978104 -18.234686 -2.890440 +v 6.280124 -18.234686 -4.196261 +v 5.340803 -18.234686 -5.340823 +v 4.196238 -18.234686 -6.280140 +v 2.890413 -18.234686 -6.978115 +v 1.473511 -18.234686 -7.407924 +v -0.000000 -19.357838 -3.850508 +v -0.751197 -19.357838 -3.776522 +v -1.473526 -19.357838 -3.557406 +v -2.139228 -19.357838 -3.201581 +v -2.722721 -19.357838 -2.722721 +v -3.201581 -19.357838 -2.139228 +v -3.557406 -19.357838 -1.473525 +v -3.776522 -19.357838 -0.751196 +v -3.850508 -19.357838 0.000001 +v -3.776522 -19.357838 0.751198 +v -3.557405 -19.357838 1.473528 +v -3.201580 -19.357838 2.139230 +v -2.722719 -19.357838 2.722722 +v -2.139225 -19.357838 3.201582 +v -1.473523 -19.357838 3.557407 +v -0.751194 -19.357838 3.776523 +v 0.000004 -19.357838 3.850508 +v 0.751201 -19.357838 3.776521 +v 1.473530 -19.357838 3.557404 +v 2.139232 -19.357838 3.201578 +v 2.722724 -19.357838 2.722717 +v 3.201584 -19.357838 2.139224 +v 3.557408 -19.357838 1.473521 +v 3.776523 -19.357838 0.751191 +v 3.850508 -19.357838 -0.000006 +v 3.776521 -19.357838 -0.751203 +v 3.557403 -19.357838 -1.473532 +v 3.201577 -19.357838 -2.139234 +v 2.722715 -19.357838 -2.722726 +v 2.139221 -19.357838 -3.201585 +v 1.473518 -19.357838 -3.557409 +v 0.751189 -19.357838 -3.776524 +v 0.000000 -19.737080 -0.000000 +# 482 vertices + +vt 0.000000 1.000000 0.000000 +vt 0.031250 1.000000 0.000000 +vt 0.062500 1.000000 0.000000 +vt 0.093750 1.000000 0.000000 +vt 0.125000 1.000000 0.000000 +vt 0.156250 1.000000 0.000000 +vt 0.187500 1.000000 0.000000 +vt 0.218750 1.000000 0.000000 +vt 0.250000 1.000000 0.000000 +vt 0.281250 1.000000 0.000000 +vt 0.312500 1.000000 0.000000 +vt 0.343750 1.000000 0.000000 +vt 0.375000 1.000000 0.000000 +vt 0.406250 1.000000 0.000000 +vt 0.437500 1.000000 0.000000 +vt 0.468750 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.531250 1.000000 0.000000 +vt 0.562500 1.000000 0.000000 +vt 0.593750 1.000000 0.000000 +vt 0.625000 1.000000 0.000000 +vt 0.656250 1.000000 0.000000 +vt 0.687500 1.000000 0.000000 +vt 0.718750 1.000000 0.000000 +vt 0.750000 1.000000 0.000000 +vt 0.781250 1.000000 0.000000 +vt 0.812500 1.000000 0.000000 +vt 0.843750 1.000000 0.000000 +vt 0.875000 1.000000 0.000000 +vt 0.906250 1.000000 0.000000 +vt 0.937500 1.000000 0.000000 +vt 0.968750 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 0.937500 0.000000 +vt 0.031250 0.937500 0.000000 +vt 0.062500 0.937500 0.000000 +vt 0.093750 0.937500 0.000000 +vt 0.125000 0.937500 0.000000 +vt 0.156250 0.937500 0.000000 +vt 0.187500 0.937500 0.000000 +vt 0.218750 0.937500 0.000000 +vt 0.250000 0.937500 0.000000 +vt 0.281250 0.937500 0.000000 +vt 0.312500 0.937500 0.000000 +vt 0.343750 0.937500 0.000000 +vt 0.375000 0.937500 0.000000 +vt 0.406250 0.937500 0.000000 +vt 0.437500 0.937500 0.000000 +vt 0.468750 0.937500 0.000000 +vt 0.500000 0.937500 0.000000 +vt 0.531250 0.937500 0.000000 +vt 0.562500 0.937500 0.000000 +vt 0.593750 0.937500 0.000000 +vt 0.625000 0.937500 0.000000 +vt 0.656250 0.937500 0.000000 +vt 0.687500 0.937500 0.000000 +vt 0.718750 0.937500 0.000000 +vt 0.750000 0.937500 0.000000 +vt 0.781250 0.937500 0.000000 +vt 0.812500 0.937500 0.000000 +vt 0.843750 0.937500 0.000000 +vt 0.875000 0.937500 0.000000 +vt 0.906250 0.937500 0.000000 +vt 0.937500 0.937500 0.000000 +vt 0.968750 0.937500 0.000000 +vt 1.000000 0.937500 0.000000 +vt 0.000000 0.875000 0.000000 +vt 0.031250 0.875000 0.000000 +vt 0.062500 0.875000 0.000000 +vt 0.093750 0.875000 0.000000 +vt 0.125000 0.875000 0.000000 +vt 0.156250 0.875000 0.000000 +vt 0.187500 0.875000 0.000000 +vt 0.218750 0.875000 0.000000 +vt 0.250000 0.875000 0.000000 +vt 0.281250 0.875000 0.000000 +vt 0.312500 0.875000 0.000000 +vt 0.343750 0.875000 0.000000 +vt 0.375000 0.875000 0.000000 +vt 0.406250 0.875000 0.000000 +vt 0.437500 0.875000 0.000000 +vt 0.468750 0.875000 0.000000 +vt 0.500000 0.875000 0.000000 +vt 0.531250 0.875000 0.000000 +vt 0.562500 0.875000 0.000000 +vt 0.593750 0.875000 0.000000 +vt 0.625000 0.875000 0.000000 +vt 0.656250 0.875000 0.000000 +vt 0.687500 0.875000 0.000000 +vt 0.718750 0.875000 0.000000 +vt 0.750000 0.875000 0.000000 +vt 0.781250 0.875000 0.000000 +vt 0.812500 0.875000 0.000000 +vt 0.843750 0.875000 0.000000 +vt 0.875000 0.875000 0.000000 +vt 0.906250 0.875000 0.000000 +vt 0.937500 0.875000 0.000000 +vt 0.968750 0.875000 0.000000 +vt 1.000000 0.875000 0.000000 +vt 0.000000 0.812500 0.000000 +vt 0.031250 0.812500 0.000000 +vt 0.062500 0.812500 0.000000 +vt 0.093750 0.812500 0.000000 +vt 0.125000 0.812500 0.000000 +vt 0.156250 0.812500 0.000000 +vt 0.187500 0.812500 0.000000 +vt 0.218750 0.812500 0.000000 +vt 0.250000 0.812500 0.000000 +vt 0.281250 0.812500 0.000000 +vt 0.312500 0.812500 0.000000 +vt 0.343750 0.812500 0.000000 +vt 0.375000 0.812500 0.000000 +vt 0.406250 0.812500 0.000000 +vt 0.437500 0.812500 0.000000 +vt 0.468750 0.812500 0.000000 +vt 0.500000 0.812500 0.000000 +vt 0.531250 0.812500 0.000000 +vt 0.562500 0.812500 0.000000 +vt 0.593750 0.812500 0.000000 +vt 0.625000 0.812500 0.000000 +vt 0.656250 0.812500 0.000000 +vt 0.687500 0.812500 0.000000 +vt 0.718750 0.812500 0.000000 +vt 0.750000 0.812500 0.000000 +vt 0.781250 0.812500 0.000000 +vt 0.812500 0.812500 0.000000 +vt 0.843750 0.812500 0.000000 +vt 0.875000 0.812500 0.000000 +vt 0.906250 0.812500 0.000000 +vt 0.937500 0.812500 0.000000 +vt 0.968750 0.812500 0.000000 +vt 1.000000 0.812500 0.000000 +vt 0.000000 0.750000 0.000000 +vt 0.031250 0.750000 0.000000 +vt 0.062500 0.750000 0.000000 +vt 0.093750 0.750000 0.000000 +vt 0.125000 0.750000 0.000000 +vt 0.156250 0.750000 0.000000 +vt 0.187500 0.750000 0.000000 +vt 0.218750 0.750000 0.000000 +vt 0.250000 0.750000 0.000000 +vt 0.281250 0.750000 0.000000 +vt 0.312500 0.750000 0.000000 +vt 0.343750 0.750000 0.000000 +vt 0.375000 0.750000 0.000000 +vt 0.406250 0.750000 0.000000 +vt 0.437500 0.750000 0.000000 +vt 0.468750 0.750000 0.000000 +vt 0.500000 0.750000 0.000000 +vt 0.531250 0.750000 0.000000 +vt 0.562500 0.750000 0.000000 +vt 0.593750 0.750000 0.000000 +vt 0.625000 0.750000 0.000000 +vt 0.656250 0.750000 0.000000 +vt 0.687500 0.750000 0.000000 +vt 0.718750 0.750000 0.000000 +vt 0.750000 0.750000 0.000000 +vt 0.781250 0.750000 0.000000 +vt 0.812500 0.750000 0.000000 +vt 0.843750 0.750000 0.000000 +vt 0.875000 0.750000 0.000000 +vt 0.906250 0.750000 0.000000 +vt 0.937500 0.750000 0.000000 +vt 0.968750 0.750000 0.000000 +vt 1.000000 0.750000 0.000000 +vt 0.000000 0.687500 0.000000 +vt 0.031250 0.687500 0.000000 +vt 0.062500 0.687500 0.000000 +vt 0.093750 0.687500 0.000000 +vt 0.125000 0.687500 0.000000 +vt 0.156250 0.687500 0.000000 +vt 0.187500 0.687500 0.000000 +vt 0.218750 0.687500 0.000000 +vt 0.250000 0.687500 0.000000 +vt 0.281250 0.687500 0.000000 +vt 0.312500 0.687500 0.000000 +vt 0.343750 0.687500 0.000000 +vt 0.375000 0.687500 0.000000 +vt 0.406250 0.687500 0.000000 +vt 0.437500 0.687500 0.000000 +vt 0.468750 0.687500 0.000000 +vt 0.500000 0.687500 0.000000 +vt 0.531250 0.687500 0.000000 +vt 0.562500 0.687500 0.000000 +vt 0.593750 0.687500 0.000000 +vt 0.625000 0.687500 0.000000 +vt 0.656250 0.687500 0.000000 +vt 0.687500 0.687500 0.000000 +vt 0.718750 0.687500 0.000000 +vt 0.750000 0.687500 0.000000 +vt 0.781250 0.687500 0.000000 +vt 0.812500 0.687500 0.000000 +vt 0.843750 0.687500 0.000000 +vt 0.875000 0.687500 0.000000 +vt 0.906250 0.687500 0.000000 +vt 0.937500 0.687500 0.000000 +vt 0.968750 0.687500 0.000000 +vt 1.000000 0.687500 0.000000 +vt 0.000000 0.625000 0.000000 +vt 0.031250 0.625000 0.000000 +vt 0.062500 0.625000 0.000000 +vt 0.093750 0.625000 0.000000 +vt 0.125000 0.625000 0.000000 +vt 0.156250 0.625000 0.000000 +vt 0.187500 0.625000 0.000000 +vt 0.218750 0.625000 0.000000 +vt 0.250000 0.625000 0.000000 +vt 0.281250 0.625000 0.000000 +vt 0.312500 0.625000 0.000000 +vt 0.343750 0.625000 0.000000 +vt 0.375000 0.625000 0.000000 +vt 0.406250 0.625000 0.000000 +vt 0.437500 0.625000 0.000000 +vt 0.468750 0.625000 0.000000 +vt 0.500000 0.625000 0.000000 +vt 0.531250 0.625000 0.000000 +vt 0.562500 0.625000 0.000000 +vt 0.593750 0.625000 0.000000 +vt 0.625000 0.625000 0.000000 +vt 0.656250 0.625000 0.000000 +vt 0.687500 0.625000 0.000000 +vt 0.718750 0.625000 0.000000 +vt 0.750000 0.625000 0.000000 +vt 0.781250 0.625000 0.000000 +vt 0.812500 0.625000 0.000000 +vt 0.843750 0.625000 0.000000 +vt 0.875000 0.625000 0.000000 +vt 0.906250 0.625000 0.000000 +vt 0.937500 0.625000 0.000000 +vt 0.968750 0.625000 0.000000 +vt 1.000000 0.625000 0.000000 +vt 0.000000 0.562500 0.000000 +vt 0.031250 0.562500 0.000000 +vt 0.062500 0.562500 0.000000 +vt 0.093750 0.562500 0.000000 +vt 0.125000 0.562500 0.000000 +vt 0.156250 0.562500 0.000000 +vt 0.187500 0.562500 0.000000 +vt 0.218750 0.562500 0.000000 +vt 0.250000 0.562500 0.000000 +vt 0.281250 0.562500 0.000000 +vt 0.312500 0.562500 0.000000 +vt 0.343750 0.562500 0.000000 +vt 0.375000 0.562500 0.000000 +vt 0.406250 0.562500 0.000000 +vt 0.437500 0.562500 0.000000 +vt 0.468750 0.562500 0.000000 +vt 0.500000 0.562500 0.000000 +vt 0.531250 0.562500 0.000000 +vt 0.562500 0.562500 0.000000 +vt 0.593750 0.562500 0.000000 +vt 0.625000 0.562500 0.000000 +vt 0.656250 0.562500 0.000000 +vt 0.687500 0.562500 0.000000 +vt 0.718750 0.562500 0.000000 +vt 0.750000 0.562500 0.000000 +vt 0.781250 0.562500 0.000000 +vt 0.812500 0.562500 0.000000 +vt 0.843750 0.562500 0.000000 +vt 0.875000 0.562500 0.000000 +vt 0.906250 0.562500 0.000000 +vt 0.937500 0.562500 0.000000 +vt 0.968750 0.562500 0.000000 +vt 1.000000 0.562500 0.000000 +vt 0.000000 0.500000 0.000000 +vt 0.031250 0.500000 0.000000 +vt 0.062500 0.500000 0.000000 +vt 0.093750 0.500000 0.000000 +vt 0.125000 0.500000 0.000000 +vt 0.156250 0.500000 0.000000 +vt 0.187500 0.500000 0.000000 +vt 0.218750 0.500000 0.000000 +vt 0.250000 0.500000 0.000000 +vt 0.281250 0.500000 0.000000 +vt 0.312500 0.500000 0.000000 +vt 0.343750 0.500000 0.000000 +vt 0.375000 0.500000 0.000000 +vt 0.406250 0.500000 0.000000 +vt 0.437500 0.500000 0.000000 +vt 0.468750 0.500000 0.000000 +vt 0.500000 0.500000 0.000000 +vt 0.531250 0.500000 0.000000 +vt 0.562500 0.500000 0.000000 +vt 0.593750 0.500000 0.000000 +vt 0.625000 0.500000 0.000000 +vt 0.656250 0.500000 0.000000 +vt 0.687500 0.500000 0.000000 +vt 0.718750 0.500000 0.000000 +vt 0.750000 0.500000 0.000000 +vt 0.781250 0.500000 0.000000 +vt 0.812500 0.500000 0.000000 +vt 0.843750 0.500000 0.000000 +vt 0.875000 0.500000 0.000000 +vt 0.906250 0.500000 0.000000 +vt 0.937500 0.500000 0.000000 +vt 0.968750 0.500000 0.000000 +vt 1.000000 0.500000 0.000000 +vt 0.000000 0.437500 0.000000 +vt 0.031250 0.437500 0.000000 +vt 0.062500 0.437500 0.000000 +vt 0.093750 0.437500 0.000000 +vt 0.125000 0.437500 0.000000 +vt 0.156250 0.437500 0.000000 +vt 0.187500 0.437500 0.000000 +vt 0.218750 0.437500 0.000000 +vt 0.250000 0.437500 0.000000 +vt 0.281250 0.437500 0.000000 +vt 0.312500 0.437500 0.000000 +vt 0.343750 0.437500 0.000000 +vt 0.375000 0.437500 0.000000 +vt 0.406250 0.437500 0.000000 +vt 0.437500 0.437500 0.000000 +vt 0.468750 0.437500 0.000000 +vt 0.500000 0.437500 0.000000 +vt 0.531250 0.437500 0.000000 +vt 0.562500 0.437500 0.000000 +vt 0.593750 0.437500 0.000000 +vt 0.625000 0.437500 0.000000 +vt 0.656250 0.437500 0.000000 +vt 0.687500 0.437500 0.000000 +vt 0.718750 0.437500 0.000000 +vt 0.750000 0.437500 0.000000 +vt 0.781250 0.437500 0.000000 +vt 0.812500 0.437500 0.000000 +vt 0.843750 0.437500 0.000000 +vt 0.875000 0.437500 0.000000 +vt 0.906250 0.437500 0.000000 +vt 0.937500 0.437500 0.000000 +vt 0.968750 0.437500 0.000000 +vt 1.000000 0.437500 0.000000 +vt 0.000000 0.375000 0.000000 +vt 0.031250 0.375000 0.000000 +vt 0.062500 0.375000 0.000000 +vt 0.093750 0.375000 0.000000 +vt 0.125000 0.375000 0.000000 +vt 0.156250 0.375000 0.000000 +vt 0.187500 0.375000 0.000000 +vt 0.218750 0.375000 0.000000 +vt 0.250000 0.375000 0.000000 +vt 0.281250 0.375000 0.000000 +vt 0.312500 0.375000 0.000000 +vt 0.343750 0.375000 0.000000 +vt 0.375000 0.375000 0.000000 +vt 0.406250 0.375000 0.000000 +vt 0.437500 0.375000 0.000000 +vt 0.468750 0.375000 0.000000 +vt 0.500000 0.375000 0.000000 +vt 0.531250 0.375000 0.000000 +vt 0.562500 0.375000 0.000000 +vt 0.593750 0.375000 0.000000 +vt 0.625000 0.375000 0.000000 +vt 0.656250 0.375000 0.000000 +vt 0.687500 0.375000 0.000000 +vt 0.718750 0.375000 0.000000 +vt 0.750000 0.375000 0.000000 +vt 0.781250 0.375000 0.000000 +vt 0.812500 0.375000 0.000000 +vt 0.843750 0.375000 0.000000 +vt 0.875000 0.375000 0.000000 +vt 0.906250 0.375000 0.000000 +vt 0.937500 0.375000 0.000000 +vt 0.968750 0.375000 0.000000 +vt 1.000000 0.375000 0.000000 +vt 0.000000 0.312500 0.000000 +vt 0.031250 0.312500 0.000000 +vt 0.062500 0.312500 0.000000 +vt 0.093750 0.312500 0.000000 +vt 0.125000 0.312500 0.000000 +vt 0.156250 0.312500 0.000000 +vt 0.187500 0.312500 0.000000 +vt 0.218750 0.312500 0.000000 +vt 0.250000 0.312500 0.000000 +vt 0.281250 0.312500 0.000000 +vt 0.312500 0.312500 0.000000 +vt 0.343750 0.312500 0.000000 +vt 0.375000 0.312500 0.000000 +vt 0.406250 0.312500 0.000000 +vt 0.437500 0.312500 0.000000 +vt 0.468750 0.312500 0.000000 +vt 0.500000 0.312500 0.000000 +vt 0.531250 0.312500 0.000000 +vt 0.562500 0.312500 0.000000 +vt 0.593750 0.312500 0.000000 +vt 0.625000 0.312500 0.000000 +vt 0.656250 0.312500 0.000000 +vt 0.687500 0.312500 0.000000 +vt 0.718750 0.312500 0.000000 +vt 0.750000 0.312500 0.000000 +vt 0.781250 0.312500 0.000000 +vt 0.812500 0.312500 0.000000 +vt 0.843750 0.312500 0.000000 +vt 0.875000 0.312500 0.000000 +vt 0.906250 0.312500 0.000000 +vt 0.937500 0.312500 0.000000 +vt 0.968750 0.312500 0.000000 +vt 1.000000 0.312500 0.000000 +vt 0.000000 0.250000 0.000000 +vt 0.031250 0.250000 0.000000 +vt 0.062500 0.250000 0.000000 +vt 0.093750 0.250000 0.000000 +vt 0.125000 0.250000 0.000000 +vt 0.156250 0.250000 0.000000 +vt 0.187500 0.250000 0.000000 +vt 0.218750 0.250000 0.000000 +vt 0.250000 0.250000 0.000000 +vt 0.281250 0.250000 0.000000 +vt 0.312500 0.250000 0.000000 +vt 0.343750 0.250000 0.000000 +vt 0.375000 0.250000 0.000000 +vt 0.406250 0.250000 0.000000 +vt 0.437500 0.250000 0.000000 +vt 0.468750 0.250000 0.000000 +vt 0.500000 0.250000 0.000000 +vt 0.531250 0.250000 0.000000 +vt 0.562500 0.250000 0.000000 +vt 0.593750 0.250000 0.000000 +vt 0.625000 0.250000 0.000000 +vt 0.656250 0.250000 0.000000 +vt 0.687500 0.250000 0.000000 +vt 0.718750 0.250000 0.000000 +vt 0.750000 0.250000 0.000000 +vt 0.781250 0.250000 0.000000 +vt 0.812500 0.250000 0.000000 +vt 0.843750 0.250000 0.000000 +vt 0.875000 0.250000 0.000000 +vt 0.906250 0.250000 0.000000 +vt 0.937500 0.250000 0.000000 +vt 0.968750 0.250000 0.000000 +vt 1.000000 0.250000 0.000000 +vt 0.000000 0.187500 0.000000 +vt 0.031250 0.187500 0.000000 +vt 0.062500 0.187500 0.000000 +vt 0.093750 0.187500 0.000000 +vt 0.125000 0.187500 0.000000 +vt 0.156250 0.187500 0.000000 +vt 0.187500 0.187500 0.000000 +vt 0.218750 0.187500 0.000000 +vt 0.250000 0.187500 0.000000 +vt 0.281250 0.187500 0.000000 +vt 0.312500 0.187500 0.000000 +vt 0.343750 0.187500 0.000000 +vt 0.375000 0.187500 0.000000 +vt 0.406250 0.187500 0.000000 +vt 0.437500 0.187500 0.000000 +vt 0.468750 0.187500 0.000000 +vt 0.500000 0.187500 0.000000 +vt 0.531250 0.187500 0.000000 +vt 0.562500 0.187500 0.000000 +vt 0.593750 0.187500 0.000000 +vt 0.625000 0.187500 0.000000 +vt 0.656250 0.187500 0.000000 +vt 0.687500 0.187500 0.000000 +vt 0.718750 0.187500 0.000000 +vt 0.750000 0.187500 0.000000 +vt 0.781250 0.187500 0.000000 +vt 0.812500 0.187500 0.000000 +vt 0.843750 0.187500 0.000000 +vt 0.875000 0.187500 0.000000 +vt 0.906250 0.187500 0.000000 +vt 0.937500 0.187500 0.000000 +vt 0.968750 0.187500 0.000000 +vt 1.000000 0.187500 0.000000 +vt 0.000000 0.125000 0.000000 +vt 0.031250 0.125000 0.000000 +vt 0.062500 0.125000 0.000000 +vt 0.093750 0.125000 0.000000 +vt 0.125000 0.125000 0.000000 +vt 0.156250 0.125000 0.000000 +vt 0.187500 0.125000 0.000000 +vt 0.218750 0.125000 0.000000 +vt 0.250000 0.125000 0.000000 +vt 0.281250 0.125000 0.000000 +vt 0.312500 0.125000 0.000000 +vt 0.343750 0.125000 0.000000 +vt 0.375000 0.125000 0.000000 +vt 0.406250 0.125000 0.000000 +vt 0.437500 0.125000 0.000000 +vt 0.468750 0.125000 0.000000 +vt 0.500000 0.125000 0.000000 +vt 0.531250 0.125000 0.000000 +vt 0.562500 0.125000 0.000000 +vt 0.593750 0.125000 0.000000 +vt 0.625000 0.125000 0.000000 +vt 0.656250 0.125000 0.000000 +vt 0.687500 0.125000 0.000000 +vt 0.718750 0.125000 0.000000 +vt 0.750000 0.125000 0.000000 +vt 0.781250 0.125000 0.000000 +vt 0.812500 0.125000 0.000000 +vt 0.843750 0.125000 0.000000 +vt 0.875000 0.125000 0.000000 +vt 0.906250 0.125000 0.000000 +vt 0.937500 0.125000 0.000000 +vt 0.968750 0.125000 0.000000 +vt 1.000000 0.125000 0.000000 +vt 0.000000 0.062500 0.000000 +vt 0.031250 0.062500 0.000000 +vt 0.062500 0.062500 0.000000 +vt 0.093750 0.062500 0.000000 +vt 0.125000 0.062500 0.000000 +vt 0.156250 0.062500 0.000000 +vt 0.187500 0.062500 0.000000 +vt 0.218750 0.062500 0.000000 +vt 0.250000 0.062500 0.000000 +vt 0.281250 0.062500 0.000000 +vt 0.312500 0.062500 0.000000 +vt 0.343750 0.062500 0.000000 +vt 0.375000 0.062500 0.000000 +vt 0.406250 0.062500 0.000000 +vt 0.437500 0.062500 0.000000 +vt 0.468750 0.062500 0.000000 +vt 0.500000 0.062500 0.000000 +vt 0.531250 0.062500 0.000000 +vt 0.562500 0.062500 0.000000 +vt 0.593750 0.062500 0.000000 +vt 0.625000 0.062500 0.000000 +vt 0.656250 0.062500 0.000000 +vt 0.687500 0.062500 0.000000 +vt 0.718750 0.062500 0.000000 +vt 0.750000 0.062500 0.000000 +vt 0.781250 0.062500 0.000000 +vt 0.812500 0.062500 0.000000 +vt 0.843750 0.062500 0.000000 +vt 0.875000 0.062500 0.000000 +vt 0.906250 0.062500 0.000000 +vt 0.937500 0.062500 0.000000 +vt 0.968750 0.062500 0.000000 +vt 1.000000 0.062500 0.000000 +vt 0.000000 -0.000000 0.000000 +vt 0.031250 -0.000000 0.000000 +vt 0.062500 -0.000000 0.000000 +vt 0.093750 -0.000000 0.000000 +vt 0.125000 -0.000000 0.000000 +vt 0.156250 -0.000000 0.000000 +vt 0.187500 -0.000000 0.000000 +vt 0.218750 -0.000000 0.000000 +vt 0.250000 -0.000000 0.000000 +vt 0.281250 -0.000000 0.000000 +vt 0.312500 -0.000000 0.000000 +vt 0.343750 -0.000000 0.000000 +vt 0.375000 -0.000000 0.000000 +vt 0.406250 -0.000000 0.000000 +vt 0.437500 -0.000000 0.000000 +vt 0.468750 -0.000000 0.000000 +vt 0.500000 -0.000000 0.000000 +vt 0.531250 -0.000000 0.000000 +vt 0.562500 -0.000000 0.000000 +vt 0.593750 -0.000000 0.000000 +vt 0.625000 -0.000000 0.000000 +vt 0.656250 -0.000000 0.000000 +vt 0.687500 -0.000000 0.000000 +vt 0.718750 -0.000000 0.000000 +vt 0.750000 -0.000000 0.000000 +vt 0.781250 -0.000000 0.000000 +vt 0.812500 -0.000000 0.000000 +vt 0.843750 -0.000000 0.000000 +vt 0.875000 -0.000000 0.000000 +vt 0.906250 -0.000000 0.000000 +vt 0.937500 -0.000000 0.000000 +vt 0.968750 -0.000000 0.000000 +vt 1.000000 -0.000000 0.000000 +# 561 texture vertices + +vn 0.000000 1.000000 -0.000000 +vn -0.005744 0.976740 -0.214348 +vn -0.047451 0.976740 -0.209109 +vn -0.087334 0.976740 -0.195834 +vn -0.123861 0.976740 -0.175033 +vn -0.155629 0.976740 -0.147506 +vn -0.181415 0.976740 -0.114310 +vn -0.200230 0.976740 -0.076721 +vn -0.211350 0.976740 -0.036184 +vn -0.214348 0.976740 0.005744 +vn -0.209109 0.976740 0.047451 +vn -0.195834 0.976740 0.087334 +vn -0.175033 0.976740 0.123861 +vn -0.147506 0.976740 0.155629 +vn -0.114310 0.976740 0.181415 +vn -0.076721 0.976740 0.200230 +vn -0.036184 0.976740 0.211350 +vn 0.005744 0.976740 0.214348 +vn 0.047451 0.976740 0.209109 +vn 0.087334 0.976740 0.195834 +vn 0.123862 0.976740 0.175033 +vn 0.155629 0.976740 0.147505 +vn 0.181415 0.976740 0.114309 +vn 0.200230 0.976740 0.076721 +vn 0.211350 0.976740 0.036184 +vn 0.214348 0.976740 -0.005744 +vn 0.209109 0.976740 -0.047451 +vn 0.195834 0.976740 -0.087334 +vn 0.175033 0.976740 -0.123862 +vn 0.147505 0.976740 -0.155629 +vn 0.114309 0.976740 -0.181415 +vn 0.076721 0.976740 -0.200230 +vn 0.036184 0.976740 -0.211350 +vn -0.002983 0.923888 -0.382651 +vn -0.077577 0.923888 -0.374717 +vn -0.149190 0.923888 -0.352382 +vn -0.215070 0.923888 -0.316506 +vn -0.272685 0.923888 -0.268466 +vn -0.319820 0.923888 -0.210109 +vn -0.354665 0.923888 -0.143678 +vn -0.375881 0.923888 -0.071726 +vn -0.382651 0.923888 0.002983 +vn -0.374717 0.923888 0.077578 +vn -0.352382 0.923888 0.149191 +vn -0.316506 0.923888 0.215070 +vn -0.268466 0.923888 0.272685 +vn -0.210109 0.923888 0.319821 +vn -0.143678 0.923888 0.354666 +vn -0.071725 0.923888 0.375881 +vn 0.002984 0.923888 0.382651 +vn 0.077578 0.923888 0.374717 +vn 0.149191 0.923888 0.352382 +vn 0.215071 0.923888 0.316505 +vn 0.272685 0.923888 0.268466 +vn 0.319821 0.923888 0.210109 +vn 0.354666 0.923888 0.143678 +vn 0.375881 0.923888 0.071725 +vn 0.382651 0.923888 -0.002984 +vn 0.374717 0.923888 -0.077578 +vn 0.352382 0.923888 -0.149191 +vn 0.316505 0.923888 -0.215071 +vn 0.268465 0.923888 -0.272685 +vn 0.210109 0.923888 -0.319821 +vn 0.143678 0.923888 -0.354666 +vn 0.071725 0.923888 -0.375881 +vn -0.002681 0.831490 -0.555533 +vn -0.111008 0.831490 -0.544335 +vn -0.215070 0.831490 -0.512219 +vn -0.310866 0.831490 -0.460419 +vn -0.394716 0.831490 -0.390925 +vn -0.463398 0.831490 -0.306408 +vn -0.514271 0.831490 -0.210116 +vn -0.545381 0.831490 -0.105750 +vn -0.555533 0.831490 0.002681 +vn -0.544335 0.831490 0.111008 +vn -0.512219 0.831490 0.215070 +vn -0.460419 0.831490 0.310867 +vn -0.390925 0.831490 0.394717 +vn -0.306408 0.831490 0.463398 +vn -0.210116 0.831490 0.514271 +vn -0.105749 0.831490 0.545381 +vn 0.002681 0.831490 0.555533 +vn 0.111009 0.831490 0.544335 +vn 0.215070 0.831490 0.512219 +vn 0.310867 0.831490 0.460419 +vn 0.394717 0.831490 0.390925 +vn 0.463398 0.831490 0.306408 +vn 0.514271 0.831490 0.210116 +vn 0.545381 0.831490 0.105749 +vn 0.555533 0.831490 -0.002681 +vn 0.544335 0.831490 -0.111009 +vn 0.512219 0.831490 -0.215071 +vn 0.460419 0.831490 -0.310867 +vn 0.390925 0.831490 -0.394717 +vn 0.306408 0.831490 -0.463398 +vn 0.210115 0.831490 -0.514271 +vn 0.105749 0.831490 -0.545381 +vn -0.002276 0.707138 -0.707072 +vn -0.140175 0.707138 -0.693042 +vn -0.272687 0.707138 -0.652379 +vn -0.394720 0.707138 -0.586645 +vn -0.501585 0.707138 -0.498367 +vn -0.589173 0.707138 -0.390936 +vn -0.654120 0.707138 -0.268482 +vn -0.693930 0.707138 -0.135711 +vn -0.707072 0.707138 0.002276 +vn -0.693042 0.707138 0.140175 +vn -0.652379 0.707138 0.272687 +vn -0.586645 0.707138 0.394721 +vn -0.498366 0.707138 0.501585 +vn -0.390936 0.707138 0.589174 +vn -0.268482 0.707138 0.654121 +vn -0.135711 0.707138 0.693930 +vn 0.002276 0.707138 0.707072 +vn 0.140176 0.707138 0.693042 +vn 0.272688 0.707138 0.652378 +vn 0.394721 0.707138 0.586644 +vn 0.501585 0.707138 0.498366 +vn 0.589174 0.707138 0.390935 +vn 0.654121 0.707138 0.268482 +vn 0.693930 0.707138 0.135710 +vn 0.707072 0.707138 -0.002277 +vn 0.693042 0.707138 -0.140176 +vn 0.652378 0.707138 -0.272688 +vn 0.586644 0.707138 -0.394721 +vn 0.498366 0.707138 -0.501585 +vn 0.390935 0.707138 -0.589174 +vn 0.268481 0.707138 -0.654121 +vn 0.135710 0.707138 -0.693930 +vn -0.001785 0.555605 -0.831445 +vn -0.163957 0.555605 -0.815120 +vn -0.319829 0.555605 -0.767472 +vn -0.463410 0.555605 -0.690329 +vn -0.589182 0.555605 -0.586658 +vn -0.692312 0.555605 -0.460442 +vn -0.768838 0.555605 -0.316531 +vn -0.815817 0.555605 -0.160456 +vn -0.831445 0.555605 0.001785 +vn -0.815120 0.555605 0.163957 +vn -0.767471 0.555605 0.319829 +vn -0.690329 0.555605 0.463410 +vn -0.586658 0.555605 0.589182 +vn -0.460441 0.555605 0.692313 +vn -0.316531 0.555605 0.768838 +vn -0.160456 0.555605 0.815817 +vn 0.001785 0.555605 0.831445 +vn 0.163958 0.555605 0.815120 +vn 0.319830 0.555605 0.767471 +vn 0.463410 0.555605 0.690329 +vn 0.589183 0.555605 0.586657 +vn 0.692313 0.555605 0.460441 +vn 0.768838 0.555605 0.316530 +vn 0.815817 0.555605 0.160455 +vn 0.831445 0.555605 -0.001786 +vn 0.815120 0.555605 -0.163958 +vn 0.767471 0.555605 -0.319830 +vn 0.690329 0.555605 -0.463411 +vn 0.586657 0.555605 -0.589183 +vn 0.460441 0.555605 -0.692313 +vn 0.316530 0.555605 -0.768838 +vn 0.160455 0.555605 -0.815817 +vn -0.001228 0.382713 -0.923866 +vn -0.181441 0.382713 -0.905875 +vn -0.354682 0.382713 -0.853072 +vn -0.514293 0.382713 -0.767485 +vn -0.654140 0.382713 -0.652404 +vn -0.768849 0.382713 -0.512252 +vn -0.854011 0.382713 -0.352414 +vn -0.906354 0.382713 -0.179033 +vn -0.923866 0.382713 0.001228 +vn -0.905875 0.382713 0.181441 +vn -0.853071 0.382713 0.354683 +vn -0.767485 0.382713 0.514294 +vn -0.652404 0.382713 0.654140 +vn -0.512252 0.382713 0.768849 +vn -0.352414 0.382713 0.854011 +vn -0.179033 0.382713 0.906354 +vn 0.001228 0.382713 0.923866 +vn 0.181442 0.382713 0.905875 +vn 0.354683 0.382713 0.853071 +vn 0.514294 0.382713 0.767484 +vn 0.654141 0.382713 0.652403 +vn 0.768849 0.382713 0.512251 +vn 0.854011 0.382713 0.352413 +vn 0.906354 0.382713 0.179032 +vn 0.923866 0.382713 -0.001229 +vn 0.905875 0.382713 -0.181443 +vn 0.853071 0.382713 -0.354684 +vn 0.767484 0.382713 -0.514295 +vn 0.652403 0.382713 -0.654141 +vn 0.512251 0.382713 -0.768850 +vn 0.352413 0.382713 -0.854012 +vn 0.179032 0.382713 -0.906354 +vn -0.000626 0.195108 -0.980782 +vn -0.191954 0.195108 -0.961814 +vn -0.375906 0.195108 -0.905885 +vn -0.545413 0.195108 -0.815143 +vn -0.693959 0.195108 -0.693075 +vn -0.815837 0.195108 -0.544373 +vn -0.906363 0.195108 -0.374751 +vn -0.962058 0.195108 -0.190728 +vn -0.980782 0.195108 0.000625 +vn -0.961814 0.195108 0.191954 +vn -0.905885 0.195108 0.375907 +vn -0.815143 0.195108 0.545413 +vn -0.693075 0.195108 0.693960 +vn -0.544373 0.195108 0.815838 +vn -0.374751 0.195108 0.906364 +vn -0.190727 0.195108 0.962058 +vn 0.000626 0.195108 0.980782 +vn 0.191955 0.195108 0.961814 +vn 0.375907 0.195108 0.905884 +vn 0.545414 0.195108 0.815142 +vn 0.693960 0.195108 0.693075 +vn 0.815838 0.195108 0.544372 +vn 0.906364 0.195108 0.374750 +vn 0.962058 0.195108 0.190727 +vn 0.980782 0.195108 -0.000627 +vn 0.961814 0.195108 -0.191956 +vn 0.905884 0.195108 -0.375908 +vn 0.815142 0.195108 -0.545414 +vn 0.693074 0.195108 -0.693961 +vn 0.544372 0.195108 -0.815839 +vn 0.374750 0.195108 -0.906364 +vn 0.190726 0.195108 -0.962058 +vn -0.000000 -0.000000 -1.000000 +vn -0.195090 -0.000000 -0.980785 +vn -0.382683 0.000000 -0.923880 +vn -0.555570 0.000000 -0.831470 +vn -0.707107 0.000000 -0.707107 +vn -0.831470 0.000000 -0.555570 +vn -0.923880 0.000000 -0.382683 +vn -0.980785 0.000000 -0.195090 +vn -1.000000 0.000000 0.000000 +vn -0.980785 -0.000000 0.195091 +vn -0.923879 0.000000 0.382684 +vn -0.831469 0.000000 0.555571 +vn -0.707106 0.000000 0.707107 +vn -0.555570 0.000000 0.831470 +vn -0.382683 -0.000000 0.923880 +vn -0.195089 0.000000 0.980785 +vn 0.000001 -0.000000 1.000000 +vn 0.195091 0.000000 0.980785 +vn 0.382685 0.000000 0.923879 +vn 0.555571 0.000000 0.831469 +vn 0.707108 0.000000 0.707106 +vn 0.831470 0.000000 0.555569 +vn 0.923880 0.000000 0.382682 +vn 0.980786 0.000000 0.195089 +vn 1.000000 0.000000 -0.000002 +vn 0.980785 -0.000000 -0.195092 +vn 0.923879 0.000000 -0.382685 +vn 0.831469 0.000000 -0.555572 +vn 0.707106 0.000000 -0.707108 +vn 0.555569 0.000000 -0.831471 +vn 0.382681 0.000000 -0.923880 +vn 0.195089 0.000000 -0.980786 +vn 0.000624 -0.195108 -0.980782 +vn -0.190728 -0.195108 -0.962058 +vn -0.374751 -0.195108 -0.906363 +vn -0.544373 -0.195107 -0.815837 +vn -0.693075 -0.195107 -0.693959 +vn -0.815143 -0.195108 -0.545413 +vn -0.905885 -0.195108 -0.375906 +vn -0.961814 -0.195107 -0.191954 +vn -0.980782 -0.195107 -0.000625 +vn -0.962058 -0.195107 0.190728 +vn -0.906363 -0.195107 0.374752 +vn -0.815837 -0.195108 0.544374 +vn -0.693959 -0.195108 0.693076 +vn -0.545412 -0.195107 0.815143 +vn -0.375906 -0.195107 0.905885 +vn -0.191953 -0.195108 0.961814 +vn -0.000624 -0.195107 0.980782 +vn 0.190729 -0.195107 0.962058 +vn 0.374753 -0.195107 0.906363 +vn 0.544374 -0.195107 0.815837 +vn 0.693076 -0.195108 0.693959 +vn 0.815144 -0.195108 0.545412 +vn 0.905885 -0.195108 0.375905 +vn 0.961815 -0.195108 0.191953 +vn 0.980782 -0.195108 0.000623 +vn 0.962058 -0.195107 -0.190730 +vn 0.906363 -0.195108 -0.374753 +vn 0.815836 -0.195107 -0.544375 +vn 0.693958 -0.195107 -0.693077 +vn 0.545411 -0.195108 -0.815144 +vn 0.375904 -0.195107 -0.905886 +vn 0.191953 -0.195107 -0.961815 +vn 0.001227 -0.382713 -0.923866 +vn -0.179034 -0.382713 -0.906354 +vn -0.352414 -0.382713 -0.854011 +vn -0.512252 -0.382713 -0.768849 +vn -0.652404 -0.382713 -0.654140 +vn -0.767485 -0.382713 -0.514293 +vn -0.853072 -0.382713 -0.354682 +vn -0.905875 -0.382713 -0.181441 +vn -0.923866 -0.382713 -0.001227 +vn -0.906354 -0.382713 0.179034 +vn -0.854011 -0.382713 0.352415 +vn -0.768848 -0.382713 0.512253 +vn -0.654140 -0.382713 0.652405 +vn -0.514293 -0.382713 0.767485 +vn -0.354682 -0.382713 0.853072 +vn -0.181440 -0.382713 0.905875 +vn -0.001227 -0.382713 0.923866 +vn 0.179035 -0.382713 0.906354 +vn 0.352415 -0.382713 0.854011 +vn 0.512253 -0.382713 0.768848 +vn 0.652405 -0.382713 0.654139 +vn 0.767486 -0.382713 0.514292 +vn 0.853072 -0.382713 0.354681 +vn 0.905875 -0.382713 0.181440 +vn 0.923866 -0.382713 0.001226 +vn 0.906354 -0.382713 -0.179035 +vn 0.854010 -0.382713 -0.352416 +vn 0.768848 -0.382713 -0.512254 +vn 0.654139 -0.382713 -0.652406 +vn 0.514292 -0.382713 -0.767486 +vn 0.354681 -0.382713 -0.853072 +vn 0.181440 -0.382713 -0.905875 +vn 0.001784 -0.555605 -0.831445 +vn -0.160456 -0.555605 -0.815817 +vn -0.316531 -0.555605 -0.768838 +vn -0.460442 -0.555605 -0.692312 +vn -0.586658 -0.555605 -0.589182 +vn -0.690329 -0.555605 -0.463410 +vn -0.767472 -0.555605 -0.319829 +vn -0.815121 -0.555605 -0.163957 +vn -0.831445 -0.555605 -0.001784 +vn -0.815817 -0.555605 0.160457 +vn -0.768837 -0.555605 0.316532 +vn -0.692312 -0.555605 0.460442 +vn -0.589182 -0.555605 0.586659 +vn -0.463409 -0.555605 0.690330 +vn -0.319828 -0.555605 0.767472 +vn -0.163956 -0.555605 0.815121 +vn -0.001784 -0.555605 0.831445 +vn 0.160457 -0.555605 0.815817 +vn 0.316532 -0.555605 0.768837 +vn 0.460443 -0.555605 0.692312 +vn 0.586659 -0.555605 0.589181 +vn 0.690330 -0.555605 0.463409 +vn 0.767472 -0.555605 0.319828 +vn 0.815121 -0.555605 0.163956 +vn 0.831445 -0.555605 0.001783 +vn 0.815816 -0.555605 -0.160458 +vn 0.768837 -0.555605 -0.316533 +vn 0.692312 -0.555605 -0.460443 +vn 0.589181 -0.555605 -0.586659 +vn 0.463408 -0.555605 -0.690330 +vn 0.319827 -0.555605 -0.767472 +vn 0.163956 -0.555605 -0.815121 +vn 0.002275 -0.707138 -0.707072 +vn -0.135711 -0.707138 -0.693930 +vn -0.268483 -0.707138 -0.654120 +vn -0.390936 -0.707138 -0.589173 +vn -0.498367 -0.707138 -0.501585 +vn -0.586645 -0.707138 -0.394720 +vn -0.652379 -0.707138 -0.272687 +vn -0.693042 -0.707138 -0.140175 +vn -0.707072 -0.707138 -0.002275 +vn -0.693930 -0.707138 0.135711 +vn -0.654120 -0.707138 0.268483 +vn -0.589173 -0.707138 0.390936 +vn -0.501584 -0.707138 0.498367 +vn -0.394720 -0.707138 0.586645 +vn -0.272687 -0.707138 0.652379 +vn -0.140174 -0.707138 0.693042 +vn -0.002275 -0.707138 0.707072 +vn 0.135712 -0.707138 0.693930 +vn 0.268483 -0.707138 0.654120 +vn 0.390937 -0.707138 0.589173 +vn 0.498367 -0.707138 0.501584 +vn 0.586645 -0.707138 0.394719 +vn 0.652379 -0.707138 0.272686 +vn 0.693042 -0.707138 0.140174 +vn 0.707072 -0.707138 0.002274 +vn 0.693930 -0.707138 -0.135712 +vn 0.654120 -0.707138 -0.268484 +vn 0.589173 -0.707138 -0.390937 +vn 0.501584 -0.707138 -0.498367 +vn 0.394719 -0.707138 -0.586646 +vn 0.272686 -0.707138 -0.652379 +vn 0.140174 -0.707138 -0.693042 +vn 0.002680 -0.831490 -0.555533 +vn -0.105750 -0.831490 -0.545381 +vn -0.210117 -0.831490 -0.514271 +vn -0.306408 -0.831490 -0.463398 +vn -0.390925 -0.831490 -0.394716 +vn -0.460419 -0.831490 -0.310866 +vn -0.512219 -0.831490 -0.215070 +vn -0.544335 -0.831490 -0.111008 +vn -0.555533 -0.831490 -0.002680 +vn -0.545381 -0.831490 0.105750 +vn -0.514271 -0.831490 0.210117 +vn -0.463398 -0.831490 0.306409 +vn -0.394716 -0.831490 0.390926 +vn -0.310866 -0.831490 0.460419 +vn -0.215069 -0.831491 0.512219 +vn -0.111008 -0.831490 0.544335 +vn -0.002680 -0.831490 0.555533 +vn 0.105750 -0.831490 0.545381 +vn 0.210117 -0.831490 0.514271 +vn 0.306409 -0.831490 0.463397 +vn 0.390926 -0.831490 0.394716 +vn 0.460420 -0.831490 0.310866 +vn 0.512220 -0.831490 0.215069 +vn 0.544335 -0.831490 0.111007 +vn 0.555533 -0.831490 0.002680 +vn 0.545381 -0.831490 -0.105751 +vn 0.514271 -0.831490 -0.210117 +vn 0.463397 -0.831491 -0.306409 +vn 0.394716 -0.831491 -0.390926 +vn 0.310865 -0.831490 -0.460420 +vn 0.215069 -0.831490 -0.512220 +vn 0.111007 -0.831490 -0.544335 +vn 0.002983 -0.923888 -0.382651 +vn -0.071726 -0.923888 -0.375880 +vn -0.143678 -0.923888 -0.354665 +vn -0.210109 -0.923888 -0.319820 +vn -0.268466 -0.923888 -0.272685 +vn -0.316505 -0.923888 -0.215070 +vn -0.352382 -0.923888 -0.149190 +vn -0.374717 -0.923888 -0.077577 +vn -0.382651 -0.923888 -0.002983 +vn -0.375880 -0.923888 0.071726 +vn -0.354665 -0.923888 0.143678 +vn -0.319820 -0.923888 0.210109 +vn -0.272684 -0.923888 0.268466 +vn -0.215070 -0.923888 0.316506 +vn -0.149190 -0.923888 0.352382 +vn -0.077577 -0.923888 0.374717 +vn -0.002983 -0.923888 0.382651 +vn 0.071726 -0.923888 0.375880 +vn 0.143679 -0.923888 0.354665 +vn 0.210109 -0.923888 0.319820 +vn 0.268466 -0.923888 0.272684 +vn 0.316506 -0.923888 0.215069 +vn 0.352382 -0.923888 0.149190 +vn 0.374717 -0.923888 0.077577 +vn 0.382651 -0.923888 0.002983 +vn 0.375880 -0.923888 -0.071726 +vn 0.354665 -0.923888 -0.143679 +vn 0.319820 -0.923888 -0.210110 +vn 0.272684 -0.923888 -0.268466 +vn 0.215069 -0.923888 -0.316506 +vn 0.149190 -0.923888 -0.352382 +vn 0.077577 -0.923888 -0.374717 +vn 0.005744 -0.976740 -0.214348 +vn -0.036184 -0.976740 -0.211350 +vn -0.076721 -0.976740 -0.200230 +vn -0.114310 -0.976740 -0.181415 +vn -0.147505 -0.976740 -0.155628 +vn -0.175033 -0.976740 -0.123861 +vn -0.195834 -0.976740 -0.087334 +vn -0.209109 -0.976740 -0.047451 +vn -0.214348 -0.976740 -0.005744 +vn -0.211350 -0.976740 0.036184 +vn -0.200230 -0.976740 0.076721 +vn -0.181415 -0.976740 0.114310 +vn -0.155628 -0.976740 0.147506 +vn -0.123861 -0.976740 0.175033 +vn -0.087334 -0.976740 0.195834 +vn -0.047450 -0.976740 0.209109 +vn -0.005744 -0.976740 0.214348 +vn 0.036184 -0.976740 0.211350 +vn 0.076721 -0.976740 0.200230 +vn 0.114310 -0.976740 0.181415 +vn 0.147506 -0.976740 0.155628 +vn 0.175033 -0.976740 0.123861 +vn 0.195834 -0.976740 0.087334 +vn 0.209109 -0.976740 0.047450 +vn 0.214348 -0.976740 0.005743 +vn 0.211350 -0.976740 -0.036184 +vn 0.200230 -0.976740 -0.076721 +vn 0.181415 -0.976740 -0.114310 +vn 0.155628 -0.976740 -0.147506 +vn 0.123861 -0.976740 -0.175033 +vn 0.087334 -0.976740 -0.195834 +vn 0.047450 -0.976740 -0.209109 +vn 0.000000 -1.000000 -0.000000 +# 482 vertex normals + +f 1/1/1 2/34/2 3/35/3 +f 1/2/1 3/35/3 4/36/4 +f 1/3/1 4/36/4 5/37/5 +f 1/4/1 5/37/5 6/38/6 +f 1/5/1 6/38/6 7/39/7 +f 1/6/1 7/39/7 8/40/8 +f 1/7/1 8/40/8 9/41/9 +f 1/8/1 9/41/9 10/42/10 +f 1/9/1 10/42/10 11/43/11 +f 1/10/1 11/43/11 12/44/12 +f 1/11/1 12/44/12 13/45/13 +f 1/12/1 13/45/13 14/46/14 +f 1/13/1 14/46/14 15/47/15 +f 1/14/1 15/47/15 16/48/16 +f 1/15/1 16/48/16 17/49/17 +f 1/16/1 17/49/17 18/50/18 +f 1/17/1 18/50/18 19/51/19 +f 1/18/1 19/51/19 20/52/20 +f 1/19/1 20/52/20 21/53/21 +f 1/20/1 21/53/21 22/54/22 +f 1/21/1 22/54/22 23/55/23 +f 1/22/1 23/55/23 24/56/24 +f 1/23/1 24/56/24 25/57/25 +f 1/24/1 25/57/25 26/58/26 +f 1/25/1 26/58/26 27/59/27 +f 1/26/1 27/59/27 28/60/28 +f 1/27/1 28/60/28 29/61/29 +f 1/28/1 29/61/29 30/62/30 +f 1/29/1 30/62/30 31/63/31 +f 1/30/1 31/63/31 32/64/32 +f 1/31/1 32/64/32 33/65/33 +f 1/32/1 33/65/33 2/66/2 +f 2/34/2 34/67/34 35/68/35 +f 2/34/2 35/68/35 3/35/3 +f 3/35/3 35/68/35 36/69/36 +f 3/35/3 36/69/36 4/36/4 +f 4/36/4 36/69/36 37/70/37 +f 4/36/4 37/70/37 5/37/5 +f 5/37/5 37/70/37 38/71/38 +f 5/37/5 38/71/38 6/38/6 +f 6/38/6 38/71/38 39/72/39 +f 6/38/6 39/72/39 7/39/7 +f 7/39/7 39/72/39 40/73/40 +f 7/39/7 40/73/40 8/40/8 +f 8/40/8 40/73/40 41/74/41 +f 8/40/8 41/74/41 9/41/9 +f 9/41/9 41/74/41 42/75/42 +f 9/41/9 42/75/42 10/42/10 +f 10/42/10 42/75/42 43/76/43 +f 10/42/10 43/76/43 11/43/11 +f 11/43/11 43/76/43 44/77/44 +f 11/43/11 44/77/44 12/44/12 +f 12/44/12 44/77/44 45/78/45 +f 12/44/12 45/78/45 13/45/13 +f 13/45/13 45/78/45 46/79/46 +f 13/45/13 46/79/46 14/46/14 +f 14/46/14 46/79/46 47/80/47 +f 14/46/14 47/80/47 15/47/15 +f 15/47/15 47/80/47 48/81/48 +f 15/47/15 48/81/48 16/48/16 +f 16/48/16 48/81/48 49/82/49 +f 16/48/16 49/82/49 17/49/17 +f 17/49/17 49/82/49 50/83/50 +f 17/49/17 50/83/50 18/50/18 +f 18/50/18 50/83/50 51/84/51 +f 18/50/18 51/84/51 19/51/19 +f 19/51/19 51/84/51 52/85/52 +f 19/51/19 52/85/52 20/52/20 +f 20/52/20 52/85/52 53/86/53 +f 20/52/20 53/86/53 21/53/21 +f 21/53/21 53/86/53 54/87/54 +f 21/53/21 54/87/54 22/54/22 +f 22/54/22 54/87/54 55/88/55 +f 22/54/22 55/88/55 23/55/23 +f 23/55/23 55/88/55 56/89/56 +f 23/55/23 56/89/56 24/56/24 +f 24/56/24 56/89/56 57/90/57 +f 24/56/24 57/90/57 25/57/25 +f 25/57/25 57/90/57 58/91/58 +f 25/57/25 58/91/58 26/58/26 +f 26/58/26 58/91/58 59/92/59 +f 26/58/26 59/92/59 27/59/27 +f 27/59/27 59/92/59 60/93/60 +f 27/59/27 60/93/60 28/60/28 +f 28/60/28 60/93/60 61/94/61 +f 28/60/28 61/94/61 29/61/29 +f 29/61/29 61/94/61 62/95/62 +f 29/61/29 62/95/62 30/62/30 +f 30/62/30 62/95/62 63/96/63 +f 30/62/30 63/96/63 31/63/31 +f 31/63/31 63/96/63 64/97/64 +f 31/63/31 64/97/64 32/64/32 +f 32/64/32 64/97/64 65/98/65 +f 32/64/32 65/98/65 33/65/33 +f 33/65/33 65/98/65 34/99/34 +f 33/65/33 34/99/34 2/66/2 +f 34/67/34 66/100/66 67/101/67 +f 34/67/34 67/101/67 35/68/35 +f 35/68/35 67/101/67 68/102/68 +f 35/68/35 68/102/68 36/69/36 +f 36/69/36 68/102/68 69/103/69 +f 36/69/36 69/103/69 37/70/37 +f 37/70/37 69/103/69 70/104/70 +f 37/70/37 70/104/70 38/71/38 +f 38/71/38 70/104/70 71/105/71 +f 38/71/38 71/105/71 39/72/39 +f 39/72/39 71/105/71 72/106/72 +f 39/72/39 72/106/72 40/73/40 +f 40/73/40 72/106/72 73/107/73 +f 40/73/40 73/107/73 41/74/41 +f 41/74/41 73/107/73 74/108/74 +f 41/74/41 74/108/74 42/75/42 +f 42/75/42 74/108/74 75/109/75 +f 42/75/42 75/109/75 43/76/43 +f 43/76/43 75/109/75 76/110/76 +f 43/76/43 76/110/76 44/77/44 +f 44/77/44 76/110/76 77/111/77 +f 44/77/44 77/111/77 45/78/45 +f 45/78/45 77/111/77 78/112/78 +f 45/78/45 78/112/78 46/79/46 +f 46/79/46 78/112/78 79/113/79 +f 46/79/46 79/113/79 47/80/47 +f 47/80/47 79/113/79 80/114/80 +f 47/80/47 80/114/80 48/81/48 +f 48/81/48 80/114/80 81/115/81 +f 48/81/48 81/115/81 49/82/49 +f 49/82/49 81/115/81 82/116/82 +f 49/82/49 82/116/82 50/83/50 +f 50/83/50 82/116/82 83/117/83 +f 50/83/50 83/117/83 51/84/51 +f 51/84/51 83/117/83 84/118/84 +f 51/84/51 84/118/84 52/85/52 +f 52/85/52 84/118/84 85/119/85 +f 52/85/52 85/119/85 53/86/53 +f 53/86/53 85/119/85 86/120/86 +f 53/86/53 86/120/86 54/87/54 +f 54/87/54 86/120/86 87/121/87 +f 54/87/54 87/121/87 55/88/55 +f 55/88/55 87/121/87 88/122/88 +f 55/88/55 88/122/88 56/89/56 +f 56/89/56 88/122/88 89/123/89 +f 56/89/56 89/123/89 57/90/57 +f 57/90/57 89/123/89 90/124/90 +f 57/90/57 90/124/90 58/91/58 +f 58/91/58 90/124/90 91/125/91 +f 58/91/58 91/125/91 59/92/59 +f 59/92/59 91/125/91 92/126/92 +f 59/92/59 92/126/92 60/93/60 +f 60/93/60 92/126/92 93/127/93 +f 60/93/60 93/127/93 61/94/61 +f 61/94/61 93/127/93 94/128/94 +f 61/94/61 94/128/94 62/95/62 +f 62/95/62 94/128/94 95/129/95 +f 62/95/62 95/129/95 63/96/63 +f 63/96/63 95/129/95 96/130/96 +f 63/96/63 96/130/96 64/97/64 +f 64/97/64 96/130/96 97/131/97 +f 64/97/64 97/131/97 65/98/65 +f 65/98/65 97/131/97 66/132/66 +f 65/98/65 66/132/66 34/99/34 +f 66/100/66 98/133/98 99/134/99 +f 66/100/66 99/134/99 67/101/67 +f 67/101/67 99/134/99 100/135/100 +f 67/101/67 100/135/100 68/102/68 +f 68/102/68 100/135/100 101/136/101 +f 68/102/68 101/136/101 69/103/69 +f 69/103/69 101/136/101 102/137/102 +f 69/103/69 102/137/102 70/104/70 +f 70/104/70 102/137/102 103/138/103 +f 70/104/70 103/138/103 71/105/71 +f 71/105/71 103/138/103 104/139/104 +f 71/105/71 104/139/104 72/106/72 +f 72/106/72 104/139/104 105/140/105 +f 72/106/72 105/140/105 73/107/73 +f 73/107/73 105/140/105 106/141/106 +f 73/107/73 106/141/106 74/108/74 +f 74/108/74 106/141/106 107/142/107 +f 74/108/74 107/142/107 75/109/75 +f 75/109/75 107/142/107 108/143/108 +f 75/109/75 108/143/108 76/110/76 +f 76/110/76 108/143/108 109/144/109 +f 76/110/76 109/144/109 77/111/77 +f 77/111/77 109/144/109 110/145/110 +f 77/111/77 110/145/110 78/112/78 +f 78/112/78 110/145/110 111/146/111 +f 78/112/78 111/146/111 79/113/79 +f 79/113/79 111/146/111 112/147/112 +f 79/113/79 112/147/112 80/114/80 +f 80/114/80 112/147/112 113/148/113 +f 80/114/80 113/148/113 81/115/81 +f 81/115/81 113/148/113 114/149/114 +f 81/115/81 114/149/114 82/116/82 +f 82/116/82 114/149/114 115/150/115 +f 82/116/82 115/150/115 83/117/83 +f 83/117/83 115/150/115 116/151/116 +f 83/117/83 116/151/116 84/118/84 +f 84/118/84 116/151/116 117/152/117 +f 84/118/84 117/152/117 85/119/85 +f 85/119/85 117/152/117 118/153/118 +f 85/119/85 118/153/118 86/120/86 +f 86/120/86 118/153/118 119/154/119 +f 86/120/86 119/154/119 87/121/87 +f 87/121/87 119/154/119 120/155/120 +f 87/121/87 120/155/120 88/122/88 +f 88/122/88 120/155/120 121/156/121 +f 88/122/88 121/156/121 89/123/89 +f 89/123/89 121/156/121 122/157/122 +f 89/123/89 122/157/122 90/124/90 +f 90/124/90 122/157/122 123/158/123 +f 90/124/90 123/158/123 91/125/91 +f 91/125/91 123/158/123 124/159/124 +f 91/125/91 124/159/124 92/126/92 +f 92/126/92 124/159/124 125/160/125 +f 92/126/92 125/160/125 93/127/93 +f 93/127/93 125/160/125 126/161/126 +f 93/127/93 126/161/126 94/128/94 +f 94/128/94 126/161/126 127/162/127 +f 94/128/94 127/162/127 95/129/95 +f 95/129/95 127/162/127 128/163/128 +f 95/129/95 128/163/128 96/130/96 +f 96/130/96 128/163/128 129/164/129 +f 96/130/96 129/164/129 97/131/97 +f 97/131/97 129/164/129 98/165/98 +f 97/131/97 98/165/98 66/132/66 +f 98/133/98 130/166/130 131/167/131 +f 98/133/98 131/167/131 99/134/99 +f 99/134/99 131/167/131 132/168/132 +f 99/134/99 132/168/132 100/135/100 +f 100/135/100 132/168/132 133/169/133 +f 100/135/100 133/169/133 101/136/101 +f 101/136/101 133/169/133 134/170/134 +f 101/136/101 134/170/134 102/137/102 +f 102/137/102 134/170/134 135/171/135 +f 102/137/102 135/171/135 103/138/103 +f 103/138/103 135/171/135 136/172/136 +f 103/138/103 136/172/136 104/139/104 +f 104/139/104 136/172/136 137/173/137 +f 104/139/104 137/173/137 105/140/105 +f 105/140/105 137/173/137 138/174/138 +f 105/140/105 138/174/138 106/141/106 +f 106/141/106 138/174/138 139/175/139 +f 106/141/106 139/175/139 107/142/107 +f 107/142/107 139/175/139 140/176/140 +f 107/142/107 140/176/140 108/143/108 +f 108/143/108 140/176/140 141/177/141 +f 108/143/108 141/177/141 109/144/109 +f 109/144/109 141/177/141 142/178/142 +f 109/144/109 142/178/142 110/145/110 +f 110/145/110 142/178/142 143/179/143 +f 110/145/110 143/179/143 111/146/111 +f 111/146/111 143/179/143 144/180/144 +f 111/146/111 144/180/144 112/147/112 +f 112/147/112 144/180/144 145/181/145 +f 112/147/112 145/181/145 113/148/113 +f 113/148/113 145/181/145 146/182/146 +f 113/148/113 146/182/146 114/149/114 +f 114/149/114 146/182/146 147/183/147 +f 114/149/114 147/183/147 115/150/115 +f 115/150/115 147/183/147 148/184/148 +f 115/150/115 148/184/148 116/151/116 +f 116/151/116 148/184/148 149/185/149 +f 116/151/116 149/185/149 117/152/117 +f 117/152/117 149/185/149 150/186/150 +f 117/152/117 150/186/150 118/153/118 +f 118/153/118 150/186/150 151/187/151 +f 118/153/118 151/187/151 119/154/119 +f 119/154/119 151/187/151 152/188/152 +f 119/154/119 152/188/152 120/155/120 +f 120/155/120 152/188/152 153/189/153 +f 120/155/120 153/189/153 121/156/121 +f 121/156/121 153/189/153 154/190/154 +f 121/156/121 154/190/154 122/157/122 +f 122/157/122 154/190/154 155/191/155 +f 122/157/122 155/191/155 123/158/123 +f 123/158/123 155/191/155 156/192/156 +f 123/158/123 156/192/156 124/159/124 +f 124/159/124 156/192/156 157/193/157 +f 124/159/124 157/193/157 125/160/125 +f 125/160/125 157/193/157 158/194/158 +f 125/160/125 158/194/158 126/161/126 +f 126/161/126 158/194/158 159/195/159 +f 126/161/126 159/195/159 127/162/127 +f 127/162/127 159/195/159 160/196/160 +f 127/162/127 160/196/160 128/163/128 +f 128/163/128 160/196/160 161/197/161 +f 128/163/128 161/197/161 129/164/129 +f 129/164/129 161/197/161 130/198/130 +f 129/164/129 130/198/130 98/165/98 +f 130/166/130 162/199/162 163/200/163 +f 130/166/130 163/200/163 131/167/131 +f 131/167/131 163/200/163 164/201/164 +f 131/167/131 164/201/164 132/168/132 +f 132/168/132 164/201/164 165/202/165 +f 132/168/132 165/202/165 133/169/133 +f 133/169/133 165/202/165 166/203/166 +f 133/169/133 166/203/166 134/170/134 +f 134/170/134 166/203/166 167/204/167 +f 134/170/134 167/204/167 135/171/135 +f 135/171/135 167/204/167 168/205/168 +f 135/171/135 168/205/168 136/172/136 +f 136/172/136 168/205/168 169/206/169 +f 136/172/136 169/206/169 137/173/137 +f 137/173/137 169/206/169 170/207/170 +f 137/173/137 170/207/170 138/174/138 +f 138/174/138 170/207/170 171/208/171 +f 138/174/138 171/208/171 139/175/139 +f 139/175/139 171/208/171 172/209/172 +f 139/175/139 172/209/172 140/176/140 +f 140/176/140 172/209/172 173/210/173 +f 140/176/140 173/210/173 141/177/141 +f 141/177/141 173/210/173 174/211/174 +f 141/177/141 174/211/174 142/178/142 +f 142/178/142 174/211/174 175/212/175 +f 142/178/142 175/212/175 143/179/143 +f 143/179/143 175/212/175 176/213/176 +f 143/179/143 176/213/176 144/180/144 +f 144/180/144 176/213/176 177/214/177 +f 144/180/144 177/214/177 145/181/145 +f 145/181/145 177/214/177 178/215/178 +f 145/181/145 178/215/178 146/182/146 +f 146/182/146 178/215/178 179/216/179 +f 146/182/146 179/216/179 147/183/147 +f 147/183/147 179/216/179 180/217/180 +f 147/183/147 180/217/180 148/184/148 +f 148/184/148 180/217/180 181/218/181 +f 148/184/148 181/218/181 149/185/149 +f 149/185/149 181/218/181 182/219/182 +f 149/185/149 182/219/182 150/186/150 +f 150/186/150 182/219/182 183/220/183 +f 150/186/150 183/220/183 151/187/151 +f 151/187/151 183/220/183 184/221/184 +f 151/187/151 184/221/184 152/188/152 +f 152/188/152 184/221/184 185/222/185 +f 152/188/152 185/222/185 153/189/153 +f 153/189/153 185/222/185 186/223/186 +f 153/189/153 186/223/186 154/190/154 +f 154/190/154 186/223/186 187/224/187 +f 154/190/154 187/224/187 155/191/155 +f 155/191/155 187/224/187 188/225/188 +f 155/191/155 188/225/188 156/192/156 +f 156/192/156 188/225/188 189/226/189 +f 156/192/156 189/226/189 157/193/157 +f 157/193/157 189/226/189 190/227/190 +f 157/193/157 190/227/190 158/194/158 +f 158/194/158 190/227/190 191/228/191 +f 158/194/158 191/228/191 159/195/159 +f 159/195/159 191/228/191 192/229/192 +f 159/195/159 192/229/192 160/196/160 +f 160/196/160 192/229/192 193/230/193 +f 160/196/160 193/230/193 161/197/161 +f 161/197/161 193/230/193 162/231/162 +f 161/197/161 162/231/162 130/198/130 +f 162/199/162 194/232/194 195/233/195 +f 162/199/162 195/233/195 163/200/163 +f 163/200/163 195/233/195 196/234/196 +f 163/200/163 196/234/196 164/201/164 +f 164/201/164 196/234/196 197/235/197 +f 164/201/164 197/235/197 165/202/165 +f 165/202/165 197/235/197 198/236/198 +f 165/202/165 198/236/198 166/203/166 +f 166/203/166 198/236/198 199/237/199 +f 166/203/166 199/237/199 167/204/167 +f 167/204/167 199/237/199 200/238/200 +f 167/204/167 200/238/200 168/205/168 +f 168/205/168 200/238/200 201/239/201 +f 168/205/168 201/239/201 169/206/169 +f 169/206/169 201/239/201 202/240/202 +f 169/206/169 202/240/202 170/207/170 +f 170/207/170 202/240/202 203/241/203 +f 170/207/170 203/241/203 171/208/171 +f 171/208/171 203/241/203 204/242/204 +f 171/208/171 204/242/204 172/209/172 +f 172/209/172 204/242/204 205/243/205 +f 172/209/172 205/243/205 173/210/173 +f 173/210/173 205/243/205 206/244/206 +f 173/210/173 206/244/206 174/211/174 +f 174/211/174 206/244/206 207/245/207 +f 174/211/174 207/245/207 175/212/175 +f 175/212/175 207/245/207 208/246/208 +f 175/212/175 208/246/208 176/213/176 +f 176/213/176 208/246/208 209/247/209 +f 176/213/176 209/247/209 177/214/177 +f 177/214/177 209/247/209 210/248/210 +f 177/214/177 210/248/210 178/215/178 +f 178/215/178 210/248/210 211/249/211 +f 178/215/178 211/249/211 179/216/179 +f 179/216/179 211/249/211 212/250/212 +f 179/216/179 212/250/212 180/217/180 +f 180/217/180 212/250/212 213/251/213 +f 180/217/180 213/251/213 181/218/181 +f 181/218/181 213/251/213 214/252/214 +f 181/218/181 214/252/214 182/219/182 +f 182/219/182 214/252/214 215/253/215 +f 182/219/182 215/253/215 183/220/183 +f 183/220/183 215/253/215 216/254/216 +f 183/220/183 216/254/216 184/221/184 +f 184/221/184 216/254/216 217/255/217 +f 184/221/184 217/255/217 185/222/185 +f 185/222/185 217/255/217 218/256/218 +f 185/222/185 218/256/218 186/223/186 +f 186/223/186 218/256/218 219/257/219 +f 186/223/186 219/257/219 187/224/187 +f 187/224/187 219/257/219 220/258/220 +f 187/224/187 220/258/220 188/225/188 +f 188/225/188 220/258/220 221/259/221 +f 188/225/188 221/259/221 189/226/189 +f 189/226/189 221/259/221 222/260/222 +f 189/226/189 222/260/222 190/227/190 +f 190/227/190 222/260/222 223/261/223 +f 190/227/190 223/261/223 191/228/191 +f 191/228/191 223/261/223 224/262/224 +f 191/228/191 224/262/224 192/229/192 +f 192/229/192 224/262/224 225/263/225 +f 192/229/192 225/263/225 193/230/193 +f 193/230/193 225/263/225 194/264/194 +f 193/230/193 194/264/194 162/231/162 +f 194/232/194 226/265/226 227/266/227 +f 194/232/194 227/266/227 195/233/195 +f 195/233/195 227/266/227 228/267/228 +f 195/233/195 228/267/228 196/234/196 +f 196/234/196 228/267/228 229/268/229 +f 196/234/196 229/268/229 197/235/197 +f 197/235/197 229/268/229 230/269/230 +f 197/235/197 230/269/230 198/236/198 +f 198/236/198 230/269/230 231/270/231 +f 198/236/198 231/270/231 199/237/199 +f 199/237/199 231/270/231 232/271/232 +f 199/237/199 232/271/232 200/238/200 +f 200/238/200 232/271/232 233/272/233 +f 200/238/200 233/272/233 201/239/201 +f 201/239/201 233/272/233 234/273/234 +f 201/239/201 234/273/234 202/240/202 +f 202/240/202 234/273/234 235/274/235 +f 202/240/202 235/274/235 203/241/203 +f 203/241/203 235/274/235 236/275/236 +f 203/241/203 236/275/236 204/242/204 +f 204/242/204 236/275/236 237/276/237 +f 204/242/204 237/276/237 205/243/205 +f 205/243/205 237/276/237 238/277/238 +f 205/243/205 238/277/238 206/244/206 +f 206/244/206 238/277/238 239/278/239 +f 206/244/206 239/278/239 207/245/207 +f 207/245/207 239/278/239 240/279/240 +f 207/245/207 240/279/240 208/246/208 +f 208/246/208 240/279/240 241/280/241 +f 208/246/208 241/280/241 209/247/209 +f 209/247/209 241/280/241 242/281/242 +f 209/247/209 242/281/242 210/248/210 +f 210/248/210 242/281/242 243/282/243 +f 210/248/210 243/282/243 211/249/211 +f 211/249/211 243/282/243 244/283/244 +f 211/249/211 244/283/244 212/250/212 +f 212/250/212 244/283/244 245/284/245 +f 212/250/212 245/284/245 213/251/213 +f 213/251/213 245/284/245 246/285/246 +f 213/251/213 246/285/246 214/252/214 +f 214/252/214 246/285/246 247/286/247 +f 214/252/214 247/286/247 215/253/215 +f 215/253/215 247/286/247 248/287/248 +f 215/253/215 248/287/248 216/254/216 +f 216/254/216 248/287/248 249/288/249 +f 216/254/216 249/288/249 217/255/217 +f 217/255/217 249/288/249 250/289/250 +f 217/255/217 250/289/250 218/256/218 +f 218/256/218 250/289/250 251/290/251 +f 218/256/218 251/290/251 219/257/219 +f 219/257/219 251/290/251 252/291/252 +f 219/257/219 252/291/252 220/258/220 +f 220/258/220 252/291/252 253/292/253 +f 220/258/220 253/292/253 221/259/221 +f 221/259/221 253/292/253 254/293/254 +f 221/259/221 254/293/254 222/260/222 +f 222/260/222 254/293/254 255/294/255 +f 222/260/222 255/294/255 223/261/223 +f 223/261/223 255/294/255 256/295/256 +f 223/261/223 256/295/256 224/262/224 +f 224/262/224 256/295/256 257/296/257 +f 224/262/224 257/296/257 225/263/225 +f 225/263/225 257/296/257 226/297/226 +f 225/263/225 226/297/226 194/264/194 +f 226/265/226 258/298/258 259/299/259 +f 226/265/226 259/299/259 227/266/227 +f 227/266/227 259/299/259 260/300/260 +f 227/266/227 260/300/260 228/267/228 +f 228/267/228 260/300/260 261/301/261 +f 228/267/228 261/301/261 229/268/229 +f 229/268/229 261/301/261 262/302/262 +f 229/268/229 262/302/262 230/269/230 +f 230/269/230 262/302/262 263/303/263 +f 230/269/230 263/303/263 231/270/231 +f 231/270/231 263/303/263 264/304/264 +f 231/270/231 264/304/264 232/271/232 +f 232/271/232 264/304/264 265/305/265 +f 232/271/232 265/305/265 233/272/233 +f 233/272/233 265/305/265 266/306/266 +f 233/272/233 266/306/266 234/273/234 +f 234/273/234 266/306/266 267/307/267 +f 234/273/234 267/307/267 235/274/235 +f 235/274/235 267/307/267 268/308/268 +f 235/274/235 268/308/268 236/275/236 +f 236/275/236 268/308/268 269/309/269 +f 236/275/236 269/309/269 237/276/237 +f 237/276/237 269/309/269 270/310/270 +f 237/276/237 270/310/270 238/277/238 +f 238/277/238 270/310/270 271/311/271 +f 238/277/238 271/311/271 239/278/239 +f 239/278/239 271/311/271 272/312/272 +f 239/278/239 272/312/272 240/279/240 +f 240/279/240 272/312/272 273/313/273 +f 240/279/240 273/313/273 241/280/241 +f 241/280/241 273/313/273 274/314/274 +f 241/280/241 274/314/274 242/281/242 +f 242/281/242 274/314/274 275/315/275 +f 242/281/242 275/315/275 243/282/243 +f 243/282/243 275/315/275 276/316/276 +f 243/282/243 276/316/276 244/283/244 +f 244/283/244 276/316/276 277/317/277 +f 244/283/244 277/317/277 245/284/245 +f 245/284/245 277/317/277 278/318/278 +f 245/284/245 278/318/278 246/285/246 +f 246/285/246 278/318/278 279/319/279 +f 246/285/246 279/319/279 247/286/247 +f 247/286/247 279/319/279 280/320/280 +f 247/286/247 280/320/280 248/287/248 +f 248/287/248 280/320/280 281/321/281 +f 248/287/248 281/321/281 249/288/249 +f 249/288/249 281/321/281 282/322/282 +f 249/288/249 282/322/282 250/289/250 +f 250/289/250 282/322/282 283/323/283 +f 250/289/250 283/323/283 251/290/251 +f 251/290/251 283/323/283 284/324/284 +f 251/290/251 284/324/284 252/291/252 +f 252/291/252 284/324/284 285/325/285 +f 252/291/252 285/325/285 253/292/253 +f 253/292/253 285/325/285 286/326/286 +f 253/292/253 286/326/286 254/293/254 +f 254/293/254 286/326/286 287/327/287 +f 254/293/254 287/327/287 255/294/255 +f 255/294/255 287/327/287 288/328/288 +f 255/294/255 288/328/288 256/295/256 +f 256/295/256 288/328/288 289/329/289 +f 256/295/256 289/329/289 257/296/257 +f 257/296/257 289/329/289 258/330/258 +f 257/296/257 258/330/258 226/297/226 +f 258/298/258 290/331/290 291/332/291 +f 258/298/258 291/332/291 259/299/259 +f 259/299/259 291/332/291 292/333/292 +f 259/299/259 292/333/292 260/300/260 +f 260/300/260 292/333/292 293/334/293 +f 260/300/260 293/334/293 261/301/261 +f 261/301/261 293/334/293 294/335/294 +f 261/301/261 294/335/294 262/302/262 +f 262/302/262 294/335/294 295/336/295 +f 262/302/262 295/336/295 263/303/263 +f 263/303/263 295/336/295 296/337/296 +f 263/303/263 296/337/296 264/304/264 +f 264/304/264 296/337/296 297/338/297 +f 264/304/264 297/338/297 265/305/265 +f 265/305/265 297/338/297 298/339/298 +f 265/305/265 298/339/298 266/306/266 +f 266/306/266 298/339/298 299/340/299 +f 266/306/266 299/340/299 267/307/267 +f 267/307/267 299/340/299 300/341/300 +f 267/307/267 300/341/300 268/308/268 +f 268/308/268 300/341/300 301/342/301 +f 268/308/268 301/342/301 269/309/269 +f 269/309/269 301/342/301 302/343/302 +f 269/309/269 302/343/302 270/310/270 +f 270/310/270 302/343/302 303/344/303 +f 270/310/270 303/344/303 271/311/271 +f 271/311/271 303/344/303 304/345/304 +f 271/311/271 304/345/304 272/312/272 +f 272/312/272 304/345/304 305/346/305 +f 272/312/272 305/346/305 273/313/273 +f 273/313/273 305/346/305 306/347/306 +f 273/313/273 306/347/306 274/314/274 +f 274/314/274 306/347/306 307/348/307 +f 274/314/274 307/348/307 275/315/275 +f 275/315/275 307/348/307 308/349/308 +f 275/315/275 308/349/308 276/316/276 +f 276/316/276 308/349/308 309/350/309 +f 276/316/276 309/350/309 277/317/277 +f 277/317/277 309/350/309 310/351/310 +f 277/317/277 310/351/310 278/318/278 +f 278/318/278 310/351/310 311/352/311 +f 278/318/278 311/352/311 279/319/279 +f 279/319/279 311/352/311 312/353/312 +f 279/319/279 312/353/312 280/320/280 +f 280/320/280 312/353/312 313/354/313 +f 280/320/280 313/354/313 281/321/281 +f 281/321/281 313/354/313 314/355/314 +f 281/321/281 314/355/314 282/322/282 +f 282/322/282 314/355/314 315/356/315 +f 282/322/282 315/356/315 283/323/283 +f 283/323/283 315/356/315 316/357/316 +f 283/323/283 316/357/316 284/324/284 +f 284/324/284 316/357/316 317/358/317 +f 284/324/284 317/358/317 285/325/285 +f 285/325/285 317/358/317 318/359/318 +f 285/325/285 318/359/318 286/326/286 +f 286/326/286 318/359/318 319/360/319 +f 286/326/286 319/360/319 287/327/287 +f 287/327/287 319/360/319 320/361/320 +f 287/327/287 320/361/320 288/328/288 +f 288/328/288 320/361/320 321/362/321 +f 288/328/288 321/362/321 289/329/289 +f 289/329/289 321/362/321 290/363/290 +f 289/329/289 290/363/290 258/330/258 +f 290/331/290 322/364/322 323/365/323 +f 290/331/290 323/365/323 291/332/291 +f 291/332/291 323/365/323 324/366/324 +f 291/332/291 324/366/324 292/333/292 +f 292/333/292 324/366/324 325/367/325 +f 292/333/292 325/367/325 293/334/293 +f 293/334/293 325/367/325 326/368/326 +f 293/334/293 326/368/326 294/335/294 +f 294/335/294 326/368/326 327/369/327 +f 294/335/294 327/369/327 295/336/295 +f 295/336/295 327/369/327 328/370/328 +f 295/336/295 328/370/328 296/337/296 +f 296/337/296 328/370/328 329/371/329 +f 296/337/296 329/371/329 297/338/297 +f 297/338/297 329/371/329 330/372/330 +f 297/338/297 330/372/330 298/339/298 +f 298/339/298 330/372/330 331/373/331 +f 298/339/298 331/373/331 299/340/299 +f 299/340/299 331/373/331 332/374/332 +f 299/340/299 332/374/332 300/341/300 +f 300/341/300 332/374/332 333/375/333 +f 300/341/300 333/375/333 301/342/301 +f 301/342/301 333/375/333 334/376/334 +f 301/342/301 334/376/334 302/343/302 +f 302/343/302 334/376/334 335/377/335 +f 302/343/302 335/377/335 303/344/303 +f 303/344/303 335/377/335 336/378/336 +f 303/344/303 336/378/336 304/345/304 +f 304/345/304 336/378/336 337/379/337 +f 304/345/304 337/379/337 305/346/305 +f 305/346/305 337/379/337 338/380/338 +f 305/346/305 338/380/338 306/347/306 +f 306/347/306 338/380/338 339/381/339 +f 306/347/306 339/381/339 307/348/307 +f 307/348/307 339/381/339 340/382/340 +f 307/348/307 340/382/340 308/349/308 +f 308/349/308 340/382/340 341/383/341 +f 308/349/308 341/383/341 309/350/309 +f 309/350/309 341/383/341 342/384/342 +f 309/350/309 342/384/342 310/351/310 +f 310/351/310 342/384/342 343/385/343 +f 310/351/310 343/385/343 311/352/311 +f 311/352/311 343/385/343 344/386/344 +f 311/352/311 344/386/344 312/353/312 +f 312/353/312 344/386/344 345/387/345 +f 312/353/312 345/387/345 313/354/313 +f 313/354/313 345/387/345 346/388/346 +f 313/354/313 346/388/346 314/355/314 +f 314/355/314 346/388/346 347/389/347 +f 314/355/314 347/389/347 315/356/315 +f 315/356/315 347/389/347 348/390/348 +f 315/356/315 348/390/348 316/357/316 +f 316/357/316 348/390/348 349/391/349 +f 316/357/316 349/391/349 317/358/317 +f 317/358/317 349/391/349 350/392/350 +f 317/358/317 350/392/350 318/359/318 +f 318/359/318 350/392/350 351/393/351 +f 318/359/318 351/393/351 319/360/319 +f 319/360/319 351/393/351 352/394/352 +f 319/360/319 352/394/352 320/361/320 +f 320/361/320 352/394/352 353/395/353 +f 320/361/320 353/395/353 321/362/321 +f 321/362/321 353/395/353 322/396/322 +f 321/362/321 322/396/322 290/363/290 +f 322/364/322 354/397/354 355/398/355 +f 322/364/322 355/398/355 323/365/323 +f 323/365/323 355/398/355 356/399/356 +f 323/365/323 356/399/356 324/366/324 +f 324/366/324 356/399/356 357/400/357 +f 324/366/324 357/400/357 325/367/325 +f 325/367/325 357/400/357 358/401/358 +f 325/367/325 358/401/358 326/368/326 +f 326/368/326 358/401/358 359/402/359 +f 326/368/326 359/402/359 327/369/327 +f 327/369/327 359/402/359 360/403/360 +f 327/369/327 360/403/360 328/370/328 +f 328/370/328 360/403/360 361/404/361 +f 328/370/328 361/404/361 329/371/329 +f 329/371/329 361/404/361 362/405/362 +f 329/371/329 362/405/362 330/372/330 +f 330/372/330 362/405/362 363/406/363 +f 330/372/330 363/406/363 331/373/331 +f 331/373/331 363/406/363 364/407/364 +f 331/373/331 364/407/364 332/374/332 +f 332/374/332 364/407/364 365/408/365 +f 332/374/332 365/408/365 333/375/333 +f 333/375/333 365/408/365 366/409/366 +f 333/375/333 366/409/366 334/376/334 +f 334/376/334 366/409/366 367/410/367 +f 334/376/334 367/410/367 335/377/335 +f 335/377/335 367/410/367 368/411/368 +f 335/377/335 368/411/368 336/378/336 +f 336/378/336 368/411/368 369/412/369 +f 336/378/336 369/412/369 337/379/337 +f 337/379/337 369/412/369 370/413/370 +f 337/379/337 370/413/370 338/380/338 +f 338/380/338 370/413/370 371/414/371 +f 338/380/338 371/414/371 339/381/339 +f 339/381/339 371/414/371 372/415/372 +f 339/381/339 372/415/372 340/382/340 +f 340/382/340 372/415/372 373/416/373 +f 340/382/340 373/416/373 341/383/341 +f 341/383/341 373/416/373 374/417/374 +f 341/383/341 374/417/374 342/384/342 +f 342/384/342 374/417/374 375/418/375 +f 342/384/342 375/418/375 343/385/343 +f 343/385/343 375/418/375 376/419/376 +f 343/385/343 376/419/376 344/386/344 +f 344/386/344 376/419/376 377/420/377 +f 344/386/344 377/420/377 345/387/345 +f 345/387/345 377/420/377 378/421/378 +f 345/387/345 378/421/378 346/388/346 +f 346/388/346 378/421/378 379/422/379 +f 346/388/346 379/422/379 347/389/347 +f 347/389/347 379/422/379 380/423/380 +f 347/389/347 380/423/380 348/390/348 +f 348/390/348 380/423/380 381/424/381 +f 348/390/348 381/424/381 349/391/349 +f 349/391/349 381/424/381 382/425/382 +f 349/391/349 382/425/382 350/392/350 +f 350/392/350 382/425/382 383/426/383 +f 350/392/350 383/426/383 351/393/351 +f 351/393/351 383/426/383 384/427/384 +f 351/393/351 384/427/384 352/394/352 +f 352/394/352 384/427/384 385/428/385 +f 352/394/352 385/428/385 353/395/353 +f 353/395/353 385/428/385 354/429/354 +f 353/395/353 354/429/354 322/396/322 +f 354/397/354 386/430/386 387/431/387 +f 354/397/354 387/431/387 355/398/355 +f 355/398/355 387/431/387 388/432/388 +f 355/398/355 388/432/388 356/399/356 +f 356/399/356 388/432/388 389/433/389 +f 356/399/356 389/433/389 357/400/357 +f 357/400/357 389/433/389 390/434/390 +f 357/400/357 390/434/390 358/401/358 +f 358/401/358 390/434/390 391/435/391 +f 358/401/358 391/435/391 359/402/359 +f 359/402/359 391/435/391 392/436/392 +f 359/402/359 392/436/392 360/403/360 +f 360/403/360 392/436/392 393/437/393 +f 360/403/360 393/437/393 361/404/361 +f 361/404/361 393/437/393 394/438/394 +f 361/404/361 394/438/394 362/405/362 +f 362/405/362 394/438/394 395/439/395 +f 362/405/362 395/439/395 363/406/363 +f 363/406/363 395/439/395 396/440/396 +f 363/406/363 396/440/396 364/407/364 +f 364/407/364 396/440/396 397/441/397 +f 364/407/364 397/441/397 365/408/365 +f 365/408/365 397/441/397 398/442/398 +f 365/408/365 398/442/398 366/409/366 +f 366/409/366 398/442/398 399/443/399 +f 366/409/366 399/443/399 367/410/367 +f 367/410/367 399/443/399 400/444/400 +f 367/410/367 400/444/400 368/411/368 +f 368/411/368 400/444/400 401/445/401 +f 368/411/368 401/445/401 369/412/369 +f 369/412/369 401/445/401 402/446/402 +f 369/412/369 402/446/402 370/413/370 +f 370/413/370 402/446/402 403/447/403 +f 370/413/370 403/447/403 371/414/371 +f 371/414/371 403/447/403 404/448/404 +f 371/414/371 404/448/404 372/415/372 +f 372/415/372 404/448/404 405/449/405 +f 372/415/372 405/449/405 373/416/373 +f 373/416/373 405/449/405 406/450/406 +f 373/416/373 406/450/406 374/417/374 +f 374/417/374 406/450/406 407/451/407 +f 374/417/374 407/451/407 375/418/375 +f 375/418/375 407/451/407 408/452/408 +f 375/418/375 408/452/408 376/419/376 +f 376/419/376 408/452/408 409/453/409 +f 376/419/376 409/453/409 377/420/377 +f 377/420/377 409/453/409 410/454/410 +f 377/420/377 410/454/410 378/421/378 +f 378/421/378 410/454/410 411/455/411 +f 378/421/378 411/455/411 379/422/379 +f 379/422/379 411/455/411 412/456/412 +f 379/422/379 412/456/412 380/423/380 +f 380/423/380 412/456/412 413/457/413 +f 380/423/380 413/457/413 381/424/381 +f 381/424/381 413/457/413 414/458/414 +f 381/424/381 414/458/414 382/425/382 +f 382/425/382 414/458/414 415/459/415 +f 382/425/382 415/459/415 383/426/383 +f 383/426/383 415/459/415 416/460/416 +f 383/426/383 416/460/416 384/427/384 +f 384/427/384 416/460/416 417/461/417 +f 384/427/384 417/461/417 385/428/385 +f 385/428/385 417/461/417 386/462/386 +f 385/428/385 386/462/386 354/429/354 +f 386/430/386 418/463/418 419/464/419 +f 386/430/386 419/464/419 387/431/387 +f 387/431/387 419/464/419 420/465/420 +f 387/431/387 420/465/420 388/432/388 +f 388/432/388 420/465/420 421/466/421 +f 388/432/388 421/466/421 389/433/389 +f 389/433/389 421/466/421 422/467/422 +f 389/433/389 422/467/422 390/434/390 +f 390/434/390 422/467/422 423/468/423 +f 390/434/390 423/468/423 391/435/391 +f 391/435/391 423/468/423 424/469/424 +f 391/435/391 424/469/424 392/436/392 +f 392/436/392 424/469/424 425/470/425 +f 392/436/392 425/470/425 393/437/393 +f 393/437/393 425/470/425 426/471/426 +f 393/437/393 426/471/426 394/438/394 +f 394/438/394 426/471/426 427/472/427 +f 394/438/394 427/472/427 395/439/395 +f 395/439/395 427/472/427 428/473/428 +f 395/439/395 428/473/428 396/440/396 +f 396/440/396 428/473/428 429/474/429 +f 396/440/396 429/474/429 397/441/397 +f 397/441/397 429/474/429 430/475/430 +f 397/441/397 430/475/430 398/442/398 +f 398/442/398 430/475/430 431/476/431 +f 398/442/398 431/476/431 399/443/399 +f 399/443/399 431/476/431 432/477/432 +f 399/443/399 432/477/432 400/444/400 +f 400/444/400 432/477/432 433/478/433 +f 400/444/400 433/478/433 401/445/401 +f 401/445/401 433/478/433 434/479/434 +f 401/445/401 434/479/434 402/446/402 +f 402/446/402 434/479/434 435/480/435 +f 402/446/402 435/480/435 403/447/403 +f 403/447/403 435/480/435 436/481/436 +f 403/447/403 436/481/436 404/448/404 +f 404/448/404 436/481/436 437/482/437 +f 404/448/404 437/482/437 405/449/405 +f 405/449/405 437/482/437 438/483/438 +f 405/449/405 438/483/438 406/450/406 +f 406/450/406 438/483/438 439/484/439 +f 406/450/406 439/484/439 407/451/407 +f 407/451/407 439/484/439 440/485/440 +f 407/451/407 440/485/440 408/452/408 +f 408/452/408 440/485/440 441/486/441 +f 408/452/408 441/486/441 409/453/409 +f 409/453/409 441/486/441 442/487/442 +f 409/453/409 442/487/442 410/454/410 +f 410/454/410 442/487/442 443/488/443 +f 410/454/410 443/488/443 411/455/411 +f 411/455/411 443/488/443 444/489/444 +f 411/455/411 444/489/444 412/456/412 +f 412/456/412 444/489/444 445/490/445 +f 412/456/412 445/490/445 413/457/413 +f 413/457/413 445/490/445 446/491/446 +f 413/457/413 446/491/446 414/458/414 +f 414/458/414 446/491/446 447/492/447 +f 414/458/414 447/492/447 415/459/415 +f 415/459/415 447/492/447 448/493/448 +f 415/459/415 448/493/448 416/460/416 +f 416/460/416 448/493/448 449/494/449 +f 416/460/416 449/494/449 417/461/417 +f 417/461/417 449/494/449 418/495/418 +f 417/461/417 418/495/418 386/462/386 +f 418/463/418 450/496/450 451/497/451 +f 418/463/418 451/497/451 419/464/419 +f 419/464/419 451/497/451 452/498/452 +f 419/464/419 452/498/452 420/465/420 +f 420/465/420 452/498/452 453/499/453 +f 420/465/420 453/499/453 421/466/421 +f 421/466/421 453/499/453 454/500/454 +f 421/466/421 454/500/454 422/467/422 +f 422/467/422 454/500/454 455/501/455 +f 422/467/422 455/501/455 423/468/423 +f 423/468/423 455/501/455 456/502/456 +f 423/468/423 456/502/456 424/469/424 +f 424/469/424 456/502/456 457/503/457 +f 424/469/424 457/503/457 425/470/425 +f 425/470/425 457/503/457 458/504/458 +f 425/470/425 458/504/458 426/471/426 +f 426/471/426 458/504/458 459/505/459 +f 426/471/426 459/505/459 427/472/427 +f 427/472/427 459/505/459 460/506/460 +f 427/472/427 460/506/460 428/473/428 +f 428/473/428 460/506/460 461/507/461 +f 428/473/428 461/507/461 429/474/429 +f 429/474/429 461/507/461 462/508/462 +f 429/474/429 462/508/462 430/475/430 +f 430/475/430 462/508/462 463/509/463 +f 430/475/430 463/509/463 431/476/431 +f 431/476/431 463/509/463 464/510/464 +f 431/476/431 464/510/464 432/477/432 +f 432/477/432 464/510/464 465/511/465 +f 432/477/432 465/511/465 433/478/433 +f 433/478/433 465/511/465 466/512/466 +f 433/478/433 466/512/466 434/479/434 +f 434/479/434 466/512/466 467/513/467 +f 434/479/434 467/513/467 435/480/435 +f 435/480/435 467/513/467 468/514/468 +f 435/480/435 468/514/468 436/481/436 +f 436/481/436 468/514/468 469/515/469 +f 436/481/436 469/515/469 437/482/437 +f 437/482/437 469/515/469 470/516/470 +f 437/482/437 470/516/470 438/483/438 +f 438/483/438 470/516/470 471/517/471 +f 438/483/438 471/517/471 439/484/439 +f 439/484/439 471/517/471 472/518/472 +f 439/484/439 472/518/472 440/485/440 +f 440/485/440 472/518/472 473/519/473 +f 440/485/440 473/519/473 441/486/441 +f 441/486/441 473/519/473 474/520/474 +f 441/486/441 474/520/474 442/487/442 +f 442/487/442 474/520/474 475/521/475 +f 442/487/442 475/521/475 443/488/443 +f 443/488/443 475/521/475 476/522/476 +f 443/488/443 476/522/476 444/489/444 +f 444/489/444 476/522/476 477/523/477 +f 444/489/444 477/523/477 445/490/445 +f 445/490/445 477/523/477 478/524/478 +f 445/490/445 478/524/478 446/491/446 +f 446/491/446 478/524/478 479/525/479 +f 446/491/446 479/525/479 447/492/447 +f 447/492/447 479/525/479 480/526/480 +f 447/492/447 480/526/480 448/493/448 +f 448/493/448 480/526/480 481/527/481 +f 448/493/448 481/527/481 449/494/449 +f 449/494/449 481/527/481 450/528/450 +f 449/494/449 450/528/450 418/495/418 +f 482/529/482 451/497/451 450/496/450 +f 482/530/482 452/498/452 451/497/451 +f 482/531/482 453/499/453 452/498/452 +f 482/532/482 454/500/454 453/499/453 +f 482/533/482 455/501/455 454/500/454 +f 482/534/482 456/502/456 455/501/455 +f 482/535/482 457/503/457 456/502/456 +f 482/536/482 458/504/458 457/503/457 +f 482/537/482 459/505/459 458/504/458 +f 482/538/482 460/506/460 459/505/459 +f 482/539/482 461/507/461 460/506/460 +f 482/540/482 462/508/462 461/507/461 +f 482/541/482 463/509/463 462/508/462 +f 482/542/482 464/510/464 463/509/463 +f 482/543/482 465/511/465 464/510/464 +f 482/544/482 466/512/466 465/511/465 +f 482/545/482 467/513/467 466/512/466 +f 482/546/482 468/514/468 467/513/467 +f 482/547/482 469/515/469 468/514/468 +f 482/548/482 470/516/470 469/515/469 +f 482/549/482 471/517/471 470/516/470 +f 482/550/482 472/518/472 471/517/471 +f 482/551/482 473/519/473 472/518/472 +f 482/552/482 474/520/474 473/519/473 +f 482/553/482 475/521/475 474/520/474 +f 482/554/482 476/522/476 475/521/475 +f 482/555/482 477/523/477 476/522/476 +f 482/556/482 478/524/478 477/523/477 +f 482/557/482 479/525/479 478/524/478 +f 482/558/482 480/526/480 479/525/479 +f 482/559/482 481/527/481 480/526/480 +f 482/560/482 450/528/450 481/527/481 +# 960 faces diff --git a/examples/sun_cast.py b/examples/sun_cast.py index b2831bb..2575e17 100644 --- a/examples/sun_cast.py +++ b/examples/sun_cast.py @@ -10,7 +10,7 @@ from hothouse.datasets import PLANTS from hothouse.scene import Scene from hothouse.blaster import OrthographicRayBlaster -from pvlib_model import sun_model +from hothouse.sun_calc import solar_ppfd def get_scene(name): @@ -22,7 +22,7 @@ def get_scene(name): forward = np.array([0.25, 1.0, 0.0], dtype='f4') up = np.array([0.0, 0.0, 1.0], dtype='f4') width = height = 800 - elif name == 'sphere': + elif name in ['sphere', 'sphere_ply']: ground = np.array([0.0, 0.0, -100.0], dtype='f4') fname = os.path.join('data', 'sphere.ply') center = np.array([0.0, -300.0, 0], dtype='f4') @@ -32,6 +32,16 @@ def get_scene(name): # forward = np.array([0.0, 0.0, -1.0], dtype='f4') # up = np.array([0.0, 1.0, 0.0], dtype='f4') width = height = 400 + elif name == 'sphere_obj': + ground = np.array([0.0, 0.0, -20.0], dtype='f4') + fname = os.path.join('data', 'sphere.obj') + center = np.array([0.0, -50.0, 0], dtype='f4') + forward = np.array([0.0, 1.0, 0.0], dtype='f4') + up = np.array([0.0, 0.0, 1.0], dtype='f4') + # center = np.array([0.0, 0.0, 300], dtype='f4') + # forward = np.array([0.0, 0.0, -1.0], dtype='f4') + # up = np.array([0.0, 1.0, 0.0], dtype='f4') + width = height = 80 elif name == 'pyramid': ground = np.array([0.0, 0.0, 0.0], dtype='f4') fname = os.path.join('data', 'pyramid.ply') @@ -42,7 +52,21 @@ def get_scene(name): # forward = np.array([0.0, 1.0, 0.0], dtype='f4') # up = np.array([0.0, 0.0, 1.0], dtype='f4') width = height = 2 - p = hothouse.plant_model.PlantModel.from_ply(fname) + elif name == 'real': + ground = np.array([-0.025391, 5.39746, -0.459961], dtype='f4') + fname = os.path.join('data', '387-js261.obj') + center = np.array([-0.025391, 4.0, -0.095703], dtype='f4') + forward = np.array([0.0, 1.0, 0.0], dtype='f4') + up = np.array([0.0, 0.0, 1.0], dtype='f4') + width = height = 0.75 + if fname.endswith('.ply'): + p = hothouse.plant_model.PlantModel.from_ply( + fname, transmittance=0.075, reflectance=0.075) + elif fname.endswith('.obj'): + p = hothouse.plant_model.PlantModel.from_obj( + fname, transmittance=0.075, reflectance=0.075) + else: + raise ValueError("Unsure how to handle file: '%s'" % fname) scene = Scene(ground=ground) scene.add_component(p) # Camera @@ -57,16 +81,17 @@ def get_scene(name): def plot_light(scene, camera, latitude_deg, longitude_deg, date, - fname="light.png"): + fname="light.png", single_bounce=False): # Solar radiation model including atmosphere - ppfd_tot = sun_model(latitude_deg, longitude_deg, date) # W m-2 + ppfd_tot = solar_ppfd(latitude_deg, longitude_deg, date) # W m-2 # Blaster representing the sun nx = ny = 1024 sun = scene.get_sun_blaster(latitude_deg, longitude_deg, date, nx=nx, ny=ny, direct_ppfd=ppfd_tot['direct'], - diffuse_ppfd=ppfd_tot['diffuse']) + diffuse_ppfd=ppfd_tot['diffuse'], + multibounce=(not single_bounce)) # Compute flux density on scene from sun o = camera.compute_flux_density(scene, sun) @@ -84,17 +109,20 @@ def plot_light(scene, camera, latitude_deg, longitude_deg, date, def iter_plot(scene, camera, latitude, longitude, - t_start, t_stop, n_step): + t_start, t_stop, n_step, single_bounce=False): dates = pd.date_range(t_start, t_stop, periods=n_step) for date in dates: - plot_light(scene, camera, latitude, longitude, date, fname=None) + plot_light(scene, camera, latitude, longitude, date, fname=None, + single_bounce=single_bounce) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('--scene', default='plant', - choices=['plant', 'sphere', 'pyramid']) + choices=['plant', 'sphere', 'sphere_ply', 'sphere_obj', + 'pyramid', 'real']) parser.add_argument('--iterate', action='store_true') + parser.add_argument('--animate', action='store_true') parser.add_argument('--nsteps', default=10, type=int) # These default to the values for Champaign, IL # Sunrise: 2020-06-17 5:23:00 @@ -105,6 +133,7 @@ def iter_plot(scene, camera, latitude, longitude, parser.add_argument('--time', default='2020-06-17 5:23:00') parser.add_argument('--start-time', default='2020-06-17 5:23:00') parser.add_argument('--stop-time', default='2020-06-17 19:25:00') + parser.add_argument('--single-bounce', action='store_true') args = parser.parse_args() scene, camera = get_scene(args.scene) @@ -116,7 +145,13 @@ def iter_plot(scene, camera, latitude, longitude, if args.iterate: iter_plot(scene, camera, args.latitude, args.longitude, - args.start_time, args.stop_time, args.nsteps) + args.start_time, args.stop_time, args.nsteps, + single_bounce=args.single_bounce) + elif args.animate: + scene.animate_sun(camera, args.latitude, args.longitude, + args.start_time, args.stop_time, args.nsteps, + fname='light.html') else: plot_light(scene, camera, args.latitude, args.longitude, - args.time) # , fname=('%s.png' % args.scene)) + args.time, single_bounce=args.single_bounce) + # , fname=('%s.png' % args.scene)) diff --git a/hothouse/blaster.py b/hothouse/blaster.py index e09d69a..3d29032 100644 --- a/hothouse/blaster.py +++ b/hothouse/blaster.py @@ -10,6 +10,7 @@ from .traits_support import check_dtype, check_shape from hothouse import sun_calc +from .ray_callbacks import RayCollisionPrinter, RayCollisionMultiBounce # pyembree receives origins and directions. @@ -25,6 +26,7 @@ class RayBlaster(traitlets.HasTraits): directions = traittypes.Array().valid(check_shape(None, 3), check_dtype("f4")) intensity = traitlets.CFloat(1.0) diffuse_intensity = traitlets.CFloat(0.0) + multibounce = traitlets.CBool(False) @property def ray_intensity(self): @@ -32,12 +34,22 @@ def ray_intensity(self): return self.intensity / self.origins.shape[0] def cast_once(self, scene, verbose_output=False, query_type=QueryType.DISTANCE): + if self.multibounce: + callback_handler = RayCollisionMultiBounce( + self.origins.shape[0], 10, + [c.transmittance for c in scene.components], + [c.reflectance for c in scene.components]) + else: + callback_handler = None output = scene.embree_scene.run( self.origins, self.directions, query=query_type._value_, output=verbose_output, + callback_handler=callback_handler ) + if self.multibounce: + output['bounces'] = callback_handler.bounces return output def compute_distance(self, scene): @@ -52,8 +64,7 @@ def compute_count(self, scene): ) return output - def compute_flux_density(self, scene, light_sources, - any_direction=True): + def compute_flux_density(self, scene, light_sources, any_direction=True): r"""Compute the flux density on each scene element touched by this blaster from a set of light sources. @@ -73,7 +84,8 @@ def compute_flux_density(self, scene, light_sources, """ fd_scene = scene.compute_flux_density( - light_sources, any_direction=any_direction) + light_sources, any_direction=any_direction + ) out = np.zeros(self.nx * self.ny, "f4") camera_hits = self.compute_count(scene) for ci, component in enumerate(scene.components): @@ -97,14 +109,15 @@ class OrthographicRayBlaster(RayBlaster): def _default_east(self): return np.cross(self.forward, self.up) - def __init__(self, *args, **kwargs): - super(OrthographicRayBlaster, self).__init__(*args, **kwargs) - - # here origin is not the center, but the bottom left + @traitlets.default("directions") + def _default_directions(self): self._directions = np.zeros((self.nx, self.ny, 3), dtype="f4") self._directions[:] = self.forward[None, None, :] - self.directions = self._directions.view().reshape((self.nx * self.ny, 3)) + return self._directions.view().reshape((self.nx * self.ny, 3)) + @traitlets.default("origins") + def _default_origins(self): + # here origin is not the center, but the bottom left self._origins = np.zeros((self.nx, self.ny, 3), dtype="f4") offset_x, offset_y = np.mgrid[ -self.width / 2 : self.width / 2 : self.nx * 1j, @@ -115,7 +128,7 @@ def __init__(self, *args, **kwargs): + offset_x[..., None] * self.east + offset_y[..., None] * self.up ) - self.origins = self._origins.view().reshape((self.nx * self.ny, 3)) + return self._origins.view().reshape((self.nx * self.ny, 3)) class SunRayBlaster(OrthographicRayBlaster): @@ -136,7 +149,10 @@ class SunRayBlaster(OrthographicRayBlaster): solar_azimuth = traitlets.CFloat() solar_distance = traitlets.CFloat() _solpos_info = traittypes.DataFrame() - + multibounce = traitlets.CBool(True) + scene_limits = traittypes.Array(None, allow_none=True).valid( + check_shape(None, 3), check_dtype("f4")) + @traitlets.default("_solpos_info") def _solpos_info_default(self): return pvlib.solarposition.get_solarposition( @@ -161,7 +177,6 @@ def _default_solar_azimuth(self): def zenith_direction(self): zd_nonorm = self.zenith - self.ground solar_distance = np.linalg.norm(zd_nonorm) - print("sd zd", solar_distance, zd_nonorm) return zd_nonorm / solar_distance @traitlets.default("solar_distance") @@ -169,27 +184,56 @@ def _solar_distance_default(self): zd_nonorm = self.zenith - self.ground return np.linalg.norm(zd_nonorm) - def solar_rotation(self, point): + def solar_rotation(self, point, is_ray=False): r"""Rotate a point according to same rotation that moves - sun from the zenith to it location in the sky. + sun from the zenith to its location in the sky. Args: point (array): 3D point to rotate + is_ray (bool, optional): If True, the point is treated as + a ray and will not be shifted prior to rotation. """ + + if is_ray: + origin = 0.0 + else: + origin = self.ground return sun_calc.rotate_u( - sun_calc.rotate_u( - point, - np.radians(90 - self.solar_altitude), - self.north), + sun_calc.rotate_u(point - origin, + np.radians(90 - self.solar_altitude), + self.north), np.radians(90 - self.solar_azimuth), - self.zenith_direction) + self.zenith_direction, + ) + origin @traitlets.default("forward") def _forward_default(self): # Negative to point from sun to the earth rather than from # eart to the sun - return -self.solar_rotation(self.zenith_direction) + return -self.solar_rotation(self.zenith_direction, is_ray=True) + + @traitlets.default("width") + def _width_default(self): + out = 1.0 + if self.scene_limits is not None: + v = self.ground - self.solar_distance * self.forward + a = self.scene_limits - v + b = self.east + adotb = np.dot(a, b) / np.linalg.norm(b) + out = np.max(adotb) - np.min(adotb) + return out + + @traitlets.default("height") + def _height_default(self): + out = 1.0 + if self.scene_limits is not None: + v = self.ground - self.solar_distance * self.forward + a = self.scene_limits - v + b = self.up + adotb = np.dot(a, b) / np.linalg.norm(b) + out = np.max(adotb) - np.min(adotb) + return out @traitlets.default("center") def _center_default(self): @@ -202,10 +246,8 @@ def _center_default(self): np.linalg.norm(v - self.ground) * np.tan(np.radians(self.solar_altitude)) ) - ) - / 2, + ), ) - print(offset) v = v + offset * self.up return v @@ -215,8 +257,8 @@ def _up_default(self): east = np.cross(self.north, zenith_direction) # The "east" used here is not the "east" used elsewhere. # This is the east wrt north etc, but we need an east for blasting from elsewhere. - return -self.solar_rotation(east) - + return -self.solar_rotation(east, is_ray=True) + class ProjectionRayBlaster(RayBlaster): pass diff --git a/hothouse/model.py b/hothouse/model.py index 6aaad9a..855903a 100644 --- a/hothouse/model.py +++ b/hothouse/model.py @@ -9,6 +9,8 @@ from .traits_support import check_shape, check_dtype +from yggdrasil.communication import open_file_comm + cached_property = getattr(functools, "cached_property", property) # From itertools cookbook @@ -46,9 +48,81 @@ class Model(traitlets.HasTraits): triangles = traittypes.Array(None, allow_none=True).valid( check_shape(None, 3, 3), check_dtype("f4") ) + normals = traittypes.Array(None, allow_none=True).valid( + check_shape(None, 3), check_dtype("f4") + ) + vertex_normals = traittypes.Array(None, allow_none=True).valid( + check_shape(None, 3, 3), check_dtype("f4") + ) + # TODO: Wavelength dependence? + transmittance = traittypes.Array(None, allow_none=True).valid( + check_dtype("f4")) + reflectance = traittypes.Array(None, allow_none=True).valid( + check_dtype("f4")) @classmethod - def from_ply(cls, filename): + def from_obj(cls, filename, transmittance=None, reflectance=None): + # with open_file_comm(filename, 'r', filetype='obj') as comm: + # flag, obj = comm.recv() + # assert(flag) + # xyz_vert = np.asarray([[v[k] for k in ['x', 'y', 'z']] + # for v in obj['vertices']], + # dtype='f4') + # xyz_faces = np.asarray([[v['vertex_index'] for v in f] + # for f in obj['faces']], dtype='i4') + # triangles = np.asarray(obj.mesh, dtype='f4') + # vertex_normals = obj.vertex_normals + # if vertex_normals is not None: + # vertex_normals = np.asarray(vertex_normals, dtype='f4') + import pywavefront + obj = pywavefront.Wavefront(filename, collect_faces=True) + xyz_vert = np.asarray(obj.vertices, dtype='f4') + xyz_faces = [] + triangles = [] + vertex_normals = [] + colors = [] + for mesh in obj.mesh_list: + ifaces = np.asarray(mesh.faces, dtype='i4') + xyz_faces.append(ifaces) + for material in mesh.materials: + if material.has_normals: + vertex_data = np.asarray( + material.vertices, dtype='f4').reshape( + (-1, 3, material.vertex_size)) + i0 = (material.has_uvs * 2) + i1 = (material.has_uvs * 2 + + material.has_normals * 3) + i2 = (material.has_uvs * 2 + + material.has_normals * 3 + + material.has_colors * 3) + vertex_normals.append( + vertex_data[:, :, i0:(i0 + 3)]) + colors.append( + vertex_data[:, :, i1:(i1 + 3)]) + triangles.append( + vertex_data[:, :, i2:(i2 + 3)]) + xyz_faces = np.concatenate(xyz_faces, axis=0) + triangles = np.concatenate(triangles, axis=0) + print('triangles', np.min(xyz_vert, axis=0), np.max(xyz_vert, axis=0)) + vertex_normals = np.concatenate(vertex_normals, axis=0) + colors = np.concatenate(colors, axis=0) + if isinstance(transmittance, (float, np.float)): + transmittance = transmittance * np.ones(triangles.shape[0], 'f4') + if isinstance(reflectance, (float, np.float)): + reflectance = reflectance * np.ones(triangles.shape[0], 'f4') + out = cls( + vertices=xyz_vert, + indices=xyz_faces, + # attributes=colors, + triangles=triangles, + vertex_normals=vertex_normals, + transmittance=transmittance, + reflectance=reflectance + ) + return out + + @classmethod + def from_ply(cls, filename, transmittance=None, reflectance=None): # This is probably not the absolute best way to do this. plydata = PlyData.read(filename) vertices = plydata["vertex"][:] @@ -70,11 +144,17 @@ def from_ply(cls, filename): axis=-1, ) triangles = np.array(triangles).swapaxes(1, 2) + if isinstance(transmittance, (float, np.float)): + transmittance = transmittance * np.ones(triangles.shape[0], 'f4') + if isinstance(reflectance, (float, np.float)): + reflectance = reflectance * np.ones(triangles.shape[0], 'f4') obj = cls( vertices=xyz_vert, indices=xyz_faces.astype('i4'), attributes=colors, triangles=triangles, + transmittance=transmittance, + reflectance=reflectance ) return obj @@ -97,12 +177,18 @@ def geometry(self): geometry.exec_three_obj_method("computeFaceNormals") return geometry - @cached_property - def normals(self): + @traitlets.default("normals") + def _default_normals(self): r"""Array of the normal vectors for the triangles in this model.""" v10 = self.triangles[:, 1, :] - self.triangles[:, 0, :] v20 = self.triangles[:, 2, :] - self.triangles[:, 0, :] - return np.cross(v10, v20) + out = np.cross(v10, v20) + if isinstance(self.vertex_normals, np.ndarray): + # Direction from vertex normals + mask = (np.einsum("ij, ij->i", out, + np.mean(self.vertex_normals, axis=1)) < 0) + out[mask] *= -1 + return out @cached_property def areas(self): diff --git a/hothouse/ray_callbacks.pyx b/hothouse/ray_callbacks.pyx new file mode 100644 index 0000000..8108e4a --- /dev/null +++ b/hothouse/ray_callbacks.pyx @@ -0,0 +1,217 @@ +# cython: language=c++ + +cimport numpy as np +import numpy as np +from pyembree.callback_handler cimport \ + RayCollisionCallback, _CALLBACK_TERMINATE, _CALLBACK_CONTINUE +from pyembree.rtcore_geometry cimport RTC_INVALID_GEOMETRY_ID +from pyembree.rtcore_ray cimport RTCRay + +cdef class RayCollisionPrinter(RayCollisionCallback): + cdef int callback(self, RTCRay &ray): + print("Hi!", ray.geomID) + return _CALLBACK_TERMINATE + +from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free + +cdef class RayCollisionMultiBounce(RayCollisionCallback): + + cdef int nray + cdef int maxbounce + cdef float power_threshold + cdef int iray + cdef float ipower + cdef public np.int32_t[:] nbounce + cdef public np.int32_t[:,:] primID + cdef public np.int32_t[:,:] geomID + cdef public np.int32_t[:,:] instID + cdef public np.float32_t[:,:] tfars + cdef public np.float32_t[:,:,:] Ng + cdef public np.float32_t[:,:,:] ray_dir + cdef public np.float32_t[:,:] power + cdef int nq + cdef RTCRay* ray_queue + cdef float* power_queue + cdef float** transmittance + cdef float** reflectance + + def __cinit__(self, int nray, int maxbounce, + list transmittance, list reflectance): + self.nray = nray + self.maxbounce = maxbounce + # TODO: Pass this in + self.power_threshold = 0.001 + self.iray = 0 + self.ipower = 1.0 + self.nbounce = np.zeros(nray, dtype="int32") + self.primID = -1 * np.ones((nray, maxbounce), dtype="int32") + self.geomID = -1 * np.ones((nray, maxbounce), dtype="int32") + self.instID = -1 * np.ones((nray, maxbounce), dtype="int32") + self.tfars = np.empty((nray, maxbounce), dtype="float32") + self.Ng = np.empty((nray, maxbounce, 3), dtype="float32") + self.ray_dir = np.empty((nray, maxbounce, 3), dtype="float32") + self.power = np.zeros((nray, maxbounce), dtype="float32") + self.nq = 0 + self.ray_queue = PyMem_Malloc(self.maxbounce * sizeof(RTCRay)) + self.power_queue = PyMem_Malloc(self.maxbounce * sizeof(float)) + self.transmittance = PyMem_Malloc(len(transmittance) * sizeof(float*)) + self.reflectance = PyMem_Malloc(len(reflectance) * sizeof(float*)) + cdef i + cdef np.ndarray[np.float32_t] buff + for i in range(len(transmittance)): + if isinstance(transmittance[i], np.ndarray): + buff = np.ascontiguousarray(transmittance[i], dtype=np.float32) + self.transmittance[i] = buff.data + else: + self.transmittance[i] = NULL + for i in range(len(reflectance)): + if isinstance(reflectance[i], np.ndarray): + buff = np.ascontiguousarray(reflectance[i], dtype=np.float32) + self.reflectance[i] = buff.data + else: + self.reflectance[i] = NULL + + def __dealloc__(self): + PyMem_Free(self.ray_queue) + PyMem_Free(self.power_queue) + PyMem_Free(self.transmittance) + PyMem_Free(self.reflectance) + + cdef int add_ray(self, float org[3], float dir[3], + float power) except -1: + if power < self.power_threshold: + return 0 + if self.nq >= self.maxbounce: + raise RuntimeError("Too many rays queued.") + cdef int i + for i in range(3): + self.ray_queue[self.nq].org[i] = org[i] + self.ray_queue[self.nq].dir[i] = dir[i] + self.ray_queue[self.nq].tnear = 0.0 + self.ray_queue[self.nq].tfar = 1e37 + self.ray_queue[self.nq].geomID = RTC_INVALID_GEOMETRY_ID + self.ray_queue[self.nq].primID = RTC_INVALID_GEOMETRY_ID + self.ray_queue[self.nq].instID = RTC_INVALID_GEOMETRY_ID + self.ray_queue[self.nq].mask = -1 + self.ray_queue[self.nq].time = 0 + self.power_queue[self.nq] = power + self.nq += 1 + return 0 + + cdef float pop_ray(self, RTCRay &ray): + if self.nq == 0: + raise RuntimeError("No rays queued.") + self.nq -= 1 + cdef int i + for i in range(3): + ray.org[i] = self.ray_queue[self.nq].org[i] + ray.dir[i] = self.ray_queue[self.nq].dir[i] + # Offset slightly to prevent intersection at orgin + ray.org[i] = ray.org[i] + 1000.0 * ray.dir[i] * np.finfo(np.float32).eps + ray.tnear = self.ray_queue[self.nq].tnear + ray.tfar = self.ray_queue[self.nq].tfar + ray.geomID = self.ray_queue[self.nq].geomID + ray.primID = self.ray_queue[self.nq].primID + ray.instID = self.ray_queue[self.nq].instID + ray.mask = self.ray_queue[self.nq].mask + ray.time = self.ray_queue[self.nq].time + return self.power_queue[self.nq] + + cdef void reflect_ray(self, RTCRay &ray, float power): + # TODO: Reflect more that one ray to account for spectral + # dependency or subsurface reflection + cdef int i + cdef float nu, ux, uy, uz + cdef float new_org[3], new_dir[3] + # Move origin to point of intersection + for i in range(3): + new_org[i] = ray.org[i] + ray.dir[i] * ray.tfar + nu = np.sqrt(ray.Ng[0] * ray.Ng[0] + + ray.Ng[1] * ray.Ng[1] + + ray.Ng[2] * ray.Ng[2]) + nx = ray.Ng[0] / nu + ny = ray.Ng[1] / nu + nz = ray.Ng[2] / nu + # Rotate inverse of original direction 180 deg around surface + # normal to get new direction + new_dir[0] = -(ray.dir[0] * (-1.0 + (2.0 * nx * nx)) + + ray.dir[1] * (2.0 * nx * ny) + + ray.dir[2] * (2.0 * nx * nz)) + new_dir[1] = -(ray.dir[0] * (2.0 * ny * nx) + + ray.dir[1] * (-1.0 + (2.0 * ny * ny)) + + ray.dir[2] * (2.0 * ny * nz)) + new_dir[2] = -(ray.dir[0] * (2.0 * nz * nx) + + ray.dir[1] * (2.0 * nz * ny) + + ray.dir[2] * (-1.0 + (2.0 * nz * nz))) + cdef float R = 0.0 + if self.reflectance[ray.geomID] is not NULL: + R = self.reflectance[ray.geomID][ray.primID] + self.add_ray(new_org, new_dir, R * power) + + cdef void transmit_ray(self, RTCRay &ray, float power): + # TODO: Refraction + cdef int i + cdef float new_org[3], new_dir[3] + # Move origin to point of intersection + for i in range(3): + new_org[i] = ray.org[i] + ray.dir[i] * ray.tfar + new_dir[i] = ray.dir[i] + cdef float T = 0.0 + if self.transmittance[ray.geomID] is not NULL: + T = self.transmittance[ray.geomID][ray.primID] + self.add_ray(new_org, new_dir, T * power) + + @property + def bounces(self): + out = {'nbounce': np.asarray(self.nbounce), + 'primID': np.asarray(self.primID), + 'geomID': np.asarray(self.geomID), + 'instID': np.asarray(self.instID), + 'tfars': np.asarray(self.tfars), + 'Ng': np.asarray(self.Ng), + 'ray_dir': np.asarray(self.ray_dir), + 'power': np.asarray(self.power)} + return out + + cdef int callback(self, RTCRay &ray): + cdef int idx + if ray.geomID == RTC_INVALID_GEOMETRY_ID: + if self.nq > 0: + self.ipower = self.pop_ray(ray) + return _CALLBACK_CONTINUE + else: + self.iray += 1 + self.ipower = 1.0 + return _CALLBACK_TERMINATE + if self.nbounce[self.iray] >= (self.maxbounce - 1): + # Reset queued since there isn't any more room and + # move to next original ray + self.nq = 0 + self.iray += 1 + self.ipower = 1.0 + return _CALLBACK_TERMINATE + # print("Hi!", self.iray, ray.geomID, ray.tnear, ray.tfar, ray.primID, ray.org, ray.dir) + # Record ray parameters for bounce + idx = self.nbounce[self.iray] + self.nbounce[self.iray] += 1 + self.primID[self.iray, idx] = ray.primID + self.geomID[self.iray, idx] = ray.geomID + self.instID[self.iray, idx] = ray.instID + self.tfars[self.iray, idx] = ray.tfar + for i in range(3): + self.Ng[self.iray, idx, i] = ray.Ng[i] + self.ray_dir[self.iray, idx, i] = ray.dir[i] + self.power[self.iray, idx] = self.ipower + # TODO: Update power based on transmittance/reflectance + # Redirect ray(s) + self.transmit_ray(ray, self.ipower) + self.reflect_ray(ray, self.ipower) + if self.nq == 0: + # Terminate and move on if no rays meet power threshold + # TODO: reset ray to ensure it is not logged twice + self.iray += 1 + self.ipower = 1.0 + return _CALLBACK_TERMINATE + # Reset ray parameters from queue + self.ipower = self.pop_ray(ray) + return _CALLBACK_CONTINUE diff --git a/hothouse/scene.py b/hothouse/scene.py index a714322..85ebe64 100644 --- a/hothouse/scene.py +++ b/hothouse/scene.py @@ -8,6 +8,7 @@ from .model import Model from .blaster import RayBlaster, OrthographicRayBlaster, SunRayBlaster from .traits_support import check_shape, check_dtype +from .sun_calc import solar_ppfd from pyembree import rtcore_scene as rtcs from pyembree.mesh_construction import TriangleMesh @@ -71,24 +72,88 @@ def get_sun_blaster(self, latitude, longitude, date, # TODO: Calculate direct/diffuse ppfd from lat/long/date # using pvi if not provided max_distance2 = 0.0 + mins = [] + maxs = [] for c in self.components: + mins.append(np.min(c.vertices, axis=0)) + maxs.append(np.max(c.vertices, axis=0)) max_distance2 = max( max_distance2, np.max(np.sum((c.vertices-self.ground)**2, axis=1))) + mins = np.min(np.vstack(mins), axis=0) + maxs = np.max(np.vstack(maxs), axis=0) + limits = np.vstack([mins, maxs]) + xx, yy, zz = np.meshgrid(limits[:, 0], limits[:, 1], limits[:, 2]) + limits = np.vstack([xx.flatten(), yy.flatten(), zz.flatten()]).T max_distance = np.sqrt(max_distance2) - kwargs.setdefault('zenith', self.up * max_distance) - kwargs.setdefault('width', 2 * max_distance) - kwargs.setdefault('height', 2 * max_distance) - kwargs.setdefault('intensity', (direct_ppfd - * kwargs['width'] - * kwargs['height'])) + kwargs.setdefault('zenith', self.up * max_distance + self.ground) kwargs.setdefault('diffuse_intensity', diffuse_ppfd) + kwargs.setdefault('scene_limits', limits) blaster = SunRayBlaster(latitude=latitude, longitude=longitude, date=date, ground=self.ground, north=self.north, **kwargs) + blaster.intensity = direct_ppfd * blaster.width * blaster.height return blaster + def animate_sun(self, camera, latitude, longitude, + t_start, t_stop, n_step, altitude=180.0, + fname=None): + r"""Create an animation of the sun moving across the scene + during the specified time. + + Args: + latitude (float): Latitude in degrees. + longitude (float): Longitude in degrees. + t_start (datetime.datetime): Start date & time w/ timezone + information. + t_stop (datetime.datetime): Stop date & time w/ timezone + information. + n_step (int): Number of steps between t_start and t_stop + to include in animation. + altitude (float, optional): Distance above sea level in + meters. Defaults to 180 meters (roughly the average for + Illinois). + fname (str, optional): File where animation should be saved. + Defaults to None and animation will be shown instead. + + Returns: + matplotlib.animation.FuncAnimation: Animation object. + + """ + import matplotlib.pyplot as plt + from matplotlib.animation import FuncAnimation, writers + from matplotlib.colors import LogNorm + import pandas as pd + nx = ny = 1024 + fig, ax = plt.subplots() + img = plt.imshow(np.nan * np.ones((nx, ny)), origin='lower', + norm=LogNorm(50, 5.0e4)) + plt.colorbar() + + def update(frame): + ppfd_tot = solar_ppfd(latitude, longitude, frame, + altitude=altitude) + sun = self.get_sun_blaster(latitude, longitude, frame, + nx=nx, ny=ny, + direct_ppfd=ppfd_tot['direct'], + diffuse_ppfd=ppfd_tot['diffuse'], + multibounce=True) + o = camera.compute_flux_density(self, sun) + o[o <= 0] = np.nan + img.set_data(o.reshape((camera.ny, camera.nx), order='F')) + return img, + + dates = pd.date_range(t_start, t_stop, periods=n_step) + ani = FuncAnimation(fig, update, frames=list(dates), blit=False) + if fname is None: + plt.show() + else: + Writer = writers['html'] + writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800) + ani.save(fname, writer=writer) + return ani + def compute_flux_density(self, light_sources, any_direction=True): r"""Compute the flux density on each scene element from a set of light sources. Values will be calculated from the @@ -118,51 +183,95 @@ def compute_flux_density(self, light_sources, any_direction=True): component_fd[ci] = np.zeros(component.triangles.shape[0], "f4") for blaster in light_sources: counts = blaster.compute_count(self) - any_hits = (counts["primID"] >= 0) - for ci, component in enumerate(self.components): - idx_hits = np.logical_and(counts["geomID"] == ci, - any_hits) - norms = component.normals - areas = component.areas - if isinstance(blaster, OrthographicRayBlaster): - component_counts = np.bincount( - counts["primID"][idx_hits], - minlength=component.triangles.shape[0]) - aoi = np.arccos( - np.dot(norms, -blaster.forward) - / (2.0 * areas * np.linalg.norm(blaster.forward))) - if any_direction: - aoi[aoi > np.pi/2] -= np.pi + if blaster.multibounce: + orthographic = isinstance(blaster, OrthographicRayBlaster) + for i in range(max(counts["bounces"]["nbounce"])): + orthographic = (orthographic and (i == 0)) + if orthographic: + ray_dir = blaster.forward + ray_intensity = blaster.ray_intensity + diffuse_intensity = blaster.diffuse_intensity else: - aoi[aoi > np.pi/2] = np.pi # No contribution - component_fd[ci] += ( - component_counts * blaster.ray_intensity - * np.cos(aoi) / areas) + ray_dir = counts["bounces"]["ray_dir"][:, i, :] + ray_intensity = ( + blaster.ray_intensity + * counts["bounces"]["power"][:, i]) + diffuse_intensity = 0.0 + primID = counts["bounces"]["primID"][:, i] + geomID = counts["bounces"]["geomID"][:, i] + self._accumulate_hits(component_fd, primID, geomID, + ray_dir, ray_intensity, + diffuse_intensity, + orthographic=orthographic, + any_direction=any_direction) + else: + if isinstance(blaster, OrthographicRayBlaster): + ray_dir = blaster.forward + orthographic = True + else: + ray_dir = blaster.directions + orthographic = False + self._accumulate_hits(component_fd, counts["primID"], + counts["geomID"], ray_dir, + blaster.ray_intensity, + blaster.diffuse_intensity, + orthographic=orthographic, + any_direction=any_direction) + return component_fd + + def _calc_incident_power(self, ray_dir, norm, area, any_direction=True): + aoi = np.arccos( + np.dot(norm, -ray_dir) / (2.0 * area * np.linalg.norm(ray_dir))) + if isinstance(aoi, np.ndarray): + if any_direction: + aoi[aoi > np.pi/2] -= np.pi + else: + aoi[aoi > np.pi/2] = np.pi # No contribution + else: + if aoi > np.pi/2: + if any_direction: + aoi -= np.pi else: - # TODO: This loop can be removed if AOI is calculated - # for each intersection by embree (or callback) - for idx_ray in np.where(idx_hits)[0]: - idx_scene = output["primID"][i] - aoi = np.arccos( - np.dot(norms[idx_scene], - -blaster.directions[idx_ray, :]) - / (2.0 * areas[idx_scene] * np.linalg.norm( - blaster.directions[idx_ray, :]))) - if any_direction: - aoi[aoi > np.pi/2] -= np.pi - else: - aoi[aoi > np.pi/2] = np.pi # No contribution - component_fd[ci][idx_scene] += ( - blaster.ray_intensity * np.cos(aoi) - / areas[idx_scene]) - # Diffuse - # TODO: This assumes diffuse light comes from everywhere + aoi = np.pi + return np.cos(aoi) / area + + def _accumulate_hits(self, component_fd, primID, geomID, + ray_dir, ray_intensity, diffuse_intensity, + orthographic=False, any_direction=True): + any_hits = (primID >= 0) + for ci, component in enumerate(self.components): + norms = component.normals + areas = component.areas + idx_hits = np.logical_and(geomID == ci, any_hits) + if orthographic: + component_counts = np.bincount( + primID[idx_hits], minlength=component.triangles.shape[0]) + component_fd[ci] += np.array( + component_counts * ray_intensity + * self._calc_incident_power( + ray_dir, norms, areas, + any_direction=any_direction)) + else: + if not isinstance(ray_intensity, np.ndarray): + ray_intensity = ray_intensity * np.ones(primID.shape) + # TODO: This loop can be removed if AOI is calculated + # for each intersection by embree (or callback) + for idx_ray in np.where(idx_hits)[0]: + idx_scene = primID[idx_ray] + component_fd[ci][idx_scene] += ( + ray_intensity[idx_ray] + * self._calc_incident_power( + ray_dir[idx_ray, :], + norms[idx_scene], areas[idx_scene], + any_direction=any_direction)) + # Diffuse + # TODO: This assumes diffuse light comes from everywhere + if diffuse_intensity > 0.0: tilt = np.arccos( np.dot(norms, self.up) / (2.0 * areas * np.linalg.norm(self.up))) component_fd[ci] += pvlib.irradiance.isotropic( - np.degrees(tilt), blaster.diffuse_intensity) - return component_fd + np.degrees(tilt), diffuse_intensity) def _ipython_display_(self): # This needs to actually display, which is not the same as returning a display. diff --git a/hothouse/sun_calc.py b/hothouse/sun_calc.py index 4d95a99..9dfd118 100755 --- a/hothouse/sun_calc.py +++ b/hothouse/sun_calc.py @@ -2,6 +2,7 @@ import numpy as np import matplotlib.pyplot as plt import pandas as pd +import pvlib #FIX: take into account daylight savings time like in Example 11.1 #ignoring for now @@ -10,6 +11,39 @@ kSOLAR_constant = 2600 +def solar_ppfd(latitude, longitude, date, altitude=180.0): + r"""Determine the Photosynthetic Photon Flux Density (PPFD) + received from the sun at a location and time. + + Args: + latitude (float): Latitude in degrees. + longitude (float): Longitude in degrees. + date (datetime.datetime): Date & time w/ timezone information. + altitude (float, optional): Distance above sea level in meters. + Defaults to 180 meters (roughly the average for Illinois). + + Returns: + dict: PPFD values for direct and diffuse light. + + """ + date = pvlib.tools._datetimelike_scalar_to_datetimeindex(date) + solpos = pvlib.solarposition.get_solarposition( + date, latitude, longitude) + dni_extra = pvlib.irradiance.get_extra_radiation(date) + airmass = pvlib.atmosphere.get_relative_airmass(solpos['apparent_zenith']) + pressure = pvlib.atmosphere.alt2pres(altitude) + am_abs = pvlib.atmosphere.get_absolute_airmass(airmass, pressure) + tl = pvlib.clearsky.lookup_linke_turbidity(date, latitude, longitude) + cs = pvlib.clearsky.ineichen(solpos['apparent_zenith'], am_abs, tl, + dni_extra=dni_extra, altitude=altitude) + # Convert from irradiance to PPFD + eta_par = 0.368 + eta_photon = 4.56 # µmol s−1 W−1 + irr2ppfd = eta_par * eta_photon + ppfd = {'direct': irr2ppfd * cs['dni'][0], + 'diffuse': irr2ppfd * cs['dhi'][0]} + return ppfd + def rotation_matrix(theta, u): r"""Get the rotation matrix necessary to rotate a 3D point around a unit vector by a specified angle. diff --git a/pvlib_model.py b/pvlib_model.py deleted file mode 100644 index 3ad40ac..0000000 --- a/pvlib_model.py +++ /dev/null @@ -1,21 +0,0 @@ -import pvlib - - -def sun_model(latitude, longitude, date, altitude=10.0, **kwargs): - date = pvlib.tools._datetimelike_scalar_to_datetimeindex(date) - solpos = pvlib.solarposition.get_solarposition( - date, latitude, longitude) - dni_extra = pvlib.irradiance.get_extra_radiation(date) - airmass = pvlib.atmosphere.get_relative_airmass(solpos['apparent_zenith']) - pressure = pvlib.atmosphere.alt2pres(altitude) - am_abs = pvlib.atmosphere.get_absolute_airmass(airmass, pressure) - tl = pvlib.clearsky.lookup_linke_turbidity(date, latitude, longitude) - cs = pvlib.clearsky.ineichen(solpos['apparent_zenith'], am_abs, tl, - dni_extra=dni_extra, altitude=altitude) - # Convert from irradiance to PPFD - eta_par = 0.368 - eta_photon = 4.56 # µmol s−1 W−1 - irr2ppfd = eta_par * eta_photon - ppfd = {'direct': irr2ppfd * cs['dni'][0], - 'diffuse': irr2ppfd * cs['dhi'][0]} - return ppfd diff --git a/requirements.txt b/requirements.txt index c559ce7..2caa323 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,5 @@ traittypes>=0.2.1 pvlib>=0.7.2 tables>=3.6.1 pythreejs>=2.2.0 +pandas +matplotlib diff --git a/setup.py b/setup.py index 9677df9..ac2cbbc 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,13 @@ """The setup script.""" from setuptools import setup, find_packages +from Cython.Build import cythonize +import numpy import versioneer +import sys +import os +from pkg_resources import resource_filename +from sys import platform as _platform with open("README.rst") as readme_file: readme = readme_file.read() @@ -24,6 +30,7 @@ "pvlib>=0.7.2", "tables>=3.6.1", "pythreejs>=2.2.0", + "Cython>=0.29.20", ] setup_requirements = [ @@ -34,6 +41,47 @@ "pytest", ] + +# These routines are taken from yt +def in_conda_env(): + return any(s in sys.version for s in ("Anaconda", "Continuum", "conda")) + + +def check_for_pyembree(): + try: + fn = resource_filename("pyembree", "rtcore.pxd") + except ImportError: + return None + return os.path.dirname(fn) + + +std_libs = [] + + +def append_embree_info(exts): + embree_prefix = os.path.abspath(check_for_pyembree()) + embree_inc_dir = [os.path.join(embree_prefix, "include")] + embree_lib_dir = [os.path.join(embree_prefix, "lib")] + if in_conda_env(): + conda_basedir = os.path.dirname(os.path.dirname(sys.executable)) + embree_inc_dir.append(os.path.join(conda_basedir, "include")) + embree_lib_dir.append(os.path.join(conda_basedir, "lib")) + + if _platform == "darwin": + embree_lib_name = "embree.2" + else: + embree_lib_name = "embree" + + for ext in exts: + ext.include_dirs += embree_inc_dir + [numpy.get_include()] + ext.library_dirs += embree_lib_dir + ext.language = "c++" + ext.libraries += std_libs + ext.libraries += [embree_lib_name] + + return exts + + setup( author="Matthew Turk", author_email="matthewturk@gmail.com", @@ -66,4 +114,5 @@ version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), zip_safe=False, + ext_modules=append_embree_info(cythonize("**/*.pyx")), )