The Y intersection had a real I3 violation that the M0.3 centroid- only check missed (parcels 0 and 7 overlapped by ~64.5 m²). This commit: - adds geo 0.28 as a dependency - replaces y_intersection_no_overlaps's centroid-in-polygon check with a rigorous polygon-polygon intersection test using geo::BooleanOps; adds rectangle_no_overlaps_rigorous as a positive-control test for the rectangle case - adds cleanup_block_parcel_overlaps pass at the end of subdivide_block: iterate parcels in placement order (corners first, regulars after), subtract previously-claimed territory from each via geo's polygon difference, drop empties, recover frontage edge index and edge_kinds for survivors - snaps polygon coords to a 1mm grid before handing to geo (helps geo's sweep-line invariants); strips collinear-triple and near-zero-length-edge artifacts from boolean output before feeding back into Polygon::new strict - wraps difference/union calls in catch_unwind so geo's occasional sweep-line panic on degenerate inputs falls back to a no-op instead of crashing subdivision Test status: 24 unit + 24 integration + 1 doc passing. Y figure visually cleaner — every parcel sits inside its own sub-block, no visible overlap between sub-blocks. Self-decisions checklist progress: rigorous I3 testing landed (checklist item ✓). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
101 lines
9.0 KiB
XML
101 lines
9.0 KiB
XML
<svg height="663.5382907247957" viewBox="-50.00000000000004 -82.94228634059945 145.00000000000006 165.88457268119893" width="580.0000000000002" xmlns="http://www.w3.org/2000/svg">
|
|
<rect fill="#ffffff" height="165.88457268119893" width="145.00000000000006" x="-50.00000000000004" y="-82.94228634059945"/>
|
|
<g transform="translate(0, 0.00000000000002842170943040401) scale(1, -1)">
|
|
<g id="roads">
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="90" y1="0" y2="0"/>
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="-44.999999999999986" y1="0" y2="77.94228634059948"/>
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="-45.00000000000004" y1="0" y2="-77.94228634059945"/>
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="90" x2="-44.999999999999986" y1="0" y2="77.94228634059948"/>
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-44.999999999999986" x2="-45.00000000000004" y1="77.94228634059948" y2="-77.94228634059945"/>
|
|
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-45.00000000000004" x2="90" y1="-77.94228634059945" y2="0"/>
|
|
</g>
|
|
<g id="parcels">
|
|
<path d="M-15,25.981 L0,0 L20,0 L20,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-15" x2="0" y1="25.981" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="20" y1="0" y2="0"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="0" y2="30"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="-15" y1="30" y2="25.981"/>
|
|
<path d="M42.997,0 L42.997,12.595 L41.519,12.99 L20,12.99 L20,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.997" x2="42.997" y1="0" y2="12.595"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.997" x2="41.519" y1="12.595" y2="12.99"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="41.519" x2="20" y1="12.99" y2="12.99"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="12.99" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.997" y1="0" y2="0"/>
|
|
<path d="M65.48,0 L65.48,6.57 L42.997,12.595 L42.997,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.48" x2="65.48" y1="0" y2="6.57"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.48" x2="42.997" y1="6.57" y2="12.595"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.997" x2="42.997" y1="12.595" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.997" x2="65.48" y1="0" y2="0"/>
|
|
<path d="M90,0 L65.48,6.57 L65.48,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="90" x2="65.48" y1="0" y2="6.57"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.48" x2="65.48" y1="6.57" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.48" x2="90" y1="0" y2="0"/>
|
|
<path d="M20,0 L0,0 L-15,-25.981 L2.321,-35.981 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="0" y2="0"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="-15" y1="0" y2="-25.981"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-15" x2="2.321" y1="-25.981" y2="-35.981"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="2.321" x2="20" y1="-35.981" y2="0"/>
|
|
<path d="M90,0 L67.003,0 L67.003,-6.162 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="90" x2="67.003" y1="0" y2="0"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.003" x2="67.003" y1="0" y2="-6.162"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.003" x2="90" y1="-6.162" y2="0"/>
|
|
<path d="M67.003,-6.162 L67.003,0 L44.52,0 L44.52,-12.186 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.003" x2="67.003" y1="-6.162" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="67.003" x2="44.52" y1="0" y2="0"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.52" x2="44.52" y1="0" y2="-12.186"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="44.52" x2="67.003" y1="-12.186" y2="-6.162"/>
|
|
<path d="M41.519,-12.99 L44.52,-12.186 L44.52,0 L20,0 L20,-12.99 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="41.519" x2="44.52" y1="-12.99" y2="-12.186"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.52" x2="44.52" y1="-12.186" y2="0"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="44.52" x2="20" y1="0" y2="0"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="0" y2="-12.99"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="41.519" y1="-12.99" y2="-12.99"/>
|
|
<path d="M27.364,-36.163 L47.073,-24.784 L40.433,-13.282 L17.674,-19.38 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="27.364" x2="47.073" y1="-36.163" y2="-24.784"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="47.073" x2="40.433" y1="-24.784" y2="-13.282"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="40.433" x2="17.674" y1="-13.282" y2="-19.38"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="17.674" x2="27.364" y1="-19.38" y2="-36.163"/>
|
|
<path d="M-39.252,56.489 L-45,77.942 L-45,56.489 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-39.252" x2="-45" y1="56.489" y2="77.942"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="77.942" y2="56.489"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-39.252" y1="56.489" y2="56.489"/>
|
|
<path d="M-33.324,34.366 L-39.252,56.489 L-45,56.489 L-45,34.366 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-33.324" x2="-39.252" y1="34.366" y2="56.489"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-39.252" x2="-45" y1="56.489" y2="56.489"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="56.489" y2="34.366"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-33.324" y1="34.366" y2="34.366"/>
|
|
<path d="M-28.458,16.206 L-33.324,34.366 L-45,34.366 L-45,16.206 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-28.458" x2="-33.324" y1="16.206" y2="34.366"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-33.324" x2="-45" y1="34.366" y2="34.366"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="34.366" y2="16.206"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-28.458" y1="16.206" y2="16.206"/>
|
|
<path d="M-24.799,-2.552 L-24.115,-0 L-28.458,16.206 L-45,16.206 L-45,-2.552 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-24.799" x2="-24.115" y1="-2.552" y2="-0"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-24.115" x2="-28.458" y1="-0" y2="16.206"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-28.458" x2="-45" y1="16.206" y2="16.206"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="16.206" y2="-2.552"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-24.799" y1="-2.552" y2="-2.552"/>
|
|
<path d="M-29.445,-19.889 L-24.799,-2.552 L-45,-2.552 L-45,-19.889 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-29.445" x2="-24.799" y1="-19.889" y2="-2.552"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-24.799" x2="-45" y1="-2.552" y2="-2.552"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="-2.552" y2="-19.889"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-29.445" y1="-19.889" y2="-19.889"/>
|
|
<path d="M-34.355,-38.214 L-29.445,-19.889 L-45,-19.889 L-45,-38.214 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-34.355" x2="-29.445" y1="-38.214" y2="-19.889"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-29.445" x2="-45" y1="-19.889" y2="-19.889"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="-19.889" y2="-38.214"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-34.355" y1="-38.214" y2="-38.214"/>
|
|
<path d="M-39.395,-57.025 L-34.355,-38.214 L-45,-38.214 L-45,-57.025 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
|
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-39.395" x2="-34.355" y1="-57.025" y2="-38.214"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-34.355" x2="-45" y1="-38.214" y2="-38.214"/>
|
|
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45" y1="-38.214" y2="-57.025"/>
|
|
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-39.395" y1="-57.025" y2="-57.025"/>
|
|
</g>
|
|
<g id="nodes">
|
|
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
|
<circle cx="90" cy="0" fill="#000000" r="0.7"/>
|
|
<circle cx="-44.999999999999986" cy="77.94228634059948" fill="#000000" r="0.7"/>
|
|
<circle cx="-45.00000000000004" cy="-77.94228634059945" fill="#000000" r="0.7"/>
|
|
</g>
|
|
</g>
|
|
</svg> |