From 8ec410d68051244f05a5402168c5cd31f04f0c6d Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 20 Nov 2025 17:14:04 +0000 Subject: [PATCH 01/41] WIP towards a flag compound ray eye representation --- examples/CMakeLists.txt | 4 + examples/ant_eyes_dhex.eye | 1024 +++++++++++++++++++++++++++++++++ examples/cray_eye.cpp | 109 ++++ maths | 2 +- mplot/SphereVisual.h | 8 +- mplot/compoundray/EyeVisual.h | 82 ++- 6 files changed, 1211 insertions(+), 18 deletions(-) create mode 100644 examples/ant_eyes_dhex.eye create mode 100644 examples/cray_eye.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9ab76924..0a663ceb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -537,3 +537,7 @@ endif() add_executable(show_boundingboxes show_boundingboxes.cpp) target_link_libraries(show_boundingboxes OpenGL::GL glfw Freetype::Freetype) + +# if have compound-ray header +add_executable(cray_eye cray_eye.cpp) +target_link_libraries(cray_eye OpenGL::GL glfw Freetype::Freetype) diff --git a/examples/ant_eyes_dhex.eye b/examples/ant_eyes_dhex.eye new file mode 100644 index 00000000..d03148b4 --- /dev/null +++ b/examples/ant_eyes_dhex.eye @@ -0,0 +1,1024 @@ +-0.000588897266 0 0.000340000173 -0.866025329 0 0.500000238 0.079482 0.00017 +-0.000593948294 -6.30000022e-06 0.000330316368 -0.873904049 -0.00926948711 0.486010015 0.0813195 0.00017 +-0.000593948294 6.30000022e-06 0.000330316368 -0.873904049 0.00926948711 0.486010015 0.081564 0.00017 +-0.000588492316 1.26000004e-05 0.000339766382 -0.865876496 0.0185389742 0.499914289 0.0799489 0.00017 +-0.000583036337 6.30000022e-06 0.000349216367 -0.857848823 0.00926948711 0.513818502 0.0779201 0.00017 +-0.000583036337 -6.30000022e-06 0.000349216367 -0.857848823 -0.00926948711 0.513818502 0.0776939 0.00017 +-0.000588492316 -1.26000004e-05 0.000339766382 -0.865876496 -0.0185389742 0.499914289 0.079482 0.00017 +-0.000598182727 -1.26000004e-05 0.000320161082 -0.881508231 -0.0185679123 0.471803427 0.0834594 0.00017 +-0.000598590996 0 0.000320396823 -0.881649673 0 0.471904457 0.0834594 0.00017 +-0.000598182727 1.26000004e-05 0.000320161082 -0.881508231 0.0185679123 0.471803427 0.0839627 0.00017 +-0.000593135017 1.89000002e-05 0.000329846836 -0.873613715 0.0278373361 0.485823154 0.0823001 0.00017 +-0.00058727077 2.52000009e-05 0.000339061109 -0.865427911 0.0371358246 0.499655306 0.0809104 0.00017 +-0.00058222306 1.89000002e-05 0.000348746835 -0.857541859 0.0278373398 0.513660491 0.0786095 0.00017 +-0.000576358812 1.26000004e-05 0.000357961108 -0.849347651 0.0185679123 0.527507186 0.076598 0.00017 +-0.000576767139 0 0.000358196849 -0.849505901 0 0.527579188 0.0761446 0.00017 +-0.000576358812 -1.26000004e-05 0.000357961108 -0.849347651 -0.0185679123 0.527507186 0.0761446 0.00017 +-0.00058222306 -1.89000002e-05 0.000348746835 -0.857541859 -0.0278373398 0.513660491 0.0779201 0.00017 +-0.00058727077 -2.52000009e-05 0.000339061109 -0.865427911 -0.0371358246 0.499655306 0.0799489 0.00017 +-0.000593135017 -1.89000002e-05 0.000329846836 -0.873613715 -0.0278373361 0.485823154 0.081564 0.00017 +-0.000601579552 -1.89000002e-05 0.000309522293 -0.888857722 -0.0279255006 0.457331479 0.0859497 0.00017 +-0.000602406741 -6.30000068e-06 0.000309999858 -0.889134884 -0.00929861795 0.457550794 0.085684 0.00017 +-0.000602406741 6.29999977e-06 0.000309999858 -0.889134884 0.00929861609 0.457550794 0.0859497 0.00017 +-0.000601579552 1.89000002e-05 0.000309522293 -0.888857722 0.0279255006 0.457331479 0.0867417 0.00017 +-0.00059695082 2.52000009e-05 0.000319449871 -0.881082058 0.0371944718 0.471498728 0.0849875 0.00017 +-0.000591494842 3.15000034e-05 0.000328899885 -0.873029172 0.046493087 0.485446662 0.0835562 0.00017 +-0.000585211674 3.78000004e-05 0.000337872276 -0.864673555 0.055851005 0.499219745 0.0824087 0.00017 +-0.000580582884 3.15000034e-05 0.000347799854 -0.856923521 0.0464930907 0.5133425 0.0798044 0.00017 +-0.000575126905 2.51999991e-05 0.000357249868 -0.848870635 0.0371944681 0.527290463 0.0775191 0.00017 +-0.000568843738 1.89000002e-05 0.000366222288 -0.840489268 0.0279255025 0.541108012 0.0755244 0.00017 +-0.000569670927 6.30000068e-06 0.000366699853 -0.840817809 0.00929861888 0.541238368 0.074822 0.00017 +-0.000569670927 -6.29999977e-06 0.000366699853 -0.840817809 -0.00929861702 0.541238368 0.0746096 0.00017 +-0.000568843738 -1.89000002e-05 0.000366222288 -0.840489268 -0.0279255025 0.541108012 0.074822 0.00017 +-0.000575126905 -2.52000009e-05 0.000357249868 -0.848870635 -0.0371944718 0.527290463 0.076598 0.00017 +-0.000580582884 -3.15000034e-05 0.000347799854 -0.856923521 -0.0464930907 0.5133425 0.0786095 0.00017 +-0.000585211674 -3.78000004e-05 0.000337872276 -0.864673555 -0.055851005 0.499219745 0.0809104 0.00017 +-0.000591494842 -3.15000034e-05 0.000328899885 -0.873029172 -0.046493087 0.485446662 0.0823001 0.00017 +-0.00059695082 -2.51999991e-05 0.000319449871 -0.881082058 -0.0371944681 0.471498728 0.0839627 0.00017 +-0.000604102155 -2.52000009e-05 0.000298378756 -0.895970285 -0.0373752192 0.44253853 0.0888388 0.00017 +-0.000605366717 -1.25999995e-05 0.000299108855 -0.896378636 -0.0186570715 0.442896456 0.0882751 0.00017 +-0.000605785695 0 0.000299350766 -0.896514118 0 0.443015039 0.0882751 0.00017 +-0.000605366717 1.26000004e-05 0.000299108855 -0.896378636 0.0186570734 0.442896456 0.0888388 0.00017 +-0.000604102155 2.52000009e-05 0.000298378756 -0.895970285 0.0373752192 0.44253853 0.0899973 0.00017 +-0.000599910796 3.15000034e-05 0.00030855884 -0.888299882 0.0466426797 0.456889182 0.0881213 0.00017 +-0.000594873796 3.78000004e-05 0.000318250735 -0.880365431 0.0559409633 0.470985502 0.0865986 0.00017 +-0.000588998897 4.41000011e-05 0.000327458838 -0.872142315 0.0652997419 0.484874815 0.0854108 0.00017 +-0.000582278357 5.04000018e-05 0.000336178724 -0.8636024 0.0747504383 0.498601347 0.0845415 0.00017 +-0.00057808694 4.41000047e-05 0.000346358836 -0.855984867 0.0652997568 0.512860417 0.0815675 0.00017 +-0.00057304994 3.78000004e-05 0.000356050761 -0.84806782 0.0559409633 0.526926458 0.0789831 0.00017 +-0.000567174982 3.15000034e-05 0.000365258835 -0.839827359 0.0466426834 0.54084605 0.0767034 0.00017 +-0.0005604545 2.52000009e-05 0.000373978721 -0.831234515 0.0373752192 0.554664135 0.0746869 0.00017 +-0.000561719062 1.25999995e-05 0.000374708819 -0.831748664 0.0186570715 0.554838836 0.0737421 0.00017 +-0.000562138041 0 0.00037495073 -0.831919134 0 0.554896951 0.0732868 0.00017 +-0.000561719062 -1.26000004e-05 0.000374708819 -0.831748664 -0.0186570734 0.554838836 0.0732868 0.00017 +-0.0005604545 -2.52000009e-05 0.000373978721 -0.831234515 -0.0373752192 0.554664135 0.0737421 0.00017 +-0.000567174982 -3.15000034e-05 0.000365258835 -0.839827359 -0.0466426834 0.54084605 0.0755244 0.00017 +-0.00057304994 -3.78000004e-05 0.000356050761 -0.84806782 -0.0559409633 0.526926458 0.0775191 0.00017 +-0.00057808694 -4.41000011e-05 0.000346358836 -0.855984867 -0.0652997494 0.512860417 0.0798044 0.00017 +-0.000582278357 -5.04000018e-05 0.000336178724 -0.8636024 -0.0747504383 0.498601347 0.0824087 0.00017 +-0.000588998897 -4.41000047e-05 0.000327458838 -0.872142315 -0.0652997494 0.484874815 0.0835562 0.00017 +-0.000594873796 -3.78000004e-05 0.000318250735 -0.880365431 -0.0559409633 0.470985502 0.0849875 0.00017 +-0.000599910796 -3.15000034e-05 0.00030855884 -0.888299882 -0.0466426797 0.456889182 0.0867417 0.00017 +-0.000605694251 -3.15000034e-05 0.000286697934 -0.902862072 -0.0469546393 0.427358657 0.0922396 0.00017 +-0.000607424881 -1.89000002e-05 0.000287697098 -0.903398275 -0.0281092003 0.427880138 0.0913246 0.00017 +-0.000608282047 -6.29999886e-06 0.000288191979 -0.903664708 -0.00935928803 0.428138435 0.0910208 0.00017 +-0.000608282047 6.30000068e-06 0.000288191979 -0.903664708 0.00935929082 0.428138435 0.0913246 0.00017 +-0.000607424881 1.89000002e-05 0.000287697098 -0.903398275 0.0281092003 0.427880138 0.0922396 0.00017 +-0.000605694251 3.15000034e-05 0.000286697934 -0.902862072 0.0469546393 0.427358657 0.0938308 0.00017 +-0.000601968903 3.78000004e-05 0.000297147111 -0.895283818 0.0562184006 0.441934764 0.0918037 0.00017 +-0.000597370148 4.41000047e-05 0.000307092007 -0.887453914 0.0655150265 0.456216276 0.0901703 0.00017 +-0.000591914228 5.04000018e-05 0.000316541991 -0.879348516 0.0748743117 0.470255196 0.0888972 0.00017 +-0.000585601083 5.67000025e-05 0.000325497094 -0.870940566 0.0843276009 0.484098554 0.0879869 0.00017 +-0.000578414474 6.30000068e-05 0.000333947944 -0.862198114 0.0939092785 0.497790605 0.0874474 0.00017 +-0.000574689126 5.67000061e-05 0.000344397093 -0.854711652 0.0843276009 0.512207747 0.0840211 0.00017 +-0.000570090313 5.04000018e-05 0.000354341988 -0.846927047 0.0748743191 0.526410997 0.081053 0.00017 +-0.000564634334 4.41000047e-05 0.000363792002 -0.83882165 0.0655150339 0.540449917 0.0784479 0.00017 +-0.000558321248 3.78000004e-05 0.000372747076 -0.830368459 0.0562184006 0.554371536 0.076156 0.00017 +-0.000551134697 3.15000034e-05 0.000381197955 -0.821534157 0.0469546355 0.568222523 0.0741285 0.00017 +-0.000552865269 1.89000002e-05 0.000382197089 -0.822254002 0.0281092003 0.568426132 0.0728881 0.00017 +-0.000553722493 6.29999886e-06 0.000382692 -0.822610855 0.0093592871 0.568527758 0.072192 0.00017 +-0.000553722493 -6.30000068e-06 0.000382692 -0.822610855 -0.00935928989 0.568527758 0.0719719 0.00017 +-0.000552865269 -1.89000002e-05 0.000382197089 -0.822254002 -0.0281092003 0.568426132 0.072192 0.00017 +-0.000551134697 -3.15000034e-05 0.000381197955 -0.821534157 -0.0469546355 0.568222523 0.0728881 0.00017 +-0.000558321248 -3.78000004e-05 0.000372747076 -0.830368459 -0.0562184006 0.554371536 0.0746869 0.00017 +-0.000564634334 -4.41000047e-05 0.000363792002 -0.83882165 -0.0655150339 0.540449917 0.0767034 0.00017 +-0.000570090313 -5.04000018e-05 0.000354341988 -0.846927047 -0.0748743191 0.526410997 0.0789831 0.00017 +-0.000574689126 -5.67000025e-05 0.000344397093 -0.854711652 -0.0843276009 0.512207747 0.0815675 0.00017 +-0.000578414474 -6.30000068e-05 0.000333947944 -0.862198114 -0.0939092785 0.497790605 0.0845415 0.00017 +-0.000585601083 -5.67000061e-05 0.000325497094 -0.870940566 -0.0843276009 0.484098554 0.0854108 0.00017 +-0.000591914228 -5.04000018e-05 0.000316541991 -0.879348516 -0.0748743117 0.470255196 0.0865986 0.00017 +-0.000597370148 -4.41000047e-05 0.000307092007 -0.887453914 -0.0655150265 0.456216276 0.0881213 0.00017 +-0.000601968903 -3.78000004e-05 0.000297147111 -0.895283818 -0.0562184006 0.441934764 0.0899973 0.00017 +-0.000606274116 -3.78000004e-05 0.000274432707 -0.909548283 -0.0567085519 0.411711127 0.0962897 0.00017 +-0.00060851255 -2.52000027e-05 0.000275725062 -0.910210073 -0.0376940407 0.41242817 0.0949284 0.00017 +-0.000609837822 -1.26000014e-05 0.000276490202 -0.910603642 -0.0188141949 0.412852347 0.0942756 0.00017 +-0.000610276649 0 0.00027674358 -0.910734355 0 0.412992805 0.0942756 0.00017 +-0.000609837822 1.25999995e-05 0.000276490202 -0.910603642 0.0188141912 0.412852347 0.0949284 0.00017 +-0.00060851255 2.51999991e-05 0.000275725062 -0.910210073 0.0376940332 0.41242817 0.0962897 0.00017 +-0.000606274116 3.78000004e-05 0.000274432707 -0.909548283 0.0567085519 0.411711127 0.0984385 0.00017 +-0.000603056571 4.41000047e-05 0.000285175047 -0.902049065 0.0659645647 0.426563412 0.0961877 0.00017 +-0.000598925864 5.04000018e-05 0.0002953902 -0.894309998 0.0752567723 0.441073656 0.0943858 0.00017 +-0.00059390883 5.67000025e-05 0.000305093563 -0.886308014 0.0846151188 0.455300331 0.093006 0.00017 +-0.000588013965 6.30000068e-05 0.00031429017 -0.878016531 0.0940709636 0.469294906 0.0920203 0.00017 +-0.000581232773 6.93000038e-05 0.000322975044 -0.869404972 0.103658594 0.483104408 0.0914604 0.00017 +-0.000573538302 7.56000009e-05 0.000331132702 -0.860437214 0.113417104 0.496773928 0.0913404 0.00017 +-0.000570320815 6.92999965e-05 0.000341875042 -0.853083074 0.103658594 0.51137501 0.0873186 0.00017 +-0.000566190109 6.30000068e-05 0.000352090196 -0.845429301 0.0940709636 0.525737524 0.0838733 0.00017 +-0.000561173016 5.67000025e-05 0.000361793558 -0.837455451 0.0846151263 0.539915502 0.0808855 0.00017 +-0.00055527821 5.03999981e-05 0.000370990165 -0.829135776 0.0752567649 0.553958774 0.0782564 0.00017 +-0.000548496959 4.41000011e-05 0.000379675039 -0.820438981 0.0659645498 0.567915976 0.0759435 0.00017 +-0.000540802546 3.78000004e-05 0.000387832697 -0.811326146 0.0567085519 0.58183676 0.0738751 0.00017 +-0.000543041038 2.52000027e-05 0.000389125024 -0.812278092 0.0376940407 0.582051337 0.0723118 0.00017 +-0.000544366252 1.26000014e-05 0.000389890192 -0.81284219 0.0188141949 0.582180083 0.0713235 0.00017 +-0.000544805138 0 0.00039014357 -0.81302917 0 0.582223058 0.0708404 0.00017 +-0.000544366252 -1.25999995e-05 0.000389890192 -0.81284219 -0.0188141912 0.582180083 0.0708404 0.00017 +-0.000543041038 -2.51999991e-05 0.000389125024 -0.812278092 -0.0376940332 0.582051337 0.0713235 0.00017 +-0.000540802546 -3.78000004e-05 0.000387832697 -0.811326146 -0.0567085519 0.58183676 0.0723118 0.00017 +-0.000548496959 -4.41000047e-05 0.000379675039 -0.820438981 -0.0659645572 0.567915976 0.0741285 0.00017 +-0.00055527821 -5.04000018e-05 0.000370990165 -0.829135776 -0.0752567723 0.553958774 0.076156 0.00017 +-0.000561173016 -5.67000025e-05 0.000361793558 -0.837455451 -0.0846151263 0.539915502 0.0784479 0.00017 +-0.000566190109 -6.30000068e-05 0.000352090196 -0.845429301 -0.0940709636 0.525737524 0.081053 0.00017 +-0.000570320815 -6.93000038e-05 0.000341875042 -0.853083074 -0.103658609 0.51137501 0.0840211 0.00017 +-0.000573538302 -7.56000009e-05 0.000331132702 -0.860437214 -0.113417104 0.496773928 0.0874474 0.00017 +-0.000581232773 -6.92999965e-05 0.000322975044 -0.869404972 -0.103658579 0.483104408 0.0879869 0.00017 +-0.000588013965 -6.30000068e-05 0.00031429017 -0.878016531 -0.0940709636 0.469294906 0.0888972 0.00017 +-0.00059390883 -5.67000025e-05 0.000305093563 -0.886308014 -0.0846151188 0.455300331 0.0901703 0.00017 +-0.000598925864 -5.03999981e-05 0.0002953902 -0.894309998 -0.0752567649 0.441073656 0.0918037 0.00017 +-0.000603056571 -4.41000011e-05 0.000285175047 -0.902049065 -0.0659645647 0.426563412 0.0938308 0.00017 +-0.000605723995 -4.41000047e-05 0.000261515088 -0.916044474 -0.0666930228 0.395492762 0.1012 0.00017 +-0.000608530827 -3.14999997e-05 0.000263135618 -0.916829824 -0.0474587902 0.396447599 0.099256 0.00017 +-0.000610368559 -1.89000002e-05 0.000264196657 -0.917347848 -0.0284055825 0.397071928 0.0981449 0.00017 +-0.000611277763 -6.29999886e-06 0.000264721573 -0.917605162 -0.00945709459 0.397380531 0.0977797 0.00017 +-0.000611277763 6.3000025e-06 0.000264721573 -0.917605162 0.00945710018 0.397380531 0.0981449 0.00017 +-0.000610368559 1.8900002e-05 0.000264196657 -0.917347848 0.0284055844 0.397071928 0.099256 0.00017 +-0.000608530827 3.15000034e-05 0.000263135618 -0.916829824 0.047458794 0.396447599 0.1012 0.00017 +-0.000605723995 4.41000047e-05 0.000261515088 -0.916044474 0.0666930228 0.395492762 0.104101 0.00017 +-0.000603074906 5.04000018e-05 0.000272585603 -0.908609688 0.0759340748 0.410685211 0.10153 0.00017 +-0.00059945666 5.67000025e-05 0.000283096626 -0.900947869 0.0852167457 0.425477475 0.0994883 0.00017 +-0.000594909885 6.30000068e-05 0.000293071585 -0.893034875 0.0945709646 0.439937472 0.097936 0.00017 +-0.000589453964 6.92999965e-05 0.00030252157 -0.884844899 0.104028054 0.45412311 0.0968425 0.00017 +-0.000583088782 7.56000009e-05 0.000311446609 -0.876347959 0.11362233 0.468085855 0.0962297 0.00017 +-0.000575795071 8.19000052e-05 0.000319835613 -0.867509186 0.123392865 0.481873393 0.0961127 0.00017 +-0.000567532261 8.82000095e-05 0.000327665068 -0.858286679 0.133386061 0.495532304 0.0965829 0.00017 +-0.000564883114 8.19000052e-05 0.000338735583 -0.851068914 0.123392865 0.510348618 0.0917439 0.00017 +-0.000561264926 7.56000081e-05 0.000349246635 -0.84354794 0.113622338 0.524897039 0.0876682 0.00017 +-0.000556718151 6.93000038e-05 0.000359221565 -0.835704267 0.104028068 0.539236963 0.0841789 0.00017 +-0.00055126223 6.30000068e-05 0.00036867155 -0.827514231 0.0945709646 0.55342257 0.0811455 0.00017 +-0.000544897048 5.67000061e-05 0.000377596647 -0.81894803 0.0852167532 0.567505419 0.0784846 0.00017 +-0.000537603337 5.04000054e-05 0.000385985593 -0.809968412 0.0759340748 0.581536829 0.0761295 0.00017 +-0.000529340527 4.41000047e-05 0.000393815048 -0.800528705 0.0666930228 0.595571756 0.0740233 0.00017 +-0.000532147358 3.14999997e-05 0.000395435578 -0.801748276 0.0474587902 0.595774472 0.0720159 0.00017 +-0.00053398509 1.89000002e-05 0.000396496616 -0.802547991 0.0284055825 0.595910966 0.0706937 0.00017 +-0.000534894294 6.29999886e-06 0.000397021562 -0.802943945 0.00945709459 0.595979512 0.0699221 0.00017 +-0.000534894294 -6.3000025e-06 0.000397021562 -0.802943945 -0.00945710018 0.595979512 0.0696865 0.00017 +-0.00053398509 -1.8900002e-05 0.000396496616 -0.802547991 -0.0284055844 0.595910966 0.0699221 0.00017 +-0.000532147358 -3.15000034e-05 0.000395435578 -0.801748276 -0.047458794 0.595774472 0.0706937 0.00017 +-0.000529340527 -4.41000047e-05 0.000393815048 -0.800528705 -0.0666930228 0.595571756 0.0720159 0.00017 +-0.000537603337 -5.04000018e-05 0.000385985593 -0.809968412 -0.0759340748 0.581536829 0.0738751 0.00017 +-0.000544897048 -5.67000025e-05 0.000377596647 -0.81894803 -0.0852167457 0.567505419 0.0759435 0.00017 +-0.00055126223 -6.30000068e-05 0.00036867155 -0.827514231 -0.0945709646 0.55342257 0.0782564 0.00017 +-0.000556718151 -6.92999965e-05 0.000359221565 -0.835704267 -0.104028054 0.539236963 0.0808855 0.00017 +-0.000561264926 -7.56000009e-05 0.000349246635 -0.84354794 -0.11362233 0.524897039 0.0838733 0.00017 +-0.000564883114 -8.19000052e-05 0.000338735583 -0.851068914 -0.123392865 0.510348618 0.0873186 0.00017 +-0.000567532261 -8.82000095e-05 0.000327665068 -0.858286679 -0.133386061 0.495532304 0.0913404 0.00017 +-0.000575795071 -8.19000052e-05 0.000319835613 -0.867509186 -0.123392865 0.481873393 0.0914604 0.00017 +-0.000583088782 -7.56000081e-05 0.000311446609 -0.876347959 -0.113622338 0.468085855 0.0920203 0.00017 +-0.000589453964 -6.93000038e-05 0.00030252157 -0.884844899 -0.104028068 0.45412311 0.093006 0.00017 +-0.000594909885 -6.30000068e-05 0.000293071585 -0.893034875 -0.0945709646 0.439937472 0.0943858 0.00017 +-0.00059945666 -5.67000061e-05 0.000283096626 -0.900947869 -0.0852167532 0.425477475 0.0961877 0.00017 +-0.000603074906 -5.04000054e-05 0.000272585603 -0.908609688 -0.0759340748 0.410685211 0.0984385 0.00017 +-0.00060387241 -5.04000018e-05 0.000247846037 -0.922367632 -0.0769820437 0.378565371 0.107301 0.00017 +-0.000607337104 -3.78000041e-05 0.000249846373 -0.923275113 -0.0574636459 0.379816979 0.104568 0.00017 +-0.00060975278 -2.51999991e-05 0.000251241087 -0.923914909 -0.0381837599 0.380687714 0.102843 0.00017 +-0.000611179974 -1.26000014e-05 0.000252065074 -0.924295604 -0.0190551504 0.381201357 0.102018 0.00017 +-0.000611652096 0 0.00025233769 -0.924421966 0 0.3813712 0.102018 0.00017 +-0.000611179974 1.26000014e-05 0.000252065074 -0.924295604 0.0190551504 0.381201357 0.102843 0.00017 +-0.00060975278 2.52000009e-05 0.000251241087 -0.923914909 0.0381837636 0.380687714 0.104568 0.00017 +-0.000607337104 3.78000004e-05 0.000249846373 -0.923275113 0.0574636385 0.379816979 0.107301 0.00017 +-0.00060387241 5.04000018e-05 0.000247846037 -0.922367632 0.0769820437 0.378565371 0.111288 0.00017 +-0.000601881125 5.67000061e-05 0.000259296357 -0.914980948 0.0861954689 0.394182891 0.108206 0.00017 +-0.000598840881 6.30000068e-05 0.000270141114 -0.907380819 0.0954594091 0.40932554 0.105806 0.00017 +-0.000594812038 6.92999965e-05 0.000280415057 -0.899542212 0.104803309 0.424075454 0.103996 0.00017 +-0.00058982824 7.56000009e-05 0.000290137687 -0.891438425 0.11425826 0.438500345 0.102742 0.00017 +-0.000583900197 8.19000052e-05 0.000299315085 -0.883040011 0.123858467 0.452658176 0.102034 0.00017 +-0.000577017025 8.82000022e-05 0.000307941082 -0.874312758 0.133643165 0.466601163 0.10191 0.00017 +-0.00056914537 9.45000065e-05 0.000315996382 -0.865215957 0.143659115 0.480378389 0.102444 0.00017 +-0.000560224697 0.000100800004 0.00032344606 -0.855699182 0.153964087 0.494038433 0.103784 0.00017 +-0.000558233412 9.44999992e-05 0.00033489638 -0.848627687 0.143659115 0.509110212 0.097762 0.00017 +-0.000555193168 8.82000095e-05 0.000345741108 -0.841244578 0.13364318 0.523876846 0.0927979 0.00017 +-0.000551164383 8.19000052e-05 0.00035601508 -0.833533227 0.123858474 0.538406372 0.0886209 0.00017 +-0.000546180585 7.56000009e-05 0.000365737651 -0.825471342 0.114258252 0.552758515 0.0850418 0.00017 +-0.000540252484 6.92999965e-05 0.000374915078 -0.817031026 0.104803309 0.566989064 0.0819487 0.00017 +-0.000533369312 6.30000068e-05 0.000383541104 -0.808176517 0.0954594091 0.581152439 0.079242 0.00017 +-0.000525497657 5.67000025e-05 0.000391596404 -0.798862636 0.0861954615 0.595305681 0.0768575 0.00017 +-0.000516576984 5.04000018e-05 0.000399046054 -0.789030731 0.0769820437 0.609511495 0.0747255 0.00017 +-0.000520041678 3.78000041e-05 0.000401046389 -0.790568411 0.0574636459 0.609671533 0.07214 0.00017 +-0.000522457412 2.51999991e-05 0.000402441103 -0.791642427 0.0381837599 0.609790325 0.0703664 0.00017 +-0.000523884548 1.26000014e-05 0.00040326509 -0.792277575 0.0190551504 0.609863162 0.0692587 0.00017 +-0.00052435667 0 0.000403537677 -0.79248786 0 0.609887719 0.0687318 0.00017 +-0.000523884548 -1.26000014e-05 0.00040326509 -0.792277575 -0.0190551504 0.609863162 0.0687318 0.00017 +-0.000522457412 -2.52000009e-05 0.000402441103 -0.791642427 -0.0381837636 0.609790325 0.0692587 0.00017 +-0.000520041678 -3.78000004e-05 0.000401046389 -0.790568411 -0.0574636385 0.609671533 0.0703664 0.00017 +-0.000516576984 -5.04000018e-05 0.000399046054 -0.789030731 -0.0769820437 0.609511495 0.07214 0.00017 +-0.000525497657 -5.67000061e-05 0.000391596404 -0.798862636 -0.0861954689 0.595305681 0.0740233 0.00017 +-0.000533369312 -6.30000068e-05 0.000383541104 -0.808176517 -0.0954594091 0.581152439 0.0761295 0.00017 +-0.000540252484 -6.92999965e-05 0.000374915078 -0.817031026 -0.104803309 0.566989064 0.0784846 0.00017 +-0.000546180585 -7.56000009e-05 0.000365737651 -0.825471342 -0.114258252 0.552758515 0.0811455 0.00017 +-0.000551164383 -8.19000052e-05 0.00035601508 -0.833533227 -0.123858474 0.538406372 0.0841789 0.00017 +-0.000555193168 -8.82000022e-05 0.000345741108 -0.841244578 -0.133643165 0.523876846 0.0876682 0.00017 +-0.000558233412 -9.45000065e-05 0.00033489638 -0.848627687 -0.14365913 0.509110212 0.0917439 0.00017 +-0.000560224697 -0.000100800004 0.00032344606 -0.855699182 -0.153964087 0.494038433 0.0965829 0.00017 +-0.00056914537 -9.44999992e-05 0.000315996382 -0.865215957 -0.1436591 0.480378389 0.0961127 0.00017 +-0.000577017025 -8.82000095e-05 0.000307941082 -0.874312758 -0.13364318 0.466601163 0.0962267 0.00017 +-0.000583900197 -8.19000052e-05 0.000299315085 -0.883040011 -0.123858467 0.452658176 0.0968425 0.00017 +-0.00058982824 -7.56000009e-05 0.000290137687 -0.891438425 -0.11425826 0.438500345 0.097936 0.00017 +-0.000594812038 -6.92999965e-05 0.000280415057 -0.899542212 -0.104803309 0.424075454 0.0994883 0.00017 +-0.000598840881 -6.30000068e-05 0.000270141114 -0.907380819 -0.0954594091 0.40932554 0.10153 0.00017 +-0.000601881125 -5.67000025e-05 0.000259296357 -0.914980948 -0.0861954615 0.394182891 0.104101 0.00017 +-0.000600459462 -5.67000025e-05 0.000233275598 -0.92853874 -0.0876797661 0.360732794 0.115173 0.00017 +-0.000604719098 -4.41000047e-05 0.000235734886 -0.929566324 -0.0677899569 0.362368613 0.111254 0.00017 +-0.000607812137 -3.1500007e-05 0.000237520653 -0.93032527 -0.0482143238 0.363552243 0.108685 0.00017 +-0.000609829498 -1.89000002e-05 0.000238685374 -0.930825889 -0.0288484059 0.364322364 0.107223 0.00017 +-0.000610825431 -6.3000025e-06 0.000239260422 -0.931074679 -0.00960302632 0.364702106 0.106743 0.00017 +-0.000610825431 6.29999886e-06 0.000239260422 -0.931074679 0.00960302074 0.364702106 0.107223 0.00017 +-0.000609829498 1.89000002e-05 0.000238685374 -0.930825889 0.0288484059 0.364322364 0.108685 0.00017 +-0.000607812137 3.14999997e-05 0.000237520653 -0.93032527 0.0482143126 0.363552243 0.111254 0.00017 +-0.000604719098 4.41000011e-05 0.000235734886 -0.929566324 0.0677899495 0.362368613 0.115173 0.00017 +-0.000600459462 5.67000025e-05 0.000233275598 -0.92853874 0.0876797661 0.360732794 0.120833 0.00017 +-0.00059926312 6.30000068e-05 0.00024518487 -0.921179533 0.0968427956 0.37689504 0.116929 0.00017 +-0.00059690018 6.93000038e-05 0.000256420637 -0.913623393 0.106071517 0.39248082 0.113923 0.00017 +-0.00059346162 7.56000009e-05 0.000267035386 -0.905842483 0.115393639 0.407595009 0.111692 0.00017 +-0.000589001575 8.19000052e-05 0.000277060404 -0.89780885 0.124839313 0.422320247 0.110165 0.00017 +-0.000583545596 8.82000095e-05 0.000286510418 -0.889492393 0.134442344 0.436724812 0.109297 0.00017 +-0.000577093742 9.44999992e-05 0.000295385369 -0.880859077 0.144242048 0.450867623 0.109141 0.00017 +-0.000569620403 0.000100800004 0.000303670618 -0.87186861 0.154285833 0.464802325 0.109753 0.00017 +-0.000561071385 0.000107100008 0.000311334879 -0.8624717 0.164632753 0.478579998 0.111314 0.00017 +-0.000551355828 0.000113400005 0.00031832559 -0.85260576 0.175359532 0.492252439 0.114095 0.00017 +-0.000550159428 0.000107100001 0.000330234878 -0.845697999 0.164632738 0.507632792 0.106176 0.00017 +-0.000547796488 0.000100800004 0.000341470644 -0.838464677 0.154285833 0.52265954 0.0998705 0.00017 +-0.000544357928 9.44999992e-05 0.000352085364 -0.830892026 0.144242048 0.537412822 0.0947032 0.00017 +-0.000539897941 8.82000022e-05 0.000362110382 -0.822960675 0.134442315 0.551961005 0.0903717 0.00017 +-0.000534441962 8.19000052e-05 0.000371560425 -0.814644158 0.124839298 0.56636554 0.0866985 0.00017 +-0.000527990051 7.56000009e-05 0.000380435376 -0.80590862 0.115393639 0.580685437 0.0835216 0.00017 +-0.000520516711 6.92999965e-05 0.000388720655 -0.796709776 0.106071495 0.594980955 0.0807891 0.00017 +-0.000511967693 6.29999995e-05 0.000396384887 -0.786990166 0.0968427882 0.60931772 0.078378 0.00017 +-0.000502252136 5.67000025e-05 0.000403375598 -0.776672781 0.0876797661 0.623772085 0.0762658 0.00017 +-0.000506511715 4.41000047e-05 0.000405834871 -0.778603315 0.0677899569 0.623844147 0.0728366 0.00017 +-0.000509604753 3.1500007e-05 0.000407620624 -0.780007899 0.0482143275 0.623909593 0.0704606 0.00017 +-0.000511622173 1.89000002e-05 0.000408785359 -0.780925095 0.0288484097 0.623958051 0.0688953 0.00017 +-0.000512618106 6.3000025e-06 0.000409360393 -0.781378329 0.00960302725 0.623983741 0.0680017 0.00017 +-0.000512618106 -6.29999886e-06 0.000409360393 -0.781378329 -0.00960302167 0.623983741 0.0677125 0.00017 +-0.000511622173 -1.89000002e-05 0.000408785359 -0.780925095 -0.0288484097 0.623958051 0.0680017 0.00017 +-0.000509604753 -3.14999997e-05 0.000407620624 -0.780007899 -0.0482143164 0.623909593 0.0688953 0.00017 +-0.000506511715 -4.41000011e-05 0.000405834871 -0.778603315 -0.0677899495 0.623844147 0.0704606 0.00017 +-0.000502252136 -5.67000025e-05 0.000403375598 -0.776672781 -0.0876797661 0.623772085 0.0728366 0.00017 +-0.000511967693 -6.30000068e-05 0.000396384887 -0.786990166 -0.0968427956 0.60931772 0.0747255 0.00017 +-0.000520516711 -6.93000038e-05 0.000388720655 -0.796709776 -0.106071509 0.594980955 0.0768575 0.00017 +-0.000527990051 -7.56000009e-05 0.000380435376 -0.80590862 -0.115393639 0.580685437 0.079242 0.00017 +-0.000534441962 -8.19000052e-05 0.000371560425 -0.814644158 -0.124839298 0.56636554 0.0819487 0.00017 +-0.000539897941 -8.82000095e-05 0.000362110382 -0.822960675 -0.134442329 0.551961005 0.0850486 0.00017 +-0.000544357928 -9.44999992e-05 0.000352085364 -0.830892026 -0.144242048 0.537412822 0.0886209 0.00017 +-0.000547796488 -0.000100800004 0.000341470644 -0.838464677 -0.154285833 0.52265954 0.0927979 0.00017 +-0.000550159428 -0.000107100008 0.000330234878 -0.845697999 -0.164632753 0.507632792 0.097759 0.00017 +-0.000551355828 -0.000113400005 0.00031832559 -0.85260576 -0.175359532 0.492252439 0.103784 0.00017 +-0.000561071385 -0.000107100001 0.000311334879 -0.8624717 -0.164632738 0.478579998 0.102444 0.00017 +-0.000569620403 -0.000100800004 0.000303670618 -0.87186861 -0.154285833 0.464802325 0.101907 0.00017 +-0.000577093742 -9.44999992e-05 0.000295385369 -0.880859077 -0.144242048 0.450867623 0.102034 0.00017 +-0.000583545596 -8.82000022e-05 0.000286510418 -0.889492393 -0.134442329 0.436724812 0.102742 0.00017 +-0.000589001575 -8.19000052e-05 0.000277060404 -0.89780885 -0.124839313 0.422320247 0.103996 0.00017 +-0.00059346162 -7.56000009e-05 0.000267035386 -0.905842483 -0.115393639 0.407595009 0.105806 0.00017 +-0.00059690018 -6.92999965e-05 0.000256420637 -0.913623393 -0.106071502 0.39248082 0.108206 0.00017 +-0.00059926312 -6.29999995e-05 0.00024518487 -0.921179533 -0.0968427882 0.37689504 0.111288 0.00017 +-0.000595065823 -6.30000068e-05 0.000217561537 -0.934588134 -0.0989454538 0.341694027 0.125893 0.00017 +-0.000600346131 -5.03999981e-05 0.000220610134 -0.935731232 -0.0785561055 0.343854636 0.120073 0.00017 +-0.000604274799 -3.78000004e-05 0.000222878356 -0.936605036 -0.0585886948 0.345453769 0.116178 0.00017 +-0.000606995658 -2.52000027e-05 0.000224449279 -0.937221646 -0.0389096476 0.3465572 0.113778 0.00017 +-0.00060859666 -1.25999977e-05 0.000225373587 -0.937588394 -0.0194112342 0.347204775 0.112631 0.00017 +-0.000609125243 0 0.00022567877 -0.937710285 0 0.347418368 0.112631 0.00017 +-0.00060859666 1.26000014e-05 0.000225373587 -0.937588394 0.0194112398 0.347204775 0.113778 0.00017 +-0.000606995658 2.52000027e-05 0.000224449279 -0.937221646 0.0389096476 0.3465572 0.116178 0.00017 +-0.000604274799 3.78000004e-05 0.000222878356 -0.936605036 0.0585886948 0.345453769 0.120073 0.00017 +-0.000600346131 5.04000018e-05 0.000220610134 -0.935731232 0.0785561129 0.343854636 0.125891 0.00017 +-0.000595065823 6.30000068e-05 0.000217561537 -0.934588134 0.0989454538 0.341694027 0.134451 0.00017 +-0.000594890153 6.92999965e-05 0.000230060148 -0.927227259 0.108014643 0.358583897 0.128972 0.00017 +-0.000593362842 7.56000009e-05 0.000241778354 -0.919691861 0.11717739 0.374748081 0.124901 0.00017 +-0.00059062778 8.19000052e-05 0.000252799276 -0.911949039 0.12645635 0.390330553 0.121936 0.00017 +-0.000586772745 8.82000095e-05 0.000263173599 -0.903967142 0.135878682 0.405438513 0.119912 0.00017 +-0.00058184535 9.45000065e-05 0.000272928766 -0.895714641 0.145476863 0.420156777 0.118765 0.00017 +-0.000575860846 0.000100800004 0.000282073597 -0.887156487 0.155289918 0.434555382 0.118503 0.00017 +-0.000568803924 0.000107100008 0.000290599273 -0.878252149 0.165365964 0.448694915 0.119202 0.00017 +-0.000560627086 0.000113400005 0.00029847835 -0.868952632 0.175766096 0.462631166 0.121062 0.00017 +-0.00055124244 0.000119700002 0.000305660156 -0.85919565 0.186570764 0.476418078 0.124427 0.00017 +-0.000540506153 0.000126000014 0.000312061544 -0.848898828 0.197890922 0.490112215 0.129962 0.00017 +-0.000540330482 0.000119700002 0.000324560126 -0.842187762 0.186570778 0.505876601 0.118629 0.00017 +-0.000538803171 0.000113400012 0.000336278375 -0.8351264 0.17576611 0.521219909 0.110065 0.00017 +-0.00053606811 0.000107100008 0.000347299268 -0.827707112 0.165365994 0.53624171 0.103316 0.00017 +-0.000532213191 0.000100800004 0.000357673562 -0.819913983 0.155289903 0.551022708 0.0978446 0.00017 +-0.000527285796 9.45000065e-05 0.000367428758 -0.81172353 0.145476863 0.565633655 0.0933065 0.00017 +-0.000521301234 8.82000095e-05 0.000376573589 -0.803103387 0.135878682 0.580139637 0.089499 0.00017 +-0.000514244311 8.19000052e-05 0.000385099236 -0.794010401 0.12645635 0.594606102 0.0862747 0.00017 +-0.000506067416 7.56000009e-05 0.000392978371 -0.784387052 0.117177397 0.609102905 0.0835251 0.00017 +-0.000496682769 6.93000038e-05 0.000400160119 -0.774156153 0.108014666 0.623710811 0.0811988 0.00017 +-0.000485946541 6.30000068e-05 0.000406561507 -0.763209522 0.0989454612 0.638530374 0.0792893 0.00017 +-0.000491226849 5.03999981e-05 0.000409610104 -0.765652239 0.0785561129 0.638440073 0.0744431 0.00017 +-0.000495155517 3.78000004e-05 0.000411878369 -0.767473936 0.0585886948 0.638397217 0.0711493 0.00017 +-0.000497876375 2.52000027e-05 0.000413449248 -0.768737793 0.0389096476 0.638379455 0.0689372 0.00017 +-0.000499477377 1.25999977e-05 0.000414373586 -0.769482076 0.0194112342 0.638373375 0.0675761 0.00017 +-0.000500005903 0 0.000414678769 -0.769727945 0 0.638372123 0.0669153 0.00017 +-0.000499477377 -1.26000014e-05 0.000414373586 -0.769482076 -0.0194112416 0.638373375 0.0669153 0.00017 +-0.000497876375 -2.52000027e-05 0.000413449248 -0.768737793 -0.0389096476 0.638379455 0.0675761 0.00017 +-0.000495155517 -3.78000004e-05 0.000411878369 -0.767473936 -0.0585886948 0.638397217 0.0689372 0.00017 +-0.000491226849 -5.04000018e-05 0.000409610104 -0.765652239 -0.0785561204 0.638440073 0.0711493 0.00017 +-0.000485946541 -6.30000068e-05 0.000406561507 -0.763209522 -0.0989454612 0.638530374 0.0744431 0.00017 +-0.000496682769 -6.92999965e-05 0.000400160119 -0.774156153 -0.108014658 0.623710811 0.0762658 0.00017 +-0.000506067416 -7.56000009e-05 0.000392978371 -0.784387052 -0.117177397 0.609102905 0.078378 0.00017 +-0.000514244311 -8.19000052e-05 0.000385099236 -0.794010401 -0.12645635 0.594606102 0.0807891 0.00017 +-0.000521301234 -8.82000095e-05 0.000376573589 -0.803103387 -0.135878682 0.580139637 0.0835216 0.00017 +-0.000527285796 -9.45000065e-05 0.000367428758 -0.81172353 -0.145476863 0.565633655 0.0866985 0.00017 +-0.000532213191 -0.000100800004 0.000357673562 -0.819913983 -0.155289903 0.551022708 0.0903749 0.00017 +-0.00053606811 -0.000107100008 0.000347299268 -0.827707112 -0.165365994 0.53624171 0.0947032 0.00017 +-0.000538803171 -0.000113400005 0.000336278375 -0.8351264 -0.175766096 0.521219909 0.0998705 0.00017 +-0.000540330482 -0.000119700002 0.000324560126 -0.842187762 -0.186570778 0.505876601 0.106176 0.00017 +-0.000540506153 -0.000126000014 0.000312061544 -0.848898828 -0.197890922 0.490112215 0.114095 0.00017 +-0.00055124244 -0.000119700002 0.000305660156 -0.85919565 -0.186570764 0.476418078 0.111314 0.00017 +-0.000560627086 -0.000113400012 0.00029847835 -0.868952632 -0.17576611 0.462631166 0.109753 0.00017 +-0.000568803924 -0.000107100008 0.000290599273 -0.878252149 -0.165365964 0.448694915 0.109141 0.00017 +-0.000575860846 -0.000100800004 0.000282073597 -0.887156487 -0.155289918 0.434555382 0.109297 0.00017 +-0.00058184535 -9.45000065e-05 0.000272928766 -0.895714641 -0.145476863 0.420156777 0.110165 0.00017 +-0.000586772745 -8.82000095e-05 0.000263173599 -0.903967142 -0.135878682 0.405438513 0.111692 0.00017 +-0.00059062778 -8.19000052e-05 0.000252799276 -0.911949039 -0.12645635 0.390330553 0.113923 0.00017 +-0.000593362842 -7.56000009e-05 0.000241778354 -0.919691861 -0.11717739 0.374748081 0.116929 0.00017 +-0.000594890153 -6.93000038e-05 0.000230060148 -0.927227259 -0.108014658 0.358583897 0.120833 0.00017 +-0.000586938288 -6.93000038e-05 0.000200269176 -0.940569043 -0.11105331 0.320931494 0.141868 0.00017 +-0.00059365714 -5.67000025e-05 0.000204148266 -0.941814482 -0.0899523944 0.32387346 0.132504 0.00017 +-0.000598697807 -4.40999975e-05 0.000207058474 -0.942793727 -0.0694460496 0.326063365 0.126342 0.00017 +-0.000602312619 -3.14999997e-05 0.000209145524 -0.94351846 -0.0493445247 0.327625006 0.122418 0.00017 +-0.000604652101 -1.89000002e-05 0.000210496204 -0.943997145 -0.0295071285 0.328631639 0.120224 0.00017 +-0.00060580211 -6.29999522e-06 0.000211160135 -0.944235206 -0.00981950574 0.329125345 0.119514 0.00017 +-0.00060580211 6.3000025e-06 0.000211160135 -0.944235206 0.00981951784 0.329125345 0.120224 0.00017 +-0.000604652101 1.89000039e-05 0.000210496204 -0.943997145 0.0295071341 0.328631639 0.122418 0.00017 +-0.000602312619 3.1500007e-05 0.000209145524 -0.94351846 0.0493445359 0.327625006 0.126342 0.00017 +-0.000598697807 4.41000047e-05 0.000207058474 -0.942793727 0.0694460645 0.326063365 0.132504 0.00017 +-0.00059365714 5.67000061e-05 0.000204148266 -0.941814482 0.0899524018 0.32387346 0.141868 0.00017 +-0.000586938288 6.93000038e-05 0.000200269176 -0.940569043 0.11105331 0.320931494 0.156394 0.00017 +-0.000588201219 7.56000009e-05 0.00021359828 -0.933158815 0.119936526 0.338865548 0.147317 0.00017 +-0.000587785849 8.19000052e-05 0.000225958473 -0.925610244 0.128971264 0.35582599 0.140972 0.00017 +-0.000585944741 8.82000095e-05 0.000237495522 -0.917878211 0.138164684 0.372035027 0.136513 0.00017 +-0.000582828186 9.45000065e-05 0.000248296186 -0.909925222 0.147535667 0.38764593 0.133531 0.00017 +-0.000578522217 0.000100800004 0.000258410146 -0.901715457 0.157112241 0.402771741 0.131816 0.00017 +-0.000573066238 0.000107100001 0.00026786013 -0.893211484 0.166931748 0.417501003 0.131314 0.00017 +-0.00056646025 0.000113400012 0.000276646198 -0.884371281 0.177042797 0.431906641 0.132096 0.00017 +-0.000558664964 0.000119700002 0.000284745533 -0.87514466 0.187509194 0.446051836 0.134393 0.00017 +-0.000549594115 0.000126000014 0.000292108452 -0.865468204 0.198417321 0.459995031 0.138678 0.00017 +-0.000539097528 0.000132300018 0.000298648287 -0.85525775 0.20988895 0.473794162 0.145887 0.00017 +-0.000526922755 0.000138600008 0.000304219167 -0.844394028 0.222106621 0.487511426 0.0821597 0.00017 +-0.00052818557 0.000132300018 0.000317548256 -0.837946355 0.20988895 0.503778279 0.138999 0.00017 +-0.000527770258 0.000126000014 0.000329908478 -0.831101239 0.198417321 0.519520283 0.125937 0.00017 +-0.000525929034 0.000119700009 0.000341445499 -0.823864162 0.187509224 0.534871936 0.1163 0.00017 +-0.000522812654 0.000113400012 0.000352246192 -0.816227496 0.177042797 0.549935102 0.108863 0.00017 +-0.000518506684 0.000107100015 0.000362360151 -0.808171928 0.166931748 0.564793706 0.102936 0.00017 +-0.000513050705 0.000100800011 0.000371810136 -0.799667954 0.157112241 0.579522967 0.0981332 0.00017 +-0.000506444718 9.45000065e-05 0.000380596175 -0.790673494 0.147535652 0.594195783 0.0942175 0.00017 +-0.000498649315 8.82000095e-05 0.000388695538 -0.781130612 0.138164684 0.608888745 0.0910144 0.00017 +-0.000489578524 8.19000124e-05 0.000396058458 -0.770959139 0.128971279 0.623689353 0.0884579 0.00017 +-0.000479081908 7.56000081e-05 0.000402598293 -0.76004529 0.119936548 0.638706923 0.0865486 0.00017 +-0.000466907135 6.93000038e-05 0.000408169173 -0.748218954 0.111053303 0.654091358 0.085421 0.00017 +-0.000473625958 5.67000025e-05 0.000412048277 -0.751389623 0.0899524018 0.653698921 0.0778015 0.00017 +-0.000478666596 4.40999975e-05 0.000414958457 -0.753775716 0.0694460496 0.65345192 0.0728762 0.00017 +-0.000482281437 3.14999997e-05 0.000417045521 -0.755490422 0.049344521 0.653298855 0.0696368 0.00017 +-0.000484620861 1.89000002e-05 0.000418396201 -0.756601632 0.0295071304 0.653210104 0.067559 0.00017 +-0.00048577087 6.29999522e-06 0.000419060118 -0.757148266 0.00981950667 0.653169334 0.0664002 0.00017 +-0.00048577087 -6.3000025e-06 0.000419060118 -0.757148266 -0.00981951784 0.653169334 0.0660342 0.00017 +-0.000484620861 -1.89000039e-05 0.000418396201 -0.756601632 -0.029507136 0.653210104 0.0664002 0.00017 +-0.000482281437 -3.1500007e-05 0.000417045521 -0.755490422 -0.0493445322 0.653298855 0.067559 0.00017 +-0.000478666596 -4.41000047e-05 0.000414958457 -0.753775716 -0.0694460645 0.65345192 0.0696368 0.00017 +-0.000473625958 -5.67000061e-05 0.000412048277 -0.751389623 -0.0899524093 0.653698921 0.0728762 0.00017 +-0.000466907135 -6.93000038e-05 0.000408169173 -0.748218954 -0.111053303 0.654091358 0.0778015 0.00017 +-0.000479081908 -7.56000009e-05 0.000402598293 -0.76004529 -0.119936533 0.638706923 0.0792893 0.00017 +-0.000489578524 -8.19000052e-05 0.000396058458 -0.770959139 -0.128971264 0.623689353 0.0811988 0.00017 +-0.000498649315 -8.82000095e-05 0.000388695538 -0.781130612 -0.138164684 0.608888745 0.0835251 0.00017 +-0.000506444718 -9.45000065e-05 0.000380596175 -0.790673494 -0.147535652 0.594195783 0.0862747 0.00017 +-0.000513050705 -0.000100800004 0.000371810136 -0.799667954 -0.157112226 0.579522967 0.089499 0.00017 +-0.000518506684 -0.000107100001 0.000362360151 -0.808171928 -0.166931733 0.564793706 0.0933065 0.00017 +-0.000522812654 -0.000113400012 0.000352246192 -0.816227496 -0.177042797 0.549935102 0.0978446 0.00017 +-0.000525929092 -0.000119700002 0.000341445528 -0.823864281 -0.187509209 0.534871995 0.103319 0.00017 +-0.000527770258 -0.000126000014 0.000329908478 -0.831101239 -0.198417321 0.519520283 0.110065 0.00017 +-0.00052818557 -0.000132300018 0.000317548256 -0.837946355 -0.20988895 0.503778279 0.118629 0.00017 +-0.000526922755 -0.000138600008 0.000304219167 -0.844394028 -0.222106621 0.487511426 0.129962 0.00017 +-0.000539097528 -0.000132300018 0.000298648287 -0.85525775 -0.20988895 0.473794162 0.124427 0.00017 +-0.000549594115 -0.000126000014 0.000292108452 -0.865468204 -0.198417321 0.459995031 0.121062 0.00017 +-0.000558664906 -0.000119700009 0.000284745503 -0.875144601 -0.187509224 0.446051806 0.119202 0.00017 +-0.00056646025 -0.000113400012 0.000276646198 -0.884371281 -0.177042797 0.431906641 0.118503 0.00017 +-0.000573066238 -0.000107100015 0.00026786013 -0.893211484 -0.166931763 0.417501003 0.118765 0.00017 +-0.000578522217 -0.000100800011 0.000258410146 -0.901715398 -0.157112241 0.402771711 0.119909 0.00017 +-0.000582828186 -9.45000065e-05 0.000248296186 -0.909925222 -0.147535667 0.38764593 0.121936 0.00017 +-0.000585944741 -8.82000095e-05 0.000237495522 -0.917878211 -0.138164684 0.372035027 0.124901 0.00017 +-0.000587785849 -8.19000124e-05 0.000225958473 -0.925610244 -0.128971279 0.35582599 0.128969 0.00017 +-0.000588201219 -7.56000081e-05 0.00021359828 -0.933158815 -0.119936541 0.338865548 0.134455 0.00017 +-0.000583555724 -6.30000141e-05 0.000185716257 -0.947904348 -0.102334678 0.301669985 0.152268 0.00017 +-0.00059027283 -5.04000054e-05 0.000189594342 -0.948961973 -0.0810264125 0.304804504 0.141399 0.00017 +-0.000595143356 -3.78000004e-05 0.000192406369 -0.949777186 -0.0603242554 0.30705741 0.13459 0.00017 +-0.000598463463 -2.52000027e-05 0.00019432322 -0.950355113 -0.0400173999 0.308583707 0.130544 0.00017 +-0.000600398751 -1.2600005e-05 0.000195440574 -0.950699985 -0.0199514478 0.309469908 0.128658 0.00017 +-0.000601035019 0 0.000195807908 -0.950814545 0 0.30976066 0.128658 0.00017 +-0.000600398751 1.25999977e-05 0.000195440574 -0.950699985 0.0199514367 0.309469908 0.130547 0.00017 +-0.000598463463 2.51999991e-05 0.00019432322 -0.950355113 0.0400173925 0.308583707 0.13459 0.00017 +-0.000595143356 3.78000004e-05 0.000192406369 -0.949777186 0.0603242554 0.30705741 0.141399 0.00017 +-0.00059027283 5.03999981e-05 0.000189594342 -0.948961973 0.0810264051 0.304804504 0.152268 0.00017 +-0.000583555724 6.30000068e-05 0.000185716257 -0.947904348 0.102334663 0.301669985 0.152268 0.00017 +-0.000578099862 8.19000052e-05 0.000195166271 -0.939042032 0.133035049 0.317020178 0.156394 0.00017 +-0.000579360931 8.82000095e-05 0.000208494326 -0.931419313 0.141796216 0.335189402 0.168001 0.00017 +-0.000578775478 9.44999992e-05 0.000220756367 -0.923656046 0.150810644 0.352300614 0.1598 0.00017 +-0.000576639606 0.000100800004 0.000232123202 -0.915699005 0.160069585 0.368609756 0.154536 0.00017 +-0.000573118974 0.000107100008 0.000242690556 -0.907503784 0.16958724 0.384287775 0.15148 0.00017 +-0.000568299263 0.000113400005 0.000252507918 -0.899027765 0.179394484 0.399457902 0.150351 0.00017 +-0.000562207075 0.000119700002 0.000261590583 -0.890225291 0.189538658 0.414214909 0.151155 0.00017 +-0.00055481575 0.000126000014 0.000269923214 -0.881042898 0.200086996 0.428635895 0.15417 0.00017 +-0.000546039781 0.000132299989 0.000277456391 -0.871413648 0.211134836 0.442786932 0.160125 0.00017 +-0.000535713218 0.000138600008 0.000284094305 -0.861248374 0.222822636 0.456728995 0.0988948 0.00017 +-0.000523540191 0.000144900012 0.000289666263 -0.850417495 0.235369742 0.470522165 0.0893505 0.00017 +-0.000512628292 0.000144899997 0.000308566261 -0.832692623 0.235369697 0.501222551 0.0976556 0.00017 +-0.000513889361 0.000138599993 0.000321894331 -0.826162815 0.222822607 0.517498851 0.0717591 0.00017 +-0.000513303967 0.000132299989 0.000334156386 -0.819171309 0.211134866 0.533273339 0.138266 0.00017 +-0.000511168095 0.000126000014 0.000345523207 -0.811730683 0.200086981 0.548687994 0.126725 0.00017 +-0.000507647463 0.000119700002 0.000356090604 -0.803833067 0.189538658 0.563850701 0.118142 0.00017 +-0.000502827752 0.000113400005 0.000365907908 -0.795454323 0.179394484 0.578852355 0.111573 0.00017 +-0.000496735564 0.000107100001 0.000374990603 -0.786554575 0.16958721 0.593777895 0.106483 0.00017 +-0.00048934418 0.000100799996 0.000383323204 -0.777074575 0.16006957 0.608714104 0.102593 0.00017 +-0.000480568124 9.44999992e-05 0.000390856352 -0.766928911 0.150810644 0.623759687 0.0998011 0.00017 +-0.000470241648 8.82000022e-05 0.000397494325 -0.755991876 0.141796201 0.639038444 0.0981802 0.00017 +-0.000458068651 8.18999979e-05 0.000403066253 -0.744068205 0.133035034 0.654724538 0.0734442 0.00017 +-0.000452612643 6.30000141e-05 0.000412516238 -0.73520571 0.102334678 0.670074701 0.0810779 0.00017 +-0.00045932972 5.04000054e-05 0.000416394323 -0.738449097 0.0810264125 0.669423282 0.0768838 0.00017 +-0.000464200246 3.78000004e-05 0.000419206335 -0.740807772 0.0603242554 0.669002891 0.0716182 0.00017 +-0.000467520353 2.52000027e-05 0.000421123201 -0.742418528 0.0400173999 0.668740213 0.068315 0.00017 +-0.000469455641 1.2600005e-05 0.000422240555 -0.743358374 0.019951446 0.668595731 0.066348 0.00017 +-0.000470091938 0 0.000422607874 -0.743667543 0 0.668549597 0.0654152 0.00017 +-0.000469455641 -1.25999977e-05 0.000422240555 -0.743358374 -0.0199514348 0.668595731 0.0654152 0.00017 +-0.000467520353 -2.51999991e-05 0.000421123201 -0.742418528 -0.0400173925 0.668740213 0.066348 0.00017 +-0.000464200246 -3.78000004e-05 0.000419206335 -0.740807772 -0.0603242554 0.669002891 0.068315 0.00017 +-0.00045932972 -5.03999981e-05 0.000416394323 -0.738449097 -0.0810264051 0.669423282 0.0716182 0.00017 +-0.000452612643 -6.30000068e-05 0.000412516238 -0.73520571 -0.102334663 0.670074701 0.0768838 0.00017 +-0.000458068651 -8.19000052e-05 0.000403066253 -0.744068205 -0.133035049 0.654724538 0.085421 0.00017 +-0.000470241648 -8.82000095e-05 0.000397494325 -0.755991876 -0.141796216 0.639038444 0.0865419 0.00017 +-0.000480568124 -9.44999992e-05 0.000390856352 -0.766928911 -0.150810644 0.623759687 0.0884579 0.00017 +-0.00048934418 -0.000100800004 0.000383323204 -0.777074575 -0.16006957 0.608714104 0.0910144 0.00017 +-0.000496735505 -0.000107100008 0.000374990545 -0.786554575 -0.16958724 0.593777835 0.0942175 0.00017 +-0.000502827752 -0.000113400005 0.000365907908 -0.795454323 -0.179394484 0.578852355 0.0981332 0.00017 +-0.000507647463 -0.000119700002 0.000356090604 -0.803833067 -0.189538658 0.563850701 0.102936 0.00017 +-0.000511168095 -0.000126000014 0.000345523207 -0.811730683 -0.200086981 0.548687994 0.108863 0.00017 +-0.000513303967 -0.000132299989 0.000334156386 -0.819171309 -0.211134866 0.533273339 0.116302 0.00017 +-0.000513889361 -0.000138600008 0.000321894331 -0.826162815 -0.222822636 0.517498851 0.125935 0.00017 +-0.000512628234 -0.000144900012 0.000308566232 -0.832692623 -0.235369742 0.501222551 0.138999 0.00017 +-0.000508970174 -0.000151200002 0.000293854246 -0.838713467 -0.249156997 0.48423174 0.158004 0.00017 +-0.00052354025 -0.000144899997 0.000289666292 -0.850417554 -0.235369697 0.470522195 0.145883 0.00017 +-0.000535713218 -0.000138599993 0.000284094305 -0.861248374 -0.222822607 0.456728995 0.138678 0.00017 +-0.000546039781 -0.000132299989 0.000277456391 -0.871413648 -0.211134836 0.442786932 0.134391 0.00017 +-0.00055481575 -0.000126000014 0.000269923214 -0.881042898 -0.200086996 0.428635895 0.132096 0.00017 +-0.000562207075 -0.000119700002 0.000261590583 -0.890225291 -0.189538658 0.414214909 0.131314 0.00017 +-0.000568299263 -0.000113400005 0.000252507918 -0.899027765 -0.179394484 0.399457902 0.131816 0.00017 +-0.000573119032 -0.000107100001 0.000242690585 -0.907503784 -0.16958721 0.384287775 0.133531 0.00017 +-0.000576639606 -0.000100799996 0.000232123202 -0.915699005 -0.16006957 0.368609756 0.136513 0.00017 +-0.000578775478 -9.44999992e-05 0.000220756367 -0.923656046 -0.150810644 0.352300614 0.140972 0.00017 +-0.000579360931 -8.82000022e-05 0.000208494326 -0.931419313 -0.141796201 0.335189402 0.147319 0.00017 +-0.000578099862 -8.18999979e-05 0.000195166271 -0.939042032 -0.133035034 0.317020178 0.156394 0.00017 +-0.000584184425 -4.41000047e-05 0.000173479217 -0.956124306 -0.0721776932 0.283930361 0.15411 0.00017 +-0.000589011761 -3.14999997e-05 0.000176266272 -0.956766844 -0.0511673242 0.286319792 0.146002 0.00017 +-0.000592067197 -1.89000002e-05 0.000178030328 -0.957196295 -0.0305556711 0.287822008 0.141703 0.00017 +-0.000593551726 -6.3000025e-06 0.000178887421 -0.95741117 -0.0101620341 0.288549095 0.140354 0.00017 +-0.000593551726 6.3000025e-06 0.000178887421 -0.95741117 0.0101620341 0.288549095 0.141703 0.00017 +-0.000592067197 1.89000002e-05 0.000178030328 -0.957196295 0.0305556711 0.287822008 0.146002 0.00017 +-0.000589011761 3.15000034e-05 0.000176266272 -0.956766844 0.0511673279 0.286319792 0.15411 0.00017 +-0.000584184425 4.41000047e-05 0.000173479217 -0.956124306 0.0721776932 0.283930361 0.15411 0.00017 +-0.000567816605 0.000100800004 0.000201829214 -0.929335356 0.16497758 0.330330312 0.168001 0.00017 +-0.000567187904 0.000107100001 0.000214066284 -0.921317101 0.173968911 0.347720593 0.0360068 0.00017 +-0.00056478742 0.000113400005 0.000225280324 -0.91309303 0.183334023 0.364211172 0.0456583 0.00017 +-0.00056081597 0.000119700002 0.000235587417 -0.904607654 0.193078578 0.380007356 0.0532483 0.00017 +-0.000555359991 0.000126000014 0.00024503743 -0.895807147 0.203240618 0.39525044 0.0599371 0.00017 +-0.000548419484 0.000132300018 0.000253630336 -0.886630952 0.213889703 0.41004467 0.0664784 0.00017 +-0.000539908069 0.000138599993 0.00026131628 -0.877004802 0.225136235 0.424471587 0.0735698 0.00017 +-0.000529624871 0.000144899997 0.000267979223 -0.866827607 0.237155274 0.438596845 0.0820718 0.00017 +-0.000496889057 0.000144899997 0.000324679218 -0.813249528 0.237155274 0.531396747 0.109413 0.00017 +-0.000496260356 0.000138600008 0.000336916215 -0.806105256 0.225136265 0.547273099 0.0648437 0.00017 +-0.000493859872 0.000132300018 0.000348130328 -0.798424304 0.213889703 0.562823057 0.0608401 0.00017 +-0.00048988848 0.000126000014 0.000358437392 -0.790200174 0.203240603 0.578166902 0.059118 0.00017 +-0.000484432472 0.000119700002 0.000367887405 -0.781399548 0.193078578 0.593409956 0.0590545 0.00017 +-0.000477491994 0.000113400005 0.00037648034 -0.771962345 0.183334023 0.608656526 0.0603879 0.00017 +-0.000468980579 0.000107100008 0.000384166255 -0.761793077 0.173968911 0.624024153 0.0631576 0.00017 +-0.000458697323 0.000100800004 0.000390829227 -0.75074178 0.16497758 0.639663279 0.0676998 0.00017 +-0.000442329416 4.41000047e-05 0.00041917921 -0.72395277 0.0721776932 0.68606323 0.0922396 0.00017 +-0.000447156752 3.14999997e-05 0.000421966281 -0.726343334 0.0511673242 0.685424924 0.0707875 0.00017 +-0.000450212188 1.89000002e-05 0.000423730322 -0.727858961 0.0305556692 0.68504566 0.0671864 0.00017 +-0.000451696716 6.3000025e-06 0.000424587401 -0.728596091 0.0101620341 0.684868217 0.0652739 0.00017 +-0.000451696716 -6.3000025e-06 0.000424587401 -0.728596091 -0.0101620341 0.684868217 0.0646789 0.00017 +-0.000450212188 -1.89000002e-05 0.000423730322 -0.727858961 -0.0305556692 0.68504566 0.0652739 0.00017 +-0.000447156752 -3.15000034e-05 0.000421966281 -0.726343334 -0.0511673279 0.685424924 0.0671864 0.00017 +-0.000442329416 -4.41000047e-05 0.00041917921 -0.72395277 -0.0721776932 0.68606323 0.0707875 0.00017 +-0.000458697323 -0.000100800004 0.000390829227 -0.75074178 -0.16497758 0.639663279 0.0981802 0.00017 +-0.000468980579 -0.000107100001 0.000384166255 -0.761793077 -0.173968911 0.624024153 0.0998011 0.00017 +-0.000477491994 -0.000113400005 0.00037648034 -0.771962345 -0.183334023 0.608656526 0.102593 0.00017 +-0.000484432472 -0.000119700002 0.000367887405 -0.781399548 -0.193078578 0.593409956 0.106483 0.00017 +-0.00048988848 -0.000126000014 0.000358437392 -0.790200174 -0.203240603 0.578166902 0.111573 0.00017 +-0.000493859872 -0.000132300018 0.000348130328 -0.798424304 -0.213889703 0.562823057 0.118142 0.00017 +-0.000496260414 -0.000138599993 0.000336916244 -0.806105316 -0.225136235 0.547273099 0.126725 0.00017 +-0.000496889057 -0.000144899997 0.000324679218 -0.813249528 -0.237155274 0.531396747 0.138266 0.00017 +-0.000529624871 -0.000144899997 0.000267979223 -0.866827607 -0.237155274 0.438596845 0.160125 0.00017 +-0.000539908011 -0.000138600008 0.000261316251 -0.877004921 -0.225136295 0.424471647 0.154172 0.00017 +-0.000548419484 -0.000132300018 0.000253630336 -0.886630952 -0.213889703 0.41004467 0.151155 0.00017 +-0.000555359991 -0.000126000014 0.00024503743 -0.895807147 -0.203240618 0.39525044 0.150351 0.00017 +-0.00056081597 -0.000119700002 0.000235587417 -0.904607654 -0.193078578 0.380007356 0.15148 0.00017 +-0.00056478742 -0.000113400005 0.000225280324 -0.91309303 -0.183334023 0.364211172 0.154533 0.00017 +-0.000567187904 -0.000107100008 0.000214066284 -0.921317101 -0.173968911 0.347720593 0.159801 0.00017 +-0.000567816605 -0.000100800004 0.000201829214 -0.929335356 -0.16497758 0.330330312 0.168004 0.00017 +0.000588897266 0 0.000340000173 0.866025329 0 0.500000238 0.079482 0.00017 +0.000593948294 -6.30000022e-06 0.000330316368 0.873904049 -0.00926948711 0.486010015 0.0813195 0.00017 +0.000593948294 6.30000022e-06 0.000330316368 0.873904049 0.00926948711 0.486010015 0.081564 0.00017 +0.000588492316 1.26000004e-05 0.000339766382 0.865876496 0.0185389742 0.499914289 0.0799489 0.00017 +0.000583036337 6.30000022e-06 0.000349216367 0.857848823 0.00926948711 0.513818502 0.0779201 0.00017 +0.000583036337 -6.30000022e-06 0.000349216367 0.857848823 -0.00926948711 0.513818502 0.0776939 0.00017 +0.000588492316 -1.26000004e-05 0.000339766382 0.865876496 -0.0185389742 0.499914289 0.079482 0.00017 +0.000598182727 -1.26000004e-05 0.000320161082 0.881508231 -0.0185679123 0.471803427 0.0834594 0.00017 +0.000598590996 0 0.000320396823 0.881649673 0 0.471904457 0.0834594 0.00017 +0.000598182727 1.26000004e-05 0.000320161082 0.881508231 0.0185679123 0.471803427 0.0839627 0.00017 +0.000593135017 1.89000002e-05 0.000329846836 0.873613715 0.0278373361 0.485823154 0.0823001 0.00017 +0.00058727077 2.52000009e-05 0.000339061109 0.865427911 0.0371358246 0.499655306 0.0809104 0.00017 +0.00058222306 1.89000002e-05 0.000348746835 0.857541859 0.0278373398 0.513660491 0.0786095 0.00017 +0.000576358812 1.26000004e-05 0.000357961108 0.849347651 0.0185679123 0.527507186 0.076598 0.00017 +0.000576767139 0 0.000358196849 0.849505901 0 0.527579188 0.0761446 0.00017 +0.000576358812 -1.26000004e-05 0.000357961108 0.849347651 -0.0185679123 0.527507186 0.0761446 0.00017 +0.00058222306 -1.89000002e-05 0.000348746835 0.857541859 -0.0278373398 0.513660491 0.0779201 0.00017 +0.00058727077 -2.52000009e-05 0.000339061109 0.865427911 -0.0371358246 0.499655306 0.0799489 0.00017 +0.000593135017 -1.89000002e-05 0.000329846836 0.873613715 -0.0278373361 0.485823154 0.081564 0.00017 +0.000601579552 -1.89000002e-05 0.000309522293 0.888857722 -0.0279255006 0.457331479 0.0859497 0.00017 +0.000602406741 -6.30000068e-06 0.000309999858 0.889134884 -0.00929861795 0.457550794 0.085684 0.00017 +0.000602406741 6.29999977e-06 0.000309999858 0.889134884 0.00929861609 0.457550794 0.0859497 0.00017 +0.000601579552 1.89000002e-05 0.000309522293 0.888857722 0.0279255006 0.457331479 0.0867417 0.00017 +0.00059695082 2.52000009e-05 0.000319449871 0.881082058 0.0371944718 0.471498728 0.0849875 0.00017 +0.000591494842 3.15000034e-05 0.000328899885 0.873029172 0.046493087 0.485446662 0.0835562 0.00017 +0.000585211674 3.78000004e-05 0.000337872276 0.864673555 0.055851005 0.499219745 0.0824087 0.00017 +0.000580582884 3.15000034e-05 0.000347799854 0.856923521 0.0464930907 0.5133425 0.0798044 0.00017 +0.000575126905 2.51999991e-05 0.000357249868 0.848870635 0.0371944681 0.527290463 0.0775191 0.00017 +0.000568843738 1.89000002e-05 0.000366222288 0.840489268 0.0279255025 0.541108012 0.0755244 0.00017 +0.000569670927 6.30000068e-06 0.000366699853 0.840817809 0.00929861888 0.541238368 0.074822 0.00017 +0.000569670927 -6.29999977e-06 0.000366699853 0.840817809 -0.00929861702 0.541238368 0.0746096 0.00017 +0.000568843738 -1.89000002e-05 0.000366222288 0.840489268 -0.0279255025 0.541108012 0.074822 0.00017 +0.000575126905 -2.52000009e-05 0.000357249868 0.848870635 -0.0371944718 0.527290463 0.076598 0.00017 +0.000580582884 -3.15000034e-05 0.000347799854 0.856923521 -0.0464930907 0.5133425 0.0786095 0.00017 +0.000585211674 -3.78000004e-05 0.000337872276 0.864673555 -0.055851005 0.499219745 0.0809104 0.00017 +0.000591494842 -3.15000034e-05 0.000328899885 0.873029172 -0.046493087 0.485446662 0.0823001 0.00017 +0.00059695082 -2.51999991e-05 0.000319449871 0.881082058 -0.0371944681 0.471498728 0.0839627 0.00017 +0.000604102155 -2.52000009e-05 0.000298378756 0.895970285 -0.0373752192 0.44253853 0.0888388 0.00017 +0.000605366717 -1.25999995e-05 0.000299108855 0.896378636 -0.0186570715 0.442896456 0.0882751 0.00017 +0.000605785695 0 0.000299350766 0.896514118 0 0.443015039 0.0882751 0.00017 +0.000605366717 1.26000004e-05 0.000299108855 0.896378636 0.0186570734 0.442896456 0.0888388 0.00017 +0.000604102155 2.52000009e-05 0.000298378756 0.895970285 0.0373752192 0.44253853 0.0899973 0.00017 +0.000599910796 3.15000034e-05 0.00030855884 0.888299882 0.0466426797 0.456889182 0.0881213 0.00017 +0.000594873796 3.78000004e-05 0.000318250735 0.880365431 0.0559409633 0.470985502 0.0865986 0.00017 +0.000588998897 4.41000011e-05 0.000327458838 0.872142315 0.0652997419 0.484874815 0.0854108 0.00017 +0.000582278357 5.04000018e-05 0.000336178724 0.8636024 0.0747504383 0.498601347 0.0845415 0.00017 +0.00057808694 4.41000047e-05 0.000346358836 0.855984867 0.0652997568 0.512860417 0.0815675 0.00017 +0.00057304994 3.78000004e-05 0.000356050761 0.84806782 0.0559409633 0.526926458 0.0789831 0.00017 +0.000567174982 3.15000034e-05 0.000365258835 0.839827359 0.0466426834 0.54084605 0.0767034 0.00017 +0.0005604545 2.52000009e-05 0.000373978721 0.831234515 0.0373752192 0.554664135 0.0746869 0.00017 +0.000561719062 1.25999995e-05 0.000374708819 0.831748664 0.0186570715 0.554838836 0.0737421 0.00017 +0.000562138041 0 0.00037495073 0.831919134 0 0.554896951 0.0732868 0.00017 +0.000561719062 -1.26000004e-05 0.000374708819 0.831748664 -0.0186570734 0.554838836 0.0732868 0.00017 +0.0005604545 -2.52000009e-05 0.000373978721 0.831234515 -0.0373752192 0.554664135 0.0737421 0.00017 +0.000567174982 -3.15000034e-05 0.000365258835 0.839827359 -0.0466426834 0.54084605 0.0755244 0.00017 +0.00057304994 -3.78000004e-05 0.000356050761 0.84806782 -0.0559409633 0.526926458 0.0775191 0.00017 +0.00057808694 -4.41000011e-05 0.000346358836 0.855984867 -0.0652997494 0.512860417 0.0798044 0.00017 +0.000582278357 -5.04000018e-05 0.000336178724 0.8636024 -0.0747504383 0.498601347 0.0824087 0.00017 +0.000588998897 -4.41000047e-05 0.000327458838 0.872142315 -0.0652997494 0.484874815 0.0835562 0.00017 +0.000594873796 -3.78000004e-05 0.000318250735 0.880365431 -0.0559409633 0.470985502 0.0849875 0.00017 +0.000599910796 -3.15000034e-05 0.00030855884 0.888299882 -0.0466426797 0.456889182 0.0867417 0.00017 +0.000605694251 -3.15000034e-05 0.000286697934 0.902862072 -0.0469546393 0.427358657 0.0922396 0.00017 +0.000607424881 -1.89000002e-05 0.000287697098 0.903398275 -0.0281092003 0.427880138 0.0913246 0.00017 +0.000608282047 -6.29999886e-06 0.000288191979 0.903664708 -0.00935928803 0.428138435 0.0910208 0.00017 +0.000608282047 6.30000068e-06 0.000288191979 0.903664708 0.00935929082 0.428138435 0.0913246 0.00017 +0.000607424881 1.89000002e-05 0.000287697098 0.903398275 0.0281092003 0.427880138 0.0922396 0.00017 +0.000605694251 3.15000034e-05 0.000286697934 0.902862072 0.0469546393 0.427358657 0.0938308 0.00017 +0.000601968903 3.78000004e-05 0.000297147111 0.895283818 0.0562184006 0.441934764 0.0918037 0.00017 +0.000597370148 4.41000047e-05 0.000307092007 0.887453914 0.0655150265 0.456216276 0.0901703 0.00017 +0.000591914228 5.04000018e-05 0.000316541991 0.879348516 0.0748743117 0.470255196 0.0888972 0.00017 +0.000585601083 5.67000025e-05 0.000325497094 0.870940566 0.0843276009 0.484098554 0.0879869 0.00017 +0.000578414474 6.30000068e-05 0.000333947944 0.862198114 0.0939092785 0.497790605 0.0874474 0.00017 +0.000574689126 5.67000061e-05 0.000344397093 0.854711652 0.0843276009 0.512207747 0.0840211 0.00017 +0.000570090313 5.04000018e-05 0.000354341988 0.846927047 0.0748743191 0.526410997 0.081053 0.00017 +0.000564634334 4.41000047e-05 0.000363792002 0.83882165 0.0655150339 0.540449917 0.0784479 0.00017 +0.000558321248 3.78000004e-05 0.000372747076 0.830368459 0.0562184006 0.554371536 0.076156 0.00017 +0.000551134697 3.15000034e-05 0.000381197955 0.821534157 0.0469546355 0.568222523 0.0741285 0.00017 +0.000552865269 1.89000002e-05 0.000382197089 0.822254002 0.0281092003 0.568426132 0.0728881 0.00017 +0.000553722493 6.29999886e-06 0.000382692 0.822610855 0.0093592871 0.568527758 0.072192 0.00017 +0.000553722493 -6.30000068e-06 0.000382692 0.822610855 -0.00935928989 0.568527758 0.0719719 0.00017 +0.000552865269 -1.89000002e-05 0.000382197089 0.822254002 -0.0281092003 0.568426132 0.072192 0.00017 +0.000551134697 -3.15000034e-05 0.000381197955 0.821534157 -0.0469546355 0.568222523 0.0728881 0.00017 +0.000558321248 -3.78000004e-05 0.000372747076 0.830368459 -0.0562184006 0.554371536 0.0746869 0.00017 +0.000564634334 -4.41000047e-05 0.000363792002 0.83882165 -0.0655150339 0.540449917 0.0767034 0.00017 +0.000570090313 -5.04000018e-05 0.000354341988 0.846927047 -0.0748743191 0.526410997 0.0789831 0.00017 +0.000574689126 -5.67000025e-05 0.000344397093 0.854711652 -0.0843276009 0.512207747 0.0815675 0.00017 +0.000578414474 -6.30000068e-05 0.000333947944 0.862198114 -0.0939092785 0.497790605 0.0845415 0.00017 +0.000585601083 -5.67000061e-05 0.000325497094 0.870940566 -0.0843276009 0.484098554 0.0854108 0.00017 +0.000591914228 -5.04000018e-05 0.000316541991 0.879348516 -0.0748743117 0.470255196 0.0865986 0.00017 +0.000597370148 -4.41000047e-05 0.000307092007 0.887453914 -0.0655150265 0.456216276 0.0881213 0.00017 +0.000601968903 -3.78000004e-05 0.000297147111 0.895283818 -0.0562184006 0.441934764 0.0899973 0.00017 +0.000606274116 -3.78000004e-05 0.000274432707 0.909548283 -0.0567085519 0.411711127 0.0962897 0.00017 +0.00060851255 -2.52000027e-05 0.000275725062 0.910210073 -0.0376940407 0.41242817 0.0949284 0.00017 +0.000609837822 -1.26000014e-05 0.000276490202 0.910603642 -0.0188141949 0.412852347 0.0942756 0.00017 +0.000610276649 0 0.00027674358 0.910734355 0 0.412992805 0.0942756 0.00017 +0.000609837822 1.25999995e-05 0.000276490202 0.910603642 0.0188141912 0.412852347 0.0949284 0.00017 +0.00060851255 2.51999991e-05 0.000275725062 0.910210073 0.0376940332 0.41242817 0.0962897 0.00017 +0.000606274116 3.78000004e-05 0.000274432707 0.909548283 0.0567085519 0.411711127 0.0984385 0.00017 +0.000603056571 4.41000047e-05 0.000285175047 0.902049065 0.0659645647 0.426563412 0.0961877 0.00017 +0.000598925864 5.04000018e-05 0.0002953902 0.894309998 0.0752567723 0.441073656 0.0943858 0.00017 +0.00059390883 5.67000025e-05 0.000305093563 0.886308014 0.0846151188 0.455300331 0.093006 0.00017 +0.000588013965 6.30000068e-05 0.00031429017 0.878016531 0.0940709636 0.469294906 0.0920203 0.00017 +0.000581232773 6.93000038e-05 0.000322975044 0.869404972 0.103658594 0.483104408 0.0914604 0.00017 +0.000573538302 7.56000009e-05 0.000331132702 0.860437214 0.113417104 0.496773928 0.0913404 0.00017 +0.000570320815 6.92999965e-05 0.000341875042 0.853083074 0.103658594 0.51137501 0.0873186 0.00017 +0.000566190109 6.30000068e-05 0.000352090196 0.845429301 0.0940709636 0.525737524 0.0838733 0.00017 +0.000561173016 5.67000025e-05 0.000361793558 0.837455451 0.0846151263 0.539915502 0.0808855 0.00017 +0.00055527821 5.03999981e-05 0.000370990165 0.829135776 0.0752567649 0.553958774 0.0782564 0.00017 +0.000548496959 4.41000011e-05 0.000379675039 0.820438981 0.0659645498 0.567915976 0.0759435 0.00017 +0.000540802546 3.78000004e-05 0.000387832697 0.811326146 0.0567085519 0.58183676 0.0738751 0.00017 +0.000543041038 2.52000027e-05 0.000389125024 0.812278092 0.0376940407 0.582051337 0.0723118 0.00017 +0.000544366252 1.26000014e-05 0.000389890192 0.81284219 0.0188141949 0.582180083 0.0713235 0.00017 +0.000544805138 0 0.00039014357 0.81302917 0 0.582223058 0.0708404 0.00017 +0.000544366252 -1.25999995e-05 0.000389890192 0.81284219 -0.0188141912 0.582180083 0.0708404 0.00017 +0.000543041038 -2.51999991e-05 0.000389125024 0.812278092 -0.0376940332 0.582051337 0.0713235 0.00017 +0.000540802546 -3.78000004e-05 0.000387832697 0.811326146 -0.0567085519 0.58183676 0.0723118 0.00017 +0.000548496959 -4.41000047e-05 0.000379675039 0.820438981 -0.0659645572 0.567915976 0.0741285 0.00017 +0.00055527821 -5.04000018e-05 0.000370990165 0.829135776 -0.0752567723 0.553958774 0.076156 0.00017 +0.000561173016 -5.67000025e-05 0.000361793558 0.837455451 -0.0846151263 0.539915502 0.0784479 0.00017 +0.000566190109 -6.30000068e-05 0.000352090196 0.845429301 -0.0940709636 0.525737524 0.081053 0.00017 +0.000570320815 -6.93000038e-05 0.000341875042 0.853083074 -0.103658609 0.51137501 0.0840211 0.00017 +0.000573538302 -7.56000009e-05 0.000331132702 0.860437214 -0.113417104 0.496773928 0.0874474 0.00017 +0.000581232773 -6.92999965e-05 0.000322975044 0.869404972 -0.103658579 0.483104408 0.0879869 0.00017 +0.000588013965 -6.30000068e-05 0.00031429017 0.878016531 -0.0940709636 0.469294906 0.0888972 0.00017 +0.00059390883 -5.67000025e-05 0.000305093563 0.886308014 -0.0846151188 0.455300331 0.0901703 0.00017 +0.000598925864 -5.03999981e-05 0.0002953902 0.894309998 -0.0752567649 0.441073656 0.0918037 0.00017 +0.000603056571 -4.41000011e-05 0.000285175047 0.902049065 -0.0659645647 0.426563412 0.0938308 0.00017 +0.000605723995 -4.41000047e-05 0.000261515088 0.916044474 -0.0666930228 0.395492762 0.1012 0.00017 +0.000608530827 -3.14999997e-05 0.000263135618 0.916829824 -0.0474587902 0.396447599 0.099256 0.00017 +0.000610368559 -1.89000002e-05 0.000264196657 0.917347848 -0.0284055825 0.397071928 0.0981449 0.00017 +0.000611277763 -6.29999886e-06 0.000264721573 0.917605162 -0.00945709459 0.397380531 0.0977797 0.00017 +0.000611277763 6.3000025e-06 0.000264721573 0.917605162 0.00945710018 0.397380531 0.0981449 0.00017 +0.000610368559 1.8900002e-05 0.000264196657 0.917347848 0.0284055844 0.397071928 0.099256 0.00017 +0.000608530827 3.15000034e-05 0.000263135618 0.916829824 0.047458794 0.396447599 0.1012 0.00017 +0.000605723995 4.41000047e-05 0.000261515088 0.916044474 0.0666930228 0.395492762 0.104101 0.00017 +0.000603074906 5.04000018e-05 0.000272585603 0.908609688 0.0759340748 0.410685211 0.10153 0.00017 +0.00059945666 5.67000025e-05 0.000283096626 0.900947869 0.0852167457 0.425477475 0.0994883 0.00017 +0.000594909885 6.30000068e-05 0.000293071585 0.893034875 0.0945709646 0.439937472 0.097936 0.00017 +0.000589453964 6.92999965e-05 0.00030252157 0.884844899 0.104028054 0.45412311 0.0968425 0.00017 +0.000583088782 7.56000009e-05 0.000311446609 0.876347959 0.11362233 0.468085855 0.0962297 0.00017 +0.000575795071 8.19000052e-05 0.000319835613 0.867509186 0.123392865 0.481873393 0.0961127 0.00017 +0.000567532261 8.82000095e-05 0.000327665068 0.858286679 0.133386061 0.495532304 0.0965829 0.00017 +0.000564883114 8.19000052e-05 0.000338735583 0.851068914 0.123392865 0.510348618 0.0917439 0.00017 +0.000561264926 7.56000081e-05 0.000349246635 0.84354794 0.113622338 0.524897039 0.0876682 0.00017 +0.000556718151 6.93000038e-05 0.000359221565 0.835704267 0.104028068 0.539236963 0.0841789 0.00017 +0.00055126223 6.30000068e-05 0.00036867155 0.827514231 0.0945709646 0.55342257 0.0811455 0.00017 +0.000544897048 5.67000061e-05 0.000377596647 0.81894803 0.0852167532 0.567505419 0.0784846 0.00017 +0.000537603337 5.04000054e-05 0.000385985593 0.809968412 0.0759340748 0.581536829 0.0761295 0.00017 +0.000529340527 4.41000047e-05 0.000393815048 0.800528705 0.0666930228 0.595571756 0.0740233 0.00017 +0.000532147358 3.14999997e-05 0.000395435578 0.801748276 0.0474587902 0.595774472 0.0720159 0.00017 +0.00053398509 1.89000002e-05 0.000396496616 0.802547991 0.0284055825 0.595910966 0.0706937 0.00017 +0.000534894294 6.29999886e-06 0.000397021562 0.802943945 0.00945709459 0.595979512 0.0699221 0.00017 +0.000534894294 -6.3000025e-06 0.000397021562 0.802943945 -0.00945710018 0.595979512 0.0696865 0.00017 +0.00053398509 -1.8900002e-05 0.000396496616 0.802547991 -0.0284055844 0.595910966 0.0699221 0.00017 +0.000532147358 -3.15000034e-05 0.000395435578 0.801748276 -0.047458794 0.595774472 0.0706937 0.00017 +0.000529340527 -4.41000047e-05 0.000393815048 0.800528705 -0.0666930228 0.595571756 0.0720159 0.00017 +0.000537603337 -5.04000018e-05 0.000385985593 0.809968412 -0.0759340748 0.581536829 0.0738751 0.00017 +0.000544897048 -5.67000025e-05 0.000377596647 0.81894803 -0.0852167457 0.567505419 0.0759435 0.00017 +0.00055126223 -6.30000068e-05 0.00036867155 0.827514231 -0.0945709646 0.55342257 0.0782564 0.00017 +0.000556718151 -6.92999965e-05 0.000359221565 0.835704267 -0.104028054 0.539236963 0.0808855 0.00017 +0.000561264926 -7.56000009e-05 0.000349246635 0.84354794 -0.11362233 0.524897039 0.0838733 0.00017 +0.000564883114 -8.19000052e-05 0.000338735583 0.851068914 -0.123392865 0.510348618 0.0873186 0.00017 +0.000567532261 -8.82000095e-05 0.000327665068 0.858286679 -0.133386061 0.495532304 0.0913404 0.00017 +0.000575795071 -8.19000052e-05 0.000319835613 0.867509186 -0.123392865 0.481873393 0.0914604 0.00017 +0.000583088782 -7.56000081e-05 0.000311446609 0.876347959 -0.113622338 0.468085855 0.0920203 0.00017 +0.000589453964 -6.93000038e-05 0.00030252157 0.884844899 -0.104028068 0.45412311 0.093006 0.00017 +0.000594909885 -6.30000068e-05 0.000293071585 0.893034875 -0.0945709646 0.439937472 0.0943858 0.00017 +0.00059945666 -5.67000061e-05 0.000283096626 0.900947869 -0.0852167532 0.425477475 0.0961877 0.00017 +0.000603074906 -5.04000054e-05 0.000272585603 0.908609688 -0.0759340748 0.410685211 0.0984385 0.00017 +0.00060387241 -5.04000018e-05 0.000247846037 0.922367632 -0.0769820437 0.378565371 0.107301 0.00017 +0.000607337104 -3.78000041e-05 0.000249846373 0.923275113 -0.0574636459 0.379816979 0.104568 0.00017 +0.00060975278 -2.51999991e-05 0.000251241087 0.923914909 -0.0381837599 0.380687714 0.102843 0.00017 +0.000611179974 -1.26000014e-05 0.000252065074 0.924295604 -0.0190551504 0.381201357 0.102018 0.00017 +0.000611652096 0 0.00025233769 0.924421966 0 0.3813712 0.102018 0.00017 +0.000611179974 1.26000014e-05 0.000252065074 0.924295604 0.0190551504 0.381201357 0.102843 0.00017 +0.00060975278 2.52000009e-05 0.000251241087 0.923914909 0.0381837636 0.380687714 0.104568 0.00017 +0.000607337104 3.78000004e-05 0.000249846373 0.923275113 0.0574636385 0.379816979 0.107301 0.00017 +0.00060387241 5.04000018e-05 0.000247846037 0.922367632 0.0769820437 0.378565371 0.111288 0.00017 +0.000601881125 5.67000061e-05 0.000259296357 0.914980948 0.0861954689 0.394182891 0.108206 0.00017 +0.000598840881 6.30000068e-05 0.000270141114 0.907380819 0.0954594091 0.40932554 0.105806 0.00017 +0.000594812038 6.92999965e-05 0.000280415057 0.899542212 0.104803309 0.424075454 0.103996 0.00017 +0.00058982824 7.56000009e-05 0.000290137687 0.891438425 0.11425826 0.438500345 0.102742 0.00017 +0.000583900197 8.19000052e-05 0.000299315085 0.883040011 0.123858467 0.452658176 0.102034 0.00017 +0.000577017025 8.82000022e-05 0.000307941082 0.874312758 0.133643165 0.466601163 0.10191 0.00017 +0.00056914537 9.45000065e-05 0.000315996382 0.865215957 0.143659115 0.480378389 0.102444 0.00017 +0.000560224697 0.000100800004 0.00032344606 0.855699182 0.153964087 0.494038433 0.103784 0.00017 +0.000558233412 9.44999992e-05 0.00033489638 0.848627687 0.143659115 0.509110212 0.097762 0.00017 +0.000555193168 8.82000095e-05 0.000345741108 0.841244578 0.13364318 0.523876846 0.0927979 0.00017 +0.000551164383 8.19000052e-05 0.00035601508 0.833533227 0.123858474 0.538406372 0.0886209 0.00017 +0.000546180585 7.56000009e-05 0.000365737651 0.825471342 0.114258252 0.552758515 0.0850418 0.00017 +0.000540252484 6.92999965e-05 0.000374915078 0.817031026 0.104803309 0.566989064 0.0819487 0.00017 +0.000533369312 6.30000068e-05 0.000383541104 0.808176517 0.0954594091 0.581152439 0.079242 0.00017 +0.000525497657 5.67000025e-05 0.000391596404 0.798862636 0.0861954615 0.595305681 0.0768575 0.00017 +0.000516576984 5.04000018e-05 0.000399046054 0.789030731 0.0769820437 0.609511495 0.0747255 0.00017 +0.000520041678 3.78000041e-05 0.000401046389 0.790568411 0.0574636459 0.609671533 0.07214 0.00017 +0.000522457412 2.51999991e-05 0.000402441103 0.791642427 0.0381837599 0.609790325 0.0703664 0.00017 +0.000523884548 1.26000014e-05 0.00040326509 0.792277575 0.0190551504 0.609863162 0.0692587 0.00017 +0.00052435667 0 0.000403537677 0.79248786 0 0.609887719 0.0687318 0.00017 +0.000523884548 -1.26000014e-05 0.00040326509 0.792277575 -0.0190551504 0.609863162 0.0687318 0.00017 +0.000522457412 -2.52000009e-05 0.000402441103 0.791642427 -0.0381837636 0.609790325 0.0692587 0.00017 +0.000520041678 -3.78000004e-05 0.000401046389 0.790568411 -0.0574636385 0.609671533 0.0703664 0.00017 +0.000516576984 -5.04000018e-05 0.000399046054 0.789030731 -0.0769820437 0.609511495 0.07214 0.00017 +0.000525497657 -5.67000061e-05 0.000391596404 0.798862636 -0.0861954689 0.595305681 0.0740233 0.00017 +0.000533369312 -6.30000068e-05 0.000383541104 0.808176517 -0.0954594091 0.581152439 0.0761295 0.00017 +0.000540252484 -6.92999965e-05 0.000374915078 0.817031026 -0.104803309 0.566989064 0.0784846 0.00017 +0.000546180585 -7.56000009e-05 0.000365737651 0.825471342 -0.114258252 0.552758515 0.0811455 0.00017 +0.000551164383 -8.19000052e-05 0.00035601508 0.833533227 -0.123858474 0.538406372 0.0841789 0.00017 +0.000555193168 -8.82000022e-05 0.000345741108 0.841244578 -0.133643165 0.523876846 0.0876682 0.00017 +0.000558233412 -9.45000065e-05 0.00033489638 0.848627687 -0.14365913 0.509110212 0.0917439 0.00017 +0.000560224697 -0.000100800004 0.00032344606 0.855699182 -0.153964087 0.494038433 0.0965829 0.00017 +0.00056914537 -9.44999992e-05 0.000315996382 0.865215957 -0.1436591 0.480378389 0.0961127 0.00017 +0.000577017025 -8.82000095e-05 0.000307941082 0.874312758 -0.13364318 0.466601163 0.0962267 0.00017 +0.000583900197 -8.19000052e-05 0.000299315085 0.883040011 -0.123858467 0.452658176 0.0968425 0.00017 +0.00058982824 -7.56000009e-05 0.000290137687 0.891438425 -0.11425826 0.438500345 0.097936 0.00017 +0.000594812038 -6.92999965e-05 0.000280415057 0.899542212 -0.104803309 0.424075454 0.0994883 0.00017 +0.000598840881 -6.30000068e-05 0.000270141114 0.907380819 -0.0954594091 0.40932554 0.10153 0.00017 +0.000601881125 -5.67000025e-05 0.000259296357 0.914980948 -0.0861954615 0.394182891 0.104101 0.00017 +0.000600459462 -5.67000025e-05 0.000233275598 0.92853874 -0.0876797661 0.360732794 0.115173 0.00017 +0.000604719098 -4.41000047e-05 0.000235734886 0.929566324 -0.0677899569 0.362368613 0.111254 0.00017 +0.000607812137 -3.1500007e-05 0.000237520653 0.93032527 -0.0482143238 0.363552243 0.108685 0.00017 +0.000609829498 -1.89000002e-05 0.000238685374 0.930825889 -0.0288484059 0.364322364 0.107223 0.00017 +0.000610825431 -6.3000025e-06 0.000239260422 0.931074679 -0.00960302632 0.364702106 0.106743 0.00017 +0.000610825431 6.29999886e-06 0.000239260422 0.931074679 0.00960302074 0.364702106 0.107223 0.00017 +0.000609829498 1.89000002e-05 0.000238685374 0.930825889 0.0288484059 0.364322364 0.108685 0.00017 +0.000607812137 3.14999997e-05 0.000237520653 0.93032527 0.0482143126 0.363552243 0.111254 0.00017 +0.000604719098 4.41000011e-05 0.000235734886 0.929566324 0.0677899495 0.362368613 0.115173 0.00017 +0.000600459462 5.67000025e-05 0.000233275598 0.92853874 0.0876797661 0.360732794 0.120833 0.00017 +0.00059926312 6.30000068e-05 0.00024518487 0.921179533 0.0968427956 0.37689504 0.116929 0.00017 +0.00059690018 6.93000038e-05 0.000256420637 0.913623393 0.106071517 0.39248082 0.113923 0.00017 +0.00059346162 7.56000009e-05 0.000267035386 0.905842483 0.115393639 0.407595009 0.111692 0.00017 +0.000589001575 8.19000052e-05 0.000277060404 0.89780885 0.124839313 0.422320247 0.110165 0.00017 +0.000583545596 8.82000095e-05 0.000286510418 0.889492393 0.134442344 0.436724812 0.109297 0.00017 +0.000577093742 9.44999992e-05 0.000295385369 0.880859077 0.144242048 0.450867623 0.109141 0.00017 +0.000569620403 0.000100800004 0.000303670618 0.87186861 0.154285833 0.464802325 0.109753 0.00017 +0.000561071385 0.000107100008 0.000311334879 0.8624717 0.164632753 0.478579998 0.111314 0.00017 +0.000551355828 0.000113400005 0.00031832559 0.85260576 0.175359532 0.492252439 0.114095 0.00017 +0.000550159428 0.000107100001 0.000330234878 0.845697999 0.164632738 0.507632792 0.106176 0.00017 +0.000547796488 0.000100800004 0.000341470644 0.838464677 0.154285833 0.52265954 0.0998705 0.00017 +0.000544357928 9.44999992e-05 0.000352085364 0.830892026 0.144242048 0.537412822 0.0947032 0.00017 +0.000539897941 8.82000022e-05 0.000362110382 0.822960675 0.134442315 0.551961005 0.0903717 0.00017 +0.000534441962 8.19000052e-05 0.000371560425 0.814644158 0.124839298 0.56636554 0.0866985 0.00017 +0.000527990051 7.56000009e-05 0.000380435376 0.80590862 0.115393639 0.580685437 0.0835216 0.00017 +0.000520516711 6.92999965e-05 0.000388720655 0.796709776 0.106071495 0.594980955 0.0807891 0.00017 +0.000511967693 6.29999995e-05 0.000396384887 0.786990166 0.0968427882 0.60931772 0.078378 0.00017 +0.000502252136 5.67000025e-05 0.000403375598 0.776672781 0.0876797661 0.623772085 0.0762658 0.00017 +0.000506511715 4.41000047e-05 0.000405834871 0.778603315 0.0677899569 0.623844147 0.0728366 0.00017 +0.000509604753 3.1500007e-05 0.000407620624 0.780007899 0.0482143275 0.623909593 0.0704606 0.00017 +0.000511622173 1.89000002e-05 0.000408785359 0.780925095 0.0288484097 0.623958051 0.0688953 0.00017 +0.000512618106 6.3000025e-06 0.000409360393 0.781378329 0.00960302725 0.623983741 0.0680017 0.00017 +0.000512618106 -6.29999886e-06 0.000409360393 0.781378329 -0.00960302167 0.623983741 0.0677125 0.00017 +0.000511622173 -1.89000002e-05 0.000408785359 0.780925095 -0.0288484097 0.623958051 0.0680017 0.00017 +0.000509604753 -3.14999997e-05 0.000407620624 0.780007899 -0.0482143164 0.623909593 0.0688953 0.00017 +0.000506511715 -4.41000011e-05 0.000405834871 0.778603315 -0.0677899495 0.623844147 0.0704606 0.00017 +0.000502252136 -5.67000025e-05 0.000403375598 0.776672781 -0.0876797661 0.623772085 0.0728366 0.00017 +0.000511967693 -6.30000068e-05 0.000396384887 0.786990166 -0.0968427956 0.60931772 0.0747255 0.00017 +0.000520516711 -6.93000038e-05 0.000388720655 0.796709776 -0.106071509 0.594980955 0.0768575 0.00017 +0.000527990051 -7.56000009e-05 0.000380435376 0.80590862 -0.115393639 0.580685437 0.079242 0.00017 +0.000534441962 -8.19000052e-05 0.000371560425 0.814644158 -0.124839298 0.56636554 0.0819487 0.00017 +0.000539897941 -8.82000095e-05 0.000362110382 0.822960675 -0.134442329 0.551961005 0.0850486 0.00017 +0.000544357928 -9.44999992e-05 0.000352085364 0.830892026 -0.144242048 0.537412822 0.0886209 0.00017 +0.000547796488 -0.000100800004 0.000341470644 0.838464677 -0.154285833 0.52265954 0.0927979 0.00017 +0.000550159428 -0.000107100008 0.000330234878 0.845697999 -0.164632753 0.507632792 0.097759 0.00017 +0.000551355828 -0.000113400005 0.00031832559 0.85260576 -0.175359532 0.492252439 0.103784 0.00017 +0.000561071385 -0.000107100001 0.000311334879 0.8624717 -0.164632738 0.478579998 0.102444 0.00017 +0.000569620403 -0.000100800004 0.000303670618 0.87186861 -0.154285833 0.464802325 0.101907 0.00017 +0.000577093742 -9.44999992e-05 0.000295385369 0.880859077 -0.144242048 0.450867623 0.102034 0.00017 +0.000583545596 -8.82000022e-05 0.000286510418 0.889492393 -0.134442329 0.436724812 0.102742 0.00017 +0.000589001575 -8.19000052e-05 0.000277060404 0.89780885 -0.124839313 0.422320247 0.103996 0.00017 +0.00059346162 -7.56000009e-05 0.000267035386 0.905842483 -0.115393639 0.407595009 0.105806 0.00017 +0.00059690018 -6.92999965e-05 0.000256420637 0.913623393 -0.106071502 0.39248082 0.108206 0.00017 +0.00059926312 -6.29999995e-05 0.00024518487 0.921179533 -0.0968427882 0.37689504 0.111288 0.00017 +0.000595065823 -6.30000068e-05 0.000217561537 0.934588134 -0.0989454538 0.341694027 0.125893 0.00017 +0.000600346131 -5.03999981e-05 0.000220610134 0.935731232 -0.0785561055 0.343854636 0.120073 0.00017 +0.000604274799 -3.78000004e-05 0.000222878356 0.936605036 -0.0585886948 0.345453769 0.116178 0.00017 +0.000606995658 -2.52000027e-05 0.000224449279 0.937221646 -0.0389096476 0.3465572 0.113778 0.00017 +0.00060859666 -1.25999977e-05 0.000225373587 0.937588394 -0.0194112342 0.347204775 0.112631 0.00017 +0.000609125243 0 0.00022567877 0.937710285 0 0.347418368 0.112631 0.00017 +0.00060859666 1.26000014e-05 0.000225373587 0.937588394 0.0194112398 0.347204775 0.113778 0.00017 +0.000606995658 2.52000027e-05 0.000224449279 0.937221646 0.0389096476 0.3465572 0.116178 0.00017 +0.000604274799 3.78000004e-05 0.000222878356 0.936605036 0.0585886948 0.345453769 0.120073 0.00017 +0.000600346131 5.04000018e-05 0.000220610134 0.935731232 0.0785561129 0.343854636 0.125891 0.00017 +0.000595065823 6.30000068e-05 0.000217561537 0.934588134 0.0989454538 0.341694027 0.134451 0.00017 +0.000594890153 6.92999965e-05 0.000230060148 0.927227259 0.108014643 0.358583897 0.128972 0.00017 +0.000593362842 7.56000009e-05 0.000241778354 0.919691861 0.11717739 0.374748081 0.124901 0.00017 +0.00059062778 8.19000052e-05 0.000252799276 0.911949039 0.12645635 0.390330553 0.121936 0.00017 +0.000586772745 8.82000095e-05 0.000263173599 0.903967142 0.135878682 0.405438513 0.119912 0.00017 +0.00058184535 9.45000065e-05 0.000272928766 0.895714641 0.145476863 0.420156777 0.118765 0.00017 +0.000575860846 0.000100800004 0.000282073597 0.887156487 0.155289918 0.434555382 0.118503 0.00017 +0.000568803924 0.000107100008 0.000290599273 0.878252149 0.165365964 0.448694915 0.119202 0.00017 +0.000560627086 0.000113400005 0.00029847835 0.868952632 0.175766096 0.462631166 0.121062 0.00017 +0.00055124244 0.000119700002 0.000305660156 0.85919565 0.186570764 0.476418078 0.124427 0.00017 +0.000540506153 0.000126000014 0.000312061544 0.848898828 0.197890922 0.490112215 0.129962 0.00017 +0.000540330482 0.000119700002 0.000324560126 0.842187762 0.186570778 0.505876601 0.118629 0.00017 +0.000538803171 0.000113400012 0.000336278375 0.8351264 0.17576611 0.521219909 0.110065 0.00017 +0.00053606811 0.000107100008 0.000347299268 0.827707112 0.165365994 0.53624171 0.103316 0.00017 +0.000532213191 0.000100800004 0.000357673562 0.819913983 0.155289903 0.551022708 0.0978446 0.00017 +0.000527285796 9.45000065e-05 0.000367428758 0.81172353 0.145476863 0.565633655 0.0933065 0.00017 +0.000521301234 8.82000095e-05 0.000376573589 0.803103387 0.135878682 0.580139637 0.089499 0.00017 +0.000514244311 8.19000052e-05 0.000385099236 0.794010401 0.12645635 0.594606102 0.0862747 0.00017 +0.000506067416 7.56000009e-05 0.000392978371 0.784387052 0.117177397 0.609102905 0.0835251 0.00017 +0.000496682769 6.93000038e-05 0.000400160119 0.774156153 0.108014666 0.623710811 0.0811988 0.00017 +0.000485946541 6.30000068e-05 0.000406561507 0.763209522 0.0989454612 0.638530374 0.0792893 0.00017 +0.000491226849 5.03999981e-05 0.000409610104 0.765652239 0.0785561129 0.638440073 0.0744431 0.00017 +0.000495155517 3.78000004e-05 0.000411878369 0.767473936 0.0585886948 0.638397217 0.0711493 0.00017 +0.000497876375 2.52000027e-05 0.000413449248 0.768737793 0.0389096476 0.638379455 0.0689372 0.00017 +0.000499477377 1.25999977e-05 0.000414373586 0.769482076 0.0194112342 0.638373375 0.0675761 0.00017 +0.000500005903 0 0.000414678769 0.769727945 0 0.638372123 0.0669153 0.00017 +0.000499477377 -1.26000014e-05 0.000414373586 0.769482076 -0.0194112416 0.638373375 0.0669153 0.00017 +0.000497876375 -2.52000027e-05 0.000413449248 0.768737793 -0.0389096476 0.638379455 0.0675761 0.00017 +0.000495155517 -3.78000004e-05 0.000411878369 0.767473936 -0.0585886948 0.638397217 0.0689372 0.00017 +0.000491226849 -5.04000018e-05 0.000409610104 0.765652239 -0.0785561204 0.638440073 0.0711493 0.00017 +0.000485946541 -6.30000068e-05 0.000406561507 0.763209522 -0.0989454612 0.638530374 0.0744431 0.00017 +0.000496682769 -6.92999965e-05 0.000400160119 0.774156153 -0.108014658 0.623710811 0.0762658 0.00017 +0.000506067416 -7.56000009e-05 0.000392978371 0.784387052 -0.117177397 0.609102905 0.078378 0.00017 +0.000514244311 -8.19000052e-05 0.000385099236 0.794010401 -0.12645635 0.594606102 0.0807891 0.00017 +0.000521301234 -8.82000095e-05 0.000376573589 0.803103387 -0.135878682 0.580139637 0.0835216 0.00017 +0.000527285796 -9.45000065e-05 0.000367428758 0.81172353 -0.145476863 0.565633655 0.0866985 0.00017 +0.000532213191 -0.000100800004 0.000357673562 0.819913983 -0.155289903 0.551022708 0.0903749 0.00017 +0.00053606811 -0.000107100008 0.000347299268 0.827707112 -0.165365994 0.53624171 0.0947032 0.00017 +0.000538803171 -0.000113400005 0.000336278375 0.8351264 -0.175766096 0.521219909 0.0998705 0.00017 +0.000540330482 -0.000119700002 0.000324560126 0.842187762 -0.186570778 0.505876601 0.106176 0.00017 +0.000540506153 -0.000126000014 0.000312061544 0.848898828 -0.197890922 0.490112215 0.114095 0.00017 +0.00055124244 -0.000119700002 0.000305660156 0.85919565 -0.186570764 0.476418078 0.111314 0.00017 +0.000560627086 -0.000113400012 0.00029847835 0.868952632 -0.17576611 0.462631166 0.109753 0.00017 +0.000568803924 -0.000107100008 0.000290599273 0.878252149 -0.165365964 0.448694915 0.109141 0.00017 +0.000575860846 -0.000100800004 0.000282073597 0.887156487 -0.155289918 0.434555382 0.109297 0.00017 +0.00058184535 -9.45000065e-05 0.000272928766 0.895714641 -0.145476863 0.420156777 0.110165 0.00017 +0.000586772745 -8.82000095e-05 0.000263173599 0.903967142 -0.135878682 0.405438513 0.111692 0.00017 +0.00059062778 -8.19000052e-05 0.000252799276 0.911949039 -0.12645635 0.390330553 0.113923 0.00017 +0.000593362842 -7.56000009e-05 0.000241778354 0.919691861 -0.11717739 0.374748081 0.116929 0.00017 +0.000594890153 -6.93000038e-05 0.000230060148 0.927227259 -0.108014658 0.358583897 0.120833 0.00017 +0.000586938288 -6.93000038e-05 0.000200269176 0.940569043 -0.11105331 0.320931494 0.141868 0.00017 +0.00059365714 -5.67000025e-05 0.000204148266 0.941814482 -0.0899523944 0.32387346 0.132504 0.00017 +0.000598697807 -4.40999975e-05 0.000207058474 0.942793727 -0.0694460496 0.326063365 0.126342 0.00017 +0.000602312619 -3.14999997e-05 0.000209145524 0.94351846 -0.0493445247 0.327625006 0.122418 0.00017 +0.000604652101 -1.89000002e-05 0.000210496204 0.943997145 -0.0295071285 0.328631639 0.120224 0.00017 +0.00060580211 -6.29999522e-06 0.000211160135 0.944235206 -0.00981950574 0.329125345 0.119514 0.00017 +0.00060580211 6.3000025e-06 0.000211160135 0.944235206 0.00981951784 0.329125345 0.120224 0.00017 +0.000604652101 1.89000039e-05 0.000210496204 0.943997145 0.0295071341 0.328631639 0.122418 0.00017 +0.000602312619 3.1500007e-05 0.000209145524 0.94351846 0.0493445359 0.327625006 0.126342 0.00017 +0.000598697807 4.41000047e-05 0.000207058474 0.942793727 0.0694460645 0.326063365 0.132504 0.00017 +0.00059365714 5.67000061e-05 0.000204148266 0.941814482 0.0899524018 0.32387346 0.141868 0.00017 +0.000586938288 6.93000038e-05 0.000200269176 0.940569043 0.11105331 0.320931494 0.156394 0.00017 +0.000588201219 7.56000009e-05 0.00021359828 0.933158815 0.119936526 0.338865548 0.147317 0.00017 +0.000587785849 8.19000052e-05 0.000225958473 0.925610244 0.128971264 0.35582599 0.140972 0.00017 +0.000585944741 8.82000095e-05 0.000237495522 0.917878211 0.138164684 0.372035027 0.136513 0.00017 +0.000582828186 9.45000065e-05 0.000248296186 0.909925222 0.147535667 0.38764593 0.133531 0.00017 +0.000578522217 0.000100800004 0.000258410146 0.901715457 0.157112241 0.402771741 0.131816 0.00017 +0.000573066238 0.000107100001 0.00026786013 0.893211484 0.166931748 0.417501003 0.131314 0.00017 +0.00056646025 0.000113400012 0.000276646198 0.884371281 0.177042797 0.431906641 0.132096 0.00017 +0.000558664964 0.000119700002 0.000284745533 0.87514466 0.187509194 0.446051836 0.134393 0.00017 +0.000549594115 0.000126000014 0.000292108452 0.865468204 0.198417321 0.459995031 0.138678 0.00017 +0.000539097528 0.000132300018 0.000298648287 0.85525775 0.20988895 0.473794162 0.145887 0.00017 +0.000526922755 0.000138600008 0.000304219167 0.844394028 0.222106621 0.487511426 0.0821597 0.00017 +0.00052818557 0.000132300018 0.000317548256 0.837946355 0.20988895 0.503778279 0.138999 0.00017 +0.000527770258 0.000126000014 0.000329908478 0.831101239 0.198417321 0.519520283 0.125937 0.00017 +0.000525929034 0.000119700009 0.000341445499 0.823864162 0.187509224 0.534871936 0.1163 0.00017 +0.000522812654 0.000113400012 0.000352246192 0.816227496 0.177042797 0.549935102 0.108863 0.00017 +0.000518506684 0.000107100015 0.000362360151 0.808171928 0.166931748 0.564793706 0.102936 0.00017 +0.000513050705 0.000100800011 0.000371810136 0.799667954 0.157112241 0.579522967 0.0981332 0.00017 +0.000506444718 9.45000065e-05 0.000380596175 0.790673494 0.147535652 0.594195783 0.0942175 0.00017 +0.000498649315 8.82000095e-05 0.000388695538 0.781130612 0.138164684 0.608888745 0.0910144 0.00017 +0.000489578524 8.19000124e-05 0.000396058458 0.770959139 0.128971279 0.623689353 0.0884579 0.00017 +0.000479081908 7.56000081e-05 0.000402598293 0.76004529 0.119936548 0.638706923 0.0865486 0.00017 +0.000466907135 6.93000038e-05 0.000408169173 0.748218954 0.111053303 0.654091358 0.085421 0.00017 +0.000473625958 5.67000025e-05 0.000412048277 0.751389623 0.0899524018 0.653698921 0.0778015 0.00017 +0.000478666596 4.40999975e-05 0.000414958457 0.753775716 0.0694460496 0.65345192 0.0728762 0.00017 +0.000482281437 3.14999997e-05 0.000417045521 0.755490422 0.049344521 0.653298855 0.0696368 0.00017 +0.000484620861 1.89000002e-05 0.000418396201 0.756601632 0.0295071304 0.653210104 0.067559 0.00017 +0.00048577087 6.29999522e-06 0.000419060118 0.757148266 0.00981950667 0.653169334 0.0664002 0.00017 +0.00048577087 -6.3000025e-06 0.000419060118 0.757148266 -0.00981951784 0.653169334 0.0660342 0.00017 +0.000484620861 -1.89000039e-05 0.000418396201 0.756601632 -0.029507136 0.653210104 0.0664002 0.00017 +0.000482281437 -3.1500007e-05 0.000417045521 0.755490422 -0.0493445322 0.653298855 0.067559 0.00017 +0.000478666596 -4.41000047e-05 0.000414958457 0.753775716 -0.0694460645 0.65345192 0.0696368 0.00017 +0.000473625958 -5.67000061e-05 0.000412048277 0.751389623 -0.0899524093 0.653698921 0.0728762 0.00017 +0.000466907135 -6.93000038e-05 0.000408169173 0.748218954 -0.111053303 0.654091358 0.0778015 0.00017 +0.000479081908 -7.56000009e-05 0.000402598293 0.76004529 -0.119936533 0.638706923 0.0792893 0.00017 +0.000489578524 -8.19000052e-05 0.000396058458 0.770959139 -0.128971264 0.623689353 0.0811988 0.00017 +0.000498649315 -8.82000095e-05 0.000388695538 0.781130612 -0.138164684 0.608888745 0.0835251 0.00017 +0.000506444718 -9.45000065e-05 0.000380596175 0.790673494 -0.147535652 0.594195783 0.0862747 0.00017 +0.000513050705 -0.000100800004 0.000371810136 0.799667954 -0.157112226 0.579522967 0.089499 0.00017 +0.000518506684 -0.000107100001 0.000362360151 0.808171928 -0.166931733 0.564793706 0.0933065 0.00017 +0.000522812654 -0.000113400012 0.000352246192 0.816227496 -0.177042797 0.549935102 0.0978446 0.00017 +0.000525929092 -0.000119700002 0.000341445528 0.823864281 -0.187509209 0.534871995 0.103319 0.00017 +0.000527770258 -0.000126000014 0.000329908478 0.831101239 -0.198417321 0.519520283 0.110065 0.00017 +0.00052818557 -0.000132300018 0.000317548256 0.837946355 -0.20988895 0.503778279 0.118629 0.00017 +0.000526922755 -0.000138600008 0.000304219167 0.844394028 -0.222106621 0.487511426 0.129962 0.00017 +0.000539097528 -0.000132300018 0.000298648287 0.85525775 -0.20988895 0.473794162 0.124427 0.00017 +0.000549594115 -0.000126000014 0.000292108452 0.865468204 -0.198417321 0.459995031 0.121062 0.00017 +0.000558664906 -0.000119700009 0.000284745503 0.875144601 -0.187509224 0.446051806 0.119202 0.00017 +0.00056646025 -0.000113400012 0.000276646198 0.884371281 -0.177042797 0.431906641 0.118503 0.00017 +0.000573066238 -0.000107100015 0.00026786013 0.893211484 -0.166931763 0.417501003 0.118765 0.00017 +0.000578522217 -0.000100800011 0.000258410146 0.901715398 -0.157112241 0.402771711 0.119909 0.00017 +0.000582828186 -9.45000065e-05 0.000248296186 0.909925222 -0.147535667 0.38764593 0.121936 0.00017 +0.000585944741 -8.82000095e-05 0.000237495522 0.917878211 -0.138164684 0.372035027 0.124901 0.00017 +0.000587785849 -8.19000124e-05 0.000225958473 0.925610244 -0.128971279 0.35582599 0.128969 0.00017 +0.000588201219 -7.56000081e-05 0.00021359828 0.933158815 -0.119936541 0.338865548 0.134455 0.00017 +0.000583555724 -6.30000141e-05 0.000185716257 0.947904348 -0.102334678 0.301669985 0.152268 0.00017 +0.00059027283 -5.04000054e-05 0.000189594342 0.948961973 -0.0810264125 0.304804504 0.141399 0.00017 +0.000595143356 -3.78000004e-05 0.000192406369 0.949777186 -0.0603242554 0.30705741 0.13459 0.00017 +0.000598463463 -2.52000027e-05 0.00019432322 0.950355113 -0.0400173999 0.308583707 0.130544 0.00017 +0.000600398751 -1.2600005e-05 0.000195440574 0.950699985 -0.0199514478 0.309469908 0.128658 0.00017 +0.000601035019 0 0.000195807908 0.950814545 0 0.30976066 0.128658 0.00017 +0.000600398751 1.25999977e-05 0.000195440574 0.950699985 0.0199514367 0.309469908 0.130547 0.00017 +0.000598463463 2.51999991e-05 0.00019432322 0.950355113 0.0400173925 0.308583707 0.13459 0.00017 +0.000595143356 3.78000004e-05 0.000192406369 0.949777186 0.0603242554 0.30705741 0.141399 0.00017 +0.00059027283 5.03999981e-05 0.000189594342 0.948961973 0.0810264051 0.304804504 0.152268 0.00017 +0.000583555724 6.30000068e-05 0.000185716257 0.947904348 0.102334663 0.301669985 0.152268 0.00017 +0.000578099862 8.19000052e-05 0.000195166271 0.939042032 0.133035049 0.317020178 0.156394 0.00017 +0.000579360931 8.82000095e-05 0.000208494326 0.931419313 0.141796216 0.335189402 0.168001 0.00017 +0.000578775478 9.44999992e-05 0.000220756367 0.923656046 0.150810644 0.352300614 0.1598 0.00017 +0.000576639606 0.000100800004 0.000232123202 0.915699005 0.160069585 0.368609756 0.154536 0.00017 +0.000573118974 0.000107100008 0.000242690556 0.907503784 0.16958724 0.384287775 0.15148 0.00017 +0.000568299263 0.000113400005 0.000252507918 0.899027765 0.179394484 0.399457902 0.150351 0.00017 +0.000562207075 0.000119700002 0.000261590583 0.890225291 0.189538658 0.414214909 0.151155 0.00017 +0.00055481575 0.000126000014 0.000269923214 0.881042898 0.200086996 0.428635895 0.15417 0.00017 +0.000546039781 0.000132299989 0.000277456391 0.871413648 0.211134836 0.442786932 0.160125 0.00017 +0.000535713218 0.000138600008 0.000284094305 0.861248374 0.222822636 0.456728995 0.0988948 0.00017 +0.000523540191 0.000144900012 0.000289666263 0.850417495 0.235369742 0.470522165 0.0893505 0.00017 +0.000512628292 0.000144899997 0.000308566261 0.832692623 0.235369697 0.501222551 0.0976556 0.00017 +0.000513889361 0.000138599993 0.000321894331 0.826162815 0.222822607 0.517498851 0.0717591 0.00017 +0.000513303967 0.000132299989 0.000334156386 0.819171309 0.211134866 0.533273339 0.138266 0.00017 +0.000511168095 0.000126000014 0.000345523207 0.811730683 0.200086981 0.548687994 0.126725 0.00017 +0.000507647463 0.000119700002 0.000356090604 0.803833067 0.189538658 0.563850701 0.118142 0.00017 +0.000502827752 0.000113400005 0.000365907908 0.795454323 0.179394484 0.578852355 0.111573 0.00017 +0.000496735564 0.000107100001 0.000374990603 0.786554575 0.16958721 0.593777895 0.106483 0.00017 +0.00048934418 0.000100799996 0.000383323204 0.777074575 0.16006957 0.608714104 0.102593 0.00017 +0.000480568124 9.44999992e-05 0.000390856352 0.766928911 0.150810644 0.623759687 0.0998011 0.00017 +0.000470241648 8.82000022e-05 0.000397494325 0.755991876 0.141796201 0.639038444 0.0981802 0.00017 +0.000458068651 8.18999979e-05 0.000403066253 0.744068205 0.133035034 0.654724538 0.0734442 0.00017 +0.000452612643 6.30000141e-05 0.000412516238 0.73520571 0.102334678 0.670074701 0.0810779 0.00017 +0.00045932972 5.04000054e-05 0.000416394323 0.738449097 0.0810264125 0.669423282 0.0768838 0.00017 +0.000464200246 3.78000004e-05 0.000419206335 0.740807772 0.0603242554 0.669002891 0.0716182 0.00017 +0.000467520353 2.52000027e-05 0.000421123201 0.742418528 0.0400173999 0.668740213 0.068315 0.00017 +0.000469455641 1.2600005e-05 0.000422240555 0.743358374 0.019951446 0.668595731 0.066348 0.00017 +0.000470091938 0 0.000422607874 0.743667543 0 0.668549597 0.0654152 0.00017 +0.000469455641 -1.25999977e-05 0.000422240555 0.743358374 -0.0199514348 0.668595731 0.0654152 0.00017 +0.000467520353 -2.51999991e-05 0.000421123201 0.742418528 -0.0400173925 0.668740213 0.066348 0.00017 +0.000464200246 -3.78000004e-05 0.000419206335 0.740807772 -0.0603242554 0.669002891 0.068315 0.00017 +0.00045932972 -5.03999981e-05 0.000416394323 0.738449097 -0.0810264051 0.669423282 0.0716182 0.00017 +0.000452612643 -6.30000068e-05 0.000412516238 0.73520571 -0.102334663 0.670074701 0.0768838 0.00017 +0.000458068651 -8.19000052e-05 0.000403066253 0.744068205 -0.133035049 0.654724538 0.085421 0.00017 +0.000470241648 -8.82000095e-05 0.000397494325 0.755991876 -0.141796216 0.639038444 0.0865419 0.00017 +0.000480568124 -9.44999992e-05 0.000390856352 0.766928911 -0.150810644 0.623759687 0.0884579 0.00017 +0.00048934418 -0.000100800004 0.000383323204 0.777074575 -0.16006957 0.608714104 0.0910144 0.00017 +0.000496735505 -0.000107100008 0.000374990545 0.786554575 -0.16958724 0.593777835 0.0942175 0.00017 +0.000502827752 -0.000113400005 0.000365907908 0.795454323 -0.179394484 0.578852355 0.0981332 0.00017 +0.000507647463 -0.000119700002 0.000356090604 0.803833067 -0.189538658 0.563850701 0.102936 0.00017 +0.000511168095 -0.000126000014 0.000345523207 0.811730683 -0.200086981 0.548687994 0.108863 0.00017 +0.000513303967 -0.000132299989 0.000334156386 0.819171309 -0.211134866 0.533273339 0.116302 0.00017 +0.000513889361 -0.000138600008 0.000321894331 0.826162815 -0.222822636 0.517498851 0.125935 0.00017 +0.000512628234 -0.000144900012 0.000308566232 0.832692623 -0.235369742 0.501222551 0.138999 0.00017 +0.000508970174 -0.000151200002 0.000293854246 0.838713467 -0.249156997 0.48423174 0.158004 0.00017 +0.00052354025 -0.000144899997 0.000289666292 0.850417554 -0.235369697 0.470522195 0.145883 0.00017 +0.000535713218 -0.000138599993 0.000284094305 0.861248374 -0.222822607 0.456728995 0.138678 0.00017 +0.000546039781 -0.000132299989 0.000277456391 0.871413648 -0.211134836 0.442786932 0.134391 0.00017 +0.00055481575 -0.000126000014 0.000269923214 0.881042898 -0.200086996 0.428635895 0.132096 0.00017 +0.000562207075 -0.000119700002 0.000261590583 0.890225291 -0.189538658 0.414214909 0.131314 0.00017 +0.000568299263 -0.000113400005 0.000252507918 0.899027765 -0.179394484 0.399457902 0.131816 0.00017 +0.000573119032 -0.000107100001 0.000242690585 0.907503784 -0.16958721 0.384287775 0.133531 0.00017 +0.000576639606 -0.000100799996 0.000232123202 0.915699005 -0.16006957 0.368609756 0.136513 0.00017 +0.000578775478 -9.44999992e-05 0.000220756367 0.923656046 -0.150810644 0.352300614 0.140972 0.00017 +0.000579360931 -8.82000022e-05 0.000208494326 0.931419313 -0.141796201 0.335189402 0.147319 0.00017 +0.000578099862 -8.18999979e-05 0.000195166271 0.939042032 -0.133035034 0.317020178 0.156394 0.00017 +0.000584184425 -4.41000047e-05 0.000173479217 0.956124306 -0.0721776932 0.283930361 0.15411 0.00017 +0.000589011761 -3.14999997e-05 0.000176266272 0.956766844 -0.0511673242 0.286319792 0.146002 0.00017 +0.000592067197 -1.89000002e-05 0.000178030328 0.957196295 -0.0305556711 0.287822008 0.141703 0.00017 +0.000593551726 -6.3000025e-06 0.000178887421 0.95741117 -0.0101620341 0.288549095 0.140354 0.00017 +0.000593551726 6.3000025e-06 0.000178887421 0.95741117 0.0101620341 0.288549095 0.141703 0.00017 +0.000592067197 1.89000002e-05 0.000178030328 0.957196295 0.0305556711 0.287822008 0.146002 0.00017 +0.000589011761 3.15000034e-05 0.000176266272 0.956766844 0.0511673279 0.286319792 0.15411 0.00017 +0.000584184425 4.41000047e-05 0.000173479217 0.956124306 0.0721776932 0.283930361 0.15411 0.00017 +0.000567816605 0.000100800004 0.000201829214 0.929335356 0.16497758 0.330330312 0.168001 0.00017 +0.000567187904 0.000107100001 0.000214066284 0.921317101 0.173968911 0.347720593 0.0360068 0.00017 +0.00056478742 0.000113400005 0.000225280324 0.91309303 0.183334023 0.364211172 0.0456583 0.00017 +0.00056081597 0.000119700002 0.000235587417 0.904607654 0.193078578 0.380007356 0.0532483 0.00017 +0.000555359991 0.000126000014 0.00024503743 0.895807147 0.203240618 0.39525044 0.0599371 0.00017 +0.000548419484 0.000132300018 0.000253630336 0.886630952 0.213889703 0.41004467 0.0664784 0.00017 +0.000539908069 0.000138599993 0.00026131628 0.877004802 0.225136235 0.424471587 0.0735698 0.00017 +0.000529624871 0.000144899997 0.000267979223 0.866827607 0.237155274 0.438596845 0.0820718 0.00017 +0.000496889057 0.000144899997 0.000324679218 0.813249528 0.237155274 0.531396747 0.109413 0.00017 +0.000496260356 0.000138600008 0.000336916215 0.806105256 0.225136265 0.547273099 0.0648437 0.00017 +0.000493859872 0.000132300018 0.000348130328 0.798424304 0.213889703 0.562823057 0.0608401 0.00017 +0.00048988848 0.000126000014 0.000358437392 0.790200174 0.203240603 0.578166902 0.059118 0.00017 +0.000484432472 0.000119700002 0.000367887405 0.781399548 0.193078578 0.593409956 0.0590545 0.00017 +0.000477491994 0.000113400005 0.00037648034 0.771962345 0.183334023 0.608656526 0.0603879 0.00017 +0.000468980579 0.000107100008 0.000384166255 0.761793077 0.173968911 0.624024153 0.0631576 0.00017 +0.000458697323 0.000100800004 0.000390829227 0.75074178 0.16497758 0.639663279 0.0676998 0.00017 +0.000442329416 4.41000047e-05 0.00041917921 0.72395277 0.0721776932 0.68606323 0.0922396 0.00017 +0.000447156752 3.14999997e-05 0.000421966281 0.726343334 0.0511673242 0.685424924 0.0707875 0.00017 +0.000450212188 1.89000002e-05 0.000423730322 0.727858961 0.0305556692 0.68504566 0.0671864 0.00017 +0.000451696716 6.3000025e-06 0.000424587401 0.728596091 0.0101620341 0.684868217 0.0652739 0.00017 +0.000451696716 -6.3000025e-06 0.000424587401 0.728596091 -0.0101620341 0.684868217 0.0646789 0.00017 +0.000450212188 -1.89000002e-05 0.000423730322 0.727858961 -0.0305556692 0.68504566 0.0652739 0.00017 +0.000447156752 -3.15000034e-05 0.000421966281 0.726343334 -0.0511673279 0.685424924 0.0671864 0.00017 +0.000442329416 -4.41000047e-05 0.00041917921 0.72395277 -0.0721776932 0.68606323 0.0707875 0.00017 +0.000458697323 -0.000100800004 0.000390829227 0.75074178 -0.16497758 0.639663279 0.0981802 0.00017 +0.000468980579 -0.000107100001 0.000384166255 0.761793077 -0.173968911 0.624024153 0.0998011 0.00017 +0.000477491994 -0.000113400005 0.00037648034 0.771962345 -0.183334023 0.608656526 0.102593 0.00017 +0.000484432472 -0.000119700002 0.000367887405 0.781399548 -0.193078578 0.593409956 0.106483 0.00017 +0.00048988848 -0.000126000014 0.000358437392 0.790200174 -0.203240603 0.578166902 0.111573 0.00017 +0.000493859872 -0.000132300018 0.000348130328 0.798424304 -0.213889703 0.562823057 0.118142 0.00017 +0.000496260414 -0.000138599993 0.000336916244 0.806105316 -0.225136235 0.547273099 0.126725 0.00017 +0.000496889057 -0.000144899997 0.000324679218 0.813249528 -0.237155274 0.531396747 0.138266 0.00017 +0.000529624871 -0.000144899997 0.000267979223 0.866827607 -0.237155274 0.438596845 0.160125 0.00017 +0.000539908011 -0.000138600008 0.000261316251 0.877004921 -0.225136295 0.424471647 0.154172 0.00017 +0.000548419484 -0.000132300018 0.000253630336 0.886630952 -0.213889703 0.41004467 0.151155 0.00017 +0.000555359991 -0.000126000014 0.00024503743 0.895807147 -0.203240618 0.39525044 0.150351 0.00017 +0.00056081597 -0.000119700002 0.000235587417 0.904607654 -0.193078578 0.380007356 0.15148 0.00017 +0.00056478742 -0.000113400005 0.000225280324 0.91309303 -0.183334023 0.364211172 0.154533 0.00017 +0.000567187904 -0.000107100008 0.000214066284 0.921317101 -0.173968911 0.347720593 0.159801 0.00017 +0.000567816605 -0.000100800004 0.000201829214 0.929335356 -0.16497758 0.330330312 0.168004 0.00017 diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp new file mode 100644 index 00000000..9fcd14ae --- /dev/null +++ b/examples/cray_eye.cpp @@ -0,0 +1,109 @@ +/* + * A compound ray eye viewer + * + * Demonstrating use of mplot::compoundray::EyeVisual + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +int main (int argc, char** argv) +{ + std::string eyefile = ""; + if (argc < 2) { + std::cout << "Usage: " << argv[0] << " path/to/eyefile.eye\n"; + return -1; + } else { + eyefile = std::string (argv[1]); + } + + auto v = mplot::Visual<>(1024, 768, "mplot::compoundray::EyeVisual"); + + // We read the information from the eye file into a vector of Ommatidium objects. Ommatidium is + // defined in "cameras/CompoundEyeDataTypes.h" in compound ray, mplot::Ommatidium is a + // mplot/Seb's maths style equivalent. It contains 2 3D float vectors and two scalar floating point + // values. + auto ommatidia = std::make_unique>(); + std::vector> ommatidiaColours; + + // Read the eye file into ommatidia data structure. compound ray does this internally when we're + // using it, but for this example we instead make use of mplot::compoundray::readEye + if (mplot::compoundray::readEye (ommatidia.get(), eyefile) == nullptr) { std::cout << "Failed to read eye\n"; return -1; } + + // Make some dummy data to demo the eye + sm::vvec ommatidiaData; + ommatidiaData.linspace (0, 1, ommatidia->size()); + // Colour it with a colour map + mplot::ColourMap cm (mplot::ColourMapType::Plasma); + ommatidiaColours.resize (ommatidia->size()); + for (size_t i = 0; i < ommatidia->size(); ++i) { + ommatidiaColours[i] = cm.convert (ommatidiaData[i]); + } + + // A second eye goes in the 'eye only' window + mplot::compoundray::EyeVisual<>* ep = nullptr; + auto eyevm = std::make_unique> (sm::vec<>{}, &ommatidiaColours, ommatidia.get()); + v.bindmodel (eyevm); + eyevm->name = "Big Eye"; + eyevm->show_cones = false; + eyevm->proj_sphere_centre = { 0, 0, 0 }; + eyevm->proj_sphere_radius = 0.6f; + eyevm->show_sphere = true; + eyevm->setAlpha (0.1f); + eyevm->finalize(); + + ep = v.addVisualModel (eyevm); + // Scale this model up, so it's not tiny like the one in the scene + ep->scaleViewMatrix (1000); + + if (ep->show_sphere) { + auto svm = std::make_unique> (ep->proj_sphere_centre, ep->proj_sphere_radius, mplot::colour::slategray1); + v.bindmodel (svm); + svm->setAlpha (0.5); + svm->finalize(); + v.addVisualModel (svm); + + + // Can now find intersections on our sphere + sm::vec<> l0 = (*ommatidia)[0].relativePosition; + sm::vec<> l = -(*ommatidia)[0].relativeDirection; + +#if 1 + auto vvm = std::make_unique> (l0); + v.bindmodel (vvm); + vvm->vgoes = mplot::VectorGoes::FromOrigin; + vvm->thickness = 0.001f; + vvm->thevec = l; + vvm->finalize(); + v.addVisualModel (vvm); +#endif + + sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (sm::vec<>{}, ep->proj_sphere_radius, l0, l); + + if (intersections[0][0] != std::numeric_limits::max()) { + auto ivm1 = std::make_unique> (intersections[0], 0.01f, mplot::colour::crimson); + v.bindmodel (ivm1); + ivm1->finalize(); + v.addVisualModel (ivm1); + } + + if (intersections[1][0] != std::numeric_limits::max()) { + auto ivm2 = std::make_unique> (intersections[1], 0.01f, mplot::colour::blue); + v.bindmodel (ivm2); + ivm2->finalize(); + v.addVisualModel (ivm2); + } + } + + v.keepOpen(); +} diff --git a/maths b/maths index ee7e1c33..6aa3da76 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit ee7e1c33787bc4e832e0b379927a872b4aa9d86d +Subproject commit 6aa3da7634a34b0e592d28ac78882b6c89616460 diff --git a/mplot/SphereVisual.h b/mplot/SphereVisual.h index d8e0e543..423982bc 100644 --- a/mplot/SphereVisual.h +++ b/mplot/SphereVisual.h @@ -1,5 +1,6 @@ /* - * You just want a sphere visual model? Here it is. + * You just want a sphere visual model? Here it is. This uses the beautiful icosahedral geodesic + * sphere primitive (computeSphereGeoFast) */ #pragma once @@ -10,7 +11,7 @@ namespace mplot { //! This class creates the vertices for a simple sphere in a 3D scene. - template + template class SphereVisual : public VisualModel { public: @@ -33,13 +34,14 @@ namespace mplot void initializeVertices() { - this->computeSphere ({0,0,0}, this->sphere_colour, this->radius); + this->template computeSphereGeoFast (sm::vec{}, this->sphere_colour, this->radius); } //! The radius of the sphere float radius = 1.0f; //! The colour of the sphere std::array sphere_colour = {1.0f, 0.0f, 0.0f}; + }; } // namespace mplot diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index e393b416..f09f1d73 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -11,10 +11,56 @@ #include #include -#include "cameras/CompoundEyeDataTypes.h" - namespace mplot::compoundray { + // This is a binary-compatible equivalent to Ommatidium from cameras/CompoundEyeDataTypes.h in compound-ray. + // Use reinterpret_cast*>(ommatidia) if using compound ray. + struct Ommatidium + { + sm::vec relativePosition = {}; + sm::vec relativeDirection = {}; + float acceptanceAngleRadians = 0.0f; + float focalPointOffset = 0.0f; + }; + + // Helper function. Read the compound-ray csv eye file into ommatidia. ommatidia should be a pointer to an allocate vector. + [[maybe_unused]] static std::vector* readEye (std::vector* ommatidia, + const std::string& path) + { + if (ommatidia == nullptr) { return ommatidia; } + + std::cout << "Path: " << path << std::endl; + + ommatidia->clear(); + + std::ifstream eyeDataFile (path, std::ifstream::in); + if(!eyeDataFile.is_open()) { + std::cout << "Failed to open eye data file " << path << "\n"; + return ommatidia; + } + + std::string line; + size_t ommCount = 0; + while (std::getline (eyeDataFile, line)) { + std::vector splitData = mplot::tools::stringToVector (line, " "); + if (splitData.size() < 8) { + std::cout << "Malformed line, continue...\n"; + continue; + } + mplot::compoundray::Ommatidium o = { + sm::vec{ std::stof(splitData[0]), std::stof(splitData[1]), std::stof(splitData[2]) }, + sm::vec{ std::stof(splitData[3]), std::stof(splitData[4]), std::stof(splitData[5]) }, + std::stof(splitData[6]), + std::stof(splitData[7]) + }; + ommatidia->push_back (o); + ommCount++; + } + std::cout << " Loaded " << ommCount << " ommatidia." << std::endl; + + return ommatidia; + } + //! This class creates a visualization of a compound-ray format compound eye model template class EyeVisual : public mplot::VisualModel @@ -25,7 +71,7 @@ namespace mplot::compoundray //! Initialise with offset, start and end coordinates, radius and a single colour. EyeVisual (const sm::vec _offset, std::vector>* _ommData, - std::vector* _ommatidia) + std::vector* _ommatidia) { this->init (_offset, _ommData, _ommatidia); } @@ -34,7 +80,7 @@ namespace mplot::compoundray void init (const sm::vec _offset, std::vector>* _ommData, - std::vector* _ommatidia) + std::vector* _ommatidia) { this->viewmatrix.translate (_offset); this->ommData = _ommData; @@ -109,12 +155,10 @@ namespace mplot::compoundray for (size_t i = 0u; i < n_omm; ++i) { // Ommatidia colour, position/shape std::array colour = (*ommData)[i]; - float3 rpos = (*ommatidia)[i].relativePosition; - float3 rdir = (*ommatidia)[i].relativeDirection; float angle = (*ommatidia)[i].acceptanceAngleRadians; float focal_point = (*ommatidia)[i].focalPointOffset; - sm::vec pos = { rpos.x, rpos.y, rpos.z }; - sm::vec dir = { rdir.x, rdir.y, rdir.z }; + sm::vec pos = (*ommatidia)[i].relativePosition; + sm::vec dir = (*ommatidia)[i].relativeDirection; dir.renormalize(); // Tip of cone is 'behind' the position of the ommatidial face/lens sm::vec ommatidial_detector_point = pos - dir * focal_point; @@ -134,12 +178,10 @@ namespace mplot::compoundray // ommatidial sensor AND the centre of the ommatidial lens for (size_t i = 0u; i < n_omm; ++i) { std::array colour = (*ommData)[i]; - float3 rpos = (*ommatidia)[i].relativePosition; - float3 rdir = (*ommatidia)[i].relativeDirection; float angle = (*ommatidia)[i].acceptanceAngleRadians; // pos will be the tip of the cone in this case, and the centre of the disc - sm::vec pos = { rpos.x, rpos.y, rpos.z }; - sm::vec dir = { rdir.x, rdir.y, rdir.z }; + sm::vec pos = (*ommatidia)[i].relativePosition; + sm::vec dir = (*ommatidia)[i].relativeDirection; dir.renormalize(); // do a cone sm::vec ommatidial_cone_pos = pos + dir * this->cone_length; @@ -158,6 +200,9 @@ namespace mplot::compoundray } } + if (this->show_2d) { + // Compute intersections between ommatidia direction vectors and our projection sphere. + } } // Visualize in two modes "disc" mode, showing just a 2D disc for each ommatidium and @@ -165,8 +210,8 @@ namespace mplot::compoundray bool show_cones = false; // The colours detected by each ommatidium std::vector>* ommData = nullptr; - // The position and orientation of each oimmatidium - std::vector* ommatidia = nullptr; + // The position and orientation of each ommatidium + std::vector* ommatidia = nullptr; // If sum is 0, then we have a special case for rendering the eye as we have no focal point // offsets specified for this eye (and hence the radius of the ommatidium is not known) float focal_point_sum = 0.0f; @@ -188,6 +233,15 @@ namespace mplot::compoundray // Setter for the disc width. To replace cone length? Or operate as alternative? void set_disc_width (float _disc_width) { this->disc_width = _disc_width; this->reinit(); } float get_disc_width() { return this->disc_width; } + + // Parameters to reduce the visual to 2D. Use these to draw a sphere externally with a + // SphereVisual for your debugging. + bool show_2d = true; + float proj_sphere_radius = 0.0f; + sm::vec proj_sphere_centre = {}; + bool show_sphere = true; + sm::vvec> proj_sphere_intersections; + private: // User-modifiable ommatidial cone length which is used if there's no focal point offset float cone_length = 0.1f; From 92671b4dc6cc117280db300254a7a583ed2cfc32 Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 21 Nov 2025 12:56:47 +0000 Subject: [PATCH 02/41] More WIP --- examples/ant_eyes_dhex.eye | 1024 ----------------------- examples/cray_eye.cpp | 58 +- examples/hexy_eyes_dhex.eye | 1560 +++++++++++++++++++++++++++++++++++ maths | 2 +- 4 files changed, 1590 insertions(+), 1054 deletions(-) delete mode 100644 examples/ant_eyes_dhex.eye create mode 100644 examples/hexy_eyes_dhex.eye diff --git a/examples/ant_eyes_dhex.eye b/examples/ant_eyes_dhex.eye deleted file mode 100644 index d03148b4..00000000 --- a/examples/ant_eyes_dhex.eye +++ /dev/null @@ -1,1024 +0,0 @@ --0.000588897266 0 0.000340000173 -0.866025329 0 0.500000238 0.079482 0.00017 --0.000593948294 -6.30000022e-06 0.000330316368 -0.873904049 -0.00926948711 0.486010015 0.0813195 0.00017 --0.000593948294 6.30000022e-06 0.000330316368 -0.873904049 0.00926948711 0.486010015 0.081564 0.00017 --0.000588492316 1.26000004e-05 0.000339766382 -0.865876496 0.0185389742 0.499914289 0.0799489 0.00017 --0.000583036337 6.30000022e-06 0.000349216367 -0.857848823 0.00926948711 0.513818502 0.0779201 0.00017 --0.000583036337 -6.30000022e-06 0.000349216367 -0.857848823 -0.00926948711 0.513818502 0.0776939 0.00017 --0.000588492316 -1.26000004e-05 0.000339766382 -0.865876496 -0.0185389742 0.499914289 0.079482 0.00017 --0.000598182727 -1.26000004e-05 0.000320161082 -0.881508231 -0.0185679123 0.471803427 0.0834594 0.00017 --0.000598590996 0 0.000320396823 -0.881649673 0 0.471904457 0.0834594 0.00017 --0.000598182727 1.26000004e-05 0.000320161082 -0.881508231 0.0185679123 0.471803427 0.0839627 0.00017 --0.000593135017 1.89000002e-05 0.000329846836 -0.873613715 0.0278373361 0.485823154 0.0823001 0.00017 --0.00058727077 2.52000009e-05 0.000339061109 -0.865427911 0.0371358246 0.499655306 0.0809104 0.00017 --0.00058222306 1.89000002e-05 0.000348746835 -0.857541859 0.0278373398 0.513660491 0.0786095 0.00017 --0.000576358812 1.26000004e-05 0.000357961108 -0.849347651 0.0185679123 0.527507186 0.076598 0.00017 --0.000576767139 0 0.000358196849 -0.849505901 0 0.527579188 0.0761446 0.00017 --0.000576358812 -1.26000004e-05 0.000357961108 -0.849347651 -0.0185679123 0.527507186 0.0761446 0.00017 --0.00058222306 -1.89000002e-05 0.000348746835 -0.857541859 -0.0278373398 0.513660491 0.0779201 0.00017 --0.00058727077 -2.52000009e-05 0.000339061109 -0.865427911 -0.0371358246 0.499655306 0.0799489 0.00017 --0.000593135017 -1.89000002e-05 0.000329846836 -0.873613715 -0.0278373361 0.485823154 0.081564 0.00017 --0.000601579552 -1.89000002e-05 0.000309522293 -0.888857722 -0.0279255006 0.457331479 0.0859497 0.00017 --0.000602406741 -6.30000068e-06 0.000309999858 -0.889134884 -0.00929861795 0.457550794 0.085684 0.00017 --0.000602406741 6.29999977e-06 0.000309999858 -0.889134884 0.00929861609 0.457550794 0.0859497 0.00017 --0.000601579552 1.89000002e-05 0.000309522293 -0.888857722 0.0279255006 0.457331479 0.0867417 0.00017 --0.00059695082 2.52000009e-05 0.000319449871 -0.881082058 0.0371944718 0.471498728 0.0849875 0.00017 --0.000591494842 3.15000034e-05 0.000328899885 -0.873029172 0.046493087 0.485446662 0.0835562 0.00017 --0.000585211674 3.78000004e-05 0.000337872276 -0.864673555 0.055851005 0.499219745 0.0824087 0.00017 --0.000580582884 3.15000034e-05 0.000347799854 -0.856923521 0.0464930907 0.5133425 0.0798044 0.00017 --0.000575126905 2.51999991e-05 0.000357249868 -0.848870635 0.0371944681 0.527290463 0.0775191 0.00017 --0.000568843738 1.89000002e-05 0.000366222288 -0.840489268 0.0279255025 0.541108012 0.0755244 0.00017 --0.000569670927 6.30000068e-06 0.000366699853 -0.840817809 0.00929861888 0.541238368 0.074822 0.00017 --0.000569670927 -6.29999977e-06 0.000366699853 -0.840817809 -0.00929861702 0.541238368 0.0746096 0.00017 --0.000568843738 -1.89000002e-05 0.000366222288 -0.840489268 -0.0279255025 0.541108012 0.074822 0.00017 --0.000575126905 -2.52000009e-05 0.000357249868 -0.848870635 -0.0371944718 0.527290463 0.076598 0.00017 --0.000580582884 -3.15000034e-05 0.000347799854 -0.856923521 -0.0464930907 0.5133425 0.0786095 0.00017 --0.000585211674 -3.78000004e-05 0.000337872276 -0.864673555 -0.055851005 0.499219745 0.0809104 0.00017 --0.000591494842 -3.15000034e-05 0.000328899885 -0.873029172 -0.046493087 0.485446662 0.0823001 0.00017 --0.00059695082 -2.51999991e-05 0.000319449871 -0.881082058 -0.0371944681 0.471498728 0.0839627 0.00017 --0.000604102155 -2.52000009e-05 0.000298378756 -0.895970285 -0.0373752192 0.44253853 0.0888388 0.00017 --0.000605366717 -1.25999995e-05 0.000299108855 -0.896378636 -0.0186570715 0.442896456 0.0882751 0.00017 --0.000605785695 0 0.000299350766 -0.896514118 0 0.443015039 0.0882751 0.00017 --0.000605366717 1.26000004e-05 0.000299108855 -0.896378636 0.0186570734 0.442896456 0.0888388 0.00017 --0.000604102155 2.52000009e-05 0.000298378756 -0.895970285 0.0373752192 0.44253853 0.0899973 0.00017 --0.000599910796 3.15000034e-05 0.00030855884 -0.888299882 0.0466426797 0.456889182 0.0881213 0.00017 --0.000594873796 3.78000004e-05 0.000318250735 -0.880365431 0.0559409633 0.470985502 0.0865986 0.00017 --0.000588998897 4.41000011e-05 0.000327458838 -0.872142315 0.0652997419 0.484874815 0.0854108 0.00017 --0.000582278357 5.04000018e-05 0.000336178724 -0.8636024 0.0747504383 0.498601347 0.0845415 0.00017 --0.00057808694 4.41000047e-05 0.000346358836 -0.855984867 0.0652997568 0.512860417 0.0815675 0.00017 --0.00057304994 3.78000004e-05 0.000356050761 -0.84806782 0.0559409633 0.526926458 0.0789831 0.00017 --0.000567174982 3.15000034e-05 0.000365258835 -0.839827359 0.0466426834 0.54084605 0.0767034 0.00017 --0.0005604545 2.52000009e-05 0.000373978721 -0.831234515 0.0373752192 0.554664135 0.0746869 0.00017 --0.000561719062 1.25999995e-05 0.000374708819 -0.831748664 0.0186570715 0.554838836 0.0737421 0.00017 --0.000562138041 0 0.00037495073 -0.831919134 0 0.554896951 0.0732868 0.00017 --0.000561719062 -1.26000004e-05 0.000374708819 -0.831748664 -0.0186570734 0.554838836 0.0732868 0.00017 --0.0005604545 -2.52000009e-05 0.000373978721 -0.831234515 -0.0373752192 0.554664135 0.0737421 0.00017 --0.000567174982 -3.15000034e-05 0.000365258835 -0.839827359 -0.0466426834 0.54084605 0.0755244 0.00017 --0.00057304994 -3.78000004e-05 0.000356050761 -0.84806782 -0.0559409633 0.526926458 0.0775191 0.00017 --0.00057808694 -4.41000011e-05 0.000346358836 -0.855984867 -0.0652997494 0.512860417 0.0798044 0.00017 --0.000582278357 -5.04000018e-05 0.000336178724 -0.8636024 -0.0747504383 0.498601347 0.0824087 0.00017 --0.000588998897 -4.41000047e-05 0.000327458838 -0.872142315 -0.0652997494 0.484874815 0.0835562 0.00017 --0.000594873796 -3.78000004e-05 0.000318250735 -0.880365431 -0.0559409633 0.470985502 0.0849875 0.00017 --0.000599910796 -3.15000034e-05 0.00030855884 -0.888299882 -0.0466426797 0.456889182 0.0867417 0.00017 --0.000605694251 -3.15000034e-05 0.000286697934 -0.902862072 -0.0469546393 0.427358657 0.0922396 0.00017 --0.000607424881 -1.89000002e-05 0.000287697098 -0.903398275 -0.0281092003 0.427880138 0.0913246 0.00017 --0.000608282047 -6.29999886e-06 0.000288191979 -0.903664708 -0.00935928803 0.428138435 0.0910208 0.00017 --0.000608282047 6.30000068e-06 0.000288191979 -0.903664708 0.00935929082 0.428138435 0.0913246 0.00017 --0.000607424881 1.89000002e-05 0.000287697098 -0.903398275 0.0281092003 0.427880138 0.0922396 0.00017 --0.000605694251 3.15000034e-05 0.000286697934 -0.902862072 0.0469546393 0.427358657 0.0938308 0.00017 --0.000601968903 3.78000004e-05 0.000297147111 -0.895283818 0.0562184006 0.441934764 0.0918037 0.00017 --0.000597370148 4.41000047e-05 0.000307092007 -0.887453914 0.0655150265 0.456216276 0.0901703 0.00017 --0.000591914228 5.04000018e-05 0.000316541991 -0.879348516 0.0748743117 0.470255196 0.0888972 0.00017 --0.000585601083 5.67000025e-05 0.000325497094 -0.870940566 0.0843276009 0.484098554 0.0879869 0.00017 --0.000578414474 6.30000068e-05 0.000333947944 -0.862198114 0.0939092785 0.497790605 0.0874474 0.00017 --0.000574689126 5.67000061e-05 0.000344397093 -0.854711652 0.0843276009 0.512207747 0.0840211 0.00017 --0.000570090313 5.04000018e-05 0.000354341988 -0.846927047 0.0748743191 0.526410997 0.081053 0.00017 --0.000564634334 4.41000047e-05 0.000363792002 -0.83882165 0.0655150339 0.540449917 0.0784479 0.00017 --0.000558321248 3.78000004e-05 0.000372747076 -0.830368459 0.0562184006 0.554371536 0.076156 0.00017 --0.000551134697 3.15000034e-05 0.000381197955 -0.821534157 0.0469546355 0.568222523 0.0741285 0.00017 --0.000552865269 1.89000002e-05 0.000382197089 -0.822254002 0.0281092003 0.568426132 0.0728881 0.00017 --0.000553722493 6.29999886e-06 0.000382692 -0.822610855 0.0093592871 0.568527758 0.072192 0.00017 --0.000553722493 -6.30000068e-06 0.000382692 -0.822610855 -0.00935928989 0.568527758 0.0719719 0.00017 --0.000552865269 -1.89000002e-05 0.000382197089 -0.822254002 -0.0281092003 0.568426132 0.072192 0.00017 --0.000551134697 -3.15000034e-05 0.000381197955 -0.821534157 -0.0469546355 0.568222523 0.0728881 0.00017 --0.000558321248 -3.78000004e-05 0.000372747076 -0.830368459 -0.0562184006 0.554371536 0.0746869 0.00017 --0.000564634334 -4.41000047e-05 0.000363792002 -0.83882165 -0.0655150339 0.540449917 0.0767034 0.00017 --0.000570090313 -5.04000018e-05 0.000354341988 -0.846927047 -0.0748743191 0.526410997 0.0789831 0.00017 --0.000574689126 -5.67000025e-05 0.000344397093 -0.854711652 -0.0843276009 0.512207747 0.0815675 0.00017 --0.000578414474 -6.30000068e-05 0.000333947944 -0.862198114 -0.0939092785 0.497790605 0.0845415 0.00017 --0.000585601083 -5.67000061e-05 0.000325497094 -0.870940566 -0.0843276009 0.484098554 0.0854108 0.00017 --0.000591914228 -5.04000018e-05 0.000316541991 -0.879348516 -0.0748743117 0.470255196 0.0865986 0.00017 --0.000597370148 -4.41000047e-05 0.000307092007 -0.887453914 -0.0655150265 0.456216276 0.0881213 0.00017 --0.000601968903 -3.78000004e-05 0.000297147111 -0.895283818 -0.0562184006 0.441934764 0.0899973 0.00017 --0.000606274116 -3.78000004e-05 0.000274432707 -0.909548283 -0.0567085519 0.411711127 0.0962897 0.00017 --0.00060851255 -2.52000027e-05 0.000275725062 -0.910210073 -0.0376940407 0.41242817 0.0949284 0.00017 --0.000609837822 -1.26000014e-05 0.000276490202 -0.910603642 -0.0188141949 0.412852347 0.0942756 0.00017 --0.000610276649 0 0.00027674358 -0.910734355 0 0.412992805 0.0942756 0.00017 --0.000609837822 1.25999995e-05 0.000276490202 -0.910603642 0.0188141912 0.412852347 0.0949284 0.00017 --0.00060851255 2.51999991e-05 0.000275725062 -0.910210073 0.0376940332 0.41242817 0.0962897 0.00017 --0.000606274116 3.78000004e-05 0.000274432707 -0.909548283 0.0567085519 0.411711127 0.0984385 0.00017 --0.000603056571 4.41000047e-05 0.000285175047 -0.902049065 0.0659645647 0.426563412 0.0961877 0.00017 --0.000598925864 5.04000018e-05 0.0002953902 -0.894309998 0.0752567723 0.441073656 0.0943858 0.00017 --0.00059390883 5.67000025e-05 0.000305093563 -0.886308014 0.0846151188 0.455300331 0.093006 0.00017 --0.000588013965 6.30000068e-05 0.00031429017 -0.878016531 0.0940709636 0.469294906 0.0920203 0.00017 --0.000581232773 6.93000038e-05 0.000322975044 -0.869404972 0.103658594 0.483104408 0.0914604 0.00017 --0.000573538302 7.56000009e-05 0.000331132702 -0.860437214 0.113417104 0.496773928 0.0913404 0.00017 --0.000570320815 6.92999965e-05 0.000341875042 -0.853083074 0.103658594 0.51137501 0.0873186 0.00017 --0.000566190109 6.30000068e-05 0.000352090196 -0.845429301 0.0940709636 0.525737524 0.0838733 0.00017 --0.000561173016 5.67000025e-05 0.000361793558 -0.837455451 0.0846151263 0.539915502 0.0808855 0.00017 --0.00055527821 5.03999981e-05 0.000370990165 -0.829135776 0.0752567649 0.553958774 0.0782564 0.00017 --0.000548496959 4.41000011e-05 0.000379675039 -0.820438981 0.0659645498 0.567915976 0.0759435 0.00017 --0.000540802546 3.78000004e-05 0.000387832697 -0.811326146 0.0567085519 0.58183676 0.0738751 0.00017 --0.000543041038 2.52000027e-05 0.000389125024 -0.812278092 0.0376940407 0.582051337 0.0723118 0.00017 --0.000544366252 1.26000014e-05 0.000389890192 -0.81284219 0.0188141949 0.582180083 0.0713235 0.00017 --0.000544805138 0 0.00039014357 -0.81302917 0 0.582223058 0.0708404 0.00017 --0.000544366252 -1.25999995e-05 0.000389890192 -0.81284219 -0.0188141912 0.582180083 0.0708404 0.00017 --0.000543041038 -2.51999991e-05 0.000389125024 -0.812278092 -0.0376940332 0.582051337 0.0713235 0.00017 --0.000540802546 -3.78000004e-05 0.000387832697 -0.811326146 -0.0567085519 0.58183676 0.0723118 0.00017 --0.000548496959 -4.41000047e-05 0.000379675039 -0.820438981 -0.0659645572 0.567915976 0.0741285 0.00017 --0.00055527821 -5.04000018e-05 0.000370990165 -0.829135776 -0.0752567723 0.553958774 0.076156 0.00017 --0.000561173016 -5.67000025e-05 0.000361793558 -0.837455451 -0.0846151263 0.539915502 0.0784479 0.00017 --0.000566190109 -6.30000068e-05 0.000352090196 -0.845429301 -0.0940709636 0.525737524 0.081053 0.00017 --0.000570320815 -6.93000038e-05 0.000341875042 -0.853083074 -0.103658609 0.51137501 0.0840211 0.00017 --0.000573538302 -7.56000009e-05 0.000331132702 -0.860437214 -0.113417104 0.496773928 0.0874474 0.00017 --0.000581232773 -6.92999965e-05 0.000322975044 -0.869404972 -0.103658579 0.483104408 0.0879869 0.00017 --0.000588013965 -6.30000068e-05 0.00031429017 -0.878016531 -0.0940709636 0.469294906 0.0888972 0.00017 --0.00059390883 -5.67000025e-05 0.000305093563 -0.886308014 -0.0846151188 0.455300331 0.0901703 0.00017 --0.000598925864 -5.03999981e-05 0.0002953902 -0.894309998 -0.0752567649 0.441073656 0.0918037 0.00017 --0.000603056571 -4.41000011e-05 0.000285175047 -0.902049065 -0.0659645647 0.426563412 0.0938308 0.00017 --0.000605723995 -4.41000047e-05 0.000261515088 -0.916044474 -0.0666930228 0.395492762 0.1012 0.00017 --0.000608530827 -3.14999997e-05 0.000263135618 -0.916829824 -0.0474587902 0.396447599 0.099256 0.00017 --0.000610368559 -1.89000002e-05 0.000264196657 -0.917347848 -0.0284055825 0.397071928 0.0981449 0.00017 --0.000611277763 -6.29999886e-06 0.000264721573 -0.917605162 -0.00945709459 0.397380531 0.0977797 0.00017 --0.000611277763 6.3000025e-06 0.000264721573 -0.917605162 0.00945710018 0.397380531 0.0981449 0.00017 --0.000610368559 1.8900002e-05 0.000264196657 -0.917347848 0.0284055844 0.397071928 0.099256 0.00017 --0.000608530827 3.15000034e-05 0.000263135618 -0.916829824 0.047458794 0.396447599 0.1012 0.00017 --0.000605723995 4.41000047e-05 0.000261515088 -0.916044474 0.0666930228 0.395492762 0.104101 0.00017 --0.000603074906 5.04000018e-05 0.000272585603 -0.908609688 0.0759340748 0.410685211 0.10153 0.00017 --0.00059945666 5.67000025e-05 0.000283096626 -0.900947869 0.0852167457 0.425477475 0.0994883 0.00017 --0.000594909885 6.30000068e-05 0.000293071585 -0.893034875 0.0945709646 0.439937472 0.097936 0.00017 --0.000589453964 6.92999965e-05 0.00030252157 -0.884844899 0.104028054 0.45412311 0.0968425 0.00017 --0.000583088782 7.56000009e-05 0.000311446609 -0.876347959 0.11362233 0.468085855 0.0962297 0.00017 --0.000575795071 8.19000052e-05 0.000319835613 -0.867509186 0.123392865 0.481873393 0.0961127 0.00017 --0.000567532261 8.82000095e-05 0.000327665068 -0.858286679 0.133386061 0.495532304 0.0965829 0.00017 --0.000564883114 8.19000052e-05 0.000338735583 -0.851068914 0.123392865 0.510348618 0.0917439 0.00017 --0.000561264926 7.56000081e-05 0.000349246635 -0.84354794 0.113622338 0.524897039 0.0876682 0.00017 --0.000556718151 6.93000038e-05 0.000359221565 -0.835704267 0.104028068 0.539236963 0.0841789 0.00017 --0.00055126223 6.30000068e-05 0.00036867155 -0.827514231 0.0945709646 0.55342257 0.0811455 0.00017 --0.000544897048 5.67000061e-05 0.000377596647 -0.81894803 0.0852167532 0.567505419 0.0784846 0.00017 --0.000537603337 5.04000054e-05 0.000385985593 -0.809968412 0.0759340748 0.581536829 0.0761295 0.00017 --0.000529340527 4.41000047e-05 0.000393815048 -0.800528705 0.0666930228 0.595571756 0.0740233 0.00017 --0.000532147358 3.14999997e-05 0.000395435578 -0.801748276 0.0474587902 0.595774472 0.0720159 0.00017 --0.00053398509 1.89000002e-05 0.000396496616 -0.802547991 0.0284055825 0.595910966 0.0706937 0.00017 --0.000534894294 6.29999886e-06 0.000397021562 -0.802943945 0.00945709459 0.595979512 0.0699221 0.00017 --0.000534894294 -6.3000025e-06 0.000397021562 -0.802943945 -0.00945710018 0.595979512 0.0696865 0.00017 --0.00053398509 -1.8900002e-05 0.000396496616 -0.802547991 -0.0284055844 0.595910966 0.0699221 0.00017 --0.000532147358 -3.15000034e-05 0.000395435578 -0.801748276 -0.047458794 0.595774472 0.0706937 0.00017 --0.000529340527 -4.41000047e-05 0.000393815048 -0.800528705 -0.0666930228 0.595571756 0.0720159 0.00017 --0.000537603337 -5.04000018e-05 0.000385985593 -0.809968412 -0.0759340748 0.581536829 0.0738751 0.00017 --0.000544897048 -5.67000025e-05 0.000377596647 -0.81894803 -0.0852167457 0.567505419 0.0759435 0.00017 --0.00055126223 -6.30000068e-05 0.00036867155 -0.827514231 -0.0945709646 0.55342257 0.0782564 0.00017 --0.000556718151 -6.92999965e-05 0.000359221565 -0.835704267 -0.104028054 0.539236963 0.0808855 0.00017 --0.000561264926 -7.56000009e-05 0.000349246635 -0.84354794 -0.11362233 0.524897039 0.0838733 0.00017 --0.000564883114 -8.19000052e-05 0.000338735583 -0.851068914 -0.123392865 0.510348618 0.0873186 0.00017 --0.000567532261 -8.82000095e-05 0.000327665068 -0.858286679 -0.133386061 0.495532304 0.0913404 0.00017 --0.000575795071 -8.19000052e-05 0.000319835613 -0.867509186 -0.123392865 0.481873393 0.0914604 0.00017 --0.000583088782 -7.56000081e-05 0.000311446609 -0.876347959 -0.113622338 0.468085855 0.0920203 0.00017 --0.000589453964 -6.93000038e-05 0.00030252157 -0.884844899 -0.104028068 0.45412311 0.093006 0.00017 --0.000594909885 -6.30000068e-05 0.000293071585 -0.893034875 -0.0945709646 0.439937472 0.0943858 0.00017 --0.00059945666 -5.67000061e-05 0.000283096626 -0.900947869 -0.0852167532 0.425477475 0.0961877 0.00017 --0.000603074906 -5.04000054e-05 0.000272585603 -0.908609688 -0.0759340748 0.410685211 0.0984385 0.00017 --0.00060387241 -5.04000018e-05 0.000247846037 -0.922367632 -0.0769820437 0.378565371 0.107301 0.00017 --0.000607337104 -3.78000041e-05 0.000249846373 -0.923275113 -0.0574636459 0.379816979 0.104568 0.00017 --0.00060975278 -2.51999991e-05 0.000251241087 -0.923914909 -0.0381837599 0.380687714 0.102843 0.00017 --0.000611179974 -1.26000014e-05 0.000252065074 -0.924295604 -0.0190551504 0.381201357 0.102018 0.00017 --0.000611652096 0 0.00025233769 -0.924421966 0 0.3813712 0.102018 0.00017 --0.000611179974 1.26000014e-05 0.000252065074 -0.924295604 0.0190551504 0.381201357 0.102843 0.00017 --0.00060975278 2.52000009e-05 0.000251241087 -0.923914909 0.0381837636 0.380687714 0.104568 0.00017 --0.000607337104 3.78000004e-05 0.000249846373 -0.923275113 0.0574636385 0.379816979 0.107301 0.00017 --0.00060387241 5.04000018e-05 0.000247846037 -0.922367632 0.0769820437 0.378565371 0.111288 0.00017 --0.000601881125 5.67000061e-05 0.000259296357 -0.914980948 0.0861954689 0.394182891 0.108206 0.00017 --0.000598840881 6.30000068e-05 0.000270141114 -0.907380819 0.0954594091 0.40932554 0.105806 0.00017 --0.000594812038 6.92999965e-05 0.000280415057 -0.899542212 0.104803309 0.424075454 0.103996 0.00017 --0.00058982824 7.56000009e-05 0.000290137687 -0.891438425 0.11425826 0.438500345 0.102742 0.00017 --0.000583900197 8.19000052e-05 0.000299315085 -0.883040011 0.123858467 0.452658176 0.102034 0.00017 --0.000577017025 8.82000022e-05 0.000307941082 -0.874312758 0.133643165 0.466601163 0.10191 0.00017 --0.00056914537 9.45000065e-05 0.000315996382 -0.865215957 0.143659115 0.480378389 0.102444 0.00017 --0.000560224697 0.000100800004 0.00032344606 -0.855699182 0.153964087 0.494038433 0.103784 0.00017 --0.000558233412 9.44999992e-05 0.00033489638 -0.848627687 0.143659115 0.509110212 0.097762 0.00017 --0.000555193168 8.82000095e-05 0.000345741108 -0.841244578 0.13364318 0.523876846 0.0927979 0.00017 --0.000551164383 8.19000052e-05 0.00035601508 -0.833533227 0.123858474 0.538406372 0.0886209 0.00017 --0.000546180585 7.56000009e-05 0.000365737651 -0.825471342 0.114258252 0.552758515 0.0850418 0.00017 --0.000540252484 6.92999965e-05 0.000374915078 -0.817031026 0.104803309 0.566989064 0.0819487 0.00017 --0.000533369312 6.30000068e-05 0.000383541104 -0.808176517 0.0954594091 0.581152439 0.079242 0.00017 --0.000525497657 5.67000025e-05 0.000391596404 -0.798862636 0.0861954615 0.595305681 0.0768575 0.00017 --0.000516576984 5.04000018e-05 0.000399046054 -0.789030731 0.0769820437 0.609511495 0.0747255 0.00017 --0.000520041678 3.78000041e-05 0.000401046389 -0.790568411 0.0574636459 0.609671533 0.07214 0.00017 --0.000522457412 2.51999991e-05 0.000402441103 -0.791642427 0.0381837599 0.609790325 0.0703664 0.00017 --0.000523884548 1.26000014e-05 0.00040326509 -0.792277575 0.0190551504 0.609863162 0.0692587 0.00017 --0.00052435667 0 0.000403537677 -0.79248786 0 0.609887719 0.0687318 0.00017 --0.000523884548 -1.26000014e-05 0.00040326509 -0.792277575 -0.0190551504 0.609863162 0.0687318 0.00017 --0.000522457412 -2.52000009e-05 0.000402441103 -0.791642427 -0.0381837636 0.609790325 0.0692587 0.00017 --0.000520041678 -3.78000004e-05 0.000401046389 -0.790568411 -0.0574636385 0.609671533 0.0703664 0.00017 --0.000516576984 -5.04000018e-05 0.000399046054 -0.789030731 -0.0769820437 0.609511495 0.07214 0.00017 --0.000525497657 -5.67000061e-05 0.000391596404 -0.798862636 -0.0861954689 0.595305681 0.0740233 0.00017 --0.000533369312 -6.30000068e-05 0.000383541104 -0.808176517 -0.0954594091 0.581152439 0.0761295 0.00017 --0.000540252484 -6.92999965e-05 0.000374915078 -0.817031026 -0.104803309 0.566989064 0.0784846 0.00017 --0.000546180585 -7.56000009e-05 0.000365737651 -0.825471342 -0.114258252 0.552758515 0.0811455 0.00017 --0.000551164383 -8.19000052e-05 0.00035601508 -0.833533227 -0.123858474 0.538406372 0.0841789 0.00017 --0.000555193168 -8.82000022e-05 0.000345741108 -0.841244578 -0.133643165 0.523876846 0.0876682 0.00017 --0.000558233412 -9.45000065e-05 0.00033489638 -0.848627687 -0.14365913 0.509110212 0.0917439 0.00017 --0.000560224697 -0.000100800004 0.00032344606 -0.855699182 -0.153964087 0.494038433 0.0965829 0.00017 --0.00056914537 -9.44999992e-05 0.000315996382 -0.865215957 -0.1436591 0.480378389 0.0961127 0.00017 --0.000577017025 -8.82000095e-05 0.000307941082 -0.874312758 -0.13364318 0.466601163 0.0962267 0.00017 --0.000583900197 -8.19000052e-05 0.000299315085 -0.883040011 -0.123858467 0.452658176 0.0968425 0.00017 --0.00058982824 -7.56000009e-05 0.000290137687 -0.891438425 -0.11425826 0.438500345 0.097936 0.00017 --0.000594812038 -6.92999965e-05 0.000280415057 -0.899542212 -0.104803309 0.424075454 0.0994883 0.00017 --0.000598840881 -6.30000068e-05 0.000270141114 -0.907380819 -0.0954594091 0.40932554 0.10153 0.00017 --0.000601881125 -5.67000025e-05 0.000259296357 -0.914980948 -0.0861954615 0.394182891 0.104101 0.00017 --0.000600459462 -5.67000025e-05 0.000233275598 -0.92853874 -0.0876797661 0.360732794 0.115173 0.00017 --0.000604719098 -4.41000047e-05 0.000235734886 -0.929566324 -0.0677899569 0.362368613 0.111254 0.00017 --0.000607812137 -3.1500007e-05 0.000237520653 -0.93032527 -0.0482143238 0.363552243 0.108685 0.00017 --0.000609829498 -1.89000002e-05 0.000238685374 -0.930825889 -0.0288484059 0.364322364 0.107223 0.00017 --0.000610825431 -6.3000025e-06 0.000239260422 -0.931074679 -0.00960302632 0.364702106 0.106743 0.00017 --0.000610825431 6.29999886e-06 0.000239260422 -0.931074679 0.00960302074 0.364702106 0.107223 0.00017 --0.000609829498 1.89000002e-05 0.000238685374 -0.930825889 0.0288484059 0.364322364 0.108685 0.00017 --0.000607812137 3.14999997e-05 0.000237520653 -0.93032527 0.0482143126 0.363552243 0.111254 0.00017 --0.000604719098 4.41000011e-05 0.000235734886 -0.929566324 0.0677899495 0.362368613 0.115173 0.00017 --0.000600459462 5.67000025e-05 0.000233275598 -0.92853874 0.0876797661 0.360732794 0.120833 0.00017 --0.00059926312 6.30000068e-05 0.00024518487 -0.921179533 0.0968427956 0.37689504 0.116929 0.00017 --0.00059690018 6.93000038e-05 0.000256420637 -0.913623393 0.106071517 0.39248082 0.113923 0.00017 --0.00059346162 7.56000009e-05 0.000267035386 -0.905842483 0.115393639 0.407595009 0.111692 0.00017 --0.000589001575 8.19000052e-05 0.000277060404 -0.89780885 0.124839313 0.422320247 0.110165 0.00017 --0.000583545596 8.82000095e-05 0.000286510418 -0.889492393 0.134442344 0.436724812 0.109297 0.00017 --0.000577093742 9.44999992e-05 0.000295385369 -0.880859077 0.144242048 0.450867623 0.109141 0.00017 --0.000569620403 0.000100800004 0.000303670618 -0.87186861 0.154285833 0.464802325 0.109753 0.00017 --0.000561071385 0.000107100008 0.000311334879 -0.8624717 0.164632753 0.478579998 0.111314 0.00017 --0.000551355828 0.000113400005 0.00031832559 -0.85260576 0.175359532 0.492252439 0.114095 0.00017 --0.000550159428 0.000107100001 0.000330234878 -0.845697999 0.164632738 0.507632792 0.106176 0.00017 --0.000547796488 0.000100800004 0.000341470644 -0.838464677 0.154285833 0.52265954 0.0998705 0.00017 --0.000544357928 9.44999992e-05 0.000352085364 -0.830892026 0.144242048 0.537412822 0.0947032 0.00017 --0.000539897941 8.82000022e-05 0.000362110382 -0.822960675 0.134442315 0.551961005 0.0903717 0.00017 --0.000534441962 8.19000052e-05 0.000371560425 -0.814644158 0.124839298 0.56636554 0.0866985 0.00017 --0.000527990051 7.56000009e-05 0.000380435376 -0.80590862 0.115393639 0.580685437 0.0835216 0.00017 --0.000520516711 6.92999965e-05 0.000388720655 -0.796709776 0.106071495 0.594980955 0.0807891 0.00017 --0.000511967693 6.29999995e-05 0.000396384887 -0.786990166 0.0968427882 0.60931772 0.078378 0.00017 --0.000502252136 5.67000025e-05 0.000403375598 -0.776672781 0.0876797661 0.623772085 0.0762658 0.00017 --0.000506511715 4.41000047e-05 0.000405834871 -0.778603315 0.0677899569 0.623844147 0.0728366 0.00017 --0.000509604753 3.1500007e-05 0.000407620624 -0.780007899 0.0482143275 0.623909593 0.0704606 0.00017 --0.000511622173 1.89000002e-05 0.000408785359 -0.780925095 0.0288484097 0.623958051 0.0688953 0.00017 --0.000512618106 6.3000025e-06 0.000409360393 -0.781378329 0.00960302725 0.623983741 0.0680017 0.00017 --0.000512618106 -6.29999886e-06 0.000409360393 -0.781378329 -0.00960302167 0.623983741 0.0677125 0.00017 --0.000511622173 -1.89000002e-05 0.000408785359 -0.780925095 -0.0288484097 0.623958051 0.0680017 0.00017 --0.000509604753 -3.14999997e-05 0.000407620624 -0.780007899 -0.0482143164 0.623909593 0.0688953 0.00017 --0.000506511715 -4.41000011e-05 0.000405834871 -0.778603315 -0.0677899495 0.623844147 0.0704606 0.00017 --0.000502252136 -5.67000025e-05 0.000403375598 -0.776672781 -0.0876797661 0.623772085 0.0728366 0.00017 --0.000511967693 -6.30000068e-05 0.000396384887 -0.786990166 -0.0968427956 0.60931772 0.0747255 0.00017 --0.000520516711 -6.93000038e-05 0.000388720655 -0.796709776 -0.106071509 0.594980955 0.0768575 0.00017 --0.000527990051 -7.56000009e-05 0.000380435376 -0.80590862 -0.115393639 0.580685437 0.079242 0.00017 --0.000534441962 -8.19000052e-05 0.000371560425 -0.814644158 -0.124839298 0.56636554 0.0819487 0.00017 --0.000539897941 -8.82000095e-05 0.000362110382 -0.822960675 -0.134442329 0.551961005 0.0850486 0.00017 --0.000544357928 -9.44999992e-05 0.000352085364 -0.830892026 -0.144242048 0.537412822 0.0886209 0.00017 --0.000547796488 -0.000100800004 0.000341470644 -0.838464677 -0.154285833 0.52265954 0.0927979 0.00017 --0.000550159428 -0.000107100008 0.000330234878 -0.845697999 -0.164632753 0.507632792 0.097759 0.00017 --0.000551355828 -0.000113400005 0.00031832559 -0.85260576 -0.175359532 0.492252439 0.103784 0.00017 --0.000561071385 -0.000107100001 0.000311334879 -0.8624717 -0.164632738 0.478579998 0.102444 0.00017 --0.000569620403 -0.000100800004 0.000303670618 -0.87186861 -0.154285833 0.464802325 0.101907 0.00017 --0.000577093742 -9.44999992e-05 0.000295385369 -0.880859077 -0.144242048 0.450867623 0.102034 0.00017 --0.000583545596 -8.82000022e-05 0.000286510418 -0.889492393 -0.134442329 0.436724812 0.102742 0.00017 --0.000589001575 -8.19000052e-05 0.000277060404 -0.89780885 -0.124839313 0.422320247 0.103996 0.00017 --0.00059346162 -7.56000009e-05 0.000267035386 -0.905842483 -0.115393639 0.407595009 0.105806 0.00017 --0.00059690018 -6.92999965e-05 0.000256420637 -0.913623393 -0.106071502 0.39248082 0.108206 0.00017 --0.00059926312 -6.29999995e-05 0.00024518487 -0.921179533 -0.0968427882 0.37689504 0.111288 0.00017 --0.000595065823 -6.30000068e-05 0.000217561537 -0.934588134 -0.0989454538 0.341694027 0.125893 0.00017 --0.000600346131 -5.03999981e-05 0.000220610134 -0.935731232 -0.0785561055 0.343854636 0.120073 0.00017 --0.000604274799 -3.78000004e-05 0.000222878356 -0.936605036 -0.0585886948 0.345453769 0.116178 0.00017 --0.000606995658 -2.52000027e-05 0.000224449279 -0.937221646 -0.0389096476 0.3465572 0.113778 0.00017 --0.00060859666 -1.25999977e-05 0.000225373587 -0.937588394 -0.0194112342 0.347204775 0.112631 0.00017 --0.000609125243 0 0.00022567877 -0.937710285 0 0.347418368 0.112631 0.00017 --0.00060859666 1.26000014e-05 0.000225373587 -0.937588394 0.0194112398 0.347204775 0.113778 0.00017 --0.000606995658 2.52000027e-05 0.000224449279 -0.937221646 0.0389096476 0.3465572 0.116178 0.00017 --0.000604274799 3.78000004e-05 0.000222878356 -0.936605036 0.0585886948 0.345453769 0.120073 0.00017 --0.000600346131 5.04000018e-05 0.000220610134 -0.935731232 0.0785561129 0.343854636 0.125891 0.00017 --0.000595065823 6.30000068e-05 0.000217561537 -0.934588134 0.0989454538 0.341694027 0.134451 0.00017 --0.000594890153 6.92999965e-05 0.000230060148 -0.927227259 0.108014643 0.358583897 0.128972 0.00017 --0.000593362842 7.56000009e-05 0.000241778354 -0.919691861 0.11717739 0.374748081 0.124901 0.00017 --0.00059062778 8.19000052e-05 0.000252799276 -0.911949039 0.12645635 0.390330553 0.121936 0.00017 --0.000586772745 8.82000095e-05 0.000263173599 -0.903967142 0.135878682 0.405438513 0.119912 0.00017 --0.00058184535 9.45000065e-05 0.000272928766 -0.895714641 0.145476863 0.420156777 0.118765 0.00017 --0.000575860846 0.000100800004 0.000282073597 -0.887156487 0.155289918 0.434555382 0.118503 0.00017 --0.000568803924 0.000107100008 0.000290599273 -0.878252149 0.165365964 0.448694915 0.119202 0.00017 --0.000560627086 0.000113400005 0.00029847835 -0.868952632 0.175766096 0.462631166 0.121062 0.00017 --0.00055124244 0.000119700002 0.000305660156 -0.85919565 0.186570764 0.476418078 0.124427 0.00017 --0.000540506153 0.000126000014 0.000312061544 -0.848898828 0.197890922 0.490112215 0.129962 0.00017 --0.000540330482 0.000119700002 0.000324560126 -0.842187762 0.186570778 0.505876601 0.118629 0.00017 --0.000538803171 0.000113400012 0.000336278375 -0.8351264 0.17576611 0.521219909 0.110065 0.00017 --0.00053606811 0.000107100008 0.000347299268 -0.827707112 0.165365994 0.53624171 0.103316 0.00017 --0.000532213191 0.000100800004 0.000357673562 -0.819913983 0.155289903 0.551022708 0.0978446 0.00017 --0.000527285796 9.45000065e-05 0.000367428758 -0.81172353 0.145476863 0.565633655 0.0933065 0.00017 --0.000521301234 8.82000095e-05 0.000376573589 -0.803103387 0.135878682 0.580139637 0.089499 0.00017 --0.000514244311 8.19000052e-05 0.000385099236 -0.794010401 0.12645635 0.594606102 0.0862747 0.00017 --0.000506067416 7.56000009e-05 0.000392978371 -0.784387052 0.117177397 0.609102905 0.0835251 0.00017 --0.000496682769 6.93000038e-05 0.000400160119 -0.774156153 0.108014666 0.623710811 0.0811988 0.00017 --0.000485946541 6.30000068e-05 0.000406561507 -0.763209522 0.0989454612 0.638530374 0.0792893 0.00017 --0.000491226849 5.03999981e-05 0.000409610104 -0.765652239 0.0785561129 0.638440073 0.0744431 0.00017 --0.000495155517 3.78000004e-05 0.000411878369 -0.767473936 0.0585886948 0.638397217 0.0711493 0.00017 --0.000497876375 2.52000027e-05 0.000413449248 -0.768737793 0.0389096476 0.638379455 0.0689372 0.00017 --0.000499477377 1.25999977e-05 0.000414373586 -0.769482076 0.0194112342 0.638373375 0.0675761 0.00017 --0.000500005903 0 0.000414678769 -0.769727945 0 0.638372123 0.0669153 0.00017 --0.000499477377 -1.26000014e-05 0.000414373586 -0.769482076 -0.0194112416 0.638373375 0.0669153 0.00017 --0.000497876375 -2.52000027e-05 0.000413449248 -0.768737793 -0.0389096476 0.638379455 0.0675761 0.00017 --0.000495155517 -3.78000004e-05 0.000411878369 -0.767473936 -0.0585886948 0.638397217 0.0689372 0.00017 --0.000491226849 -5.04000018e-05 0.000409610104 -0.765652239 -0.0785561204 0.638440073 0.0711493 0.00017 --0.000485946541 -6.30000068e-05 0.000406561507 -0.763209522 -0.0989454612 0.638530374 0.0744431 0.00017 --0.000496682769 -6.92999965e-05 0.000400160119 -0.774156153 -0.108014658 0.623710811 0.0762658 0.00017 --0.000506067416 -7.56000009e-05 0.000392978371 -0.784387052 -0.117177397 0.609102905 0.078378 0.00017 --0.000514244311 -8.19000052e-05 0.000385099236 -0.794010401 -0.12645635 0.594606102 0.0807891 0.00017 --0.000521301234 -8.82000095e-05 0.000376573589 -0.803103387 -0.135878682 0.580139637 0.0835216 0.00017 --0.000527285796 -9.45000065e-05 0.000367428758 -0.81172353 -0.145476863 0.565633655 0.0866985 0.00017 --0.000532213191 -0.000100800004 0.000357673562 -0.819913983 -0.155289903 0.551022708 0.0903749 0.00017 --0.00053606811 -0.000107100008 0.000347299268 -0.827707112 -0.165365994 0.53624171 0.0947032 0.00017 --0.000538803171 -0.000113400005 0.000336278375 -0.8351264 -0.175766096 0.521219909 0.0998705 0.00017 --0.000540330482 -0.000119700002 0.000324560126 -0.842187762 -0.186570778 0.505876601 0.106176 0.00017 --0.000540506153 -0.000126000014 0.000312061544 -0.848898828 -0.197890922 0.490112215 0.114095 0.00017 --0.00055124244 -0.000119700002 0.000305660156 -0.85919565 -0.186570764 0.476418078 0.111314 0.00017 --0.000560627086 -0.000113400012 0.00029847835 -0.868952632 -0.17576611 0.462631166 0.109753 0.00017 --0.000568803924 -0.000107100008 0.000290599273 -0.878252149 -0.165365964 0.448694915 0.109141 0.00017 --0.000575860846 -0.000100800004 0.000282073597 -0.887156487 -0.155289918 0.434555382 0.109297 0.00017 --0.00058184535 -9.45000065e-05 0.000272928766 -0.895714641 -0.145476863 0.420156777 0.110165 0.00017 --0.000586772745 -8.82000095e-05 0.000263173599 -0.903967142 -0.135878682 0.405438513 0.111692 0.00017 --0.00059062778 -8.19000052e-05 0.000252799276 -0.911949039 -0.12645635 0.390330553 0.113923 0.00017 --0.000593362842 -7.56000009e-05 0.000241778354 -0.919691861 -0.11717739 0.374748081 0.116929 0.00017 --0.000594890153 -6.93000038e-05 0.000230060148 -0.927227259 -0.108014658 0.358583897 0.120833 0.00017 --0.000586938288 -6.93000038e-05 0.000200269176 -0.940569043 -0.11105331 0.320931494 0.141868 0.00017 --0.00059365714 -5.67000025e-05 0.000204148266 -0.941814482 -0.0899523944 0.32387346 0.132504 0.00017 --0.000598697807 -4.40999975e-05 0.000207058474 -0.942793727 -0.0694460496 0.326063365 0.126342 0.00017 --0.000602312619 -3.14999997e-05 0.000209145524 -0.94351846 -0.0493445247 0.327625006 0.122418 0.00017 --0.000604652101 -1.89000002e-05 0.000210496204 -0.943997145 -0.0295071285 0.328631639 0.120224 0.00017 --0.00060580211 -6.29999522e-06 0.000211160135 -0.944235206 -0.00981950574 0.329125345 0.119514 0.00017 --0.00060580211 6.3000025e-06 0.000211160135 -0.944235206 0.00981951784 0.329125345 0.120224 0.00017 --0.000604652101 1.89000039e-05 0.000210496204 -0.943997145 0.0295071341 0.328631639 0.122418 0.00017 --0.000602312619 3.1500007e-05 0.000209145524 -0.94351846 0.0493445359 0.327625006 0.126342 0.00017 --0.000598697807 4.41000047e-05 0.000207058474 -0.942793727 0.0694460645 0.326063365 0.132504 0.00017 --0.00059365714 5.67000061e-05 0.000204148266 -0.941814482 0.0899524018 0.32387346 0.141868 0.00017 --0.000586938288 6.93000038e-05 0.000200269176 -0.940569043 0.11105331 0.320931494 0.156394 0.00017 --0.000588201219 7.56000009e-05 0.00021359828 -0.933158815 0.119936526 0.338865548 0.147317 0.00017 --0.000587785849 8.19000052e-05 0.000225958473 -0.925610244 0.128971264 0.35582599 0.140972 0.00017 --0.000585944741 8.82000095e-05 0.000237495522 -0.917878211 0.138164684 0.372035027 0.136513 0.00017 --0.000582828186 9.45000065e-05 0.000248296186 -0.909925222 0.147535667 0.38764593 0.133531 0.00017 --0.000578522217 0.000100800004 0.000258410146 -0.901715457 0.157112241 0.402771741 0.131816 0.00017 --0.000573066238 0.000107100001 0.00026786013 -0.893211484 0.166931748 0.417501003 0.131314 0.00017 --0.00056646025 0.000113400012 0.000276646198 -0.884371281 0.177042797 0.431906641 0.132096 0.00017 --0.000558664964 0.000119700002 0.000284745533 -0.87514466 0.187509194 0.446051836 0.134393 0.00017 --0.000549594115 0.000126000014 0.000292108452 -0.865468204 0.198417321 0.459995031 0.138678 0.00017 --0.000539097528 0.000132300018 0.000298648287 -0.85525775 0.20988895 0.473794162 0.145887 0.00017 --0.000526922755 0.000138600008 0.000304219167 -0.844394028 0.222106621 0.487511426 0.0821597 0.00017 --0.00052818557 0.000132300018 0.000317548256 -0.837946355 0.20988895 0.503778279 0.138999 0.00017 --0.000527770258 0.000126000014 0.000329908478 -0.831101239 0.198417321 0.519520283 0.125937 0.00017 --0.000525929034 0.000119700009 0.000341445499 -0.823864162 0.187509224 0.534871936 0.1163 0.00017 --0.000522812654 0.000113400012 0.000352246192 -0.816227496 0.177042797 0.549935102 0.108863 0.00017 --0.000518506684 0.000107100015 0.000362360151 -0.808171928 0.166931748 0.564793706 0.102936 0.00017 --0.000513050705 0.000100800011 0.000371810136 -0.799667954 0.157112241 0.579522967 0.0981332 0.00017 --0.000506444718 9.45000065e-05 0.000380596175 -0.790673494 0.147535652 0.594195783 0.0942175 0.00017 --0.000498649315 8.82000095e-05 0.000388695538 -0.781130612 0.138164684 0.608888745 0.0910144 0.00017 --0.000489578524 8.19000124e-05 0.000396058458 -0.770959139 0.128971279 0.623689353 0.0884579 0.00017 --0.000479081908 7.56000081e-05 0.000402598293 -0.76004529 0.119936548 0.638706923 0.0865486 0.00017 --0.000466907135 6.93000038e-05 0.000408169173 -0.748218954 0.111053303 0.654091358 0.085421 0.00017 --0.000473625958 5.67000025e-05 0.000412048277 -0.751389623 0.0899524018 0.653698921 0.0778015 0.00017 --0.000478666596 4.40999975e-05 0.000414958457 -0.753775716 0.0694460496 0.65345192 0.0728762 0.00017 --0.000482281437 3.14999997e-05 0.000417045521 -0.755490422 0.049344521 0.653298855 0.0696368 0.00017 --0.000484620861 1.89000002e-05 0.000418396201 -0.756601632 0.0295071304 0.653210104 0.067559 0.00017 --0.00048577087 6.29999522e-06 0.000419060118 -0.757148266 0.00981950667 0.653169334 0.0664002 0.00017 --0.00048577087 -6.3000025e-06 0.000419060118 -0.757148266 -0.00981951784 0.653169334 0.0660342 0.00017 --0.000484620861 -1.89000039e-05 0.000418396201 -0.756601632 -0.029507136 0.653210104 0.0664002 0.00017 --0.000482281437 -3.1500007e-05 0.000417045521 -0.755490422 -0.0493445322 0.653298855 0.067559 0.00017 --0.000478666596 -4.41000047e-05 0.000414958457 -0.753775716 -0.0694460645 0.65345192 0.0696368 0.00017 --0.000473625958 -5.67000061e-05 0.000412048277 -0.751389623 -0.0899524093 0.653698921 0.0728762 0.00017 --0.000466907135 -6.93000038e-05 0.000408169173 -0.748218954 -0.111053303 0.654091358 0.0778015 0.00017 --0.000479081908 -7.56000009e-05 0.000402598293 -0.76004529 -0.119936533 0.638706923 0.0792893 0.00017 --0.000489578524 -8.19000052e-05 0.000396058458 -0.770959139 -0.128971264 0.623689353 0.0811988 0.00017 --0.000498649315 -8.82000095e-05 0.000388695538 -0.781130612 -0.138164684 0.608888745 0.0835251 0.00017 --0.000506444718 -9.45000065e-05 0.000380596175 -0.790673494 -0.147535652 0.594195783 0.0862747 0.00017 --0.000513050705 -0.000100800004 0.000371810136 -0.799667954 -0.157112226 0.579522967 0.089499 0.00017 --0.000518506684 -0.000107100001 0.000362360151 -0.808171928 -0.166931733 0.564793706 0.0933065 0.00017 --0.000522812654 -0.000113400012 0.000352246192 -0.816227496 -0.177042797 0.549935102 0.0978446 0.00017 --0.000525929092 -0.000119700002 0.000341445528 -0.823864281 -0.187509209 0.534871995 0.103319 0.00017 --0.000527770258 -0.000126000014 0.000329908478 -0.831101239 -0.198417321 0.519520283 0.110065 0.00017 --0.00052818557 -0.000132300018 0.000317548256 -0.837946355 -0.20988895 0.503778279 0.118629 0.00017 --0.000526922755 -0.000138600008 0.000304219167 -0.844394028 -0.222106621 0.487511426 0.129962 0.00017 --0.000539097528 -0.000132300018 0.000298648287 -0.85525775 -0.20988895 0.473794162 0.124427 0.00017 --0.000549594115 -0.000126000014 0.000292108452 -0.865468204 -0.198417321 0.459995031 0.121062 0.00017 --0.000558664906 -0.000119700009 0.000284745503 -0.875144601 -0.187509224 0.446051806 0.119202 0.00017 --0.00056646025 -0.000113400012 0.000276646198 -0.884371281 -0.177042797 0.431906641 0.118503 0.00017 --0.000573066238 -0.000107100015 0.00026786013 -0.893211484 -0.166931763 0.417501003 0.118765 0.00017 --0.000578522217 -0.000100800011 0.000258410146 -0.901715398 -0.157112241 0.402771711 0.119909 0.00017 --0.000582828186 -9.45000065e-05 0.000248296186 -0.909925222 -0.147535667 0.38764593 0.121936 0.00017 --0.000585944741 -8.82000095e-05 0.000237495522 -0.917878211 -0.138164684 0.372035027 0.124901 0.00017 --0.000587785849 -8.19000124e-05 0.000225958473 -0.925610244 -0.128971279 0.35582599 0.128969 0.00017 --0.000588201219 -7.56000081e-05 0.00021359828 -0.933158815 -0.119936541 0.338865548 0.134455 0.00017 --0.000583555724 -6.30000141e-05 0.000185716257 -0.947904348 -0.102334678 0.301669985 0.152268 0.00017 --0.00059027283 -5.04000054e-05 0.000189594342 -0.948961973 -0.0810264125 0.304804504 0.141399 0.00017 --0.000595143356 -3.78000004e-05 0.000192406369 -0.949777186 -0.0603242554 0.30705741 0.13459 0.00017 --0.000598463463 -2.52000027e-05 0.00019432322 -0.950355113 -0.0400173999 0.308583707 0.130544 0.00017 --0.000600398751 -1.2600005e-05 0.000195440574 -0.950699985 -0.0199514478 0.309469908 0.128658 0.00017 --0.000601035019 0 0.000195807908 -0.950814545 0 0.30976066 0.128658 0.00017 --0.000600398751 1.25999977e-05 0.000195440574 -0.950699985 0.0199514367 0.309469908 0.130547 0.00017 --0.000598463463 2.51999991e-05 0.00019432322 -0.950355113 0.0400173925 0.308583707 0.13459 0.00017 --0.000595143356 3.78000004e-05 0.000192406369 -0.949777186 0.0603242554 0.30705741 0.141399 0.00017 --0.00059027283 5.03999981e-05 0.000189594342 -0.948961973 0.0810264051 0.304804504 0.152268 0.00017 --0.000583555724 6.30000068e-05 0.000185716257 -0.947904348 0.102334663 0.301669985 0.152268 0.00017 --0.000578099862 8.19000052e-05 0.000195166271 -0.939042032 0.133035049 0.317020178 0.156394 0.00017 --0.000579360931 8.82000095e-05 0.000208494326 -0.931419313 0.141796216 0.335189402 0.168001 0.00017 --0.000578775478 9.44999992e-05 0.000220756367 -0.923656046 0.150810644 0.352300614 0.1598 0.00017 --0.000576639606 0.000100800004 0.000232123202 -0.915699005 0.160069585 0.368609756 0.154536 0.00017 --0.000573118974 0.000107100008 0.000242690556 -0.907503784 0.16958724 0.384287775 0.15148 0.00017 --0.000568299263 0.000113400005 0.000252507918 -0.899027765 0.179394484 0.399457902 0.150351 0.00017 --0.000562207075 0.000119700002 0.000261590583 -0.890225291 0.189538658 0.414214909 0.151155 0.00017 --0.00055481575 0.000126000014 0.000269923214 -0.881042898 0.200086996 0.428635895 0.15417 0.00017 --0.000546039781 0.000132299989 0.000277456391 -0.871413648 0.211134836 0.442786932 0.160125 0.00017 --0.000535713218 0.000138600008 0.000284094305 -0.861248374 0.222822636 0.456728995 0.0988948 0.00017 --0.000523540191 0.000144900012 0.000289666263 -0.850417495 0.235369742 0.470522165 0.0893505 0.00017 --0.000512628292 0.000144899997 0.000308566261 -0.832692623 0.235369697 0.501222551 0.0976556 0.00017 --0.000513889361 0.000138599993 0.000321894331 -0.826162815 0.222822607 0.517498851 0.0717591 0.00017 --0.000513303967 0.000132299989 0.000334156386 -0.819171309 0.211134866 0.533273339 0.138266 0.00017 --0.000511168095 0.000126000014 0.000345523207 -0.811730683 0.200086981 0.548687994 0.126725 0.00017 --0.000507647463 0.000119700002 0.000356090604 -0.803833067 0.189538658 0.563850701 0.118142 0.00017 --0.000502827752 0.000113400005 0.000365907908 -0.795454323 0.179394484 0.578852355 0.111573 0.00017 --0.000496735564 0.000107100001 0.000374990603 -0.786554575 0.16958721 0.593777895 0.106483 0.00017 --0.00048934418 0.000100799996 0.000383323204 -0.777074575 0.16006957 0.608714104 0.102593 0.00017 --0.000480568124 9.44999992e-05 0.000390856352 -0.766928911 0.150810644 0.623759687 0.0998011 0.00017 --0.000470241648 8.82000022e-05 0.000397494325 -0.755991876 0.141796201 0.639038444 0.0981802 0.00017 --0.000458068651 8.18999979e-05 0.000403066253 -0.744068205 0.133035034 0.654724538 0.0734442 0.00017 --0.000452612643 6.30000141e-05 0.000412516238 -0.73520571 0.102334678 0.670074701 0.0810779 0.00017 --0.00045932972 5.04000054e-05 0.000416394323 -0.738449097 0.0810264125 0.669423282 0.0768838 0.00017 --0.000464200246 3.78000004e-05 0.000419206335 -0.740807772 0.0603242554 0.669002891 0.0716182 0.00017 --0.000467520353 2.52000027e-05 0.000421123201 -0.742418528 0.0400173999 0.668740213 0.068315 0.00017 --0.000469455641 1.2600005e-05 0.000422240555 -0.743358374 0.019951446 0.668595731 0.066348 0.00017 --0.000470091938 0 0.000422607874 -0.743667543 0 0.668549597 0.0654152 0.00017 --0.000469455641 -1.25999977e-05 0.000422240555 -0.743358374 -0.0199514348 0.668595731 0.0654152 0.00017 --0.000467520353 -2.51999991e-05 0.000421123201 -0.742418528 -0.0400173925 0.668740213 0.066348 0.00017 --0.000464200246 -3.78000004e-05 0.000419206335 -0.740807772 -0.0603242554 0.669002891 0.068315 0.00017 --0.00045932972 -5.03999981e-05 0.000416394323 -0.738449097 -0.0810264051 0.669423282 0.0716182 0.00017 --0.000452612643 -6.30000068e-05 0.000412516238 -0.73520571 -0.102334663 0.670074701 0.0768838 0.00017 --0.000458068651 -8.19000052e-05 0.000403066253 -0.744068205 -0.133035049 0.654724538 0.085421 0.00017 --0.000470241648 -8.82000095e-05 0.000397494325 -0.755991876 -0.141796216 0.639038444 0.0865419 0.00017 --0.000480568124 -9.44999992e-05 0.000390856352 -0.766928911 -0.150810644 0.623759687 0.0884579 0.00017 --0.00048934418 -0.000100800004 0.000383323204 -0.777074575 -0.16006957 0.608714104 0.0910144 0.00017 --0.000496735505 -0.000107100008 0.000374990545 -0.786554575 -0.16958724 0.593777835 0.0942175 0.00017 --0.000502827752 -0.000113400005 0.000365907908 -0.795454323 -0.179394484 0.578852355 0.0981332 0.00017 --0.000507647463 -0.000119700002 0.000356090604 -0.803833067 -0.189538658 0.563850701 0.102936 0.00017 --0.000511168095 -0.000126000014 0.000345523207 -0.811730683 -0.200086981 0.548687994 0.108863 0.00017 --0.000513303967 -0.000132299989 0.000334156386 -0.819171309 -0.211134866 0.533273339 0.116302 0.00017 --0.000513889361 -0.000138600008 0.000321894331 -0.826162815 -0.222822636 0.517498851 0.125935 0.00017 --0.000512628234 -0.000144900012 0.000308566232 -0.832692623 -0.235369742 0.501222551 0.138999 0.00017 --0.000508970174 -0.000151200002 0.000293854246 -0.838713467 -0.249156997 0.48423174 0.158004 0.00017 --0.00052354025 -0.000144899997 0.000289666292 -0.850417554 -0.235369697 0.470522195 0.145883 0.00017 --0.000535713218 -0.000138599993 0.000284094305 -0.861248374 -0.222822607 0.456728995 0.138678 0.00017 --0.000546039781 -0.000132299989 0.000277456391 -0.871413648 -0.211134836 0.442786932 0.134391 0.00017 --0.00055481575 -0.000126000014 0.000269923214 -0.881042898 -0.200086996 0.428635895 0.132096 0.00017 --0.000562207075 -0.000119700002 0.000261590583 -0.890225291 -0.189538658 0.414214909 0.131314 0.00017 --0.000568299263 -0.000113400005 0.000252507918 -0.899027765 -0.179394484 0.399457902 0.131816 0.00017 --0.000573119032 -0.000107100001 0.000242690585 -0.907503784 -0.16958721 0.384287775 0.133531 0.00017 --0.000576639606 -0.000100799996 0.000232123202 -0.915699005 -0.16006957 0.368609756 0.136513 0.00017 --0.000578775478 -9.44999992e-05 0.000220756367 -0.923656046 -0.150810644 0.352300614 0.140972 0.00017 --0.000579360931 -8.82000022e-05 0.000208494326 -0.931419313 -0.141796201 0.335189402 0.147319 0.00017 --0.000578099862 -8.18999979e-05 0.000195166271 -0.939042032 -0.133035034 0.317020178 0.156394 0.00017 --0.000584184425 -4.41000047e-05 0.000173479217 -0.956124306 -0.0721776932 0.283930361 0.15411 0.00017 --0.000589011761 -3.14999997e-05 0.000176266272 -0.956766844 -0.0511673242 0.286319792 0.146002 0.00017 --0.000592067197 -1.89000002e-05 0.000178030328 -0.957196295 -0.0305556711 0.287822008 0.141703 0.00017 --0.000593551726 -6.3000025e-06 0.000178887421 -0.95741117 -0.0101620341 0.288549095 0.140354 0.00017 --0.000593551726 6.3000025e-06 0.000178887421 -0.95741117 0.0101620341 0.288549095 0.141703 0.00017 --0.000592067197 1.89000002e-05 0.000178030328 -0.957196295 0.0305556711 0.287822008 0.146002 0.00017 --0.000589011761 3.15000034e-05 0.000176266272 -0.956766844 0.0511673279 0.286319792 0.15411 0.00017 --0.000584184425 4.41000047e-05 0.000173479217 -0.956124306 0.0721776932 0.283930361 0.15411 0.00017 --0.000567816605 0.000100800004 0.000201829214 -0.929335356 0.16497758 0.330330312 0.168001 0.00017 --0.000567187904 0.000107100001 0.000214066284 -0.921317101 0.173968911 0.347720593 0.0360068 0.00017 --0.00056478742 0.000113400005 0.000225280324 -0.91309303 0.183334023 0.364211172 0.0456583 0.00017 --0.00056081597 0.000119700002 0.000235587417 -0.904607654 0.193078578 0.380007356 0.0532483 0.00017 --0.000555359991 0.000126000014 0.00024503743 -0.895807147 0.203240618 0.39525044 0.0599371 0.00017 --0.000548419484 0.000132300018 0.000253630336 -0.886630952 0.213889703 0.41004467 0.0664784 0.00017 --0.000539908069 0.000138599993 0.00026131628 -0.877004802 0.225136235 0.424471587 0.0735698 0.00017 --0.000529624871 0.000144899997 0.000267979223 -0.866827607 0.237155274 0.438596845 0.0820718 0.00017 --0.000496889057 0.000144899997 0.000324679218 -0.813249528 0.237155274 0.531396747 0.109413 0.00017 --0.000496260356 0.000138600008 0.000336916215 -0.806105256 0.225136265 0.547273099 0.0648437 0.00017 --0.000493859872 0.000132300018 0.000348130328 -0.798424304 0.213889703 0.562823057 0.0608401 0.00017 --0.00048988848 0.000126000014 0.000358437392 -0.790200174 0.203240603 0.578166902 0.059118 0.00017 --0.000484432472 0.000119700002 0.000367887405 -0.781399548 0.193078578 0.593409956 0.0590545 0.00017 --0.000477491994 0.000113400005 0.00037648034 -0.771962345 0.183334023 0.608656526 0.0603879 0.00017 --0.000468980579 0.000107100008 0.000384166255 -0.761793077 0.173968911 0.624024153 0.0631576 0.00017 --0.000458697323 0.000100800004 0.000390829227 -0.75074178 0.16497758 0.639663279 0.0676998 0.00017 --0.000442329416 4.41000047e-05 0.00041917921 -0.72395277 0.0721776932 0.68606323 0.0922396 0.00017 --0.000447156752 3.14999997e-05 0.000421966281 -0.726343334 0.0511673242 0.685424924 0.0707875 0.00017 --0.000450212188 1.89000002e-05 0.000423730322 -0.727858961 0.0305556692 0.68504566 0.0671864 0.00017 --0.000451696716 6.3000025e-06 0.000424587401 -0.728596091 0.0101620341 0.684868217 0.0652739 0.00017 --0.000451696716 -6.3000025e-06 0.000424587401 -0.728596091 -0.0101620341 0.684868217 0.0646789 0.00017 --0.000450212188 -1.89000002e-05 0.000423730322 -0.727858961 -0.0305556692 0.68504566 0.0652739 0.00017 --0.000447156752 -3.15000034e-05 0.000421966281 -0.726343334 -0.0511673279 0.685424924 0.0671864 0.00017 --0.000442329416 -4.41000047e-05 0.00041917921 -0.72395277 -0.0721776932 0.68606323 0.0707875 0.00017 --0.000458697323 -0.000100800004 0.000390829227 -0.75074178 -0.16497758 0.639663279 0.0981802 0.00017 --0.000468980579 -0.000107100001 0.000384166255 -0.761793077 -0.173968911 0.624024153 0.0998011 0.00017 --0.000477491994 -0.000113400005 0.00037648034 -0.771962345 -0.183334023 0.608656526 0.102593 0.00017 --0.000484432472 -0.000119700002 0.000367887405 -0.781399548 -0.193078578 0.593409956 0.106483 0.00017 --0.00048988848 -0.000126000014 0.000358437392 -0.790200174 -0.203240603 0.578166902 0.111573 0.00017 --0.000493859872 -0.000132300018 0.000348130328 -0.798424304 -0.213889703 0.562823057 0.118142 0.00017 --0.000496260414 -0.000138599993 0.000336916244 -0.806105316 -0.225136235 0.547273099 0.126725 0.00017 --0.000496889057 -0.000144899997 0.000324679218 -0.813249528 -0.237155274 0.531396747 0.138266 0.00017 --0.000529624871 -0.000144899997 0.000267979223 -0.866827607 -0.237155274 0.438596845 0.160125 0.00017 --0.000539908011 -0.000138600008 0.000261316251 -0.877004921 -0.225136295 0.424471647 0.154172 0.00017 --0.000548419484 -0.000132300018 0.000253630336 -0.886630952 -0.213889703 0.41004467 0.151155 0.00017 --0.000555359991 -0.000126000014 0.00024503743 -0.895807147 -0.203240618 0.39525044 0.150351 0.00017 --0.00056081597 -0.000119700002 0.000235587417 -0.904607654 -0.193078578 0.380007356 0.15148 0.00017 --0.00056478742 -0.000113400005 0.000225280324 -0.91309303 -0.183334023 0.364211172 0.154533 0.00017 --0.000567187904 -0.000107100008 0.000214066284 -0.921317101 -0.173968911 0.347720593 0.159801 0.00017 --0.000567816605 -0.000100800004 0.000201829214 -0.929335356 -0.16497758 0.330330312 0.168004 0.00017 -0.000588897266 0 0.000340000173 0.866025329 0 0.500000238 0.079482 0.00017 -0.000593948294 -6.30000022e-06 0.000330316368 0.873904049 -0.00926948711 0.486010015 0.0813195 0.00017 -0.000593948294 6.30000022e-06 0.000330316368 0.873904049 0.00926948711 0.486010015 0.081564 0.00017 -0.000588492316 1.26000004e-05 0.000339766382 0.865876496 0.0185389742 0.499914289 0.0799489 0.00017 -0.000583036337 6.30000022e-06 0.000349216367 0.857848823 0.00926948711 0.513818502 0.0779201 0.00017 -0.000583036337 -6.30000022e-06 0.000349216367 0.857848823 -0.00926948711 0.513818502 0.0776939 0.00017 -0.000588492316 -1.26000004e-05 0.000339766382 0.865876496 -0.0185389742 0.499914289 0.079482 0.00017 -0.000598182727 -1.26000004e-05 0.000320161082 0.881508231 -0.0185679123 0.471803427 0.0834594 0.00017 -0.000598590996 0 0.000320396823 0.881649673 0 0.471904457 0.0834594 0.00017 -0.000598182727 1.26000004e-05 0.000320161082 0.881508231 0.0185679123 0.471803427 0.0839627 0.00017 -0.000593135017 1.89000002e-05 0.000329846836 0.873613715 0.0278373361 0.485823154 0.0823001 0.00017 -0.00058727077 2.52000009e-05 0.000339061109 0.865427911 0.0371358246 0.499655306 0.0809104 0.00017 -0.00058222306 1.89000002e-05 0.000348746835 0.857541859 0.0278373398 0.513660491 0.0786095 0.00017 -0.000576358812 1.26000004e-05 0.000357961108 0.849347651 0.0185679123 0.527507186 0.076598 0.00017 -0.000576767139 0 0.000358196849 0.849505901 0 0.527579188 0.0761446 0.00017 -0.000576358812 -1.26000004e-05 0.000357961108 0.849347651 -0.0185679123 0.527507186 0.0761446 0.00017 -0.00058222306 -1.89000002e-05 0.000348746835 0.857541859 -0.0278373398 0.513660491 0.0779201 0.00017 -0.00058727077 -2.52000009e-05 0.000339061109 0.865427911 -0.0371358246 0.499655306 0.0799489 0.00017 -0.000593135017 -1.89000002e-05 0.000329846836 0.873613715 -0.0278373361 0.485823154 0.081564 0.00017 -0.000601579552 -1.89000002e-05 0.000309522293 0.888857722 -0.0279255006 0.457331479 0.0859497 0.00017 -0.000602406741 -6.30000068e-06 0.000309999858 0.889134884 -0.00929861795 0.457550794 0.085684 0.00017 -0.000602406741 6.29999977e-06 0.000309999858 0.889134884 0.00929861609 0.457550794 0.0859497 0.00017 -0.000601579552 1.89000002e-05 0.000309522293 0.888857722 0.0279255006 0.457331479 0.0867417 0.00017 -0.00059695082 2.52000009e-05 0.000319449871 0.881082058 0.0371944718 0.471498728 0.0849875 0.00017 -0.000591494842 3.15000034e-05 0.000328899885 0.873029172 0.046493087 0.485446662 0.0835562 0.00017 -0.000585211674 3.78000004e-05 0.000337872276 0.864673555 0.055851005 0.499219745 0.0824087 0.00017 -0.000580582884 3.15000034e-05 0.000347799854 0.856923521 0.0464930907 0.5133425 0.0798044 0.00017 -0.000575126905 2.51999991e-05 0.000357249868 0.848870635 0.0371944681 0.527290463 0.0775191 0.00017 -0.000568843738 1.89000002e-05 0.000366222288 0.840489268 0.0279255025 0.541108012 0.0755244 0.00017 -0.000569670927 6.30000068e-06 0.000366699853 0.840817809 0.00929861888 0.541238368 0.074822 0.00017 -0.000569670927 -6.29999977e-06 0.000366699853 0.840817809 -0.00929861702 0.541238368 0.0746096 0.00017 -0.000568843738 -1.89000002e-05 0.000366222288 0.840489268 -0.0279255025 0.541108012 0.074822 0.00017 -0.000575126905 -2.52000009e-05 0.000357249868 0.848870635 -0.0371944718 0.527290463 0.076598 0.00017 -0.000580582884 -3.15000034e-05 0.000347799854 0.856923521 -0.0464930907 0.5133425 0.0786095 0.00017 -0.000585211674 -3.78000004e-05 0.000337872276 0.864673555 -0.055851005 0.499219745 0.0809104 0.00017 -0.000591494842 -3.15000034e-05 0.000328899885 0.873029172 -0.046493087 0.485446662 0.0823001 0.00017 -0.00059695082 -2.51999991e-05 0.000319449871 0.881082058 -0.0371944681 0.471498728 0.0839627 0.00017 -0.000604102155 -2.52000009e-05 0.000298378756 0.895970285 -0.0373752192 0.44253853 0.0888388 0.00017 -0.000605366717 -1.25999995e-05 0.000299108855 0.896378636 -0.0186570715 0.442896456 0.0882751 0.00017 -0.000605785695 0 0.000299350766 0.896514118 0 0.443015039 0.0882751 0.00017 -0.000605366717 1.26000004e-05 0.000299108855 0.896378636 0.0186570734 0.442896456 0.0888388 0.00017 -0.000604102155 2.52000009e-05 0.000298378756 0.895970285 0.0373752192 0.44253853 0.0899973 0.00017 -0.000599910796 3.15000034e-05 0.00030855884 0.888299882 0.0466426797 0.456889182 0.0881213 0.00017 -0.000594873796 3.78000004e-05 0.000318250735 0.880365431 0.0559409633 0.470985502 0.0865986 0.00017 -0.000588998897 4.41000011e-05 0.000327458838 0.872142315 0.0652997419 0.484874815 0.0854108 0.00017 -0.000582278357 5.04000018e-05 0.000336178724 0.8636024 0.0747504383 0.498601347 0.0845415 0.00017 -0.00057808694 4.41000047e-05 0.000346358836 0.855984867 0.0652997568 0.512860417 0.0815675 0.00017 -0.00057304994 3.78000004e-05 0.000356050761 0.84806782 0.0559409633 0.526926458 0.0789831 0.00017 -0.000567174982 3.15000034e-05 0.000365258835 0.839827359 0.0466426834 0.54084605 0.0767034 0.00017 -0.0005604545 2.52000009e-05 0.000373978721 0.831234515 0.0373752192 0.554664135 0.0746869 0.00017 -0.000561719062 1.25999995e-05 0.000374708819 0.831748664 0.0186570715 0.554838836 0.0737421 0.00017 -0.000562138041 0 0.00037495073 0.831919134 0 0.554896951 0.0732868 0.00017 -0.000561719062 -1.26000004e-05 0.000374708819 0.831748664 -0.0186570734 0.554838836 0.0732868 0.00017 -0.0005604545 -2.52000009e-05 0.000373978721 0.831234515 -0.0373752192 0.554664135 0.0737421 0.00017 -0.000567174982 -3.15000034e-05 0.000365258835 0.839827359 -0.0466426834 0.54084605 0.0755244 0.00017 -0.00057304994 -3.78000004e-05 0.000356050761 0.84806782 -0.0559409633 0.526926458 0.0775191 0.00017 -0.00057808694 -4.41000011e-05 0.000346358836 0.855984867 -0.0652997494 0.512860417 0.0798044 0.00017 -0.000582278357 -5.04000018e-05 0.000336178724 0.8636024 -0.0747504383 0.498601347 0.0824087 0.00017 -0.000588998897 -4.41000047e-05 0.000327458838 0.872142315 -0.0652997494 0.484874815 0.0835562 0.00017 -0.000594873796 -3.78000004e-05 0.000318250735 0.880365431 -0.0559409633 0.470985502 0.0849875 0.00017 -0.000599910796 -3.15000034e-05 0.00030855884 0.888299882 -0.0466426797 0.456889182 0.0867417 0.00017 -0.000605694251 -3.15000034e-05 0.000286697934 0.902862072 -0.0469546393 0.427358657 0.0922396 0.00017 -0.000607424881 -1.89000002e-05 0.000287697098 0.903398275 -0.0281092003 0.427880138 0.0913246 0.00017 -0.000608282047 -6.29999886e-06 0.000288191979 0.903664708 -0.00935928803 0.428138435 0.0910208 0.00017 -0.000608282047 6.30000068e-06 0.000288191979 0.903664708 0.00935929082 0.428138435 0.0913246 0.00017 -0.000607424881 1.89000002e-05 0.000287697098 0.903398275 0.0281092003 0.427880138 0.0922396 0.00017 -0.000605694251 3.15000034e-05 0.000286697934 0.902862072 0.0469546393 0.427358657 0.0938308 0.00017 -0.000601968903 3.78000004e-05 0.000297147111 0.895283818 0.0562184006 0.441934764 0.0918037 0.00017 -0.000597370148 4.41000047e-05 0.000307092007 0.887453914 0.0655150265 0.456216276 0.0901703 0.00017 -0.000591914228 5.04000018e-05 0.000316541991 0.879348516 0.0748743117 0.470255196 0.0888972 0.00017 -0.000585601083 5.67000025e-05 0.000325497094 0.870940566 0.0843276009 0.484098554 0.0879869 0.00017 -0.000578414474 6.30000068e-05 0.000333947944 0.862198114 0.0939092785 0.497790605 0.0874474 0.00017 -0.000574689126 5.67000061e-05 0.000344397093 0.854711652 0.0843276009 0.512207747 0.0840211 0.00017 -0.000570090313 5.04000018e-05 0.000354341988 0.846927047 0.0748743191 0.526410997 0.081053 0.00017 -0.000564634334 4.41000047e-05 0.000363792002 0.83882165 0.0655150339 0.540449917 0.0784479 0.00017 -0.000558321248 3.78000004e-05 0.000372747076 0.830368459 0.0562184006 0.554371536 0.076156 0.00017 -0.000551134697 3.15000034e-05 0.000381197955 0.821534157 0.0469546355 0.568222523 0.0741285 0.00017 -0.000552865269 1.89000002e-05 0.000382197089 0.822254002 0.0281092003 0.568426132 0.0728881 0.00017 -0.000553722493 6.29999886e-06 0.000382692 0.822610855 0.0093592871 0.568527758 0.072192 0.00017 -0.000553722493 -6.30000068e-06 0.000382692 0.822610855 -0.00935928989 0.568527758 0.0719719 0.00017 -0.000552865269 -1.89000002e-05 0.000382197089 0.822254002 -0.0281092003 0.568426132 0.072192 0.00017 -0.000551134697 -3.15000034e-05 0.000381197955 0.821534157 -0.0469546355 0.568222523 0.0728881 0.00017 -0.000558321248 -3.78000004e-05 0.000372747076 0.830368459 -0.0562184006 0.554371536 0.0746869 0.00017 -0.000564634334 -4.41000047e-05 0.000363792002 0.83882165 -0.0655150339 0.540449917 0.0767034 0.00017 -0.000570090313 -5.04000018e-05 0.000354341988 0.846927047 -0.0748743191 0.526410997 0.0789831 0.00017 -0.000574689126 -5.67000025e-05 0.000344397093 0.854711652 -0.0843276009 0.512207747 0.0815675 0.00017 -0.000578414474 -6.30000068e-05 0.000333947944 0.862198114 -0.0939092785 0.497790605 0.0845415 0.00017 -0.000585601083 -5.67000061e-05 0.000325497094 0.870940566 -0.0843276009 0.484098554 0.0854108 0.00017 -0.000591914228 -5.04000018e-05 0.000316541991 0.879348516 -0.0748743117 0.470255196 0.0865986 0.00017 -0.000597370148 -4.41000047e-05 0.000307092007 0.887453914 -0.0655150265 0.456216276 0.0881213 0.00017 -0.000601968903 -3.78000004e-05 0.000297147111 0.895283818 -0.0562184006 0.441934764 0.0899973 0.00017 -0.000606274116 -3.78000004e-05 0.000274432707 0.909548283 -0.0567085519 0.411711127 0.0962897 0.00017 -0.00060851255 -2.52000027e-05 0.000275725062 0.910210073 -0.0376940407 0.41242817 0.0949284 0.00017 -0.000609837822 -1.26000014e-05 0.000276490202 0.910603642 -0.0188141949 0.412852347 0.0942756 0.00017 -0.000610276649 0 0.00027674358 0.910734355 0 0.412992805 0.0942756 0.00017 -0.000609837822 1.25999995e-05 0.000276490202 0.910603642 0.0188141912 0.412852347 0.0949284 0.00017 -0.00060851255 2.51999991e-05 0.000275725062 0.910210073 0.0376940332 0.41242817 0.0962897 0.00017 -0.000606274116 3.78000004e-05 0.000274432707 0.909548283 0.0567085519 0.411711127 0.0984385 0.00017 -0.000603056571 4.41000047e-05 0.000285175047 0.902049065 0.0659645647 0.426563412 0.0961877 0.00017 -0.000598925864 5.04000018e-05 0.0002953902 0.894309998 0.0752567723 0.441073656 0.0943858 0.00017 -0.00059390883 5.67000025e-05 0.000305093563 0.886308014 0.0846151188 0.455300331 0.093006 0.00017 -0.000588013965 6.30000068e-05 0.00031429017 0.878016531 0.0940709636 0.469294906 0.0920203 0.00017 -0.000581232773 6.93000038e-05 0.000322975044 0.869404972 0.103658594 0.483104408 0.0914604 0.00017 -0.000573538302 7.56000009e-05 0.000331132702 0.860437214 0.113417104 0.496773928 0.0913404 0.00017 -0.000570320815 6.92999965e-05 0.000341875042 0.853083074 0.103658594 0.51137501 0.0873186 0.00017 -0.000566190109 6.30000068e-05 0.000352090196 0.845429301 0.0940709636 0.525737524 0.0838733 0.00017 -0.000561173016 5.67000025e-05 0.000361793558 0.837455451 0.0846151263 0.539915502 0.0808855 0.00017 -0.00055527821 5.03999981e-05 0.000370990165 0.829135776 0.0752567649 0.553958774 0.0782564 0.00017 -0.000548496959 4.41000011e-05 0.000379675039 0.820438981 0.0659645498 0.567915976 0.0759435 0.00017 -0.000540802546 3.78000004e-05 0.000387832697 0.811326146 0.0567085519 0.58183676 0.0738751 0.00017 -0.000543041038 2.52000027e-05 0.000389125024 0.812278092 0.0376940407 0.582051337 0.0723118 0.00017 -0.000544366252 1.26000014e-05 0.000389890192 0.81284219 0.0188141949 0.582180083 0.0713235 0.00017 -0.000544805138 0 0.00039014357 0.81302917 0 0.582223058 0.0708404 0.00017 -0.000544366252 -1.25999995e-05 0.000389890192 0.81284219 -0.0188141912 0.582180083 0.0708404 0.00017 -0.000543041038 -2.51999991e-05 0.000389125024 0.812278092 -0.0376940332 0.582051337 0.0713235 0.00017 -0.000540802546 -3.78000004e-05 0.000387832697 0.811326146 -0.0567085519 0.58183676 0.0723118 0.00017 -0.000548496959 -4.41000047e-05 0.000379675039 0.820438981 -0.0659645572 0.567915976 0.0741285 0.00017 -0.00055527821 -5.04000018e-05 0.000370990165 0.829135776 -0.0752567723 0.553958774 0.076156 0.00017 -0.000561173016 -5.67000025e-05 0.000361793558 0.837455451 -0.0846151263 0.539915502 0.0784479 0.00017 -0.000566190109 -6.30000068e-05 0.000352090196 0.845429301 -0.0940709636 0.525737524 0.081053 0.00017 -0.000570320815 -6.93000038e-05 0.000341875042 0.853083074 -0.103658609 0.51137501 0.0840211 0.00017 -0.000573538302 -7.56000009e-05 0.000331132702 0.860437214 -0.113417104 0.496773928 0.0874474 0.00017 -0.000581232773 -6.92999965e-05 0.000322975044 0.869404972 -0.103658579 0.483104408 0.0879869 0.00017 -0.000588013965 -6.30000068e-05 0.00031429017 0.878016531 -0.0940709636 0.469294906 0.0888972 0.00017 -0.00059390883 -5.67000025e-05 0.000305093563 0.886308014 -0.0846151188 0.455300331 0.0901703 0.00017 -0.000598925864 -5.03999981e-05 0.0002953902 0.894309998 -0.0752567649 0.441073656 0.0918037 0.00017 -0.000603056571 -4.41000011e-05 0.000285175047 0.902049065 -0.0659645647 0.426563412 0.0938308 0.00017 -0.000605723995 -4.41000047e-05 0.000261515088 0.916044474 -0.0666930228 0.395492762 0.1012 0.00017 -0.000608530827 -3.14999997e-05 0.000263135618 0.916829824 -0.0474587902 0.396447599 0.099256 0.00017 -0.000610368559 -1.89000002e-05 0.000264196657 0.917347848 -0.0284055825 0.397071928 0.0981449 0.00017 -0.000611277763 -6.29999886e-06 0.000264721573 0.917605162 -0.00945709459 0.397380531 0.0977797 0.00017 -0.000611277763 6.3000025e-06 0.000264721573 0.917605162 0.00945710018 0.397380531 0.0981449 0.00017 -0.000610368559 1.8900002e-05 0.000264196657 0.917347848 0.0284055844 0.397071928 0.099256 0.00017 -0.000608530827 3.15000034e-05 0.000263135618 0.916829824 0.047458794 0.396447599 0.1012 0.00017 -0.000605723995 4.41000047e-05 0.000261515088 0.916044474 0.0666930228 0.395492762 0.104101 0.00017 -0.000603074906 5.04000018e-05 0.000272585603 0.908609688 0.0759340748 0.410685211 0.10153 0.00017 -0.00059945666 5.67000025e-05 0.000283096626 0.900947869 0.0852167457 0.425477475 0.0994883 0.00017 -0.000594909885 6.30000068e-05 0.000293071585 0.893034875 0.0945709646 0.439937472 0.097936 0.00017 -0.000589453964 6.92999965e-05 0.00030252157 0.884844899 0.104028054 0.45412311 0.0968425 0.00017 -0.000583088782 7.56000009e-05 0.000311446609 0.876347959 0.11362233 0.468085855 0.0962297 0.00017 -0.000575795071 8.19000052e-05 0.000319835613 0.867509186 0.123392865 0.481873393 0.0961127 0.00017 -0.000567532261 8.82000095e-05 0.000327665068 0.858286679 0.133386061 0.495532304 0.0965829 0.00017 -0.000564883114 8.19000052e-05 0.000338735583 0.851068914 0.123392865 0.510348618 0.0917439 0.00017 -0.000561264926 7.56000081e-05 0.000349246635 0.84354794 0.113622338 0.524897039 0.0876682 0.00017 -0.000556718151 6.93000038e-05 0.000359221565 0.835704267 0.104028068 0.539236963 0.0841789 0.00017 -0.00055126223 6.30000068e-05 0.00036867155 0.827514231 0.0945709646 0.55342257 0.0811455 0.00017 -0.000544897048 5.67000061e-05 0.000377596647 0.81894803 0.0852167532 0.567505419 0.0784846 0.00017 -0.000537603337 5.04000054e-05 0.000385985593 0.809968412 0.0759340748 0.581536829 0.0761295 0.00017 -0.000529340527 4.41000047e-05 0.000393815048 0.800528705 0.0666930228 0.595571756 0.0740233 0.00017 -0.000532147358 3.14999997e-05 0.000395435578 0.801748276 0.0474587902 0.595774472 0.0720159 0.00017 -0.00053398509 1.89000002e-05 0.000396496616 0.802547991 0.0284055825 0.595910966 0.0706937 0.00017 -0.000534894294 6.29999886e-06 0.000397021562 0.802943945 0.00945709459 0.595979512 0.0699221 0.00017 -0.000534894294 -6.3000025e-06 0.000397021562 0.802943945 -0.00945710018 0.595979512 0.0696865 0.00017 -0.00053398509 -1.8900002e-05 0.000396496616 0.802547991 -0.0284055844 0.595910966 0.0699221 0.00017 -0.000532147358 -3.15000034e-05 0.000395435578 0.801748276 -0.047458794 0.595774472 0.0706937 0.00017 -0.000529340527 -4.41000047e-05 0.000393815048 0.800528705 -0.0666930228 0.595571756 0.0720159 0.00017 -0.000537603337 -5.04000018e-05 0.000385985593 0.809968412 -0.0759340748 0.581536829 0.0738751 0.00017 -0.000544897048 -5.67000025e-05 0.000377596647 0.81894803 -0.0852167457 0.567505419 0.0759435 0.00017 -0.00055126223 -6.30000068e-05 0.00036867155 0.827514231 -0.0945709646 0.55342257 0.0782564 0.00017 -0.000556718151 -6.92999965e-05 0.000359221565 0.835704267 -0.104028054 0.539236963 0.0808855 0.00017 -0.000561264926 -7.56000009e-05 0.000349246635 0.84354794 -0.11362233 0.524897039 0.0838733 0.00017 -0.000564883114 -8.19000052e-05 0.000338735583 0.851068914 -0.123392865 0.510348618 0.0873186 0.00017 -0.000567532261 -8.82000095e-05 0.000327665068 0.858286679 -0.133386061 0.495532304 0.0913404 0.00017 -0.000575795071 -8.19000052e-05 0.000319835613 0.867509186 -0.123392865 0.481873393 0.0914604 0.00017 -0.000583088782 -7.56000081e-05 0.000311446609 0.876347959 -0.113622338 0.468085855 0.0920203 0.00017 -0.000589453964 -6.93000038e-05 0.00030252157 0.884844899 -0.104028068 0.45412311 0.093006 0.00017 -0.000594909885 -6.30000068e-05 0.000293071585 0.893034875 -0.0945709646 0.439937472 0.0943858 0.00017 -0.00059945666 -5.67000061e-05 0.000283096626 0.900947869 -0.0852167532 0.425477475 0.0961877 0.00017 -0.000603074906 -5.04000054e-05 0.000272585603 0.908609688 -0.0759340748 0.410685211 0.0984385 0.00017 -0.00060387241 -5.04000018e-05 0.000247846037 0.922367632 -0.0769820437 0.378565371 0.107301 0.00017 -0.000607337104 -3.78000041e-05 0.000249846373 0.923275113 -0.0574636459 0.379816979 0.104568 0.00017 -0.00060975278 -2.51999991e-05 0.000251241087 0.923914909 -0.0381837599 0.380687714 0.102843 0.00017 -0.000611179974 -1.26000014e-05 0.000252065074 0.924295604 -0.0190551504 0.381201357 0.102018 0.00017 -0.000611652096 0 0.00025233769 0.924421966 0 0.3813712 0.102018 0.00017 -0.000611179974 1.26000014e-05 0.000252065074 0.924295604 0.0190551504 0.381201357 0.102843 0.00017 -0.00060975278 2.52000009e-05 0.000251241087 0.923914909 0.0381837636 0.380687714 0.104568 0.00017 -0.000607337104 3.78000004e-05 0.000249846373 0.923275113 0.0574636385 0.379816979 0.107301 0.00017 -0.00060387241 5.04000018e-05 0.000247846037 0.922367632 0.0769820437 0.378565371 0.111288 0.00017 -0.000601881125 5.67000061e-05 0.000259296357 0.914980948 0.0861954689 0.394182891 0.108206 0.00017 -0.000598840881 6.30000068e-05 0.000270141114 0.907380819 0.0954594091 0.40932554 0.105806 0.00017 -0.000594812038 6.92999965e-05 0.000280415057 0.899542212 0.104803309 0.424075454 0.103996 0.00017 -0.00058982824 7.56000009e-05 0.000290137687 0.891438425 0.11425826 0.438500345 0.102742 0.00017 -0.000583900197 8.19000052e-05 0.000299315085 0.883040011 0.123858467 0.452658176 0.102034 0.00017 -0.000577017025 8.82000022e-05 0.000307941082 0.874312758 0.133643165 0.466601163 0.10191 0.00017 -0.00056914537 9.45000065e-05 0.000315996382 0.865215957 0.143659115 0.480378389 0.102444 0.00017 -0.000560224697 0.000100800004 0.00032344606 0.855699182 0.153964087 0.494038433 0.103784 0.00017 -0.000558233412 9.44999992e-05 0.00033489638 0.848627687 0.143659115 0.509110212 0.097762 0.00017 -0.000555193168 8.82000095e-05 0.000345741108 0.841244578 0.13364318 0.523876846 0.0927979 0.00017 -0.000551164383 8.19000052e-05 0.00035601508 0.833533227 0.123858474 0.538406372 0.0886209 0.00017 -0.000546180585 7.56000009e-05 0.000365737651 0.825471342 0.114258252 0.552758515 0.0850418 0.00017 -0.000540252484 6.92999965e-05 0.000374915078 0.817031026 0.104803309 0.566989064 0.0819487 0.00017 -0.000533369312 6.30000068e-05 0.000383541104 0.808176517 0.0954594091 0.581152439 0.079242 0.00017 -0.000525497657 5.67000025e-05 0.000391596404 0.798862636 0.0861954615 0.595305681 0.0768575 0.00017 -0.000516576984 5.04000018e-05 0.000399046054 0.789030731 0.0769820437 0.609511495 0.0747255 0.00017 -0.000520041678 3.78000041e-05 0.000401046389 0.790568411 0.0574636459 0.609671533 0.07214 0.00017 -0.000522457412 2.51999991e-05 0.000402441103 0.791642427 0.0381837599 0.609790325 0.0703664 0.00017 -0.000523884548 1.26000014e-05 0.00040326509 0.792277575 0.0190551504 0.609863162 0.0692587 0.00017 -0.00052435667 0 0.000403537677 0.79248786 0 0.609887719 0.0687318 0.00017 -0.000523884548 -1.26000014e-05 0.00040326509 0.792277575 -0.0190551504 0.609863162 0.0687318 0.00017 -0.000522457412 -2.52000009e-05 0.000402441103 0.791642427 -0.0381837636 0.609790325 0.0692587 0.00017 -0.000520041678 -3.78000004e-05 0.000401046389 0.790568411 -0.0574636385 0.609671533 0.0703664 0.00017 -0.000516576984 -5.04000018e-05 0.000399046054 0.789030731 -0.0769820437 0.609511495 0.07214 0.00017 -0.000525497657 -5.67000061e-05 0.000391596404 0.798862636 -0.0861954689 0.595305681 0.0740233 0.00017 -0.000533369312 -6.30000068e-05 0.000383541104 0.808176517 -0.0954594091 0.581152439 0.0761295 0.00017 -0.000540252484 -6.92999965e-05 0.000374915078 0.817031026 -0.104803309 0.566989064 0.0784846 0.00017 -0.000546180585 -7.56000009e-05 0.000365737651 0.825471342 -0.114258252 0.552758515 0.0811455 0.00017 -0.000551164383 -8.19000052e-05 0.00035601508 0.833533227 -0.123858474 0.538406372 0.0841789 0.00017 -0.000555193168 -8.82000022e-05 0.000345741108 0.841244578 -0.133643165 0.523876846 0.0876682 0.00017 -0.000558233412 -9.45000065e-05 0.00033489638 0.848627687 -0.14365913 0.509110212 0.0917439 0.00017 -0.000560224697 -0.000100800004 0.00032344606 0.855699182 -0.153964087 0.494038433 0.0965829 0.00017 -0.00056914537 -9.44999992e-05 0.000315996382 0.865215957 -0.1436591 0.480378389 0.0961127 0.00017 -0.000577017025 -8.82000095e-05 0.000307941082 0.874312758 -0.13364318 0.466601163 0.0962267 0.00017 -0.000583900197 -8.19000052e-05 0.000299315085 0.883040011 -0.123858467 0.452658176 0.0968425 0.00017 -0.00058982824 -7.56000009e-05 0.000290137687 0.891438425 -0.11425826 0.438500345 0.097936 0.00017 -0.000594812038 -6.92999965e-05 0.000280415057 0.899542212 -0.104803309 0.424075454 0.0994883 0.00017 -0.000598840881 -6.30000068e-05 0.000270141114 0.907380819 -0.0954594091 0.40932554 0.10153 0.00017 -0.000601881125 -5.67000025e-05 0.000259296357 0.914980948 -0.0861954615 0.394182891 0.104101 0.00017 -0.000600459462 -5.67000025e-05 0.000233275598 0.92853874 -0.0876797661 0.360732794 0.115173 0.00017 -0.000604719098 -4.41000047e-05 0.000235734886 0.929566324 -0.0677899569 0.362368613 0.111254 0.00017 -0.000607812137 -3.1500007e-05 0.000237520653 0.93032527 -0.0482143238 0.363552243 0.108685 0.00017 -0.000609829498 -1.89000002e-05 0.000238685374 0.930825889 -0.0288484059 0.364322364 0.107223 0.00017 -0.000610825431 -6.3000025e-06 0.000239260422 0.931074679 -0.00960302632 0.364702106 0.106743 0.00017 -0.000610825431 6.29999886e-06 0.000239260422 0.931074679 0.00960302074 0.364702106 0.107223 0.00017 -0.000609829498 1.89000002e-05 0.000238685374 0.930825889 0.0288484059 0.364322364 0.108685 0.00017 -0.000607812137 3.14999997e-05 0.000237520653 0.93032527 0.0482143126 0.363552243 0.111254 0.00017 -0.000604719098 4.41000011e-05 0.000235734886 0.929566324 0.0677899495 0.362368613 0.115173 0.00017 -0.000600459462 5.67000025e-05 0.000233275598 0.92853874 0.0876797661 0.360732794 0.120833 0.00017 -0.00059926312 6.30000068e-05 0.00024518487 0.921179533 0.0968427956 0.37689504 0.116929 0.00017 -0.00059690018 6.93000038e-05 0.000256420637 0.913623393 0.106071517 0.39248082 0.113923 0.00017 -0.00059346162 7.56000009e-05 0.000267035386 0.905842483 0.115393639 0.407595009 0.111692 0.00017 -0.000589001575 8.19000052e-05 0.000277060404 0.89780885 0.124839313 0.422320247 0.110165 0.00017 -0.000583545596 8.82000095e-05 0.000286510418 0.889492393 0.134442344 0.436724812 0.109297 0.00017 -0.000577093742 9.44999992e-05 0.000295385369 0.880859077 0.144242048 0.450867623 0.109141 0.00017 -0.000569620403 0.000100800004 0.000303670618 0.87186861 0.154285833 0.464802325 0.109753 0.00017 -0.000561071385 0.000107100008 0.000311334879 0.8624717 0.164632753 0.478579998 0.111314 0.00017 -0.000551355828 0.000113400005 0.00031832559 0.85260576 0.175359532 0.492252439 0.114095 0.00017 -0.000550159428 0.000107100001 0.000330234878 0.845697999 0.164632738 0.507632792 0.106176 0.00017 -0.000547796488 0.000100800004 0.000341470644 0.838464677 0.154285833 0.52265954 0.0998705 0.00017 -0.000544357928 9.44999992e-05 0.000352085364 0.830892026 0.144242048 0.537412822 0.0947032 0.00017 -0.000539897941 8.82000022e-05 0.000362110382 0.822960675 0.134442315 0.551961005 0.0903717 0.00017 -0.000534441962 8.19000052e-05 0.000371560425 0.814644158 0.124839298 0.56636554 0.0866985 0.00017 -0.000527990051 7.56000009e-05 0.000380435376 0.80590862 0.115393639 0.580685437 0.0835216 0.00017 -0.000520516711 6.92999965e-05 0.000388720655 0.796709776 0.106071495 0.594980955 0.0807891 0.00017 -0.000511967693 6.29999995e-05 0.000396384887 0.786990166 0.0968427882 0.60931772 0.078378 0.00017 -0.000502252136 5.67000025e-05 0.000403375598 0.776672781 0.0876797661 0.623772085 0.0762658 0.00017 -0.000506511715 4.41000047e-05 0.000405834871 0.778603315 0.0677899569 0.623844147 0.0728366 0.00017 -0.000509604753 3.1500007e-05 0.000407620624 0.780007899 0.0482143275 0.623909593 0.0704606 0.00017 -0.000511622173 1.89000002e-05 0.000408785359 0.780925095 0.0288484097 0.623958051 0.0688953 0.00017 -0.000512618106 6.3000025e-06 0.000409360393 0.781378329 0.00960302725 0.623983741 0.0680017 0.00017 -0.000512618106 -6.29999886e-06 0.000409360393 0.781378329 -0.00960302167 0.623983741 0.0677125 0.00017 -0.000511622173 -1.89000002e-05 0.000408785359 0.780925095 -0.0288484097 0.623958051 0.0680017 0.00017 -0.000509604753 -3.14999997e-05 0.000407620624 0.780007899 -0.0482143164 0.623909593 0.0688953 0.00017 -0.000506511715 -4.41000011e-05 0.000405834871 0.778603315 -0.0677899495 0.623844147 0.0704606 0.00017 -0.000502252136 -5.67000025e-05 0.000403375598 0.776672781 -0.0876797661 0.623772085 0.0728366 0.00017 -0.000511967693 -6.30000068e-05 0.000396384887 0.786990166 -0.0968427956 0.60931772 0.0747255 0.00017 -0.000520516711 -6.93000038e-05 0.000388720655 0.796709776 -0.106071509 0.594980955 0.0768575 0.00017 -0.000527990051 -7.56000009e-05 0.000380435376 0.80590862 -0.115393639 0.580685437 0.079242 0.00017 -0.000534441962 -8.19000052e-05 0.000371560425 0.814644158 -0.124839298 0.56636554 0.0819487 0.00017 -0.000539897941 -8.82000095e-05 0.000362110382 0.822960675 -0.134442329 0.551961005 0.0850486 0.00017 -0.000544357928 -9.44999992e-05 0.000352085364 0.830892026 -0.144242048 0.537412822 0.0886209 0.00017 -0.000547796488 -0.000100800004 0.000341470644 0.838464677 -0.154285833 0.52265954 0.0927979 0.00017 -0.000550159428 -0.000107100008 0.000330234878 0.845697999 -0.164632753 0.507632792 0.097759 0.00017 -0.000551355828 -0.000113400005 0.00031832559 0.85260576 -0.175359532 0.492252439 0.103784 0.00017 -0.000561071385 -0.000107100001 0.000311334879 0.8624717 -0.164632738 0.478579998 0.102444 0.00017 -0.000569620403 -0.000100800004 0.000303670618 0.87186861 -0.154285833 0.464802325 0.101907 0.00017 -0.000577093742 -9.44999992e-05 0.000295385369 0.880859077 -0.144242048 0.450867623 0.102034 0.00017 -0.000583545596 -8.82000022e-05 0.000286510418 0.889492393 -0.134442329 0.436724812 0.102742 0.00017 -0.000589001575 -8.19000052e-05 0.000277060404 0.89780885 -0.124839313 0.422320247 0.103996 0.00017 -0.00059346162 -7.56000009e-05 0.000267035386 0.905842483 -0.115393639 0.407595009 0.105806 0.00017 -0.00059690018 -6.92999965e-05 0.000256420637 0.913623393 -0.106071502 0.39248082 0.108206 0.00017 -0.00059926312 -6.29999995e-05 0.00024518487 0.921179533 -0.0968427882 0.37689504 0.111288 0.00017 -0.000595065823 -6.30000068e-05 0.000217561537 0.934588134 -0.0989454538 0.341694027 0.125893 0.00017 -0.000600346131 -5.03999981e-05 0.000220610134 0.935731232 -0.0785561055 0.343854636 0.120073 0.00017 -0.000604274799 -3.78000004e-05 0.000222878356 0.936605036 -0.0585886948 0.345453769 0.116178 0.00017 -0.000606995658 -2.52000027e-05 0.000224449279 0.937221646 -0.0389096476 0.3465572 0.113778 0.00017 -0.00060859666 -1.25999977e-05 0.000225373587 0.937588394 -0.0194112342 0.347204775 0.112631 0.00017 -0.000609125243 0 0.00022567877 0.937710285 0 0.347418368 0.112631 0.00017 -0.00060859666 1.26000014e-05 0.000225373587 0.937588394 0.0194112398 0.347204775 0.113778 0.00017 -0.000606995658 2.52000027e-05 0.000224449279 0.937221646 0.0389096476 0.3465572 0.116178 0.00017 -0.000604274799 3.78000004e-05 0.000222878356 0.936605036 0.0585886948 0.345453769 0.120073 0.00017 -0.000600346131 5.04000018e-05 0.000220610134 0.935731232 0.0785561129 0.343854636 0.125891 0.00017 -0.000595065823 6.30000068e-05 0.000217561537 0.934588134 0.0989454538 0.341694027 0.134451 0.00017 -0.000594890153 6.92999965e-05 0.000230060148 0.927227259 0.108014643 0.358583897 0.128972 0.00017 -0.000593362842 7.56000009e-05 0.000241778354 0.919691861 0.11717739 0.374748081 0.124901 0.00017 -0.00059062778 8.19000052e-05 0.000252799276 0.911949039 0.12645635 0.390330553 0.121936 0.00017 -0.000586772745 8.82000095e-05 0.000263173599 0.903967142 0.135878682 0.405438513 0.119912 0.00017 -0.00058184535 9.45000065e-05 0.000272928766 0.895714641 0.145476863 0.420156777 0.118765 0.00017 -0.000575860846 0.000100800004 0.000282073597 0.887156487 0.155289918 0.434555382 0.118503 0.00017 -0.000568803924 0.000107100008 0.000290599273 0.878252149 0.165365964 0.448694915 0.119202 0.00017 -0.000560627086 0.000113400005 0.00029847835 0.868952632 0.175766096 0.462631166 0.121062 0.00017 -0.00055124244 0.000119700002 0.000305660156 0.85919565 0.186570764 0.476418078 0.124427 0.00017 -0.000540506153 0.000126000014 0.000312061544 0.848898828 0.197890922 0.490112215 0.129962 0.00017 -0.000540330482 0.000119700002 0.000324560126 0.842187762 0.186570778 0.505876601 0.118629 0.00017 -0.000538803171 0.000113400012 0.000336278375 0.8351264 0.17576611 0.521219909 0.110065 0.00017 -0.00053606811 0.000107100008 0.000347299268 0.827707112 0.165365994 0.53624171 0.103316 0.00017 -0.000532213191 0.000100800004 0.000357673562 0.819913983 0.155289903 0.551022708 0.0978446 0.00017 -0.000527285796 9.45000065e-05 0.000367428758 0.81172353 0.145476863 0.565633655 0.0933065 0.00017 -0.000521301234 8.82000095e-05 0.000376573589 0.803103387 0.135878682 0.580139637 0.089499 0.00017 -0.000514244311 8.19000052e-05 0.000385099236 0.794010401 0.12645635 0.594606102 0.0862747 0.00017 -0.000506067416 7.56000009e-05 0.000392978371 0.784387052 0.117177397 0.609102905 0.0835251 0.00017 -0.000496682769 6.93000038e-05 0.000400160119 0.774156153 0.108014666 0.623710811 0.0811988 0.00017 -0.000485946541 6.30000068e-05 0.000406561507 0.763209522 0.0989454612 0.638530374 0.0792893 0.00017 -0.000491226849 5.03999981e-05 0.000409610104 0.765652239 0.0785561129 0.638440073 0.0744431 0.00017 -0.000495155517 3.78000004e-05 0.000411878369 0.767473936 0.0585886948 0.638397217 0.0711493 0.00017 -0.000497876375 2.52000027e-05 0.000413449248 0.768737793 0.0389096476 0.638379455 0.0689372 0.00017 -0.000499477377 1.25999977e-05 0.000414373586 0.769482076 0.0194112342 0.638373375 0.0675761 0.00017 -0.000500005903 0 0.000414678769 0.769727945 0 0.638372123 0.0669153 0.00017 -0.000499477377 -1.26000014e-05 0.000414373586 0.769482076 -0.0194112416 0.638373375 0.0669153 0.00017 -0.000497876375 -2.52000027e-05 0.000413449248 0.768737793 -0.0389096476 0.638379455 0.0675761 0.00017 -0.000495155517 -3.78000004e-05 0.000411878369 0.767473936 -0.0585886948 0.638397217 0.0689372 0.00017 -0.000491226849 -5.04000018e-05 0.000409610104 0.765652239 -0.0785561204 0.638440073 0.0711493 0.00017 -0.000485946541 -6.30000068e-05 0.000406561507 0.763209522 -0.0989454612 0.638530374 0.0744431 0.00017 -0.000496682769 -6.92999965e-05 0.000400160119 0.774156153 -0.108014658 0.623710811 0.0762658 0.00017 -0.000506067416 -7.56000009e-05 0.000392978371 0.784387052 -0.117177397 0.609102905 0.078378 0.00017 -0.000514244311 -8.19000052e-05 0.000385099236 0.794010401 -0.12645635 0.594606102 0.0807891 0.00017 -0.000521301234 -8.82000095e-05 0.000376573589 0.803103387 -0.135878682 0.580139637 0.0835216 0.00017 -0.000527285796 -9.45000065e-05 0.000367428758 0.81172353 -0.145476863 0.565633655 0.0866985 0.00017 -0.000532213191 -0.000100800004 0.000357673562 0.819913983 -0.155289903 0.551022708 0.0903749 0.00017 -0.00053606811 -0.000107100008 0.000347299268 0.827707112 -0.165365994 0.53624171 0.0947032 0.00017 -0.000538803171 -0.000113400005 0.000336278375 0.8351264 -0.175766096 0.521219909 0.0998705 0.00017 -0.000540330482 -0.000119700002 0.000324560126 0.842187762 -0.186570778 0.505876601 0.106176 0.00017 -0.000540506153 -0.000126000014 0.000312061544 0.848898828 -0.197890922 0.490112215 0.114095 0.00017 -0.00055124244 -0.000119700002 0.000305660156 0.85919565 -0.186570764 0.476418078 0.111314 0.00017 -0.000560627086 -0.000113400012 0.00029847835 0.868952632 -0.17576611 0.462631166 0.109753 0.00017 -0.000568803924 -0.000107100008 0.000290599273 0.878252149 -0.165365964 0.448694915 0.109141 0.00017 -0.000575860846 -0.000100800004 0.000282073597 0.887156487 -0.155289918 0.434555382 0.109297 0.00017 -0.00058184535 -9.45000065e-05 0.000272928766 0.895714641 -0.145476863 0.420156777 0.110165 0.00017 -0.000586772745 -8.82000095e-05 0.000263173599 0.903967142 -0.135878682 0.405438513 0.111692 0.00017 -0.00059062778 -8.19000052e-05 0.000252799276 0.911949039 -0.12645635 0.390330553 0.113923 0.00017 -0.000593362842 -7.56000009e-05 0.000241778354 0.919691861 -0.11717739 0.374748081 0.116929 0.00017 -0.000594890153 -6.93000038e-05 0.000230060148 0.927227259 -0.108014658 0.358583897 0.120833 0.00017 -0.000586938288 -6.93000038e-05 0.000200269176 0.940569043 -0.11105331 0.320931494 0.141868 0.00017 -0.00059365714 -5.67000025e-05 0.000204148266 0.941814482 -0.0899523944 0.32387346 0.132504 0.00017 -0.000598697807 -4.40999975e-05 0.000207058474 0.942793727 -0.0694460496 0.326063365 0.126342 0.00017 -0.000602312619 -3.14999997e-05 0.000209145524 0.94351846 -0.0493445247 0.327625006 0.122418 0.00017 -0.000604652101 -1.89000002e-05 0.000210496204 0.943997145 -0.0295071285 0.328631639 0.120224 0.00017 -0.00060580211 -6.29999522e-06 0.000211160135 0.944235206 -0.00981950574 0.329125345 0.119514 0.00017 -0.00060580211 6.3000025e-06 0.000211160135 0.944235206 0.00981951784 0.329125345 0.120224 0.00017 -0.000604652101 1.89000039e-05 0.000210496204 0.943997145 0.0295071341 0.328631639 0.122418 0.00017 -0.000602312619 3.1500007e-05 0.000209145524 0.94351846 0.0493445359 0.327625006 0.126342 0.00017 -0.000598697807 4.41000047e-05 0.000207058474 0.942793727 0.0694460645 0.326063365 0.132504 0.00017 -0.00059365714 5.67000061e-05 0.000204148266 0.941814482 0.0899524018 0.32387346 0.141868 0.00017 -0.000586938288 6.93000038e-05 0.000200269176 0.940569043 0.11105331 0.320931494 0.156394 0.00017 -0.000588201219 7.56000009e-05 0.00021359828 0.933158815 0.119936526 0.338865548 0.147317 0.00017 -0.000587785849 8.19000052e-05 0.000225958473 0.925610244 0.128971264 0.35582599 0.140972 0.00017 -0.000585944741 8.82000095e-05 0.000237495522 0.917878211 0.138164684 0.372035027 0.136513 0.00017 -0.000582828186 9.45000065e-05 0.000248296186 0.909925222 0.147535667 0.38764593 0.133531 0.00017 -0.000578522217 0.000100800004 0.000258410146 0.901715457 0.157112241 0.402771741 0.131816 0.00017 -0.000573066238 0.000107100001 0.00026786013 0.893211484 0.166931748 0.417501003 0.131314 0.00017 -0.00056646025 0.000113400012 0.000276646198 0.884371281 0.177042797 0.431906641 0.132096 0.00017 -0.000558664964 0.000119700002 0.000284745533 0.87514466 0.187509194 0.446051836 0.134393 0.00017 -0.000549594115 0.000126000014 0.000292108452 0.865468204 0.198417321 0.459995031 0.138678 0.00017 -0.000539097528 0.000132300018 0.000298648287 0.85525775 0.20988895 0.473794162 0.145887 0.00017 -0.000526922755 0.000138600008 0.000304219167 0.844394028 0.222106621 0.487511426 0.0821597 0.00017 -0.00052818557 0.000132300018 0.000317548256 0.837946355 0.20988895 0.503778279 0.138999 0.00017 -0.000527770258 0.000126000014 0.000329908478 0.831101239 0.198417321 0.519520283 0.125937 0.00017 -0.000525929034 0.000119700009 0.000341445499 0.823864162 0.187509224 0.534871936 0.1163 0.00017 -0.000522812654 0.000113400012 0.000352246192 0.816227496 0.177042797 0.549935102 0.108863 0.00017 -0.000518506684 0.000107100015 0.000362360151 0.808171928 0.166931748 0.564793706 0.102936 0.00017 -0.000513050705 0.000100800011 0.000371810136 0.799667954 0.157112241 0.579522967 0.0981332 0.00017 -0.000506444718 9.45000065e-05 0.000380596175 0.790673494 0.147535652 0.594195783 0.0942175 0.00017 -0.000498649315 8.82000095e-05 0.000388695538 0.781130612 0.138164684 0.608888745 0.0910144 0.00017 -0.000489578524 8.19000124e-05 0.000396058458 0.770959139 0.128971279 0.623689353 0.0884579 0.00017 -0.000479081908 7.56000081e-05 0.000402598293 0.76004529 0.119936548 0.638706923 0.0865486 0.00017 -0.000466907135 6.93000038e-05 0.000408169173 0.748218954 0.111053303 0.654091358 0.085421 0.00017 -0.000473625958 5.67000025e-05 0.000412048277 0.751389623 0.0899524018 0.653698921 0.0778015 0.00017 -0.000478666596 4.40999975e-05 0.000414958457 0.753775716 0.0694460496 0.65345192 0.0728762 0.00017 -0.000482281437 3.14999997e-05 0.000417045521 0.755490422 0.049344521 0.653298855 0.0696368 0.00017 -0.000484620861 1.89000002e-05 0.000418396201 0.756601632 0.0295071304 0.653210104 0.067559 0.00017 -0.00048577087 6.29999522e-06 0.000419060118 0.757148266 0.00981950667 0.653169334 0.0664002 0.00017 -0.00048577087 -6.3000025e-06 0.000419060118 0.757148266 -0.00981951784 0.653169334 0.0660342 0.00017 -0.000484620861 -1.89000039e-05 0.000418396201 0.756601632 -0.029507136 0.653210104 0.0664002 0.00017 -0.000482281437 -3.1500007e-05 0.000417045521 0.755490422 -0.0493445322 0.653298855 0.067559 0.00017 -0.000478666596 -4.41000047e-05 0.000414958457 0.753775716 -0.0694460645 0.65345192 0.0696368 0.00017 -0.000473625958 -5.67000061e-05 0.000412048277 0.751389623 -0.0899524093 0.653698921 0.0728762 0.00017 -0.000466907135 -6.93000038e-05 0.000408169173 0.748218954 -0.111053303 0.654091358 0.0778015 0.00017 -0.000479081908 -7.56000009e-05 0.000402598293 0.76004529 -0.119936533 0.638706923 0.0792893 0.00017 -0.000489578524 -8.19000052e-05 0.000396058458 0.770959139 -0.128971264 0.623689353 0.0811988 0.00017 -0.000498649315 -8.82000095e-05 0.000388695538 0.781130612 -0.138164684 0.608888745 0.0835251 0.00017 -0.000506444718 -9.45000065e-05 0.000380596175 0.790673494 -0.147535652 0.594195783 0.0862747 0.00017 -0.000513050705 -0.000100800004 0.000371810136 0.799667954 -0.157112226 0.579522967 0.089499 0.00017 -0.000518506684 -0.000107100001 0.000362360151 0.808171928 -0.166931733 0.564793706 0.0933065 0.00017 -0.000522812654 -0.000113400012 0.000352246192 0.816227496 -0.177042797 0.549935102 0.0978446 0.00017 -0.000525929092 -0.000119700002 0.000341445528 0.823864281 -0.187509209 0.534871995 0.103319 0.00017 -0.000527770258 -0.000126000014 0.000329908478 0.831101239 -0.198417321 0.519520283 0.110065 0.00017 -0.00052818557 -0.000132300018 0.000317548256 0.837946355 -0.20988895 0.503778279 0.118629 0.00017 -0.000526922755 -0.000138600008 0.000304219167 0.844394028 -0.222106621 0.487511426 0.129962 0.00017 -0.000539097528 -0.000132300018 0.000298648287 0.85525775 -0.20988895 0.473794162 0.124427 0.00017 -0.000549594115 -0.000126000014 0.000292108452 0.865468204 -0.198417321 0.459995031 0.121062 0.00017 -0.000558664906 -0.000119700009 0.000284745503 0.875144601 -0.187509224 0.446051806 0.119202 0.00017 -0.00056646025 -0.000113400012 0.000276646198 0.884371281 -0.177042797 0.431906641 0.118503 0.00017 -0.000573066238 -0.000107100015 0.00026786013 0.893211484 -0.166931763 0.417501003 0.118765 0.00017 -0.000578522217 -0.000100800011 0.000258410146 0.901715398 -0.157112241 0.402771711 0.119909 0.00017 -0.000582828186 -9.45000065e-05 0.000248296186 0.909925222 -0.147535667 0.38764593 0.121936 0.00017 -0.000585944741 -8.82000095e-05 0.000237495522 0.917878211 -0.138164684 0.372035027 0.124901 0.00017 -0.000587785849 -8.19000124e-05 0.000225958473 0.925610244 -0.128971279 0.35582599 0.128969 0.00017 -0.000588201219 -7.56000081e-05 0.00021359828 0.933158815 -0.119936541 0.338865548 0.134455 0.00017 -0.000583555724 -6.30000141e-05 0.000185716257 0.947904348 -0.102334678 0.301669985 0.152268 0.00017 -0.00059027283 -5.04000054e-05 0.000189594342 0.948961973 -0.0810264125 0.304804504 0.141399 0.00017 -0.000595143356 -3.78000004e-05 0.000192406369 0.949777186 -0.0603242554 0.30705741 0.13459 0.00017 -0.000598463463 -2.52000027e-05 0.00019432322 0.950355113 -0.0400173999 0.308583707 0.130544 0.00017 -0.000600398751 -1.2600005e-05 0.000195440574 0.950699985 -0.0199514478 0.309469908 0.128658 0.00017 -0.000601035019 0 0.000195807908 0.950814545 0 0.30976066 0.128658 0.00017 -0.000600398751 1.25999977e-05 0.000195440574 0.950699985 0.0199514367 0.309469908 0.130547 0.00017 -0.000598463463 2.51999991e-05 0.00019432322 0.950355113 0.0400173925 0.308583707 0.13459 0.00017 -0.000595143356 3.78000004e-05 0.000192406369 0.949777186 0.0603242554 0.30705741 0.141399 0.00017 -0.00059027283 5.03999981e-05 0.000189594342 0.948961973 0.0810264051 0.304804504 0.152268 0.00017 -0.000583555724 6.30000068e-05 0.000185716257 0.947904348 0.102334663 0.301669985 0.152268 0.00017 -0.000578099862 8.19000052e-05 0.000195166271 0.939042032 0.133035049 0.317020178 0.156394 0.00017 -0.000579360931 8.82000095e-05 0.000208494326 0.931419313 0.141796216 0.335189402 0.168001 0.00017 -0.000578775478 9.44999992e-05 0.000220756367 0.923656046 0.150810644 0.352300614 0.1598 0.00017 -0.000576639606 0.000100800004 0.000232123202 0.915699005 0.160069585 0.368609756 0.154536 0.00017 -0.000573118974 0.000107100008 0.000242690556 0.907503784 0.16958724 0.384287775 0.15148 0.00017 -0.000568299263 0.000113400005 0.000252507918 0.899027765 0.179394484 0.399457902 0.150351 0.00017 -0.000562207075 0.000119700002 0.000261590583 0.890225291 0.189538658 0.414214909 0.151155 0.00017 -0.00055481575 0.000126000014 0.000269923214 0.881042898 0.200086996 0.428635895 0.15417 0.00017 -0.000546039781 0.000132299989 0.000277456391 0.871413648 0.211134836 0.442786932 0.160125 0.00017 -0.000535713218 0.000138600008 0.000284094305 0.861248374 0.222822636 0.456728995 0.0988948 0.00017 -0.000523540191 0.000144900012 0.000289666263 0.850417495 0.235369742 0.470522165 0.0893505 0.00017 -0.000512628292 0.000144899997 0.000308566261 0.832692623 0.235369697 0.501222551 0.0976556 0.00017 -0.000513889361 0.000138599993 0.000321894331 0.826162815 0.222822607 0.517498851 0.0717591 0.00017 -0.000513303967 0.000132299989 0.000334156386 0.819171309 0.211134866 0.533273339 0.138266 0.00017 -0.000511168095 0.000126000014 0.000345523207 0.811730683 0.200086981 0.548687994 0.126725 0.00017 -0.000507647463 0.000119700002 0.000356090604 0.803833067 0.189538658 0.563850701 0.118142 0.00017 -0.000502827752 0.000113400005 0.000365907908 0.795454323 0.179394484 0.578852355 0.111573 0.00017 -0.000496735564 0.000107100001 0.000374990603 0.786554575 0.16958721 0.593777895 0.106483 0.00017 -0.00048934418 0.000100799996 0.000383323204 0.777074575 0.16006957 0.608714104 0.102593 0.00017 -0.000480568124 9.44999992e-05 0.000390856352 0.766928911 0.150810644 0.623759687 0.0998011 0.00017 -0.000470241648 8.82000022e-05 0.000397494325 0.755991876 0.141796201 0.639038444 0.0981802 0.00017 -0.000458068651 8.18999979e-05 0.000403066253 0.744068205 0.133035034 0.654724538 0.0734442 0.00017 -0.000452612643 6.30000141e-05 0.000412516238 0.73520571 0.102334678 0.670074701 0.0810779 0.00017 -0.00045932972 5.04000054e-05 0.000416394323 0.738449097 0.0810264125 0.669423282 0.0768838 0.00017 -0.000464200246 3.78000004e-05 0.000419206335 0.740807772 0.0603242554 0.669002891 0.0716182 0.00017 -0.000467520353 2.52000027e-05 0.000421123201 0.742418528 0.0400173999 0.668740213 0.068315 0.00017 -0.000469455641 1.2600005e-05 0.000422240555 0.743358374 0.019951446 0.668595731 0.066348 0.00017 -0.000470091938 0 0.000422607874 0.743667543 0 0.668549597 0.0654152 0.00017 -0.000469455641 -1.25999977e-05 0.000422240555 0.743358374 -0.0199514348 0.668595731 0.0654152 0.00017 -0.000467520353 -2.51999991e-05 0.000421123201 0.742418528 -0.0400173925 0.668740213 0.066348 0.00017 -0.000464200246 -3.78000004e-05 0.000419206335 0.740807772 -0.0603242554 0.669002891 0.068315 0.00017 -0.00045932972 -5.03999981e-05 0.000416394323 0.738449097 -0.0810264051 0.669423282 0.0716182 0.00017 -0.000452612643 -6.30000068e-05 0.000412516238 0.73520571 -0.102334663 0.670074701 0.0768838 0.00017 -0.000458068651 -8.19000052e-05 0.000403066253 0.744068205 -0.133035049 0.654724538 0.085421 0.00017 -0.000470241648 -8.82000095e-05 0.000397494325 0.755991876 -0.141796216 0.639038444 0.0865419 0.00017 -0.000480568124 -9.44999992e-05 0.000390856352 0.766928911 -0.150810644 0.623759687 0.0884579 0.00017 -0.00048934418 -0.000100800004 0.000383323204 0.777074575 -0.16006957 0.608714104 0.0910144 0.00017 -0.000496735505 -0.000107100008 0.000374990545 0.786554575 -0.16958724 0.593777835 0.0942175 0.00017 -0.000502827752 -0.000113400005 0.000365907908 0.795454323 -0.179394484 0.578852355 0.0981332 0.00017 -0.000507647463 -0.000119700002 0.000356090604 0.803833067 -0.189538658 0.563850701 0.102936 0.00017 -0.000511168095 -0.000126000014 0.000345523207 0.811730683 -0.200086981 0.548687994 0.108863 0.00017 -0.000513303967 -0.000132299989 0.000334156386 0.819171309 -0.211134866 0.533273339 0.116302 0.00017 -0.000513889361 -0.000138600008 0.000321894331 0.826162815 -0.222822636 0.517498851 0.125935 0.00017 -0.000512628234 -0.000144900012 0.000308566232 0.832692623 -0.235369742 0.501222551 0.138999 0.00017 -0.000508970174 -0.000151200002 0.000293854246 0.838713467 -0.249156997 0.48423174 0.158004 0.00017 -0.00052354025 -0.000144899997 0.000289666292 0.850417554 -0.235369697 0.470522195 0.145883 0.00017 -0.000535713218 -0.000138599993 0.000284094305 0.861248374 -0.222822607 0.456728995 0.138678 0.00017 -0.000546039781 -0.000132299989 0.000277456391 0.871413648 -0.211134836 0.442786932 0.134391 0.00017 -0.00055481575 -0.000126000014 0.000269923214 0.881042898 -0.200086996 0.428635895 0.132096 0.00017 -0.000562207075 -0.000119700002 0.000261590583 0.890225291 -0.189538658 0.414214909 0.131314 0.00017 -0.000568299263 -0.000113400005 0.000252507918 0.899027765 -0.179394484 0.399457902 0.131816 0.00017 -0.000573119032 -0.000107100001 0.000242690585 0.907503784 -0.16958721 0.384287775 0.133531 0.00017 -0.000576639606 -0.000100799996 0.000232123202 0.915699005 -0.16006957 0.368609756 0.136513 0.00017 -0.000578775478 -9.44999992e-05 0.000220756367 0.923656046 -0.150810644 0.352300614 0.140972 0.00017 -0.000579360931 -8.82000022e-05 0.000208494326 0.931419313 -0.141796201 0.335189402 0.147319 0.00017 -0.000578099862 -8.18999979e-05 0.000195166271 0.939042032 -0.133035034 0.317020178 0.156394 0.00017 -0.000584184425 -4.41000047e-05 0.000173479217 0.956124306 -0.0721776932 0.283930361 0.15411 0.00017 -0.000589011761 -3.14999997e-05 0.000176266272 0.956766844 -0.0511673242 0.286319792 0.146002 0.00017 -0.000592067197 -1.89000002e-05 0.000178030328 0.957196295 -0.0305556711 0.287822008 0.141703 0.00017 -0.000593551726 -6.3000025e-06 0.000178887421 0.95741117 -0.0101620341 0.288549095 0.140354 0.00017 -0.000593551726 6.3000025e-06 0.000178887421 0.95741117 0.0101620341 0.288549095 0.141703 0.00017 -0.000592067197 1.89000002e-05 0.000178030328 0.957196295 0.0305556711 0.287822008 0.146002 0.00017 -0.000589011761 3.15000034e-05 0.000176266272 0.956766844 0.0511673279 0.286319792 0.15411 0.00017 -0.000584184425 4.41000047e-05 0.000173479217 0.956124306 0.0721776932 0.283930361 0.15411 0.00017 -0.000567816605 0.000100800004 0.000201829214 0.929335356 0.16497758 0.330330312 0.168001 0.00017 -0.000567187904 0.000107100001 0.000214066284 0.921317101 0.173968911 0.347720593 0.0360068 0.00017 -0.00056478742 0.000113400005 0.000225280324 0.91309303 0.183334023 0.364211172 0.0456583 0.00017 -0.00056081597 0.000119700002 0.000235587417 0.904607654 0.193078578 0.380007356 0.0532483 0.00017 -0.000555359991 0.000126000014 0.00024503743 0.895807147 0.203240618 0.39525044 0.0599371 0.00017 -0.000548419484 0.000132300018 0.000253630336 0.886630952 0.213889703 0.41004467 0.0664784 0.00017 -0.000539908069 0.000138599993 0.00026131628 0.877004802 0.225136235 0.424471587 0.0735698 0.00017 -0.000529624871 0.000144899997 0.000267979223 0.866827607 0.237155274 0.438596845 0.0820718 0.00017 -0.000496889057 0.000144899997 0.000324679218 0.813249528 0.237155274 0.531396747 0.109413 0.00017 -0.000496260356 0.000138600008 0.000336916215 0.806105256 0.225136265 0.547273099 0.0648437 0.00017 -0.000493859872 0.000132300018 0.000348130328 0.798424304 0.213889703 0.562823057 0.0608401 0.00017 -0.00048988848 0.000126000014 0.000358437392 0.790200174 0.203240603 0.578166902 0.059118 0.00017 -0.000484432472 0.000119700002 0.000367887405 0.781399548 0.193078578 0.593409956 0.0590545 0.00017 -0.000477491994 0.000113400005 0.00037648034 0.771962345 0.183334023 0.608656526 0.0603879 0.00017 -0.000468980579 0.000107100008 0.000384166255 0.761793077 0.173968911 0.624024153 0.0631576 0.00017 -0.000458697323 0.000100800004 0.000390829227 0.75074178 0.16497758 0.639663279 0.0676998 0.00017 -0.000442329416 4.41000047e-05 0.00041917921 0.72395277 0.0721776932 0.68606323 0.0922396 0.00017 -0.000447156752 3.14999997e-05 0.000421966281 0.726343334 0.0511673242 0.685424924 0.0707875 0.00017 -0.000450212188 1.89000002e-05 0.000423730322 0.727858961 0.0305556692 0.68504566 0.0671864 0.00017 -0.000451696716 6.3000025e-06 0.000424587401 0.728596091 0.0101620341 0.684868217 0.0652739 0.00017 -0.000451696716 -6.3000025e-06 0.000424587401 0.728596091 -0.0101620341 0.684868217 0.0646789 0.00017 -0.000450212188 -1.89000002e-05 0.000423730322 0.727858961 -0.0305556692 0.68504566 0.0652739 0.00017 -0.000447156752 -3.15000034e-05 0.000421966281 0.726343334 -0.0511673279 0.685424924 0.0671864 0.00017 -0.000442329416 -4.41000047e-05 0.00041917921 0.72395277 -0.0721776932 0.68606323 0.0707875 0.00017 -0.000458697323 -0.000100800004 0.000390829227 0.75074178 -0.16497758 0.639663279 0.0981802 0.00017 -0.000468980579 -0.000107100001 0.000384166255 0.761793077 -0.173968911 0.624024153 0.0998011 0.00017 -0.000477491994 -0.000113400005 0.00037648034 0.771962345 -0.183334023 0.608656526 0.102593 0.00017 -0.000484432472 -0.000119700002 0.000367887405 0.781399548 -0.193078578 0.593409956 0.106483 0.00017 -0.00048988848 -0.000126000014 0.000358437392 0.790200174 -0.203240603 0.578166902 0.111573 0.00017 -0.000493859872 -0.000132300018 0.000348130328 0.798424304 -0.213889703 0.562823057 0.118142 0.00017 -0.000496260414 -0.000138599993 0.000336916244 0.806105316 -0.225136235 0.547273099 0.126725 0.00017 -0.000496889057 -0.000144899997 0.000324679218 0.813249528 -0.237155274 0.531396747 0.138266 0.00017 -0.000529624871 -0.000144899997 0.000267979223 0.866827607 -0.237155274 0.438596845 0.160125 0.00017 -0.000539908011 -0.000138600008 0.000261316251 0.877004921 -0.225136295 0.424471647 0.154172 0.00017 -0.000548419484 -0.000132300018 0.000253630336 0.886630952 -0.213889703 0.41004467 0.151155 0.00017 -0.000555359991 -0.000126000014 0.00024503743 0.895807147 -0.203240618 0.39525044 0.150351 0.00017 -0.00056081597 -0.000119700002 0.000235587417 0.904607654 -0.193078578 0.380007356 0.15148 0.00017 -0.00056478742 -0.000113400005 0.000225280324 0.91309303 -0.183334023 0.364211172 0.154533 0.00017 -0.000567187904 -0.000107100008 0.000214066284 0.921317101 -0.173968911 0.347720593 0.159801 0.00017 -0.000567816605 -0.000100800004 0.000201829214 0.929335356 -0.16497758 0.330330312 0.168004 0.00017 diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 9fcd14ae..e10fbb18 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -63,8 +63,6 @@ int main (int argc, char** argv) eyevm->finalize(); ep = v.addVisualModel (eyevm); - // Scale this model up, so it's not tiny like the one in the scene - ep->scaleViewMatrix (1000); if (ep->show_sphere) { auto svm = std::make_unique> (ep->proj_sphere_centre, ep->proj_sphere_radius, mplot::colour::slategray1); @@ -74,34 +72,36 @@ int main (int argc, char** argv) v.addVisualModel (svm); - // Can now find intersections on our sphere - sm::vec<> l0 = (*ommatidia)[0].relativePosition; - sm::vec<> l = -(*ommatidia)[0].relativeDirection; - -#if 1 - auto vvm = std::make_unique> (l0); - v.bindmodel (vvm); - vvm->vgoes = mplot::VectorGoes::FromOrigin; - vvm->thickness = 0.001f; - vvm->thevec = l; - vvm->finalize(); - v.addVisualModel (vvm); + for (size_t i = 0; i < ommatidia->size(); ++i) { + // Can now find intersections on our sphere + sm::vec<> l0 = (*ommatidia)[i].relativePosition; + sm::vec<> l = -(*ommatidia)[i].relativeDirection; + + // Show direction vector from ommatidium position + auto vvm = std::make_unique> (l0); + v.bindmodel (vvm); + vvm->vgoes = mplot::VectorGoes::FromOrigin; + vvm->thickness = 0.001f; + vvm->thevec = l; + vvm->finalize(); + v.addVisualModel (vvm); + + sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (sm::vec<>{}, ep->proj_sphere_radius, l0, l); + + if (intersections[0][0] != std::numeric_limits::max()) { + auto ivm1 = std::make_unique> (intersections[0], 0.01f, mplot::colour::crimson); + v.bindmodel (ivm1); + ivm1->finalize(); + v.addVisualModel (ivm1); + } +#if 0 + if (intersections[1][0] != std::numeric_limits::max()) { + auto ivm2 = std::make_unique> (intersections[1], 0.01f, mplot::colour::blue); + v.bindmodel (ivm2); + ivm2->finalize(); + v.addVisualModel (ivm2); + } #endif - - sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (sm::vec<>{}, ep->proj_sphere_radius, l0, l); - - if (intersections[0][0] != std::numeric_limits::max()) { - auto ivm1 = std::make_unique> (intersections[0], 0.01f, mplot::colour::crimson); - v.bindmodel (ivm1); - ivm1->finalize(); - v.addVisualModel (ivm1); - } - - if (intersections[1][0] != std::numeric_limits::max()) { - auto ivm2 = std::make_unique> (intersections[1], 0.01f, mplot::colour::blue); - v.bindmodel (ivm2); - ivm2->finalize(); - v.addVisualModel (ivm2); } } diff --git a/examples/hexy_eyes_dhex.eye b/examples/hexy_eyes_dhex.eye new file mode 100644 index 00000000..243ac413 --- /dev/null +++ b/examples/hexy_eyes_dhex.eye @@ -0,0 +1,1560 @@ +1.38564062 0 0.800000012 0.866025388 0 0.5 0.059501 1 +1.35484648 -0.0333333351 0.848887682 0.847220838 -0.0208442044 0.530831635 0.0586682 1 +1.35484648 0.0333333351 0.848887682 0.847220838 0.0208442044 0.530831635 0.0588084 1 +1.38371396 0.0666666701 0.79888767 0.865272462 0.0416884087 0.499565303 0.059784 1 +1.41258144 0.0333333351 0.748887658 0.883324146 0.0208442062 0.468299031 0.0604536 1 +1.41258144 -0.0333333351 0.748887658 0.883324146 -0.0208442062 0.468299031 0.0603094 1 +1.38371396 -0.0666666701 0.79888767 0.865272462 -0.0416884087 0.499565303 0.059501 1 +1.32017303 -0.0666666701 0.895535648 0.826840222 -0.0417541377 0.560884714 0.0579523 1 +1.3221128 0 0.89665556 0.827618957 0 0.561290324 0.0579523 1 +1.32017303 0.0666666701 0.895535648 0.826840222 0.0417541377 0.560884714 0.0582305 1 +1.3509804 0.100000009 0.846655548 0.845689476 0.0625982136 0.52999115 0.0592297 1 +1.37790811 0.13333334 0.795535624 0.863000393 0.0835082754 0.498253524 0.0603628 1 +1.40871537 0.100000009 0.746655524 0.881830633 0.0625982136 0.467393011 0.0608891 1 +1.4356432 0.0666666701 0.6955356 0.899160564 0.0417541377 0.435622305 0.061537 1 +1.43758297 0 0.696655512 0.899901152 0 0.436093837 0.0612397 1 +1.4356432 -0.0666666701 0.6955356 0.899160564 -0.0417541377 0.435622305 0.0612397 1 +1.40871537 -0.100000009 0.746655524 0.881830633 -0.0625982136 0.467393011 0.0604536 1 +1.37790811 -0.13333334 0.795535624 0.863000393 -0.0835082754 0.498253524 0.059784 1 +1.3509804 -0.100000009 0.846655548 0.845689476 -0.0625982136 0.52999115 0.0588084 1 +1.28154075 -0.100000001 0.939897954 0.804782927 -0.0627980754 0.590237856 0.0573419 1 +1.28546011 -0.0333333313 0.942160785 0.806381166 -0.0209103115 0.591026306 0.0572024 1 +1.28546011 0.0333333388 0.942160785 0.806381166 0.0209103171 0.591026306 0.0573419 1 +1.28154075 0.100000009 0.939897954 0.804782927 0.0627980828 0.590237856 0.0577647 1 +1.3143276 0.13333334 0.892160773 0.82449013 0.0836412609 0.559660852 0.0587982 1 +1.3431952 0.166666672 0.842160761 0.842598975 0.104551569 0.528295338 0.0599553 1 +1.36814332 0.200000018 0.789897919 0.859167695 0.125596166 0.496040702 0.0612573 1 +1.40093017 0.166666672 0.742160738 0.878816724 0.104551576 0.46556443 0.0616358 1 +1.42979777 0.13333334 0.692160726 0.896925569 0.0836412534 0.434198916 0.0621446 1 +1.45474589 0.100000001 0.639897883 0.913552463 0.0627980754 0.401843578 0.0627711 1 +1.45866525 0.0333333313 0.642160714 0.915034413 0.0209103115 0.402833432 0.0623085 1 +1.45866525 -0.0333333388 0.642160714 0.915034413 -0.0209103171 0.402833432 0.0621533 1 +1.45474589 -0.100000009 0.639897883 0.913552463 -0.0627980828 0.401843578 0.0623085 1 +1.42979777 -0.13333334 0.692160726 0.896925569 -0.0836412534 0.434198916 0.061537 1 +1.40093017 -0.166666672 0.742160738 0.878816724 -0.104551576 0.46556443 0.0608891 1 +1.36814332 -0.200000018 0.789897919 0.859167695 -0.125596166 0.496040702 0.0603628 1 +1.3431952 -0.166666672 0.842160761 0.842598975 -0.104551569 0.528295338 0.0592297 1 +1.3143276 -0.13333334 0.892160773 0.82449013 -0.0836412609 0.559660852 0.0582305 1 +1.23881078 -0.13333334 0.981894433 0.780912697 -0.084049724 0.618959606 0.0568416 1 +1.24477983 -0.0666666701 0.985340655 0.783389151 -0.0419559702 0.62011379 0.0565618 1 +1.24676013 0 0.986483991 0.784209371 0 0.620496273 0.0565618 1 +1.24477983 0.0666666701 0.985340655 0.783389151 0.0419559702 0.62011379 0.0568416 1 +1.23881078 0.13333334 0.981894433 0.780912697 0.084049724 0.618959606 0.0574188 1 +1.27364731 0.166666687 0.935340703 0.801556587 0.104889929 0.588646889 0.058487 1 +1.3044951 0.200000018 0.886484027 0.820524573 0.125799567 0.557596505 0.0596811 1 +1.33138239 0.233333349 0.835340679 0.837891579 0.146845892 0.525712907 0.0610134 1 +1.35428083 0.266666681 0.781894445 0.85370189 0.168099448 0.492885053 0.062514 1 +1.38911736 0.233333349 0.735340655 0.874226451 0.146845892 0.462778926 0.0627254 1 +1.41996527 0.200000018 0.686483979 0.893154919 0.125799567 0.431796879 0.063081 1 +1.44685245 0.166666672 0.635340631 0.910561502 0.104889929 0.399845004 0.0635633 1 +1.46975088 0.13333334 0.581894457 0.926491082 0.084049724 0.366810501 0.0641787 1 +1.47571993 0.0666666701 0.585340679 0.928728878 0.0419559702 0.368378013 0.0635267 1 +1.47770023 0 0.586484015 0.929470181 0 0.36889717 0.0632066 1 +1.47571993 -0.0666666701 0.585340679 0.928728878 -0.0419559702 0.368378013 0.0632066 1 +1.46975088 -0.13333334 0.581894457 0.926491082 -0.084049724 0.366810501 0.0635267 1 +1.44685245 -0.166666687 0.635340631 0.910561502 -0.104889944 0.399845004 0.0627711 1 +1.41996527 -0.200000018 0.686483979 0.893154919 -0.125799567 0.431796879 0.0621446 1 +1.38911736 -0.233333349 0.735340655 0.874226451 -0.146845892 0.462778926 0.0616358 1 +1.35428083 -0.266666681 0.781894445 0.85370189 -0.168099448 0.492885053 0.0612573 1 +1.33138239 -0.233333349 0.835340679 0.837891579 -0.146845892 0.525712907 0.0599553 1 +1.3044951 -0.200000018 0.886484027 0.820524573 -0.125799567 0.557596505 0.0587982 1 +1.27364731 -0.166666672 0.935340703 0.801556587 -0.104889922 0.588646889 0.0577647 1 +1.19177425 -0.166666687 1.0214045 0.755048394 -0.105591655 0.647110701 0.0564605 1 +1.19989884 -0.100000009 1.02609527 0.758484006 -0.0632123351 0.648618698 0.056029 1 +1.20393121 -0.0333333388 1.02842331 0.760184824 -0.0210472979 0.649365842 0.0558851 1 +1.20393121 0.0333333313 1.02842331 0.760184824 0.0210472923 0.649365842 0.056029 1 +1.19989884 0.100000001 1.02609527 0.758484006 0.0632123277 0.648618698 0.0564605 1 +1.19177425 0.166666672 1.0214045 0.755048394 0.105591647 0.647110701 0.0572076 1 +1.22876632 0.200000018 0.976095259 0.776731789 0.12642467 0.61701256 0.0583155 1 +1.26166618 0.233333349 0.928423345 0.79663986 0.147331089 0.58622402 0.0595471 1 +1.29053366 0.266666681 0.878423333 0.814867318 0.168378383 0.554653108 0.0609175 1 +1.31536889 0.300000012 0.826095283 0.831475317 0.18963699 0.522194088 0.0624548 1 +1.33611178 0.333333343 0.771404505 0.846493423 0.211183295 0.488723218 0.0641917 1 +1.37310386 0.300000012 0.726095259 0.867970943 0.18963699 0.458981723 0.0642131 1 +1.40600383 0.266666681 0.678423285 0.887777269 0.168378368 0.428369224 0.0643967 1 +1.43487132 0.233333349 0.628423274 0.906004786 0.147331074 0.396798283 0.0647256 1 +1.45970643 0.200000018 0.576095283 0.922714412 0.12642467 0.36416325 0.0651911 1 +1.48044932 0.166666687 0.521404505 0.937938452 0.105591655 0.330335766 0.0657968 1 +1.48857391 0.100000009 0.526095271 0.940962255 0.0632123351 0.332557082 0.0649234 1 +1.49260628 0.0333333388 0.528423309 0.942459822 0.0210472997 0.33365646 0.0644152 1 +1.49260628 -0.0333333313 0.528423309 0.942459822 -0.0210472941 0.33365646 0.0642456 1 +1.48857391 -0.100000001 0.526095271 0.940962255 -0.0632123277 0.332557082 0.0644152 1 +1.48044932 -0.166666672 0.521404505 0.937938452 -0.105591647 0.330335766 0.0649234 1 +1.45970643 -0.200000018 0.576095283 0.922714412 -0.12642467 0.36416325 0.0641787 1 +1.43487132 -0.233333349 0.628423274 0.906004786 -0.147331074 0.396798283 0.0635633 1 +1.40600383 -0.266666681 0.678423285 0.887777269 -0.168378368 0.428369224 0.063081 1 +1.37310386 -0.300000012 0.726095259 0.867970943 -0.18963699 0.458981723 0.0627254 1 +1.33611178 -0.333333343 0.771404505 0.846493423 -0.211183295 0.488723218 0.062514 1 +1.31536889 -0.300000012 0.826095283 0.831475317 -0.18963699 0.522194088 0.0610134 1 +1.29053366 -0.266666681 0.878423333 0.814867318 -0.168378383 0.554653108 0.0596811 1 +1.26166618 -0.233333349 0.928423345 0.79663986 -0.147331089 0.58622402 0.058487 1 +1.22876632 -0.200000018 0.976095259 0.776731789 -0.12642467 0.61701256 0.0574188 1 +1.14013553 -0.200000003 1.05825758 0.726950765 -0.127520069 0.674745381 0.0562107 1 +1.15056598 -0.133333325 1.06427968 0.731455445 -0.0847647041 0.676600218 0.0556069 1 +1.15675986 -0.0666666627 1.06785572 0.734121025 -0.0423090383 0.677699268 0.0553102 1 +1.15881395 7.4505806e-09 1.06904161 0.735003412 4.72569583e-09 0.678063333 0.0553102 1 +1.15675986 0.0666666776 1.06785572 0.734121025 0.0423090495 0.677699268 0.0556069 1 +1.15056598 0.133333355 1.06427968 0.731455445 0.0847647265 0.676600218 0.0562107 1 +1.14013553 0.200000018 1.05825758 0.726950765 0.127520069 0.674745381 0.0571555 1 +1.17943358 0.233333349 1.0142796 0.749807596 0.148338258 0.644813359 0.0583052 1 +1.21449494 0.266666681 0.967855632 0.770761788 0.169236183 0.61423564 0.0595761 1 +1.24541652 0.300000012 0.919041634 0.789933026 0.190281659 0.582922518 0.0609889 1 +1.27222991 0.333333343 0.867855668 0.807402432 0.211545214 0.55077213 0.0625722 1 +1.29490364 0.366666675 0.814279616 0.823215902 0.233102933 0.51766628 0.0643559 1 +1.31334066 0.400000036 0.758257568 0.83738631 0.255040109 0.483465225 0.0663852 1 +1.3526386 0.366666675 0.714279592 0.859920144 0.233102962 0.454092771 0.0661755 1 +1.38770008 0.333333343 0.66785562 0.880683899 0.211545214 0.423844963 0.0661584 1 +1.41862166 0.300000012 0.619041562 0.899792194 0.190281659 0.392640829 0.0663115 1 +1.44543505 0.266666681 0.567855656 0.917324603 0.169236183 0.360381424 0.0666184 1 +1.46810865 0.233333349 0.514279604 0.933328569 0.148338258 0.326945722 0.0670762 1 +1.4865458 0.200000003 0.458257556 0.947821975 0.127520055 0.292185128 0.0676711 1 +1.49697626 0.133333325 0.464279592 0.95168072 0.0847647041 0.295158952 0.066536 1 +1.50317013 0.0666666627 0.467855632 0.953965247 0.0423090346 0.296917826 0.0658058 1 +1.50522423 -7.4505806e-09 0.469041586 0.954721808 -4.72569583e-09 0.297500014 0.0654487 1 +1.50317013 -0.0666666776 0.467855632 0.953965247 -0.0423090458 0.296917826 0.0654487 1 +1.49697626 -0.133333355 0.464279592 0.95168072 -0.0847647265 0.295158952 0.0658058 1 +1.4865458 -0.200000018 0.458257556 0.947821975 -0.127520055 0.292185128 0.0665342 1 +1.46810865 -0.233333349 0.514279604 0.933328569 -0.148338258 0.326945722 0.0657968 1 +1.44543505 -0.266666681 0.567855656 0.917324603 -0.169236183 0.360381424 0.0651911 1 +1.41862166 -0.300000012 0.619041562 0.899792194 -0.190281659 0.392640829 0.0647256 1 +1.38770008 -0.333333343 0.66785562 0.880683899 -0.211545214 0.423844963 0.0643967 1 +1.3526386 -0.366666675 0.714279592 0.859920144 -0.233102962 0.454092771 0.0642131 1 +1.31334066 -0.400000036 0.758257568 0.83738631 -0.255040109 0.483465225 0.0641917 1 +1.29490364 -0.366666675 0.814279616 0.823215902 -0.233102933 0.51766628 0.0624548 1 +1.27222991 -0.333333343 0.867855668 0.807402432 -0.211545214 0.55077213 0.0609175 1 +1.24541652 -0.300000012 0.919041634 0.789933026 -0.190281659 0.582922518 0.0595471 1 +1.21449494 -0.266666681 0.967855632 0.770761788 -0.169236183 0.61423564 0.0583155 1 +1.17943358 -0.233333349 1.0142796 0.749807596 -0.148338258 0.644813359 0.0572076 1 +1.08348429 -0.233333349 1.09221661 0.696300268 -0.149951488 0.701912105 0.0561183 1 +1.09643066 -0.166666672 1.09969127 0.70202446 -0.106713615 0.704112172 0.0553155 1 +1.10494339 -0.100000001 1.10460603 0.705770612 -0.0638739169 0.705555141 0.0548511 1 +1.10916543 -0.0333333313 1.10704362 0.707623422 -0.0212659407 0.706269741 0.0546954 1 +1.10916543 0.0333333388 1.10704362 0.707623422 0.0212659445 0.706269741 0.0548511 1 +1.10494339 0.100000009 1.10460603 0.705770612 0.0638739243 0.705555141 0.0553155 1 +1.09643066 0.166666687 1.09969127 0.70202446 0.106713623 0.704112172 0.0561183 1 +1.08348429 0.233333349 1.09221661 0.696300268 0.149951488 0.701912105 0.0572993 1 +1.12529814 0.266666681 1.04969132 0.720507801 0.170741796 0.6720981 0.058488 1 +1.16267848 0.300000012 1.00460613 0.742648125 0.191621721 0.641681135 0.0598069 1 +1.195768 0.333333343 0.957043648 0.762873888 0.212659404 0.610572994 0.061267 1 +1.22463548 0.366666675 0.907043695 0.781290829 0.233925372 0.578674138 0.0628992 1 +1.24928093 0.400000036 0.854606092 0.797964573 0.255495667 0.545870304 0.0647403 1 +1.2696358 0.433333367 0.79969126 0.812924445 0.277455389 0.512027621 0.0668312 1 +1.28555691 0.466666698 0.742216647 0.82616204 0.299902946 0.476984859 0.0692405 1 +1.32737076 0.433333367 0.699691236 0.849891186 0.277455419 0.447999477 0.0687269 1 +1.3647511 0.400000036 0.654606044 0.871719897 0.255495667 0.41812247 0.0684625 1 +1.39784062 0.366666675 0.607043624 0.89179194 0.233925372 0.387280643 0.0684058 1 +1.4267081 0.333333343 0.557043672 0.910208642 0.212659404 0.355381727 0.068533 1 +1.45135355 0.300000012 0.504606068 0.927036345 0.191621765 0.32231167 0.0688275 1 +1.47170842 0.266666681 0.449691236 0.94230783 0.170741767 0.287929028 0.0692793 1 +1.48762953 0.233333349 0.392216623 0.956023812 0.149951473 0.252057672 0.0698854 1 +1.5005759 0.166666672 0.399691224 0.96079123 0.106713615 0.255914956 0.0684146 1 +1.50908864 0.100000001 0.404606044 0.963913918 0.0638739094 0.258437693 0.0674159 1 +1.51331067 0.0333333313 0.407043636 0.965459287 0.0212659407 0.25968498 0.0668365 1 +1.51331067 -0.0333333388 0.407043636 0.965459287 -0.0212659445 0.25968498 0.0666471 1 +1.50908864 -0.100000009 0.404606044 0.963913918 -0.0638739169 0.258437693 0.0668365 1 +1.5005759 -0.166666687 0.399691224 0.96079123 -0.106713623 0.255914956 0.0674159 1 +1.48762953 -0.233333349 0.392216623 0.956023812 -0.149951473 0.252057672 0.0684146 1 +1.47170842 -0.266666681 0.449691236 0.94230783 -0.170741767 0.287929028 0.0676711 1 +1.45135355 -0.300000012 0.504606068 0.927036345 -0.191621765 0.32231167 0.0670762 1 +1.4267081 -0.333333343 0.557043672 0.910208642 -0.212659404 0.355381727 0.0666184 1 +1.39784062 -0.366666675 0.607043624 0.89179194 -0.233925372 0.387280643 0.0663115 1 +1.3647511 -0.400000036 0.654606044 0.871719897 -0.255495667 0.41812247 0.0661584 1 +1.32737076 -0.433333367 0.699691236 0.849891186 -0.277455419 0.447999477 0.0661755 1 +1.28555691 -0.466666698 0.742216647 0.82616204 -0.299902946 0.476984859 0.0663852 1 +1.2696358 -0.433333367 0.79969126 0.812924445 -0.277455389 0.512027621 0.0643559 1 +1.24928093 -0.400000036 0.854606092 0.797964573 -0.255495667 0.545870304 0.0625722 1 +1.22463548 -0.366666675 0.907043695 0.781290829 -0.233925372 0.578674138 0.0609889 1 +1.195768 -0.333333343 0.957043648 0.762873888 -0.212659404 0.610572994 0.0595761 1 +1.16267848 -0.300000012 1.00460613 0.742648125 -0.191621721 0.641681135 0.0583052 1 +1.12529814 -0.266666681 1.04969132 0.720507801 -0.170741796 0.6720981 0.0571555 1 +1.02125049 -0.266666681 1.12295258 0.662662804 -0.173033059 0.728654623 0.056216 1 +1.03700662 -0.200000018 1.13204944 0.669815063 -0.129182428 0.731204391 0.0551763 1 +1.04806089 -0.13333334 1.13843155 0.674802423 -0.0858477429 0.732988298 0.0545119 1 +1.05461681 -0.0666666701 1.14221668 0.677748561 -0.0428432748 0.734044552 0.0541883 1 +1.05678964 0 1.14347112 0.678723156 0 0.734394312 0.0541883 1 +1.05461681 0.0666666701 1.14221668 0.677748561 0.0428432748 0.734044552 0.0545119 1 +1.04806089 0.13333334 1.13843155 0.674802423 0.0858477429 0.732988298 0.0551763 1 +1.03700662 0.200000018 1.13204944 0.669815063 0.129182428 0.731204391 0.056216 1 +1.02125049 0.266666681 1.12295258 0.662662804 0.173033059 0.728654623 0.0576955 1 +1.0658741 0.300000012 1.08204937 0.688460946 0.193773627 0.698908746 0.0589289 1 +1.10579586 0.333333373 1.03843164 0.711975515 0.214619368 0.668602526 0.0602896 1 +1.14121938 0.366666675 0.992216647 0.733403623 0.235638008 0.637647152 0.061803 1 +1.17225969 0.400000036 0.943471134 0.752883732 0.256900012 0.605944276 0.0634929 1 +1.19895434 0.433333367 0.892216682 0.770506918 0.278481305 0.573382258 0.0653958 1 +1.22126591 0.466666698 0.838431597 0.786321819 0.300467104 0.539830923 0.0675626 1 +1.23907924 0.5 0.782049417 0.800336182 0.322956026 0.505135119 0.0700576 1 +1.25219059 0.533333361 0.722952604 0.812513828 0.346066117 0.469105095 0.0729754 1 +1.2968142 0.5 0.682049394 0.837627947 0.322956026 0.44054392 0.0720524 1 +1.33673608 0.466666698 0.638431549 0.860668242 0.300467104 0.41105926 0.0714655 1 +1.37215948 0.433333337 0.592216611 0.881817102 0.278481275 0.380587488 0.0711408 1 +1.40319979 0.400000036 0.543471158 0.901205063 0.256900012 0.349044353 0.0710502 1 +1.42989445 0.366666675 0.492216617 0.918920457 0.235638037 0.316322595 0.0711601 1 +1.45220613 0.333333343 0.438431561 0.935014546 0.214619339 0.282287687 0.0714521 1 +1.47001934 0.300000012 0.382049382 0.949503183 0.193773627 0.246770293 0.071914 1 +1.48313069 0.266666681 0.322952598 0.962364852 0.173033059 0.209555522 0.0725475 1 +1.49888682 0.200000018 0.3320494 0.968149066 0.129182428 0.214474708 0.0706452 1 +1.5099411 0.13333334 0.338431567 0.972187698 0.0858477429 0.217901871 0.0693085 1 +1.51649702 0.0666666701 0.342216641 0.974575579 0.0428432822 0.21992524 0.0684564 1 +1.51866984 0 0.34347114 0.975365698 0 0.220594347 0.0680421 1 +1.51649702 -0.0666666701 0.342216641 0.974575579 -0.0428432822 0.21992524 0.0680421 1 +1.5099411 -0.13333334 0.338431567 0.972187698 -0.0858477429 0.217901871 0.0684564 1 +1.49888682 -0.200000018 0.3320494 0.968149066 -0.129182428 0.214474708 0.0693085 1 +1.48313069 -0.266666681 0.322952598 0.962364852 -0.173033059 0.209555522 0.0706452 1 +1.47001934 -0.300000012 0.382049382 0.949503183 -0.193773627 0.246770293 0.0698854 1 +1.45220613 -0.333333373 0.438431561 0.935014546 -0.214619368 0.282287687 0.0692793 1 +1.42989445 -0.366666675 0.492216617 0.918920457 -0.235638037 0.316322595 0.0688275 1 +1.40319979 -0.400000036 0.543471158 0.901205063 -0.256900012 0.349044353 0.068533 1 +1.37215948 -0.433333367 0.592216611 0.881817102 -0.278481305 0.380587488 0.0684058 1 +1.33673608 -0.466666698 0.638431549 0.860668242 -0.300467104 0.41105926 0.0684625 1 +1.2968142 -0.5 0.682049394 0.837627947 -0.322956026 0.44054392 0.0687269 1 +1.25219059 -0.533333361 0.722952604 0.812513828 -0.346066117 0.469105095 0.0692405 1 +1.23907924 -0.5 0.782049417 0.800336182 -0.322956026 0.505135119 0.0668312 1 +1.22126591 -0.466666698 0.838431597 0.786321819 -0.300467104 0.539830923 0.0647403 1 +1.19895434 -0.433333337 0.892216682 0.770506918 -0.278481275 0.573382258 0.0628992 1 +1.17225969 -0.400000036 0.943471134 0.752883732 -0.256900012 0.605944276 0.061267 1 +1.14121938 -0.366666675 0.992216647 0.733403623 -0.235638008 0.637647152 0.0598069 1 +1.10579586 -0.333333343 1.03843164 0.711975515 -0.214619339 0.668602526 0.0584891 1 +1.0658741 -0.300000012 1.08204937 0.688460946 -0.193773627 0.698908746 0.0572993 1 +0.952627957 -0.300000012 1.1500001 0.625430822 -0.196959645 0.755011976 0.0565734 1 +0.971612751 -0.233333349 1.16096091 0.634308934 -0.152329654 0.757923245 0.0552292 1 +0.985525548 -0.166666687 1.16899347 0.640764892 -0.108362645 0.76005125 0.0543267 1 +0.994654477 -0.100000009 1.17426407 0.644978166 -0.0648444444 0.761444986 0.053805 1 +0.999176681 -0.0333333388 1.176875 0.647058666 -0.0215863977 0.762134612 0.053633 1 +0.999176681 0.0333333313 1.176875 0.647058666 0.0215863939 0.762134612 0.053805 1 +0.994654477 0.100000001 1.17426407 0.644978166 0.0648444444 0.761444986 0.0543267 1 +0.985525548 0.166666672 1.16899347 0.640764892 0.108362637 0.76005125 0.0552292 1 +0.971612751 0.233333349 1.16096091 0.634308934 0.152329654 0.757923245 0.0565734 1 +0.952627957 0.300000012 1.1500001 0.625430822 0.196959645 0.755011976 0.0584452 1 +1.00048029 0.333333343 1.11096096 0.65315491 0.217613786 0.725281239 0.0597111 1 +1.04326069 0.366666675 1.06899357 0.678302765 0.238397762 0.69503361 0.0611159 1 +1.08125699 0.400000036 1.0242641 0.701135039 0.259377778 0.664178312 0.0626769 1 +1.11464679 0.433333337 0.976874948 0.72183615 0.280623138 0.632616222 0.0644291 1 +1.14351428 0.466666698 0.926874936 0.740530431 0.302209526 0.600236595 0.0664077 1 +1.16785955 0.5 0.874264121 0.757292032 0.324222207 0.566911697 0.0686635 1 +1.18759823 0.533333361 0.818993568 0.772147596 0.346760422 0.532489777 0.0712682 1 +1.20255291 0.566666722 0.760960937 0.785076261 0.36994347 0.496786743 0.0743177 1 +1.2124356 0.600000024 0.700000048 0.796002924 0.393919289 0.459572494 0.0779568 1 +1.26028788 0.566666722 0.660960913 0.822768033 0.36994347 0.43150261 0.0764467 1 +1.3030684 0.533333361 0.618993521 0.847223401 0.346760392 0.402454525 0.0754048 1 +1.34106469 0.5 0.57426405 0.869605899 0.324222207 0.37237832 0.0747276 1 +1.37445438 0.466666698 0.526874959 0.890085399 0.302209526 0.341199905 0.0743506 1 +1.40332186 0.433333367 0.476874918 0.9087798 0.280623138 0.308820307 0.0742253 1 +1.42766726 0.400000006 0.424264073 0.925762773 0.259377748 0.275111645 0.074329 1 +1.44740593 0.366666675 0.368993521 0.941068172 0.238397762 0.239910617 0.0746373 1 +1.4623605 0.333333343 0.310960919 0.954689384 0.217613786 0.203008145 0.075144 1 +1.47224331 0.300000012 0.25 0.966575027 0.196959645 0.164133027 0.0758458 1 +1.4912281 0.233333349 0.260960877 0.973535359 0.152329654 0.170366049 0.0733538 1 +1.50514078 0.166666687 0.268993437 0.978606105 0.108362645 0.174893022 0.0715697 1 +1.51426983 0.100000009 0.274263978 0.981919706 0.0648444444 0.177844927 0.0703677 1 +1.51879191 0.0333333388 0.2768749 0.983557224 0.0215863977 0.179301918 0.0696725 1 +1.51879191 -0.0333333313 0.2768749 0.983557224 -0.0215863939 0.179301918 0.0694444 1 +1.51426983 -0.100000001 0.274263978 0.981919706 -0.0648444369 0.177844927 0.0696725 1 +1.50514078 -0.166666672 0.268993437 0.978606105 -0.108362637 0.174893022 0.0703677 1 +1.4912281 -0.233333349 0.260960877 0.973535359 -0.152329654 0.170366049 0.0715697 1 +1.47224331 -0.300000012 0.25 0.966575027 -0.196959645 0.164133027 0.0733538 1 +1.4623605 -0.333333343 0.310960919 0.954689384 -0.217613786 0.203008145 0.0725475 1 +1.44740593 -0.366666675 0.368993521 0.941068172 -0.238397762 0.239910617 0.071914 1 +1.42766726 -0.400000036 0.424264073 0.925762773 -0.259377778 0.275111645 0.0714521 1 +1.40332186 -0.433333337 0.476874918 0.9087798 -0.280623138 0.308820307 0.0711601 1 +1.37445438 -0.466666698 0.526874959 0.890085399 -0.302209526 0.341199905 0.0710502 1 +1.34106469 -0.5 0.57426405 0.869605899 -0.324222207 0.37237832 0.0711408 1 +1.3030684 -0.533333361 0.618993521 0.847223401 -0.346760392 0.402454525 0.0714655 1 +1.26028788 -0.566666722 0.660960913 0.822768033 -0.36994347 0.43150261 0.0720524 1 +1.2124356 -0.600000024 0.700000048 0.796002924 -0.393919289 0.459572494 0.0729754 1 +1.20255291 -0.566666722 0.760960937 0.785076261 -0.36994347 0.496786743 0.0700576 1 +1.18759823 -0.533333361 0.818993568 0.772147596 -0.346760422 0.532489777 0.0675626 1 +1.16785955 -0.5 0.874264121 0.757292032 -0.324222207 0.566911697 0.0653976 1 +1.14351428 -0.466666698 0.926874936 0.740530431 -0.302209526 0.600236595 0.0634929 1 +1.11464679 -0.433333367 0.976874948 0.72183615 -0.280623138 0.632616222 0.061803 1 +1.08125699 -0.400000006 1.0242641 0.701135039 -0.259377778 0.664178312 0.0602896 1 +1.04326069 -0.366666675 1.06899357 0.678302765 -0.238397762 0.69503361 0.0589289 1 +1.00048029 -0.333333343 1.11096096 0.65315491 -0.217613786 0.725281239 0.0576955 1 +0.876437306 -0.333333373 1.17267799 0.583717525 -0.222003937 0.781017303 0.0573024 1 +0.89927125 -0.266666681 1.18586123 0.5947662 -0.176369831 0.784313023 0.0555501 1 +0.916505456 -0.200000018 1.19581139 0.603023231 -0.131591856 0.786795139 0.0543311 1 +0.928555012 -0.133333355 1.20276821 0.608755231 -0.0874125734 0.788527846 0.0535606 1 +0.935685873 -0.0666666776 1.20688522 0.612131715 -0.0436137691 0.789552093 0.0531897 1 +0.938046813 -7.4505806e-09 1.20824826 0.613247216 -4.87080998e-09 0.789891124 0.0531897 1 +0.935685873 0.0666666627 1.20688522 0.612131715 0.0436137617 0.789552093 0.0535618 1 +0.928555012 0.133333325 1.20276821 0.608755231 0.087412551 0.788527846 0.0543311 1 +0.916505456 0.200000003 1.19581139 0.603023231 0.131591842 0.786795139 0.0555501 1 +0.89927125 0.266666681 1.18586123 0.5947662 0.176369831 0.784313023 0.0573024 1 +0.876437306 0.333333343 1.17267799 0.583717525 0.222003922 0.781017303 0.0597391 1 +0.928138793 0.366666675 1.13586128 0.613858759 0.242508501 0.751243651 0.0610007 1 +0.974240541 0.400000036 1.09581137 0.641010523 0.263183713 0.720999181 0.0624262 1 +1.01515758 0.433333367 1.05276823 0.665531397 0.284090817 0.690188706 0.0640298 1 +1.05115592 0.466666698 1.00688529 0.687672973 0.305296361 0.658710837 0.0658394 1 +1.08238447 0.5 0.958248258 0.707607746 0.326874495 0.626453817 0.0679008 1 +1.10889101 0.533333361 0.906885207 0.725443661 0.348910123 0.59329015 0.0702625 1 +1.13062763 0.566666722 0.852768242 0.741232812 0.371503353 0.559069812 0.0730008 1 +1.14744556 0.600000024 0.795811415 0.754972398 0.39477554 0.523611486 0.0762271 1 +1.15907896 0.633333385 0.735861242 0.766599536 0.418878347 0.486688912 0.0800906 1 +1.1651125 0.666666687 0.672677994 0.775978625 0.444007844 0.448011458 0.0848333 1 +1.21681392 0.633333385 0.635861218 0.804784715 0.418878376 0.420550257 0.0824019 1 +1.26291573 0.600000024 0.595811367 0.830947042 0.39477554 0.39201957 0.08068 1 +1.30383277 0.566666722 0.552768171 0.854785085 0.371503353 0.362391561 0.0794901 1 +1.33983111 0.533333361 0.506885231 0.876526177 0.348910123 0.33160758 0.0787147 1 +1.37105954 0.5 0.458248228 0.896328866 0.326874524 0.299579352 0.0782822 1 +1.3975662 0.466666698 0.406885207 0.914296806 0.305296361 0.266186923 0.0781418 1 +1.41930282 0.433333337 0.352768183 0.93048656 0.284090787 0.231272742 0.0782662 1 +1.43612075 0.400000036 0.295811385 0.944908917 0.263183713 0.19463183 0.0786373 1 +1.44775414 0.366666675 0.235861197 0.957525492 0.242508501 0.155995473 0.079248 1 +1.45378768 0.333333373 0.172677964 0.968239605 0.222003922 0.115005545 0.0801062 1 +1.47662163 0.266666681 0.1858612 0.976618052 0.176369816 0.122926146 0.0767544 1 +1.49385583 0.200000018 0.195811361 0.982896209 0.131591856 0.128835887 0.074341 1 +1.50590539 0.133333355 0.202768177 0.987262726 0.0874125659 0.132933617 0.0726666 1 +1.51303625 0.0666666776 0.206885189 0.989838064 0.0436137691 0.135345623 0.0716081 1 +1.51539719 7.4505806e-09 0.208248228 0.990689278 4.87080909e-09 0.13614206 0.0710955 1 +1.51303625 -0.0666666627 0.206885189 0.989838064 -0.0436137617 0.135345623 0.0710955 1 +1.50590539 -0.133333325 0.202768177 0.987262726 -0.0874125436 0.132933617 0.0716081 1 +1.49385583 -0.200000003 0.195811361 0.982896209 -0.131591842 0.128835887 0.0726674 1 +1.47662163 -0.266666681 0.1858612 0.976618052 -0.176369816 0.122926146 0.074341 1 +1.45378768 -0.333333343 0.172677964 0.968239605 -0.222003907 0.115005545 0.0767544 1 +1.44775414 -0.366666675 0.235861197 0.957525492 -0.242508501 0.155995473 0.0758458 1 +1.43612075 -0.400000036 0.295811385 0.944908917 -0.263183713 0.19463183 0.075144 1 +1.41930282 -0.433333367 0.352768183 0.93048656 -0.284090817 0.231272742 0.0746373 1 +1.3975662 -0.466666698 0.406885207 0.914296806 -0.305296361 0.266186923 0.074329 1 +1.37105954 -0.5 0.458248228 0.896328866 -0.326874524 0.299579352 0.0742253 1 +1.33983111 -0.533333361 0.506885231 0.876526177 -0.348910123 0.33160758 0.0743506 1 +1.30383277 -0.566666722 0.552768171 0.854785085 -0.371503353 0.362391561 0.0747276 1 +1.26291573 -0.600000024 0.595811367 0.830947042 -0.39477554 0.39201957 0.0754048 1 +1.21681392 -0.633333385 0.635861218 0.804784715 -0.418878376 0.420550257 0.0764467 1 +1.1651125 -0.666666687 0.672677994 0.775978625 -0.444007844 0.448011458 0.0779568 1 +1.15907896 -0.633333385 0.735861242 0.766599536 -0.418878347 0.486688912 0.0743177 1 +1.14744556 -0.600000024 0.795811415 0.754972398 -0.39477554 0.523611486 0.0712682 1 +1.13062763 -0.566666722 0.852768242 0.741232812 -0.371503353 0.559069812 0.0686635 1 +1.10889101 -0.533333361 0.906885207 0.725443661 -0.348910123 0.59329015 0.0664077 1 +1.08238447 -0.5 0.958248258 0.707607746 -0.326874495 0.626453817 0.0644291 1 +1.05115592 -0.466666698 1.00688529 0.687672973 -0.305296361 0.658710837 0.0626769 1 +1.01515758 -0.433333337 1.05276823 0.665531397 -0.284090817 0.690188706 0.0611159 1 +0.974240541 -0.400000036 1.09581137 0.641010523 -0.263183713 0.720999181 0.0597111 1 +0.928138793 -0.366666675 1.13586128 0.613858759 -0.242508501 0.751243651 0.0584452 1 +0.7908566 -0.366666704 1.18993473 0.536147118 -0.248575151 0.806694984 0.0586215 1 +0.818513989 -0.300000012 1.2059027 0.550073862 -0.201611891 0.810414374 0.0562679 1 +0.839776754 -0.233333349 1.21817875 0.560645461 -0.155776262 0.813271344 0.0546147 1 +0.85526979 -0.166666687 1.22712362 0.568276584 -0.110740229 0.815351605 0.0535183 1 +0.865397453 -0.100000016 1.23297083 0.573232889 -0.066239275 0.81671077 0.0528895 1 +0.870403767 -0.0333333462 1.2358613 0.57567358 -0.0220462345 0.817382336 0.0526839 1 +0.870403767 0.0333333239 1.2358613 0.57567358 0.0220462196 0.817382336 0.0528895 1 +0.865397453 0.099999994 1.23297083 0.573232889 0.0662392601 0.81671077 0.0535183 1 +0.85526979 0.166666657 1.22712362 0.568276584 0.110740207 0.815351605 0.0546147 1 +0.839776754 0.233333334 1.21817875 0.560645461 0.155776247 0.813271344 0.0562679 1 +0.818513989 0.300000012 1.2059027 0.550073862 0.201611891 0.810414374 0.0586215 1 +0.7908566 0.366666675 1.18993473 0.536147118 0.248575121 0.806694984 0.0619322 1 +0.847381473 0.400000006 1.15590262 0.569473922 0.268815845 0.776812375 0.0631018 1 +0.89751178 0.433333337 1.11817873 0.599190116 0.289298773 0.746510148 0.0644856 1 +0.941872358 0.466666698 1.07712364 0.625818908 0.310072631 0.715685427 0.0660971 1 +0.980867624 0.5 1.03297091 0.649719417 0.331196278 0.684232235 0.0679518 1 +1.0147413 0.533333361 0.985861242 0.671136558 0.352739662 0.652035654 0.0700899 1 +1.0436089 0.566666722 0.93586123 0.690229118 0.37478587 0.618966281 0.0725746 1 +1.06747019 0.600000024 0.88297087 0.707084298 0.397435546 0.584873319 0.0754823 1 +1.08620989 0.633333385 0.827123642 0.721722782 0.420812875 0.54957515 0.0789327 1 +1.09958434 0.666666687 0.768178701 0.734096289 0.445075035 0.512845755 0.0831049 1 +1.10718918 0.700000048 0.705902636 0.744075 0.470427781 0.47439453 0.0882712 1 +1.10839927 0.733333349 0.639934659 0.751419485 0.497150242 0.433832288 0.0948841 1 +1.16492414 0.700000048 0.605902612 0.78287518 0.470427781 0.407190561 0.0908404 1 +1.21505451 0.666666687 0.568178654 0.811185598 0.445075005 0.379323155 0.087999 1 +1.25941503 0.633333385 0.52712357 0.83680737 0.420812845 0.350242674 0.085998 1 +1.2984103 0.600000024 0.482970864 0.860057294 0.397435546 0.319916308 0.0846262 1 +1.33228397 0.566666722 0.4358612 0.881155074 0.37478593 0.288272858 0.0837458 1 +1.36115158 0.533333361 0.385861218 0.900247693 0.352739632 0.255203515 0.0832685 1 +1.38501287 0.5 0.332970858 0.917422235 0.331196278 0.220557421 0.0831523 1 +1.40375257 0.466666698 0.2771236 0.932711244 0.31007266 0.184132382 0.0833609 1 +1.41712713 0.433333367 0.218178645 0.946091771 0.289298773 0.145658791 0.0838854 1 +1.42473173 0.400000036 0.155902535 0.957476199 0.268815875 0.10477268 0.0847397 1 +1.42594194 0.366666704 0.0899346247 0.966691852 0.248575151 0.0609695725 0.085957 1 +1.45359933 0.300000012 0.10590259 0.976876378 0.201611891 0.0711707398 0.0812364 1 +1.4748621 0.233333349 0.118178643 0.984636426 0.155776277 0.0788975433 0.0778803 1 +1.49035513 0.166666687 0.127123579 0.990253508 0.110740229 0.0844661519 0.0755257 1 +1.5004828 0.100000016 0.132970795 0.993908703 0.066239275 0.0880788714 0.0739637 1 +1.50548911 0.0333333462 0.135861203 0.995710671 0.0220462363 0.0898568109 0.0730694 1 +1.50548911 -0.0333333239 0.135861203 0.995710671 -0.0220462214 0.0898568109 0.0727782 1 +1.5004828 -0.099999994 0.132970795 0.993908703 -0.0662392601 0.0880788714 0.0730694 1 +1.49035513 -0.166666657 0.127123579 0.990253508 -0.110740207 0.0844661519 0.0739637 1 +1.4748621 -0.233333334 0.118178643 0.984636426 -0.155776262 0.0788975433 0.0755257 1 +1.45359933 -0.300000012 0.10590259 0.976876378 -0.201611891 0.0711707398 0.0778803 1 +1.42594194 -0.366666675 0.0899346247 0.966691852 -0.248575121 0.0609695725 0.0812364 1 +1.42473185 -0.400000006 0.155902594 0.957476258 -0.268815845 0.104772724 0.080107 1 +1.41712713 -0.433333337 0.218178645 0.946091771 -0.289298743 0.145658791 0.0792473 1 +1.40375257 -0.466666698 0.2771236 0.932711244 -0.31007266 0.184132382 0.0786373 1 +1.38501287 -0.5 0.332970858 0.917422235 -0.331196278 0.220557421 0.0782662 1 +1.36115158 -0.533333361 0.385861218 0.900247693 -0.352739632 0.255203515 0.0781418 1 +1.33228397 -0.566666722 0.4358612 0.881155074 -0.37478593 0.288272858 0.0782822 1 +1.2984103 -0.600000024 0.482970864 0.860057294 -0.397435546 0.319916308 0.0787147 1 +1.25941503 -0.633333385 0.52712357 0.83680737 -0.420812845 0.350242674 0.0794901 1 +1.21505451 -0.666666687 0.568178654 0.811185598 -0.445075005 0.379323155 0.08068 1 +1.16492414 -0.700000048 0.605902612 0.78287518 -0.470427781 0.407190561 0.0824019 1 +1.10839927 -0.733333349 0.639934659 0.751419485 -0.497150242 0.433832288 0.0848333 1 +1.10718918 -0.700000048 0.705902636 0.744075 -0.470427781 0.47439453 0.0800906 1 +1.09958434 -0.666666687 0.768178701 0.734096289 -0.445075035 0.512845755 0.0762271 1 +1.08620989 -0.633333385 0.827123642 0.721722782 -0.420812875 0.54957515 0.0730008 1 +1.06747019 -0.600000024 0.88297087 0.707084298 -0.397435546 0.584873319 0.0702625 1 +1.0436089 -0.566666722 0.93586123 0.690229118 -0.37478587 0.618966281 0.0679008 1 +1.0147413 -0.533333361 0.985861242 0.671136558 -0.352739662 0.652035654 0.0658394 1 +0.980867624 -0.5 1.03297091 0.649719417 -0.331196278 0.684232235 0.0640298 1 +0.941872358 -0.466666698 1.07712364 0.625818908 -0.310072631 0.715685427 0.0624262 1 +0.89751178 -0.433333367 1.11817873 0.599190056 -0.289298773 0.746510088 0.0610007 1 +0.847381353 -0.400000036 1.15590262 0.569473863 -0.268815875 0.776812375 0.0597391 1 +0.692820191 -0.400000006 1.20000005 0.480384409 -0.277350128 0.832050383 0.0609919 1 +0.72698009 -0.333333343 1.21972215 0.498430669 -0.228539348 0.836263537 0.05765 1 +0.753434896 -0.266666651 1.23499584 0.512174666 -0.181276321 0.83953321 0.0553296 1 +0.773205042 -0.199999988 1.24641025 0.522318482 -0.135104761 0.841979861 0.0537607 1 +0.78693676 -0.133333325 1.25433826 0.529301643 -0.0896813497 0.84368068 0.0527846 1 +0.795030355 -0.0666666552 1.25901103 0.533394098 -0.0447273478 0.844683528 0.0523136 1 +0.797704816 1.49011612e-08 1.26055515 0.534742594 9.98901495e-09 0.845014989 0.0523136 1 +0.795030355 0.066666685 1.25901103 0.533394098 0.0447273701 0.844683528 0.0527834 1 +0.78693676 0.133333355 1.25433826 0.529301643 0.089681372 0.84368068 0.0537607 1 +0.773204923 0.200000018 1.24641013 0.522318482 0.135104805 0.84197998 0.0553296 1 +0.753434896 0.26666671 1.23499584 0.512174666 0.181276366 0.83953321 0.0576479 1 +0.72698009 0.333333373 1.21972215 0.498430669 0.228539377 0.836263537 0.0609919 1 +0.692820191 0.400000036 1.20000005 0.480384409 0.277350128 0.832050383 0.0658711 1 +0.755847573 0.433333337 1.1697222 0.518222749 0.29710114 0.801982641 0.0666551 1 +0.811169863 0.466666698 1.13499582 0.551422119 0.317233622 0.771554589 0.0678261 1 +0.859807551 0.5 1.09641016 0.58082056 0.337761968 0.740651309 0.0693318 1 +0.902406812 0.533333361 1.05433822 0.606967986 0.358725429 0.709158599 0.071171 1 +0.93936789 0.566666722 1.00901103 0.630231619 0.380182564 0.676955938 0.0733684 1 +0.970909894 0.600000024 0.960555136 0.650850832 0.402210891 0.643909514 0.075977 1 +0.997102916 0.633333385 0.909011006 0.668966651 0.42490992 0.609864891 0.0790898 1 +1.01787686 0.666666687 0.854338169 0.684634328 0.448406786 0.574636519 0.0828432 1 +1.03301251 0.700000048 0.796410143 0.697824717 0.472866833 0.537994146 0.0874472 1 +1.04210997 0.733333349 0.734995902 0.708412051 0.498509943 0.499640107 0.093238 1 +1.04452276 0.76666671 0.66972214 0.716143668 0.525640547 0.45917359 0.100777 1 +1.03923035 0.800000072 0.599999964 0.720576644 0.554700255 0.416025162 0.111114 1 +1.10225773 0.76666671 0.569722116 0.755727768 0.525640547 0.390611768 0.103741 1 +1.15758014 0.733333349 0.534995854 0.786907017 0.498509884 0.363682806 0.0987829 1 +1.20621765 0.700000048 0.496410102 0.814828992 0.472866833 0.335336924 0.0953467 1 +1.24881697 0.666666687 0.454338163 0.839967012 0.448406786 0.305592477 0.0929648 1 +1.28577805 0.633333385 0.409010977 0.862641811 0.42490992 0.274409711 0.0913613 1 +1.31732011 0.600000024 0.360555112 0.883067429 0.402210891 0.241698638 0.0903733 1 +1.34351313 0.566666722 0.309010983 0.901376903 0.380182564 0.207318664 0.0899039 1 +1.36428702 0.533333361 0.254338175 0.917633295 0.358725429 0.171070442 0.0898966 1 +1.3794229 0.5 0.196410134 0.931833088 0.337761939 0.132679731 0.0903383 1 +1.38852024 0.466666698 0.134995788 0.943897009 0.317233622 0.0917682797 0.0912482 1 +1.39093292 0.433333367 0.0697220936 0.953648686 0.29710117 0.0478027239 0.0926967 1 +1.3856405 0.400000006 -6.58440484e-08 0.960768878 0.277350128 -4.56546374e-08 0.0948363 1 +1.4198004 0.333333343 0.0197220985 0.973440766 0.228539348 0.0135218268 0.0876204 1 +1.44625521 0.266666651 0.0349957868 0.983144403 0.181276321 0.0237896554 0.082678 1 +1.46602535 0.199999988 0.0464101359 0.990335286 0.13510479 0.0313511603 0.0792511 1 +1.47975707 0.133333325 0.0543381497 0.995299637 0.0896813497 0.036548391 0.0769337 1 +1.48785067 0.0666666552 0.0590109751 0.998214424 0.0447273478 0.039591074 0.0754902 1 +1.49052513 -1.49011612e-08 0.060555093 0.999175787 -9.98901584e-09 0.0405931994 0.0747978 1 +1.48785067 -0.066666685 0.0590109751 0.998214424 -0.0447273701 0.039591074 0.0747978 1 +1.47975707 -0.133333355 0.0543381497 0.995299637 -0.089681372 0.036548391 0.0754902 1 +1.46602523 -0.200000018 0.0464100763 0.990335226 -0.135104805 0.0313511193 0.076933 1 +1.44625521 -0.26666671 0.0349957868 0.983144403 -0.181276366 0.0237896554 0.0792518 1 +1.4198004 -0.333333373 0.0197220985 0.973440766 -0.228539377 0.0135218268 0.082678 1 +1.3856405 -0.400000036 -6.58440484e-08 0.960768878 -0.277350128 -4.56546374e-08 0.0876198 1 +1.39093292 -0.433333337 0.0697220936 0.953648686 -0.29710114 0.0478027239 0.0859584 1 +1.38852024 -0.466666698 0.134995788 0.943897009 -0.317233622 0.0917682797 0.0847383 1 +1.3794229 -0.5 0.196410134 0.931833088 -0.337761939 0.132679731 0.0838847 1 +1.36428702 -0.533333361 0.254338175 0.917633295 -0.358725429 0.171070442 0.0833609 1 +1.34351313 -0.566666722 0.309010983 0.901376903 -0.380182564 0.207318664 0.0831523 1 +1.31732011 -0.600000024 0.360555112 0.883067429 -0.402210891 0.241698638 0.0832685 1 +1.28577805 -0.633333385 0.409010977 0.862641811 -0.42490992 0.274409711 0.0837458 1 +1.24881697 -0.666666687 0.454338163 0.839967012 -0.448406786 0.305592477 0.0846262 1 +1.20621765 -0.700000048 0.496410102 0.814828992 -0.472866833 0.335336924 0.085998 1 +1.15758014 -0.733333349 0.534995854 0.786907017 -0.498509884 0.363682806 0.087999 1 +1.10225773 -0.76666671 0.569722116 0.755727768 -0.525640547 0.390611768 0.0908404 1 +1.03923035 -0.800000072 0.599999964 0.720576644 -0.554700255 0.416025162 0.0948841 1 +1.04452276 -0.76666671 0.66972214 0.716143668 -0.525640547 0.45917359 0.0882712 1 +1.04210997 -0.733333349 0.734995902 0.708412051 -0.498509943 0.499640107 0.0831049 1 +1.03301251 -0.700000048 0.796410143 0.697824717 -0.472866833 0.537994146 0.0789327 1 +1.01787686 -0.666666687 0.854338169 0.684634328 -0.448406786 0.574636519 0.0754823 1 +0.997102916 -0.633333385 0.909011006 0.668966651 -0.42490992 0.609864891 0.0725746 1 +0.970909894 -0.600000024 0.960555136 0.650850832 -0.402210891 0.643909514 0.0700899 1 +0.93936789 -0.566666722 1.00901103 0.630231619 -0.380182564 0.676955938 0.0679518 1 +0.902406812 -0.533333361 1.05433822 0.606967986 -0.358725429 0.709158599 0.0660971 1 +0.859807551 -0.5 1.09641016 0.58082056 -0.337761968 0.740651309 0.0644856 1 +0.811169863 -0.466666698 1.13499582 0.551422119 -0.317233622 0.771554589 0.0631018 1 +0.755847573 -0.433333367 1.1697222 0.518222749 -0.29710117 0.801982641 0.0619322 1 +0.576386809 -0.433333337 1.19944382 0.411845148 -0.309629291 0.857037485 0.0656216 1 +0.620432734 -0.366666675 1.22487366 0.436567724 -0.258005142 0.861882806 0.0603361 1 +0.654239476 -0.300000012 1.24439204 0.455108255 -0.208688855 0.865635812 0.0568374 1 +0.679750144 -0.233333334 1.25912058 0.468861312 -0.160942927 0.868485212 0.0544944 1 +0.698112547 -0.166666657 1.2697221 0.47863856 -0.114269666 0.870544374 0.0529842 1 +0.710022867 -0.099999994 1.27659857 0.484927177 -0.0682974011 0.87188369 0.0521366 1 +0.715885103 -0.0333333239 1.27998316 0.488007247 -0.0227227863 0.872543752 0.0518614 1 +0.715885103 0.0333333462 1.27998316 0.488007247 0.0227228012 0.872543752 0.0521366 1 +0.710022867 0.100000016 1.27659857 0.484927177 0.068297416 0.87188369 0.0529842 1 +0.698112547 0.166666687 1.2697221 0.47863856 0.114269689 0.870544374 0.0544944 1 +0.679750144 0.233333349 1.25912058 0.468861312 0.160942927 0.868485212 0.0568374 1 +0.654239476 0.300000012 1.24439204 0.455108255 0.208688855 0.865635812 0.0603361 1 +0.620432734 0.366666704 1.22487366 0.436567724 0.258005142 0.861882806 0.0656207 1 +0.576386809 0.433333367 1.19944382 0.411845148 0.309629291 0.857037485 0.0740749 1 +0.649300218 0.466666698 1.17487371 0.456880331 0.328370184 0.82670033 0.0733351 1 +0.711974502 0.5 1.14439213 0.495270461 0.347814739 0.7960729 0.0736865 1 +0.766352654 0.533333361 1.10912061 0.528595865 0.367869556 0.76502192 0.0747428 1 +0.81358248 0.566666722 1.06972206 0.557806849 0.388516963 0.733420789 0.0763616 1 +0.854360461 0.600000024 1.02659857 0.583505988 0.409784406 0.701140106 0.078509 1 +0.88909018 0.633333385 0.979983151 0.606078327 0.431733102 0.668038607 0.0812173 1 +0.917957842 0.666666687 0.929983199 0.625756979 0.454455853 0.633954465 0.084574 1 +0.94096297 0.700000048 0.876598597 0.642653227 0.478081822 0.598694026 0.0887412 1 +0.957920194 0.733333349 0.819722116 0.656767368 0.502786577 0.562016249 0.0939859 1 +0.968425274 0.76666671 0.759120643 0.667976499 0.528812468 0.523607492 0.100753 1 +0.971782148 0.800000072 0.694392025 0.676000297 0.556503654 0.483039558 0.109837 1 +0.96684289 0.833333373 0.624873698 0.680319369 0.586375296 0.439692587 0.1228 1 +0.951664507 0.866666734 0.549443781 0.679991961 0.619258583 0.392593563 0.143336 1 +1.02457798 0.833333373 0.524873674 0.720944583 0.586375296 0.369327515 0.126463 1 +1.08725226 0.800000072 0.494392008 0.756324708 0.556503654 0.343913645 0.116452 1 +1.14163041 0.76666671 0.459120601 0.787445664 0.528812468 0.316680878 0.109959 1 +1.1888603 0.733333349 0.41972211 0.815104067 0.502786577 0.287769049 0.105592 1 +1.2296381 0.700000048 0.376598567 0.839810908 0.478081852 0.257207036 0.10265 1 +1.26436806 0.666666687 0.329983175 0.861899137 0.454455823 0.224944159 0.100755 1 +1.29323542 0.633333385 0.279983103 0.881577611 0.431733102 0.190859944 0.0996925 1 +1.31624067 0.600000024 0.226598591 0.898958147 0.409784406 0.154760942 0.0993554 1 +1.33319783 0.566666722 0.169722036 0.914064467 0.388516933 0.116364487 0.0997069 1 +1.34370303 0.533333361 0.10912057 0.926826298 0.367869526 0.0752664953 0.100786 1 +1.34705985 0.50000006 0.0443919711 0.937054634 0.347814798 0.0308803655 0.102738 1 +1.34212065 0.466666669 -0.0251263436 0.944383562 0.328370154 -0.0176801588 0.105888 1 +1.32694221 0.433333337 -0.100556247 0.948138833 0.309629291 -0.0718503669 0.110988 1 +1.37098813 0.366666675 -0.0751263425 0.964696229 0.258005112 -0.052862674 0.0979935 1 +1.40479493 0.300000012 -0.0556080267 0.97721678 0.208688855 -0.0386825837 0.08988 1 +1.43030548 0.233333334 -0.0408794209 0.986560881 0.160942927 -0.0281968005 0.0845126 1 +1.448668 0.166666657 -0.0302779004 0.993232906 0.114269666 -0.020759074 0.0809192 1 +1.4605782 0.099999994 -0.0234014317 0.997537017 0.0682974011 -0.0159825701 0.0786055 1 +1.46644044 0.0333333239 -0.0200169012 0.999648631 0.0227227863 -0.0136451973 0.0773043 1 +1.46644044 -0.0333333462 -0.0200169012 0.999648631 -0.0227228012 -0.0136451973 0.0768841 1 +1.4605782 -0.100000016 -0.0234014317 0.997537017 -0.068297416 -0.0159825701 0.0773043 1 +1.448668 -0.166666687 -0.0302779004 0.993232906 -0.114269689 -0.020759074 0.0786055 1 +1.43030548 -0.233333349 -0.0408794209 0.986560881 -0.160942927 -0.0281968005 0.0809192 1 +1.40479493 -0.300000012 -0.0556080267 0.97721678 -0.208688855 -0.0386825837 0.0845126 1 +1.37098813 -0.366666704 -0.0751263425 0.964696229 -0.258005142 -0.052862674 0.08988 1 +1.32694221 -0.433333367 -0.100556247 0.948138833 -0.309629291 -0.0718503669 0.0979929 1 +1.34212065 -0.466666698 -0.0251263436 0.944383562 -0.328370154 -0.0176801588 0.0948363 1 +1.34705985 -0.5 0.0443920307 0.937054515 -0.347814739 0.0308804046 0.092696 1 +1.34370303 -0.533333361 0.10912057 0.926826298 -0.367869526 0.0752664953 0.0912482 1 +1.33319783 -0.566666722 0.169722036 0.914064467 -0.388516933 0.116364487 0.0903383 1 +1.31624067 -0.600000024 0.226598591 0.898958147 -0.409784406 0.154760942 0.0898966 1 +1.29323542 -0.633333385 0.279983103 0.881577611 -0.431733102 0.190859944 0.0899039 1 +1.26436806 -0.666666687 0.329983175 0.861899137 -0.454455823 0.224944159 0.0903733 1 +1.2296381 -0.700000048 0.376598567 0.839810908 -0.478081852 0.257207036 0.0913613 1 +1.1888603 -0.733333349 0.41972211 0.815104067 -0.502786577 0.287769049 0.0929648 1 +1.14163041 -0.76666671 0.459120601 0.787445664 -0.528812468 0.316680878 0.0953467 1 +1.08725226 -0.800000072 0.494392008 0.756324708 -0.556503654 0.343913645 0.0987829 1 +1.02457798 -0.833333373 0.524873674 0.720944583 -0.586375296 0.369327515 0.103741 1 +0.951664507 -0.866666734 0.549443781 0.679991961 -0.619258583 0.392593563 0.111114 1 +0.96684289 -0.833333373 0.624873698 0.680319369 -0.586375296 0.439692587 0.100777 1 +0.971782148 -0.800000072 0.694392025 0.676000297 -0.556503654 0.483039558 0.093238 1 +0.968425274 -0.76666671 0.759120643 0.667976499 -0.528812468 0.523607492 0.0874472 1 +0.957920194 -0.733333349 0.819722116 0.656767368 -0.502786577 0.562016249 0.0828432 1 +0.94096297 -0.700000048 0.876598597 0.642653227 -0.478081822 0.598694026 0.0790898 1 +0.917957842 -0.666666687 0.929983199 0.625756979 -0.454455853 0.633954465 0.075977 1 +0.88909018 -0.633333385 0.979983151 0.606078327 -0.431733102 0.668038607 0.0733684 1 +0.854360461 -0.600000024 1.02659857 0.583505988 -0.409784406 0.701140106 0.071171 1 +0.81358248 -0.566666722 1.06972206 0.557806849 -0.388516963 0.733420789 0.0693318 1 +0.766352654 -0.533333361 1.10912061 0.528595865 -0.367869556 0.76502192 0.0678261 1 +0.711974502 -0.50000006 1.14439201 0.495270461 -0.347814769 0.796072841 0.0666551 1 +0.649300218 -0.466666669 1.17487371 0.456880331 -0.328370154 0.82670033 0.0658711 1 +0.426382512 -0.466666698 1.17950547 0.31862089 -0.348723888 0.881403625 0.0770384 1 +0.489635676 -0.400000006 1.21602464 0.357249945 -0.291849613 0.887240827 0.0663025 1 +0.535787344 -0.333333343 1.2426703 0.384434313 -0.239170954 0.891631901 0.0601133 1 +0.570076108 -0.266666681 1.26246691 0.40412429 -0.189038768 0.894956887 0.0562319 1 +0.595053196 -0.200000003 1.27688754 0.418209255 -0.140561983 0.897409141 0.0537629 1 +0.612125516 -0.133333325 1.28674424 0.427716255 -0.0931652561 0.899098992 0.0522828 1 +0.622092724 -0.0666666627 1.29249883 0.433222592 -0.0464263633 0.900090396 0.0515882 1 +0.625371933 7.4505806e-09 1.29439199 0.435027182 5.18284393e-09 0.900417328 0.0515882 1 +0.622092724 0.0666666776 1.29249883 0.433222592 0.0464263745 0.900090396 0.0522828 1 +0.612125516 0.133333355 1.28674424 0.427716255 0.0931652784 0.899098992 0.0537629 1 +0.595053196 0.200000018 1.27688754 0.418209255 0.140561983 0.897409141 0.0562319 1 +0.570076108 0.266666681 1.26246691 0.40412429 0.189038768 0.894956887 0.0601133 1 +0.535787344 0.333333373 1.2426703 0.384434313 0.239170983 0.891631901 0.0663007 1 +0.489635676 0.400000036 1.21602464 0.357249945 0.291849643 0.887240827 0.0770384 1 +0.426382512 0.466666698 1.17950547 0.31862089 0.348723888 0.881403625 0.100344 1 +0.518503189 0.50000006 1.16602468 0.378312349 0.364812016 0.850759566 0.0895587 1 +0.59352231 0.533333361 1.14267039 0.425859869 0.382673532 0.819880664 0.085982 1 +0.656678617 0.566666663 1.11246693 0.465516388 0.401707351 0.788622618 0.0851058 1 +0.710523248 0.600000024 1.07688749 0.499362797 0.421685964 0.756847203 0.0857206 1 +0.756462991 0.633333385 1.03674412 0.528570592 0.442535073 0.72441411 0.087396 1 +0.795297861 0.666666687 0.992498815 0.553841889 0.464263678 0.691171706 0.0900107 1 +0.827444553 0.700000048 0.944392025 0.575594842 0.486940712 0.656947017 0.0936092 1 +0.853032887 0.733333349 0.892498791 0.594048262 0.510690033 0.621532142 0.0983699 1 +0.871933043 0.76666671 0.83674413 0.609254062 0.535700321 0.584666193 0.104667 1 +0.883728266 0.800000072 0.776887417 0.621092975 0.562247992 0.546004176 0.113183 1 +0.887618601 0.833333373 0.712466896 0.629228711 0.590746164 0.505064487 0.12526 1 +0.882197499 0.866666734 0.642670333 0.632988036 0.62184453 0.461124212 0.143925 1 +0.864913344 0.900000036 0.566024661 0.631061554 0.65666163 0.412985206 0.178323 1 +0.830527723 0.933333397 0.47950542 0.620624602 0.697447777 0.358317822 0.118789 1 +0.92264843 0.900000036 0.466024637 0.673186421 0.65666163 0.340022743 0.183761 1 +0.997667551 0.866666734 0.442670316 0.715839267 0.62184453 0.317621648 0.152746 1 +1.06082368 0.833333373 0.412466854 0.752013028 0.590746164 0.29239586 0.136883 1 +1.11466837 0.800000072 0.376887411 0.783400059 0.562248051 0.26488024 0.127357 1 +1.16060817 0.76666671 0.3367441 0.810962796 0.535700321 0.235296413 0.121288 1 +1.1994431 0.733333349 0.292498767 0.835286796 0.510690033 0.203694835 0.117425 1 +1.23158979 0.700000048 0.244391993 0.856730163 0.486940682 0.170006275 0.115158 1 +1.25717807 0.666666687 0.192498773 0.875493169 0.464263678 0.134055287 0.11419 1 +1.27607822 0.633333385 0.136744097 0.891646326 0.442535073 0.0955485031 0.114422 1 +1.28787363 0.600000024 0.0768874511 0.905130267 0.421685934 0.054037258 0.115938 1 +1.29176378 0.566666722 0.0124668283 0.91572541 0.401707411 0.00883767754 0.119067 1 +1.28634274 0.533333361 -0.0573297217 0.922967434 0.382673532 -0.0411348119 0.124635 1 +1.26905859 0.5 -0.133975372 0.925935626 0.364812016 -0.0977516547 0.13482 1 +1.2346729 0.466666698 -0.220494613 0.922628343 0.348723888 -0.164767995 0.157429 1 +1.29792607 0.400000006 -0.183975384 0.94699806 0.291849613 -0.134232864 0.120117 1 +1.34407771 0.333333343 -0.157329723 0.96439302 0.239170954 -0.112886101 0.102962 1 +1.37836647 0.266666681 -0.137533113 0.977117538 0.189038768 -0.0974965841 0.0930835 1 +1.40334368 0.200000003 -0.123112537 0.986283779 0.140561983 -0.0865247026 0.0868948 1 +1.420416 0.133333325 -0.113255836 0.992500663 0.0931652486 -0.0791363195 0.0829626 1 +1.43038321 0.0666666627 -0.107501246 0.996112466 0.0464263633 -0.0748633891 0.080606 1 +1.43366241 -7.4505806e-09 -0.105608024 0.997297823 -5.18284349e-09 -0.0734640509 0.0794984 1 +1.43038321 -0.0666666776 -0.107501246 0.996112466 -0.0464263745 -0.0748633891 0.0794984 1 +1.420416 -0.133333355 -0.113255836 0.992500663 -0.093165271 -0.0791363195 0.080606 1 +1.40334368 -0.200000018 -0.123112537 0.986283779 -0.140561983 -0.0865247026 0.0829619 1 +1.37836647 -0.266666681 -0.137533113 0.977117538 -0.189038768 -0.0974965841 0.0868948 1 +1.34407771 -0.333333373 -0.157329723 0.96439302 -0.239170983 -0.112886101 0.0930835 1 +1.29792607 -0.400000036 -0.183975384 0.94699806 -0.291849643 -0.134232864 0.102961 1 +1.2346729 -0.466666698 -0.220494613 0.922628343 -0.348723888 -0.164767995 0.120117 1 +1.26905859 -0.50000006 -0.133975372 0.925935626 -0.364812046 -0.0977516547 0.110987 1 +1.28634274 -0.533333361 -0.0573297217 0.922967434 -0.382673532 -0.0411348119 0.105888 1 +1.29176402 -0.566666663 0.0124668879 0.91572541 -0.401707321 0.00883771759 0.102739 1 +1.28787363 -0.600000024 0.0768874511 0.905130267 -0.421685934 0.054037258 0.100786 1 +1.27607822 -0.633333385 0.136744097 0.891646326 -0.442535073 0.0955485031 0.0997069 1 +1.25717807 -0.666666687 0.192498773 0.875493169 -0.464263678 0.134055287 0.0993554 1 +1.23158979 -0.700000048 0.244391993 0.856730163 -0.486940682 0.170006275 0.0996925 1 +1.1994431 -0.733333349 0.292498767 0.835286796 -0.510690033 0.203694835 0.100755 1 +1.16060817 -0.76666671 0.3367441 0.810962796 -0.535700321 0.235296413 0.10265 1 +1.11466837 -0.800000072 0.376887411 0.783400059 -0.562248051 0.26488024 0.105592 1 +1.06082368 -0.833333373 0.412466854 0.752013028 -0.590746164 0.29239586 0.109959 1 +0.997667551 -0.866666734 0.442670316 0.715839267 -0.62184453 0.317621648 0.116452 1 +0.92264843 -0.900000036 0.466024637 0.673186421 -0.65666163 0.340022743 0.126463 1 +0.830527723 -0.933333397 0.47950542 0.620624602 -0.697447777 0.358317822 0.143336 1 +0.864913344 -0.900000036 0.566024661 0.631061554 -0.65666163 0.412985206 0.1228 1 +0.882197499 -0.866666734 0.642670333 0.632988036 -0.62184453 0.461124212 0.109837 1 +0.887618601 -0.833333373 0.712466896 0.629228711 -0.590746164 0.505064487 0.100753 1 +0.883728266 -0.800000072 0.776887417 0.621092975 -0.562247992 0.546004176 0.0939859 1 +0.871933043 -0.76666671 0.83674413 0.609254062 -0.535700321 0.584666193 0.0887412 1 +0.853032887 -0.733333349 0.892498791 0.594048262 -0.510690033 0.621532142 0.084574 1 +0.827444553 -0.700000048 0.944392025 0.575594842 -0.486940712 0.656947017 0.0812173 1 +0.795297861 -0.666666687 0.992498815 0.553841889 -0.464263678 0.691171706 0.078509 1 +0.756462991 -0.633333385 1.03674412 0.528570592 -0.442535073 0.72441411 0.0763616 1 +0.710523248 -0.600000024 1.07688749 0.499362797 -0.421685964 0.756847203 0.0747428 1 +0.656678498 -0.566666722 1.11246693 0.465516359 -0.401707411 0.788622677 0.0736865 1 +0.59352231 -0.533333361 1.14267039 0.425859869 -0.382673532 0.819880664 0.0733359 1 +0.518503189 -0.5 1.16602468 0.378312379 -0.364812016 0.850759625 0.0740765 1 +0.302626967 -0.433333397 1.17472184 0.234931335 -0.336399615 0.911944449 0.0870656 1 +0.380994439 -0.366666704 1.21996725 0.286541253 -0.275765538 0.91752243 0.0692784 1 +0.433012545 -0.300000042 1.25 0.319221079 -0.221162975 0.921512246 0.0607881 1 +0.469573259 -0.233333379 1.27110827 0.341504693 -0.169695452 0.924433947 0.05598 1 +0.494850755 -0.166666701 1.28570223 0.356600195 -0.120103642 0.92650491 0.0531639 1 +0.510866523 -0.100000031 1.29494894 0.366038412 -0.07165052 0.927837372 0.0516656 1 +0.518651783 -0.0333333611 1.29944384 0.370591789 -0.0238176566 0.92849046 0.0511937 1 +0.518651783 0.033333309 1.29944384 0.370591789 0.0238176193 0.92849046 0.0516656 1 +0.510866523 0.0999999791 1.29494894 0.366038412 0.0716504827 0.927837372 0.0531662 1 +0.494850755 0.166666657 1.28570223 0.356600195 0.120103613 0.92650491 0.055981 1 +0.469573259 0.233333319 1.27110827 0.341504693 0.169695407 0.924433947 0.0607881 1 +0.433012545 0.299999982 1.25 0.319221079 0.22116293 0.921512246 0.0692784 1 +0.380994439 0.366666675 1.21996725 0.286541253 0.275765508 0.91752243 0.0870642 1 +0.302627087 0.433333337 1.17472184 0.234931409 0.336399555 0.91194433 0.0870642 1 +0.3314946 0.533333361 1.12472188 0.257341444 0.414030224 0.87312907 0.100344 1 +0.438729405 0.566666722 1.11996722 0.329963058 0.426183134 0.842313707 0.131075 1 +0.519615054 0.600000024 1.10000002 0.383065313 0.44232589 0.810930789 0.11316 1 +0.585043311 0.633333325 1.07110834 0.425482094 0.460601777 0.778980613 0.107453 1 +0.63918829 0.666666687 1.03570223 0.460612953 0.48041448 0.746349514 0.10624 1 +0.6840716 0.700000048 0.994948983 0.490140676 0.501553476 0.712885857 0.10764 1 +0.720724523 0.733333349 0.949443877 0.514978588 0.523987949 0.678405225 0.111132 1 +0.749591887 0.76666671 0.899443805 0.535605192 0.547805667 0.642678797 0.116796 1 +0.770674169 0.800000072 0.844948947 0.552191854 0.573203981 0.605410099 0.125227 1 +0.783525884 0.833333373 0.785702229 0.56462574 0.600518107 0.566194057 0.137869 1 +0.787115932 0.866666734 0.721108258 0.57244271 0.630297303 0.524437547 0.158262 1 +0.7794227 0.900000036 0.649999976 0.574598074 0.663488865 0.479186356 0.125665 1 +0.756272137 0.933333397 0.56996727 0.568782985 0.701948583 0.42866537 0.0785295 1 +0.706772327 0.966666698 0.474721909 0.54867202 0.750429749 0.368529767 0.100757 1 +0.764507413 0.966666698 0.374721885 0.59349215 0.75042969 0.290899068 0.118599 1 +0.871742189 0.933333397 0.369967252 0.655626655 0.701948643 0.278247833 0.107222 1 +0.952627838 0.900000036 0.349999934 0.702286601 0.663488865 0.258023381 0.0860174 1 +1.01805604 0.866666734 0.321108252 0.740397513 0.630297184 0.233531103 0.178503 1 +1.07220101 0.833333373 0.285702199 0.772651315 0.600518107 0.205883205 0.160172 1 +1.11708438 0.800000012 0.244948924 0.800396562 0.573203981 0.175507128 0.149904 1 +1.15373707 0.76666671 0.199443772 0.824378729 0.547805667 0.142508373 0.144125 1 +1.18260479 0.733333349 0.149443835 0.845005453 0.523987949 0.10678196 0.14146 1 +1.20368695 0.700000048 0.0949489027 0.862447619 0.501553476 0.0680313557 0.141455 1 +1.21653867 0.666666687 0.035702195 0.876664162 0.48041448 0.0257277768 0.144298 1 +1.22012866 0.633333385 -0.0288917627 0.887358189 0.460601896 -0.0210119989 0.151062 1 +1.21243548 0.600000024 -0.100000091 0.893819332 0.44232589 -0.0737210438 0.164999 1 +1.1892848 0.566666663 -0.180032775 0.894446611 0.426183105 -0.135400459 0.10106 1 +1.13978505 0.533333361 -0.275278181 0.884822667 0.414030224 -0.21370028 0.131894 1 +1.16865242 0.433333397 -0.325278252 0.907232642 0.336399585 -0.252515674 0.154905 1 +1.24701989 0.366666704 -0.280032784 0.937868416 0.275765538 -0.210609227 0.141906 1 +1.29903793 0.300000042 -0.250000089 0.957663596 0.22116299 -0.184302524 0.112296 1 +1.33559871 0.233333379 -0.22889176 0.971335649 0.169695452 -0.166465208 0.098187 1 +1.3608762 0.166666701 -0.214297801 0.980676949 0.120103642 -0.154427648 0.0902054 1 +1.37689197 0.100000031 -0.205051094 0.986549973 0.07165052 -0.14692013 0.0855387 1 +1.38467717 0.0333333611 -0.200556248 0.989392221 0.0238176584 -0.14330329 0.0830518 1 +1.38467717 -0.033333309 -0.200556248 0.989392221 -0.0238176212 -0.14330329 0.0822671 1 +1.37689197 -0.0999999791 -0.205051094 0.986549973 -0.0716504827 -0.14692013 0.0830518 1 +1.3608762 -0.166666657 -0.214297801 0.980676949 -0.120103613 -0.154427648 0.0855387 1 +1.33559871 -0.233333319 -0.22889176 0.971335649 -0.169695407 -0.166465208 0.0902061 1 +1.29903793 -0.299999982 -0.250000089 0.957663596 -0.221162945 -0.184302524 0.0981876 1 +1.24701989 -0.366666675 -0.280032784 0.937868416 -0.275765508 -0.210609227 0.112297 1 +1.16865253 -0.433333337 -0.325278193 0.907232702 -0.336399555 -0.252515614 0.141907 1 +1.13978505 -0.533333361 -0.275278181 0.884822667 -0.414030224 -0.21370028 0.157429 1 +1.1892848 -0.566666722 -0.180032805 0.894446552 -0.426183105 -0.135400474 0.13482 1 +1.21243548 -0.600000024 -0.100000091 0.893819332 -0.44232589 -0.0737210438 0.124635 1 +1.22012866 -0.633333325 -0.0288917627 0.887358189 -0.460601836 -0.0210119989 0.119068 1 +1.21653867 -0.666666687 0.035702195 0.876664162 -0.48041448 0.0257277768 0.115938 1 +1.20368695 -0.700000048 0.0949489027 0.862447619 -0.501553476 0.0680313557 0.114422 1 +1.18260479 -0.733333349 0.149443835 0.845005453 -0.523987949 0.10678196 0.11419 1 +1.15373707 -0.76666671 0.199443772 0.824378729 -0.547805667 0.142508373 0.115158 1 +1.11708438 -0.800000072 0.244948924 0.800396442 -0.573203981 0.175507113 0.117426 1 +1.07220101 -0.833333373 0.285702199 0.772651315 -0.600518107 0.205883205 0.121288 1 +1.01805604 -0.866666734 0.321108252 0.740397513 -0.630297184 0.233531103 0.127357 1 +0.952627838 -0.900000036 0.349999934 0.702286601 -0.663488865 0.258023381 0.136883 1 +0.871742189 -0.933333397 0.369967252 0.655626655 -0.701948643 0.278247833 0.152746 1 +0.764507413 -0.966666698 0.374721885 0.59349215 -0.75042969 0.290899068 0.183761 1 +0.706772327 -0.966666698 0.474721909 0.54867202 -0.750429749 0.368529767 0.178323 1 +0.756272137 -0.933333397 0.56996727 0.568782985 -0.701948583 0.42866537 0.143925 1 +0.7794227 -0.900000036 0.649999976 0.574598074 -0.663488865 0.479186356 0.12526 1 +0.787115932 -0.866666734 0.721108258 0.57244271 -0.630297303 0.524437547 0.113183 1 +0.783525884 -0.833333373 0.785702229 0.56462574 -0.600518107 0.566194057 0.104667 1 +0.770674169 -0.800000012 0.844948947 0.552191913 -0.573203981 0.605410159 0.0983705 1 +0.749591887 -0.76666671 0.899443805 0.535605192 -0.547805667 0.642678797 0.0936092 1 +0.720724523 -0.733333349 0.949443877 0.514978588 -0.523987949 0.678405225 0.0900107 1 +0.6840716 -0.700000048 0.994948983 0.490140676 -0.501553476 0.712885857 0.087396 1 +0.63918829 -0.666666687 1.03570223 0.460612953 -0.48041448 0.746349514 0.0857206 1 +0.585043311 -0.633333385 1.07110834 0.425482094 -0.460601807 0.778980613 0.0851079 1 +0.519615054 -0.600000024 1.10000002 0.383065313 -0.44232589 0.810930789 0.085982 1 +0.438729465 -0.566666663 1.11996722 0.329963088 -0.426183105 0.842313707 0.0895593 1 +0.3314946 -0.533333361 1.12472188 0.257341444 -0.414030224 0.87312907 0.100344 1 +0.221034139 -0.333333343 1.19428086 0.175497234 -0.264660835 0.948238015 0.0838683 1 +0.295782417 -0.266666681 1.23743677 0.227535158 -0.205137432 0.951917231 0.0646989 1 +0.340577573 -0.200000018 1.26329923 0.257311463 -0.15110302 0.954441547 0.0567439 1 +0.368647486 -0.13333334 1.27950549 0.275477499 -0.0996353924 0.956130207 0.0528297 1 +0.384333581 -0.0666666701 1.28856182 0.285472006 -0.0495180972 0.957106948 0.0511541 1 +0.389397413 0 1.29148543 0.28867507 0 0.957427144 0.0511541 1 +0.384333581 0.0666666701 1.28856182 0.285472006 0.0495180972 0.957106948 0.0528297 1 +0.368647486 0.13333334 1.27950549 0.275477499 0.0996353924 0.956130207 0.0567439 1 +0.340577573 0.200000018 1.26329923 0.257311463 0.15110302 0.954441547 0.0646989 1 +0.295782417 0.266666681 1.23743677 0.227535158 0.205137432 0.951917231 0.0646989 1 +0.307636559 0.633333385 1.04428077 0.244258046 0.502855599 0.829140663 0.131075 1 +0.411252409 0.666666746 1.03743672 0.316362232 0.512843609 0.798064113 0.0869064 1 +0.484915137 0.700000048 1.01329923 0.366360664 0.528860569 0.765562832 0.0674 1 +0.541852713 0.733333349 0.979505539 0.404907763 0.547994614 0.731950521 0.0594388 1 +0.586406112 0.76666671 0.938561797 0.43556571 0.569458127 0.697136879 0.0556884 1 +0.620337486 0.800000072 0.891485393 0.459879726 0.593070388 0.66089195 0.0543191 1 +0.644141138 0.833333373 0.838561773 0.478449672 0.618976295 0.622859776 0.0548032 1 +0.657322645 0.866666734 0.779505432 0.491194457 0.647630036 0.582497418 0.0572066 1 +0.658120215 0.900000036 0.713299274 0.497219712 0.679963589 0.538908303 0.0622539 1 +0.642192602 0.933333397 0.637436748 0.494016469 0.717980981 0.490357965 0.0721393 1 +0.873132706 0.933333397 0.237436756 0.671670675 0.717980981 0.182651863 0.137311 1 +0.946795404 0.900000036 0.21329923 0.715318143 0.679963589 0.161150783 0.0838292 1 +1.00373292 0.866666675 0.179505467 0.750054836 0.647629976 0.134138212 0.0740717 1 +1.04828632 0.833333373 0.138561741 0.77863723 0.618976295 0.102919713 0.0695783 1 +1.08221769 0.800000072 0.0914853439 0.802289069 0.593070388 0.0678215548 0.0681096 1 +1.1060214 0.76666671 0.038561713 0.821521163 0.569458187 0.0286425408 0.0690429 1 +1.11920297 0.733333349 -0.0204945542 0.836341679 0.547994614 -0.0153148714 0.0725376 1 +1.12000048 0.700000048 -0.0867007896 0.84617722 0.528860569 -0.0655037537 0.0796273 1 +1.10407281 0.666666687 -0.162563264 0.849324942 0.512843609 -0.125054285 0.0933819 1 +1.21954286 0.266666681 -0.362563252 0.938152075 0.205137432 -0.278907359 0.175696 1 +1.26433802 0.200000018 -0.336700767 0.955226362 0.15110302 -0.254382491 0.109631 1 +1.29240799 0.13333334 -0.320494592 0.965771794 0.0996353924 -0.239494517 0.0958525 1 +1.30809402 0.0666666701 -0.311438233 0.971614897 0.0495180972 -0.231327429 0.0890802 1 +1.31315792 0 -0.308514625 0.973493814 0 -0.228713602 0.0861824 1 +1.30809402 -0.0666666701 -0.311438233 0.971614897 -0.0495180972 -0.231327429 0.0861824 1 +1.29240799 -0.13333334 -0.320494592 0.965771794 -0.0996353924 -0.239494517 0.0890802 1 +1.26433802 -0.200000018 -0.336700767 0.955226362 -0.15110302 -0.254382491 0.0958525 1 +1.21954286 -0.266666681 -0.362563252 0.938152075 -0.205137432 -0.278907359 0.109631 1 +1.14479458 -0.333333343 -0.405719191 0.908946812 -0.264660835 -0.322133929 0.142895 1 +1.05819201 -0.633333385 -0.255719304 0.84018594 -0.502855599 -0.203036651 0.198882 1 +1.10407281 -0.666666746 -0.162563324 0.849324942 -0.512843609 -0.12505433 0.164999 1 +1.12000048 -0.700000048 -0.0867007896 0.84617722 -0.528860569 -0.0655037537 0.151062 1 +1.11920297 -0.733333349 -0.0204945542 0.836341679 -0.547994614 -0.0153148714 0.144298 1 +1.1060214 -0.76666671 0.038561713 0.821521163 -0.569458187 0.0286425408 0.141455 1 +1.08221769 -0.800000072 0.0914853439 0.802289069 -0.593070388 0.0678215548 0.14146 1 +1.04828632 -0.833333373 0.138561741 0.77863723 -0.618976295 0.102919713 0.144125 1 +1.0037328 -0.866666734 0.179505408 0.750054777 -0.647630036 0.134138182 0.149905 1 +0.946795404 -0.900000036 0.21329923 0.715318143 -0.679963589 0.161150783 0.160172 1 +0.873132706 -0.933333397 0.237436756 0.671670675 -0.717980981 0.182651863 0.178503 1 +0.769516945 -0.966666698 0.244280815 0.610982955 -0.767516375 0.193954676 0.217237 1 +0.596311808 -0.966666698 0.544280827 0.473461121 -0.767516375 0.43214941 0.198343 1 +0.642192602 -0.933333397 0.637436748 0.494016469 -0.717980981 0.490357965 0.158262 1 +0.658120215 -0.900000036 0.713299274 0.497219712 -0.679963589 0.538908303 0.137869 1 +0.657322764 -0.866666675 0.779505491 0.491194516 -0.647629976 0.582497418 0.125227 1 +0.644141138 -0.833333373 0.838561773 0.478449672 -0.618976295 0.622859776 0.116796 1 +0.620337486 -0.800000072 0.891485393 0.459879726 -0.593070388 0.66089195 0.111132 1 +0.586406112 -0.76666671 0.938561797 0.43556571 -0.569458127 0.697136879 0.10764 1 +0.541852713 -0.733333349 0.979505539 0.404907763 -0.547994614 0.731950521 0.10624 1 +0.484915137 -0.700000048 1.01329923 0.366360664 -0.528860569 0.765562832 0.107453 1 +0.411252469 -0.666666687 1.03743684 0.316362262 -0.512843549 0.798064172 0.11316 1 +0.307636678 -0.633333325 1.04428089 0.244258121 -0.502855539 0.829140663 0.131075 1 +0.942721903 -0.833333373 -0.0557193048 0.748504698 -0.661652148 -0.0442401543 0.219203 1 +0.913854361 -0.866666734 -0.00571927987 0.725584388 -0.688118219 -0.00454100827 0.220669 1 +0.451974154 -0.866666734 0.794280767 0.358859569 -0.688118219 0.630645037 0.172366 1 +0.423106611 -0.833333373 0.844280779 0.335939258 -0.661652148 0.670344174 0.165746 1 +-1.38564062 0 0.800000012 -0.866025388 0 0.5 0.059501 1 +-1.35484648 -0.0333333351 0.848887682 -0.847220838 -0.0208442044 0.530831635 0.0586682 1 +-1.35484648 0.0333333351 0.848887682 -0.847220838 0.0208442044 0.530831635 0.0588084 1 +-1.38371396 0.0666666701 0.79888767 -0.865272462 0.0416884087 0.499565303 0.059784 1 +-1.41258144 0.0333333351 0.748887658 -0.883324146 0.0208442062 0.468299031 0.0604536 1 +-1.41258144 -0.0333333351 0.748887658 -0.883324146 -0.0208442062 0.468299031 0.0603094 1 +-1.38371396 -0.0666666701 0.79888767 -0.865272462 -0.0416884087 0.499565303 0.059501 1 +-1.32017303 -0.0666666701 0.895535648 -0.826840222 -0.0417541377 0.560884714 0.0579523 1 +-1.3221128 0 0.89665556 -0.827618957 0 0.561290324 0.0579523 1 +-1.32017303 0.0666666701 0.895535648 -0.826840222 0.0417541377 0.560884714 0.0582305 1 +-1.3509804 0.100000009 0.846655548 -0.845689476 0.0625982136 0.52999115 0.0592297 1 +-1.37790811 0.13333334 0.795535624 -0.863000393 0.0835082754 0.498253524 0.0603628 1 +-1.40871537 0.100000009 0.746655524 -0.881830633 0.0625982136 0.467393011 0.0608891 1 +-1.4356432 0.0666666701 0.6955356 -0.899160564 0.0417541377 0.435622305 0.061537 1 +-1.43758297 0 0.696655512 -0.899901152 0 0.436093837 0.0612397 1 +-1.4356432 -0.0666666701 0.6955356 -0.899160564 -0.0417541377 0.435622305 0.0612397 1 +-1.40871537 -0.100000009 0.746655524 -0.881830633 -0.0625982136 0.467393011 0.0604536 1 +-1.37790811 -0.13333334 0.795535624 -0.863000393 -0.0835082754 0.498253524 0.059784 1 +-1.3509804 -0.100000009 0.846655548 -0.845689476 -0.0625982136 0.52999115 0.0588084 1 +-1.28154075 -0.100000001 0.939897954 -0.804782927 -0.0627980754 0.590237856 0.0573419 1 +-1.28546011 -0.0333333313 0.942160785 -0.806381166 -0.0209103115 0.591026306 0.0572024 1 +-1.28546011 0.0333333388 0.942160785 -0.806381166 0.0209103171 0.591026306 0.0573419 1 +-1.28154075 0.100000009 0.939897954 -0.804782927 0.0627980828 0.590237856 0.0577647 1 +-1.3143276 0.13333334 0.892160773 -0.82449013 0.0836412609 0.559660852 0.0587982 1 +-1.3431952 0.166666672 0.842160761 -0.842598975 0.104551569 0.528295338 0.0599553 1 +-1.36814332 0.200000018 0.789897919 -0.859167695 0.125596166 0.496040702 0.0612573 1 +-1.40093017 0.166666672 0.742160738 -0.878816724 0.104551576 0.46556443 0.0616358 1 +-1.42979777 0.13333334 0.692160726 -0.896925569 0.0836412534 0.434198916 0.0621446 1 +-1.45474589 0.100000001 0.639897883 -0.913552463 0.0627980754 0.401843578 0.0627711 1 +-1.45866525 0.0333333313 0.642160714 -0.915034413 0.0209103115 0.402833432 0.0623085 1 +-1.45866525 -0.0333333388 0.642160714 -0.915034413 -0.0209103171 0.402833432 0.0621533 1 +-1.45474589 -0.100000009 0.639897883 -0.913552463 -0.0627980828 0.401843578 0.0623085 1 +-1.42979777 -0.13333334 0.692160726 -0.896925569 -0.0836412534 0.434198916 0.061537 1 +-1.40093017 -0.166666672 0.742160738 -0.878816724 -0.104551576 0.46556443 0.0608891 1 +-1.36814332 -0.200000018 0.789897919 -0.859167695 -0.125596166 0.496040702 0.0603628 1 +-1.3431952 -0.166666672 0.842160761 -0.842598975 -0.104551569 0.528295338 0.0592297 1 +-1.3143276 -0.13333334 0.892160773 -0.82449013 -0.0836412609 0.559660852 0.0582305 1 +-1.23881078 -0.13333334 0.981894433 -0.780912697 -0.084049724 0.618959606 0.0568416 1 +-1.24477983 -0.0666666701 0.985340655 -0.783389151 -0.0419559702 0.62011379 0.0565618 1 +-1.24676013 0 0.986483991 -0.784209371 0 0.620496273 0.0565618 1 +-1.24477983 0.0666666701 0.985340655 -0.783389151 0.0419559702 0.62011379 0.0568416 1 +-1.23881078 0.13333334 0.981894433 -0.780912697 0.084049724 0.618959606 0.0574188 1 +-1.27364731 0.166666687 0.935340703 -0.801556587 0.104889929 0.588646889 0.058487 1 +-1.3044951 0.200000018 0.886484027 -0.820524573 0.125799567 0.557596505 0.0596811 1 +-1.33138239 0.233333349 0.835340679 -0.837891579 0.146845892 0.525712907 0.0610134 1 +-1.35428083 0.266666681 0.781894445 -0.85370189 0.168099448 0.492885053 0.062514 1 +-1.38911736 0.233333349 0.735340655 -0.874226451 0.146845892 0.462778926 0.0627254 1 +-1.41996527 0.200000018 0.686483979 -0.893154919 0.125799567 0.431796879 0.063081 1 +-1.44685245 0.166666672 0.635340631 -0.910561502 0.104889929 0.399845004 0.0635633 1 +-1.46975088 0.13333334 0.581894457 -0.926491082 0.084049724 0.366810501 0.0641787 1 +-1.47571993 0.0666666701 0.585340679 -0.928728878 0.0419559702 0.368378013 0.0635267 1 +-1.47770023 0 0.586484015 -0.929470181 0 0.36889717 0.0632066 1 +-1.47571993 -0.0666666701 0.585340679 -0.928728878 -0.0419559702 0.368378013 0.0632066 1 +-1.46975088 -0.13333334 0.581894457 -0.926491082 -0.084049724 0.366810501 0.0635267 1 +-1.44685245 -0.166666687 0.635340631 -0.910561502 -0.104889944 0.399845004 0.0627711 1 +-1.41996527 -0.200000018 0.686483979 -0.893154919 -0.125799567 0.431796879 0.0621446 1 +-1.38911736 -0.233333349 0.735340655 -0.874226451 -0.146845892 0.462778926 0.0616358 1 +-1.35428083 -0.266666681 0.781894445 -0.85370189 -0.168099448 0.492885053 0.0612573 1 +-1.33138239 -0.233333349 0.835340679 -0.837891579 -0.146845892 0.525712907 0.0599553 1 +-1.3044951 -0.200000018 0.886484027 -0.820524573 -0.125799567 0.557596505 0.0587982 1 +-1.27364731 -0.166666672 0.935340703 -0.801556587 -0.104889922 0.588646889 0.0577647 1 +-1.19177425 -0.166666687 1.0214045 -0.755048394 -0.105591655 0.647110701 0.0564605 1 +-1.19989884 -0.100000009 1.02609527 -0.758484006 -0.0632123351 0.648618698 0.056029 1 +-1.20393121 -0.0333333388 1.02842331 -0.760184824 -0.0210472979 0.649365842 0.0558851 1 +-1.20393121 0.0333333313 1.02842331 -0.760184824 0.0210472923 0.649365842 0.056029 1 +-1.19989884 0.100000001 1.02609527 -0.758484006 0.0632123277 0.648618698 0.0564605 1 +-1.19177425 0.166666672 1.0214045 -0.755048394 0.105591647 0.647110701 0.0572076 1 +-1.22876632 0.200000018 0.976095259 -0.776731789 0.12642467 0.61701256 0.0583155 1 +-1.26166618 0.233333349 0.928423345 -0.79663986 0.147331089 0.58622402 0.0595471 1 +-1.29053366 0.266666681 0.878423333 -0.814867318 0.168378383 0.554653108 0.0609175 1 +-1.31536889 0.300000012 0.826095283 -0.831475317 0.18963699 0.522194088 0.0624548 1 +-1.33611178 0.333333343 0.771404505 -0.846493423 0.211183295 0.488723218 0.0641917 1 +-1.37310386 0.300000012 0.726095259 -0.867970943 0.18963699 0.458981723 0.0642131 1 +-1.40600383 0.266666681 0.678423285 -0.887777269 0.168378368 0.428369224 0.0643967 1 +-1.43487132 0.233333349 0.628423274 -0.906004786 0.147331074 0.396798283 0.0647256 1 +-1.45970643 0.200000018 0.576095283 -0.922714412 0.12642467 0.36416325 0.0651911 1 +-1.48044932 0.166666687 0.521404505 -0.937938452 0.105591655 0.330335766 0.0657968 1 +-1.48857391 0.100000009 0.526095271 -0.940962255 0.0632123351 0.332557082 0.0649234 1 +-1.49260628 0.0333333388 0.528423309 -0.942459822 0.0210472997 0.33365646 0.0644152 1 +-1.49260628 -0.0333333313 0.528423309 -0.942459822 -0.0210472941 0.33365646 0.0642456 1 +-1.48857391 -0.100000001 0.526095271 -0.940962255 -0.0632123277 0.332557082 0.0644152 1 +-1.48044932 -0.166666672 0.521404505 -0.937938452 -0.105591647 0.330335766 0.0649234 1 +-1.45970643 -0.200000018 0.576095283 -0.922714412 -0.12642467 0.36416325 0.0641787 1 +-1.43487132 -0.233333349 0.628423274 -0.906004786 -0.147331074 0.396798283 0.0635633 1 +-1.40600383 -0.266666681 0.678423285 -0.887777269 -0.168378368 0.428369224 0.063081 1 +-1.37310386 -0.300000012 0.726095259 -0.867970943 -0.18963699 0.458981723 0.0627254 1 +-1.33611178 -0.333333343 0.771404505 -0.846493423 -0.211183295 0.488723218 0.062514 1 +-1.31536889 -0.300000012 0.826095283 -0.831475317 -0.18963699 0.522194088 0.0610134 1 +-1.29053366 -0.266666681 0.878423333 -0.814867318 -0.168378383 0.554653108 0.0596811 1 +-1.26166618 -0.233333349 0.928423345 -0.79663986 -0.147331089 0.58622402 0.058487 1 +-1.22876632 -0.200000018 0.976095259 -0.776731789 -0.12642467 0.61701256 0.0574188 1 +-1.14013553 -0.200000003 1.05825758 -0.726950765 -0.127520069 0.674745381 0.0562107 1 +-1.15056598 -0.133333325 1.06427968 -0.731455445 -0.0847647041 0.676600218 0.0556069 1 +-1.15675986 -0.0666666627 1.06785572 -0.734121025 -0.0423090383 0.677699268 0.0553102 1 +-1.15881395 7.4505806e-09 1.06904161 -0.735003412 4.72569583e-09 0.678063333 0.0553102 1 +-1.15675986 0.0666666776 1.06785572 -0.734121025 0.0423090495 0.677699268 0.0556069 1 +-1.15056598 0.133333355 1.06427968 -0.731455445 0.0847647265 0.676600218 0.0562107 1 +-1.14013553 0.200000018 1.05825758 -0.726950765 0.127520069 0.674745381 0.0571555 1 +-1.17943358 0.233333349 1.0142796 -0.749807596 0.148338258 0.644813359 0.0583052 1 +-1.21449494 0.266666681 0.967855632 -0.770761788 0.169236183 0.61423564 0.0595761 1 +-1.24541652 0.300000012 0.919041634 -0.789933026 0.190281659 0.582922518 0.0609889 1 +-1.27222991 0.333333343 0.867855668 -0.807402432 0.211545214 0.55077213 0.0625722 1 +-1.29490364 0.366666675 0.814279616 -0.823215902 0.233102933 0.51766628 0.0643559 1 +-1.31334066 0.400000036 0.758257568 -0.83738631 0.255040109 0.483465225 0.0663852 1 +-1.3526386 0.366666675 0.714279592 -0.859920144 0.233102962 0.454092771 0.0661755 1 +-1.38770008 0.333333343 0.66785562 -0.880683899 0.211545214 0.423844963 0.0661584 1 +-1.41862166 0.300000012 0.619041562 -0.899792194 0.190281659 0.392640829 0.0663115 1 +-1.44543505 0.266666681 0.567855656 -0.917324603 0.169236183 0.360381424 0.0666184 1 +-1.46810865 0.233333349 0.514279604 -0.933328569 0.148338258 0.326945722 0.0670762 1 +-1.4865458 0.200000003 0.458257556 -0.947821975 0.127520055 0.292185128 0.0676711 1 +-1.49697626 0.133333325 0.464279592 -0.95168072 0.0847647041 0.295158952 0.066536 1 +-1.50317013 0.0666666627 0.467855632 -0.953965247 0.0423090346 0.296917826 0.0658058 1 +-1.50522423 -7.4505806e-09 0.469041586 -0.954721808 -4.72569583e-09 0.297500014 0.0654487 1 +-1.50317013 -0.0666666776 0.467855632 -0.953965247 -0.0423090458 0.296917826 0.0654487 1 +-1.49697626 -0.133333355 0.464279592 -0.95168072 -0.0847647265 0.295158952 0.0658058 1 +-1.4865458 -0.200000018 0.458257556 -0.947821975 -0.127520055 0.292185128 0.0665342 1 +-1.46810865 -0.233333349 0.514279604 -0.933328569 -0.148338258 0.326945722 0.0657968 1 +-1.44543505 -0.266666681 0.567855656 -0.917324603 -0.169236183 0.360381424 0.0651911 1 +-1.41862166 -0.300000012 0.619041562 -0.899792194 -0.190281659 0.392640829 0.0647256 1 +-1.38770008 -0.333333343 0.66785562 -0.880683899 -0.211545214 0.423844963 0.0643967 1 +-1.3526386 -0.366666675 0.714279592 -0.859920144 -0.233102962 0.454092771 0.0642131 1 +-1.31334066 -0.400000036 0.758257568 -0.83738631 -0.255040109 0.483465225 0.0641917 1 +-1.29490364 -0.366666675 0.814279616 -0.823215902 -0.233102933 0.51766628 0.0624548 1 +-1.27222991 -0.333333343 0.867855668 -0.807402432 -0.211545214 0.55077213 0.0609175 1 +-1.24541652 -0.300000012 0.919041634 -0.789933026 -0.190281659 0.582922518 0.0595471 1 +-1.21449494 -0.266666681 0.967855632 -0.770761788 -0.169236183 0.61423564 0.0583155 1 +-1.17943358 -0.233333349 1.0142796 -0.749807596 -0.148338258 0.644813359 0.0572076 1 +-1.08348429 -0.233333349 1.09221661 -0.696300268 -0.149951488 0.701912105 0.0561183 1 +-1.09643066 -0.166666672 1.09969127 -0.70202446 -0.106713615 0.704112172 0.0553155 1 +-1.10494339 -0.100000001 1.10460603 -0.705770612 -0.0638739169 0.705555141 0.0548511 1 +-1.10916543 -0.0333333313 1.10704362 -0.707623422 -0.0212659407 0.706269741 0.0546954 1 +-1.10916543 0.0333333388 1.10704362 -0.707623422 0.0212659445 0.706269741 0.0548511 1 +-1.10494339 0.100000009 1.10460603 -0.705770612 0.0638739243 0.705555141 0.0553155 1 +-1.09643066 0.166666687 1.09969127 -0.70202446 0.106713623 0.704112172 0.0561183 1 +-1.08348429 0.233333349 1.09221661 -0.696300268 0.149951488 0.701912105 0.0572993 1 +-1.12529814 0.266666681 1.04969132 -0.720507801 0.170741796 0.6720981 0.058488 1 +-1.16267848 0.300000012 1.00460613 -0.742648125 0.191621721 0.641681135 0.0598069 1 +-1.195768 0.333333343 0.957043648 -0.762873888 0.212659404 0.610572994 0.061267 1 +-1.22463548 0.366666675 0.907043695 -0.781290829 0.233925372 0.578674138 0.0628992 1 +-1.24928093 0.400000036 0.854606092 -0.797964573 0.255495667 0.545870304 0.0647403 1 +-1.2696358 0.433333367 0.79969126 -0.812924445 0.277455389 0.512027621 0.0668312 1 +-1.28555691 0.466666698 0.742216647 -0.82616204 0.299902946 0.476984859 0.0692405 1 +-1.32737076 0.433333367 0.699691236 -0.849891186 0.277455419 0.447999477 0.0687269 1 +-1.3647511 0.400000036 0.654606044 -0.871719897 0.255495667 0.41812247 0.0684625 1 +-1.39784062 0.366666675 0.607043624 -0.89179194 0.233925372 0.387280643 0.0684058 1 +-1.4267081 0.333333343 0.557043672 -0.910208642 0.212659404 0.355381727 0.068533 1 +-1.45135355 0.300000012 0.504606068 -0.927036345 0.191621765 0.32231167 0.0688275 1 +-1.47170842 0.266666681 0.449691236 -0.94230783 0.170741767 0.287929028 0.0692793 1 +-1.48762953 0.233333349 0.392216623 -0.956023812 0.149951473 0.252057672 0.0698854 1 +-1.5005759 0.166666672 0.399691224 -0.96079123 0.106713615 0.255914956 0.0684146 1 +-1.50908864 0.100000001 0.404606044 -0.963913918 0.0638739094 0.258437693 0.0674159 1 +-1.51331067 0.0333333313 0.407043636 -0.965459287 0.0212659407 0.25968498 0.0668365 1 +-1.51331067 -0.0333333388 0.407043636 -0.965459287 -0.0212659445 0.25968498 0.0666471 1 +-1.50908864 -0.100000009 0.404606044 -0.963913918 -0.0638739169 0.258437693 0.0668365 1 +-1.5005759 -0.166666687 0.399691224 -0.96079123 -0.106713623 0.255914956 0.0674159 1 +-1.48762953 -0.233333349 0.392216623 -0.956023812 -0.149951473 0.252057672 0.0684146 1 +-1.47170842 -0.266666681 0.449691236 -0.94230783 -0.170741767 0.287929028 0.0676711 1 +-1.45135355 -0.300000012 0.504606068 -0.927036345 -0.191621765 0.32231167 0.0670762 1 +-1.4267081 -0.333333343 0.557043672 -0.910208642 -0.212659404 0.355381727 0.0666184 1 +-1.39784062 -0.366666675 0.607043624 -0.89179194 -0.233925372 0.387280643 0.0663115 1 +-1.3647511 -0.400000036 0.654606044 -0.871719897 -0.255495667 0.41812247 0.0661584 1 +-1.32737076 -0.433333367 0.699691236 -0.849891186 -0.277455419 0.447999477 0.0661755 1 +-1.28555691 -0.466666698 0.742216647 -0.82616204 -0.299902946 0.476984859 0.0663852 1 +-1.2696358 -0.433333367 0.79969126 -0.812924445 -0.277455389 0.512027621 0.0643559 1 +-1.24928093 -0.400000036 0.854606092 -0.797964573 -0.255495667 0.545870304 0.0625722 1 +-1.22463548 -0.366666675 0.907043695 -0.781290829 -0.233925372 0.578674138 0.0609889 1 +-1.195768 -0.333333343 0.957043648 -0.762873888 -0.212659404 0.610572994 0.0595761 1 +-1.16267848 -0.300000012 1.00460613 -0.742648125 -0.191621721 0.641681135 0.0583052 1 +-1.12529814 -0.266666681 1.04969132 -0.720507801 -0.170741796 0.6720981 0.0571555 1 +-1.02125049 -0.266666681 1.12295258 -0.662662804 -0.173033059 0.728654623 0.056216 1 +-1.03700662 -0.200000018 1.13204944 -0.669815063 -0.129182428 0.731204391 0.0551763 1 +-1.04806089 -0.13333334 1.13843155 -0.674802423 -0.0858477429 0.732988298 0.0545119 1 +-1.05461681 -0.0666666701 1.14221668 -0.677748561 -0.0428432748 0.734044552 0.0541883 1 +-1.05678964 0 1.14347112 -0.678723156 0 0.734394312 0.0541883 1 +-1.05461681 0.0666666701 1.14221668 -0.677748561 0.0428432748 0.734044552 0.0545119 1 +-1.04806089 0.13333334 1.13843155 -0.674802423 0.0858477429 0.732988298 0.0551763 1 +-1.03700662 0.200000018 1.13204944 -0.669815063 0.129182428 0.731204391 0.056216 1 +-1.02125049 0.266666681 1.12295258 -0.662662804 0.173033059 0.728654623 0.0576955 1 +-1.0658741 0.300000012 1.08204937 -0.688460946 0.193773627 0.698908746 0.0589289 1 +-1.10579586 0.333333373 1.03843164 -0.711975515 0.214619368 0.668602526 0.0602896 1 +-1.14121938 0.366666675 0.992216647 -0.733403623 0.235638008 0.637647152 0.061803 1 +-1.17225969 0.400000036 0.943471134 -0.752883732 0.256900012 0.605944276 0.0634929 1 +-1.19895434 0.433333367 0.892216682 -0.770506918 0.278481305 0.573382258 0.0653958 1 +-1.22126591 0.466666698 0.838431597 -0.786321819 0.300467104 0.539830923 0.0675626 1 +-1.23907924 0.5 0.782049417 -0.800336182 0.322956026 0.505135119 0.0700576 1 +-1.25219059 0.533333361 0.722952604 -0.812513828 0.346066117 0.469105095 0.0729754 1 +-1.2968142 0.5 0.682049394 -0.837627947 0.322956026 0.44054392 0.0720524 1 +-1.33673608 0.466666698 0.638431549 -0.860668242 0.300467104 0.41105926 0.0714655 1 +-1.37215948 0.433333337 0.592216611 -0.881817102 0.278481275 0.380587488 0.0711408 1 +-1.40319979 0.400000036 0.543471158 -0.901205063 0.256900012 0.349044353 0.0710502 1 +-1.42989445 0.366666675 0.492216617 -0.918920457 0.235638037 0.316322595 0.0711601 1 +-1.45220613 0.333333343 0.438431561 -0.935014546 0.214619339 0.282287687 0.0714521 1 +-1.47001934 0.300000012 0.382049382 -0.949503183 0.193773627 0.246770293 0.071914 1 +-1.48313069 0.266666681 0.322952598 -0.962364852 0.173033059 0.209555522 0.0725475 1 +-1.49888682 0.200000018 0.3320494 -0.968149066 0.129182428 0.214474708 0.0706452 1 +-1.5099411 0.13333334 0.338431567 -0.972187698 0.0858477429 0.217901871 0.0693085 1 +-1.51649702 0.0666666701 0.342216641 -0.974575579 0.0428432822 0.21992524 0.0684564 1 +-1.51866984 0 0.34347114 -0.975365698 0 0.220594347 0.0680421 1 +-1.51649702 -0.0666666701 0.342216641 -0.974575579 -0.0428432822 0.21992524 0.0680421 1 +-1.5099411 -0.13333334 0.338431567 -0.972187698 -0.0858477429 0.217901871 0.0684564 1 +-1.49888682 -0.200000018 0.3320494 -0.968149066 -0.129182428 0.214474708 0.0693085 1 +-1.48313069 -0.266666681 0.322952598 -0.962364852 -0.173033059 0.209555522 0.0706452 1 +-1.47001934 -0.300000012 0.382049382 -0.949503183 -0.193773627 0.246770293 0.0698854 1 +-1.45220613 -0.333333373 0.438431561 -0.935014546 -0.214619368 0.282287687 0.0692793 1 +-1.42989445 -0.366666675 0.492216617 -0.918920457 -0.235638037 0.316322595 0.0688275 1 +-1.40319979 -0.400000036 0.543471158 -0.901205063 -0.256900012 0.349044353 0.068533 1 +-1.37215948 -0.433333367 0.592216611 -0.881817102 -0.278481305 0.380587488 0.0684058 1 +-1.33673608 -0.466666698 0.638431549 -0.860668242 -0.300467104 0.41105926 0.0684625 1 +-1.2968142 -0.5 0.682049394 -0.837627947 -0.322956026 0.44054392 0.0687269 1 +-1.25219059 -0.533333361 0.722952604 -0.812513828 -0.346066117 0.469105095 0.0692405 1 +-1.23907924 -0.5 0.782049417 -0.800336182 -0.322956026 0.505135119 0.0668312 1 +-1.22126591 -0.466666698 0.838431597 -0.786321819 -0.300467104 0.539830923 0.0647403 1 +-1.19895434 -0.433333337 0.892216682 -0.770506918 -0.278481275 0.573382258 0.0628992 1 +-1.17225969 -0.400000036 0.943471134 -0.752883732 -0.256900012 0.605944276 0.061267 1 +-1.14121938 -0.366666675 0.992216647 -0.733403623 -0.235638008 0.637647152 0.0598069 1 +-1.10579586 -0.333333343 1.03843164 -0.711975515 -0.214619339 0.668602526 0.0584891 1 +-1.0658741 -0.300000012 1.08204937 -0.688460946 -0.193773627 0.698908746 0.0572993 1 +-0.952627957 -0.300000012 1.1500001 -0.625430822 -0.196959645 0.755011976 0.0565734 1 +-0.971612751 -0.233333349 1.16096091 -0.634308934 -0.152329654 0.757923245 0.0552292 1 +-0.985525548 -0.166666687 1.16899347 -0.640764892 -0.108362645 0.76005125 0.0543267 1 +-0.994654477 -0.100000009 1.17426407 -0.644978166 -0.0648444444 0.761444986 0.053805 1 +-0.999176681 -0.0333333388 1.176875 -0.647058666 -0.0215863977 0.762134612 0.053633 1 +-0.999176681 0.0333333313 1.176875 -0.647058666 0.0215863939 0.762134612 0.053805 1 +-0.994654477 0.100000001 1.17426407 -0.644978166 0.0648444444 0.761444986 0.0543267 1 +-0.985525548 0.166666672 1.16899347 -0.640764892 0.108362637 0.76005125 0.0552292 1 +-0.971612751 0.233333349 1.16096091 -0.634308934 0.152329654 0.757923245 0.0565734 1 +-0.952627957 0.300000012 1.1500001 -0.625430822 0.196959645 0.755011976 0.0584452 1 +-1.00048029 0.333333343 1.11096096 -0.65315491 0.217613786 0.725281239 0.0597111 1 +-1.04326069 0.366666675 1.06899357 -0.678302765 0.238397762 0.69503361 0.0611159 1 +-1.08125699 0.400000036 1.0242641 -0.701135039 0.259377778 0.664178312 0.0626769 1 +-1.11464679 0.433333337 0.976874948 -0.72183615 0.280623138 0.632616222 0.0644291 1 +-1.14351428 0.466666698 0.926874936 -0.740530431 0.302209526 0.600236595 0.0664077 1 +-1.16785955 0.5 0.874264121 -0.757292032 0.324222207 0.566911697 0.0686635 1 +-1.18759823 0.533333361 0.818993568 -0.772147596 0.346760422 0.532489777 0.0712682 1 +-1.20255291 0.566666722 0.760960937 -0.785076261 0.36994347 0.496786743 0.0743177 1 +-1.2124356 0.600000024 0.700000048 -0.796002924 0.393919289 0.459572494 0.0779568 1 +-1.26028788 0.566666722 0.660960913 -0.822768033 0.36994347 0.43150261 0.0764467 1 +-1.3030684 0.533333361 0.618993521 -0.847223401 0.346760392 0.402454525 0.0754048 1 +-1.34106469 0.5 0.57426405 -0.869605899 0.324222207 0.37237832 0.0747276 1 +-1.37445438 0.466666698 0.526874959 -0.890085399 0.302209526 0.341199905 0.0743506 1 +-1.40332186 0.433333367 0.476874918 -0.9087798 0.280623138 0.308820307 0.0742253 1 +-1.42766726 0.400000006 0.424264073 -0.925762773 0.259377748 0.275111645 0.074329 1 +-1.44740593 0.366666675 0.368993521 -0.941068172 0.238397762 0.239910617 0.0746373 1 +-1.4623605 0.333333343 0.310960919 -0.954689384 0.217613786 0.203008145 0.075144 1 +-1.47224331 0.300000012 0.25 -0.966575027 0.196959645 0.164133027 0.0758458 1 +-1.4912281 0.233333349 0.260960877 -0.973535359 0.152329654 0.170366049 0.0733538 1 +-1.50514078 0.166666687 0.268993437 -0.978606105 0.108362645 0.174893022 0.0715697 1 +-1.51426983 0.100000009 0.274263978 -0.981919706 0.0648444444 0.177844927 0.0703677 1 +-1.51879191 0.0333333388 0.2768749 -0.983557224 0.0215863977 0.179301918 0.0696725 1 +-1.51879191 -0.0333333313 0.2768749 -0.983557224 -0.0215863939 0.179301918 0.0694444 1 +-1.51426983 -0.100000001 0.274263978 -0.981919706 -0.0648444369 0.177844927 0.0696725 1 +-1.50514078 -0.166666672 0.268993437 -0.978606105 -0.108362637 0.174893022 0.0703677 1 +-1.4912281 -0.233333349 0.260960877 -0.973535359 -0.152329654 0.170366049 0.0715697 1 +-1.47224331 -0.300000012 0.25 -0.966575027 -0.196959645 0.164133027 0.0733538 1 +-1.4623605 -0.333333343 0.310960919 -0.954689384 -0.217613786 0.203008145 0.0725475 1 +-1.44740593 -0.366666675 0.368993521 -0.941068172 -0.238397762 0.239910617 0.071914 1 +-1.42766726 -0.400000036 0.424264073 -0.925762773 -0.259377778 0.275111645 0.0714521 1 +-1.40332186 -0.433333337 0.476874918 -0.9087798 -0.280623138 0.308820307 0.0711601 1 +-1.37445438 -0.466666698 0.526874959 -0.890085399 -0.302209526 0.341199905 0.0710502 1 +-1.34106469 -0.5 0.57426405 -0.869605899 -0.324222207 0.37237832 0.0711408 1 +-1.3030684 -0.533333361 0.618993521 -0.847223401 -0.346760392 0.402454525 0.0714655 1 +-1.26028788 -0.566666722 0.660960913 -0.822768033 -0.36994347 0.43150261 0.0720524 1 +-1.2124356 -0.600000024 0.700000048 -0.796002924 -0.393919289 0.459572494 0.0729754 1 +-1.20255291 -0.566666722 0.760960937 -0.785076261 -0.36994347 0.496786743 0.0700576 1 +-1.18759823 -0.533333361 0.818993568 -0.772147596 -0.346760422 0.532489777 0.0675626 1 +-1.16785955 -0.5 0.874264121 -0.757292032 -0.324222207 0.566911697 0.0653976 1 +-1.14351428 -0.466666698 0.926874936 -0.740530431 -0.302209526 0.600236595 0.0634929 1 +-1.11464679 -0.433333367 0.976874948 -0.72183615 -0.280623138 0.632616222 0.061803 1 +-1.08125699 -0.400000006 1.0242641 -0.701135039 -0.259377778 0.664178312 0.0602896 1 +-1.04326069 -0.366666675 1.06899357 -0.678302765 -0.238397762 0.69503361 0.0589289 1 +-1.00048029 -0.333333343 1.11096096 -0.65315491 -0.217613786 0.725281239 0.0576955 1 +-0.876437306 -0.333333373 1.17267799 -0.583717525 -0.222003937 0.781017303 0.0573024 1 +-0.89927125 -0.266666681 1.18586123 -0.5947662 -0.176369831 0.784313023 0.0555501 1 +-0.916505456 -0.200000018 1.19581139 -0.603023231 -0.131591856 0.786795139 0.0543311 1 +-0.928555012 -0.133333355 1.20276821 -0.608755231 -0.0874125734 0.788527846 0.0535606 1 +-0.935685873 -0.0666666776 1.20688522 -0.612131715 -0.0436137691 0.789552093 0.0531897 1 +-0.938046813 -7.4505806e-09 1.20824826 -0.613247216 -4.87080998e-09 0.789891124 0.0531897 1 +-0.935685873 0.0666666627 1.20688522 -0.612131715 0.0436137617 0.789552093 0.0535618 1 +-0.928555012 0.133333325 1.20276821 -0.608755231 0.087412551 0.788527846 0.0543311 1 +-0.916505456 0.200000003 1.19581139 -0.603023231 0.131591842 0.786795139 0.0555501 1 +-0.89927125 0.266666681 1.18586123 -0.5947662 0.176369831 0.784313023 0.0573024 1 +-0.876437306 0.333333343 1.17267799 -0.583717525 0.222003922 0.781017303 0.0597391 1 +-0.928138793 0.366666675 1.13586128 -0.613858759 0.242508501 0.751243651 0.0610007 1 +-0.974240541 0.400000036 1.09581137 -0.641010523 0.263183713 0.720999181 0.0624262 1 +-1.01515758 0.433333367 1.05276823 -0.665531397 0.284090817 0.690188706 0.0640298 1 +-1.05115592 0.466666698 1.00688529 -0.687672973 0.305296361 0.658710837 0.0658394 1 +-1.08238447 0.5 0.958248258 -0.707607746 0.326874495 0.626453817 0.0679008 1 +-1.10889101 0.533333361 0.906885207 -0.725443661 0.348910123 0.59329015 0.0702625 1 +-1.13062763 0.566666722 0.852768242 -0.741232812 0.371503353 0.559069812 0.0730008 1 +-1.14744556 0.600000024 0.795811415 -0.754972398 0.39477554 0.523611486 0.0762271 1 +-1.15907896 0.633333385 0.735861242 -0.766599536 0.418878347 0.486688912 0.0800906 1 +-1.1651125 0.666666687 0.672677994 -0.775978625 0.444007844 0.448011458 0.0848333 1 +-1.21681392 0.633333385 0.635861218 -0.804784715 0.418878376 0.420550257 0.0824019 1 +-1.26291573 0.600000024 0.595811367 -0.830947042 0.39477554 0.39201957 0.08068 1 +-1.30383277 0.566666722 0.552768171 -0.854785085 0.371503353 0.362391561 0.0794901 1 +-1.33983111 0.533333361 0.506885231 -0.876526177 0.348910123 0.33160758 0.0787147 1 +-1.37105954 0.5 0.458248228 -0.896328866 0.326874524 0.299579352 0.0782822 1 +-1.3975662 0.466666698 0.406885207 -0.914296806 0.305296361 0.266186923 0.0781418 1 +-1.41930282 0.433333337 0.352768183 -0.93048656 0.284090787 0.231272742 0.0782662 1 +-1.43612075 0.400000036 0.295811385 -0.944908917 0.263183713 0.19463183 0.0786373 1 +-1.44775414 0.366666675 0.235861197 -0.957525492 0.242508501 0.155995473 0.079248 1 +-1.45378768 0.333333373 0.172677964 -0.968239605 0.222003922 0.115005545 0.0801062 1 +-1.47662163 0.266666681 0.1858612 -0.976618052 0.176369816 0.122926146 0.0767544 1 +-1.49385583 0.200000018 0.195811361 -0.982896209 0.131591856 0.128835887 0.074341 1 +-1.50590539 0.133333355 0.202768177 -0.987262726 0.0874125659 0.132933617 0.0726666 1 +-1.51303625 0.0666666776 0.206885189 -0.989838064 0.0436137691 0.135345623 0.0716081 1 +-1.51539719 7.4505806e-09 0.208248228 -0.990689278 4.87080909e-09 0.13614206 0.0710955 1 +-1.51303625 -0.0666666627 0.206885189 -0.989838064 -0.0436137617 0.135345623 0.0710955 1 +-1.50590539 -0.133333325 0.202768177 -0.987262726 -0.0874125436 0.132933617 0.0716081 1 +-1.49385583 -0.200000003 0.195811361 -0.982896209 -0.131591842 0.128835887 0.0726674 1 +-1.47662163 -0.266666681 0.1858612 -0.976618052 -0.176369816 0.122926146 0.074341 1 +-1.45378768 -0.333333343 0.172677964 -0.968239605 -0.222003907 0.115005545 0.0767544 1 +-1.44775414 -0.366666675 0.235861197 -0.957525492 -0.242508501 0.155995473 0.0758458 1 +-1.43612075 -0.400000036 0.295811385 -0.944908917 -0.263183713 0.19463183 0.075144 1 +-1.41930282 -0.433333367 0.352768183 -0.93048656 -0.284090817 0.231272742 0.0746373 1 +-1.3975662 -0.466666698 0.406885207 -0.914296806 -0.305296361 0.266186923 0.074329 1 +-1.37105954 -0.5 0.458248228 -0.896328866 -0.326874524 0.299579352 0.0742253 1 +-1.33983111 -0.533333361 0.506885231 -0.876526177 -0.348910123 0.33160758 0.0743506 1 +-1.30383277 -0.566666722 0.552768171 -0.854785085 -0.371503353 0.362391561 0.0747276 1 +-1.26291573 -0.600000024 0.595811367 -0.830947042 -0.39477554 0.39201957 0.0754048 1 +-1.21681392 -0.633333385 0.635861218 -0.804784715 -0.418878376 0.420550257 0.0764467 1 +-1.1651125 -0.666666687 0.672677994 -0.775978625 -0.444007844 0.448011458 0.0779568 1 +-1.15907896 -0.633333385 0.735861242 -0.766599536 -0.418878347 0.486688912 0.0743177 1 +-1.14744556 -0.600000024 0.795811415 -0.754972398 -0.39477554 0.523611486 0.0712682 1 +-1.13062763 -0.566666722 0.852768242 -0.741232812 -0.371503353 0.559069812 0.0686635 1 +-1.10889101 -0.533333361 0.906885207 -0.725443661 -0.348910123 0.59329015 0.0664077 1 +-1.08238447 -0.5 0.958248258 -0.707607746 -0.326874495 0.626453817 0.0644291 1 +-1.05115592 -0.466666698 1.00688529 -0.687672973 -0.305296361 0.658710837 0.0626769 1 +-1.01515758 -0.433333337 1.05276823 -0.665531397 -0.284090817 0.690188706 0.0611159 1 +-0.974240541 -0.400000036 1.09581137 -0.641010523 -0.263183713 0.720999181 0.0597111 1 +-0.928138793 -0.366666675 1.13586128 -0.613858759 -0.242508501 0.751243651 0.0584452 1 +-0.7908566 -0.366666704 1.18993473 -0.536147118 -0.248575151 0.806694984 0.0586215 1 +-0.818513989 -0.300000012 1.2059027 -0.550073862 -0.201611891 0.810414374 0.0562679 1 +-0.839776754 -0.233333349 1.21817875 -0.560645461 -0.155776262 0.813271344 0.0546147 1 +-0.85526979 -0.166666687 1.22712362 -0.568276584 -0.110740229 0.815351605 0.0535183 1 +-0.865397453 -0.100000016 1.23297083 -0.573232889 -0.066239275 0.81671077 0.0528895 1 +-0.870403767 -0.0333333462 1.2358613 -0.57567358 -0.0220462345 0.817382336 0.0526839 1 +-0.870403767 0.0333333239 1.2358613 -0.57567358 0.0220462196 0.817382336 0.0528895 1 +-0.865397453 0.099999994 1.23297083 -0.573232889 0.0662392601 0.81671077 0.0535183 1 +-0.85526979 0.166666657 1.22712362 -0.568276584 0.110740207 0.815351605 0.0546147 1 +-0.839776754 0.233333334 1.21817875 -0.560645461 0.155776247 0.813271344 0.0562679 1 +-0.818513989 0.300000012 1.2059027 -0.550073862 0.201611891 0.810414374 0.0586215 1 +-0.7908566 0.366666675 1.18993473 -0.536147118 0.248575121 0.806694984 0.0619322 1 +-0.847381473 0.400000006 1.15590262 -0.569473922 0.268815845 0.776812375 0.0631018 1 +-0.89751178 0.433333337 1.11817873 -0.599190116 0.289298773 0.746510148 0.0644856 1 +-0.941872358 0.466666698 1.07712364 -0.625818908 0.310072631 0.715685427 0.0660971 1 +-0.980867624 0.5 1.03297091 -0.649719417 0.331196278 0.684232235 0.0679518 1 +-1.0147413 0.533333361 0.985861242 -0.671136558 0.352739662 0.652035654 0.0700899 1 +-1.0436089 0.566666722 0.93586123 -0.690229118 0.37478587 0.618966281 0.0725746 1 +-1.06747019 0.600000024 0.88297087 -0.707084298 0.397435546 0.584873319 0.0754823 1 +-1.08620989 0.633333385 0.827123642 -0.721722782 0.420812875 0.54957515 0.0789327 1 +-1.09958434 0.666666687 0.768178701 -0.734096289 0.445075035 0.512845755 0.0831049 1 +-1.10718918 0.700000048 0.705902636 -0.744075 0.470427781 0.47439453 0.0882712 1 +-1.10839927 0.733333349 0.639934659 -0.751419485 0.497150242 0.433832288 0.0948841 1 +-1.16492414 0.700000048 0.605902612 -0.78287518 0.470427781 0.407190561 0.0908404 1 +-1.21505451 0.666666687 0.568178654 -0.811185598 0.445075005 0.379323155 0.087999 1 +-1.25941503 0.633333385 0.52712357 -0.83680737 0.420812845 0.350242674 0.085998 1 +-1.2984103 0.600000024 0.482970864 -0.860057294 0.397435546 0.319916308 0.0846262 1 +-1.33228397 0.566666722 0.4358612 -0.881155074 0.37478593 0.288272858 0.0837458 1 +-1.36115158 0.533333361 0.385861218 -0.900247693 0.352739632 0.255203515 0.0832685 1 +-1.38501287 0.5 0.332970858 -0.917422235 0.331196278 0.220557421 0.0831523 1 +-1.40375257 0.466666698 0.2771236 -0.932711244 0.31007266 0.184132382 0.0833609 1 +-1.41712713 0.433333367 0.218178645 -0.946091771 0.289298773 0.145658791 0.0838854 1 +-1.42473173 0.400000036 0.155902535 -0.957476199 0.268815875 0.10477268 0.0847397 1 +-1.42594194 0.366666704 0.0899346247 -0.966691852 0.248575151 0.0609695725 0.085957 1 +-1.45359933 0.300000012 0.10590259 -0.976876378 0.201611891 0.0711707398 0.0812364 1 +-1.4748621 0.233333349 0.118178643 -0.984636426 0.155776277 0.0788975433 0.0778803 1 +-1.49035513 0.166666687 0.127123579 -0.990253508 0.110740229 0.0844661519 0.0755257 1 +-1.5004828 0.100000016 0.132970795 -0.993908703 0.066239275 0.0880788714 0.0739637 1 +-1.50548911 0.0333333462 0.135861203 -0.995710671 0.0220462363 0.0898568109 0.0730694 1 +-1.50548911 -0.0333333239 0.135861203 -0.995710671 -0.0220462214 0.0898568109 0.0727782 1 +-1.5004828 -0.099999994 0.132970795 -0.993908703 -0.0662392601 0.0880788714 0.0730694 1 +-1.49035513 -0.166666657 0.127123579 -0.990253508 -0.110740207 0.0844661519 0.0739637 1 +-1.4748621 -0.233333334 0.118178643 -0.984636426 -0.155776262 0.0788975433 0.0755257 1 +-1.45359933 -0.300000012 0.10590259 -0.976876378 -0.201611891 0.0711707398 0.0778803 1 +-1.42594194 -0.366666675 0.0899346247 -0.966691852 -0.248575121 0.0609695725 0.0812364 1 +-1.42473185 -0.400000006 0.155902594 -0.957476258 -0.268815845 0.104772724 0.080107 1 +-1.41712713 -0.433333337 0.218178645 -0.946091771 -0.289298743 0.145658791 0.0792473 1 +-1.40375257 -0.466666698 0.2771236 -0.932711244 -0.31007266 0.184132382 0.0786373 1 +-1.38501287 -0.5 0.332970858 -0.917422235 -0.331196278 0.220557421 0.0782662 1 +-1.36115158 -0.533333361 0.385861218 -0.900247693 -0.352739632 0.255203515 0.0781418 1 +-1.33228397 -0.566666722 0.4358612 -0.881155074 -0.37478593 0.288272858 0.0782822 1 +-1.2984103 -0.600000024 0.482970864 -0.860057294 -0.397435546 0.319916308 0.0787147 1 +-1.25941503 -0.633333385 0.52712357 -0.83680737 -0.420812845 0.350242674 0.0794901 1 +-1.21505451 -0.666666687 0.568178654 -0.811185598 -0.445075005 0.379323155 0.08068 1 +-1.16492414 -0.700000048 0.605902612 -0.78287518 -0.470427781 0.407190561 0.0824019 1 +-1.10839927 -0.733333349 0.639934659 -0.751419485 -0.497150242 0.433832288 0.0848333 1 +-1.10718918 -0.700000048 0.705902636 -0.744075 -0.470427781 0.47439453 0.0800906 1 +-1.09958434 -0.666666687 0.768178701 -0.734096289 -0.445075035 0.512845755 0.0762271 1 +-1.08620989 -0.633333385 0.827123642 -0.721722782 -0.420812875 0.54957515 0.0730008 1 +-1.06747019 -0.600000024 0.88297087 -0.707084298 -0.397435546 0.584873319 0.0702625 1 +-1.0436089 -0.566666722 0.93586123 -0.690229118 -0.37478587 0.618966281 0.0679008 1 +-1.0147413 -0.533333361 0.985861242 -0.671136558 -0.352739662 0.652035654 0.0658394 1 +-0.980867624 -0.5 1.03297091 -0.649719417 -0.331196278 0.684232235 0.0640298 1 +-0.941872358 -0.466666698 1.07712364 -0.625818908 -0.310072631 0.715685427 0.0624262 1 +-0.89751178 -0.433333367 1.11817873 -0.599190056 -0.289298773 0.746510088 0.0610007 1 +-0.847381353 -0.400000036 1.15590262 -0.569473863 -0.268815875 0.776812375 0.0597391 1 +-0.692820191 -0.400000006 1.20000005 -0.480384409 -0.277350128 0.832050383 0.0609919 1 +-0.72698009 -0.333333343 1.21972215 -0.498430669 -0.228539348 0.836263537 0.05765 1 +-0.753434896 -0.266666651 1.23499584 -0.512174666 -0.181276321 0.83953321 0.0553296 1 +-0.773205042 -0.199999988 1.24641025 -0.522318482 -0.135104761 0.841979861 0.0537607 1 +-0.78693676 -0.133333325 1.25433826 -0.529301643 -0.0896813497 0.84368068 0.0527846 1 +-0.795030355 -0.0666666552 1.25901103 -0.533394098 -0.0447273478 0.844683528 0.0523136 1 +-0.797704816 1.49011612e-08 1.26055515 -0.534742594 9.98901495e-09 0.845014989 0.0523136 1 +-0.795030355 0.066666685 1.25901103 -0.533394098 0.0447273701 0.844683528 0.0527834 1 +-0.78693676 0.133333355 1.25433826 -0.529301643 0.089681372 0.84368068 0.0537607 1 +-0.773204923 0.200000018 1.24641013 -0.522318482 0.135104805 0.84197998 0.0553296 1 +-0.753434896 0.26666671 1.23499584 -0.512174666 0.181276366 0.83953321 0.0576479 1 +-0.72698009 0.333333373 1.21972215 -0.498430669 0.228539377 0.836263537 0.0609919 1 +-0.692820191 0.400000036 1.20000005 -0.480384409 0.277350128 0.832050383 0.0658711 1 +-0.755847573 0.433333337 1.1697222 -0.518222749 0.29710114 0.801982641 0.0666551 1 +-0.811169863 0.466666698 1.13499582 -0.551422119 0.317233622 0.771554589 0.0678261 1 +-0.859807551 0.5 1.09641016 -0.58082056 0.337761968 0.740651309 0.0693318 1 +-0.902406812 0.533333361 1.05433822 -0.606967986 0.358725429 0.709158599 0.071171 1 +-0.93936789 0.566666722 1.00901103 -0.630231619 0.380182564 0.676955938 0.0733684 1 +-0.970909894 0.600000024 0.960555136 -0.650850832 0.402210891 0.643909514 0.075977 1 +-0.997102916 0.633333385 0.909011006 -0.668966651 0.42490992 0.609864891 0.0790898 1 +-1.01787686 0.666666687 0.854338169 -0.684634328 0.448406786 0.574636519 0.0828432 1 +-1.03301251 0.700000048 0.796410143 -0.697824717 0.472866833 0.537994146 0.0874472 1 +-1.04210997 0.733333349 0.734995902 -0.708412051 0.498509943 0.499640107 0.093238 1 +-1.04452276 0.76666671 0.66972214 -0.716143668 0.525640547 0.45917359 0.100777 1 +-1.03923035 0.800000072 0.599999964 -0.720576644 0.554700255 0.416025162 0.111114 1 +-1.10225773 0.76666671 0.569722116 -0.755727768 0.525640547 0.390611768 0.103741 1 +-1.15758014 0.733333349 0.534995854 -0.786907017 0.498509884 0.363682806 0.0987829 1 +-1.20621765 0.700000048 0.496410102 -0.814828992 0.472866833 0.335336924 0.0953467 1 +-1.24881697 0.666666687 0.454338163 -0.839967012 0.448406786 0.305592477 0.0929648 1 +-1.28577805 0.633333385 0.409010977 -0.862641811 0.42490992 0.274409711 0.0913613 1 +-1.31732011 0.600000024 0.360555112 -0.883067429 0.402210891 0.241698638 0.0903733 1 +-1.34351313 0.566666722 0.309010983 -0.901376903 0.380182564 0.207318664 0.0899039 1 +-1.36428702 0.533333361 0.254338175 -0.917633295 0.358725429 0.171070442 0.0898966 1 +-1.3794229 0.5 0.196410134 -0.931833088 0.337761939 0.132679731 0.0903383 1 +-1.38852024 0.466666698 0.134995788 -0.943897009 0.317233622 0.0917682797 0.0912482 1 +-1.39093292 0.433333367 0.0697220936 -0.953648686 0.29710117 0.0478027239 0.0926967 1 +-1.3856405 0.400000006 -6.58440484e-08 -0.960768878 0.277350128 -4.56546374e-08 0.0948363 1 +-1.4198004 0.333333343 0.0197220985 -0.973440766 0.228539348 0.0135218268 0.0876204 1 +-1.44625521 0.266666651 0.0349957868 -0.983144403 0.181276321 0.0237896554 0.082678 1 +-1.46602535 0.199999988 0.0464101359 -0.990335286 0.13510479 0.0313511603 0.0792511 1 +-1.47975707 0.133333325 0.0543381497 -0.995299637 0.0896813497 0.036548391 0.0769337 1 +-1.48785067 0.0666666552 0.0590109751 -0.998214424 0.0447273478 0.039591074 0.0754902 1 +-1.49052513 -1.49011612e-08 0.060555093 -0.999175787 -9.98901584e-09 0.0405931994 0.0747978 1 +-1.48785067 -0.066666685 0.0590109751 -0.998214424 -0.0447273701 0.039591074 0.0747978 1 +-1.47975707 -0.133333355 0.0543381497 -0.995299637 -0.089681372 0.036548391 0.0754902 1 +-1.46602523 -0.200000018 0.0464100763 -0.990335226 -0.135104805 0.0313511193 0.076933 1 +-1.44625521 -0.26666671 0.0349957868 -0.983144403 -0.181276366 0.0237896554 0.0792518 1 +-1.4198004 -0.333333373 0.0197220985 -0.973440766 -0.228539377 0.0135218268 0.082678 1 +-1.3856405 -0.400000036 -6.58440484e-08 -0.960768878 -0.277350128 -4.56546374e-08 0.0876198 1 +-1.39093292 -0.433333337 0.0697220936 -0.953648686 -0.29710114 0.0478027239 0.0859584 1 +-1.38852024 -0.466666698 0.134995788 -0.943897009 -0.317233622 0.0917682797 0.0847383 1 +-1.3794229 -0.5 0.196410134 -0.931833088 -0.337761939 0.132679731 0.0838847 1 +-1.36428702 -0.533333361 0.254338175 -0.917633295 -0.358725429 0.171070442 0.0833609 1 +-1.34351313 -0.566666722 0.309010983 -0.901376903 -0.380182564 0.207318664 0.0831523 1 +-1.31732011 -0.600000024 0.360555112 -0.883067429 -0.402210891 0.241698638 0.0832685 1 +-1.28577805 -0.633333385 0.409010977 -0.862641811 -0.42490992 0.274409711 0.0837458 1 +-1.24881697 -0.666666687 0.454338163 -0.839967012 -0.448406786 0.305592477 0.0846262 1 +-1.20621765 -0.700000048 0.496410102 -0.814828992 -0.472866833 0.335336924 0.085998 1 +-1.15758014 -0.733333349 0.534995854 -0.786907017 -0.498509884 0.363682806 0.087999 1 +-1.10225773 -0.76666671 0.569722116 -0.755727768 -0.525640547 0.390611768 0.0908404 1 +-1.03923035 -0.800000072 0.599999964 -0.720576644 -0.554700255 0.416025162 0.0948841 1 +-1.04452276 -0.76666671 0.66972214 -0.716143668 -0.525640547 0.45917359 0.0882712 1 +-1.04210997 -0.733333349 0.734995902 -0.708412051 -0.498509943 0.499640107 0.0831049 1 +-1.03301251 -0.700000048 0.796410143 -0.697824717 -0.472866833 0.537994146 0.0789327 1 +-1.01787686 -0.666666687 0.854338169 -0.684634328 -0.448406786 0.574636519 0.0754823 1 +-0.997102916 -0.633333385 0.909011006 -0.668966651 -0.42490992 0.609864891 0.0725746 1 +-0.970909894 -0.600000024 0.960555136 -0.650850832 -0.402210891 0.643909514 0.0700899 1 +-0.93936789 -0.566666722 1.00901103 -0.630231619 -0.380182564 0.676955938 0.0679518 1 +-0.902406812 -0.533333361 1.05433822 -0.606967986 -0.358725429 0.709158599 0.0660971 1 +-0.859807551 -0.5 1.09641016 -0.58082056 -0.337761968 0.740651309 0.0644856 1 +-0.811169863 -0.466666698 1.13499582 -0.551422119 -0.317233622 0.771554589 0.0631018 1 +-0.755847573 -0.433333367 1.1697222 -0.518222749 -0.29710117 0.801982641 0.0619322 1 +-0.576386809 -0.433333337 1.19944382 -0.411845148 -0.309629291 0.857037485 0.0656216 1 +-0.620432734 -0.366666675 1.22487366 -0.436567724 -0.258005142 0.861882806 0.0603361 1 +-0.654239476 -0.300000012 1.24439204 -0.455108255 -0.208688855 0.865635812 0.0568374 1 +-0.679750144 -0.233333334 1.25912058 -0.468861312 -0.160942927 0.868485212 0.0544944 1 +-0.698112547 -0.166666657 1.2697221 -0.47863856 -0.114269666 0.870544374 0.0529842 1 +-0.710022867 -0.099999994 1.27659857 -0.484927177 -0.0682974011 0.87188369 0.0521366 1 +-0.715885103 -0.0333333239 1.27998316 -0.488007247 -0.0227227863 0.872543752 0.0518614 1 +-0.715885103 0.0333333462 1.27998316 -0.488007247 0.0227228012 0.872543752 0.0521366 1 +-0.710022867 0.100000016 1.27659857 -0.484927177 0.068297416 0.87188369 0.0529842 1 +-0.698112547 0.166666687 1.2697221 -0.47863856 0.114269689 0.870544374 0.0544944 1 +-0.679750144 0.233333349 1.25912058 -0.468861312 0.160942927 0.868485212 0.0568374 1 +-0.654239476 0.300000012 1.24439204 -0.455108255 0.208688855 0.865635812 0.0603361 1 +-0.620432734 0.366666704 1.22487366 -0.436567724 0.258005142 0.861882806 0.0656207 1 +-0.576386809 0.433333367 1.19944382 -0.411845148 0.309629291 0.857037485 0.0740749 1 +-0.649300218 0.466666698 1.17487371 -0.456880331 0.328370184 0.82670033 0.0733351 1 +-0.711974502 0.5 1.14439213 -0.495270461 0.347814739 0.7960729 0.0736865 1 +-0.766352654 0.533333361 1.10912061 -0.528595865 0.367869556 0.76502192 0.0747428 1 +-0.81358248 0.566666722 1.06972206 -0.557806849 0.388516963 0.733420789 0.0763616 1 +-0.854360461 0.600000024 1.02659857 -0.583505988 0.409784406 0.701140106 0.078509 1 +-0.88909018 0.633333385 0.979983151 -0.606078327 0.431733102 0.668038607 0.0812173 1 +-0.917957842 0.666666687 0.929983199 -0.625756979 0.454455853 0.633954465 0.084574 1 +-0.94096297 0.700000048 0.876598597 -0.642653227 0.478081822 0.598694026 0.0887412 1 +-0.957920194 0.733333349 0.819722116 -0.656767368 0.502786577 0.562016249 0.0939859 1 +-0.968425274 0.76666671 0.759120643 -0.667976499 0.528812468 0.523607492 0.100753 1 +-0.971782148 0.800000072 0.694392025 -0.676000297 0.556503654 0.483039558 0.109837 1 +-0.96684289 0.833333373 0.624873698 -0.680319369 0.586375296 0.439692587 0.1228 1 +-0.951664507 0.866666734 0.549443781 -0.679991961 0.619258583 0.392593563 0.143336 1 +-1.02457798 0.833333373 0.524873674 -0.720944583 0.586375296 0.369327515 0.126463 1 +-1.08725226 0.800000072 0.494392008 -0.756324708 0.556503654 0.343913645 0.116452 1 +-1.14163041 0.76666671 0.459120601 -0.787445664 0.528812468 0.316680878 0.109959 1 +-1.1888603 0.733333349 0.41972211 -0.815104067 0.502786577 0.287769049 0.105592 1 +-1.2296381 0.700000048 0.376598567 -0.839810908 0.478081852 0.257207036 0.10265 1 +-1.26436806 0.666666687 0.329983175 -0.861899137 0.454455823 0.224944159 0.100755 1 +-1.29323542 0.633333385 0.279983103 -0.881577611 0.431733102 0.190859944 0.0996925 1 +-1.31624067 0.600000024 0.226598591 -0.898958147 0.409784406 0.154760942 0.0993554 1 +-1.33319783 0.566666722 0.169722036 -0.914064467 0.388516933 0.116364487 0.0997069 1 +-1.34370303 0.533333361 0.10912057 -0.926826298 0.367869526 0.0752664953 0.100786 1 +-1.34705985 0.50000006 0.0443919711 -0.937054634 0.347814798 0.0308803655 0.102738 1 +-1.34212065 0.466666669 -0.0251263436 -0.944383562 0.328370154 -0.0176801588 0.105888 1 +-1.32694221 0.433333337 -0.100556247 -0.948138833 0.309629291 -0.0718503669 0.110988 1 +-1.37098813 0.366666675 -0.0751263425 -0.964696229 0.258005112 -0.052862674 0.0979935 1 +-1.40479493 0.300000012 -0.0556080267 -0.97721678 0.208688855 -0.0386825837 0.08988 1 +-1.43030548 0.233333334 -0.0408794209 -0.986560881 0.160942927 -0.0281968005 0.0845126 1 +-1.448668 0.166666657 -0.0302779004 -0.993232906 0.114269666 -0.020759074 0.0809192 1 +-1.4605782 0.099999994 -0.0234014317 -0.997537017 0.0682974011 -0.0159825701 0.0786055 1 +-1.46644044 0.0333333239 -0.0200169012 -0.999648631 0.0227227863 -0.0136451973 0.0773043 1 +-1.46644044 -0.0333333462 -0.0200169012 -0.999648631 -0.0227228012 -0.0136451973 0.0768841 1 +-1.4605782 -0.100000016 -0.0234014317 -0.997537017 -0.068297416 -0.0159825701 0.0773043 1 +-1.448668 -0.166666687 -0.0302779004 -0.993232906 -0.114269689 -0.020759074 0.0786055 1 +-1.43030548 -0.233333349 -0.0408794209 -0.986560881 -0.160942927 -0.0281968005 0.0809192 1 +-1.40479493 -0.300000012 -0.0556080267 -0.97721678 -0.208688855 -0.0386825837 0.0845126 1 +-1.37098813 -0.366666704 -0.0751263425 -0.964696229 -0.258005142 -0.052862674 0.08988 1 +-1.32694221 -0.433333367 -0.100556247 -0.948138833 -0.309629291 -0.0718503669 0.0979929 1 +-1.34212065 -0.466666698 -0.0251263436 -0.944383562 -0.328370154 -0.0176801588 0.0948363 1 +-1.34705985 -0.5 0.0443920307 -0.937054515 -0.347814739 0.0308804046 0.092696 1 +-1.34370303 -0.533333361 0.10912057 -0.926826298 -0.367869526 0.0752664953 0.0912482 1 +-1.33319783 -0.566666722 0.169722036 -0.914064467 -0.388516933 0.116364487 0.0903383 1 +-1.31624067 -0.600000024 0.226598591 -0.898958147 -0.409784406 0.154760942 0.0898966 1 +-1.29323542 -0.633333385 0.279983103 -0.881577611 -0.431733102 0.190859944 0.0899039 1 +-1.26436806 -0.666666687 0.329983175 -0.861899137 -0.454455823 0.224944159 0.0903733 1 +-1.2296381 -0.700000048 0.376598567 -0.839810908 -0.478081852 0.257207036 0.0913613 1 +-1.1888603 -0.733333349 0.41972211 -0.815104067 -0.502786577 0.287769049 0.0929648 1 +-1.14163041 -0.76666671 0.459120601 -0.787445664 -0.528812468 0.316680878 0.0953467 1 +-1.08725226 -0.800000072 0.494392008 -0.756324708 -0.556503654 0.343913645 0.0987829 1 +-1.02457798 -0.833333373 0.524873674 -0.720944583 -0.586375296 0.369327515 0.103741 1 +-0.951664507 -0.866666734 0.549443781 -0.679991961 -0.619258583 0.392593563 0.111114 1 +-0.96684289 -0.833333373 0.624873698 -0.680319369 -0.586375296 0.439692587 0.100777 1 +-0.971782148 -0.800000072 0.694392025 -0.676000297 -0.556503654 0.483039558 0.093238 1 +-0.968425274 -0.76666671 0.759120643 -0.667976499 -0.528812468 0.523607492 0.0874472 1 +-0.957920194 -0.733333349 0.819722116 -0.656767368 -0.502786577 0.562016249 0.0828432 1 +-0.94096297 -0.700000048 0.876598597 -0.642653227 -0.478081822 0.598694026 0.0790898 1 +-0.917957842 -0.666666687 0.929983199 -0.625756979 -0.454455853 0.633954465 0.075977 1 +-0.88909018 -0.633333385 0.979983151 -0.606078327 -0.431733102 0.668038607 0.0733684 1 +-0.854360461 -0.600000024 1.02659857 -0.583505988 -0.409784406 0.701140106 0.071171 1 +-0.81358248 -0.566666722 1.06972206 -0.557806849 -0.388516963 0.733420789 0.0693318 1 +-0.766352654 -0.533333361 1.10912061 -0.528595865 -0.367869556 0.76502192 0.0678261 1 +-0.711974502 -0.50000006 1.14439201 -0.495270461 -0.347814769 0.796072841 0.0666551 1 +-0.649300218 -0.466666669 1.17487371 -0.456880331 -0.328370154 0.82670033 0.0658711 1 +-0.426382512 -0.466666698 1.17950547 -0.31862089 -0.348723888 0.881403625 0.0770384 1 +-0.489635676 -0.400000006 1.21602464 -0.357249945 -0.291849613 0.887240827 0.0663025 1 +-0.535787344 -0.333333343 1.2426703 -0.384434313 -0.239170954 0.891631901 0.0601133 1 +-0.570076108 -0.266666681 1.26246691 -0.40412429 -0.189038768 0.894956887 0.0562319 1 +-0.595053196 -0.200000003 1.27688754 -0.418209255 -0.140561983 0.897409141 0.0537629 1 +-0.612125516 -0.133333325 1.28674424 -0.427716255 -0.0931652561 0.899098992 0.0522828 1 +-0.622092724 -0.0666666627 1.29249883 -0.433222592 -0.0464263633 0.900090396 0.0515882 1 +-0.625371933 7.4505806e-09 1.29439199 -0.435027182 5.18284393e-09 0.900417328 0.0515882 1 +-0.622092724 0.0666666776 1.29249883 -0.433222592 0.0464263745 0.900090396 0.0522828 1 +-0.612125516 0.133333355 1.28674424 -0.427716255 0.0931652784 0.899098992 0.0537629 1 +-0.595053196 0.200000018 1.27688754 -0.418209255 0.140561983 0.897409141 0.0562319 1 +-0.570076108 0.266666681 1.26246691 -0.40412429 0.189038768 0.894956887 0.0601133 1 +-0.535787344 0.333333373 1.2426703 -0.384434313 0.239170983 0.891631901 0.0663007 1 +-0.489635676 0.400000036 1.21602464 -0.357249945 0.291849643 0.887240827 0.0770384 1 +-0.426382512 0.466666698 1.17950547 -0.31862089 0.348723888 0.881403625 0.100344 1 +-0.518503189 0.50000006 1.16602468 -0.378312349 0.364812016 0.850759566 0.0895587 1 +-0.59352231 0.533333361 1.14267039 -0.425859869 0.382673532 0.819880664 0.085982 1 +-0.656678617 0.566666663 1.11246693 -0.465516388 0.401707351 0.788622618 0.0851058 1 +-0.710523248 0.600000024 1.07688749 -0.499362797 0.421685964 0.756847203 0.0857206 1 +-0.756462991 0.633333385 1.03674412 -0.528570592 0.442535073 0.72441411 0.087396 1 +-0.795297861 0.666666687 0.992498815 -0.553841889 0.464263678 0.691171706 0.0900107 1 +-0.827444553 0.700000048 0.944392025 -0.575594842 0.486940712 0.656947017 0.0936092 1 +-0.853032887 0.733333349 0.892498791 -0.594048262 0.510690033 0.621532142 0.0983699 1 +-0.871933043 0.76666671 0.83674413 -0.609254062 0.535700321 0.584666193 0.104667 1 +-0.883728266 0.800000072 0.776887417 -0.621092975 0.562247992 0.546004176 0.113183 1 +-0.887618601 0.833333373 0.712466896 -0.629228711 0.590746164 0.505064487 0.12526 1 +-0.882197499 0.866666734 0.642670333 -0.632988036 0.62184453 0.461124212 0.143925 1 +-0.864913344 0.900000036 0.566024661 -0.631061554 0.65666163 0.412985206 0.178323 1 +-0.830527723 0.933333397 0.47950542 -0.620624602 0.697447777 0.358317822 0.118789 1 +-0.92264843 0.900000036 0.466024637 -0.673186421 0.65666163 0.340022743 0.183761 1 +-0.997667551 0.866666734 0.442670316 -0.715839267 0.62184453 0.317621648 0.152746 1 +-1.06082368 0.833333373 0.412466854 -0.752013028 0.590746164 0.29239586 0.136883 1 +-1.11466837 0.800000072 0.376887411 -0.783400059 0.562248051 0.26488024 0.127357 1 +-1.16060817 0.76666671 0.3367441 -0.810962796 0.535700321 0.235296413 0.121288 1 +-1.1994431 0.733333349 0.292498767 -0.835286796 0.510690033 0.203694835 0.117425 1 +-1.23158979 0.700000048 0.244391993 -0.856730163 0.486940682 0.170006275 0.115158 1 +-1.25717807 0.666666687 0.192498773 -0.875493169 0.464263678 0.134055287 0.11419 1 +-1.27607822 0.633333385 0.136744097 -0.891646326 0.442535073 0.0955485031 0.114422 1 +-1.28787363 0.600000024 0.0768874511 -0.905130267 0.421685934 0.054037258 0.115938 1 +-1.29176378 0.566666722 0.0124668283 -0.91572541 0.401707411 0.00883767754 0.119067 1 +-1.28634274 0.533333361 -0.0573297217 -0.922967434 0.382673532 -0.0411348119 0.124635 1 +-1.26905859 0.5 -0.133975372 -0.925935626 0.364812016 -0.0977516547 0.13482 1 +-1.2346729 0.466666698 -0.220494613 -0.922628343 0.348723888 -0.164767995 0.157429 1 +-1.29792607 0.400000006 -0.183975384 -0.94699806 0.291849613 -0.134232864 0.120117 1 +-1.34407771 0.333333343 -0.157329723 -0.96439302 0.239170954 -0.112886101 0.102962 1 +-1.37836647 0.266666681 -0.137533113 -0.977117538 0.189038768 -0.0974965841 0.0930835 1 +-1.40334368 0.200000003 -0.123112537 -0.986283779 0.140561983 -0.0865247026 0.0868948 1 +-1.420416 0.133333325 -0.113255836 -0.992500663 0.0931652486 -0.0791363195 0.0829626 1 +-1.43038321 0.0666666627 -0.107501246 -0.996112466 0.0464263633 -0.0748633891 0.080606 1 +-1.43366241 -7.4505806e-09 -0.105608024 -0.997297823 -5.18284349e-09 -0.0734640509 0.0794984 1 +-1.43038321 -0.0666666776 -0.107501246 -0.996112466 -0.0464263745 -0.0748633891 0.0794984 1 +-1.420416 -0.133333355 -0.113255836 -0.992500663 -0.093165271 -0.0791363195 0.080606 1 +-1.40334368 -0.200000018 -0.123112537 -0.986283779 -0.140561983 -0.0865247026 0.0829619 1 +-1.37836647 -0.266666681 -0.137533113 -0.977117538 -0.189038768 -0.0974965841 0.0868948 1 +-1.34407771 -0.333333373 -0.157329723 -0.96439302 -0.239170983 -0.112886101 0.0930835 1 +-1.29792607 -0.400000036 -0.183975384 -0.94699806 -0.291849643 -0.134232864 0.102961 1 +-1.2346729 -0.466666698 -0.220494613 -0.922628343 -0.348723888 -0.164767995 0.120117 1 +-1.26905859 -0.50000006 -0.133975372 -0.925935626 -0.364812046 -0.0977516547 0.110987 1 +-1.28634274 -0.533333361 -0.0573297217 -0.922967434 -0.382673532 -0.0411348119 0.105888 1 +-1.29176402 -0.566666663 0.0124668879 -0.91572541 -0.401707321 0.00883771759 0.102739 1 +-1.28787363 -0.600000024 0.0768874511 -0.905130267 -0.421685934 0.054037258 0.100786 1 +-1.27607822 -0.633333385 0.136744097 -0.891646326 -0.442535073 0.0955485031 0.0997069 1 +-1.25717807 -0.666666687 0.192498773 -0.875493169 -0.464263678 0.134055287 0.0993554 1 +-1.23158979 -0.700000048 0.244391993 -0.856730163 -0.486940682 0.170006275 0.0996925 1 +-1.1994431 -0.733333349 0.292498767 -0.835286796 -0.510690033 0.203694835 0.100755 1 +-1.16060817 -0.76666671 0.3367441 -0.810962796 -0.535700321 0.235296413 0.10265 1 +-1.11466837 -0.800000072 0.376887411 -0.783400059 -0.562248051 0.26488024 0.105592 1 +-1.06082368 -0.833333373 0.412466854 -0.752013028 -0.590746164 0.29239586 0.109959 1 +-0.997667551 -0.866666734 0.442670316 -0.715839267 -0.62184453 0.317621648 0.116452 1 +-0.92264843 -0.900000036 0.466024637 -0.673186421 -0.65666163 0.340022743 0.126463 1 +-0.830527723 -0.933333397 0.47950542 -0.620624602 -0.697447777 0.358317822 0.143336 1 +-0.864913344 -0.900000036 0.566024661 -0.631061554 -0.65666163 0.412985206 0.1228 1 +-0.882197499 -0.866666734 0.642670333 -0.632988036 -0.62184453 0.461124212 0.109837 1 +-0.887618601 -0.833333373 0.712466896 -0.629228711 -0.590746164 0.505064487 0.100753 1 +-0.883728266 -0.800000072 0.776887417 -0.621092975 -0.562247992 0.546004176 0.0939859 1 +-0.871933043 -0.76666671 0.83674413 -0.609254062 -0.535700321 0.584666193 0.0887412 1 +-0.853032887 -0.733333349 0.892498791 -0.594048262 -0.510690033 0.621532142 0.084574 1 +-0.827444553 -0.700000048 0.944392025 -0.575594842 -0.486940712 0.656947017 0.0812173 1 +-0.795297861 -0.666666687 0.992498815 -0.553841889 -0.464263678 0.691171706 0.078509 1 +-0.756462991 -0.633333385 1.03674412 -0.528570592 -0.442535073 0.72441411 0.0763616 1 +-0.710523248 -0.600000024 1.07688749 -0.499362797 -0.421685964 0.756847203 0.0747428 1 +-0.656678498 -0.566666722 1.11246693 -0.465516359 -0.401707411 0.788622677 0.0736865 1 +-0.59352231 -0.533333361 1.14267039 -0.425859869 -0.382673532 0.819880664 0.0733359 1 +-0.518503189 -0.5 1.16602468 -0.378312379 -0.364812016 0.850759625 0.0740765 1 +-0.302626967 -0.433333397 1.17472184 -0.234931335 -0.336399615 0.911944449 0.0870656 1 +-0.380994439 -0.366666704 1.21996725 -0.286541253 -0.275765538 0.91752243 0.0692784 1 +-0.433012545 -0.300000042 1.25 -0.319221079 -0.221162975 0.921512246 0.0607881 1 +-0.469573259 -0.233333379 1.27110827 -0.341504693 -0.169695452 0.924433947 0.05598 1 +-0.494850755 -0.166666701 1.28570223 -0.356600195 -0.120103642 0.92650491 0.0531639 1 +-0.510866523 -0.100000031 1.29494894 -0.366038412 -0.07165052 0.927837372 0.0516656 1 +-0.518651783 -0.0333333611 1.29944384 -0.370591789 -0.0238176566 0.92849046 0.0511937 1 +-0.518651783 0.033333309 1.29944384 -0.370591789 0.0238176193 0.92849046 0.0516656 1 +-0.510866523 0.0999999791 1.29494894 -0.366038412 0.0716504827 0.927837372 0.0531662 1 +-0.494850755 0.166666657 1.28570223 -0.356600195 0.120103613 0.92650491 0.055981 1 +-0.469573259 0.233333319 1.27110827 -0.341504693 0.169695407 0.924433947 0.0607881 1 +-0.433012545 0.299999982 1.25 -0.319221079 0.22116293 0.921512246 0.0692784 1 +-0.380994439 0.366666675 1.21996725 -0.286541253 0.275765508 0.91752243 0.0870642 1 +-0.302627087 0.433333337 1.17472184 -0.234931409 0.336399555 0.91194433 0.0870642 1 +-0.3314946 0.533333361 1.12472188 -0.257341444 0.414030224 0.87312907 0.100344 1 +-0.438729405 0.566666722 1.11996722 -0.329963058 0.426183134 0.842313707 0.131075 1 +-0.519615054 0.600000024 1.10000002 -0.383065313 0.44232589 0.810930789 0.11316 1 +-0.585043311 0.633333325 1.07110834 -0.425482094 0.460601777 0.778980613 0.107453 1 +-0.63918829 0.666666687 1.03570223 -0.460612953 0.48041448 0.746349514 0.10624 1 +-0.6840716 0.700000048 0.994948983 -0.490140676 0.501553476 0.712885857 0.10764 1 +-0.720724523 0.733333349 0.949443877 -0.514978588 0.523987949 0.678405225 0.111132 1 +-0.749591887 0.76666671 0.899443805 -0.535605192 0.547805667 0.642678797 0.116796 1 +-0.770674169 0.800000072 0.844948947 -0.552191854 0.573203981 0.605410099 0.125227 1 +-0.783525884 0.833333373 0.785702229 -0.56462574 0.600518107 0.566194057 0.137869 1 +-0.787115932 0.866666734 0.721108258 -0.57244271 0.630297303 0.524437547 0.158262 1 +-0.7794227 0.900000036 0.649999976 -0.574598074 0.663488865 0.479186356 0.125665 1 +-0.756272137 0.933333397 0.56996727 -0.568782985 0.701948583 0.42866537 0.0785295 1 +-0.706772327 0.966666698 0.474721909 -0.54867202 0.750429749 0.368529767 0.100757 1 +-0.764507413 0.966666698 0.374721885 -0.59349215 0.75042969 0.290899068 0.118599 1 +-0.871742189 0.933333397 0.369967252 -0.655626655 0.701948643 0.278247833 0.107222 1 +-0.952627838 0.900000036 0.349999934 -0.702286601 0.663488865 0.258023381 0.0860174 1 +-1.01805604 0.866666734 0.321108252 -0.740397513 0.630297184 0.233531103 0.178503 1 +-1.07220101 0.833333373 0.285702199 -0.772651315 0.600518107 0.205883205 0.160172 1 +-1.11708438 0.800000012 0.244948924 -0.800396562 0.573203981 0.175507128 0.149904 1 +-1.15373707 0.76666671 0.199443772 -0.824378729 0.547805667 0.142508373 0.144125 1 +-1.18260479 0.733333349 0.149443835 -0.845005453 0.523987949 0.10678196 0.14146 1 +-1.20368695 0.700000048 0.0949489027 -0.862447619 0.501553476 0.0680313557 0.141455 1 +-1.21653867 0.666666687 0.035702195 -0.876664162 0.48041448 0.0257277768 0.144298 1 +-1.22012866 0.633333385 -0.0288917627 -0.887358189 0.460601896 -0.0210119989 0.151062 1 +-1.21243548 0.600000024 -0.100000091 -0.893819332 0.44232589 -0.0737210438 0.164999 1 +-1.1892848 0.566666663 -0.180032775 -0.894446611 0.426183105 -0.135400459 0.10106 1 +-1.13978505 0.533333361 -0.275278181 -0.884822667 0.414030224 -0.21370028 0.131894 1 +-1.16865242 0.433333397 -0.325278252 -0.907232642 0.336399585 -0.252515674 0.154905 1 +-1.24701989 0.366666704 -0.280032784 -0.937868416 0.275765538 -0.210609227 0.141906 1 +-1.29903793 0.300000042 -0.250000089 -0.957663596 0.22116299 -0.184302524 0.112296 1 +-1.33559871 0.233333379 -0.22889176 -0.971335649 0.169695452 -0.166465208 0.098187 1 +-1.3608762 0.166666701 -0.214297801 -0.980676949 0.120103642 -0.154427648 0.0902054 1 +-1.37689197 0.100000031 -0.205051094 -0.986549973 0.07165052 -0.14692013 0.0855387 1 +-1.38467717 0.0333333611 -0.200556248 -0.989392221 0.0238176584 -0.14330329 0.0830518 1 +-1.38467717 -0.033333309 -0.200556248 -0.989392221 -0.0238176212 -0.14330329 0.0822671 1 +-1.37689197 -0.0999999791 -0.205051094 -0.986549973 -0.0716504827 -0.14692013 0.0830518 1 +-1.3608762 -0.166666657 -0.214297801 -0.980676949 -0.120103613 -0.154427648 0.0855387 1 +-1.33559871 -0.233333319 -0.22889176 -0.971335649 -0.169695407 -0.166465208 0.0902061 1 +-1.29903793 -0.299999982 -0.250000089 -0.957663596 -0.221162945 -0.184302524 0.0981876 1 +-1.24701989 -0.366666675 -0.280032784 -0.937868416 -0.275765508 -0.210609227 0.112297 1 +-1.16865253 -0.433333337 -0.325278193 -0.907232702 -0.336399555 -0.252515614 0.141907 1 +-1.13978505 -0.533333361 -0.275278181 -0.884822667 -0.414030224 -0.21370028 0.157429 1 +-1.1892848 -0.566666722 -0.180032805 -0.894446552 -0.426183105 -0.135400474 0.13482 1 +-1.21243548 -0.600000024 -0.100000091 -0.893819332 -0.44232589 -0.0737210438 0.124635 1 +-1.22012866 -0.633333325 -0.0288917627 -0.887358189 -0.460601836 -0.0210119989 0.119068 1 +-1.21653867 -0.666666687 0.035702195 -0.876664162 -0.48041448 0.0257277768 0.115938 1 +-1.20368695 -0.700000048 0.0949489027 -0.862447619 -0.501553476 0.0680313557 0.114422 1 +-1.18260479 -0.733333349 0.149443835 -0.845005453 -0.523987949 0.10678196 0.11419 1 +-1.15373707 -0.76666671 0.199443772 -0.824378729 -0.547805667 0.142508373 0.115158 1 +-1.11708438 -0.800000072 0.244948924 -0.800396442 -0.573203981 0.175507113 0.117426 1 +-1.07220101 -0.833333373 0.285702199 -0.772651315 -0.600518107 0.205883205 0.121288 1 +-1.01805604 -0.866666734 0.321108252 -0.740397513 -0.630297184 0.233531103 0.127357 1 +-0.952627838 -0.900000036 0.349999934 -0.702286601 -0.663488865 0.258023381 0.136883 1 +-0.871742189 -0.933333397 0.369967252 -0.655626655 -0.701948643 0.278247833 0.152746 1 +-0.764507413 -0.966666698 0.374721885 -0.59349215 -0.75042969 0.290899068 0.183761 1 +-0.706772327 -0.966666698 0.474721909 -0.54867202 -0.750429749 0.368529767 0.178323 1 +-0.756272137 -0.933333397 0.56996727 -0.568782985 -0.701948583 0.42866537 0.143925 1 +-0.7794227 -0.900000036 0.649999976 -0.574598074 -0.663488865 0.479186356 0.12526 1 +-0.787115932 -0.866666734 0.721108258 -0.57244271 -0.630297303 0.524437547 0.113183 1 +-0.783525884 -0.833333373 0.785702229 -0.56462574 -0.600518107 0.566194057 0.104667 1 +-0.770674169 -0.800000012 0.844948947 -0.552191913 -0.573203981 0.605410159 0.0983705 1 +-0.749591887 -0.76666671 0.899443805 -0.535605192 -0.547805667 0.642678797 0.0936092 1 +-0.720724523 -0.733333349 0.949443877 -0.514978588 -0.523987949 0.678405225 0.0900107 1 +-0.6840716 -0.700000048 0.994948983 -0.490140676 -0.501553476 0.712885857 0.087396 1 +-0.63918829 -0.666666687 1.03570223 -0.460612953 -0.48041448 0.746349514 0.0857206 1 +-0.585043311 -0.633333385 1.07110834 -0.425482094 -0.460601807 0.778980613 0.0851079 1 +-0.519615054 -0.600000024 1.10000002 -0.383065313 -0.44232589 0.810930789 0.085982 1 +-0.438729465 -0.566666663 1.11996722 -0.329963088 -0.426183105 0.842313707 0.0895593 1 +-0.3314946 -0.533333361 1.12472188 -0.257341444 -0.414030224 0.87312907 0.100344 1 +-0.221034139 -0.333333343 1.19428086 -0.175497234 -0.264660835 0.948238015 0.0838683 1 +-0.295782417 -0.266666681 1.23743677 -0.227535158 -0.205137432 0.951917231 0.0646989 1 +-0.340577573 -0.200000018 1.26329923 -0.257311463 -0.15110302 0.954441547 0.0567439 1 +-0.368647486 -0.13333334 1.27950549 -0.275477499 -0.0996353924 0.956130207 0.0528297 1 +-0.384333581 -0.0666666701 1.28856182 -0.285472006 -0.0495180972 0.957106948 0.0511541 1 +-0.389397413 0 1.29148543 -0.28867507 0 0.957427144 0.0511541 1 +-0.384333581 0.0666666701 1.28856182 -0.285472006 0.0495180972 0.957106948 0.0528297 1 +-0.368647486 0.13333334 1.27950549 -0.275477499 0.0996353924 0.956130207 0.0567439 1 +-0.340577573 0.200000018 1.26329923 -0.257311463 0.15110302 0.954441547 0.0646989 1 +-0.295782417 0.266666681 1.23743677 -0.227535158 0.205137432 0.951917231 0.0646989 1 +-0.307636559 0.633333385 1.04428077 -0.244258046 0.502855599 0.829140663 0.131075 1 +-0.411252409 0.666666746 1.03743672 -0.316362232 0.512843609 0.798064113 0.0869064 1 +-0.484915137 0.700000048 1.01329923 -0.366360664 0.528860569 0.765562832 0.0674 1 +-0.541852713 0.733333349 0.979505539 -0.404907763 0.547994614 0.731950521 0.0594388 1 +-0.586406112 0.76666671 0.938561797 -0.43556571 0.569458127 0.697136879 0.0556884 1 +-0.620337486 0.800000072 0.891485393 -0.459879726 0.593070388 0.66089195 0.0543191 1 +-0.644141138 0.833333373 0.838561773 -0.478449672 0.618976295 0.622859776 0.0548032 1 +-0.657322645 0.866666734 0.779505432 -0.491194457 0.647630036 0.582497418 0.0572066 1 +-0.658120215 0.900000036 0.713299274 -0.497219712 0.679963589 0.538908303 0.0622539 1 +-0.642192602 0.933333397 0.637436748 -0.494016469 0.717980981 0.490357965 0.0721393 1 +-0.873132706 0.933333397 0.237436756 -0.671670675 0.717980981 0.182651863 0.137311 1 +-0.946795404 0.900000036 0.21329923 -0.715318143 0.679963589 0.161150783 0.0838292 1 +-1.00373292 0.866666675 0.179505467 -0.750054836 0.647629976 0.134138212 0.0740717 1 +-1.04828632 0.833333373 0.138561741 -0.77863723 0.618976295 0.102919713 0.0695783 1 +-1.08221769 0.800000072 0.0914853439 -0.802289069 0.593070388 0.0678215548 0.0681096 1 +-1.1060214 0.76666671 0.038561713 -0.821521163 0.569458187 0.0286425408 0.0690429 1 +-1.11920297 0.733333349 -0.0204945542 -0.836341679 0.547994614 -0.0153148714 0.0725376 1 +-1.12000048 0.700000048 -0.0867007896 -0.84617722 0.528860569 -0.0655037537 0.0796273 1 +-1.10407281 0.666666687 -0.162563264 -0.849324942 0.512843609 -0.125054285 0.0933819 1 +-1.21954286 0.266666681 -0.362563252 -0.938152075 0.205137432 -0.278907359 0.175696 1 +-1.26433802 0.200000018 -0.336700767 -0.955226362 0.15110302 -0.254382491 0.109631 1 +-1.29240799 0.13333334 -0.320494592 -0.965771794 0.0996353924 -0.239494517 0.0958525 1 +-1.30809402 0.0666666701 -0.311438233 -0.971614897 0.0495180972 -0.231327429 0.0890802 1 +-1.31315792 0 -0.308514625 -0.973493814 0 -0.228713602 0.0861824 1 +-1.30809402 -0.0666666701 -0.311438233 -0.971614897 -0.0495180972 -0.231327429 0.0861824 1 +-1.29240799 -0.13333334 -0.320494592 -0.965771794 -0.0996353924 -0.239494517 0.0890802 1 +-1.26433802 -0.200000018 -0.336700767 -0.955226362 -0.15110302 -0.254382491 0.0958525 1 +-1.21954286 -0.266666681 -0.362563252 -0.938152075 -0.205137432 -0.278907359 0.109631 1 +-1.14479458 -0.333333343 -0.405719191 -0.908946812 -0.264660835 -0.322133929 0.142895 1 +-1.05819201 -0.633333385 -0.255719304 -0.84018594 -0.502855599 -0.203036651 0.198882 1 +-1.10407281 -0.666666746 -0.162563324 -0.849324942 -0.512843609 -0.12505433 0.164999 1 +-1.12000048 -0.700000048 -0.0867007896 -0.84617722 -0.528860569 -0.0655037537 0.151062 1 +-1.11920297 -0.733333349 -0.0204945542 -0.836341679 -0.547994614 -0.0153148714 0.144298 1 +-1.1060214 -0.76666671 0.038561713 -0.821521163 -0.569458187 0.0286425408 0.141455 1 +-1.08221769 -0.800000072 0.0914853439 -0.802289069 -0.593070388 0.0678215548 0.14146 1 +-1.04828632 -0.833333373 0.138561741 -0.77863723 -0.618976295 0.102919713 0.144125 1 +-1.0037328 -0.866666734 0.179505408 -0.750054777 -0.647630036 0.134138182 0.149905 1 +-0.946795404 -0.900000036 0.21329923 -0.715318143 -0.679963589 0.161150783 0.160172 1 +-0.873132706 -0.933333397 0.237436756 -0.671670675 -0.717980981 0.182651863 0.178503 1 +-0.769516945 -0.966666698 0.244280815 -0.610982955 -0.767516375 0.193954676 0.217237 1 +-0.596311808 -0.966666698 0.544280827 -0.473461121 -0.767516375 0.43214941 0.198343 1 +-0.642192602 -0.933333397 0.637436748 -0.494016469 -0.717980981 0.490357965 0.158262 1 +-0.658120215 -0.900000036 0.713299274 -0.497219712 -0.679963589 0.538908303 0.137869 1 +-0.657322764 -0.866666675 0.779505491 -0.491194516 -0.647629976 0.582497418 0.125227 1 +-0.644141138 -0.833333373 0.838561773 -0.478449672 -0.618976295 0.622859776 0.116796 1 +-0.620337486 -0.800000072 0.891485393 -0.459879726 -0.593070388 0.66089195 0.111132 1 +-0.586406112 -0.76666671 0.938561797 -0.43556571 -0.569458127 0.697136879 0.10764 1 +-0.541852713 -0.733333349 0.979505539 -0.404907763 -0.547994614 0.731950521 0.10624 1 +-0.484915137 -0.700000048 1.01329923 -0.366360664 -0.528860569 0.765562832 0.107453 1 +-0.411252469 -0.666666687 1.03743684 -0.316362262 -0.512843549 0.798064172 0.11316 1 +-0.307636678 -0.633333325 1.04428089 -0.244258121 -0.502855539 0.829140663 0.131075 1 +-0.942721903 -0.833333373 -0.0557193048 -0.748504698 -0.661652148 -0.0442401543 0.219203 1 +-0.913854361 -0.866666734 -0.00571927987 -0.725584388 -0.688118219 -0.00454100827 0.220669 1 +-0.451974154 -0.866666734 0.794280767 -0.358859569 -0.688118219 0.630645037 0.172366 1 +-0.423106611 -0.833333373 0.844280779 -0.335939258 -0.661652148 0.670344174 0.165746 1 diff --git a/maths b/maths index 6aa3da76..ba808f14 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 6aa3da7634a34b0e592d28ac78882b6c89616460 +Subproject commit ba808f14826047e1aece0e650fefce4fdadf9c45 From aa314351f6e0df835e3cce67a5ee852dcebbfc02 Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 21 Nov 2025 13:12:10 +0000 Subject: [PATCH 03/41] runtime radius modification --- examples/cray_eye.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index e10fbb18..cad50d18 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -21,12 +21,15 @@ int main (int argc, char** argv) { std::string eyefile = ""; if (argc < 2) { - std::cout << "Usage: " << argv[0] << " path/to/eyefile.eye\n"; + std::cout << "Usage: " << argv[0] << " path/to/eyefile.eye [projection sphere radius]\n"; return -1; } else { eyefile = std::string (argv[1]); } + float psrad = 0.6f; + if (argc > 2) { psrad = std::atof (argv[2]); } + auto v = mplot::Visual<>(1024, 768, "mplot::compoundray::EyeVisual"); // We read the information from the eye file into a vector of Ommatidium objects. Ommatidium is @@ -57,7 +60,7 @@ int main (int argc, char** argv) eyevm->name = "Big Eye"; eyevm->show_cones = false; eyevm->proj_sphere_centre = { 0, 0, 0 }; - eyevm->proj_sphere_radius = 0.6f; + eyevm->proj_sphere_radius = psrad; eyevm->show_sphere = true; eyevm->setAlpha (0.1f); eyevm->finalize(); @@ -89,14 +92,15 @@ int main (int argc, char** argv) sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (sm::vec<>{}, ep->proj_sphere_radius, l0, l); if (intersections[0][0] != std::numeric_limits::max()) { - auto ivm1 = std::make_unique> (intersections[0], 0.01f, mplot::colour::crimson); + // intersections[0] is the coordinate for the ommatidia pixel on the sphere + auto ivm1 = std::make_unique> (intersections[0], 0.01f * psrad, mplot::colour::crimson); v.bindmodel (ivm1); ivm1->finalize(); v.addVisualModel (ivm1); } #if 0 if (intersections[1][0] != std::numeric_limits::max()) { - auto ivm2 = std::make_unique> (intersections[1], 0.01f, mplot::colour::blue); + auto ivm2 = std::make_unique> (intersections[1], 0.01f * psrad, mplot::colour::blue); v.bindmodel (ivm2); ivm2->finalize(); v.addVisualModel (ivm2); From 3e75dd02813eb796c90eebed4861aa11598b41bf Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 21 Nov 2025 16:54:25 +0000 Subject: [PATCH 04/41] WIP towards a 2D compound ray projections --- examples/cray_eye.cpp | 2 +- maths | 2 +- mplot/compoundray/EyeVisual.h | 152 ++++++++++++++++++++++++++++++++-- 3 files changed, 148 insertions(+), 8 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index cad50d18..682d1a28 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -61,7 +61,7 @@ int main (int argc, char** argv) eyevm->show_cones = false; eyevm->proj_sphere_centre = { 0, 0, 0 }; eyevm->proj_sphere_radius = psrad; - eyevm->show_sphere = true; + eyevm->show_sphere = false; eyevm->setAlpha (0.1f); eyevm->finalize(); diff --git a/maths b/maths index ba808f14..c78fef2a 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit ba808f14826047e1aece0e650fefce4fdadf9c45 +Subproject commit c78fef2abc0774e71e8017862fca50c6808a30e4 diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index f09f1d73..75255919 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -8,9 +8,14 @@ #include #include #include +#include +#include #include #include +#define JC_VORONOI_IMPLEMENTATION +#include + namespace mplot::compoundray { // This is a binary-compatible equivalent to Ommatidium from cameras/CompoundEyeDataTypes.h in compound-ray. @@ -103,9 +108,9 @@ namespace mplot::compoundray } // else num_vertices = disc_vertices; // 3 colours, n_omm tubes, cone_vertices vertices per cone. - if (n_verts != 3u * n_omm * static_cast(num_vertices)) { - throw std::runtime_error ("EyeVisual: n_verts/n_omm sizes mismatch!"); - } + //if (n_verts != 3u * n_omm * static_cast(num_vertices)) { + // throw std::runtime_error ("EyeVisual: n_verts/n_omm sizes mismatch!"); + //} // Could test on: if (this->focal_point_sum > 0.0f) { // if the number of vertices were // different, but I chose cones in both cases @@ -119,6 +124,26 @@ namespace mplot::compoundray } } + //////////////// 2D map + if (!this->omm2d.empty()) { + // Replace elements of vertexColors + //unsigned int tcounts = 0; + sm::vec<> cv = {}; + for (std::size_t i = 0u; i < this->triangle_counts.size(); ++i) { + auto c = (*ommData)[this->site_indices[i]]; + //std::size_t d_idx = tcounts * 9; // 3 floats per vtx, 3 vtxs per tri + for (std::size_t j = 0; j < 3 * this->triangle_counts[i]; ++j) { + // This is ONE colour vertex. Need 3 per triangle. + this->vertex_push (c, this->vertexColors); + //this->vertexColors[d_idx + 3 * j] = c[0]; + //this->vertexColors[d_idx + 3 * j + 1] = c[1]; + //this->vertexColors[d_idx + 3 * j + 2] = c[2]; + } + //tcounts += this->triangle_counts[i]; + } + } + /////////////////// + // Lastly, this call copies vertexColors (etc) into the OpenGL memory space this->reinit_colour_buffer(); } @@ -202,9 +227,89 @@ namespace mplot::compoundray if (this->show_2d) { // Compute intersections between ommatidia direction vectors and our projection sphere. + for (size_t i = 0; i < this->ommatidia->size(); ++i) { + sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (sm::vec<>{}, this->proj_sphere_radius, + (*ommatidia)[i].relativePosition, + -(*ommatidia)[i].relativeDirection); + if (sph_coord[0][0] != std::numeric_limits::max()) { + // sph_coord[0] is the coordinate for the ommatidia pixel on the sphere + sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (sph_coord[0], this->proj_sphere_radius); + sm::vec xy = sm::geometry::spherical_projection::mercator (ll, this->proj_sphere_radius); + // Add xy as one of the points that we'll make a Voronoi diagram from. + this->omm2d.push_back (xy.plus_one_dim()); + } + } + // Make 2D Voronoi of omm2d. + this->voronoi2d(); } } + void voronoi2d() + { + // Use mplot::range to find the extents of dataCoords. From these create a + // rectangle to pass to jcv_diagram_generate. + uint32_t ncoords = this->omm2d.size(); + const sm::vvec>* d_ptr = &this->omm2d; // may not need + sm::range rx, ry; + rx.search_init(); + ry.search_init(); + for (unsigned int i = 0; i < ncoords; ++i) { + rx.update (this->omm2d[i][0]); + ry.update (this->omm2d[i][1]); + } + // Generate the 2D Voronoi diagram + jcv_diagram diagram; + std::memset (&diagram, 0, sizeof(jcv_diagram)); + jcv_rect domain = { + jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + }; + jcv_diagram_generate (ncoords, d_ptr->data(), &domain, 0, &diagram); + // We obtain access the the Voronoi cell sites: + const jcv_site* sites = jcv_diagram_get_sites (&diagram); + + if (static_cast(diagram.numsites) != ncoords) { + std::cout << "WARNING: numsites != ncoords ?!?!\n"; + } + + for (int i = 0; i < diagram.numsites; ++i) { + const jcv_site* site = &sites[i]; + jcv_graphedge* e = site->edges; // The very first edge + while (e) { + // Set z. Should be done in jcvoronoi, but haven't found out how + e->pos[0][2] = this->omm2d[i][2]; + e->pos[1][2] = e->pos[0][2]; + e = e->next; + } + } + + // To draw triangles iterate over the 'sites' and get the edges + this->triangle_counts.resize (ncoords, 0); + this->site_indices.resize (ncoords, 0); + this->triangle_count_sum = 0; + + // To draw triangles iterate over the 'sites' and draw triangles + for (int i = 0; i < diagram.numsites; ++i) { + const jcv_site* site = &sites[i]; + const jcv_graphedge* e = site->edges; + std::array colour = (*ommData)[i]; + unsigned int site_triangles = 0; + while (e) { + this->computeTriangle (site->p + this->twod_offset, + e->pos[0] + this->twod_offset, + e->pos[1] + this->twod_offset, colour); + ++site_triangles; + e = e->next; + } + this->triangle_counts[i] = site_triangles; + this->site_indices[i] = site->index; + this->triangle_count_sum += site_triangles; + } + + // At end free the Voronoi diagram memory + jcv_diagram_free (&diagram); + } + // Visualize in two modes "disc" mode, showing just a 2D disc for each ommatidium and // disc+cone mode, where the acceptance angle is displayed too. Runtime switchable. bool show_cones = false; @@ -234,19 +339,54 @@ namespace mplot::compoundray void set_disc_width (float _disc_width) { this->disc_width = _disc_width; this->reinit(); } float get_disc_width() { return this->disc_width; } - // Parameters to reduce the visual to 2D. Use these to draw a sphere externally with a - // SphereVisual for your debugging. + // Parameters for a 2D representation bool show_2d = true; + // 2D positions for the ommatidia centres encoded in 3D vecs + sm::vvec> omm2d; + // Use this to position the 2D map wrt the three D model + sm::vec twod_offset = {0, 0, 0}; + // The user-provided radius of the projection sphere. Will need to match the size of the compound ray eye float proj_sphere_radius = 0.0f; + // The centre of the user-provided projection sphere sm::vec proj_sphere_centre = {}; + // Should the sphere be shown visually (maybe by external code? bool show_sphere = true; - sm::vvec> proj_sphere_intersections; + // Width of border around 2D map + float border_width = std::numeric_limits::epsilon(); + // Have to record the number of triangles in each cell in the 2D map in order to update the colours + sm::vvec triangle_counts; + // Record the data index for each Voronoi cell index. For reinitColours + sm::vvec site_indices; + // Sum of triangles used for reinitColours + unsigned int triangle_count_sum = 0; private: // User-modifiable ommatidial cone length which is used if there's no focal point offset float cone_length = 0.1f; // User-modifiable ommatidial disc width. If negative ignored? float disc_width = -1.0f; + + //! Compute a triangle from 3 arbitrary corners + void computeTriangle (sm::vec c1, sm::vec c2, sm::vec c3, const std::array& colr) + { + // v is the face normal + sm::vec u1 = c1-c2; + sm::vec u2 = c2-c3; + sm::vec v = u1.cross(u2); + v.renormalize(); + // Push corner vertices + this->vertex_push (c1, this->vertexPositions); + this->vertex_push (c2, this->vertexPositions); + this->vertex_push (c3, this->vertexPositions); + // Colours/normals + for (unsigned int i = 0; i < 3U; ++i) { + this->vertex_push (colr, this->vertexColors); + this->vertex_push (v, this->vertexNormals); + } + this->indices.push_back (this->idx++); + this->indices.push_back (this->idx++); + this->indices.push_back (this->idx++); + } }; } // namespace comray From 915c782409ed30e7c638498daec7db4361337c09 Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 21 Nov 2025 22:00:27 +0000 Subject: [PATCH 05/41] puts rays and sphere inside EyeVisual. reinitColours needs work --- examples/cray_eye.cpp | 13 +++++--- maths | 2 +- mplot/compoundray/EyeVisual.h | 59 ++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 682d1a28..982c0a59 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -54,19 +54,22 @@ int main (int argc, char** argv) } // A second eye goes in the 'eye only' window - mplot::compoundray::EyeVisual<>* ep = nullptr; + //mplot::compoundray::EyeVisual<>* ep = nullptr; auto eyevm = std::make_unique> (sm::vec<>{}, &ommatidiaColours, ommatidia.get()); v.bindmodel (eyevm); eyevm->name = "Big Eye"; eyevm->show_cones = false; eyevm->proj_sphere_centre = { 0, 0, 0 }; eyevm->proj_sphere_radius = psrad; - eyevm->show_sphere = false; - eyevm->setAlpha (0.1f); + eyevm->twod_offset = { 0, 2, 0 }; + eyevm->show_sphere = true; + eyevm->show_rays = true; eyevm->finalize(); - ep = v.addVisualModel (eyevm); + v.addVisualModel (eyevm); +#if 0 + ep = v.addVisualModel (eyevm); if (ep->show_sphere) { auto svm = std::make_unique> (ep->proj_sphere_centre, ep->proj_sphere_radius, mplot::colour::slategray1); v.bindmodel (svm); @@ -108,6 +111,6 @@ int main (int argc, char** argv) #endif } } - +#endif v.keepOpen(); } diff --git a/maths b/maths index c78fef2a..59e15381 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit c78fef2abc0774e71e8017862fca50c6808a30e4 +Subproject commit 59e153819d969936c0210accd8e8085f87c28041 diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 75255919..d7b15681 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -148,6 +148,19 @@ namespace mplot::compoundray this->reinit_colour_buffer(); } + sm::vec spherical_projection (const sm::vec& ll) + { + sm::vec xy = {}; + if (this->proj_type == sm::geometry::spherical_projection::type::equirectangular) { + xy = sm::geometry::spherical_projection::equirectangular (ll, this->proj_sphere_radius); + } else if (this->proj_type == sm::geometry::spherical_projection::type::cassini) { + xy = sm::geometry::spherical_projection::cassini (ll, this->proj_sphere_radius); + } else { + xy = sm::geometry::spherical_projection::mercator (ll, this->proj_sphere_radius); + } + return xy; + } + //! Initialize vertex buffer objects and vertex array object. void initializeVertices() { @@ -227,14 +240,19 @@ namespace mplot::compoundray if (this->show_2d) { // Compute intersections between ommatidia direction vectors and our projection sphere. + sm::mat44 coord_rotn; + coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); + //coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); for (size_t i = 0; i < this->ommatidia->size(); ++i) { - sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (sm::vec<>{}, this->proj_sphere_radius, + sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->proj_sphere_centre, + this->proj_sphere_radius, (*ommatidia)[i].relativePosition, -(*ommatidia)[i].relativeDirection); if (sph_coord[0][0] != std::numeric_limits::max()) { // sph_coord[0] is the coordinate for the ommatidia pixel on the sphere - sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (sph_coord[0], this->proj_sphere_radius); - sm::vec xy = sm::geometry::spherical_projection::mercator (ll, this->proj_sphere_radius); + sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); + sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->proj_sphere_radius); + sm::vec xy = this->spherical_projection (ll); // Add xy as one of the points that we'll make a Voronoi diagram from. this->omm2d.push_back (xy.plus_one_dim()); } @@ -242,6 +260,33 @@ namespace mplot::compoundray // Make 2D Voronoi of omm2d. this->voronoi2d(); } + + if (this->show_sphere) { + //this->template computeSphereGeoFast (this->proj_sphere_centre, + // mplot::colour::grey50, + // this->proj_sphere_radius); + this->computeSphere (this->proj_sphere_centre, + mplot::colour::grey50, mplot::colour::grey50, + this->proj_sphere_radius); + } + + if (this->show_rays) { + for (size_t i = 0; i < this->ommatidia->size(); ++i) { + // Can now find intersections on our sphere + sm::vec<> l0 = (*ommatidia)[i].relativePosition; + sm::vec<> l = -(*ommatidia)[i].relativeDirection; + // Show direction vector from ommatidium position + this->computeArrow (l0, l0 + l, mplot::colour::grey80, 0.002f * this->proj_sphere_radius); + // Recompute intersections + sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (this->proj_sphere_centre, + this->proj_sphere_radius, l0, l); + if (intersections[0][0] != std::numeric_limits::max()) { + // intersections[0] is the coordinate for the ommatidia pixel on the sphere + this->computeSphere (intersections[0], + mplot::colour::crimson, mplot::colour::crimson, 0.006f * this->proj_sphere_radius); + } + } + } } void voronoi2d() @@ -340,7 +385,7 @@ namespace mplot::compoundray float get_disc_width() { return this->disc_width; } // Parameters for a 2D representation - bool show_2d = true; + bool show_2d = false; // 2D positions for the ommatidia centres encoded in 3D vecs sm::vvec> omm2d; // Use this to position the 2D map wrt the three D model @@ -349,8 +394,12 @@ namespace mplot::compoundray float proj_sphere_radius = 0.0f; // The centre of the user-provided projection sphere sm::vec proj_sphere_centre = {}; + // Which spherical to 2D projection to use? + sm::geometry::spherical_projection::type proj_type = sm::geometry::spherical_projection::type::mercator; // Should the sphere be shown visually (maybe by external code? - bool show_sphere = true; + bool show_sphere = false; + // Arrows/intersection locations with the projection sphere + bool show_rays = false; // Width of border around 2D map float border_width = std::numeric_limits::epsilon(); // Have to record the number of triangles in each cell in the 2D map in order to update the colours From de7e46a7c55c98e8ef2fa0f7d7a58138f7afbe02 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 22 Nov 2025 13:59:39 +0000 Subject: [PATCH 06/41] Working towards multiple projections --- examples/cray_eye.cpp | 8 +- mplot/compoundray/EyeVisual.h | 163 ++++++++++++++++++++-------------- 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 982c0a59..33c8598e 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -59,9 +59,11 @@ int main (int argc, char** argv) v.bindmodel (eyevm); eyevm->name = "Big Eye"; eyevm->show_cones = false; - eyevm->proj_sphere_centre = { 0, 0, 0 }; - eyevm->proj_sphere_radius = psrad; - eyevm->twod_offset = { 0, 2, 0 }; + + sm::vec<> centre = { 0, 0, 0 }; + sm::vec<> twod_offset = { 0, 2, 0 }; + + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); eyevm->show_sphere = true; eyevm->show_rays = true; eyevm->finalize(); diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index d7b15681..24cac867 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -148,19 +148,69 @@ namespace mplot::compoundray this->reinit_colour_buffer(); } - sm::vec spherical_projection (const sm::vec& ll) + // Available projections + enum class projection_type : uint8_t + { + mercator, + cassini, + equirectangular, + cylindrical + }; + + // Project latitude/longitude ll with projection type t and given radius + sm::vec spherical_projection (const sm::vec& ll, projection_type t, const float radius) { sm::vec xy = {}; - if (this->proj_type == sm::geometry::spherical_projection::type::equirectangular) { - xy = sm::geometry::spherical_projection::equirectangular (ll, this->proj_sphere_radius); - } else if (this->proj_type == sm::geometry::spherical_projection::type::cassini) { - xy = sm::geometry::spherical_projection::cassini (ll, this->proj_sphere_radius); + if (t == projection_type::equirectangular) { + xy = sm::geometry::spherical_projection::equirectangular (ll, radius); + } else if (t == projection_type::cassini) { + xy = sm::geometry::spherical_projection::cassini (ll, radius); } else { - xy = sm::geometry::spherical_projection::mercator (ll, this->proj_sphere_radius); + xy = sm::geometry::spherical_projection::mercator (ll, radius); } return xy; } + // 2D positions for the ommatidia centres encoded in 3D vecs. Gets re-used for each projection + sm::vvec> omm2d; + + /* + * Possibly each of these need replication for each of multiple 2d projections + */ + struct projection_data + { + // Use this to position the 2D map wrt the three D model + sm::vec twod_offset = {0, 0, 0}; + // The user-provided radius of the projection sphere. Will need to match the size of the compound ray eye + float proj_sphere_radius = 0.0f; + // The centre of the user-provided projection sphere + sm::vec proj_sphere_centre = {}; + // Which spherical to 2D projection to use? + projection_type proj_type = projection_type::mercator; + // Have to record the number of triangles in each cell in the 2D map in order to update the colours + sm::vvec triangle_counts; + // Record the data index for each Voronoi cell index. For reinitColours + sm::vvec site_indices; + // Sum of triangles used for reinitColours + unsigned int triangle_count_sum = 0; + }; + + // A compound eye visualization may require several projections to 2D + std::vector projections; + + void add_spherical_projection (const sm::vec& _twod_offset, projection_type t, + const sm::vec& centre, const float radius) + { + projection_data d; + d.proj_type = t; + d.twod_offset = _twod_offset; + d.proj_sphere_centre = centre; + d.proj_sphere_radius = radius; + this->projections.push_back (d); + } + + // void add_cylindrical_projection (_twod_offset, centre, radius, height); + //! Initialize vertex buffer objects and vertex array object. void initializeVertices() { @@ -238,58 +288,59 @@ namespace mplot::compoundray } } - if (this->show_2d) { - // Compute intersections between ommatidia direction vectors and our projection sphere. + for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { + this->omm2d.clear(); + // Compute intersections between ommatidia direction vectoras and our projection sphere. sm::mat44 coord_rotn; coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); //coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); for (size_t i = 0; i < this->ommatidia->size(); ++i) { - sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->proj_sphere_centre, - this->proj_sphere_radius, + sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_sphere_centre, + this->projections[pri].proj_sphere_radius, (*ommatidia)[i].relativePosition, -(*ommatidia)[i].relativeDirection); if (sph_coord[0][0] != std::numeric_limits::max()) { // sph_coord[0] is the coordinate for the ommatidia pixel on the sphere sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); - sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->proj_sphere_radius); - sm::vec xy = this->spherical_projection (ll); + sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_sphere_radius); + sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_sphere_radius); // Add xy as one of the points that we'll make a Voronoi diagram from. this->omm2d.push_back (xy.plus_one_dim()); } } // Make 2D Voronoi of omm2d. - this->voronoi2d(); + this->voronoi2d (pri); } - if (this->show_sphere) { - //this->template computeSphereGeoFast (this->proj_sphere_centre, - // mplot::colour::grey50, - // this->proj_sphere_radius); - this->computeSphere (this->proj_sphere_centre, - mplot::colour::grey50, mplot::colour::grey50, - this->proj_sphere_radius); - } + for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { - if (this->show_rays) { - for (size_t i = 0; i < this->ommatidia->size(); ++i) { - // Can now find intersections on our sphere - sm::vec<> l0 = (*ommatidia)[i].relativePosition; - sm::vec<> l = -(*ommatidia)[i].relativeDirection; - // Show direction vector from ommatidium position - this->computeArrow (l0, l0 + l, mplot::colour::grey80, 0.002f * this->proj_sphere_radius); - // Recompute intersections - sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (this->proj_sphere_centre, - this->proj_sphere_radius, l0, l); - if (intersections[0][0] != std::numeric_limits::max()) { - // intersections[0] is the coordinate for the ommatidia pixel on the sphere - this->computeSphere (intersections[0], - mplot::colour::crimson, mplot::colour::crimson, 0.006f * this->proj_sphere_radius); + if (this->show_sphere) { + this->computeSphere (this->projections[pri].proj_sphere_centre, + mplot::colour::grey50, mplot::colour::grey50, + this->projections[pri].proj_sphere_radius); + } + + if (this->show_rays) { + for (size_t i = 0; i < this->ommatidia->size(); ++i) { + // Can now find intersections on our sphere + sm::vec<> l0 = (*ommatidia)[i].relativePosition; + sm::vec<> l = -(*ommatidia)[i].relativeDirection; + // Show direction vector from ommatidium position + this->computeArrow (l0, l0 + l, mplot::colour::grey80, 0.002f * this->projections[pri].proj_sphere_radius); + // Recompute intersections + sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_sphere_centre, + this->projections[pri].proj_sphere_radius, l0, l); + if (intersections[0][0] != std::numeric_limits::max()) { + // intersections[0] is the coordinate for the ommatidia pixel on the sphere + this->computeSphere (intersections[0], + mplot::colour::crimson, mplot::colour::crimson, 0.006f * this->projections[pri].proj_sphere_radius); + } } } } } - void voronoi2d() + void voronoi2d (uint32_t pri) { // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. @@ -329,9 +380,9 @@ namespace mplot::compoundray } // To draw triangles iterate over the 'sites' and get the edges - this->triangle_counts.resize (ncoords, 0); - this->site_indices.resize (ncoords, 0); - this->triangle_count_sum = 0; + this->projections[pri].triangle_counts.resize (ncoords, 0); + this->projections[pri].site_indices.resize (ncoords, 0); + this->projections[pri].triangle_count_sum = 0; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diagram.numsites; ++i) { @@ -340,15 +391,15 @@ namespace mplot::compoundray std::array colour = (*ommData)[i]; unsigned int site_triangles = 0; while (e) { - this->computeTriangle (site->p + this->twod_offset, - e->pos[0] + this->twod_offset, - e->pos[1] + this->twod_offset, colour); + this->computeTriangle (site->p + this->projections[pri].twod_offset, + e->pos[0] + this->projections[pri].twod_offset, + e->pos[1] + this->projections[pri].twod_offset, colour); ++site_triangles; e = e->next; } - this->triangle_counts[i] = site_triangles; - this->site_indices[i] = site->index; - this->triangle_count_sum += site_triangles; + this->projections[pri].triangle_counts[i] = site_triangles; + this->projections[pri].site_indices[i] = site->index; + this->projections[pri].triangle_count_sum += site_triangles; } // At end free the Voronoi diagram memory @@ -384,30 +435,12 @@ namespace mplot::compoundray void set_disc_width (float _disc_width) { this->disc_width = _disc_width; this->reinit(); } float get_disc_width() { return this->disc_width; } - // Parameters for a 2D representation - bool show_2d = false; - // 2D positions for the ommatidia centres encoded in 3D vecs - sm::vvec> omm2d; - // Use this to position the 2D map wrt the three D model - sm::vec twod_offset = {0, 0, 0}; - // The user-provided radius of the projection sphere. Will need to match the size of the compound ray eye - float proj_sphere_radius = 0.0f; - // The centre of the user-provided projection sphere - sm::vec proj_sphere_centre = {}; - // Which spherical to 2D projection to use? - sm::geometry::spherical_projection::type proj_type = sm::geometry::spherical_projection::type::mercator; // Should the sphere be shown visually (maybe by external code? bool show_sphere = false; - // Arrows/intersection locations with the projection sphere + // Arrows/intersection locations with the projection sphere(s) bool show_rays = false; - // Width of border around 2D map + // Width of borders around 2D map(s) float border_width = std::numeric_limits::epsilon(); - // Have to record the number of triangles in each cell in the 2D map in order to update the colours - sm::vvec triangle_counts; - // Record the data index for each Voronoi cell index. For reinitColours - sm::vvec site_indices; - // Sum of triangles used for reinitColours - unsigned int triangle_count_sum = 0; private: // User-modifiable ommatidial cone length which is used if there's no focal point offset From 3c4df19b2e410fe59d39ec9da65acc679111d909 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 22 Nov 2025 17:06:55 +0000 Subject: [PATCH 07/41] Bug fix. Works for one projection; not so well for two --- examples/cray_eye.cpp | 14 +++++++---- mplot/compoundray/EyeVisual.h | 44 +++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 33c8598e..9ccbeede 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -60,16 +60,20 @@ int main (int argc, char** argv) eyevm->name = "Big Eye"; eyevm->show_cones = false; - sm::vec<> centre = { 0, 0, 0 }; - sm::vec<> twod_offset = { 0, 2, 0 }; - + sm::vec<> centre = { -0.5, 0, 0 }; + sm::vec<> twod_offset = { 3, 2, 0 }; + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); +/* + twod_offset = { -3, 2, 0 }; + centre = { 0.5, 0, 0 }; eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); +*/ eyevm->show_sphere = true; eyevm->show_rays = true; eyevm->finalize(); - v.addVisualModel (eyevm); - + [[maybe_unused]] auto ep = v.addVisualModel (eyevm); + ep->reinitColours(); #if 0 ep = v.addVisualModel (eyevm); if (ep->show_sphere) { diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 24cac867..8604d4bf 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -99,7 +99,7 @@ namespace mplot::compoundray size_t n_verts = this->vertexColors.size(); // should be tube_vertices * n_omm if (n_verts == 0u) { return; } // model doesn't exist yet - this->vertexColors.clear(); // Could re-write not clear/push + // this->vertexColors.clear(); // Could re-write not clear/push size_t n_omm = ommData->size(); int num_vertices = disc_vertices; @@ -120,27 +120,34 @@ namespace mplot::compoundray // Update the 3 RGB values in vertexColors tube_vertices times int j = 0; for (; j < num_vertices; ++j) { - this->vertex_push ((*ommData)[i], this->vertexColors); + this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; + this->vertexColors[i * num_vertices * 3 + j * 3 + 1] = (*ommData)[i][1]; + this->vertexColors[i * num_vertices * 3 + j * 3 + 2] = (*ommData)[i][2]; + //this->vertex_push ((*ommData)[i], this->vertexColors); } } + std::size_t i_3d = n_omm * num_vertices * 3; + //////////////// 2D map - if (!this->omm2d.empty()) { + for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { // Replace elements of vertexColors - //unsigned int tcounts = 0; - sm::vec<> cv = {}; - for (std::size_t i = 0u; i < this->triangle_counts.size(); ++i) { - auto c = (*ommData)[this->site_indices[i]]; - //std::size_t d_idx = tcounts * 9; // 3 floats per vtx, 3 vtxs per tri - for (std::size_t j = 0; j < 3 * this->triangle_counts[i]; ++j) { + std::size_t tcounts = 0; + std::size_t d_2d = 0; + for (std::size_t i = 0u; i < this->projections[pri].triangle_counts.size(); ++i) { + auto c = (*ommData)[this->projections[pri].site_indices[i]]; + std::size_t d_idx = i_3d + tcounts * 9; // 3 floats per vtx, 3 vtxs per tri + for (std::size_t j = 0; j < 3 * this->projections[pri].triangle_counts[i]; ++j) { // This is ONE colour vertex. Need 3 per triangle. - this->vertex_push (c, this->vertexColors); - //this->vertexColors[d_idx + 3 * j] = c[0]; - //this->vertexColors[d_idx + 3 * j + 1] = c[1]; - //this->vertexColors[d_idx + 3 * j + 2] = c[2]; + //this->vertex_push (c, this->vertexColors); + this->vertexColors[d_idx + 3 * j] = c[0]; + this->vertexColors[d_idx + 3 * j + 1] = c[1]; + this->vertexColors[d_idx + 3 * j + 2] = c[2]; + d_2d++; } - //tcounts += this->triangle_counts[i]; + tcounts += this->projections[pri].triangle_counts[i]; } + i_3d += d_2d; } /////////////////// @@ -316,8 +323,8 @@ namespace mplot::compoundray if (this->show_sphere) { this->computeSphere (this->projections[pri].proj_sphere_centre, - mplot::colour::grey50, mplot::colour::grey50, - this->projections[pri].proj_sphere_radius); + mplot::colour::grey50, + this->projections[pri].proj_sphere_radius, 18, 18); } if (this->show_rays) { @@ -333,7 +340,7 @@ namespace mplot::compoundray if (intersections[0][0] != std::numeric_limits::max()) { // intersections[0] is the coordinate for the ommatidia pixel on the sphere this->computeSphere (intersections[0], - mplot::colour::crimson, mplot::colour::crimson, 0.006f * this->projections[pri].proj_sphere_radius); + mplot::colour::crimson, 0.006f * this->projections[pri].proj_sphere_radius); } } } @@ -388,7 +395,8 @@ namespace mplot::compoundray for (int i = 0; i < diagram.numsites; ++i) { const jcv_site* site = &sites[i]; const jcv_graphedge* e = site->edges; - std::array colour = (*ommData)[i]; + std::array colour = (*ommData)[this->projections[pri].site_indices[i]]; + unsigned int site_triangles = 0; while (e) { this->computeTriangle (site->p + this->projections[pri].twod_offset, From faaa7915b146f15b541086231e061885e9760023 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 24 Nov 2025 09:35:59 +0000 Subject: [PATCH 08/41] Debugging, not progress --- examples/cray_eye.cpp | 13 +++++++------ mplot/compoundray/EyeVisual.h | 17 ++++++++++------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 9ccbeede..d1c7b524 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -51,6 +51,7 @@ int main (int argc, char** argv) ommatidiaColours.resize (ommatidia->size()); for (size_t i = 0; i < ommatidia->size(); ++i) { ommatidiaColours[i] = cm.convert (ommatidiaData[i]); + std::cout << "ommatidiaColours[" << i << "] = " << ommatidiaColours[i][0] << "...GB\n"; } // A second eye goes in the 'eye only' window @@ -61,19 +62,19 @@ int main (int argc, char** argv) eyevm->show_cones = false; sm::vec<> centre = { -0.5, 0, 0 }; - sm::vec<> twod_offset = { 3, 2, 0 }; + sm::vec<> twod_offset = { -3, 2, 0 }; eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); -/* - twod_offset = { -3, 2, 0 }; - centre = { 0.5, 0, 0 }; + + twod_offset = { 3, 2, 0 }; + centre = { 1, 0, 0 }; eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); -*/ + eyevm->show_sphere = true; eyevm->show_rays = true; eyevm->finalize(); [[maybe_unused]] auto ep = v.addVisualModel (eyevm); - ep->reinitColours(); + //ep->reinitColours(); #if 0 ep = v.addVisualModel (eyevm); if (ep->show_sphere) { diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 8604d4bf..e86c59a6 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -297,6 +297,7 @@ namespace mplot::compoundray for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { this->omm2d.clear(); + std::cout << "omm2d cleared; size is " << omm2d.size() << std::endl; // Compute intersections between ommatidia direction vectoras and our projection sphere. sm::mat44 coord_rotn; coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); @@ -315,6 +316,7 @@ namespace mplot::compoundray this->omm2d.push_back (xy.plus_one_dim()); } } + std::cout << "omm2d re-built; size is " << omm2d.size() << std::endl; // Make 2D Voronoi of omm2d. this->voronoi2d (pri); } @@ -349,14 +351,15 @@ namespace mplot::compoundray void voronoi2d (uint32_t pri) { + std::cout << "voronoi2d (" << pri << ")\n"; // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. - uint32_t ncoords = this->omm2d.size(); + int ncoords = static_cast(this->omm2d.size()); const sm::vvec>* d_ptr = &this->omm2d; // may not need sm::range rx, ry; rx.search_init(); ry.search_init(); - for (unsigned int i = 0; i < ncoords; ++i) { + for (int i = 0; i < ncoords; ++i) { rx.update (this->omm2d[i][0]); ry.update (this->omm2d[i][1]); } @@ -370,12 +373,11 @@ namespace mplot::compoundray jcv_diagram_generate (ncoords, d_ptr->data(), &domain, 0, &diagram); // We obtain access the the Voronoi cell sites: const jcv_site* sites = jcv_diagram_get_sites (&diagram); - - if (static_cast(diagram.numsites) != ncoords) { - std::cout << "WARNING: numsites != ncoords ?!?!\n"; + if (diagram.numsites != ncoords) { + std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; } - for (int i = 0; i < diagram.numsites; ++i) { + for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; jcv_graphedge* e = site->edges; // The very first edge while (e) { @@ -392,13 +394,14 @@ namespace mplot::compoundray this->projections[pri].triangle_count_sum = 0; // To draw triangles iterate over the 'sites' and draw triangles - for (int i = 0; i < diagram.numsites; ++i) { + for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; const jcv_graphedge* e = site->edges; std::array colour = (*ommData)[this->projections[pri].site_indices[i]]; unsigned int site_triangles = 0; while (e) { + //std::cout << "Triangle colour " << i << " = " << colour[0] << "...GB\n"; this->computeTriangle (site->p + this->projections[pri].twod_offset, e->pos[0] + this->projections[pri].twod_offset, e->pos[1] + this->projections[pri].twod_offset, colour); From 369fd45c2867e62a4610d5d16a3d30b03334369b Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 24 Nov 2025 13:25:15 +0000 Subject: [PATCH 09/41] Some progress, moving to laptop --- examples/cray_eye.cpp | 7 +++---- mplot/compoundray/EyeVisual.h | 13 +++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index d1c7b524..4e8f85c1 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -51,7 +51,6 @@ int main (int argc, char** argv) ommatidiaColours.resize (ommatidia->size()); for (size_t i = 0; i < ommatidia->size(); ++i) { ommatidiaColours[i] = cm.convert (ommatidiaData[i]); - std::cout << "ommatidiaColours[" << i << "] = " << ommatidiaColours[i][0] << "...GB\n"; } // A second eye goes in the 'eye only' window @@ -66,15 +65,15 @@ int main (int argc, char** argv) eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); twod_offset = { 3, 2, 0 }; - centre = { 1, 0, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); + centre = { 0, 0, 0 }; + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad * 0.9); eyevm->show_sphere = true; eyevm->show_rays = true; eyevm->finalize(); [[maybe_unused]] auto ep = v.addVisualModel (eyevm); - //ep->reinitColours(); + // ep->reinitColours(); #if 0 ep = v.addVisualModel (eyevm); if (ep->show_sphere) { diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index e86c59a6..f5df69e5 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -29,8 +29,8 @@ namespace mplot::compoundray }; // Helper function. Read the compound-ray csv eye file into ommatidia. ommatidia should be a pointer to an allocate vector. - [[maybe_unused]] static std::vector* readEye (std::vector* ommatidia, - const std::string& path) + [[maybe_unused]] static std::vector* + readEye (std::vector* ommatidia, const std::string& path) { if (ommatidia == nullptr) { return ommatidia; } @@ -120,7 +120,7 @@ namespace mplot::compoundray // Update the 3 RGB values in vertexColors tube_vertices times int j = 0; for (; j < num_vertices; ++j) { - this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; + this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; this->vertexColors[i * num_vertices * 3 + j * 3 + 1] = (*ommData)[i][1]; this->vertexColors[i * num_vertices * 3 + j * 3 + 2] = (*ommData)[i][2]; //this->vertex_push ((*ommData)[i], this->vertexColors); @@ -297,7 +297,6 @@ namespace mplot::compoundray for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { this->omm2d.clear(); - std::cout << "omm2d cleared; size is " << omm2d.size() << std::endl; // Compute intersections between ommatidia direction vectoras and our projection sphere. sm::mat44 coord_rotn; coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); @@ -316,7 +315,6 @@ namespace mplot::compoundray this->omm2d.push_back (xy.plus_one_dim()); } } - std::cout << "omm2d re-built; size is " << omm2d.size() << std::endl; // Make 2D Voronoi of omm2d. this->voronoi2d (pri); } @@ -390,18 +388,17 @@ namespace mplot::compoundray // To draw triangles iterate over the 'sites' and get the edges this->projections[pri].triangle_counts.resize (ncoords, 0); - this->projections[pri].site_indices.resize (ncoords, 0); + this->projections[pri].site_indices.resize (ncoords, 0); // << !!! this->projections[pri].triangle_count_sum = 0; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; const jcv_graphedge* e = site->edges; - std::array colour = (*ommData)[this->projections[pri].site_indices[i]]; + std::array colour = (*ommData)[site->index]; unsigned int site_triangles = 0; while (e) { - //std::cout << "Triangle colour " << i << " = " << colour[0] << "...GB\n"; this->computeTriangle (site->p + this->projections[pri].twod_offset, e->pos[0] + this->projections[pri].twod_offset, e->pos[1] + this->projections[pri].twod_offset, colour); From ea4836cbff46d4251ceec00ebc539c52fba2c554 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 24 Nov 2025 14:13:21 +0000 Subject: [PATCH 10/41] Sorted --- examples/cray_eye.cpp | 10 ++++++---- mplot/compoundray/EyeVisual.h | 9 ++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 4e8f85c1..089e04fa 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -28,7 +28,9 @@ int main (int argc, char** argv) } float psrad = 0.6f; - if (argc > 2) { psrad = std::atof (argv[2]); } + + float cx = 0.0f; + if (argc > 2) { cx = std::atof (argv[2]); } auto v = mplot::Visual<>(1024, 768, "mplot::compoundray::EyeVisual"); @@ -65,15 +67,15 @@ int main (int argc, char** argv) eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); twod_offset = { 3, 2, 0 }; - centre = { 0, 0, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad * 0.9); + centre = { cx, 0, 0 }; + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); eyevm->show_sphere = true; eyevm->show_rays = true; eyevm->finalize(); [[maybe_unused]] auto ep = v.addVisualModel (eyevm); - // ep->reinitColours(); + ep->reinitColours(); #if 0 ep = v.addVisualModel (eyevm); if (ep->show_sphere) { diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index f5df69e5..6127a33e 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -102,6 +102,7 @@ namespace mplot::compoundray // this->vertexColors.clear(); // Could re-write not clear/push size_t n_omm = ommData->size(); + // How many vertices in the 3D part of the model? int num_vertices = disc_vertices; if (this->show_cones == true) { num_vertices = cone_vertices + disc_vertices; @@ -143,7 +144,7 @@ namespace mplot::compoundray this->vertexColors[d_idx + 3 * j] = c[0]; this->vertexColors[d_idx + 3 * j + 1] = c[1]; this->vertexColors[d_idx + 3 * j + 2] = c[2]; - d_2d++; + d_2d += 9; } tcounts += this->projections[pri].triangle_counts[i]; } @@ -349,7 +350,6 @@ namespace mplot::compoundray void voronoi2d (uint32_t pri) { - std::cout << "voronoi2d (" << pri << ")\n"; // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->omm2d.size()); @@ -388,15 +388,14 @@ namespace mplot::compoundray // To draw triangles iterate over the 'sites' and get the edges this->projections[pri].triangle_counts.resize (ncoords, 0); - this->projections[pri].site_indices.resize (ncoords, 0); // << !!! + this->projections[pri].site_indices.resize (ncoords, 0); this->projections[pri].triangle_count_sum = 0; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; const jcv_graphedge* e = site->edges; - std::array colour = (*ommData)[site->index]; - + const std::array& colour = (*ommData)[site->index]; unsigned int site_triangles = 0; while (e) { this->computeTriangle (site->p + this->projections[pri].twod_offset, From 8c83ace0b4133e8f80a02bf1fc535d45c3aadf23 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 24 Nov 2025 14:18:16 +0000 Subject: [PATCH 11/41] Tidy up before defining ranges of ommatidia to show for a projection --- mplot/compoundray/EyeVisual.h | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 6127a33e..c2f1210a 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -98,24 +98,14 @@ namespace mplot::compoundray if (ommData->empty()) { return; } size_t n_verts = this->vertexColors.size(); // should be tube_vertices * n_omm if (n_verts == 0u) { return; } // model doesn't exist yet - - // this->vertexColors.clear(); // Could re-write not clear/push size_t n_omm = ommData->size(); - // How many vertices in the 3D part of the model? + // Replace colours for the 3D part of the model int num_vertices = disc_vertices; if (this->show_cones == true) { num_vertices = cone_vertices + disc_vertices; } // else num_vertices = disc_vertices; - // 3 colours, n_omm tubes, cone_vertices vertices per cone. - //if (n_verts != 3u * n_omm * static_cast(num_vertices)) { - // throw std::runtime_error ("EyeVisual: n_verts/n_omm sizes mismatch!"); - //} - - // Could test on: if (this->focal_point_sum > 0.0f) { // if the number of vertices were - // different, but I chose cones in both cases - // Re-colour cones built from a focal point offset and acceptance angle for (size_t i = 0u; i < n_omm; ++i) { // Update the 3 RGB values in vertexColors tube_vertices times @@ -124,13 +114,12 @@ namespace mplot::compoundray this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; this->vertexColors[i * num_vertices * 3 + j * 3 + 1] = (*ommData)[i][1]; this->vertexColors[i * num_vertices * 3 + j * 3 + 2] = (*ommData)[i][2]; - //this->vertex_push ((*ommData)[i], this->vertexColors); } } - + // i_3d is the index offset for the 3D part std::size_t i_3d = n_omm * num_vertices * 3; - //////////////// 2D map + // Replace colours in the 2D part of the model for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { // Replace elements of vertexColors std::size_t tcounts = 0; @@ -150,7 +139,6 @@ namespace mplot::compoundray } i_3d += d_2d; } - /////////////////// // Lastly, this call copies vertexColors (etc) into the OpenGL memory space this->reinit_colour_buffer(); From ce4628db9fe90ccd0830cf65768e53435fa86e40 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 24 Nov 2025 16:43:34 +0000 Subject: [PATCH 12/41] Now have a portion of each projection showing. Quite neat --- examples/cray_eye.cpp | 57 ++++------------------------------- mplot/compoundray/EyeVisual.h | 47 +++++++++++++++++++---------- 2 files changed, 37 insertions(+), 67 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 089e04fa..574185de 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -29,7 +29,7 @@ int main (int argc, char** argv) float psrad = 0.6f; - float cx = 0.0f; + float cx = 0.5f; if (argc > 2) { cx = std::atof (argv[2]); } auto v = mplot::Visual<>(1024, 768, "mplot::compoundray::EyeVisual"); @@ -55,20 +55,18 @@ int main (int argc, char** argv) ommatidiaColours[i] = cm.convert (ommatidiaData[i]); } - // A second eye goes in the 'eye only' window - //mplot::compoundray::EyeVisual<>* ep = nullptr; auto eyevm = std::make_unique> (sm::vec<>{}, &ommatidiaColours, ommatidia.get()); v.bindmodel (eyevm); eyevm->name = "Big Eye"; eyevm->show_cones = false; sm::vec<> centre = { -0.5, 0, 0 }; - sm::vec<> twod_offset = { -3, 2, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); + sm::vec<> twod_offset = { -.5, 2, 0 }; + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad, 780, 1560); - twod_offset = { 3, 2, 0 }; + twod_offset = { .5, 2, 0 }; centre = { cx, 0, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad); + eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad, 0, 780); eyevm->show_sphere = true; eyevm->show_rays = true; @@ -76,49 +74,6 @@ int main (int argc, char** argv) [[maybe_unused]] auto ep = v.addVisualModel (eyevm); ep->reinitColours(); -#if 0 - ep = v.addVisualModel (eyevm); - if (ep->show_sphere) { - auto svm = std::make_unique> (ep->proj_sphere_centre, ep->proj_sphere_radius, mplot::colour::slategray1); - v.bindmodel (svm); - svm->setAlpha (0.5); - svm->finalize(); - v.addVisualModel (svm); - - - for (size_t i = 0; i < ommatidia->size(); ++i) { - // Can now find intersections on our sphere - sm::vec<> l0 = (*ommatidia)[i].relativePosition; - sm::vec<> l = -(*ommatidia)[i].relativeDirection; - - // Show direction vector from ommatidium position - auto vvm = std::make_unique> (l0); - v.bindmodel (vvm); - vvm->vgoes = mplot::VectorGoes::FromOrigin; - vvm->thickness = 0.001f; - vvm->thevec = l; - vvm->finalize(); - v.addVisualModel (vvm); - - sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (sm::vec<>{}, ep->proj_sphere_radius, l0, l); - - if (intersections[0][0] != std::numeric_limits::max()) { - // intersections[0] is the coordinate for the ommatidia pixel on the sphere - auto ivm1 = std::make_unique> (intersections[0], 0.01f * psrad, mplot::colour::crimson); - v.bindmodel (ivm1); - ivm1->finalize(); - v.addVisualModel (ivm1); - } -#if 0 - if (intersections[1][0] != std::numeric_limits::max()) { - auto ivm2 = std::make_unique> (intersections[1], 0.01f * psrad, mplot::colour::blue); - v.bindmodel (ivm2); - ivm2->finalize(); - v.addVisualModel (ivm2); - } -#endif - } - } -#endif + v.keepOpen(); } diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index c2f1210a..feba9cce 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -125,11 +125,10 @@ namespace mplot::compoundray std::size_t tcounts = 0; std::size_t d_2d = 0; for (std::size_t i = 0u; i < this->projections[pri].triangle_counts.size(); ++i) { - auto c = (*ommData)[this->projections[pri].site_indices[i]]; + auto c = (*ommData)[this->projections[pri].site_indices[i] + this->projections[pri].start_i]; std::size_t d_idx = i_3d + tcounts * 9; // 3 floats per vtx, 3 vtxs per tri for (std::size_t j = 0; j < 3 * this->projections[pri].triangle_counts[i]; ++j) { // This is ONE colour vertex. Need 3 per triangle. - //this->vertex_push (c, this->vertexColors); this->vertexColors[d_idx + 3 * j] = c[0]; this->vertexColors[d_idx + 3 * j + 1] = c[1]; this->vertexColors[d_idx + 3 * j + 2] = c[2]; @@ -154,13 +153,16 @@ namespace mplot::compoundray }; // Project latitude/longitude ll with projection type t and given radius - sm::vec spherical_projection (const sm::vec& ll, projection_type t, const float radius) + sm::vec spherical_projection (const sm::vec& ll, projection_type t, + const float radius) { sm::vec xy = {}; if (t == projection_type::equirectangular) { xy = sm::geometry::spherical_projection::equirectangular (ll, radius); } else if (t == projection_type::cassini) { xy = sm::geometry::spherical_projection::cassini (ll, radius); + } else if (t == projection_type::cylindrical) { + throw std::runtime_error ("Not a spherical projection"); } else { xy = sm::geometry::spherical_projection::mercator (ll, radius); } @@ -184,24 +186,32 @@ namespace mplot::compoundray // Which spherical to 2D projection to use? projection_type proj_type = projection_type::mercator; // Have to record the number of triangles in each cell in the 2D map in order to update the colours - sm::vvec triangle_counts; + sm::vvec triangle_counts; // Record the data index for each Voronoi cell index. For reinitColours - sm::vvec site_indices; + sm::vvec site_indices; // Sum of triangles used for reinitColours - unsigned int triangle_count_sum = 0; + uint32_t triangle_count_sum = 0; + // Starting ommatidium index for projection + uint32_t start_i = 0; + // End index + uint32_t end_i = std::numeric_limits::max(); }; // A compound eye visualization may require several projections to 2D std::vector projections; void add_spherical_projection (const sm::vec& _twod_offset, projection_type t, - const sm::vec& centre, const float radius) + const sm::vec& centre, const float radius, + const uint32_t _start_i = 0, + const uint32_t _end_i = std::numeric_limits::max()) { projection_data d; d.proj_type = t; d.twod_offset = _twod_offset; d.proj_sphere_centre = centre; d.proj_sphere_radius = radius; + d.start_i = _start_i; + d.end_i = _end_i; this->projections.push_back (d); } @@ -290,7 +300,7 @@ namespace mplot::compoundray sm::mat44 coord_rotn; coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); //coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); - for (size_t i = 0; i < this->ommatidia->size(); ++i) { + for (size_t i = this->projections[pri].start_i; i < this->ommatidia->size() && i < this->projections[pri].end_i; ++i) { sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_sphere_centre, this->projections[pri].proj_sphere_radius, (*ommatidia)[i].relativePosition, @@ -341,14 +351,14 @@ namespace mplot::compoundray // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->omm2d.size()); - const sm::vvec>* d_ptr = &this->omm2d; // may not need sm::range rx, ry; rx.search_init(); ry.search_init(); - for (int i = 0; i < ncoords; ++i) { + for (int i = 0; i < ncoords ; ++i) { rx.update (this->omm2d[i][0]); ry.update (this->omm2d[i][1]); } + std::cout << "rx: "<< rx << ", ry " << ry << std::endl; // Generate the 2D Voronoi diagram jcv_diagram diagram; std::memset (&diagram, 0, sizeof(jcv_diagram)); @@ -356,8 +366,8 @@ namespace mplot::compoundray jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} }; - jcv_diagram_generate (ncoords, d_ptr->data(), &domain, 0, &diagram); - // We obtain access the the Voronoi cell sites: + jcv_diagram_generate (ncoords, this->omm2d.data(), &domain, 0, &diagram); + // We obtain access to the Voronoi cell sites: const jcv_site* sites = jcv_diagram_get_sites (&diagram); if (diagram.numsites != ncoords) { std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; @@ -383,8 +393,14 @@ namespace mplot::compoundray for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; const jcv_graphedge* e = site->edges; - const std::array& colour = (*ommData)[site->index]; - unsigned int site_triangles = 0; + this->projections[pri].site_indices[i] = site->index; + std::array colour = mplot::colour::black; + if (site->index + this->projections[pri].start_i < ommData->size()) { + colour = (*ommData)[site->index + this->projections[pri].start_i]; + } else { + std::cout << "Uh oh, can't access colour [" << site->index << " + " << this->projections[pri].start_i << "]\n"; + } + uint32_t site_triangles = 0; while (e) { this->computeTriangle (site->p + this->projections[pri].twod_offset, e->pos[0] + this->projections[pri].twod_offset, @@ -393,7 +409,6 @@ namespace mplot::compoundray e = e->next; } this->projections[pri].triangle_counts[i] = site_triangles; - this->projections[pri].site_indices[i] = site->index; this->projections[pri].triangle_count_sum += site_triangles; } @@ -456,7 +471,7 @@ namespace mplot::compoundray this->vertex_push (c2, this->vertexPositions); this->vertex_push (c3, this->vertexPositions); // Colours/normals - for (unsigned int i = 0; i < 3U; ++i) { + for (uint32_t i = 0; i < 3U; ++i) { this->vertex_push (colr, this->vertexColors); this->vertex_push (v, this->vertexNormals); } From 85e93a92d237cb6a3ef6b0293b2f7437a89cd3ce Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 25 Nov 2025 11:55:55 +0000 Subject: [PATCH 13/41] Bug fix on reinitColours for multiple projections --- mplot/compoundray/EyeVisual.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index feba9cce..53f9f38f 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -132,7 +132,7 @@ namespace mplot::compoundray this->vertexColors[d_idx + 3 * j] = c[0]; this->vertexColors[d_idx + 3 * j + 1] = c[1]; this->vertexColors[d_idx + 3 * j + 2] = c[2]; - d_2d += 9; + d_2d += 3; } tcounts += this->projections[pri].triangle_counts[i]; } @@ -296,7 +296,7 @@ namespace mplot::compoundray for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { this->omm2d.clear(); - // Compute intersections between ommatidia direction vectoras and our projection sphere. + // Compute intersections between ommatidia direction vectors and our projection sphere. sm::mat44 coord_rotn; coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); //coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); @@ -317,6 +317,7 @@ namespace mplot::compoundray // Make 2D Voronoi of omm2d. this->voronoi2d (pri); } + std::cout << "After 2D stuff, idx = " << this->idx << " for " << this->name << std::endl; for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { @@ -358,7 +359,6 @@ namespace mplot::compoundray rx.update (this->omm2d[i][0]); ry.update (this->omm2d[i][1]); } - std::cout << "rx: "<< rx << ", ry " << ry << std::endl; // Generate the 2D Voronoi diagram jcv_diagram diagram; std::memset (&diagram, 0, sizeof(jcv_diagram)); From bbf1bb054809a281235cca47f2f89abeb1b51c46 Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 25 Nov 2025 12:07:08 +0000 Subject: [PATCH 14/41] Prepare to be able to do cylindrical projections --- examples/cray_eye.cpp | 4 +- mplot/compoundray/EyeVisual.h | 82 +++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 574185de..2d16ff84 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -62,11 +62,11 @@ int main (int argc, char** argv) sm::vec<> centre = { -0.5, 0, 0 }; sm::vec<> twod_offset = { -.5, 2, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad, 780, 1560); + eyevm->add_spherical_projection (mplot::compoundray::EyeVisual<>::projection_type::mercator, twod_offset, centre, psrad, 780, 1560); twod_offset = { .5, 2, 0 }; centre = { cx, 0, 0 }; - eyevm->add_spherical_projection (twod_offset, mplot::compoundray::EyeVisual<>::projection_type::mercator, centre, psrad, 0, 780); + eyevm->add_spherical_projection (mplot::compoundray::EyeVisual<>::projection_type::mercator, twod_offset, centre, psrad, 0, 780); eyevm->show_sphere = true; eyevm->show_rays = true; diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 53f9f38f..b047f83b 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -180,9 +180,11 @@ namespace mplot::compoundray // Use this to position the 2D map wrt the three D model sm::vec twod_offset = {0, 0, 0}; // The user-provided radius of the projection sphere. Will need to match the size of the compound ray eye - float proj_sphere_radius = 0.0f; - // The centre of the user-provided projection sphere - sm::vec proj_sphere_centre = {}; + float proj_radius = 0.0f; + // The centre of the user-provided projection sphere or cylinder + sm::vec proj_centre = {}; + // The height of a projection cylinder + sm::vec proj_height = {}; // Which spherical to 2D projection to use? projection_type proj_type = projection_type::mercator; // Have to record the number of triangles in each cell in the 2D map in order to update the colours @@ -200,7 +202,7 @@ namespace mplot::compoundray // A compound eye visualization may require several projections to 2D std::vector projections; - void add_spherical_projection (const sm::vec& _twod_offset, projection_type t, + void add_spherical_projection (projection_type t, const sm::vec& _twod_offset, const sm::vec& centre, const float radius, const uint32_t _start_i = 0, const uint32_t _end_i = std::numeric_limits::max()) @@ -208,14 +210,28 @@ namespace mplot::compoundray projection_data d; d.proj_type = t; d.twod_offset = _twod_offset; - d.proj_sphere_centre = centre; - d.proj_sphere_radius = radius; + d.proj_centre = centre; + d.proj_radius = radius; d.start_i = _start_i; d.end_i = _end_i; this->projections.push_back (d); } - // void add_cylindrical_projection (_twod_offset, centre, radius, height); + void add_cylindrical_projection (const sm::vec& _twod_offset, const sm::vec& centre, + const float radius, const float height, + const uint32_t _start_i = 0, + const uint32_t _end_i = std::numeric_limits::max()) + { + projection_data d; + d.proj_type = projection_data::cylindrical; + d.twod_offset = _twod_offset; + d.proj_centre = centre; + d.proj_radius = radius; + d.proj_height = height; + d.start_i = _start_i; + d.end_i = _end_i; + this->projections.push_back (d); + } //! Initialize vertex buffer objects and vertex array object. void initializeVertices() @@ -296,35 +312,37 @@ namespace mplot::compoundray for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { this->omm2d.clear(); - // Compute intersections between ommatidia direction vectors and our projection sphere. - sm::mat44 coord_rotn; - coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); - //coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); - for (size_t i = this->projections[pri].start_i; i < this->ommatidia->size() && i < this->projections[pri].end_i; ++i) { - sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_sphere_centre, - this->projections[pri].proj_sphere_radius, - (*ommatidia)[i].relativePosition, - -(*ommatidia)[i].relativeDirection); - if (sph_coord[0][0] != std::numeric_limits::max()) { - // sph_coord[0] is the coordinate for the ommatidia pixel on the sphere - sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); - sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_sphere_radius); - sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_sphere_radius); - // Add xy as one of the points that we'll make a Voronoi diagram from. - this->omm2d.push_back (xy.plus_one_dim()); + if (this->projections[pri].proj_type == projection_type::cylindrical) { + std::cout << "NOTE: Cylindrical projections are currently unimplemented\n"; + } else { + // Compute intersections between ommatidia direction vectors and our projection sphere. + sm::mat44 coord_rotn; + coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); + for (size_t i = this->projections[pri].start_i; i < this->ommatidia->size() && i < this->projections[pri].end_i; ++i) { + sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_centre, + this->projections[pri].proj_radius, + (*ommatidia)[i].relativePosition, + -(*ommatidia)[i].relativeDirection); + if (sph_coord[0][0] != std::numeric_limits::max()) { + // sph_coord[0] is the coordinate for the ommatidia pixel on the sphere + sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); + sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_radius); + sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_radius); + // Add xy as one of the points that we'll make a Voronoi diagram from. + this->omm2d.push_back (xy.plus_one_dim()); + } } + // Make 2D Voronoi of omm2d. + this->voronoi2d (pri); } - // Make 2D Voronoi of omm2d. - this->voronoi2d (pri); } - std::cout << "After 2D stuff, idx = " << this->idx << " for " << this->name << std::endl; for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { if (this->show_sphere) { - this->computeSphere (this->projections[pri].proj_sphere_centre, + this->computeSphere (this->projections[pri].proj_centre, mplot::colour::grey50, - this->projections[pri].proj_sphere_radius, 18, 18); + this->projections[pri].proj_radius, 18, 18); } if (this->show_rays) { @@ -333,14 +351,14 @@ namespace mplot::compoundray sm::vec<> l0 = (*ommatidia)[i].relativePosition; sm::vec<> l = -(*ommatidia)[i].relativeDirection; // Show direction vector from ommatidium position - this->computeArrow (l0, l0 + l, mplot::colour::grey80, 0.002f * this->projections[pri].proj_sphere_radius); + this->computeArrow (l0, l0 + l, mplot::colour::grey80, 0.002f * this->projections[pri].proj_radius); // Recompute intersections - sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_sphere_centre, - this->projections[pri].proj_sphere_radius, l0, l); + sm::vec, 2> intersections = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_centre, + this->projections[pri].proj_radius, l0, l); if (intersections[0][0] != std::numeric_limits::max()) { // intersections[0] is the coordinate for the ommatidia pixel on the sphere this->computeSphere (intersections[0], - mplot::colour::crimson, 0.006f * this->projections[pri].proj_sphere_radius); + mplot::colour::crimson, 0.006f * this->projections[pri].proj_radius); } } } From 9554ccab84a18d29db4c09d1f3196445c829d185 Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 25 Nov 2025 15:27:12 +0000 Subject: [PATCH 15/41] WIP on spherical projection displays --- examples/cray_eye.cpp | 15 +-- maths | 2 +- mplot/compoundray/EyeVisual.h | 196 ++++++++++++++++++++-------------- 3 files changed, 127 insertions(+), 86 deletions(-) diff --git a/examples/cray_eye.cpp b/examples/cray_eye.cpp index 2d16ff84..e6ee0292 100644 --- a/examples/cray_eye.cpp +++ b/examples/cray_eye.cpp @@ -29,7 +29,7 @@ int main (int argc, char** argv) float psrad = 0.6f; - float cx = 0.5f; + [[maybe_unused]] float cx = 0.5f; if (argc > 2) { cx = std::atof (argv[2]); } auto v = mplot::Visual<>(1024, 768, "mplot::compoundray::EyeVisual"); @@ -60,13 +60,14 @@ int main (int argc, char** argv) eyevm->name = "Big Eye"; eyevm->show_cones = false; - sm::vec<> centre = { -0.5, 0, 0 }; - sm::vec<> twod_offset = { -.5, 2, 0 }; - eyevm->add_spherical_projection (mplot::compoundray::EyeVisual<>::projection_type::mercator, twod_offset, centre, psrad, 780, 1560); + auto ptype = mplot::compoundray::EyeVisual<>::projection_type::equirectangular; // mercator, equirectangular or cassini + sm::vec<> centre = { 0, 0, 0 }; + sm::mat44 twod_tr; + twod_tr.translate (sm::vec<>{0,0,-2}); + eyevm->add_spherical_projection (ptype, twod_tr, centre, psrad); - twod_offset = { .5, 2, 0 }; - centre = { cx, 0, 0 }; - eyevm->add_spherical_projection (mplot::compoundray::EyeVisual<>::projection_type::mercator, twod_offset, centre, psrad, 0, 780); + //centre = { cx, 0, 0 }; + //eyevm->add_spherical_projection (ptype, twod_offset, centre, psrad, 780, 1560); eyevm->show_sphere = true; eyevm->show_rays = true; diff --git a/maths b/maths index 59e15381..f2bf7687 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 59e153819d969936c0210accd8e8085f87c28041 +Subproject commit f2bf76872c21f803a2f5ab42b4fd030f593f7974 diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index b047f83b..2f800b43 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -100,24 +100,27 @@ namespace mplot::compoundray if (n_verts == 0u) { return; } // model doesn't exist yet size_t n_omm = ommData->size(); - // Replace colours for the 3D part of the model - int num_vertices = disc_vertices; - if (this->show_cones == true) { - num_vertices = cone_vertices + disc_vertices; - } // else num_vertices = disc_vertices; - - // Re-colour cones built from a focal point offset and acceptance angle - for (size_t i = 0u; i < n_omm; ++i) { - // Update the 3 RGB values in vertexColors tube_vertices times - int j = 0; - for (; j < num_vertices; ++j) { - this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; - this->vertexColors[i * num_vertices * 3 + j * 3 + 1] = (*ommData)[i][1]; - this->vertexColors[i * num_vertices * 3 + j * 3 + 2] = (*ommData)[i][2]; + std::size_t i_3d = 0; + if (show_3d) { + // Replace colours for the 3D part of the model + int num_vertices = disc_vertices; + if (this->show_cones == true) { + num_vertices = cone_vertices + disc_vertices; + } // else num_vertices = disc_vertices; + + // Re-colour cones built from a focal point offset and acceptance angle + for (size_t i = 0u; i < n_omm; ++i) { + // Update the 3 RGB values in vertexColors tube_vertices times + int j = 0; + for (; j < num_vertices; ++j) { + this->vertexColors[i * num_vertices * 3 + j * 3] = (*ommData)[i][0]; + this->vertexColors[i * num_vertices * 3 + j * 3 + 1] = (*ommData)[i][1]; + this->vertexColors[i * num_vertices * 3 + j * 3 + 2] = (*ommData)[i][2]; + } } + // i_3d is the index offset for the 3D part + i_3d = n_omm * num_vertices * 3; } - // i_3d is the index offset for the 3D part - std::size_t i_3d = n_omm * num_vertices * 3; // Replace colours in the 2D part of the model for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { @@ -153,12 +156,12 @@ namespace mplot::compoundray }; // Project latitude/longitude ll with projection type t and given radius - sm::vec spherical_projection (const sm::vec& ll, projection_type t, - const float radius) + sm::vec spherical_projection (const sm::vec& ll, projection_type t, const float radius) { sm::vec xy = {}; if (t == projection_type::equirectangular) { - xy = sm::geometry::spherical_projection::equirectangular (ll, radius); + //sm::mathconst::pi_over_2 + xy = sm::geometry::spherical_projection::equirectangular (ll, radius); } else if (t == projection_type::cassini) { xy = sm::geometry::spherical_projection::cassini (ll, radius); } else if (t == projection_type::cylindrical) { @@ -177,8 +180,8 @@ namespace mplot::compoundray */ struct projection_data { - // Use this to position the 2D map wrt the three D model - sm::vec twod_offset = {0, 0, 0}; + // Use this to position the 2D map wrt the three D model. You can translate, scale and rotate + sm::mat44 twod_transform; // The user-provided radius of the projection sphere. Will need to match the size of the compound ray eye float proj_radius = 0.0f; // The centre of the user-provided projection sphere or cylinder @@ -202,14 +205,14 @@ namespace mplot::compoundray // A compound eye visualization may require several projections to 2D std::vector projections; - void add_spherical_projection (projection_type t, const sm::vec& _twod_offset, + void add_spherical_projection (projection_type t, const sm::mat44& _twod_transform, const sm::vec& centre, const float radius, const uint32_t _start_i = 0, const uint32_t _end_i = std::numeric_limits::max()) { projection_data d; d.proj_type = t; - d.twod_offset = _twod_offset; + d.twod_transform = _twod_transform; d.proj_centre = centre; d.proj_radius = radius; d.start_i = _start_i; @@ -217,14 +220,24 @@ namespace mplot::compoundray this->projections.push_back (d); } - void add_cylindrical_projection (const sm::vec& _twod_offset, const sm::vec& centre, + void add_spherical_projection (projection_type t, const sm::vec& _twod_offset, + const sm::vec& centre, const float radius, + const uint32_t _start_i = 0, + const uint32_t _end_i = std::numeric_limits::max()) + { + sm::mat44 tr; + tr.translate (_twod_offset); + this->add_spherical_projection (t, tr, centre, radius, _start_i, _end_i); + } + + void add_cylindrical_projection (const sm::mat44& _twod_transform, const sm::vec& centre, const float radius, const float height, const uint32_t _start_i = 0, const uint32_t _end_i = std::numeric_limits::max()) { projection_data d; d.proj_type = projection_data::cylindrical; - d.twod_offset = _twod_offset; + d.twod_transform = _twod_transform; d.proj_centre = centre; d.proj_radius = radius; d.proj_height = height; @@ -258,54 +271,56 @@ namespace mplot::compoundray this->focal_point_sum += (*ommatidia)[i].focalPointOffset; } - if (this->focal_point_sum > 0.0f) { - // We have focal points, so draw with the relativePosition representing the centre - // of the ommatidial lens - the base of a cone - which then extends back to the cone - // tip, which can be thought of as the location of the ommatidial 'sensor' - for (size_t i = 0u; i < n_omm; ++i) { - // Ommatidia colour, position/shape - std::array colour = (*ommData)[i]; - float angle = (*ommatidia)[i].acceptanceAngleRadians; - float focal_point = (*ommatidia)[i].focalPointOffset; - sm::vec pos = (*ommatidia)[i].relativePosition; - sm::vec dir = (*ommatidia)[i].relativeDirection; - dir.renormalize(); - // Tip of cone is 'behind' the position of the ommatidial face/lens - sm::vec ommatidial_detector_point = pos - dir * focal_point; - // work out radius from acceptance angle and focal_point - float radius = focal_point * std::tan (angle / 2.0f); - // The disc - this->computeTube (pos, pos + (0.1f * radius * dir), colour, colour, radius, tube_faces); - if (this->show_cones == true) { - // Colour comes from ommData. ringoffset is 1.0f - this->computeCone (pos, ommatidial_detector_point, 0.0f, colour, radius, tube_faces); - } - } - } else { - // All our focal_points are 0. Don't have focal point offset to help define our - // cones, only acceptance angle. Use manually specified tube_length (or computed - // radius) to figure out the size of a cone, whose tip is the location of the - // ommatidial sensor AND the centre of the ommatidial lens - for (size_t i = 0u; i < n_omm; ++i) { - std::array colour = (*ommData)[i]; - float angle = (*ommatidia)[i].acceptanceAngleRadians; - // pos will be the tip of the cone in this case, and the centre of the disc - sm::vec pos = (*ommatidia)[i].relativePosition; - sm::vec dir = (*ommatidia)[i].relativeDirection; - dir.renormalize(); - // do a cone - sm::vec ommatidial_cone_pos = pos + dir * this->cone_length; - float ringoffset = 0.0f; - // work out radius from acceptance angle and focal_point - float radius = this->disc_width / 2.0f; // will be negative if not set - if (radius < 0.0f) { // fall back to using cone_length - radius = this->cone_length * std::tan (angle / 2.0f); + if (show_3d) { + if (this->focal_point_sum > 0.0f) { + // We have focal points, so draw with the relativePosition representing the centre + // of the ommatidial lens - the base of a cone - which then extends back to the cone + // tip, which can be thought of as the location of the ommatidial 'sensor' + for (size_t i = 0u; i < n_omm; ++i) { + // Ommatidia colour, position/shape + std::array colour = (*ommData)[i]; + float angle = (*ommatidia)[i].acceptanceAngleRadians; + float focal_point = (*ommatidia)[i].focalPointOffset; + sm::vec pos = (*ommatidia)[i].relativePosition; + sm::vec dir = (*ommatidia)[i].relativeDirection; + dir.renormalize(); + // Tip of cone is 'behind' the position of the ommatidial face/lens + sm::vec ommatidial_detector_point = pos - dir * focal_point; + // work out radius from acceptance angle and focal_point + float radius = focal_point * std::tan (angle / 2.0f); + // The disc + this->computeTube (pos, pos + (0.1f * radius * dir), colour, colour, radius, tube_faces); + if (this->show_cones == true) { + // Colour comes from ommData. ringoffset is 1.0f + this->computeCone (pos, ommatidial_detector_point, 0.0f, colour, radius, tube_faces); + } } - // Show a disc. Use disc_width, or if it is -ve, cone_length and computed radius - this->computeTube (pos, pos - (0.1f * radius * dir), colour, colour, radius, tube_faces); - // And optionally a cone - if (this->show_cones == true) { - this->computeCone (ommatidial_cone_pos, pos, ringoffset, colour, radius, tube_faces); + } else { + // All our focal_points are 0. Don't have focal point offset to help define our + // cones, only acceptance angle. Use manually specified tube_length (or computed + // radius) to figure out the size of a cone, whose tip is the location of the + // ommatidial sensor AND the centre of the ommatidial lens + for (size_t i = 0u; i < n_omm; ++i) { + std::array colour = (*ommData)[i]; + float angle = (*ommatidia)[i].acceptanceAngleRadians; + // pos will be the tip of the cone in this case, and the centre of the disc + sm::vec pos = (*ommatidia)[i].relativePosition; + sm::vec dir = (*ommatidia)[i].relativeDirection; + dir.renormalize(); + // do a cone + sm::vec ommatidial_cone_pos = pos + dir * this->cone_length; + float ringoffset = 0.0f; + // work out radius from acceptance angle and focal_point + float radius = this->disc_width / 2.0f; // will be negative if not set + if (radius < 0.0f) { // fall back to using cone_length + radius = this->cone_length * std::tan (angle / 2.0f); + } + // Show a disc. Use disc_width, or if it is -ve, cone_length and computed radius + this->computeTube (pos, pos - (0.1f * radius * dir), colour, colour, radius, tube_faces); + // And optionally a cone + if (this->show_cones == true) { + this->computeCone (ommatidial_cone_pos, pos, ringoffset, colour, radius, tube_faces); + } } } } @@ -328,6 +343,7 @@ namespace mplot::compoundray sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_radius); sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_radius); + //xy[0] = -xy[0]; // invert x // Add xy as one of the points that we'll make a Voronoi diagram from. this->omm2d.push_back (xy.plus_one_dim()); } @@ -340,8 +356,7 @@ namespace mplot::compoundray for (uint32_t pri = 0; pri < this->projections.size(); ++pri) { if (this->show_sphere) { - this->computeSphere (this->projections[pri].proj_centre, - mplot::colour::grey50, + this->computeSphere (this->projections[pri].proj_centre, mplot::colour::grey50, this->projections[pri].proj_radius, 18, 18); } @@ -407,6 +422,8 @@ namespace mplot::compoundray this->projections[pri].site_indices.resize (ncoords, 0); this->projections[pri].triangle_count_sum = 0; + sm::vvec> flat_triangles; // contains a sequence of triplets of vecs + sm::vvec> flat_colours; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { const jcv_site* site = &sites[i]; @@ -420,20 +437,43 @@ namespace mplot::compoundray } uint32_t site_triangles = 0; while (e) { - this->computeTriangle (site->p + this->projections[pri].twod_offset, - e->pos[0] + this->projections[pri].twod_offset, - e->pos[1] + this->projections[pri].twod_offset, colour); +#if 0 + sm::vec t1 = {}; + sm::vec t2 = {}; + sm::vec t3 = {}; + t1 = (this->projections[pri].twod_transform * site->p).less_one_dim(); + t2 = (this->projections[pri].twod_transform * e->pos[0]).less_one_dim(); + t3 = (this->projections[pri].twod_transform * e->pos[1]).less_one_dim(); + this->computeTriangle (t1, t2, t3, colour); +#else + flat_triangles.push_back (site->p); + flat_triangles.push_back (e->pos[0]); + flat_triangles.push_back (e->pos[1]); + flat_colours.push_back (colour); +#endif ++site_triangles; e = e->next; } this->projections[pri].triangle_counts[i] = site_triangles; this->projections[pri].triangle_count_sum += site_triangles; } - +#if 1 + // Can now computeTriangles + //sm::vec flat_mean = flat_triangles.mean(); + //flat_triangles -= flat_mean; + for (uint32_t i = 0; i < flat_triangles.size(); i += 3) { + sm::vec t1 = (this->projections[pri].twod_transform * flat_triangles[i]).less_one_dim(); + sm::vec t2 = (this->projections[pri].twod_transform * flat_triangles[i + 1]).less_one_dim(); + sm::vec t3 = (this->projections[pri].twod_transform * flat_triangles[i + 2]).less_one_dim(); + this->computeTriangle (t1, t2, t3, flat_colours[i/3]); + } +#endif // At end free the Voronoi diagram memory jcv_diagram_free (&diagram); } + // If false, hide 3D representation (the ommatidial cones and discs) + bool show_3d = true; // Visualize in two modes "disc" mode, showing just a 2D disc for each ommatidium and // disc+cone mode, where the acceptance angle is displayed too. Runtime switchable. bool show_cones = false; From 578ccec26c360e55147978f29e59badc949b9f79 Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 25 Nov 2025 17:52:55 +0000 Subject: [PATCH 16/41] A spherical projection visual --- maths | 2 +- mplot/CMakeLists.txt | 1 + mplot/SphericalProjectionVisual.h | 147 ++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 mplot/SphericalProjectionVisual.h diff --git a/maths b/maths index f2bf7687..0c72dd72 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit f2bf76872c21f803a2f5ab42b4fd030f593f7974 +Subproject commit 0c72dd72a487cfce063490ec6f76c758a24e9bac diff --git a/mplot/CMakeLists.txt b/mplot/CMakeLists.txt index 168e23f8..3c149f64 100644 --- a/mplot/CMakeLists.txt +++ b/mplot/CMakeLists.txt @@ -91,6 +91,7 @@ install( RodVisual.h ScatterVisual.h SphereVisual.h + SphericalProjectionVisual.h TriangleVisual.h TriaxesVisual.h TriFrameVisual.h diff --git a/mplot/SphericalProjectionVisual.h b/mplot/SphericalProjectionVisual.h new file mode 100644 index 00000000..713e47de --- /dev/null +++ b/mplot/SphericalProjectionVisual.h @@ -0,0 +1,147 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#define JC_VORONOI_IMPLEMENTATION +#include + +namespace mplot +{ + //! This class creates a flat projection of spherical data provided as vvecs of + //! latitude-longitude pairs and scalar or vector values. Use VisualDataModel? + template requires std::is_floating_point_v + class SphericalProjectionVisual : public mplot::VisualModel + { + public: + SphericalProjectionVisual() {} + SphericalProjectionVisual (const sm::vec _offset) : mplot::VisualModel(_offset) {} + + sm::geometry::spherical_projection::type proj_type = sm::geometry::spherical_projection::type::mercator; + + sm::vec project (const sm::vec& ll, const T radius) + { + if (this->proj_type == sm::geometry::spherical_projection::type::equirectangular) { + return sm::geometry::spherical_projection::equirectangular (ll, radius); + } else if (this->proj_type == sm::geometry::spherical_projection::type::cassini) { + return sm::geometry::spherical_projection::cassini (ll, radius); + } else { + return sm::geometry::spherical_projection::mercator (ll, radius); + } + } + + void initializeVertices() + { + this->vertexPositions.clear(); + this->vertexNormals.clear(); + this->vertexColors.clear(); + this->indices.clear(); + this->xy.resize (this->latlong.size()); + for (uint32_t i = 0; i < this->latlong.size(); ++i) { + this->xy[i] = this->project (this->latlong[i], this->radius).plus_one_dim(); + } + this->voronoi2d(); + } + + //! Compute a triangle from 3 arbitrary corners + void computeTriangle (sm::vec c1, sm::vec c2, sm::vec c3, const std::array& colr) + { + // v is the face normal + sm::vec u1 = c1-c2; + sm::vec u2 = c2-c3; + sm::vec v = u1.cross(u2); + v.renormalize(); + // Push corner vertices + this->vertex_push (c1.as_float(), this->vertexPositions); + this->vertex_push (c2.as_float(), this->vertexPositions); + this->vertex_push (c3.as_float(), this->vertexPositions); + // Colours/normals + for (uint32_t i = 0; i < 3U; ++i) { + this->vertex_push (colr, this->vertexColors); + this->vertex_push (v.as_float(), this->vertexNormals); + } + this->indices.push_back (this->idx++); + this->indices.push_back (this->idx++); + this->indices.push_back (this->idx++); + } + + void voronoi2d() + { + // Use mplot::range to find the extents of dataCoords. From these create a + // rectangle to pass to jcv_diagram_generate. + int ncoords = static_cast(this->xy.size()); + sm::range rx, ry; + rx.search_init(); + ry.search_init(); + for (int i = 0; i < ncoords ; ++i) { + if (std::isinf(this->xy[i][0])) { + std::cout << "xy["<xy[i][1])) { + std::cout << "xy["<xy[i][0]); + ry.update (this->xy[i][1]); + } + std::cout << "rx: " << rx << " ry: " << ry << std::endl; + // Generate the 2D Voronoi diagram + jcv_diagram diagram; + std::memset (&diagram, 0, sizeof(jcv_diagram)); + jcv_rect domain = { + jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + }; + + jcv_diagram_generate (ncoords, this->xy.data(), &domain, 0, &diagram); + + // We obtain access to the Voronoi cell sites: + const jcv_site* sites = jcv_diagram_get_sites (&diagram); + if (diagram.numsites != ncoords) { + std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; + } + + for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { + const jcv_site* site = &sites[i]; + jcv_graphedge* e = site->edges; // The very first edge + while (e) { + // Set z. Should be done in jcvoronoi, but haven't found out how + e->pos[0][2] = this->xy[i][2]; + e->pos[1][2] = e->pos[0][2]; + e = e->next; + } + } + + // To draw triangles iterate over the 'sites' and draw triangles + for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { + const jcv_site* site = &sites[i]; + const jcv_graphedge* e = site->edges; + std::array c = mplot::colour::black; + if (static_cast(site->index) < this->colour.size()) { c = this->colour[site->index]; } + uint32_t site_triangles = 0; + while (e) { + this->computeTriangle (site->p, e->pos[0], e->pos[1], c); + ++site_triangles; + e = e->next; + } + } + // At end free the Voronoi diagram memory + jcv_diagram_free (&diagram); + } + + // latlong, supplied by user + sm::vvec> latlong; + // Colour, supplied by user + sm::vvec> colour; + // xy, result of projection, but in 3D + sm::vvec> xy; + // The radius of our sphere + T radius = T{1}; + T border_width = std::numeric_limits::epsilon(); + }; +} From 85e9be29ddfc3a54eba64dea24f9751ec0caea3d Mon Sep 17 00:00:00 2001 From: Seb James Date: Wed, 26 Nov 2025 10:41:19 +0000 Subject: [PATCH 17/41] Adds spherical projections to healpix.cpp --- examples/healpix.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/examples/healpix.cpp b/examples/healpix.cpp index f380b271..495a43ef 100644 --- a/examples/healpix.cpp +++ b/examples/healpix.cpp @@ -7,6 +7,7 @@ #include #include #include +#include int main (int argc, char** argv) { @@ -37,7 +38,60 @@ int main (int argc, char** argv) // Finalize and add hpv->finalize(); - v.addVisualModel (hpv); + auto hpvp = v.addVisualModel (hpv); + + // Show some 2D projections, as well + sm::vvec> hpvcolours (hpvp->pixeldata.size(), mplot::colour::crimson); + sm::vvec> latlong (hpvp->pixeldata.size()); + for (uint32_t i = 0; i < hpvp->pixeldata.size(); ++i) { + + hp::t_ang ang = hp::nest2ang (hpvp->get_nside(), i); + + // ang.theta is co-latitude (and needs re-casting to be longitude), ang.phi is a longitude + float lat = ang.theta - sm::mathconst::pi_over_2; + // constrain to range -pi/2 < lat <= pi/2 + lat *= 2.0f; + sm::algo::minus_pi_to_pi (lat); + lat /= 2.0f; + + latlong[i] = { lat, static_cast(ang.phi) }; + + hpvcolours[i] = hpvp->cm.convert (hpvp->pixeldata[i]); + } + + // Add two-dimensional projections + auto spv = std::make_unique> (sm::vec{4,0,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->proj_type = sm::geometry::spherical_projection::type::mercator; + spv->latlong = latlong; + spv->colour = hpvcolours; + spv->finalize(); + auto spvp = v.addVisualModel (spv); + auto ext = spvp->extents(); // Use VisualModel::extents() to help place the label + spvp->addLabel ("Mercator projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + + spv = std::make_unique> (sm::vec{-5,-4,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->proj_type = sm::geometry::spherical_projection::type::equirectangular; + spv->latlong = latlong; + spv->colour = hpvcolours; + spv->finalize(); + spvp = v.addVisualModel (spv); + ext = spvp->extents(); + spvp->addLabel ("Equirectangular projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + + spv = std::make_unique> (sm::vec{-4,3,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->proj_type = sm::geometry::spherical_projection::type::cassini; + spv->latlong = latlong; + spv->colour = hpvcolours; + spv->finalize(); + spvp = v.addVisualModel (spv); + ext = spvp->extents(); + spvp->addLabel ("Cassini projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); v.keepOpen(); return 0; From a77bd587fe73bcb2669bbfe0f4d92d0e45f27bed Mon Sep 17 00:00:00 2001 From: Seb James Date: Wed, 26 Nov 2025 16:04:12 +0000 Subject: [PATCH 18/41] Corrections to spherical projections --- examples/healpix.cpp | 52 ++++++++++++++++++++++++++----- maths | 2 +- mplot/SphericalProjectionVisual.h | 31 +++++++++++------- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/examples/healpix.cpp b/examples/healpix.cpp index 495a43ef..3d3b112b 100644 --- a/examples/healpix.cpp +++ b/examples/healpix.cpp @@ -45,17 +45,14 @@ int main (int argc, char** argv) sm::vvec> latlong (hpvp->pixeldata.size()); for (uint32_t i = 0; i < hpvp->pixeldata.size(); ++i) { - hp::t_ang ang = hp::nest2ang (hpvp->get_nside(), i); - // ang.theta is co-latitude (and needs re-casting to be longitude), ang.phi is a longitude - float lat = ang.theta - sm::mathconst::pi_over_2; - // constrain to range -pi/2 < lat <= pi/2 - lat *= 2.0f; - sm::algo::minus_pi_to_pi (lat); - lat /= 2.0f; + hp::t_ang ang = hp::nest2ang (hpvp->get_nside(), i); - latlong[i] = { lat, static_cast(ang.phi) }; + // ang.theta is pi for the South pole and 0 for the North pole + // latitude should be in range -pi/2 (S) < lat <= pi/2 (N) + float _lat = (sm::mathconst::pi - ang.theta) - sm::mathconst::pi_over_2; + latlong[i] = { _lat, static_cast(ang.phi) }; hpvcolours[i] = hpvp->cm.convert (hpvp->pixeldata[i]); } @@ -65,12 +62,25 @@ int main (int argc, char** argv) spv->twodimensional (true); spv->proj_type = sm::geometry::spherical_projection::type::mercator; spv->latlong = latlong; + spv->lambda0 = 0.0f; spv->colour = hpvcolours; spv->finalize(); auto spvp = v.addVisualModel (spv); auto ext = spvp->extents(); // Use VisualModel::extents() to help place the label spvp->addLabel ("Mercator projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + spv = std::make_unique> (sm::vec{12,0,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->proj_type = sm::geometry::spherical_projection::type::mercator; + spv->latlong = latlong; + spv->lambda0 = sm::mathconst::pi_over_4; + spv->colour = hpvcolours; + spv->finalize(); + spvp = v.addVisualModel (spv); + ext = spvp->extents(); // Use VisualModel::extents() to help place the label + spvp->addLabel ("Mercator projection 2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + spv = std::make_unique> (sm::vec{-5,-4,0}); v.bindmodel (spv); spv->twodimensional (true); @@ -82,6 +92,20 @@ int main (int argc, char** argv) ext = spvp->extents(); spvp->addLabel ("Equirectangular projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + spv = std::make_unique> (sm::vec{-5,-8,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->lambda0 = sm::mathconst::pi_over_4; + //spv->phi0 = sm::mathconst::pi_over_4; // Latitude offset + //spv->phi1 = sm::mathconst::pi_over_4; // Longitude scaling + spv->proj_type = sm::geometry::spherical_projection::type::equirectangular; + spv->latlong = latlong; + spv->colour = hpvcolours; + spv->finalize(); + spvp = v.addVisualModel (spv); + ext = spvp->extents(); + spvp->addLabel ("Equirectangular projection2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + spv = std::make_unique> (sm::vec{-4,3,0}); v.bindmodel (spv); spv->twodimensional (true); @@ -93,6 +117,18 @@ int main (int argc, char** argv) ext = spvp->extents(); spvp->addLabel ("Cassini projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + spv = std::make_unique> (sm::vec{-7,3,0}); + v.bindmodel (spv); + spv->twodimensional (true); + spv->lambda0 = sm::mathconst::pi_over_4; + spv->proj_type = sm::geometry::spherical_projection::type::cassini; + spv->latlong = latlong; + spv->colour = hpvcolours; + spv->finalize(); + spvp = v.addVisualModel (spv); + ext = spvp->extents(); + spvp->addLabel ("Cassini projection2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + v.keepOpen(); return 0; } diff --git a/maths b/maths index 0c72dd72..ccf8297f 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 0c72dd72a487cfce063490ec6f76c758a24e9bac +Subproject commit ccf8297f4eff355854d44e66fb6990b537b3b496 diff --git a/mplot/SphericalProjectionVisual.h b/mplot/SphericalProjectionVisual.h index 713e47de..9f45ed2c 100644 --- a/mplot/SphericalProjectionVisual.h +++ b/mplot/SphericalProjectionVisual.h @@ -28,11 +28,11 @@ namespace mplot sm::vec project (const sm::vec& ll, const T radius) { if (this->proj_type == sm::geometry::spherical_projection::type::equirectangular) { - return sm::geometry::spherical_projection::equirectangular (ll, radius); + return sm::geometry::spherical_projection::equirectangular (ll, radius, this->lambda0, this->phi0, this->phi1); } else if (this->proj_type == sm::geometry::spherical_projection::type::cassini) { - return sm::geometry::spherical_projection::cassini (ll, radius); + return sm::geometry::spherical_projection::cassini (ll, radius, this->lambda0); } else { - return sm::geometry::spherical_projection::mercator (ll, radius); + return sm::geometry::spherical_projection::mercator (ll, radius, this->lambda0); } } @@ -80,16 +80,10 @@ namespace mplot rx.search_init(); ry.search_init(); for (int i = 0; i < ncoords ; ++i) { - if (std::isinf(this->xy[i][0])) { - std::cout << "xy["<xy[i][1])) { - std::cout << "xy["<xy[i][0]); ry.update (this->xy[i][1]); } - std::cout << "rx: " << rx << " ry: " << ry << std::endl; + // Generate the 2D Voronoi diagram jcv_diagram diagram; std::memset (&diagram, 0, sizeof(jcv_diagram)); @@ -126,6 +120,10 @@ namespace mplot uint32_t site_triangles = 0; while (e) { this->computeTriangle (site->p, e->pos[0], e->pos[1], c); + if constexpr (show_centres) { + auto sphc = (site->p + e->pos[0] + e->pos[1]) / T{3}; + this->computeSphere (sphc, this->centre_col, this->centre_rad, 4, 4); + } ++site_triangles; e = e->next; } @@ -142,6 +140,17 @@ namespace mplot sm::vvec> xy; // The radius of our sphere T radius = T{1}; - T border_width = std::numeric_limits::epsilon(); + // The longitudinal offset + T lambda0 = T{0}; + // Params for equirectangular projection + T phi0 = T{0}; + T phi1 = T{0}; + // A border width for the Voronoi cells + T border_width = T{0.001}; + + // To debug the centres of the Voronoi cells, set show_centres true + static constexpr bool show_centres = false; + static constexpr std::array centre_col = mplot::colour::black; + static constexpr T centre_rad = T{0.005}; }; } From 013d36eaf5491caa0c4ff24e4be82e91df705f8a Mon Sep 17 00:00:00 2001 From: Seb James Date: Wed, 26 Nov 2025 17:18:50 +0000 Subject: [PATCH 19/41] WIP on coord systems --- examples/healpix.cpp | 13 +++++++++++++ maths | 2 +- mplot/healpix/healpix_bare.hpp | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/healpix.cpp b/examples/healpix.cpp index 3d3b112b..21a5a1d7 100644 --- a/examples/healpix.cpp +++ b/examples/healpix.cpp @@ -40,6 +40,19 @@ int main (int argc, char** argv) hpv->finalize(); auto hpvp = v.addVisualModel (hpv); +#if 1 // Testing healpix angle to xyz + hp::t_ang ang_tst; + ang_tst.phi = 0; + ang_tst.theta = 0; + hp::t_vec pv = hp::loc2vec (hp::ang2loc (ang_tst)); + std::cout << "Test angle theta = " << ang_tst.theta << ", phi = " << ang_tst.phi << " gives xyz " << sm::vec({pv.x, pv.y, pv.z}) << std::endl; + + ang_tst.phi = 0; + ang_tst.theta = sm::mathconst::pi_over_2; + pv = hp::loc2vec (hp::ang2loc (ang_tst)); + std::cout << "Test angle theta = " << ang_tst.theta << ", phi = " << ang_tst.phi << " gives xyz " << sm::vec({pv.x, pv.y, pv.z}) << std::endl; +#endif + // Show some 2D projections, as well sm::vvec> hpvcolours (hpvp->pixeldata.size(), mplot::colour::crimson); sm::vvec> latlong (hpvp->pixeldata.size()); diff --git a/maths b/maths index ccf8297f..8751b727 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit ccf8297f4eff355854d44e66fb6990b537b3b496 +Subproject commit 8751b72785e62a3aaad89d0c7fafbd7d25468f9e diff --git a/mplot/healpix/healpix_bare.hpp b/mplot/healpix/healpix_bare.hpp index 9065d3f9..cbeb4e81 100644 --- a/mplot/healpix/healpix_bare.hpp +++ b/mplot/healpix/healpix_bare.hpp @@ -48,7 +48,7 @@ namespace hp { /*! * A structure describing a location on the sphere. \a Theta is the co-latitude * in radians (0 at the North Pole, increasing to pi at the South Pole. - * \a Phi is the azimuth in radians. + * \a Phi is the azimuth in radians. Starting where? And rotating which way? */ typedef struct { double theta, phi; } t_ang; /*! From fea1e794c44421e26e9c20b383a9a115550fcc9b Mon Sep 17 00:00:00 2001 From: Seb James Date: Wed, 26 Nov 2025 19:48:51 +0000 Subject: [PATCH 20/41] Shows xyz directions on the healpix and on the projections --- examples/healpix.cpp | 25 +++++++++++-------------- mplot/healpix/healpix_bare.hpp | 11 ++++++++--- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/examples/healpix.cpp b/examples/healpix.cpp index 21a5a1d7..70fbfa99 100644 --- a/examples/healpix.cpp +++ b/examples/healpix.cpp @@ -26,7 +26,17 @@ int main (int argc, char** argv) // scheme. If we fill it with sequential values, then the colour map will show the // hierarchical nature of the HEALPix. for (int64_t p = 0; p < hpv->n_pixels(); ++p) { - hpv->pixeldata[p] = static_cast(p) / hpv->n_pixels(); + hpv->pixeldata[p] = 0.5f * static_cast(p) / hpv->n_pixels(); + // Mark circles for the x, y and z axes to check they line up + hp::t_vec pv = hp::nest2vec (hpv->get_nside(), p); + auto v = sm::vec({pv.x, pv.y, pv.z}); + if (v.angle (sm::vec::ux()) < 0.05) { + hpv->pixeldata[p] = 0.6; + } else if (v.angle (sm::vec::uy()) < 0.05) { + hpv->pixeldata[p] = 0.8; + } else if (v.angle (sm::vec::uz()) < 0.05) { + hpv->pixeldata[p] = 1.0; + } } std::stringstream ss; @@ -40,19 +50,6 @@ int main (int argc, char** argv) hpv->finalize(); auto hpvp = v.addVisualModel (hpv); -#if 1 // Testing healpix angle to xyz - hp::t_ang ang_tst; - ang_tst.phi = 0; - ang_tst.theta = 0; - hp::t_vec pv = hp::loc2vec (hp::ang2loc (ang_tst)); - std::cout << "Test angle theta = " << ang_tst.theta << ", phi = " << ang_tst.phi << " gives xyz " << sm::vec({pv.x, pv.y, pv.z}) << std::endl; - - ang_tst.phi = 0; - ang_tst.theta = sm::mathconst::pi_over_2; - pv = hp::loc2vec (hp::ang2loc (ang_tst)); - std::cout << "Test angle theta = " << ang_tst.theta << ", phi = " << ang_tst.phi << " gives xyz " << sm::vec({pv.x, pv.y, pv.z}) << std::endl; -#endif - // Show some 2D projections, as well sm::vvec> hpvcolours (hpvp->pixeldata.size(), mplot::colour::crimson); sm::vvec> latlong (hpvp->pixeldata.size()); diff --git a/mplot/healpix/healpix_bare.hpp b/mplot/healpix/healpix_bare.hpp index cbeb4e81..281dddfb 100644 --- a/mplot/healpix/healpix_bare.hpp +++ b/mplot/healpix/healpix_bare.hpp @@ -46,9 +46,14 @@ namespace hp { */ /*! - * A structure describing a location on the sphere. \a Theta is the co-latitude - * in radians (0 at the North Pole, increasing to pi at the South Pole. - * \a Phi is the azimuth in radians. Starting where? And rotating which way? + * A structure describing a location on the sphere. \a theta is the co-latitude in radians (0 at + * the North Pole, increasing to pi at the South Pole. \a phi is the azimuth in radians. It's + * also correct to describe it as the longitude. With theta on the equator (theta = pi/2), phi = + * 0 gives the x unit vector (1,0,0) and phi = pi/2 gives the y unit vector (0,1,0). This + * matches longitude in the Earth-centered Earth-fixed (ECEF) scheme. Test by passing these + * values to + * + * hp::loc2vec (hp::ang2loc (_t_ang)) */ typedef struct { double theta, phi; } t_ang; /*! From b1a2ba525c1467f8f7698da04408e1bca32d9edc Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 10:30:20 +0000 Subject: [PATCH 21/41] Healpix and 2D projections are good. --- examples/healpix.cpp | 35 +++++++++++++++++++++++++++-------- maths | 2 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/examples/healpix.cpp b/examples/healpix.cpp index 70fbfa99..ca17eef8 100644 --- a/examples/healpix.cpp +++ b/examples/healpix.cpp @@ -1,5 +1,8 @@ /* * Make a healpix visual, showing the NEST index in a colour map + * + * This program also demonstrates 2D spherical projections that are available in sm::geometry and + * the Visual class mplot::SphereProjectionVisual */ #include #include @@ -67,7 +70,7 @@ int main (int argc, char** argv) } // Add two-dimensional projections - auto spv = std::make_unique> (sm::vec{4,0,0}); + auto spv = std::make_unique> (sm::vec{5,0,0}); v.bindmodel (spv); spv->twodimensional (true); spv->proj_type = sm::geometry::spherical_projection::type::mercator; @@ -79,7 +82,7 @@ int main (int argc, char** argv) auto ext = spvp->extents(); // Use VisualModel::extents() to help place the label spvp->addLabel ("Mercator projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); - spv = std::make_unique> (sm::vec{12,0,0}); + spv = std::make_unique> (sm::vec{13,0,0}); v.bindmodel (spv); spv->twodimensional (true); spv->proj_type = sm::geometry::spherical_projection::type::mercator; @@ -89,7 +92,13 @@ int main (int argc, char** argv) spv->finalize(); spvp = v.addVisualModel (spv); ext = spvp->extents(); // Use VisualModel::extents() to help place the label - spvp->addLabel ("Mercator projection 2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + std::stringstream ss1; + ss1 << "Mercator projection with " + << mplot::unicode::toUtf8(mplot::unicode::lambda) + << mplot::unicode::toUtf8(mplot::unicode::subs0) + << " = " << mplot::unicode::toUtf8(mplot::unicode::pi) << "/4"; + spvp->addLabel (ss1.str(), + sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); spv = std::make_unique> (sm::vec{-5,-4,0}); v.bindmodel (spv); @@ -114,9 +123,14 @@ int main (int argc, char** argv) spv->finalize(); spvp = v.addVisualModel (spv); ext = spvp->extents(); - spvp->addLabel ("Equirectangular projection2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); - - spv = std::make_unique> (sm::vec{-4,3,0}); + std::stringstream ss2; + ss2 << "Equirectangular projection with " + << mplot::unicode::toUtf8(mplot::unicode::lambda) + << mplot::unicode::toUtf8(mplot::unicode::subs0) + << " = " << mplot::unicode::toUtf8(mplot::unicode::pi) << "/4"; + spvp->addLabel (ss2.str(), sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + + spv = std::make_unique> (sm::vec{-9,3,0}); v.bindmodel (spv); spv->twodimensional (true); spv->proj_type = sm::geometry::spherical_projection::type::cassini; @@ -127,7 +141,7 @@ int main (int argc, char** argv) ext = spvp->extents(); spvp->addLabel ("Cassini projection", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); - spv = std::make_unique> (sm::vec{-7,3,0}); + spv = std::make_unique> (sm::vec{-4,3,0}); v.bindmodel (spv); spv->twodimensional (true); spv->lambda0 = sm::mathconst::pi_over_4; @@ -137,7 +151,12 @@ int main (int argc, char** argv) spv->finalize(); spvp = v.addVisualModel (spv); ext = spvp->extents(); - spvp->addLabel ("Cassini projection2", sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); + std::stringstream ss3; + ss3 << "Cassini projection with " + << mplot::unicode::toUtf8(mplot::unicode::lambda) + << mplot::unicode::toUtf8(mplot::unicode::subs0) + << " = " << mplot::unicode::toUtf8(mplot::unicode::pi) << "/4"; + spvp->addLabel (ss3.str(), sm::vec<>{ ext[0].min, ext[1].min - 0.16f, 0.0f }, mplot::TextFeatures(0.08f)); v.keepOpen(); return 0; diff --git a/maths b/maths index 8751b727..d7b77a7d 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit 8751b72785e62a3aaad89d0c7fafbd7d25468f9e +Subproject commit d7b77a7d5be2f1295a99df91a210d55eef7a247c From 1af90cd036961e44f6d2bbf18729daf712775751 Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 13:26:00 +0000 Subject: [PATCH 22/41] Just whitespace --- mplot/SphereVisual.h | 1 - 1 file changed, 1 deletion(-) diff --git a/mplot/SphereVisual.h b/mplot/SphereVisual.h index 423982bc..47cc17f6 100644 --- a/mplot/SphereVisual.h +++ b/mplot/SphereVisual.h @@ -41,7 +41,6 @@ namespace mplot float radius = 1.0f; //! The colour of the sphere std::array sphere_colour = {1.0f, 0.0f, 0.0f}; - }; } // namespace mplot From 717a7626d1dd6fce90b244f392d4d38990b42ec5 Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 13:26:21 +0000 Subject: [PATCH 23/41] Latest maths --- maths | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths b/maths index d7b77a7d..c9fd7d78 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit d7b77a7d5be2f1295a99df91a210d55eef7a247c +Subproject commit c9fd7d787541365515458cf7f894d7085ed10532 From 393a76691318d069c368ab5c12b109f0353979cb Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 13:27:24 +0000 Subject: [PATCH 24/41] Switch to main maths --- maths | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths b/maths index c9fd7d78..9e9373fc 160000 --- a/maths +++ b/maths @@ -1 +1 @@ -Subproject commit c9fd7d787541365515458cf7f894d7085ed10532 +Subproject commit 9e9373fc3e327b5802b6b843fbe0aab0d07365e4 From eee44380e3e2ab7c0cc8399def31957dc790d3a3 Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 17:10:36 +0000 Subject: [PATCH 25/41] Changed API in sm::maths --- mplot/compoundray/EyeVisual.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 2f800b43..3daf10b2 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -161,7 +161,7 @@ namespace mplot::compoundray sm::vec xy = {}; if (t == projection_type::equirectangular) { //sm::mathconst::pi_over_2 - xy = sm::geometry::spherical_projection::equirectangular (ll, radius); + xy = sm::geometry::spherical_projection::equirectangular (ll, radius); } else if (t == projection_type::cassini) { xy = sm::geometry::spherical_projection::cassini (ll, radius); } else if (t == projection_type::cylindrical) { From 5371a988b0b7c717a29858b4fb2b25b1c0984780 Mon Sep 17 00:00:00 2001 From: Seb James Date: Thu, 27 Nov 2025 17:10:36 +0000 Subject: [PATCH 26/41] Changed API in sm::maths --- mplot/compoundray/EyeVisual.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 2f800b43..3daf10b2 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -161,7 +161,7 @@ namespace mplot::compoundray sm::vec xy = {}; if (t == projection_type::equirectangular) { //sm::mathconst::pi_over_2 - xy = sm::geometry::spherical_projection::equirectangular (ll, radius); + xy = sm::geometry::spherical_projection::equirectangular (ll, radius); } else if (t == projection_type::cassini) { xy = sm::geometry::spherical_projection::cassini (ll, radius); } else if (t == projection_type::cylindrical) { From 090a60b78bde5086cd48b7d269413ce38c50f7bc Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 28 Nov 2025 17:45:22 +0000 Subject: [PATCH 27/41] Some more C++-ification --- mplot/jcvoronoi/jc_voronoi.h | 210 ++++++++++++----------------------- 1 file changed, 70 insertions(+), 140 deletions(-) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 76c3f262..a346b7ff 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -8,50 +8,24 @@ #ifndef JC_VORONOI_H #define JC_VORONOI_H +#include #include -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif +#include // assert() +#include // uintptr_t etc +#include +#include +#include // malloc() & free() #ifndef JCV_REAL_TYPE #define JCV_REAL_TYPE float #endif - -#ifndef JCV_REAL_TYPE_EPSILON - #define JCV_REAL_TYPE_EPSILON FLT_EPSILON -#endif - -#ifndef JCV_ATAN2 -#define JCV_ATAN2(_Y_, _X_) std::atan2(_Y_, _X_) -#endif - -#ifndef JCV_SQRT -#define JCV_SQRT(_X_) std::sqrt(_X_) -#endif - -#ifndef JCV_PI - #define JCV_PI 3.14159265358979323846264338327950288f -#endif - -#ifndef JCV_FLT_MAX - #define JCV_FLT_MAX 3.402823466e+38F -#endif +typedef JCV_REAL_TYPE jcv_real; #ifndef JCV_EDGE_INTERSECT_THRESHOLD // Fix for Issue #40 #define JCV_EDGE_INTERSECT_THRESHOLD 1.0e-10F #endif - -typedef JCV_REAL_TYPE jcv_real; - -#include +static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; typedef sm::vec jcv_point; typedef struct jcv_rect_ jcv_rect; @@ -76,8 +50,6 @@ typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, jcv_edge* e); */ typedef void (*jcv_clip_fillgap_fn)(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); - - /** * Uses malloc * If a clipper is not supplied, a default box clipper will be used @@ -187,82 +159,44 @@ struct jcv_diagram_ #pragma pack(pop) -#ifdef __cplusplus -} -#endif - #endif // JC_VORONOI_H #ifdef JC_VORONOI_IMPLEMENTATION #undef JC_VORONOI_IMPLEMENTATION -#include - // INTERNAL FUNCTIONS -#if defined(_MSC_VER) && !defined(__cplusplus) - #define inline __inline -#endif - static const int JCV_DIRECTION_LEFT = 0; static const int JCV_DIRECTION_RIGHT = 1; -static const jcv_real JCV_INVALID_VALUE = (jcv_real)-JCV_FLT_MAX; -// jcv_real +static constexpr jcv_real jcv_invalid_value = std::numeric_limits::lowest(); -static inline jcv_real jcv_abs(jcv_real v) { - return (v < 0) ? -v : v; -} - -static inline int jcv_real_eq(jcv_real a, jcv_real b) +// jcv_real +static int jcv_real_eq(jcv_real a, jcv_real b) { - return jcv_abs(a - b) < JCV_REAL_TYPE_EPSILON; -} - -static inline jcv_real jcv_real_to_int(jcv_real v) { - return (sizeof(jcv_real) == 4) ? (jcv_real)(int)v : (jcv_real)(long long)v; -} - -// Only used for calculating the initial bounding box -static inline jcv_real jcv_floor(jcv_real v) { - jcv_real i = jcv_real_to_int(v); - return (v < i) ? i - 1 : i; -} - -// Only used for calculating the initial bounding box -static inline jcv_real jcv_ceil(jcv_real v) { - jcv_real i = jcv_real_to_int(v); - return (v > i) ? i + 1 : i; -} - -static inline jcv_real jcv_min(jcv_real a, jcv_real b) { - return a < b ? a : b; -} - -static inline jcv_real jcv_max(jcv_real a, jcv_real b) { - return a > b ? a : b; + return std::abs(a - b) < std::numeric_limits::epsilon(); } // jcv_point - -static inline int jcv_point_cmp(const void* p1, const void* p2) +static int jcv_point_cmp(const void* p1, const void* p2) { - const jcv_point* s1 = (const jcv_point*) p1; - const jcv_point* s2 = (const jcv_point*) p2; + const jcv_point* s1 = static_cast(p1); + const jcv_point* s2 = static_cast(p2); return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); } -static inline int jcv_point_less( const jcv_point* pt1, const jcv_point* pt2 ) +static int jcv_point_less( const jcv_point* pt1, const jcv_point* pt2 ) { return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); } -static inline int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) +static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) { return jcv_real_eq(pt1->y(), pt2->y()) && jcv_real_eq(pt1->x(), pt2->x()); } -static inline int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) +[[maybe_unused]] +static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) { return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); } @@ -280,7 +214,7 @@ static const int JCV_CORNER_BOTTOM_LEFT = 2; static const int JCV_CORNER_BOTTOM_RIGHT = 3; static const int JCV_CORNER_TOP_RIGHT = 4; -static inline int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) +static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) { int flags = 0; if (pt->x() == min->x()) flags |= JCV_EDGE_LEFT; @@ -290,7 +224,7 @@ static inline int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, return flags; } -static inline int jcv_edge_flags_to_corner(int edge_flags) +static int jcv_edge_flags_to_corner(int edge_flags) { #define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_LEFT, JCV_CORNER_TOP_LEFT); @@ -301,38 +235,35 @@ static inline int jcv_edge_flags_to_corner(int edge_flags) return 0; } -static inline int jcv_is_corner(int corner) -{ - return corner != 0; -} +[[maybe_unused]] static int jcv_is_corner(int corner) { return corner != 0; } -static inline int jcv_corner_rotate_90(int corner) +static int jcv_corner_rotate_90(int corner) { corner--; corner = (corner+1)%4; return corner + 1; } -static inline jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) +static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) { jcv_point p; if (corner == JCV_CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } else if (corner == JCV_CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } else if (corner == JCV_CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } else if (corner == JCV_CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } - else { p[0] = JCV_INVALID_VALUE; p[1] = JCV_INVALID_VALUE; } + else { p[0] = jcv_invalid_value; p[1] = jcv_invalid_value; } return p; } -static inline jcv_real jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) +static jcv_real jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) { jcv_real diffx = pt1->x() - pt2->x(); jcv_real diffy = pt1->y() - pt2->y(); return diffx * diffx + diffy * diffy; } -static inline jcv_real jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) +static jcv_real jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) { - return (jcv_real)(JCV_SQRT(jcv_point_dist_sq(pt1, pt2))); + return std::sqrt (jcv_point_dist_sq (pt1, pt2)); } // Structs @@ -472,7 +403,7 @@ int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) return 1; } -static inline void* jcv_align(void* value, size_t alignment) +static void* jcv_align(void* value, size_t alignment) { return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); } @@ -533,9 +464,9 @@ static void jcv_free_fn(void* memctx, void* p) // jcv_edge -static inline int jcv_is_valid(const jcv_point* p) +static int jcv_is_valid(const jcv_point* p) { - return (p->x() != JCV_INVALID_VALUE || p->y() != JCV_INVALID_VALUE) ? 1 : 0; + return (p->x() != jcv_invalid_value || p->y() != jcv_invalid_value) ? 1 : 0; } static void jcv_edge_create(jcv_edge* e, jcv_site* s1, jcv_site* s2) @@ -543,10 +474,10 @@ static void jcv_edge_create(jcv_edge* e, jcv_site* s1, jcv_site* s2) e->next = 0; e->sites[0] = s1; e->sites[1] = s2; - e->pos[0][0] = JCV_INVALID_VALUE; - e->pos[0][1] = JCV_INVALID_VALUE; - e->pos[1][0] = JCV_INVALID_VALUE; - e->pos[1][1] = JCV_INVALID_VALUE; + e->pos[0][0] = jcv_invalid_value; + e->pos[0][1] = jcv_invalid_value; + e->pos[1][0] = jcv_invalid_value; + e->pos[1][1] = jcv_invalid_value; // Create line equation between S1 and S2: // jcv_real a = -1 * (s2->p[1] - s1->p[1]); @@ -740,7 +671,7 @@ static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) edge->right = newedge; } -static inline void jcv_halfedge_unlink(jcv_halfedge* he) +static void jcv_halfedge_unlink(jcv_halfedge* he) { he->left->right = he->right; he->right->left = he->left; @@ -748,7 +679,7 @@ static inline void jcv_halfedge_unlink(jcv_halfedge* he) he->right = 0; } -static inline jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, jcv_edge* e, int direction) +static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, jcv_edge* e, int direction) { jcv_halfedge* he = jcv_alloc_halfedge(internal); he->edge = e; @@ -768,12 +699,12 @@ static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he internal->halfedgepool = he; } -static inline jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) +static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) { return he->edge->sites[he->direction]; } -static inline jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) +static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) { return he->edge ? he->edge->sites[1 - he->direction] : 0; } @@ -832,9 +763,9 @@ static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) // Keeps the priority queue sorted with events sorted in ascending order // Return 1 if the edges needs to be swapped -static inline int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) +static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) { - return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; + return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; } static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) @@ -843,7 +774,7 @@ static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* h const jcv_edge* e2 = he2->edge; jcv_real d = e1->a * e2->b - e1->b * e2->a; - if( ((jcv_real)-JCV_EDGE_INTERSECT_THRESHOLD < d && d < (jcv_real)JCV_EDGE_INTERSECT_THRESHOLD) ) + if(-jcv_edge_intersect_threshold < d && d < jcv_edge_intersect_threshold) { return 0; } @@ -979,7 +910,7 @@ static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) // internal functions -static inline jcv_site* jcv_nextsite(jcv_context_internal* internal) +static jcv_site* jcv_nextsite(jcv_context_internal* internal) { return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; } @@ -1068,25 +999,26 @@ static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) } // https://cp-algorithms.com/geometry/oriented-triangle-area.html -static inline jcv_real jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) +static jcv_real jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) { return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); } -static inline jcv_real jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) +static jcv_real jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) { // We take the average of the two points, since we can better distinguish between very small edges - jcv_real half = 1/(jcv_real)2; + constexpr jcv_real half = jcv_real{0.5}; jcv_real x = (edge->pos[0][0] + edge->pos[1][0]) * half; jcv_real y = (edge->pos[0][1] + edge->pos[1][1]) * half; jcv_real diffy = y - site->p[1]; - jcv_real angle = JCV_ATAN2( diffy, x - site->p[0] ); - if( diffy < 0 ) - angle = angle + 2 * JCV_PI; - return (jcv_real)angle; + jcv_real angle = std::atan2( diffy, x - site->p[0] ); + if( diffy < 0 ) { + angle = angle + sm::mathconst::two_pi; + } + return angle; } -static inline int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) +static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) { return jcv_real_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); } @@ -1159,7 +1091,7 @@ static void jcv_endpos(jcv_context_internal* internal, jcv_edge* e, const jcv_po jcv_finishline(internal, e); } -static inline void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) +static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) { gap->neighbor = 0; gap->pos[0] = current->pos[1]; @@ -1385,23 +1317,23 @@ typedef union jcv_cast_align_struct_ void** voidpp; } jcv_cast_align_struct; -static inline void jcv_rect_union(jcv_rect* rect, const jcv_point* p) +static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) { - rect->min[0] = jcv_min(rect->min[0], p->x()); - rect->min[1] = jcv_min(rect->min[1], p->y()); - rect->max[0] = jcv_max(rect->max[0], p->x()); - rect->max[1] = jcv_max(rect->max[1], p->y()); + rect->min[0] = std::min(rect->min[0], p->x()); + rect->min[1] = std::min(rect->min[1], p->y()); + rect->max[0] = std::max(rect->max[0], p->x()); + rect->max[1] = std::max(rect->max[1], p->y()); } -static inline void jcv_rect_round(jcv_rect* rect) +static void jcv_rect_round(jcv_rect* rect) { - rect->min[0] = jcv_floor(rect->min[0]); - rect->min[1] = jcv_floor(rect->min[1]); - rect->max[0] = jcv_ceil(rect->max[0]); - rect->max[1] = jcv_ceil(rect->max[1]); + rect->min[0] = std::floor(rect->min[0]); + rect->min[1] = std::floor(rect->min[1]); + rect->max[0] = std::ceil(rect->max[0]); + rect->max[1] = std::ceil(rect->max[1]); } -static inline void jcv_rect_inflate(jcv_rect* rect, jcv_real amount) +static void jcv_rect_inflate(jcv_rect* rect, jcv_real amount) { rect->min[0] -= amount; rect->min[1] -= amount; @@ -1415,8 +1347,8 @@ static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) jcv_site* sites = internal->sites; jcv_rect r; - r.min[0] = r.min[1] = JCV_FLT_MAX; - r.max[0] = r.max[1] = -JCV_FLT_MAX; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; // Prune duplicates first @@ -1447,8 +1379,8 @@ static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect jcv_site* sites = internal->sites; jcv_rect r; - r.min[0] = r.min[1] = JCV_FLT_MAX; - r.max[0] = r.max[1] = -JCV_FLT_MAX; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; for (int i = 0; i < num_sites; i++) @@ -1554,8 +1486,8 @@ void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, con internal->clipper = *clipper; jcv_rect tmp_rect; - tmp_rect.min[0] = tmp_rect.min[1] = JCV_FLT_MAX; - tmp_rect.max[0] = tmp_rect.max[1] = -JCV_FLT_MAX; + tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); + tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); jcv_prune_duplicates(internal, &tmp_rect); // Prune using the test second @@ -1713,8 +1645,6 @@ void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, con #define JC_VORONOI_IMPLEMENTATION // If you wish to use doubles //#define JCV_REAL_TYPE double - //#define JCV_ATAN2 atan2 - //#define JCV_FLT_MAX 1.7976931348623157E+308 #include "jc_voronoi.h" void draw_edges(const jcv_diagram* diagram); From 3dca72b642730f28b541e821ca57293288248120 Mon Sep 17 00:00:00 2001 From: Seb James Date: Fri, 28 Nov 2025 17:46:14 +0000 Subject: [PATCH 28/41] It's necessary to use double precision in jcvoronoi to avoid bugs --- mplot/compoundray/EyeVisual.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 3daf10b2..c614da88 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -14,10 +14,13 @@ #include #define JC_VORONOI_IMPLEMENTATION +#define JCV_REAL_TYPE double // double precision in jcvoronoi necessary #include namespace mplot::compoundray { + using jcv_real = JCV_REAL_TYPE; + // This is a binary-compatible equivalent to Ommatidium from cameras/CompoundEyeDataTypes.h in compound-ray. // Use reinterpret_cast*>(ommatidia) if using compound ray. struct Ommatidium @@ -173,7 +176,7 @@ namespace mplot::compoundray } // 2D positions for the ommatidia centres encoded in 3D vecs. Gets re-used for each projection - sm::vvec> omm2d; + sm::vvec> omm2d; /* * Possibly each of these need replication for each of multiple 2d projections @@ -343,9 +346,8 @@ namespace mplot::compoundray sm::vec rot_coord = (coord_rotn * sph_coord[0]).less_one_dim(); sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_radius); sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_radius); - //xy[0] = -xy[0]; // invert x // Add xy as one of the points that we'll make a Voronoi diagram from. - this->omm2d.push_back (xy.plus_one_dim()); + this->omm2d.push_back (xy.plus_one_dim().as()); } } // Make 2D Voronoi of omm2d. @@ -385,7 +387,7 @@ namespace mplot::compoundray // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->omm2d.size()); - sm::range rx, ry; + sm::range rx, ry; rx.search_init(); ry.search_init(); for (int i = 0; i < ncoords ; ++i) { @@ -446,9 +448,9 @@ namespace mplot::compoundray t3 = (this->projections[pri].twod_transform * e->pos[1]).less_one_dim(); this->computeTriangle (t1, t2, t3, colour); #else - flat_triangles.push_back (site->p); - flat_triangles.push_back (e->pos[0]); - flat_triangles.push_back (e->pos[1]); + flat_triangles.push_back (site->p.as()); + flat_triangles.push_back (e->pos[0].as()); + flat_triangles.push_back (e->pos[1].as()); flat_colours.push_back (colour); #endif ++site_triangles; From f737150f8affc6dd09a35f9bed5edfa1a6a5255c Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 09:35:51 +0000 Subject: [PATCH 29/41] Corrected rotation of coords for CompoundRay --- mplot/compoundray/EyeVisual.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index c614da88..0003af34 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -334,8 +334,13 @@ namespace mplot::compoundray std::cout << "NOTE: Cylindrical projections are currently unimplemented\n"; } else { // Compute intersections between ommatidia direction vectors and our projection sphere. + + // Rotate coordinates as the compound eye looks forwards along z, whereas 2D + // projections look forwards along x by convention. sm::mat44 coord_rotn; + coord_rotn.rotate (sm::vec<>::uz(), sm::mathconst::pi_over_2); coord_rotn.rotate (sm::vec<>::ux(), sm::mathconst::pi_over_2); + for (size_t i = this->projections[pri].start_i; i < this->ommatidia->size() && i < this->projections[pri].end_i; ++i) { sm::vec, 2> sph_coord = sm::geometry::ray_sphere_intersection (this->projections[pri].proj_centre, this->projections[pri].proj_radius, From a63aa2c67fb14d36561a0dff88ac2dd1157524a3 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 11:25:03 +0000 Subject: [PATCH 30/41] More C++ification of jc_voronoi --- mplot/compoundray/EyeVisual.h | 37 +- mplot/jcvoronoi/jc_voronoi.h | 2663 +++++++++++++++++---------------- 2 files changed, 1361 insertions(+), 1339 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 0003af34..da436b12 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -13,13 +13,12 @@ #include #include -#define JC_VORONOI_IMPLEMENTATION -#define JCV_REAL_TYPE double // double precision in jcvoronoi necessary +//#define JCV_REAL_TYPE double // double precision in jcvoronoi necessary #include namespace mplot::compoundray { - using jcv_real = JCV_REAL_TYPE; + //using jcv_real = JCV_REAL_TYPE; // This is a binary-compatible equivalent to Ommatidium from cameras/CompoundEyeDataTypes.h in compound-ray. // Use reinterpret_cast*>(ommatidia) if using compound ray. @@ -176,7 +175,7 @@ namespace mplot::compoundray } // 2D positions for the ommatidia centres encoded in 3D vecs. Gets re-used for each projection - sm::vvec> omm2d; + sm::vvec> omm2d; /* * Possibly each of these need replication for each of multiple 2d projections @@ -352,7 +351,7 @@ namespace mplot::compoundray sm::vec ll = sm::geometry::spherical_projection::xyz_to_latlong (rot_coord, this->projections[pri].proj_radius); sm::vec xy = this->spherical_projection (ll, this->projections[pri].proj_type, this->projections[pri].proj_radius); // Add xy as one of the points that we'll make a Voronoi diagram from. - this->omm2d.push_back (xy.plus_one_dim().as()); + this->omm2d.push_back (xy.plus_one_dim().as()); } } // Make 2D Voronoi of omm2d. @@ -392,7 +391,7 @@ namespace mplot::compoundray // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->omm2d.size()); - sm::range rx, ry; + sm::range rx, ry; rx.search_init(); ry.search_init(); for (int i = 0; i < ncoords ; ++i) { @@ -400,22 +399,24 @@ namespace mplot::compoundray ry.update (this->omm2d[i][1]); } // Generate the 2D Voronoi diagram - jcv_diagram diagram; - std::memset (&diagram, 0, sizeof(jcv_diagram)); - jcv_rect domain = { - jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + // jc::voronoi vd; // will then do some of the following in constructor: + + jc::jcv_diagram diagram; + std::memset (&diagram, 0, sizeof(jc::jcv_diagram)); + jc::jcv_rect domain = { + jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} }; - jcv_diagram_generate (ncoords, this->omm2d.data(), &domain, 0, &diagram); + jc::voronoi::jcv_diagram_generate (ncoords, this->omm2d.data(), &domain, 0, &diagram); // We obtain access to the Voronoi cell sites: - const jcv_site* sites = jcv_diagram_get_sites (&diagram); + const jc::jcv_site* sites = jc::voronoi::jcv_diagram_get_sites (&diagram); if (diagram.numsites != ncoords) { std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; } for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { - const jcv_site* site = &sites[i]; - jcv_graphedge* e = site->edges; // The very first edge + const jc::jcv_site* site = &sites[i]; + jc::jcv_graphedge* e = site->edges; // The very first edge while (e) { // Set z. Should be done in jcvoronoi, but haven't found out how e->pos[0][2] = this->omm2d[i][2]; @@ -433,8 +434,8 @@ namespace mplot::compoundray sm::vvec> flat_colours; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; this->projections[pri].site_indices[i] = site->index; std::array colour = mplot::colour::black; if (site->index + this->projections[pri].start_i < ommData->size()) { @@ -476,7 +477,7 @@ namespace mplot::compoundray } #endif // At end free the Voronoi diagram memory - jcv_diagram_free (&diagram); + jc::voronoi::jcv_diagram_free (&diagram); } // If false, hide 3D representation (the ommatidial cones and discs) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index a346b7ff..b50c0349 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -5,1559 +5,1580 @@ // Copyright (c) 2015-2023 Mathias Westerdahl // For LICENSE (MIT), USAGE or HISTORY, see bottom of file -#ifndef JC_VORONOI_H -#define JC_VORONOI_H +#pragma once +#include // malloc() & free() #include #include #include // assert() #include // uintptr_t etc +#include #include #include -#include // malloc() & free() - -#ifndef JCV_REAL_TYPE - #define JCV_REAL_TYPE float -#endif -typedef JCV_REAL_TYPE jcv_real; #ifndef JCV_EDGE_INTERSECT_THRESHOLD // Fix for Issue #40 #define JCV_EDGE_INTERSECT_THRESHOLD 1.0e-10F #endif -static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; - -typedef sm::vec jcv_point; -typedef struct jcv_rect_ jcv_rect; -typedef struct jcv_site_ jcv_site; -typedef struct jcv_edge_ jcv_edge; -typedef struct jcv_graphedge_ jcv_graphedge; -typedef struct jcv_delauney_edge_ jcv_delauney_edge; -typedef struct jcv_delauney_iter_ jcv_delauney_iter; -typedef struct jcv_diagram_ jcv_diagram; -typedef struct jcv_clipper_ jcv_clipper; -typedef struct jcv_context_internal_ jcv_context_internal; - -/// Tests if a point is inside the final shape -typedef int (*jcv_clip_test_point_fn)(const jcv_clipper* clipper, const jcv_point p); -/** Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] - * Returns 0 if not successful - */ -typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, jcv_edge* e); -/** Given the clipper, the site and the last edge, - * closes any gaps in the polygon by adding new edges that follow the bounding shape - * The internal context is use when allocating new edges. - */ -typedef void (*jcv_clip_fillgap_fn)(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); - -/** - * Uses malloc - * If a clipper is not supplied, a default box clipper will be used - * If rect is null, an automatic bounding box is calculated, with an extra padding of 10 units - * All points will be culled against the bounding rect, and all edges will be clipped against it. - */ -extern void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* diagram ); - -typedef void* (*FJCVAllocFn)(void* userctx, size_t size); -typedef void (*FJCVFreeFn)(void* userctx, void* p); - -// Same as above, but allows the client to use a custom allocator -extern void jcv_diagram_generate_useralloc( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* diagram ); -// Uses free (or the registered custom free function) -extern void jcv_diagram_free( jcv_diagram* diagram ); - -// Returns an array of sites, where each index is the same as the original input point array. -extern const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ); - -// Returns a linked list of all the voronoi edges -// excluding the ones that lie on the borders of the bounding box. -// For a full list of edges, you need to iterate over the sites, and their graph edges. -extern const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ); - -// Iterates over a list of edges, skipping invalid edges (where p0==p1) -extern const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ); - -// Creates an iterator over the delauney edges of a voronoi diagram -void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ); - -// Steps the iterator and returns the next edge -// Returns 0 when there are no more edges -int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ); - -// For the default clipper -extern int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p); -extern int jcv_boxshape_clip(const jcv_clipper* clipper, jcv_edge* e); -extern void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); - - -#pragma pack(push, 1) - -struct jcv_graphedge_ -{ - struct jcv_graphedge_* next; - struct jcv_edge_* edge; - struct jcv_site_* neighbor; - jcv_point pos[2]; - jcv_real angle; -}; - -struct jcv_site_ +namespace jc { - jcv_point p; - int index; // Index into the original list of points - jcv_graphedge* edges; // The half edges owned by the cell -}; +#pragma pack(push, 1) -// The coefficients a, b and c are from the general line equation: ax * by + c = 0 -struct jcv_edge_ -{ - struct jcv_edge_* next; - jcv_site* sites[2]; - jcv_point pos[2]; - jcv_real a; - jcv_real b; - jcv_real c; -}; - -struct jcv_delauney_iter_ -{ - const jcv_edge* sentinel; - const jcv_edge* current; -}; + template + using jcv_point = sm::vec; -struct jcv_delauney_edge_ -{ - const jcv_edge* edge; // The voronoi edge separating the two sites - const jcv_site* sites[2]; - jcv_point pos[2]; // the positions of the two sites -}; + // fwd declar graphpedge + template struct jcv_graphedge; -struct jcv_rect_ -{ - jcv_point min; - jcv_point max; -}; + template + struct jcv_site + { + jcv_point p; + int index; // Index into the original list of points + jcv_graphedge* edges; // The half edges owned by the cell + }; + + // The coefficients a, b and c are from the general line equation: ax * by + c = 0 + template + struct jcv_edge + { + struct jcv_edge* next; + jcv_site* sites[2]; + jcv_point pos[2]; + jcv_real a; + jcv_real b; + jcv_real c; + }; + + template + struct jcv_graphedge + { + struct jcv_graphedge* next; + struct jcv_edge* edge; + struct jcv_site* neighbor; + jcv_point pos[2]; + jcv_real angle; + }; + + template + struct jcv_delauney_iter + { + const jcv_edge* sentinel; + const jcv_edge* current; + }; -struct jcv_clipper_ -{ - jcv_clip_test_point_fn test_fn; - jcv_clip_edge_fn clip_fn; - jcv_clip_fillgap_fn fill_fn; - jcv_point min; // The bounding rect min - jcv_point max; // The bounding rect max - void* ctx; // User defined context -}; - -struct jcv_diagram_ -{ - jcv_context_internal* internal; - int numsites; - jcv_point min; - jcv_point max; -}; + template + struct jcv_delauney_edge + { + const jcv_edge* edge; // The voronoi edge separating the two sites + const jcv_site* sites[2]; + jcv_point pos[2]; // the positions of the two sites + }; + template + struct jcv_rect + { + jcv_point min; + jcv_point max; + }; + + // Convert these to templated usings? or use std::function? + /// Tests if a point is inside the final shape + //typedef int (*jcv_clip_test_point_fn)(const jcv_clipper* clipper, const jcv_point p); + //template + + /** Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] + * Returns 0 if not successful + */ + //typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, jcv_edge* e); + + /** Given the clipper, the site and the last edge, + * closes any gaps in the polygon by adding new edges that follow the bounding shape + * The internal context is use when allocating new edges. + */ + //typedef void (*jcv_clip_fillgap_fn)(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); + + // Forward declare jcv_context_internal for the std::function + template struct jcv_context_internal; + + template + struct jcv_clipper + { + // Tests if a point is inside the final shape + std::function* clipper, const jcv_point p)> test_fn; + // Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] + // Returns 0 if not successful + std::function* clipper, jcv_edge* e)> clip_fn; + // Given the clipper, the site and the last edge, + // closes any gaps in the polygon by adding new edges that follow the bounding shape + // The internal context is use when allocating new edges. + std::function* clipper, jcv_context_internal* allocator, jcv_site* s)> fill_fn; + jcv_point min; // The bounding rect min + jcv_point max; // The bounding rect max + void* ctx; // User defined context + }; + +#if 0 // shift to after context_internal + template + struct jcv_diagram + { + jcv_context_internal* internal; + int numsites; + jcv_point min; + jcv_point max; + }; +#endif #pragma pack(pop) -#endif // JC_VORONOI_H - -#ifdef JC_VORONOI_IMPLEMENTATION -#undef JC_VORONOI_IMPLEMENTATION - -// INTERNAL FUNCTIONS - -static const int JCV_DIRECTION_LEFT = 0; -static const int JCV_DIRECTION_RIGHT = 1; - -static constexpr jcv_real jcv_invalid_value = std::numeric_limits::lowest(); - -// jcv_real -static int jcv_real_eq(jcv_real a, jcv_real b) -{ - return std::abs(a - b) < std::numeric_limits::epsilon(); -} - -// jcv_point -static int jcv_point_cmp(const void* p1, const void* p2) -{ - const jcv_point* s1 = static_cast(p1); - const jcv_point* s2 = static_cast(p2); - return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); -} - -static int jcv_point_less( const jcv_point* pt1, const jcv_point* pt2 ) -{ - return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); -} - -static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) -{ - return jcv_real_eq(pt1->y(), pt2->y()) && jcv_real_eq(pt1->x(), pt2->x()); -} - -[[maybe_unused]] -static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) -{ - return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); -} - -// corners - -static const int JCV_EDGE_LEFT = 1; -static const int JCV_EDGE_RIGHT = 2; -static const int JCV_EDGE_BOTTOM = 4; -static const int JCV_EDGE_TOP = 8; - -static const int JCV_CORNER_NONE = 0; -static const int JCV_CORNER_TOP_LEFT = 1; -static const int JCV_CORNER_BOTTOM_LEFT = 2; -static const int JCV_CORNER_BOTTOM_RIGHT = 3; -static const int JCV_CORNER_TOP_RIGHT = 4; - -static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) -{ - int flags = 0; - if (pt->x() == min->x()) flags |= JCV_EDGE_LEFT; - else if (pt->x() == max->x()) flags |= JCV_EDGE_RIGHT; - if (pt->y() == min->y()) flags |= JCV_EDGE_BOTTOM; - else if (pt->y() == max->y()) flags |= JCV_EDGE_TOP; - return flags; -} - -static int jcv_edge_flags_to_corner(int edge_flags) -{ - #define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL - TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_LEFT, JCV_CORNER_TOP_LEFT); - TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_RIGHT, JCV_CORNER_TOP_RIGHT); - TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT); - TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT); - #undef TEST_FLAGS - return 0; -} - -[[maybe_unused]] static int jcv_is_corner(int corner) { return corner != 0; } - -static int jcv_corner_rotate_90(int corner) -{ - corner--; - corner = (corner+1)%4; - return corner + 1; -} -static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) -{ - jcv_point p; - if (corner == JCV_CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } - else if (corner == JCV_CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } - else if (corner == JCV_CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } - else if (corner == JCV_CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } - else { p[0] = jcv_invalid_value; p[1] = jcv_invalid_value; } - return p; -} - -static jcv_real jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) -{ - jcv_real diffx = pt1->x() - pt2->x(); - jcv_real diffy = pt1->y() - pt2->y(); - return diffx * diffx + diffy * diffy; -} - -static jcv_real jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) -{ - return std::sqrt (jcv_point_dist_sq (pt1, pt2)); -} - -// Structs - #pragma pack(push, 1) -typedef struct jcv_halfedge_ -{ - jcv_edge* edge; - struct jcv_halfedge_* left; - struct jcv_halfedge_* right; - jcv_point vertex; - jcv_real y; - int direction; // 0=left, 1=right - int pqpos; -} jcv_halfedge; - -typedef struct jcv_memoryblock_ -{ - size_t sizefree; - struct jcv_memoryblock_* next; - char* memory; -} jcv_memoryblock; - + // Second batch of structs + template + struct jcv_halfedge + { + jcv_edge* edge; + struct jcv_halfedge* left; + struct jcv_halfedge* right; + jcv_point vertex; + jcv_real y; + int direction; // 0=left, 1=right + int pqpos; + }; + + struct jcv_memoryblock + { + size_t sizefree; + struct jcv_memoryblock* next; + char* memory; + }; -typedef int (*FJCVPriorityQueuePrint)(const void* node, int pos); + typedef int (*FJCVPriorityQueuePrint)(const void* node, int pos); -typedef struct jcv_priorityqueue_ -{ - // Implements a binary heap - int maxnumitems; - int numitems; - void** items; -} jcv_priorityqueue; + struct jcv_priorityqueue + { + // Implements a binary heap + int maxnumitems; + int numitems; + void** items; + }; + using FJCVAllocFn = void*(void* userctx, size_t size); + using FJCVFreeFn = void(void* userctx, void* p); -struct jcv_context_internal_ -{ - void* mem; - jcv_edge* edges; - jcv_halfedge* beachline_start; - jcv_halfedge* beachline_end; - jcv_halfedge* last_inserted; - jcv_priorityqueue* eventqueue; - - jcv_site* sites; - jcv_site* bottomsite; - int numsites; - int currentsite; - int _padding; - - jcv_memoryblock* memblocks; - jcv_edge* edgepool; - jcv_halfedge* halfedgepool; - void** eventmem; - jcv_clipper clipper; - - void* memctx; // Given by the user - FJCVAllocFn alloc; - FJCVFreeFn free; - - jcv_rect rect; -}; + template + struct jcv_context_internal + { + void* mem; + jcv_edge* edges; + jcv_halfedge* beachline_start; + jcv_halfedge* beachline_end; + jcv_halfedge* last_inserted; + jcv_priorityqueue* eventqueue; + + jcv_site* sites; + jcv_site* bottomsite; + int numsites; + int currentsite; + int _padding; + + jcv_memoryblock* memblocks; + jcv_edge* edgepool; + jcv_halfedge* halfedgepool; + void** eventmem; + jcv_clipper clipper; + + void* memctx; // Given by the user + std::function alloc; + std::function free; + + jcv_rect rect; + }; + + template + struct jcv_diagram + { + jcv_context_internal* internal; + int numsites; + jcv_point min; + jcv_point max; + }; #pragma pack(pop) -void jcv_diagram_free( jcv_diagram* d ) -{ - jcv_context_internal* internal = d->internal; - void* memctx = internal->memctx; - FJCVFreeFn freefn = internal->free; - while(internal->memblocks) + template requires std::is_floating_point_v + struct voronoi { - jcv_memoryblock* p = internal->memblocks; - internal->memblocks = internal->memblocks->next; - freefn( memctx, p ); - } - - freefn( memctx, internal->mem ); -} - -const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ) -{ - return diagram->internal->sites; -} + voronoi(){} + ~voronoi(){} -const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ) -{ - jcv_edge e; - e.next = diagram->internal->edges; - return jcv_diagram_get_next_edge(&e); -} + static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; -const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ) -{ - const jcv_edge* e = edge->next; - while (e != 0 && jcv_point_eq(&e->pos[0], &e->pos[1])) { - e = e->next; - } - return e; -} - -void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ) -{ - iter->current = 0; - iter->sentinel = jcv_diagram_get_edges(diagram); -} - -int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) -{ - if (iter->sentinel) - { - iter->current = iter->sentinel; - iter->sentinel = 0; - } - else { - // Note: If we use the raw edges, we still get a proper delauney triangulation - // However, the result looks less relevant to the cells contained within the bounding box - // E.g. some cells that look isolated from each other, suddenly still are connected, - // because they share an edge outside of the bounding box - iter->current = jcv_diagram_get_next_edge(iter->current); - } +/* + typedef sm::vec jcv_point; + typedef struct jcv_rect_ jcv_rect; + typedef struct jcv_site_ jcv_site; + typedef struct jcv_edge_ jcv_edge; + typedef struct jcv_graphedge_ jcv_graphedge; + typedef struct jcv_delauney_edge_ jcv_delauney_edge; + typedef struct jcv_delauney_iter_ jcv_delauney_iter; + typedef struct jcv_diagram_ jcv_diagram; + typedef struct jcv_clipper_ jcv_clipper; + typedef struct jcv_context_internal_ jcv_context_internal; + + typedef void* (*FJCVAllocFn)(void* userctx, size_t size); + typedef void (*FJCVFreeFn)(void* userctx, void* p); +*/ + // FIRST batch of structs were here + + // INTERNAL FUNCTIONS + + static const int JCV_DIRECTION_LEFT = 0; + static const int JCV_DIRECTION_RIGHT = 1; + + static constexpr jcv_real jcv_invalid_value = std::numeric_limits::lowest(); + + // App specific equality + static int jcv_real_eq(jcv_real a, jcv_real b) + { + return std::abs(a - b) < std::numeric_limits::epsilon(); + } - while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0)) - { - iter->current = jcv_diagram_get_next_edge(iter->current); - } + // jcv_point + static int jcv_point_cmp(const void* p1, const void* p2) + { + const jcv_point* s1 = static_cast*>(p1); + const jcv_point* s2 = static_cast*>(p2); + return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); + } - if (!iter->current) - return 0; + static int jcv_point_less (const jcv_point* pt1, const jcv_point* pt2 ) + { + return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); + } - next->edge = iter->current; - next->sites[0] = next->edge->sites[0]; - next->sites[1] = next->edge->sites[1]; - next->pos[0] = next->sites[0]->p; - next->pos[1] = next->sites[1]->p; - return 1; -} + static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) + { + return jcv_real_eq(pt1->y(), pt2->y()) && jcv_real_eq(pt1->x(), pt2->x()); + } -static void* jcv_align(void* value, size_t alignment) -{ - return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); -} + [[maybe_unused]] + static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + { + return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); + } -static void* jcv_alloc(jcv_context_internal* internal, size_t size) -{ - if( !internal->memblocks || internal->memblocks->sizefree < (size+sizeof(void*)) ) - { - size_t blocksize = 16 * 1024; - jcv_memoryblock* block = (jcv_memoryblock*)internal->alloc( internal->memctx, blocksize ); - size_t offset = sizeof(jcv_memoryblock); - block->sizefree = blocksize - offset; - block->next = internal->memblocks; - block->memory = ((char*)block) + offset; - internal->memblocks = block; - } - void* p_raw = internal->memblocks->memory; - void* p_aligned = jcv_align(p_raw, sizeof(void*)); - size += (uintptr_t)p_aligned - (uintptr_t)p_raw; - internal->memblocks->memory += size; - internal->memblocks->sizefree -= size; - return p_aligned; -} - -static jcv_edge* jcv_alloc_edge(jcv_context_internal* internal) -{ - return (jcv_edge*)jcv_alloc(internal, sizeof(jcv_edge)); -} + // edges and corners + static const int JCV_EDGE_LEFT = 1; + static const int JCV_EDGE_RIGHT = 2; + static const int JCV_EDGE_BOTTOM = 4; + static const int JCV_EDGE_TOP = 8; -static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal) -{ - if( internal->halfedgepool ) - { - jcv_halfedge* edge = internal->halfedgepool; - internal->halfedgepool = internal->halfedgepool->right; - return edge; - } + static const int JCV_CORNER_NONE = 0; + static const int JCV_CORNER_TOP_LEFT = 1; + static const int JCV_CORNER_BOTTOM_LEFT = 2; + static const int JCV_CORNER_BOTTOM_RIGHT = 3; + static const int JCV_CORNER_TOP_RIGHT = 4; - return (jcv_halfedge*)jcv_alloc(internal, sizeof(jcv_halfedge)); -} + static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + { + int flags = 0; + if (pt->x() == min->x()) flags |= JCV_EDGE_LEFT; + else if (pt->x() == max->x()) flags |= JCV_EDGE_RIGHT; + if (pt->y() == min->y()) flags |= JCV_EDGE_BOTTOM; + else if (pt->y() == max->y()) flags |= JCV_EDGE_TOP; + return flags; + } -static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal) -{ - return (jcv_graphedge*)jcv_alloc(internal, sizeof(jcv_graphedge)); -} + static int jcv_edge_flags_to_corner(int edge_flags) + { +#define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL + TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_LEFT, JCV_CORNER_TOP_LEFT); + TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_RIGHT, JCV_CORNER_TOP_RIGHT); + TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT); + TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT); +#undef TEST_FLAGS + return 0; + } -static void* jcv_alloc_fn(void* memctx, size_t size) -{ - (void)memctx; - return malloc(size); -} + [[maybe_unused]] static int jcv_is_corner(int corner) { return corner != 0; } -static void jcv_free_fn(void* memctx, void* p) -{ - (void)memctx; - free(p); -} + static int jcv_corner_rotate_90(int corner) + { + corner--; + corner = (corner+1)%4; + return corner + 1; + } + static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) + { + jcv_point p; + if (corner == JCV_CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } + else if (corner == JCV_CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } + else if (corner == JCV_CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } + else if (corner == JCV_CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } + else { p[0] = jcv_invalid_value; p[1] = jcv_invalid_value; } + return p; + } -// jcv_edge + static jcv_real jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) + { + jcv_real diffx = pt1->x() - pt2->x(); + jcv_real diffy = pt1->y() - pt2->y(); + return diffx * diffx + diffy * diffy; + } -static int jcv_is_valid(const jcv_point* p) -{ - return (p->x() != jcv_invalid_value || p->y() != jcv_invalid_value) ? 1 : 0; -} + static jcv_real jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) + { + return std::sqrt (jcv_point_dist_sq (pt1, pt2)); + } -static void jcv_edge_create(jcv_edge* e, jcv_site* s1, jcv_site* s2) -{ - e->next = 0; - e->sites[0] = s1; - e->sites[1] = s2; - e->pos[0][0] = jcv_invalid_value; - e->pos[0][1] = jcv_invalid_value; - e->pos[1][0] = jcv_invalid_value; - e->pos[1][1] = jcv_invalid_value; - - // Create line equation between S1 and S2: - // jcv_real a = -1 * (s2->p[1] - s1->p[1]); - // jcv_real b = s2->p[0] - s1->p[0]; - // //jcv_real c = -1 * (s2->p[0] - s1->p[0]) * s1->p[1] + (s2->p[1] - s1->p[1]) * s1->p[0]; - // - // // create perpendicular line - // jcv_real pa = b; - // jcv_real pb = -a; - // //jcv_real pc = pa * s1->p[0] + pb * s1->p[1]; - // - // // Move to the mid point - // jcv_real mx = s1->p[0] + dx * jcv_real(0.5); - // jcv_real my = s1->p[1] + dy * jcv_real(0.5); - // jcv_real pc = ( pa * mx + pb * my ); - - jcv_real dx = s2->p[0] - s1->p[0]; - jcv_real dy = s2->p[1] - s1->p[1]; - int dx_is_larger = (dx*dx) > (dy*dy); // instead of fabs - - // Simplify it, using dx and dy - e->c = dx * (s1->p[0] + dx * (jcv_real)0.5) + dy * (s1->p[1] + dy * (jcv_real)0.5); - - if( dx_is_larger ) - { - e->a = (jcv_real)1; - e->b = dy / dx; - e->c /= dx; - } - else - { - e->a = dx / dy; - e->b = (jcv_real)1; - e->c /= dy; - } -} + // SECOND batch of Structs were here -// CLIPPING -int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p) -{ - return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] && - p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; -} + // Uses free (or the registered custom free function) + static void jcv_diagram_free( jcv_diagram* d ) + { + jcv_context_internal* internal = d->internal; + void* memctx = internal->memctx; + //FJCVFreeFn& freefn = internal->free; + while(internal->memblocks) + { + jcv_memoryblock* p = internal->memblocks; + internal->memblocks = internal->memblocks->next; + internal->free( memctx, p ); + } -// The line equation: ax + by + c = 0 -// see jcv_edge_create -int jcv_boxshape_clip(const jcv_clipper* clipper, jcv_edge* e) -{ - jcv_real pxmin = clipper->min[0]; - jcv_real pxmax = clipper->max[0]; - jcv_real pymin = clipper->min[1]; - jcv_real pymax = clipper->max[1]; - - jcv_real x1, y1, x2, y2; - jcv_point* s1; - jcv_point* s2; - if (e->a == (jcv_real)1 && e->b >= (jcv_real)0) - { - s1 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; - s2 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; - } - else - { - s1 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; - s2 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; - } + internal->free( memctx, internal->mem ); + } - if (e->a == (jcv_real)1) // delta x is larger - { - y1 = pymin; - if (s1 != 0 && s1->y() > pymin) + // Returns an array of sites, where each index is the same as the original input point array. + static const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ) { - y1 = s1->y(); + return diagram->internal->sites; } - if( y1 > pymax ) + + // Iterates over a list of edges, skipping invalid edges (where p0==p1) + const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ) { - y1 = pymax; + const jcv_edge* e = edge->next; + while (e != 0 && jcv_point_eq(&e->pos[0], &e->pos[1])) { + e = e->next; + } + return e; } - x1 = e->c - e->b * y1; - y2 = pymax; - if (s2 != 0 && s2->y() < pymax) - y2 = s2->y(); - if( y2 < pymin ) + // Returns a linked list of all the voronoi edges excluding the ones that lie on the borders of + // the bounding box. For a full list of edges, you need to iterate over the sites, and their + // graph edges. + const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ) { - y2 = pymin; + jcv_edge e; + e.next = diagram->internal->edges; + return jcv_diagram_get_next_edge(&e); } - x2 = (e->c) - (e->b) * y2; - // Never occurs according to lcov - // if( ((x1 > pxmax) & (x2 > pxmax)) | ((x1 < pxmin) & (x2 < pxmin)) ) - // { - // return 0; - // } - if (x1 > pxmax) + + // Creates an iterator over the delauney edges of a voronoi diagram + void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ) { - x1 = pxmax; - y1 = (e->c - x1) / e->b; + iter->current = 0; + iter->sentinel = jcv_diagram_get_edges(diagram); } - else if (x1 < pxmin) + + // Steps the iterator and returns the next edge Returns 0 when there are no more edges + int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) { - x1 = pxmin; - y1 = (e->c - x1) / e->b; + if (iter->sentinel) + { + iter->current = iter->sentinel; + iter->sentinel = 0; + } + else { + // Note: If we use the raw edges, we still get a proper delauney triangulation + // However, the result looks less relevant to the cells contained within the bounding box + // E.g. some cells that look isolated from each other, suddenly still are connected, + // because they share an edge outside of the bounding box + iter->current = jcv_diagram_get_next_edge(iter->current); + } + + while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0)) + { + iter->current = jcv_diagram_get_next_edge(iter->current); + } + + if (!iter->current) + return 0; + + next->edge = iter->current; + next->sites[0] = next->edge->sites[0]; + next->sites[1] = next->edge->sites[1]; + next->pos[0] = next->sites[0]->p; + next->pos[1] = next->sites[1]->p; + return 1; } - if (x2 > pxmax) + + static void* jcv_align(void* value, size_t alignment) { - x2 = pxmax; - y2 = (e->c - x2) / e->b; + return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); } - else if (x2 < pxmin) + + static void* jcv_alloc(jcv_context_internal* internal, size_t size) { - x2 = pxmin; - y2 = (e->c - x2) / e->b; + if( !internal->memblocks || internal->memblocks->sizefree < (size+sizeof(void*)) ) + { + size_t blocksize = 16 * 1024; + jcv_memoryblock* block = (jcv_memoryblock*)internal->alloc( internal->memctx, blocksize ); + size_t offset = sizeof(jcv_memoryblock); + block->sizefree = blocksize - offset; + block->next = internal->memblocks; + block->memory = ((char*)block) + offset; + internal->memblocks = block; + } + void* p_raw = internal->memblocks->memory; + void* p_aligned = jcv_align(p_raw, sizeof(void*)); + size += (uintptr_t)p_aligned - (uintptr_t)p_raw; + internal->memblocks->memory += size; + internal->memblocks->sizefree -= size; + return p_aligned; } - } - else // delta y is larger - { - x1 = pxmin; - if( s1 != 0 && s1->x() > pxmin ) - x1 = s1->x(); - if( x1 > pxmax ) + + static jcv_edge* jcv_alloc_edge(jcv_context_internal* internal) { - x1 = pxmax; + return (jcv_edge*)jcv_alloc(internal, sizeof(jcv_edge)); } - y1 = e->c - e->a * x1; - x2 = pxmax; - if( s2 != 0 && s2->x() < pxmax ) - x2 = s2->x(); - if( x2 < pxmin ) + + static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal) { - x2 = pxmin; + if( internal->halfedgepool ) + { + jcv_halfedge* edge = internal->halfedgepool; + internal->halfedgepool = internal->halfedgepool->right; + return edge; + } + + return (jcv_halfedge*)jcv_alloc(internal, sizeof(jcv_halfedge)); } - y2 = e->c - e->a * x2; - // Never occurs according to lcov - // if( ((y1 > pymax) & (y2 > pymax)) | ((y1 < pymin) & (y2 < pymin)) ) - // { - // return 0; - // } - if( y1 > pymax ) + + static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal) { - y1 = pymax; - x1 = (e->c - y1) / e->a; + return (jcv_graphedge*)jcv_alloc(internal, sizeof(jcv_graphedge)); } - else if( y1 < pymin ) + + static void* jcv_alloc_fn(void* memctx, size_t size) { - y1 = pymin; - x1 = (e->c - y1) / e->a; + (void)memctx; + return malloc(size); } - if( y2 > pymax ) + + static void jcv_free_fn(void* memctx, void* p) { - y2 = pymax; - x2 = (e->c - y2) / e->a; + (void)memctx; + free(p); } - else if( y2 < pymin ) + + // jcv_edge methods + static int jcv_is_valid(const jcv_point* p) { - y2 = pymin; - x2 = (e->c - y2) / e->a; + return (p->x() != jcv_invalid_value || p->y() != jcv_invalid_value) ? 1 : 0; } - } - e->pos[0][0] = x1; - e->pos[0][1] = y1; - e->pos[1][0] = x2; - e->pos[1][1] = y2; + static void jcv_edge_create(jcv_edge* e, jcv_site* s1, jcv_site* s2) + { + e->next = 0; + e->sites[0] = s1; + e->sites[1] = s2; + e->pos[0][0] = jcv_invalid_value; + e->pos[0][1] = jcv_invalid_value; + e->pos[1][0] = jcv_invalid_value; + e->pos[1][1] = jcv_invalid_value; + + // Create line equation between S1 and S2: + // jcv_real a = -1 * (s2->p[1] - s1->p[1]); + // jcv_real b = s2->p[0] - s1->p[0]; + // //jcv_real c = -1 * (s2->p[0] - s1->p[0]) * s1->p[1] + (s2->p[1] - s1->p[1]) * s1->p[0]; + // + // // create perpendicular line + // jcv_real pa = b; + // jcv_real pb = -a; + // //jcv_real pc = pa * s1->p[0] + pb * s1->p[1]; + // + // // Move to the mid point + // jcv_real mx = s1->p[0] + dx * jcv_real(0.5); + // jcv_real my = s1->p[1] + dy * jcv_real(0.5); + // jcv_real pc = ( pa * mx + pb * my ); + + jcv_real dx = s2->p[0] - s1->p[0]; + jcv_real dy = s2->p[1] - s1->p[1]; + int dx_is_larger = (dx*dx) > (dy*dy); // instead of fabs + + // Simplify it, using dx and dy + e->c = dx * (s1->p[0] + dx * (jcv_real)0.5) + dy * (s1->p[1] + dy * (jcv_real)0.5); + + if( dx_is_larger ) + { + e->a = (jcv_real)1; + e->b = dy / dx; + e->c /= dx; + } + else + { + e->a = dx / dy; + e->b = (jcv_real)1; + e->c /= dy; + } + } - // If the two points are equal, the result is invalid - return (x1 == x2 && y1 == y2) ? 0 : 1; -} + // CLIPPING + static int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p) + { + return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] && + p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; + } -// The line equation: ax + by + c = 0 -// see jcv_edge_create -static int jcv_edge_clipline(jcv_context_internal* internal, jcv_edge* e) -{ - return internal->clipper.clip_fn(&internal->clipper, e); -} + // The line equation: ax + by + c = 0 + // see jcv_edge_create + static int jcv_boxshape_clip(const jcv_clipper* clipper, jcv_edge* e) + { + jcv_real pxmin = clipper->min[0]; + jcv_real pxmax = clipper->max[0]; + jcv_real pymin = clipper->min[1]; + jcv_real pymax = clipper->max[1]; + + jcv_real x1, y1, x2, y2; + jcv_point* s1; + jcv_point* s2; + if (e->a == (jcv_real)1 && e->b >= (jcv_real)0) + { + s1 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; + s2 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; + } + else + { + s1 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; + s2 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; + } -static jcv_edge* jcv_edge_new(jcv_context_internal* internal, jcv_site* s1, jcv_site* s2) -{ - jcv_edge* e = jcv_alloc_edge(internal); - jcv_edge_create(e, s1, s2); - return e; -} + if (e->a == (jcv_real)1) // delta x is larger + { + y1 = pymin; + if (s1 != 0 && s1->y() > pymin) + { + y1 = s1->y(); + } + if( y1 > pymax ) + { + y1 = pymax; + } + x1 = e->c - e->b * y1; + y2 = pymax; + if (s2 != 0 && s2->y() < pymax) + y2 = s2->y(); + if( y2 < pymin ) + { + y2 = pymin; + } + x2 = (e->c) - (e->b) * y2; + // Never occurs according to lcov + // if( ((x1 > pxmax) & (x2 > pxmax)) | ((x1 < pxmin) & (x2 < pxmin)) ) + // { + // return 0; + // } + if (x1 > pxmax) + { + x1 = pxmax; + y1 = (e->c - x1) / e->b; + } + else if (x1 < pxmin) + { + x1 = pxmin; + y1 = (e->c - x1) / e->b; + } + if (x2 > pxmax) + { + x2 = pxmax; + y2 = (e->c - x2) / e->b; + } + else if (x2 < pxmin) + { + x2 = pxmin; + y2 = (e->c - x2) / e->b; + } + } + else // delta y is larger + { + x1 = pxmin; + if( s1 != 0 && s1->x() > pxmin ) + x1 = s1->x(); + if( x1 > pxmax ) + { + x1 = pxmax; + } + y1 = e->c - e->a * x1; + x2 = pxmax; + if( s2 != 0 && s2->x() < pxmax ) + x2 = s2->x(); + if( x2 < pxmin ) + { + x2 = pxmin; + } + y2 = e->c - e->a * x2; + // Never occurs according to lcov + // if( ((y1 > pymax) & (y2 > pymax)) | ((y1 < pymin) & (y2 < pymin)) ) + // { + // return 0; + // } + if( y1 > pymax ) + { + y1 = pymax; + x1 = (e->c - y1) / e->a; + } + else if( y1 < pymin ) + { + y1 = pymin; + x1 = (e->c - y1) / e->a; + } + if( y2 > pymax ) + { + y2 = pymax; + x2 = (e->c - y2) / e->a; + } + else if( y2 < pymin ) + { + y2 = pymin; + x2 = (e->c - y2) / e->a; + } + } -// jcv_halfedge + e->pos[0][0] = x1; + e->pos[0][1] = y1; + e->pos[1][0] = x2; + e->pos[1][1] = y2; -static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) -{ - newedge->left = edge; - newedge->right = edge->right; - edge->right->left = newedge; - edge->right = newedge; -} + // If the two points are equal, the result is invalid + return (x1 == x2 && y1 == y2) ? 0 : 1; + } -static void jcv_halfedge_unlink(jcv_halfedge* he) -{ - he->left->right = he->right; - he->right->left = he->left; - he->left = 0; - he->right = 0; -} + // The line equation: ax + by + c = 0 + // see jcv_edge_create + static int jcv_edge_clipline(jcv_context_internal* internal, jcv_edge* e) + { + return internal->clipper.clip_fn(&internal->clipper, e); + } -static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, jcv_edge* e, int direction) -{ - jcv_halfedge* he = jcv_alloc_halfedge(internal); - he->edge = e; - he->left = 0; - he->right = 0; - he->direction = direction; - he->pqpos = 0; - // These are set outside - //he->y() - //he->vertex - return he; -} - -static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he) -{ - he->right = internal->halfedgepool; - internal->halfedgepool = he; -} + static jcv_edge* jcv_edge_new(jcv_context_internal* internal, jcv_site* s1, jcv_site* s2) + { + jcv_edge* e = jcv_alloc_edge(internal); + jcv_edge_create(e, s1, s2); + return e; + } -static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) -{ - return he->edge->sites[he->direction]; -} -static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) -{ - return he->edge ? he->edge->sites[1 - he->direction] : 0; -} + // jcv_halfedge -static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) -{ - const jcv_edge* e = he->edge; - const jcv_site* topsite = e->sites[1]; + static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) + { + newedge->left = edge; + newedge->right = edge->right; + edge->right->left = newedge; + edge->right = newedge; + } - int right_of_site = (p->x() > topsite->p[0]) ? 1 : 0; - if (right_of_site && he->direction == JCV_DIRECTION_LEFT) - return 1; - if (!right_of_site && he->direction == JCV_DIRECTION_RIGHT) - return 0; + static void jcv_halfedge_unlink(jcv_halfedge* he) + { + he->left->right = he->right; + he->right->left = he->left; + he->left = 0; + he->right = 0; + } - jcv_real dxp, dyp, dxs, t1, t2, t3, yl; + static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, jcv_edge* e, int direction) + { + jcv_halfedge* he = jcv_alloc_halfedge(internal); + he->edge = e; + he->left = 0; + he->right = 0; + he->direction = direction; + he->pqpos = 0; + // These are set outside + //he->y() + //he->vertex + return he; + } - int above; - if (e->a == (jcv_real)1) - { - dyp = p->y() - topsite->p[1]; - dxp = p->x() - topsite->p[0]; - int fast = 0; - if( (!right_of_site & (e->b < (jcv_real)0)) | (right_of_site & (e->b >= (jcv_real)0)) ) + static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he) { - above = dyp >= e->b * dxp; - fast = above; + he->right = internal->halfedgepool; + internal->halfedgepool = he; } - else + + static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) { - above = (p->x() + p->y() * e->b) > e->c; - if (e->b < (jcv_real)0) - above = !above; - if (!above) - fast = 1; + return he->edge->sites[he->direction]; } - if (!fast) + + static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) { - dxs = topsite->p[0] - e->sites[0]->p[0]; - above = e->b * (dxp * dxp - dyp * dyp) - < dxs * dyp * ((jcv_real)1 + (jcv_real)2 * dxp / dxs + e->b * e->b); - if (e->b < (jcv_real)0) - above = !above; + return he->edge ? he->edge->sites[1 - he->direction] : 0; } - } - else // e->b == 1 - { - yl = e->c - e->a * p->x(); - t1 = p->y() - yl; - t2 = p->x() - topsite->p[0]; - t3 = yl - topsite->p[1]; - above = t1 * t1 > (t2 * t2 + t3 * t3); - } - return (he->direction == JCV_DIRECTION_LEFT ? above : !above); -} -// Keeps the priority queue sorted with events sorted in ascending order -// Return 1 if the edges needs to be swapped -static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) -{ - return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; -} + static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) + { + const jcv_edge* e = he->edge; + const jcv_site* topsite = e->sites[1]; -static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) -{ - const jcv_edge* e1 = he1->edge; - const jcv_edge* e2 = he2->edge; + int right_of_site = (p->x() > topsite->p[0]) ? 1 : 0; + if (right_of_site && he->direction == JCV_DIRECTION_LEFT) + return 1; + if (!right_of_site && he->direction == JCV_DIRECTION_RIGHT) + return 0; - jcv_real d = e1->a * e2->b - e1->b * e2->a; - if(-jcv_edge_intersect_threshold < d && d < jcv_edge_intersect_threshold) - { - return 0; - } - (*out)[0] = (e1->c * e2->b - e1->b * e2->c) / d; - (*out)[1] = (e1->a * e2->c - e1->c * e2->a) / d; - // I considered trying to determine the correct z here, but we don't have all the - // information required. So just set out->z to a default value meaning 'unset' (Seb) - (*out)[2] = 0.0f; // NB: this does not set z for all edges - - const jcv_edge* e; - const jcv_halfedge* he; - if( jcv_point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) - { - he = he1; - e = e1; - } - else - { - he = he2; - e = e2; - } + jcv_real dxp, dyp, dxs, t1, t2, t3, yl; - int right_of_site = out->x() >= e->sites[1]->p[0]; - if ((right_of_site && he->direction == JCV_DIRECTION_LEFT) || (!right_of_site && he->direction == JCV_DIRECTION_RIGHT)) - { - return 0; - } + int above; + if (e->a == (jcv_real)1) + { + dyp = p->y() - topsite->p[1]; + dxp = p->x() - topsite->p[0]; + int fast = 0; + if( (!right_of_site & (e->b < (jcv_real)0)) | (right_of_site & (e->b >= (jcv_real)0)) ) + { + above = dyp >= e->b * dxp; + fast = above; + } + else + { + above = (p->x() + p->y() * e->b) > e->c; + if (e->b < (jcv_real)0) + above = !above; + if (!above) + fast = 1; + } + if (!fast) + { + dxs = topsite->p[0] - e->sites[0]->p[0]; + above = e->b * (dxp * dxp - dyp * dyp) + < dxs * dyp * ((jcv_real)1 + (jcv_real)2 * dxp / dxs + e->b * e->b); + if (e->b < (jcv_real)0) + above = !above; + } + } + else // e->b == 1 + { + yl = e->c - e->a * p->x(); + t1 = p->y() - yl; + t2 = p->x() - topsite->p[0]; + t3 = yl - topsite->p[1]; + above = t1 * t1 > (t2 * t2 + t3 * t3); + } + return (he->direction == JCV_DIRECTION_LEFT ? above : !above); + } - return 1; -} + // Keeps the priority queue sorted with events sorted in ascending order + // Return 1 if the edges needs to be swapped + static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) + { + return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; + } + static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) + { + const jcv_edge* e1 = he1->edge; + const jcv_edge* e2 = he2->edge; -// Priority queue + jcv_real d = e1->a * e2->b - e1->b * e2->a; + if(-jcv_edge_intersect_threshold < d && d < jcv_edge_intersect_threshold) + { + return 0; + } + (*out)[0] = (e1->c * e2->b - e1->b * e2->c) / d; + (*out)[1] = (e1->a * e2->c - e1->c * e2->a) / d; + // I considered trying to determine the correct z here, but we don't have all the + // information required. So just set out->z to a default value meaning 'unset' (Seb) + (*out)[2] = 0.0f; // NB: this does not set z for all edges + + const jcv_edge* e; + const jcv_halfedge* he; + if( jcv_point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) + { + he = he1; + e = e1; + } + else + { + he = he2; + e = e2; + } -static int jcv_pq_moveup(jcv_priorityqueue* pq, int pos) -{ - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + int right_of_site = out->x() >= e->sites[1]->p[0]; + if ((right_of_site && he->direction == JCV_DIRECTION_LEFT) || (!right_of_site && he->direction == JCV_DIRECTION_RIGHT)) + { + return 0; + } - for( int parent = (pos >> 1); - pos > 1 && jcv_halfedge_compare(items[parent], node); - pos = parent, parent = parent >> 1) - { - items[pos] = items[parent]; - items[pos]->pqpos = pos; - } + return 1; + } - node->pqpos = pos; - items[pos] = node; - return pos; -} -static int jcv_pq_maxchild(jcv_priorityqueue* pq, int pos) -{ - int child = pos << 1; - if( child >= pq->numitems ) - return 0; - jcv_halfedge** items = (jcv_halfedge**)pq->items; - if( (child + 1) < pq->numitems && jcv_halfedge_compare(items[child], items[child+1]) ) - return child+1; - return child; -} - -static int jcv_pq_movedown(jcv_priorityqueue* pq, int pos) -{ - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + // Priority queue - int child = jcv_pq_maxchild(pq, pos); - while( child && jcv_halfedge_compare(node, items[child]) ) - { - items[pos] = items[child]; - items[pos]->pqpos = pos; - pos = child; - child = jcv_pq_maxchild(pq, pos); - } + static int jcv_pq_moveup(jcv_priorityqueue* pq, int pos) + { + jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge* node = items[pos]; - items[pos] = node; - items[pos]->pqpos = pos; - return pos; -} + for( int parent = (pos >> 1); + pos > 1 && jcv_halfedge_compare(items[parent], node); + pos = parent, parent = parent >> 1) + { + items[pos] = items[parent]; + items[pos]->pqpos = pos; + } -static void jcv_pq_create(jcv_priorityqueue* pq, int capacity, void** buffer) -{ - pq->maxnumitems = capacity; - pq->numitems = 1; - pq->items = buffer; -} + node->pqpos = pos; + items[pos] = node; + return pos; + } -static int jcv_pq_empty(jcv_priorityqueue* pq) -{ - return pq->numitems == 1 ? 1 : 0; -} + static int jcv_pq_maxchild(jcv_priorityqueue* pq, int pos) + { + int child = pos << 1; + if( child >= pq->numitems ) + return 0; + jcv_halfedge** items = (jcv_halfedge**)pq->items; + if( (child + 1) < pq->numitems && jcv_halfedge_compare(items[child], items[child+1]) ) + return child+1; + return child; + } -static int jcv_pq_push(jcv_priorityqueue* pq, void* node) -{ - assert(pq->numitems < pq->maxnumitems); - int n = pq->numitems++; - pq->items[n] = node; - return jcv_pq_moveup(pq, n); -} + static int jcv_pq_movedown(jcv_priorityqueue* pq, int pos) + { + jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge* node = items[pos]; -static void* jcv_pq_pop(jcv_priorityqueue* pq) -{ - void* node = pq->items[1]; - pq->items[1] = pq->items[--pq->numitems]; - jcv_pq_movedown(pq, 1); - return node; -} + int child = jcv_pq_maxchild(pq, pos); + while( child && jcv_halfedge_compare(node, items[child]) ) + { + items[pos] = items[child]; + items[pos]->pqpos = pos; + pos = child; + child = jcv_pq_maxchild(pq, pos); + } -static void* jcv_pq_top(jcv_priorityqueue* pq) -{ - return pq->items[1]; -} + items[pos] = node; + items[pos]->pqpos = pos; + return pos; + } -static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) -{ - if( pq->numitems == 1 ) - return; - int pos = node->pqpos; - if( pos == 0 ) - return; + static void jcv_pq_create(jcv_priorityqueue* pq, int capacity, void** buffer) + { + pq->maxnumitems = capacity; + pq->numitems = 1; + pq->items = buffer; + } - jcv_halfedge** items = (jcv_halfedge**)pq->items; + static int jcv_pq_empty(jcv_priorityqueue* pq) + { + return pq->numitems == 1 ? 1 : 0; + } - items[pos] = items[--pq->numitems]; - if( jcv_halfedge_compare( node, items[pos] ) ) - jcv_pq_moveup( pq, pos ); - else - jcv_pq_movedown( pq, pos ); - node->pqpos = pos; -} + static int jcv_pq_push(jcv_priorityqueue* pq, void* node) + { + assert(pq->numitems < pq->maxnumitems); + int n = pq->numitems++; + pq->items[n] = node; + return jcv_pq_moveup(pq, n); + } -// internal functions + static void* jcv_pq_pop(jcv_priorityqueue* pq) + { + void* node = pq->items[1]; + pq->items[1] = pq->items[--pq->numitems]; + jcv_pq_movedown(pq, 1); + return node; + } -static jcv_site* jcv_nextsite(jcv_context_internal* internal) -{ - return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; -} + static void* jcv_pq_top(jcv_priorityqueue* pq) + { + return pq->items[1]; + } -static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, const jcv_point* p) -{ - // Gets the arc on the beach line at the x coordinate (i.e. right above the new site event) + static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) + { + if( pq->numitems == 1 ) + return; + int pos = node->pqpos; + if( pos == 0 ) + return; + + jcv_halfedge** items = (jcv_halfedge**)pq->items; + + items[pos] = items[--pq->numitems]; + if( jcv_halfedge_compare( node, items[pos] ) ) + jcv_pq_moveup( pq, pos ); + else + jcv_pq_movedown( pq, pos ); + node->pqpos = pos; + } - // A good guess it's close by (Can be optimized) - jcv_halfedge* he = internal->last_inserted; - if( !he ) - { - if( p->x() < (internal->rect.max[0] - internal->rect.min[0]) / 2 ) - he = internal->beachline_start; - else - he = internal->beachline_end; - } + // internal functions - // - if( he == internal->beachline_start || (he != internal->beachline_end && jcv_halfedge_rightof(he, p)) ) - { - do { - he = he->right; + static jcv_site* jcv_nextsite(jcv_context_internal* internal) + { + return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; } - while( he != internal->beachline_end && jcv_halfedge_rightof(he, p) ); - he = he->left; - } - else - { - do { - he = he->left; - } - while( he != internal->beachline_start && !jcv_halfedge_rightof(he, p) ); - } + static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, const jcv_point* p) + { + // Gets the arc on the beach line at the x coordinate (i.e. right above the new site event) - return he; -} + // A good guess it's close by (Can be optimized) + jcv_halfedge* he = internal->last_inserted; + if( !he ) + { + if( p->x() < (internal->rect.max[0] - internal->rect.min[0]) / 2 ) + he = internal->beachline_start; + else + he = internal->beachline_end; + } -static int jcv_check_circle_event(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* vertex) -{ - jcv_edge* e1 = he1->edge; - jcv_edge* e2 = he2->edge; - if( e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1] ) - { - return 0; - } + // + if( he == internal->beachline_start || (he != internal->beachline_end && jcv_halfedge_rightof(he, p)) ) + { + do { + he = he->right; + } + while( he != internal->beachline_end && jcv_halfedge_rightof(he, p) ); - return jcv_halfedge_intersect(he1, he2, vertex); -} + he = he->left; + } + else + { + do { + he = he->left; + } + while( he != internal->beachline_start && !jcv_halfedge_rightof(he, p) ); + } -static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) -{ - jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p); - jcv_halfedge* right = left->right; - jcv_site* bottom = jcv_halfedge_rightsite(left); - if( !bottom ) - bottom = internal->bottomsite; + return he; + } - jcv_edge* edge = jcv_edge_new(internal, bottom, site); - edge->next = internal->edges; - internal->edges = edge; + static int jcv_check_circle_event(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* vertex) + { + jcv_edge* e1 = he1->edge; + jcv_edge* e2 = he2->edge; + if( e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1] ) + { + return 0; + } - jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT); - jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT); + return jcv_halfedge_intersect(he1, he2, vertex); + } - jcv_halfedge_link(left, edge1); - jcv_halfedge_link(edge1, edge2); + static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) + { + jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p); + jcv_halfedge* right = left->right; + jcv_site* bottom = jcv_halfedge_rightsite(left); + if( !bottom ) + bottom = internal->bottomsite; - internal->last_inserted = right; + jcv_edge* edge = jcv_edge_new(internal, bottom, site); + edge->next = internal->edges; + internal->edges = edge; - jcv_point p; - if( jcv_check_circle_event( left, edge1, &p ) ) - { - jcv_pq_remove(internal->eventqueue, left); - left->vertex = p; - left->y = p[1] + jcv_point_dist(&site->p, &p); - jcv_pq_push(internal->eventqueue, left); - } - if( jcv_check_circle_event( edge2, right, &p ) ) - { - edge2->vertex = p; - edge2->y = p[1] + jcv_point_dist(&site->p, &p); - jcv_pq_push(internal->eventqueue, edge2); - } -} + jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT); + jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT); -// https://cp-algorithms.com/geometry/oriented-triangle-area.html -static jcv_real jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) -{ - return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); -} + jcv_halfedge_link(left, edge1); + jcv_halfedge_link(edge1, edge2); -static jcv_real jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) -{ - // We take the average of the two points, since we can better distinguish between very small edges - constexpr jcv_real half = jcv_real{0.5}; - jcv_real x = (edge->pos[0][0] + edge->pos[1][0]) * half; - jcv_real y = (edge->pos[0][1] + edge->pos[1][1]) * half; - jcv_real diffy = y - site->p[1]; - jcv_real angle = std::atan2( diffy, x - site->p[0] ); - if( diffy < 0 ) { - angle = angle + sm::mathconst::two_pi; - } - return angle; -} + internal->last_inserted = right; -static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) -{ - return jcv_real_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); -} + jcv_point p; + if( jcv_check_circle_event( left, edge1, &p ) ) + { + jcv_pq_remove(internal->eventqueue, left); + left->vertex = p; + left->y = p[1] + jcv_point_dist(&site->p, &p); + jcv_pq_push(internal->eventqueue, left); + } + if( jcv_check_circle_event( edge2, right, &p ) ) + { + edge2->vertex = p; + edge2->y = p[1] + jcv_point_dist(&site->p, &p); + jcv_pq_push(internal->eventqueue, edge2); + } + } -static void jcv_sortedges_insert(jcv_site* site, jcv_graphedge* edge) -{ - // Special case for the head end - jcv_graphedge* prev = 0; - if (site->edges == 0 || site->edges->angle >= edge->angle) - { - edge->next = site->edges; - site->edges = edge; - } - else - { - // Locate the node before the point of insertion - jcv_graphedge* current = site->edges; - while(current->next != 0 && current->next->angle < edge->angle) + // https://cp-algorithms.com/geometry/oriented-triangle-area.html + static jcv_real jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) { - current = current->next; + return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); } - prev = current; - edge->next = current->next; - current->next = edge; - } - // check to avoid duplicates - if (prev && jcv_graphedge_eq(prev, edge)) - { - prev->next = edge->next; - } - else if (edge->next && jcv_graphedge_eq(edge, edge->next)) - { - edge->next = edge->next->next; - } -} + static jcv_real jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) + { + // We take the average of the two points, since we can better distinguish between very small edges + constexpr jcv_real half = jcv_real{0.5}; + jcv_real x = (edge->pos[0][0] + edge->pos[1][0]) * half; + jcv_real y = (edge->pos[0][1] + edge->pos[1][1]) * half; + jcv_real diffy = y - site->p[1]; + jcv_real angle = std::atan2( diffy, x - site->p[0] ); + if( diffy < 0 ) { + angle = angle + sm::mathconst::two_pi; + } + return angle; + } -static void jcv_finishline(jcv_context_internal* internal, jcv_edge* e) -{ - if( !jcv_edge_clipline(internal, e) ) { - return; - } + static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) + { + return jcv_real_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); + } + + static void jcv_sortedges_insert(jcv_site* site, jcv_graphedge* edge) + { + // Special case for the head end + jcv_graphedge* prev = 0; + if (site->edges == 0 || site->edges->angle >= edge->angle) + { + edge->next = site->edges; + site->edges = edge; + } + else + { + // Locate the node before the point of insertion + jcv_graphedge* current = site->edges; + while(current->next != 0 && current->next->angle < edge->angle) + { + current = current->next; + } + prev = current; + edge->next = current->next; + current->next = edge; + } - // Make sure the graph edges are CCW - int flip = jcv_determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (jcv_real)0 ? 0 : 1; + // check to avoid duplicates + if (prev && jcv_graphedge_eq(prev, edge)) + { + prev->next = edge->next; + } + else if (edge->next && jcv_graphedge_eq(edge, edge->next)) + { + edge->next = edge->next->next; + } + } - for( int i = 0; i < 2; ++i ) - { - jcv_graphedge* ge = jcv_alloc_graphedge(internal); + static void jcv_finishline(jcv_context_internal* internal, jcv_edge* e) + { + if( !jcv_edge_clipline(internal, e) ) { + return; + } - ge->edge = e; - ge->next = 0; - ge->neighbor = e->sites[1-i]; - ge->pos[flip] = e->pos[i]; - ge->pos[1-flip] = e->pos[1-i]; - ge->angle = jcv_calc_sort_metric(e->sites[i], ge); + // Make sure the graph edges are CCW + int flip = jcv_determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (jcv_real)0 ? 0 : 1; - jcv_sortedges_insert( e->sites[i], ge ); - } -} + for( int i = 0; i < 2; ++i ) + { + jcv_graphedge* ge = jcv_alloc_graphedge(internal); + ge->edge = e; + ge->next = 0; + ge->neighbor = e->sites[1-i]; + ge->pos[flip] = e->pos[i]; + ge->pos[1-flip] = e->pos[1-i]; + ge->angle = jcv_calc_sort_metric(e->sites[i], ge); -static void jcv_endpos(jcv_context_internal* internal, jcv_edge* e, const jcv_point* p, int direction) -{ - e->pos[direction] = *p; + jcv_sortedges_insert( e->sites[i], ge ); + } + } - if( !jcv_is_valid(&e->pos[1 - direction]) ) - return; - jcv_finishline(internal, e); -} + static void jcv_endpos(jcv_context_internal* internal, jcv_edge* e, const jcv_point* p, int direction) + { + e->pos[direction] = *p; -static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) -{ - gap->neighbor = 0; - gap->pos[0] = current->pos[1]; + if( !jcv_is_valid(&e->pos[1 - direction]) ) + return; - if( current->pos[1][0] < internal->rect.max[0] && current->pos[1][1] == internal->rect.min[1] ) - { - gap->pos[1][0] = internal->rect.max[0]; - gap->pos[1][1] = internal->rect.min[1]; - } - else if( current->pos[1][0] > internal->rect.min[0] && current->pos[1][1] == internal->rect.max[1] ) - { - gap->pos[1][0] = internal->rect.min[0]; - gap->pos[1][1] = internal->rect.max[1]; - } - else if( current->pos[1][1] > internal->rect.min[1] && current->pos[1][0] == internal->rect.min[0] ) - { - gap->pos[1][0] = internal->rect.min[0]; - gap->pos[1][1] = internal->rect.min[1]; - } - else if( current->pos[1][1] < internal->rect.max[1] && current->pos[1][0] == internal->rect.max[0] ) - { - gap->pos[1][0] = internal->rect.max[0]; - gap->pos[1][1] = internal->rect.max[1]; - } + jcv_finishline(internal, e); + } - gap->angle = jcv_calc_sort_metric(site, gap); -} + static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) + { + gap->neighbor = 0; + gap->pos[0] = current->pos[1]; -static jcv_edge* jcv_create_gap_edge(jcv_context_internal* internal, jcv_site* site, jcv_graphedge* ge) -{ - jcv_edge* edge = jcv_alloc_edge(internal); - edge->pos[0] = ge->pos[0]; - edge->pos[1] = ge->pos[1]; - edge->sites[0] = site; - edge->sites[1] = 0; - edge->a = edge->b = edge->c = 0; - edge->next = internal->edges; - internal->edges = edge; - return edge; -} - -void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* site) -{ - // They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap - jcv_graphedge* current = site->edges; - if( !current ) - { - // No edges, then it should be a single cell - assert( allocator->numsites == 1 ); - - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); - gap->neighbor = 0; - gap->pos[0] = clipper->min; - gap->pos[1][0] = clipper->max[0]; - gap->pos[1][1] = clipper->min[1]; - gap->angle = jcv_calc_sort_metric(site, gap); - gap->next = 0; - gap->edge = jcv_create_gap_edge(allocator, site, gap); - - current = gap; - site->edges = gap; - } + if( current->pos[1][0] < internal->rect.max[0] && current->pos[1][1] == internal->rect.min[1] ) + { + gap->pos[1][0] = internal->rect.max[0]; + gap->pos[1][1] = internal->rect.min[1]; + } + else if( current->pos[1][0] > internal->rect.min[0] && current->pos[1][1] == internal->rect.max[1] ) + { + gap->pos[1][0] = internal->rect.min[0]; + gap->pos[1][1] = internal->rect.max[1]; + } + else if( current->pos[1][1] > internal->rect.min[1] && current->pos[1][0] == internal->rect.min[0] ) + { + gap->pos[1][0] = internal->rect.min[0]; + gap->pos[1][1] = internal->rect.min[1]; + } + else if( current->pos[1][1] < internal->rect.max[1] && current->pos[1][0] == internal->rect.max[0] ) + { + gap->pos[1][0] = internal->rect.max[0]; + gap->pos[1][1] = internal->rect.max[1]; + } - jcv_graphedge* next = current->next; - if( !next ) - { - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); - jcv_create_corner_edge(allocator, site, current, gap); - gap->edge = jcv_create_gap_edge(allocator, site, gap); - - gap->next = current->next; - current->next = gap; - current = gap; - next = site->edges; - } + gap->angle = jcv_calc_sort_metric(site, gap); + } - while( current && next ) - { - int current_edge_flags = jcv_get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); - if( current_edge_flags && !jcv_point_eq(¤t->pos[1], &next->pos[0])) + static jcv_edge* jcv_create_gap_edge(jcv_context_internal* internal, jcv_site* site, jcv_graphedge* ge) { - // Cases: - // Current and Next on the same border - // Current on one border, and Next on another border - // Current on the corner, Next on the border - // Current on the corner, Next on another border (another corner in between) + jcv_edge* edge = jcv_alloc_edge(internal); + edge->pos[0] = ge->pos[0]; + edge->pos[1] = ge->pos[1]; + edge->sites[0] = site; + edge->sites[1] = 0; + edge->a = edge->b = edge->c = 0; + edge->next = internal->edges; + internal->edges = edge; + return edge; + } - int next_edge_flags = jcv_get_edge_flags(&next->pos[0], &clipper->min, &clipper->max); - if (current_edge_flags & next_edge_flags) + static void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* site) + { + // They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap + jcv_graphedge* current = site->edges; + if( !current ) { - // Current and Next on the same border - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + // No edges, then it should be a single cell + assert( allocator->numsites == 1 ); + + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); gap->neighbor = 0; - gap->pos[0] = current->pos[1]; - gap->pos[1] = next->pos[0]; + gap->pos[0] = clipper->min; + gap->pos[1][0] = clipper->max[0]; + gap->pos[1][1] = clipper->min[1]; gap->angle = jcv_calc_sort_metric(site, gap); + gap->next = 0; gap->edge = jcv_create_gap_edge(allocator, site, gap); + current = gap; + site->edges = gap; + } + + jcv_graphedge* next = current->next; + if( !next ) + { + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + jcv_create_corner_edge(allocator, site, current, gap); + gap->edge = jcv_create_gap_edge(allocator, site, gap); + gap->next = current->next; current->next = gap; + current = gap; + next = site->edges; } - else { - // Current and Next on different borders - int corner_flag = jcv_edge_flags_to_corner(current_edge_flags); - if (corner_flag) + + while( current && next ) + { + int current_edge_flags = jcv_get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); + if( current_edge_flags && !jcv_point_eq(¤t->pos[1], &next->pos[0])) { - // we are already at one corner, so we need to find the next one - corner_flag = jcv_corner_rotate_90(corner_flag); + // Cases: + // Current and Next on the same border + // Current on one border, and Next on another border + // Current on the corner, Next on the border + // Current on the corner, Next on another border (another corner in between) + + int next_edge_flags = jcv_get_edge_flags(&next->pos[0], &clipper->min, &clipper->max); + if (current_edge_flags & next_edge_flags) + { + // Current and Next on the same border + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + gap->neighbor = 0; + gap->pos[0] = current->pos[1]; + gap->pos[1] = next->pos[0]; + gap->angle = jcv_calc_sort_metric(site, gap); + gap->edge = jcv_create_gap_edge(allocator, site, gap); + + gap->next = current->next; + current->next = gap; + } + else { + // Current and Next on different borders + int corner_flag = jcv_edge_flags_to_corner(current_edge_flags); + if (corner_flag) + { + // we are already at one corner, so we need to find the next one + corner_flag = jcv_corner_rotate_90(corner_flag); + } + else + { + // we are on the middle of a border + // we need to find the adjacent corner, following the borders CCW + if (current_edge_flags == JCV_EDGE_TOP) { corner_flag = JCV_CORNER_TOP_LEFT; } + else if (current_edge_flags == JCV_EDGE_LEFT) { corner_flag = JCV_CORNER_BOTTOM_LEFT; } + else if (current_edge_flags == JCV_EDGE_BOTTOM) { corner_flag = JCV_CORNER_BOTTOM_RIGHT; } + else if (current_edge_flags == JCV_EDGE_RIGHT) { corner_flag = JCV_CORNER_TOP_RIGHT; } + + } + jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max); + + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + gap->neighbor = 0; + gap->pos[0] = current->pos[1]; + gap->pos[1] = corner; + gap->angle = jcv_calc_sort_metric(site, gap); + gap->edge = jcv_create_gap_edge(allocator, site, gap); + + gap->next = current->next; + current->next = gap; + } } - else - { - // we are on the middle of a border - // we need to find the adjacent corner, following the borders CCW - if (current_edge_flags == JCV_EDGE_TOP) { corner_flag = JCV_CORNER_TOP_LEFT; } - else if (current_edge_flags == JCV_EDGE_LEFT) { corner_flag = JCV_CORNER_BOTTOM_LEFT; } - else if (current_edge_flags == JCV_EDGE_BOTTOM) { corner_flag = JCV_CORNER_BOTTOM_RIGHT; } - else if (current_edge_flags == JCV_EDGE_RIGHT) { corner_flag = JCV_CORNER_TOP_RIGHT; } + current = current->next; + if( current ) + { + next = current->next; + if( !next ) + next = site->edges; } - jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max); - - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); - gap->neighbor = 0; - gap->pos[0] = current->pos[1]; - gap->pos[1] = corner; - gap->angle = jcv_calc_sort_metric(site, gap); - gap->edge = jcv_create_gap_edge(allocator, site, gap); - - gap->next = current->next; - current->next = gap; } } - current = current->next; - if( current ) - { - next = current->next; - if( !next ) - next = site->edges; - } - } -} - - -// Since the algorithm leaves gaps at the borders/corner, we want to fill them -static void jcv_fillgaps(jcv_diagram* diagram) -{ - jcv_context_internal* internal = diagram->internal; - if (!internal->clipper.fill_fn) - return; - - for( int i = 0; i < internal->numsites; ++i ) - { - jcv_site* site = &internal->sites[i]; - internal->clipper.fill_fn(&internal->clipper, internal, site); - } -} - - -static void jcv_circle_event(jcv_context_internal* internal) -{ - jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue); - - jcv_halfedge* leftleft = left->left; - jcv_halfedge* right = left->right; - jcv_halfedge* rightright= right->right; - jcv_site* bottom = jcv_halfedge_leftsite(left); - jcv_site* top = jcv_halfedge_rightsite(right); - jcv_point vertex = left->vertex; - jcv_endpos(internal, left->edge, &vertex, left->direction); - jcv_endpos(internal, right->edge, &vertex, right->direction); + // Since the algorithm leaves gaps at the borders/corner, we want to fill them + static void jcv_fillgaps(jcv_diagram* diagram) + { + jcv_context_internal* internal = diagram->internal; + if (!internal->clipper.fill_fn) + return; - internal->last_inserted = rightright; + for( int i = 0; i < internal->numsites; ++i ) + { + jcv_site* site = &internal->sites[i]; + internal->clipper.fill_fn(&internal->clipper, internal, site); + } + } - jcv_pq_remove(internal->eventqueue, right); - jcv_halfedge_unlink(left); - jcv_halfedge_unlink(right); - jcv_halfedge_delete(internal, left); - jcv_halfedge_delete(internal, right); - int direction = JCV_DIRECTION_LEFT; - if( bottom->p[1] > top->p[1] ) - { - jcv_site* temp = bottom; - bottom = top; - top = temp; - direction = JCV_DIRECTION_RIGHT; - } + static void jcv_circle_event(jcv_context_internal* internal) + { + jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue); - jcv_edge* edge = jcv_edge_new(internal, bottom, top); - edge->next = internal->edges; - internal->edges = edge; + jcv_halfedge* leftleft = left->left; + jcv_halfedge* right = left->right; + jcv_halfedge* rightright= right->right; + jcv_site* bottom = jcv_halfedge_leftsite(left); + jcv_site* top = jcv_halfedge_rightsite(right); - jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction); - jcv_halfedge_link(leftleft, he); - jcv_endpos(internal, edge, &vertex, JCV_DIRECTION_RIGHT - direction); + jcv_point vertex = left->vertex; + jcv_endpos(internal, left->edge, &vertex, left->direction); + jcv_endpos(internal, right->edge, &vertex, right->direction); - jcv_point p; - if( jcv_check_circle_event( leftleft, he, &p ) ) - { - jcv_pq_remove(internal->eventqueue, leftleft); - leftleft->vertex = p; - leftleft->y = p[1] + jcv_point_dist(&bottom->p, &p); - jcv_pq_push(internal->eventqueue, leftleft); - } - if( jcv_check_circle_event( he, rightright, &p ) ) - { - he->vertex = p; - he->y = p[1] + jcv_point_dist(&bottom->p, &p); - jcv_pq_push(internal->eventqueue, he); - } -} + internal->last_inserted = rightright; -void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* d ) -{ - jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); -} + jcv_pq_remove(internal->eventqueue, right); + jcv_halfedge_unlink(left); + jcv_halfedge_unlink(right); + jcv_halfedge_delete(internal, left); + jcv_halfedge_delete(internal, right); -typedef union jcv_cast_align_struct_ -{ - char* charp; - void** voidpp; -} jcv_cast_align_struct; + int direction = JCV_DIRECTION_LEFT; + if( bottom->p[1] > top->p[1] ) + { + jcv_site* temp = bottom; + bottom = top; + top = temp; + direction = JCV_DIRECTION_RIGHT; + } -static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) -{ - rect->min[0] = std::min(rect->min[0], p->x()); - rect->min[1] = std::min(rect->min[1], p->y()); - rect->max[0] = std::max(rect->max[0], p->x()); - rect->max[1] = std::max(rect->max[1], p->y()); -} + jcv_edge* edge = jcv_edge_new(internal, bottom, top); + edge->next = internal->edges; + internal->edges = edge; -static void jcv_rect_round(jcv_rect* rect) -{ - rect->min[0] = std::floor(rect->min[0]); - rect->min[1] = std::floor(rect->min[1]); - rect->max[0] = std::ceil(rect->max[0]); - rect->max[1] = std::ceil(rect->max[1]); -} + jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction); + jcv_halfedge_link(leftleft, he); + jcv_endpos(internal, edge, &vertex, JCV_DIRECTION_RIGHT - direction); -static void jcv_rect_inflate(jcv_rect* rect, jcv_real amount) -{ - rect->min[0] -= amount; - rect->min[1] -= amount; - rect->max[0] += amount; - rect->max[1] += amount; -} + jcv_point p; + if( jcv_check_circle_event( leftleft, he, &p ) ) + { + jcv_pq_remove(internal->eventqueue, leftleft); + leftleft->vertex = p; + leftleft->y = p[1] + jcv_point_dist(&bottom->p, &p); + jcv_pq_push(internal->eventqueue, leftleft); + } + if( jcv_check_circle_event( he, rightright, &p ) ) + { + he->vertex = p; + he->y = p[1] + jcv_point_dist(&bottom->p, &p); + jcv_pq_push(internal->eventqueue, he); + } + } -static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) -{ - int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + typedef union jcv_cast_align_struct_ + { + char* charp; + void** voidpp; + } jcv_cast_align_struct; - jcv_rect r; - r.min[0] = r.min[1] = std::numeric_limits::max(); - r.max[0] = r.max[1] = std::numeric_limits::lowest(); + static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) + { + rect->min[0] = std::min(rect->min[0], p->x()); + rect->min[1] = std::min(rect->min[1], p->y()); + rect->max[0] = std::max(rect->max[0], p->x()); + rect->max[1] = std::max(rect->max[1], p->y()); + } - int offset = 0; - // Prune duplicates first - for (int i = 0; i < num_sites; i++) - { - const jcv_site* s = &sites[i]; - // Remove duplicates, to avoid anomalies - if( i > 0 && jcv_point_eq(&s->p, &sites[i - 1].p) ) + static void jcv_rect_round(jcv_rect* rect) { - offset++; - continue; + rect->min[0] = std::floor(rect->min[0]); + rect->min[1] = std::floor(rect->min[1]); + rect->max[0] = std::ceil(rect->max[0]); + rect->max[1] = std::ceil(rect->max[1]); } - sites[i - offset] = sites[i]; + static void jcv_rect_inflate(jcv_rect* rect, jcv_real amount) + { + rect->min[0] -= amount; + rect->min[1] -= amount; + rect->max[0] += amount; + rect->max[1] += amount; + } - jcv_rect_union(&r, &s->p); - } - internal->numsites -= offset; - if (rect) { - *rect = r; - } - return offset; -} + static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) + { + int num_sites = internal->numsites; + jcv_site* sites = internal->sites; -static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect) -{ - int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + jcv_rect r; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); - jcv_rect r; - r.min[0] = r.min[1] = std::numeric_limits::max(); - r.max[0] = r.max[1] = std::numeric_limits::lowest(); + int offset = 0; + // Prune duplicates first + for (int i = 0; i < num_sites; i++) + { + const jcv_site* s = &sites[i]; + // Remove duplicates, to avoid anomalies + if( i > 0 && jcv_point_eq(&s->p, &sites[i - 1].p) ) + { + offset++; + continue; + } - int offset = 0; - for (int i = 0; i < num_sites; i++) - { - const jcv_site* s = &sites[i]; + sites[i - offset] = sites[i]; - if (!internal->clipper.test_fn(&internal->clipper, s->p)) - { - offset++; - continue; + jcv_rect_union(&r, &s->p); + } + internal->numsites -= offset; + if (rect) { + *rect = r; + } + return offset; } - sites[i - offset] = sites[i]; - - jcv_rect_union(&r, &s->p); - } - internal->numsites -= offset; - if (rect) { - *rect = r; - } - return offset; -} + static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect) + { + int num_sites = internal->numsites; + jcv_site* sites = internal->sites; -static jcv_context_internal* jcv_alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) -{ - // Interesting limits from Euler's equation - // Slide 81: https://courses.cs.washington.edu/courses/csep521/01au/lectures/lecture10slides.pdf - // Page 3: https://sites.cs.ucsb.edu/~suri/cs235/Voronoi.pdf - size_t eventssize = (size_t)(num_points*2) * sizeof(void*); // beachline can have max 2*n-5 parabolas - size_t sitessize = (size_t)num_points * sizeof(jcv_site); - size_t memsize = sizeof(jcv_priorityqueue) + eventssize + sitessize + sizeof(jcv_context_internal) + 16u; // 16 bytes padding for alignment + jcv_rect r; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); - char* originalmem = (char*)allocfn(userallocctx, memsize); - memset(originalmem, 0, memsize); + int offset = 0; + for (int i = 0; i < num_sites; i++) + { + const jcv_site* s = &sites[i]; - // align memory - char* mem = (char*)jcv_align(originalmem, sizeof(void*)); + if (!internal->clipper.test_fn(&internal->clipper, s->p)) + { + offset++; + continue; + } - jcv_context_internal* internal = (jcv_context_internal*)mem; - mem += sizeof(jcv_context_internal); - internal->mem = originalmem; - internal->memctx = userallocctx; - internal->alloc = allocfn; - internal->free = freefn; + sites[i - offset] = sites[i]; - mem = (char*)jcv_align(mem, sizeof(void*)); - internal->sites = (jcv_site*) mem; - mem += sitessize; + jcv_rect_union(&r, &s->p); + } + internal->numsites -= offset; + if (rect) { + *rect = r; + } + return offset; + } - mem = (char*)jcv_align(mem, sizeof(void*)); - internal->eventqueue = (jcv_priorityqueue*)mem; - mem += sizeof(jcv_priorityqueue); - assert( ((uintptr_t)mem & (sizeof(void*)-1)) == 0 ); + static jcv_context_internal* jcv_alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) + { + // Interesting limits from Euler's equation + // Slide 81: https://courses.cs.washington.edu/courses/csep521/01au/lectures/lecture10slides.pdf + // Page 3: https://sites.cs.ucsb.edu/~suri/cs235/Voronoi.pdf + size_t eventssize = (size_t)(num_points*2) * sizeof(void*); // beachline can have max 2*n-5 parabolas + size_t sitessize = (size_t)num_points * sizeof(jcv_site); + size_t memsize = sizeof(jcv_priorityqueue) + eventssize + sitessize + sizeof(jcv_context_internal) + 16u; // 16 bytes padding for alignment + + char* originalmem = (char*)allocfn(userallocctx, memsize); + memset(originalmem, 0, memsize); + + // align memory + char* mem = (char*)jcv_align(originalmem, sizeof(void*)); + + jcv_context_internal* internal = (jcv_context_internal*)mem; + mem += sizeof(jcv_context_internal); + internal->mem = originalmem; + internal->memctx = userallocctx; + internal->alloc = allocfn; + internal->free = freefn; + + mem = (char*)jcv_align(mem, sizeof(void*)); + internal->sites = (jcv_site*) mem; + mem += sitessize; + + mem = (char*)jcv_align(mem, sizeof(void*)); + internal->eventqueue = (jcv_priorityqueue*)mem; + mem += sizeof(jcv_priorityqueue); + assert( ((uintptr_t)mem & (sizeof(void*)-1)) == 0 ); + + jcv_cast_align_struct tmp; + tmp.charp = mem; + internal->eventmem = tmp.voidpp; + + assert((mem+eventssize) <= (originalmem+memsize)); + + return internal; + } - jcv_cast_align_struct tmp; - tmp.charp = mem; - internal->eventmem = tmp.voidpp; + // This version of jcv_diagram_generate allows the client to use a custom allocator + static void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* d) + { + if( d->internal ) + jcv_diagram_free( d ); - assert((mem+eventssize) <= (originalmem+memsize)); + jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn); - return internal; -} + internal->beachline_start = jcv_halfedge_new(internal, 0, 0); + internal->beachline_end = jcv_halfedge_new(internal, 0, 0); -void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* d) -{ - if( d->internal ) - jcv_diagram_free( d ); + internal->beachline_start->left = 0; + internal->beachline_start->right = internal->beachline_end; + internal->beachline_end->left = internal->beachline_start; + internal->beachline_end->right = 0; - jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn); + internal->last_inserted = 0; - internal->beachline_start = jcv_halfedge_new(internal, 0, 0); - internal->beachline_end = jcv_halfedge_new(internal, 0, 0); + int max_num_events = num_points*2; // beachline can have max 2*n-5 parabolas + jcv_pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); - internal->beachline_start->left = 0; - internal->beachline_start->right = internal->beachline_end; - internal->beachline_end->left = internal->beachline_start; - internal->beachline_end->right = 0; + internal->numsites = num_points; + jcv_site* sites = internal->sites; - internal->last_inserted = 0; + for( int i = 0; i < num_points; ++i ) + { + sites[i].p = points[i]; + sites[i].edges = 0; + sites[i].index = i; + } - int max_num_events = num_points*2; // beachline can have max 2*n-5 parabolas - jcv_pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); + qsort(sites, (size_t)num_points, sizeof(jcv_site), jcv_point_cmp); - internal->numsites = num_points; - jcv_site* sites = internal->sites; + jcv_clipper box_clipper; + if (clipper == 0) { + // model->get_shaderprogs = &mplot::VisualBase::get_shaderprogs; + box_clipper.test_fn = &jc::voronoi::jcv_boxshape_test; + box_clipper.clip_fn = &jc::voronoi::jcv_boxshape_clip; + box_clipper.fill_fn = &jc::voronoi::jcv_boxshape_fillgaps; + clipper = &box_clipper; + } + internal->clipper = *clipper; - for( int i = 0; i < num_points; ++i ) - { - sites[i].p = points[i]; - sites[i].edges = 0; - sites[i].index = i; - } + jcv_rect tmp_rect; + tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); + tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); + jcv_prune_duplicates(internal, &tmp_rect); - qsort(sites, (size_t)num_points, sizeof(jcv_site), jcv_point_cmp); + // Prune using the test second + if (internal->clipper.test_fn) + { + // e.g. used by the box clipper in the test_fn + internal->clipper.min = rect ? rect->min : tmp_rect.min; + internal->clipper.max = rect ? rect->max : tmp_rect.max; - jcv_clipper box_clipper; - if (clipper == 0) { - box_clipper.test_fn = jcv_boxshape_test; - box_clipper.clip_fn = jcv_boxshape_clip; - box_clipper.fill_fn = jcv_boxshape_fillgaps; - clipper = &box_clipper; - } - internal->clipper = *clipper; + jcv_prune_not_in_shape(internal, &tmp_rect); - jcv_rect tmp_rect; - tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); - tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); - jcv_prune_duplicates(internal, &tmp_rect); + // The pruning might have made the bounding box smaller + if (!rect) { + // In the case of all sites being all on a horizontal or vertical line, the + // rect area will be zero, and the diagram generation will most likely fail + jcv_rect_round(&tmp_rect); + jcv_rect_inflate(&tmp_rect, 10); - // Prune using the test second - if (internal->clipper.test_fn) - { - // e.g. used by the box clipper in the test_fn - internal->clipper.min = rect ? rect->min : tmp_rect.min; - internal->clipper.max = rect ? rect->max : tmp_rect.max; + internal->clipper.min = tmp_rect.min; + internal->clipper.max = tmp_rect.max; + } + } - jcv_prune_not_in_shape(internal, &tmp_rect); + internal->rect = rect ? *rect : tmp_rect; - // The pruning might have made the bounding box smaller - if (!rect) { - // In the case of all sites being all on a horizontal or vertical line, the - // rect area will be zero, and the diagram generation will most likely fail - jcv_rect_round(&tmp_rect); - jcv_rect_inflate(&tmp_rect, 10); + d->min = internal->rect.min; + d->max = internal->rect.max; + d->numsites = internal->numsites; + d->internal = internal; - internal->clipper.min = tmp_rect.min; - internal->clipper.max = tmp_rect.max; - } - } + internal->bottomsite = jcv_nextsite(internal); - internal->rect = rect ? *rect : tmp_rect; + jcv_priorityqueue* pq = internal->eventqueue; + jcv_site* site = jcv_nextsite(internal); - d->min = internal->rect.min; - d->max = internal->rect.max; - d->numsites = internal->numsites; - d->internal = internal; + int finished = 0; + while( !finished ) + { + jcv_point lowest_pq_point; + if( !jcv_pq_empty(pq) ) + { + jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq); + lowest_pq_point[0] = he->vertex[0]; + lowest_pq_point[1] = he->y; + } - internal->bottomsite = jcv_nextsite(internal); + if( site != 0 && (jcv_pq_empty(pq) || jcv_point_less(&site->p, &lowest_pq_point) ) ) + { + jcv_site_event(internal, site); + site = jcv_nextsite(internal); + } + else if( !jcv_pq_empty(pq) ) + { + jcv_circle_event(internal); + } + else + { + finished = 1; + } + } - jcv_priorityqueue* pq = internal->eventqueue; - jcv_site* site = jcv_nextsite(internal); + for( jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) + { + jcv_finishline(internal, he->edge); + } - int finished = 0; - while( !finished ) - { - jcv_point lowest_pq_point; - if( !jcv_pq_empty(pq) ) - { - jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq); - lowest_pq_point[0] = he->vertex[0]; - lowest_pq_point[1] = he->y; + jcv_fillgaps(d); } - if( site != 0 && (jcv_pq_empty(pq) || jcv_point_less(&site->p, &lowest_pq_point) ) ) + /** + * Uses malloc + * If a clipper is not supplied, a default box clipper will be used + * If rect is null, an automatic bounding box is calculated, with an extra padding of 10 units + * All points will be culled against the bounding rect, and all edges will be clipped against it. + */ + static void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* d ) { - jcv_site_event(internal, site); - site = jcv_nextsite(internal); + jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); } - else if( !jcv_pq_empty(pq) ) - { - jcv_circle_event(internal); - } - else - { - finished = 1; - } - } - - for( jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) - { - jcv_finishline(internal, he->edge); - } - jcv_fillgaps(d); -} + }; // end struct jcv -#endif // JC_VORONOI_IMPLEMENTATION +} // namespace /* @@ -1565,7 +1586,7 @@ void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, con A fast single file 2D voronoi diagram generator -HISTORY: +(Pre mathplot) HISTORY: 0.9 2023-01-22 - Modified the Delauney iterator creation api 0.8 2022-12-20 - Added fix for missing border edges More robust removal of duplicate graph edges From c241a5074fdd1ccc3088fcc24b9a52e98f6b59c5 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 12:25:33 +0000 Subject: [PATCH 31/41] Pull some more API into the jc::voronoi class --- mplot/compoundray/EyeVisual.h | 39 +++++++------------- mplot/jcvoronoi/jc_voronoi.h | 67 ++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index da436b12..a48c33f8 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -13,13 +13,10 @@ #include #include -//#define JCV_REAL_TYPE double // double precision in jcvoronoi necessary #include namespace mplot::compoundray { - //using jcv_real = JCV_REAL_TYPE; - // This is a binary-compatible equivalent to Ommatidium from cameras/CompoundEyeDataTypes.h in compound-ray. // Use reinterpret_cast*>(ommatidia) if using compound ray. struct Ommatidium @@ -391,30 +388,20 @@ namespace mplot::compoundray // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->omm2d.size()); - sm::range rx, ry; - rx.search_init(); - ry.search_init(); - for (int i = 0; i < ncoords ; ++i) { - rx.update (this->omm2d[i][0]); - ry.update (this->omm2d[i][1]); + + jc::voronoi vd; // we need double precision for projections, float may run into trouble + vd.border_width = this->border_width; + vd.jcv_diagram_generate (this->omm2d); + + int diag_nsites = vd.diagram_numsites(); + if (diag_nsites != ncoords) { + std::cout << "WARNING: diagram's ncoords (" << diag_nsites << ") != ncoords (" << ncoords << ")?!?!\n"; } - // Generate the 2D Voronoi diagram - // jc::voronoi vd; // will then do some of the following in constructor: - - jc::jcv_diagram diagram; - std::memset (&diagram, 0, sizeof(jc::jcv_diagram)); - jc::jcv_rect domain = { - jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} - }; - jc::voronoi::jcv_diagram_generate (ncoords, this->omm2d.data(), &domain, 0, &diagram); + // We obtain access to the Voronoi cell sites: - const jc::jcv_site* sites = jc::voronoi::jcv_diagram_get_sites (&diagram); - if (diagram.numsites != ncoords) { - std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; - } + const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); - for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { + for (int i = 0; i < diag_nsites && i < ncoords; ++i) { const jc::jcv_site* site = &sites[i]; jc::jcv_graphedge* e = site->edges; // The very first edge while (e) { @@ -433,7 +420,7 @@ namespace mplot::compoundray sm::vvec> flat_triangles; // contains a sequence of triplets of vecs sm::vvec> flat_colours; // To draw triangles iterate over the 'sites' and draw triangles - for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { + for (int i = 0; i < diag_nsites && i < ncoords; ++i) { const jc::jcv_site* site = &sites[i]; const jc::jcv_graphedge* e = site->edges; this->projections[pri].site_indices[i] = site->index; @@ -476,8 +463,6 @@ namespace mplot::compoundray this->computeTriangle (t1, t2, t3, flat_colours[i/3]); } #endif - // At end free the Voronoi diagram memory - jc::voronoi::jcv_diagram_free (&diagram); } // If false, hide 3D representation (the ommatidial cones and discs) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index b50c0349..5efbe464 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -119,20 +119,6 @@ namespace jc void* ctx; // User defined context }; -#if 0 // shift to after context_internal - template - struct jcv_diagram - { - jcv_context_internal* internal; - int numsites; - jcv_point min; - jcv_point max; - }; -#endif -#pragma pack(pop) - -#pragma pack(push, 1) - // Second batch of structs template struct jcv_halfedge @@ -210,7 +196,13 @@ namespace jc struct voronoi { voronoi(){} - ~voronoi(){} + ~voronoi() + { + if (this->diagram) { + jc::voronoi::jcv_diagram_free (this->diagram); + delete this->diagram; + } + } static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; @@ -339,7 +331,6 @@ namespace jc { jcv_context_internal* internal = d->internal; void* memctx = internal->memctx; - //FJCVFreeFn& freefn = internal->free; while(internal->memblocks) { jcv_memoryblock* p = internal->memblocks; @@ -356,6 +347,15 @@ namespace jc return diagram->internal->sites; } + const jcv_site* jcv_diagram_get_sites() + { + const jcv_site* sites = nullptr; + if (this->diagram) { + sites = jcv_diagram_get_sites (this->diagram); + } + return sites; + } + // Iterates over a list of edges, skipping invalid edges (where p0==p1) const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ) { @@ -1576,6 +1576,41 @@ namespace jc jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); } + void jcv_diagram_generate (const std::vector>& centres) + { + int ncoords = static_cast(centres.size()); + sm::range rx, ry; + rx.search_init(); + ry.search_init(); + for (int i = 0; i < ncoords ; ++i) { + rx.update (centres[i][0]); + ry.update (centres[i][1]); + } + // Have to actually new the diagram! + this->diagram = new jc::jcv_diagram; + std::memset (this->diagram, 0, sizeof(jc::jcv_diagram)); + this->domain = { + jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + }; + jc::voronoi::jcv_diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); + } + + int diagram_numsites() const + { + int n = 0; + if (this->diagram) { n = this->diagram->numsites; } + return n; + } + + // User-configurable border width + jcv_real border_width = std::numeric_limits::epsilon(); + + private: + // Our diagram + jc::jcv_diagram* diagram = nullptr; + // A domain for the diagram. + jc::jcv_rect domain = {}; }; // end struct jcv } // namespace From 756baee963d81b496e16d1bac75dee667e14d7db Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 14:02:04 +0000 Subject: [PATCH 32/41] Get everything building with the new voronoi scheme --- mplot/SphericalProjectionVisual.h | 56 ++++++++-------------- mplot/VoronoiVisual.h | 79 ++++++++++++++----------------- mplot/jcvoronoi/jc_voronoi.h | 23 ++------- 3 files changed, 59 insertions(+), 99 deletions(-) diff --git a/mplot/SphericalProjectionVisual.h b/mplot/SphericalProjectionVisual.h index 9f45ed2c..e75e2118 100644 --- a/mplot/SphericalProjectionVisual.h +++ b/mplot/SphericalProjectionVisual.h @@ -9,7 +9,6 @@ #include #include -#define JC_VORONOI_IMPLEMENTATION #include namespace mplot @@ -44,18 +43,18 @@ namespace mplot this->indices.clear(); this->xy.resize (this->latlong.size()); for (uint32_t i = 0; i < this->latlong.size(); ++i) { - this->xy[i] = this->project (this->latlong[i], this->radius).plus_one_dim(); + this->xy[i] = this->project (this->latlong[i], this->radius).plus_one_dim().template as(); } this->voronoi2d(); } //! Compute a triangle from 3 arbitrary corners - void computeTriangle (sm::vec c1, sm::vec c2, sm::vec c3, const std::array& colr) + void computeTriangle (sm::vec c1, sm::vec c2, sm::vec c3, const std::array& colr) { // v is the face normal - sm::vec u1 = c1-c2; - sm::vec u2 = c2-c3; - sm::vec v = u1.cross(u2); + sm::vec u1 = c1-c2; + sm::vec u2 = c2-c3; + sm::vec v = u1.cross(u2); v.renormalize(); // Push corner vertices this->vertex_push (c1.as_float(), this->vertexPositions); @@ -76,33 +75,22 @@ namespace mplot // Use mplot::range to find the extents of dataCoords. From these create a // rectangle to pass to jcv_diagram_generate. int ncoords = static_cast(this->xy.size()); - sm::range rx, ry; - rx.search_init(); - ry.search_init(); - for (int i = 0; i < ncoords ; ++i) { - rx.update (this->xy[i][0]); - ry.update (this->xy[i][1]); - } - // Generate the 2D Voronoi diagram - jcv_diagram diagram; - std::memset (&diagram, 0, sizeof(jcv_diagram)); - jcv_rect domain = { - jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} - }; + jc::voronoi vd; // we need double precision for projections, float may run into trouble + vd.border_width = this->border_width; + vd.jcv_diagram_generate (this->xy); - jcv_diagram_generate (ncoords, this->xy.data(), &domain, 0, &diagram); + int diag_nsites = vd.diagram_numsites(); + if (diag_nsites != ncoords) { + std::cout << "WARNING: diagram's ncoords (" << diag_nsites << ") != ncoords (" << ncoords << ")?!?!\n"; + } // We obtain access to the Voronoi cell sites: - const jcv_site* sites = jcv_diagram_get_sites (&diagram); - if (diagram.numsites != ncoords) { - std::cout << "WARNING: diagram's ncoords (" << diagram.numsites << ") != ncoords (" << ncoords << ")?!?!\n"; - } + const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); - for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { - const jcv_site* site = &sites[i]; - jcv_graphedge* e = site->edges; // The very first edge + for (int i = 0; i < vd.diagram_numsites() && i < ncoords; ++i) { + const jc::jcv_site* site = &sites[i]; + jc::jcv_graphedge* e = site->edges; // The very first edge while (e) { // Set z. Should be done in jcvoronoi, but haven't found out how e->pos[0][2] = this->xy[i][2]; @@ -112,9 +100,9 @@ namespace mplot } // To draw triangles iterate over the 'sites' and draw triangles - for (int i = 0; i < diagram.numsites && i < ncoords; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites() && i < ncoords; ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; std::array c = mplot::colour::black; if (static_cast(site->index) < this->colour.size()) { c = this->colour[site->index]; } uint32_t site_triangles = 0; @@ -128,16 +116,14 @@ namespace mplot e = e->next; } } - // At end free the Voronoi diagram memory - jcv_diagram_free (&diagram); } // latlong, supplied by user sm::vvec> latlong; // Colour, supplied by user sm::vvec> colour; - // xy, result of projection, but in 3D - sm::vvec> xy; + // xy, result of projection, but in 3D. double precision always + sm::vvec> xy; // The radius of our sphere T radius = T{1}; // The longitudinal offset diff --git a/mplot/VoronoiVisual.h b/mplot/VoronoiVisual.h index e07eec51..7e279318 100644 --- a/mplot/VoronoiVisual.h +++ b/mplot/VoronoiVisual.h @@ -25,7 +25,6 @@ #include #include -#define JC_VORONOI_IMPLEMENTATION #include namespace mplot { @@ -101,17 +100,12 @@ namespace mplot { } // Generate the 2D Voronoi diagram - jcv_diagram diagram; - std::memset (&diagram, 0, sizeof(jcv_diagram)); + jc::voronoi vd; + vd.border_width = this->border_width; + vd.jcv_diagram_generate (*(dcoords_ptr)); - jcv_rect domain = { - jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} - }; - jcv_diagram_generate (ncoords, this->dcoords_ptr->data(), &domain, 0, &diagram); - - // We obtain access the the Voronoi cell sites: - const jcv_site* sites = jcv_diagram_get_sites (&diagram); + // We obtain access to the Voronoi cell sites: + const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); // Now scan through the Voronoi cell 'sites' and 'edges' to re-assign z // values in the edges. This is not going to be particularly efficient, but @@ -130,21 +124,21 @@ namespace mplot { // Mapping same edge end-point locations to the averate z value of the adjacent cell centres std::map, float, veccmp> edge_end_zsums; - for (int i = 0; i < diagram.numsites; ++i) { + for (int i = 0; i < vd.diagram_numsites(); ++i) { // We have the current edge_1, the next edge_2 and the previous edge_0 - const jcv_site* site = &sites[i]; - jcv_graphedge* edge_first = site->edges; // The very first edge - jcv_graphedge* edge_1 = edge_first; - jcv_graphedge* edge_2 = edge_first; - jcv_graphedge* edge_0 = edge_first; + const jc::jcv_site* site = &sites[i]; + jc::jcv_graphedge* edge_first = site->edges; // The very first edge + jc::jcv_graphedge* edge_1 = edge_first; + jc::jcv_graphedge* edge_2 = edge_first; + jc::jcv_graphedge* edge_0 = edge_first; while (edge_0->next) { edge_0 = edge_0->next; } while (edge_1) { // Set z to 0. Should be done in jcvoronoi, but haven't found out how - edge_1->pos[0][2] = jcv_real{0}; - edge_1->pos[1][2] = jcv_real{0}; + edge_1->pos[0][2] = 0.0f; + edge_1->pos[1][2] = 0.0f; edge_2 = edge_1->next ? edge_1->next : edge_first; // edge_0 already set @@ -192,9 +186,9 @@ namespace mplot { } // Now go through edge_end_zsums and edges and update z values - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - jcv_graphedge* edge_1 = site->edges; // The very first edge + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + jc::jcv_graphedge* edge_1 = site->edges; // The very first edge while (edge_1) { // For each edge, set z from the map float zsum0 = 0.0f; @@ -228,9 +222,9 @@ namespace mplot { sm::vec t1 = {0.0f}; sm::vec t2 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; unsigned int site_triangles = 0; while (e) { // NB: There are 3 each of pos/col/norm vertices (and 3 indices) per @@ -249,9 +243,9 @@ namespace mplot { } } else { // No need to inverse rotate - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; unsigned int site_triangles = 0; while (e) { this->computeTriangle (site->p, e->pos[0], e->pos[1], this->setColour(site->index)); @@ -263,7 +257,7 @@ namespace mplot { this->triangle_count_sum += site_triangles; } } - if (static_cast(diagram.numsites) != ncoords) { + if (static_cast(vd.diagram_numsites()) != ncoords) { std::cout << "WARNING: numsites != ncoords ?!?!\n"; } @@ -275,9 +269,9 @@ namespace mplot { sm::vec t0 = {0.0f}; sm::vec t1 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; while (e) { t0 = rqinv * (e->pos[0] * this->zoom); t1 = rqinv * (e->pos[1] * this->zoom); @@ -288,9 +282,9 @@ namespace mplot { } else { // No rotations required - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; while (e) { this->computeTube (e->pos[0] * this->zoom, e->pos[1] * this->zoom, mplot::colour::royalblue, mplot::colour::goldenrod2, this->voronoi_grid_thickness, 12); @@ -307,9 +301,9 @@ namespace mplot { sm::vec t1 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; while (e) { t0 = rqinv * sm::vec{ e->pos[0].x() * this->zoom, e->pos[0].y() * this->zoom, 0.0f }; t1 = rqinv * sm::vec{ e->pos[1].x() * this->zoom, e->pos[1].y() * this->zoom, 0.0f }; @@ -320,9 +314,9 @@ namespace mplot { } else { // Show the 2D Voronoi diagram's edges at z=0 - for (int i = 0; i < diagram.numsites; ++i) { - const jcv_site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + for (int i = 0; i < vd.diagram_numsites(); ++i) { + const jc::jcv_site* site = &sites[i]; + const jc::jcv_graphedge* e = site->edges; while (e) { this->computeTube ({ e->pos[0].x() * this->zoom, e->pos[0].y() * this->zoom, 0.0f }, { e->pos[1].x() * this->zoom, e->pos[1].y() * this->zoom, 0.0f }, @@ -339,9 +333,6 @@ namespace mplot { this->computeSphere ((*this->dataCoords)[i] * this->zoom, mplot::colour::black, this->dataCoord_sphere_size); } } - - // At end free the Voronoi diagram memory - jcv_diagram_free (&diagram); } void reinitColoursScalar() diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 5efbe464..68ce8bc3 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -199,30 +199,13 @@ namespace jc ~voronoi() { if (this->diagram) { - jc::voronoi::jcv_diagram_free (this->diagram); + jc::voronoi::jcv_diagram_free (this->diagram); delete this->diagram; } } static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; -/* - typedef sm::vec jcv_point; - typedef struct jcv_rect_ jcv_rect; - typedef struct jcv_site_ jcv_site; - typedef struct jcv_edge_ jcv_edge; - typedef struct jcv_graphedge_ jcv_graphedge; - typedef struct jcv_delauney_edge_ jcv_delauney_edge; - typedef struct jcv_delauney_iter_ jcv_delauney_iter; - typedef struct jcv_diagram_ jcv_diagram; - typedef struct jcv_clipper_ jcv_clipper; - typedef struct jcv_context_internal_ jcv_context_internal; - - typedef void* (*FJCVAllocFn)(void* userctx, size_t size); - typedef void (*FJCVFreeFn)(void* userctx, void* p); -*/ - // FIRST batch of structs were here - // INTERNAL FUNCTIONS static const int JCV_DIRECTION_LEFT = 0; @@ -324,8 +307,6 @@ namespace jc return std::sqrt (jcv_point_dist_sq (pt1, pt2)); } - // SECOND batch of Structs were here - // Uses free (or the registered custom free function) static void jcv_diagram_free( jcv_diagram* d ) { @@ -347,6 +328,7 @@ namespace jc return diagram->internal->sites; } + // User API const jcv_site* jcv_diagram_get_sites() { const jcv_site* sites = nullptr; @@ -1576,6 +1558,7 @@ namespace jc jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); } + // User API void jcv_diagram_generate (const std::vector>& centres) { int ncoords = static_cast(centres.size()); From 275d20a7501a2ff8303f32cf3b6438222c62aaf8 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 14:26:53 +0000 Subject: [PATCH 33/41] Stage 1 refactoring. T and jcv_edge --- mplot/VoronoiVisual.h | 22 +- mplot/jcvoronoi/jc_voronoi.h | 621 +++++++++++++++--------------- mplot/jcvoronoi/jc_voronoi_clip.h | 3 + 3 files changed, 325 insertions(+), 321 deletions(-) diff --git a/mplot/VoronoiVisual.h b/mplot/VoronoiVisual.h index 7e279318..9cb4e92a 100644 --- a/mplot/VoronoiVisual.h +++ b/mplot/VoronoiVisual.h @@ -90,7 +90,7 @@ namespace mplot { } // Use mplot::range to find the extents of dataCoords. From these create a - // rectangle to pass to jcv_diagram_generate. + // rectangle to pass to diagram_generate. sm::range rx, ry; rx.search_init(); ry.search_init(); @@ -100,12 +100,12 @@ namespace mplot { } // Generate the 2D Voronoi diagram - jc::voronoi vd; + jc::manager vd; vd.border_width = this->border_width; - vd.jcv_diagram_generate (*(dcoords_ptr)); + vd.diagram_generate (*(dcoords_ptr)); // We obtain access to the Voronoi cell sites: - const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); + const jc::jcv_site* sites = vd.diagram_get_sites(); // Now scan through the Voronoi cell 'sites' and 'edges' to re-assign z // values in the edges. This is not going to be particularly efficient, but @@ -149,21 +149,21 @@ namespace mplot { // solution would be to modify the jcvoronoi algorithm to populate // both ends of all edges with additional logic. for (unsigned int j = 0; j < 2; ++j) { - if (edge_1->edge->sites[j]) { + if (edge_1->edge_->sites[j]) { //std::cout << "insert edge_1 " << edge_1->edge->sites[j]->p << " into edge_pos_centres[" << edge_1->pos[1] << "]\n"; - edge_pos_centres[edge_1->pos[1]].insert (edge_1->edge->sites[j]->p); + edge_pos_centres[edge_1->pos[1]].insert (edge_1->edge_->sites[j]->p); //std::cout << "insert edge_1 " << edge_1->edge->sites[j]->p << " into edge_pos_centres[" << edge_1->pos[0] << "]\n"; - edge_pos_centres[edge_1->pos[0]].insert (edge_1->edge->sites[j]->p); + edge_pos_centres[edge_1->pos[0]].insert (edge_1->edge_->sites[j]->p); } // By definition, cellcentres_1 also gets edge_2 sites... - if (edge_2->edge->sites[j]) { + if (edge_2->edge_->sites[j]) { //std::cout << "insert edge_2 " << edge_2->edge->sites[j]->p << " into edge_pos_centres[" << edge_1->pos[1] << "]\n"; - edge_pos_centres[edge_1->pos[1]].insert (edge_2->edge->sites[j]->p); + edge_pos_centres[edge_1->pos[1]].insert (edge_2->edge_->sites[j]->p); } // and cellcentres_0 gets edge_0 sites - if (edge_0->edge->sites[j]) { + if (edge_0->edge_->sites[j]) { //std::cout << "insert edge_0 " << edge_0->edge->sites[j]->p << " into edge_pos_centres[" << edge_1->pos[0] << "]\n"; - edge_pos_centres[edge_1->pos[0]].insert (edge_0->edge->sites[j]->p); + edge_pos_centres[edge_1->pos[0]].insert (edge_0->edge_->sites[j]->p); } } diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 68ce8bc3..5491d235 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -25,73 +25,73 @@ namespace jc { #pragma pack(push, 1) - template - using jcv_point = sm::vec; + template + using jcv_point = sm::vec; // fwd declar graphpedge - template struct jcv_graphedge; + template struct jcv_graphedge; - template + template struct jcv_site { - jcv_point p; + jcv_point p; int index; // Index into the original list of points - jcv_graphedge* edges; // The half edges owned by the cell + jcv_graphedge* edges; // The half edges owned by the cell }; // The coefficients a, b and c are from the general line equation: ax * by + c = 0 - template - struct jcv_edge + template + struct edge { - struct jcv_edge* next; - jcv_site* sites[2]; - jcv_point pos[2]; - jcv_real a; - jcv_real b; - jcv_real c; + struct edge* next; + jcv_site* sites[2]; + jcv_point pos[2]; + T a; + T b; + T c; }; - template + template struct jcv_graphedge { - struct jcv_graphedge* next; - struct jcv_edge* edge; - struct jcv_site* neighbor; - jcv_point pos[2]; - jcv_real angle; + struct jcv_graphedge* next; + struct edge* edge_; + struct jcv_site* neighbor; + jcv_point pos[2]; + T angle; }; - template + template struct jcv_delauney_iter { - const jcv_edge* sentinel; - const jcv_edge* current; + const edge* sentinel; + const edge* current; }; - template + template struct jcv_delauney_edge { - const jcv_edge* edge; // The voronoi edge separating the two sites - const jcv_site* sites[2]; - jcv_point pos[2]; // the positions of the two sites + const edge* edge_; // The voronoi edge separating the two sites + const jcv_site* sites[2]; + jcv_point pos[2]; // the positions of the two sites }; - template + template struct jcv_rect { - jcv_point min; - jcv_point max; + jcv_point min; + jcv_point max; }; // Convert these to templated usings? or use std::function? /// Tests if a point is inside the final shape - //typedef int (*jcv_clip_test_point_fn)(const jcv_clipper* clipper, const jcv_point p); - //template + //typedef int (*jcv_clip_test_point_fn)(const jcv_clipper* clipper, const jcv_point p); + //template /** Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] * Returns 0 if not successful */ - //typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, jcv_edge* e); + //typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, edge* e); /** Given the clipper, the site and the last edge, * closes any gaps in the polygon by adding new edges that follow the bounding shape @@ -100,34 +100,34 @@ namespace jc //typedef void (*jcv_clip_fillgap_fn)(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); // Forward declare jcv_context_internal for the std::function - template struct jcv_context_internal; + template struct jcv_context_internal; - template + template struct jcv_clipper { // Tests if a point is inside the final shape - std::function* clipper, const jcv_point p)> test_fn; + std::function* clipper, const jcv_point p)> test_fn; // Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] // Returns 0 if not successful - std::function* clipper, jcv_edge* e)> clip_fn; + std::function* clipper, edge* e)> clip_fn; // Given the clipper, the site and the last edge, // closes any gaps in the polygon by adding new edges that follow the bounding shape // The internal context is use when allocating new edges. - std::function* clipper, jcv_context_internal* allocator, jcv_site* s)> fill_fn; - jcv_point min; // The bounding rect min - jcv_point max; // The bounding rect max + std::function* clipper, jcv_context_internal* allocator, jcv_site* s)> fill_fn; + jcv_point min; // The bounding rect min + jcv_point max; // The bounding rect max void* ctx; // User defined context }; // Second batch of structs - template + template struct jcv_halfedge { - jcv_edge* edge; - struct jcv_halfedge* left; - struct jcv_halfedge* right; - jcv_point vertex; - jcv_real y; + edge* edge_; + struct jcv_halfedge* left; + struct jcv_halfedge* right; + jcv_point vertex; + T y; int direction; // 0=left, 1=right int pqpos; }; @@ -152,102 +152,103 @@ namespace jc using FJCVAllocFn = void*(void* userctx, size_t size); using FJCVFreeFn = void(void* userctx, void* p); - template + template struct jcv_context_internal { void* mem; - jcv_edge* edges; - jcv_halfedge* beachline_start; - jcv_halfedge* beachline_end; - jcv_halfedge* last_inserted; + edge* edges; + jcv_halfedge* beachline_start; + jcv_halfedge* beachline_end; + jcv_halfedge* last_inserted; jcv_priorityqueue* eventqueue; - jcv_site* sites; - jcv_site* bottomsite; + jcv_site* sites; + jcv_site* bottomsite; int numsites; int currentsite; int _padding; jcv_memoryblock* memblocks; - jcv_edge* edgepool; - jcv_halfedge* halfedgepool; + edge* edgepool; + jcv_halfedge* halfedgepool; void** eventmem; - jcv_clipper clipper; + jcv_clipper clipper; void* memctx; // Given by the user std::function alloc; std::function free; - jcv_rect rect; + jcv_rect rect; }; - template + template struct jcv_diagram { - jcv_context_internal* internal; + jcv_context_internal* internal; int numsites; - jcv_point min; - jcv_point max; + jcv_point min; + jcv_point max; }; #pragma pack(pop) - template requires std::is_floating_point_v - struct voronoi + // The mananger class. Type T is what is called jcv_real in the original code + template requires std::is_floating_point_v + struct manager { - voronoi(){} - ~voronoi() + manager(){} + ~manager() { if (this->diagram) { - jc::voronoi::jcv_diagram_free (this->diagram); + jc::manager::jcv_diagram_free (this->diagram); delete this->diagram; } } - static constexpr jcv_real jcv_edge_intersect_threshold = jcv_real{JCV_EDGE_INTERSECT_THRESHOLD}; + static constexpr T edge_intersect_threshold = T{JCV_EDGE_INTERSECT_THRESHOLD}; // INTERNAL FUNCTIONS static const int JCV_DIRECTION_LEFT = 0; static const int JCV_DIRECTION_RIGHT = 1; - static constexpr jcv_real jcv_invalid_value = std::numeric_limits::lowest(); + static constexpr T jcv_invalid_value = std::numeric_limits::lowest(); // App specific equality - static int jcv_real_eq(jcv_real a, jcv_real b) + static int T_eq(T a, T b) { - return std::abs(a - b) < std::numeric_limits::epsilon(); + return std::abs(a - b) < std::numeric_limits::epsilon(); } // jcv_point static int jcv_point_cmp(const void* p1, const void* p2) { - const jcv_point* s1 = static_cast*>(p1); - const jcv_point* s2 = static_cast*>(p2); + const jcv_point* s1 = static_cast*>(p1); + const jcv_point* s2 = static_cast*>(p2); return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); } - static int jcv_point_less (const jcv_point* pt1, const jcv_point* pt2 ) + static int jcv_point_less (const jcv_point* pt1, const jcv_point* pt2 ) { return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); } - static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) + static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) { - return jcv_real_eq(pt1->y(), pt2->y()) && jcv_real_eq(pt1->x(), pt2->x()); + return T_eq(pt1->y(), pt2->y()) && T_eq(pt1->x(), pt2->x()); } [[maybe_unused]] - static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) { return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); } // edges and corners - static const int JCV_EDGE_LEFT = 1; - static const int JCV_EDGE_RIGHT = 2; - static const int JCV_EDGE_BOTTOM = 4; - static const int JCV_EDGE_TOP = 8; + static const int EDGE_LEFT = 1; + static const int EDGE_RIGHT = 2; + static const int EDGE_BOTTOM = 4; + static const int EDGE_TOP = 8; static const int JCV_CORNER_NONE = 0; static const int JCV_CORNER_TOP_LEFT = 1; @@ -255,23 +256,23 @@ namespace jc static const int JCV_CORNER_BOTTOM_RIGHT = 3; static const int JCV_CORNER_TOP_RIGHT = 4; - static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) { int flags = 0; - if (pt->x() == min->x()) flags |= JCV_EDGE_LEFT; - else if (pt->x() == max->x()) flags |= JCV_EDGE_RIGHT; - if (pt->y() == min->y()) flags |= JCV_EDGE_BOTTOM; - else if (pt->y() == max->y()) flags |= JCV_EDGE_TOP; + if (pt->x() == min->x()) flags |= EDGE_LEFT; + else if (pt->x() == max->x()) flags |= EDGE_RIGHT; + if (pt->y() == min->y()) flags |= EDGE_BOTTOM; + else if (pt->y() == max->y()) flags |= EDGE_TOP; return flags; } - static int jcv_edge_flags_to_corner(int edge_flags) + static int edge_flags_to_corner(int edge_flags) { #define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL - TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_LEFT, JCV_CORNER_TOP_LEFT); - TEST_FLAGS(JCV_EDGE_TOP|JCV_EDGE_RIGHT, JCV_CORNER_TOP_RIGHT); - TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT); - TEST_FLAGS(JCV_EDGE_BOTTOM|JCV_EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT); + TEST_FLAGS(EDGE_TOP|EDGE_LEFT, JCV_CORNER_TOP_LEFT); + TEST_FLAGS(EDGE_TOP|EDGE_RIGHT, JCV_CORNER_TOP_RIGHT); + TEST_FLAGS(EDGE_BOTTOM|EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT); + TEST_FLAGS(EDGE_BOTTOM|EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT); #undef TEST_FLAGS return 0; } @@ -284,9 +285,9 @@ namespace jc corner = (corner+1)%4; return corner + 1; } - static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) + static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) { - jcv_point p; + jcv_point p; if (corner == JCV_CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } else if (corner == JCV_CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } else if (corner == JCV_CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } @@ -295,22 +296,22 @@ namespace jc return p; } - static jcv_real jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) + static T jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) { - jcv_real diffx = pt1->x() - pt2->x(); - jcv_real diffy = pt1->y() - pt2->y(); + T diffx = pt1->x() - pt2->x(); + T diffy = pt1->y() - pt2->y(); return diffx * diffx + diffy * diffy; } - static jcv_real jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) + static T jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) { return std::sqrt (jcv_point_dist_sq (pt1, pt2)); } // Uses free (or the registered custom free function) - static void jcv_diagram_free( jcv_diagram* d ) + static void jcv_diagram_free( jcv_diagram* d ) { - jcv_context_internal* internal = d->internal; + jcv_context_internal* internal = d->internal; void* memctx = internal->memctx; while(internal->memblocks) { @@ -323,15 +324,15 @@ namespace jc } // Returns an array of sites, where each index is the same as the original input point array. - static const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ) + static const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ) { return diagram->internal->sites; } // User API - const jcv_site* jcv_diagram_get_sites() + const jcv_site* diagram_get_sites() { - const jcv_site* sites = nullptr; + const jcv_site* sites = nullptr; if (this->diagram) { sites = jcv_diagram_get_sites (this->diagram); } @@ -339,9 +340,9 @@ namespace jc } // Iterates over a list of edges, skipping invalid edges (where p0==p1) - const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ) + const edge* jcv_diagram_get_next_edge( const edge* _edge ) { - const jcv_edge* e = edge->next; + const edge* e = _edge->next; while (e != 0 && jcv_point_eq(&e->pos[0], &e->pos[1])) { e = e->next; } @@ -351,22 +352,22 @@ namespace jc // Returns a linked list of all the voronoi edges excluding the ones that lie on the borders of // the bounding box. For a full list of edges, you need to iterate over the sites, and their // graph edges. - const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ) + const edge* jcv_diagram_get_edges( const jcv_diagram* diagram ) { - jcv_edge e; + edge e; e.next = diagram->internal->edges; return jcv_diagram_get_next_edge(&e); } // Creates an iterator over the delauney edges of a voronoi diagram - void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ) + void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ) { iter->current = 0; iter->sentinel = jcv_diagram_get_edges(diagram); } // Steps the iterator and returns the next edge Returns 0 when there are no more edges - int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) + int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) { if (iter->sentinel) { @@ -389,9 +390,9 @@ namespace jc if (!iter->current) return 0; - next->edge = iter->current; - next->sites[0] = next->edge->sites[0]; - next->sites[1] = next->edge->sites[1]; + next->edge_ = iter->current; + next->sites[0] = next->edge_->sites[0]; + next->sites[1] = next->edge_->sites[1]; next->pos[0] = next->sites[0]->p; next->pos[1] = next->sites[1]->p; return 1; @@ -402,7 +403,7 @@ namespace jc return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); } - static void* jcv_alloc(jcv_context_internal* internal, size_t size) + static void* jcv_alloc(jcv_context_internal* internal, size_t size) { if( !internal->memblocks || internal->memblocks->sizefree < (size+sizeof(void*)) ) { @@ -422,26 +423,26 @@ namespace jc return p_aligned; } - static jcv_edge* jcv_alloc_edge(jcv_context_internal* internal) + static edge* jcv_alloc_edge(jcv_context_internal* internal) { - return (jcv_edge*)jcv_alloc(internal, sizeof(jcv_edge)); + return (edge*)jcv_alloc(internal, sizeof(edge)); } - static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal) + static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal) { if( internal->halfedgepool ) { - jcv_halfedge* edge = internal->halfedgepool; + jcv_halfedge* edge = internal->halfedgepool; internal->halfedgepool = internal->halfedgepool->right; return edge; } - return (jcv_halfedge*)jcv_alloc(internal, sizeof(jcv_halfedge)); + return (jcv_halfedge*)jcv_alloc(internal, sizeof(jcv_halfedge)); } - static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal) + static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal) { - return (jcv_graphedge*)jcv_alloc(internal, sizeof(jcv_graphedge)); + return (jcv_graphedge*)jcv_alloc(internal, sizeof(jcv_graphedge)); } static void* jcv_alloc_fn(void* memctx, size_t size) @@ -456,13 +457,13 @@ namespace jc free(p); } - // jcv_edge methods - static int jcv_is_valid(const jcv_point* p) + // edge methods + static int jcv_is_valid(const jcv_point* p) { return (p->x() != jcv_invalid_value || p->y() != jcv_invalid_value) ? 1 : 0; } - static void jcv_edge_create(jcv_edge* e, jcv_site* s1, jcv_site* s2) + static void edge_create(edge* e, jcv_site* s1, jcv_site* s2) { e->next = 0; e->sites[0] = s1; @@ -473,61 +474,61 @@ namespace jc e->pos[1][1] = jcv_invalid_value; // Create line equation between S1 and S2: - // jcv_real a = -1 * (s2->p[1] - s1->p[1]); - // jcv_real b = s2->p[0] - s1->p[0]; - // //jcv_real c = -1 * (s2->p[0] - s1->p[0]) * s1->p[1] + (s2->p[1] - s1->p[1]) * s1->p[0]; + // T a = -1 * (s2->p[1] - s1->p[1]); + // T b = s2->p[0] - s1->p[0]; + // //T c = -1 * (s2->p[0] - s1->p[0]) * s1->p[1] + (s2->p[1] - s1->p[1]) * s1->p[0]; // // // create perpendicular line - // jcv_real pa = b; - // jcv_real pb = -a; - // //jcv_real pc = pa * s1->p[0] + pb * s1->p[1]; + // T pa = b; + // T pb = -a; + // //T pc = pa * s1->p[0] + pb * s1->p[1]; // // // Move to the mid point - // jcv_real mx = s1->p[0] + dx * jcv_real(0.5); - // jcv_real my = s1->p[1] + dy * jcv_real(0.5); - // jcv_real pc = ( pa * mx + pb * my ); + // T mx = s1->p[0] + dx * T(0.5); + // T my = s1->p[1] + dy * T(0.5); + // T pc = ( pa * mx + pb * my ); - jcv_real dx = s2->p[0] - s1->p[0]; - jcv_real dy = s2->p[1] - s1->p[1]; + T dx = s2->p[0] - s1->p[0]; + T dy = s2->p[1] - s1->p[1]; int dx_is_larger = (dx*dx) > (dy*dy); // instead of fabs // Simplify it, using dx and dy - e->c = dx * (s1->p[0] + dx * (jcv_real)0.5) + dy * (s1->p[1] + dy * (jcv_real)0.5); + e->c = dx * (s1->p[0] + dx * (T)0.5) + dy * (s1->p[1] + dy * (T)0.5); if( dx_is_larger ) { - e->a = (jcv_real)1; + e->a = (T)1; e->b = dy / dx; e->c /= dx; } else { e->a = dx / dy; - e->b = (jcv_real)1; + e->b = (T)1; e->c /= dy; } } // CLIPPING - static int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p) + static int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p) { return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] && p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; } // The line equation: ax + by + c = 0 - // see jcv_edge_create - static int jcv_boxshape_clip(const jcv_clipper* clipper, jcv_edge* e) - { - jcv_real pxmin = clipper->min[0]; - jcv_real pxmax = clipper->max[0]; - jcv_real pymin = clipper->min[1]; - jcv_real pymax = clipper->max[1]; - - jcv_real x1, y1, x2, y2; - jcv_point* s1; - jcv_point* s2; - if (e->a == (jcv_real)1 && e->b >= (jcv_real)0) + // see edge_create + static int jcv_boxshape_clip(const jcv_clipper* clipper, edge* e) + { + T pxmin = clipper->min[0]; + T pxmax = clipper->max[0]; + T pymin = clipper->min[1]; + T pymax = clipper->max[1]; + + T x1, y1, x2, y2; + jcv_point* s1; + jcv_point* s2; + if (e->a == (T)1 && e->b >= (T)0) { s1 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; s2 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; @@ -538,7 +539,7 @@ namespace jc s2 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; } - if (e->a == (jcv_real)1) // delta x is larger + if (e->a == (T)1) // delta x is larger { y1 = pymin; if (s1 != 0 && s1->y() > pymin) @@ -640,23 +641,23 @@ namespace jc } // The line equation: ax + by + c = 0 - // see jcv_edge_create - static int jcv_edge_clipline(jcv_context_internal* internal, jcv_edge* e) + // see edge_create + static int edge_clipline(jcv_context_internal* internal, edge* e) { return internal->clipper.clip_fn(&internal->clipper, e); } - static jcv_edge* jcv_edge_new(jcv_context_internal* internal, jcv_site* s1, jcv_site* s2) + static edge* edge_new(jcv_context_internal* internal, jcv_site* s1, jcv_site* s2) { - jcv_edge* e = jcv_alloc_edge(internal); - jcv_edge_create(e, s1, s2); + edge* e = jcv_alloc_edge(internal); + edge_create(e, s1, s2); return e; } // jcv_halfedge - static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) + static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) { newedge->left = edge; newedge->right = edge->right; @@ -664,7 +665,7 @@ namespace jc edge->right = newedge; } - static void jcv_halfedge_unlink(jcv_halfedge* he) + static void jcv_halfedge_unlink(jcv_halfedge* he) { he->left->right = he->right; he->right->left = he->left; @@ -672,10 +673,10 @@ namespace jc he->right = 0; } - static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, jcv_edge* e, int direction) + static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, edge* e, int direction) { - jcv_halfedge* he = jcv_alloc_halfedge(internal); - he->edge = e; + jcv_halfedge* he = jcv_alloc_halfedge(internal); + he->edge_ = e; he->left = 0; he->right = 0; he->direction = direction; @@ -686,26 +687,26 @@ namespace jc return he; } - static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he) + static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he) { he->right = internal->halfedgepool; internal->halfedgepool = he; } - static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) + static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) { - return he->edge->sites[he->direction]; + return he->edge_->sites[he->direction]; } - static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) + static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) { - return he->edge ? he->edge->sites[1 - he->direction] : 0; + return he->edge_ ? he->edge_->sites[1 - he->direction] : 0; } - static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) + static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) { - const jcv_edge* e = he->edge; - const jcv_site* topsite = e->sites[1]; + const edge* e = he->edge_; + const jcv_site* topsite = e->sites[1]; int right_of_site = (p->x() > topsite->p[0]) ? 1 : 0; if (right_of_site && he->direction == JCV_DIRECTION_LEFT) @@ -713,15 +714,15 @@ namespace jc if (!right_of_site && he->direction == JCV_DIRECTION_RIGHT) return 0; - jcv_real dxp, dyp, dxs, t1, t2, t3, yl; + T dxp, dyp, dxs, t1, t2, t3, yl; int above; - if (e->a == (jcv_real)1) + if (e->a == (T)1) { dyp = p->y() - topsite->p[1]; dxp = p->x() - topsite->p[0]; int fast = 0; - if( (!right_of_site & (e->b < (jcv_real)0)) | (right_of_site & (e->b >= (jcv_real)0)) ) + if( (!right_of_site & (e->b < (T)0)) | (right_of_site & (e->b >= (T)0)) ) { above = dyp >= e->b * dxp; fast = above; @@ -729,7 +730,7 @@ namespace jc else { above = (p->x() + p->y() * e->b) > e->c; - if (e->b < (jcv_real)0) + if (e->b < (T)0) above = !above; if (!above) fast = 1; @@ -738,8 +739,8 @@ namespace jc { dxs = topsite->p[0] - e->sites[0]->p[0]; above = e->b * (dxp * dxp - dyp * dyp) - < dxs * dyp * ((jcv_real)1 + (jcv_real)2 * dxp / dxs + e->b * e->b); - if (e->b < (jcv_real)0) + < dxs * dyp * ((T)1 + (T)2 * dxp / dxs + e->b * e->b); + if (e->b < (T)0) above = !above; } } @@ -756,18 +757,18 @@ namespace jc // Keeps the priority queue sorted with events sorted in ascending order // Return 1 if the edges needs to be swapped - static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) + static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) { return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; } - static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) + static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) { - const jcv_edge* e1 = he1->edge; - const jcv_edge* e2 = he2->edge; + const edge* e1 = he1->edge_; + const edge* e2 = he2->edge_; - jcv_real d = e1->a * e2->b - e1->b * e2->a; - if(-jcv_edge_intersect_threshold < d && d < jcv_edge_intersect_threshold) + T d = e1->a * e2->b - e1->b * e2->a; + if(-edge_intersect_threshold < d && d < edge_intersect_threshold) { return 0; } @@ -777,8 +778,8 @@ namespace jc // information required. So just set out->z to a default value meaning 'unset' (Seb) (*out)[2] = 0.0f; // NB: this does not set z for all edges - const jcv_edge* e; - const jcv_halfedge* he; + const edge* e; + const jcv_halfedge* he; if( jcv_point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) { he = he1; @@ -804,8 +805,8 @@ namespace jc static int jcv_pq_moveup(jcv_priorityqueue* pq, int pos) { - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge* node = items[pos]; for( int parent = (pos >> 1); pos > 1 && jcv_halfedge_compare(items[parent], node); @@ -825,7 +826,7 @@ namespace jc int child = pos << 1; if( child >= pq->numitems ) return 0; - jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge** items = (jcv_halfedge**)pq->items; if( (child + 1) < pq->numitems && jcv_halfedge_compare(items[child], items[child+1]) ) return child+1; return child; @@ -833,8 +834,8 @@ namespace jc static int jcv_pq_movedown(jcv_priorityqueue* pq, int pos) { - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge* node = items[pos]; int child = jcv_pq_maxchild(pq, pos); while( child && jcv_halfedge_compare(node, items[child]) ) @@ -883,7 +884,7 @@ namespace jc return pq->items[1]; } - static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) + static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) { if( pq->numitems == 1 ) return; @@ -891,7 +892,7 @@ namespace jc if( pos == 0 ) return; - jcv_halfedge** items = (jcv_halfedge**)pq->items; + jcv_halfedge** items = (jcv_halfedge**)pq->items; items[pos] = items[--pq->numitems]; if( jcv_halfedge_compare( node, items[pos] ) ) @@ -903,17 +904,17 @@ namespace jc // internal functions - static jcv_site* jcv_nextsite(jcv_context_internal* internal) + static jcv_site* jcv_nextsite(jcv_context_internal* internal) { return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; } - static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, const jcv_point* p) + static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, const jcv_point* p) { // Gets the arc on the beach line at the x coordinate (i.e. right above the new site event) // A good guess it's close by (Can be optimized) - jcv_halfedge* he = internal->last_inserted; + jcv_halfedge* he = internal->last_inserted; if( !he ) { if( p->x() < (internal->rect.max[0] - internal->rect.min[0]) / 2 ) @@ -943,10 +944,10 @@ namespace jc return he; } - static int jcv_check_circle_event(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* vertex) + static int jcv_check_circle_event(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* vertex) { - jcv_edge* e1 = he1->edge; - jcv_edge* e2 = he2->edge; + edge* e1 = he1->edge_; + edge* e2 = he2->edge_; if( e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1] ) { return 0; @@ -955,27 +956,27 @@ namespace jc return jcv_halfedge_intersect(he1, he2, vertex); } - static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) + static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) { - jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p); - jcv_halfedge* right = left->right; - jcv_site* bottom = jcv_halfedge_rightsite(left); + jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p); + jcv_halfedge* right = left->right; + jcv_site* bottom = jcv_halfedge_rightsite(left); if( !bottom ) bottom = internal->bottomsite; - jcv_edge* edge = jcv_edge_new(internal, bottom, site); + edge* edge = edge_new(internal, bottom, site); edge->next = internal->edges; internal->edges = edge; - jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT); - jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT); + jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT); + jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT); jcv_halfedge_link(left, edge1); jcv_halfedge_link(edge1, edge2); internal->last_inserted = right; - jcv_point p; + jcv_point p; if( jcv_check_circle_event( left, edge1, &p ) ) { jcv_pq_remove(internal->eventqueue, left); @@ -992,34 +993,34 @@ namespace jc } // https://cp-algorithms.com/geometry/oriented-triangle-area.html - static jcv_real jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) + static T jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) { return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); } - static jcv_real jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) + static T jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) { // We take the average of the two points, since we can better distinguish between very small edges - constexpr jcv_real half = jcv_real{0.5}; - jcv_real x = (edge->pos[0][0] + edge->pos[1][0]) * half; - jcv_real y = (edge->pos[0][1] + edge->pos[1][1]) * half; - jcv_real diffy = y - site->p[1]; - jcv_real angle = std::atan2( diffy, x - site->p[0] ); + constexpr T half = T{0.5}; + T x = (edge->pos[0][0] + edge->pos[1][0]) * half; + T y = (edge->pos[0][1] + edge->pos[1][1]) * half; + T diffy = y - site->p[1]; + T angle = std::atan2( diffy, x - site->p[0] ); if( diffy < 0 ) { - angle = angle + sm::mathconst::two_pi; + angle = angle + sm::mathconst::two_pi; } return angle; } - static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) + static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) { - return jcv_real_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); + return T_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); } - static void jcv_sortedges_insert(jcv_site* site, jcv_graphedge* edge) + static void jcv_sortedges_insert(jcv_site* site, jcv_graphedge* edge) { // Special case for the head end - jcv_graphedge* prev = 0; + jcv_graphedge* prev = 0; if (site->edges == 0 || site->edges->angle >= edge->angle) { edge->next = site->edges; @@ -1028,7 +1029,7 @@ namespace jc else { // Locate the node before the point of insertion - jcv_graphedge* current = site->edges; + jcv_graphedge* current = site->edges; while(current->next != 0 && current->next->angle < edge->angle) { current = current->next; @@ -1049,20 +1050,20 @@ namespace jc } } - static void jcv_finishline(jcv_context_internal* internal, jcv_edge* e) + static void jcv_finishline(jcv_context_internal* internal, edge* e) { - if( !jcv_edge_clipline(internal, e) ) { + if( !edge_clipline(internal, e) ) { return; } // Make sure the graph edges are CCW - int flip = jcv_determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (jcv_real)0 ? 0 : 1; + int flip = jcv_determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (T)0 ? 0 : 1; for( int i = 0; i < 2; ++i ) { - jcv_graphedge* ge = jcv_alloc_graphedge(internal); + jcv_graphedge* ge = jcv_alloc_graphedge(internal); - ge->edge = e; + ge->edge_ = e; ge->next = 0; ge->neighbor = e->sites[1-i]; ge->pos[flip] = e->pos[i]; @@ -1074,7 +1075,7 @@ namespace jc } - static void jcv_endpos(jcv_context_internal* internal, jcv_edge* e, const jcv_point* p, int direction) + static void jcv_endpos(jcv_context_internal* internal, edge* e, const jcv_point* p, int direction) { e->pos[direction] = *p; @@ -1084,7 +1085,7 @@ namespace jc jcv_finishline(internal, e); } - static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) + static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) { gap->neighbor = 0; gap->pos[0] = current->pos[1]; @@ -1113,9 +1114,9 @@ namespace jc gap->angle = jcv_calc_sort_metric(site, gap); } - static jcv_edge* jcv_create_gap_edge(jcv_context_internal* internal, jcv_site* site, jcv_graphedge* ge) + static edge* jcv_create_gap_edge(jcv_context_internal* internal, jcv_site* site, jcv_graphedge* ge) { - jcv_edge* edge = jcv_alloc_edge(internal); + edge* edge = jcv_alloc_edge(internal); edge->pos[0] = ge->pos[0]; edge->pos[1] = ge->pos[1]; edge->sites[0] = site; @@ -1126,34 +1127,34 @@ namespace jc return edge; } - static void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* site) + static void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* site) { // They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap - jcv_graphedge* current = site->edges; + jcv_graphedge* current = site->edges; if( !current ) { // No edges, then it should be a single cell assert( allocator->numsites == 1 ); - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = clipper->min; gap->pos[1][0] = clipper->max[0]; gap->pos[1][1] = clipper->min[1]; gap->angle = jcv_calc_sort_metric(site, gap); gap->next = 0; - gap->edge = jcv_create_gap_edge(allocator, site, gap); + gap->edge_ = jcv_create_gap_edge(allocator, site, gap); current = gap; site->edges = gap; } - jcv_graphedge* next = current->next; + jcv_graphedge* next = current->next; if( !next ) { - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); jcv_create_corner_edge(allocator, site, current, gap); - gap->edge = jcv_create_gap_edge(allocator, site, gap); + gap->edge_ = jcv_create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1176,19 +1177,19 @@ namespace jc if (current_edge_flags & next_edge_flags) { // Current and Next on the same border - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = next->pos[0]; gap->angle = jcv_calc_sort_metric(site, gap); - gap->edge = jcv_create_gap_edge(allocator, site, gap); + gap->edge_ = jcv_create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; } else { // Current and Next on different borders - int corner_flag = jcv_edge_flags_to_corner(current_edge_flags); + int corner_flag = edge_flags_to_corner(current_edge_flags); if (corner_flag) { // we are already at one corner, so we need to find the next one @@ -1198,20 +1199,20 @@ namespace jc { // we are on the middle of a border // we need to find the adjacent corner, following the borders CCW - if (current_edge_flags == JCV_EDGE_TOP) { corner_flag = JCV_CORNER_TOP_LEFT; } - else if (current_edge_flags == JCV_EDGE_LEFT) { corner_flag = JCV_CORNER_BOTTOM_LEFT; } - else if (current_edge_flags == JCV_EDGE_BOTTOM) { corner_flag = JCV_CORNER_BOTTOM_RIGHT; } - else if (current_edge_flags == JCV_EDGE_RIGHT) { corner_flag = JCV_CORNER_TOP_RIGHT; } + if (current_edge_flags == EDGE_TOP) { corner_flag = JCV_CORNER_TOP_LEFT; } + else if (current_edge_flags == EDGE_LEFT) { corner_flag = JCV_CORNER_BOTTOM_LEFT; } + else if (current_edge_flags == EDGE_BOTTOM) { corner_flag = JCV_CORNER_BOTTOM_RIGHT; } + else if (current_edge_flags == EDGE_RIGHT) { corner_flag = JCV_CORNER_TOP_RIGHT; } } - jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max); + jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max); - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + jcv_graphedge* gap = jcv_alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = corner; gap->angle = jcv_calc_sort_metric(site, gap); - gap->edge = jcv_create_gap_edge(allocator, site, gap); + gap->edge_ = jcv_create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1230,33 +1231,33 @@ namespace jc // Since the algorithm leaves gaps at the borders/corner, we want to fill them - static void jcv_fillgaps(jcv_diagram* diagram) + static void jcv_fillgaps(jcv_diagram* diagram) { - jcv_context_internal* internal = diagram->internal; + jcv_context_internal* internal = diagram->internal; if (!internal->clipper.fill_fn) return; for( int i = 0; i < internal->numsites; ++i ) { - jcv_site* site = &internal->sites[i]; + jcv_site* site = &internal->sites[i]; internal->clipper.fill_fn(&internal->clipper, internal, site); } } - static void jcv_circle_event(jcv_context_internal* internal) + static void jcv_circle_event(jcv_context_internal* internal) { - jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue); + jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue); - jcv_halfedge* leftleft = left->left; - jcv_halfedge* right = left->right; - jcv_halfedge* rightright= right->right; - jcv_site* bottom = jcv_halfedge_leftsite(left); - jcv_site* top = jcv_halfedge_rightsite(right); + jcv_halfedge* leftleft = left->left; + jcv_halfedge* right = left->right; + jcv_halfedge* rightright= right->right; + jcv_site* bottom = jcv_halfedge_leftsite(left); + jcv_site* top = jcv_halfedge_rightsite(right); - jcv_point vertex = left->vertex; - jcv_endpos(internal, left->edge, &vertex, left->direction); - jcv_endpos(internal, right->edge, &vertex, right->direction); + jcv_point vertex = left->vertex; + jcv_endpos(internal, left->edge_, &vertex, left->direction); + jcv_endpos(internal, right->edge_, &vertex, right->direction); internal->last_inserted = rightright; @@ -1269,21 +1270,21 @@ namespace jc int direction = JCV_DIRECTION_LEFT; if( bottom->p[1] > top->p[1] ) { - jcv_site* temp = bottom; + jcv_site* temp = bottom; bottom = top; top = temp; direction = JCV_DIRECTION_RIGHT; } - jcv_edge* edge = jcv_edge_new(internal, bottom, top); + edge* edge = edge_new(internal, bottom, top); edge->next = internal->edges; internal->edges = edge; - jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction); + jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction); jcv_halfedge_link(leftleft, he); jcv_endpos(internal, edge, &vertex, JCV_DIRECTION_RIGHT - direction); - jcv_point p; + jcv_point p; if( jcv_check_circle_event( leftleft, he, &p ) ) { jcv_pq_remove(internal->eventqueue, leftleft); @@ -1305,7 +1306,7 @@ namespace jc void** voidpp; } jcv_cast_align_struct; - static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) + static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) { rect->min[0] = std::min(rect->min[0], p->x()); rect->min[1] = std::min(rect->min[1], p->y()); @@ -1313,7 +1314,7 @@ namespace jc rect->max[1] = std::max(rect->max[1], p->y()); } - static void jcv_rect_round(jcv_rect* rect) + static void jcv_rect_round(jcv_rect* rect) { rect->min[0] = std::floor(rect->min[0]); rect->min[1] = std::floor(rect->min[1]); @@ -1321,7 +1322,7 @@ namespace jc rect->max[1] = std::ceil(rect->max[1]); } - static void jcv_rect_inflate(jcv_rect* rect, jcv_real amount) + static void jcv_rect_inflate(jcv_rect* rect, T amount) { rect->min[0] -= amount; rect->min[1] -= amount; @@ -1329,20 +1330,20 @@ namespace jc rect->max[1] += amount; } - static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) + static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) { int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + jcv_site* sites = internal->sites; - jcv_rect r; - r.min[0] = r.min[1] = std::numeric_limits::max(); - r.max[0] = r.max[1] = std::numeric_limits::lowest(); + jcv_rect r; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; // Prune duplicates first for (int i = 0; i < num_sites; i++) { - const jcv_site* s = &sites[i]; + const jcv_site* s = &sites[i]; // Remove duplicates, to avoid anomalies if( i > 0 && jcv_point_eq(&s->p, &sites[i - 1].p) ) { @@ -1361,19 +1362,19 @@ namespace jc return offset; } - static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect) + static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect) { int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + jcv_site* sites = internal->sites; - jcv_rect r; - r.min[0] = r.min[1] = std::numeric_limits::max(); - r.max[0] = r.max[1] = std::numeric_limits::lowest(); + jcv_rect r; + r.min[0] = r.min[1] = std::numeric_limits::max(); + r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; for (int i = 0; i < num_sites; i++) { - const jcv_site* s = &sites[i]; + const jcv_site* s = &sites[i]; if (!internal->clipper.test_fn(&internal->clipper, s->p)) { @@ -1392,14 +1393,14 @@ namespace jc return offset; } - static jcv_context_internal* jcv_alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) + static jcv_context_internal* jcv_alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) { // Interesting limits from Euler's equation // Slide 81: https://courses.cs.washington.edu/courses/csep521/01au/lectures/lecture10slides.pdf // Page 3: https://sites.cs.ucsb.edu/~suri/cs235/Voronoi.pdf size_t eventssize = (size_t)(num_points*2) * sizeof(void*); // beachline can have max 2*n-5 parabolas - size_t sitessize = (size_t)num_points * sizeof(jcv_site); - size_t memsize = sizeof(jcv_priorityqueue) + eventssize + sitessize + sizeof(jcv_context_internal) + 16u; // 16 bytes padding for alignment + size_t sitessize = (size_t)num_points * sizeof(jcv_site); + size_t memsize = sizeof(jcv_priorityqueue) + eventssize + sitessize + sizeof(jcv_context_internal) + 16u; // 16 bytes padding for alignment char* originalmem = (char*)allocfn(userallocctx, memsize); memset(originalmem, 0, memsize); @@ -1407,15 +1408,15 @@ namespace jc // align memory char* mem = (char*)jcv_align(originalmem, sizeof(void*)); - jcv_context_internal* internal = (jcv_context_internal*)mem; - mem += sizeof(jcv_context_internal); + jcv_context_internal* internal = (jcv_context_internal*)mem; + mem += sizeof(jcv_context_internal); internal->mem = originalmem; internal->memctx = userallocctx; internal->alloc = allocfn; internal->free = freefn; mem = (char*)jcv_align(mem, sizeof(void*)); - internal->sites = (jcv_site*) mem; + internal->sites = (jcv_site*) mem; mem += sitessize; mem = (char*)jcv_align(mem, sizeof(void*)); @@ -1433,12 +1434,12 @@ namespace jc } // This version of jcv_diagram_generate allows the client to use a custom allocator - static void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* d) + static void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* d) { if( d->internal ) jcv_diagram_free( d ); - jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn); + jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn); internal->beachline_start = jcv_halfedge_new(internal, 0, 0); internal->beachline_end = jcv_halfedge_new(internal, 0, 0); @@ -1454,7 +1455,7 @@ namespace jc jcv_pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); internal->numsites = num_points; - jcv_site* sites = internal->sites; + jcv_site* sites = internal->sites; for( int i = 0; i < num_points; ++i ) { @@ -1463,21 +1464,21 @@ namespace jc sites[i].index = i; } - qsort(sites, (size_t)num_points, sizeof(jcv_site), jcv_point_cmp); + qsort(sites, (size_t)num_points, sizeof(jcv_site), jcv_point_cmp); - jcv_clipper box_clipper; + jcv_clipper box_clipper; if (clipper == 0) { // model->get_shaderprogs = &mplot::VisualBase::get_shaderprogs; - box_clipper.test_fn = &jc::voronoi::jcv_boxshape_test; - box_clipper.clip_fn = &jc::voronoi::jcv_boxshape_clip; - box_clipper.fill_fn = &jc::voronoi::jcv_boxshape_fillgaps; + box_clipper.test_fn = &jc::manager::jcv_boxshape_test; + box_clipper.clip_fn = &jc::manager::jcv_boxshape_clip; + box_clipper.fill_fn = &jc::manager::jcv_boxshape_fillgaps; clipper = &box_clipper; } internal->clipper = *clipper; - jcv_rect tmp_rect; - tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); - tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); + jcv_rect tmp_rect; + tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); + tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); jcv_prune_duplicates(internal, &tmp_rect); // Prune using the test second @@ -1511,15 +1512,15 @@ namespace jc internal->bottomsite = jcv_nextsite(internal); jcv_priorityqueue* pq = internal->eventqueue; - jcv_site* site = jcv_nextsite(internal); + jcv_site* site = jcv_nextsite(internal); int finished = 0; while( !finished ) { - jcv_point lowest_pq_point; + jcv_point lowest_pq_point; if( !jcv_pq_empty(pq) ) { - jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq); + jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq); lowest_pq_point[0] = he->vertex[0]; lowest_pq_point[1] = he->y; } @@ -1539,9 +1540,9 @@ namespace jc } } - for( jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) + for( jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) { - jcv_finishline(internal, he->edge); + jcv_finishline(internal, he->edge_); } jcv_fillgaps(d); @@ -1553,16 +1554,16 @@ namespace jc * If rect is null, an automatic bounding box is calculated, with an extra padding of 10 units * All points will be culled against the bounding rect, and all edges will be clipped against it. */ - static void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* d ) + static void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* d ) { jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); } // User API - void jcv_diagram_generate (const std::vector>& centres) + void diagram_generate (const std::vector>& centres) { int ncoords = static_cast(centres.size()); - sm::range rx, ry; + sm::range rx, ry; rx.search_init(); ry.search_init(); for (int i = 0; i < ncoords ; ++i) { @@ -1570,13 +1571,13 @@ namespace jc ry.update (centres[i][1]); } // Have to actually new the diagram! - this->diagram = new jc::jcv_diagram; - std::memset (this->diagram, 0, sizeof(jc::jcv_diagram)); + this->diagram = new jc::jcv_diagram; + std::memset (this->diagram, 0, sizeof(jc::jcv_diagram)); this->domain = { - jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} }; - jc::voronoi::jcv_diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); + jc::manager::jcv_diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); } int diagram_numsites() const @@ -1587,13 +1588,13 @@ namespace jc } // User-configurable border width - jcv_real border_width = std::numeric_limits::epsilon(); + T border_width = std::numeric_limits::epsilon(); private: // Our diagram - jc::jcv_diagram* diagram = nullptr; + jc::jcv_diagram* diagram = nullptr; // A domain for the diagram. - jc::jcv_rect domain = {}; + jc::jcv_rect domain = {}; }; // end struct jcv } // namespace @@ -1610,7 +1611,7 @@ namespace jc More robust removal of duplicate graph edges Added iterator for Delauney edges 0.7 2019-10-25 - Added support for clipping against convex polygons - - Added JCV_EDGE_INTERSECT_THRESHOLD for edge intersections + - Added EDGE_INTERSECT_THRESHOLD for edge intersections - Fixed issue where the bounds calculation wasn’t considering all points 0.6 2018-10-21 - Removed JCV_CEIL/JCV_FLOOR/JCV_FABS - Optimizations: Fewer indirections, better beach head approximation @@ -1676,8 +1677,8 @@ namespace jc void jcv_diagram_free( jcv_diagram* diagram ); const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ); - const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ); - const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ); + const edge* jcv_diagram_get_edges( const jcv_diagram* diagram ); + const edge* jcv_diagram_get_next_edge( const edge* edge ); An example usage: @@ -1704,7 +1705,7 @@ namespace jc void draw_edges(const jcv_diagram* diagram) { // If all you need are the edges - const jcv_edge* edge = jcv_diagram_get_edges( diagram ); + const edge* edge = jcv_diagram_get_edges( diagram ); while( edge ) { draw_line(edge->pos[0], edge->pos[1]); diff --git a/mplot/jcvoronoi/jc_voronoi_clip.h b/mplot/jcvoronoi/jc_voronoi_clip.h index 7f0a6087..1a2a9fa4 100644 --- a/mplot/jcvoronoi/jc_voronoi_clip.h +++ b/mplot/jcvoronoi/jc_voronoi_clip.h @@ -1,3 +1,6 @@ +// Note: This will need to be brought in-line with changes in jc_voronoi.h made as part of Seb's +// mathplot work. + // Copyright (c) 2019 Mathias Westerdahl // For full LICENSE (MIT) or USAGE, see bottom of file From e926fa8ad7b322c3abcfd34872c4f08ae2776104 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 14:46:56 +0000 Subject: [PATCH 34/41] More refcatoring --- mplot/VoronoiVisual.h | 66 +-- mplot/jcvoronoi/jc_voronoi.h | 904 +++++++++++++++++------------------ 2 files changed, 476 insertions(+), 494 deletions(-) diff --git a/mplot/VoronoiVisual.h b/mplot/VoronoiVisual.h index 9cb4e92a..8da3c7a6 100644 --- a/mplot/VoronoiVisual.h +++ b/mplot/VoronoiVisual.h @@ -56,7 +56,7 @@ namespace mplot { //! Compute 2.5D Voronoi diagram using code adapted from // https://github.com/JCash/voronoi. The adaptation is to add a third dimension - // to jcv_point. + // to point. void initializeVertices() { unsigned int ncoords = this->dataCoords == nullptr ? 0 : this->dataCoords->size(); @@ -100,12 +100,12 @@ namespace mplot { } // Generate the 2D Voronoi diagram - jc::manager vd; - vd.border_width = this->border_width; - vd.diagram_generate (*(dcoords_ptr)); + jcv::manager vorman; + vorman.border_width = this->border_width; + vorman.diagram_generate (*(dcoords_ptr)); // We obtain access to the Voronoi cell sites: - const jc::jcv_site* sites = vd.diagram_get_sites(); + const jcv::site* sites = vorman.diagram_get_sites(); // Now scan through the Voronoi cell 'sites' and 'edges' to re-assign z // values in the edges. This is not going to be particularly efficient, but @@ -124,14 +124,14 @@ namespace mplot { // Mapping same edge end-point locations to the averate z value of the adjacent cell centres std::map, float, veccmp> edge_end_zsums; - for (int i = 0; i < vd.diagram_numsites(); ++i) { + for (int i = 0; i < vorman.diagram_numsites(); ++i) { // We have the current edge_1, the next edge_2 and the previous edge_0 - const jc::jcv_site* site = &sites[i]; - jc::jcv_graphedge* edge_first = site->edges; // The very first edge - jc::jcv_graphedge* edge_1 = edge_first; - jc::jcv_graphedge* edge_2 = edge_first; - jc::jcv_graphedge* edge_0 = edge_first; + const jcv::site* site = &sites[i]; + jcv::graphedge* edge_first = site->edges; // The very first edge + jcv::graphedge* edge_1 = edge_first; + jcv::graphedge* edge_2 = edge_first; + jcv::graphedge* edge_0 = edge_first; while (edge_0->next) { edge_0 = edge_0->next; } while (edge_1) { @@ -186,9 +186,9 @@ namespace mplot { } // Now go through edge_end_zsums and edges and update z values - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - jc::jcv_graphedge* edge_1 = site->edges; // The very first edge + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + jcv::graphedge* edge_1 = site->edges; // The very first edge while (edge_1) { // For each edge, set z from the map float zsum0 = 0.0f; @@ -222,9 +222,9 @@ namespace mplot { sm::vec t1 = {0.0f}; sm::vec t2 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; unsigned int site_triangles = 0; while (e) { // NB: There are 3 each of pos/col/norm vertices (and 3 indices) per @@ -243,9 +243,9 @@ namespace mplot { } } else { // No need to inverse rotate - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; unsigned int site_triangles = 0; while (e) { this->computeTriangle (site->p, e->pos[0], e->pos[1], this->setColour(site->index)); @@ -257,7 +257,7 @@ namespace mplot { this->triangle_count_sum += site_triangles; } } - if (static_cast(vd.diagram_numsites()) != ncoords) { + if (static_cast(vorman.diagram_numsites()) != ncoords) { std::cout << "WARNING: numsites != ncoords ?!?!\n"; } @@ -269,9 +269,9 @@ namespace mplot { sm::vec t0 = {0.0f}; sm::vec t1 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; while (e) { t0 = rqinv * (e->pos[0] * this->zoom); t1 = rqinv * (e->pos[1] * this->zoom); @@ -282,9 +282,9 @@ namespace mplot { } else { // No rotations required - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; while (e) { this->computeTube (e->pos[0] * this->zoom, e->pos[1] * this->zoom, mplot::colour::royalblue, mplot::colour::goldenrod2, this->voronoi_grid_thickness, 12); @@ -301,9 +301,9 @@ namespace mplot { sm::vec t1 = {0.0f}; sm::quaternion rqinv = rq.invert(); - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; while (e) { t0 = rqinv * sm::vec{ e->pos[0].x() * this->zoom, e->pos[0].y() * this->zoom, 0.0f }; t1 = rqinv * sm::vec{ e->pos[1].x() * this->zoom, e->pos[1].y() * this->zoom, 0.0f }; @@ -314,9 +314,9 @@ namespace mplot { } else { // Show the 2D Voronoi diagram's edges at z=0 - for (int i = 0; i < vd.diagram_numsites(); ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites(); ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; while (e) { this->computeTube ({ e->pos[0].x() * this->zoom, e->pos[0].y() * this->zoom, 0.0f }, { e->pos[1].x() * this->zoom, e->pos[1].y() * this->zoom, 0.0f }, diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 5491d235..5a3d9bfc 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -21,22 +21,22 @@ #define JCV_EDGE_INTERSECT_THRESHOLD 1.0e-10F #endif -namespace jc +namespace jcv { #pragma pack(push, 1) template - using jcv_point = sm::vec; + using point = sm::vec; // fwd declar graphpedge - template struct jcv_graphedge; + template struct graphedge; template - struct jcv_site + struct site { - jcv_point p; - int index; // Index into the original list of points - jcv_graphedge* edges; // The half edges owned by the cell + point p; + int index; // Index into the original list of points + graphedge* edges; // The half edges owned by the cell }; // The coefficients a, b and c are from the general line equation: ax * by + c = 0 @@ -44,155 +44,139 @@ namespace jc struct edge { struct edge* next; - jcv_site* sites[2]; - jcv_point pos[2]; + site* sites[2]; + point pos[2]; T a; T b; T c; }; template - struct jcv_graphedge + struct graphedge { - struct jcv_graphedge* next; + struct graphedge* next; struct edge* edge_; - struct jcv_site* neighbor; - jcv_point pos[2]; - T angle; + struct site* neighbor; + point pos[2]; + T angle; }; template - struct jcv_delauney_iter + struct delauney_iter { const edge* sentinel; const edge* current; }; template - struct jcv_delauney_edge + struct delauney_edge { - const edge* edge_; // The voronoi edge separating the two sites - const jcv_site* sites[2]; - jcv_point pos[2]; // the positions of the two sites + const edge* edge_; // The voronoi edge separating the two sites + const site* sites[2]; + point pos[2]; // the positions of the two sites }; template - struct jcv_rect + struct rect { - jcv_point min; - jcv_point max; + point min; + point max; }; - // Convert these to templated usings? or use std::function? - /// Tests if a point is inside the final shape - //typedef int (*jcv_clip_test_point_fn)(const jcv_clipper* clipper, const jcv_point p); - //template - - /** Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] - * Returns 0 if not successful - */ - //typedef int (*jcv_clip_edge_fn)(const jcv_clipper* clipper, edge* e); - - /** Given the clipper, the site and the last edge, - * closes any gaps in the polygon by adding new edges that follow the bounding shape - * The internal context is use when allocating new edges. - */ - //typedef void (*jcv_clip_fillgap_fn)(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* s); - - // Forward declare jcv_context_internal for the std::function - template struct jcv_context_internal; + // Forward declare context_internal for the std::function + template struct context_internal; template - struct jcv_clipper + struct clipper { // Tests if a point is inside the final shape - std::function* clipper, const jcv_point p)> test_fn; + std::function* _clipper, const point p)> test_fn; // Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] // Returns 0 if not successful - std::function* clipper, edge* e)> clip_fn; + std::function* _clipper, edge* e)> clip_fn; // Given the clipper, the site and the last edge, // closes any gaps in the polygon by adding new edges that follow the bounding shape // The internal context is use when allocating new edges. - std::function* clipper, jcv_context_internal* allocator, jcv_site* s)> fill_fn; - jcv_point min; // The bounding rect min - jcv_point max; // The bounding rect max - void* ctx; // User defined context + std::function* _clipper, context_internal* allocator, site* s)> fill_fn; + point min; // The bounding rect min + point max; // The bounding rect max + void* ctx; // User defined context }; // Second batch of structs template - struct jcv_halfedge + struct halfedge { - edge* edge_; - struct jcv_halfedge* left; - struct jcv_halfedge* right; - jcv_point vertex; - T y; - int direction; // 0=left, 1=right - int pqpos; + edge* edge_; + struct halfedge* left; + struct halfedge* right; + point vertex; + T y; + int direction; // 0=left, 1=right + int pqpos; }; - struct jcv_memoryblock + struct memoryblock { size_t sizefree; - struct jcv_memoryblock* next; + struct memoryblock* next; char* memory; }; typedef int (*FJCVPriorityQueuePrint)(const void* node, int pos); - struct jcv_priorityqueue + struct priorityqueue { // Implements a binary heap - int maxnumitems; - int numitems; - void** items; + int maxnumitems; + int numitems; + void** items; }; using FJCVAllocFn = void*(void* userctx, size_t size); using FJCVFreeFn = void(void* userctx, void* p); template - struct jcv_context_internal + struct context_internal { - void* mem; + void* mem; edge* edges; - jcv_halfedge* beachline_start; - jcv_halfedge* beachline_end; - jcv_halfedge* last_inserted; - jcv_priorityqueue* eventqueue; - - jcv_site* sites; - jcv_site* bottomsite; - int numsites; - int currentsite; - int _padding; - - jcv_memoryblock* memblocks; + halfedge* beachline_start; + halfedge* beachline_end; + halfedge* last_inserted; + priorityqueue* eventqueue; + + site* sites; + site* bottomsite; + int numsites; + int currentsite; + int _padding; + + memoryblock* memblocks; edge* edgepool; - jcv_halfedge* halfedgepool; - void** eventmem; - jcv_clipper clipper; + halfedge* halfedgepool; + void** eventmem; + clipper clipper_; void* memctx; // Given by the user std::function alloc; std::function free; - jcv_rect rect; + rect rect_; }; template - struct jcv_diagram + struct diagram { - jcv_context_internal* internal; - int numsites; - jcv_point min; - jcv_point max; + context_internal* internal; + int numsites; + point min; + point max; }; #pragma pack(pop) - // The mananger class. Type T is what is called jcv_real in the original code + // The mananger class. Type T is what is called real in the original code template requires std::is_floating_point_v struct manager { @@ -200,7 +184,7 @@ namespace jc ~manager() { if (this->diagram) { - jc::manager::jcv_diagram_free (this->diagram); + jcv::manager::diagram_free (this->diagram); delete this->diagram; } } @@ -209,10 +193,10 @@ namespace jc // INTERNAL FUNCTIONS - static const int JCV_DIRECTION_LEFT = 0; - static const int JCV_DIRECTION_RIGHT = 1; + static const int DIRECTION_LEFT = 0; + static const int DIRECTION_RIGHT = 1; - static constexpr T jcv_invalid_value = std::numeric_limits::lowest(); + static constexpr T invalid_value = std::numeric_limits::lowest(); // App specific equality static int T_eq(T a, T b) @@ -220,26 +204,26 @@ namespace jc return std::abs(a - b) < std::numeric_limits::epsilon(); } - // jcv_point - static int jcv_point_cmp(const void* p1, const void* p2) + // point + static int point_cmp(const void* p1, const void* p2) { - const jcv_point* s1 = static_cast*>(p1); - const jcv_point* s2 = static_cast*>(p2); + const point* s1 = static_cast*>(p1); + const point* s2 = static_cast*>(p2); return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); } - static int jcv_point_less (const jcv_point* pt1, const jcv_point* pt2 ) + static int point_less (const point* pt1, const point* pt2 ) { return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); } - static int jcv_point_eq( const jcv_point* pt1, const jcv_point* pt2 ) + static int point_eq( const point* pt1, const point* pt2 ) { return T_eq(pt1->y(), pt2->y()) && T_eq(pt1->x(), pt2->x()); } [[maybe_unused]] - static int jcv_point_on_box_edge( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + static int point_on_box_edge( const point* pt, const point* min, const point* max ) { return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); } @@ -250,13 +234,13 @@ namespace jc static const int EDGE_BOTTOM = 4; static const int EDGE_TOP = 8; - static const int JCV_CORNER_NONE = 0; - static const int JCV_CORNER_TOP_LEFT = 1; - static const int JCV_CORNER_BOTTOM_LEFT = 2; - static const int JCV_CORNER_BOTTOM_RIGHT = 3; - static const int JCV_CORNER_TOP_RIGHT = 4; + static const int CORNER_NONE = 0; + static const int CORNER_TOP_LEFT = 1; + static const int CORNER_BOTTOM_LEFT = 2; + static const int CORNER_BOTTOM_RIGHT = 3; + static const int CORNER_TOP_RIGHT = 4; - static int jcv_get_edge_flags( const jcv_point* pt, const jcv_point* min, const jcv_point* max ) + static int get_edge_flags( const point* pt, const point* min, const point* max ) { int flags = 0; if (pt->x() == min->x()) flags |= EDGE_LEFT; @@ -269,53 +253,53 @@ namespace jc static int edge_flags_to_corner(int edge_flags) { #define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL - TEST_FLAGS(EDGE_TOP|EDGE_LEFT, JCV_CORNER_TOP_LEFT); - TEST_FLAGS(EDGE_TOP|EDGE_RIGHT, JCV_CORNER_TOP_RIGHT); - TEST_FLAGS(EDGE_BOTTOM|EDGE_LEFT, JCV_CORNER_BOTTOM_LEFT); - TEST_FLAGS(EDGE_BOTTOM|EDGE_RIGHT, JCV_CORNER_BOTTOM_RIGHT); + TEST_FLAGS(EDGE_TOP|EDGE_LEFT, CORNER_TOP_LEFT); + TEST_FLAGS(EDGE_TOP|EDGE_RIGHT, CORNER_TOP_RIGHT); + TEST_FLAGS(EDGE_BOTTOM|EDGE_LEFT, CORNER_BOTTOM_LEFT); + TEST_FLAGS(EDGE_BOTTOM|EDGE_RIGHT, CORNER_BOTTOM_RIGHT); #undef TEST_FLAGS return 0; } - [[maybe_unused]] static int jcv_is_corner(int corner) { return corner != 0; } + [[maybe_unused]] static int is_corner(int corner) { return corner != 0; } - static int jcv_corner_rotate_90(int corner) + static int corner_rotate_90(int corner) { corner--; corner = (corner+1)%4; return corner + 1; } - static jcv_point jcv_corner_to_point(int corner, const jcv_point* min, const jcv_point* max ) + static point corner_to_point(int corner, const point* min, const point* max ) { - jcv_point p; - if (corner == JCV_CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } - else if (corner == JCV_CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } - else if (corner == JCV_CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } - else if (corner == JCV_CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } - else { p[0] = jcv_invalid_value; p[1] = jcv_invalid_value; } + point p; + if (corner == CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } + else if (corner == CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } + else if (corner == CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } + else if (corner == CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } + else { p[0] = invalid_value; p[1] = invalid_value; } return p; } - static T jcv_point_dist_sq( const jcv_point* pt1, const jcv_point* pt2) + static T point_dist_sq( const point* pt1, const point* pt2) { T diffx = pt1->x() - pt2->x(); T diffy = pt1->y() - pt2->y(); return diffx * diffx + diffy * diffy; } - static T jcv_point_dist( const jcv_point* pt1, const jcv_point* pt2 ) + static T point_dist( const point* pt1, const point* pt2 ) { - return std::sqrt (jcv_point_dist_sq (pt1, pt2)); + return std::sqrt (point_dist_sq (pt1, pt2)); } // Uses free (or the registered custom free function) - static void jcv_diagram_free( jcv_diagram* d ) + static void diagram_free( diagram* d ) { - jcv_context_internal* internal = d->internal; + context_internal* internal = d->internal; void* memctx = internal->memctx; while(internal->memblocks) { - jcv_memoryblock* p = internal->memblocks; + memoryblock* p = internal->memblocks; internal->memblocks = internal->memblocks->next; internal->free( memctx, p ); } @@ -324,26 +308,26 @@ namespace jc } // Returns an array of sites, where each index is the same as the original input point array. - static const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ) + static const site* diagram_get_sites( const diagram* diagram ) { return diagram->internal->sites; } // User API - const jcv_site* diagram_get_sites() + const site* diagram_get_sites() { - const jcv_site* sites = nullptr; + const site* sites = nullptr; if (this->diagram) { - sites = jcv_diagram_get_sites (this->diagram); + sites = diagram_get_sites (this->diagram); } return sites; } // Iterates over a list of edges, skipping invalid edges (where p0==p1) - const edge* jcv_diagram_get_next_edge( const edge* _edge ) + const edge* diagram_get_next_edge( const edge* _edge ) { const edge* e = _edge->next; - while (e != 0 && jcv_point_eq(&e->pos[0], &e->pos[1])) { + while (e != 0 && point_eq(&e->pos[0], &e->pos[1])) { e = e->next; } return e; @@ -352,22 +336,22 @@ namespace jc // Returns a linked list of all the voronoi edges excluding the ones that lie on the borders of // the bounding box. For a full list of edges, you need to iterate over the sites, and their // graph edges. - const edge* jcv_diagram_get_edges( const jcv_diagram* diagram ) + const edge* diagram_get_edges( const diagram* diagram ) { edge e; e.next = diagram->internal->edges; - return jcv_diagram_get_next_edge(&e); + return diagram_get_next_edge(&e); } // Creates an iterator over the delauney edges of a voronoi diagram - void jcv_delauney_begin( const jcv_diagram* diagram, jcv_delauney_iter* iter ) + void delauney_begin( const diagram* diagram, delauney_iter* iter ) { iter->current = 0; - iter->sentinel = jcv_diagram_get_edges(diagram); + iter->sentinel = diagram_get_edges(diagram); } // Steps the iterator and returns the next edge Returns 0 when there are no more edges - int jcv_delauney_next( jcv_delauney_iter* iter, jcv_delauney_edge* next ) + int delauney_next( delauney_iter* iter, delauney_edge* next ) { if (iter->sentinel) { @@ -379,12 +363,12 @@ namespace jc // However, the result looks less relevant to the cells contained within the bounding box // E.g. some cells that look isolated from each other, suddenly still are connected, // because they share an edge outside of the bounding box - iter->current = jcv_diagram_get_next_edge(iter->current); + iter->current = diagram_get_next_edge(iter->current); } while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0)) { - iter->current = jcv_diagram_get_next_edge(iter->current); + iter->current = diagram_get_next_edge(iter->current); } if (!iter->current) @@ -398,80 +382,80 @@ namespace jc return 1; } - static void* jcv_align(void* value, size_t alignment) + static void* align(void* value, size_t alignment) { return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); } - static void* jcv_alloc(jcv_context_internal* internal, size_t size) + static void* alloc(context_internal* internal, size_t size) { if( !internal->memblocks || internal->memblocks->sizefree < (size+sizeof(void*)) ) { size_t blocksize = 16 * 1024; - jcv_memoryblock* block = (jcv_memoryblock*)internal->alloc( internal->memctx, blocksize ); - size_t offset = sizeof(jcv_memoryblock); + memoryblock* block = (memoryblock*)internal->alloc( internal->memctx, blocksize ); + size_t offset = sizeof(memoryblock); block->sizefree = blocksize - offset; block->next = internal->memblocks; block->memory = ((char*)block) + offset; internal->memblocks = block; } void* p_raw = internal->memblocks->memory; - void* p_aligned = jcv_align(p_raw, sizeof(void*)); + void* p_aligned = align(p_raw, sizeof(void*)); size += (uintptr_t)p_aligned - (uintptr_t)p_raw; internal->memblocks->memory += size; internal->memblocks->sizefree -= size; return p_aligned; } - static edge* jcv_alloc_edge(jcv_context_internal* internal) + static edge* alloc_edge(context_internal* internal) { - return (edge*)jcv_alloc(internal, sizeof(edge)); + return (edge*)alloc(internal, sizeof(edge)); } - static jcv_halfedge* jcv_alloc_halfedge(jcv_context_internal* internal) + static halfedge* alloc_halfedge(context_internal* internal) { if( internal->halfedgepool ) { - jcv_halfedge* edge = internal->halfedgepool; + halfedge* edge = internal->halfedgepool; internal->halfedgepool = internal->halfedgepool->right; return edge; } - return (jcv_halfedge*)jcv_alloc(internal, sizeof(jcv_halfedge)); + return (halfedge*)alloc(internal, sizeof(halfedge)); } - static jcv_graphedge* jcv_alloc_graphedge(jcv_context_internal* internal) + static graphedge* alloc_graphedge(context_internal* internal) { - return (jcv_graphedge*)jcv_alloc(internal, sizeof(jcv_graphedge)); + return (graphedge*)alloc(internal, sizeof(graphedge)); } - static void* jcv_alloc_fn(void* memctx, size_t size) + static void* alloc_fn(void* memctx, size_t size) { (void)memctx; return malloc(size); } - static void jcv_free_fn(void* memctx, void* p) + static void free_fn(void* memctx, void* p) { (void)memctx; free(p); } // edge methods - static int jcv_is_valid(const jcv_point* p) + static int is_valid(const point* p) { - return (p->x() != jcv_invalid_value || p->y() != jcv_invalid_value) ? 1 : 0; + return (p->x() != invalid_value || p->y() != invalid_value) ? 1 : 0; } - static void edge_create(edge* e, jcv_site* s1, jcv_site* s2) + static void edge_create(edge* e, site* s1, site* s2) { e->next = 0; e->sites[0] = s1; e->sites[1] = s2; - e->pos[0][0] = jcv_invalid_value; - e->pos[0][1] = jcv_invalid_value; - e->pos[1][0] = jcv_invalid_value; - e->pos[1][1] = jcv_invalid_value; + e->pos[0][0] = invalid_value; + e->pos[0][1] = invalid_value; + e->pos[1][0] = invalid_value; + e->pos[1][1] = invalid_value; // Create line equation between S1 and S2: // T a = -1 * (s2->p[1] - s1->p[1]); @@ -510,7 +494,7 @@ namespace jc } // CLIPPING - static int jcv_boxshape_test(const jcv_clipper* clipper, const jcv_point p) + static int boxshape_test(const clipper* clipper, const point p) { return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] && p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; @@ -518,7 +502,7 @@ namespace jc // The line equation: ax + by + c = 0 // see edge_create - static int jcv_boxshape_clip(const jcv_clipper* clipper, edge* e) + static int boxshape_clip(const clipper* clipper, edge* e) { T pxmin = clipper->min[0]; T pxmax = clipper->max[0]; @@ -526,17 +510,17 @@ namespace jc T pymax = clipper->max[1]; T x1, y1, x2, y2; - jcv_point* s1; - jcv_point* s2; + point* s1; + point* s2; if (e->a == (T)1 && e->b >= (T)0) { - s1 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; - s2 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; + s1 = is_valid(&e->pos[1]) ? &e->pos[1] : 0; + s2 = is_valid(&e->pos[0]) ? &e->pos[0] : 0; } else { - s1 = jcv_is_valid(&e->pos[0]) ? &e->pos[0] : 0; - s2 = jcv_is_valid(&e->pos[1]) ? &e->pos[1] : 0; + s1 = is_valid(&e->pos[0]) ? &e->pos[0] : 0; + s2 = is_valid(&e->pos[1]) ? &e->pos[1] : 0; } if (e->a == (T)1) // delta x is larger @@ -642,22 +626,22 @@ namespace jc // The line equation: ax + by + c = 0 // see edge_create - static int edge_clipline(jcv_context_internal* internal, edge* e) + static int edge_clipline(context_internal* internal, edge* e) { - return internal->clipper.clip_fn(&internal->clipper, e); + return internal->clipper_.clip_fn(&internal->clipper_, e); } - static edge* edge_new(jcv_context_internal* internal, jcv_site* s1, jcv_site* s2) + static edge* edge_new(context_internal* internal, site* s1, site* s2) { - edge* e = jcv_alloc_edge(internal); + edge* e = alloc_edge(internal); edge_create(e, s1, s2); return e; } - // jcv_halfedge + // halfedge - static void jcv_halfedge_link(jcv_halfedge* edge, jcv_halfedge* newedge) + static void halfedge_link(halfedge* edge, halfedge* newedge) { newedge->left = edge; newedge->right = edge->right; @@ -665,7 +649,7 @@ namespace jc edge->right = newedge; } - static void jcv_halfedge_unlink(jcv_halfedge* he) + static void halfedge_unlink(halfedge* he) { he->left->right = he->right; he->right->left = he->left; @@ -673,9 +657,9 @@ namespace jc he->right = 0; } - static jcv_halfedge* jcv_halfedge_new(jcv_context_internal* internal, edge* e, int direction) + static halfedge* halfedge_new(context_internal* internal, edge* e, int direction) { - jcv_halfedge* he = jcv_alloc_halfedge(internal); + halfedge* he = alloc_halfedge(internal); he->edge_ = e; he->left = 0; he->right = 0; @@ -687,31 +671,31 @@ namespace jc return he; } - static void jcv_halfedge_delete(jcv_context_internal* internal, jcv_halfedge* he) + static void halfedge_delete(context_internal* internal, halfedge* he) { he->right = internal->halfedgepool; internal->halfedgepool = he; } - static jcv_site* jcv_halfedge_leftsite(const jcv_halfedge* he) + static site* halfedge_leftsite(const halfedge* he) { return he->edge_->sites[he->direction]; } - static jcv_site* jcv_halfedge_rightsite(const jcv_halfedge* he) + static site* halfedge_rightsite(const halfedge* he) { return he->edge_ ? he->edge_->sites[1 - he->direction] : 0; } - static int jcv_halfedge_rightof(const jcv_halfedge* he, const jcv_point* p) + static int halfedge_rightof(const halfedge* he, const point* p) { const edge* e = he->edge_; - const jcv_site* topsite = e->sites[1]; + const site* topsite = e->sites[1]; int right_of_site = (p->x() > topsite->p[0]) ? 1 : 0; - if (right_of_site && he->direction == JCV_DIRECTION_LEFT) + if (right_of_site && he->direction == DIRECTION_LEFT) return 1; - if (!right_of_site && he->direction == JCV_DIRECTION_RIGHT) + if (!right_of_site && he->direction == DIRECTION_RIGHT) return 0; T dxp, dyp, dxs, t1, t2, t3, yl; @@ -752,17 +736,17 @@ namespace jc t3 = yl - topsite->p[1]; above = t1 * t1 > (t2 * t2 + t3 * t3); } - return (he->direction == JCV_DIRECTION_LEFT ? above : !above); + return (he->direction == DIRECTION_LEFT ? above : !above); } // Keeps the priority queue sorted with events sorted in ascending order // Return 1 if the edges needs to be swapped - static int jcv_halfedge_compare( const jcv_halfedge* he1, const jcv_halfedge* he2 ) + static int halfedge_compare( const halfedge* he1, const halfedge* he2 ) { return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; } - static int jcv_halfedge_intersect(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* out) + static int halfedge_intersect(const halfedge* he1, const halfedge* he2, point* out) { const edge* e1 = he1->edge_; const edge* e2 = he2->edge_; @@ -779,8 +763,8 @@ namespace jc (*out)[2] = 0.0f; // NB: this does not set z for all edges const edge* e; - const jcv_halfedge* he; - if( jcv_point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) + const halfedge* he; + if( point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) { he = he1; e = e1; @@ -792,7 +776,7 @@ namespace jc } int right_of_site = out->x() >= e->sites[1]->p[0]; - if ((right_of_site && he->direction == JCV_DIRECTION_LEFT) || (!right_of_site && he->direction == JCV_DIRECTION_RIGHT)) + if ((right_of_site && he->direction == DIRECTION_LEFT) || (!right_of_site && he->direction == DIRECTION_RIGHT)) { return 0; } @@ -803,13 +787,13 @@ namespace jc // Priority queue - static int jcv_pq_moveup(jcv_priorityqueue* pq, int pos) + static int pq_moveup(priorityqueue* pq, int pos) { - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + halfedge** items = (halfedge**)pq->items; + halfedge* node = items[pos]; for( int parent = (pos >> 1); - pos > 1 && jcv_halfedge_compare(items[parent], node); + pos > 1 && halfedge_compare(items[parent], node); pos = parent, parent = parent >> 1) { items[pos] = items[parent]; @@ -821,29 +805,29 @@ namespace jc return pos; } - static int jcv_pq_maxchild(jcv_priorityqueue* pq, int pos) + static int pq_maxchild(priorityqueue* pq, int pos) { int child = pos << 1; if( child >= pq->numitems ) return 0; - jcv_halfedge** items = (jcv_halfedge**)pq->items; - if( (child + 1) < pq->numitems && jcv_halfedge_compare(items[child], items[child+1]) ) + halfedge** items = (halfedge**)pq->items; + if( (child + 1) < pq->numitems && halfedge_compare(items[child], items[child+1]) ) return child+1; return child; } - static int jcv_pq_movedown(jcv_priorityqueue* pq, int pos) + static int pq_movedown(priorityqueue* pq, int pos) { - jcv_halfedge** items = (jcv_halfedge**)pq->items; - jcv_halfedge* node = items[pos]; + halfedge** items = (halfedge**)pq->items; + halfedge* node = items[pos]; - int child = jcv_pq_maxchild(pq, pos); - while( child && jcv_halfedge_compare(node, items[child]) ) + int child = pq_maxchild(pq, pos); + while( child && halfedge_compare(node, items[child]) ) { items[pos] = items[child]; items[pos]->pqpos = pos; pos = child; - child = jcv_pq_maxchild(pq, pos); + child = pq_maxchild(pq, pos); } items[pos] = node; @@ -851,40 +835,40 @@ namespace jc return pos; } - static void jcv_pq_create(jcv_priorityqueue* pq, int capacity, void** buffer) + static void pq_create(priorityqueue* pq, int capacity, void** buffer) { pq->maxnumitems = capacity; pq->numitems = 1; pq->items = buffer; } - static int jcv_pq_empty(jcv_priorityqueue* pq) + static int pq_empty(priorityqueue* pq) { return pq->numitems == 1 ? 1 : 0; } - static int jcv_pq_push(jcv_priorityqueue* pq, void* node) + static int pq_push(priorityqueue* pq, void* node) { assert(pq->numitems < pq->maxnumitems); int n = pq->numitems++; pq->items[n] = node; - return jcv_pq_moveup(pq, n); + return pq_moveup(pq, n); } - static void* jcv_pq_pop(jcv_priorityqueue* pq) + static void* pq_pop(priorityqueue* pq) { void* node = pq->items[1]; pq->items[1] = pq->items[--pq->numitems]; - jcv_pq_movedown(pq, 1); + pq_movedown(pq, 1); return node; } - static void* jcv_pq_top(jcv_priorityqueue* pq) + static void* pq_top(priorityqueue* pq) { return pq->items[1]; } - static void jcv_pq_remove(jcv_priorityqueue* pq, jcv_halfedge* node) + static void pq_remove(priorityqueue* pq, halfedge* node) { if( pq->numitems == 1 ) return; @@ -892,44 +876,44 @@ namespace jc if( pos == 0 ) return; - jcv_halfedge** items = (jcv_halfedge**)pq->items; + halfedge** items = (halfedge**)pq->items; items[pos] = items[--pq->numitems]; - if( jcv_halfedge_compare( node, items[pos] ) ) - jcv_pq_moveup( pq, pos ); + if( halfedge_compare( node, items[pos] ) ) + pq_moveup( pq, pos ); else - jcv_pq_movedown( pq, pos ); + pq_movedown( pq, pos ); node->pqpos = pos; } // internal functions - static jcv_site* jcv_nextsite(jcv_context_internal* internal) + static site* nextsite(context_internal* internal) { return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; } - static jcv_halfedge* jcv_get_edge_above_x(jcv_context_internal* internal, const jcv_point* p) + static halfedge* get_edge_above_x(context_internal* internal, const point* p) { // Gets the arc on the beach line at the x coordinate (i.e. right above the new site event) // A good guess it's close by (Can be optimized) - jcv_halfedge* he = internal->last_inserted; + halfedge* he = internal->last_inserted; if( !he ) { - if( p->x() < (internal->rect.max[0] - internal->rect.min[0]) / 2 ) + if( p->x() < (internal->rect_.max[0] - internal->rect_.min[0]) / 2 ) he = internal->beachline_start; else he = internal->beachline_end; } // - if( he == internal->beachline_start || (he != internal->beachline_end && jcv_halfedge_rightof(he, p)) ) + if( he == internal->beachline_start || (he != internal->beachline_end && halfedge_rightof(he, p)) ) { do { he = he->right; } - while( he != internal->beachline_end && jcv_halfedge_rightof(he, p) ); + while( he != internal->beachline_end && halfedge_rightof(he, p) ); he = he->left; } @@ -938,13 +922,13 @@ namespace jc do { he = he->left; } - while( he != internal->beachline_start && !jcv_halfedge_rightof(he, p) ); + while( he != internal->beachline_start && !halfedge_rightof(he, p) ); } return he; } - static int jcv_check_circle_event(const jcv_halfedge* he1, const jcv_halfedge* he2, jcv_point* vertex) + static int check_circle_event(const halfedge* he1, const halfedge* he2, point* vertex) { edge* e1 = he1->edge_; edge* e2 = he2->edge_; @@ -953,170 +937,170 @@ namespace jc return 0; } - return jcv_halfedge_intersect(he1, he2, vertex); + return halfedge_intersect(he1, he2, vertex); } - static void jcv_site_event(jcv_context_internal* internal, jcv_site* site) + static void site_event(context_internal* internal, site* _site) { - jcv_halfedge* left = jcv_get_edge_above_x(internal, &site->p); - jcv_halfedge* right = left->right; - jcv_site* bottom = jcv_halfedge_rightsite(left); + halfedge* left = get_edge_above_x(internal, &_site->p); + halfedge* right = left->right; + site* bottom = halfedge_rightsite(left); if( !bottom ) bottom = internal->bottomsite; - edge* edge = edge_new(internal, bottom, site); - edge->next = internal->edges; - internal->edges = edge; + edge* _edge = edge_new(internal, bottom, _site); + _edge->next = internal->edges; + internal->edges = _edge; - jcv_halfedge* edge1 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_LEFT); - jcv_halfedge* edge2 = jcv_halfedge_new(internal, edge, JCV_DIRECTION_RIGHT); + halfedge* edge1 = halfedge_new(internal, _edge, DIRECTION_LEFT); + halfedge* edge2 = halfedge_new(internal, _edge, DIRECTION_RIGHT); - jcv_halfedge_link(left, edge1); - jcv_halfedge_link(edge1, edge2); + halfedge_link(left, edge1); + halfedge_link(edge1, edge2); internal->last_inserted = right; - jcv_point p; - if( jcv_check_circle_event( left, edge1, &p ) ) + point p; + if( check_circle_event( left, edge1, &p ) ) { - jcv_pq_remove(internal->eventqueue, left); + pq_remove(internal->eventqueue, left); left->vertex = p; - left->y = p[1] + jcv_point_dist(&site->p, &p); - jcv_pq_push(internal->eventqueue, left); + left->y = p[1] + point_dist(&_site->p, &p); + pq_push(internal->eventqueue, left); } - if( jcv_check_circle_event( edge2, right, &p ) ) + if( check_circle_event( edge2, right, &p ) ) { edge2->vertex = p; - edge2->y = p[1] + jcv_point_dist(&site->p, &p); - jcv_pq_push(internal->eventqueue, edge2); + edge2->y = p[1] + point_dist(&_site->p, &p); + pq_push(internal->eventqueue, edge2); } } // https://cp-algorithms.com/geometry/oriented-triangle-area.html - static T jcv_determinant(const jcv_point* a, const jcv_point* b, const jcv_point* c) + static T determinant(const point* a, const point* b, const point* c) { return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); } - static T jcv_calc_sort_metric(const jcv_site* site, const jcv_graphedge* edge) + static T calc_sort_metric(const site* _site, const graphedge* _edge) { // We take the average of the two points, since we can better distinguish between very small edges constexpr T half = T{0.5}; - T x = (edge->pos[0][0] + edge->pos[1][0]) * half; - T y = (edge->pos[0][1] + edge->pos[1][1]) * half; - T diffy = y - site->p[1]; - T angle = std::atan2( diffy, x - site->p[0] ); + T x = (_edge->pos[0][0] + _edge->pos[1][0]) * half; + T y = (_edge->pos[0][1] + _edge->pos[1][1]) * half; + T diffy = y - _site->p[1]; + T angle = std::atan2( diffy, x - _site->p[0] ); if( diffy < 0 ) { angle = angle + sm::mathconst::two_pi; } return angle; } - static int jcv_graphedge_eq(jcv_graphedge* a, jcv_graphedge* b) + static int graphedge_eq(graphedge* a, graphedge* b) { - return T_eq(a->angle, b->angle) && jcv_point_eq( &a->pos[0], &b->pos[0] ) && jcv_point_eq( &a->pos[1], &b->pos[1] ); + return T_eq(a->angle, b->angle) && point_eq( &a->pos[0], &b->pos[0] ) && point_eq( &a->pos[1], &b->pos[1] ); } - static void jcv_sortedges_insert(jcv_site* site, jcv_graphedge* edge) + static void sortedges_insert(site* _site, graphedge* _edge) { // Special case for the head end - jcv_graphedge* prev = 0; - if (site->edges == 0 || site->edges->angle >= edge->angle) + graphedge* prev = 0; + if (_site->edges == 0 || _site->edges->angle >= _edge->angle) { - edge->next = site->edges; - site->edges = edge; + _edge->next = _site->edges; + _site->edges = _edge; } else { // Locate the node before the point of insertion - jcv_graphedge* current = site->edges; - while(current->next != 0 && current->next->angle < edge->angle) + graphedge* current = _site->edges; + while(current->next != 0 && current->next->angle < _edge->angle) { current = current->next; } prev = current; - edge->next = current->next; - current->next = edge; + _edge->next = current->next; + current->next = _edge; } // check to avoid duplicates - if (prev && jcv_graphedge_eq(prev, edge)) + if (prev && graphedge_eq(prev, _edge)) { - prev->next = edge->next; + prev->next = _edge->next; } - else if (edge->next && jcv_graphedge_eq(edge, edge->next)) + else if (_edge->next && graphedge_eq(_edge, _edge->next)) { - edge->next = edge->next->next; + _edge->next = _edge->next->next; } } - static void jcv_finishline(jcv_context_internal* internal, edge* e) + static void finishline(context_internal* internal, edge* e) { if( !edge_clipline(internal, e) ) { return; } // Make sure the graph edges are CCW - int flip = jcv_determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (T)0 ? 0 : 1; + int flip = determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (T)0 ? 0 : 1; for( int i = 0; i < 2; ++i ) { - jcv_graphedge* ge = jcv_alloc_graphedge(internal); + graphedge* ge = alloc_graphedge(internal); ge->edge_ = e; ge->next = 0; ge->neighbor = e->sites[1-i]; ge->pos[flip] = e->pos[i]; ge->pos[1-flip] = e->pos[1-i]; - ge->angle = jcv_calc_sort_metric(e->sites[i], ge); + ge->angle = calc_sort_metric(e->sites[i], ge); - jcv_sortedges_insert( e->sites[i], ge ); + sortedges_insert( e->sites[i], ge ); } } - static void jcv_endpos(jcv_context_internal* internal, edge* e, const jcv_point* p, int direction) + static void endpos(context_internal* internal, edge* e, const point* p, int direction) { e->pos[direction] = *p; - if( !jcv_is_valid(&e->pos[1 - direction]) ) + if( !is_valid(&e->pos[1 - direction]) ) return; - jcv_finishline(internal, e); + finishline(internal, e); } - static void jcv_create_corner_edge(jcv_context_internal* internal, const jcv_site* site, jcv_graphedge* current, jcv_graphedge* gap) + static void create_corner_edge(context_internal* internal, const site* site, graphedge* current, graphedge* gap) { gap->neighbor = 0; gap->pos[0] = current->pos[1]; - if( current->pos[1][0] < internal->rect.max[0] && current->pos[1][1] == internal->rect.min[1] ) + if( current->pos[1][0] < internal->rect_.max[0] && current->pos[1][1] == internal->rect_.min[1] ) { - gap->pos[1][0] = internal->rect.max[0]; - gap->pos[1][1] = internal->rect.min[1]; + gap->pos[1][0] = internal->rect_.max[0]; + gap->pos[1][1] = internal->rect_.min[1]; } - else if( current->pos[1][0] > internal->rect.min[0] && current->pos[1][1] == internal->rect.max[1] ) + else if( current->pos[1][0] > internal->rect_.min[0] && current->pos[1][1] == internal->rect_.max[1] ) { - gap->pos[1][0] = internal->rect.min[0]; - gap->pos[1][1] = internal->rect.max[1]; + gap->pos[1][0] = internal->rect_.min[0]; + gap->pos[1][1] = internal->rect_.max[1]; } - else if( current->pos[1][1] > internal->rect.min[1] && current->pos[1][0] == internal->rect.min[0] ) + else if( current->pos[1][1] > internal->rect_.min[1] && current->pos[1][0] == internal->rect_.min[0] ) { - gap->pos[1][0] = internal->rect.min[0]; - gap->pos[1][1] = internal->rect.min[1]; + gap->pos[1][0] = internal->rect_.min[0]; + gap->pos[1][1] = internal->rect_.min[1]; } - else if( current->pos[1][1] < internal->rect.max[1] && current->pos[1][0] == internal->rect.max[0] ) + else if( current->pos[1][1] < internal->rect_.max[1] && current->pos[1][0] == internal->rect_.max[0] ) { - gap->pos[1][0] = internal->rect.max[0]; - gap->pos[1][1] = internal->rect.max[1]; + gap->pos[1][0] = internal->rect_.max[0]; + gap->pos[1][1] = internal->rect_.max[1]; } - gap->angle = jcv_calc_sort_metric(site, gap); + gap->angle = calc_sort_metric(site, gap); } - static edge* jcv_create_gap_edge(jcv_context_internal* internal, jcv_site* site, jcv_graphedge* ge) + static edge* create_gap_edge(context_internal* internal, site* site, graphedge* ge) { - edge* edge = jcv_alloc_edge(internal); + edge* edge = alloc_edge(internal); edge->pos[0] = ge->pos[0]; edge->pos[1] = ge->pos[1]; edge->sites[0] = site; @@ -1127,34 +1111,34 @@ namespace jc return edge; } - static void jcv_boxshape_fillgaps(const jcv_clipper* clipper, jcv_context_internal* allocator, jcv_site* site) + static void boxshape_fillgaps(const clipper* clipper, context_internal* allocator, site* site) { // They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap - jcv_graphedge* current = site->edges; + graphedge* current = site->edges; if( !current ) { // No edges, then it should be a single cell assert( allocator->numsites == 1 ); - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = clipper->min; gap->pos[1][0] = clipper->max[0]; gap->pos[1][1] = clipper->min[1]; - gap->angle = jcv_calc_sort_metric(site, gap); + gap->angle = calc_sort_metric(site, gap); gap->next = 0; - gap->edge_ = jcv_create_gap_edge(allocator, site, gap); + gap->edge_ = create_gap_edge(allocator, site, gap); current = gap; site->edges = gap; } - jcv_graphedge* next = current->next; + graphedge* next = current->next; if( !next ) { - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); - jcv_create_corner_edge(allocator, site, current, gap); - gap->edge_ = jcv_create_gap_edge(allocator, site, gap); + graphedge* gap = alloc_graphedge(allocator); + create_corner_edge(allocator, site, current, gap); + gap->edge_ = create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1164,8 +1148,8 @@ namespace jc while( current && next ) { - int current_edge_flags = jcv_get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); - if( current_edge_flags && !jcv_point_eq(¤t->pos[1], &next->pos[0])) + int current_edge_flags = get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); + if( current_edge_flags && !point_eq(¤t->pos[1], &next->pos[0])) { // Cases: // Current and Next on the same border @@ -1173,16 +1157,16 @@ namespace jc // Current on the corner, Next on the border // Current on the corner, Next on another border (another corner in between) - int next_edge_flags = jcv_get_edge_flags(&next->pos[0], &clipper->min, &clipper->max); + int next_edge_flags = get_edge_flags(&next->pos[0], &clipper->min, &clipper->max); if (current_edge_flags & next_edge_flags) { // Current and Next on the same border - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = next->pos[0]; - gap->angle = jcv_calc_sort_metric(site, gap); - gap->edge_ = jcv_create_gap_edge(allocator, site, gap); + gap->angle = calc_sort_metric(site, gap); + gap->edge_ = create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1193,26 +1177,26 @@ namespace jc if (corner_flag) { // we are already at one corner, so we need to find the next one - corner_flag = jcv_corner_rotate_90(corner_flag); + corner_flag = corner_rotate_90(corner_flag); } else { // we are on the middle of a border // we need to find the adjacent corner, following the borders CCW - if (current_edge_flags == EDGE_TOP) { corner_flag = JCV_CORNER_TOP_LEFT; } - else if (current_edge_flags == EDGE_LEFT) { corner_flag = JCV_CORNER_BOTTOM_LEFT; } - else if (current_edge_flags == EDGE_BOTTOM) { corner_flag = JCV_CORNER_BOTTOM_RIGHT; } - else if (current_edge_flags == EDGE_RIGHT) { corner_flag = JCV_CORNER_TOP_RIGHT; } + if (current_edge_flags == EDGE_TOP) { corner_flag = CORNER_TOP_LEFT; } + else if (current_edge_flags == EDGE_LEFT) { corner_flag = CORNER_BOTTOM_LEFT; } + else if (current_edge_flags == EDGE_BOTTOM) { corner_flag = CORNER_BOTTOM_RIGHT; } + else if (current_edge_flags == EDGE_RIGHT) { corner_flag = CORNER_TOP_RIGHT; } } - jcv_point corner = jcv_corner_to_point(corner_flag, &clipper->min, &clipper->max); + point corner = corner_to_point(corner_flag, &clipper->min, &clipper->max); - jcv_graphedge* gap = jcv_alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge(allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = corner; - gap->angle = jcv_calc_sort_metric(site, gap); - gap->edge_ = jcv_create_gap_edge(allocator, site, gap); + gap->angle = calc_sort_metric(site, gap); + gap->edge_ = create_gap_edge(allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1231,82 +1215,82 @@ namespace jc // Since the algorithm leaves gaps at the borders/corner, we want to fill them - static void jcv_fillgaps(jcv_diagram* diagram) + static void fillgaps(diagram* diagram) { - jcv_context_internal* internal = diagram->internal; - if (!internal->clipper.fill_fn) + context_internal* internal = diagram->internal; + if (!internal->clipper_.fill_fn) return; for( int i = 0; i < internal->numsites; ++i ) { - jcv_site* site = &internal->sites[i]; - internal->clipper.fill_fn(&internal->clipper, internal, site); + site* site = &internal->sites[i]; + internal->clipper_.fill_fn(&internal->clipper_, internal, site); } } - static void jcv_circle_event(jcv_context_internal* internal) + static void circle_event(context_internal* internal) { - jcv_halfedge* left = (jcv_halfedge*)jcv_pq_pop(internal->eventqueue); + halfedge* left = (halfedge*)pq_pop(internal->eventqueue); - jcv_halfedge* leftleft = left->left; - jcv_halfedge* right = left->right; - jcv_halfedge* rightright= right->right; - jcv_site* bottom = jcv_halfedge_leftsite(left); - jcv_site* top = jcv_halfedge_rightsite(right); + halfedge* leftleft = left->left; + halfedge* right = left->right; + halfedge* rightright= right->right; + site* bottom = halfedge_leftsite(left); + site* top = halfedge_rightsite(right); - jcv_point vertex = left->vertex; - jcv_endpos(internal, left->edge_, &vertex, left->direction); - jcv_endpos(internal, right->edge_, &vertex, right->direction); + point vertex = left->vertex; + endpos(internal, left->edge_, &vertex, left->direction); + endpos(internal, right->edge_, &vertex, right->direction); internal->last_inserted = rightright; - jcv_pq_remove(internal->eventqueue, right); - jcv_halfedge_unlink(left); - jcv_halfedge_unlink(right); - jcv_halfedge_delete(internal, left); - jcv_halfedge_delete(internal, right); + pq_remove(internal->eventqueue, right); + halfedge_unlink(left); + halfedge_unlink(right); + halfedge_delete(internal, left); + halfedge_delete(internal, right); - int direction = JCV_DIRECTION_LEFT; + int direction = DIRECTION_LEFT; if( bottom->p[1] > top->p[1] ) { - jcv_site* temp = bottom; + site* temp = bottom; bottom = top; top = temp; - direction = JCV_DIRECTION_RIGHT; + direction = DIRECTION_RIGHT; } edge* edge = edge_new(internal, bottom, top); edge->next = internal->edges; internal->edges = edge; - jcv_halfedge* he = jcv_halfedge_new(internal, edge, direction); - jcv_halfedge_link(leftleft, he); - jcv_endpos(internal, edge, &vertex, JCV_DIRECTION_RIGHT - direction); + halfedge* he = halfedge_new(internal, edge, direction); + halfedge_link(leftleft, he); + endpos(internal, edge, &vertex, DIRECTION_RIGHT - direction); - jcv_point p; - if( jcv_check_circle_event( leftleft, he, &p ) ) + point p; + if( check_circle_event( leftleft, he, &p ) ) { - jcv_pq_remove(internal->eventqueue, leftleft); + pq_remove(internal->eventqueue, leftleft); leftleft->vertex = p; - leftleft->y = p[1] + jcv_point_dist(&bottom->p, &p); - jcv_pq_push(internal->eventqueue, leftleft); + leftleft->y = p[1] + point_dist(&bottom->p, &p); + pq_push(internal->eventqueue, leftleft); } - if( jcv_check_circle_event( he, rightright, &p ) ) + if( check_circle_event( he, rightright, &p ) ) { he->vertex = p; - he->y = p[1] + jcv_point_dist(&bottom->p, &p); - jcv_pq_push(internal->eventqueue, he); + he->y = p[1] + point_dist(&bottom->p, &p); + pq_push(internal->eventqueue, he); } } - typedef union jcv_cast_align_struct_ + typedef union cast_align_struct_ { char* charp; void** voidpp; - } jcv_cast_align_struct; + } cast_align_struct; - static void jcv_rect_union(jcv_rect* rect, const jcv_point* p) + static void rect_union(rect* rect, const point* p) { rect->min[0] = std::min(rect->min[0], p->x()); rect->min[1] = std::min(rect->min[1], p->y()); @@ -1314,7 +1298,7 @@ namespace jc rect->max[1] = std::max(rect->max[1], p->y()); } - static void jcv_rect_round(jcv_rect* rect) + static void rect_round(rect* rect) { rect->min[0] = std::floor(rect->min[0]); rect->min[1] = std::floor(rect->min[1]); @@ -1322,7 +1306,7 @@ namespace jc rect->max[1] = std::ceil(rect->max[1]); } - static void jcv_rect_inflate(jcv_rect* rect, T amount) + static void rect_inflate(rect* rect, T amount) { rect->min[0] -= amount; rect->min[1] -= amount; @@ -1330,12 +1314,12 @@ namespace jc rect->max[1] += amount; } - static int jcv_prune_duplicates(jcv_context_internal* internal, jcv_rect* rect) + static int prune_duplicates(context_internal* internal, rect* _rect) { int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + site* sites = internal->sites; - jcv_rect r; + rect r; r.min[0] = r.min[1] = std::numeric_limits::max(); r.max[0] = r.max[1] = std::numeric_limits::lowest(); @@ -1343,9 +1327,9 @@ namespace jc // Prune duplicates first for (int i = 0; i < num_sites; i++) { - const jcv_site* s = &sites[i]; + const site* s = &sites[i]; // Remove duplicates, to avoid anomalies - if( i > 0 && jcv_point_eq(&s->p, &sites[i - 1].p) ) + if( i > 0 && point_eq(&s->p, &sites[i - 1].p) ) { offset++; continue; @@ -1353,30 +1337,28 @@ namespace jc sites[i - offset] = sites[i]; - jcv_rect_union(&r, &s->p); + rect_union(&r, &s->p); } internal->numsites -= offset; - if (rect) { - *rect = r; - } + if (_rect) { *_rect = r; } return offset; } - static int jcv_prune_not_in_shape(jcv_context_internal* internal, jcv_rect* rect) + static int prune_not_in_shape(context_internal* internal, rect* _rect) { int num_sites = internal->numsites; - jcv_site* sites = internal->sites; + site* sites = internal->sites; - jcv_rect r; + rect r; r.min[0] = r.min[1] = std::numeric_limits::max(); r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; for (int i = 0; i < num_sites; i++) { - const jcv_site* s = &sites[i]; + const site* s = &sites[i]; - if (!internal->clipper.test_fn(&internal->clipper, s->p)) + if (!internal->clipper_.test_fn(&internal->clipper_, s->p)) { offset++; continue; @@ -1384,47 +1366,45 @@ namespace jc sites[i - offset] = sites[i]; - jcv_rect_union(&r, &s->p); + rect_union(&r, &s->p); } internal->numsites -= offset; - if (rect) { - *rect = r; - } + if (_rect) { *_rect = r; } return offset; } - static jcv_context_internal* jcv_alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) + static context_internal* alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) { // Interesting limits from Euler's equation // Slide 81: https://courses.cs.washington.edu/courses/csep521/01au/lectures/lecture10slides.pdf // Page 3: https://sites.cs.ucsb.edu/~suri/cs235/Voronoi.pdf size_t eventssize = (size_t)(num_points*2) * sizeof(void*); // beachline can have max 2*n-5 parabolas - size_t sitessize = (size_t)num_points * sizeof(jcv_site); - size_t memsize = sizeof(jcv_priorityqueue) + eventssize + sitessize + sizeof(jcv_context_internal) + 16u; // 16 bytes padding for alignment + size_t sitessize = (size_t)num_points * sizeof(site); + size_t memsize = sizeof(priorityqueue) + eventssize + sitessize + sizeof(context_internal) + 16u; // 16 bytes padding for alignment char* originalmem = (char*)allocfn(userallocctx, memsize); memset(originalmem, 0, memsize); // align memory - char* mem = (char*)jcv_align(originalmem, sizeof(void*)); + char* mem = (char*)align(originalmem, sizeof(void*)); - jcv_context_internal* internal = (jcv_context_internal*)mem; - mem += sizeof(jcv_context_internal); + context_internal* internal = (context_internal*)mem; + mem += sizeof(context_internal); internal->mem = originalmem; internal->memctx = userallocctx; internal->alloc = allocfn; internal->free = freefn; - mem = (char*)jcv_align(mem, sizeof(void*)); - internal->sites = (jcv_site*) mem; + mem = (char*)align(mem, sizeof(void*)); + internal->sites = (site*) mem; mem += sitessize; - mem = (char*)jcv_align(mem, sizeof(void*)); - internal->eventqueue = (jcv_priorityqueue*)mem; - mem += sizeof(jcv_priorityqueue); + mem = (char*)align(mem, sizeof(void*)); + internal->eventqueue = (priorityqueue*)mem; + mem += sizeof(priorityqueue); assert( ((uintptr_t)mem & (sizeof(void*)-1)) == 0 ); - jcv_cast_align_struct tmp; + cast_align_struct tmp; tmp.charp = mem; internal->eventmem = tmp.voidpp; @@ -1433,16 +1413,18 @@ namespace jc return internal; } - // This version of jcv_diagram_generate allows the client to use a custom allocator - static void jcv_diagram_generate_useralloc(int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* d) + // This version of diagram_generate allows the client to use a custom allocator + static void diagram_generate_useralloc (int num_points, const point* points, + const rect* _rect, const clipper* _clipper, + void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* d) { if( d->internal ) - jcv_diagram_free( d ); + diagram_free( d ); - jcv_context_internal* internal = jcv_alloc_internal(num_points, userallocctx, allocfn, freefn); + context_internal* internal = alloc_internal(num_points, userallocctx, allocfn, freefn); - internal->beachline_start = jcv_halfedge_new(internal, 0, 0); - internal->beachline_end = jcv_halfedge_new(internal, 0, 0); + internal->beachline_start = halfedge_new(internal, 0, 0); + internal->beachline_end = halfedge_new(internal, 0, 0); internal->beachline_start->left = 0; internal->beachline_start->right = internal->beachline_end; @@ -1452,10 +1434,10 @@ namespace jc internal->last_inserted = 0; int max_num_events = num_points*2; // beachline can have max 2*n-5 parabolas - jcv_pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); + pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); internal->numsites = num_points; - jcv_site* sites = internal->sites; + site* sites = internal->sites; for( int i = 0; i < num_points; ++i ) { @@ -1464,75 +1446,75 @@ namespace jc sites[i].index = i; } - qsort(sites, (size_t)num_points, sizeof(jcv_site), jcv_point_cmp); + qsort(sites, (size_t)num_points, sizeof(site), point_cmp); - jcv_clipper box_clipper; - if (clipper == 0) { + clipper box_clipper; + if (_clipper == 0) { // model->get_shaderprogs = &mplot::VisualBase::get_shaderprogs; - box_clipper.test_fn = &jc::manager::jcv_boxshape_test; - box_clipper.clip_fn = &jc::manager::jcv_boxshape_clip; - box_clipper.fill_fn = &jc::manager::jcv_boxshape_fillgaps; - clipper = &box_clipper; + box_clipper.test_fn = &jcv::manager::boxshape_test; + box_clipper.clip_fn = &jcv::manager::boxshape_clip; + box_clipper.fill_fn = &jcv::manager::boxshape_fillgaps; + _clipper = &box_clipper; } - internal->clipper = *clipper; + internal->clipper_ = *_clipper; - jcv_rect tmp_rect; + rect tmp_rect; tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); - jcv_prune_duplicates(internal, &tmp_rect); + prune_duplicates(internal, &tmp_rect); // Prune using the test second - if (internal->clipper.test_fn) + if (internal->clipper_.test_fn) { // e.g. used by the box clipper in the test_fn - internal->clipper.min = rect ? rect->min : tmp_rect.min; - internal->clipper.max = rect ? rect->max : tmp_rect.max; + internal->clipper_.min = _rect ? _rect->min : tmp_rect.min; + internal->clipper_.max = _rect ? _rect->max : tmp_rect.max; - jcv_prune_not_in_shape(internal, &tmp_rect); + prune_not_in_shape(internal, &tmp_rect); // The pruning might have made the bounding box smaller - if (!rect) { + if (!_rect) { // In the case of all sites being all on a horizontal or vertical line, the // rect area will be zero, and the diagram generation will most likely fail - jcv_rect_round(&tmp_rect); - jcv_rect_inflate(&tmp_rect, 10); + rect_round(&tmp_rect); + rect_inflate(&tmp_rect, 10); - internal->clipper.min = tmp_rect.min; - internal->clipper.max = tmp_rect.max; + internal->clipper_.min = tmp_rect.min; + internal->clipper_.max = tmp_rect.max; } } - internal->rect = rect ? *rect : tmp_rect; + internal->rect_ = _rect ? *_rect : tmp_rect; - d->min = internal->rect.min; - d->max = internal->rect.max; + d->min = internal->rect_.min; + d->max = internal->rect_.max; d->numsites = internal->numsites; d->internal = internal; - internal->bottomsite = jcv_nextsite(internal); + internal->bottomsite = nextsite(internal); - jcv_priorityqueue* pq = internal->eventqueue; - jcv_site* site = jcv_nextsite(internal); + priorityqueue* pq = internal->eventqueue; + site* site = nextsite(internal); int finished = 0; while( !finished ) { - jcv_point lowest_pq_point; - if( !jcv_pq_empty(pq) ) + point lowest_pq_point; + if( !pq_empty(pq) ) { - jcv_halfedge* he = (jcv_halfedge*)jcv_pq_top(pq); + halfedge* he = (halfedge*)pq_top(pq); lowest_pq_point[0] = he->vertex[0]; lowest_pq_point[1] = he->y; } - if( site != 0 && (jcv_pq_empty(pq) || jcv_point_less(&site->p, &lowest_pq_point) ) ) + if( site != 0 && (pq_empty(pq) || point_less(&site->p, &lowest_pq_point) ) ) { - jcv_site_event(internal, site); - site = jcv_nextsite(internal); + site_event(internal, site); + site = nextsite(internal); } - else if( !jcv_pq_empty(pq) ) + else if( !pq_empty(pq) ) { - jcv_circle_event(internal); + circle_event(internal); } else { @@ -1540,12 +1522,12 @@ namespace jc } } - for( jcv_halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) + for( halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) { - jcv_finishline(internal, he->edge_); + finishline(internal, he->edge_); } - jcv_fillgaps(d); + fillgaps(d); } /** @@ -1554,13 +1536,13 @@ namespace jc * If rect is null, an automatic bounding box is calculated, with an extra padding of 10 units * All points will be culled against the bounding rect, and all edges will be clipped against it. */ - static void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* d ) + static void diagram_generate( int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* d ) { - jcv_diagram_generate_useralloc(num_points, points, rect, clipper, 0, jcv_alloc_fn, jcv_free_fn, d); + diagram_generate_useralloc(num_points, points, rect, clipper, 0, alloc_fn, free_fn, d); } // User API - void diagram_generate (const std::vector>& centres) + void diagram_generate (const std::vector>& centres) { int ncoords = static_cast(centres.size()); sm::range rx, ry; @@ -1571,13 +1553,13 @@ namespace jc ry.update (centres[i][1]); } // Have to actually new the diagram! - this->diagram = new jc::jcv_diagram; - std::memset (this->diagram, 0, sizeof(jc::jcv_diagram)); + this->diagram = new jcv::diagram; + std::memset (this->diagram, 0, sizeof(jcv::diagram)); this->domain = { - jc::jcv_point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, - jc::jcv_point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} + jcv::point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, + jcv::point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} }; - jc::manager::jcv_diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); + jcv::manager::diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); } int diagram_numsites() const @@ -1592,9 +1574,9 @@ namespace jc private: // Our diagram - jc::jcv_diagram* diagram = nullptr; + jcv::diagram* diagram = nullptr; // A domain for the diagram. - jc::jcv_rect domain = {}; + jcv::rect domain = {}; }; // end struct jcv } // namespace @@ -1613,13 +1595,13 @@ namespace jc 0.7 2019-10-25 - Added support for clipping against convex polygons - Added EDGE_INTERSECT_THRESHOLD for edge intersections - Fixed issue where the bounds calculation wasn’t considering all points - 0.6 2018-10-21 - Removed JCV_CEIL/JCV_FLOOR/JCV_FABS + 0.6 2018-10-21 - Removed CEIL/FLOOR/FABS - Optimizations: Fewer indirections, better beach head approximation 0.5 2018-10-14 - Fixed issue where the graph edge had the wrong edge assigned (issue #28) - - Fixed issue where a point was falsely passing the jcv_is_valid() test (issue #22) - - Fixed jcv_diagram_get_edges() so it now returns _all_ edges (issue #28) - - Added jcv_diagram_get_next_edge() to skip zero length edges (issue #10) - - Added defines JCV_CEIL/JCV_FLOOR/JCV_FLT_MAX for easier configuration + - Fixed issue where a point was falsely passing the is_valid() test (issue #22) + - Fixed diagram_get_edges() so it now returns _all_ edges (issue #28) + - Added diagram_get_next_edge() to skip zero length edges (issue #10) + - Added defines CEIL/FLOOR/FLT_MAX for easier configuration 0.4 2017-06-03 - Increased the max number of events that are preallocated 0.3 2017-04-16 - Added clipping box as input argument (Automatically calculated if needed) - Input points are pruned based on bounding box @@ -1672,57 +1654,57 @@ namespace jc The api consists of these functions: - void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* diagram ); - void jcv_diagram_generate_useralloc( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* diagram ); - void jcv_diagram_free( jcv_diagram* diagram ); + void diagram_generate( int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* diagram ); + void diagram_generate_useralloc( int num_points, const point* points, const rect* rect, const clipper* clipper, const clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* diagram ); + void diagram_free( diagram* diagram ); - const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ); - const edge* jcv_diagram_get_edges( const jcv_diagram* diagram ); - const edge* jcv_diagram_get_next_edge( const edge* edge ); + const site* diagram_get_sites( const diagram* diagram ); + const edge* diagram_get_edges( const diagram* diagram ); + const edge* diagram_get_next_edge( const edge* edge ); An example usage: #define JC_VORONOI_IMPLEMENTATION // If you wish to use doubles - //#define JCV_REAL_TYPE double + //#define REAL_TYPE double #include "jc_voronoi.h" - void draw_edges(const jcv_diagram* diagram); - void draw_cells(const jcv_diagram* diagram); + void draw_edges(const diagram* diagram); + void draw_cells(const diagram* diagram); - void generate_and_draw(int numpoints, const jcv_point* points) + void generate_and_draw(int numpoints, const point* points) { - jcv_diagram diagram; - memset(&diagram, 0, sizeof(jcv_diagram)); - jcv_diagram_generate(count, points, 0, 0, &diagram); + diagram diagram; + memset(&diagram, 0, sizeof(diagram)); + diagram_generate(count, points, 0, 0, &diagram); draw_edges(diagram); draw_cells(diagram); - jcv_diagram_free( &diagram ); + diagram_free( &diagram ); } - void draw_edges(const jcv_diagram* diagram) + void draw_edges(const diagram* diagram) { // If all you need are the edges - const edge* edge = jcv_diagram_get_edges( diagram ); + const edge* edge = diagram_get_edges( diagram ); while( edge ) { draw_line(edge->pos[0], edge->pos[1]); - edge = jcv_diagram_get_next_edge(edge); + edge = diagram_get_next_edge(edge); } } - void draw_cells(const jcv_diagram* diagram) + void draw_cells(const diagram* diagram) { // If you want to draw triangles, or relax the diagram, // you can iterate over the sites and get all edges easily - const jcv_site* sites = jcv_diagram_get_sites( diagram ); + const site* sites = diagram_get_sites( diagram ); for( int i = 0; i < diagram->numsites; ++i ) { - const jcv_site* site = &sites[i]; + const site* site = &sites[i]; - const jcv_graphedge* e = site->edges; + const graphedge* e = site->edges; while( e ) { draw_triangle( site->p, e->pos[0], e->pos[1]); @@ -1732,16 +1714,16 @@ namespace jc } // Here is a simple example of how to do the relaxations of the cells - void relax_points(const jcv_diagram* diagram, jcv_point* points) + void relax_points(const diagram* diagram, point* points) { - const jcv_site* sites = jcv_diagram_get_sites(diagram); + const site* sites = diagram_get_sites(diagram); for( int i = 0; i < diagram->numsites; ++i ) { - const jcv_site* site = &sites[i]; - jcv_point sum = site->p; + const site* site = &sites[i]; + point sum = site->p; int count = 1; - const jcv_graphedge* edge = site->edges; + const graphedge* edge = site->edges; while( edge ) { From 8caf065d86984f1c7edd093117383af69f94e9f5 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 15:03:26 +0000 Subject: [PATCH 35/41] Completes refactoring --- mplot/SphericalProjectionVisual.h | 25 ++++++++++++------------- mplot/compoundray/EyeVisual.h | 20 ++++++++++---------- mplot/jcvoronoi/jc_voronoi.h | 6 ++---- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/mplot/SphericalProjectionVisual.h b/mplot/SphericalProjectionVisual.h index e75e2118..933d0664 100644 --- a/mplot/SphericalProjectionVisual.h +++ b/mplot/SphericalProjectionVisual.h @@ -8,7 +8,6 @@ #include #include #include - #include namespace mplot @@ -73,24 +72,24 @@ namespace mplot void voronoi2d() { // Use mplot::range to find the extents of dataCoords. From these create a - // rectangle to pass to jcv_diagram_generate. + // rectangle to pass to diagram_generate. int ncoords = static_cast(this->xy.size()); - jc::voronoi vd; // we need double precision for projections, float may run into trouble - vd.border_width = this->border_width; - vd.jcv_diagram_generate (this->xy); + jcv::manager vorman; // we need double precision for projections, float may run into trouble + vorman.border_width = this->border_width; + vorman.diagram_generate (this->xy); - int diag_nsites = vd.diagram_numsites(); + int diag_nsites = vorman.diagram_numsites(); if (diag_nsites != ncoords) { std::cout << "WARNING: diagram's ncoords (" << diag_nsites << ") != ncoords (" << ncoords << ")?!?!\n"; } // We obtain access to the Voronoi cell sites: - const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); + const jcv::site* sites = vorman.diagram_get_sites(); - for (int i = 0; i < vd.diagram_numsites() && i < ncoords; ++i) { - const jc::jcv_site* site = &sites[i]; - jc::jcv_graphedge* e = site->edges; // The very first edge + for (int i = 0; i < vorman.diagram_numsites() && i < ncoords; ++i) { + const jcv::site* site = &sites[i]; + jcv::graphedge* e = site->edges; // The very first edge while (e) { // Set z. Should be done in jcvoronoi, but haven't found out how e->pos[0][2] = this->xy[i][2]; @@ -100,9 +99,9 @@ namespace mplot } // To draw triangles iterate over the 'sites' and draw triangles - for (int i = 0; i < vd.diagram_numsites() && i < ncoords; ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + for (int i = 0; i < vorman.diagram_numsites() && i < ncoords; ++i) { + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; std::array c = mplot::colour::black; if (static_cast(site->index) < this->colour.size()) { c = this->colour[site->index]; } uint32_t site_triangles = 0; diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index a48c33f8..45166194 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -386,24 +386,24 @@ namespace mplot::compoundray void voronoi2d (uint32_t pri) { // Use mplot::range to find the extents of dataCoords. From these create a - // rectangle to pass to jcv_diagram_generate. + // rectangle to pass to diagram_generate. int ncoords = static_cast(this->omm2d.size()); - jc::voronoi vd; // we need double precision for projections, float may run into trouble - vd.border_width = this->border_width; - vd.jcv_diagram_generate (this->omm2d); + jcv::manager vorman; // we need double precision for projections, float may run into trouble + vorman.border_width = this->border_width; + vorman.diagram_generate (this->omm2d); - int diag_nsites = vd.diagram_numsites(); + int diag_nsites = vorman.diagram_numsites(); if (diag_nsites != ncoords) { std::cout << "WARNING: diagram's ncoords (" << diag_nsites << ") != ncoords (" << ncoords << ")?!?!\n"; } // We obtain access to the Voronoi cell sites: - const jc::jcv_site* sites = vd.jcv_diagram_get_sites(); + const jcv::site* sites = vorman.diagram_get_sites(); for (int i = 0; i < diag_nsites && i < ncoords; ++i) { - const jc::jcv_site* site = &sites[i]; - jc::jcv_graphedge* e = site->edges; // The very first edge + const jcv::site* site = &sites[i]; + jcv::graphedge* e = site->edges; // The very first edge while (e) { // Set z. Should be done in jcvoronoi, but haven't found out how e->pos[0][2] = this->omm2d[i][2]; @@ -421,8 +421,8 @@ namespace mplot::compoundray sm::vvec> flat_colours; // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diag_nsites && i < ncoords; ++i) { - const jc::jcv_site* site = &sites[i]; - const jc::jcv_graphedge* e = site->edges; + const jcv::site* site = &sites[i]; + const jcv::graphedge* e = site->edges; this->projections[pri].site_indices[i] = site->index; std::array colour = mplot::colour::black; if (site->index + this->projections[pri].start_i < ommData->size()) { diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 5a3d9bfc..7707bb6b 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -118,13 +118,11 @@ namespace jcv struct memoryblock { - size_t sizefree; + size_t sizefree; struct memoryblock* next; - char* memory; + char* memory; }; - typedef int (*FJCVPriorityQueuePrint)(const void* node, int pos); - struct priorityqueue { // Implements a binary heap From e5d7104df8e77c87306834d3a286127ebf293639 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 15:09:22 +0000 Subject: [PATCH 36/41] diagram should just be a nonpointer member --- mplot/jcvoronoi/jc_voronoi.h | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 7707bb6b..9563bf50 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -179,13 +179,7 @@ namespace jcv struct manager { manager(){} - ~manager() - { - if (this->diagram) { - jcv::manager::diagram_free (this->diagram); - delete this->diagram; - } - } + ~manager() { jcv::manager::diagram_free (&this->diagram); } static constexpr T edge_intersect_threshold = T{JCV_EDGE_INTERSECT_THRESHOLD}; @@ -312,14 +306,7 @@ namespace jcv } // User API - const site* diagram_get_sites() - { - const site* sites = nullptr; - if (this->diagram) { - sites = diagram_get_sites (this->diagram); - } - return sites; - } + const site* diagram_get_sites() { return diagram_get_sites (&this->diagram); } // Iterates over a list of edges, skipping invalid edges (where p0==p1) const edge* diagram_get_next_edge( const edge* _edge ) @@ -1550,29 +1537,22 @@ namespace jcv rx.update (centres[i][0]); ry.update (centres[i][1]); } - // Have to actually new the diagram! - this->diagram = new jcv::diagram; - std::memset (this->diagram, 0, sizeof(jcv::diagram)); + std::memset (&this->diagram, 0, sizeof(jcv::diagram)); this->domain = { jcv::point{rx.min - this->border_width, ry.min - this->border_width, 0.0f}, jcv::point{rx.max + this->border_width, ry.max + this->border_width, 0.0f} }; - jcv::manager::diagram_generate (ncoords, centres.data(), &this->domain, 0, this->diagram); + jcv::manager::diagram_generate (ncoords, centres.data(), &this->domain, 0, &this->diagram); } - int diagram_numsites() const - { - int n = 0; - if (this->diagram) { n = this->diagram->numsites; } - return n; - } + int diagram_numsites() const { return this->diagram.numsites; } // User-configurable border width T border_width = std::numeric_limits::epsilon(); private: // Our diagram - jcv::diagram* diagram = nullptr; + jcv::diagram diagram; // A domain for the diagram. jcv::rect domain = {}; }; // end struct jcv From 3d6db8f55ffbca8e0f7a1726a111d204af9fd441 Mon Sep 17 00:00:00 2001 From: Seb James Date: Sat, 29 Nov 2025 15:49:24 +0000 Subject: [PATCH 37/41] Adds the loop sanity count to avoid getting bitten in the future --- mplot/jcvoronoi/jc_voronoi.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 9563bf50..c37ca57d 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -8,6 +8,7 @@ #pragma once #include // malloc() & free() +#include // one sanity message #include #include #include // assert() @@ -1131,7 +1132,13 @@ namespace jcv next = site->edges; } - while( current && next ) + // Need a sanity check, as this while loop can go infinite if earlier code fails to + // generate the Voronoi diagram correctly. We usually go 5 or 6 times around the while, + // so if we get to 1024 we're probably in an interminable loop. + constexpr int loopcount_thresh = 1024; + int loopcount = 0; + + while (current && next && loopcount < loopcount_thresh) { int current_edge_flags = get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); if( current_edge_flags && !point_eq(¤t->pos[1], &next->pos[0])) @@ -1195,6 +1202,10 @@ namespace jcv if( !next ) next = site->edges; } + ++loopcount; + if (loopcount > 1000) { + std::cout << "Too many loops. Thi can be caused by numerical precision errors when using T==float on some sets of points\n"; + } } } From 3523855370079cd19fc06e9d217c93398f27b58d Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 1 Dec 2025 10:58:54 +0000 Subject: [PATCH 38/41] Enforce house style --- mplot/jcvoronoi/jc_voronoi.h | 922 +++++++++++++++-------------------- 1 file changed, 392 insertions(+), 530 deletions(-) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index c37ca57d..549b63a2 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -5,9 +5,15 @@ // Copyright (c) 2015-2023 Mathias Westerdahl // For LICENSE (MIT), USAGE or HISTORY, see bottom of file +// This version has been re-written by Seb into a templated C++ style, to allow easy choice between +// the use of single or double precision floating point values (the type T). It has also been +// namespaced (jcv) so that type names look like jcv::site instead of jcv_site; jcv::edge rather +// than jcv_edge, and so on. + #pragma once -#include // malloc() & free() +#include // qsort(), malloc() & free(). Seb hasn't altered the C-style memory allocation + // used when diagrams are generated #include // one sanity message #include #include @@ -26,47 +32,49 @@ namespace jcv { #pragma pack(push, 1) + // Seb has replaced the original point struct with use of his fixed-size mathematical vector + // class, sm::vec template using point = sm::vec; - // fwd declar graphpedge + // forward-declare graphedge template struct graphedge; template struct site { - point p; - int index; // Index into the original list of points - graphedge* edges; // The half edges owned by the cell + point p; + int index; // Index into the original list of points + graphedge* edges; // The half edges owned by the cell }; // The coefficients a, b and c are from the general line equation: ax * by + c = 0 template struct edge { - struct edge* next; - site* sites[2]; - point pos[2]; - T a; - T b; - T c; + struct edge* next; + site* sites[2]; + point pos[2]; + T a; + T b; + T c; }; template struct graphedge { - struct graphedge* next; - struct edge* edge_; - struct site* neighbor; - point pos[2]; - T angle; + struct graphedge* next; + struct edge* edge_; + struct site* neighbor; + point pos[2]; + T angle; }; template struct delauney_iter { - const edge* sentinel; - const edge* current; + const edge* sentinel; + const edge* current; }; template @@ -80,8 +88,8 @@ namespace jcv template struct rect { - point min; - point max; + point min; + point max; }; // Forward declare context_internal for the std::function @@ -94,11 +102,13 @@ namespace jcv std::function* _clipper, const point p)> test_fn; // Given an edge, and the clipper, calculates the e->pos[0] and e->pos[1] // Returns 0 if not successful - std::function* _clipper, edge* e)> clip_fn; + std::function* _clipper, edge* e)> clip_fn; // Given the clipper, the site and the last edge, // closes any gaps in the polygon by adding new edges that follow the bounding shape // The internal context is use when allocating new edges. - std::function* _clipper, context_internal* allocator, site* s)> fill_fn; + std::function* _clipper, + context_internal* allocator, site* s)> fill_fn; + point min; // The bounding rect min point max; // The bounding rect max void* ctx; // User defined context @@ -138,39 +148,39 @@ namespace jcv template struct context_internal { - void* mem; - edge* edges; - halfedge* beachline_start; - halfedge* beachline_end; - halfedge* last_inserted; - priorityqueue* eventqueue; - - site* sites; - site* bottomsite; - int numsites; - int currentsite; - int _padding; - - memoryblock* memblocks; - edge* edgepool; - halfedge* halfedgepool; - void** eventmem; - clipper clipper_; - - void* memctx; // Given by the user - std::function alloc; - std::function free; - - rect rect_; + void* mem; + edge* edges; + halfedge* beachline_start; + halfedge* beachline_end; + halfedge* last_inserted; + priorityqueue* eventqueue; + + site* sites; + site* bottomsite; + int numsites; + int currentsite; + int _padding; + + memoryblock* memblocks; + edge* edgepool; + halfedge* halfedgepool; + void** eventmem; + clipper clipper_; + + void* memctx; // Given by the user + std::function alloc; + std::function free; + + rect rect_; }; template struct diagram { - context_internal* internal; - int numsites; - point min; - point max; + context_internal* internal; + int numsites; + point min; + point max; }; #pragma pack(pop) @@ -191,32 +201,31 @@ namespace jcv static constexpr T invalid_value = std::numeric_limits::lowest(); - // App specific equality - static int T_eq(T a, T b) + // App specific equality of scalars + static int equal (T a, T b) { return std::abs(a - b) < std::numeric_limits::epsilon(); } + + // Vector equality + static int equal (const point* pt1, const point* pt2) { - return std::abs(a - b) < std::numeric_limits::epsilon(); + return equal (pt1->y(), pt2->y()) && equal (pt1->x(), pt2->x()); } - // point - static int point_cmp(const void* p1, const void* p2) + // point (i.e. vector) comparison, accepting void pointers + static int point_cmp (const void* p1, const void* p2) { const point* s1 = static_cast*>(p1); const point* s2 = static_cast*>(p2); return (s1->y() != s2->y()) ? (s1->y() < s2->y() ? -1 : 1) : (s1->x() < s2->x() ? -1 : 1); } - static int point_less (const point* pt1, const point* pt2 ) + // Return app-specific pt1 < pt2 operation between vectors + static int lessthan (const point* pt1, const point* pt2) { return (pt1->y() == pt2->y()) ? (pt1->x() < pt2->x()) : pt1->y() < pt2->y(); } - static int point_eq( const point* pt1, const point* pt2 ) - { - return T_eq(pt1->y(), pt2->y()) && T_eq(pt1->x(), pt2->x()); - } - [[maybe_unused]] - static int point_on_box_edge( const point* pt, const point* min, const point* max ) + static int point_on_box_edge (const point* pt, const point* min, const point* max) { return pt->x() == min->x() || pt->y() == min->y() || pt->x() == max->x() || pt->y() == max->y(); } @@ -233,75 +242,81 @@ namespace jcv static const int CORNER_BOTTOM_RIGHT = 3; static const int CORNER_TOP_RIGHT = 4; - static int get_edge_flags( const point* pt, const point* min, const point* max ) + static int get_edge_flags (const point* pt, const point* min, const point* max) { int flags = 0; - if (pt->x() == min->x()) flags |= EDGE_LEFT; - else if (pt->x() == max->x()) flags |= EDGE_RIGHT; - if (pt->y() == min->y()) flags |= EDGE_BOTTOM; - else if (pt->y() == max->y()) flags |= EDGE_TOP; + if (pt->x() == min->x()) { + flags |= EDGE_LEFT; + } else if (pt->x() == max->x()) { + flags |= EDGE_RIGHT; + } + if (pt->y() == min->y()) { + flags |= EDGE_BOTTOM; + } else if (pt->y() == max->y()) { + flags |= EDGE_TOP; + } return flags; } - static int edge_flags_to_corner(int edge_flags) + static int edge_flags_to_corner (int edge_flags) { -#define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags ) return _RETVAL - TEST_FLAGS(EDGE_TOP|EDGE_LEFT, CORNER_TOP_LEFT); - TEST_FLAGS(EDGE_TOP|EDGE_RIGHT, CORNER_TOP_RIGHT); - TEST_FLAGS(EDGE_BOTTOM|EDGE_LEFT, CORNER_BOTTOM_LEFT); - TEST_FLAGS(EDGE_BOTTOM|EDGE_RIGHT, CORNER_BOTTOM_RIGHT); +#define TEST_FLAGS(_FLAGS, _RETVAL) if ( (_FLAGS) == edge_flags) return _RETVAL + TEST_FLAGS (EDGE_TOP|EDGE_LEFT, CORNER_TOP_LEFT); + TEST_FLAGS (EDGE_TOP|EDGE_RIGHT, CORNER_TOP_RIGHT); + TEST_FLAGS (EDGE_BOTTOM|EDGE_LEFT, CORNER_BOTTOM_LEFT); + TEST_FLAGS (EDGE_BOTTOM|EDGE_RIGHT, CORNER_BOTTOM_RIGHT); #undef TEST_FLAGS return 0; } [[maybe_unused]] static int is_corner(int corner) { return corner != 0; } - static int corner_rotate_90(int corner) + static int corner_rotate_90 (int corner) { corner--; corner = (corner+1)%4; return corner + 1; } - static point corner_to_point(int corner, const point* min, const point* max ) + + static point corner_to_point (int corner, const point* min, const point* max) { point p; if (corner == CORNER_TOP_LEFT) { p[0] = min->x(); p[1] = max->y(); } else if (corner == CORNER_TOP_RIGHT) { p[0] = max->x(); p[1] = max->y(); } else if (corner == CORNER_BOTTOM_LEFT) { p[0] = min->x(); p[1] = min->y(); } else if (corner == CORNER_BOTTOM_RIGHT) { p[0] = max->x(); p[1] = min->y(); } - else { p[0] = invalid_value; p[1] = invalid_value; } + else { p[0] = invalid_value; p[1] = invalid_value; } return p; } - static T point_dist_sq( const point* pt1, const point* pt2) + static T point_dist_sq (const point* pt1, const point* pt2) { T diffx = pt1->x() - pt2->x(); T diffy = pt1->y() - pt2->y(); return diffx * diffx + diffy * diffy; } - static T point_dist( const point* pt1, const point* pt2 ) + static T point_dist (const point* pt1, const point* pt2) { return std::sqrt (point_dist_sq (pt1, pt2)); } // Uses free (or the registered custom free function) - static void diagram_free( diagram* d ) + static void diagram_free (diagram* d) { context_internal* internal = d->internal; void* memctx = internal->memctx; - while(internal->memblocks) - { + while (internal->memblocks) { memoryblock* p = internal->memblocks; internal->memblocks = internal->memblocks->next; - internal->free( memctx, p ); + internal->free (memctx, p); } - internal->free( memctx, internal->mem ); + internal->free (memctx, internal->mem); } // Returns an array of sites, where each index is the same as the original input point array. - static const site* diagram_get_sites( const diagram* diagram ) + static const site* diagram_get_sites (const diagram* diagram) { return diagram->internal->sites; } @@ -310,10 +325,10 @@ namespace jcv const site* diagram_get_sites() { return diagram_get_sites (&this->diagram); } // Iterates over a list of edges, skipping invalid edges (where p0==p1) - const edge* diagram_get_next_edge( const edge* _edge ) + const edge* diagram_get_next_edge (const edge* _edge) { const edge* e = _edge->next; - while (e != 0 && point_eq(&e->pos[0], &e->pos[1])) { + while (e != 0 && equal (&e->pos[0], &e->pos[1])) { e = e->next; } return e; @@ -322,43 +337,39 @@ namespace jcv // Returns a linked list of all the voronoi edges excluding the ones that lie on the borders of // the bounding box. For a full list of edges, you need to iterate over the sites, and their // graph edges. - const edge* diagram_get_edges( const diagram* diagram ) + const edge* diagram_get_edges (const diagram* diagram) { edge e; e.next = diagram->internal->edges; - return diagram_get_next_edge(&e); + return diagram_get_next_edge (&e); } // Creates an iterator over the delauney edges of a voronoi diagram - void delauney_begin( const diagram* diagram, delauney_iter* iter ) + void delauney_begin (const diagram* diagram, delauney_iter* iter) { iter->current = 0; - iter->sentinel = diagram_get_edges(diagram); + iter->sentinel = diagram_get_edges (diagram); } // Steps the iterator and returns the next edge Returns 0 when there are no more edges - int delauney_next( delauney_iter* iter, delauney_edge* next ) + int delauney_next (delauney_iter* iter, delauney_edge* next) { - if (iter->sentinel) - { + if (iter->sentinel) { iter->current = iter->sentinel; iter->sentinel = 0; - } - else { + } else { // Note: If we use the raw edges, we still get a proper delauney triangulation // However, the result looks less relevant to the cells contained within the bounding box // E.g. some cells that look isolated from each other, suddenly still are connected, // because they share an edge outside of the bounding box - iter->current = diagram_get_next_edge(iter->current); + iter->current = diagram_get_next_edge (iter->current); } - while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0)) - { + while (iter->current && (iter->current->sites[0] == 0 || iter->current->sites[1] == 0)) { iter->current = diagram_get_next_edge(iter->current); } - if (!iter->current) - return 0; + if (!iter->current) { return 0; } next->edge_ = iter->current; next->sites[0] = next->edge_->sites[0]; @@ -368,17 +379,16 @@ namespace jcv return 1; } - static void* align(void* value, size_t alignment) + static void* align (void* value, size_t alignment) { return (void*) (((uintptr_t) value + (alignment-1)) & ~(alignment-1)); } - static void* alloc(context_internal* internal, size_t size) + static void* alloc (context_internal* internal, size_t size) { - if( !internal->memblocks || internal->memblocks->sizefree < (size+sizeof(void*)) ) - { + if (!internal->memblocks || internal->memblocks->sizefree < (size + sizeof(void*))) { size_t blocksize = 16 * 1024; - memoryblock* block = (memoryblock*)internal->alloc( internal->memctx, blocksize ); + memoryblock* block = (memoryblock*)internal->alloc (internal->memctx, blocksize); size_t offset = sizeof(memoryblock); block->sizefree = blocksize - offset; block->next = internal->memblocks; @@ -386,54 +396,52 @@ namespace jcv internal->memblocks = block; } void* p_raw = internal->memblocks->memory; - void* p_aligned = align(p_raw, sizeof(void*)); + void* p_aligned = align (p_raw, sizeof(void*)); size += (uintptr_t)p_aligned - (uintptr_t)p_raw; internal->memblocks->memory += size; internal->memblocks->sizefree -= size; return p_aligned; } - static edge* alloc_edge(context_internal* internal) + static edge* alloc_edge (context_internal* internal) { - return (edge*)alloc(internal, sizeof(edge)); + return (edge*) alloc (internal, sizeof(edge)); } - static halfedge* alloc_halfedge(context_internal* internal) + static halfedge* alloc_halfedge (context_internal* internal) { - if( internal->halfedgepool ) - { + if (internal->halfedgepool) { halfedge* edge = internal->halfedgepool; internal->halfedgepool = internal->halfedgepool->right; return edge; } - - return (halfedge*)alloc(internal, sizeof(halfedge)); + return (halfedge*) alloc (internal, sizeof(halfedge)); } - static graphedge* alloc_graphedge(context_internal* internal) + static graphedge* alloc_graphedge (context_internal* internal) { - return (graphedge*)alloc(internal, sizeof(graphedge)); + return (graphedge*) alloc (internal, sizeof(graphedge)); } - static void* alloc_fn(void* memctx, size_t size) + static void* alloc_fn (void* memctx, size_t size) { (void)memctx; - return malloc(size); + return malloc (size); } - static void free_fn(void* memctx, void* p) + static void free_fn (void* memctx, void* p) { (void)memctx; - free(p); + free (p); } // edge methods - static int is_valid(const point* p) + static int is_valid (const point* p) { return (p->x() != invalid_value || p->y() != invalid_value) ? 1 : 0; } - static void edge_create(edge* e, site* s1, site* s2) + static void edge_create (edge* e, site* s1, site* s2) { e->next = 0; e->sites[0] = s1; @@ -456,39 +464,36 @@ namespace jcv // // Move to the mid point // T mx = s1->p[0] + dx * T(0.5); // T my = s1->p[1] + dy * T(0.5); - // T pc = ( pa * mx + pb * my ); + // T pc = (pa * mx + pb * my); T dx = s2->p[0] - s1->p[0]; T dy = s2->p[1] - s1->p[1]; int dx_is_larger = (dx*dx) > (dy*dy); // instead of fabs // Simplify it, using dx and dy - e->c = dx * (s1->p[0] + dx * (T)0.5) + dy * (s1->p[1] + dy * (T)0.5); + e->c = dx * (s1->p[0] + dx * T{0.5}) + dy * (s1->p[1] + dy * T{0.5}); - if( dx_is_larger ) - { - e->a = (T)1; + if (dx_is_larger) { + e->a = T{1}; e->b = dy / dx; e->c /= dx; - } - else - { + } else { e->a = dx / dy; - e->b = (T)1; + e->b = T{1}; e->c /= dy; } } // CLIPPING - static int boxshape_test(const clipper* clipper, const point p) + static int boxshape_test (const clipper* clipper, const point p) { - return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] && - p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; + return p[0] >= clipper->min[0] && p[0] <= clipper->max[0] + && p[1] >= clipper->min[1] && p[1] <= clipper->max[1]; } // The line equation: ax + by + c = 0 // see edge_create - static int boxshape_clip(const clipper* clipper, edge* e) + static int boxshape_clip (const clipper* clipper, edge* e) { T pxmin = clipper->min[0]; T pxmax = clipper->max[0]; @@ -498,104 +503,67 @@ namespace jcv T x1, y1, x2, y2; point* s1; point* s2; - if (e->a == (T)1 && e->b >= (T)0) - { + if (e->a == T{1} && e->b >= T{0}) { s1 = is_valid(&e->pos[1]) ? &e->pos[1] : 0; s2 = is_valid(&e->pos[0]) ? &e->pos[0] : 0; - } - else - { + } else { s1 = is_valid(&e->pos[0]) ? &e->pos[0] : 0; s2 = is_valid(&e->pos[1]) ? &e->pos[1] : 0; } - if (e->a == (T)1) // delta x is larger - { + if (e->a == T{1}) { // delta x is larger y1 = pymin; - if (s1 != 0 && s1->y() > pymin) - { - y1 = s1->y(); - } - if( y1 > pymax ) - { - y1 = pymax; - } + if (s1 != 0 && s1->y() > pymin) { y1 = s1->y(); } + if (y1 > pymax) { y1 = pymax; } x1 = e->c - e->b * y1; y2 = pymax; - if (s2 != 0 && s2->y() < pymax) - y2 = s2->y(); + if (s2 != 0 && s2->y() < pymax) { y2 = s2->y(); } - if( y2 < pymin ) - { - y2 = pymin; - } + if (y2 < pymin) { y2 = pymin; } x2 = (e->c) - (e->b) * y2; // Never occurs according to lcov - // if( ((x1 > pxmax) & (x2 > pxmax)) | ((x1 < pxmin) & (x2 < pxmin)) ) + // if (((x1 > pxmax) & (x2 > pxmax)) | ((x1 < pxmin) & (x2 < pxmin))) // { // return 0; // } - if (x1 > pxmax) - { + if (x1 > pxmax) { x1 = pxmax; y1 = (e->c - x1) / e->b; - } - else if (x1 < pxmin) - { + } else if (x1 < pxmin) { x1 = pxmin; y1 = (e->c - x1) / e->b; } - if (x2 > pxmax) - { + if (x2 > pxmax) { x2 = pxmax; y2 = (e->c - x2) / e->b; - } - else if (x2 < pxmin) - { + } else if (x2 < pxmin) { x2 = pxmin; y2 = (e->c - x2) / e->b; } - } - else // delta y is larger - { + + } else { // delta y is larger + x1 = pxmin; - if( s1 != 0 && s1->x() > pxmin ) - x1 = s1->x(); - if( x1 > pxmax ) - { - x1 = pxmax; - } + if (s1 != 0 && s1->x() > pxmin) { x1 = s1->x(); } + if (x1 > pxmax) { x1 = pxmax; } y1 = e->c - e->a * x1; x2 = pxmax; - if( s2 != 0 && s2->x() < pxmax ) - x2 = s2->x(); - if( x2 < pxmin ) - { - x2 = pxmin; - } + if (s2 != 0 && s2->x() < pxmax) { x2 = s2->x(); } + if (x2 < pxmin) { x2 = pxmin; } y2 = e->c - e->a * x2; // Never occurs according to lcov - // if( ((y1 > pymax) & (y2 > pymax)) | ((y1 < pymin) & (y2 < pymin)) ) - // { - // return 0; - // } - if( y1 > pymax ) - { + // if (((y1 > pymax) & (y2 > pymax)) | ((y1 < pymin) & (y2 < pymin))) { return 0; } + if (y1 > pymax) { y1 = pymax; x1 = (e->c - y1) / e->a; - } - else if( y1 < pymin ) - { + } else if (y1 < pymin) { y1 = pymin; x1 = (e->c - y1) / e->a; } - if( y2 > pymax ) - { + if (y2 > pymax) { y2 = pymax; x2 = (e->c - y2) / e->a; - } - else if( y2 < pymin ) - { + } else if (y2 < pymin) { y2 = pymin; x2 = (e->c - y2) / e->a; } @@ -612,22 +580,22 @@ namespace jcv // The line equation: ax + by + c = 0 // see edge_create - static int edge_clipline(context_internal* internal, edge* e) + static int edge_clipline (context_internal* internal, edge* e) { - return internal->clipper_.clip_fn(&internal->clipper_, e); + return internal->clipper_.clip_fn (&internal->clipper_, e); } - static edge* edge_new(context_internal* internal, site* s1, site* s2) + static edge* edge_new (context_internal* internal, site* s1, site* s2) { - edge* e = alloc_edge(internal); - edge_create(e, s1, s2); + edge* e = alloc_edge (internal); + edge_create (e, s1, s2); return e; } // halfedge - static void halfedge_link(halfedge* edge, halfedge* newedge) + static void halfedge_link (halfedge* edge, halfedge* newedge) { newedge->left = edge; newedge->right = edge->right; @@ -635,7 +603,7 @@ namespace jcv edge->right = newedge; } - static void halfedge_unlink(halfedge* he) + static void halfedge_unlink (halfedge* he) { he->left->right = he->right; he->right->left = he->left; @@ -643,9 +611,9 @@ namespace jcv he->right = 0; } - static halfedge* halfedge_new(context_internal* internal, edge* e, int direction) + static halfedge* halfedge_new (context_internal* internal, edge* e, int direction) { - halfedge* he = alloc_halfedge(internal); + halfedge* he = alloc_halfedge (internal); he->edge_ = e; he->left = 0; he->right = 0; @@ -657,65 +625,53 @@ namespace jcv return he; } - static void halfedge_delete(context_internal* internal, halfedge* he) + static void halfedge_delete (context_internal* internal, halfedge* he) { he->right = internal->halfedgepool; internal->halfedgepool = he; } - static site* halfedge_leftsite(const halfedge* he) + static site* halfedge_leftsite (const halfedge* he) { return he->edge_->sites[he->direction]; } - static site* halfedge_rightsite(const halfedge* he) + static site* halfedge_rightsite (const halfedge* he) { return he->edge_ ? he->edge_->sites[1 - he->direction] : 0; } - static int halfedge_rightof(const halfedge* he, const point* p) + static int halfedge_rightof (const halfedge* he, const point* p) { const edge* e = he->edge_; const site* topsite = e->sites[1]; int right_of_site = (p->x() > topsite->p[0]) ? 1 : 0; - if (right_of_site && he->direction == DIRECTION_LEFT) - return 1; - if (!right_of_site && he->direction == DIRECTION_RIGHT) - return 0; + if (right_of_site && he->direction == DIRECTION_LEFT) { return 1; } + if (!right_of_site && he->direction == DIRECTION_RIGHT) { return 0; } T dxp, dyp, dxs, t1, t2, t3, yl; int above; - if (e->a == (T)1) - { + if (e->a == T{1}) { dyp = p->y() - topsite->p[1]; dxp = p->x() - topsite->p[0]; int fast = 0; - if( (!right_of_site & (e->b < (T)0)) | (right_of_site & (e->b >= (T)0)) ) - { + if ((!right_of_site & (e->b < T{0})) | (right_of_site & (e->b >= T{0}))) { above = dyp >= e->b * dxp; fast = above; - } - else - { + } else { above = (p->x() + p->y() * e->b) > e->c; - if (e->b < (T)0) - above = !above; - if (!above) - fast = 1; + if (e->b < T{0}) { above = !above; } + if (!above) { fast = 1; } } - if (!fast) - { + if (!fast) { dxs = topsite->p[0] - e->sites[0]->p[0]; above = e->b * (dxp * dxp - dyp * dyp) - < dxs * dyp * ((T)1 + (T)2 * dxp / dxs + e->b * e->b); - if (e->b < (T)0) - above = !above; + < dxs * dyp * (T{1} + T{2} * dxp / dxs + e->b * e->b); + if (e->b < T{0}) { above = !above; } } - } - else // e->b == 1 - { + } else { // e->b == 1 yl = e->c - e->a * p->x(); t1 = p->y() - yl; t2 = p->x() - topsite->p[0]; @@ -727,21 +683,18 @@ namespace jcv // Keeps the priority queue sorted with events sorted in ascending order // Return 1 if the edges needs to be swapped - static int halfedge_compare( const halfedge* he1, const halfedge* he2 ) + static int halfedge_compare (const halfedge* he1, const halfedge* he2) { return (he1->y == he2->y) ? he1->vertex[0] > he2->vertex[0] : he1->y > he2->y; } - static int halfedge_intersect(const halfedge* he1, const halfedge* he2, point* out) + static int halfedge_intersect (const halfedge* he1, const halfedge* he2, point* out) { const edge* e1 = he1->edge_; const edge* e2 = he2->edge_; T d = e1->a * e2->b - e1->b * e2->a; - if(-edge_intersect_threshold < d && d < edge_intersect_threshold) - { - return 0; - } + if (-edge_intersect_threshold < d && d < edge_intersect_threshold) { return 0; } (*out)[0] = (e1->c * e2->b - e1->b * e2->c) / d; (*out)[1] = (e1->a * e2->c - e1->c * e2->a) / d; // I considered trying to determine the correct z here, but we don't have all the @@ -750,20 +703,17 @@ namespace jcv const edge* e; const halfedge* he; - if( point_less( &e1->sites[1]->p, &e2->sites[1]->p) ) - { + if (lessthan (&e1->sites[1]->p, &e2->sites[1]->p)) { he = he1; e = e1; - } - else - { + } else { he = he2; e = e2; } int right_of_site = out->x() >= e->sites[1]->p[0]; - if ((right_of_site && he->direction == DIRECTION_LEFT) || (!right_of_site && he->direction == DIRECTION_RIGHT)) - { + if ((right_of_site && he->direction == DIRECTION_LEFT) + || (!right_of_site && he->direction == DIRECTION_RIGHT)) { return 0; } @@ -773,15 +723,12 @@ namespace jcv // Priority queue - static int pq_moveup(priorityqueue* pq, int pos) + static int pq_moveup (priorityqueue* pq, int pos) { halfedge** items = (halfedge**)pq->items; halfedge* node = items[pos]; - for( int parent = (pos >> 1); - pos > 1 && halfedge_compare(items[parent], node); - pos = parent, parent = parent >> 1) - { + for (int parent = (pos >> 1); pos > 1 && halfedge_compare(items[parent], node); pos = parent, parent = parent >> 1) { items[pos] = items[parent]; items[pos]->pqpos = pos; } @@ -791,25 +738,22 @@ namespace jcv return pos; } - static int pq_maxchild(priorityqueue* pq, int pos) + static int pq_maxchild (priorityqueue* pq, int pos) { int child = pos << 1; - if( child >= pq->numitems ) - return 0; + if (child >= pq->numitems) { return 0; } halfedge** items = (halfedge**)pq->items; - if( (child + 1) < pq->numitems && halfedge_compare(items[child], items[child+1]) ) - return child+1; + if ((child + 1) < pq->numitems && halfedge_compare (items[child], items[child+1])) { return child + 1; } return child; } - static int pq_movedown(priorityqueue* pq, int pos) + static int pq_movedown (priorityqueue* pq, int pos) { halfedge** items = (halfedge**)pq->items; halfedge* node = items[pos]; - int child = pq_maxchild(pq, pos); - while( child && halfedge_compare(node, items[child]) ) - { + int child = pq_maxchild (pq, pos); + while (child && halfedge_compare (node, items[child])) { items[pos] = items[child]; items[pos]->pqpos = pos; pos = child; @@ -821,27 +765,24 @@ namespace jcv return pos; } - static void pq_create(priorityqueue* pq, int capacity, void** buffer) + static void pq_create (priorityqueue* pq, int capacity, void** buffer) { pq->maxnumitems = capacity; pq->numitems = 1; pq->items = buffer; } - static int pq_empty(priorityqueue* pq) - { - return pq->numitems == 1 ? 1 : 0; - } + static int pq_empty (priorityqueue* pq) { return pq->numitems == 1 ? 1 : 0; } - static int pq_push(priorityqueue* pq, void* node) + static int pq_push (priorityqueue* pq, void* node) { - assert(pq->numitems < pq->maxnumitems); + assert (pq->numitems < pq->maxnumitems); int n = pq->numitems++; pq->items[n] = node; return pq_moveup(pq, n); } - static void* pq_pop(priorityqueue* pq) + static void* pq_pop (priorityqueue* pq) { void* node = pq->items[1]; pq->items[1] = pq->items[--pq->numitems]; @@ -849,234 +790,186 @@ namespace jcv return node; } - static void* pq_top(priorityqueue* pq) - { - return pq->items[1]; - } + static void* pq_top (priorityqueue* pq) { return pq->items[1]; } - static void pq_remove(priorityqueue* pq, halfedge* node) + static void pq_remove (priorityqueue* pq, halfedge* node) { - if( pq->numitems == 1 ) - return; + if (pq->numitems == 1) { return; } int pos = node->pqpos; - if( pos == 0 ) - return; + if (pos == 0) { return; } halfedge** items = (halfedge**)pq->items; items[pos] = items[--pq->numitems]; - if( halfedge_compare( node, items[pos] ) ) - pq_moveup( pq, pos ); - else - pq_movedown( pq, pos ); + if (halfedge_compare (node, items[pos])) { + pq_moveup (pq, pos); + } else { + pq_movedown (pq, pos); + } node->pqpos = pos; } // internal functions - static site* nextsite(context_internal* internal) + static site* nextsite (context_internal* internal) { return (internal->currentsite < internal->numsites) ? &internal->sites[internal->currentsite++] : 0; } - static halfedge* get_edge_above_x(context_internal* internal, const point* p) + static halfedge* get_edge_above_x (context_internal* internal, const point* p) { // Gets the arc on the beach line at the x coordinate (i.e. right above the new site event) // A good guess it's close by (Can be optimized) halfedge* he = internal->last_inserted; - if( !he ) - { - if( p->x() < (internal->rect_.max[0] - internal->rect_.min[0]) / 2 ) - he = internal->beachline_start; - else - he = internal->beachline_end; + if (!he) { + if (p->x() < (internal->rect_.max[0] - internal->rect_.min[0]) / 2) { he = internal->beachline_start; } + else { he = internal->beachline_end; } } - // - if( he == internal->beachline_start || (he != internal->beachline_end && halfedge_rightof(he, p)) ) - { - do { - he = he->right; - } - while( he != internal->beachline_end && halfedge_rightof(he, p) ); + if (he == internal->beachline_start || (he != internal->beachline_end && halfedge_rightof(he, p))) { + do { he = he->right; } + while (he != internal->beachline_end && halfedge_rightof(he, p)); he = he->left; - } - else - { - do { - he = he->left; - } - while( he != internal->beachline_start && !halfedge_rightof(he, p) ); + } else { + do { he = he->left; } + while (he != internal->beachline_start && !halfedge_rightof(he, p)); } return he; } - static int check_circle_event(const halfedge* he1, const halfedge* he2, point* vertex) + static int check_circle_event (const halfedge* he1, const halfedge* he2, point* vertex) { edge* e1 = he1->edge_; edge* e2 = he2->edge_; - if( e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1] ) - { - return 0; - } + if (e1 == 0 || e2 == 0 || e1->sites[1] == e2->sites[1]) { return 0; } - return halfedge_intersect(he1, he2, vertex); + return halfedge_intersect (he1, he2, vertex); } - static void site_event(context_internal* internal, site* _site) + static void site_event (context_internal* internal, site* _site) { halfedge* left = get_edge_above_x(internal, &_site->p); halfedge* right = left->right; site* bottom = halfedge_rightsite(left); - if( !bottom ) - bottom = internal->bottomsite; + if (!bottom) { bottom = internal->bottomsite; } - edge* _edge = edge_new(internal, bottom, _site); + edge* _edge = edge_new (internal, bottom, _site); _edge->next = internal->edges; internal->edges = _edge; - halfedge* edge1 = halfedge_new(internal, _edge, DIRECTION_LEFT); - halfedge* edge2 = halfedge_new(internal, _edge, DIRECTION_RIGHT); + halfedge* edge1 = halfedge_new (internal, _edge, DIRECTION_LEFT); + halfedge* edge2 = halfedge_new (internal, _edge, DIRECTION_RIGHT); - halfedge_link(left, edge1); - halfedge_link(edge1, edge2); + halfedge_link (left, edge1); + halfedge_link (edge1, edge2); internal->last_inserted = right; point p; - if( check_circle_event( left, edge1, &p ) ) - { - pq_remove(internal->eventqueue, left); + if (check_circle_event (left, edge1, &p)) { + pq_remove (internal->eventqueue, left); left->vertex = p; - left->y = p[1] + point_dist(&_site->p, &p); + left->y = p[1] + point_dist (&_site->p, &p); pq_push(internal->eventqueue, left); } - if( check_circle_event( edge2, right, &p ) ) - { + if (check_circle_event (edge2, right, &p)) { edge2->vertex = p; - edge2->y = p[1] + point_dist(&_site->p, &p); - pq_push(internal->eventqueue, edge2); + edge2->y = p[1] + point_dist (&_site->p, &p); + pq_push (internal->eventqueue, edge2); } } // https://cp-algorithms.com/geometry/oriented-triangle-area.html - static T determinant(const point* a, const point* b, const point* c) + static T determinant (const point* a, const point* b, const point* c) { return (b->x() - a->x())*(c->y() - a->y()) - (b->y() - a->y())*(c->x() - a->x()); } - static T calc_sort_metric(const site* _site, const graphedge* _edge) + static T calc_sort_metric (const site* _site, const graphedge* _edge) { // We take the average of the two points, since we can better distinguish between very small edges - constexpr T half = T{0.5}; - T x = (_edge->pos[0][0] + _edge->pos[1][0]) * half; - T y = (_edge->pos[0][1] + _edge->pos[1][1]) * half; + T x = (_edge->pos[0][0] + _edge->pos[1][0]) * T{0.5}; + T y = (_edge->pos[0][1] + _edge->pos[1][1]) * T{0.5}; T diffy = y - _site->p[1]; - T angle = std::atan2( diffy, x - _site->p[0] ); - if( diffy < 0 ) { - angle = angle + sm::mathconst::two_pi; - } + T angle = std::atan2 (diffy, x - _site->p[0]); + if (diffy < 0) { angle = angle + sm::mathconst::two_pi; } return angle; } - static int graphedge_eq(graphedge* a, graphedge* b) + static int graphedge_eq (graphedge* a, graphedge* b) { - return T_eq(a->angle, b->angle) && point_eq( &a->pos[0], &b->pos[0] ) && point_eq( &a->pos[1], &b->pos[1] ); + return equal (a->angle, b->angle) && equal (&a->pos[0], &b->pos[0]) && equal (&a->pos[1], &b->pos[1]); } - static void sortedges_insert(site* _site, graphedge* _edge) + static void sortedges_insert (site* _site, graphedge* _edge) { // Special case for the head end graphedge* prev = 0; - if (_site->edges == 0 || _site->edges->angle >= _edge->angle) - { + if (_site->edges == 0 || _site->edges->angle >= _edge->angle) { _edge->next = _site->edges; _site->edges = _edge; - } - else - { + } else { // Locate the node before the point of insertion graphedge* current = _site->edges; - while(current->next != 0 && current->next->angle < _edge->angle) - { - current = current->next; - } + while (current->next != 0 && current->next->angle < _edge->angle) { current = current->next; } prev = current; _edge->next = current->next; current->next = _edge; } // check to avoid duplicates - if (prev && graphedge_eq(prev, _edge)) - { + if (prev && graphedge_eq(prev, _edge)) { prev->next = _edge->next; - } - else if (_edge->next && graphedge_eq(_edge, _edge->next)) - { + } else if (_edge->next && graphedge_eq(_edge, _edge->next)) { _edge->next = _edge->next->next; } } - static void finishline(context_internal* internal, edge* e) + static void finishline (context_internal* internal, edge* e) { - if( !edge_clipline(internal, e) ) { - return; - } + if (!edge_clipline (internal, e)) { return; } // Make sure the graph edges are CCW - int flip = determinant(&e->sites[0]->p, &e->pos[0], &e->pos[1]) > (T)0 ? 0 : 1; - - for( int i = 0; i < 2; ++i ) - { - graphedge* ge = alloc_graphedge(internal); + int flip = determinant (&e->sites[0]->p, &e->pos[0], &e->pos[1]) > T{0} ? 0 : 1; + for (int i = 0; i < 2; ++i) { + graphedge* ge = alloc_graphedge (internal); ge->edge_ = e; ge->next = 0; ge->neighbor = e->sites[1-i]; ge->pos[flip] = e->pos[i]; ge->pos[1-flip] = e->pos[1-i]; ge->angle = calc_sort_metric(e->sites[i], ge); - - sortedges_insert( e->sites[i], ge ); + sortedges_insert (e->sites[i], ge); } } - static void endpos(context_internal* internal, edge* e, const point* p, int direction) + static void endpos (context_internal* internal, edge* e, const point* p, int direction) { e->pos[direction] = *p; - - if( !is_valid(&e->pos[1 - direction]) ) - return; - - finishline(internal, e); + if (!is_valid(&e->pos[1 - direction])) { return; } + finishline (internal, e); } - static void create_corner_edge(context_internal* internal, const site* site, graphedge* current, graphedge* gap) + static void create_corner_edge (context_internal* internal, const site* site, graphedge* current, graphedge* gap) { gap->neighbor = 0; gap->pos[0] = current->pos[1]; - if( current->pos[1][0] < internal->rect_.max[0] && current->pos[1][1] == internal->rect_.min[1] ) - { + if (current->pos[1][0] < internal->rect_.max[0] && current->pos[1][1] == internal->rect_.min[1]) { gap->pos[1][0] = internal->rect_.max[0]; gap->pos[1][1] = internal->rect_.min[1]; - } - else if( current->pos[1][0] > internal->rect_.min[0] && current->pos[1][1] == internal->rect_.max[1] ) - { + } else if (current->pos[1][0] > internal->rect_.min[0] && current->pos[1][1] == internal->rect_.max[1]) { gap->pos[1][0] = internal->rect_.min[0]; gap->pos[1][1] = internal->rect_.max[1]; - } - else if( current->pos[1][1] > internal->rect_.min[1] && current->pos[1][0] == internal->rect_.min[0] ) - { + } else if (current->pos[1][1] > internal->rect_.min[1] && current->pos[1][0] == internal->rect_.min[0]) { gap->pos[1][0] = internal->rect_.min[0]; gap->pos[1][1] = internal->rect_.min[1]; - } - else if( current->pos[1][1] < internal->rect_.max[1] && current->pos[1][0] == internal->rect_.max[0] ) - { + } else if (current->pos[1][1] < internal->rect_.max[1] && current->pos[1][0] == internal->rect_.max[0]) { gap->pos[1][0] = internal->rect_.max[0]; gap->pos[1][1] = internal->rect_.max[1]; } @@ -1084,9 +977,9 @@ namespace jcv gap->angle = calc_sort_metric(site, gap); } - static edge* create_gap_edge(context_internal* internal, site* site, graphedge* ge) + static edge* create_gap_edge (context_internal* internal, site* site, graphedge* ge) { - edge* edge = alloc_edge(internal); + edge* edge = alloc_edge (internal); edge->pos[0] = ge->pos[0]; edge->pos[1] = ge->pos[1]; edge->sites[0] = site; @@ -1097,34 +990,32 @@ namespace jcv return edge; } - static void boxshape_fillgaps(const clipper* clipper, context_internal* allocator, site* site) + static void boxshape_fillgaps (const clipper* clipper, context_internal* allocator, site* site) { // They're sorted CCW, so if the current->pos[1] != next->pos[0], then we have a gap graphedge* current = site->edges; - if( !current ) - { + if (!current) { // No edges, then it should be a single cell - assert( allocator->numsites == 1 ); + assert (allocator->numsites == 1); - graphedge* gap = alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge (allocator); gap->neighbor = 0; gap->pos[0] = clipper->min; gap->pos[1][0] = clipper->max[0]; gap->pos[1][1] = clipper->min[1]; gap->angle = calc_sort_metric(site, gap); gap->next = 0; - gap->edge_ = create_gap_edge(allocator, site, gap); + gap->edge_ = create_gap_edge (allocator, site, gap); current = gap; site->edges = gap; } graphedge* next = current->next; - if( !next ) - { - graphedge* gap = alloc_graphedge(allocator); + if (!next) { + graphedge* gap = alloc_graphedge (allocator); create_corner_edge(allocator, site, current, gap); - gap->edge_ = create_gap_edge(allocator, site, gap); + gap->edge_ = create_gap_edge (allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1138,11 +1029,10 @@ namespace jcv constexpr int loopcount_thresh = 1024; int loopcount = 0; - while (current && next && loopcount < loopcount_thresh) - { + while (current && next && loopcount < loopcount_thresh) { + int current_edge_flags = get_edge_flags(¤t->pos[1], &clipper->min, &clipper->max); - if( current_edge_flags && !point_eq(¤t->pos[1], &next->pos[0])) - { + if (current_edge_flags && !equal(¤t->pos[1], &next->pos[0])) { // Cases: // Current and Next on the same border // Current on one border, and Next on another border @@ -1150,29 +1040,24 @@ namespace jcv // Current on the corner, Next on another border (another corner in between) int next_edge_flags = get_edge_flags(&next->pos[0], &clipper->min, &clipper->max); - if (current_edge_flags & next_edge_flags) - { + if (current_edge_flags & next_edge_flags) { // Current and Next on the same border - graphedge* gap = alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge (allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = next->pos[0]; - gap->angle = calc_sort_metric(site, gap); - gap->edge_ = create_gap_edge(allocator, site, gap); + gap->angle = calc_sort_metric (site, gap); + gap->edge_ = create_gap_edge (allocator, site, gap); gap->next = current->next; current->next = gap; - } - else { + } else { // Current and Next on different borders - int corner_flag = edge_flags_to_corner(current_edge_flags); - if (corner_flag) - { + int corner_flag = edge_flags_to_corner (current_edge_flags); + if (corner_flag) { // we are already at one corner, so we need to find the next one - corner_flag = corner_rotate_90(corner_flag); - } - else - { + corner_flag = corner_rotate_90 (corner_flag); + } else { // we are on the middle of a border // we need to find the adjacent corner, following the borders CCW if (current_edge_flags == EDGE_TOP) { corner_flag = CORNER_TOP_LEFT; } @@ -1181,14 +1066,14 @@ namespace jcv else if (current_edge_flags == EDGE_RIGHT) { corner_flag = CORNER_TOP_RIGHT; } } - point corner = corner_to_point(corner_flag, &clipper->min, &clipper->max); + point corner = corner_to_point (corner_flag, &clipper->min, &clipper->max); - graphedge* gap = alloc_graphedge(allocator); + graphedge* gap = alloc_graphedge (allocator); gap->neighbor = 0; gap->pos[0] = current->pos[1]; gap->pos[1] = corner; gap->angle = calc_sort_metric(site, gap); - gap->edge_ = create_gap_edge(allocator, site, gap); + gap->edge_ = create_gap_edge (allocator, site, gap); gap->next = current->next; current->next = gap; @@ -1196,11 +1081,9 @@ namespace jcv } current = current->next; - if( current ) - { + if (current) { next = current->next; - if( !next ) - next = site->edges; + if (!next) { next = site->edges; } } ++loopcount; if (loopcount > 1000) { @@ -1211,24 +1094,20 @@ namespace jcv // Since the algorithm leaves gaps at the borders/corner, we want to fill them - static void fillgaps(diagram* diagram) + static void fillgaps (diagram* diagram) { context_internal* internal = diagram->internal; - if (!internal->clipper_.fill_fn) - return; - - for( int i = 0; i < internal->numsites; ++i ) - { + if (!internal->clipper_.fill_fn) { return; } + for (int i = 0; i < internal->numsites; ++i) { site* site = &internal->sites[i]; - internal->clipper_.fill_fn(&internal->clipper_, internal, site); + internal->clipper_.fill_fn (&internal->clipper_, internal, site); } } - static void circle_event(context_internal* internal) + static void circle_event (context_internal* internal) { - halfedge* left = (halfedge*)pq_pop(internal->eventqueue); - + halfedge* left = (halfedge*)pq_pop (internal->eventqueue); halfedge* leftleft = left->left; halfedge* right = left->right; halfedge* rightright= right->right; @@ -1236,47 +1115,44 @@ namespace jcv site* top = halfedge_rightsite(right); point vertex = left->vertex; - endpos(internal, left->edge_, &vertex, left->direction); - endpos(internal, right->edge_, &vertex, right->direction); + endpos (internal, left->edge_, &vertex, left->direction); + endpos (internal, right->edge_, &vertex, right->direction); internal->last_inserted = rightright; - pq_remove(internal->eventqueue, right); - halfedge_unlink(left); - halfedge_unlink(right); - halfedge_delete(internal, left); - halfedge_delete(internal, right); + pq_remove (internal->eventqueue, right); + halfedge_unlink (left); + halfedge_unlink (right); + halfedge_delete (internal, left); + halfedge_delete (internal, right); int direction = DIRECTION_LEFT; - if( bottom->p[1] > top->p[1] ) - { + if (bottom->p[1] > top->p[1]) { site* temp = bottom; bottom = top; top = temp; direction = DIRECTION_RIGHT; } - edge* edge = edge_new(internal, bottom, top); + edge* edge = edge_new (internal, bottom, top); edge->next = internal->edges; internal->edges = edge; - halfedge* he = halfedge_new(internal, edge, direction); - halfedge_link(leftleft, he); - endpos(internal, edge, &vertex, DIRECTION_RIGHT - direction); + halfedge* he = halfedge_new (internal, edge, direction); + halfedge_link (leftleft, he); + endpos (internal, edge, &vertex, DIRECTION_RIGHT - direction); point p; - if( check_circle_event( leftleft, he, &p ) ) - { - pq_remove(internal->eventqueue, leftleft); + if (check_circle_event (leftleft, he, &p)) { + pq_remove (internal->eventqueue, leftleft); leftleft->vertex = p; - leftleft->y = p[1] + point_dist(&bottom->p, &p); - pq_push(internal->eventqueue, leftleft); + leftleft->y = p[1] + point_dist (&bottom->p, &p); + pq_push (internal->eventqueue, leftleft); } - if( check_circle_event( he, rightright, &p ) ) - { + if (check_circle_event (he, rightright, &p)) { he->vertex = p; - he->y = p[1] + point_dist(&bottom->p, &p); - pq_push(internal->eventqueue, he); + he->y = p[1] + point_dist (&bottom->p, &p); + pq_push (internal->eventqueue, he); } } @@ -1286,23 +1162,23 @@ namespace jcv void** voidpp; } cast_align_struct; - static void rect_union(rect* rect, const point* p) + static void rect_union (rect* rect, const point* p) { - rect->min[0] = std::min(rect->min[0], p->x()); - rect->min[1] = std::min(rect->min[1], p->y()); - rect->max[0] = std::max(rect->max[0], p->x()); - rect->max[1] = std::max(rect->max[1], p->y()); + rect->min[0] = std::min (rect->min[0], p->x()); + rect->min[1] = std::min (rect->min[1], p->y()); + rect->max[0] = std::max (rect->max[0], p->x()); + rect->max[1] = std::max (rect->max[1], p->y()); } - static void rect_round(rect* rect) + static void rect_round (rect* rect) { - rect->min[0] = std::floor(rect->min[0]); - rect->min[1] = std::floor(rect->min[1]); - rect->max[0] = std::ceil(rect->max[0]); - rect->max[1] = std::ceil(rect->max[1]); + rect->min[0] = std::floor (rect->min[0]); + rect->min[1] = std::floor (rect->min[1]); + rect->max[0] = std::ceil (rect->max[0]); + rect->max[1] = std::ceil (rect->max[1]); } - static void rect_inflate(rect* rect, T amount) + static void rect_inflate (rect* rect, T amount) { rect->min[0] -= amount; rect->min[1] -= amount; @@ -1310,7 +1186,7 @@ namespace jcv rect->max[1] += amount; } - static int prune_duplicates(context_internal* internal, rect* _rect) + static int prune_duplicates (context_internal* internal, rect* _rect) { int num_sites = internal->numsites; site* sites = internal->sites; @@ -1321,26 +1197,24 @@ namespace jcv int offset = 0; // Prune duplicates first - for (int i = 0; i < num_sites; i++) - { + for (int i = 0; i < num_sites; i++) { const site* s = &sites[i]; // Remove duplicates, to avoid anomalies - if( i > 0 && point_eq(&s->p, &sites[i - 1].p) ) - { + if (i > 0 && equal (&s->p, &sites[i - 1].p)) { offset++; continue; } sites[i - offset] = sites[i]; - rect_union(&r, &s->p); + rect_union (&r, &s->p); } internal->numsites -= offset; if (_rect) { *_rect = r; } return offset; } - static int prune_not_in_shape(context_internal* internal, rect* _rect) + static int prune_not_in_shape (context_internal* internal, rect* _rect) { int num_sites = internal->numsites; site* sites = internal->sites; @@ -1350,26 +1224,24 @@ namespace jcv r.max[0] = r.max[1] = std::numeric_limits::lowest(); int offset = 0; - for (int i = 0; i < num_sites; i++) - { + for (int i = 0; i < num_sites; i++) { const site* s = &sites[i]; - if (!internal->clipper_.test_fn(&internal->clipper_, s->p)) - { + if (!internal->clipper_.test_fn (&internal->clipper_, s->p)) { offset++; continue; } sites[i - offset] = sites[i]; - rect_union(&r, &s->p); + rect_union (&r, &s->p); } internal->numsites -= offset; if (_rect) { *_rect = r; } return offset; } - static context_internal* alloc_internal(int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) + static context_internal* alloc_internal (int num_points, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn) { // Interesting limits from Euler's equation // Slide 81: https://courses.cs.washington.edu/courses/csep521/01au/lectures/lecture10slides.pdf @@ -1378,11 +1250,11 @@ namespace jcv size_t sitessize = (size_t)num_points * sizeof(site); size_t memsize = sizeof(priorityqueue) + eventssize + sitessize + sizeof(context_internal) + 16u; // 16 bytes padding for alignment - char* originalmem = (char*)allocfn(userallocctx, memsize); - memset(originalmem, 0, memsize); + char* originalmem = (char*)allocfn (userallocctx, memsize); + memset (originalmem, 0, memsize); // align memory - char* mem = (char*)align(originalmem, sizeof(void*)); + char* mem = (char*)align (originalmem, sizeof(void*)); context_internal* internal = (context_internal*)mem; mem += sizeof(context_internal); @@ -1391,20 +1263,20 @@ namespace jcv internal->alloc = allocfn; internal->free = freefn; - mem = (char*)align(mem, sizeof(void*)); + mem = (char*)align (mem, sizeof(void*)); internal->sites = (site*) mem; mem += sitessize; - mem = (char*)align(mem, sizeof(void*)); + mem = (char*)align (mem, sizeof(void*)); internal->eventqueue = (priorityqueue*)mem; mem += sizeof(priorityqueue); - assert( ((uintptr_t)mem & (sizeof(void*)-1)) == 0 ); + assert (((uintptr_t)mem & (sizeof(void*)-1)) == 0); cast_align_struct tmp; tmp.charp = mem; internal->eventmem = tmp.voidpp; - assert((mem+eventssize) <= (originalmem+memsize)); + assert ((mem+eventssize) <= (originalmem+memsize)); return internal; } @@ -1414,13 +1286,12 @@ namespace jcv const rect* _rect, const clipper* _clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* d) { - if( d->internal ) - diagram_free( d ); + if (d->internal) { diagram_free (d); } - context_internal* internal = alloc_internal(num_points, userallocctx, allocfn, freefn); + context_internal* internal = alloc_internal (num_points, userallocctx, allocfn, freefn); - internal->beachline_start = halfedge_new(internal, 0, 0); - internal->beachline_end = halfedge_new(internal, 0, 0); + internal->beachline_start = halfedge_new (internal, 0, 0); + internal->beachline_end = halfedge_new (internal, 0, 0); internal->beachline_start->left = 0; internal->beachline_start->right = internal->beachline_end; @@ -1429,20 +1300,19 @@ namespace jcv internal->last_inserted = 0; - int max_num_events = num_points*2; // beachline can have max 2*n-5 parabolas - pq_create(internal->eventqueue, max_num_events, (void**)internal->eventmem); + int max_num_events = num_points * 2; // beachline can have max 2*n-5 parabolas + pq_create (internal->eventqueue, max_num_events, (void**)internal->eventmem); internal->numsites = num_points; site* sites = internal->sites; - for( int i = 0; i < num_points; ++i ) - { + for (int i = 0; i < num_points; ++i) { sites[i].p = points[i]; sites[i].edges = 0; sites[i].index = i; } - qsort(sites, (size_t)num_points, sizeof(site), point_cmp); + qsort (sites, (size_t)num_points, sizeof(site), point_cmp); clipper box_clipper; if (_clipper == 0) { @@ -1457,16 +1327,15 @@ namespace jcv rect tmp_rect; tmp_rect.min[0] = tmp_rect.min[1] = std::numeric_limits::max(); tmp_rect.max[0] = tmp_rect.max[1] = std::numeric_limits::lowest(); - prune_duplicates(internal, &tmp_rect); + prune_duplicates (internal, &tmp_rect); // Prune using the test second - if (internal->clipper_.test_fn) - { + if (internal->clipper_.test_fn) { // e.g. used by the box clipper in the test_fn internal->clipper_.min = _rect ? _rect->min : tmp_rect.min; internal->clipper_.max = _rect ? _rect->max : tmp_rect.max; - prune_not_in_shape(internal, &tmp_rect); + prune_not_in_shape (internal, &tmp_rect); // The pruning might have made the bounding box smaller if (!_rect) { @@ -1487,43 +1356,36 @@ namespace jcv d->numsites = internal->numsites; d->internal = internal; - internal->bottomsite = nextsite(internal); + internal->bottomsite = nextsite (internal); priorityqueue* pq = internal->eventqueue; - site* site = nextsite(internal); + site* site = nextsite (internal); int finished = 0; - while( !finished ) - { + while (!finished) { + point lowest_pq_point; - if( !pq_empty(pq) ) - { - halfedge* he = (halfedge*)pq_top(pq); + if (!pq_empty (pq)) { + halfedge* he = (halfedge*)pq_top (pq); lowest_pq_point[0] = he->vertex[0]; lowest_pq_point[1] = he->y; } - if( site != 0 && (pq_empty(pq) || point_less(&site->p, &lowest_pq_point) ) ) - { - site_event(internal, site); - site = nextsite(internal); - } - else if( !pq_empty(pq) ) - { - circle_event(internal); - } - else - { + if (site != 0 && (pq_empty(pq) || lessthan (&site->p, &lowest_pq_point))) { + site_event (internal, site); + site = nextsite (internal); + } else if (!pq_empty (pq)) { + circle_event (internal); + } else { finished = 1; } } - for( halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right ) - { - finishline(internal, he->edge_); + for (halfedge* he = internal->beachline_start->right; he != internal->beachline_end; he = he->right) { + finishline (internal, he->edge_); } - fillgaps(d); + fillgaps (d); } /** @@ -1532,7 +1394,7 @@ namespace jcv * If rect is null, an automatic bounding box is calculated, with an extra padding of 10 units * All points will be culled against the bounding rect, and all edges will be clipped against it. */ - static void diagram_generate( int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* d ) + static void diagram_generate (int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* d) { diagram_generate_useralloc(num_points, points, rect, clipper, 0, alloc_fn, free_fn, d); } @@ -1643,13 +1505,13 @@ namespace jcv The api consists of these functions: - void diagram_generate( int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* diagram ); - void diagram_generate_useralloc( int num_points, const point* points, const rect* rect, const clipper* clipper, const clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* diagram ); - void diagram_free( diagram* diagram ); + void diagram_generate (int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* diagram); + void diagram_generate_useralloc (int num_points, const point* points, const rect* rect, const clipper* clipper, const clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* diagram); + void diagram_free (diagram* diagram); - const site* diagram_get_sites( const diagram* diagram ); - const edge* diagram_get_edges( const diagram* diagram ); - const edge* diagram_get_next_edge( const edge* edge ); + const site* diagram_get_sites (const diagram* diagram); + const edge* diagram_get_edges (const diagram* diagram); + const edge* diagram_get_next_edge (const edge* edge); An example usage: @@ -1670,14 +1532,14 @@ namespace jcv draw_edges(diagram); draw_cells(diagram); - diagram_free( &diagram ); + diagram_free (&diagram); } void draw_edges(const diagram* diagram) { // If all you need are the edges - const edge* edge = diagram_get_edges( diagram ); - while( edge ) + const edge* edge = diagram_get_edges (diagram); + while (edge) { draw_line(edge->pos[0], edge->pos[1]); edge = diagram_get_next_edge(edge); @@ -1688,15 +1550,15 @@ namespace jcv { // If you want to draw triangles, or relax the diagram, // you can iterate over the sites and get all edges easily - const site* sites = diagram_get_sites( diagram ); - for( int i = 0; i < diagram->numsites; ++i ) + const site* sites = diagram_get_sites (diagram); + for (int i = 0; i < diagram->numsites; ++i) { const site* site = &sites[i]; const graphedge* e = site->edges; - while( e ) + while (e) { - draw_triangle( site->p, e->pos[0], e->pos[1]); + draw_triangle (site->p, e->pos[0], e->pos[1]); e = e->next; } } @@ -1706,7 +1568,7 @@ namespace jcv void relax_points(const diagram* diagram, point* points) { const site* sites = diagram_get_sites(diagram); - for( int i = 0; i < diagram->numsites; ++i ) + for (int i = 0; i < diagram->numsites; ++i) { const site* site = &sites[i]; point sum = site->p; @@ -1714,7 +1576,7 @@ namespace jcv const graphedge* edge = site->edges; - while( edge ) + while (edge) { sum[0] += edge->pos[0][0]; sum[1] += edge->pos[0][1]; From b550b4dc90df930e5f41860d73c5a4dda03a85b3 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 1 Dec 2025 11:01:49 +0000 Subject: [PATCH 39/41] Restore original about message --- mplot/jcvoronoi/jc_voronoi.h | 84 +++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/mplot/jcvoronoi/jc_voronoi.h b/mplot/jcvoronoi/jc_voronoi.h index 549b63a2..ec7e85d4 100644 --- a/mplot/jcvoronoi/jc_voronoi.h +++ b/mplot/jcvoronoi/jc_voronoi.h @@ -1432,27 +1432,31 @@ namespace jcv } // namespace +/* + * The Original, pre-mathplot about message follows: + */ + /* ABOUT: A fast single file 2D voronoi diagram generator -(Pre mathplot) HISTORY: +HISTORY: 0.9 2023-01-22 - Modified the Delauney iterator creation api 0.8 2022-12-20 - Added fix for missing border edges More robust removal of duplicate graph edges Added iterator for Delauney edges 0.7 2019-10-25 - Added support for clipping against convex polygons - - Added EDGE_INTERSECT_THRESHOLD for edge intersections + - Added JCV_EDGE_INTERSECT_THRESHOLD for edge intersections - Fixed issue where the bounds calculation wasn’t considering all points - 0.6 2018-10-21 - Removed CEIL/FLOOR/FABS + 0.6 2018-10-21 - Removed JCV_CEIL/JCV_FLOOR/JCV_FABS - Optimizations: Fewer indirections, better beach head approximation 0.5 2018-10-14 - Fixed issue where the graph edge had the wrong edge assigned (issue #28) - - Fixed issue where a point was falsely passing the is_valid() test (issue #22) - - Fixed diagram_get_edges() so it now returns _all_ edges (issue #28) - - Added diagram_get_next_edge() to skip zero length edges (issue #10) - - Added defines CEIL/FLOOR/FLT_MAX for easier configuration + - Fixed issue where a point was falsely passing the jcv_is_valid() test (issue #22) + - Fixed jcv_diagram_get_edges() so it now returns _all_ edges (issue #28) + - Added jcv_diagram_get_next_edge() to skip zero length edges (issue #10) + - Added defines JCV_CEIL/JCV_FLOOR/JCV_FLT_MAX for easier configuration 0.4 2017-06-03 - Increased the max number of events that are preallocated 0.3 2017-04-16 - Added clipping box as input argument (Automatically calculated if needed) - Input points are pruned based on bounding box @@ -1505,78 +1509,80 @@ namespace jcv The api consists of these functions: - void diagram_generate (int num_points, const point* points, const rect* rect, const clipper* clipper, diagram* diagram); - void diagram_generate_useralloc (int num_points, const point* points, const rect* rect, const clipper* clipper, const clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, diagram* diagram); - void diagram_free (diagram* diagram); + void jcv_diagram_generate( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, jcv_diagram* diagram ); + void jcv_diagram_generate_useralloc( int num_points, const jcv_point* points, const jcv_rect* rect, const jcv_clipper* clipper, const jcv_clipper* clipper, void* userallocctx, FJCVAllocFn allocfn, FJCVFreeFn freefn, jcv_diagram* diagram ); + void jcv_diagram_free( jcv_diagram* diagram ); - const site* diagram_get_sites (const diagram* diagram); - const edge* diagram_get_edges (const diagram* diagram); - const edge* diagram_get_next_edge (const edge* edge); + const jcv_site* jcv_diagram_get_sites( const jcv_diagram* diagram ); + const jcv_edge* jcv_diagram_get_edges( const jcv_diagram* diagram ); + const jcv_edge* jcv_diagram_get_next_edge( const jcv_edge* edge ); An example usage: #define JC_VORONOI_IMPLEMENTATION // If you wish to use doubles - //#define REAL_TYPE double + //#define JCV_REAL_TYPE double + //#define JCV_ATAN2 atan2 + //#define JCV_FLT_MAX 1.7976931348623157E+308 #include "jc_voronoi.h" - void draw_edges(const diagram* diagram); - void draw_cells(const diagram* diagram); + void draw_edges(const jcv_diagram* diagram); + void draw_cells(const jcv_diagram* diagram); - void generate_and_draw(int numpoints, const point* points) + void generate_and_draw(int numpoints, const jcv_point* points) { - diagram diagram; - memset(&diagram, 0, sizeof(diagram)); - diagram_generate(count, points, 0, 0, &diagram); + jcv_diagram diagram; + memset(&diagram, 0, sizeof(jcv_diagram)); + jcv_diagram_generate(count, points, 0, 0, &diagram); draw_edges(diagram); draw_cells(diagram); - diagram_free (&diagram); + jcv_diagram_free( &diagram ); } - void draw_edges(const diagram* diagram) + void draw_edges(const jcv_diagram* diagram) { // If all you need are the edges - const edge* edge = diagram_get_edges (diagram); - while (edge) + const jcv_edge* edge = jcv_diagram_get_edges( diagram ); + while( edge ) { draw_line(edge->pos[0], edge->pos[1]); - edge = diagram_get_next_edge(edge); + edge = jcv_diagram_get_next_edge(edge); } } - void draw_cells(const diagram* diagram) + void draw_cells(const jcv_diagram* diagram) { // If you want to draw triangles, or relax the diagram, // you can iterate over the sites and get all edges easily - const site* sites = diagram_get_sites (diagram); - for (int i = 0; i < diagram->numsites; ++i) + const jcv_site* sites = jcv_diagram_get_sites( diagram ); + for( int i = 0; i < diagram->numsites; ++i ) { - const site* site = &sites[i]; + const jcv_site* site = &sites[i]; - const graphedge* e = site->edges; - while (e) + const jcv_graphedge* e = site->edges; + while( e ) { - draw_triangle (site->p, e->pos[0], e->pos[1]); + draw_triangle( site->p, e->pos[0], e->pos[1]); e = e->next; } } } // Here is a simple example of how to do the relaxations of the cells - void relax_points(const diagram* diagram, point* points) + void relax_points(const jcv_diagram* diagram, jcv_point* points) { - const site* sites = diagram_get_sites(diagram); - for (int i = 0; i < diagram->numsites; ++i) + const jcv_site* sites = jcv_diagram_get_sites(diagram); + for( int i = 0; i < diagram->numsites; ++i ) { - const site* site = &sites[i]; - point sum = site->p; + const jcv_site* site = &sites[i]; + jcv_point sum = site->p; int count = 1; - const graphedge* edge = site->edges; + const jcv_graphedge* edge = site->edges; - while (edge) + while( edge ) { sum[0] += edge->pos[0][0]; sum[1] += edge->pos[0][1]; From 4e08d0635c2077e3bcfd39ccd2af6257bb52b0bc Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 1 Dec 2025 11:19:11 +0000 Subject: [PATCH 40/41] Restore changes in SphereVisual --- mplot/SphereVisual.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mplot/SphereVisual.h b/mplot/SphereVisual.h index 47cc17f6..d8e0e543 100644 --- a/mplot/SphereVisual.h +++ b/mplot/SphereVisual.h @@ -1,6 +1,5 @@ /* - * You just want a sphere visual model? Here it is. This uses the beautiful icosahedral geodesic - * sphere primitive (computeSphereGeoFast) + * You just want a sphere visual model? Here it is. */ #pragma once @@ -11,7 +10,7 @@ namespace mplot { //! This class creates the vertices for a simple sphere in a 3D scene. - template + template class SphereVisual : public VisualModel { public: @@ -34,7 +33,7 @@ namespace mplot void initializeVertices() { - this->template computeSphereGeoFast (sm::vec{}, this->sphere_colour, this->radius); + this->computeSphere ({0,0,0}, this->sphere_colour, this->radius); } //! The radius of the sphere From 93db686210cfa6dbbb137caf5c4cb0bb6a620a36 Mon Sep 17 00:00:00 2001 From: Seb James Date: Mon, 1 Dec 2025 11:19:20 +0000 Subject: [PATCH 41/41] Tidyup --- mplot/compoundray/EyeVisual.h | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index 45166194..4fac371b 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -417,8 +417,8 @@ namespace mplot::compoundray this->projections[pri].site_indices.resize (ncoords, 0); this->projections[pri].triangle_count_sum = 0; - sm::vvec> flat_triangles; // contains a sequence of triplets of vecs - sm::vvec> flat_colours; + sm::vvec> flat_triangles; // contains a sequence of triplets of vecs + sm::vvec> flat_colours; // fewer elements than flat_triangles // To draw triangles iterate over the 'sites' and draw triangles for (int i = 0; i < diag_nsites && i < ncoords; ++i) { const jcv::site* site = &sites[i]; @@ -432,37 +432,24 @@ namespace mplot::compoundray } uint32_t site_triangles = 0; while (e) { -#if 0 - sm::vec t1 = {}; - sm::vec t2 = {}; - sm::vec t3 = {}; - t1 = (this->projections[pri].twod_transform * site->p).less_one_dim(); - t2 = (this->projections[pri].twod_transform * e->pos[0]).less_one_dim(); - t3 = (this->projections[pri].twod_transform * e->pos[1]).less_one_dim(); - this->computeTriangle (t1, t2, t3, colour); -#else flat_triangles.push_back (site->p.as()); flat_triangles.push_back (e->pos[0].as()); flat_triangles.push_back (e->pos[1].as()); flat_colours.push_back (colour); -#endif ++site_triangles; e = e->next; } this->projections[pri].triangle_counts[i] = site_triangles; this->projections[pri].triangle_count_sum += site_triangles; } -#if 1 + // Can now computeTriangles - //sm::vec flat_mean = flat_triangles.mean(); - //flat_triangles -= flat_mean; for (uint32_t i = 0; i < flat_triangles.size(); i += 3) { sm::vec t1 = (this->projections[pri].twod_transform * flat_triangles[i]).less_one_dim(); sm::vec t2 = (this->projections[pri].twod_transform * flat_triangles[i + 1]).less_one_dim(); sm::vec t3 = (this->projections[pri].twod_transform * flat_triangles[i + 2]).less_one_dim(); this->computeTriangle (t1, t2, t3, flat_colours[i/3]); } -#endif } // If false, hide 3D representation (the ommatidial cones and discs)