From 7ecfe9256206d7696391e7fff79811db77d0879d Mon Sep 17 00:00:00 2001 From: Florian Fontan Date: Tue, 24 Mar 2026 21:03:06 +0100 Subject: [PATCH] Fix rasterization --- data/tests/rasterization/0.json | 1792 +++++++++++++++++++++++++++++++ include/shape/rasterization.hpp | 18 + src/rasterization.cpp | 89 +- test/rasterization_test.cpp | 33 + 4 files changed, 1914 insertions(+), 18 deletions(-) create mode 100644 data/tests/rasterization/0.json diff --git a/data/tests/rasterization/0.json b/data/tests/rasterization/0.json new file mode 100644 index 0000000..98128fe --- /dev/null +++ b/data/tests/rasterization/0.json @@ -0,0 +1,1792 @@ +{ + "cell_height": 35.35533905932736, + "cell_width": 35.35533905932736, + "shape": { + "elements": [ + { + "end": { + "x": 140.80126016, + "y": 0.05634808 + }, + "start": { + "x": 140.61082456, + "y": 0.01416168 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 140.98357832, + "y": 0.12566968 + }, + "start": { + "x": 140.80126016, + "y": 0.05634808 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.1539348, + "y": 0.2206648 + }, + "start": { + "x": 140.98357832, + "y": 0.12566968 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.30873752, + "y": 0.33933048 + }, + "start": { + "x": 141.1539348, + "y": 0.2206648 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.4447224, + "y": 0.4791644 + }, + "start": { + "x": 141.30873752, + "y": 0.33933048 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.559022, + "y": 0.63721824 + }, + "start": { + "x": 141.4447224, + "y": 0.4791644 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.64922632, + "y": 0.81015928 + }, + "start": { + "x": 141.559022, + "y": 0.63721824 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.71343328, + "y": 0.99434088 + }, + "start": { + "x": 141.64922632, + "y": 0.81015928 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.75028912, + "y": 1.1858796 + }, + "start": { + "x": 141.71343328, + "y": 0.99434088 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.75901664, + "y": 1.38073656 + }, + "start": { + "x": 141.75028912, + "y": 1.1858796 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 141.73943192, + "y": 1.57480312 + }, + "start": { + "x": 141.75901664, + "y": 1.38073656 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.58029456, + "y": 13.91273088 + }, + "start": { + "x": 141.73943192, + "y": 1.57480312 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.52826544, + "y": 14.13652688 + }, + "start": { + "x": 139.58029456, + "y": 13.91273088 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.45190432, + "y": 14.35323096 + }, + "start": { + "x": 139.52826544, + "y": 14.13652688 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.35214032, + "y": 14.56020632 + }, + "start": { + "x": 139.45190432, + "y": 14.35323096 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.23018736, + "y": 14.75493472 + }, + "start": { + "x": 139.35214032, + "y": 14.56020632 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 139.0875292, + "y": 14.93504672 + }, + "start": { + "x": 139.23018736, + "y": 14.75493472 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 138.92590176, + "y": 15.0983508 + }, + "start": { + "x": 139.0875292, + "y": 14.93504672 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 138.74727152, + "y": 15.24286 + }, + "start": { + "x": 138.92590176, + "y": 15.0983508 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 138.553812, + "y": 15.366816 + }, + "start": { + "x": 138.74727152, + "y": 15.24286 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 138.34787712, + "y": 15.46871056 + }, + "start": { + "x": 138.553812, + "y": 15.366816 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 138.13197264, + "y": 15.54730384 + }, + "start": { + "x": 138.34787712, + "y": 15.46871056 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 137.90872552, + "y": 15.60163968 + }, + "start": { + "x": 138.13197264, + "y": 15.54730384 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 137.68085208, + "y": 15.6310568 + }, + "start": { + "x": 137.90872552, + "y": 15.60163968 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 32.33149216, + "y": 23.8113664 + }, + "start": { + "x": 137.68085208, + "y": 15.6310568 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 26.03350208, + "y": 59.79988112 + }, + "start": { + "x": 32.33149216, + "y": 23.8113664 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 16.10563592, + "y": 58.06250456 + }, + "start": { + "x": 26.03350208, + "y": 59.79988112 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 16.116078, + "y": 57.816062 + }, + "start": { + "x": 16.10563592, + "y": 58.06250456 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 16.06238032, + "y": 57.57531416 + }, + "start": { + "x": 16.116078, + "y": 57.816062 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.94820216, + "y": 57.3566676 + }, + "start": { + "x": 16.06238032, + "y": 57.57531416 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.78132464, + "y": 57.17502272 + }, + "start": { + "x": 15.94820216, + "y": 57.3566676 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.57312016, + "y": 57.04275832 + }, + "start": { + "x": 15.78132464, + "y": 57.17502272 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.33777752, + "y": 56.96888808 + }, + "start": { + "x": 15.57312016, + "y": 57.04275832 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.09133496, + "y": 56.95844592 + }, + "start": { + "x": 15.33777752, + "y": 56.96888808 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.8505872, + "y": 57.01214368 + }, + "start": { + "x": 15.09133496, + "y": 56.95844592 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.63194064, + "y": 57.12632184 + }, + "start": { + "x": 14.8505872, + "y": 57.01214368 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.45029576, + "y": 57.29319936 + }, + "start": { + "x": 14.63194064, + "y": 57.12632184 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.31803136, + "y": 57.50140384 + }, + "start": { + "x": 14.45029576, + "y": 57.29319936 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.24416104, + "y": 57.7367464 + }, + "start": { + "x": 14.31803136, + "y": 57.50140384 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.23371896, + "y": 57.98318896 + }, + "start": { + "x": 14.24416104, + "y": 57.7367464 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.28741672, + "y": 58.2239368 + }, + "start": { + "x": 14.23371896, + "y": 57.98318896 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.40159488, + "y": 58.44258336 + }, + "start": { + "x": 14.28741672, + "y": 58.2239368 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.5684724, + "y": 58.62422824 + }, + "start": { + "x": 14.40159488, + "y": 58.44258336 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.7766768, + "y": 58.75649264 + }, + "start": { + "x": 14.5684724, + "y": 58.62422824 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.01201944, + "y": 58.83036296 + }, + "start": { + "x": 14.7766768, + "y": 58.75649264 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.52338224, + "y": 61.62257528 + }, + "start": { + "x": 15.01201944, + "y": 58.83036296 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.27693976, + "y": 61.6121332 + }, + "start": { + "x": 14.52338224, + "y": 61.62257528 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.03619192, + "y": 61.66583096 + }, + "start": { + "x": 14.27693976, + "y": 61.6121332 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.81754536, + "y": 61.78000912 + }, + "start": { + "x": 14.03619192, + "y": 61.66583096 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.63590048, + "y": 61.94688664 + }, + "start": { + "x": 13.81754536, + "y": 61.78000912 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.50363608, + "y": 62.15509104 + }, + "start": { + "x": 13.63590048, + "y": 61.94688664 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.42976576, + "y": 62.39043368 + }, + "start": { + "x": 13.50363608, + "y": 62.15509104 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.41932368, + "y": 62.63687624 + }, + "start": { + "x": 13.42976576, + "y": 62.39043368 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.47302144, + "y": 62.87762408 + }, + "start": { + "x": 13.41932368, + "y": 62.63687624 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.5871996, + "y": 63.09627064 + }, + "start": { + "x": 13.47302144, + "y": 62.87762408 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.75407712, + "y": 63.27791552 + }, + "start": { + "x": 13.5871996, + "y": 63.09627064 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.96228152, + "y": 63.41017984 + }, + "start": { + "x": 13.75407712, + "y": 63.27791552 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.19762416, + "y": 63.48405016 + }, + "start": { + "x": 13.96228152, + "y": 63.41017984 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.44406672, + "y": 63.49449224 + }, + "start": { + "x": 14.19762416, + "y": 63.48405016 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.68481456, + "y": 63.44079456 + }, + "start": { + "x": 14.44406672, + "y": 63.49449224 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.90346112, + "y": 63.3266164 + }, + "start": { + "x": 14.68481456, + "y": 63.44079456 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.085106, + "y": 63.15973888 + }, + "start": { + "x": 14.90346112, + "y": 63.3266164 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.21737032, + "y": 62.9515344 + }, + "start": { + "x": 15.085106, + "y": 63.15973888 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 15.29124064, + "y": 62.71619176 + }, + "start": { + "x": 15.21737032, + "y": 62.9515344 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 25.2191068, + "y": 64.4535684 + }, + "start": { + "x": 15.29124064, + "y": 62.71619176 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 23.34599768, + "y": 75.15704904 + }, + "start": { + "x": 25.2191068, + "y": 64.4535684 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 23.053772, + "y": 76.35797064 + }, + "start": { + "x": 23.34599768, + "y": 75.15704904 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.60729456, + "y": 77.51047512 + }, + "start": { + "x": 23.053772, + "y": 76.35797064 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.0142048, + "y": 78.59484272 + }, + "start": { + "x": 22.60729456, + "y": 77.51047512 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.28465064, + "y": 79.59251976 + }, + "start": { + "x": 22.0142048, + "y": 78.59484272 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.43111496, + "y": 80.48643552 + }, + "start": { + "x": 21.28465064, + "y": 79.59251976 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 19.468202, + "y": 81.26129496 + }, + "start": { + "x": 20.43111496, + "y": 80.48643552 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 18.41238736, + "y": 81.90384 + }, + "start": { + "x": 19.468202, + "y": 81.26129496 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 17.28173648, + "y": 82.40307648 + }, + "start": { + "x": 18.41238736, + "y": 81.90384 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 16.09559496, + "y": 82.75046248 + }, + "start": { + "x": 17.28173648, + "y": 82.40307648 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.87425808, + "y": 82.94005392 + }, + "start": { + "x": 16.09559496, + "y": 82.75046248 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 13.63862336, + "y": 82.96860696 + }, + "start": { + "x": 14.87425808, + "y": 82.94005392 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 12.40983264, + "y": 82.83563296 + }, + "start": { + "x": 13.63862336, + "y": 82.96860696 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 0.0, + "y": 80.66391224 + }, + "start": { + "x": 12.40983264, + "y": 82.83563296 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.23927624, + "y": 50.72519096 + }, + "start": { + "x": 0.0, + "y": 80.66391224 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.4857188, + "y": 50.73563304 + }, + "start": { + "x": 5.23927624, + "y": 50.72519096 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.72646656, + "y": 50.68193536 + }, + "start": { + "x": 5.4857188, + "y": 50.73563304 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.94511312, + "y": 50.5677572 + }, + "start": { + "x": 5.72646656, + "y": 50.68193536 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.126758, + "y": 50.40087968 + }, + "start": { + "x": 5.94511312, + "y": 50.5677572 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.2590224, + "y": 50.1926752 + }, + "start": { + "x": 6.126758, + "y": 50.40087968 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.33289272, + "y": 49.95733256 + }, + "start": { + "x": 6.2590224, + "y": 50.1926752 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.3433348, + "y": 49.71089008 + }, + "start": { + "x": 6.33289272, + "y": 49.95733256 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.28963704, + "y": 49.47014224 + }, + "start": { + "x": 6.3433348, + "y": 49.71089008 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.17545888, + "y": 49.25149568 + }, + "start": { + "x": 6.28963704, + "y": 49.47014224 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 6.00858136, + "y": 49.0698508 + }, + "start": { + "x": 6.17545888, + "y": 49.25149568 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.80037696, + "y": 48.9375864 + }, + "start": { + "x": 6.00858136, + "y": 49.0698508 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.56503432, + "y": 48.86371608 + }, + "start": { + "x": 5.80037696, + "y": 48.9375864 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.31859176, + "y": 48.853274 + }, + "start": { + "x": 5.56503432, + "y": 48.86371608 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 5.07784392, + "y": 48.90697176 + }, + "start": { + "x": 5.31859176, + "y": 48.853274 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 4.85919736, + "y": 49.02114992 + }, + "start": { + "x": 5.07784392, + "y": 48.90697176 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 4.67755256, + "y": 49.18802744 + }, + "start": { + "x": 4.85919736, + "y": 49.02114992 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 4.54528816, + "y": 49.39623184 + }, + "start": { + "x": 4.67755256, + "y": 49.18802744 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 4.47141784, + "y": 49.63157448 + }, + "start": { + "x": 4.54528816, + "y": 49.39623184 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 0.748468, + "y": 48.98005824 + }, + "start": { + "x": 4.47141784, + "y": 49.63157448 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 4.06034208, + "y": 30.05506344 + }, + "start": { + "x": 0.748468, + "y": 48.98005824 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 7.78329192, + "y": 30.70657968 + }, + "start": { + "x": 4.06034208, + "y": 30.05506344 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 7.77284984, + "y": 30.95302224 + }, + "start": { + "x": 7.78329192, + "y": 30.70657968 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 7.82654752, + "y": 31.19377008 + }, + "start": { + "x": 7.77284984, + "y": 30.95302224 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 7.94072568, + "y": 31.41241664 + }, + "start": { + "x": 7.82654752, + "y": 31.19377008 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 8.1076032, + "y": 31.59406152 + }, + "start": { + "x": 7.94072568, + "y": 31.41241664 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 8.31580768, + "y": 31.72632584 + }, + "start": { + "x": 8.1076032, + "y": 31.59406152 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 8.55115032, + "y": 31.80019616 + }, + "start": { + "x": 8.31580768, + "y": 31.72632584 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 8.79759288, + "y": 31.81063824 + }, + "start": { + "x": 8.55115032, + "y": 31.80019616 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.03834072, + "y": 31.75694056 + }, + "start": { + "x": 8.79759288, + "y": 31.81063824 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.25698728, + "y": 31.6427624 + }, + "start": { + "x": 9.03834072, + "y": 31.75694056 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.43863208, + "y": 31.47588488 + }, + "start": { + "x": 9.25698728, + "y": 31.6427624 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.57089648, + "y": 31.2676804 + }, + "start": { + "x": 9.43863208, + "y": 31.47588488 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.6447668, + "y": 31.03233776 + }, + "start": { + "x": 9.57089648, + "y": 31.2676804 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.65520888, + "y": 30.78589528 + }, + "start": { + "x": 9.6447668, + "y": 31.03233776 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.6015112, + "y": 30.54514744 + }, + "start": { + "x": 9.65520888, + "y": 30.78589528 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.48733304, + "y": 30.32650088 + }, + "start": { + "x": 9.6015112, + "y": 30.54514744 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.32045552, + "y": 30.144856 + }, + "start": { + "x": 9.48733304, + "y": 30.32650088 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.11225104, + "y": 30.0125916 + }, + "start": { + "x": 9.32045552, + "y": 30.144856 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 8.8769084, + "y": 29.93872128 + }, + "start": { + "x": 9.11225104, + "y": 30.0125916 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 9.79988968, + "y": 24.6645424 + }, + "start": { + "x": 8.8769084, + "y": 29.93872128 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 19.72775584, + "y": 26.40191896 + }, + "start": { + "x": 9.79988968, + "y": 24.6645424 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 19.71731376, + "y": 26.64836152 + }, + "start": { + "x": 19.72775584, + "y": 26.40191896 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 19.77101152, + "y": 26.88910936 + }, + "start": { + "x": 19.71731376, + "y": 26.64836152 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 19.88518968, + "y": 27.10775592 + }, + "start": { + "x": 19.77101152, + "y": 26.88910936 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.0520672, + "y": 27.2894008 + }, + "start": { + "x": 19.88518968, + "y": 27.10775592 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.2602716, + "y": 27.4216652 + }, + "start": { + "x": 20.0520672, + "y": 27.2894008 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.49561424, + "y": 27.49553552 + }, + "start": { + "x": 20.2602716, + "y": 27.4216652 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.7420568, + "y": 27.5059776 + }, + "start": { + "x": 20.49561424, + "y": 27.49553552 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.98280464, + "y": 27.45227984 + }, + "start": { + "x": 20.7420568, + "y": 27.5059776 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.2014512, + "y": 27.33810168 + }, + "start": { + "x": 20.98280464, + "y": 27.45227984 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.38309608, + "y": 27.17122416 + }, + "start": { + "x": 21.2014512, + "y": 27.33810168 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.5153604, + "y": 26.96301968 + }, + "start": { + "x": 21.38309608, + "y": 27.17122416 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.58923072, + "y": 26.72767712 + }, + "start": { + "x": 21.5153604, + "y": 26.96301968 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.5996728, + "y": 26.48123456 + }, + "start": { + "x": 21.58923072, + "y": 26.72767712 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.54597512, + "y": 26.24048672 + }, + "start": { + "x": 21.5996728, + "y": 26.48123456 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.43179696, + "y": 26.02184016 + }, + "start": { + "x": 21.54597512, + "y": 26.24048672 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.26491944, + "y": 25.84019528 + }, + "start": { + "x": 21.43179696, + "y": 26.02184016 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.05671496, + "y": 25.70793088 + }, + "start": { + "x": 21.26491944, + "y": 25.84019528 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.82137232, + "y": 25.63406056 + }, + "start": { + "x": 21.05671496, + "y": 25.70793088 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.31000952, + "y": 22.84184824 + }, + "start": { + "x": 20.82137232, + "y": 25.63406056 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.55645208, + "y": 22.85229032 + }, + "start": { + "x": 21.31000952, + "y": 22.84184824 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.79719992, + "y": 22.79859256 + }, + "start": { + "x": 21.55645208, + "y": 22.85229032 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.01584648, + "y": 22.6844144 + }, + "start": { + "x": 21.79719992, + "y": 22.79859256 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.19749128, + "y": 22.51753688 + }, + "start": { + "x": 22.01584648, + "y": 22.6844144 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.32975568, + "y": 22.30933248 + }, + "start": { + "x": 22.19749128, + "y": 22.51753688 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.403626, + "y": 22.07398984 + }, + "start": { + "x": 22.32975568, + "y": 22.30933248 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.41406808, + "y": 21.82754728 + }, + "start": { + "x": 22.403626, + "y": 22.07398984 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.3603704, + "y": 21.58679944 + }, + "start": { + "x": 22.41406808, + "y": 21.82754728 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.24619224, + "y": 21.36815288 + }, + "start": { + "x": 22.3603704, + "y": 21.58679944 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 22.07931472, + "y": 21.186508 + }, + "start": { + "x": 22.24619224, + "y": 21.36815288 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.87111024, + "y": 21.05424368 + }, + "start": { + "x": 22.07931472, + "y": 21.186508 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.6357676, + "y": 20.98037336 + }, + "start": { + "x": 21.87111024, + "y": 21.05424368 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.38932504, + "y": 20.96993128 + }, + "start": { + "x": 21.6357676, + "y": 20.98037336 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 21.1485772, + "y": 21.02362896 + }, + "start": { + "x": 21.38932504, + "y": 20.96993128 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.92993072, + "y": 21.13780712 + }, + "start": { + "x": 21.1485772, + "y": 21.02362896 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.74828584, + "y": 21.30468464 + }, + "start": { + "x": 20.92993072, + "y": 21.13780712 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.61602144, + "y": 21.51288912 + }, + "start": { + "x": 20.74828584, + "y": 21.30468464 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 20.54215112, + "y": 21.74823176 + }, + "start": { + "x": 20.61602144, + "y": 21.51288912 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 10.61428496, + "y": 20.01085512 + }, + "start": { + "x": 20.54215112, + "y": 21.74823176 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 14.11618464, + "y": 0.0 + }, + "start": { + "x": 10.61428496, + "y": 20.01085512 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 140.41628696, + "y": 0.0 + }, + "start": { + "x": 14.11618464, + "y": 0.0 + }, + "type": "LineSegment" + }, + { + "end": { + "x": 140.61082456, + "y": 0.01416168 + }, + "start": { + "x": 140.41628696, + "y": 0.0 + }, + "type": "LineSegment" + } + ], + "is_path": false, + "type": "general" + } +} diff --git a/include/shape/rasterization.hpp b/include/shape/rasterization.hpp index 3f154fc..bd2502a 100644 --- a/include/shape/rasterization.hpp +++ b/include/shape/rasterization.hpp @@ -31,6 +31,15 @@ std::vector rasterization( LengthDbl cell_width, LengthDbl cell_height); +void rasterization_export_inputs( + const std::string& file_path, + const ShapeWithHoles& shape, + LengthDbl cell_width, + LengthDbl cell_height); + +/** + * Convert a cell to a shape. + */ Shape cell_to_shape( const Cell& cell, LengthDbl cell_width, @@ -44,4 +53,13 @@ std::vector cells_to_shapes( LengthDbl cell_width, LengthDbl cell_height); +/** + * Convert a list of intersected cells into shapes with holes. + */ +std::vector cells_to_shapes( + const std::vector& cells, + LengthDbl cell_width, + LengthDbl cell_height, + bool only_full = false); + } diff --git a/src/rasterization.cpp b/src/rasterization.cpp index 57ad5dc..12885e7 100644 --- a/src/rasterization.cpp +++ b/src/rasterization.cpp @@ -1,11 +1,19 @@ +//#define RASTERIZATION_ENABLE_DEBUG + #include "shape/rasterization.hpp" #include "shape/boolean_operations.hpp" #include "shape/elements_intersections.hpp" +#ifdef RASTERIZATION_ENABLE_DEBUG +#include "shape/writer.hpp" +#endif #include #include -//#include +#include +#ifdef RASTERIZATION_ENABLE_DEBUG +#include +#endif using namespace shape; @@ -93,9 +101,11 @@ void fill_columns_intersections( intersection_points.push_back({element_pos, point}); } } - //std::cout << "intersection_points" << std::endl; - //for (const ShapePoint& point: intersection_points) - // std::cout << point.element_pos << " " << point.point.to_string() << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "intersection_points" << std::endl; + for (const ShapePoint& point: intersection_points) + std::cout << point.element_pos << " " << point.point.to_string() << std::endl; +#endif if (intersection_points.empty()) return; // Sort intersection points by their length on the element. @@ -149,10 +159,12 @@ void fill_columns_intersections( if (is_hole) column_intersection.is_above_inside = !column_intersection.is_above_inside; column_intersections[cell.column - column_intersections_offset].push_back(column_intersection); - //std::cout << "column " << cell.column - // << " y_min " << column_intersection.y_min - // << " y_max " << column_intersection.y_max - // << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "column " << cell.column + << " y_min " << column_intersection.y_min + << " y_max " << column_intersection.y_max + << std::endl; +#endif } point_prev = point; } @@ -170,8 +182,10 @@ std::vector shape::rasterization( ColumnId column_max = find_cell(cell_width, cell_height, {aabb.x_max, aabb.y_max}).column; RowId row_min = find_cell(cell_width, cell_height, {aabb.x_min, aabb.y_min}).row; RowId row_max = find_cell(cell_width, cell_height, {aabb.x_max, aabb.y_max}).row; - //std::cout << "column min " << column_min << " max " << column_max << std::endl; - //std::cout << "row min " << row_min << " max " << row_max << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "column min " << column_min << " max " << column_max << std::endl; + std::cout << "row min " << row_min << " max " << row_max << std::endl; +#endif // General case: column_inters is guaranteed non-empty for each column. std::vector> column_intersections(column_max - column_min + 1); @@ -194,7 +208,9 @@ std::vector shape::rasterization( ElementPos number_of_intersections = 0; for (ColumnId column = column_min; column <= column_max; ++column) number_of_intersections += column_intersections[column - column_min].size(); - //std::cout << "number_of_intersections " << number_of_intersections << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "number_of_intersections " << number_of_intersections << std::endl; +#endif // Single-column or single-row case: fill_columns_intersections produces no // records because the shape crosses no horizontal grid lines. @@ -207,12 +223,16 @@ std::vector shape::rasterization( cells.push_back(cell); } } - //std::cout << "cells.size() " << cells.size() << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "cells.size() " << cells.size() << std::endl; +#endif return cells; } for (ColumnId column = column_min; column <= column_max; ++column) { - //std::cout << "column " << column << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "column " << column << std::endl; +#endif const std::vector& column_inters = column_intersections[column - column_min]; @@ -229,6 +249,7 @@ std::vector shape::rasterization( }); LengthDbl y_max_prev = -std::numeric_limits::infinity(); + RowId row_hi_prev = row_min - 1; bool is_above_inside_prev = false; for (ElementPos intersection_pos = 0; intersection_pos < sorted_intersections.size(); @@ -240,11 +261,16 @@ std::vector shape::rasterization( RowId row_hi = (RowId)std::floor(column_intersection.y_max / cell_height); if (equal(row_hi * cell_height, column_intersection.y_max)) row_hi--; - RowId row_hi_prev = (RowId)std::floor(y_max_prev / cell_height); - //std::cout << "i " << intersection_pos - // << " row_lo " << row_lo - // << " row_hi " << row_hi - // << std::endl; +#ifdef RASTERIZATION_ENABLE_DEBUG + std::cout << "i " << intersection_pos + << " is_above_inside_prev " << is_above_inside_prev + << " row_hi_prev " << row_hi_prev + << " y_min " << column_intersection.y_min + << " y_max " << column_intersection.y_max + << " row_lo " << row_lo + << " row_hi " << row_hi + << std::endl; +#endif if (is_above_inside_prev) { for (RowId row = row_hi_prev + 1; row < row_lo; ++row) { IntersectedCell cell; @@ -292,3 +318,30 @@ std::vector shape::cells_to_shapes( union_input.push_back({cell_to_shape(cell, cell_width, cell_height)}); return compute_union(union_input); } + +std::vector shape::cells_to_shapes( + const std::vector& cells, + LengthDbl cell_width, + LengthDbl cell_height, + bool only_full) +{ + std::vector union_input; + for (const IntersectedCell& cell: cells) + if (cell.full || !only_full) + union_input.push_back({cell_to_shape(cell.cell, cell_width, cell_height)}); + return compute_union(union_input); +} + +void shape::rasterization_export_inputs( + const std::string& file_path, + const ShapeWithHoles& shape, + LengthDbl cell_width, + LengthDbl cell_height) +{ + std::ofstream file{file_path}; + nlohmann::json json; + json["shape"] = shape.to_json(); + json["cell_width"] = cell_width; + json["cell_height"] = cell_height; + file << std::setw(4) << json << std::endl; +} diff --git a/test/rasterization_test.cpp b/test/rasterization_test.cpp index cd065a7..72f99c9 100644 --- a/test/rasterization_test.cpp +++ b/test/rasterization_test.cpp @@ -10,9 +10,13 @@ #include +#include + #include +#include using namespace shape; +namespace fs = boost::filesystem; struct RasterizationTestParams @@ -20,6 +24,33 @@ struct RasterizationTestParams ShapeWithHoles shape; LengthDbl cell_width; LengthDbl cell_height; + + + template + static RasterizationTestParams from_json( + basic_json& json_item) + { + RasterizationTestParams test_params; + test_params.shape = ShapeWithHoles::from_json(json_item["shape"]); + test_params.cell_width = json_item["cell_width"]; + test_params.cell_height = json_item["cell_height"]; + return test_params; + } + + static RasterizationTestParams read_json( + const std::string& file_path) + { + std::ifstream file(file_path); + if (!file.good()) { + throw std::runtime_error( + FUNC_SIGNATURE + ": " + "unable to open file \"" + file_path + "\"."); + } + + nlohmann::json json; + file >> json; + return from_json(json); + } }; bool operator==(const Cell& a, const Cell& b) @@ -175,4 +206,6 @@ INSTANTIATE_TEST_SUITE_P( 10, 10, }, + RasterizationTestParams::read_json( + (fs::path("data") / "tests" / "rasterization" / "0.json").string()), }));