From 543e87f10f2639d349470ae2a4aa4676c4df6f9b Mon Sep 17 00:00:00 2001 From: Kamelia Date: Sun, 30 Aug 2026 11:08:02 +0200 Subject: [PATCH 1/3] Addition of tumors related to cutting --- CMakeLists.txt | 6 + TestScene.scn | 35 +- TestScene_p_1.scn | 99 ++ TestScene_p_8.scn | 92 + ...m_skeleton_at_comp_meshSkeletonization.txt | 1569 +++++++++++++++++ .../Patient_08_venoussystem_skeleton.txt | 1330 ++++++++++++++ src/MeshSkeletonizationPlugin/CGALMeshUtils.h | 89 + .../SegmentMapping/SkeletonSegmentMapper.h | 11 +- .../SegmentMapping/SkeletonSegmentMapper.inl | 85 +- .../SkeletonGraph/SkeletonGraph.cpp | 57 +- .../SkeletonGraph/SkeletonGraph.h | 12 +- .../SkeletonGraph/SkeletonReader.inl | 20 +- .../SkeletonResectionSimulator.h | 21 +- .../SkeletonResectionSimulator.inl | 39 +- .../TumorMapping/TumorCutPointSelector.cpp | 22 + .../TumorMapping/TumorCutPointSelector.h | 113 ++ .../TumorMapping/TumorCutPointSelector.inl | 205 +++ .../TumorMapping/TumorSet.cpp | 124 ++ .../TumorMapping/TumorSet.h | 49 + src/MeshSkeletonizationPlugin/init.cpp | 2 + 20 files changed, 3857 insertions(+), 123 deletions(-) create mode 100644 TestScene_p_1.scn create mode 100644 TestScene_p_8.scn create mode 100644 data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt create mode 100644 data/patient_08/Patient_08_venoussystem_skeleton.txt create mode 100644 src/MeshSkeletonizationPlugin/CGALMeshUtils.h create mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp create mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h create mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl create mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp create mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dc5547..59c9217 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,10 @@ set(HEADER_FILES ${PLUGIN_SKELETONIZATION_SRC_DIR}/SegmentMapping/SkeletonSegmentMapper.h ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.h ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.inl + ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorSet.h + ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.h + ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.inl + ${PLUGIN_SKELETONIZATION_SRC_DIR}/CGALMeshUtils.h ) set(SOURCE_FILES ${PLUGIN_SKELETONIZATION_SRC_DIR}/init.cpp @@ -30,6 +34,8 @@ set(SOURCE_FILES ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonReader.cpp ${PLUGIN_SKELETONIZATION_SRC_DIR}/SegmentMapping/SkeletonSegmentMapper.cpp ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.cpp + ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorSet.cpp + ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.cpp ) set(README_FILES README.md) diff --git a/TestScene.scn b/TestScene.scn index d077089..d8507a8 100644 --- a/TestScene.scn +++ b/TestScene.scn @@ -14,28 +14,25 @@ --> - - - - + + outputSkeleton="C:\Projects\Sofa\dev\sofa-plugins\MeshSkeletonization\data\patient_08\Patient_08_venoussystem_skeleton.txt" /> + outputVTK="C:\Projects\Sofa\dev\sofa-plugins\MeshSkeletonization\data\patient_08\Patient_08_venoussystem_skeleton.vtk" + outputReport="C:\Projects\Sofa\dev\sofa-plugins\MeshSkeletonization\Results\Patient_08_venoussystem_report_skeleton_mapper.csv" /> @@ -43,14 +40,14 @@ segmentNames must stay in the SAME order as these loaders, since that order is what maps index 0/1/2... to "II"/"III"/"IVa"... below. --> - - - - - - - - + + + + + + + + @@ -66,15 +63,15 @@ skeletonReader="@../Mesh/reader" segmentMeshes="@segII @segIII @segIVa @segIVb @segV @segVI @segVII @segVIII" segmentNames="II III IVa IVb V VI VII VIII" - outSegmentReportFilename="\Results\Patient_08_liver_segment_report_before.csv"/> + outSegmentReportFilename="C:\Projects\Sofa\dev\sofa-plugins\MeshSkeletonization\Results\Patient_08_liver_segment_report_before.csv"/> + outReportFilename="C:\Projects\Sofa\dev\sofa-plugins\MeshSkeletonization\Results\Patient_08_resection_report_after.csv"/> \ No newline at end of file diff --git a/TestScene_p_1.scn b/TestScene_p_1.scn new file mode 100644 index 0000000..ca9621a --- /dev/null +++ b/TestScene_p_1.scn @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestScene_p_8.scn b/TestScene_p_8.scn new file mode 100644 index 0000000..f11f663 --- /dev/null +++ b/TestScene_p_8.scn @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt b/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt new file mode 100644 index 0000000..c252711 --- /dev/null +++ b/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt @@ -0,0 +1,1569 @@ +128.653 146.214 3.89446 +130.123 145.243 4.89655 +131.369 144.325 5.93882 +131.935 143.885 6.4967 +133.158 143.288 7.42637 +133.975 142.903 8.01925 +134.644 142.582 8.53416 +135.734 142.107 9.24291 + +100.966 141.188 43.9713 +101.453 141.253 45.0956 +102.487 141.635 46.9503 +103.358 141.99 48.5195 +103.789 142.147 49.3191 +103.93 142.929 50.7286 + +103.93 142.929 50.7286 +105.282 142.377 52.1685 +105.945 142.11 53.1628 +106.294 141.992 53.7934 +107.468 141.619 56.0637 +108.078 141.407 57.4263 +108.304 141.315 57.9656 +108.839 141.088 59.4213 +109.462 140.781 60.8066 +109.971 140.485 61.7521 +110.726 139.935 62.835 +111.107 139.663 63.398 +111.643 139.279 64.1883 +112.672 138.584 65.7132 +113.333 138.163 66.7143 +114.164 137.681 68.0228 +115.068 137.284 69.5878 +115.707 137.099 70.8099 +116.38 136.936 72.1354 +116.784 136.844 72.9403 +117.698 136.639 74.7577 +118.739 136.321 76.6949 +119.59 136.296 78.2873 +120.933 136.166 79.422 +122.518 136.178 80.699 +123.385 136.184 81.3472 +124.251 136.204 81.8466 +125.244 136.213 82.4264 +126.338 136.248 82.9469 +127.087 136.257 83.3583 +128.395 136.255 84.1024 +130.405 136.23 85.3274 + +103.93 142.929 50.7286 +103.156 144.165 51.5221 +101.848 145.427 51.7407 +100.486 146.555 51.1776 +99.8611 147.043 50.8641 +98.8436 147.808 50.6965 +97.7802 148.753 50.3181 +97.1885 149.231 50.3929 +96.9984 149.404 50.382 +96.5906 149.842 50.3492 +96.0357 150.374 50.2907 +95.0542 151.436 50.1634 +94.4162 151.894 49.9048 +93.426 152.159 49.3773 +92.3763 152.5 48.7854 + +69.9695 138.333 67.9241 +69.9364 138.214 67.9146 + +66.023 150.541 73.1918 +66.2509 149.911 74.1547 +66.5492 149.422 74.8443 +66.9327 148.841 75.7225 +67.4382 148.103 76.7591 +68.2134 147.152 78.0239 +68.9174 146.331 79.0113 +69.2681 146.022 79.3979 +69.9561 144.896 80.0133 +70.6874 143.67 80.3656 + +65.2652 123.69 75.2001 +65.2652 123.69 75.2001 + +85.4913 132.498 79.9998 +84.7371 132.75 80.0704 +84.5065 132.828 80.1006 +83.9893 133.006 80.1766 +83.4319 133.207 80.2727 +82.0487 133.736 80.5432 +80.8669 134.287 80.6128 +80.3884 134.526 80.6313 +79.658 134.934 80.6577 +78.638 135.573 80.6957 +77.7083 136.247 80.8318 +77.1651 136.676 80.9704 +76.8841 136.902 81.0408 +76.3475 137.389 81.2361 +75.718 137.97 81.5143 +75.2253 138.489 81.7932 +73.6567 139.601 82.0371 +72.709 140.299 82.2588 + +70.6874 143.67 80.3656 +70.7991 142.988 79.0742 +70.7767 142.455 77.7925 +70.6715 142.162 76.8256 +70.3835 141.803 75.6543 +70.3508 141.482 74.9494 +70.1957 140.74 73.161 +70.0033 139.416 70.3849 +70.0653 138.814 69.3142 +69.9364 138.214 67.9146 + +70.6874 143.67 80.3656 +71.12 143.325 81.5849 +71.3822 143.12 82.4407 +71.8553 141.902 83.0875 + +72.709 140.299 82.2588 +71.8553 141.902 83.0875 + +72.709 140.299 82.2588 +72.4955 139.391 81.7616 +72.3973 139.083 81.5862 +71.9956 138.211 81.0537 +70.8611 136.531 79.9978 +67.3174 130.972 76.5092 + +59.9087 136.467 85.6705 +62.2661 137.925 85.8238 +64.1926 139.13 85.9173 +65.1336 139.635 86.0307 +65.7755 139.909 86.1746 +66.2029 140.121 86.2482 +66.7526 140.393 86.3458 +68.3603 141.197 86.5677 +70.2812 142.143 85.9285 +71.8635 142.969 86.2029 + +56.2284 132.442 88.0001 +56.2284 132.442 88.0001 + +73.843 170.216 91.7748 +73.2268 171.121 92.1674 +72.736 171.754 92.3573 +72.4079 172.209 92.4449 +72.1288 172.567 92.5363 +71.8445 172.921 92.628 +71.5287 173.309 92.7197 +71.1971 173.701 92.8108 +70.8624 174.092 92.8906 +70.5193 174.482 92.9759 +70.1065 174.931 93.0785 +69.1951 175.829 93.3652 +68.8601 176.138 93.4802 + +73.843 170.216 91.7748 +74.0967 167.968 93.1549 +74.0658 167.394 93.53 +74.23 165.686 94.4827 + +73.843 170.216 91.7748 +74.3628 170.594 90.4206 +74.7586 170.651 89.6066 +74.826 170.661 89.4479 + +79.634 151.555 105.559 +79.3834 150.561 104.277 +79.0581 149.917 103.131 +78.4722 149.106 101.313 +77.765 148.129 99.1256 +77.2504 147.351 97.3685 +76.6524 146.91 95.8767 +76.3706 146.75 95.2022 +75.8898 146.435 93.8955 +75.2525 145.82 92.3793 +74.4944 145.115 90.6509 +73.6045 144.319 88.7936 +73.2227 143.987 88.054 +71.8635 142.969 86.2029 + +79.634 151.555 105.559 +79.108 153.065 105.3 +78.803 153.84 104.97 +78.5739 154.301 104.358 +78.0646 155.38 103.236 +77.59 156.701 101.729 +77.4345 157.237 101.155 +77.183 157.977 100.387 +76.9746 158.755 99.5975 +76.6567 159.703 98.75 +76.4687 160.308 98.2136 +76.2587 160.927 97.6817 +76.0272 161.505 97.219 +75.4437 162.499 96.6452 +75.2727 163.176 96.0891 +74.93 164.035 95.5382 +74.23 165.686 94.4827 + +79.634 151.555 105.559 +80.4853 151.101 107.377 +80.6525 150.976 107.71 +80.9383 150.815 108.315 +81.2201 150.63 108.887 +81.6235 150.458 109.843 +81.9488 150.331 110.647 +82.3274 150.214 111.644 +82.7142 150.121 112.73 +83.0655 150.078 113.869 +83.5427 150.055 115.601 +83.877 150.07 116.976 +84.2581 150.107 118.634 +84.512 150.176 120.04 +84.677 150.275 121.37 +84.6109 150.528 122.744 +84.6887 150.713 123.5 +84.6982 150.796 123.872 +84.7851 150.991 124.527 + +178.504 148.681 105.668 +178.572 146.977 106.454 +178.45 146.094 107.205 +178.175 144.632 108.634 +177.148 142.855 111.843 +176.552 141.961 113.434 +176.176 141.442 114.581 +175.814 141.245 115.92 + +178.504 148.681 105.668 +178.814 149.015 104.356 +179.172 148.953 102.981 +179.406 149.308 101.493 +179.652 149.742 99.7551 +179.69 149.831 99.3892 +179.884 150.329 97.5736 +180.03 150.387 95.8776 +180.005 150.581 95.096 +179.941 150.708 93.7296 +179.814 150.862 92.5014 +179.584 150.977 90.7851 +179.371 151.092 89.0339 +179.298 151.153 88.2271 + +178.504 148.681 105.668 +177.96 150.193 106.44 +177.373 151.492 107.582 +176.967 152.43 108.44 +176.448 153.593 109.706 +175.914 154.743 111.406 +175.501 155.646 113.613 +175.229 156.245 115.146 +175.208 156.294 115.277 +175.124 156.493 116.03 +175.036 156.699 116.789 +174.991 156.805 117.339 +174.931 156.949 118.222 +174.847 157.148 119.483 +174.679 157.52 121.906 +174.594 157.625 122.898 +174.456 157.767 124.301 +174.335 157.862 125.246 +174.157 157.98 126.407 +173.991 158.068 127.209 +173.771 158.172 128.063 +173.344 158.372 129.545 +172.746 158.677 131.266 +172.478 158.824 132.014 +171.937 159.147 133.465 +171.242 159.576 135.318 +170.971 159.745 136.032 +170.469 160.101 137.392 +170.247 160.375 138.184 +169.816 160.903 139.716 +169.545 162.033 142.324 +169.365 162.754 143.998 +169.336 163.37 145.765 + +175.814 141.245 115.92 +176.692 141.906 117.72 +177.555 142.572 118.617 +179.925 144.449 120.89 +181.325 145.665 121.443 +182.401 146.656 121.839 +183.565 147.751 122.132 +184.993 149.109 122.449 +186.18 150.265 122.627 +186.799 150.871 122.709 +187.576 151.658 122.744 +188.297 152.408 122.736 +189.183 153.395 122.612 +190.118 154.463 122.443 +190.872 155.36 122.263 +191.542 156.186 122.069 +192.2 157.025 121.877 +193.141 158.347 121.523 +193.696 159.204 121.276 +194.553 160.638 120.521 + +175.814 141.245 115.92 +173.986 140.008 115.648 +172.141 138.824 115.368 +171.215 138.238 115.201 +170.141 137.565 114.981 +168.953 136.824 114.724 +168.162 136.337 114.552 +166.313 135.216 114.167 +164.967 134.536 113.811 +164.236 134.178 113.568 +163.61 133.89 113.366 +162.253 133.32 113.17 +161.091 132.896 113.091 +160.21 132.6 113.067 +158.873 132.21 113.064 +157.988 132 113.074 +156.915 131.788 113.086 +155.751 131.614 113.091 +155.079 131.537 113.093 +154.149 131.441 113.093 +152.744 131.37 113.073 +150.776 131.344 113.088 +149.181 131.438 113.043 +147.093 131.753 113.018 +145.717 131.979 113.024 +143.785 132.338 113.228 +142.87 132.504 113.172 +141.896 132.692 113.19 +140.108 133.07 113.388 +139.165 133.311 113.537 +137.566 133.633 113.294 + +70.6836 179.738 116.922 +70.9508 179.529 116.982 +72.2121 178.546 117.329 +72.9833 177.987 117.459 +74.4971 176.882 117.669 +75.2913 176.305 117.72 +75.7535 175.982 117.722 +76.63 175.359 117.685 +77.1315 175.016 117.602 +77.4705 174.811 117.51 +78.4235 174.252 117.215 +78.8016 174.006 117.121 +79.2323 173.705 117.007 +80.1626 173.008 116.741 +81.1121 172.199 116.417 +82.0488 171.26 116.186 +82.6161 170.982 115.688 + +195.917 172.038 121.843 +195.471 170.238 120.816 +195.55 168.63 120.673 +195.675 167.462 120.683 +195.854 165.956 120.717 +196.469 164.885 121.021 + +195.917 172.038 121.843 +197.571 172.354 122.903 +198.381 172.183 123.282 +199.286 171.783 123.613 +200.298 171.274 123.909 +200.777 170.365 123.832 +200.856 168.92 123.519 + +195.917 172.038 121.843 +195.119 173.401 122.153 +194.522 174.423 122.527 + +111.939 96.2717 125.007 +110.839 96.4467 126.385 +109.992 96.6537 127.627 +109.291 96.936 129.002 +108.593 97.3038 130.523 +108.025 97.911 131.943 +107.531 98.8524 133.051 +107.317 99.3945 133.698 +107.037 100.186 134.578 +105.842 102.004 135.047 + +57.6081 165.844 123.725 +58.425 165.325 124.207 +59.1528 164.969 124.722 +60.4597 164.342 125.786 +60.8922 164.107 126.16 +61.5408 163.75 126.574 +62.9595 162.979 127.15 +63.8113 162.501 127.402 +64.5285 162.108 127.457 +65.6048 161.561 127.482 +66.8151 160.965 127.502 +67.4436 160.668 127.523 +68.0801 160.337 127.576 +68.7708 159.992 127.629 +69.1543 159.759 127.698 +69.7075 159.44 127.803 +70.8212 158.77 128.096 +72.0704 158.019 128.505 +73.1279 157.378 128.793 +73.5353 157.165 128.84 +74.1072 156.883 128.88 +74.792 156.512 128.936 +75.5798 156.092 128.989 +76.3104 155.683 129.062 +76.6951 155.465 129.119 +77.1289 155.21 129.207 +77.4824 155.005 129.288 +78.1009 154.628 129.48 +79.0888 153.972 129.823 +79.5687 153.625 130.142 +79.6834 153.528 130.159 +80.3094 153.082 130.272 +80.8322 152.723 130.36 +81.2248 152.232 129.689 +82.7413 151.327 128.49 + +60.1843 119.538 130.418 +62.321 121.2 131.328 + +62.321 121.2 131.328 +62.558 123.445 131.832 +62.668 126.554 132.039 + +62.321 121.2 131.328 +63.2646 120.176 131.268 +63.4944 119.983 131.263 + +52.8487 135.85 137.606 +53.5688 135.948 137.603 +54.0893 136.031 137.601 +55.3648 136.282 137.598 +56.2534 136.476 137.6 +57.1867 136.668 137.609 +57.8513 136.758 137.622 +58.39 136.822 137.633 +58.8768 136.853 137.646 +59.5067 136.893 137.662 +60.172 136.905 137.674 +61.1372 136.916 137.678 +61.8299 136.884 137.658 +62.1555 136.87 137.642 +62.8073 136.83 137.6 +63.4473 136.76 137.54 +64.248 136.681 137.48 +66.6129 133.884 136.805 + +66.6129 133.884 136.805 +69.5025 136.348 138.724 +71.2089 137.292 139.585 +72.4775 137.614 140.258 +74.2717 137.917 141.426 +76.5385 138.276 142.94 +77.7112 138.451 143.674 +79.2137 138.767 144.461 +81.2 139.192 145.423 +83.1155 139.596 146.463 +84.0471 139.674 147.154 +85.1481 139.88 147.837 +86.1543 140.012 148.403 +86.725 138.58 150.168 +87.3641 136.629 152.293 + +66.6129 133.884 136.805 +64.8292 129.865 134.503 +63.9207 127.941 133.422 +62.668 126.554 132.039 + +178.117 144.98 136.768 +178.121 144.982 136.774 +178.125 144.983 136.778 + +75.5278 92.2165 141.032 +76.3128 92.362 141.331 +77.2795 92.5782 141.694 +78.5001 92.9404 142.125 +79.5376 93.2644 142.464 +80.5892 93.5739 142.805 +82.0155 93.9047 143.301 +82.6997 94.0306 143.526 +83.3112 94.1512 143.686 +83.925 94.2881 143.825 +84.692 94.4755 143.995 +85.5238 94.7586 144.176 +86.3511 95.086 144.382 +87.4636 95.6182 144.687 +90.4503 97.0554 145.624 +92.589 97.9937 146.466 +94.0638 98.6371 147.288 +94.5913 98.903 147.717 +95.0225 99.1636 148.239 +95.3683 99.4522 148.665 +95.8675 99.6695 149.375 +96.334 99.8449 150.079 +97.0981 100.351 151.4 + +169.115 162.169 142.322 +169.123 162.457 143.044 +169.336 163.37 145.765 + +81.6272 190.511 143.274 +81.8388 190.221 143.596 +82.5262 189.384 144.575 +82.9483 188.926 145.224 +83.82 188.07 146.47 +84.2492 187.666 147.06 +84.6476 187.035 147.945 +84.8341 186.545 148.643 +84.6263 185.84 149.629 +84.3089 185.206 150.542 +83.7096 184.419 151.811 +83.3808 183.277 153.346 + +169.336 163.37 145.765 +169.961 165.623 153.239 + +169.961 165.623 153.239 +170.052 165.889 154.667 + +169.961 165.623 153.239 +169.654 165.185 151.191 +169.265 164.452 148.371 +169.216 164.297 147.866 + +91.8089 90.7389 153.445 +93.2221 91.4541 153.239 +94.4216 92.1965 153.001 +95.2984 92.4769 152.835 +96.8278 92.913 152.546 + +112.281 105.816 151.523 +111.805 105.259 148.751 +111.423 104.895 146.929 +110.976 104.557 145.35 +110.636 104.311 144.196 +110.194 103.935 142.837 +109.5 103.542 141.667 +108.861 103.266 140.461 +108.326 103.036 139.495 +107.68 102.726 138.298 +106.751 102.504 137.205 +105.842 102.004 135.047 + +112.281 105.816 151.523 +114.163 106.773 153.02 +115.315 107.407 154.313 +116.36 108 155.625 +117.93 108.916 157.737 +119.163 109.671 159.517 +119.589 109.952 160.2 +120.338 110.486 161.45 +120.816 110.847 162.298 +121.336 111.327 163.195 +122.075 112.056 164.466 +122.745 112.706 165.673 +123.66 113.612 167.39 +124.221 114.171 168.496 +124.834 114.772 169.833 +125.12 115.067 170.494 +125.686 115.693 171.625 +126.111 116.212 173.409 + +112.281 105.816 151.523 +110.977 105.235 151.12 +110.357 104.982 151.124 +109.025 104.417 151.108 +107.172 103.603 151.132 +105.748 102.974 151.151 +104.065 102.229 151.173 +103.546 101.995 151.178 +102.215 101.368 151.188 +101.065 100.82 151.197 +99.4337 99.8942 151.25 + +82.4759 130.952 153.64 +83.1138 131.549 153.537 +84.8572 133.537 153.112 +86.6279 135.431 152.78 +87.3641 136.629 152.293 + +95.1726 141.887 154.426 +95.0954 141.88 156.052 + +95.1726 141.887 154.426 +96.3974 142.268 155.181 +97.8977 142.548 156.139 +99.0365 142.743 156.983 +99.9552 142.825 158.135 +100.762 142.87 159.333 +101.449 142.89 160.33 +102.337 142.947 162.933 + +95.1726 141.887 154.426 +94.974 142.476 152.399 +95.073 142.874 151.544 +95.2274 143.619 149.925 +94.947 143.948 149.008 +94.8729 144.508 147.917 +94.5622 145.139 146.498 +94.0899 145.477 145.444 +93.7075 145.801 144.416 +93.0665 146.127 143.231 +92.4071 146.4 142.24 +91.974 146.597 141.485 +91.7582 146.702 141.053 +91.0257 147.016 139.859 +90.1539 147.409 138.322 +89.3191 147.791 136.864 +88.9903 147.958 136.24 +88.3107 148.369 134.75 +87.8238 148.68 133.676 +87.452 148.925 132.861 +87.1502 149.21 131.925 +86.412 149.595 131.048 +86.3234 149.65 130.916 +85.5105 150.094 129.921 +82.7413 151.327 128.49 + +95.1726 141.887 154.426 +93.3219 140.684 153.572 +91.6468 139.439 152.977 +90.6485 138.637 152.968 +89.7363 137.918 152.924 +89.1779 137.482 152.883 +87.3641 136.629 152.293 + +79.9183 185.198 159.485 +79.9372 185.181 159.472 +80.6966 184.279 159.019 +80.9902 183.941 158.845 +81.4217 183.455 158.6 +81.7945 183.043 158.398 +82.3736 182.425 158.093 +83.0243 181.566 157.363 + +77.6271 188.777 161.6 +77.6271 188.777 161.6 +77.6271 188.777 161.6 + +84.8477 172.472 161.225 +84.9281 173.377 160.463 +85.0975 174.185 159.718 +85.0127 174.987 159.184 +84.8452 176.04 158.562 +84.6627 177.119 157.946 +84.3913 178.438 157.276 +84.0422 179.714 156.794 +83.0243 181.566 157.363 + +84.8477 172.472 161.225 +83.3179 172.69 162.217 +82.073 173.007 162.815 +81.5838 173.163 163.023 +81.1044 173.381 163.202 +80.4891 173.698 163.434 +80.2634 173.839 163.524 +79.7472 174.172 163.738 +79.004 174.743 164.083 +77.8545 175.758 164.606 +77.1431 176.433 164.906 +76.639 176.903 165.121 +76.0458 177.414 165.399 +75.4984 177.828 165.679 +74.811 178.33 166.065 +74.1982 178.796 166.421 +73.6373 179.215 166.758 +73.0603 179.653 167.086 +72.3006 180.208 167.442 +71.4377 180.844 167.87 +70.9157 181.217 168.122 +70.1162 181.761 168.484 +69.3266 182.271 168.787 +68.8096 182.646 168.885 +68.1256 183.114 169.014 +67.688 183.416 169.077 +67.3154 183.657 169.145 +66.41 184.23 169.314 +65.8882 184.51 169.405 +65.5257 184.688 169.464 +64.9453 184.937 169.538 +64.1814 185.201 169.607 +63.5813 185.371 169.63 +63.0571 185.505 169.64 +62.3638 185.678 169.639 +61.7702 185.831 169.631 +61.35 185.942 169.623 + +84.8477 172.472 161.225 +85.4766 171.757 161.321 +85.8185 171.181 161.526 +86.2383 170.44 161.819 +86.9123 169.025 162.491 +87.1322 168.545 162.729 +87.4481 167.776 163.154 +87.8212 166.774 163.758 +88.2113 165.667 164.485 +88.3696 164.902 165.057 +88.5843 163.755 166.281 + +59.7207 119.951 166.744 +60.7063 120.928 167.241 +62.5908 125.852 167.324 +64.1072 129.695 167.343 +66.8879 136.301 167.235 + +57.5513 133.84 166.4 +57.5685 133.841 166.4 +57.577 133.842 166.401 + +72.341 142.616 165.337 +73.9312 142.856 165.618 +74.8865 143.124 165.661 +75.899 143.361 165.664 +77.7619 143.64 165.642 +79.4049 143.776 165.607 +80.1266 143.786 165.584 +80.9375 143.784 165.558 +82.1831 143.729 165.509 +83.4322 143.651 165.453 +84.6068 143.587 165.414 +85.6687 143.552 165.418 +86.7176 143.499 165.42 +88.0512 143.332 165.653 +88.961 143.201 165.844 +89.4015 143.179 165.88 +90.2904 143.217 165.837 +92.048 143.102 165.941 +92.6474 143.066 165.961 +93.4134 143.023 165.955 +94.1623 142.984 165.92 +95.2459 142.933 165.85 +96.1706 142.905 165.756 +97.0835 142.889 165.546 +99.2584 142.888 164.036 +100.573 142.897 163.206 +102.337 142.947 162.933 + +72.341 142.616 165.337 +71.5039 144.08 164.153 +70.3964 144.878 163.247 +69.7697 145.113 162.86 +68.7833 145.293 162.607 +68.0212 145.471 162.351 +67.2671 145.615 162.142 +65.9934 145.882 161.824 +65.2736 146.073 161.676 +64.4162 146.32 161.524 +63.7159 146.5 161.413 +62.9814 146.701 161.285 +61.7516 146.396 160.697 +60.7946 146.101 160.195 +59.9925 145.894 159.808 +59.0276 145.682 159.369 +57.3895 145.427 158.723 +56.5521 145.345 158.434 +55.5433 145.233 158.092 +53.6523 144.933 157.394 +52.5549 144.785 157.046 +51.2356 144.644 156.84 +50.7996 144.607 156.803 +50.2871 144.576 156.791 +49.6646 144.541 156.786 +48.9364 144.501 156.77 +48.0077 144.428 156.704 +47.2006 144.315 156.565 +46.2592 144.161 156.368 +45.5419 144.01 156.161 + +72.341 142.616 165.337 +71.512 141.09 165.901 +70.3089 139.589 166.23 +68.4469 137.406 166.672 +68.0203 136.884 166.782 +66.8879 136.301 167.235 + +88.5843 163.755 166.281 +87.8239 162.905 166.824 +86.9083 162.537 166.925 +85.3756 162.393 167.059 +83.6542 162.273 167.242 +82.1972 162.523 167.149 +81.418 162.64 167.119 +80.3236 162.82 167.079 +78.9247 163.059 167.095 +78.3246 163.159 167.152 +77.3323 163.26 167.505 + +88.5843 163.755 166.281 +90.089 162.984 168.836 + +60.7052 144.78 169.6 +60.7052 144.78 169.6 + +167.109 99.8344 171.491 +169.047 100.115 170.584 +170.352 99.0507 169.748 +171.268 98.3428 169.072 +171.976 97.6583 168.511 +172.686 96.9865 167.713 +173.456 96.158 166.778 +173.893 95.6829 166.206 +174.23 95.2955 165.796 +174.641 94.8263 165.307 +175.134 94.3097 164.705 +175.758 93.7084 163.986 +176.435 93.0604 163.292 +177.236 92.4017 162.397 +178.089 91.5913 161.45 +179.294 90.4434 160.201 +179.64 90.1296 159.831 +180.098 89.6753 159.367 +180.231 89.5659 159.225 +180.694 89.1337 158.667 +181.234 88.6294 157.976 +181.681 88.2595 157.456 +182.313 87.7136 156.886 +183.152 86.9999 155.907 +185.134 85.9225 156.129 +185.767 85.575 156.117 +186.068 85.4261 156.09 +187.044 84.9338 155.981 +187.932 84.5305 155.808 +188.671 84.1817 155.623 +189.374 83.8716 155.46 +189.982 83.5945 155.352 +190.384 83.4081 155.297 +190.714 83.263 155.26 +191.122 83.085 155.224 +191.513 82.9124 155.199 + +167.109 99.8344 171.491 +166.855 98.7311 171.103 +166.762 97.382 170.46 +166.696 95.566 169.697 +166.784 95.0435 169.312 +167.027 94.6057 168.628 +167.383 93.5726 167.682 +167.669 92.9789 166.964 +168.097 92.038 166.005 +169.202 89.6428 163.547 + +167.109 99.8344 171.491 +166.352 100.514 172.201 +165.863 101.072 172.697 +165.368 101.645 173.197 +164.95 102.166 173.63 +164.352 102.932 174.253 +163.802 103.708 174.845 +163.022 104.922 175.711 +161.737 106.982 177.173 +161.483 107.587 177.504 +161.234 108.381 178.05 +161.014 108.96 178.489 +160.859 110.46 179.689 +161.346 111.947 180.867 + +107.994 144.094 171.668 +107.224 145.053 172.255 +106.72 145.772 172.828 +105.807 146.787 172.796 +105.331 147.393 172.853 +104.228 148.667 172.809 +103.704 149.263 172.779 +102.744 150.3 172.668 +102.08 150.976 172.561 +101.308 151.704 172.39 +100.532 152.387 172.188 +99.4036 153.318 171.819 +98.5635 153.991 171.515 +97.4215 154.905 170.944 +96.1131 155.974 170.313 +95.7761 156.254 170.153 +95.1723 156.768 169.845 +94.7853 157.107 169.647 +94.0702 157.754 169.319 +93.1554 158.641 168.859 +92.5214 159.301 168.587 +91.6018 160.296 168.224 +90.089 162.984 168.836 + +107.994 144.094 171.668 +107.515 143.868 170.59 +107.146 143.726 169.85 +106.64 143.494 168.772 +106.519 143.458 168.553 +105.947 143.33 167.608 +105.189 143.234 166.501 +104.689 143.16 165.728 +103.685 143.028 164.338 +102.337 142.947 162.933 + +107.994 144.094 171.668 +108.664 143.903 172.282 +109.371 143.703 172.935 +110.122 143.548 173.737 +110.975 143.386 174.748 +111.714 143.255 175.678 +112.727 143.081 177.03 +112.925 143.047 177.303 +113.641 142.922 178.34 +114.731 142.712 180.02 +115.23 142.626 180.741 +115.2 141.737 183.381 + +60.4872 166.349 174.407 +60.7654 166.306 174.375 +61.1149 166.252 174.321 +61.9757 166.114 174.152 +62.1204 166.09 174.115 +62.8022 165.974 173.913 +63.8219 165.801 173.577 +65.2007 165.553 173.094 +65.6659 165.465 172.931 +66.1795 165.364 172.748 +66.8545 165.231 172.476 +67.9943 165.009 171.961 +69.3103 164.765 171.363 +69.5752 164.704 171.267 +70.3813 164.532 170.977 +71.2974 164.322 170.705 +72.3554 164.063 170.467 +73.1278 163.881 170.271 +74.1599 163.648 169.916 +75.2534 163.39 169.531 +76.5296 163.073 169.104 +77.3103 162.959 168.625 +77.3323 163.26 167.505 + +84.1561 171.789 174.448 +84.7189 171.209 174.313 +85.0759 170.879 174.206 +85.5794 170.463 174.018 +86.5124 170.077 173.53 +87.7213 171.351 172.953 + +179.143 92.0806 175.998 +178.881 92.8673 176 + +126.111 116.212 173.409 +127.047 117.563 174.981 +127.621 118.532 176.285 +128.397 119.947 178.198 +129.233 122.256 181.094 +130.424 125.849 185.635 +130.967 127.117 187.107 +131.387 128.44 188.814 +131.828 129.635 190.411 +132.225 130.944 192.049 +132.798 133.197 194.441 +132.669 135.255 195.831 + +126.111 116.212 173.409 +124.909 114.674 174.724 +123.958 113.548 176.41 +123.043 112.765 176.804 +119.612 109.582 176.42 +117.338 107.47 176.138 +111.518 102.048 175.403 + +89.4072 157.154 175.268 +88.3863 157.446 175.877 +87.8846 157.595 176.163 +87.3317 157.773 176.448 +86.7141 157.913 176.745 +85.5413 158.131 177.261 +84.8802 158.237 177.526 +84.634 158.278 177.63 +83.835 158.378 177.96 +82.9667 158.468 178.323 +82.0866 158.543 178.708 +81.6035 158.574 178.918 +81.1517 158.626 179.109 +80.9124 158.644 179.218 +79.8326 158.713 179.78 +79.1383 158.762 180.173 +78.1705 158.881 180.722 +77.2303 159.096 181.286 +76.676 159.217 181.612 +75.6392 159.437 182.172 +74.6995 159.603 182.657 +73.4684 159.675 183.27 +72.7538 159.685 183.607 +72.2055 159.678 183.835 +71.8326 159.67 183.989 +71.3261 159.668 184.192 +70.8968 159.658 184.37 +70.4407 159.657 184.558 +69.6648 159.655 184.916 + +177.367 109.655 177.604 +177.2 109.666 177.603 +176.983 109.676 177.602 + +81.5102 111.15 179.2 +81.5102 111.15 179.2 + +161.346 111.947 180.867 +159.913 112.61 181.387 +159.246 113.13 181.796 +157.573 114.267 182.592 +156.544 114.953 183.135 +156.283 115.147 183.279 +155.926 115.408 183.493 +155.519 115.782 183.759 +154.307 116.954 184.614 +153.797 117.405 184.946 +153.561 117.626 185.089 +153.143 118.058 185.357 +152.108 118.992 186.147 +151.273 119.886 186.746 +150.251 121.072 187.507 +149.659 121.763 187.774 +148.791 122.837 188.016 +147.944 123.906 188.14 +147.492 124.509 188.162 +146.394 126.39 188.371 +144.996 127.879 189.272 +144.269 128.583 189.883 +143.593 129.367 190.592 +143.09 129.988 191.16 +142.589 130.989 192.03 +141.535 132.358 193.473 +139.953 132.998 194.305 +138.718 133.518 194.914 +137.438 134.099 195.543 +135.37 134.863 196.078 +134.59 135.123 196.24 +134.111 135.312 196.348 +132.669 135.255 195.831 + +161.346 111.947 180.867 +162.614 111.861 180.874 +163.509 111.521 180.694 +163.926 111.362 180.619 +164.581 111.131 180.493 +165.443 110.737 180.307 +166.047 110.484 180.174 +167.27 110.111 179.877 +168.282 109.896 179.626 +169.086 109.762 179.462 +170.202 109.594 179.283 +170.552 109.502 179.248 + +94.2346 148.878 186.053 +93.4394 148.752 186.386 +92.6899 148.637 186.679 +91.6862 148.512 186.975 +91.5026 148.494 187.018 +91.019 148.447 187.112 +90.5029 148.4 187.183 +90.0956 148.364 187.229 +89.4858 148.311 187.265 + +76.9636 126.936 187.226 +77.0048 126.946 187.227 +77.5446 127.136 187.233 +78.2155 127.329 187.234 +79.0643 127.526 187.224 +79.6086 127.618 187.206 +79.854 127.638 187.187 +80.7155 127.678 187.113 +81.5957 127.678 186.971 +82.3244 127.657 186.817 +83.5524 127.656 186.497 +84.9129 127.71 186.139 +85.8786 127.765 185.922 +86.8576 127.819 185.737 +87.5832 127.798 185.665 +88.2139 127.801 185.595 +89.5513 127.856 185.438 +90.643 127.982 185.262 +91.7053 128.168 185.025 +92.6269 128.363 184.79 +93.5762 128.715 184.427 +95.212 129.285 183.815 +96.3006 129.636 183.396 +97.5871 130.012 182.995 +99.4632 130.679 182.559 +100.726 131.189 182.444 +101.593 131.581 182.468 +102.503 132.111 182.564 +107.759 136.528 184.253 +111.118 139.449 185.334 +112.838 140.586 184.495 +113.042 140.725 184.373 +113.71 141.126 184.062 +115.2 141.737 183.381 + +202.67 166.715 102.83 +201.567 166.325 103.596 +200.836 166.041 104.171 +200.079 165.766 104.73 +199.586 165.434 105.37 +198.703 164.387 106.937 +198.288 163.979 107.591 +198.036 163.711 108.042 +197.581 163.247 108.925 +196.967 162.622 110.22 +196.399 162.163 111.661 +196.197 162.079 112.623 +196.085 162.025 113.196 +195.809 161.9 114.651 +195.317 161.667 117.363 +194.553 160.638 120.521 + +59.8742 146.681 114.041 +60.7988 146.955 114.672 +61.5217 147.159 115.205 +62.2305 147.363 115.736 +63.1237 147.593 116.402 +63.8093 147.771 116.91 +64.493 147.948 117.386 +67.3722 148.5 119.103 +68.7238 148.707 119.837 +69.4639 148.771 120.225 +70.2793 148.876 120.642 +71.241 148.979 121.151 +73.3006 149.249 122.401 +74.4924 149.338 123.151 +76.0756 149.357 124.191 +77.0104 149.258 124.907 +78.6682 149.342 125.88 +80.0307 149.633 126.177 +81.117 150.343 126.925 +82.7413 151.327 128.49 + +105.842 102.004 135.047 +104.467 102.578 133.682 +103.906 102.642 132.989 +103.269 102.701 131.939 +102.806 102.797 131.181 +102.535 102.826 130.746 +101.927 102.859 129.745 +101.499 102.911 129.036 + +67.9015 140.29 167.757 +66.8879 136.301 167.235 + +69.8722 133.879 58.4448 +69.8622 134.214 59.707 +69.863 134.954 61.7061 +69.6265 136.479 65.209 +69.9364 138.214 67.9146 + +65.1215 166.899 93.9701 +65.8125 166.673 93.8817 +66.2607 166.541 93.8661 +67.1521 166.313 93.9129 +68.1032 166.082 94.0389 +68.9168 165.901 94.192 +69.5339 165.777 94.3034 +70.3269 165.632 94.4318 +71.449 165.475 94.589 +74.23 165.686 94.4827 + +87.7579 183.725 102.224 +87.5673 183.06 102.861 +87.399 181.967 103.75 +87.2015 180.724 104.718 +87.0363 180.033 105.258 +86.7235 178.906 106.241 +86.5539 178.378 106.7 +85.9846 177.007 107.93 +85.5317 176.05 108.788 +85.2543 175.513 109.299 +84.8989 174.867 110.065 +84.3726 173.917 111.161 +84.167 173.475 111.695 +83.8032 172.852 112.572 +83.3437 171.848 113.995 +83.0191 171.244 114.941 +82.6161 170.982 115.688 + +58.1745 130.532 128.366 +59.8796 131.204 129.45 +60.9747 129.987 130.399 +61.4027 129.182 130.811 +61.7705 128.486 131.165 +62.1995 127.65 131.582 +62.668 126.554 132.039 + +173.744 84.4425 149.963 +173.353 84.9731 150.991 +172.825 85.6005 152.338 +172.38 86.1432 153.563 +172.126 86.4566 154.332 +171.636 87.1108 155.948 +171.333 87.6147 157.096 +171.163 87.8786 157.699 +170.693 88.5896 159.286 +170.091 89.4579 161.059 +169.595 89.9304 162.374 +169.202 89.6428 163.547 + +52.2718 173.646 149.975 +52.2967 173.632 149.984 +52.4228 173.56 150.023 +53.1026 173.161 150.211 +53.8067 172.722 150.396 +54.6547 172.167 150.632 +55.6121 171.511 150.974 +56.0793 171.184 151.171 +56.4828 170.882 151.393 +57.1075 170.428 151.781 +58.138 169.665 152.557 +58.7925 169.253 153.018 +59.7386 168.658 153.771 +60.787 168.061 154.544 +61.6683 167.765 155.408 +61.9886 167.652 155.718 +62.5402 167.474 156.15 +63.1364 167.373 156.446 +64.4205 167.176 157.246 +65.2961 166.992 157.902 +65.9481 166.841 158.466 +67.0206 166.681 159.078 +67.8442 166.512 159.766 +68.9022 166.34 160.569 +69.9838 166.077 161.304 +70.53 165.963 161.626 +71.4534 165.774 162.052 +72.3544 165.508 162.675 +73.5272 165.094 163.406 +74.8094 164.629 164.257 +75.7044 164.336 164.755 +76.7549 163.795 165.975 +77.3323 163.26 167.505 + +81.2481 184.464 153.386 +81.7592 184.255 153.275 +83.3808 183.277 153.346 + +71.8662 102.418 155.08 +72.0726 102.375 155.13 +72.9222 102.199 155.302 +73.5088 102.096 155.405 +74.4979 101.976 155.565 +75.7914 101.83 155.774 +76.8892 101.813 155.766 +77.4468 101.854 155.718 +78.0227 101.995 155.6 +79.2175 102.146 155.444 +80.2234 102.279 155.315 +81.3102 102.337 155.198 +82.1555 102.346 155.109 +82.5653 102.354 155.062 +83.264 102.366 154.986 +84.129 102.421 154.845 +85.3338 102.47 154.738 +86.2417 102.524 154.648 +87.2493 102.624 154.44 +88.6582 102.728 154.183 +90.1627 102.833 153.785 +91.0275 102.862 153.555 +91.7874 102.796 153.356 +92.4463 102.683 153.248 +93.3794 102.497 153.105 +94.2709 102.258 152.962 +95.182 102.01 152.768 +96.1254 101.019 151.829 +97.0981 100.351 151.4 + +169.024 87.7602 164.561 +169.017 87.9164 164.532 +169.011 88.0331 164.508 +169.202 89.6428 163.547 + +66.316 142.773 167.806 +66.4257 142.697 167.79 +67.2615 142.286 167.661 +66.6037 138.005 167.395 +66.8879 136.301 167.235 + +91.5826 179.267 171.736 +91.4687 179.144 171.796 +90.6988 178.064 172.307 +89.9989 176.504 172.403 +89.1565 174.441 172.59 +87.7213 171.351 172.953 + +111.518 102.048 175.403 +111.173 99.9685 175.76 +111.09 99.292 175.841 +111.088 98.6491 175.912 +111.106 98.328 175.949 +111.146 97.7287 175.997 +111.234 96.7723 176.043 +111.391 95.724 176.054 +111.562 94.9268 176.046 +111.781 94.1655 176.03 + +111.518 102.048 175.403 +110.438 101.538 175.184 +109.057 100.895 174.845 +107.764 100.406 174.622 +107.151 100.235 174.501 +106.118 99.8567 174.478 +104.782 99.5323 174.534 +103.954 99.3817 174.674 +102.893 99.2995 174.955 +101.384 99.2294 175.464 +100.744 99.2102 175.659 +100.4 99.1918 175.748 +99.956 99.1638 175.854 +99.2933 99.1063 175.962 + +176.954 99.7568 177.602 +176.875 99.9012 177.604 +176.812 100.024 177.604 +176.684 100.267 177.604 +176.152 101.233 177.607 +175.979 101.527 177.607 +175.765 101.89 177.608 +175.344 102.593 177.607 +174.917 103.248 177.607 +174.735 103.528 177.606 +174.38 104.057 177.605 +174.178 104.364 177.604 + +131.322 135.609 43.3718 +131.079 135.782 43.1609 + +71.8553 141.902 83.0875 +71.5524 142.495 84.546 +71.8635 142.969 86.2029 + +215.038 176.519 122.635 +213.447 175.246 122.861 +212.17 174.08 122.862 +211.306 173.549 123.033 +210.298 172.859 123.185 +209.06 172.197 123.435 +208.214 171.655 123.544 +207.478 171.251 123.656 +206.02 170.689 123.692 +205.452 170.481 123.697 +204.47 170.13 123.694 +203.259 169.692 123.686 +202.09 169.337 123.646 +200.856 168.92 123.519 + +99.4337 99.8942 151.25 +97.9589 97.2116 151.646 +97.775 96.3902 151.809 +97.4821 94.9923 152.093 +96.8278 92.913 152.546 + +99.4337 99.8942 151.25 +97.0981 100.351 151.4 + +97.8414 91.1207 152.698 +96.8278 92.913 152.546 + +83.3808 183.277 153.346 +83.6782 181.956 154.803 +83.5796 181.583 155.691 +83.0243 181.566 157.363 + +82.6161 170.982 115.688 +83.1211 170.046 115.838 +83.2748 169.231 116.334 +83.404 168.622 116.686 +83.5143 168.087 117.002 +83.7721 166.951 117.624 +83.9247 165.825 118.465 +84.1383 165.047 118.934 +84.5255 163.975 119.266 +84.7867 163.203 119.808 +85.2191 162.048 120.436 +85.6017 161.498 120.766 +85.7829 161.201 120.961 +86.0429 160.81 121.144 +86.3498 160.344 121.411 +86.9068 159.778 121.953 +87.4672 158.636 122.839 +87.2137 156.037 123.863 +86.9803 154.57 124.469 +86.8712 154.008 124.705 +86.691 153.204 125.081 +86.3997 152.159 125.658 +85.9691 151.836 125.767 +84.7851 150.991 124.527 + +90.089 162.984 168.836 +89.8987 164.957 170.576 +89.7081 165.489 170.86 +89.5733 165.788 171.025 +89.2581 166.496 171.39 +88.7415 167.755 171.84 +88.4179 169.28 172.267 +87.7213 171.351 172.953 + +148.131 142.704 3.70934 +146.072 142.424 4.59721 +143.831 142.168 5.60645 +142.595 142.04 6.14898 +141.445 141.937 6.6574 +140.619 141.86 7.10711 +139.94 141.812 7.49441 +138.904 141.931 7.76347 +137.229 142.106 8.27962 +135.734 142.107 9.24291 + +131.079 135.782 43.1609 +131.105 135.94 41.8939 +131.187 136.072 40.7448 +131.246 136.259 39.4345 +131.284 136.42 38.4226 +131.354 136.621 37.1584 +131.456 136.901 35.4977 +131.576 137.255 33.4679 +131.672 137.494 32.0916 +131.74 137.653 31.2041 +131.842 137.89 29.9179 +131.935 138.079 28.88 +132.025 138.252 27.9305 +132.166 138.525 26.4419 +132.393 138.821 24.78 +132.544 139.068 23.4507 +132.857 139.297 22.1451 +133.314 139.739 19.6675 +133.63 140.013 18.1275 +133.893 140.209 17.0392 +134.205 140.53 15.3925 +134.901 141.793 10.7873 +135.734 142.107 9.24291 + +131.079 135.782 43.1609 +131.072 135.641 44.7699 +131.043 135.558 46.2842 +131.067 135.509 47.8606 +131.337 135.418 50.3526 +131.266 135.66 53.2877 +131.468 135.851 55.1908 +131.719 136.013 56.8924 +131.977 136.212 58.3686 +132.272 136.421 59.9484 +132.468 136.563 61.0536 +132.694 136.728 62.3631 +132.994 136.957 64.2912 +133.048 137.001 64.6806 +133.314 137.226 66.8636 +133.52 137.408 68.7152 +133.619 137.511 69.893 +133.697 137.637 71.7167 +133.688 137.748 74.0155 +133.564 137.76 75.4613 +133.499 137.759 76.3906 +133.431 137.75 77.4357 +133.192 137.661 78.741 +132.659 137.459 80.2182 +132.095 137.177 81.3773 +131.862 137.062 81.8157 +131.281 136.752 83.1137 +130.405 136.23 85.3274 + +115.2 141.737 183.381 +117.523 142.061 183.769 +118.347 142.065 184.224 +119.739 142.081 184.897 +122.286 141.842 186.676 +123.999 141.606 187.998 + +82.7413 151.327 128.49 +84.0276 151.073 126.382 +84.7851 150.991 124.527 + +194.553 160.638 120.521 +196.121 163.41 120.833 +196.469 164.885 121.021 + +200.856 168.92 123.519 +199.907 167.623 123.164 +199.463 167.08 122.979 +198.798 166.322 122.684 +198.28 165.866 122.334 +197.598 165.402 121.832 +196.469 164.885 121.021 + +132.669 135.255 195.831 +131.489 136.474 196.108 +130.1 137.32 196.082 +129.105 137.924 195.931 +128.208 138.465 195.769 +126.877 139.449 194.383 +125.857 140.258 192.789 +125.36 140.664 191.715 +125.102 140.874 191.021 +124.74 141.161 189.898 +124.497 141.39 188.937 +123.999 141.606 187.998 + +137.566 133.633 113.294 +136.88 134.048 114.669 +136.624 134.187 115.097 +136.078 134.522 116.202 +135.859 135.024 117.841 +135.598 135.597 119.615 +135.526 135.752 120.079 +135.194 136.591 122.56 +134.859 137.21 124.166 +134.747 137.65 125.387 +134.54 138.558 127.919 +134.466 138.934 128.975 +134.417 139.3 130.012 +134.307 139.943 131.943 +134.219 140.199 132.766 +134.126 140.472 133.664 +134.233 140.881 135.4 +134.64 141.606 138.608 +134.615 141.971 141.075 +134.608 142.114 142.058 +134.603 142.149 142.31 +134.555 142.372 143.948 +134.509 142.507 145.013 +134.449 142.621 145.999 +134.35 142.8 147.573 +134.256 142.919 148.731 +134.1 143.109 150.603 +134.006 143.213 151.668 +133.951 143.268 152.251 +133.876 143.334 152.988 +133.635 143.504 155.036 +133.4 143.548 156.278 +133.039 143.54 157.751 +132.679 143.538 159.39 +132.421 143.521 160.682 +132.114 143.468 162.148 +131.86 143.415 163.373 +131.465 143.28 165.419 +131.238 143.195 166.614 +130.895 143.062 168.415 +130.716 142.996 169.341 +130.473 142.916 170.574 +130.289 142.858 171.504 +130.074 142.817 172.47 +129.913 142.77 173.295 +129.757 142.736 174.037 +129.476 142.711 175.098 +129.256 142.68 175.907 +128.926 142.66 176.991 +128.088 142.51 179.343 +126.888 142.368 182.164 +126.353 142.288 183.255 +125.261 141.967 185.647 +124.598 141.768 187.036 +123.999 141.606 187.998 + +137.566 133.633 113.294 +136.131 133.628 111.488 +135.759 133.598 110.862 +135.404 133.57 110.267 +134.881 133.495 109.163 +134.15 133.509 107.478 +133.636 133.523 105.873 +133.368 133.544 105.064 +133.01 133.595 103.864 +132.685 133.679 102.589 +132.244 133.834 100.672 +131.897 134.013 98.9006 +131.701 134.139 97.7952 +131.648 134.165 97.5438 +131.469 134.316 96.407 +131.348 134.456 95.4476 +131.202 134.643 94.2253 +130.995 134.92 92.4675 +130.915 135.096 91.4794 +130.797 135.327 90.1767 +130.68 135.471 89.3444 +130.589 135.609 88.5861 +130.604 135.95 86.8884 +130.405 136.23 85.3274 + diff --git a/data/patient_08/Patient_08_venoussystem_skeleton.txt b/data/patient_08/Patient_08_venoussystem_skeleton.txt new file mode 100644 index 0000000..e824fde --- /dev/null +++ b/data/patient_08/Patient_08_venoussystem_skeleton.txt @@ -0,0 +1,1330 @@ +124.847 84.4897 34.42 +124.929 84.5022 34.5772 +125.643 84.5831 35.8539 +125.901 84.7885 37.7116 + +123.042 88.3776 54.5085 +123.214 88.515 55.2484 + +194.212 110.69 160.864 +193.643 111.415 161.304 +192.833 112.434 161.934 +192.446 112.91 162.239 +191.02 114.77 163.445 +191.85 115.854 164.196 + +65.8874 136.055 49.1372 +66.6845 135.002 50.0835 +66.8917 134.726 50.3257 +68.0989 133.096 51.7116 +69.0322 131.751 52.7607 +70.0813 130.187 53.8771 +70.8367 128.629 54.3381 +71.6768 126.994 55.2105 +72.1984 126.006 55.8317 +72.5729 125.076 56.1057 +73.9801 119.509 57.1376 + +78.071 158.086 59.845 +78.1325 157.866 60.8743 +78.2282 157.485 62.6068 +78.3101 157.142 64.1188 +78.3664 156.924 65.3104 +78.392 156.826 65.8751 +78.4147 156.996 67.9795 + +60.2039 155.341 71.6785 +60.3399 155.33 72.5722 +60.4304 155.324 73.1424 +60.7675 155.323 75.1102 +61.0034 155.266 77.2087 +61.0796 155.278 78.0135 +61.1706 155.428 79.4894 +61.0173 156.758 81.4062 + +137.163 85.092 74.5876 +137.006 85.1093 75.4299 +136.791 85.1271 76.6176 +136.37 85.1386 78.9678 +136.104 85.3324 82.2544 +136.513 85.7459 84.3486 +136.749 85.9748 85.5818 +136.82 86.2036 87.085 +137.913 86.9824 90.8748 + +104.1 86.5675 70.8634 +102.958 88.3178 71.4794 +102.37 89.953 72.9031 + +59.6024 138.075 81.831 +59.6619 138.109 81.8917 +60.5798 138.655 82.7245 +62.2433 139.653 84.0144 +63.8185 140.449 84.9221 +64.7391 140.795 85.3336 +67.2101 141.299 86.6562 + +125.457 106.864 158.045 +122.632 103.734 149.272 + +125.457 106.864 158.045 +126.737 109.082 159.321 +127.961 111.187 161.484 +128.532 112.153 162.541 +128.794 112.596 163.027 +129.14 113.18 163.665 +129.586 113.948 164.516 +130.03 114.817 165.447 +130.227 116.673 167.898 + +125.457 106.864 158.045 +124.617 105.028 158.788 +124.534 103.932 160.485 +124.681 103.259 161.692 +124.875 102.132 163.675 +124.889 101.083 165.303 +124.797 99.7985 167.085 +124.613 98.9346 168.069 +124.491 98.4369 168.659 + +84.9269 179.043 85.5297 +84.9876 178.452 86.3632 +85.1387 176.786 88.6976 +85.222 175.019 91.0726 +85.2864 173.549 93.0427 +85.3214 172.774 94.0817 +85.3519 172.048 95.0576 +85.4086 170.568 97.0421 +84.8833 168.875 99.1214 +84.3757 167.435 100.86 +83.7539 165.739 102.859 +82.7873 163.469 105.302 +81.7354 162.01 107.086 +81.0079 160.186 108.87 +78.5962 158.884 111.503 + +148.79 75.3299 87.1424 +148.406 75.6382 87.7389 +147.667 76.2275 88.8712 +147.3 76.5477 89.5006 +146.747 77.2283 90.9686 +146.403 77.6623 91.9134 +145.849 78.3654 93.4483 +145.587 78.7011 94.1836 +145.321 79.0457 94.943 +144.671 80.0604 97.4016 +144.557 80.7497 99.5844 +144.551 81.1474 100.942 +143.789 82.3533 103.716 + +61.0173 156.758 81.4062 +60.0179 160.838 81.2346 +59.3482 163.105 80.9458 +58.9502 164.585 80.7231 +58.9488 164.591 80.7222 +58.947 164.597 80.721 + +61.0173 156.758 81.4062 +61.5186 155.006 82.5176 +61.7994 153.031 84.8869 +63.3386 151.021 85.3607 +64.6575 149.411 85.8313 +66.0364 147.811 86.2995 +68.073 144.339 87.0143 +67.2101 141.299 86.6562 + +90.7024 140.89 85.4398 +90.4432 141.064 85.4101 +89.0715 141.99 85.2423 +88.2669 142.511 85.1326 +86.9446 143.145 84.862 +85.5599 143.709 84.6407 +82.6381 144.087 84.6342 +80.3282 144.293 84.7584 + +142.957 87.784 89.5012 +142.26 87.6998 89.5785 +140.827 87.4643 89.6202 +137.913 86.9824 90.8748 + +115.064 95.1406 94.0754 +114.321 98.0252 95.5105 + +115.064 95.1406 94.0754 +116.119 93.7546 97.1936 +116.302 93.6433 97.997 +116.924 93.3885 99.9499 +117.469 93.0765 101.913 +118.322 92.695 103.737 +118.684 92.5415 104.437 +119.342 92.1358 105.522 +121.308 90.1466 110.362 + +115.064 95.1406 94.0754 +114.826 94.7176 92.168 +114.245 94.4389 88.7568 +113.874 94.0078 86.2572 +113.015 93.611 83.2099 +112.247 93.2826 80.8076 +108.779 92.0873 75.342 + +83.0616 116.469 101.194 +83.0746 116.601 101.15 +83.1327 117.256 100.923 +83.2576 118.403 100.523 +83.4035 119.602 100.087 +83.7359 121.925 99.2861 +83.2766 125.401 96.3324 + +60.1339 110.395 99.8877 +60.0678 110.68 100.002 +59.8273 111.751 100.435 +59.5351 113.299 101.053 +59.2226 114.997 101.732 +58.9327 116.846 102.464 +59.3508 118.136 103.057 +60.5475 121.632 104.644 +61.615 124.739 106.053 +61.8904 125.528 106.403 +62.4854 127.186 107.098 +63.0756 128.838 107.795 +63.7248 130.624 108.502 +64.17 131.873 108.995 +64.5734 133.253 109.473 +64.0551 135.842 109.722 +65.7557 138.894 109.509 + +90.3733 123.382 100.082 +88.3308 124.128 99.6338 +87.6055 124.725 99.4783 +85.4958 125.715 98.3503 +83.2766 125.401 96.3324 + +105.728 86.0623 102.144 +105.763 86.9818 103.358 +106.349 88.3762 105.107 +106.883 89.5362 106.576 +105.863 91.6136 109.516 + +59.0806 172.943 102.879 +59.6145 172.107 103.97 +60.5768 170.592 105.928 +61.0244 169.905 106.777 +61.5277 169.14 107.71 +62.047 168.265 108.807 +62.5938 167.02 110.478 +65.2745 163.976 113.788 + +75.289 183.143 109.052 +75.2835 182.848 109.515 + +123.214 88.515 55.2484 +124.06 88.0184 53.2858 +124.334 87.7243 52.0909 +124.835 87.2365 50.1839 +125.645 86.5985 48.0148 + +123.214 88.515 55.2484 +121.99 89.1055 57.8561 +121.431 89.3442 58.8862 +119.522 90.1316 62.2955 +118.835 90.4081 63.4899 +117.418 90.9507 65.7539 +116.89 91.1439 66.5483 +112.438 92.2765 70.8728 +110.461 92.2893 72.2288 + +88.1816 97.2536 110.696 +89.0148 96.5852 110.893 +89.856 95.9571 110.972 +90.8048 95.2674 111.024 +92.7994 92.9853 111.383 + +151.772 79.6779 129.217 +151.394 80.3266 130.898 +150.917 81.1439 133.018 +150.324 82.2103 135.811 +149.825 83.1552 138.307 +149.436 83.9595 140.454 +148.882 85.2101 143.79 +148.467 86.28 146.761 +148.289 87.0198 148.749 +147.851 86.5095 151.619 + +49.9261 142.58 119.632 +50.2884 142.488 119.362 +51.4191 142.121 118.54 +52.2455 141.411 117.977 + +65.3679 171.39 129.221 +66.0789 171.467 128.962 +66.4468 171.508 128.829 +67.8691 171.683 128.31 +69.7787 171.918 127.627 +71.8539 172.404 126.74 +76.4149 173.901 124.526 + +105.486 162.228 145.628 +105.639 161.646 146.29 +105.717 161.328 146.653 +105.961 160.159 147.997 +106.125 159.239 149.051 +105.701 158.994 149.604 +105.232 158.731 150.218 +102.836 158.339 152.718 + +52.9788 155.622 146.398 +54.2184 155.689 147.308 + +58.595 116.628 149.578 +59.5359 117.068 150.013 +60.6451 117.579 150.541 +61.5376 117.98 150.973 +62.7628 117.635 152.398 + +51.8804 157.179 146.412 +53.4637 156.257 147.056 +54.2184 155.689 147.308 + +46.6617 140.452 147.581 +47.146 140.405 147.678 +48.5185 140.264 147.956 +50.9146 139.98 148.448 +53.1244 139.685 148.946 +55.5227 139.344 149.58 +58.2477 138.93 150.348 +60.6974 138.317 151.733 +61.881 137.993 152.521 +62.5414 137.793 152.983 +64.3833 137.64 154.341 +66.0255 137.624 155.595 +69.3503 138.067 158.082 + +147.944 82.6213 150.006 +147.867 83.5909 150.499 +147.787 84.8522 151.226 +147.851 86.5095 151.619 + +99.615 95.6746 147.363 +99.1811 92.8 143.863 +98.5766 91.8938 142.548 +98.3313 91.5686 142.074 +97.8069 90.9323 141.139 +96.6192 89.517 139.041 + +99.615 95.6746 147.363 +102.972 97.3308 149.452 +104.724 97.7544 150.579 + +99.615 95.6746 147.363 +96.1198 96.1695 147.903 +95.0086 96.1916 147.91 +93.1309 96.1242 147.756 +91.1169 95.9514 147.36 +88.2995 95.8544 146.527 +86.8508 95.7558 145.991 +85.4867 95.6793 145.513 +81.8621 95.3218 144.064 +80.0653 95.1249 143.33 +78.6254 94.9421 142.705 +78.1847 94.8804 142.515 + +90.5135 150.292 138.104 +86.8999 147.594 131.34 +85.7142 146.474 129.26 +85.0025 145.966 127.84 +83.4109 144.779 124.722 +81.5923 143.393 121.457 +80.619 142.64 119.533 + +90.5135 150.292 138.104 +90.9449 156.055 135.739 +91.046 156.754 135.604 +91.003 159.158 134.818 +90.9703 160.014 134.535 +90.508 161.847 133.739 +88.8763 164.418 132.233 +88.0501 165.851 131.555 +87.0119 167.71 130.646 +85.5179 171.209 128.274 + +90.5135 150.292 138.104 +91.7676 149.196 141.659 +92.6349 148.853 143.849 +94.066 148.192 147.703 +94.401 146.989 152.587 + +117.221 76.2543 102.398 +117.477 76.6777 103.125 +118.17 77.7991 105.035 +118.751 78.9295 106.95 +119.366 80.2807 109.132 +119.813 81.2675 110.718 +120.326 82.4553 112.487 +120.452 84.0333 114.02 +120.492 84.7095 114.356 +120.903 88.3144 116.109 + +54.2184 155.689 147.308 +57.0426 154.63 149.221 +58.5487 153.913 149.791 +59.8621 153.294 150.305 +60.9499 152.784 150.755 +61.8698 152.348 151.137 +62.8903 151.86 151.561 +64.4202 151.129 152.209 +66.049 150.344 152.905 +68.2328 149.278 153.867 +70.8738 147.886 155.079 +75.1578 146.144 156.294 + +122.632 103.734 149.272 +117.694 103.487 151.503 + +122.632 103.734 149.272 +123.145 102.933 146.461 +123.447 102.248 144.325 +123.82 101.861 142.852 +124.038 101.061 140.313 +124.281 100.052 137.138 +124.09 99.1014 134.701 +123.87 98.2222 132.421 +123.533 97.3655 130.079 +123.059 96.2007 126.885 +122.742 95.3799 124.62 +122.636 94.6555 123.085 +122.51 94.0483 121.798 +122.185 93.2856 120.15 +121.861 92.5243 118.589 +120.903 88.3144 116.109 + +118.701 106.065 155.053 +117.694 103.487 151.503 + +64.4974 164.956 157.59 +64.5156 164.946 157.598 +65.0859 164.625 157.85 +66.3986 163.876 158.422 +67.6684 162.831 158.559 +69.0688 161.62 158.644 +70.9686 159.96 158.75 +72.4147 158.653 158.796 +74.1191 157.101 158.843 +76.2692 154.908 158.734 +77.8233 153.315 158.644 +77.9301 152.355 158.274 +77.9222 151.356 157.794 +77.5416 150.202 157.441 +75.1578 146.144 156.294 + +117.694 103.487 151.503 +115.42 103.032 151.971 +113.722 102.385 151.522 +112.305 101.886 151.08 +110.468 101.446 150.166 + +201.848 162.011 83.8723 +201.124 161.121 84.8928 +200.194 160.251 87.0208 + +67.0005 130.345 158.177 +72.0285 129.975 162.498 +73.639 127.635 164.847 +74.6077 125.423 166.914 +77.3838 122.734 169.568 + +67.0005 130.345 158.177 +63.0468 129.398 156.51 +62.0203 129.257 156.478 +61.0808 129.26 156.412 +59.0677 129.253 156.27 +58.1169 129.26 156.256 +57.6527 129.276 156.318 +57.024 129.303 156.48 + +67.0005 130.345 158.177 +66.4227 127.289 156.419 +66.3024 125.243 155.531 +65.3908 121.006 153.687 +62.7628 117.635 152.398 + +67.0005 130.345 158.177 +69.3503 138.067 158.082 + +95.6139 165.986 154.885 +96.3134 165.368 154.77 +97.102 164.67 154.642 +98.8221 163.138 154.372 +99.7056 161.844 154.137 +100.648 160.434 153.897 +102.836 158.339 152.718 + +219.934 113.058 162.207 +218.951 113.721 162.473 +216.507 115.078 163.08 +213.201 115.421 163.34 +211.098 115.528 163.466 +209.969 115.582 163.532 +209.625 115.598 163.552 +208.593 115.644 163.61 +207.315 115.7 163.682 +206.195 115.747 163.743 +204.462 115.814 163.836 +203.275 115.857 163.897 +201.767 115.91 163.975 +199.614 115.981 164.081 +197.699 116.042 164.174 +195.356 116.063 164.251 +191.85 115.854 164.196 + +153.62 112.901 167.546 +157.111 113.414 167.089 + +153.62 112.901 167.546 +149.791 109.724 169.376 +149.438 108.554 169.871 +149.286 108.163 169.813 +147.6 103.59 168.988 + +153.62 112.901 167.546 +149.915 115.226 166.531 +147.437 116.318 166.089 +145.268 117.172 165.542 +142.772 118.189 164.888 +141.038 119.129 164.274 +139.629 119.958 163.805 +137.462 121.764 162.517 + +113.148 122.841 173.304 +111.953 122.8 173.804 + +113.148 122.841 173.304 +115.304 123.432 172.989 +116.774 123.932 172.879 +118.334 124.481 172.781 +119.206 124.788 172.726 +121.121 125.456 172.597 +123.168 126.268 172.627 +124.975 126.993 172.69 +125.924 127.377 172.74 + +113.148 122.841 173.304 +111.797 122.127 173.146 +109.777 121.373 173.237 +107.475 120.518 173.343 +106.354 120.102 173.396 +104.263 119.326 173.493 +100.703 118.019 173.664 +98.6779 117.373 173.819 +96.9282 117.471 173.852 +96.1139 117.51 173.868 +94.6261 117.581 173.896 +92.7821 117.672 173.929 +84.9554 118.093 174.051 +83.5101 119.082 173.103 +82.7744 119.619 172.59 +81.9479 120.223 172.012 +81.2223 120.752 171.503 +80.35 121.406 170.873 +79.2821 121.689 170.595 +77.3838 122.734 169.568 + +169.647 103.832 166.361 +167.651 106.343 166.082 +166.241 108.065 166.461 +164.779 109.874 166.659 +166.755 112.973 165.526 + +169.647 103.832 166.361 +170.795 103.121 169.698 +171.284 102.76 170.868 +172.046 102.205 172.538 +172.624 101.834 173.708 +173.386 101.603 174.246 + +169.647 103.832 166.361 +170.013 102.384 162.458 +170.805 100.589 159.464 +171.825 98.2257 155.406 +173.033 95.8115 151.423 +174.218 93.5197 147.414 +174.691 92.399 145.017 +175.121 91.4092 142.871 +175.981 89.5399 138.873 +177.245 88.2945 136.794 +178.653 86.4597 133.523 + +144.878 102.899 174.575 +145.926 102.852 172.102 +147.6 103.59 168.988 + +157.111 113.414 167.089 +155.956 112.376 164.095 +155.767 110.934 161.429 +155.805 110.262 160.268 + +157.111 113.414 167.089 +159.262 113.363 166.721 +160.313 113.329 166.517 +161.797 113.25 166.285 +163.174 113.143 166.082 +166.755 112.973 165.526 + +86.4552 138.786 182.726 +86.6826 138.82 182.694 +88.0337 138.451 182.615 +89.1041 139.051 182.228 +90.7668 139.753 181.623 +91.568 140.136 181.318 +97.8852 142.007 177.897 + +76.4149 173.901 124.526 +73.0052 175.991 122.067 +73.7819 178.355 118.272 + +76.4149 173.901 124.526 +80.6521 172.429 126.21 +82.1857 172.136 126.748 +85.5179 171.209 128.274 + +110.468 101.446 150.166 +109.014 102.08 148.018 + +110.468 101.446 150.166 +108.398 100.169 150.271 +107.086 99.2783 150.439 +104.724 97.7544 150.579 + +183.805 83.5312 107.034 +182.672 83.9233 110.921 +181.76 84.2278 113.572 +180.878 84.5326 116.585 +180.129 84.7947 119.226 +179.648 84.9788 120.996 +179.245 85.1445 122.486 +178.704 85.2489 123.758 +177.811 84.9822 124.699 +177.024 84.7271 125.434 +176.097 84.5352 126.866 + +183.805 83.5312 107.034 +184.724 83.2719 106.16 +185.453 83.0613 105.256 + +183.805 83.5312 107.034 +183.315 83.597 104.329 +183.147 83.6126 103.086 +183.19 83.5729 101.808 +183.235 83.5298 100.405 + +85.8789 90.414 113.068 +88.1286 90.9798 112.686 +89.6339 91.5392 112.316 +90.8942 92.0501 111.967 +92.7994 92.9853 111.383 + +62.2229 140.746 166.423 +62.5428 140.75 166.295 +63.8134 140.762 165.756 +65.5329 140.774 165.02 +69.1583 140.775 163.383 +70.4663 140.718 162.331 +71.0564 140.71 161.605 +70.9685 140.637 160.562 +70.8593 140.397 158.559 + +214.075 90.4427 105.451 +213.86 91.0083 107.619 +213.646 91.4771 109.374 +212.969 92.0581 110.811 +212.249 92.6467 112.194 +211.869 92.9524 112.903 +209.612 94.7392 117.003 +208.035 95.9874 119.867 +206.526 97.1813 122.605 +205.428 98.051 124.601 +203.941 99.2284 127.302 +202.409 100.433 130.056 +200.388 102.067 133.851 + +137.098 134.09 147.622 +134.623 132.853 151.31 + +137.098 134.09 147.622 +137.85 134.9 145.148 +138.546 135.479 143.226 +139.225 136.045 140.711 +140.361 136.347 136.975 +140.855 136.477 135.356 +141.22 136.573 134.162 +141.909 136.728 131.841 +142.705 136.625 128.71 +143.103 136.566 127.024 +143.411 136.52 125.714 +143.8 136.461 124.044 +144.272 136.368 121.207 +144.838 136.232 116.982 +145.098 136.164 114.943 +145.202 136.135 114.091 +145.533 136.058 111.62 +146.238 136.047 108.485 +146.539 136.052 107.311 +146.75 136.038 106.242 +147.794 136.206 104.565 +149.71 136.551 102.057 +151.631 136.917 100.099 +152.834 137.101 97.8628 + +137.098 134.09 147.622 +140.206 132.06 152.686 +141.508 132.159 152.541 +142.919 131.961 153.077 +143.337 131.665 153.163 +145.583 128.927 152.801 +147.056 126.976 152.362 +147.975 125.733 152.035 +148.881 124.505 151.68 +150.002 122.957 151.274 +151.344 121.712 150.116 +153.14 120.126 148.511 +154.545 119.009 147.154 + +94.401 146.989 152.587 +98.2275 147.032 153.527 +100.515 147.028 154.956 + +94.401 146.989 152.587 +91.9812 146.575 153.567 +90.6046 146.36 154.346 +87.6461 146.343 154.728 +86.6685 146.277 154.882 +80.5806 146.487 155.935 +75.1578 146.144 156.294 + +93.6349 150.686 107.521 +93.5741 150.643 107.536 +92.6802 150.014 107.735 +90.3461 148.391 108.194 +87.7417 146.639 108.314 +82.5022 143.212 108.495 +78.7852 141.901 110.422 + +100.531 94.6789 33.5643 +100.353 95.0535 35.6746 +100.311 95.1391 36.1734 +100.179 95.3463 37.0777 +100.162 95.4491 38.2798 +99.7832 95.5787 39.87 +98.4802 95.8123 42.5902 + +72.8208 105.14 35.2123 +72.7628 105.807 36.1948 +72.6135 107.594 38.8184 +72.5596 109.027 40.8303 +72.5508 111.297 43.9262 +72.6056 111.86 44.388 +72.6875 112.526 45 +72.736 113.612 45.5606 +72.7807 115.338 46.39 +72.8152 116.523 47.0159 +72.8121 119.169 47.7203 + +127.503 83.8366 36.4597 +125.901 84.7885 37.7116 + +93.2669 95.8549 42.5271 +94.2488 95.8892 42.9568 +98.4802 95.8123 42.5902 + +147.851 86.5095 151.619 +147.95 89.3227 153.319 +147.881 90.539 154.9 +147.851 92.4524 156.779 +147.804 94.2277 158.692 +147.798 94.412 158.898 +147.778 95.1611 159.731 +147.757 95.9829 160.639 +147.744 96.7291 161.452 +147.728 97.8233 162.635 +147.686 99.6101 164.613 +147.6 103.59 168.988 + +73.4588 110.468 60.4054 +73.8005 111.867 60.4663 +74.2254 116.638 58.7871 +73.9801 119.509 57.1376 + +80.0347 128.548 125.692 +79.6636 129.345 125.723 +79.2256 130.962 125.236 +77.3069 131.484 124.371 + +53.1627 149.63 106.66 +54.3526 148.384 107.549 +55.3439 147.353 108.228 +56.7029 145.936 109.141 +58.0363 144.486 109.819 +60.2184 141.923 110.96 + +96.051 182.453 114.395 +95.8722 181.658 114.877 +95.5631 180.898 115.463 +95.221 179.989 116.198 +94.5418 178.171 117.661 +94.1405 177.03 118.525 +93.3338 175.4 119.843 + +201.409 161.651 87.2789 +200.194 160.251 87.0208 + +52.2455 141.411 117.977 +55.2916 141.535 115.95 +56.7823 141.5 114.945 +60.2184 141.923 110.96 + +52.2455 141.411 117.977 +51.0541 140.335 118.923 +50.5032 139.992 119.338 +50.1404 139.782 119.608 + +83.033 178.113 134.072 +83.568 176.122 133.049 +83.7573 175.436 132.675 +83.9421 174.715 132.264 +84.2232 173.744 131.678 +84.4189 173.074 131.199 +84.6744 172.327 130.77 +85.5179 171.209 128.274 + +54.6579 116.021 125.201 +55.9795 116.287 125.151 +57.1855 116.563 125.111 +59.4458 117.38 125.062 +63.2676 118.529 124.945 + +62.6789 113.824 154.732 +62.9124 115.255 153.96 +62.7628 117.635 152.398 + +103.424 139.242 164.383 +101.803 141.887 161.722 +101.136 142.794 160.754 +101.369 143.464 159.673 +100.515 147.028 154.956 + +181.919 113.747 160.026 +183.167 115.827 163.453 +183.837 116.927 164.886 +187.954 117.175 165.248 +189.649 116.67 164.845 +191.85 115.854 164.196 + +181.919 113.747 160.026 +175.277 114.133 162.987 +173.927 114.074 163.36 +170.51 114.013 164.447 +168.158 113.647 165.115 +166.755 112.973 165.526 + +181.919 113.747 160.026 +184.289 112.924 157.704 +185.314 111.936 155.535 +186.055 111.229 153.98 +186.655 110.968 153.298 +187.594 110.624 152.351 +188.453 110.213 151.365 +189.325 109.697 150.242 +189.968 109.302 149.392 +190.524 108.95 148.637 +191.124 108.562 147.808 +192.145 107.887 146.369 +192.981 107.322 145.167 +193.935 106.676 143.794 +194.407 106.355 143.111 +195.09 105.885 142.109 +195.806 105.389 141.054 +196.937 104.584 139.323 +198.614 103.35 136.622 +200.388 102.067 133.851 + +124.018 117.11 176.88 +124.776 117.435 176.679 +126.384 118.116 176.214 +127.229 118.318 175.476 +127.71 118.401 174.968 +128.481 118.313 173.777 +129.285 118.213 172.479 +130.227 116.673 167.898 + +72.8121 119.169 47.7203 +72.5342 121.663 45.6542 +72.4665 121.793 44.106 +72.3487 122.123 43.165 +72.1927 122.505 41.9108 +72.1556 122.598 41.6129 +72.0415 122.878 40.7008 +71.8382 123.378 39.0778 +71.5627 124.111 36.8786 +71.1584 125.81 33.6384 +71.0324 126.556 32.5039 + +72.8121 119.169 47.7203 +73.2291 119.406 51.4996 +73.9801 119.509 57.1376 + +134.623 132.853 151.31 +133.954 129.566 155.945 +134.209 128.131 157.348 +134.428 126.48 158.935 +135.042 124.917 160.126 +135.427 123.843 160.935 +137.462 121.764 162.517 + +134.623 132.853 151.31 +132.381 133.243 152.498 +130.198 133.269 154.174 +128.142 133.489 155.507 +125.215 134.943 155.871 +123.636 135.754 156.034 +122.364 136.328 156.274 +121.335 136.793 156.467 +120.322 137.251 156.657 +119.315 137.706 156.846 +117.81 138.387 157.133 +114.438 139.91 157.771 +113.287 140.442 158.036 +111.115 141.497 158.904 +108.582 142.76 159.536 + +138.162 138.601 9.71481 +139.196 137.043 17.2367 +140.009 135.837 23.3368 +140.225 135.518 24.9814 +140.494 135.121 27.0234 +140.704 134.811 28.6256 +140.95 134.446 30.4981 +141.365 133.834 33.6622 +141.665 133.403 36.3515 +141.873 133.115 38.5699 +141.973 132.977 39.6369 +142.103 132.797 41.0426 +142.246 132.598 42.5289 +142.504 132.277 46.0637 +142.733 132.034 49.9747 +142.825 131.937 51.5179 +142.906 131.851 52.8913 +143.052 131.702 55.165 +143.173 131.575 57.1548 +143.194 131.693 59.6412 +143.151 131.824 61.5241 +143.134 131.928 63.073 +143.083 132.098 65.6293 +142.991 132.436 70.5731 +142.816 132.695 73.3165 +142.2 132.875 75.0686 +141.329 133.133 77.5512 +139.671 133.2 79.1787 + +130.218 84.4908 44.9766 +129.854 84.658 44.9649 +125.645 86.5985 48.0148 + +125.645 86.5985 48.0148 +125.525 86.1982 45.3974 +125.6 85.9339 43.9746 +125.72 85.6376 42.4654 +125.901 84.7885 37.7116 + +99.134 98.6006 58.3369 +100.866 96.8182 55.5209 + +77.5689 162.766 66.1985 +77.6291 162.511 66.347 +77.7696 161.54 66.8938 +77.8554 160.992 67.1833 +78.0001 160.011 67.6884 +78.4147 156.996 67.9795 + +86.2866 91.5121 71.941 +87.0984 91.4126 72.2989 +89.4314 91.1494 73.3702 +92.0223 90.9428 74.8762 +95.0145 90.8691 74.3417 +96.611 90.8302 74.0764 +97.9104 90.7819 73.8512 +99.0862 90.4824 73.5335 +102.37 89.953 72.9031 + +71.6117 104.63 83.3448 +70.9731 106.201 83.0274 +70.1649 108.405 82.6446 +69.5535 110.538 82.3844 +68.9269 113.019 82.1301 +69.8552 114.587 82.7025 +71.1654 117.024 83.5028 +72.3494 118.96 84.1649 +73.4834 120.613 84.7469 +74.3676 121.51 85.1141 +75.6483 122.63 85.5455 +76.9758 123.252 85.142 +81.7039 124.026 85 + +75.5857 183.215 108.611 +75.5789 183.197 108.646 +75.5652 183.162 108.713 +75.2835 182.848 109.515 + +56.2777 165.156 116.875 +57.2439 165.052 116.564 +57.4957 165.022 116.484 +58.7704 164.867 116.073 +59.8366 164.761 115.674 +60.7432 164.905 114.922 +65.2745 163.976 113.788 + +59.7953 104.835 123.029 +60.1185 106.612 123.226 +60.5099 108.413 123.502 +61.7244 113.687 124.33 +63.2676 118.529 124.945 + +117.575 84.4393 120.476 +118.145 84.8318 120.289 +118.938 85.617 118.995 +120.903 88.3144 116.109 + +191.646 82.1407 128.141 +189.874 82.6614 129.423 +186.81 83.5814 131.57 +185.567 84.1305 132.33 +183.662 85.1007 133.383 +181.529 86.1133 134.35 +178.653 86.4597 133.523 + +67.7233 179.217 121.751 +68.5052 178.942 121.484 +69.2559 178.643 121.33 +70.3307 178.241 121.163 +73.7819 178.355 118.272 + +104.419 96.1337 153.083 +104.417 96.2148 152.916 +104.724 97.7544 150.579 + +70.6218 115.037 175.9 +70.6411 115.096 175.875 +71.0189 116.138 175.328 +71.2814 116.84 174.941 +71.6723 117.852 174.326 +73.2648 119.515 172.736 +74.0039 120.279 172.003 +74.348 120.709 171.584 +74.8063 121.81 170.495 +77.3838 122.734 169.568 + +95.606 142.97 180.448 +97.8852 142.007 177.897 + +121.984 132.135 69.8458 +123.096 132.005 71.3436 +124.699 131.96 72.8582 +125.351 131.947 73.4661 +126.282 131.932 74.335 +128.913 131.996 76.5196 +130.561 132.163 77.5723 +133.032 132.505 78.6017 +134.6 132.726 79.2376 +135.927 132.879 79.4344 +139.671 133.2 79.1787 + +63.2676 118.529 124.945 +66.8928 121.8 125.14 +68.4283 123.11 125.203 +70.0249 124.546 125.255 +70.2913 124.799 125.256 +71.8896 126.336 125.242 +73.1014 127.529 125.174 +74.0631 128.488 125.103 +75.1523 129.933 124.598 +77.3069 131.484 124.371 + +102.836 158.339 152.718 +102.383 156.439 153.586 +102.148 151.2 154.516 +100.515 147.028 154.956 + +93.3338 175.4 119.843 +96.3426 172.993 118.861 +97.6247 172.439 118.114 +98.4465 172.205 117.616 + +93.3338 175.4 119.843 +92.6589 175.112 120.445 +91.7177 174.356 121.451 +89.5162 172.455 123.98 +85.5179 171.209 128.274 + +92.7994 92.9853 111.383 +95.8883 92.7141 110.964 +97.9353 92.552 110.668 +99.1637 92.414 110.501 +100.643 92.2564 110.305 +105.863 91.6136 109.516 + +204.379 99.5227 128.948 +200.388 102.067 133.851 + +83.2766 125.401 96.3324 +80.7928 130.01 97.0484 +79.7561 131.935 98.2504 +79.5274 132.399 98.4313 +78.913 133.681 98.9454 +77.7852 136.307 100.615 + +83.2766 125.401 96.3324 +81.962 125.383 89.8166 +81.7039 124.026 85 + +60.2184 141.923 110.96 +65.7557 138.894 109.509 + +102.37 89.953 72.9031 +105.116 90.7493 73.5158 +105.86 91.0468 73.7937 +108.779 92.0873 75.342 + +78.4147 156.996 67.9795 +78.6679 155.523 70.3109 +78.8451 154.547 72.2847 +78.9555 153.887 73.1561 +79.0495 153.323 73.8664 +79.1491 152.743 74.5967 +79.3014 151.856 75.7108 +79.4575 151.311 76.3675 +79.7234 150.331 77.4993 +80.1313 148.875 79.1721 +80.3282 144.293 84.7584 + +139.671 133.2 79.1787 +141.156 133.657 81.4758 +141.584 133.79 82.145 +141.94 133.914 82.7939 +142.398 134.066 83.5873 +143.671 134.419 85.2669 +144.723 134.715 86.6897 +145.903 135.06 88.3537 +147.384 135.497 90.4895 +148.417 135.804 92.0152 +149.255 136.051 93.1952 +151.082 136.571 95.2191 +152.834 137.101 97.8628 + +78.5962 158.884 111.503 +75.8372 160.375 112.438 +73.876 160.721 113.486 +71.4088 161.302 114.376 +67.4892 163.144 113.842 +65.2745 163.976 113.788 + +78.5962 158.884 111.503 +80.1904 153.948 113.773 +80.4862 151.972 114.928 +80.7639 150.556 115.736 +80.8499 148.33 116.299 +80.3308 145.31 115.445 + +121.308 90.1466 110.362 +115.522 91.7707 111.272 +111.353 91.5936 109.642 +105.863 91.6136 109.516 + +121.308 90.1466 110.362 +128.016 88.9504 106.464 +129.03 88.6759 105.818 +130.262 88.3392 105.092 +131.722 87.8825 104.212 +136.177 85.8858 102.65 + +121.308 90.1466 110.362 +120.903 88.3144 116.109 + +200.194 160.251 87.0208 +197.122 156.859 88.0642 +195.462 155.071 88.9655 +194.69 154.269 89.4532 +193.926 153.499 89.9147 +193.239 152.832 90.3166 +192.326 151.98 90.8258 +191.207 150.939 91.4489 +190.286 150.111 91.9389 +188.286 148.416 92.9241 +186.582 147.054 93.7021 +185.27 146.095 94.2338 +183.078 145.393 94.8614 +181.254 144.844 95.3606 +180.035 144.48 95.6921 +177.285 143.664 96.4358 +175.813 143.235 96.8293 +174.181 142.764 97.2618 +171.843 142.103 97.8707 +170.148 141.629 98.3073 +165.931 140.47 99.3846 +161.92 139.38 100.143 +160.714 139.054 99.69 +159.037 138.618 99.0589 +156.994 138.113 98.5701 +155.215 137.665 97.9346 +152.834 137.101 97.8628 + +77.3069 131.484 124.371 +77.8011 136.842 119.925 +78.6694 138.726 119.642 +80.619 142.64 119.533 + +80.3308 145.31 115.445 +78.7852 141.901 110.422 + +80.3308 145.31 115.445 +80.1472 142.876 117.329 +80.619 142.64 119.533 + +178.653 86.4597 133.523 +176.858 85.7053 130.906 +175.88 84.7912 128.761 +176.097 84.5352 126.866 + +67.2101 141.299 86.6562 +73.9272 140.856 90.4568 + +137.913 86.9824 90.8748 +136.676 87.0994 93.6931 +135.142 87.0835 96.0474 +134.246 87.1896 98.4681 +136.177 85.8858 102.65 + +78.7852 141.901 110.422 +76.3985 139.181 106.35 + +75.2835 182.848 109.515 +75.1767 182.295 110.575 +74.9107 181.426 112.338 +74.5579 180.158 114.885 +73.7819 178.355 118.272 + +100.866 96.8182 55.5209 +103.523 95.5641 59.8603 +104.308 95.2298 61.3552 +104.733 95.036 62.0998 +105.013 94.9114 62.6383 +106.451 94.2613 65.4832 +107.404 93.8369 66.9428 +108.241 93.4638 68.1883 +109.118 93.0328 69.8205 +110.461 92.2893 72.2288 + +100.866 96.8182 55.5209 +100.482 96.3446 51.1849 +100.086 96.2835 49.1402 +99.7205 96.234 47.7864 +98.4802 95.8123 42.5902 + +97.8852 142.007 177.897 +100.871 142.517 175.978 +102.611 142.864 174.9 +104.725 143.29 173.588 +105.706 143.415 172.755 +106.169 143.471 172.33 +107.164 143.594 171.179 +108.816 143.77 169.608 +107.08 143.438 161.908 +108.582 142.76 159.536 + +65.7557 138.894 109.509 +68.5713 139.132 108.973 +69.9468 139.2 108.555 +76.3985 139.181 106.35 + +143.789 82.3533 103.716 +147.069 81.3156 106.068 +147.936 81.1058 106.859 +149.228 80.8158 108.041 +149.897 80.6672 108.657 +151.652 80.2673 110.152 +154.164 79.8105 111.524 +156.897 79.359 113.066 +160.592 78.9805 115.411 +163.282 78.8926 117.329 +164.072 78.9211 117.954 +167.681 79.8606 121.603 +171.169 81.5775 125.86 +172.087 82.3002 126.498 +173.057 83.0278 126.968 +176.097 84.5352 126.866 + +143.789 82.3533 103.716 +140.925 83.5917 102.805 +139.854 84.1147 102.719 +138.756 84.6463 102.675 +136.177 85.8858 102.65 + +108.779 92.0873 75.342 +110.461 92.2893 72.2288 + +69.3503 138.067 158.082 +70.8593 140.397 158.559 + +73.9272 140.856 90.4568 +78.2128 142.331 87.8051 +80.3282 144.293 84.7584 + +73.9272 140.856 90.4568 +75.3867 139.578 93.3638 +75.7 138.444 95.7412 +75.8338 138.202 96.3378 +77.7852 136.307 100.615 + +83.2234 120.801 76.5165 +82.4246 120.156 73.4506 +80.677 121.173 72.1018 +80.3677 121.269 71.673 +79.4916 121.559 70.4854 +78.3154 121.628 67.8343 +77.5388 121.724 66.1089 +76.9422 121.792 64.793 +76.4322 121.994 63.6542 +75.8873 121.971 62.4044 +75.4683 121.981 61.4311 +74.7801 122.032 59.782 +73.9801 119.509 57.1376 + +83.2234 120.801 76.5165 +82.2348 122.635 80.8777 +82.0259 122.962 81.7245 +81.7039 124.026 85 + +83.2234 120.801 76.5165 +85.9082 120.537 79.1001 +87.9279 119.848 79.4764 +90.9187 118.57 78.7805 +92.1933 118.14 78.8521 +93.1586 117.814 78.9335 + +130.227 116.673 167.898 +133.124 119.598 166.151 +134.296 120.499 164.837 +137.462 121.764 162.517 + +108.582 142.76 159.536 +105.886 144.329 157.561 +104.232 145.167 156.896 +100.515 147.028 154.956 + +77.7852 136.307 100.615 +77.4771 137.823 103.34 +76.3985 139.181 106.35 + +70.8593 140.397 158.559 +71.7459 141.746 157.883 +72.7059 143.232 157.281 +75.1578 146.144 156.294 + diff --git a/src/MeshSkeletonizationPlugin/CGALMeshUtils.h b/src/MeshSkeletonizationPlugin/CGALMeshUtils.h new file mode 100644 index 0000000..9ac9857 --- /dev/null +++ b/src/MeshSkeletonizationPlugin/CGALMeshUtils.h @@ -0,0 +1,89 @@ +#pragma once +// Reuses the Kernel/Polyhedron/Point/HalfedgeDS typedefs already declared (at global scope) in MeshSkeletonization.h. +#include +#include +#include +#include +#include +#include + +#include + +namespace meshskeletonizationplugin +{ +namespace cgalutils +{ + /// Builds a CGAL Polyhedron_3 from a flat vertex/triangle mesh, mirroring + /// MeshSkeletonization::geometryToPolyhedronOp but as a free/shared helper + /// so multiple components can build closed meshes without duplicating it. + template + class MeshToPolyhedronOp : public CGAL::Modifier_base + { + public: + MeshToPolyhedronOp(const VecCoord& vertices, const SeqTriangles& triangles) + : m_vertices(vertices), m_triangles(triangles) + { + } + + void operator()(HalfedgeDS& hds) override + { + CGAL::Polyhedron_incremental_builder_3 builder(hds, true); + builder.begin_surface(m_vertices.size(), m_triangles.size()); + + for (const auto& v : m_vertices) + builder.add_vertex(Point(v[0], v[1], v[2])); + + for (const auto& tri : m_triangles) + { + builder.begin_facet(); + for (int j = 0; j < 3; ++j) + builder.add_vertex_to_facet(tri[j]); + builder.end_facet(); + } + + if (builder.check_unconnected_vertices()) + builder.remove_unconnected_vertices(); + + builder.end_surface(); + } + + private: + const VecCoord& m_vertices; + const SeqTriangles& m_triangles; + }; + + using AABBTraits = CGAL::AABB_traits>; + using AABBTree = CGAL::AABB_tree; + using PointInsideTest = CGAL::Side_of_triangle_mesh; + + /// A closed mesh (segment, tumor, ...) ready for point-in-mesh and + /// closest-point queries: build a Polyhedron_3 from raw vertices/ + /// triangles, then an AABB tree + inside/outside test backed by it. + struct ClosedMeshQuery + { + Polyhedron polyhedron; + std::unique_ptr tree; + std::unique_ptr insideTest; + + void build() + { + tree = std::make_unique(CGAL::faces(polyhedron).first, CGAL::faces(polyhedron).second, polyhedron); + tree->accelerate_distance_queries(); + insideTest = std::make_unique(*tree); + } + + /// Convenience: build the polyhedron from flat vertices/triangles and + /// immediately build the tree/inside-test on top of it. No-ops (and + /// leaves tree/insideTest null) if the resulting polyhedron is empty. + template + void buildFrom(const VecCoord& vertices, const SeqTriangles& triangles) + { + MeshToPolyhedronOp op(vertices, triangles); + polyhedron.delegate(op); + if (!polyhedron.is_empty()) + build(); + } + }; + +} // namespace cgalutils +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h index c59ea3d..ed2b5e1 100644 --- a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h +++ b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h @@ -38,18 +38,17 @@ class SkeletonSegmentMapper : public sofa::core::DataEngine sofa::core::objectmodel::BaseLink::FLAG_STOREPATH | sofa::core::objectmodel::BaseLink::FLAG_STRONGLINK> l_skeletonReader; - /// One closed mesh per liver segment (e.g. the Couinaud collision meshes), - /// in the same order as d_inSegmentNames. + /// One closed mesh per liver segment (the Couinaud collision meshes), in the same order as d_inSegmentNames. sofa::core::objectmodel::MultiLink< SkeletonSegmentMapper, sofa::core::loader::MeshLoader, sofa::core::objectmodel::BaseLink::FLAG_STOREPATH> l_segmentMeshes; - - //Component parameters + // Inputs sofa::core::objectmodel::Data> d_inSegmentNames; ///< Human-readable name per entry of l_segmentMeshes, e.g. "II", "IVa", "VIII" sofa::core::objectmodel::DataFileName d_outSegmentReportFilename; ///< Optional CSV report: id, x, y, z, segment name + // Outputs sofa::core::objectmodel::Data> d_outNodeSegments; ///< Segment index per skeleton node (into l_segmentMeshes/d_inSegmentNames, -1 = unknown), indexed like graph().nodes() sofa::core::objectmodel::Data> d_outNodeSegmentNames; ///< Same as d_outNodeSegments, resolved to names ("unknown" if -1) @@ -66,9 +65,7 @@ class SkeletonSegmentMapper : public sofa::core::DataEngine private: SkeletonSegmentMapper(); virtual ~SkeletonSegmentMapper() = default; - - /// Local working copy of the linked reader's graph, augmented with - /// segment labels (SkeletonGraph is a plain value type, cheap to copy). + /// Local working copy of the linked reader's graph, augmented with segment labels SkeletonGraph m_graph; }; diff --git a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl index 9f1870b..7e390e7 100644 --- a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl +++ b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl @@ -3,19 +3,14 @@ // Reuses the Kernel/Polyhedron/Point typedefs already declared (at global // scope) in MeshSkeletonization.h, so segment meshes are built the same way -// MeshSkeletonization builds its own polyhedron. +// MeshSkeletonization builds its own polyhedron - and the shared closed-mesh +// query helper (also used by TumorCutPointSelector) so this doesn't keep its +// own private copy of the same CGAL polyhedron/AABB-tree plumbing. #include - +#include #include #include #include - -#include -#include -#include -#include -#include - #include #include #include @@ -23,67 +18,6 @@ namespace meshskeletonizationplugin { -namespace -{ - // Builds a CGAL Polyhedron_3 from a flat vertex/triangle mesh, mirroring - // MeshSkeletonization::geometryToPolyhedronOp but as a free function so it - // can be reused here without duplicating a private nested class. - template - class MeshToPolyhedronOp : public CGAL::Modifier_base - { - public: - MeshToPolyhedronOp(const VecCoord& vertices, const SeqTriangles& triangles) - : m_vertices(vertices), m_triangles(triangles) - { - } - - void operator()(HalfedgeDS& hds) override - { - CGAL::Polyhedron_incremental_builder_3 builder(hds, true); - builder.begin_surface(m_vertices.size(), m_triangles.size()); - - for (const auto& v : m_vertices) - builder.add_vertex(Point(v[0], v[1], v[2])); - - for (const auto& tri : m_triangles) - { - builder.begin_facet(); - for (int j = 0; j < 3; ++j) - builder.add_vertex_to_facet(tri[j]); - builder.end_facet(); - } - - if (builder.check_unconnected_vertices()) - builder.remove_unconnected_vertices(); - - builder.end_surface(); - } - - private: - const VecCoord& m_vertices; - const SeqTriangles& m_triangles; - }; - - using AABBTraits = CGAL::AABB_traits>; - using AABBTree = CGAL::AABB_tree; - using PointInsideTest = CGAL::Side_of_triangle_mesh; - - /// One segment mesh, ready for point-in-mesh + closest-point queries. - struct SegmentMeshQuery - { - Polyhedron polyhedron; - std::unique_ptr tree; - std::unique_ptr insideTest; - - void build() - { - tree = std::make_unique(CGAL::faces(polyhedron).first, CGAL::faces(polyhedron).second, polyhedron); - tree->accelerate_distance_queries(); - insideTest = std::make_unique(*tree); - } - }; -} // anonymous namespace - template SkeletonSegmentMapper::SkeletonSegmentMapper() : l_skeletonReader(initLink("skeletonReader", @@ -148,21 +82,14 @@ void SkeletonSegmentMapper::doUpdate() m_graph = l_skeletonReader->graph(); // Build one point-in-mesh query per linked segment mesh. - std::vector segmentQueries(l_segmentMeshes.size()); + std::vector segmentQueries(l_segmentMeshes.size()); for (std::size_t i = 0; i < l_segmentMeshes.size(); ++i) { sofa::core::loader::MeshLoader* loader = l_segmentMeshes.get(i); if (!loader) continue; - MeshToPolyhedronOp< - sofa::type::vector, - sofa::type::vector> - op(loader->d_positions.getValue(), loader->d_triangles.getValue()); - - segmentQueries[i].polyhedron.delegate(op); - if (!segmentQueries[i].polyhedron.is_empty()) - segmentQueries[i].build(); + segmentQueries[i].buildFrom(loader->d_positions.getValue(), loader->d_triangles.getValue()); } // Raw per-node label: which segment mesh contains this node, or (if none diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp index f7e51be..9ac467a 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp @@ -1,5 +1,4 @@ #include "SkeletonGraph.h" - #include #include #include @@ -65,8 +64,7 @@ bool SkeletonGraph::loadFromFile(const std::string& filename, double mergeTolera while (std::getline(in, line)) { - // Trim trailing whitespace/CR so blank-line detection works on - // files written or edited on Windows too. + // Trim trailing whitespace/CR so blank-line detection works on files written or edited on Windows too. while (!line.empty() && (line.back() == '\r' || line.back() == ' ' || line.back() == '\t')) line.pop_back(); @@ -199,6 +197,57 @@ int SkeletonGraph::closestNodeId(const std::array& p) const return best; } +void SkeletonGraph::buildTreeAutoRoot() +{ + if (m_nodes.empty()) + return; + + std::vector visited(m_nodes.size(), false); + int bestRoot = -1; + std::size_t bestSize = 0; + + for (const SkeletonNode& start : m_nodes) + { + if (visited[start.id()]) + continue; + + // BFS this component, just to measure it and grab a representative node. + std::vector component; + std::queue q; + visited[start.id()] = true; + q.push(start.id()); + + while (!q.empty()) + { + int u = q.front(); + q.pop(); + component.push_back(u); + + auto it = m_adjacency.find(u); + if (it == m_adjacency.end()) + continue; + + for (int v : it->second) + { + if (!visited[v]) + { + visited[v] = true; + q.push(v); + } + } + } + + if (component.size() > bestSize) + { + bestSize = component.size(); + bestRoot = component.front(); + } + } + + if (bestRoot >= 0) + buildTree(bestRoot); +} + void SkeletonGraph::buildTree(const std::array& entryPoint) { int root = closestNodeId(entryPoint); @@ -697,4 +746,4 @@ std::vector SkeletonGraph::affectedSegments(const std::vector& affecte return std::vector(segments.begin(), segments.end()); } -} // namespace meshskeletonizationplugin +} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h index 200542f..9dd0e4a 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h @@ -37,6 +37,16 @@ class SkeletonGraph void buildTree(const std::array& entryPoint); void buildTree(int rootId); + /// Picks a root automatically, with no entry point needed: the node + /// belonging to the LARGEST connected component of the raw connectivity + /// graph. Real vessel skeletonization output is typically one dominant + /// tree plus a handful of small disconnected fragments (noise); this + /// guarantees the tree is rooted in the dominant structure instead of + /// risking a tiny isolated fragment, which is easy to hit by accident + /// with a naive nearest-point-to-some-coordinate pick (e.g. a caller + /// falling back to the origin when no real entry point is known). + void buildTreeAutoRoot(); + /// Best-effort correspondence between each skeleton node and the closest /// vertex of the input (vessel) mesh; fills meshVertexId/distanceToMesh. void computeMeshCorrespondence(const std::vector>& meshVertices); @@ -129,4 +139,4 @@ class SkeletonGraph std::vector m_nodeSegment; }; -} // namespace meshskeletonizationplugin +} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl index 1745b8f..93170ea 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl @@ -10,7 +10,7 @@ template SkeletonReader::SkeletonReader() : d_inSkeletonFilename(initData(&d_inSkeletonFilename, "filename", "Skeleton polyline file to read (e.g. skeleton.txt)")) , d_inVertices(initData(&d_inVertices, "inputVertices", "Optional input mesh vertices, to link skeleton nodes to the mesh")) - , d_inEntryPoint(initData(&d_inEntryPoint, Vec3(0, 0, 0), "entryPoint", "Approx. entry point; closest node becomes the tree root")) + , d_inEntryPoint(initData(&d_inEntryPoint, Vec3(0, 0, 0), "entryPoint", "Approx. entry point; closest node becomes the tree root. If left unset, a root is instead picked automatically from the largest connected component of the skeleton.")) , d_outVTKFilename(initData(&d_outVTKFilename, "outputVTK", "File path to export the rooted tree (.vtk)")) , d_outReportFilename(initData(&d_outReportFilename, "outputReport", "File path to export a per-node CSV report (id, x, y, z, parentId, childrenIds, pathFromRoot)")) , d_outNodeCount(initData(&d_outNodeCount, 0, "nodeCount", "Number of skeleton nodes read")) @@ -61,8 +61,22 @@ void SkeletonReader::doUpdate() msg_info() << "Skeleton loaded: " << m_graph.nodes().size() << " node(s)."; d_outNodeCount.setValue(static_cast(m_graph.nodes().size())); - const Vec3& entry = d_inEntryPoint.getValue(); - m_graph.buildTree({ double(entry[0]), double(entry[1]), double(entry[2]) }); + if (d_inEntryPoint.isSet()) + { + const Vec3& entry = d_inEntryPoint.getValue(); + m_graph.buildTree({ double(entry[0]), double(entry[1]), double(entry[2]) }); + msg_info() << "Rooted using explicit entryPoint " << entry << "."; + } + else + { + // No explicit entry point given - don't silently root the tree at + // whatever's nearest the origin (which can land in a small, + // disconnected fragment far from the real vessel trunk, since real + // coordinates are almost never near (0,0,0)). Pick a root from the + // largest connected component instead. + m_graph.buildTreeAutoRoot(); + msg_info() << "No entryPoint set; auto-rooted from the largest connected component."; + } if (!m_graph.hasRoot()) { diff --git a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h index 484a811..cebec57 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h +++ b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h @@ -19,6 +19,22 @@ using namespace sofa::defaulttype; namespace meshskeletonizationplugin { +/// Simulates a resection (vessel transection) at one or more skeleton node +/// ids and reports what it would devascularize: which skeleton nodes can no +/// longer reach the root (blood source) once the cut node(s) are removed +/// from the vessel graph, and which liver segments those nodes belong to. +/// +/// This is deliberately NOT a plain "everything below the cut" (subtree) +/// computation: a node distal to a cut can still be perfused if a +/// collateral/anastomosis connects it back to the root via a path that +/// avoids every cut node. See SkeletonGraph::simulateResection() for the +/// underlying reachability analysis. +/// +/// Typical use: link to an existing SkeletonSegmentMapper (so both the tree +/// and the segment labels are available), set d_inCutNodeIds to the node(s) +/// a candidate resection would sever, and read back d_outAffectedNodeIds / +/// d_outAffectedSegmentNames to see the consequence before committing to a +/// surgical plan. template class SkeletonResectionSimulator : public sofa::core::DataEngine { @@ -31,7 +47,8 @@ class SkeletonResectionSimulator : public sofa::core::DataEngine typedef type::Vec<3, Real> Vec3; /// The segmented skeleton to run resection scenarios against. If left - /// unset, the first SkeletonSegmentMapper found in the context is used. + /// unset, the first SkeletonSegmentMapper found in the + /// context is used. sofa::core::objectmodel::SingleLink< SkeletonResectionSimulator, SkeletonSegmentMapper, @@ -92,4 +109,4 @@ class SkeletonResectionSimulator : public sofa::core::DataEngine extern template class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonResectionSimulator; #endif -} // namespace meshskeletonizationplugin \ No newline at end of file +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl index f7ac96b..71af6e3 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl +++ b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl @@ -66,7 +66,7 @@ void SkeletonResectionSimulator::init() } setDirtyValue(); - update(); // computes each time without waiting for something to read an output Data + update(); // compute eagerly, don't wait for something to read an output Data } template @@ -74,7 +74,9 @@ void SkeletonResectionSimulator::doUpdate() { if (!l_segmentMapper) return; - // Working on copy of the already segmented graph so the candidate is re-run per candidate without touching the mapper + + // Work on our own copy of the mapper's (already segmented) graph so we + // can re-run this per candidate cut without touching the mapper. m_graph = l_segmentMapper->graph(); const auto& cutIds = d_inCutNodeIds.getValue(); @@ -123,7 +125,9 @@ void SkeletonResectionSimulator::doUpdate() template void SkeletonResectionSimulator::updateSegmentColors() { - // colors of the segments before and after (green --> red) + // Re-checked every draw() call since there's no cheap event hook here + // for "time crossed the threshold" - this is a handful of colors, so + // recomputing it every frame is negligible. static const sofa::type::RGBAColor safeColor(0.20f, 0.80f, 0.20f, 1.0f); static const sofa::type::RGBAColor affectedColor(0.90f, 0.10f, 0.10f, 1.0f); @@ -132,7 +136,8 @@ void SkeletonResectionSimulator::updateSegmentColors() if (!l_segmentMapper) return; - // --- Diagnostics: run once, so we can see exactly what's wrong instead of silently doing nothing. + // --- Diagnostics: run once, so we can see exactly what's wrong instead + // of silently doing nothing. if (!m_loggedVisualModelLinkStatus) { m_loggedVisualModelLinkStatus = true; @@ -179,7 +184,12 @@ void SkeletonResectionSimulator::updateSegmentColors() if (!obj) continue; - // OglModel doesn't expose a plain "color" Data that is why this method was used + // OglModel doesn't expose a plain "color" Data - color lives inside + // its "material" Data (a Material struct: name + ambient/diffuse/ + // specular/emissive/shininess). Rather than guess that struct's + // exact serialization format, round-trip it: read the CURRENT valid + // string, patch only the "Diffuse r g b a" tokens, write it + // back - preserves everything else regardless of exact format. sofa::core::objectmodel::BaseData* materialData = obj->findData("material"); if (!materialData) { @@ -212,6 +222,20 @@ void SkeletonResectionSimulator::updateSegmentColors() } const auto& c = colors[i]; + + if (i < m_loggedMissingColorData.size() && !m_loggedMissingColorData[i]) + { + // One-time sanity check: print exactly what tokens we're about + // to overwrite, so the "Diffuse r g b a" assumption can + // be visually confirmed against this SOFA build's real format + // instead of trusted blindly. + m_loggedMissingColorData[i] = true; + std::ostringstream window; + for (auto it = diffuseIt; it != tokens.end() && it != diffuseIt + 6; ++it) + window << "'" << *it << "' "; + msg_info() << "'" << obj->getName() << "' Diffuse token window before patch: " << window.str(); + } + *(diffuseIt + 1) = "1"; // force useDiffuse on, so our color is actually applied std::ostringstream rs, gs, bs, as; rs << c[0]; gs << c[1]; bs << c[2]; as << c[3]; @@ -235,10 +259,9 @@ void SkeletonResectionSimulator::draw(const sofa::core::visual::Visua if (!vparams->displayFlags().getShowBehaviorModels()) return; - static const sofa::type::RGBAColor perfusedColor(0.20f, 0.80f, 0.20f, 1.0f); + static const sofa::type::RGBAColor perfusedColor(1.0f, 1.0f, 1.0f, 1.0f); static const sofa::type::RGBAColor affectedColor(0.0f, 0.0f, 0.0f, 1.0f); - static const sofa::type::RGBAColor cutColor(1.0f, 1.0f, 1.0f, 1.0f); - + static const sofa::type::RGBAColor cutColor(0.0f, 0.0f, 0.0f, 1.0f); const auto& affected = d_outAffectedNodeIds.getValue(); std::set affectedSet(affected.begin(), affected.end()); std::set cutSet(d_inCutNodeIds.getValue().begin(), d_inCutNodeIds.getValue().end()); diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp new file mode 100644 index 0000000..472643a --- /dev/null +++ b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp @@ -0,0 +1,22 @@ +#define TUMORCUTPOINTSELECTOR_CPP +#include + +#include +#include + +namespace meshskeletonizationplugin +{ +using namespace sofa::defaulttype; + +void registerTumorCutPointSelector(sofa::core::ObjectFactory* factory) +{ + factory->registerObjects(sofa::core::ObjectRegistrationData( + "Case 1 tumor-driven cut point selection: splits a (possibly multi-tumor) mesh " + "into its separate tumors and finds which skeleton node(s) each one directly " + "touches, via bounding-box pre-filtering plus a real point-in-mesh test") + .add< TumorCutPointSelector >()); +} + +template class SOFA_MESHSKELETONIZATIONPLUGIN_API TumorCutPointSelector; + +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h new file mode 100644 index 0000000..b58d56b --- /dev/null +++ b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h @@ -0,0 +1,113 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace sofa; +using namespace sofa::defaulttype; + +namespace meshskeletonizationplugin +{ + +/// Case 1 of tumor-driven cut point selection: for each tumor that directly +/// touches the vessel skeleton, find which skeleton node(s) it touches, so +/// those can be fed straight into SkeletonResectionSimulator.cutNodeIds. +/// +/// Tumors are provided as a list of already-separate mesh loaders (one per +/// tumor) - same MultiLink pattern SkeletonSegmentMapper uses for its 8 +/// segment meshes. If your tumors currently live merged in a single file, +/// split them into individual meshes upstream of this component (e.g. with +/// TumorSet::splitConnectedComponents(), kept available separately) before +/// loading each one with its own MeshOBJLoader. +/// +/// For each tumor / skeleton node pair: a cheap bounding-box check first +/// discards nodes nowhere near that tumor (broad phase), then a real +/// point-in-mesh test (CGAL::Side_of_triangle_mesh, same approach as +/// SkeletonSegmentMapper) decides whether the node is actually inside the +/// tumor volume (narrow phase). The bounding box alone is not used as the +/// decision - a non-convex or elongated tumor's box can contain a lot of +/// space the tumor doesn't actually occupy, which would false-positive. +/// +/// Tumors that touch no skeleton node at all are reported separately +/// (outUntouchedTumorIds) - those are candidates for Case 2 (nearest node +/// in the tumor's segment), not yet implemented here. +template +class TumorCutPointSelector : public sofa::core::DataEngine +{ +public: + SOFA_CLASS(SOFA_TEMPLATE(TumorCutPointSelector, DataTypes), sofa::core::DataEngine); + + typedef typename DataTypes::Coord Coord; + typedef typename DataTypes::VecCoord VecCoord; + typedef typename Coord::value_type Real; + typedef type::Vec<3, Real> Vec3; + + /// One mesh loader per tumor, already separate (no merged-file splitting + /// is done by this component). + sofa::core::objectmodel::MultiLink< + TumorCutPointSelector, + sofa::core::loader::MeshLoader, + sofa::core::objectmodel::BaseLink::FLAG_STOREPATH> + l_tumorMeshes; + + /// The segmented skeleton to test tumor(s) against. If left unset, the + /// first SkeletonSegmentMapper found in the context is used. + sofa::core::objectmodel::SingleLink< + TumorCutPointSelector, + SkeletonSegmentMapper, + sofa::core::objectmodel::BaseLink::FLAG_STOREPATH | sofa::core::objectmodel::BaseLink::FLAG_STRONGLINK> + l_segmentMapper; + + // Inputs + sofa::core::objectmodel::Data> d_inTumorNames; ///< Optional, same order as l_tumorMeshes, e.g. "tumor 1", "tumor 2" - purely for readable output/reports + + // Outputs + sofa::core::objectmodel::Data d_outTumorCount; ///< Number of linked tumors + sofa::core::objectmodel::Data> d_outCutNodeIds; ///< Union of every touching node across all tumors - link this straight into SkeletonResectionSimulator.cutNodeIds + sofa::core::objectmodel::Data> d_outTouchingTumorIndex; ///< Same length/order as outCutNodeIds: which tumor (0-based, into l_tumorMeshes) each entry belongs to + sofa::core::objectmodel::Data> d_outUntouchedTumorIds; ///< 0-based indices of tumors touching no skeleton node at all + + void init() override; + void doUpdate() override; + void draw(const sofa::core::visual::VisualParams* vparams) override; + +private: + TumorCutPointSelector(); + virtual ~TumorCutPointSelector() = default; + + /// One linked tumor's geometry (bbox + CGAL point-in-mesh query) plus + /// which skeleton nodes it was found to touch (filled by doUpdate(), + /// used by draw()). + struct TumorQuery + { + std::array bboxMin{}; + std::array bboxMax{}; + cgalutils::ClosedMeshQuery query; + std::vector touchingNodeIds; + }; + + /// Rebuilds bbox + ClosedMeshQuery for every linked tumor mesh. Pure + /// geometry prep, no skeleton involved yet. + void rebuildTumors(); + + std::vector m_tumors; + SkeletonGraph m_graph; ///< local copy of the linked mapper's graph, for node positions +}; + +#if !defined(TUMORCUTPOINTSELECTOR_CPP) +extern template class SOFA_MESHSKELETONIZATIONPLUGIN_API TumorCutPointSelector; +#endif + +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl new file mode 100644 index 0000000..1b320a5 --- /dev/null +++ b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl @@ -0,0 +1,205 @@ +#pragma once +#include + +#include +#include +#include + +#include +#include + +namespace meshskeletonizationplugin +{ + +template +TumorCutPointSelector::TumorCutPointSelector() + : l_tumorMeshes(initLink("tumorMeshes", + "One mesh loader per tumor, already separate")) + , l_segmentMapper(initLink("segmentMapper", + "Segmented skeleton to test the tumor(s) against; if empty, the first " + "SkeletonSegmentMapper found in the scene is used")) + , d_inTumorNames(initData(&d_inTumorNames, "tumorNames", + "Optional, same order as tumorMeshes, e.g. 'tumor 1', 'tumor 2' - for readable output/reports")) + , d_outTumorCount(initData(&d_outTumorCount, 0, "tumorCount", + "Number of linked tumors")) + , d_outCutNodeIds(initData(&d_outCutNodeIds, "cutNodeIds", + "Union of every touching node across all tumors - link this into SkeletonResectionSimulator.cutNodeIds")) + , d_outTouchingTumorIndex(initData(&d_outTouchingTumorIndex, "touchingTumorIndex", + "Same length/order as cutNodeIds: which tumor (0-based, into tumorMeshes) each entry belongs to")) + , d_outUntouchedTumorIds(initData(&d_outUntouchedTumorIds, "untouchedTumorIds", + "0-based indices of tumors touching no skeleton node at all")) +{ + addOutput(&d_outTumorCount); + addOutput(&d_outCutNodeIds); + addOutput(&d_outTouchingTumorIndex); + addOutput(&d_outUntouchedTumorIds); +} + +template +void TumorCutPointSelector::init() +{ + if (!l_segmentMapper) + l_segmentMapper.set(this->getContext()->template get>()); + + if (l_tumorMeshes.empty()) + msg_error() << "No tumor meshes linked. Set 'tumorMeshes' to a list of MeshLoader component paths."; + if (!l_segmentMapper) + msg_error() << "No SkeletonSegmentMapper found. Set 'segmentMapper' to a " + "valid component path, or add one earlier in the scene."; + else if (!l_tumorMeshes.empty() && d_inTumorNames.getValue().size() != l_tumorMeshes.size()) + msg_warning() << "tumorMeshes (" << l_tumorMeshes.size() << ") and tumorNames (" + << d_inTumorNames.getValue().size() << ") have different sizes; " + "unnamed tumors will be reported by index only."; + + setDirtyValue(); + update(); // compute eagerly, don't wait for something to read an output Data +} + +template +void TumorCutPointSelector::rebuildTumors() +{ + m_tumors.clear(); + m_tumors.resize(l_tumorMeshes.size()); + + for (std::size_t i = 0; i < l_tumorMeshes.size(); ++i) + { + sofa::core::loader::MeshLoader* loader = l_tumorMeshes.get(i); + if (!loader) + continue; + + const auto& positions = loader->d_positions.getValue(); + const auto& triangles = loader->d_triangles.getValue(); + + TumorQuery& tumor = m_tumors[i]; + tumor.bboxMin = { std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; + tumor.bboxMax = { -std::numeric_limits::max(), -std::numeric_limits::max(), -std::numeric_limits::max() }; + for (const auto& v : positions) + { + for (int d = 0; d < 3; ++d) + { + tumor.bboxMin[d] = std::min(tumor.bboxMin[d], static_cast(v[d])); + tumor.bboxMax[d] = std::max(tumor.bboxMax[d], static_cast(v[d])); + } + } + + tumor.query.buildFrom(positions, triangles); + } +} + +template +void TumorCutPointSelector::doUpdate() +{ + if (l_tumorMeshes.empty() || !l_segmentMapper) + return; + + rebuildTumors(); + m_graph = l_segmentMapper->graph(); + + std::vector cutNodeIds; + std::vector touchingTumorIndex; + std::vector tumorTouched(m_tumors.size(), false); + + for (const SkeletonNode& node : m_graph.nodes()) + { + const auto& p = node.position(); + + for (std::size_t t = 0; t < m_tumors.size(); ++t) + { + TumorQuery& tumor = m_tumors[t]; + + // Broad phase: cheap bounding-box rejection. + bool insideBBox = true; + for (int d = 0; d < 3; ++d) + { + if (p[d] < tumor.bboxMin[d] || p[d] > tumor.bboxMax[d]) + { + insideBBox = false; + break; + } + } + if (!insideBBox) + continue; + + // Narrow phase: real point-in-mesh test against the tumor surface. + if (!tumor.query.insideTest) + continue; + + Point query(p[0], p[1], p[2]); + if ((*tumor.query.insideTest)(query) == CGAL::ON_BOUNDED_SIDE) + { + cutNodeIds.push_back(node.id()); + touchingTumorIndex.push_back(static_cast(t)); + tumorTouched[t] = true; + tumor.touchingNodeIds.push_back(node.id()); + } + } + } + + std::vector untouchedTumorIds; + for (std::size_t t = 0; t < m_tumors.size(); ++t) + if (!tumorTouched[t]) + untouchedTumorIds.push_back(static_cast(t)); + + d_outTumorCount.setValue(static_cast(m_tumors.size())); + d_outCutNodeIds.setValue(cutNodeIds); + d_outTouchingTumorIndex.setValue(touchingTumorIndex); + d_outUntouchedTumorIds.setValue(untouchedTumorIds); + + if (!untouchedTumorIds.empty()) + { + msg_warning() << untouchedTumorIds.size() << " of " << m_tumors.size() + << " tumor(s) touch no skeleton node directly (Case 2 - nearest node " + "in the tumor's segment - is not yet implemented)."; + } +} + +template +void TumorCutPointSelector::draw(const sofa::core::visual::VisualParams* vparams) +{ + if (!vparams->displayFlags().getShowBehaviorModels()) + return; + + static const sofa::type::RGBAColor tumorBoxColor(1.0f, 1.0f, 1.0f, 1.0f); + static const sofa::type::RGBAColor touchingNodeColor(0.0f, 0.0f, 0.0f, 1.0f); + + // Tumor bounding boxes, wireframe - a visual sanity check that the + // bbox broad-phase looks right. + for (const TumorQuery& tumor : m_tumors) + { + const auto& lo = tumor.bboxMin; + const auto& hi = tumor.bboxMax; + std::vector corners = { + {lo[0], lo[1], lo[2]}, {hi[0], lo[1], lo[2]}, {hi[0], hi[1], lo[2]}, {lo[0], hi[1], lo[2]}, + {lo[0], lo[1], hi[2]}, {hi[0], lo[1], hi[2]}, {hi[0], hi[1], hi[2]}, {lo[0], hi[1], hi[2]}, + }; + static const int edges[12][2] = { + {0,1},{1,2},{2,3},{3,0}, {4,5},{5,6},{6,7},{7,4}, {0,4},{1,5},{2,6},{3,7} + }; + std::vector lines; + lines.reserve(24); + for (auto& e : edges) + { + lines.push_back(corners[e[0]]); + lines.push_back(corners[e[1]]); + } + vparams->drawTool()->drawLines(lines, 1.5f, tumorBoxColor); + } + + // Touching skeleton nodes, highlighted. + std::vector touchingPoints; + for (const TumorQuery& tumor : m_tumors) + { + for (int id : tumor.touchingNodeIds) + { + const SkeletonNode* n = m_graph.node(id); + if (!n) + continue; + const auto& p = n->position(); + touchingPoints.emplace_back(p[0], p[1], p[2]); + } + } + if (!touchingPoints.empty()) + vparams->drawTool()->drawPoints(touchingPoints, 9.0f, touchingNodeColor); +} + +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp new file mode 100644 index 0000000..6ab44a9 --- /dev/null +++ b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp @@ -0,0 +1,124 @@ +#include "TumorSet.h" + +#include +#include + +namespace meshskeletonizationplugin +{ + +int TumorSet::find(std::vector& parent, int x) +{ + while (parent[x] != x) + { + parent[x] = parent[parent[x]]; // path halving + x = parent[x]; + } + return x; +} + +void TumorSet::unite(std::vector& parent, int a, int b) +{ + int ra = find(parent, a); + int rb = find(parent, b); + if (ra != rb) + parent[ra] = rb; +} + +std::vector TumorSet::splitConnectedComponents( + const std::vector>& vertices, + const std::vector>& triangles) +{ + std::vector result; + if (vertices.empty()) + return result; + + // Union-find over vertices, connected by triangle edges. + std::vector parent(vertices.size()); + for (std::size_t i = 0; i < parent.size(); ++i) + parent[i] = static_cast(i); + + for (const auto& tri : triangles) + { + unite(parent, tri[0], tri[1]); + unite(parent, tri[1], tri[2]); + unite(parent, tri[2], tri[0]); + } + + // Group vertices by root, assigning each distinct root a stable, + // deterministic tumor id in first-seen order. + std::map rootToTumorId; // union-find root -> tumor index + std::vector> tumorVertexIds; // tumor index -> original vertex ids + + for (std::size_t i = 0; i < vertices.size(); ++i) + { + int root = find(parent, static_cast(i)); + auto it = rootToTumorId.find(root); + int tumorId; + if (it == rootToTumorId.end()) + { + tumorId = static_cast(tumorVertexIds.size()); + rootToTumorId[root] = tumorId; + tumorVertexIds.emplace_back(); + } + else + { + tumorId = it->second; + } + tumorVertexIds[tumorId].push_back(static_cast(i)); + } + + // Build each Tumor: remap global vertex ids to local (0..n-1) ids, + // carry over only the triangles fully inside this component, and + // compute bbox/centroid while we're at it. + result.resize(tumorVertexIds.size()); + std::vector globalToLocal(vertices.size(), -1); + + for (std::size_t t = 0; t < tumorVertexIds.size(); ++t) + { + Tumor& tumor = result[t]; + tumor.id = static_cast(t); + + const auto& ids = tumorVertexIds[t]; + tumor.vertices.reserve(ids.size()); + + std::array bmin{ std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; + std::array bmax{ std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest() }; + std::array sum{ 0.0, 0.0, 0.0 }; + + for (int localIdx = 0; localIdx < static_cast(ids.size()); ++localIdx) + { + int globalIdx = ids[localIdx]; + globalToLocal[globalIdx] = localIdx; + + const auto& p = vertices[globalIdx]; + tumor.vertices.push_back(p); + + for (int k = 0; k < 3; ++k) + { + bmin[k] = std::min(bmin[k], p[k]); + bmax[k] = std::max(bmax[k], p[k]); + sum[k] += p[k]; + } + } + + tumor.bboxMin = bmin; + tumor.bboxMax = bmax; + for (int k = 0; k < 3; ++k) + tumor.centroid[k] = sum[k] / static_cast(ids.size()); + } + + for (const auto& tri : triangles) + { + int root = find(parent, tri[0]); + int tumorId = rootToTumorId.at(root); + result[tumorId].triangles.push_back({ + globalToLocal[tri[0]], + globalToLocal[tri[1]], + globalToLocal[tri[2]] + }); + } + + return result; +} + +} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h new file mode 100644 index 0000000..6e1b7dd --- /dev/null +++ b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +namespace meshskeletonizationplugin +{ + +/// One connected tumor extracted from a (possibly merged) tumor mesh. +/// Vertex/triangle indices are LOCAL to this tumor (remapped from the +/// original merged mesh), so each Tumor is a fully self-contained mesh. +struct Tumor +{ + std::vector> vertices; + std::vector> triangles; + + std::array bboxMin{ 0.0, 0.0, 0.0 }; + std::array bboxMax{ 0.0, 0.0, 0.0 }; + std::array centroid{ 0.0, 0.0, 0.0 }; + + /// Index of this tumor's original connected component in the source + /// mesh (0, 1, 2, ...), stable/deterministic for a given input so it + /// can be used as a display label ("tumor 0", "tumor 1", ...). + int id{ -1 }; +}; + +/// Splits a single mesh that may contain several disjoint tumors merged +/// into one file (common when tumors are exported together from a +/// segmentation tool) into one Tumor per connected component, each with +/// its own bounding box and centroid precomputed. +/// +/// Two vertices are considered connected if some triangle has an edge +/// between them; a tumor is a maximal set of vertices connected this way. +/// No SOFA/CGAL dependency, so it's usable and testable independently of +/// the plugin's SOFA components. +class TumorSet +{ +public: + static std::vector splitConnectedComponents( + const std::vector>& vertices, + const std::vector>& triangles); + +private: + static int find(std::vector& parent, int x); + static void unite(std::vector& parent, int a, int b); +}; + +} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/init.cpp b/src/MeshSkeletonizationPlugin/init.cpp index 4c994ef..446b341 100644 --- a/src/MeshSkeletonizationPlugin/init.cpp +++ b/src/MeshSkeletonizationPlugin/init.cpp @@ -32,6 +32,7 @@ extern void registerMeshSkeletonization(sofa::core::ObjectFactory* factory); extern void registerSkeletonReader(sofa::core::ObjectFactory* factory); extern void registerSkeletonSegmentMapper(sofa::core::ObjectFactory* factory); extern void registerSkeletonResectionSimulator(sofa::core::ObjectFactory* factory); +extern void registerTumorCutPointSelector(sofa::core::ObjectFactory* factory); //Here are just several convenient functions to help users know what the plugin contains extern "C" { @@ -87,6 +88,7 @@ void registerObjects(sofa::core::ObjectFactory* factory) registerSkeletonReader(factory); registerSkeletonSegmentMapper(factory); registerSkeletonResectionSimulator(factory); + registerTumorCutPointSelector(factory); } } From fc9aeca8113cf1b8d8255a9f4e6531683146a0c9 Mon Sep 17 00:00:00 2001 From: epernod Date: Tue, 15 Sep 2026 16:34:26 +0200 Subject: [PATCH 2/3] [src] Remove skeleton component related to liver to keep this plugin generic --- CMakeLists.txt | 11 - TestScene.scn | 77 - TestScene_p_1.scn | 99 -- TestScene_p_8.scn | 92 - ...m_skeleton_at_comp_meshSkeletonization.txt | 1569 ----------------- .../Patient_08_venoussystem_skeleton.txt | 1330 -------------- .../SegmentMapping/SkeletonSegmentMapper.cpp | 22 - .../SegmentMapping/SkeletonSegmentMapper.h | 76 - .../SegmentMapping/SkeletonSegmentMapper.inl | 200 --- .../SkeletonResectionSimulator.cpp | 22 - .../SkeletonResectionSimulator.h | 112 -- .../SkeletonResectionSimulator.inl | 292 --- .../TumorMapping/TumorCutPointSelector.cpp | 22 - .../TumorMapping/TumorCutPointSelector.h | 113 -- .../TumorMapping/TumorCutPointSelector.inl | 205 --- .../TumorMapping/TumorSet.cpp | 124 -- .../TumorMapping/TumorSet.h | 49 - src/MeshSkeletonizationPlugin/init.cpp | 6 - 18 files changed, 4421 deletions(-) delete mode 100644 TestScene.scn delete mode 100644 TestScene_p_1.scn delete mode 100644 TestScene_p_8.scn delete mode 100644 data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt delete mode 100644 data/patient_08/Patient_08_venoussystem_skeleton.txt delete mode 100644 src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.cpp delete mode 100644 src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h delete mode 100644 src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl delete mode 100644 src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.cpp delete mode 100644 src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h delete mode 100644 src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl delete mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp delete mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h delete mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl delete mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp delete mode 100644 src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 59c9217..e07e1a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,13 +18,6 @@ set(HEADER_FILES ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonGraph.h ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonReader.h ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonReader.inl - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SegmentMapping/SkeletonSegmentMapper.inl - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SegmentMapping/SkeletonSegmentMapper.h - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.h - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.inl - ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorSet.h - ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.h - ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.inl ${PLUGIN_SKELETONIZATION_SRC_DIR}/CGALMeshUtils.h ) set(SOURCE_FILES @@ -32,10 +25,6 @@ set(SOURCE_FILES ${PLUGIN_SKELETONIZATION_SRC_DIR}/MeshSkeletonization.cpp ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonGraph.cpp ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonGraph/SkeletonReader.cpp - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SegmentMapping/SkeletonSegmentMapper.cpp - ${PLUGIN_SKELETONIZATION_SRC_DIR}/SkeletonResection/SkeletonResectionSimulator.cpp - ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorSet.cpp - ${PLUGIN_SKELETONIZATION_SRC_DIR}/TumorMapping/TumorCutPointSelector.cpp ) set(README_FILES README.md) diff --git a/TestScene.scn b/TestScene.scn deleted file mode 100644 index d8507a8..0000000 --- a/TestScene.scn +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/TestScene_p_1.scn b/TestScene_p_1.scn deleted file mode 100644 index ca9621a..0000000 --- a/TestScene_p_1.scn +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestScene_p_8.scn b/TestScene_p_8.scn deleted file mode 100644 index f11f663..0000000 --- a/TestScene_p_8.scn +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt b/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt deleted file mode 100644 index c252711..0000000 --- a/data/patient_01/reports/Patient_01_venoussystem_skeleton_at_comp_meshSkeletonization.txt +++ /dev/null @@ -1,1569 +0,0 @@ -128.653 146.214 3.89446 -130.123 145.243 4.89655 -131.369 144.325 5.93882 -131.935 143.885 6.4967 -133.158 143.288 7.42637 -133.975 142.903 8.01925 -134.644 142.582 8.53416 -135.734 142.107 9.24291 - -100.966 141.188 43.9713 -101.453 141.253 45.0956 -102.487 141.635 46.9503 -103.358 141.99 48.5195 -103.789 142.147 49.3191 -103.93 142.929 50.7286 - -103.93 142.929 50.7286 -105.282 142.377 52.1685 -105.945 142.11 53.1628 -106.294 141.992 53.7934 -107.468 141.619 56.0637 -108.078 141.407 57.4263 -108.304 141.315 57.9656 -108.839 141.088 59.4213 -109.462 140.781 60.8066 -109.971 140.485 61.7521 -110.726 139.935 62.835 -111.107 139.663 63.398 -111.643 139.279 64.1883 -112.672 138.584 65.7132 -113.333 138.163 66.7143 -114.164 137.681 68.0228 -115.068 137.284 69.5878 -115.707 137.099 70.8099 -116.38 136.936 72.1354 -116.784 136.844 72.9403 -117.698 136.639 74.7577 -118.739 136.321 76.6949 -119.59 136.296 78.2873 -120.933 136.166 79.422 -122.518 136.178 80.699 -123.385 136.184 81.3472 -124.251 136.204 81.8466 -125.244 136.213 82.4264 -126.338 136.248 82.9469 -127.087 136.257 83.3583 -128.395 136.255 84.1024 -130.405 136.23 85.3274 - -103.93 142.929 50.7286 -103.156 144.165 51.5221 -101.848 145.427 51.7407 -100.486 146.555 51.1776 -99.8611 147.043 50.8641 -98.8436 147.808 50.6965 -97.7802 148.753 50.3181 -97.1885 149.231 50.3929 -96.9984 149.404 50.382 -96.5906 149.842 50.3492 -96.0357 150.374 50.2907 -95.0542 151.436 50.1634 -94.4162 151.894 49.9048 -93.426 152.159 49.3773 -92.3763 152.5 48.7854 - -69.9695 138.333 67.9241 -69.9364 138.214 67.9146 - -66.023 150.541 73.1918 -66.2509 149.911 74.1547 -66.5492 149.422 74.8443 -66.9327 148.841 75.7225 -67.4382 148.103 76.7591 -68.2134 147.152 78.0239 -68.9174 146.331 79.0113 -69.2681 146.022 79.3979 -69.9561 144.896 80.0133 -70.6874 143.67 80.3656 - -65.2652 123.69 75.2001 -65.2652 123.69 75.2001 - -85.4913 132.498 79.9998 -84.7371 132.75 80.0704 -84.5065 132.828 80.1006 -83.9893 133.006 80.1766 -83.4319 133.207 80.2727 -82.0487 133.736 80.5432 -80.8669 134.287 80.6128 -80.3884 134.526 80.6313 -79.658 134.934 80.6577 -78.638 135.573 80.6957 -77.7083 136.247 80.8318 -77.1651 136.676 80.9704 -76.8841 136.902 81.0408 -76.3475 137.389 81.2361 -75.718 137.97 81.5143 -75.2253 138.489 81.7932 -73.6567 139.601 82.0371 -72.709 140.299 82.2588 - -70.6874 143.67 80.3656 -70.7991 142.988 79.0742 -70.7767 142.455 77.7925 -70.6715 142.162 76.8256 -70.3835 141.803 75.6543 -70.3508 141.482 74.9494 -70.1957 140.74 73.161 -70.0033 139.416 70.3849 -70.0653 138.814 69.3142 -69.9364 138.214 67.9146 - -70.6874 143.67 80.3656 -71.12 143.325 81.5849 -71.3822 143.12 82.4407 -71.8553 141.902 83.0875 - -72.709 140.299 82.2588 -71.8553 141.902 83.0875 - -72.709 140.299 82.2588 -72.4955 139.391 81.7616 -72.3973 139.083 81.5862 -71.9956 138.211 81.0537 -70.8611 136.531 79.9978 -67.3174 130.972 76.5092 - -59.9087 136.467 85.6705 -62.2661 137.925 85.8238 -64.1926 139.13 85.9173 -65.1336 139.635 86.0307 -65.7755 139.909 86.1746 -66.2029 140.121 86.2482 -66.7526 140.393 86.3458 -68.3603 141.197 86.5677 -70.2812 142.143 85.9285 -71.8635 142.969 86.2029 - -56.2284 132.442 88.0001 -56.2284 132.442 88.0001 - -73.843 170.216 91.7748 -73.2268 171.121 92.1674 -72.736 171.754 92.3573 -72.4079 172.209 92.4449 -72.1288 172.567 92.5363 -71.8445 172.921 92.628 -71.5287 173.309 92.7197 -71.1971 173.701 92.8108 -70.8624 174.092 92.8906 -70.5193 174.482 92.9759 -70.1065 174.931 93.0785 -69.1951 175.829 93.3652 -68.8601 176.138 93.4802 - -73.843 170.216 91.7748 -74.0967 167.968 93.1549 -74.0658 167.394 93.53 -74.23 165.686 94.4827 - -73.843 170.216 91.7748 -74.3628 170.594 90.4206 -74.7586 170.651 89.6066 -74.826 170.661 89.4479 - -79.634 151.555 105.559 -79.3834 150.561 104.277 -79.0581 149.917 103.131 -78.4722 149.106 101.313 -77.765 148.129 99.1256 -77.2504 147.351 97.3685 -76.6524 146.91 95.8767 -76.3706 146.75 95.2022 -75.8898 146.435 93.8955 -75.2525 145.82 92.3793 -74.4944 145.115 90.6509 -73.6045 144.319 88.7936 -73.2227 143.987 88.054 -71.8635 142.969 86.2029 - -79.634 151.555 105.559 -79.108 153.065 105.3 -78.803 153.84 104.97 -78.5739 154.301 104.358 -78.0646 155.38 103.236 -77.59 156.701 101.729 -77.4345 157.237 101.155 -77.183 157.977 100.387 -76.9746 158.755 99.5975 -76.6567 159.703 98.75 -76.4687 160.308 98.2136 -76.2587 160.927 97.6817 -76.0272 161.505 97.219 -75.4437 162.499 96.6452 -75.2727 163.176 96.0891 -74.93 164.035 95.5382 -74.23 165.686 94.4827 - -79.634 151.555 105.559 -80.4853 151.101 107.377 -80.6525 150.976 107.71 -80.9383 150.815 108.315 -81.2201 150.63 108.887 -81.6235 150.458 109.843 -81.9488 150.331 110.647 -82.3274 150.214 111.644 -82.7142 150.121 112.73 -83.0655 150.078 113.869 -83.5427 150.055 115.601 -83.877 150.07 116.976 -84.2581 150.107 118.634 -84.512 150.176 120.04 -84.677 150.275 121.37 -84.6109 150.528 122.744 -84.6887 150.713 123.5 -84.6982 150.796 123.872 -84.7851 150.991 124.527 - -178.504 148.681 105.668 -178.572 146.977 106.454 -178.45 146.094 107.205 -178.175 144.632 108.634 -177.148 142.855 111.843 -176.552 141.961 113.434 -176.176 141.442 114.581 -175.814 141.245 115.92 - -178.504 148.681 105.668 -178.814 149.015 104.356 -179.172 148.953 102.981 -179.406 149.308 101.493 -179.652 149.742 99.7551 -179.69 149.831 99.3892 -179.884 150.329 97.5736 -180.03 150.387 95.8776 -180.005 150.581 95.096 -179.941 150.708 93.7296 -179.814 150.862 92.5014 -179.584 150.977 90.7851 -179.371 151.092 89.0339 -179.298 151.153 88.2271 - -178.504 148.681 105.668 -177.96 150.193 106.44 -177.373 151.492 107.582 -176.967 152.43 108.44 -176.448 153.593 109.706 -175.914 154.743 111.406 -175.501 155.646 113.613 -175.229 156.245 115.146 -175.208 156.294 115.277 -175.124 156.493 116.03 -175.036 156.699 116.789 -174.991 156.805 117.339 -174.931 156.949 118.222 -174.847 157.148 119.483 -174.679 157.52 121.906 -174.594 157.625 122.898 -174.456 157.767 124.301 -174.335 157.862 125.246 -174.157 157.98 126.407 -173.991 158.068 127.209 -173.771 158.172 128.063 -173.344 158.372 129.545 -172.746 158.677 131.266 -172.478 158.824 132.014 -171.937 159.147 133.465 -171.242 159.576 135.318 -170.971 159.745 136.032 -170.469 160.101 137.392 -170.247 160.375 138.184 -169.816 160.903 139.716 -169.545 162.033 142.324 -169.365 162.754 143.998 -169.336 163.37 145.765 - -175.814 141.245 115.92 -176.692 141.906 117.72 -177.555 142.572 118.617 -179.925 144.449 120.89 -181.325 145.665 121.443 -182.401 146.656 121.839 -183.565 147.751 122.132 -184.993 149.109 122.449 -186.18 150.265 122.627 -186.799 150.871 122.709 -187.576 151.658 122.744 -188.297 152.408 122.736 -189.183 153.395 122.612 -190.118 154.463 122.443 -190.872 155.36 122.263 -191.542 156.186 122.069 -192.2 157.025 121.877 -193.141 158.347 121.523 -193.696 159.204 121.276 -194.553 160.638 120.521 - -175.814 141.245 115.92 -173.986 140.008 115.648 -172.141 138.824 115.368 -171.215 138.238 115.201 -170.141 137.565 114.981 -168.953 136.824 114.724 -168.162 136.337 114.552 -166.313 135.216 114.167 -164.967 134.536 113.811 -164.236 134.178 113.568 -163.61 133.89 113.366 -162.253 133.32 113.17 -161.091 132.896 113.091 -160.21 132.6 113.067 -158.873 132.21 113.064 -157.988 132 113.074 -156.915 131.788 113.086 -155.751 131.614 113.091 -155.079 131.537 113.093 -154.149 131.441 113.093 -152.744 131.37 113.073 -150.776 131.344 113.088 -149.181 131.438 113.043 -147.093 131.753 113.018 -145.717 131.979 113.024 -143.785 132.338 113.228 -142.87 132.504 113.172 -141.896 132.692 113.19 -140.108 133.07 113.388 -139.165 133.311 113.537 -137.566 133.633 113.294 - -70.6836 179.738 116.922 -70.9508 179.529 116.982 -72.2121 178.546 117.329 -72.9833 177.987 117.459 -74.4971 176.882 117.669 -75.2913 176.305 117.72 -75.7535 175.982 117.722 -76.63 175.359 117.685 -77.1315 175.016 117.602 -77.4705 174.811 117.51 -78.4235 174.252 117.215 -78.8016 174.006 117.121 -79.2323 173.705 117.007 -80.1626 173.008 116.741 -81.1121 172.199 116.417 -82.0488 171.26 116.186 -82.6161 170.982 115.688 - -195.917 172.038 121.843 -195.471 170.238 120.816 -195.55 168.63 120.673 -195.675 167.462 120.683 -195.854 165.956 120.717 -196.469 164.885 121.021 - -195.917 172.038 121.843 -197.571 172.354 122.903 -198.381 172.183 123.282 -199.286 171.783 123.613 -200.298 171.274 123.909 -200.777 170.365 123.832 -200.856 168.92 123.519 - -195.917 172.038 121.843 -195.119 173.401 122.153 -194.522 174.423 122.527 - -111.939 96.2717 125.007 -110.839 96.4467 126.385 -109.992 96.6537 127.627 -109.291 96.936 129.002 -108.593 97.3038 130.523 -108.025 97.911 131.943 -107.531 98.8524 133.051 -107.317 99.3945 133.698 -107.037 100.186 134.578 -105.842 102.004 135.047 - -57.6081 165.844 123.725 -58.425 165.325 124.207 -59.1528 164.969 124.722 -60.4597 164.342 125.786 -60.8922 164.107 126.16 -61.5408 163.75 126.574 -62.9595 162.979 127.15 -63.8113 162.501 127.402 -64.5285 162.108 127.457 -65.6048 161.561 127.482 -66.8151 160.965 127.502 -67.4436 160.668 127.523 -68.0801 160.337 127.576 -68.7708 159.992 127.629 -69.1543 159.759 127.698 -69.7075 159.44 127.803 -70.8212 158.77 128.096 -72.0704 158.019 128.505 -73.1279 157.378 128.793 -73.5353 157.165 128.84 -74.1072 156.883 128.88 -74.792 156.512 128.936 -75.5798 156.092 128.989 -76.3104 155.683 129.062 -76.6951 155.465 129.119 -77.1289 155.21 129.207 -77.4824 155.005 129.288 -78.1009 154.628 129.48 -79.0888 153.972 129.823 -79.5687 153.625 130.142 -79.6834 153.528 130.159 -80.3094 153.082 130.272 -80.8322 152.723 130.36 -81.2248 152.232 129.689 -82.7413 151.327 128.49 - -60.1843 119.538 130.418 -62.321 121.2 131.328 - -62.321 121.2 131.328 -62.558 123.445 131.832 -62.668 126.554 132.039 - -62.321 121.2 131.328 -63.2646 120.176 131.268 -63.4944 119.983 131.263 - -52.8487 135.85 137.606 -53.5688 135.948 137.603 -54.0893 136.031 137.601 -55.3648 136.282 137.598 -56.2534 136.476 137.6 -57.1867 136.668 137.609 -57.8513 136.758 137.622 -58.39 136.822 137.633 -58.8768 136.853 137.646 -59.5067 136.893 137.662 -60.172 136.905 137.674 -61.1372 136.916 137.678 -61.8299 136.884 137.658 -62.1555 136.87 137.642 -62.8073 136.83 137.6 -63.4473 136.76 137.54 -64.248 136.681 137.48 -66.6129 133.884 136.805 - -66.6129 133.884 136.805 -69.5025 136.348 138.724 -71.2089 137.292 139.585 -72.4775 137.614 140.258 -74.2717 137.917 141.426 -76.5385 138.276 142.94 -77.7112 138.451 143.674 -79.2137 138.767 144.461 -81.2 139.192 145.423 -83.1155 139.596 146.463 -84.0471 139.674 147.154 -85.1481 139.88 147.837 -86.1543 140.012 148.403 -86.725 138.58 150.168 -87.3641 136.629 152.293 - -66.6129 133.884 136.805 -64.8292 129.865 134.503 -63.9207 127.941 133.422 -62.668 126.554 132.039 - -178.117 144.98 136.768 -178.121 144.982 136.774 -178.125 144.983 136.778 - -75.5278 92.2165 141.032 -76.3128 92.362 141.331 -77.2795 92.5782 141.694 -78.5001 92.9404 142.125 -79.5376 93.2644 142.464 -80.5892 93.5739 142.805 -82.0155 93.9047 143.301 -82.6997 94.0306 143.526 -83.3112 94.1512 143.686 -83.925 94.2881 143.825 -84.692 94.4755 143.995 -85.5238 94.7586 144.176 -86.3511 95.086 144.382 -87.4636 95.6182 144.687 -90.4503 97.0554 145.624 -92.589 97.9937 146.466 -94.0638 98.6371 147.288 -94.5913 98.903 147.717 -95.0225 99.1636 148.239 -95.3683 99.4522 148.665 -95.8675 99.6695 149.375 -96.334 99.8449 150.079 -97.0981 100.351 151.4 - -169.115 162.169 142.322 -169.123 162.457 143.044 -169.336 163.37 145.765 - -81.6272 190.511 143.274 -81.8388 190.221 143.596 -82.5262 189.384 144.575 -82.9483 188.926 145.224 -83.82 188.07 146.47 -84.2492 187.666 147.06 -84.6476 187.035 147.945 -84.8341 186.545 148.643 -84.6263 185.84 149.629 -84.3089 185.206 150.542 -83.7096 184.419 151.811 -83.3808 183.277 153.346 - -169.336 163.37 145.765 -169.961 165.623 153.239 - -169.961 165.623 153.239 -170.052 165.889 154.667 - -169.961 165.623 153.239 -169.654 165.185 151.191 -169.265 164.452 148.371 -169.216 164.297 147.866 - -91.8089 90.7389 153.445 -93.2221 91.4541 153.239 -94.4216 92.1965 153.001 -95.2984 92.4769 152.835 -96.8278 92.913 152.546 - -112.281 105.816 151.523 -111.805 105.259 148.751 -111.423 104.895 146.929 -110.976 104.557 145.35 -110.636 104.311 144.196 -110.194 103.935 142.837 -109.5 103.542 141.667 -108.861 103.266 140.461 -108.326 103.036 139.495 -107.68 102.726 138.298 -106.751 102.504 137.205 -105.842 102.004 135.047 - -112.281 105.816 151.523 -114.163 106.773 153.02 -115.315 107.407 154.313 -116.36 108 155.625 -117.93 108.916 157.737 -119.163 109.671 159.517 -119.589 109.952 160.2 -120.338 110.486 161.45 -120.816 110.847 162.298 -121.336 111.327 163.195 -122.075 112.056 164.466 -122.745 112.706 165.673 -123.66 113.612 167.39 -124.221 114.171 168.496 -124.834 114.772 169.833 -125.12 115.067 170.494 -125.686 115.693 171.625 -126.111 116.212 173.409 - -112.281 105.816 151.523 -110.977 105.235 151.12 -110.357 104.982 151.124 -109.025 104.417 151.108 -107.172 103.603 151.132 -105.748 102.974 151.151 -104.065 102.229 151.173 -103.546 101.995 151.178 -102.215 101.368 151.188 -101.065 100.82 151.197 -99.4337 99.8942 151.25 - -82.4759 130.952 153.64 -83.1138 131.549 153.537 -84.8572 133.537 153.112 -86.6279 135.431 152.78 -87.3641 136.629 152.293 - -95.1726 141.887 154.426 -95.0954 141.88 156.052 - -95.1726 141.887 154.426 -96.3974 142.268 155.181 -97.8977 142.548 156.139 -99.0365 142.743 156.983 -99.9552 142.825 158.135 -100.762 142.87 159.333 -101.449 142.89 160.33 -102.337 142.947 162.933 - -95.1726 141.887 154.426 -94.974 142.476 152.399 -95.073 142.874 151.544 -95.2274 143.619 149.925 -94.947 143.948 149.008 -94.8729 144.508 147.917 -94.5622 145.139 146.498 -94.0899 145.477 145.444 -93.7075 145.801 144.416 -93.0665 146.127 143.231 -92.4071 146.4 142.24 -91.974 146.597 141.485 -91.7582 146.702 141.053 -91.0257 147.016 139.859 -90.1539 147.409 138.322 -89.3191 147.791 136.864 -88.9903 147.958 136.24 -88.3107 148.369 134.75 -87.8238 148.68 133.676 -87.452 148.925 132.861 -87.1502 149.21 131.925 -86.412 149.595 131.048 -86.3234 149.65 130.916 -85.5105 150.094 129.921 -82.7413 151.327 128.49 - -95.1726 141.887 154.426 -93.3219 140.684 153.572 -91.6468 139.439 152.977 -90.6485 138.637 152.968 -89.7363 137.918 152.924 -89.1779 137.482 152.883 -87.3641 136.629 152.293 - -79.9183 185.198 159.485 -79.9372 185.181 159.472 -80.6966 184.279 159.019 -80.9902 183.941 158.845 -81.4217 183.455 158.6 -81.7945 183.043 158.398 -82.3736 182.425 158.093 -83.0243 181.566 157.363 - -77.6271 188.777 161.6 -77.6271 188.777 161.6 -77.6271 188.777 161.6 - -84.8477 172.472 161.225 -84.9281 173.377 160.463 -85.0975 174.185 159.718 -85.0127 174.987 159.184 -84.8452 176.04 158.562 -84.6627 177.119 157.946 -84.3913 178.438 157.276 -84.0422 179.714 156.794 -83.0243 181.566 157.363 - -84.8477 172.472 161.225 -83.3179 172.69 162.217 -82.073 173.007 162.815 -81.5838 173.163 163.023 -81.1044 173.381 163.202 -80.4891 173.698 163.434 -80.2634 173.839 163.524 -79.7472 174.172 163.738 -79.004 174.743 164.083 -77.8545 175.758 164.606 -77.1431 176.433 164.906 -76.639 176.903 165.121 -76.0458 177.414 165.399 -75.4984 177.828 165.679 -74.811 178.33 166.065 -74.1982 178.796 166.421 -73.6373 179.215 166.758 -73.0603 179.653 167.086 -72.3006 180.208 167.442 -71.4377 180.844 167.87 -70.9157 181.217 168.122 -70.1162 181.761 168.484 -69.3266 182.271 168.787 -68.8096 182.646 168.885 -68.1256 183.114 169.014 -67.688 183.416 169.077 -67.3154 183.657 169.145 -66.41 184.23 169.314 -65.8882 184.51 169.405 -65.5257 184.688 169.464 -64.9453 184.937 169.538 -64.1814 185.201 169.607 -63.5813 185.371 169.63 -63.0571 185.505 169.64 -62.3638 185.678 169.639 -61.7702 185.831 169.631 -61.35 185.942 169.623 - -84.8477 172.472 161.225 -85.4766 171.757 161.321 -85.8185 171.181 161.526 -86.2383 170.44 161.819 -86.9123 169.025 162.491 -87.1322 168.545 162.729 -87.4481 167.776 163.154 -87.8212 166.774 163.758 -88.2113 165.667 164.485 -88.3696 164.902 165.057 -88.5843 163.755 166.281 - -59.7207 119.951 166.744 -60.7063 120.928 167.241 -62.5908 125.852 167.324 -64.1072 129.695 167.343 -66.8879 136.301 167.235 - -57.5513 133.84 166.4 -57.5685 133.841 166.4 -57.577 133.842 166.401 - -72.341 142.616 165.337 -73.9312 142.856 165.618 -74.8865 143.124 165.661 -75.899 143.361 165.664 -77.7619 143.64 165.642 -79.4049 143.776 165.607 -80.1266 143.786 165.584 -80.9375 143.784 165.558 -82.1831 143.729 165.509 -83.4322 143.651 165.453 -84.6068 143.587 165.414 -85.6687 143.552 165.418 -86.7176 143.499 165.42 -88.0512 143.332 165.653 -88.961 143.201 165.844 -89.4015 143.179 165.88 -90.2904 143.217 165.837 -92.048 143.102 165.941 -92.6474 143.066 165.961 -93.4134 143.023 165.955 -94.1623 142.984 165.92 -95.2459 142.933 165.85 -96.1706 142.905 165.756 -97.0835 142.889 165.546 -99.2584 142.888 164.036 -100.573 142.897 163.206 -102.337 142.947 162.933 - -72.341 142.616 165.337 -71.5039 144.08 164.153 -70.3964 144.878 163.247 -69.7697 145.113 162.86 -68.7833 145.293 162.607 -68.0212 145.471 162.351 -67.2671 145.615 162.142 -65.9934 145.882 161.824 -65.2736 146.073 161.676 -64.4162 146.32 161.524 -63.7159 146.5 161.413 -62.9814 146.701 161.285 -61.7516 146.396 160.697 -60.7946 146.101 160.195 -59.9925 145.894 159.808 -59.0276 145.682 159.369 -57.3895 145.427 158.723 -56.5521 145.345 158.434 -55.5433 145.233 158.092 -53.6523 144.933 157.394 -52.5549 144.785 157.046 -51.2356 144.644 156.84 -50.7996 144.607 156.803 -50.2871 144.576 156.791 -49.6646 144.541 156.786 -48.9364 144.501 156.77 -48.0077 144.428 156.704 -47.2006 144.315 156.565 -46.2592 144.161 156.368 -45.5419 144.01 156.161 - -72.341 142.616 165.337 -71.512 141.09 165.901 -70.3089 139.589 166.23 -68.4469 137.406 166.672 -68.0203 136.884 166.782 -66.8879 136.301 167.235 - -88.5843 163.755 166.281 -87.8239 162.905 166.824 -86.9083 162.537 166.925 -85.3756 162.393 167.059 -83.6542 162.273 167.242 -82.1972 162.523 167.149 -81.418 162.64 167.119 -80.3236 162.82 167.079 -78.9247 163.059 167.095 -78.3246 163.159 167.152 -77.3323 163.26 167.505 - -88.5843 163.755 166.281 -90.089 162.984 168.836 - -60.7052 144.78 169.6 -60.7052 144.78 169.6 - -167.109 99.8344 171.491 -169.047 100.115 170.584 -170.352 99.0507 169.748 -171.268 98.3428 169.072 -171.976 97.6583 168.511 -172.686 96.9865 167.713 -173.456 96.158 166.778 -173.893 95.6829 166.206 -174.23 95.2955 165.796 -174.641 94.8263 165.307 -175.134 94.3097 164.705 -175.758 93.7084 163.986 -176.435 93.0604 163.292 -177.236 92.4017 162.397 -178.089 91.5913 161.45 -179.294 90.4434 160.201 -179.64 90.1296 159.831 -180.098 89.6753 159.367 -180.231 89.5659 159.225 -180.694 89.1337 158.667 -181.234 88.6294 157.976 -181.681 88.2595 157.456 -182.313 87.7136 156.886 -183.152 86.9999 155.907 -185.134 85.9225 156.129 -185.767 85.575 156.117 -186.068 85.4261 156.09 -187.044 84.9338 155.981 -187.932 84.5305 155.808 -188.671 84.1817 155.623 -189.374 83.8716 155.46 -189.982 83.5945 155.352 -190.384 83.4081 155.297 -190.714 83.263 155.26 -191.122 83.085 155.224 -191.513 82.9124 155.199 - -167.109 99.8344 171.491 -166.855 98.7311 171.103 -166.762 97.382 170.46 -166.696 95.566 169.697 -166.784 95.0435 169.312 -167.027 94.6057 168.628 -167.383 93.5726 167.682 -167.669 92.9789 166.964 -168.097 92.038 166.005 -169.202 89.6428 163.547 - -167.109 99.8344 171.491 -166.352 100.514 172.201 -165.863 101.072 172.697 -165.368 101.645 173.197 -164.95 102.166 173.63 -164.352 102.932 174.253 -163.802 103.708 174.845 -163.022 104.922 175.711 -161.737 106.982 177.173 -161.483 107.587 177.504 -161.234 108.381 178.05 -161.014 108.96 178.489 -160.859 110.46 179.689 -161.346 111.947 180.867 - -107.994 144.094 171.668 -107.224 145.053 172.255 -106.72 145.772 172.828 -105.807 146.787 172.796 -105.331 147.393 172.853 -104.228 148.667 172.809 -103.704 149.263 172.779 -102.744 150.3 172.668 -102.08 150.976 172.561 -101.308 151.704 172.39 -100.532 152.387 172.188 -99.4036 153.318 171.819 -98.5635 153.991 171.515 -97.4215 154.905 170.944 -96.1131 155.974 170.313 -95.7761 156.254 170.153 -95.1723 156.768 169.845 -94.7853 157.107 169.647 -94.0702 157.754 169.319 -93.1554 158.641 168.859 -92.5214 159.301 168.587 -91.6018 160.296 168.224 -90.089 162.984 168.836 - -107.994 144.094 171.668 -107.515 143.868 170.59 -107.146 143.726 169.85 -106.64 143.494 168.772 -106.519 143.458 168.553 -105.947 143.33 167.608 -105.189 143.234 166.501 -104.689 143.16 165.728 -103.685 143.028 164.338 -102.337 142.947 162.933 - -107.994 144.094 171.668 -108.664 143.903 172.282 -109.371 143.703 172.935 -110.122 143.548 173.737 -110.975 143.386 174.748 -111.714 143.255 175.678 -112.727 143.081 177.03 -112.925 143.047 177.303 -113.641 142.922 178.34 -114.731 142.712 180.02 -115.23 142.626 180.741 -115.2 141.737 183.381 - -60.4872 166.349 174.407 -60.7654 166.306 174.375 -61.1149 166.252 174.321 -61.9757 166.114 174.152 -62.1204 166.09 174.115 -62.8022 165.974 173.913 -63.8219 165.801 173.577 -65.2007 165.553 173.094 -65.6659 165.465 172.931 -66.1795 165.364 172.748 -66.8545 165.231 172.476 -67.9943 165.009 171.961 -69.3103 164.765 171.363 -69.5752 164.704 171.267 -70.3813 164.532 170.977 -71.2974 164.322 170.705 -72.3554 164.063 170.467 -73.1278 163.881 170.271 -74.1599 163.648 169.916 -75.2534 163.39 169.531 -76.5296 163.073 169.104 -77.3103 162.959 168.625 -77.3323 163.26 167.505 - -84.1561 171.789 174.448 -84.7189 171.209 174.313 -85.0759 170.879 174.206 -85.5794 170.463 174.018 -86.5124 170.077 173.53 -87.7213 171.351 172.953 - -179.143 92.0806 175.998 -178.881 92.8673 176 - -126.111 116.212 173.409 -127.047 117.563 174.981 -127.621 118.532 176.285 -128.397 119.947 178.198 -129.233 122.256 181.094 -130.424 125.849 185.635 -130.967 127.117 187.107 -131.387 128.44 188.814 -131.828 129.635 190.411 -132.225 130.944 192.049 -132.798 133.197 194.441 -132.669 135.255 195.831 - -126.111 116.212 173.409 -124.909 114.674 174.724 -123.958 113.548 176.41 -123.043 112.765 176.804 -119.612 109.582 176.42 -117.338 107.47 176.138 -111.518 102.048 175.403 - -89.4072 157.154 175.268 -88.3863 157.446 175.877 -87.8846 157.595 176.163 -87.3317 157.773 176.448 -86.7141 157.913 176.745 -85.5413 158.131 177.261 -84.8802 158.237 177.526 -84.634 158.278 177.63 -83.835 158.378 177.96 -82.9667 158.468 178.323 -82.0866 158.543 178.708 -81.6035 158.574 178.918 -81.1517 158.626 179.109 -80.9124 158.644 179.218 -79.8326 158.713 179.78 -79.1383 158.762 180.173 -78.1705 158.881 180.722 -77.2303 159.096 181.286 -76.676 159.217 181.612 -75.6392 159.437 182.172 -74.6995 159.603 182.657 -73.4684 159.675 183.27 -72.7538 159.685 183.607 -72.2055 159.678 183.835 -71.8326 159.67 183.989 -71.3261 159.668 184.192 -70.8968 159.658 184.37 -70.4407 159.657 184.558 -69.6648 159.655 184.916 - -177.367 109.655 177.604 -177.2 109.666 177.603 -176.983 109.676 177.602 - -81.5102 111.15 179.2 -81.5102 111.15 179.2 - -161.346 111.947 180.867 -159.913 112.61 181.387 -159.246 113.13 181.796 -157.573 114.267 182.592 -156.544 114.953 183.135 -156.283 115.147 183.279 -155.926 115.408 183.493 -155.519 115.782 183.759 -154.307 116.954 184.614 -153.797 117.405 184.946 -153.561 117.626 185.089 -153.143 118.058 185.357 -152.108 118.992 186.147 -151.273 119.886 186.746 -150.251 121.072 187.507 -149.659 121.763 187.774 -148.791 122.837 188.016 -147.944 123.906 188.14 -147.492 124.509 188.162 -146.394 126.39 188.371 -144.996 127.879 189.272 -144.269 128.583 189.883 -143.593 129.367 190.592 -143.09 129.988 191.16 -142.589 130.989 192.03 -141.535 132.358 193.473 -139.953 132.998 194.305 -138.718 133.518 194.914 -137.438 134.099 195.543 -135.37 134.863 196.078 -134.59 135.123 196.24 -134.111 135.312 196.348 -132.669 135.255 195.831 - -161.346 111.947 180.867 -162.614 111.861 180.874 -163.509 111.521 180.694 -163.926 111.362 180.619 -164.581 111.131 180.493 -165.443 110.737 180.307 -166.047 110.484 180.174 -167.27 110.111 179.877 -168.282 109.896 179.626 -169.086 109.762 179.462 -170.202 109.594 179.283 -170.552 109.502 179.248 - -94.2346 148.878 186.053 -93.4394 148.752 186.386 -92.6899 148.637 186.679 -91.6862 148.512 186.975 -91.5026 148.494 187.018 -91.019 148.447 187.112 -90.5029 148.4 187.183 -90.0956 148.364 187.229 -89.4858 148.311 187.265 - -76.9636 126.936 187.226 -77.0048 126.946 187.227 -77.5446 127.136 187.233 -78.2155 127.329 187.234 -79.0643 127.526 187.224 -79.6086 127.618 187.206 -79.854 127.638 187.187 -80.7155 127.678 187.113 -81.5957 127.678 186.971 -82.3244 127.657 186.817 -83.5524 127.656 186.497 -84.9129 127.71 186.139 -85.8786 127.765 185.922 -86.8576 127.819 185.737 -87.5832 127.798 185.665 -88.2139 127.801 185.595 -89.5513 127.856 185.438 -90.643 127.982 185.262 -91.7053 128.168 185.025 -92.6269 128.363 184.79 -93.5762 128.715 184.427 -95.212 129.285 183.815 -96.3006 129.636 183.396 -97.5871 130.012 182.995 -99.4632 130.679 182.559 -100.726 131.189 182.444 -101.593 131.581 182.468 -102.503 132.111 182.564 -107.759 136.528 184.253 -111.118 139.449 185.334 -112.838 140.586 184.495 -113.042 140.725 184.373 -113.71 141.126 184.062 -115.2 141.737 183.381 - -202.67 166.715 102.83 -201.567 166.325 103.596 -200.836 166.041 104.171 -200.079 165.766 104.73 -199.586 165.434 105.37 -198.703 164.387 106.937 -198.288 163.979 107.591 -198.036 163.711 108.042 -197.581 163.247 108.925 -196.967 162.622 110.22 -196.399 162.163 111.661 -196.197 162.079 112.623 -196.085 162.025 113.196 -195.809 161.9 114.651 -195.317 161.667 117.363 -194.553 160.638 120.521 - -59.8742 146.681 114.041 -60.7988 146.955 114.672 -61.5217 147.159 115.205 -62.2305 147.363 115.736 -63.1237 147.593 116.402 -63.8093 147.771 116.91 -64.493 147.948 117.386 -67.3722 148.5 119.103 -68.7238 148.707 119.837 -69.4639 148.771 120.225 -70.2793 148.876 120.642 -71.241 148.979 121.151 -73.3006 149.249 122.401 -74.4924 149.338 123.151 -76.0756 149.357 124.191 -77.0104 149.258 124.907 -78.6682 149.342 125.88 -80.0307 149.633 126.177 -81.117 150.343 126.925 -82.7413 151.327 128.49 - -105.842 102.004 135.047 -104.467 102.578 133.682 -103.906 102.642 132.989 -103.269 102.701 131.939 -102.806 102.797 131.181 -102.535 102.826 130.746 -101.927 102.859 129.745 -101.499 102.911 129.036 - -67.9015 140.29 167.757 -66.8879 136.301 167.235 - -69.8722 133.879 58.4448 -69.8622 134.214 59.707 -69.863 134.954 61.7061 -69.6265 136.479 65.209 -69.9364 138.214 67.9146 - -65.1215 166.899 93.9701 -65.8125 166.673 93.8817 -66.2607 166.541 93.8661 -67.1521 166.313 93.9129 -68.1032 166.082 94.0389 -68.9168 165.901 94.192 -69.5339 165.777 94.3034 -70.3269 165.632 94.4318 -71.449 165.475 94.589 -74.23 165.686 94.4827 - -87.7579 183.725 102.224 -87.5673 183.06 102.861 -87.399 181.967 103.75 -87.2015 180.724 104.718 -87.0363 180.033 105.258 -86.7235 178.906 106.241 -86.5539 178.378 106.7 -85.9846 177.007 107.93 -85.5317 176.05 108.788 -85.2543 175.513 109.299 -84.8989 174.867 110.065 -84.3726 173.917 111.161 -84.167 173.475 111.695 -83.8032 172.852 112.572 -83.3437 171.848 113.995 -83.0191 171.244 114.941 -82.6161 170.982 115.688 - -58.1745 130.532 128.366 -59.8796 131.204 129.45 -60.9747 129.987 130.399 -61.4027 129.182 130.811 -61.7705 128.486 131.165 -62.1995 127.65 131.582 -62.668 126.554 132.039 - -173.744 84.4425 149.963 -173.353 84.9731 150.991 -172.825 85.6005 152.338 -172.38 86.1432 153.563 -172.126 86.4566 154.332 -171.636 87.1108 155.948 -171.333 87.6147 157.096 -171.163 87.8786 157.699 -170.693 88.5896 159.286 -170.091 89.4579 161.059 -169.595 89.9304 162.374 -169.202 89.6428 163.547 - -52.2718 173.646 149.975 -52.2967 173.632 149.984 -52.4228 173.56 150.023 -53.1026 173.161 150.211 -53.8067 172.722 150.396 -54.6547 172.167 150.632 -55.6121 171.511 150.974 -56.0793 171.184 151.171 -56.4828 170.882 151.393 -57.1075 170.428 151.781 -58.138 169.665 152.557 -58.7925 169.253 153.018 -59.7386 168.658 153.771 -60.787 168.061 154.544 -61.6683 167.765 155.408 -61.9886 167.652 155.718 -62.5402 167.474 156.15 -63.1364 167.373 156.446 -64.4205 167.176 157.246 -65.2961 166.992 157.902 -65.9481 166.841 158.466 -67.0206 166.681 159.078 -67.8442 166.512 159.766 -68.9022 166.34 160.569 -69.9838 166.077 161.304 -70.53 165.963 161.626 -71.4534 165.774 162.052 -72.3544 165.508 162.675 -73.5272 165.094 163.406 -74.8094 164.629 164.257 -75.7044 164.336 164.755 -76.7549 163.795 165.975 -77.3323 163.26 167.505 - -81.2481 184.464 153.386 -81.7592 184.255 153.275 -83.3808 183.277 153.346 - -71.8662 102.418 155.08 -72.0726 102.375 155.13 -72.9222 102.199 155.302 -73.5088 102.096 155.405 -74.4979 101.976 155.565 -75.7914 101.83 155.774 -76.8892 101.813 155.766 -77.4468 101.854 155.718 -78.0227 101.995 155.6 -79.2175 102.146 155.444 -80.2234 102.279 155.315 -81.3102 102.337 155.198 -82.1555 102.346 155.109 -82.5653 102.354 155.062 -83.264 102.366 154.986 -84.129 102.421 154.845 -85.3338 102.47 154.738 -86.2417 102.524 154.648 -87.2493 102.624 154.44 -88.6582 102.728 154.183 -90.1627 102.833 153.785 -91.0275 102.862 153.555 -91.7874 102.796 153.356 -92.4463 102.683 153.248 -93.3794 102.497 153.105 -94.2709 102.258 152.962 -95.182 102.01 152.768 -96.1254 101.019 151.829 -97.0981 100.351 151.4 - -169.024 87.7602 164.561 -169.017 87.9164 164.532 -169.011 88.0331 164.508 -169.202 89.6428 163.547 - -66.316 142.773 167.806 -66.4257 142.697 167.79 -67.2615 142.286 167.661 -66.6037 138.005 167.395 -66.8879 136.301 167.235 - -91.5826 179.267 171.736 -91.4687 179.144 171.796 -90.6988 178.064 172.307 -89.9989 176.504 172.403 -89.1565 174.441 172.59 -87.7213 171.351 172.953 - -111.518 102.048 175.403 -111.173 99.9685 175.76 -111.09 99.292 175.841 -111.088 98.6491 175.912 -111.106 98.328 175.949 -111.146 97.7287 175.997 -111.234 96.7723 176.043 -111.391 95.724 176.054 -111.562 94.9268 176.046 -111.781 94.1655 176.03 - -111.518 102.048 175.403 -110.438 101.538 175.184 -109.057 100.895 174.845 -107.764 100.406 174.622 -107.151 100.235 174.501 -106.118 99.8567 174.478 -104.782 99.5323 174.534 -103.954 99.3817 174.674 -102.893 99.2995 174.955 -101.384 99.2294 175.464 -100.744 99.2102 175.659 -100.4 99.1918 175.748 -99.956 99.1638 175.854 -99.2933 99.1063 175.962 - -176.954 99.7568 177.602 -176.875 99.9012 177.604 -176.812 100.024 177.604 -176.684 100.267 177.604 -176.152 101.233 177.607 -175.979 101.527 177.607 -175.765 101.89 177.608 -175.344 102.593 177.607 -174.917 103.248 177.607 -174.735 103.528 177.606 -174.38 104.057 177.605 -174.178 104.364 177.604 - -131.322 135.609 43.3718 -131.079 135.782 43.1609 - -71.8553 141.902 83.0875 -71.5524 142.495 84.546 -71.8635 142.969 86.2029 - -215.038 176.519 122.635 -213.447 175.246 122.861 -212.17 174.08 122.862 -211.306 173.549 123.033 -210.298 172.859 123.185 -209.06 172.197 123.435 -208.214 171.655 123.544 -207.478 171.251 123.656 -206.02 170.689 123.692 -205.452 170.481 123.697 -204.47 170.13 123.694 -203.259 169.692 123.686 -202.09 169.337 123.646 -200.856 168.92 123.519 - -99.4337 99.8942 151.25 -97.9589 97.2116 151.646 -97.775 96.3902 151.809 -97.4821 94.9923 152.093 -96.8278 92.913 152.546 - -99.4337 99.8942 151.25 -97.0981 100.351 151.4 - -97.8414 91.1207 152.698 -96.8278 92.913 152.546 - -83.3808 183.277 153.346 -83.6782 181.956 154.803 -83.5796 181.583 155.691 -83.0243 181.566 157.363 - -82.6161 170.982 115.688 -83.1211 170.046 115.838 -83.2748 169.231 116.334 -83.404 168.622 116.686 -83.5143 168.087 117.002 -83.7721 166.951 117.624 -83.9247 165.825 118.465 -84.1383 165.047 118.934 -84.5255 163.975 119.266 -84.7867 163.203 119.808 -85.2191 162.048 120.436 -85.6017 161.498 120.766 -85.7829 161.201 120.961 -86.0429 160.81 121.144 -86.3498 160.344 121.411 -86.9068 159.778 121.953 -87.4672 158.636 122.839 -87.2137 156.037 123.863 -86.9803 154.57 124.469 -86.8712 154.008 124.705 -86.691 153.204 125.081 -86.3997 152.159 125.658 -85.9691 151.836 125.767 -84.7851 150.991 124.527 - -90.089 162.984 168.836 -89.8987 164.957 170.576 -89.7081 165.489 170.86 -89.5733 165.788 171.025 -89.2581 166.496 171.39 -88.7415 167.755 171.84 -88.4179 169.28 172.267 -87.7213 171.351 172.953 - -148.131 142.704 3.70934 -146.072 142.424 4.59721 -143.831 142.168 5.60645 -142.595 142.04 6.14898 -141.445 141.937 6.6574 -140.619 141.86 7.10711 -139.94 141.812 7.49441 -138.904 141.931 7.76347 -137.229 142.106 8.27962 -135.734 142.107 9.24291 - -131.079 135.782 43.1609 -131.105 135.94 41.8939 -131.187 136.072 40.7448 -131.246 136.259 39.4345 -131.284 136.42 38.4226 -131.354 136.621 37.1584 -131.456 136.901 35.4977 -131.576 137.255 33.4679 -131.672 137.494 32.0916 -131.74 137.653 31.2041 -131.842 137.89 29.9179 -131.935 138.079 28.88 -132.025 138.252 27.9305 -132.166 138.525 26.4419 -132.393 138.821 24.78 -132.544 139.068 23.4507 -132.857 139.297 22.1451 -133.314 139.739 19.6675 -133.63 140.013 18.1275 -133.893 140.209 17.0392 -134.205 140.53 15.3925 -134.901 141.793 10.7873 -135.734 142.107 9.24291 - -131.079 135.782 43.1609 -131.072 135.641 44.7699 -131.043 135.558 46.2842 -131.067 135.509 47.8606 -131.337 135.418 50.3526 -131.266 135.66 53.2877 -131.468 135.851 55.1908 -131.719 136.013 56.8924 -131.977 136.212 58.3686 -132.272 136.421 59.9484 -132.468 136.563 61.0536 -132.694 136.728 62.3631 -132.994 136.957 64.2912 -133.048 137.001 64.6806 -133.314 137.226 66.8636 -133.52 137.408 68.7152 -133.619 137.511 69.893 -133.697 137.637 71.7167 -133.688 137.748 74.0155 -133.564 137.76 75.4613 -133.499 137.759 76.3906 -133.431 137.75 77.4357 -133.192 137.661 78.741 -132.659 137.459 80.2182 -132.095 137.177 81.3773 -131.862 137.062 81.8157 -131.281 136.752 83.1137 -130.405 136.23 85.3274 - -115.2 141.737 183.381 -117.523 142.061 183.769 -118.347 142.065 184.224 -119.739 142.081 184.897 -122.286 141.842 186.676 -123.999 141.606 187.998 - -82.7413 151.327 128.49 -84.0276 151.073 126.382 -84.7851 150.991 124.527 - -194.553 160.638 120.521 -196.121 163.41 120.833 -196.469 164.885 121.021 - -200.856 168.92 123.519 -199.907 167.623 123.164 -199.463 167.08 122.979 -198.798 166.322 122.684 -198.28 165.866 122.334 -197.598 165.402 121.832 -196.469 164.885 121.021 - -132.669 135.255 195.831 -131.489 136.474 196.108 -130.1 137.32 196.082 -129.105 137.924 195.931 -128.208 138.465 195.769 -126.877 139.449 194.383 -125.857 140.258 192.789 -125.36 140.664 191.715 -125.102 140.874 191.021 -124.74 141.161 189.898 -124.497 141.39 188.937 -123.999 141.606 187.998 - -137.566 133.633 113.294 -136.88 134.048 114.669 -136.624 134.187 115.097 -136.078 134.522 116.202 -135.859 135.024 117.841 -135.598 135.597 119.615 -135.526 135.752 120.079 -135.194 136.591 122.56 -134.859 137.21 124.166 -134.747 137.65 125.387 -134.54 138.558 127.919 -134.466 138.934 128.975 -134.417 139.3 130.012 -134.307 139.943 131.943 -134.219 140.199 132.766 -134.126 140.472 133.664 -134.233 140.881 135.4 -134.64 141.606 138.608 -134.615 141.971 141.075 -134.608 142.114 142.058 -134.603 142.149 142.31 -134.555 142.372 143.948 -134.509 142.507 145.013 -134.449 142.621 145.999 -134.35 142.8 147.573 -134.256 142.919 148.731 -134.1 143.109 150.603 -134.006 143.213 151.668 -133.951 143.268 152.251 -133.876 143.334 152.988 -133.635 143.504 155.036 -133.4 143.548 156.278 -133.039 143.54 157.751 -132.679 143.538 159.39 -132.421 143.521 160.682 -132.114 143.468 162.148 -131.86 143.415 163.373 -131.465 143.28 165.419 -131.238 143.195 166.614 -130.895 143.062 168.415 -130.716 142.996 169.341 -130.473 142.916 170.574 -130.289 142.858 171.504 -130.074 142.817 172.47 -129.913 142.77 173.295 -129.757 142.736 174.037 -129.476 142.711 175.098 -129.256 142.68 175.907 -128.926 142.66 176.991 -128.088 142.51 179.343 -126.888 142.368 182.164 -126.353 142.288 183.255 -125.261 141.967 185.647 -124.598 141.768 187.036 -123.999 141.606 187.998 - -137.566 133.633 113.294 -136.131 133.628 111.488 -135.759 133.598 110.862 -135.404 133.57 110.267 -134.881 133.495 109.163 -134.15 133.509 107.478 -133.636 133.523 105.873 -133.368 133.544 105.064 -133.01 133.595 103.864 -132.685 133.679 102.589 -132.244 133.834 100.672 -131.897 134.013 98.9006 -131.701 134.139 97.7952 -131.648 134.165 97.5438 -131.469 134.316 96.407 -131.348 134.456 95.4476 -131.202 134.643 94.2253 -130.995 134.92 92.4675 -130.915 135.096 91.4794 -130.797 135.327 90.1767 -130.68 135.471 89.3444 -130.589 135.609 88.5861 -130.604 135.95 86.8884 -130.405 136.23 85.3274 - diff --git a/data/patient_08/Patient_08_venoussystem_skeleton.txt b/data/patient_08/Patient_08_venoussystem_skeleton.txt deleted file mode 100644 index e824fde..0000000 --- a/data/patient_08/Patient_08_venoussystem_skeleton.txt +++ /dev/null @@ -1,1330 +0,0 @@ -124.847 84.4897 34.42 -124.929 84.5022 34.5772 -125.643 84.5831 35.8539 -125.901 84.7885 37.7116 - -123.042 88.3776 54.5085 -123.214 88.515 55.2484 - -194.212 110.69 160.864 -193.643 111.415 161.304 -192.833 112.434 161.934 -192.446 112.91 162.239 -191.02 114.77 163.445 -191.85 115.854 164.196 - -65.8874 136.055 49.1372 -66.6845 135.002 50.0835 -66.8917 134.726 50.3257 -68.0989 133.096 51.7116 -69.0322 131.751 52.7607 -70.0813 130.187 53.8771 -70.8367 128.629 54.3381 -71.6768 126.994 55.2105 -72.1984 126.006 55.8317 -72.5729 125.076 56.1057 -73.9801 119.509 57.1376 - -78.071 158.086 59.845 -78.1325 157.866 60.8743 -78.2282 157.485 62.6068 -78.3101 157.142 64.1188 -78.3664 156.924 65.3104 -78.392 156.826 65.8751 -78.4147 156.996 67.9795 - -60.2039 155.341 71.6785 -60.3399 155.33 72.5722 -60.4304 155.324 73.1424 -60.7675 155.323 75.1102 -61.0034 155.266 77.2087 -61.0796 155.278 78.0135 -61.1706 155.428 79.4894 -61.0173 156.758 81.4062 - -137.163 85.092 74.5876 -137.006 85.1093 75.4299 -136.791 85.1271 76.6176 -136.37 85.1386 78.9678 -136.104 85.3324 82.2544 -136.513 85.7459 84.3486 -136.749 85.9748 85.5818 -136.82 86.2036 87.085 -137.913 86.9824 90.8748 - -104.1 86.5675 70.8634 -102.958 88.3178 71.4794 -102.37 89.953 72.9031 - -59.6024 138.075 81.831 -59.6619 138.109 81.8917 -60.5798 138.655 82.7245 -62.2433 139.653 84.0144 -63.8185 140.449 84.9221 -64.7391 140.795 85.3336 -67.2101 141.299 86.6562 - -125.457 106.864 158.045 -122.632 103.734 149.272 - -125.457 106.864 158.045 -126.737 109.082 159.321 -127.961 111.187 161.484 -128.532 112.153 162.541 -128.794 112.596 163.027 -129.14 113.18 163.665 -129.586 113.948 164.516 -130.03 114.817 165.447 -130.227 116.673 167.898 - -125.457 106.864 158.045 -124.617 105.028 158.788 -124.534 103.932 160.485 -124.681 103.259 161.692 -124.875 102.132 163.675 -124.889 101.083 165.303 -124.797 99.7985 167.085 -124.613 98.9346 168.069 -124.491 98.4369 168.659 - -84.9269 179.043 85.5297 -84.9876 178.452 86.3632 -85.1387 176.786 88.6976 -85.222 175.019 91.0726 -85.2864 173.549 93.0427 -85.3214 172.774 94.0817 -85.3519 172.048 95.0576 -85.4086 170.568 97.0421 -84.8833 168.875 99.1214 -84.3757 167.435 100.86 -83.7539 165.739 102.859 -82.7873 163.469 105.302 -81.7354 162.01 107.086 -81.0079 160.186 108.87 -78.5962 158.884 111.503 - -148.79 75.3299 87.1424 -148.406 75.6382 87.7389 -147.667 76.2275 88.8712 -147.3 76.5477 89.5006 -146.747 77.2283 90.9686 -146.403 77.6623 91.9134 -145.849 78.3654 93.4483 -145.587 78.7011 94.1836 -145.321 79.0457 94.943 -144.671 80.0604 97.4016 -144.557 80.7497 99.5844 -144.551 81.1474 100.942 -143.789 82.3533 103.716 - -61.0173 156.758 81.4062 -60.0179 160.838 81.2346 -59.3482 163.105 80.9458 -58.9502 164.585 80.7231 -58.9488 164.591 80.7222 -58.947 164.597 80.721 - -61.0173 156.758 81.4062 -61.5186 155.006 82.5176 -61.7994 153.031 84.8869 -63.3386 151.021 85.3607 -64.6575 149.411 85.8313 -66.0364 147.811 86.2995 -68.073 144.339 87.0143 -67.2101 141.299 86.6562 - -90.7024 140.89 85.4398 -90.4432 141.064 85.4101 -89.0715 141.99 85.2423 -88.2669 142.511 85.1326 -86.9446 143.145 84.862 -85.5599 143.709 84.6407 -82.6381 144.087 84.6342 -80.3282 144.293 84.7584 - -142.957 87.784 89.5012 -142.26 87.6998 89.5785 -140.827 87.4643 89.6202 -137.913 86.9824 90.8748 - -115.064 95.1406 94.0754 -114.321 98.0252 95.5105 - -115.064 95.1406 94.0754 -116.119 93.7546 97.1936 -116.302 93.6433 97.997 -116.924 93.3885 99.9499 -117.469 93.0765 101.913 -118.322 92.695 103.737 -118.684 92.5415 104.437 -119.342 92.1358 105.522 -121.308 90.1466 110.362 - -115.064 95.1406 94.0754 -114.826 94.7176 92.168 -114.245 94.4389 88.7568 -113.874 94.0078 86.2572 -113.015 93.611 83.2099 -112.247 93.2826 80.8076 -108.779 92.0873 75.342 - -83.0616 116.469 101.194 -83.0746 116.601 101.15 -83.1327 117.256 100.923 -83.2576 118.403 100.523 -83.4035 119.602 100.087 -83.7359 121.925 99.2861 -83.2766 125.401 96.3324 - -60.1339 110.395 99.8877 -60.0678 110.68 100.002 -59.8273 111.751 100.435 -59.5351 113.299 101.053 -59.2226 114.997 101.732 -58.9327 116.846 102.464 -59.3508 118.136 103.057 -60.5475 121.632 104.644 -61.615 124.739 106.053 -61.8904 125.528 106.403 -62.4854 127.186 107.098 -63.0756 128.838 107.795 -63.7248 130.624 108.502 -64.17 131.873 108.995 -64.5734 133.253 109.473 -64.0551 135.842 109.722 -65.7557 138.894 109.509 - -90.3733 123.382 100.082 -88.3308 124.128 99.6338 -87.6055 124.725 99.4783 -85.4958 125.715 98.3503 -83.2766 125.401 96.3324 - -105.728 86.0623 102.144 -105.763 86.9818 103.358 -106.349 88.3762 105.107 -106.883 89.5362 106.576 -105.863 91.6136 109.516 - -59.0806 172.943 102.879 -59.6145 172.107 103.97 -60.5768 170.592 105.928 -61.0244 169.905 106.777 -61.5277 169.14 107.71 -62.047 168.265 108.807 -62.5938 167.02 110.478 -65.2745 163.976 113.788 - -75.289 183.143 109.052 -75.2835 182.848 109.515 - -123.214 88.515 55.2484 -124.06 88.0184 53.2858 -124.334 87.7243 52.0909 -124.835 87.2365 50.1839 -125.645 86.5985 48.0148 - -123.214 88.515 55.2484 -121.99 89.1055 57.8561 -121.431 89.3442 58.8862 -119.522 90.1316 62.2955 -118.835 90.4081 63.4899 -117.418 90.9507 65.7539 -116.89 91.1439 66.5483 -112.438 92.2765 70.8728 -110.461 92.2893 72.2288 - -88.1816 97.2536 110.696 -89.0148 96.5852 110.893 -89.856 95.9571 110.972 -90.8048 95.2674 111.024 -92.7994 92.9853 111.383 - -151.772 79.6779 129.217 -151.394 80.3266 130.898 -150.917 81.1439 133.018 -150.324 82.2103 135.811 -149.825 83.1552 138.307 -149.436 83.9595 140.454 -148.882 85.2101 143.79 -148.467 86.28 146.761 -148.289 87.0198 148.749 -147.851 86.5095 151.619 - -49.9261 142.58 119.632 -50.2884 142.488 119.362 -51.4191 142.121 118.54 -52.2455 141.411 117.977 - -65.3679 171.39 129.221 -66.0789 171.467 128.962 -66.4468 171.508 128.829 -67.8691 171.683 128.31 -69.7787 171.918 127.627 -71.8539 172.404 126.74 -76.4149 173.901 124.526 - -105.486 162.228 145.628 -105.639 161.646 146.29 -105.717 161.328 146.653 -105.961 160.159 147.997 -106.125 159.239 149.051 -105.701 158.994 149.604 -105.232 158.731 150.218 -102.836 158.339 152.718 - -52.9788 155.622 146.398 -54.2184 155.689 147.308 - -58.595 116.628 149.578 -59.5359 117.068 150.013 -60.6451 117.579 150.541 -61.5376 117.98 150.973 -62.7628 117.635 152.398 - -51.8804 157.179 146.412 -53.4637 156.257 147.056 -54.2184 155.689 147.308 - -46.6617 140.452 147.581 -47.146 140.405 147.678 -48.5185 140.264 147.956 -50.9146 139.98 148.448 -53.1244 139.685 148.946 -55.5227 139.344 149.58 -58.2477 138.93 150.348 -60.6974 138.317 151.733 -61.881 137.993 152.521 -62.5414 137.793 152.983 -64.3833 137.64 154.341 -66.0255 137.624 155.595 -69.3503 138.067 158.082 - -147.944 82.6213 150.006 -147.867 83.5909 150.499 -147.787 84.8522 151.226 -147.851 86.5095 151.619 - -99.615 95.6746 147.363 -99.1811 92.8 143.863 -98.5766 91.8938 142.548 -98.3313 91.5686 142.074 -97.8069 90.9323 141.139 -96.6192 89.517 139.041 - -99.615 95.6746 147.363 -102.972 97.3308 149.452 -104.724 97.7544 150.579 - -99.615 95.6746 147.363 -96.1198 96.1695 147.903 -95.0086 96.1916 147.91 -93.1309 96.1242 147.756 -91.1169 95.9514 147.36 -88.2995 95.8544 146.527 -86.8508 95.7558 145.991 -85.4867 95.6793 145.513 -81.8621 95.3218 144.064 -80.0653 95.1249 143.33 -78.6254 94.9421 142.705 -78.1847 94.8804 142.515 - -90.5135 150.292 138.104 -86.8999 147.594 131.34 -85.7142 146.474 129.26 -85.0025 145.966 127.84 -83.4109 144.779 124.722 -81.5923 143.393 121.457 -80.619 142.64 119.533 - -90.5135 150.292 138.104 -90.9449 156.055 135.739 -91.046 156.754 135.604 -91.003 159.158 134.818 -90.9703 160.014 134.535 -90.508 161.847 133.739 -88.8763 164.418 132.233 -88.0501 165.851 131.555 -87.0119 167.71 130.646 -85.5179 171.209 128.274 - -90.5135 150.292 138.104 -91.7676 149.196 141.659 -92.6349 148.853 143.849 -94.066 148.192 147.703 -94.401 146.989 152.587 - -117.221 76.2543 102.398 -117.477 76.6777 103.125 -118.17 77.7991 105.035 -118.751 78.9295 106.95 -119.366 80.2807 109.132 -119.813 81.2675 110.718 -120.326 82.4553 112.487 -120.452 84.0333 114.02 -120.492 84.7095 114.356 -120.903 88.3144 116.109 - -54.2184 155.689 147.308 -57.0426 154.63 149.221 -58.5487 153.913 149.791 -59.8621 153.294 150.305 -60.9499 152.784 150.755 -61.8698 152.348 151.137 -62.8903 151.86 151.561 -64.4202 151.129 152.209 -66.049 150.344 152.905 -68.2328 149.278 153.867 -70.8738 147.886 155.079 -75.1578 146.144 156.294 - -122.632 103.734 149.272 -117.694 103.487 151.503 - -122.632 103.734 149.272 -123.145 102.933 146.461 -123.447 102.248 144.325 -123.82 101.861 142.852 -124.038 101.061 140.313 -124.281 100.052 137.138 -124.09 99.1014 134.701 -123.87 98.2222 132.421 -123.533 97.3655 130.079 -123.059 96.2007 126.885 -122.742 95.3799 124.62 -122.636 94.6555 123.085 -122.51 94.0483 121.798 -122.185 93.2856 120.15 -121.861 92.5243 118.589 -120.903 88.3144 116.109 - -118.701 106.065 155.053 -117.694 103.487 151.503 - -64.4974 164.956 157.59 -64.5156 164.946 157.598 -65.0859 164.625 157.85 -66.3986 163.876 158.422 -67.6684 162.831 158.559 -69.0688 161.62 158.644 -70.9686 159.96 158.75 -72.4147 158.653 158.796 -74.1191 157.101 158.843 -76.2692 154.908 158.734 -77.8233 153.315 158.644 -77.9301 152.355 158.274 -77.9222 151.356 157.794 -77.5416 150.202 157.441 -75.1578 146.144 156.294 - -117.694 103.487 151.503 -115.42 103.032 151.971 -113.722 102.385 151.522 -112.305 101.886 151.08 -110.468 101.446 150.166 - -201.848 162.011 83.8723 -201.124 161.121 84.8928 -200.194 160.251 87.0208 - -67.0005 130.345 158.177 -72.0285 129.975 162.498 -73.639 127.635 164.847 -74.6077 125.423 166.914 -77.3838 122.734 169.568 - -67.0005 130.345 158.177 -63.0468 129.398 156.51 -62.0203 129.257 156.478 -61.0808 129.26 156.412 -59.0677 129.253 156.27 -58.1169 129.26 156.256 -57.6527 129.276 156.318 -57.024 129.303 156.48 - -67.0005 130.345 158.177 -66.4227 127.289 156.419 -66.3024 125.243 155.531 -65.3908 121.006 153.687 -62.7628 117.635 152.398 - -67.0005 130.345 158.177 -69.3503 138.067 158.082 - -95.6139 165.986 154.885 -96.3134 165.368 154.77 -97.102 164.67 154.642 -98.8221 163.138 154.372 -99.7056 161.844 154.137 -100.648 160.434 153.897 -102.836 158.339 152.718 - -219.934 113.058 162.207 -218.951 113.721 162.473 -216.507 115.078 163.08 -213.201 115.421 163.34 -211.098 115.528 163.466 -209.969 115.582 163.532 -209.625 115.598 163.552 -208.593 115.644 163.61 -207.315 115.7 163.682 -206.195 115.747 163.743 -204.462 115.814 163.836 -203.275 115.857 163.897 -201.767 115.91 163.975 -199.614 115.981 164.081 -197.699 116.042 164.174 -195.356 116.063 164.251 -191.85 115.854 164.196 - -153.62 112.901 167.546 -157.111 113.414 167.089 - -153.62 112.901 167.546 -149.791 109.724 169.376 -149.438 108.554 169.871 -149.286 108.163 169.813 -147.6 103.59 168.988 - -153.62 112.901 167.546 -149.915 115.226 166.531 -147.437 116.318 166.089 -145.268 117.172 165.542 -142.772 118.189 164.888 -141.038 119.129 164.274 -139.629 119.958 163.805 -137.462 121.764 162.517 - -113.148 122.841 173.304 -111.953 122.8 173.804 - -113.148 122.841 173.304 -115.304 123.432 172.989 -116.774 123.932 172.879 -118.334 124.481 172.781 -119.206 124.788 172.726 -121.121 125.456 172.597 -123.168 126.268 172.627 -124.975 126.993 172.69 -125.924 127.377 172.74 - -113.148 122.841 173.304 -111.797 122.127 173.146 -109.777 121.373 173.237 -107.475 120.518 173.343 -106.354 120.102 173.396 -104.263 119.326 173.493 -100.703 118.019 173.664 -98.6779 117.373 173.819 -96.9282 117.471 173.852 -96.1139 117.51 173.868 -94.6261 117.581 173.896 -92.7821 117.672 173.929 -84.9554 118.093 174.051 -83.5101 119.082 173.103 -82.7744 119.619 172.59 -81.9479 120.223 172.012 -81.2223 120.752 171.503 -80.35 121.406 170.873 -79.2821 121.689 170.595 -77.3838 122.734 169.568 - -169.647 103.832 166.361 -167.651 106.343 166.082 -166.241 108.065 166.461 -164.779 109.874 166.659 -166.755 112.973 165.526 - -169.647 103.832 166.361 -170.795 103.121 169.698 -171.284 102.76 170.868 -172.046 102.205 172.538 -172.624 101.834 173.708 -173.386 101.603 174.246 - -169.647 103.832 166.361 -170.013 102.384 162.458 -170.805 100.589 159.464 -171.825 98.2257 155.406 -173.033 95.8115 151.423 -174.218 93.5197 147.414 -174.691 92.399 145.017 -175.121 91.4092 142.871 -175.981 89.5399 138.873 -177.245 88.2945 136.794 -178.653 86.4597 133.523 - -144.878 102.899 174.575 -145.926 102.852 172.102 -147.6 103.59 168.988 - -157.111 113.414 167.089 -155.956 112.376 164.095 -155.767 110.934 161.429 -155.805 110.262 160.268 - -157.111 113.414 167.089 -159.262 113.363 166.721 -160.313 113.329 166.517 -161.797 113.25 166.285 -163.174 113.143 166.082 -166.755 112.973 165.526 - -86.4552 138.786 182.726 -86.6826 138.82 182.694 -88.0337 138.451 182.615 -89.1041 139.051 182.228 -90.7668 139.753 181.623 -91.568 140.136 181.318 -97.8852 142.007 177.897 - -76.4149 173.901 124.526 -73.0052 175.991 122.067 -73.7819 178.355 118.272 - -76.4149 173.901 124.526 -80.6521 172.429 126.21 -82.1857 172.136 126.748 -85.5179 171.209 128.274 - -110.468 101.446 150.166 -109.014 102.08 148.018 - -110.468 101.446 150.166 -108.398 100.169 150.271 -107.086 99.2783 150.439 -104.724 97.7544 150.579 - -183.805 83.5312 107.034 -182.672 83.9233 110.921 -181.76 84.2278 113.572 -180.878 84.5326 116.585 -180.129 84.7947 119.226 -179.648 84.9788 120.996 -179.245 85.1445 122.486 -178.704 85.2489 123.758 -177.811 84.9822 124.699 -177.024 84.7271 125.434 -176.097 84.5352 126.866 - -183.805 83.5312 107.034 -184.724 83.2719 106.16 -185.453 83.0613 105.256 - -183.805 83.5312 107.034 -183.315 83.597 104.329 -183.147 83.6126 103.086 -183.19 83.5729 101.808 -183.235 83.5298 100.405 - -85.8789 90.414 113.068 -88.1286 90.9798 112.686 -89.6339 91.5392 112.316 -90.8942 92.0501 111.967 -92.7994 92.9853 111.383 - -62.2229 140.746 166.423 -62.5428 140.75 166.295 -63.8134 140.762 165.756 -65.5329 140.774 165.02 -69.1583 140.775 163.383 -70.4663 140.718 162.331 -71.0564 140.71 161.605 -70.9685 140.637 160.562 -70.8593 140.397 158.559 - -214.075 90.4427 105.451 -213.86 91.0083 107.619 -213.646 91.4771 109.374 -212.969 92.0581 110.811 -212.249 92.6467 112.194 -211.869 92.9524 112.903 -209.612 94.7392 117.003 -208.035 95.9874 119.867 -206.526 97.1813 122.605 -205.428 98.051 124.601 -203.941 99.2284 127.302 -202.409 100.433 130.056 -200.388 102.067 133.851 - -137.098 134.09 147.622 -134.623 132.853 151.31 - -137.098 134.09 147.622 -137.85 134.9 145.148 -138.546 135.479 143.226 -139.225 136.045 140.711 -140.361 136.347 136.975 -140.855 136.477 135.356 -141.22 136.573 134.162 -141.909 136.728 131.841 -142.705 136.625 128.71 -143.103 136.566 127.024 -143.411 136.52 125.714 -143.8 136.461 124.044 -144.272 136.368 121.207 -144.838 136.232 116.982 -145.098 136.164 114.943 -145.202 136.135 114.091 -145.533 136.058 111.62 -146.238 136.047 108.485 -146.539 136.052 107.311 -146.75 136.038 106.242 -147.794 136.206 104.565 -149.71 136.551 102.057 -151.631 136.917 100.099 -152.834 137.101 97.8628 - -137.098 134.09 147.622 -140.206 132.06 152.686 -141.508 132.159 152.541 -142.919 131.961 153.077 -143.337 131.665 153.163 -145.583 128.927 152.801 -147.056 126.976 152.362 -147.975 125.733 152.035 -148.881 124.505 151.68 -150.002 122.957 151.274 -151.344 121.712 150.116 -153.14 120.126 148.511 -154.545 119.009 147.154 - -94.401 146.989 152.587 -98.2275 147.032 153.527 -100.515 147.028 154.956 - -94.401 146.989 152.587 -91.9812 146.575 153.567 -90.6046 146.36 154.346 -87.6461 146.343 154.728 -86.6685 146.277 154.882 -80.5806 146.487 155.935 -75.1578 146.144 156.294 - -93.6349 150.686 107.521 -93.5741 150.643 107.536 -92.6802 150.014 107.735 -90.3461 148.391 108.194 -87.7417 146.639 108.314 -82.5022 143.212 108.495 -78.7852 141.901 110.422 - -100.531 94.6789 33.5643 -100.353 95.0535 35.6746 -100.311 95.1391 36.1734 -100.179 95.3463 37.0777 -100.162 95.4491 38.2798 -99.7832 95.5787 39.87 -98.4802 95.8123 42.5902 - -72.8208 105.14 35.2123 -72.7628 105.807 36.1948 -72.6135 107.594 38.8184 -72.5596 109.027 40.8303 -72.5508 111.297 43.9262 -72.6056 111.86 44.388 -72.6875 112.526 45 -72.736 113.612 45.5606 -72.7807 115.338 46.39 -72.8152 116.523 47.0159 -72.8121 119.169 47.7203 - -127.503 83.8366 36.4597 -125.901 84.7885 37.7116 - -93.2669 95.8549 42.5271 -94.2488 95.8892 42.9568 -98.4802 95.8123 42.5902 - -147.851 86.5095 151.619 -147.95 89.3227 153.319 -147.881 90.539 154.9 -147.851 92.4524 156.779 -147.804 94.2277 158.692 -147.798 94.412 158.898 -147.778 95.1611 159.731 -147.757 95.9829 160.639 -147.744 96.7291 161.452 -147.728 97.8233 162.635 -147.686 99.6101 164.613 -147.6 103.59 168.988 - -73.4588 110.468 60.4054 -73.8005 111.867 60.4663 -74.2254 116.638 58.7871 -73.9801 119.509 57.1376 - -80.0347 128.548 125.692 -79.6636 129.345 125.723 -79.2256 130.962 125.236 -77.3069 131.484 124.371 - -53.1627 149.63 106.66 -54.3526 148.384 107.549 -55.3439 147.353 108.228 -56.7029 145.936 109.141 -58.0363 144.486 109.819 -60.2184 141.923 110.96 - -96.051 182.453 114.395 -95.8722 181.658 114.877 -95.5631 180.898 115.463 -95.221 179.989 116.198 -94.5418 178.171 117.661 -94.1405 177.03 118.525 -93.3338 175.4 119.843 - -201.409 161.651 87.2789 -200.194 160.251 87.0208 - -52.2455 141.411 117.977 -55.2916 141.535 115.95 -56.7823 141.5 114.945 -60.2184 141.923 110.96 - -52.2455 141.411 117.977 -51.0541 140.335 118.923 -50.5032 139.992 119.338 -50.1404 139.782 119.608 - -83.033 178.113 134.072 -83.568 176.122 133.049 -83.7573 175.436 132.675 -83.9421 174.715 132.264 -84.2232 173.744 131.678 -84.4189 173.074 131.199 -84.6744 172.327 130.77 -85.5179 171.209 128.274 - -54.6579 116.021 125.201 -55.9795 116.287 125.151 -57.1855 116.563 125.111 -59.4458 117.38 125.062 -63.2676 118.529 124.945 - -62.6789 113.824 154.732 -62.9124 115.255 153.96 -62.7628 117.635 152.398 - -103.424 139.242 164.383 -101.803 141.887 161.722 -101.136 142.794 160.754 -101.369 143.464 159.673 -100.515 147.028 154.956 - -181.919 113.747 160.026 -183.167 115.827 163.453 -183.837 116.927 164.886 -187.954 117.175 165.248 -189.649 116.67 164.845 -191.85 115.854 164.196 - -181.919 113.747 160.026 -175.277 114.133 162.987 -173.927 114.074 163.36 -170.51 114.013 164.447 -168.158 113.647 165.115 -166.755 112.973 165.526 - -181.919 113.747 160.026 -184.289 112.924 157.704 -185.314 111.936 155.535 -186.055 111.229 153.98 -186.655 110.968 153.298 -187.594 110.624 152.351 -188.453 110.213 151.365 -189.325 109.697 150.242 -189.968 109.302 149.392 -190.524 108.95 148.637 -191.124 108.562 147.808 -192.145 107.887 146.369 -192.981 107.322 145.167 -193.935 106.676 143.794 -194.407 106.355 143.111 -195.09 105.885 142.109 -195.806 105.389 141.054 -196.937 104.584 139.323 -198.614 103.35 136.622 -200.388 102.067 133.851 - -124.018 117.11 176.88 -124.776 117.435 176.679 -126.384 118.116 176.214 -127.229 118.318 175.476 -127.71 118.401 174.968 -128.481 118.313 173.777 -129.285 118.213 172.479 -130.227 116.673 167.898 - -72.8121 119.169 47.7203 -72.5342 121.663 45.6542 -72.4665 121.793 44.106 -72.3487 122.123 43.165 -72.1927 122.505 41.9108 -72.1556 122.598 41.6129 -72.0415 122.878 40.7008 -71.8382 123.378 39.0778 -71.5627 124.111 36.8786 -71.1584 125.81 33.6384 -71.0324 126.556 32.5039 - -72.8121 119.169 47.7203 -73.2291 119.406 51.4996 -73.9801 119.509 57.1376 - -134.623 132.853 151.31 -133.954 129.566 155.945 -134.209 128.131 157.348 -134.428 126.48 158.935 -135.042 124.917 160.126 -135.427 123.843 160.935 -137.462 121.764 162.517 - -134.623 132.853 151.31 -132.381 133.243 152.498 -130.198 133.269 154.174 -128.142 133.489 155.507 -125.215 134.943 155.871 -123.636 135.754 156.034 -122.364 136.328 156.274 -121.335 136.793 156.467 -120.322 137.251 156.657 -119.315 137.706 156.846 -117.81 138.387 157.133 -114.438 139.91 157.771 -113.287 140.442 158.036 -111.115 141.497 158.904 -108.582 142.76 159.536 - -138.162 138.601 9.71481 -139.196 137.043 17.2367 -140.009 135.837 23.3368 -140.225 135.518 24.9814 -140.494 135.121 27.0234 -140.704 134.811 28.6256 -140.95 134.446 30.4981 -141.365 133.834 33.6622 -141.665 133.403 36.3515 -141.873 133.115 38.5699 -141.973 132.977 39.6369 -142.103 132.797 41.0426 -142.246 132.598 42.5289 -142.504 132.277 46.0637 -142.733 132.034 49.9747 -142.825 131.937 51.5179 -142.906 131.851 52.8913 -143.052 131.702 55.165 -143.173 131.575 57.1548 -143.194 131.693 59.6412 -143.151 131.824 61.5241 -143.134 131.928 63.073 -143.083 132.098 65.6293 -142.991 132.436 70.5731 -142.816 132.695 73.3165 -142.2 132.875 75.0686 -141.329 133.133 77.5512 -139.671 133.2 79.1787 - -130.218 84.4908 44.9766 -129.854 84.658 44.9649 -125.645 86.5985 48.0148 - -125.645 86.5985 48.0148 -125.525 86.1982 45.3974 -125.6 85.9339 43.9746 -125.72 85.6376 42.4654 -125.901 84.7885 37.7116 - -99.134 98.6006 58.3369 -100.866 96.8182 55.5209 - -77.5689 162.766 66.1985 -77.6291 162.511 66.347 -77.7696 161.54 66.8938 -77.8554 160.992 67.1833 -78.0001 160.011 67.6884 -78.4147 156.996 67.9795 - -86.2866 91.5121 71.941 -87.0984 91.4126 72.2989 -89.4314 91.1494 73.3702 -92.0223 90.9428 74.8762 -95.0145 90.8691 74.3417 -96.611 90.8302 74.0764 -97.9104 90.7819 73.8512 -99.0862 90.4824 73.5335 -102.37 89.953 72.9031 - -71.6117 104.63 83.3448 -70.9731 106.201 83.0274 -70.1649 108.405 82.6446 -69.5535 110.538 82.3844 -68.9269 113.019 82.1301 -69.8552 114.587 82.7025 -71.1654 117.024 83.5028 -72.3494 118.96 84.1649 -73.4834 120.613 84.7469 -74.3676 121.51 85.1141 -75.6483 122.63 85.5455 -76.9758 123.252 85.142 -81.7039 124.026 85 - -75.5857 183.215 108.611 -75.5789 183.197 108.646 -75.5652 183.162 108.713 -75.2835 182.848 109.515 - -56.2777 165.156 116.875 -57.2439 165.052 116.564 -57.4957 165.022 116.484 -58.7704 164.867 116.073 -59.8366 164.761 115.674 -60.7432 164.905 114.922 -65.2745 163.976 113.788 - -59.7953 104.835 123.029 -60.1185 106.612 123.226 -60.5099 108.413 123.502 -61.7244 113.687 124.33 -63.2676 118.529 124.945 - -117.575 84.4393 120.476 -118.145 84.8318 120.289 -118.938 85.617 118.995 -120.903 88.3144 116.109 - -191.646 82.1407 128.141 -189.874 82.6614 129.423 -186.81 83.5814 131.57 -185.567 84.1305 132.33 -183.662 85.1007 133.383 -181.529 86.1133 134.35 -178.653 86.4597 133.523 - -67.7233 179.217 121.751 -68.5052 178.942 121.484 -69.2559 178.643 121.33 -70.3307 178.241 121.163 -73.7819 178.355 118.272 - -104.419 96.1337 153.083 -104.417 96.2148 152.916 -104.724 97.7544 150.579 - -70.6218 115.037 175.9 -70.6411 115.096 175.875 -71.0189 116.138 175.328 -71.2814 116.84 174.941 -71.6723 117.852 174.326 -73.2648 119.515 172.736 -74.0039 120.279 172.003 -74.348 120.709 171.584 -74.8063 121.81 170.495 -77.3838 122.734 169.568 - -95.606 142.97 180.448 -97.8852 142.007 177.897 - -121.984 132.135 69.8458 -123.096 132.005 71.3436 -124.699 131.96 72.8582 -125.351 131.947 73.4661 -126.282 131.932 74.335 -128.913 131.996 76.5196 -130.561 132.163 77.5723 -133.032 132.505 78.6017 -134.6 132.726 79.2376 -135.927 132.879 79.4344 -139.671 133.2 79.1787 - -63.2676 118.529 124.945 -66.8928 121.8 125.14 -68.4283 123.11 125.203 -70.0249 124.546 125.255 -70.2913 124.799 125.256 -71.8896 126.336 125.242 -73.1014 127.529 125.174 -74.0631 128.488 125.103 -75.1523 129.933 124.598 -77.3069 131.484 124.371 - -102.836 158.339 152.718 -102.383 156.439 153.586 -102.148 151.2 154.516 -100.515 147.028 154.956 - -93.3338 175.4 119.843 -96.3426 172.993 118.861 -97.6247 172.439 118.114 -98.4465 172.205 117.616 - -93.3338 175.4 119.843 -92.6589 175.112 120.445 -91.7177 174.356 121.451 -89.5162 172.455 123.98 -85.5179 171.209 128.274 - -92.7994 92.9853 111.383 -95.8883 92.7141 110.964 -97.9353 92.552 110.668 -99.1637 92.414 110.501 -100.643 92.2564 110.305 -105.863 91.6136 109.516 - -204.379 99.5227 128.948 -200.388 102.067 133.851 - -83.2766 125.401 96.3324 -80.7928 130.01 97.0484 -79.7561 131.935 98.2504 -79.5274 132.399 98.4313 -78.913 133.681 98.9454 -77.7852 136.307 100.615 - -83.2766 125.401 96.3324 -81.962 125.383 89.8166 -81.7039 124.026 85 - -60.2184 141.923 110.96 -65.7557 138.894 109.509 - -102.37 89.953 72.9031 -105.116 90.7493 73.5158 -105.86 91.0468 73.7937 -108.779 92.0873 75.342 - -78.4147 156.996 67.9795 -78.6679 155.523 70.3109 -78.8451 154.547 72.2847 -78.9555 153.887 73.1561 -79.0495 153.323 73.8664 -79.1491 152.743 74.5967 -79.3014 151.856 75.7108 -79.4575 151.311 76.3675 -79.7234 150.331 77.4993 -80.1313 148.875 79.1721 -80.3282 144.293 84.7584 - -139.671 133.2 79.1787 -141.156 133.657 81.4758 -141.584 133.79 82.145 -141.94 133.914 82.7939 -142.398 134.066 83.5873 -143.671 134.419 85.2669 -144.723 134.715 86.6897 -145.903 135.06 88.3537 -147.384 135.497 90.4895 -148.417 135.804 92.0152 -149.255 136.051 93.1952 -151.082 136.571 95.2191 -152.834 137.101 97.8628 - -78.5962 158.884 111.503 -75.8372 160.375 112.438 -73.876 160.721 113.486 -71.4088 161.302 114.376 -67.4892 163.144 113.842 -65.2745 163.976 113.788 - -78.5962 158.884 111.503 -80.1904 153.948 113.773 -80.4862 151.972 114.928 -80.7639 150.556 115.736 -80.8499 148.33 116.299 -80.3308 145.31 115.445 - -121.308 90.1466 110.362 -115.522 91.7707 111.272 -111.353 91.5936 109.642 -105.863 91.6136 109.516 - -121.308 90.1466 110.362 -128.016 88.9504 106.464 -129.03 88.6759 105.818 -130.262 88.3392 105.092 -131.722 87.8825 104.212 -136.177 85.8858 102.65 - -121.308 90.1466 110.362 -120.903 88.3144 116.109 - -200.194 160.251 87.0208 -197.122 156.859 88.0642 -195.462 155.071 88.9655 -194.69 154.269 89.4532 -193.926 153.499 89.9147 -193.239 152.832 90.3166 -192.326 151.98 90.8258 -191.207 150.939 91.4489 -190.286 150.111 91.9389 -188.286 148.416 92.9241 -186.582 147.054 93.7021 -185.27 146.095 94.2338 -183.078 145.393 94.8614 -181.254 144.844 95.3606 -180.035 144.48 95.6921 -177.285 143.664 96.4358 -175.813 143.235 96.8293 -174.181 142.764 97.2618 -171.843 142.103 97.8707 -170.148 141.629 98.3073 -165.931 140.47 99.3846 -161.92 139.38 100.143 -160.714 139.054 99.69 -159.037 138.618 99.0589 -156.994 138.113 98.5701 -155.215 137.665 97.9346 -152.834 137.101 97.8628 - -77.3069 131.484 124.371 -77.8011 136.842 119.925 -78.6694 138.726 119.642 -80.619 142.64 119.533 - -80.3308 145.31 115.445 -78.7852 141.901 110.422 - -80.3308 145.31 115.445 -80.1472 142.876 117.329 -80.619 142.64 119.533 - -178.653 86.4597 133.523 -176.858 85.7053 130.906 -175.88 84.7912 128.761 -176.097 84.5352 126.866 - -67.2101 141.299 86.6562 -73.9272 140.856 90.4568 - -137.913 86.9824 90.8748 -136.676 87.0994 93.6931 -135.142 87.0835 96.0474 -134.246 87.1896 98.4681 -136.177 85.8858 102.65 - -78.7852 141.901 110.422 -76.3985 139.181 106.35 - -75.2835 182.848 109.515 -75.1767 182.295 110.575 -74.9107 181.426 112.338 -74.5579 180.158 114.885 -73.7819 178.355 118.272 - -100.866 96.8182 55.5209 -103.523 95.5641 59.8603 -104.308 95.2298 61.3552 -104.733 95.036 62.0998 -105.013 94.9114 62.6383 -106.451 94.2613 65.4832 -107.404 93.8369 66.9428 -108.241 93.4638 68.1883 -109.118 93.0328 69.8205 -110.461 92.2893 72.2288 - -100.866 96.8182 55.5209 -100.482 96.3446 51.1849 -100.086 96.2835 49.1402 -99.7205 96.234 47.7864 -98.4802 95.8123 42.5902 - -97.8852 142.007 177.897 -100.871 142.517 175.978 -102.611 142.864 174.9 -104.725 143.29 173.588 -105.706 143.415 172.755 -106.169 143.471 172.33 -107.164 143.594 171.179 -108.816 143.77 169.608 -107.08 143.438 161.908 -108.582 142.76 159.536 - -65.7557 138.894 109.509 -68.5713 139.132 108.973 -69.9468 139.2 108.555 -76.3985 139.181 106.35 - -143.789 82.3533 103.716 -147.069 81.3156 106.068 -147.936 81.1058 106.859 -149.228 80.8158 108.041 -149.897 80.6672 108.657 -151.652 80.2673 110.152 -154.164 79.8105 111.524 -156.897 79.359 113.066 -160.592 78.9805 115.411 -163.282 78.8926 117.329 -164.072 78.9211 117.954 -167.681 79.8606 121.603 -171.169 81.5775 125.86 -172.087 82.3002 126.498 -173.057 83.0278 126.968 -176.097 84.5352 126.866 - -143.789 82.3533 103.716 -140.925 83.5917 102.805 -139.854 84.1147 102.719 -138.756 84.6463 102.675 -136.177 85.8858 102.65 - -108.779 92.0873 75.342 -110.461 92.2893 72.2288 - -69.3503 138.067 158.082 -70.8593 140.397 158.559 - -73.9272 140.856 90.4568 -78.2128 142.331 87.8051 -80.3282 144.293 84.7584 - -73.9272 140.856 90.4568 -75.3867 139.578 93.3638 -75.7 138.444 95.7412 -75.8338 138.202 96.3378 -77.7852 136.307 100.615 - -83.2234 120.801 76.5165 -82.4246 120.156 73.4506 -80.677 121.173 72.1018 -80.3677 121.269 71.673 -79.4916 121.559 70.4854 -78.3154 121.628 67.8343 -77.5388 121.724 66.1089 -76.9422 121.792 64.793 -76.4322 121.994 63.6542 -75.8873 121.971 62.4044 -75.4683 121.981 61.4311 -74.7801 122.032 59.782 -73.9801 119.509 57.1376 - -83.2234 120.801 76.5165 -82.2348 122.635 80.8777 -82.0259 122.962 81.7245 -81.7039 124.026 85 - -83.2234 120.801 76.5165 -85.9082 120.537 79.1001 -87.9279 119.848 79.4764 -90.9187 118.57 78.7805 -92.1933 118.14 78.8521 -93.1586 117.814 78.9335 - -130.227 116.673 167.898 -133.124 119.598 166.151 -134.296 120.499 164.837 -137.462 121.764 162.517 - -108.582 142.76 159.536 -105.886 144.329 157.561 -104.232 145.167 156.896 -100.515 147.028 154.956 - -77.7852 136.307 100.615 -77.4771 137.823 103.34 -76.3985 139.181 106.35 - -70.8593 140.397 158.559 -71.7459 141.746 157.883 -72.7059 143.232 157.281 -75.1578 146.144 156.294 - diff --git a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.cpp b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.cpp deleted file mode 100644 index dbe59d5..0000000 --- a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define SKELETONSEGMENTMAPPER_CPP -#include - -#include -#include - -namespace meshskeletonizationplugin -{ -using namespace sofa::defaulttype; - -void registerSkeletonSegmentMapper(sofa::core::ObjectFactory* factory) -{ - factory->registerObjects(sofa::core::ObjectRegistrationData( - "Maps a previously-read skeleton (SkeletonReader) onto liver segments (e.g. " - "Couinaud I-VIII), using a per-mesh-vertex segment label and smoothing " - "per-branch by majority vote") - .add< SkeletonSegmentMapper >()); -} - -template class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonSegmentMapper; - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h deleted file mode 100644 index ed2b5e1..0000000 --- a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace sofa; -using namespace sofa::defaulttype; - -namespace meshskeletonizationplugin -{ - -template -class SkeletonSegmentMapper : public sofa::core::DataEngine -{ -public: - SOFA_CLASS(SOFA_TEMPLATE(SkeletonSegmentMapper, DataTypes), sofa::core::DataEngine); - - typedef typename DataTypes::Coord Coord; - typedef typename DataTypes::VecCoord VecCoord; - typedef typename Coord::value_type Real; - typedef type::Vec<3, Real> Vec3; - - /// The SkeletonReader whose graph should be segmented. If left unset, the - /// first SkeletonReader found in the context is used. - sofa::core::objectmodel::SingleLink< - SkeletonSegmentMapper, - SkeletonReader, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH | sofa::core::objectmodel::BaseLink::FLAG_STRONGLINK> - l_skeletonReader; - - /// One closed mesh per liver segment (the Couinaud collision meshes), in the same order as d_inSegmentNames. - sofa::core::objectmodel::MultiLink< - SkeletonSegmentMapper, - sofa::core::loader::MeshLoader, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH> - l_segmentMeshes; - - // Inputs - sofa::core::objectmodel::Data> d_inSegmentNames; ///< Human-readable name per entry of l_segmentMeshes, e.g. "II", "IVa", "VIII" - sofa::core::objectmodel::DataFileName d_outSegmentReportFilename; ///< Optional CSV report: id, x, y, z, segment name - - // Outputs - sofa::core::objectmodel::Data> d_outNodeSegments; ///< Segment index per skeleton node (into l_segmentMeshes/d_inSegmentNames, -1 = unknown), indexed like graph().nodes() - sofa::core::objectmodel::Data> d_outNodeSegmentNames; ///< Same as d_outNodeSegments, resolved to names ("unknown" if -1) - sofa::core::objectmodel::Data d_outSegmentCount; ///< Number of distinct segments found (excluding unknown) - - /// Direct access to the segmented graph, e.g. for another component to - /// query via getContext()->get>()->graph(). - const SkeletonGraph& graph() const { return m_graph; } - - void init() override; - void doUpdate() override; - void draw(const sofa::core::visual::VisualParams* vparams) override; - -private: - SkeletonSegmentMapper(); - virtual ~SkeletonSegmentMapper() = default; - /// Local working copy of the linked reader's graph, augmented with segment labels - SkeletonGraph m_graph; -}; - -#if !defined(SKELETONSEGMENTMAPPER_CPP) -extern template class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonSegmentMapper; -#endif - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl b/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl deleted file mode 100644 index 7e390e7..0000000 --- a/src/MeshSkeletonizationPlugin/SegmentMapping/SkeletonSegmentMapper.inl +++ /dev/null @@ -1,200 +0,0 @@ -#pragma once -#include - -// Reuses the Kernel/Polyhedron/Point typedefs already declared (at global -// scope) in MeshSkeletonization.h, so segment meshes are built the same way -// MeshSkeletonization builds its own polyhedron - and the shared closed-mesh -// query helper (also used by TumorCutPointSelector) so this doesn't keep its -// own private copy of the same CGAL polyhedron/AABB-tree plumbing. -#include -#include -#include -#include -#include -#include -#include -#include - -namespace meshskeletonizationplugin -{ - -template -SkeletonSegmentMapper::SkeletonSegmentMapper() - : l_skeletonReader(initLink("skeletonReader", - "SkeletonReader whose graph should be segmented; if empty, the first " - "SkeletonReader found in the scene is used")) - , l_segmentMeshes(initLink("segmentMeshes", - "One closed mesh loader per liver segment (e.g. Couinaud collision meshes), " - "in the same order as segmentNames")) - , d_inSegmentNames(initData(&d_inSegmentNames, "segmentNames", - "Human-readable name per entry of segmentMeshes, e.g. 'II', 'IVa', 'VIII'")) - , d_outSegmentReportFilename(initData(&d_outSegmentReportFilename, "outSegmentReportFilename", - "Optional path to export a CSV report: id, x, y, z, segment name")) - , d_outNodeSegments(initData(&d_outNodeSegments, "nodeSegments", - "Segment index per skeleton node (-1 if unknown), indexed like the graph's nodes")) - , d_outNodeSegmentNames(initData(&d_outNodeSegmentNames, "nodeSegmentNames", - "Same as nodeSegments, resolved to names ('unknown' if -1)")) - , d_outSegmentCount(initData(&d_outSegmentCount, 0, "segmentCount", - "Number of distinct segments found (excluding -1/unknown)")) -{ - addOutput(&d_outNodeSegments); - addOutput(&d_outNodeSegmentNames); - addOutput(&d_outSegmentCount); -} - -template -void SkeletonSegmentMapper::init() -{ - if (!l_skeletonReader) - { - l_skeletonReader.set(this->getContext()->template get>()); - } - if (!l_skeletonReader) - { - msg_error() << "No SkeletonReader found. Set 'skeletonReader' to a valid " - "component path, or add one earlier in the scene."; - } - - if (l_segmentMeshes.empty()) - { - msg_error() << "No segment meshes linked: set 'segmentMeshes' to a list of mesh " - "loader paths (one per liver segment)."; - } - else if (l_segmentMeshes.size() != d_inSegmentNames.getValue().size()) - { - msg_warning() << "segmentMeshes (" << l_segmentMeshes.size() << ") and segmentNames (" - << d_inSegmentNames.getValue().size() << ") have different sizes; " - "unnamed segments will be reported by index only."; - } - - setDirtyValue(); - update(); // compute eagerly, don't wait for something to read an output Data -} - -template -void SkeletonSegmentMapper::doUpdate() -{ - if (!l_skeletonReader || l_segmentMeshes.empty()) - return; - - // Work on our own copy of the reader's graph so we don't need a - // non-const accessor on SkeletonReader just for this. - m_graph = l_skeletonReader->graph(); - - // Build one point-in-mesh query per linked segment mesh. - std::vector segmentQueries(l_segmentMeshes.size()); - for (std::size_t i = 0; i < l_segmentMeshes.size(); ++i) - { - sofa::core::loader::MeshLoader* loader = l_segmentMeshes.get(i); - if (!loader) - continue; - - segmentQueries[i].buildFrom(loader->d_positions.getValue(), loader->d_triangles.getValue()); - } - - // Raw per-node label: which segment mesh contains this node, or (if none - // does) whichever segment mesh's surface is closest. - const auto& nodes = m_graph.nodes(); - std::vector raw(nodes.size(), -1); - - for (const SkeletonNode& node : nodes) - { - const auto& p = node.position(); - Point query(p[0], p[1], p[2]); - - int inside = -1; - for (std::size_t i = 0; i < segmentQueries.size() && inside == -1; ++i) - { - if (segmentQueries[i].insideTest && - (*segmentQueries[i].insideTest)(query) == CGAL::ON_BOUNDED_SIDE) - { - inside = static_cast(i); - } - } - - if (inside != -1) - { - raw[node.id()] = inside; - continue; - } - - // Fallback: closest segment surface. - double bestDist2 = std::numeric_limits::max(); - int bestSeg = -1; - for (std::size_t i = 0; i < segmentQueries.size(); ++i) - { - if (!segmentQueries[i].tree) - continue; - double d2 = CGAL::to_double(segmentQueries[i].tree->squared_distance(query)); - if (d2 < bestDist2) - { - bestDist2 = d2; - bestSeg = static_cast(i); - } - } - raw[node.id()] = bestSeg; - } - - m_graph.assignSegmentLabels(raw); - - const auto& names = d_inSegmentNames.getValue(); - - sofa::helper::WriteAccessor>> outSegments(d_outNodeSegments); - sofa::helper::WriteAccessor>> outSegmentNames(d_outNodeSegmentNames); - outSegments.resize(nodes.size()); - outSegmentNames.resize(nodes.size()); - - std::set distinct; - for (const SkeletonNode& n : nodes) - { - int seg = m_graph.segmentOf(n.id()); - outSegments[n.id()] = seg; - outSegmentNames[n.id()] = (seg >= 0 && seg < static_cast(names.size())) ? names[seg] : "unknown"; - if (seg != -1) - distinct.insert(seg); - } - - d_outSegmentCount.setValue(static_cast(distinct.size())); - - if (d_outSegmentReportFilename.isSet() && !d_outSegmentReportFilename.getFullPath().empty()) - { - m_graph.exportSegmentReportCSV(d_outSegmentReportFilename.getFullPath(), names); - } -} - -template -void SkeletonSegmentMapper::draw(const sofa::core::visual::VisualParams* vparams) -{ - if (!vparams->displayFlags().getShowBehaviorModels()) - return; - - static const std::vector palette = { - sofa::type::RGBAColor(0.90f, 0.10f, 0.10f, 1.0f), - sofa::type::RGBAColor(0.10f, 0.60f, 0.90f, 1.0f), - sofa::type::RGBAColor(0.20f, 0.80f, 0.20f, 1.0f), - sofa::type::RGBAColor(0.95f, 0.75f, 0.10f, 1.0f), - sofa::type::RGBAColor(0.60f, 0.20f, 0.80f, 1.0f), - sofa::type::RGBAColor(0.90f, 0.45f, 0.10f, 1.0f), - sofa::type::RGBAColor(0.10f, 0.80f, 0.70f, 1.0f), - sofa::type::RGBAColor(0.50f, 0.50f, 0.50f, 1.0f), - }; - static const sofa::type::RGBAColor unknownColor(0.7f, 0.7f, 0.7f, 1.0f); - - std::vector points; - std::vector colors; - points.reserve(m_graph.nodes().size()); - colors.reserve(m_graph.nodes().size()); - - for (const SkeletonNode& n : m_graph.nodes()) - { - const auto& p = n.position(); - points.emplace_back(p[0], p[1], p[2]); - - int seg = m_graph.segmentOf(n.id()); - colors.push_back(seg >= 0 ? palette[seg % palette.size()] : unknownColor); - } - - vparams->drawTool()->drawPoints(points, 6.0f, colors); -} - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.cpp b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.cpp deleted file mode 100644 index 88e59be..0000000 --- a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define SKELETONRESECTIONSIMULATOR_CPP -#include - -#include -#include - -namespace meshskeletonizationplugin -{ -using namespace sofa::defaulttype; - -void registerSkeletonResectionSimulator(sofa::core::ObjectFactory* factory) -{ - factory->registerObjects(sofa::core::ObjectRegistrationData( - "Simulates a vessel resection at one or more skeleton nodes and reports which " - "nodes and liver segments would lose blood supply, accounting for collateral " - "(loop/anastomosis) paths that bypass the cut") - .add< SkeletonResectionSimulator >()); -} - -template class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonResectionSimulator; - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h deleted file mode 100644 index cebec57..0000000 --- a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace sofa; -using namespace sofa::defaulttype; - -namespace meshskeletonizationplugin -{ - -/// Simulates a resection (vessel transection) at one or more skeleton node -/// ids and reports what it would devascularize: which skeleton nodes can no -/// longer reach the root (blood source) once the cut node(s) are removed -/// from the vessel graph, and which liver segments those nodes belong to. -/// -/// This is deliberately NOT a plain "everything below the cut" (subtree) -/// computation: a node distal to a cut can still be perfused if a -/// collateral/anastomosis connects it back to the root via a path that -/// avoids every cut node. See SkeletonGraph::simulateResection() for the -/// underlying reachability analysis. -/// -/// Typical use: link to an existing SkeletonSegmentMapper (so both the tree -/// and the segment labels are available), set d_inCutNodeIds to the node(s) -/// a candidate resection would sever, and read back d_outAffectedNodeIds / -/// d_outAffectedSegmentNames to see the consequence before committing to a -/// surgical plan. -template -class SkeletonResectionSimulator : public sofa::core::DataEngine -{ -public: - SOFA_CLASS(SOFA_TEMPLATE(SkeletonResectionSimulator, DataTypes), sofa::core::DataEngine); - - typedef typename DataTypes::Coord Coord; - typedef typename DataTypes::VecCoord VecCoord; - typedef typename Coord::value_type Real; - typedef type::Vec<3, Real> Vec3; - - /// The segmented skeleton to run resection scenarios against. If left - /// unset, the first SkeletonSegmentMapper found in the - /// context is used. - sofa::core::objectmodel::SingleLink< - SkeletonResectionSimulator, - SkeletonSegmentMapper, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH | sofa::core::objectmodel::BaseLink::FLAG_STRONGLINK> - l_segmentMapper; - - /// Optional: the actual visual object (e.g. OglModel) for each segment, - /// in the same order as the linked mapper's segmentNames. If set, their - /// "color" Data is pushed directly every draw() call - more reliable - /// than a scene-level Data link, since most visual models don't re-read - /// a linked color every frame on their own. - sofa::core::objectmodel::MultiLink< - SkeletonResectionSimulator, - sofa::core::objectmodel::BaseObject, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH> - l_segmentVisualModels; - - // Inputs - sofa::core::objectmodel::Data> d_inCutNodeIds; ///< Node id(s) where the vessel is (candidate) severed - sofa::core::objectmodel::Data d_activationDelay; ///< Seconds after simulation start before affected nodes/segments actually switch color (default 5.0); everything shows as perfused (green) until then - sofa::core::objectmodel::DataFileName d_outReportFilename; ///< Optional CSV report: id, x, y, z, segment, for affected nodes only - - // Outputs - sofa::core::objectmodel::Data> d_outAffectedNodeIds; ///< Node ids that would lose blood supply (includes the cut nodes themselves) - sofa::core::objectmodel::Data d_outAffectedNodeCount; ///< Convenience: size of d_outAffectedNodeIds - sofa::core::objectmodel::Data> d_outAffectedSegmentIds; ///< Distinct segment indices touched by the affected nodes - sofa::core::objectmodel::Data> d_outAffectedSegmentNames; ///< Same, resolved to names via the linked SkeletonSegmentMapper's segmentNames - sofa::core::objectmodel::Data> d_outSegmentColors; ///< One color per segment, same order as the linked mapper's segmentNames - green until activationDelay elapses, then red for affected segments. Link an OglModel's "color" to e.g. "@resectionSim.segmentColors[0]" per segment (index syntax support depends on SOFA version). - - void init() override; - void doUpdate() override; - void draw(const sofa::core::visual::VisualParams* vparams) override; - -private: - SkeletonResectionSimulator(); - virtual ~SkeletonResectionSimulator() = default; - - /// Recomputes m_colorsActive from the current simulation time and - /// refreshes d_outSegmentColors accordingly. Called every draw() so the - /// activationDelay threshold takes effect without needing an event - /// listener (and the Sofa.Simulation.Core dependency that would add). - void updateSegmentColors(); - - /// Local working copy of the linked mapper's (already segmented) graph. - SkeletonGraph m_graph; - - /// Whether affected nodes/segments should currently render as - /// affected (red/black) rather than perfused (green) - false until - /// d_activationDelay seconds have elapsed since simulation start. - bool m_colorsActive{ false }; - - /// Guards so diagnostic messages below are logged once, not every frame. - bool m_loggedVisualModelLinkStatus{ false }; - std::vector m_loggedMissingColorData; -}; - -#if !defined(SKELETONRESECTIONSIMULATOR_CPP) -extern template class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonResectionSimulator; -#endif - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl b/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl deleted file mode 100644 index 71af6e3..0000000 --- a/src/MeshSkeletonizationPlugin/SkeletonResection/SkeletonResectionSimulator.inl +++ /dev/null @@ -1,292 +0,0 @@ -#pragma once -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace meshskeletonizationplugin -{ - -template -SkeletonResectionSimulator::SkeletonResectionSimulator() - : l_segmentMapper(initLink("segmentMapper", - "Segmented skeleton to run resection scenarios against; if empty, the first " - "SkeletonSegmentMapper found in the scene is used")) - , l_segmentVisualModels(initLink("segmentVisualModels", - "Optional: the visual object (e.g. OglModel) for each segment, same order as " - "segmentNames. Its 'color' Data is pushed directly every frame - more reliable " - "than linking a color attribute to segmentColors[i] in the scene.")) - , d_inCutNodeIds(initData(&d_inCutNodeIds, "cutNodeIds", - "Node id(s) where the vessel is (candidate) severed")) - , d_activationDelay(initData(&d_activationDelay, 5.0, "activationDelay", - "Seconds after simulation start before affected nodes/segments actually switch " - "color to red/black; everything renders as perfused (green) until then")) - , d_outReportFilename(initData(&d_outReportFilename, "outReportFilename", - "Optional path to export a CSV report (id, x, y, z, segment) of the affected nodes")) - , d_outAffectedNodeIds(initData(&d_outAffectedNodeIds, "affectedNodeIds", - "Node ids that would lose blood supply (includes the cut nodes themselves)")) - , d_outAffectedNodeCount(initData(&d_outAffectedNodeCount, 0, "affectedNodeCount", - "Convenience: size of affectedNodeIds")) - , d_outAffectedSegmentIds(initData(&d_outAffectedSegmentIds, "affectedSegmentIds", - "Distinct segment indices touched by the affected nodes")) - , d_outAffectedSegmentNames(initData(&d_outAffectedSegmentNames, "affectedSegmentNames", - "Same as affectedSegmentIds, resolved to names")) - , d_outSegmentColors(initData(&d_outSegmentColors, "segmentColors", - "One color per segment (same order as the linked mapper's segmentNames): green " - "until activationDelay elapses, then red for affected segments. Link an OglModel's " - "'color' Data to e.g. '@resectionSim.segmentColors[0]' for the first segment.")) -{ - addInput(&d_inCutNodeIds); - addOutput(&d_outAffectedNodeIds); - addOutput(&d_outAffectedNodeCount); - addOutput(&d_outAffectedSegmentIds); - addOutput(&d_outAffectedSegmentNames); - addOutput(&d_outSegmentColors); -} - -template -void SkeletonResectionSimulator::init() -{ - if (!l_segmentMapper) - { - l_segmentMapper.set(this->getContext()->template get>()); - } - if (!l_segmentMapper) - { - msg_error() << "No SkeletonSegmentMapper found. Set 'segmentMapper' to a " - "valid component path, or add one earlier in the scene."; - } - - setDirtyValue(); - update(); // compute eagerly, don't wait for something to read an output Data -} - -template -void SkeletonResectionSimulator::doUpdate() -{ - if (!l_segmentMapper) - return; - - // Work on our own copy of the mapper's (already segmented) graph so we - // can re-run this per candidate cut without touching the mapper. - m_graph = l_segmentMapper->graph(); - - const auto& cutIds = d_inCutNodeIds.getValue(); - std::vector affected = m_graph.simulateResection(cutIds); - std::vector segments = m_graph.affectedSegments(affected); - - const auto& segmentNames = l_segmentMapper->d_inSegmentNames.getValue(); - std::vector segmentNameStrs; - segmentNameStrs.reserve(segments.size()); - for (int seg : segments) - segmentNameStrs.push_back(seg >= 0 && seg < static_cast(segmentNames.size()) - ? segmentNames[seg] : "unknown"); - - d_outAffectedNodeIds.setValue(affected); - d_outAffectedNodeCount.setValue(static_cast(affected.size())); - d_outAffectedSegmentIds.setValue(segments); - d_outAffectedSegmentNames.setValue(segmentNameStrs); - - updateSegmentColors(); // initial colors; draw() keeps these fresh every frame after this - - if (d_outReportFilename.isSet() && !d_outReportFilename.getFullPath().empty()) - { - std::ofstream out(d_outReportFilename.getFullPath(), std::ofstream::out | std::ofstream::trunc); - out << "# cutNodeIds=" << cutIds.size() - << ",affectedNodeCount=" << affected.size() - << ",affectedSegmentCount=" << segments.size() - << ",affectedSegments="; - for (std::size_t i = 0; i < segmentNameStrs.size(); ++i) - out << (i ? ";" : "") << segmentNameStrs[i]; - out << "\n"; - out << "id,x,y,z,segment\n"; - out << std::fixed << std::setprecision(6); - for (int id : affected) - { - const SkeletonNode* n = m_graph.node(id); - if (!n) - continue; - const auto& p = n->position(); - int seg = m_graph.segmentOf(id); - std::string segName = (seg >= 0 && seg < static_cast(segmentNames.size())) ? segmentNames[seg] : "unknown"; - out << id << "," << p[0] << "," << p[1] << "," << p[2] << "," << segName << "\n"; - } - } -} - -template -void SkeletonResectionSimulator::updateSegmentColors() -{ - // Re-checked every draw() call since there's no cheap event hook here - // for "time crossed the threshold" - this is a handful of colors, so - // recomputing it every frame is negligible. - static const sofa::type::RGBAColor safeColor(0.20f, 0.80f, 0.20f, 1.0f); - static const sofa::type::RGBAColor affectedColor(0.90f, 0.10f, 0.10f, 1.0f); - - m_colorsActive = (this->getContext()->getTime() >= d_activationDelay.getValue()); - - if (!l_segmentMapper) - return; - - // --- Diagnostics: run once, so we can see exactly what's wrong instead - // of silently doing nothing. - if (!m_loggedVisualModelLinkStatus) - { - m_loggedVisualModelLinkStatus = true; - if (l_segmentVisualModels.empty()) - { - msg_warning() << "segmentVisualModels is empty: no visual objects linked, so no " - "mesh color will ever change. Check the 'segmentVisualModels' " - "attribute/paths in the scene."; - } - else - { - m_loggedMissingColorData.assign(l_segmentVisualModels.size(), false); - for (std::size_t i = 0; i < l_segmentVisualModels.size(); ++i) - { - sofa::core::objectmodel::BaseObject* obj = l_segmentVisualModels.get(i); - if (!obj) - { - msg_warning() << "segmentVisualModels[" << i << "] did not resolve to any object " - "(bad path?)."; - continue; - } - msg_info() << "segmentVisualModels[" << i << "] resolved to '" << obj->getName() - << "' (" << obj->getClassName() << ")."; - } - } - } - - const auto& segmentNames = l_segmentMapper->d_inSegmentNames.getValue(); - const auto& segments = d_outAffectedSegmentIds.getValue(); - std::set affectedSegSet(segments.begin(), segments.end()); - - sofa::helper::WriteAccessor>> colors(d_outSegmentColors); - colors.resize(segmentNames.size()); - for (std::size_t i = 0; i < segmentNames.size(); ++i) - colors[i] = (m_colorsActive && affectedSegSet.count(static_cast(i))) ? affectedColor : safeColor; - - // Push directly into each linked visual model's own "color" Data, if - // provided - this is what actually makes the mesh repaint, since a - // passive scene-level Data link to segmentColors[i] isn't guaranteed to - // be re-read every frame by the visual model itself. - for (std::size_t i = 0; i < l_segmentVisualModels.size() && i < colors.size(); ++i) - { - sofa::core::objectmodel::BaseObject* obj = l_segmentVisualModels.get(i); - if (!obj) - continue; - - // OglModel doesn't expose a plain "color" Data - color lives inside - // its "material" Data (a Material struct: name + ambient/diffuse/ - // specular/emissive/shininess). Rather than guess that struct's - // exact serialization format, round-trip it: read the CURRENT valid - // string, patch only the "Diffuse r g b a" tokens, write it - // back - preserves everything else regardless of exact format. - sofa::core::objectmodel::BaseData* materialData = obj->findData("material"); - if (!materialData) - { - if (i < m_loggedMissingColorData.size() && !m_loggedMissingColorData[i]) - { - m_loggedMissingColorData[i] = true; - std::ostringstream fields; - for (sofa::core::objectmodel::BaseData* d : obj->getDataFields()) - fields << d->getName() << " "; - msg_warning() << "'" << obj->getName() << "' (" << obj->getClassName() - << ") has no Data named 'material' either. Its actual Data fields are: " - << fields.str(); - } - continue; - } - - std::istringstream iss(materialData->getValueString()); - std::vector tokens{ std::istream_iterator(iss), std::istream_iterator() }; - - auto diffuseIt = std::find(tokens.begin(), tokens.end(), "Diffuse"); - if (diffuseIt == tokens.end() || std::distance(diffuseIt, tokens.end()) < 6) - { - if (i < m_loggedMissingColorData.size() && !m_loggedMissingColorData[i]) - { - m_loggedMissingColorData[i] = true; - msg_warning() << "Could not find a 'Diffuse r g b a' pattern in '" - << obj->getName() << "'s material string: " << materialData->getValueString(); - } - continue; - } - - const auto& c = colors[i]; - - if (i < m_loggedMissingColorData.size() && !m_loggedMissingColorData[i]) - { - // One-time sanity check: print exactly what tokens we're about - // to overwrite, so the "Diffuse r g b a" assumption can - // be visually confirmed against this SOFA build's real format - // instead of trusted blindly. - m_loggedMissingColorData[i] = true; - std::ostringstream window; - for (auto it = diffuseIt; it != tokens.end() && it != diffuseIt + 6; ++it) - window << "'" << *it << "' "; - msg_info() << "'" << obj->getName() << "' Diffuse token window before patch: " << window.str(); - } - - *(diffuseIt + 1) = "1"; // force useDiffuse on, so our color is actually applied - std::ostringstream rs, gs, bs, as; - rs << c[0]; gs << c[1]; bs << c[2]; as << c[3]; - *(diffuseIt + 2) = rs.str(); - *(diffuseIt + 3) = gs.str(); - *(diffuseIt + 4) = bs.str(); - *(diffuseIt + 5) = as.str(); - - std::ostringstream newStr; - for (std::size_t k = 0; k < tokens.size(); ++k) - newStr << (k ? " " : "") << tokens[k]; - materialData->read(newStr.str()); - } -} - -template -void SkeletonResectionSimulator::draw(const sofa::core::visual::VisualParams* vparams) -{ - updateSegmentColors(); // keeps segmentColors (and m_colorsActive) current every frame - - if (!vparams->displayFlags().getShowBehaviorModels()) - return; - - static const sofa::type::RGBAColor perfusedColor(1.0f, 1.0f, 1.0f, 1.0f); - static const sofa::type::RGBAColor affectedColor(0.0f, 0.0f, 0.0f, 1.0f); - static const sofa::type::RGBAColor cutColor(0.0f, 0.0f, 0.0f, 1.0f); - const auto& affected = d_outAffectedNodeIds.getValue(); - std::set affectedSet(affected.begin(), affected.end()); - std::set cutSet(d_inCutNodeIds.getValue().begin(), d_inCutNodeIds.getValue().end()); - - std::vector points; - std::vector colors; - points.reserve(m_graph.nodes().size()); - colors.reserve(m_graph.nodes().size()); - - for (const SkeletonNode& n : m_graph.nodes()) - { - const auto& p = n.position(); - points.emplace_back(p[0], p[1], p[2]); - - if (!m_colorsActive) - colors.push_back(perfusedColor); // before activationDelay: everything shows as perfused - else if (cutSet.count(n.id())) - colors.push_back(cutColor); - else if (affectedSet.count(n.id())) - colors.push_back(affectedColor); - else - colors.push_back(perfusedColor); - } - - vparams->drawTool()->drawPoints(points, 7.0f, colors); -} - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp deleted file mode 100644 index 472643a..0000000 --- a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define TUMORCUTPOINTSELECTOR_CPP -#include - -#include -#include - -namespace meshskeletonizationplugin -{ -using namespace sofa::defaulttype; - -void registerTumorCutPointSelector(sofa::core::ObjectFactory* factory) -{ - factory->registerObjects(sofa::core::ObjectRegistrationData( - "Case 1 tumor-driven cut point selection: splits a (possibly multi-tumor) mesh " - "into its separate tumors and finds which skeleton node(s) each one directly " - "touches, via bounding-box pre-filtering plus a real point-in-mesh test") - .add< TumorCutPointSelector >()); -} - -template class SOFA_MESHSKELETONIZATIONPLUGIN_API TumorCutPointSelector; - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h deleted file mode 100644 index b58d56b..0000000 --- a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.h +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -using namespace sofa; -using namespace sofa::defaulttype; - -namespace meshskeletonizationplugin -{ - -/// Case 1 of tumor-driven cut point selection: for each tumor that directly -/// touches the vessel skeleton, find which skeleton node(s) it touches, so -/// those can be fed straight into SkeletonResectionSimulator.cutNodeIds. -/// -/// Tumors are provided as a list of already-separate mesh loaders (one per -/// tumor) - same MultiLink pattern SkeletonSegmentMapper uses for its 8 -/// segment meshes. If your tumors currently live merged in a single file, -/// split them into individual meshes upstream of this component (e.g. with -/// TumorSet::splitConnectedComponents(), kept available separately) before -/// loading each one with its own MeshOBJLoader. -/// -/// For each tumor / skeleton node pair: a cheap bounding-box check first -/// discards nodes nowhere near that tumor (broad phase), then a real -/// point-in-mesh test (CGAL::Side_of_triangle_mesh, same approach as -/// SkeletonSegmentMapper) decides whether the node is actually inside the -/// tumor volume (narrow phase). The bounding box alone is not used as the -/// decision - a non-convex or elongated tumor's box can contain a lot of -/// space the tumor doesn't actually occupy, which would false-positive. -/// -/// Tumors that touch no skeleton node at all are reported separately -/// (outUntouchedTumorIds) - those are candidates for Case 2 (nearest node -/// in the tumor's segment), not yet implemented here. -template -class TumorCutPointSelector : public sofa::core::DataEngine -{ -public: - SOFA_CLASS(SOFA_TEMPLATE(TumorCutPointSelector, DataTypes), sofa::core::DataEngine); - - typedef typename DataTypes::Coord Coord; - typedef typename DataTypes::VecCoord VecCoord; - typedef typename Coord::value_type Real; - typedef type::Vec<3, Real> Vec3; - - /// One mesh loader per tumor, already separate (no merged-file splitting - /// is done by this component). - sofa::core::objectmodel::MultiLink< - TumorCutPointSelector, - sofa::core::loader::MeshLoader, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH> - l_tumorMeshes; - - /// The segmented skeleton to test tumor(s) against. If left unset, the - /// first SkeletonSegmentMapper found in the context is used. - sofa::core::objectmodel::SingleLink< - TumorCutPointSelector, - SkeletonSegmentMapper, - sofa::core::objectmodel::BaseLink::FLAG_STOREPATH | sofa::core::objectmodel::BaseLink::FLAG_STRONGLINK> - l_segmentMapper; - - // Inputs - sofa::core::objectmodel::Data> d_inTumorNames; ///< Optional, same order as l_tumorMeshes, e.g. "tumor 1", "tumor 2" - purely for readable output/reports - - // Outputs - sofa::core::objectmodel::Data d_outTumorCount; ///< Number of linked tumors - sofa::core::objectmodel::Data> d_outCutNodeIds; ///< Union of every touching node across all tumors - link this straight into SkeletonResectionSimulator.cutNodeIds - sofa::core::objectmodel::Data> d_outTouchingTumorIndex; ///< Same length/order as outCutNodeIds: which tumor (0-based, into l_tumorMeshes) each entry belongs to - sofa::core::objectmodel::Data> d_outUntouchedTumorIds; ///< 0-based indices of tumors touching no skeleton node at all - - void init() override; - void doUpdate() override; - void draw(const sofa::core::visual::VisualParams* vparams) override; - -private: - TumorCutPointSelector(); - virtual ~TumorCutPointSelector() = default; - - /// One linked tumor's geometry (bbox + CGAL point-in-mesh query) plus - /// which skeleton nodes it was found to touch (filled by doUpdate(), - /// used by draw()). - struct TumorQuery - { - std::array bboxMin{}; - std::array bboxMax{}; - cgalutils::ClosedMeshQuery query; - std::vector touchingNodeIds; - }; - - /// Rebuilds bbox + ClosedMeshQuery for every linked tumor mesh. Pure - /// geometry prep, no skeleton involved yet. - void rebuildTumors(); - - std::vector m_tumors; - SkeletonGraph m_graph; ///< local copy of the linked mapper's graph, for node positions -}; - -#if !defined(TUMORCUTPOINTSELECTOR_CPP) -extern template class SOFA_MESHSKELETONIZATIONPLUGIN_API TumorCutPointSelector; -#endif - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl b/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl deleted file mode 100644 index 1b320a5..0000000 --- a/src/MeshSkeletonizationPlugin/TumorMapping/TumorCutPointSelector.inl +++ /dev/null @@ -1,205 +0,0 @@ -#pragma once -#include - -#include -#include -#include - -#include -#include - -namespace meshskeletonizationplugin -{ - -template -TumorCutPointSelector::TumorCutPointSelector() - : l_tumorMeshes(initLink("tumorMeshes", - "One mesh loader per tumor, already separate")) - , l_segmentMapper(initLink("segmentMapper", - "Segmented skeleton to test the tumor(s) against; if empty, the first " - "SkeletonSegmentMapper found in the scene is used")) - , d_inTumorNames(initData(&d_inTumorNames, "tumorNames", - "Optional, same order as tumorMeshes, e.g. 'tumor 1', 'tumor 2' - for readable output/reports")) - , d_outTumorCount(initData(&d_outTumorCount, 0, "tumorCount", - "Number of linked tumors")) - , d_outCutNodeIds(initData(&d_outCutNodeIds, "cutNodeIds", - "Union of every touching node across all tumors - link this into SkeletonResectionSimulator.cutNodeIds")) - , d_outTouchingTumorIndex(initData(&d_outTouchingTumorIndex, "touchingTumorIndex", - "Same length/order as cutNodeIds: which tumor (0-based, into tumorMeshes) each entry belongs to")) - , d_outUntouchedTumorIds(initData(&d_outUntouchedTumorIds, "untouchedTumorIds", - "0-based indices of tumors touching no skeleton node at all")) -{ - addOutput(&d_outTumorCount); - addOutput(&d_outCutNodeIds); - addOutput(&d_outTouchingTumorIndex); - addOutput(&d_outUntouchedTumorIds); -} - -template -void TumorCutPointSelector::init() -{ - if (!l_segmentMapper) - l_segmentMapper.set(this->getContext()->template get>()); - - if (l_tumorMeshes.empty()) - msg_error() << "No tumor meshes linked. Set 'tumorMeshes' to a list of MeshLoader component paths."; - if (!l_segmentMapper) - msg_error() << "No SkeletonSegmentMapper found. Set 'segmentMapper' to a " - "valid component path, or add one earlier in the scene."; - else if (!l_tumorMeshes.empty() && d_inTumorNames.getValue().size() != l_tumorMeshes.size()) - msg_warning() << "tumorMeshes (" << l_tumorMeshes.size() << ") and tumorNames (" - << d_inTumorNames.getValue().size() << ") have different sizes; " - "unnamed tumors will be reported by index only."; - - setDirtyValue(); - update(); // compute eagerly, don't wait for something to read an output Data -} - -template -void TumorCutPointSelector::rebuildTumors() -{ - m_tumors.clear(); - m_tumors.resize(l_tumorMeshes.size()); - - for (std::size_t i = 0; i < l_tumorMeshes.size(); ++i) - { - sofa::core::loader::MeshLoader* loader = l_tumorMeshes.get(i); - if (!loader) - continue; - - const auto& positions = loader->d_positions.getValue(); - const auto& triangles = loader->d_triangles.getValue(); - - TumorQuery& tumor = m_tumors[i]; - tumor.bboxMin = { std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; - tumor.bboxMax = { -std::numeric_limits::max(), -std::numeric_limits::max(), -std::numeric_limits::max() }; - for (const auto& v : positions) - { - for (int d = 0; d < 3; ++d) - { - tumor.bboxMin[d] = std::min(tumor.bboxMin[d], static_cast(v[d])); - tumor.bboxMax[d] = std::max(tumor.bboxMax[d], static_cast(v[d])); - } - } - - tumor.query.buildFrom(positions, triangles); - } -} - -template -void TumorCutPointSelector::doUpdate() -{ - if (l_tumorMeshes.empty() || !l_segmentMapper) - return; - - rebuildTumors(); - m_graph = l_segmentMapper->graph(); - - std::vector cutNodeIds; - std::vector touchingTumorIndex; - std::vector tumorTouched(m_tumors.size(), false); - - for (const SkeletonNode& node : m_graph.nodes()) - { - const auto& p = node.position(); - - for (std::size_t t = 0; t < m_tumors.size(); ++t) - { - TumorQuery& tumor = m_tumors[t]; - - // Broad phase: cheap bounding-box rejection. - bool insideBBox = true; - for (int d = 0; d < 3; ++d) - { - if (p[d] < tumor.bboxMin[d] || p[d] > tumor.bboxMax[d]) - { - insideBBox = false; - break; - } - } - if (!insideBBox) - continue; - - // Narrow phase: real point-in-mesh test against the tumor surface. - if (!tumor.query.insideTest) - continue; - - Point query(p[0], p[1], p[2]); - if ((*tumor.query.insideTest)(query) == CGAL::ON_BOUNDED_SIDE) - { - cutNodeIds.push_back(node.id()); - touchingTumorIndex.push_back(static_cast(t)); - tumorTouched[t] = true; - tumor.touchingNodeIds.push_back(node.id()); - } - } - } - - std::vector untouchedTumorIds; - for (std::size_t t = 0; t < m_tumors.size(); ++t) - if (!tumorTouched[t]) - untouchedTumorIds.push_back(static_cast(t)); - - d_outTumorCount.setValue(static_cast(m_tumors.size())); - d_outCutNodeIds.setValue(cutNodeIds); - d_outTouchingTumorIndex.setValue(touchingTumorIndex); - d_outUntouchedTumorIds.setValue(untouchedTumorIds); - - if (!untouchedTumorIds.empty()) - { - msg_warning() << untouchedTumorIds.size() << " of " << m_tumors.size() - << " tumor(s) touch no skeleton node directly (Case 2 - nearest node " - "in the tumor's segment - is not yet implemented)."; - } -} - -template -void TumorCutPointSelector::draw(const sofa::core::visual::VisualParams* vparams) -{ - if (!vparams->displayFlags().getShowBehaviorModels()) - return; - - static const sofa::type::RGBAColor tumorBoxColor(1.0f, 1.0f, 1.0f, 1.0f); - static const sofa::type::RGBAColor touchingNodeColor(0.0f, 0.0f, 0.0f, 1.0f); - - // Tumor bounding boxes, wireframe - a visual sanity check that the - // bbox broad-phase looks right. - for (const TumorQuery& tumor : m_tumors) - { - const auto& lo = tumor.bboxMin; - const auto& hi = tumor.bboxMax; - std::vector corners = { - {lo[0], lo[1], lo[2]}, {hi[0], lo[1], lo[2]}, {hi[0], hi[1], lo[2]}, {lo[0], hi[1], lo[2]}, - {lo[0], lo[1], hi[2]}, {hi[0], lo[1], hi[2]}, {hi[0], hi[1], hi[2]}, {lo[0], hi[1], hi[2]}, - }; - static const int edges[12][2] = { - {0,1},{1,2},{2,3},{3,0}, {4,5},{5,6},{6,7},{7,4}, {0,4},{1,5},{2,6},{3,7} - }; - std::vector lines; - lines.reserve(24); - for (auto& e : edges) - { - lines.push_back(corners[e[0]]); - lines.push_back(corners[e[1]]); - } - vparams->drawTool()->drawLines(lines, 1.5f, tumorBoxColor); - } - - // Touching skeleton nodes, highlighted. - std::vector touchingPoints; - for (const TumorQuery& tumor : m_tumors) - { - for (int id : tumor.touchingNodeIds) - { - const SkeletonNode* n = m_graph.node(id); - if (!n) - continue; - const auto& p = n->position(); - touchingPoints.emplace_back(p[0], p[1], p[2]); - } - } - if (!touchingPoints.empty()) - vparams->drawTool()->drawPoints(touchingPoints, 9.0f, touchingNodeColor); -} - -} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp deleted file mode 100644 index 6ab44a9..0000000 --- a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "TumorSet.h" - -#include -#include - -namespace meshskeletonizationplugin -{ - -int TumorSet::find(std::vector& parent, int x) -{ - while (parent[x] != x) - { - parent[x] = parent[parent[x]]; // path halving - x = parent[x]; - } - return x; -} - -void TumorSet::unite(std::vector& parent, int a, int b) -{ - int ra = find(parent, a); - int rb = find(parent, b); - if (ra != rb) - parent[ra] = rb; -} - -std::vector TumorSet::splitConnectedComponents( - const std::vector>& vertices, - const std::vector>& triangles) -{ - std::vector result; - if (vertices.empty()) - return result; - - // Union-find over vertices, connected by triangle edges. - std::vector parent(vertices.size()); - for (std::size_t i = 0; i < parent.size(); ++i) - parent[i] = static_cast(i); - - for (const auto& tri : triangles) - { - unite(parent, tri[0], tri[1]); - unite(parent, tri[1], tri[2]); - unite(parent, tri[2], tri[0]); - } - - // Group vertices by root, assigning each distinct root a stable, - // deterministic tumor id in first-seen order. - std::map rootToTumorId; // union-find root -> tumor index - std::vector> tumorVertexIds; // tumor index -> original vertex ids - - for (std::size_t i = 0; i < vertices.size(); ++i) - { - int root = find(parent, static_cast(i)); - auto it = rootToTumorId.find(root); - int tumorId; - if (it == rootToTumorId.end()) - { - tumorId = static_cast(tumorVertexIds.size()); - rootToTumorId[root] = tumorId; - tumorVertexIds.emplace_back(); - } - else - { - tumorId = it->second; - } - tumorVertexIds[tumorId].push_back(static_cast(i)); - } - - // Build each Tumor: remap global vertex ids to local (0..n-1) ids, - // carry over only the triangles fully inside this component, and - // compute bbox/centroid while we're at it. - result.resize(tumorVertexIds.size()); - std::vector globalToLocal(vertices.size(), -1); - - for (std::size_t t = 0; t < tumorVertexIds.size(); ++t) - { - Tumor& tumor = result[t]; - tumor.id = static_cast(t); - - const auto& ids = tumorVertexIds[t]; - tumor.vertices.reserve(ids.size()); - - std::array bmin{ std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; - std::array bmax{ std::numeric_limits::lowest(), std::numeric_limits::lowest(), std::numeric_limits::lowest() }; - std::array sum{ 0.0, 0.0, 0.0 }; - - for (int localIdx = 0; localIdx < static_cast(ids.size()); ++localIdx) - { - int globalIdx = ids[localIdx]; - globalToLocal[globalIdx] = localIdx; - - const auto& p = vertices[globalIdx]; - tumor.vertices.push_back(p); - - for (int k = 0; k < 3; ++k) - { - bmin[k] = std::min(bmin[k], p[k]); - bmax[k] = std::max(bmax[k], p[k]); - sum[k] += p[k]; - } - } - - tumor.bboxMin = bmin; - tumor.bboxMax = bmax; - for (int k = 0; k < 3; ++k) - tumor.centroid[k] = sum[k] / static_cast(ids.size()); - } - - for (const auto& tri : triangles) - { - int root = find(parent, tri[0]); - int tumorId = rootToTumorId.at(root); - result[tumorId].triangles.push_back({ - globalToLocal[tri[0]], - globalToLocal[tri[1]], - globalToLocal[tri[2]] - }); - } - - return result; -} - -} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h b/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h deleted file mode 100644 index 6e1b7dd..0000000 --- a/src/MeshSkeletonizationPlugin/TumorMapping/TumorSet.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace meshskeletonizationplugin -{ - -/// One connected tumor extracted from a (possibly merged) tumor mesh. -/// Vertex/triangle indices are LOCAL to this tumor (remapped from the -/// original merged mesh), so each Tumor is a fully self-contained mesh. -struct Tumor -{ - std::vector> vertices; - std::vector> triangles; - - std::array bboxMin{ 0.0, 0.0, 0.0 }; - std::array bboxMax{ 0.0, 0.0, 0.0 }; - std::array centroid{ 0.0, 0.0, 0.0 }; - - /// Index of this tumor's original connected component in the source - /// mesh (0, 1, 2, ...), stable/deterministic for a given input so it - /// can be used as a display label ("tumor 0", "tumor 1", ...). - int id{ -1 }; -}; - -/// Splits a single mesh that may contain several disjoint tumors merged -/// into one file (common when tumors are exported together from a -/// segmentation tool) into one Tumor per connected component, each with -/// its own bounding box and centroid precomputed. -/// -/// Two vertices are considered connected if some triangle has an edge -/// between them; a tumor is a maximal set of vertices connected this way. -/// No SOFA/CGAL dependency, so it's usable and testable independently of -/// the plugin's SOFA components. -class TumorSet -{ -public: - static std::vector splitConnectedComponents( - const std::vector>& vertices, - const std::vector>& triangles); - -private: - static int find(std::vector& parent, int x); - static void unite(std::vector& parent, int a, int b); -}; - -} // namespace meshskeletonizationplugin \ No newline at end of file diff --git a/src/MeshSkeletonizationPlugin/init.cpp b/src/MeshSkeletonizationPlugin/init.cpp index 446b341..ab4c9c2 100644 --- a/src/MeshSkeletonizationPlugin/init.cpp +++ b/src/MeshSkeletonizationPlugin/init.cpp @@ -30,9 +30,6 @@ namespace meshskeletonizationplugin extern void registerMeshSkeletonization(sofa::core::ObjectFactory* factory); //extern void registerSkeletonizationLoader(sofa::core::ObjectFactory* factory); extern void registerSkeletonReader(sofa::core::ObjectFactory* factory); -extern void registerSkeletonSegmentMapper(sofa::core::ObjectFactory* factory); -extern void registerSkeletonResectionSimulator(sofa::core::ObjectFactory* factory); -extern void registerTumorCutPointSelector(sofa::core::ObjectFactory* factory); //Here are just several convenient functions to help users know what the plugin contains extern "C" { @@ -86,9 +83,6 @@ void registerObjects(sofa::core::ObjectFactory* factory) registerMeshSkeletonization(factory); // registerSkeletonizationLoader(factory); registerSkeletonReader(factory); - registerSkeletonSegmentMapper(factory); - registerSkeletonResectionSimulator(factory); - registerTumorCutPointSelector(factory); } } From dd30ca70cb3d65232b0de08a74709c4fb23a5451 Mon Sep 17 00:00:00 2001 From: erik pernod Date: Tue, 15 Sep 2026 18:14:38 +0200 Subject: [PATCH 3/3] Apply batched suggestions from code review Co-authored-by: erik pernod --- .../SkeletonGraph/SkeletonGraph.cpp | 2 +- .../SkeletonGraph/SkeletonGraph.h | 12 +++--------- .../SkeletonGraph/SkeletonReader.inl | 6 +----- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp index 159e877..256cb1e 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.cpp @@ -747,4 +747,4 @@ std::vector SkeletonGraph::affectedSegments(const std::vector& affecte return std::vector(segments.begin(), segments.end()); } -} // namespace meshskeletonizationplugin \ No newline at end of file +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h index 9703ebf..f621e0c 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonGraph.h @@ -38,14 +38,8 @@ class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonGraph void buildTree(const std::array& entryPoint); void buildTree(int rootId); - /// Picks a root automatically, with no entry point needed: the node - /// belonging to the LARGEST connected component of the raw connectivity - /// graph. Real vessel skeletonization output is typically one dominant - /// tree plus a handful of small disconnected fragments (noise); this - /// guarantees the tree is rooted in the dominant structure instead of - /// risking a tiny isolated fragment, which is easy to hit by accident - /// with a naive nearest-point-to-some-coordinate pick (e.g. a caller - /// falling back to the origin when no real entry point is known). + /// Picks a root automatically, with no entry point needed: the node belonging to the LARGEST connected component of the raw connectivity graph. + /// This guarantees the tree is rooted in the dominant structure instead of risking a tiny isolated fragment. void buildTreeAutoRoot(); /// Best-effort correspondence between each skeleton node and the closest @@ -140,4 +134,4 @@ class SOFA_MESHSKELETONIZATIONPLUGIN_API SkeletonGraph std::vector m_nodeSegment; }; -} // namespace meshskeletonizationplugin \ No newline at end of file +} // namespace meshskeletonizationplugin diff --git a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl index 93170ea..eeb5202 100644 --- a/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl +++ b/src/MeshSkeletonizationPlugin/SkeletonGraph/SkeletonReader.inl @@ -69,11 +69,7 @@ void SkeletonReader::doUpdate() } else { - // No explicit entry point given - don't silently root the tree at - // whatever's nearest the origin (which can land in a small, - // disconnected fragment far from the real vessel trunk, since real - // coordinates are almost never near (0,0,0)). Pick a root from the - // largest connected component instead. + // No explicit entry point given . Pick a root from the largest connected component instead. m_graph.buildTreeAutoRoot(); msg_info() << "No entryPoint set; auto-rooted from the largest connected component."; }