initial commit
BIN
figures/fig_01_grid_block.pdf
Normal file
139
figures/fig_01_grid_block.svg
Normal file
@ -0,0 +1,139 @@
|
||||
<svg height="440" viewBox="-5 -5 210 110" width="840" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="110" width="210" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 100) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="200" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="200" x2="200" y1="0" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="200" x2="0" y1="100" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="100" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20,0 L20,30 L0,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<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="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M200,0 L200,30 L180,30 L180,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="200" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="200" x2="180" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="200" y1="0" y2="0"/>
|
||||
<path d="M200,100 L180,100 L180,70 L200,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="180" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="200" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="200" y1="70" y2="100"/>
|
||||
<path d="M0,100 L0,70 L20,70 L20,100 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="70" y2="100"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="100" y2="100"/>
|
||||
<path d="M20,0 L42.996502,0 L42.996502,29.52622 L20,29.52622 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M42.996502,0 L65.47971,0 L65.47971,31.147902 L42.996502,31.147902 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M65.47971,0 L88.27847,0 L88.27847,29.876335 L65.47971,29.876335 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="88.27847104373568" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M88.27847,0 L109.00264,0 L109.00264,30.25849 L88.27847,30.25849 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="88.27847104373568" x2="109.00264275540263" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M109.00264,0 L127.212425,0 L127.212425,34 L109.00264,34 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="109.00264275540263" x2="127.2124223685276" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="34.000001" y2="0"/>
|
||||
<path d="M127.212425,0 L146.8415,0 L146.8415,31.470558 L127.212425,31.470558 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="127.2124223685276" x2="146.84151010926075" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M146.8415,0 L166.40808,0 L166.40808,33.89513 L146.8415,33.89513 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="146.84151010926075" x2="166.4080836096857" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="166.4080836096857" x2="166.4080836096857" y1="0" y2="33.89512833223243"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="166.4080836096857" x2="146.84151010926075" y1="33.89512833223243" y2="33.89512833223243"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="33.89512833223243" y2="0"/>
|
||||
<path d="M166.40808,0 L180,0 L180,29.999052 L166.40808,29.999052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="166.4080836096857" x2="180" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="0" y2="29.999051502429545"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="166.4080836096857" y1="29.999051502429545" y2="29.999051502429545"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="166.4080836096857" x2="166.4080836096857" y1="29.999051502429545" y2="0"/>
|
||||
<path d="M200,30 L200,52.855724 L169.38701,52.855724 L169.38701,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="200" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="169.3870078110646" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="169.3870078110646" x2="169.3870078110646" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="169.3870078110646" x2="200" y1="30" y2="30"/>
|
||||
<path d="M200,52.855724 L200,70 L172.17726,70 L172.17726,52.855724 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="200" y1="52.855722506414395" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="172.17726330629023" y1="70" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="172.17726330629023" x2="172.17726330629023" y1="70" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="172.17726330629023" x2="200" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M180,100 L161.1955,100 L161.1955,72.466 L180,72.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="161.19549058892116" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="100" y2="72.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="161.19549058892116" x2="180" y1="72.46600595599794" y2="72.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="72.46600595599794" y2="100"/>
|
||||
<path d="M161.1955,100 L140.25922,100 L140.25922,68.26361 L161.1955,68.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="161.19549058892116" x2="140.25920977847343" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="100" y2="68.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="140.25920977847343" x2="161.19549058892116" y1="68.26360853604555" y2="68.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="68.26360853604555" y2="100"/>
|
||||
<path d="M140.25922,100 L120.000404,100 L120.000404,66 L140.25922,66 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="140.25920977847343" x2="120.0004046814901" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="100" y2="65.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.0004046814901" x2="140.25920977847343" y1="65.999999" y2="65.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="65.999999" y2="100"/>
|
||||
<path d="M120.000404,100 L98.191284,100 L98.191284,71.2734 L120.000404,71.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.0004046814901" x2="98.19128506754218" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="100" y2="71.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="98.19128506754218" x2="120.0004046814901" y1="71.27339761286972" y2="71.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="71.27339761286972" y2="100"/>
|
||||
<path d="M98.191284,100 L81.11824,100 L81.11824,72.8639 L98.191284,72.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="98.19128506754218" x2="81.11823933536908" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="100" y2="72.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="81.11823933536908" x2="98.19128506754218" y1="72.86389925174167" y2="72.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="72.86389925174167" y2="100"/>
|
||||
<path d="M81.11824,100 L63.12904,100 L63.12904,70.637054 L81.11824,70.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="81.11823933536908" x2="63.129039299600635" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="100" y2="70.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="63.129039299600635" x2="81.11823933536908" y1="70.63705247970552" y2="70.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="70.63705247970552" y2="100"/>
|
||||
<path d="M63.12904,100 L40.141674,100 L40.141674,68.958885 L63.12904,68.958885 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="63.129039299600635" x2="40.14167365815044" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="100" y2="68.95888431009364"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="40.14167365815044" x2="63.129039299600635" y1="68.95888431009364" y2="68.95888431009364"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="68.95888431009364" y2="100"/>
|
||||
<path d="M40.141674,100 L20,100 L20,72.17421 L40.141674,72.17421 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="40.14167365815044" x2="20" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="100" y2="72.17420690790317"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="40.14167365815044" y1="72.17420690790317" y2="72.17420690790317"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="72.17420690790317" y2="100"/>
|
||||
<path d="M0,70 L0,51.044052 L32.357586,51.044052 L32.357586,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="70" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="32.357584460743425" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="32.357584460743425" x2="32.357584460743425" y1="51.04405176448549" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="32.357584460743425" x2="0" y1="70" y2="70"/>
|
||||
<path d="M0,51.044052 L0,30 L29.8626,30 L29.8626,51.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="51.04405176448549" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="30" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="200" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="200" cy="100" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="100" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
figures/fig_02_curved_road.pdf
Normal file
183
figures/fig_02_curved_road.svg
Normal file
@ -0,0 +1,183 @@
|
||||
<svg height="474.31457505076196" viewBox="-146.42135623730948 -5 292.84271247461896 118.57864376269049" width="1171.3708498984759" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="118.57864376269049" width="292.84271247461896" x="-146.42135623730948" y="-5"/>
|
||||
<g transform="translate(0, 108.57864376269049) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-141.42135623730948" x2="-111.11404660392043" y1="58.57864376269049" y2="33.70607753949096"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-111.11404660392043" x2="-76.53668647301795" y1="33.70607753949096" y2="15.224093497742643"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-76.53668647301795" x2="-39.01806440322565" y1="15.224093497742643" y2="3.8429439193538997"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-39.01806440322565" x2="0" y1="3.8429439193538997" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="39.01806440322565" y1="0" y2="3.8429439193538997"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="39.01806440322565" x2="76.53668647301795" y1="3.8429439193538997" y2="15.224093497742643"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="76.53668647301795" x2="111.11404660392043" y1="15.224093497742643" y2="33.70607753949096"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="111.11404660392043" x2="141.42135623730948" y1="33.70607753949096" y2="58.57864376269049"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="141.42135623730948" x2="141.42135623730948" y1="58.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="141.42135623730948" x2="-141.42135623730948" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="-141.42135623730948" x2="-141.42135623730948" y1="108.57864376269049" y2="58.57864376269049"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M-141.42136,78.182076 L-141.42136,58.578644 L-126.2677,46.14236 L-113.83142,61.296017 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-141.42135623730948" x2="-141.42135623730948" y1="78.1820718286026" y2="58.57864376269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-141.42135623730948" x2="-126.26770142061496" y1="58.57864376269049" y2="46.142360651090726"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-126.26770142061496" x2="-113.83141830901519" y1="46.142360651090726" y2="61.29601546778525"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-113.83141830901519" x2="-141.42135623730948" y1="61.29601546778525" y2="78.1820718286026"/>
|
||||
<path d="M126.2677,46.14236 L141.42136,58.578644 L141.42136,78.182076 L121.817924,78.182076 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="126.26770142061496" x2="141.42135623730948" y1="46.142360651090726" y2="58.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.42135623730948" x2="141.42135623730948" y1="58.57864376269049" y2="78.1820718286026"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="141.42135623730948" x2="121.81792817139737" y1="78.1820718286026" y2="78.1820718286026"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="121.81792817139737" x2="126.26770142061496" y1="78.1820718286026" y2="46.142360651090726"/>
|
||||
<path d="M141.42136,83.57864 L141.42136,108.57864 L121.42136,108.57864 L121.42136,83.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="141.42135623730948" x2="141.42135623730948" y1="83.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.42135623730948" x2="121.42135623730948" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="121.42135623730948" x2="121.42135623730948" y1="108.57864376269049" y2="83.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="121.42135623730948" x2="141.42135623730948" y1="83.57864376269049" y2="83.57864376269049"/>
|
||||
<path d="M-121.42136,108.57864 L-141.42136,108.57864 L-141.42136,83.57864 L-121.42136,83.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-121.42135623730948" x2="-141.42135623730948" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-141.42135623730948" x2="-141.42135623730948" y1="108.57864376269049" y2="83.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-141.42135623730948" x2="-121.42135623730948" y1="83.57864376269049" y2="83.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-121.42135623730948" x2="-121.42135623730948" y1="83.57864376269049" y2="108.57864376269049"/>
|
||||
<path d="M-104.698326,72.42471 L-126.2677,46.14236 L-111.114044,33.706078 L-89.54468,59.988434 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-104.69832912465773" x2="-126.26770142061496" y1="72.42471683843424" y2="46.142360651090726"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-126.26770142061496" x2="-111.11404660392043" y1="46.142360651090726" y2="33.70607753949096"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-111.11404660392043" x2="-89.5446743079632" y1="33.70607753949096" y2="59.98843372683447"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-89.5446743079632" x2="-104.69832912465773" y1="59.98843372683447" y2="72.42471683843424"/>
|
||||
<path d="M-96.68318,60.704327 L-111.114044,33.706078 L-90.9571,22.931965 L-76.52624,49.930214 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-96.6831819815765" x2="-111.11404660392043" y1="60.7043263162432" y2="33.70607753949096"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-111.11404660392043" x2="-90.95709891346829" y1="33.70607753949096" y2="22.931964532166692"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-90.95709891346829" x2="-76.52623429112435" y1="22.931964532166692" y2="49.93021330891892"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-76.52623429112435" x2="-96.6831819815765" y1="49.93021330891892" y2="60.7043263162432"/>
|
||||
<path d="M-77.84155,47.46943 L-90.9571,22.931965 L-76.53669,15.224093 L-63.42114,39.761555 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-77.84155162648455" x2="-90.95709891346829" y1="47.46942765471458" y2="22.931964532166692"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-90.95709891346829" x2="-76.53668647301795" y1="22.931964532166692" y2="15.224093497742643"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-76.53668647301795" x2="-63.42113918603421" y1="15.224093497742643" y2="39.761556620290534"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-63.42113918603421" x2="-77.84155162648455" y1="39.761556620290534" y2="47.46942765471458"/>
|
||||
<path d="M-67.43769,45.21946 L-76.53669,15.224093 L-58.541893,9.765432 L-49.442898,39.7608 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-67.43769193939679" x2="-76.53668647301795" y1="45.21945862063639" y2="15.224093497742643"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-76.53668647301795" x2="-58.54189292390069" y1="15.224093497742643" y2="9.76543255241912"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-58.54189292390069" x2="-49.442898390279524" y1="9.76543255241912" y2="39.76079767531286"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-49.442898390279524" x2="-67.43769193939679" y1="39.76079767531286" y2="45.21945862063639"/>
|
||||
<path d="M-48.842854,41.738876 L-58.541893,9.765432 L-39.018063,3.842944 L-29.319027,35.816387 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-48.84285499134623" x2="-58.54189292390069" y1="41.73887566778566" y2="9.76543255241912"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-58.54189292390069" x2="-39.01806440322565" y1="9.76543255241912" y2="3.8429439193538997"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-39.01806440322565" x2="-29.319026470671194" y1="3.8429439193538997" y2="35.816387034720435"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-29.319026470671194" x2="-48.84285499134623" y1="35.816387034720435" y2="41.73887566778566"/>
|
||||
<path d="M-35.846466,36.044716 L-39.018063,3.842944 L-20.153395,1.9849361 L-16.981796,34.18671 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.84646650641136" x2="-39.01806440322565" y1="36.04471776669137" y2="3.8429439193538997"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-39.01806440322565" x2="-20.153394239652826" y1="3.8429439193538997" y2="1.9849360810735917"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-20.153394239652826" x2="-16.981796342838535" y1="1.9849360810735917" y2="34.18670992841106"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-16.981796342838535" x2="-35.84646650641136" y1="34.18670992841106" y2="36.04471776669137"/>
|
||||
<path d="M-17.226347,31.703741 L-20.153395,1.9849361 L0,0 L2.9270468,29.718805 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-17.22634748873851" x2="-20.153394239652826" y1="31.70374047560363" y2="1.9849360810735917"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-20.153394239652826" x2="0" y1="1.9849360810735917" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="2.927046750914316" y1="0" y2="29.71880439453004"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="2.927046750914316" x2="-17.22634748873851" y1="29.71880439453004" y2="31.70374047560363"/>
|
||||
<path d="M-2.7981045,28.409632 L0,0 L21.350157,2.1028068 L18.552052,30.512438 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-2.7981044921361704" x2="0" y1="28.40963167099237" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="21.350155898545456" y1="0" y2="2.1028068163419746"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="21.350155898545456" x2="18.552051406409284" y1="2.1028068163419746" y2="30.512438487334343"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="18.552051406409284" x2="-2.7981044921361704" y1="30.512438487334343" y2="28.40963167099237"/>
|
||||
<path d="M18.473928,31.305632 L21.350157,2.1028068 L39.018063,3.842944 L36.141838,33.04577 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="18.473928778980437" x2="21.350155898545456" y1="31.30563083474714" y2="2.1028068163419746"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="21.350155898545456" x2="39.01806440322565" y1="2.1028068163419746" y2="3.8429439193538997"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="39.01806440322565" x2="36.14183728366063" y1="3.8429439193538997" y2="33.04576793775907"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="36.14183728366063" x2="18.473928778980437" y1="33.04576793775907" y2="31.30563083474714"/>
|
||||
<path d="M29.676126,34.639187 L39.018063,3.842944 L55.306503,8.783988 L45.964565,39.58023 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.676126141626234" x2="39.01806440322565" y1="34.63918718302443" y2="3.8429439193538997"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="39.01806440322565" x2="55.30650452687427" y1="3.8429439193538997" y2="8.783988211999482"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="55.30650452687427" x2="45.964566265274854" y1="8.783988211999482" y2="39.58023147567001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="45.964566265274854" x2="29.676126141626234" y1="39.58023147567001" y2="34.63918718302443"/>
|
||||
<path d="M45.436825,41.31996 L55.306503,8.783988 L76.53669,15.224093 L66.66701,47.760067 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="45.436825209937865" x2="55.30650452687427" y1="41.31996058383491" y2="8.783988211999482"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="55.30650452687427" x2="76.53668647301795" y1="8.783988211999482" y2="15.224093497742643"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="76.53668647301795" x2="66.66700715608155" y1="15.224093497742643" y2="47.76006586957808"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="66.66700715608155" x2="45.436825209937865" y1="47.76006586957808" y2="41.31996058383491"/>
|
||||
<path d="M63.186447,40.200634 L76.53669,15.224093 L93.47632,24.278517 L80.12608,49.25506 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.18644721838215" x2="76.53668647301795" y1="40.20063440907146" y2="15.224093497742643"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="76.53668647301795" x2="93.47631974740862" y1="15.224093497742643" y2="24.27851612182704"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="93.47631974740862" x2="80.12608049277281" y1="24.27851612182704" y2="49.25505703315586"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="80.12608049277281" x2="63.18644721838215" y1="49.25505703315586" y2="40.20063440907146"/>
|
||||
<path d="M78.17772,52.90018 L93.47632,24.278517 L111.114044,33.706078 L95.815445,62.327744 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.1777208090943" x2="93.47631974740862" y1="52.90018162015397" y2="24.27851612182704"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="93.47631974740862" x2="111.11404660392043" y1="24.27851612182704" y2="33.70607753949096"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="111.11404660392043" x2="95.8154476656061" y1="33.70607753949096" y2="62.327743037817896"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="95.8154476656061" x2="78.1777208090943" y1="62.327743037817896" y2="52.90018162015397"/>
|
||||
<path d="M90.74086,58.53088 L111.114044,33.706078 L126.2677,46.14236 L105.894516,70.96716 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="90.7408578741026" x2="111.11404660392043" y1="58.53087983424322" y2="33.70607753949096"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="111.11404660392043" x2="126.26770142061496" y1="33.70607753949096" y2="46.142360651090726"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="126.26770142061496" x2="105.89451269079713" y1="46.142360651090726" y2="70.96716294584299"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="105.89451269079713" x2="90.7408578741026" y1="70.96716294584299" y2="58.53087983424322"/>
|
||||
<path d="M121.42136,78.98262 L121.42136,108.57864 L99.49015,108.57864 L99.49015,78.98262 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="121.42135623730948" x2="121.42135623730948" y1="78.98261674535236" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="121.42135623730948" x2="99.49015362260259" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="99.49015362260259" x2="99.49015362260259" y1="108.57864376269049" y2="78.98261674535236"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="99.49015362260259" x2="121.42135623730948" y1="78.98261674535236" y2="78.98261674535236"/>
|
||||
<path d="M99.49015,80.18517 L99.49015,108.57864 L80.528275,108.57864 L80.528275,80.18517 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="99.49015362260259" x2="99.49015362260259" y1="80.18517400362686" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="99.49015362260259" x2="80.52827179289598" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="80.52827179289598" x2="80.52827179289598" y1="108.57864376269049" y2="80.18517400362686"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="80.52827179289598" x2="99.49015362260259" y1="80.18517400362686" y2="80.18517400362686"/>
|
||||
<path d="M80.528275,80.378174 L80.528275,108.57864 L61.465908,108.57864 L61.465908,80.378174 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="80.52827179289598" x2="80.52827179289598" y1="80.37817743225405" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="80.52827179289598" x2="61.46590754151808" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.46590754151808" x2="61.46590754151808" y1="108.57864376269049" y2="80.37817743225405"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="61.46590754151808" x2="80.52827179289598" y1="80.37817743225405" y2="80.37817743225405"/>
|
||||
<path d="M61.465908,74.57864 L61.465908,108.57864 L44.11051,108.57864 L44.11051,74.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.46590754151808" x2="61.46590754151808" y1="74.57864276269049" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="61.46590754151808" x2="44.11051097877353" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.11051097877353" x2="44.11051097877353" y1="108.57864376269049" y2="74.57864276269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="44.11051097877353" x2="61.46590754151808" y1="74.57864276269049" y2="74.57864276269049"/>
|
||||
<path d="M44.11051,78.17331 L44.11051,108.57864 L25.038666,108.57864 L25.038666,78.17331 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.11051097877353" x2="44.11051097877353" y1="78.17331141636416" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="44.11051097877353" x2="25.03866594691874" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="25.03866594691874" x2="25.03866594691874" y1="108.57864376269049" y2="78.17331141636416"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="25.03866594691874" x2="44.11051097877353" y1="78.17331141636416" y2="78.17331141636416"/>
|
||||
<path d="M25.038666,79.174446 L25.038666,108.57864 L2.420242,108.57864 L2.420242,79.174446 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="25.03866594691874" x2="25.03866594691874" y1="79.17444777206498" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="25.03866594691874" x2="2.4202421168091632" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="2.4202421168091632" x2="2.4202421168091632" y1="108.57864376269049" y2="79.17444777206498"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="2.4202421168091632" x2="25.03866594691874" y1="79.17444777206498" y2="79.17444777206498"/>
|
||||
<path d="M2.420242,74.57864 L2.420242,108.57864 L-20.558802,108.57864 L-20.558802,74.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="2.4202421168091632" x2="2.4202421168091632" y1="74.57864276269049" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="2.4202421168091632" x2="-20.558801380058355" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-20.558801380058355" x2="-20.558801380058355" y1="108.57864376269049" y2="74.57864276269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-20.558801380058355" x2="2.4202421168091632" y1="74.57864276269049" y2="74.57864276269049"/>
|
||||
<path d="M-20.558802,79.67424 L-20.558802,108.57864 L-39.86155,108.57864 L-39.86155,79.67424 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-20.558801380058355" x2="-20.558801380058355" y1="79.67424164828014" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-20.558801380058355" x2="-39.86154910109951" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-39.86154910109951" x2="-39.86154910109951" y1="108.57864376269049" y2="79.67424164828014"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-39.86154910109951" x2="-20.558801380058355" y1="79.67424164828014" y2="79.67424164828014"/>
|
||||
<path d="M-39.86155,76.30053 L-39.86155,108.57864 L-58.38272,108.57864 L-58.38272,76.30053 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-39.86154910109951" x2="-39.86154910109951" y1="76.30053248116458" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-39.86154910109951" x2="-58.38272096776976" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-58.38272096776976" x2="-58.38272096776976" y1="108.57864376269049" y2="76.30053248116458"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-58.38272096776976" x2="-39.86154910109951" y1="76.30053248116458" y2="76.30053248116458"/>
|
||||
<path d="M-58.38272,79.101776 L-58.38272,108.57864 L-80.86967,108.57864 L-80.86967,79.101776 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-58.38272096776976" x2="-58.38272096776976" y1="79.1017752456556" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-58.38272096776976" x2="-80.86966768798288" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-80.86966768798288" x2="-80.86966768798288" y1="108.57864376269049" y2="79.1017752456556"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-80.86966768798288" x2="-58.38272096776976" y1="79.1017752456556" y2="79.1017752456556"/>
|
||||
<path d="M-80.86967,74.57864 L-80.86967,108.57864 L-98.31728,108.57864 L-98.31728,74.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-80.86966768798288" x2="-80.86966768798288" y1="74.57864276269049" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-80.86966768798288" x2="-98.3172806944311" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-98.3172806944311" x2="-98.3172806944311" y1="108.57864376269049" y2="74.57864276269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-98.3172806944311" x2="-80.86966768798288" y1="74.57864276269049" y2="74.57864276269049"/>
|
||||
<path d="M-98.31728,74.57864 L-98.31728,108.57864 L-121.42136,108.57864 L-121.42136,74.57864 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-98.3172806944311" x2="-98.3172806944311" y1="74.57864276269049" y2="108.57864376269049"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-98.3172806944311" x2="-121.42135623730948" y1="108.57864376269049" y2="108.57864376269049"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-121.42135623730948" x2="-121.42135623730948" y1="108.57864376269049" y2="74.57864276269049"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-121.42135623730948" x2="-98.3172806944311" y1="74.57864276269049" y2="74.57864276269049"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="141.42135623730948" cy="108.57864376269049" fill="#000000" r="0.7"/>
|
||||
<circle cx="-141.42135623730948" cy="108.57864376269049" fill="#000000" r="0.7"/>
|
||||
<circle cx="-141.42135623730948" cy="58.57864376269049" fill="#000000" r="0.7"/>
|
||||
<circle cx="-111.11404660392043" cy="33.70607753949096" fill="#000000" r="0.7"/>
|
||||
<circle cx="-76.53668647301795" cy="15.224093497742643" fill="#000000" r="0.7"/>
|
||||
<circle cx="-39.01806440322565" cy="3.8429439193538997" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="39.01806440322565" cy="3.8429439193538997" fill="#000000" r="0.7"/>
|
||||
<circle cx="76.53668647301795" cy="15.224093497742643" fill="#000000" r="0.7"/>
|
||||
<circle cx="111.11404660392043" cy="33.70607753949096" fill="#000000" r="0.7"/>
|
||||
<circle cx="141.42135623730948" cy="58.57864376269049" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
BIN
figures/fig_04_y_intersection.pdf
Normal file
243
figures/fig_04_y_intersection.svg
Normal file
@ -0,0 +1,243 @@
|
||||
<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.980762 L0,0 L20,0 L20,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-14.999999999999998" x2="0" y1="25.980762113533164" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="20" y1="0" y2="0"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="20" y1="0" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="-14.999999999999998" y1="30" y2="25.980762113533164"/>
|
||||
<path d="M20,12.990381 L20,0 L42.996502,0 L42.996502,12.990381 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="12.99038105676658" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="12.99038105676658"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="12.99038105676658" y2="12.99038105676658"/>
|
||||
<path d="M42.996502,12.990381 L42.996502,0 L65.47971,0 L65.47971,12.990381 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="12.99038105676658" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="12.99038105676658"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="12.99038105676658" y2="12.99038105676658"/>
|
||||
<path d="M67.5,12.990381 L65.47971,12.990381 L65.47971,0 L90,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="67.5" x2="65.47971305349805" y1="12.99038105676658" y2="12.99038105676658"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="12.99038105676658" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="90" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="90" x2="67.5" y1="0" y2="12.99038105676658"/>
|
||||
<path d="M90,0 L73.583664,9.477974 L68.11156,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="90" x2="73.58366727522163" y1="0" y2="9.477974117757258"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="73.58366727522163" x2="68.11155636696218" y1="9.477974117757258" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="68.11155636696218" x2="90" y1="0" y2="0"/>
|
||||
<path d="M45,0 L68.11156,0 L73.583664,9.477974 L55.575096,19.875227 L44.325096,0.38965538 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="45" x2="68.11155636696218" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="68.11155636696218" x2="73.58366727522163" y1="0" y2="9.477974117757258"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="73.58366727522163" x2="55.57509710703826" y1="9.477974117757258" y2="19.875226952078187"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="55.57509710703826" x2="44.32509710703826" y1="19.875226952078187" y2="0.3896553669283165"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="44.32509710703826" x2="45" y1="0.3896553669283165" y2="0"/>
|
||||
<path d="M44.325096,0.38965538 L55.575096,19.875227 L37.37281,30.384321 L26.122812,10.898749 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.32509710703826" x2="55.57509710703826" y1="0.3896553669283165" y2="19.875226952078187"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="55.57509710703826" x2="37.37281205825939" y1="19.875226952078187" y2="30.384321124856967"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="37.37281205825939" x2="26.12281205825939" y1="30.384321124856967" y2="10.898749539707097"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="26.12281205825939" x2="44.32509710703826" y1="10.898749539707097" y2="0.3896553669283165"/>
|
||||
<path d="M26.122812,10.898749 L37.37281,30.384321 L20.791067,39.957798 L9.541066,20.472225 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="26.12281205825939" x2="37.37281205825939" y1="10.898749539707097" y2="30.384321124856967"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="37.37281205825939" x2="20.791066316395757" y1="30.384321124856967" y2="39.95779649255587"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20.791066316395757" x2="9.541066316395757" y1="39.95779649255587" y2="20.472224907406"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="9.541066316395757" x2="26.12281205825939" y1="20.472224907406" y2="10.898749539707097"/>
|
||||
<path d="M9.541066,20.472225 L20.791067,39.957798 L5.2092485,48.953964 L-6.0407515,29.468391 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="9.541066316395757" x2="20.791066316395757" y1="20.472224907406" y2="39.95779649255587"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20.791066316395757" x2="5.2092487340263744" y1="39.95779649255587" y2="48.95396306820048"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="5.2092487340263744" x2="-6.0407512659736256" y1="48.95396306820048" y2="29.46839148305061"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-6.0407512659736256" x2="9.541066316395757" y1="29.46839148305061" y2="20.472224907406"/>
|
||||
<path d="M-22.5,38.97114 L-6.0407515,29.468391 L5.2092485,48.953964 L-12.245153,59.031265 L-23.163435,40.120247 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.499999999999993" x2="-6.0407512659736256" y1="38.97114317029974" y2="29.46839148305061"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-6.0407512659736256" x2="5.2092487340263744" y1="29.46839148305061" y2="48.95396306820048"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="5.2092487340263744" x2="-12.245153214380935" y1="48.95396306820048" y2="59.03126673165737"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-12.245153214380935" x2="-23.16343547625395" y1="59.03126673165737" y2="40.120247122715256"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-23.16343547625395" x2="-22.499999999999993" y1="40.120247122715256" y2="38.97114317029974"/>
|
||||
<path d="M-23.163435,40.120247 L-12.245153,59.031265 L-30.50305,69.57247 L-35.335365,61.202652 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-23.163435476253955" x2="-12.245153214380935" y1="40.120247122715256" y2="59.03126673165737"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-12.245153214380935" x2="-30.503050418986206" y1="59.03126673165737" y2="69.57246859757274"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-30.503050418986206" x2="-35.3353669459908" y1="69.57246859757274" y2="61.20265085454599"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-35.3353669459908" x2="-23.163435476253955" y1="61.20265085454599" y2="40.120247122715256"/>
|
||||
<path d="M-35.335365,61.202652 L-30.50305,69.57247 L-45,77.94228 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.3353669459908" x2="-30.503050418986206" y1="61.202650854546" y2="69.57246859757274"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-30.503050418986206" x2="-45" y1="69.57246859757274" y2="77.94228634059948"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-35.3353669459908" y1="77.94228634059948" y2="61.202650854546"/>
|
||||
<path d="M-22.5,64.951904 L-45,77.94228 L-33.57214,58.14865 L-22.322138,64.64384 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.499999999999986" x2="-44.999999999999986" y1="64.9519052838329" y2="77.94228634059948"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-44.999999999999986" x2="-33.57213874679279" y1="77.94228634059948" y2="58.14865002819687"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-33.57213874679279" x2="-22.32213874679279" y1="58.14865002819687" y2="64.64384055658016"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.32213874679279" x2="-22.499999999999986" y1="64.64384055658016" y2="64.9519052838329"/>
|
||||
<path d="M-22.322138,64.64384 L-33.57214,58.14865 L-22.822025,39.528908 L-11.572025,46.024097 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.32213874679279" x2="-33.57213874679279" y1="64.64384055658016" y2="58.14865002819687"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-33.57213874679279" x2="-22.82202535134675" y1="58.14865002819687" y2="39.52890744015754"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.82202535134675" x2="-11.572025351346747" y1="39.52890744015754" y2="46.02409796854083"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-11.572025351346747" x2="-22.32213874679279" y1="46.02409796854083" y2="64.64384055658016"/>
|
||||
<path d="M-11.572025,46.024097 L-22.822025,39.528908 L-15,25.980762 L-3.75,32.475952 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-11.572025351346747" x2="-22.82202535134675" y1="46.02409796854083" y2="39.52890744015754"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-22.82202535134675" x2="-14.999999999999996" y1="39.52890744015754" y2="25.98076211353316"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-14.999999999999996" x2="-3.7499999999999947" y1="25.98076211353316" y2="32.47595264191645"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-3.7499999999999947" x2="-11.572025351346747" y1="32.47595264191645" y2="46.02409796854083"/>
|
||||
<path d="M20,0 L0,0 L-15,-25.980762 L2.320508,-35.980762 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="0" y1="0" y2="0"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="-15.000000000000014" y1="0" y2="-25.980762113533153"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-15.000000000000014" x2="2.3205080756887533" y1="-25.980762113533153" y2="-35.98076211353316"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="2.3205080756887533" x2="20" y1="-35.98076211353316" y2="0"/>
|
||||
<path d="M67.5,-12.990381 L90,0 L67.003494,0 L67.003494,-12.990381 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.49999999999999" x2="90" y1="-12.990381056766575" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="90" x2="67.00349662162836" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.00349662162836" x2="67.00349662162836" y1="0" y2="-12.990381056766575"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="67.00349662162836" x2="67.49999999999999" y1="-12.990381056766575" y2="-12.990381056766575"/>
|
||||
<path d="M67.003494,-12.990381 L67.003494,0 L44.520287,0 L44.520287,-12.990381 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="67.00349662162836" x2="67.00349662162836" y1="-12.990381056766575" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="67.00349662162836" x2="44.52028694650196" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.52028694650196" x2="44.52028694650196" y1="0" y2="-12.990381056766575"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="44.52028694650196" x2="67.00349662162836" y1="-12.990381056766575" y2="-12.990381056766575"/>
|
||||
<path d="M44.520287,-12.990381 L44.520287,0 L20,0 L20,-12.990381 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.52028694650196" x2="44.52028694650196" y1="-12.990381056766575" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="44.52028694650196" x2="20" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="0" y2="-12.990381056766575"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="44.52028694650196" y1="-12.990381056766575" y2="-12.990381056766575"/>
|
||||
<path d="M-3.75,-32.475952 L-15,-25.980762 L-24.402254,-42.265945 L-13.152255,-48.761135 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-3.750000000000025" x2="-15.000000000000014" y1="-32.47595264191644" y2="-25.980762113533153"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-15.000000000000014" x2="-24.402254705539438" y1="-25.980762113533153" y2="-42.26594496923097"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-24.402254705539438" x2="-13.152254705539448" y1="-42.26594496923097" y2="-48.76113549761426"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-13.152254705539448" x2="-3.750000000000025" y1="-48.76113549761426" y2="-32.47595264191644"/>
|
||||
<path d="M-22.5,-64.951904 L-13.152255,-48.761135 L-24.402254,-42.265945 L-34.870396,-60.397297 L-24.74079,-66.24563 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.50000000000003" x2="-13.152254705539448" y1="-64.95190528383287" y2="-48.76113549761426"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-13.152254705539448" x2="-24.402254705539438" y1="-48.76113549761426" y2="-42.26594496923097"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-24.402254705539438" x2="-34.87039511076331" y1="-42.26594496923097" y2="-60.39729601184336"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-34.87039511076331" x2="-24.740790221526616" y1="-60.39729601184336" y2="-66.24562612142873"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-24.740790221526616" x2="-22.50000000000003" y1="-66.24562612142873" y2="-64.95190528383287"/>
|
||||
<path d="M-24.74079,-66.24563 L-34.870396,-60.397297 L-45,-77.94228 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-24.740790221526613" x2="-34.87039511076331" y1="-66.24562612142873" y2="-60.39729601184336"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-34.87039511076331" x2="-45.00000000000004" y1="-60.39729601184336" y2="-77.94228634059945"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.00000000000004" x2="-24.740790221526613" y1="-77.94228634059945" y2="-66.24562612142873"/>
|
||||
<path d="M-45,-77.94228 L-30.259056,-69.4316 L-35.172703,-60.92091 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.00000000000004" x2="-30.25905700870268" y1="-77.94228634059945" y2="-69.431598936465"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-30.25905700870268" x2="-35.172704672468456" y1="-69.431598936465" y2="-60.92091153233055"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.172704672468456" x2="-45.00000000000004" y1="-60.92091153233055" y2="-77.94228634059945"/>
|
||||
<path d="M-22.5,-38.97114 L-35.172703,-60.92091 L-30.259056,-69.4316 L-10.41208,-57.972942 L-21.662079,-38.48737 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.500000000000032" x2="-35.172704672468456" y1="-38.97114317029975" y2="-60.92091153233055"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.172704672468456" x2="-30.25905700870268" y1="-60.92091153233055" y2="-69.431598936465"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-30.25905700870268" x2="-10.41207961667945" y1="-69.431598936465" y2="-57.97294119657998"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-10.41207961667945" x2="-21.662079616679435" y1="-57.97294119657998" y2="-38.487369611430125"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-21.662079616679435" x2="-22.500000000000032" y1="-38.487369611430125" y2="-38.97114317029975"/>
|
||||
<path d="M-21.662079,-38.48737 L-10.41208,-57.972942 L7.6761527,-47.529694 L-3.5738473,-28.044125 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-21.662079616679435" x2="-10.41207961667945" y1="-38.487369611430125" y2="-57.97294119657998"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-10.41207961667945" x2="7.676152770599806" y1="-57.97294119657998" y2="-47.529695358619804"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="7.676152770599806" x2="-3.5738472294001795" y1="-47.529695358619804" y2="-28.044123773469945"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-3.5738472294001795" x2="-21.662079616679435" y1="-28.044123773469945" y2="-38.487369611430125"/>
|
||||
<path d="M-3.5738473,-28.044125 L7.6761527,-47.529694 L27.363934,-36.16295 L16.113934,-16.677378 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-3.5738472294001795" x2="7.676152770599806" y1="-28.044123773469945" y2="-47.529695358619804"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="7.676152770599806" x2="27.3639339040313" y1="-47.529695358619804" y2="-36.162949621486696"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="27.3639339040313" x2="16.113933904031313" y1="-36.162949621486696" y2="-16.677378036336837"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="16.113933904031313" x2="-3.5738472294001795" y1="-16.677378036336837" y2="-28.044123773469945"/>
|
||||
<path d="M16.113934,-16.677378 L27.363934,-36.16295 L47.07334,-24.783718 L35.82334,-5.2981467 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="16.113933904031313" x2="27.3639339040313" y1="-16.677378036336837" y2="-36.162949621486696"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="27.3639339040313" x2="47.07334043858461" y1="-36.162949621486696" y2="-24.783718453194588"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="47.07334043858461" x2="35.82334043858462" y1="-24.783718453194588" y2="-5.298146868044729"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="35.82334043858462" x2="16.113933904031313" y1="-5.298146868044729" y2="-16.677378036336837"/>
|
||||
<path d="M45,0 L35.82334,-5.2981467 L47.07334,-24.783718 L63.216145,-15.463665 L54.288197,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="45.00000000000002" x2="35.82334043858462" y1="0" y2="-5.298146868044729"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="35.82334043858462" x2="47.07334043858461" y1="-5.298146868044729" y2="-24.783718453194588"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="47.07334043858461" x2="63.216146085134696" y1="-24.783718453194588" y2="-15.46366526768309"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.216146085134696" x2="54.2881947801796" y1="-15.46366526768309" y2="0"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="54.2881947801796" x2="45.00000000000002" y1="0" y2="0"/>
|
||||
<path d="M54.288197,0 L63.216145,-15.463665 L80.78675,-5.319271 L77.71567,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="54.2881947801796" x2="63.216146085134696" y1="0" y2="-15.46366526768309"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="63.216146085134696" x2="80.78675235361686" y1="-15.46366526768309" y2="-5.319271008749993"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="80.78675235361686" x2="77.71566980482248" y1="-5.319271008749993" y2="0"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="77.71566980482248" x2="54.2881947801796" y1="0" y2="0"/>
|
||||
<path d="M-15,-25.980762 L0,0 L-10,17.320509 L-35.980762,2.320508 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-15.000000000000014" x2="0" y1="-25.980762113533153" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="-9.999999999999998" y1="0" y2="17.320508075688778"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-9.999999999999998" x2="-35.98076211353316" y1="17.320508075688778" y2="2.32050807568878"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.98076211353316" x2="-15.000000000000014" y1="2.32050807568878" y2="-25.980762113533153"/>
|
||||
<path d="M-21.25,10.825317 L-10,17.320509 L-21.427862,37.114143 L-32.67786,30.618954 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-21.250000000000004" x2="-9.999999999999998" y1="10.825317547305488" y2="17.320508075688778"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-9.999999999999998" x2="-21.427861253207194" y1="17.320508075688778" y2="37.11414438809139"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-21.427861253207194" x2="-32.6778612532072" y1="37.11414438809139" y2="30.6189538597081"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-32.6778612532072" x2="-21.250000000000004" y1="30.6189538597081" y2="10.825317547305488"/>
|
||||
<path d="M-32.67786,30.618954 L-21.427862,37.114143 L-32.177975,55.733887 L-43.427975,49.238697 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-32.6778612532072" x2="-21.427861253207194" y1="30.6189538597081" y2="37.11414438809139"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-21.427861253207194" x2="-32.177974648653226" y1="37.11414438809139" y2="55.733886976130705"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-32.177974648653226" x2="-43.42797464865323" y1="55.733886976130705" y2="49.238696447747415"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-43.42797464865323" x2="-32.6778612532072" y1="49.238696447747415" y2="30.6189538597081"/>
|
||||
<path d="M-45,51.961525 L-43.427975,49.238697 L-32.177975,55.733887 L-42.03285,72.803024 L-45,71.08994 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-44.99999999999999" x2="-43.42797464865323" y1="51.96152422706632" y2="49.238696447747415"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-43.42797464865323" x2="-32.177974648653226" y1="49.238696447747415" y2="55.733886976130705"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-32.177974648653226" x2="-42.03284671950401" y1="55.733886976130705" y2="72.80302610493578"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-42.03284671950401" x2="-44.999999999999986" y1="72.80302610493578" y2="71.08993935971455"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-44.999999999999986" x2="-44.99999999999999" y1="71.08993935971455" y2="51.96152422706632"/>
|
||||
<path d="M-45,77.94228 L-45,56.488827 L-32.61384,56.488827 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-44.999999999999986" x2="-44.99999999999999" y1="77.94228634059948" y2="56.48882616749338"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-44.99999999999999" x2="-32.61383899400827" y1="56.48882616749338" y2="56.48882616749337"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-32.61383899400827" x2="-44.999999999999986" y1="56.48882616749337" y2="77.94228634059948"/>
|
||||
<path d="M-22.5,38.97114 L-32.61384,56.488827 L-45,56.488827 L-45,34.366146 L-22.5,34.366146 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.499999999999993" x2="-32.61383899400827" y1="38.97114317029974" y2="56.48882616749337"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-32.61383899400827" x2="-44.99999999999999" y1="56.48882616749337" y2="56.48882616749338"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-44.99999999999999" x2="-45" y1="56.48882616749338" y2="34.36614540874733"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45" x2="-22.499999999999993" y1="34.36614540874733" y2="34.36614540874732"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.499999999999993" x2="-22.499999999999993" y1="34.36614540874732" y2="38.97114317029974"/>
|
||||
<path d="M-22.5,34.366146 L-45,34.366146 L-45,16.205826 L-22.5,16.205826 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.499999999999993" x2="-45" y1="34.36614540874732" y2="34.36614540874733"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45" x2="-45.00000000000001" y1="34.36614540874733" y2="16.205825111234716"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.00000000000001" x2="-22.5" y1="16.205825111234716" y2="16.20582511123471"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.5" x2="-22.499999999999993" y1="16.20582511123471" y2="34.36614540874732"/>
|
||||
<path d="M-22.5,16.205826 L-45,16.205826 L-45,-2.5522678 L-22.5,-2.5522678 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.5" x2="-45.00000000000001" y1="16.20582511123471" y2="16.205825111234716"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.00000000000001" x2="-45.000000000000014" y1="16.205825111234716" y2="-2.5522678857734604"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.000000000000014" x2="-22.500000000000007" y1="-2.5522678857734604" y2="-2.5522678857734684"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.500000000000007" x2="-22.5" y1="-2.5522678857734684" y2="16.20582511123471"/>
|
||||
<path d="M-22.5,-2.5522678 L-45,-2.5522678 L-45,-19.88903 L-22.5,-19.88903 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.500000000000007" x2="-45.000000000000014" y1="-2.5522678857734684" y2="-2.5522678857734604"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.000000000000014" x2="-45.00000000000002" y1="-2.5522678857734604" y2="-19.88903112236116"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.00000000000002" x2="-22.500000000000014" y1="-19.88903112236116" y2="-19.889031122361168"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.500000000000014" x2="-22.500000000000007" y1="-19.889031122361168" y2="-2.5522678857734684"/>
|
||||
<path d="M-22.5,-19.88903 L-45,-19.88903 L-45,-38.21426 L-22.5,-38.21426 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.500000000000014" x2="-45.00000000000002" y1="-19.889031122361168" y2="-19.88903112236116"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.00000000000002" x2="-45.00000000000003" y1="-19.88903112236116" y2="-38.21426049589469"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.00000000000003" x2="-22.50000000000002" y1="-38.21426049589469" y2="-38.2142604958947"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.50000000000002" x2="-22.500000000000014" y1="-38.2142604958947" y2="-19.889031122361168"/>
|
||||
<path d="M-22.5,-38.97114 L-22.5,-38.21426 L-45,-38.21426 L-45,-57.02484 L-32.92331,-57.02484 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-22.50000000000002" x2="-22.50000000000002" y1="-38.971143170299726" y2="-38.2142604958947"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-22.50000000000002" x2="-45.00000000000003" y1="-38.2142604958947" y2="-38.21426049589469"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.00000000000003" x2="-45.000000000000036" y1="-38.21426049589469" y2="-57.0248414835568"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.000000000000036" x2="-32.9233075810273" y1="-57.0248414835568" y2="-57.024841483556806"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-32.9233075810273" x2="-22.50000000000002" y1="-57.024841483556806" y2="-38.971143170299726"/>
|
||||
<path d="M-32.92331,-57.02484 L-45,-57.02484 L-45,-77.94228 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-32.9233075810273" x2="-45.000000000000036" y1="-57.024841483556806" y2="-57.0248414835568"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.000000000000036" x2="-45.00000000000004" y1="-57.0248414835568" y2="-77.94228634059945"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.00000000000004" x2="-32.9233075810273" y1="-77.94228634059945" y2="-57.024841483556806"/>
|
||||
<path d="M-45,-77.94228 L-35.597744,-61.657104 L-45,-56.22871 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-45.00000000000004" x2="-35.597745294460616" y1="-77.94228634059945" y2="-61.65710348490163"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-35.597745294460616" x2="-45.000000000000036" y1="-61.65710348490163" y2="-56.22870919966902"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.000000000000036" x2="-45.00000000000004" y1="-56.22870919966902" y2="-77.94228634059945"/>
|
||||
<path d="M-45,-51.961525 L-45,-56.22871 L-35.597744,-61.657104 L-25.129604,-43.525753 L-36.379604,-37.030563 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-45.000000000000036" x2="-45.000000000000036" y1="-51.96152422706629" y2="-56.22870919966902"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-45.000000000000036" x2="-35.597745294460616" y1="-56.22870919966902" y2="-61.65710348490163"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-35.597745294460616" x2="-25.12960488923674" y1="-61.65710348490163" y2="-43.525752442289246"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-25.12960488923674" x2="-36.379604889236745" y1="-43.525752442289246" y2="-37.03056191390595"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-36.379604889236745" x2="-45.000000000000036" y1="-37.03056191390595" y2="-51.96152422706629"/>
|
||||
<path d="M-36.379604,-37.030563 L-25.129604,-43.525753 L-15,-25.980762 L-26.25,-19.48557 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-36.379604889236745" x2="-25.12960488923674" y1="-37.03056191390595" y2="-43.525752442289246"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="-25.12960488923674" x2="-15.000000000000014" y1="-43.525752442289246" y2="-25.980762113533146"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="-15.000000000000014" x2="-26.250000000000014" y1="-25.980762113533146" y2="-19.48557158514985"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="-26.250000000000014" x2="-36.379604889236745" y1="-19.48557158514985" y2="-37.03056191390595"/>
|
||||
</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>
|
||||
|
After Width: | Height: | Size: 31 KiB |
BIN
figures/fig_06a_road_edit_before.pdf
Normal file
139
figures/fig_06a_road_edit_before.svg
Normal file
@ -0,0 +1,139 @@
|
||||
<svg height="440" viewBox="-5 -5 210 110" width="840" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="110" width="210" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 100) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="200" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="200" x2="200" y1="0" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="200" x2="0" y1="100" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="100" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20,0 L20,30 L0,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<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="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M200,0 L200,30 L180,30 L180,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="200" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="200" x2="180" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="200" y1="0" y2="0"/>
|
||||
<path d="M200,100 L180,100 L180,70 L200,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="180" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="200" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="200" y1="70" y2="100"/>
|
||||
<path d="M0,100 L0,70 L20,70 L20,100 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="70" y2="100"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="100" y2="100"/>
|
||||
<path d="M20,0 L42.996502,0 L42.996502,29.52622 L20,29.52622 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M42.996502,0 L65.47971,0 L65.47971,31.147902 L42.996502,31.147902 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M65.47971,0 L88.27847,0 L88.27847,29.876335 L65.47971,29.876335 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="88.27847104373568" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M88.27847,0 L109.00264,0 L109.00264,30.25849 L88.27847,30.25849 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="88.27847104373568" x2="109.00264275540263" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M109.00264,0 L127.212425,0 L127.212425,34 L109.00264,34 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="109.00264275540263" x2="127.2124223685276" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="34.000001" y2="0"/>
|
||||
<path d="M127.212425,0 L146.8415,0 L146.8415,31.470558 L127.212425,31.470558 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="127.2124223685276" x2="146.84151010926075" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M146.8415,0 L166.40808,0 L166.40808,33.89513 L146.8415,33.89513 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="146.84151010926075" x2="166.4080836096857" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="166.4080836096857" x2="166.4080836096857" y1="0" y2="33.89512833223243"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="166.4080836096857" x2="146.84151010926075" y1="33.89512833223243" y2="33.89512833223243"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="33.89512833223243" y2="0"/>
|
||||
<path d="M166.40808,0 L180,0 L180,29.999052 L166.40808,29.999052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="166.4080836096857" x2="180" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="0" y2="29.999051502429545"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="166.4080836096857" y1="29.999051502429545" y2="29.999051502429545"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="166.4080836096857" x2="166.4080836096857" y1="29.999051502429545" y2="0"/>
|
||||
<path d="M200,30 L200,52.855724 L169.38701,52.855724 L169.38701,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="200" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="169.3870078110646" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="169.3870078110646" x2="169.3870078110646" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="169.3870078110646" x2="200" y1="30" y2="30"/>
|
||||
<path d="M200,52.855724 L200,70 L172.17726,70 L172.17726,52.855724 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="200" y1="52.855722506414395" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="172.17726330629023" y1="70" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="172.17726330629023" x2="172.17726330629023" y1="70" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="172.17726330629023" x2="200" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M180,100 L161.1955,100 L161.1955,72.466 L180,72.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="161.19549058892116" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="100" y2="72.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="161.19549058892116" x2="180" y1="72.46600595599794" y2="72.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="72.46600595599794" y2="100"/>
|
||||
<path d="M161.1955,100 L140.25922,100 L140.25922,68.26361 L161.1955,68.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="161.19549058892116" x2="140.25920977847343" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="100" y2="68.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="140.25920977847343" x2="161.19549058892116" y1="68.26360853604555" y2="68.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="68.26360853604555" y2="100"/>
|
||||
<path d="M140.25922,100 L120.000404,100 L120.000404,66 L140.25922,66 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="140.25920977847343" x2="120.0004046814901" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="100" y2="65.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.0004046814901" x2="140.25920977847343" y1="65.999999" y2="65.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="65.999999" y2="100"/>
|
||||
<path d="M120.000404,100 L98.191284,100 L98.191284,71.2734 L120.000404,71.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.0004046814901" x2="98.19128506754218" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="100" y2="71.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="98.19128506754218" x2="120.0004046814901" y1="71.27339761286972" y2="71.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="71.27339761286972" y2="100"/>
|
||||
<path d="M98.191284,100 L81.11824,100 L81.11824,72.8639 L98.191284,72.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="98.19128506754218" x2="81.11823933536908" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="100" y2="72.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="81.11823933536908" x2="98.19128506754218" y1="72.86389925174167" y2="72.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="72.86389925174167" y2="100"/>
|
||||
<path d="M81.11824,100 L63.12904,100 L63.12904,70.637054 L81.11824,70.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="81.11823933536908" x2="63.129039299600635" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="100" y2="70.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="63.129039299600635" x2="81.11823933536908" y1="70.63705247970552" y2="70.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="70.63705247970552" y2="100"/>
|
||||
<path d="M63.12904,100 L40.141674,100 L40.141674,68.958885 L63.12904,68.958885 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="63.129039299600635" x2="40.14167365815044" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="100" y2="68.95888431009364"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="40.14167365815044" x2="63.129039299600635" y1="68.95888431009364" y2="68.95888431009364"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="68.95888431009364" y2="100"/>
|
||||
<path d="M40.141674,100 L20,100 L20,72.17421 L40.141674,72.17421 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="40.14167365815044" x2="20" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="100" y2="72.17420690790317"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="40.14167365815044" y1="72.17420690790317" y2="72.17420690790317"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="72.17420690790317" y2="100"/>
|
||||
<path d="M0,70 L0,51.044052 L32.357586,51.044052 L32.357586,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="70" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="32.357584460743425" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="32.357584460743425" x2="32.357584460743425" y1="51.04405176448549" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="32.357584460743425" x2="0" y1="70" y2="70"/>
|
||||
<path d="M0,51.044052 L0,30 L29.8626,30 L29.8626,51.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="51.04405176448549" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="30" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="200" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="200" cy="100" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="100" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
figures/fig_06b_road_edit_after.pdf
Normal file
139
figures/fig_06b_road_edit_after.svg
Normal file
@ -0,0 +1,139 @@
|
||||
<svg height="440" viewBox="-5 -5 218 110" width="872" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="110" width="218" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 100) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="208" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="208" x2="200" y1="0" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="200" x2="0" y1="100" y2="100"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="100" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20.8,0 L20,30 L0,30 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="20.8" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20.8" x2="20" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M208,0 L200,30 L180,30 L187.2,0 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="208" x2="200" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="200" x2="180" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="187.20000000000002" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="187.20000000000002" x2="208" y1="0" y2="0"/>
|
||||
<path d="M200,100 L180,100 L180,70 L200,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="200" x2="180" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="200" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="200" x2="200" y1="70" y2="100"/>
|
||||
<path d="M0,100 L0,70 L20,70 L20,100 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="100" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="70" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="70" y2="100"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="100" y2="100"/>
|
||||
<path d="M20.8,0 L44.716362,0 L42.996502,29.52622 L20,29.52622 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20.8" x2="44.71636351350652" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="44.71636351350652" x2="42.99650337837165" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20.8" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M44.716362,0 L68.0989,0 L65.47971,31.147902 L42.996502,31.147902 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="44.71636351350652" x2="68.09890157563797" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="68.09890157563797" x2="65.47971305349805" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="44.71636351350652" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M68.0989,0 L91.80961,0 L88.27847,29.876335 L65.47971,29.876335 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="68.09890157563797" x2="91.80960988548512" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="91.80960988548512" x2="88.27847104373568" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="68.09890157563797" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M91.80961,0 L113.36275,0 L109.00264,30.25849 L88.27847,30.25849 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="91.80960988548512" x2="113.36274846561874" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="113.36274846561874" x2="109.00264275540263" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="91.80960988548512" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M113.36275,0 L132.30092,0 L127.212425,34 L109.00264,34 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="113.36274846561874" x2="132.30091926326872" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="132.30091926326872" x2="127.2124223685276" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="113.36274846561874" y1="34.000001" y2="0"/>
|
||||
<path d="M132.30092,0 L152.71516,0 L146.8415,31.470558 L127.212425,31.470558 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="132.30091926326872" x2="152.71517051363116" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="152.71517051363116" x2="146.84151010926075" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="132.30091926326872" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M152.71516,0 L173.0644,0 L166.40808,33.89513 L146.8415,33.89513 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="152.71517051363116" x2="173.0644069540731" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="173.0644069540731" x2="166.4080836096857" y1="0" y2="33.89512833223243"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="166.4080836096857" x2="146.84151010926075" y1="33.89512833223243" y2="33.89512833223243"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="152.71517051363116" y1="33.89512833223243" y2="0"/>
|
||||
<path d="M173.0644,0 L187.2,0 L180,29.999052 L166.40808,29.999052 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="173.0644069540731" x2="187.20000000000002" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="187.20000000000002" x2="180" y1="0" y2="29.999051502429545"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="166.4080836096857" y1="29.999051502429545" y2="29.999051502429545"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="166.4080836096857" x2="173.0644069540731" y1="29.999051502429545" y2="0"/>
|
||||
<path d="M205.6,30 L203.77155,52.855724 L169.38701,52.855724 L169.38701,30 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="205.6" x2="203.77154219948684" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="203.77154219948684" x2="169.3870078110646" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="169.3870078110646" x2="169.3870078110646" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="169.3870078110646" x2="205.6" y1="30" y2="30"/>
|
||||
<path d="M203.77155,52.855724 L202.4,70 L172.17726,70 L172.17726,52.855724 z" fill="#9fd99a" fill-opacity="0.55" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="203.77154219948684" x2="202.4" y1="52.855722506414395" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="202.4" x2="172.17726330629023" y1="70" y2="70"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="172.17726330629023" x2="172.17726330629023" y1="70" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="172.17726330629023" x2="203.77154219948684" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M180,100 L161.1955,100 L161.1955,72.466 L180,72.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="161.19549058892116" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="100" y2="72.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="161.19549058892116" x2="180" y1="72.46600595599794" y2="72.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="72.46600595599794" y2="100"/>
|
||||
<path d="M161.1955,100 L140.25922,100 L140.25922,68.26361 L161.1955,68.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="161.19549058892116" x2="140.25920977847343" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="100" y2="68.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="140.25920977847343" x2="161.19549058892116" y1="68.26360853604555" y2="68.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="161.19549058892116" x2="161.19549058892116" y1="68.26360853604555" y2="100"/>
|
||||
<path d="M140.25922,100 L120.000404,100 L120.000404,66 L140.25922,66 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="140.25920977847343" x2="120.0004046814901" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="100" y2="65.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.0004046814901" x2="140.25920977847343" y1="65.999999" y2="65.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="140.25920977847343" x2="140.25920977847343" y1="65.999999" y2="100"/>
|
||||
<path d="M120.000404,100 L98.191284,100 L98.191284,71.2734 L120.000404,71.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.0004046814901" x2="98.19128506754218" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="100" y2="71.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="98.19128506754218" x2="120.0004046814901" y1="71.27339761286972" y2="71.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.0004046814901" x2="120.0004046814901" y1="71.27339761286972" y2="100"/>
|
||||
<path d="M98.191284,100 L81.11824,100 L81.11824,72.8639 L98.191284,72.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="98.19128506754218" x2="81.11823933536908" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="100" y2="72.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="81.11823933536908" x2="98.19128506754218" y1="72.86389925174167" y2="72.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="98.19128506754218" x2="98.19128506754218" y1="72.86389925174167" y2="100"/>
|
||||
<path d="M81.11824,100 L63.12904,100 L63.12904,70.637054 L81.11824,70.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="81.11823933536908" x2="63.129039299600635" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="100" y2="70.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="63.129039299600635" x2="81.11823933536908" y1="70.63705247970552" y2="70.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="81.11823933536908" x2="81.11823933536908" y1="70.63705247970552" y2="100"/>
|
||||
<path d="M63.12904,100 L40.141674,100 L40.141674,68.958885 L63.12904,68.958885 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="63.129039299600635" x2="40.14167365815044" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="100" y2="68.95888431009364"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="40.14167365815044" x2="63.129039299600635" y1="68.95888431009364" y2="68.95888431009364"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="63.129039299600635" x2="63.129039299600635" y1="68.95888431009364" y2="100"/>
|
||||
<path d="M40.141674,100 L20,100 L20,72.17421 L40.141674,72.17421 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="40.14167365815044" x2="20" y1="100" y2="100"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="100" y2="72.17420690790317"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="40.14167365815044" y1="72.17420690790317" y2="72.17420690790317"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="40.14167365815044" x2="40.14167365815044" y1="72.17420690790317" y2="100"/>
|
||||
<path d="M0,70 L0,51.044052 L32.357586,51.044052 L32.357586,70 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="70" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="32.357584460743425" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="32.357584460743425" x2="32.357584460743425" y1="51.04405176448549" y2="70"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="32.357584460743425" x2="0" y1="70" y2="70"/>
|
||||
<path d="M0,51.044052 L0,30 L29.8626,30 L29.8626,51.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="51.04405176448549" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="30" y2="51.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="51.04405176448549" y2="51.04405176448549"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="208" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="200" cy="100" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="100" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
BIN
figures/fig_07_regularity_slider_rho_0_0.pdf
Normal file
134
figures/fig_07_regularity_slider_rho_0_0.svg
Normal file
@ -0,0 +1,134 @@
|
||||
<svg height="480" viewBox="-5 -5 190 120" width="760" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="120" width="190" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 110) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="180" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="180" y1="0" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="0" y1="110" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="110" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20,0 L20,30 L0,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<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="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M180,0 L180,30 L160,30 L160,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="160" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="180" y1="0" y2="0"/>
|
||||
<path d="M180,110 L160,110 L160,80 L180,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="160" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="180" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="80" y2="110"/>
|
||||
<path d="M0,110 L0,80 L20,80 L20,110 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="80" y2="110"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="110" y2="110"/>
|
||||
<path d="M20,0 L42.996502,0 L42.996502,27.409153 L20,27.409153 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="27.409153569625865"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="27.409153569625865" y2="27.409153569625865"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="27.409153569625865" y2="0"/>
|
||||
<path d="M42.996502,0 L65.47971,0 L65.47971,29.52622 L42.996502,29.52622 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M65.47971,0 L88.27847,0 L88.27847,31.147902 L65.47971,31.147902 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="88.27847104373568" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M88.27847,0 L109.00264,0 L109.00264,29.876335 L88.27847,29.876335 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="88.27847104373568" x2="109.00264275540263" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M109.00264,0 L127.212425,0 L127.212425,30.25849 L109.00264,30.25849 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="109.00264275540263" x2="127.2124223685276" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M127.212425,0 L146.8415,0 L146.8415,34 L127.212425,34 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="127.2124223685276" x2="146.84151010926075" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="34.000001" y2="0"/>
|
||||
<path d="M146.8415,0 L160,0 L160,31.470558 L146.8415,31.470558 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="146.84151010926075" x2="160" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="146.84151010926075" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M180,30 L180,52.855724 L152.17726,52.855724 L152.17726,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="152.17726330629023" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="152.17726330629023" x2="152.17726330629023" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="152.17726330629023" x2="180" y1="30" y2="30"/>
|
||||
<path d="M180,52.855724 L180,74.35595 L151.5346,74.35595 L151.5346,52.855724 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="52.855722506414395" y2="74.35594929730647"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="151.5346047936249" y1="74.35594929730647" y2="74.35594929730647"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="151.5346047936249" x2="151.5346047936249" y1="74.35594929730647" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="151.5346047936249" x2="180" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M160,110 L141.1955,110 L141.1955,76.1546 L160,76.1546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="141.19549058892116" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="110" y2="76.1546017562395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="141.19549058892116" x2="160" y1="76.1546017562395" y2="76.1546017562395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="76.1546017562395" y2="110"/>
|
||||
<path d="M141.1955,110 L120.25921,110 L120.25921,82.466 L141.1955,82.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="141.19549058892116" x2="120.25920977847343" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="110" y2="82.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.25920977847343" x2="141.19549058892116" y1="82.46600595599794" y2="82.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="82.46600595599794" y2="110"/>
|
||||
<path d="M120.25921,110 L100.000404,110 L100.000404,78.26361 L120.25921,78.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.25920977847343" x2="100.0004046814901" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="110" y2="78.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="100.0004046814901" x2="120.25920977847343" y1="78.26360853604555" y2="78.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="78.26360853604555" y2="110"/>
|
||||
<path d="M100.000404,110 L78.191284,110 L78.191284,76 L100.000404,76 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="100.0004046814901" x2="78.19128506754218" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="110" y2="75.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="78.19128506754218" x2="100.0004046814901" y1="75.999999" y2="75.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="75.999999" y2="110"/>
|
||||
<path d="M78.191284,110 L61.11824,110 L61.11824,81.2734 L78.191284,81.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="78.19128506754218" x2="61.11823933536908" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="110" y2="81.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="61.11823933536908" x2="78.19128506754218" y1="81.27339761286972" y2="81.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="81.27339761286972" y2="110"/>
|
||||
<path d="M61.11824,110 L43.12904,110 L43.12904,82.8639 L61.11824,82.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="61.11823933536908" x2="43.129039299600635" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="110" y2="82.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="43.129039299600635" x2="61.11823933536908" y1="82.86389925174167" y2="82.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="82.86389925174167" y2="110"/>
|
||||
<path d="M43.12904,110 L20,110 L20,80.637054 L43.12904,80.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="43.129039299600635" x2="20" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="110" y2="80.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="43.129039299600635" y1="80.63705247970552" y2="80.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="80.63705247970552" y2="110"/>
|
||||
<path d="M0,80 L0,61.044052 L29.8626,61.044052 L29.8626,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="80" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="61.04405176448549" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="80" y2="80"/>
|
||||
<path d="M0,61.044052 L0,40.249546 L28.32311,40.249546 L28.32311,61.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="61.04405176448549" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="28.323110868385612" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="28.323110868385612" x2="28.323110868385612" y1="40.24954609584363" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="28.323110868385612" x2="0" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<path d="M0,40.249546 L0,30 L31.206142,30 L31.206142,40.249546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="40.24954609584363" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="31.206143102551692" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="31.206143102551692" x2="31.206143102551692" y1="30" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="31.206143102551692" x2="0" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="110" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="110" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
figures/fig_07_regularity_slider_rho_0_5.pdf
Normal file
134
figures/fig_07_regularity_slider_rho_0_5.svg
Normal file
@ -0,0 +1,134 @@
|
||||
<svg height="480" viewBox="-5 -5 190 120" width="760" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="120" width="190" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 110) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="180" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="180" y1="0" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="0" y1="110" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="110" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20,0 L20,30 L0,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<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="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M180,0 L180,30 L160,30 L160,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="160" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="180" y1="0" y2="0"/>
|
||||
<path d="M180,110 L160,110 L160,80 L180,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="160" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="180" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="80" y2="110"/>
|
||||
<path d="M0,110 L0,80 L20,80 L20,110 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="80" y2="110"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="110" y2="110"/>
|
||||
<path d="M20,0 L42.996502,0 L42.996502,27.409153 L20,27.409153 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="27.409153569625865"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="27.409153569625865" y2="27.409153569625865"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="27.409153569625865" y2="0"/>
|
||||
<path d="M42.996502,0 L65.47971,0 L65.47971,29.52622 L42.996502,29.52622 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M65.47971,0 L88.27847,0 L88.27847,31.147902 L65.47971,31.147902 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="88.27847104373568" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M88.27847,0 L109.00264,0 L109.00264,29.876335 L88.27847,29.876335 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="88.27847104373568" x2="109.00264275540263" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M109.00264,0 L127.212425,0 L127.212425,30.25849 L109.00264,30.25849 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="109.00264275540263" x2="127.2124223685276" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M127.212425,0 L146.8415,0 L146.8415,34 L127.212425,34 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="127.2124223685276" x2="146.84151010926075" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="34.000001" y2="0"/>
|
||||
<path d="M146.8415,0 L160,0 L160,31.470558 L146.8415,31.470558 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="146.84151010926075" x2="160" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="146.84151010926075" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M180,30 L180,52.855724 L152.17726,52.855724 L152.17726,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="152.17726330629023" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="152.17726330629023" x2="152.17726330629023" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="152.17726330629023" x2="180" y1="30" y2="30"/>
|
||||
<path d="M180,52.855724 L180,74.35595 L151.5346,74.35595 L151.5346,52.855724 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="52.855722506414395" y2="74.35594929730647"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="151.5346047936249" y1="74.35594929730647" y2="74.35594929730647"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="151.5346047936249" x2="151.5346047936249" y1="74.35594929730647" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="151.5346047936249" x2="180" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M160,110 L141.1955,110 L141.1955,76.1546 L160,76.1546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="141.19549058892116" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="110" y2="76.1546017562395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="141.19549058892116" x2="160" y1="76.1546017562395" y2="76.1546017562395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="76.1546017562395" y2="110"/>
|
||||
<path d="M141.1955,110 L120.25921,110 L120.25921,82.466 L141.1955,82.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="141.19549058892116" x2="120.25920977847343" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="110" y2="82.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.25920977847343" x2="141.19549058892116" y1="82.46600595599794" y2="82.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="82.46600595599794" y2="110"/>
|
||||
<path d="M120.25921,110 L100.000404,110 L100.000404,78.26361 L120.25921,78.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.25920977847343" x2="100.0004046814901" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="110" y2="78.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="100.0004046814901" x2="120.25920977847343" y1="78.26360853604555" y2="78.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="78.26360853604555" y2="110"/>
|
||||
<path d="M100.000404,110 L78.191284,110 L78.191284,76 L100.000404,76 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="100.0004046814901" x2="78.19128506754218" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="110" y2="75.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="78.19128506754218" x2="100.0004046814901" y1="75.999999" y2="75.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="75.999999" y2="110"/>
|
||||
<path d="M78.191284,110 L61.11824,110 L61.11824,81.2734 L78.191284,81.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="78.19128506754218" x2="61.11823933536908" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="110" y2="81.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="61.11823933536908" x2="78.19128506754218" y1="81.27339761286972" y2="81.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="81.27339761286972" y2="110"/>
|
||||
<path d="M61.11824,110 L43.12904,110 L43.12904,82.8639 L61.11824,82.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="61.11823933536908" x2="43.129039299600635" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="110" y2="82.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="43.129039299600635" x2="61.11823933536908" y1="82.86389925174167" y2="82.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="82.86389925174167" y2="110"/>
|
||||
<path d="M43.12904,110 L20,110 L20,80.637054 L43.12904,80.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="43.129039299600635" x2="20" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="110" y2="80.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="43.129039299600635" y1="80.63705247970552" y2="80.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="80.63705247970552" y2="110"/>
|
||||
<path d="M0,80 L0,61.044052 L29.8626,61.044052 L29.8626,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="80" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="61.04405176448549" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="80" y2="80"/>
|
||||
<path d="M0,61.044052 L0,40.249546 L28.32311,40.249546 L28.32311,61.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="61.04405176448549" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="28.323110868385612" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="28.323110868385612" x2="28.323110868385612" y1="40.24954609584363" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="28.323110868385612" x2="0" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<path d="M0,40.249546 L0,30 L31.206142,30 L31.206142,40.249546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="40.24954609584363" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="31.206143102551692" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="31.206143102551692" x2="31.206143102551692" y1="30" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="31.206143102551692" x2="0" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="110" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="110" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
figures/fig_07_regularity_slider_rho_1_0.pdf
Normal file
134
figures/fig_07_regularity_slider_rho_1_0.svg
Normal file
@ -0,0 +1,134 @@
|
||||
<svg height="480" viewBox="-5 -5 190 120" width="760" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="#ffffff" height="120" width="190" x="-5" y="-5"/>
|
||||
<g transform="translate(0, 110) scale(1, -1)">
|
||||
<g id="roads">
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="180" y1="0" y2="0"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="180" y1="0" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="180" x2="0" y1="110" y2="110"/>
|
||||
<line stroke="#000000" stroke-linecap="round" stroke-width="0.6" x1="0" x2="0" y1="110" y2="0"/>
|
||||
</g>
|
||||
<g id="parcels">
|
||||
<path d="M0,0 L20,0 L20,30 L0,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<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="0" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="30" y2="0"/>
|
||||
<path d="M180,0 L180,30 L160,30 L160,0 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="0" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="180" x2="160" y1="30" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="30" y2="0"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="180" y1="0" y2="0"/>
|
||||
<path d="M180,110 L160,110 L160,80 L180,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="160" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="180" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="180" y1="80" y2="110"/>
|
||||
<path d="M0,110 L0,80 L20,80 L20,110 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="0" y1="110" y2="80"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="0" x2="20" y1="80" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="80" y2="110"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="0" y1="110" y2="110"/>
|
||||
<path d="M20,0 L42.996502,0 L42.996502,27.409153 L20,27.409153 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="20" x2="42.99650337837165" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="0" y2="27.409153569625865"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="42.99650337837165" x2="20" y1="27.409153569625865" y2="27.409153569625865"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="27.409153569625865" y2="0"/>
|
||||
<path d="M42.996502,0 L65.47971,0 L65.47971,29.52622 L42.996502,29.52622 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="42.99650337837165" x2="65.47971305349805" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="0" y2="29.526220147024308"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="65.47971305349805" x2="42.99650337837165" y1="29.526220147024308" y2="29.526220147024308"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="42.99650337837165" x2="42.99650337837165" y1="29.526220147024308" y2="0"/>
|
||||
<path d="M65.47971,0 L88.27847,0 L88.27847,31.147902 L65.47971,31.147902 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="65.47971305349805" x2="88.27847104373568" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="0" y2="31.1479024543553"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="88.27847104373568" x2="65.47971305349805" y1="31.1479024543553" y2="31.1479024543553"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="65.47971305349805" x2="65.47971305349805" y1="31.1479024543553" y2="0"/>
|
||||
<path d="M88.27847,0 L109.00264,0 L109.00264,29.876335 L88.27847,29.876335 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="88.27847104373568" x2="109.00264275540263" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="0" y2="29.87633532437634"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="109.00264275540263" x2="88.27847104373568" y1="29.87633532437634" y2="29.87633532437634"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="88.27847104373568" x2="88.27847104373568" y1="29.87633532437634" y2="0"/>
|
||||
<path d="M109.00264,0 L127.212425,0 L127.212425,30.25849 L109.00264,30.25849 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="109.00264275540263" x2="127.2124223685276" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="0" y2="30.25848985257909"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="127.2124223685276" x2="109.00264275540263" y1="30.25848985257909" y2="30.25848985257909"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="109.00264275540263" x2="109.00264275540263" y1="30.25848985257909" y2="0"/>
|
||||
<path d="M127.212425,0 L146.8415,0 L146.8415,34 L127.212425,34 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="127.2124223685276" x2="146.84151010926075" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="0" y2="34.000001"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="146.84151010926075" x2="127.2124223685276" y1="34.000001" y2="34.000001"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="127.2124223685276" x2="127.2124223685276" y1="34.000001" y2="0"/>
|
||||
<path d="M146.8415,0 L160,0 L160,31.470558 L146.8415,31.470558 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="146.84151010926075" x2="160" y1="0" y2="0"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="0" y2="31.47055834801727"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="160" x2="146.84151010926075" y1="31.47055834801727" y2="31.47055834801727"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="146.84151010926075" x2="146.84151010926075" y1="31.47055834801727" y2="0"/>
|
||||
<path d="M180,30 L180,52.855724 L152.17726,52.855724 L152.17726,30 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="30" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="152.17726330629023" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="152.17726330629023" x2="152.17726330629023" y1="52.855722506414395" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="152.17726330629023" x2="180" y1="30" y2="30"/>
|
||||
<path d="M180,52.855724 L180,74.35595 L151.5346,74.35595 L151.5346,52.855724 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="180" x2="180" y1="52.855722506414395" y2="74.35594929730647"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="180" x2="151.5346047936249" y1="74.35594929730647" y2="74.35594929730647"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="151.5346047936249" x2="151.5346047936249" y1="74.35594929730647" y2="52.855722506414395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="151.5346047936249" x2="180" y1="52.855722506414395" y2="52.855722506414395"/>
|
||||
<path d="M160,110 L141.1955,110 L141.1955,76.1546 L160,76.1546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="160" x2="141.19549058892116" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="110" y2="76.1546017562395"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="141.19549058892116" x2="160" y1="76.1546017562395" y2="76.1546017562395"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="160" x2="160" y1="76.1546017562395" y2="110"/>
|
||||
<path d="M141.1955,110 L120.25921,110 L120.25921,82.466 L141.1955,82.466 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="141.19549058892116" x2="120.25920977847343" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="110" y2="82.46600595599794"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="120.25920977847343" x2="141.19549058892116" y1="82.46600595599794" y2="82.46600595599794"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="141.19549058892116" x2="141.19549058892116" y1="82.46600595599794" y2="110"/>
|
||||
<path d="M120.25921,110 L100.000404,110 L100.000404,78.26361 L120.25921,78.26361 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="120.25920977847343" x2="100.0004046814901" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="110" y2="78.26360853604555"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="100.0004046814901" x2="120.25920977847343" y1="78.26360853604555" y2="78.26360853604555"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="120.25920977847343" x2="120.25920977847343" y1="78.26360853604555" y2="110"/>
|
||||
<path d="M100.000404,110 L78.191284,110 L78.191284,76 L100.000404,76 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="100.0004046814901" x2="78.19128506754218" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="110" y2="75.999999"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="78.19128506754218" x2="100.0004046814901" y1="75.999999" y2="75.999999"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="100.0004046814901" x2="100.0004046814901" y1="75.999999" y2="110"/>
|
||||
<path d="M78.191284,110 L61.11824,110 L61.11824,81.2734 L78.191284,81.2734 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="78.19128506754218" x2="61.11823933536908" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="110" y2="81.27339761286972"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="61.11823933536908" x2="78.19128506754218" y1="81.27339761286972" y2="81.27339761286972"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="78.19128506754218" x2="78.19128506754218" y1="81.27339761286972" y2="110"/>
|
||||
<path d="M61.11824,110 L43.12904,110 L43.12904,82.8639 L61.11824,82.8639 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="61.11823933536908" x2="43.129039299600635" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="110" y2="82.86389925174167"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="43.129039299600635" x2="61.11823933536908" y1="82.86389925174167" y2="82.86389925174167"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="61.11823933536908" x2="61.11823933536908" y1="82.86389925174167" y2="110"/>
|
||||
<path d="M43.12904,110 L20,110 L20,80.637054 L43.12904,80.637054 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="43.129039299600635" x2="20" y1="110" y2="110"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="20" x2="20" y1="110" y2="80.63705247970552"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="20" x2="43.129039299600635" y1="80.63705247970552" y2="80.63705247970552"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="43.129039299600635" x2="43.129039299600635" y1="80.63705247970552" y2="110"/>
|
||||
<path d="M0,80 L0,61.044052 L29.8626,61.044052 L29.8626,80 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="80" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="29.862600980530416" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="29.862600980530416" x2="29.862600980530416" y1="61.04405176448549" y2="80"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="29.862600980530416" x2="0" y1="80" y2="80"/>
|
||||
<path d="M0,61.044052 L0,40.249546 L28.32311,40.249546 L28.32311,61.044052 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="61.04405176448549" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="28.323110868385612" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="28.323110868385612" x2="28.323110868385612" y1="40.24954609584363" y2="61.04405176448549"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="28.323110868385612" x2="0" y1="61.04405176448549" y2="61.04405176448549"/>
|
||||
<path d="M0,40.249546 L0,30 L31.206142,30 L31.206142,40.249546 z" fill="#fff7c2" fill-opacity="0.3" stroke="none"/>
|
||||
<line stroke="#1f5fb4" stroke-width="0.9" x1="0" x2="0" y1="40.24954609584363" y2="30"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="0" x2="31.206143102551692" y1="30" y2="30"/>
|
||||
<line stroke="#bdbdbd" stroke-dasharray="1.6,1.2" stroke-width="0.4" x1="31.206143102551692" x2="31.206143102551692" y1="30" y2="40.24954609584363"/>
|
||||
<line stroke="#6b6b6b" stroke-width="0.4" x1="31.206143102551692" x2="0" y1="40.24954609584363" y2="40.24954609584363"/>
|
||||
</g>
|
||||
<g id="nodes">
|
||||
<circle cx="0" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="0" fill="#000000" r="0.7"/>
|
||||
<circle cx="180" cy="110" fill="#000000" r="0.7"/>
|
||||
<circle cx="0" cy="110" fill="#000000" r="0.7"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
149
journal.aux
Normal file
@ -0,0 +1,149 @@
|
||||
\relax
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\providecommand\HyField@AuxAddToFields[1]{}
|
||||
\providecommand\HyField@AuxAddToCoFields[2]{}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {1}Project Context and Motivation}{3}{section.1}\protected@file@percent }
|
||||
\newlabel{sec:context}{{1}{3}{Project Context and Motivation}{section.1}{}}
|
||||
\newlabel{sec:context@cref}{{[section][1][]1}{[1][3][]3}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Why Build This}{3}{subsection.1.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Scope of This Document}{3}{subsection.1.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Audience}{3}{subsection.1.3}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Core Invariants}{3}{section.2}\protected@file@percent }
|
||||
\newlabel{sec:invariants}{{2}{3}{Core Invariants}{section.2}{}}
|
||||
\newlabel{sec:invariants@cref}{{[section][2][]2}{[1][3][]3}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {3}Geometric Foundations}{4}{section.3}\protected@file@percent }
|
||||
\newlabel{sec:geometry}{{3}{4}{Geometric Foundations}{section.3}{}}
|
||||
\newlabel{sec:geometry@cref}{{[section][3][]3}{[1][4][]4}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Coordinate System and Numerical Type}{4}{subsection.3.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Road Network as a Planar Graph}{4}{subsection.3.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Block Extraction}{5}{subsection.3.3}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}Inward Offsetting}{5}{subsection.3.4}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {4}Subdivision Algorithm}{5}{section.4}\protected@file@percent }
|
||||
\newlabel{sec:subdivision}{{4}{5}{Subdivision Algorithm}{section.4}{}}
|
||||
\newlabel{sec:subdivision@cref}{{[section][4][]4}{[1][5][]5}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Frontage-First Subdivision}{5}{subsection.4.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Inputs.}{5}{subsection.4.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Procedure.}{5}{subsection.4.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Edge Classification}{6}{subsection.4.2}\protected@file@percent }
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Edge classification scheme.}}{6}{table.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Regularization Pass}{6}{subsection.4.3}\protected@file@percent }
|
||||
\newlabel{sec:regularization}{{4.3}{6}{Regularization Pass}{subsection.4.3}{}}
|
||||
\newlabel{sec:regularization@cref}{{[subsection][3][4]4.3}{[1][6][]6}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {5}Road Edit Handling}{6}{section.5}\protected@file@percent }
|
||||
\newlabel{sec:edit-handling}{{5}{6}{Road Edit Handling}{section.5}{}}
|
||||
\newlabel{sec:edit-handling@cref}{{[section][5][]5}{[1][6][]6}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Edit Types}{7}{subsection.5.1}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}Road edit enum.}{7}{lstlisting.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Deformation Pipeline}{7}{subsection.5.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}Regeneration Thresholds}{7}{subsection.5.3}\protected@file@percent }
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Thresholds that trigger regeneration or condemnation. $\alpha _{\max }$ defaults to $30^\circ $.}}{7}{table.2}\protected@file@percent }
|
||||
\gdef \LT@i {\LT@entry
|
||||
{1}{140.0374pt}\LT@entry
|
||||
{1}{182.71652pt}\LT@entry
|
||||
{1}{111.58464pt}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.4}Determinism and Idempotence}{8}{subsection.5.4}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.5}Building Footprint Preservation}{8}{subsection.5.5}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}Building persistence hook.}{8}{lstlisting.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {6}Degenerate Cases}{8}{section.6}\protected@file@percent }
|
||||
\newlabel{sec:degenerate}{{6}{8}{Degenerate Cases}{section.6}{}}
|
||||
\newlabel{sec:degenerate@cref}{{[section][6][]6}{[1][8][]8}{}{}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {3}{Required degenerate-case tests. Each must exist by name and pass.}}{9}{table.3}\protected@file@percent }
|
||||
\newlabel{tab:degenerate}{{3}{9}{Required degenerate-case tests. Each must exist by name and pass}{table.3}{}}
|
||||
\newlabel{tab:degenerate@cref}{{[table][3][]3}{[1][8][]9}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {7}Crate Architecture}{9}{section.7}\protected@file@percent }
|
||||
\newlabel{sec:architecture}{{7}{9}{Crate Architecture}{section.7}{}}
|
||||
\newlabel{sec:architecture@cref}{{[section][7][]7}{[1][9][]9}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {7.1}Module Layout}{9}{subsection.7.1}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}Crate structure.}{9}{lstlisting.3}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {7.2}Public API Surface}{10}{subsection.7.2}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {4}Public API in \texttt {lib.rs}.}{10}{lstlisting.4}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {7.3}Error Types}{10}{subsection.7.3}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {5}Error enum.}{10}{lstlisting.5}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {7.4}Dependencies}{11}{subsection.7.4}\protected@file@percent }
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {4}{\ignorespaces Dependency manifest.}}{11}{table.4}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {8}Idiomatic Rust Requirements}{11}{section.8}\protected@file@percent }
|
||||
\newlabel{sec:idioms}{{8}{11}{Idiomatic Rust Requirements}{section.8}{}}
|
||||
\newlabel{sec:idioms@cref}{{[section][8][]8}{[1][11][]11}{}{}{}}
|
||||
\gdef \LT@ii {\LT@entry
|
||||
{2}{168.13437pt}\LT@entry
|
||||
{2}{188.11266pt}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {9}Testing Strategy}{12}{section.9}\protected@file@percent }
|
||||
\newlabel{sec:testing}{{9}{12}{Testing Strategy}{section.9}{}}
|
||||
\newlabel{sec:testing@cref}{{[section][9][]9}{[1][12][]12}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {9.1}Three Layers}{12}{subsection.9.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Unit tests}{12}{subsection.9.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Integration tests}{12}{subsection.9.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Property tests}{12}{subsection.9.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {9.2}Snapshot Testing}{12}{subsection.9.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {9.3}Coverage Requirement}{12}{subsection.9.3}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {10}Visualization and Figures}{12}{section.10}\protected@file@percent }
|
||||
\newlabel{sec:figures}{{10}{12}{Visualization and Figures}{section.10}{}}
|
||||
\newlabel{sec:figures@cref}{{[section][10][]10}{[1][12][]12}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {10.1}Required Figures}{12}{subsection.10.1}\protected@file@percent }
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {5}{Required figure deliverables.}}{13}{table.5}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {10.2}Color Conventions}{13}{subsection.10.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {10.3}Inclusion in This Journal}{13}{subsection.10.3}\protected@file@percent }
|
||||
\@writefile{lol}{\contentsline {lstlisting}{\numberline {6}Including a generated figure.}{13}{lstlisting.6}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {11}Performance Targets}{13}{section.11}\protected@file@percent }
|
||||
\newlabel{sec:performance}{{11}{13}{Performance Targets}{section.11}{}}
|
||||
\newlabel{sec:performance@cref}{{[section][11][]11}{[1][13][]13}{}{}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {6}{\ignorespaces Performance targets. Measured via Criterion.}}{13}{table.6}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {12}Out of Scope}{13}{section.12}\protected@file@percent }
|
||||
\newlabel{sec:oos}{{12}{13}{Out of Scope}{section.12}{}}
|
||||
\newlabel{sec:oos@cref}{{[section][12][]12}{[1][13][]13}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {13}Claude Code Contract}{14}{section.13}\protected@file@percent }
|
||||
\newlabel{sec:contract}{{13}{14}{Claude Code Contract}{section.13}{}}
|
||||
\newlabel{sec:contract@cref}{{[section][13][]13}{[1][14][]14}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {14}Open Questions}{15}{section.14}\protected@file@percent }
|
||||
\newlabel{sec:open}{{14}{15}{Open Questions}{section.14}{}}
|
||||
\newlabel{sec:open@cref}{{[section][14][]14}{[1][15][]15}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {15}Design Decisions}{15}{section.15}\protected@file@percent }
|
||||
\newlabel{sec:decisions}{{15}{15}{Design Decisions}{section.15}{}}
|
||||
\newlabel{sec:decisions@cref}{{[section][15][]15}{[1][15][]15}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {16}Revisions and Deviations}{16}{section.16}\protected@file@percent }
|
||||
\newlabel{sec:revisions}{{16}{16}{Revisions and Deviations}{section.16}{}}
|
||||
\newlabel{sec:revisions@cref}{{[section][16][]16}{[1][16][]16}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {16.1}2026-04-25 --- Session 1: Milestone 0.1, rectangle end-to-end}{16}{subsection.16.1}\protected@file@percent }
|
||||
\newlabel{sec:session-1}{{16.1}{16}{2026-04-25 --- Session 1: Milestone 0.1, rectangle end-to-end}{subsection.16.1}{}}
|
||||
\newlabel{sec:session-1@cref}{{[subsection][1][16]16.1}{[1][16][]16}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {paragraph}{Goal of the session.}{16}{subsection.16.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{What got built.}{17}{subsection.16.1}\protected@file@percent }
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces The first figure produced by the crate: a $200 \times 100$ rectangular block subdivided at default parameters ($w_f=20$, $d_p=30$, $d_s=1$, $\rho =0$). Roads in black; parcel frontage edges in blue, side edges gray, back edges light-gray dashed. Corner pie-slice parcels are the bisector-clipped triangles at each block corner. The empty central strip is the medial gap: the block's vertical extent ($100$\,m) exceeds $2 d_p$, so the depth cap stops parcels short of the centerline. Generated by \texttt {cargo run --example generate\_figures --features viz}.}}{17}{figure.1}\protected@file@percent }
|
||||
\newlabel{fig:grid-block}{{1}{17}{The first figure produced by the crate: a $200 \times 100$ rectangular block subdivided at default parameters ($w_f=20$, $d_p=30$, $d_s=1$, $\rho =0$). Roads in black; parcel frontage edges in blue, side edges gray, back edges light-gray dashed. Corner pie-slice parcels are the bisector-clipped triangles at each block corner. The empty central strip is the medial gap: the block's vertical extent ($100$\,m) exceeds $2 d_p$, so the depth cap stops parcels short of the centerline. Generated by \texttt {cargo run --example generate\_figures --features viz}}{figure.1}{}}
|
||||
\newlabel{fig:grid-block@cref}{{[figure][1][]1}{[1][17][]17}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {paragraph}{Tooling gates.}{17}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Test status.}{17}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Design decisions locked in this session.}{18}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Spec deviations recorded this session.}{18}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Open questions touched.}{20}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Next session --- milestone 0.2 queue.}{20}{figure.1}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {16.2}2026-04-25 --- Session 2: Milestone 0.2 (corner parcels, sticky back edges, preserve-on-deform)}{20}{subsection.16.2}\protected@file@percent }
|
||||
\newlabel{sec:session-2}{{16.2}{20}{2026-04-25 --- Session 2: Milestone 0.2 (corner parcels, sticky back edges, preserve-on-deform)}{subsection.16.2}{}}
|
||||
\newlabel{sec:session-2@cref}{{[subsection][2][16]16.2}{[1][20][]20}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {paragraph}{Goal of the session.}{20}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Decisions locked in at session kickoff.}{20}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Status during writing.}{21}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Performance instrumentation.}{21}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Corner parcel rework.}{22}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Preserve-on-deform pipeline.}{22}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{New figures.}{22}{subsection.16.2}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{Deviations from spec.}{22}{figure.5}\protected@file@percent }
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Default 200×100 rectangle subdivided by milestone 0.2. Compare with milestone 0.1: the four corners are now proper rectangle corner parcels rather than bisector-clipped triangles.}}{23}{figure.2}\protected@file@percent }
|
||||
\newlabel{fig:grid-block-v02}{{2}{23}{Default 200×100 rectangle subdivided by milestone 0.2. Compare with milestone 0.1: the four corners are now proper rectangle corner parcels rather than bisector-clipped triangles}{figure.2}{}}
|
||||
\newlabel{fig:grid-block-v02@cref}{{[figure][2][]2}{[1][22][]23}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {paragraph}{Performance.}{23}{figure.5}\protected@file@percent }
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Y intersection. Three roads at 120° from the origin meet three outer triangle vertices; corner parcels appear at the inner 120° corners (origin) and are skipped at the 30° outer corners.}}{24}{figure.3}\protected@file@percent }
|
||||
\newlabel{fig:y-intersection}{{3}{24}{Y intersection. Three roads at 120° from the origin meet three outer triangle vertices; corner parcels appear at the inner 120° corners (origin) and are skipped at the 30° outer corners}{figure.3}{}}
|
||||
\newlabel{fig:y-intersection@cref}{{[figure][3][]3}{[1][22][]24}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {paragraph}{Test status.}{24}{figure.5}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {paragraph}{What's next --- milestone 0.3 queue.}{24}{figure.5}\protected@file@percent }
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces Before: \cref {fig:grid-block-v02}'s rectangle.}}{25}{figure.4}\protected@file@percent }
|
||||
\newlabel{fig:edit-before}{{4}{25}{Before: \cref {fig:grid-block-v02}'s rectangle}{figure.4}{}}
|
||||
\newlabel{fig:edit-before@cref}{{[figure][4][]4}{[1][22][]25}{}{}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces After: bottom-right corner moved 8\,m right; deformed parcels are green.}}{25}{figure.5}\protected@file@percent }
|
||||
\newlabel{fig:edit-after}{{5}{25}{After: bottom-right corner moved 8\,m right; deformed parcels are green}{figure.5}{}}
|
||||
\newlabel{fig:edit-after@cref}{{[figure][5][]5}{[1][22][]25}{}{}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {A}Notation Reference}{25}{appendix.A}\protected@file@percent }
|
||||
\newlabel{app:notation}{{A}{25}{Notation Reference}{appendix.A}{}}
|
||||
\newlabel{app:notation@cref}{{[section][1][]A}{[1][24][]25}{}{}{}}
|
||||
\gdef \@abspage@last{25}
|
||||
220
journal.fdb_latexmk
Normal file
@ -0,0 +1,220 @@
|
||||
# Fdb version 4
|
||||
["pdflatex"] 1777140696.64118 "journal.tex" "journal.pdf" "journal" 1777140697.51808 0
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc" 1136849721 2900 1537cc8184ad1792082cd229ecc269f4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/jknappen/ec/tcbx1095.tfm" 1136768653 1536 0adca69c597a47fe7664bf81057bb53b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/jknappen/ec/tcrm1095.tfm" 1136768653 1536 02c06700a42be0f5a28664c7273f82e7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm" 1246382020 916 f87d7c45f9c908e672703b83b72241a3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm" 1246382020 928 2dc8d444221b7a635bb58038579b861a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm" 1246382020 908 2921f8a10601f252058503cc6570e581 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm" 1246382020 940 228d6584342e91276bf566bcf9716b83 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm" 1136768653 1328 c834bbb027764024c09d3d2bf908b5f0 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm" 1136768653 1324 c910af8c371558dc20f2d7822f66fe64 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmex10.tfm" 1136768653 992 662f679a0b3d2d53c1b94050fdaa3f50 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmitt10.tfm" 1136768653 768 2297ad2ac26f37e67f756dad27c77d68 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi10.tfm" 1136768653 1528 abec98dbc43e172678c11b3b9031252a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm" 1136768653 1524 4414a8315f39513458b80dfc63bff03a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm" 1136768653 1512 f21f83efb36853c0b70002322c1ab3ad ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm" 1136768653 1520 eccf95517727cb11801f4f1aee3a21b4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr10.tfm" 1136768653 1296 45809c5a464d5f32c8f98ba97c1bb47f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr6.tfm" 1136768653 1300 b62933e007d01cfd073f79b963c01526 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr8.tfm" 1136768653 1292 21c1c5bfeaebccffdb478fd231a0997d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm" 1136768653 1116 933a60c408fc0a863a92debe84b2d294 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm" 1136768653 1120 8b7d695260f3cff42e636090a8002094 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmti10.tfm" 1136768653 1480 aa8e34af0eb6a2941b776984cf1dfdc4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt10.tfm" 1136768653 768 1321e9409b4137d6fb428ac9dc956269 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt8.tfm" 1136768653 768 d7b9a2629a0c353102ad947dc9221d49 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb" 1248133631 34811 78b52f49e893bcba91bd7581cdc144c0 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb" 1248133631 32080 340ef9bf63678554ee606688e7b5339d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmitt10.pfb" 1248133631 26057 fad158094905eaf20f4ae3782af0c45c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi6.pfb" 1248133631 37166 8ab3487cbe3ab49ebce74c29ea2418db ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb" 1248133631 35469 70d41d2b9ea31d5d813066df7c99281c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb" 1248133631 35752 024fb6c41858982481f6968b5fc26508 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb" 1248133631 32722 d7379af29a190c3f453aba36302ff5a9 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr6.pfb" 1248133631 32734 69e00a6b65cedb993666e42eedb3d48f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb" 1248133631 32726 0a1aea6fcd6468ee2cf64d891f5c43c8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1248133631 32569 5e5ddc8df908dea60932f3c484a54c0d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy8.pfb" 1248133631 32626 4f5c1b83753b1dd3a97d1b399a005b4b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb" 1248133631 37944 359e864bd06cde3b1cf57bb20757fb06 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb" 1248133631 31099 c85edf1dd5b9e826d67c9c7293b6786c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfbx1095.pfb" 1215737283 154600 ea54091d31de803b613ba9e80ca51709 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfrm1095.pfb" 1215737283 145929 f25e56369a345c4ff583b067cd87ce8e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/atbegshi/atbegshi.sty" 1575674566 24708 5584a51a7101caf7e6bbf1fc27d8f7b1 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty" 1576625341 40635 c40361e206be584d448876bba8a64a3b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/bitset/bitset.sty" 1576016050 33961 6b5c75130e435b2bfdb9f480a09a39f9 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty" 1576625223 8371 9d55b8bd010bc717624922fb3477d92e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/iftex/iftex.sty" 1734129479 7984 7dbb9280f03c0a315425f1b4f35d43ee ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/iftex/ifvtex.sty" 1572645307 1057 525c2192b5febbd8c1f662c9468335bb ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/infwarerr/infwarerr.sty" 1575499628 8356 7bbb2c2373aa810be568c29e333da8ed ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/intcalc/intcalc.sty" 1576625065 31769 002a487f55041f8e805cfbf6385ffd97 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty" 1576878844 5412 d5a2436094cd7be85769db90f29250a6 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty" 1701727651 17865 1a9bd36b4f98178fa551aca822290953 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pdfescape/pdfescape.sty" 1576015897 19007 15924f7228aca6c6d184b115f4baa231 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty" 1593379760 20089 80423eac55aa175305d35b49e04fe23b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex" 1673816307 1016 1c2b89187d12a2768764b83b4945667c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex" 1601326656 43820 1fef971b75380574ab35a0d37fd92608 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex" 1601326656 19324 f4e4c6403dd0f1605fd20ed22fa79dea ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex" 1601326656 6038 ccb406740cc3f03bbfb58ad504fe8c27 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex" 1673816307 6911 f6d4cf5a3fef5cc879d668b810e82868 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex" 1601326656 4883 42daaf41e27c3735286e23e48d2d7af9 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex" 1601326656 2544 8c06d2a7f0f469616ac9e13db6d2f842 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex" 1601326656 44195 5e390c414de027626ca5e2df888fa68d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex" 1601326656 17311 2ef6b2e29e2fc6a2fc8d6d652176e257 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex" 1601326656 21302 788a79944eb22192a4929e46963a3067 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex" 1673816307 9691 3d42d89522f4650c2f3dc616ca2b925e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex" 1601326656 33335 dd1fa4814d4e51f18be97d88bf0da60c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex" 1601326656 2965 4c2b1f4e0826925746439038172e5d6f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex" 1601326656 5196 2cc249e0ee7e03da5f5f6589257b1e5b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex" 1673816307 20821 7579108c1e9363e61a0b1584778804aa ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex" 1601326656 35249 abd4adf948f960299a4b3d27c5dddf46 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex" 1673816307 22012 81b34a0aa8fa1a6158cc6220b00e4f10 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex" 1601326656 8893 e851de2175338fdf7c17f3e091d94618 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarycalc.code.tex" 1601326656 15929 463535aa2c4268fead6674a75c0e8266 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.code.tex" 1673816307 5628 dc0ee4ba7f3e40acae5600067ce833de ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.pathmorphing.code.tex" 1601326656 321 cdd11262840e01e25374a2d458f15e99 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex" 1601326656 3937 3f208572dd82c71103831da976d74f1a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.geometric.code.tex" 1601326656 339 be0fe46d92a80e3385dd6a83511a46f2 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex" 1608933718 11518 738408f795261b70ce8dd47459171309 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex" 1673816307 186782 af500404a9edec4d362912fe762ded92 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.pathmorphing.code.tex" 1601326656 8843 5533436db3e30fbad1e0440db6027dac ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex" 1601326656 58801 1e750fb0692eb99aaac45698bbec96b1 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex" 1601326656 32995 ac577023e12c0e4bd8aa420b2e852d1a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.geometric.code.tex" 1673816307 161011 76ab54df0aa1a9d3b27a94864771d38d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfint.code.tex" 1557692582 3063 8c415c68a0f3394e45cfeca0b65f6ee6 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex" 1673816307 949 cea70942e7b7eddabfb3186befada2e6 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex" 1673816307 13270 2e54f2ce7622437bf37e013d399743e3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex" 1673816307 104717 9b2393fbf004a0ce7fa688dbce423848 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex" 1601326656 10165 cec5fa73d49da442e56efc2d605ef154 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex" 1601326656 28178 41c17713108e0795aac6fef3d275fbca ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex" 1673816307 9649 85779d3d8d573bfd2cd4137ba8202e60 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex" 1601326656 3865 ac538ab80c5cf82b345016e474786549 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex" 1557692582 3177 27d85c44fbfe09ff3b2cf2879e3ea434 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex" 1621110968 11024 0179538121bc2dba172013a3ef89519f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex" 1673816307 7890 0a86dbf4edfd88d022e0d889ec78cc03 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex" 1601326656 3379 781797a101f647bab82741a99944a229 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex" 1601326656 92405 f515f31275db273f97b9d8f52e1b0736 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex" 1673816307 37466 97b0a1ba732e306a1a2034f5a73e239f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex" 1601326656 8471 c2883569d03f69e8e1cabfef4999cfd7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex" 1673816307 71742 3da44a8be6626eef1c400c68776c7a0f ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex" 1673816307 21211 1e73ec76bd73964d84197cc3d2685b01 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex" 1601326656 16121 346f9013d34804439f7436ff6786cef7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex" 1673816307 44792 271e2e1934f34c759f4dedb1e14a5015 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/pgf.revision.tex" 1673816307 114 e6d443369d0673933b38834bf99e422d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg" 1601326656 926 2963ea0dcf6cc6c0a770b69ec46a477b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def" 1673816307 5542 32f75a31ea6c3a7e1148cd6d5e93dbb7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def" 1673816307 12612 7774ba67bfd72e593c4436c2de6201e3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex" 1673816307 61351 bc5f86e0355834391e736e97a61abced ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex" 1601326656 1896 b8e0ca0ac371d74c0ca05583f6313c91 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex" 1601326656 7778 53c8b5623d80238f6a20aa1df1868e63 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex" 1673816307 24033 d8893a1ec4d1bfa101b172754743d340 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex" 1673816307 39784 414c54e866ebab4b801e2ad81d9b21d8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfiltered.code.tex" 1673816307 37433 940bc6d409f1ffd298adfdcaf125dd86 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex" 1673816307 4385 510565c2f07998c8a0e14f0ec07ff23c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex" 1673816307 29239 22e8c7516012992a49873eff0d868fed ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def" 1673816307 6950 8524a062d82b7afdc4a88a57cb377784 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/stringenc/stringenc.sty" 1575152242 21514 b7557edcee22835ef6b03ede1802dad4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty" 1576624663 7008 f92eaa0a3872ed622bbf538217cd2ab7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amscls/amsthm.sty" 1591045760 12594 0d51ac3a545aaaa555021326ff22a6cc ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amsfonts.sty" 1359763108 5949 3f3fd50a8cc94c3d4cbf4fc66cd3df1c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amssymb.sty" 1359763108 13829 94730e64147574077f8ecfea9bb69af4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsa.fd" 1359763108 961 6518c6525a34feb5e8250ffa91731cff ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsb.fd" 1359763108 961 d02606146ba5601b5645f987c92e6193 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsbsy.sty" 1717359999 2222 2166a1f7827be30ddc30434e5efcee1b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsgen.sty" 1717359999 4173 d22509bc0c91281d991b2de7c88720dd ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsmath.sty" 1730928152 88370 c780f23aea0ece6add91e09b44dca2cd ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsopn.sty" 1717359999 4474 23ca1d3a79a57b405388059456d0a8df ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amstext.sty" 1717359999 2444 71618ea5f2377e33b04fb97afdd0eac2 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/atveryend/atveryend.sty" 1728505250 1695 be6b4d13b33db697fd3fd30b24716c1a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/base/article.cls" 1738182759 20144 63d8bacaf52e5abf4db3bc322373e1d4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/base/atbegshi-ltx.sty" 1738182759 2963 d8ec5a1b4e0a106c5c737900202763e4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/base/atveryend-ltx.sty" 1738182759 2378 14b657ee5031da98cf91648f19642694 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/base/size11.clo" 1738182759 8464 e73911cdcc738e82d6adccd28e654bb1 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/booktabs/booktabs.sty" 1579038678 6078 f1cb470c9199e7110a27851508ed7a5c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/cleveref/cleveref.sty" 1525128982 329481 7fc6b003158402a4c694bc0a1b729308 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/enumitem/enumitem.sty" 1738874546 52272 63d293bc0d496619edb57585740861a2 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/environ/environ.sty" 1399239813 4378 f429f0da968c278653359293040a8f52 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty" 1579991033 13886 d1306dcf79a944f6988e688c1785f9ce ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/etoolbox/etoolbox.sty" 1739306980 46850 d87daedc2abdc653769a6f1067849fe0 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty" 1739048179 31715 19e60610b63819fe670dfa1cd84a4e94 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/geometry/geometry.sty" 1578002852 41601 9cf6c5257b1bc7af01a58859749dd37a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/color.cfg" 1459978653 1213 620bba36b25224fa9b7e1ccb4ecb76fd ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/graphics.cfg" 1465944070 1224 978390e9c2234eab29404bc21b268d1e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-def/pdftex.def" 1713382759 19440 9da9dcbb27470349a580fca7372d454b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/color.sty" 1730496337 7245 57f7defed4fb41562dc4b6ca13958ca9 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphics.sty" 1730496337 18363 dee506cb8d56825d8a4d020f5d5f8704 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphicx.sty" 1717359999 8010 6f2ad8c2b2ffbd607af6475441c7b5e4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/keyval.sty" 1717359999 2671 70891d50dac933918b827d326687c6e8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/mathcolor.ltx" 1667332637 2885 9c645d672ae17285bba324998918efd8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/trig.sty" 1717359999 4023 2c9f39712cf7b43d3eb93a8bbd5c8f67 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hycolor/hycolor.sty" 1580250785 17914 4c28a13fc3d975e6e81c9bea1d697276 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hpdftex.def" 1730838014 48154 82da9991b9f0390b3a9d3af6c8618af4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hyperref.sty" 1730838014 222112 c22dbd2288f89f7ba942ac22f7d00f11 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/nameref.sty" 1705871765 11026 182c63f139a71afd30a28e5f1ed2cd1c ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/pd1enc.def" 1730838014 14249 ff700eb13ce975a424b2dd99b1a83044 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/puenc.def" 1730838014 117112 7533bff456301d32e6d6356fad15f543 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/kvoptions/kvoptions.sty" 1655478651 22555 6d8e155cfef6d82c3d5c742fea7c992e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty" 1665067230 13815 760b0c02f691ea230f5359c4e1de23a7 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1716410060 29785 9f93ab201fe5dd053afcc6c1bcf7d266 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg" 1279039959 678 4792914a8f45be57bb98413425e4c7af ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.cfg" 1727126400 1865 301ae3c26fb8c0243307b619a6aa2dd3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.sty" 1727126400 81640 997090b6c021dc4af9ee00a97b85c5b4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty" 1727126400 206518 4eb59a801ad842a713fa168c34227290 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty" 1727126400 93855 83782cbe438f9229c1d17e92cee1446d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty" 1727126400 90497 606307f9d31e805cfff0cd62ff91a50e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty" 1727126400 77051 be68720e5402397a830abb9eed5a2cb4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstpatch.sty" 1710360531 353 9024412f43e92cd5b21fe9ded82d0610 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mathtools.sty" 1728349409 62711 3b0ed1d68b598a75677c10d16646d5e5 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mhsetup.sty" 1616101747 5582 a43dedf8e5ec418356f1e9dfe5d29fc3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pdfcol/pdfcol.sty" 1663877585 8086 ac143843b6ea88d172677dc3ed532925 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty" 1601326656 1090 bae35ef70b3168089ef166db3e66f5b2 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty" 1673816307 373 00b204b1d7d095b892ad31a7494b0373 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty" 1601326656 21013 f4ff83d25bb56552493b030f27c075ae ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty" 1601326656 989 c49c8ae06d96f8b15869da7428047b1e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty" 1601326656 339 c2e180022e3afdb99c7d0ea5ce469b7d ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/math/pgfmath.sty" 1601326656 306 c56a323ca5bf9242f54474ced10fca71 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty" 1601326656 443 8c872229db56122037e86bcda49e14f3 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgffor.sty" 1601326656 348 ee405e64380c11319f0e249fed57e6c5 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty" 1601326656 274 5ae372b7df79135d240456a1c6f2cf9a ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty" 1601326656 325 f9f16d12354225b7dd52a3321f085955 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/refcount/refcount.sty" 1576624809 9878 9e94e8fa600d95f9c7731bb21dfb67a4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty" 1657483315 9714 ba3194bd52c8499b3f1e3eb91d409670 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbbreakable.code.tex" 1729629551 34681 5ad5619477798e0585ce97e92ba075bc ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbskins.code.tex" 1729629551 83599 50e7ac6ad41eaf61a7736beda9e3416b ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbskinsjigsaw.code.tex" 1729629551 10040 cd3f87486a5ead1213ec367836f72332 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty" 1729629551 105823 554671f5b2d97c7efbbaf6dae11c29a8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill-common.sty" 1691524336 2573 42712c9e0a2df004e43df5b3c95f0c1e ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill.image.sty" 1691524336 1120 ba535da48caa03bf1fd3f03ea87779f8 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzlibraryfill.image.code.tex" 1691524336 10931 717eb52299f416934beb8b2b7cd8cee6 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/titlesec/titlesec.sty" 1736023606 48766 87a17a4ef312a39cd43896e34a679a56 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tools/calc.sty" 1717359999 10214 61188260d324e94bc2f66825d7d3fdf4 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tools/longtable.sty" 1730496337 15900 3cb191e576c7a313634d2813c55d4bf1 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/tools/verbatim.sty" 1717359999 7532 d2e1111e17bfebb1607d8ffa779705ec ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/trimspaces/trimspaces.sty" 1253232110 1380 971a51b00a14503ddf754cab24c3f209 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/url/url.sty" 1388531844 12796 8edb7d69a20b857904dd0ea757c14ec9 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/tex/latex/xcolor/xcolor.sty" 1727642399 55384 b454dec21c2d9f45ec0b793f0995b992 ""
|
||||
"/usr/local/texlive/2025/texmf-dist/web2c/texmf.cnf" 1739380943 42148 61becc7c670cd061bb319c643c27fdd4 ""
|
||||
"/usr/local/texlive/2025/texmf-var/fonts/map/pdftex/updmap/pdftex.map" 1765668892 5467155 19efa205003f9ecad95fbbaa6ff24da1 ""
|
||||
"/usr/local/texlive/2025/texmf-var/web2c/pdftex/pdflatex.fmt" 1741450574 3345740 46b66fdb0378f7bf5921b5eabf1762b8 ""
|
||||
"/usr/local/texlive/2025/texmf.cnf" 1741450484 577 418a7058ec8e006d8704f60ecd22c938 ""
|
||||
"figures/fig_01_grid_block.pdf" 1777140637.75552 2464 4afa36c9ffe6748f9444fe1c6683c57a ""
|
||||
"figures/fig_04_y_intersection.pdf" 1777140637.72077 4132 48ae290f23898b9c57edaf1e6f41cd8d ""
|
||||
"figures/fig_06a_road_edit_before.pdf" 1777140637.7328 2464 4afa36c9ffe6748f9444fe1c6683c57a ""
|
||||
"figures/fig_06b_road_edit_after.pdf" 1777140637.74404 2743 b0ec83cdbf2bfadba761f8a1ac2b9968 ""
|
||||
"journal.aux" 1777140697.44399 16488 17a40913721efd28c03ecdf32e5c5795 "pdflatex"
|
||||
"journal.out" 1777140697.44505 7378 77f42c324f401b5e4ee697fb18722086 "pdflatex"
|
||||
"journal.tex" 1777140692.87318 61768 583822489f15c2459e1db67789800de3 ""
|
||||
"journal.toc" 1777140697.4452 5375 f068ca2b1e38c68d7c5a2eca61b8d2ee "pdflatex"
|
||||
(generated)
|
||||
"journal.aux"
|
||||
"journal.log"
|
||||
"journal.out"
|
||||
"journal.pdf"
|
||||
"journal.toc"
|
||||
(rewritten before read)
|
||||
420
journal.fls
Normal file
@ -0,0 +1,420 @@
|
||||
PWD /Users/danesabo/Projects/Historia_Urbis
|
||||
INPUT /usr/local/texlive/2025/texmf.cnf
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/web2c/texmf.cnf
|
||||
INPUT /usr/local/texlive/2025/texmf-var/web2c/pdftex/pdflatex.fmt
|
||||
INPUT journal.tex
|
||||
OUTPUT journal.log
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/article.cls
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/article.cls
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/size11.clo
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/size11.clo
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/size11.clo
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/map/fontname/texfonts.map
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/geometry/geometry.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/geometry/geometry.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/keyval.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/keyval.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/iftex/ifvtex.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/iftex/ifvtex.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/iftex/iftex.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/iftex/iftex.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsmath.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsmath.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsopn.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amstext.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amstext.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsgen.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsgen.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsbsy.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsbsy.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsopn.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amssymb.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amssymb.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amsfonts.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amsfonts.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amscls/amsthm.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amscls/amsthm.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mathtools.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mathtools.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/calc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/calc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mhsetup.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/mathtools/mhsetup.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphicx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphicx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphics.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphics.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/trig.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/trig.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/pgf.revision.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/pgf.revision.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfiltered.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/xcolor/xcolor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/xcolor/xcolor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/color.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/color.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/color.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/mathcolor.ltx
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/mathcolor.ltx
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/mathcolor.ltx
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfint.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/math/pgfmath.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pgf/math/pgfmath.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarycalc.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarycalc.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/pgflibraryarrows.meta.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.geometric.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.geometric.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.geometric.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.geometric.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.pathmorphing.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.pathmorphing.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarydecorations.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.pathmorphing.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.pathmorphing.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/booktabs/booktabs.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/booktabs/booktabs.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/longtable.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/longtable.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/enumitem/enumitem.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/enumitem/enumitem.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstpatch.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstpatch.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstpatch.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hyperref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hyperref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pdfescape/pdfescape.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pdfescape/pdfescape.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/infwarerr/infwarerr.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/infwarerr/infwarerr.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hycolor/hycolor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hycolor/hycolor.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/nameref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/nameref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/refcount/refcount.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/refcount/refcount.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/kvoptions/kvoptions.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/kvoptions/kvoptions.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/etoolbox/etoolbox.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/etoolbox/etoolbox.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/stringenc/stringenc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/stringenc/stringenc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/pd1enc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/pd1enc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/pd1enc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/intcalc/intcalc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/intcalc/intcalc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/puenc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/puenc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/puenc.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/url/url.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/url/url.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/bitset/bitset.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/bitset/bitset.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/atbegshi/atbegshi.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/atbegshi-ltx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/atbegshi-ltx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hpdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hpdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hpdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/atveryend/atveryend.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/atveryend-ltx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/base/atveryend-ltx.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/cleveref/cleveref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/cleveref/cleveref.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/titlesec/titlesec.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/titlesec/titlesec.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/verbatim.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tools/verbatim.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/environ/environ.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/environ/environ.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/trimspaces/trimspaces.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/trimspaces/trimspaces.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbbreakable.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pdfcol/pdfcol.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/pdfcol/pdfcol.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/graphics/color.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbskins.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill.image.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill.image.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill-common.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzfill-common.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzlibraryfill.image.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tikzfill/tikzlibraryfill.image.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/tcolorbox/tcbskinsjigsaw.code.tex
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
|
||||
INPUT ./journal.aux
|
||||
INPUT ./journal.aux
|
||||
INPUT journal.aux
|
||||
OUTPUT journal.aux
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||
INPUT ./journal.out
|
||||
INPUT ./journal.out
|
||||
INPUT journal.out
|
||||
INPUT journal.out
|
||||
OUTPUT journal.pdf
|
||||
INPUT ./journal.out
|
||||
INPUT ./journal.out
|
||||
OUTPUT journal.out
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr17.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr12.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr8.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr6.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmex10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmr12.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm
|
||||
INPUT ./journal.toc
|
||||
INPUT ./journal.toc
|
||||
INPUT journal.toc
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmmi10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmex10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-var/fonts/map/pdftex/updmap/pdftex.map
|
||||
OUTPUT journal.toc
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmti10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/jknappen/ec/tcrm1095.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmitt10.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang1.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang2.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstlang3.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt8.tfm
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/public/cm/cmtt8.tfm
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_01_grid_block.pdf
|
||||
INPUT ./figures/fig_04_y_intersection.pdf
|
||||
INPUT ./figures/fig_04_y_intersection.pdf
|
||||
INPUT ./figures/fig_04_y_intersection.pdf
|
||||
INPUT ./figures/fig_04_y_intersection.pdf
|
||||
INPUT ./figures/fig_04_y_intersection.pdf
|
||||
INPUT ./figures/fig_06a_road_edit_before.pdf
|
||||
INPUT ./figures/fig_06a_road_edit_before.pdf
|
||||
INPUT ./figures/fig_06a_road_edit_before.pdf
|
||||
INPUT ./figures/fig_06a_road_edit_before.pdf
|
||||
INPUT ./figures/fig_06a_road_edit_before.pdf
|
||||
INPUT ./figures/fig_06b_road_edit_after.pdf
|
||||
INPUT ./figures/fig_06b_road_edit_after.pdf
|
||||
INPUT ./figures/fig_06b_road_edit_after.pdf
|
||||
INPUT ./figures/fig_06b_road_edit_after.pdf
|
||||
INPUT ./figures/fig_06b_road_edit_after.pdf
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/tfm/jknappen/ec/tcbx1095.tfm
|
||||
INPUT journal.aux
|
||||
INPUT ./journal.out
|
||||
INPUT ./journal.out
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmitt10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi6.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr6.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy8.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfbx1095.pfb
|
||||
INPUT /usr/local/texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfrm1095.pfb
|
||||
1297
journal.log
Normal file
44
journal.out
Normal file
@ -0,0 +1,44 @@
|
||||
\BOOKMARK [1][-]{section.1}{\376\377\000P\000r\000o\000j\000e\000c\000t\000\040\000C\000o\000n\000t\000e\000x\000t\000\040\000a\000n\000d\000\040\000M\000o\000t\000i\000v\000a\000t\000i\000o\000n}{}% 1
|
||||
\BOOKMARK [2][-]{subsection.1.1}{\376\377\000W\000h\000y\000\040\000B\000u\000i\000l\000d\000\040\000T\000h\000i\000s}{section.1}% 2
|
||||
\BOOKMARK [2][-]{subsection.1.2}{\376\377\000S\000c\000o\000p\000e\000\040\000o\000f\000\040\000T\000h\000i\000s\000\040\000D\000o\000c\000u\000m\000e\000n\000t}{section.1}% 3
|
||||
\BOOKMARK [2][-]{subsection.1.3}{\376\377\000A\000u\000d\000i\000e\000n\000c\000e}{section.1}% 4
|
||||
\BOOKMARK [1][-]{section.2}{\376\377\000C\000o\000r\000e\000\040\000I\000n\000v\000a\000r\000i\000a\000n\000t\000s}{}% 5
|
||||
\BOOKMARK [1][-]{section.3}{\376\377\000G\000e\000o\000m\000e\000t\000r\000i\000c\000\040\000F\000o\000u\000n\000d\000a\000t\000i\000o\000n\000s}{}% 6
|
||||
\BOOKMARK [2][-]{subsection.3.1}{\376\377\000C\000o\000o\000r\000d\000i\000n\000a\000t\000e\000\040\000S\000y\000s\000t\000e\000m\000\040\000a\000n\000d\000\040\000N\000u\000m\000e\000r\000i\000c\000a\000l\000\040\000T\000y\000p\000e}{section.3}% 7
|
||||
\BOOKMARK [2][-]{subsection.3.2}{\376\377\000R\000o\000a\000d\000\040\000N\000e\000t\000w\000o\000r\000k\000\040\000a\000s\000\040\000a\000\040\000P\000l\000a\000n\000a\000r\000\040\000G\000r\000a\000p\000h}{section.3}% 8
|
||||
\BOOKMARK [2][-]{subsection.3.3}{\376\377\000B\000l\000o\000c\000k\000\040\000E\000x\000t\000r\000a\000c\000t\000i\000o\000n}{section.3}% 9
|
||||
\BOOKMARK [2][-]{subsection.3.4}{\376\377\000I\000n\000w\000a\000r\000d\000\040\000O\000f\000f\000s\000e\000t\000t\000i\000n\000g}{section.3}% 10
|
||||
\BOOKMARK [1][-]{section.4}{\376\377\000S\000u\000b\000d\000i\000v\000i\000s\000i\000o\000n\000\040\000A\000l\000g\000o\000r\000i\000t\000h\000m}{}% 11
|
||||
\BOOKMARK [2][-]{subsection.4.1}{\376\377\000F\000r\000o\000n\000t\000a\000g\000e\000-\000F\000i\000r\000s\000t\000\040\000S\000u\000b\000d\000i\000v\000i\000s\000i\000o\000n}{section.4}% 12
|
||||
\BOOKMARK [2][-]{subsection.4.2}{\376\377\000E\000d\000g\000e\000\040\000C\000l\000a\000s\000s\000i\000f\000i\000c\000a\000t\000i\000o\000n}{section.4}% 13
|
||||
\BOOKMARK [2][-]{subsection.4.3}{\376\377\000R\000e\000g\000u\000l\000a\000r\000i\000z\000a\000t\000i\000o\000n\000\040\000P\000a\000s\000s}{section.4}% 14
|
||||
\BOOKMARK [1][-]{section.5}{\376\377\000R\000o\000a\000d\000\040\000E\000d\000i\000t\000\040\000H\000a\000n\000d\000l\000i\000n\000g}{}% 15
|
||||
\BOOKMARK [2][-]{subsection.5.1}{\376\377\000E\000d\000i\000t\000\040\000T\000y\000p\000e\000s}{section.5}% 16
|
||||
\BOOKMARK [2][-]{subsection.5.2}{\376\377\000D\000e\000f\000o\000r\000m\000a\000t\000i\000o\000n\000\040\000P\000i\000p\000e\000l\000i\000n\000e}{section.5}% 17
|
||||
\BOOKMARK [2][-]{subsection.5.3}{\376\377\000R\000e\000g\000e\000n\000e\000r\000a\000t\000i\000o\000n\000\040\000T\000h\000r\000e\000s\000h\000o\000l\000d\000s}{section.5}% 18
|
||||
\BOOKMARK [2][-]{subsection.5.4}{\376\377\000D\000e\000t\000e\000r\000m\000i\000n\000i\000s\000m\000\040\000a\000n\000d\000\040\000I\000d\000e\000m\000p\000o\000t\000e\000n\000c\000e}{section.5}% 19
|
||||
\BOOKMARK [2][-]{subsection.5.5}{\376\377\000B\000u\000i\000l\000d\000i\000n\000g\000\040\000F\000o\000o\000t\000p\000r\000i\000n\000t\000\040\000P\000r\000e\000s\000e\000r\000v\000a\000t\000i\000o\000n}{section.5}% 20
|
||||
\BOOKMARK [1][-]{section.6}{\376\377\000D\000e\000g\000e\000n\000e\000r\000a\000t\000e\000\040\000C\000a\000s\000e\000s}{}% 21
|
||||
\BOOKMARK [1][-]{section.7}{\376\377\000C\000r\000a\000t\000e\000\040\000A\000r\000c\000h\000i\000t\000e\000c\000t\000u\000r\000e}{}% 22
|
||||
\BOOKMARK [2][-]{subsection.7.1}{\376\377\000M\000o\000d\000u\000l\000e\000\040\000L\000a\000y\000o\000u\000t}{section.7}% 23
|
||||
\BOOKMARK [2][-]{subsection.7.2}{\376\377\000P\000u\000b\000l\000i\000c\000\040\000A\000P\000I\000\040\000S\000u\000r\000f\000a\000c\000e}{section.7}% 24
|
||||
\BOOKMARK [2][-]{subsection.7.3}{\376\377\000E\000r\000r\000o\000r\000\040\000T\000y\000p\000e\000s}{section.7}% 25
|
||||
\BOOKMARK [2][-]{subsection.7.4}{\376\377\000D\000e\000p\000e\000n\000d\000e\000n\000c\000i\000e\000s}{section.7}% 26
|
||||
\BOOKMARK [1][-]{section.8}{\376\377\000I\000d\000i\000o\000m\000a\000t\000i\000c\000\040\000R\000u\000s\000t\000\040\000R\000e\000q\000u\000i\000r\000e\000m\000e\000n\000t\000s}{}% 27
|
||||
\BOOKMARK [1][-]{section.9}{\376\377\000T\000e\000s\000t\000i\000n\000g\000\040\000S\000t\000r\000a\000t\000e\000g\000y}{}% 28
|
||||
\BOOKMARK [2][-]{subsection.9.1}{\376\377\000T\000h\000r\000e\000e\000\040\000L\000a\000y\000e\000r\000s}{section.9}% 29
|
||||
\BOOKMARK [2][-]{subsection.9.2}{\376\377\000S\000n\000a\000p\000s\000h\000o\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.9}% 30
|
||||
\BOOKMARK [2][-]{subsection.9.3}{\376\377\000C\000o\000v\000e\000r\000a\000g\000e\000\040\000R\000e\000q\000u\000i\000r\000e\000m\000e\000n\000t}{section.9}% 31
|
||||
\BOOKMARK [1][-]{section.10}{\376\377\000V\000i\000s\000u\000a\000l\000i\000z\000a\000t\000i\000o\000n\000\040\000a\000n\000d\000\040\000F\000i\000g\000u\000r\000e\000s}{}% 32
|
||||
\BOOKMARK [2][-]{subsection.10.1}{\376\377\000R\000e\000q\000u\000i\000r\000e\000d\000\040\000F\000i\000g\000u\000r\000e\000s}{section.10}% 33
|
||||
\BOOKMARK [2][-]{subsection.10.2}{\376\377\000C\000o\000l\000o\000r\000\040\000C\000o\000n\000v\000e\000n\000t\000i\000o\000n\000s}{section.10}% 34
|
||||
\BOOKMARK [2][-]{subsection.10.3}{\376\377\000I\000n\000c\000l\000u\000s\000i\000o\000n\000\040\000i\000n\000\040\000T\000h\000i\000s\000\040\000J\000o\000u\000r\000n\000a\000l}{section.10}% 35
|
||||
\BOOKMARK [1][-]{section.11}{\376\377\000P\000e\000r\000f\000o\000r\000m\000a\000n\000c\000e\000\040\000T\000a\000r\000g\000e\000t\000s}{}% 36
|
||||
\BOOKMARK [1][-]{section.12}{\376\377\000O\000u\000t\000\040\000o\000f\000\040\000S\000c\000o\000p\000e}{}% 37
|
||||
\BOOKMARK [1][-]{section.13}{\376\377\000C\000l\000a\000u\000d\000e\000\040\000C\000o\000d\000e\000\040\000C\000o\000n\000t\000r\000a\000c\000t}{}% 38
|
||||
\BOOKMARK [1][-]{section.14}{\376\377\000O\000p\000e\000n\000\040\000Q\000u\000e\000s\000t\000i\000o\000n\000s}{}% 39
|
||||
\BOOKMARK [1][-]{section.15}{\376\377\000D\000e\000s\000i\000g\000n\000\040\000D\000e\000c\000i\000s\000i\000o\000n\000s}{}% 40
|
||||
\BOOKMARK [1][-]{section.16}{\376\377\000R\000e\000v\000i\000s\000i\000o\000n\000s\000\040\000a\000n\000d\000\040\000D\000e\000v\000i\000a\000t\000i\000o\000n\000s}{}% 41
|
||||
\BOOKMARK [2][-]{subsection.16.1}{\376\377\0002\0000\0002\0006\000-\0000\0004\000-\0002\0005\000\040\040\024\000\040\000S\000e\000s\000s\000i\000o\000n\000\040\0001\000:\000\040\000M\000i\000l\000e\000s\000t\000o\000n\000e\000\040\0000\000.\0001\000,\000\040\000r\000e\000c\000t\000a\000n\000g\000l\000e\000\040\000e\000n\000d\000-\000t\000o\000-\000e\000n\000d}{section.16}% 42
|
||||
\BOOKMARK [2][-]{subsection.16.2}{\376\377\0002\0000\0002\0006\000-\0000\0004\000-\0002\0005\000\040\040\024\000\040\000S\000e\000s\000s\000i\000o\000n\000\040\0002\000:\000\040\000M\000i\000l\000e\000s\000t\000o\000n\000e\000\040\0000\000.\0002\000\040\000\050\000c\000o\000r\000n\000e\000r\000\040\000p\000a\000r\000c\000e\000l\000s\000,\000\040\000s\000t\000i\000c\000k\000y\000\040\000b\000a\000c\000k\000\040\000e\000d\000g\000e\000s\000,\000\040\000p\000r\000e\000s\000e\000r\000v\000e\000-\000o\000n\000-\000d\000e\000f\000o\000r\000m\000\051}{section.16}% 43
|
||||
\BOOKMARK [1][-]{appendix.A}{\376\377\000N\000o\000t\000a\000t\000i\000o\000n\000\040\000R\000e\000f\000e\000r\000e\000n\000c\000e}{}% 44
|
||||
BIN
journal.pdf
Normal file
1316
journal.tex
Normal file
68
journal.toc
Normal file
@ -0,0 +1,68 @@
|
||||
\contentsline {section}{\numberline {1}Project Context and Motivation}{3}{section.1}%
|
||||
\contentsline {subsection}{\numberline {1.1}Why Build This}{3}{subsection.1.1}%
|
||||
\contentsline {subsection}{\numberline {1.2}Scope of This Document}{3}{subsection.1.2}%
|
||||
\contentsline {subsection}{\numberline {1.3}Audience}{3}{subsection.1.3}%
|
||||
\contentsline {section}{\numberline {2}Core Invariants}{3}{section.2}%
|
||||
\contentsline {section}{\numberline {3}Geometric Foundations}{4}{section.3}%
|
||||
\contentsline {subsection}{\numberline {3.1}Coordinate System and Numerical Type}{4}{subsection.3.1}%
|
||||
\contentsline {subsection}{\numberline {3.2}Road Network as a Planar Graph}{4}{subsection.3.2}%
|
||||
\contentsline {subsection}{\numberline {3.3}Block Extraction}{5}{subsection.3.3}%
|
||||
\contentsline {subsection}{\numberline {3.4}Inward Offsetting}{5}{subsection.3.4}%
|
||||
\contentsline {section}{\numberline {4}Subdivision Algorithm}{5}{section.4}%
|
||||
\contentsline {subsection}{\numberline {4.1}Frontage-First Subdivision}{5}{subsection.4.1}%
|
||||
\contentsline {paragraph}{Inputs.}{5}{subsection.4.1}%
|
||||
\contentsline {paragraph}{Procedure.}{5}{subsection.4.1}%
|
||||
\contentsline {subsection}{\numberline {4.2}Edge Classification}{6}{subsection.4.2}%
|
||||
\contentsline {subsection}{\numberline {4.3}Regularization Pass}{6}{subsection.4.3}%
|
||||
\contentsline {section}{\numberline {5}Road Edit Handling}{6}{section.5}%
|
||||
\contentsline {subsection}{\numberline {5.1}Edit Types}{7}{subsection.5.1}%
|
||||
\contentsline {subsection}{\numberline {5.2}Deformation Pipeline}{7}{subsection.5.2}%
|
||||
\contentsline {subsection}{\numberline {5.3}Regeneration Thresholds}{7}{subsection.5.3}%
|
||||
\contentsline {subsection}{\numberline {5.4}Determinism and Idempotence}{8}{subsection.5.4}%
|
||||
\contentsline {subsection}{\numberline {5.5}Building Footprint Preservation}{8}{subsection.5.5}%
|
||||
\contentsline {section}{\numberline {6}Degenerate Cases}{8}{section.6}%
|
||||
\contentsline {section}{\numberline {7}Crate Architecture}{9}{section.7}%
|
||||
\contentsline {subsection}{\numberline {7.1}Module Layout}{9}{subsection.7.1}%
|
||||
\contentsline {subsection}{\numberline {7.2}Public API Surface}{10}{subsection.7.2}%
|
||||
\contentsline {subsection}{\numberline {7.3}Error Types}{10}{subsection.7.3}%
|
||||
\contentsline {subsection}{\numberline {7.4}Dependencies}{11}{subsection.7.4}%
|
||||
\contentsline {section}{\numberline {8}Idiomatic Rust Requirements}{11}{section.8}%
|
||||
\contentsline {section}{\numberline {9}Testing Strategy}{12}{section.9}%
|
||||
\contentsline {subsection}{\numberline {9.1}Three Layers}{12}{subsection.9.1}%
|
||||
\contentsline {paragraph}{Unit tests}{12}{subsection.9.1}%
|
||||
\contentsline {paragraph}{Integration tests}{12}{subsection.9.1}%
|
||||
\contentsline {paragraph}{Property tests}{12}{subsection.9.1}%
|
||||
\contentsline {subsection}{\numberline {9.2}Snapshot Testing}{12}{subsection.9.2}%
|
||||
\contentsline {subsection}{\numberline {9.3}Coverage Requirement}{12}{subsection.9.3}%
|
||||
\contentsline {section}{\numberline {10}Visualization and Figures}{12}{section.10}%
|
||||
\contentsline {subsection}{\numberline {10.1}Required Figures}{12}{subsection.10.1}%
|
||||
\contentsline {subsection}{\numberline {10.2}Color Conventions}{13}{subsection.10.2}%
|
||||
\contentsline {subsection}{\numberline {10.3}Inclusion in This Journal}{13}{subsection.10.3}%
|
||||
\contentsline {section}{\numberline {11}Performance Targets}{13}{section.11}%
|
||||
\contentsline {section}{\numberline {12}Out of Scope}{13}{section.12}%
|
||||
\contentsline {section}{\numberline {13}Claude Code Contract}{14}{section.13}%
|
||||
\contentsline {section}{\numberline {14}Open Questions}{15}{section.14}%
|
||||
\contentsline {section}{\numberline {15}Design Decisions}{15}{section.15}%
|
||||
\contentsline {section}{\numberline {16}Revisions and Deviations}{16}{section.16}%
|
||||
\contentsline {subsection}{\numberline {16.1}2026-04-25 --- Session 1: Milestone 0.1, rectangle end-to-end}{16}{subsection.16.1}%
|
||||
\contentsline {paragraph}{Goal of the session.}{16}{subsection.16.1}%
|
||||
\contentsline {paragraph}{What got built.}{17}{subsection.16.1}%
|
||||
\contentsline {paragraph}{Tooling gates.}{17}{figure.1}%
|
||||
\contentsline {paragraph}{Test status.}{17}{figure.1}%
|
||||
\contentsline {paragraph}{Design decisions locked in this session.}{18}{figure.1}%
|
||||
\contentsline {paragraph}{Spec deviations recorded this session.}{18}{figure.1}%
|
||||
\contentsline {paragraph}{Open questions touched.}{20}{figure.1}%
|
||||
\contentsline {paragraph}{Next session --- milestone 0.2 queue.}{20}{figure.1}%
|
||||
\contentsline {subsection}{\numberline {16.2}2026-04-25 --- Session 2: Milestone 0.2 (corner parcels, sticky back edges, preserve-on-deform)}{20}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Goal of the session.}{20}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Decisions locked in at session kickoff.}{20}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Status during writing.}{21}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Performance instrumentation.}{21}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Corner parcel rework.}{22}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Preserve-on-deform pipeline.}{22}{subsection.16.2}%
|
||||
\contentsline {paragraph}{New figures.}{22}{subsection.16.2}%
|
||||
\contentsline {paragraph}{Deviations from spec.}{22}{figure.5}%
|
||||
\contentsline {paragraph}{Performance.}{23}{figure.5}%
|
||||
\contentsline {paragraph}{Test status.}{24}{figure.5}%
|
||||
\contentsline {paragraph}{What's next --- milestone 0.3 queue.}{24}{figure.5}%
|
||||
\contentsline {section}{\numberline {A}Notation Reference}{25}{appendix.A}%
|
||||
BIN
road_parceling/.DS_Store
vendored
Normal file
1007
road_parceling/Cargo.lock
generated
Normal file
53
road_parceling/Cargo.toml
Normal file
@ -0,0 +1,53 @@
|
||||
[package]
|
||||
name = "road_parceling"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Dane Sabo"]
|
||||
description = "Road-frontage-based parcel subdivision for a city simulation. Pure logic, no rendering or game loop."
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/danesabo/Historia_Urbis"
|
||||
readme = "README.md"
|
||||
keywords = ["geometry", "city", "simulation", "parcel", "gis"]
|
||||
categories = ["algorithms", "game-development", "science::geo"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
viz = ["dep:svg"]
|
||||
serde = ["dep:serde", "glam/serde", "slotmap/serde"]
|
||||
|
||||
[dependencies]
|
||||
glam = { version = "0.29", features = ["mint"] }
|
||||
slotmap = "1"
|
||||
thiserror = "2"
|
||||
rand = "0.8"
|
||||
rand_chacha = "0.3"
|
||||
|
||||
# optional
|
||||
svg = { version = "0.18", optional = true }
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "1"
|
||||
insta = { version = "1", features = ["yaml"] }
|
||||
criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] }
|
||||
|
||||
[[bench]]
|
||||
name = "subdivision"
|
||||
harness = false
|
||||
|
||||
[[example]]
|
||||
name = "generate_figures"
|
||||
required-features = ["viz"]
|
||||
|
||||
[lints.rust]
|
||||
missing_docs = "deny"
|
||||
unsafe_code = "forbid"
|
||||
|
||||
[lints.clippy]
|
||||
all = { level = "warn", priority = -1 }
|
||||
# Pragmatic exceptions for a numerical/geometry crate. We deliberately
|
||||
# do *not* enable `pedantic` here — its naming and idiom checks fight
|
||||
# the conventions of geometry code (single-letter coordinate names,
|
||||
# small struct field reassignments) without buying real safety.
|
||||
if_same_then_else = "allow"
|
||||
field_reassign_with_default = "allow"
|
||||
36
road_parceling/benches/subdivision.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! Criterion benches against the performance targets in spec §9.
|
||||
//!
|
||||
//! Status: stub for milestone 0.1 — we measure `subdivide_all` on a
|
||||
//! single block and on a 10x10 grid. The 100/10000-block targets
|
||||
//! land in milestone 0.2.
|
||||
|
||||
#![allow(missing_docs)] // criterion_group! generates undocumented items
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use glam::DVec2;
|
||||
use road_parceling::{subdivide_all, RoadGraph, SubdivisionParams};
|
||||
|
||||
fn rectangle_graph(w: f64, h: f64) -> RoadGraph {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(w, 0.0));
|
||||
let c = g.add_node(DVec2::new(w, h));
|
||||
let d = g.add_node(DVec2::new(0.0, h));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(b, c).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
g.add_road(d, a).unwrap();
|
||||
g.rebuild_topology().unwrap();
|
||||
g
|
||||
}
|
||||
|
||||
fn bench_one_block(c: &mut Criterion) {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
c.bench_function("subdivide_one_rectangle", |b| {
|
||||
b.iter(|| subdivide_all(&g, ¶ms).unwrap());
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_one_block);
|
||||
criterion_main!(benches);
|
||||
37
road_parceling/examples/debug_y.rs
Normal file
@ -0,0 +1,37 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use glam::DVec2;
|
||||
use road_parceling::{subdivide_all, RoadGraph, SubdivisionParams};
|
||||
|
||||
fn main() {
|
||||
let r = 100.0;
|
||||
let third = std::f64::consts::TAU / 3.0;
|
||||
let mut g = RoadGraph::new();
|
||||
let center = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let p1 = g.add_node(DVec2::new(r * 0.0_f64.cos(), r * 0.0_f64.sin()));
|
||||
let p2 = g.add_node(DVec2::new(r * third.cos(), r * third.sin()));
|
||||
let p3 = g.add_node(DVec2::new(r * (2.0 * third).cos(), r * (2.0 * third).sin()));
|
||||
g.add_road(center, p1).unwrap();
|
||||
g.add_road(center, p2).unwrap();
|
||||
g.add_road(center, p3).unwrap();
|
||||
g.add_road(p1, p2).unwrap();
|
||||
g.add_road(p2, p3).unwrap();
|
||||
g.add_road(p3, p1).unwrap();
|
||||
g.rebuild_topology().unwrap();
|
||||
let params = SubdivisionParams::default();
|
||||
let parcels = subdivide_all(&g, ¶ms).unwrap();
|
||||
println!("p1 = {:?}", g.node_position(p1));
|
||||
println!("p2 = {:?}", g.node_position(p2));
|
||||
println!("p3 = {:?}", g.node_position(p3));
|
||||
println!("center = {:?}", g.node_position(center));
|
||||
println!("\n{} parcels:", parcels.len());
|
||||
for (i, (id, p)) in parcels.iter().enumerate() {
|
||||
println!(
|
||||
" [{}] id={:?} centroid={:?} verts={:?}",
|
||||
i,
|
||||
id,
|
||||
p.polygon().centroid(),
|
||||
p.vertices()
|
||||
);
|
||||
}
|
||||
}
|
||||
26
road_parceling/examples/generate_figures.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//! Regenerates every figure referenced in `journal.tex` (spec §8).
|
||||
//!
|
||||
//! Run with:
|
||||
//!
|
||||
//! ```sh
|
||||
//! cargo run --example generate_figures --features viz -- <out_dir>
|
||||
//! ```
|
||||
|
||||
#[cfg(not(feature = "viz"))]
|
||||
fn main() {
|
||||
eprintln!("rebuild with --features viz");
|
||||
}
|
||||
|
||||
#[cfg(feature = "viz")]
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let out: PathBuf = env::args()
|
||||
.nth(1)
|
||||
.map_or_else(|| PathBuf::from("figures"), PathBuf::from);
|
||||
std::fs::create_dir_all(&out)?;
|
||||
road_parceling::viz::generate_all_figures(&out)?;
|
||||
println!("wrote figures to {}", out.display());
|
||||
Ok(())
|
||||
}
|
||||
58
road_parceling/examples/perfprobe.rs
Normal file
@ -0,0 +1,58 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use glam::DVec2;
|
||||
use road_parceling::{subdivide_all_with_stats, RoadGraph, SubdivisionParams};
|
||||
|
||||
fn rect(g: &mut RoadGraph, x0: f64, y0: f64, w: f64, h: f64) {
|
||||
let a = g.add_node(DVec2::new(x0, y0));
|
||||
let b = g.add_node(DVec2::new(x0 + w, y0));
|
||||
let c = g.add_node(DVec2::new(x0 + w, y0 + h));
|
||||
let d = g.add_node(DVec2::new(x0, y0 + h));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(b, c).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
g.add_road(d, a).unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut single = RoadGraph::new();
|
||||
rect(&mut single, 0.0, 0.0, 200.0, 100.0);
|
||||
single.rebuild_topology().unwrap();
|
||||
let params = SubdivisionParams::default();
|
||||
// warm
|
||||
for _ in 0..5 {
|
||||
let _ = subdivide_all_with_stats(&single, ¶ms).unwrap();
|
||||
}
|
||||
let (_, s) = subdivide_all_with_stats(&single, ¶ms).unwrap();
|
||||
println!("single rectangle: {} blocks, {} parcels, total {:.1}us, topo {:.1}us, blocks {:.1}us, sub {:.1}us, {:.0} parcels/s",
|
||||
s.block_count, s.parcel_count, s.total.as_secs_f64()*1e6, s.topology_rebuild.as_secs_f64()*1e6,
|
||||
s.block_extraction.as_secs_f64()*1e6, s.block_subdivide_total.as_secs_f64()*1e6, s.parcels_per_second());
|
||||
println!(" → {:.2} us/parcel", s.time_per_parcel_us());
|
||||
|
||||
// 5x5 grid of small blocks — quickly approaches 25 blocks
|
||||
let mut grid = RoadGraph::new();
|
||||
for i in 0..5 {
|
||||
for j in 0..5 {
|
||||
rect(
|
||||
&mut grid,
|
||||
(i as f64) * 220.0,
|
||||
(j as f64) * 120.0,
|
||||
200.0,
|
||||
100.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
grid.rebuild_topology().unwrap();
|
||||
for _ in 0..3 {
|
||||
let _ = subdivide_all_with_stats(&grid, ¶ms).unwrap();
|
||||
}
|
||||
let (_, s) = subdivide_all_with_stats(&grid, ¶ms).unwrap();
|
||||
println!(
|
||||
"5x5 grid (25 disjoint blocks): {} blocks, {} parcels, total {:.1}us, {:.0} parcels/s",
|
||||
s.block_count,
|
||||
s.parcel_count,
|
||||
s.total.as_secs_f64() * 1e6,
|
||||
s.parcels_per_second()
|
||||
);
|
||||
println!(" → {:.2} us/parcel", s.time_per_parcel_us());
|
||||
}
|
||||
BIN
road_parceling/src/.DS_Store
vendored
Normal file
89
road_parceling/src/config.rs
Normal file
@ -0,0 +1,89 @@
|
||||
//! Tunable parameters for subdivision. (Spec §3.1.)
|
||||
//!
|
||||
//! `SubdivisionParams` is the single configuration object passed to
|
||||
//! every public subdivision and edit operation. All distances are in
|
||||
//! meters, areas in m², angles in radians.
|
||||
|
||||
use crate::error::SubdivisionError;
|
||||
|
||||
/// Parameters controlling frontage-first subdivision.
|
||||
///
|
||||
/// See spec §3 (algorithm) and §4 (regeneration thresholds).
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct SubdivisionParams {
|
||||
/// Target frontage width `w_f`, meters.
|
||||
pub frontage_width: f64,
|
||||
/// Frontage width variance `sigma_f`, meters.
|
||||
pub frontage_variance: f64,
|
||||
/// Target parcel depth `d_p`, meters.
|
||||
pub depth: f64,
|
||||
/// Depth variance `sigma_d`, meters.
|
||||
pub depth_variance: f64,
|
||||
/// Setback from road edge into the block, `d_s` meters.
|
||||
pub setback: f64,
|
||||
/// Regularity slider `rho` in `[0, 1]`. 0 = raw, 1 = OBB-snapped.
|
||||
pub regularity: f64,
|
||||
/// Minimum frontage `w_min`, meters.
|
||||
pub min_frontage: f64,
|
||||
/// Minimum parcel area `A_min`, m².
|
||||
pub min_area: f64,
|
||||
/// Maximum side-edge rotation before a deformed parcel is
|
||||
/// regenerated, `alpha_max` radians. Default ~30°.
|
||||
pub max_side_rotation: f64,
|
||||
/// Deterministic RNG seed.
|
||||
pub seed: u64,
|
||||
}
|
||||
|
||||
impl Default for SubdivisionParams {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
frontage_width: 20.0,
|
||||
frontage_variance: 3.0,
|
||||
depth: 30.0,
|
||||
depth_variance: 4.0,
|
||||
setback: 1.0,
|
||||
regularity: 0.0,
|
||||
min_frontage: 6.0,
|
||||
min_area: 60.0,
|
||||
max_side_rotation: 30.0_f64.to_radians(),
|
||||
seed: 0xC17_1E5_u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubdivisionParams {
|
||||
/// Validate that every parameter is in a sane range. Called at the
|
||||
/// top of every public entry point.
|
||||
pub fn validate(&self) -> Result<(), SubdivisionError> {
|
||||
let bad = |s: &str| Err(SubdivisionError::InvalidParams(s.to_string()));
|
||||
if !self.frontage_width.is_finite() || self.frontage_width <= 0.0 {
|
||||
return bad("frontage_width must be finite and positive");
|
||||
}
|
||||
if !self.frontage_variance.is_finite() || self.frontage_variance < 0.0 {
|
||||
return bad("frontage_variance must be finite and >= 0");
|
||||
}
|
||||
if !self.depth.is_finite() || self.depth <= 0.0 {
|
||||
return bad("depth must be finite and positive");
|
||||
}
|
||||
if !self.depth_variance.is_finite() || self.depth_variance < 0.0 {
|
||||
return bad("depth_variance must be finite and >= 0");
|
||||
}
|
||||
if !self.setback.is_finite() || self.setback < 0.0 {
|
||||
return bad("setback must be finite and >= 0");
|
||||
}
|
||||
if !(0.0..=1.0).contains(&self.regularity) {
|
||||
return bad("regularity must be in [0, 1]");
|
||||
}
|
||||
if self.min_frontage <= 0.0 || self.min_frontage > self.frontage_width {
|
||||
return bad("min_frontage must be in (0, frontage_width]");
|
||||
}
|
||||
if self.min_area <= 0.0 {
|
||||
return bad("min_area must be positive");
|
||||
}
|
||||
if self.max_side_rotation <= 0.0 || self.max_side_rotation >= std::f64::consts::PI {
|
||||
return bad("max_side_rotation must be in (0, π)");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
51
road_parceling/src/error.rs
Normal file
@ -0,0 +1,51 @@
|
||||
//! Typed errors returned by the public API. (Spec §6.3.)
|
||||
//!
|
||||
//! Every fallible operation returns a `Result`. The library does not
|
||||
//! panic on invalid input; it returns one of the variants below.
|
||||
|
||||
use crate::network::NodeId;
|
||||
|
||||
/// Errors that can arise during initial subdivision.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum SubdivisionError {
|
||||
/// The road graph is not planar at the given node (two roads cross
|
||||
/// without a graph node at the crossing point).
|
||||
#[error("road graph is not planar at node {0:?}")]
|
||||
NonPlanarGraph(NodeId),
|
||||
|
||||
/// A block boundary failed to close into a cycle.
|
||||
#[error("block boundary is not closed")]
|
||||
OpenBlock,
|
||||
|
||||
/// `SubdivisionParams` failed validation.
|
||||
#[error("subdivision parameters invalid: {0}")]
|
||||
InvalidParams(String),
|
||||
|
||||
/// A geometric operation (offset, intersection, ...) failed in a
|
||||
/// way that suggests degenerate input rather than a bug.
|
||||
#[error("geometric operation failed: {0}")]
|
||||
GeometryFailure(String),
|
||||
|
||||
/// Reserved for features deferred to a later milestone.
|
||||
#[error("feature not yet implemented: {0}")]
|
||||
Unimplemented(&'static str),
|
||||
}
|
||||
|
||||
/// Errors returned by `apply_road_edit`.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum ParcelError {
|
||||
/// The road or node referenced by the edit no longer exists.
|
||||
#[error("edit references unknown entity")]
|
||||
UnknownEntity,
|
||||
|
||||
/// The edit produced an inconsistent graph; the operation was
|
||||
/// rolled back.
|
||||
#[error("edit produced inconsistent graph: {0}")]
|
||||
InconsistentEdit(String),
|
||||
|
||||
/// Re-subdivision of an affected block failed.
|
||||
#[error("re-subdivision after edit failed: {0}")]
|
||||
Resubdivide(#[from] SubdivisionError),
|
||||
}
|
||||
63
road_parceling/src/geometry/mod.rs
Normal file
@ -0,0 +1,63 @@
|
||||
//! 2-D geometric primitives operating in `glam::DVec2` (f64) coords.
|
||||
//!
|
||||
//! All coordinates are in meters in a flat Euclidean plane. See spec
|
||||
//! §2 (invariants) for the numerical tolerances and §3.1 (D1) for the
|
||||
//! rationale behind double precision.
|
||||
|
||||
pub mod offset;
|
||||
pub mod polygon;
|
||||
|
||||
pub use offset::offset_inward;
|
||||
pub use polygon::{Polygon, PolygonError};
|
||||
|
||||
use glam::DVec2;
|
||||
|
||||
/// Signed area of a closed ring. Positive for CCW, negative for CW.
|
||||
/// Used by both polygon validation and DCEL face classification.
|
||||
#[must_use]
|
||||
pub fn signed_area(verts: &[DVec2]) -> f64 {
|
||||
let n = verts.len();
|
||||
if n < 3 {
|
||||
return 0.0;
|
||||
}
|
||||
let mut a = 0.0;
|
||||
for i in 0..n {
|
||||
let p = verts[i];
|
||||
let q = verts[(i + 1) % n];
|
||||
a += p.x * q.y - q.x * p.y;
|
||||
}
|
||||
0.5 * a
|
||||
}
|
||||
|
||||
/// Proper segment-segment intersection: true iff the two segments
|
||||
/// cross strictly in their interiors. Used both by polygon
|
||||
/// self-intersection checks and planar-graph validation.
|
||||
#[must_use]
|
||||
pub fn segments_properly_intersect(p1: DVec2, p2: DVec2, p3: DVec2, p4: DVec2) -> bool {
|
||||
let d1 = cross_sign(p3, p4, p1);
|
||||
let d2 = cross_sign(p3, p4, p2);
|
||||
let d3 = cross_sign(p1, p2, p3);
|
||||
let d4 = cross_sign(p1, p2, p4);
|
||||
(d1 * d2 < 0.0) && (d3 * d4 < 0.0)
|
||||
}
|
||||
|
||||
fn cross_sign(a: DVec2, b: DVec2, c: DVec2) -> f64 {
|
||||
let v = (b - a).perp_dot(c - a);
|
||||
if v.abs() < EPS_GEOM {
|
||||
0.0
|
||||
} else {
|
||||
v.signum()
|
||||
}
|
||||
}
|
||||
|
||||
/// Geometric tolerance, meters. Used for "two points are the same" and
|
||||
/// "edge has zero length" tests.
|
||||
pub const EPS_GEOM: f64 = 1.0e-6;
|
||||
|
||||
/// Area tolerance, m². Used for "polygon has zero area" and "two
|
||||
/// parcels overlap" tests.
|
||||
pub const EPS_AREA: f64 = 1.0e-9;
|
||||
|
||||
/// Angular tolerance, radians. Used for "three points are collinear"
|
||||
/// tests.
|
||||
pub const EPS_ANGLE: f64 = 1.0e-4;
|
||||
142
road_parceling/src/geometry/offset.rs
Normal file
@ -0,0 +1,142 @@
|
||||
//! Inward offsetting of polygons (spec §2.5).
|
||||
//!
|
||||
//! Used to compute the developable polygon `B'` of a block: `B`
|
||||
//! shrunk by the road setback distance `d_s`. For convex inputs this
|
||||
//! is exact. For concave inputs the result is the intersection of the
|
||||
//! inward half-planes of every edge — a conservative approximation
|
||||
//! that may shave off concave outer-corner detail but never produces
|
||||
//! an invalid polygon.
|
||||
|
||||
use glam::DVec2;
|
||||
|
||||
use super::polygon::Polygon;
|
||||
use super::EPS_GEOM;
|
||||
|
||||
/// Compute the inward offset of `poly` by `distance` while preserving
|
||||
/// a 1-1 correspondence between input edges and output vertices.
|
||||
///
|
||||
/// Vertex `i` of the returned ring is the intersection of the inward
|
||||
/// offset lines of input edges `i-1` and `i`. This is well-defined
|
||||
/// for convex inputs and modest offsets; for highly non-convex inputs
|
||||
/// or large offsets the result may self-intersect, in which case
|
||||
/// the caller should fall back to [`offset_inward`].
|
||||
#[must_use]
|
||||
pub fn correlated_offset_inward(poly: &Polygon, distance: f64) -> Option<Vec<DVec2>> {
|
||||
let n = poly.len();
|
||||
if n < 3 || distance < 0.0 {
|
||||
return None;
|
||||
}
|
||||
let verts = poly.vertices();
|
||||
let mut offset_lines: Vec<(DVec2, DVec2)> = Vec::with_capacity(n);
|
||||
for i in 0..n {
|
||||
let p = verts[i];
|
||||
let q = verts[(i + 1) % n];
|
||||
let edge = q - p;
|
||||
let len = edge.length();
|
||||
if len < EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let tangent = edge / len;
|
||||
let inward = DVec2::new(-tangent.y, tangent.x);
|
||||
let p_off = p + inward * distance;
|
||||
let q_off = q + inward * distance;
|
||||
offset_lines.push((p_off, q_off));
|
||||
}
|
||||
let mut new_verts = Vec::with_capacity(n);
|
||||
for i in 0..n {
|
||||
let prev = offset_lines[(i + n - 1) % n];
|
||||
let curr = offset_lines[i];
|
||||
let isect = line_line_intersect(prev.0, prev.1, curr.0, curr.1)?;
|
||||
new_verts.push(isect);
|
||||
}
|
||||
Some(new_verts)
|
||||
}
|
||||
|
||||
fn line_line_intersect(p1: DVec2, p2: DVec2, p3: DVec2, p4: DVec2) -> Option<DVec2> {
|
||||
let d1 = p2 - p1;
|
||||
let d2 = p4 - p3;
|
||||
let denom = d1.x * d2.y - d1.y * d2.x;
|
||||
if denom.abs() < EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let dp = p3 - p1;
|
||||
let t = (dp.x * d2.y - dp.y * d2.x) / denom;
|
||||
Some(p1 + d1 * t)
|
||||
}
|
||||
|
||||
/// Compute the inward offset of `poly` by `distance`. Returns `None`
|
||||
/// when the result is empty (block too narrow to offset) or invalid.
|
||||
///
|
||||
/// Implementation: clip `poly` once by the inward-shifted half-plane
|
||||
/// of each edge and validate the result.
|
||||
#[must_use]
|
||||
pub fn offset_inward(poly: &Polygon, distance: f64) -> Option<Polygon> {
|
||||
if distance.abs() < EPS_GEOM {
|
||||
return Some(poly.clone());
|
||||
}
|
||||
if distance < 0.0 {
|
||||
return None;
|
||||
}
|
||||
let mut working = poly.clone();
|
||||
for (a, b) in poly.edges().collect::<Vec<_>>() {
|
||||
let edge = b - a;
|
||||
let len = edge.length();
|
||||
if len < EPS_GEOM {
|
||||
continue;
|
||||
}
|
||||
// Inward normal of a CCW polygon: rotate the tangent +90°
|
||||
// (left-perpendicular).
|
||||
let tangent = edge / len;
|
||||
let inward = DVec2::new(-tangent.y, tangent.x);
|
||||
let shifted = a + inward * distance;
|
||||
match working.clip_half_plane(shifted, inward) {
|
||||
Some(p) => working = p,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
Some(working)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn rectangle_inward_offset_shrinks() {
|
||||
let p = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(100.0, 0.0),
|
||||
DVec2::new(100.0, 50.0),
|
||||
DVec2::new(0.0, 50.0),
|
||||
])
|
||||
.unwrap();
|
||||
let off = offset_inward(&p, 5.0).unwrap();
|
||||
// Result should be the rectangle (5,5)-(95,45), area = 90*40.
|
||||
assert!((off.area() - 90.0 * 40.0).abs() < 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_large_offset_returns_none() {
|
||||
let p = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(10.0, 0.0),
|
||||
DVec2::new(10.0, 10.0),
|
||||
DVec2::new(0.0, 10.0),
|
||||
])
|
||||
.unwrap();
|
||||
assert!(offset_inward(&p, 50.0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_offset_is_identity() {
|
||||
let p = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(1.0, 0.0),
|
||||
DVec2::new(1.0, 1.0),
|
||||
DVec2::new(0.0, 1.0),
|
||||
])
|
||||
.unwrap();
|
||||
let off = offset_inward(&p, 0.0).unwrap();
|
||||
assert!((off.area() - p.area()).abs() < 1e-12);
|
||||
}
|
||||
}
|
||||
372
road_parceling/src/geometry/polygon.rs
Normal file
@ -0,0 +1,372 @@
|
||||
//! Simple polygon type with validation and basic operations.
|
||||
//!
|
||||
//! Per invariant **I1** (spec §2): every parcel polygon must be simple
|
||||
//! (no self-intersections, no holes), CCW-ordered, with no zero-length
|
||||
//! edges and no collinear triples within tolerance.
|
||||
|
||||
use glam::DVec2;
|
||||
|
||||
use super::{segments_properly_intersect, signed_area, EPS_ANGLE, EPS_AREA, EPS_GEOM};
|
||||
|
||||
/// Validation errors returned by [`Polygon::new`] and friends.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum PolygonError {
|
||||
/// Fewer than 3 vertices.
|
||||
#[error("polygon needs at least 3 vertices, got {0}")]
|
||||
TooFewVertices(usize),
|
||||
/// Two consecutive vertices coincide within `EPS_GEOM`.
|
||||
#[error("polygon has a zero-length edge at vertex {0}")]
|
||||
ZeroEdge(usize),
|
||||
/// Three consecutive vertices are collinear within `EPS_ANGLE`.
|
||||
#[error("polygon has collinear vertices at {0}")]
|
||||
CollinearTriple(usize),
|
||||
/// Polygon edges cross.
|
||||
#[error("polygon is self-intersecting")]
|
||||
SelfIntersecting,
|
||||
/// |signed area| < `EPS_AREA`.
|
||||
#[error("polygon has near-zero area")]
|
||||
Degenerate,
|
||||
}
|
||||
|
||||
/// A simple polygon stored as a CCW ring of vertices. The ring is not
|
||||
/// closed in storage (last vertex != first vertex).
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Polygon {
|
||||
verts: Vec<DVec2>,
|
||||
}
|
||||
|
||||
impl Polygon {
|
||||
/// Construct a polygon from a vertex ring. Validates I1.
|
||||
///
|
||||
/// Cleans up trailing duplicates of the first vertex and reverses
|
||||
/// the ring if it was passed clockwise.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a [`PolygonError`] if validation fails.
|
||||
pub fn new(verts: Vec<DVec2>) -> Result<Self, PolygonError> {
|
||||
Self::new_inner(verts, true)
|
||||
}
|
||||
|
||||
/// Like [`Polygon::new`] but does *not* reject collinear triples.
|
||||
/// Used internally for block boundaries, which legitimately
|
||||
/// contain collinear-corner vertices when adjacent road segments
|
||||
/// are end-to-end (the `colinear_roads` degenerate case in spec
|
||||
/// §5).
|
||||
pub(crate) fn new_relaxed(verts: Vec<DVec2>) -> Result<Self, PolygonError> {
|
||||
Self::new_inner(verts, false)
|
||||
}
|
||||
|
||||
fn new_inner(mut verts: Vec<DVec2>, strict: bool) -> Result<Self, PolygonError> {
|
||||
// Drop a closing duplicate if present.
|
||||
if verts.len() >= 2 {
|
||||
let first = verts[0];
|
||||
let last = *verts.last().expect("len >= 2");
|
||||
if (first - last).length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
verts.pop();
|
||||
}
|
||||
}
|
||||
if verts.len() < 3 {
|
||||
return Err(PolygonError::TooFewVertices(verts.len()));
|
||||
}
|
||||
// Zero-edge check.
|
||||
for i in 0..verts.len() {
|
||||
let j = (i + 1) % verts.len();
|
||||
if (verts[j] - verts[i]).length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
return Err(PolygonError::ZeroEdge(i));
|
||||
}
|
||||
}
|
||||
// Self-intersection check first — bowtie shapes can have
|
||||
// zero algebraic area, which would otherwise be reported as
|
||||
// `Degenerate` and obscure the real reason.
|
||||
if has_self_intersection(&verts) {
|
||||
return Err(PolygonError::SelfIntersecting);
|
||||
}
|
||||
// Compute signed area; if negative, reverse to CCW.
|
||||
let mut area = signed_area(&verts);
|
||||
if area < 0.0 {
|
||||
verts.reverse();
|
||||
area = -area;
|
||||
}
|
||||
if area < EPS_AREA {
|
||||
return Err(PolygonError::Degenerate);
|
||||
}
|
||||
if strict {
|
||||
// Collinear triple check (parcel polygons only — block
|
||||
// polygons skip this).
|
||||
for i in 0..verts.len() {
|
||||
let h = (i + verts.len() - 1) % verts.len();
|
||||
let j = (i + 1) % verts.len();
|
||||
let a = (verts[i] - verts[h]).normalize_or_zero();
|
||||
let b = (verts[j] - verts[i]).normalize_or_zero();
|
||||
if (a.x * b.y - a.y * b.x).abs() < EPS_ANGLE && a.dot(b) > 0.0 {
|
||||
return Err(PolygonError::CollinearTriple(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self { verts })
|
||||
}
|
||||
|
||||
/// Access the vertex ring (CCW, not closed).
|
||||
#[must_use]
|
||||
pub fn vertices(&self) -> &[DVec2] {
|
||||
&self.verts
|
||||
}
|
||||
|
||||
/// Number of vertices in the ring.
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.verts.len()
|
||||
}
|
||||
|
||||
/// Whether the ring is empty. Always false for a valid polygon
|
||||
/// (kept for clippy `len_without_is_empty`).
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.verts.is_empty()
|
||||
}
|
||||
|
||||
/// Signed area; always non-negative for a valid CCW polygon.
|
||||
#[must_use]
|
||||
pub fn area(&self) -> f64 {
|
||||
signed_area(&self.verts).abs()
|
||||
}
|
||||
|
||||
/// Edges as iterator of `(start, end)` pairs in ring order.
|
||||
pub fn edges(&self) -> impl Iterator<Item = (DVec2, DVec2)> + '_ {
|
||||
let n = self.verts.len();
|
||||
(0..n).map(move |i| (self.verts[i], self.verts[(i + 1) % n]))
|
||||
}
|
||||
|
||||
/// Centroid (area-weighted), well-defined for non-degenerate
|
||||
/// polygons.
|
||||
#[must_use]
|
||||
pub fn centroid(&self) -> DVec2 {
|
||||
let mut a = 0.0;
|
||||
let mut cx = 0.0;
|
||||
let mut cy = 0.0;
|
||||
let n = self.verts.len();
|
||||
for i in 0..n {
|
||||
let p = self.verts[i];
|
||||
let q = self.verts[(i + 1) % n];
|
||||
let cross = p.x * q.y - q.x * p.y;
|
||||
a += cross;
|
||||
cx += (p.x + q.x) * cross;
|
||||
cy += (p.y + q.y) * cross;
|
||||
}
|
||||
a *= 0.5;
|
||||
if a.abs() < EPS_AREA {
|
||||
// Fall back to vertex average for near-degenerate input.
|
||||
let sum: DVec2 = self.verts.iter().copied().sum();
|
||||
return sum / (n as f64);
|
||||
}
|
||||
DVec2::new(cx / (6.0 * a), cy / (6.0 * a))
|
||||
}
|
||||
|
||||
/// Clip this polygon against the closed half-plane defined by a
|
||||
/// point on the line and an inward normal. Returns `None` if the
|
||||
/// result is empty (everything was on the outer side) or invalid.
|
||||
///
|
||||
/// Implements Sutherland–Hodgman polygon-vs-half-plane clipping.
|
||||
/// Robust for convex *and* concave inputs as long as the half
|
||||
/// plane carves a single piece.
|
||||
#[must_use]
|
||||
pub fn clip_half_plane(&self, point: DVec2, inward_normal: DVec2) -> Option<Self> {
|
||||
let n = inward_normal;
|
||||
if n.length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
return Some(self.clone());
|
||||
}
|
||||
let n = n.normalize();
|
||||
let inside = |p: DVec2| (p - point).dot(n) >= -EPS_GEOM;
|
||||
let intersect = |a: DVec2, b: DVec2| -> Option<DVec2> {
|
||||
let da = (a - point).dot(n);
|
||||
let db = (b - point).dot(n);
|
||||
let denom = da - db;
|
||||
if denom.abs() < EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let t = da / denom;
|
||||
Some(a + (b - a) * t)
|
||||
};
|
||||
|
||||
let mut out = Vec::with_capacity(self.verts.len() + 2);
|
||||
let len = self.verts.len();
|
||||
for i in 0..len {
|
||||
let a = self.verts[i];
|
||||
let b = self.verts[(i + 1) % len];
|
||||
let a_in = inside(a);
|
||||
let b_in = inside(b);
|
||||
match (a_in, b_in) {
|
||||
(true, true) => out.push(b),
|
||||
(true, false) => {
|
||||
if let Some(p) = intersect(a, b) {
|
||||
out.push(p);
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
if let Some(p) = intersect(a, b) {
|
||||
out.push(p);
|
||||
}
|
||||
out.push(b);
|
||||
}
|
||||
(false, false) => {}
|
||||
}
|
||||
}
|
||||
if out.len() < 3 {
|
||||
return None;
|
||||
}
|
||||
// Strip near-duplicate consecutive vertices.
|
||||
let cleaned = strip_near_duplicates(out);
|
||||
if cleaned.len() < 3 {
|
||||
return None;
|
||||
}
|
||||
Self::new(cleaned).ok()
|
||||
}
|
||||
|
||||
/// Check whether this polygon contains a point (open interior, by
|
||||
/// even-odd rule). Valid for simple polygons of any convexity.
|
||||
#[must_use]
|
||||
pub fn contains(&self, p: DVec2) -> bool {
|
||||
let mut inside = false;
|
||||
let n = self.verts.len();
|
||||
let mut j = n - 1;
|
||||
for i in 0..n {
|
||||
let a = self.verts[i];
|
||||
let b = self.verts[j];
|
||||
let cond =
|
||||
(a.y > p.y) != (b.y > p.y) && p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x;
|
||||
if cond {
|
||||
inside = !inside;
|
||||
}
|
||||
j = i;
|
||||
}
|
||||
inside
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_near_duplicates(verts: Vec<DVec2>) -> Vec<DVec2> {
|
||||
let mut out: Vec<DVec2> = Vec::with_capacity(verts.len());
|
||||
for v in verts {
|
||||
if let Some(&last) = out.last() {
|
||||
if (v - last).length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
out.push(v);
|
||||
}
|
||||
if out.len() >= 2 {
|
||||
let first = out[0];
|
||||
let last = *out.last().expect("len >= 2");
|
||||
if (first - last).length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
out.pop();
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn has_self_intersection(verts: &[DVec2]) -> bool {
|
||||
let n = verts.len();
|
||||
if n < 4 {
|
||||
return false;
|
||||
}
|
||||
for i in 0..n {
|
||||
let a1 = verts[i];
|
||||
let a2 = verts[(i + 1) % n];
|
||||
// skip self and adjacent edges (share a vertex)
|
||||
for j in (i + 2)..n {
|
||||
// adjacency wrap: edge (n-1, 0) is adjacent to edge (0, 1)
|
||||
if i == 0 && j == n - 1 {
|
||||
continue;
|
||||
}
|
||||
let b1 = verts[j];
|
||||
let b2 = verts[(j + 1) % n];
|
||||
if segments_properly_intersect(a1, a2, b1, b2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn unit_square() -> Polygon {
|
||||
Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(1.0, 0.0),
|
||||
DVec2::new(1.0, 1.0),
|
||||
DVec2::new(0.0, 1.0),
|
||||
])
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_square_area_is_one() {
|
||||
assert!((unit_square().area() - 1.0).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cw_input_is_normalized_to_ccw() {
|
||||
let p = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(0.0, 1.0),
|
||||
DVec2::new(1.0, 1.0),
|
||||
DVec2::new(1.0, 0.0),
|
||||
])
|
||||
.unwrap();
|
||||
assert!((p.area() - 1.0).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collinear_triple_rejected() {
|
||||
let err = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(1.0, 0.0),
|
||||
DVec2::new(2.0, 0.0),
|
||||
DVec2::new(2.0, 1.0),
|
||||
DVec2::new(0.0, 1.0),
|
||||
])
|
||||
.unwrap_err();
|
||||
matches!(err, PolygonError::CollinearTriple(_));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_intersection_rejected() {
|
||||
let err = Polygon::new(vec![
|
||||
DVec2::new(0.0, 0.0),
|
||||
DVec2::new(1.0, 1.0),
|
||||
DVec2::new(1.0, 0.0),
|
||||
DVec2::new(0.0, 1.0),
|
||||
])
|
||||
.unwrap_err();
|
||||
assert!(matches!(err, PolygonError::SelfIntersecting));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_point() {
|
||||
let p = unit_square();
|
||||
assert!(p.contains(DVec2::new(0.5, 0.5)));
|
||||
assert!(!p.contains(DVec2::new(1.5, 0.5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn half_plane_clip_keeps_inside() {
|
||||
let p = unit_square();
|
||||
// keep y >= 0.5
|
||||
let clipped = p
|
||||
.clip_half_plane(DVec2::new(0.0, 0.5), DVec2::new(0.0, 1.0))
|
||||
.unwrap();
|
||||
assert!((clipped.area() - 0.5).abs() < 1e-9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn half_plane_clip_returns_none_when_empty() {
|
||||
let p = unit_square();
|
||||
let clipped = p.clip_half_plane(DVec2::new(0.0, 2.0), DVec2::new(0.0, 1.0));
|
||||
assert!(clipped.is_none());
|
||||
}
|
||||
}
|
||||
50
road_parceling/src/lib.rs
Normal file
@ -0,0 +1,50 @@
|
||||
//! Road-frontage-based parcel subdivision for a city simulation game.
|
||||
//!
|
||||
//! This crate is a pure-logic geometric layer: it consumes a planar
|
||||
//! road graph and produces a set of polygonal parcels with each parcel
|
||||
//! facing exactly one road. It does not render, simulate buildings, or
|
||||
//! drive a game loop.
|
||||
//!
|
||||
//! See `journal.tex` at the repository root for the full design
|
||||
//! specification. Section numbers cited here refer to that document.
|
||||
//!
|
||||
//! # Quick start
|
||||
//!
|
||||
//! ```
|
||||
//! use road_parceling::{RoadGraph, SubdivisionParams, subdivide_all};
|
||||
//! use glam::DVec2;
|
||||
//!
|
||||
//! let mut g = RoadGraph::new();
|
||||
//! let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
//! let b = g.add_node(DVec2::new(200.0, 0.0));
|
||||
//! let c = g.add_node(DVec2::new(200.0, 100.0));
|
||||
//! let d = g.add_node(DVec2::new(0.0, 100.0));
|
||||
//! g.add_road(a, b).unwrap();
|
||||
//! g.add_road(b, c).unwrap();
|
||||
//! g.add_road(c, d).unwrap();
|
||||
//! g.add_road(d, a).unwrap();
|
||||
//!
|
||||
//! let params = SubdivisionParams::default();
|
||||
//! let parcels = subdivide_all(&g, ¶ms).unwrap();
|
||||
//! assert!(!parcels.is_empty());
|
||||
//! ```
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod geometry;
|
||||
pub mod network;
|
||||
pub mod parcel;
|
||||
|
||||
#[cfg(feature = "viz")]
|
||||
pub mod viz;
|
||||
|
||||
pub use config::SubdivisionParams;
|
||||
pub use error::{ParcelError, SubdivisionError};
|
||||
pub use network::{NodeId, RoadGraph, RoadId};
|
||||
pub use parcel::{
|
||||
apply_road_edit, subdivide_all, subdivide_all_with_stats, BuildingFitCheck, BuildingHandle,
|
||||
EdgeKind, EditOutcome, Parcel, ParcelId, ParcelSet, RoadEdit, SubdivisionStats,
|
||||
};
|
||||
113
road_parceling/src/network/blocks.rs
Normal file
@ -0,0 +1,113 @@
|
||||
//! Block extraction from the half-edge graph (spec §2.4).
|
||||
//!
|
||||
//! A *block* is a bounded face of the planar road graph. Each block
|
||||
//! carries its boundary polygon (CCW) plus, for every edge in the
|
||||
//! ring, the [`RoadId`] of the road that edge runs along.
|
||||
|
||||
use glam::DVec2;
|
||||
|
||||
use crate::geometry::Polygon;
|
||||
use crate::network::graph::{FaceId, HalfEdgeId, RoadGraph, RoadId};
|
||||
|
||||
/// A bounded face — the geometric block to be subdivided.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Block {
|
||||
/// Stable face identifier within the graph.
|
||||
pub(crate) face: FaceId,
|
||||
/// Boundary polygon, CCW, with vertex \(i\) at the origin of
|
||||
/// `boundary_edges[i]`.
|
||||
pub polygon: Polygon,
|
||||
/// Half-edge cycle bounding this block, parallel to
|
||||
/// `polygon.vertices()`. Reserved for milestone 0.2's
|
||||
/// edit-preserves path.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) boundary_edges: Vec<HalfEdgeId>,
|
||||
/// Road associated with each boundary edge, parallel to
|
||||
/// `polygon.vertices()`.
|
||||
pub roads: Vec<RoadId>,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
/// Vertex positions of the block boundary, CCW.
|
||||
#[must_use]
|
||||
pub fn boundary(&self) -> &[DVec2] {
|
||||
self.polygon.vertices()
|
||||
}
|
||||
|
||||
/// Face id this block was extracted from.
|
||||
#[must_use]
|
||||
pub(crate) fn face_id(&self) -> FaceId {
|
||||
self.face
|
||||
}
|
||||
|
||||
/// Half-edge cycle for this block. Reserved for milestone 0.2's
|
||||
/// edit-preserves path; currently exposed crate-internally so
|
||||
/// the edit pipeline can wire up to it.
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn boundary_edges(&self) -> &[HalfEdgeId] {
|
||||
&self.boundary_edges
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract every bounded face of `graph` as a [`Block`]. Caller must
|
||||
/// ensure `rebuild_topology` has been run.
|
||||
pub(crate) fn extract_blocks(graph: &RoadGraph) -> Vec<Block> {
|
||||
let mut out = Vec::new();
|
||||
for (face_id, face) in &graph.faces {
|
||||
if face.is_exterior {
|
||||
continue;
|
||||
}
|
||||
let mut edges = Vec::new();
|
||||
let mut verts = Vec::new();
|
||||
let mut roads = Vec::new();
|
||||
let start = face.boundary;
|
||||
let mut h = start;
|
||||
loop {
|
||||
edges.push(h);
|
||||
let he = graph.half_edges[h];
|
||||
verts.push(graph.nodes[he.origin].pos);
|
||||
roads.push(he.road);
|
||||
h = he.next;
|
||||
if h == start {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Block boundaries may legitimately contain collinear-corner
|
||||
// vertices (where two end-to-end roads share a node), so use
|
||||
// the relaxed validator here. Parcel polygons remain strict.
|
||||
let Ok(polygon) = Polygon::new_relaxed(verts) else {
|
||||
continue;
|
||||
};
|
||||
out.push(Block {
|
||||
face: face_id,
|
||||
polygon,
|
||||
boundary_edges: edges,
|
||||
roads,
|
||||
});
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn square_yields_one_block() {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(100.0, 0.0));
|
||||
let c = g.add_node(DVec2::new(100.0, 50.0));
|
||||
let d = g.add_node(DVec2::new(0.0, 50.0));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(b, c).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
g.add_road(d, a).unwrap();
|
||||
g.rebuild_topology().unwrap();
|
||||
let blocks = extract_blocks(&g);
|
||||
assert_eq!(blocks.len(), 1);
|
||||
assert_eq!(blocks[0].polygon.len(), 4);
|
||||
assert!((blocks[0].polygon.area() - 100.0 * 50.0).abs() < 1e-6);
|
||||
}
|
||||
}
|
||||
395
road_parceling/src/network/graph.rs
Normal file
@ -0,0 +1,395 @@
|
||||
//! Half-edge / DCEL graph (spec §2.3, D2).
|
||||
//!
|
||||
//! Construction is two-phase:
|
||||
//!
|
||||
//! 1. Caller adds nodes (`add_node`) and roads (`add_road`).
|
||||
//! 2. The graph runs `rebuild_topology` (called automatically by
|
||||
//! `subdivide_all`) which builds half-edges, sorts them at each
|
||||
//! vertex by angle, links `next`/`prev`, and extracts faces.
|
||||
|
||||
use glam::DVec2;
|
||||
use slotmap::{new_key_type, Key, SlotMap};
|
||||
|
||||
use crate::error::SubdivisionError;
|
||||
use crate::geometry::{segments_properly_intersect, signed_area, EPS_GEOM};
|
||||
|
||||
new_key_type! {
|
||||
/// Stable identifier for a graph node (intersection).
|
||||
pub struct NodeId;
|
||||
/// Stable identifier for a road segment.
|
||||
pub struct RoadId;
|
||||
}
|
||||
|
||||
new_key_type! {
|
||||
pub(crate) struct HalfEdgeId;
|
||||
pub(crate) struct FaceId;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub(crate) struct Node {
|
||||
pub pos: DVec2,
|
||||
/// Outgoing half-edges sorted CCW by direction angle. Maintained
|
||||
/// by `rebuild_topology`.
|
||||
pub outgoing: Vec<HalfEdgeId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub(crate) struct Road {
|
||||
pub a: NodeId,
|
||||
pub b: NodeId,
|
||||
pub half_a_to_b: HalfEdgeId,
|
||||
pub half_b_to_a: HalfEdgeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub(crate) struct HalfEdge {
|
||||
pub origin: NodeId,
|
||||
pub twin: HalfEdgeId,
|
||||
pub next: HalfEdgeId,
|
||||
pub prev: HalfEdgeId,
|
||||
pub face: Option<FaceId>,
|
||||
pub road: RoadId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub(crate) struct Face {
|
||||
pub boundary: HalfEdgeId,
|
||||
pub is_exterior: bool,
|
||||
}
|
||||
|
||||
/// Planar road graph. Maintains a half-edge data structure with stable
|
||||
/// IDs across edits.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct RoadGraph {
|
||||
pub(crate) nodes: SlotMap<NodeId, Node>,
|
||||
pub(crate) roads: SlotMap<RoadId, Road>,
|
||||
pub(crate) half_edges: SlotMap<HalfEdgeId, HalfEdge>,
|
||||
pub(crate) faces: SlotMap<FaceId, Face>,
|
||||
/// True after `rebuild_topology`; cleared by any mutation.
|
||||
pub(crate) topology_valid: bool,
|
||||
}
|
||||
|
||||
impl RoadGraph {
|
||||
/// Empty graph.
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Insert a new node at `pos`. The graph allows two nodes within
|
||||
/// `EPS_GEOM` of each other but downstream subdivision will reject
|
||||
/// them via the `near_duplicate_nodes` test in §5.
|
||||
pub fn add_node(&mut self, pos: DVec2) -> NodeId {
|
||||
self.topology_valid = false;
|
||||
self.nodes.insert(Node {
|
||||
pos,
|
||||
outgoing: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Position of a node, or `None` if the ID has been deleted.
|
||||
#[must_use]
|
||||
pub fn node_position(&self, id: NodeId) -> Option<DVec2> {
|
||||
self.nodes.get(id).map(|n| n.pos)
|
||||
}
|
||||
|
||||
/// Insert a road between two existing nodes.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `InvalidParams` if either node is unknown, the two
|
||||
/// nodes are the same, or a duplicate road already exists.
|
||||
pub fn add_road(&mut self, a: NodeId, b: NodeId) -> Result<RoadId, SubdivisionError> {
|
||||
if a == b {
|
||||
return Err(SubdivisionError::InvalidParams(
|
||||
"road endpoints must differ".into(),
|
||||
));
|
||||
}
|
||||
if !self.nodes.contains_key(a) || !self.nodes.contains_key(b) {
|
||||
return Err(SubdivisionError::InvalidParams("unknown node id".into()));
|
||||
}
|
||||
if self.find_road_between(a, b).is_some() {
|
||||
return Err(SubdivisionError::InvalidParams(
|
||||
"duplicate road between nodes".into(),
|
||||
));
|
||||
}
|
||||
self.topology_valid = false;
|
||||
Ok(self.roads.insert(Road {
|
||||
a,
|
||||
b,
|
||||
half_a_to_b: HalfEdgeId::null(),
|
||||
half_b_to_a: HalfEdgeId::null(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Iterate over `(RoadId, NodeId, NodeId)` triples — useful for
|
||||
/// rendering and for tests.
|
||||
pub fn road_endpoints(&self) -> impl Iterator<Item = (RoadId, NodeId, NodeId)> + '_ {
|
||||
self.roads.iter().map(|(rid, r)| (rid, r.a, r.b))
|
||||
}
|
||||
|
||||
/// Number of roads currently in the graph.
|
||||
#[must_use]
|
||||
pub fn road_count(&self) -> usize {
|
||||
self.roads.len()
|
||||
}
|
||||
|
||||
/// Number of nodes currently in the graph.
|
||||
#[must_use]
|
||||
pub fn node_count(&self) -> usize {
|
||||
self.nodes.len()
|
||||
}
|
||||
|
||||
/// Find the road between `a` and `b`, in either direction.
|
||||
pub(crate) fn find_road_between(&self, a: NodeId, b: NodeId) -> Option<RoadId> {
|
||||
self.roads
|
||||
.iter()
|
||||
.find(|(_, r)| (r.a == a && r.b == b) || (r.a == b && r.b == a))
|
||||
.map(|(rid, _)| rid)
|
||||
}
|
||||
|
||||
/// Endpoints of a road, in storage order.
|
||||
pub(crate) fn road_nodes(&self, rid: RoadId) -> Option<(NodeId, NodeId)> {
|
||||
self.roads.get(rid).map(|r| (r.a, r.b))
|
||||
}
|
||||
|
||||
/// Build twin/next/prev pointers and extract faces. Idempotent.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// `NonPlanarGraph` if two non-incident roads cross. `OpenBlock`
|
||||
/// if face traversal fails.
|
||||
pub fn rebuild_topology(&mut self) -> Result<(), SubdivisionError> {
|
||||
if self.topology_valid {
|
||||
return Ok(());
|
||||
}
|
||||
self.check_planarity()?;
|
||||
self.build_half_edges();
|
||||
self.sort_outgoing_by_angle();
|
||||
self.link_next_and_prev();
|
||||
self.extract_faces()?;
|
||||
self.topology_valid = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_planarity(&self) -> Result<(), SubdivisionError> {
|
||||
let segs: Vec<(RoadId, DVec2, DVec2)> = self
|
||||
.roads
|
||||
.iter()
|
||||
.map(|(rid, r)| (rid, self.nodes[r.a].pos, self.nodes[r.b].pos))
|
||||
.collect();
|
||||
let road_endpts: Vec<(NodeId, NodeId)> = self.roads.values().map(|r| (r.a, r.b)).collect();
|
||||
for (i, &(_, p1, p2)) in segs.iter().enumerate() {
|
||||
for j in (i + 1)..segs.len() {
|
||||
let (_, p3, p4) = segs[j];
|
||||
let (a1, b1) = road_endpts[i];
|
||||
let (a2, b2) = road_endpts[j];
|
||||
// skip pairs that share a node — they meet legally
|
||||
if a1 == a2 || a1 == b2 || b1 == a2 || b1 == b2 {
|
||||
continue;
|
||||
}
|
||||
if segments_properly_intersect(p1, p2, p3, p4) {
|
||||
// Pick the closer of (a2, b2) for the error
|
||||
// message; either is informative.
|
||||
return Err(SubdivisionError::NonPlanarGraph(a2));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_half_edges(&mut self) {
|
||||
// Clear prior topology.
|
||||
self.half_edges.clear();
|
||||
self.faces.clear();
|
||||
for (_, n) in &mut self.nodes {
|
||||
n.outgoing.clear();
|
||||
}
|
||||
let road_keys: Vec<RoadId> = self.roads.keys().collect();
|
||||
for rid in road_keys {
|
||||
let (a, b) = {
|
||||
let r = &self.roads[rid];
|
||||
(r.a, r.b)
|
||||
};
|
||||
let h_ab = self.half_edges.insert(HalfEdge {
|
||||
origin: a,
|
||||
twin: HalfEdgeId::null(),
|
||||
next: HalfEdgeId::null(),
|
||||
prev: HalfEdgeId::null(),
|
||||
face: None,
|
||||
road: rid,
|
||||
});
|
||||
let h_ba = self.half_edges.insert(HalfEdge {
|
||||
origin: b,
|
||||
twin: h_ab,
|
||||
next: HalfEdgeId::null(),
|
||||
prev: HalfEdgeId::null(),
|
||||
face: None,
|
||||
road: rid,
|
||||
});
|
||||
self.half_edges[h_ab].twin = h_ba;
|
||||
self.nodes[a].outgoing.push(h_ab);
|
||||
self.nodes[b].outgoing.push(h_ba);
|
||||
let r = &mut self.roads[rid];
|
||||
r.half_a_to_b = h_ab;
|
||||
r.half_b_to_a = h_ba;
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_outgoing_by_angle(&mut self) {
|
||||
let node_keys: Vec<NodeId> = self.nodes.keys().collect();
|
||||
for nid in node_keys {
|
||||
let pos = self.nodes[nid].pos;
|
||||
let outgoing: Vec<HalfEdgeId> = self.nodes[nid].outgoing.clone();
|
||||
let mut with_angles: Vec<(f64, HalfEdgeId)> = Vec::with_capacity(outgoing.len());
|
||||
for h in outgoing {
|
||||
let twin = self.half_edges[h].twin;
|
||||
let target = self.half_edges[twin].origin;
|
||||
let dir = self.nodes[target].pos - pos;
|
||||
let angle = dir.y.atan2(dir.x);
|
||||
with_angles.push((angle, h));
|
||||
}
|
||||
with_angles.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(std::cmp::Ordering::Equal));
|
||||
self.nodes[nid].outgoing = with_angles.into_iter().map(|(_, h)| h).collect();
|
||||
}
|
||||
}
|
||||
|
||||
fn link_next_and_prev(&mut self) {
|
||||
let edge_keys: Vec<HalfEdgeId> = self.half_edges.keys().collect();
|
||||
for h in edge_keys {
|
||||
// For a CCW interior face, h's `next` is the half-edge
|
||||
// making the smallest left turn at h.target. Concretely:
|
||||
// at v = h.target, scan v's CCW-sorted outgoing list and
|
||||
// take the immediate predecessor (CW neighbor) of
|
||||
// h.twin. This is the standard DCEL rule.
|
||||
let twin = self.half_edges[h].twin;
|
||||
let v = self.half_edges[twin].origin;
|
||||
let v_outgoing = &self.nodes[v].outgoing;
|
||||
let pos_in_v = v_outgoing
|
||||
.iter()
|
||||
.position(|&x| x == twin)
|
||||
.expect("twin must appear in target's outgoing list");
|
||||
let next = v_outgoing[(pos_in_v + v_outgoing.len() - 1) % v_outgoing.len()];
|
||||
self.half_edges[h].next = next;
|
||||
|
||||
// h.prev = the half-edge whose `.next` is h. That is the
|
||||
// CCW *successor* of h in h.origin's outgoing list,
|
||||
// taken twin-of.
|
||||
let u = self.half_edges[h].origin;
|
||||
let u_outgoing = &self.nodes[u].outgoing;
|
||||
let pos_in_u = u_outgoing
|
||||
.iter()
|
||||
.position(|&x| x == h)
|
||||
.expect("h must appear in origin's outgoing list");
|
||||
let succ = u_outgoing[(pos_in_u + 1) % u_outgoing.len()];
|
||||
let prev = self.half_edges[succ].twin;
|
||||
self.half_edges[h].prev = prev;
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_faces(&mut self) -> Result<(), SubdivisionError> {
|
||||
let edge_keys: Vec<HalfEdgeId> = self.half_edges.keys().collect();
|
||||
for h_start in edge_keys {
|
||||
if self.half_edges[h_start].face.is_some() {
|
||||
continue;
|
||||
}
|
||||
// Walk the cycle, capturing vertex positions for area sign.
|
||||
let mut cycle = Vec::new();
|
||||
let mut h = h_start;
|
||||
let max_iter = self.half_edges.len() + 4;
|
||||
let mut iters = 0;
|
||||
loop {
|
||||
cycle.push(h);
|
||||
let next = self.half_edges[h].next;
|
||||
if next.is_null() {
|
||||
return Err(SubdivisionError::OpenBlock);
|
||||
}
|
||||
h = next;
|
||||
iters += 1;
|
||||
if iters > max_iter {
|
||||
return Err(SubdivisionError::OpenBlock);
|
||||
}
|
||||
if h == h_start {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let pts: Vec<DVec2> = cycle
|
||||
.iter()
|
||||
.map(|&hid| self.nodes[self.half_edges[hid].origin].pos)
|
||||
.collect();
|
||||
let signed = signed_area(&pts);
|
||||
let is_exterior = signed < 0.0 || signed.abs() < EPS_GEOM;
|
||||
let face_id = self.faces.insert(Face {
|
||||
boundary: h_start,
|
||||
is_exterior,
|
||||
});
|
||||
for h in cycle {
|
||||
self.half_edges[h].face = Some(face_id);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn square_graph() -> RoadGraph {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(1.0, 0.0));
|
||||
let c = g.add_node(DVec2::new(1.0, 1.0));
|
||||
let d = g.add_node(DVec2::new(0.0, 1.0));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(b, c).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
g.add_road(d, a).unwrap();
|
||||
g
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn square_yields_two_faces() {
|
||||
let mut g = square_graph();
|
||||
g.rebuild_topology().unwrap();
|
||||
assert_eq!(g.faces.len(), 2);
|
||||
let exterior = g.faces.values().filter(|f| f.is_exterior).count();
|
||||
assert_eq!(exterior, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_road_rejected() {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(1.0, 0.0));
|
||||
g.add_road(a, b).unwrap();
|
||||
assert!(g.add_road(a, b).is_err());
|
||||
assert!(g.add_road(b, a).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_loop_rejected() {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
assert!(g.add_road(a, a).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_planar_graph_detected() {
|
||||
// Two crossing roads with no node at the crossing.
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(2.0, 2.0));
|
||||
let c = g.add_node(DVec2::new(0.0, 2.0));
|
||||
let d = g.add_node(DVec2::new(2.0, 0.0));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
let err = g.rebuild_topology().unwrap_err();
|
||||
assert!(matches!(err, SubdivisionError::NonPlanarGraph(_)));
|
||||
}
|
||||
}
|
||||
14
road_parceling/src/network/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//! Planar road graph in half-edge / DCEL form (spec §2.3).
|
||||
//!
|
||||
//! Nodes are intersections; roads are straight edges between two
|
||||
//! nodes. Each road is represented internally by two opposing
|
||||
//! half-edges. Blocks are the bounded faces of this graph.
|
||||
//!
|
||||
//! Stable IDs are minted by `slotmap` so that the same node, road, or
|
||||
//! parcel survives unrelated insertions and deletions (D3).
|
||||
|
||||
pub mod blocks;
|
||||
pub mod graph;
|
||||
|
||||
pub use blocks::Block;
|
||||
pub use graph::{NodeId, RoadGraph, RoadId};
|
||||
61
road_parceling/src/parcel/classify.rs
Normal file
@ -0,0 +1,61 @@
|
||||
//! Edge classification (spec §3.2).
|
||||
//!
|
||||
//! After the parcel polygon is built and its frontage edge index
|
||||
//! recorded, this pass labels every edge as `Frontage`, `Side`, or
|
||||
//! `Back`. Side edges are the two adjacent to the frontage edge in
|
||||
//! ring order; back edges are everything else.
|
||||
|
||||
use super::EdgeKind;
|
||||
|
||||
/// Build an edge-kind vector parallel to a polygon's edge ring.
|
||||
#[must_use]
|
||||
pub(crate) fn classify_edges(num_edges: usize, frontage_idx: usize) -> Vec<EdgeKind> {
|
||||
let mut kinds = vec![EdgeKind::Back; num_edges];
|
||||
if num_edges == 0 {
|
||||
return kinds;
|
||||
}
|
||||
kinds[frontage_idx] = EdgeKind::Frontage;
|
||||
let prev = (frontage_idx + num_edges - 1) % num_edges;
|
||||
let next = (frontage_idx + 1) % num_edges;
|
||||
if prev != frontage_idx {
|
||||
kinds[prev] = EdgeKind::Side;
|
||||
}
|
||||
if next != frontage_idx && next != prev {
|
||||
kinds[next] = EdgeKind::Side;
|
||||
}
|
||||
kinds
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn quadrilateral_classification() {
|
||||
let k = classify_edges(4, 0);
|
||||
assert_eq!(
|
||||
k,
|
||||
vec![
|
||||
EdgeKind::Frontage,
|
||||
EdgeKind::Side,
|
||||
EdgeKind::Back,
|
||||
EdgeKind::Side,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pentagonal_classification() {
|
||||
let k = classify_edges(5, 2);
|
||||
assert_eq!(
|
||||
k,
|
||||
vec![
|
||||
EdgeKind::Back,
|
||||
EdgeKind::Side,
|
||||
EdgeKind::Frontage,
|
||||
EdgeKind::Side,
|
||||
EdgeKind::Back,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
506
road_parceling/src/parcel/deform.rs
Normal file
@ -0,0 +1,506 @@
|
||||
//! Road-edit deformation pipeline (spec §4, milestone 0.2).
|
||||
//!
|
||||
//! `apply_road_edit` is the public entry point. The implementation
|
||||
//! tries to *preserve* parcels when possible (re-projecting only the
|
||||
//! frontage vertices onto the new road geometry; side and back
|
||||
//! vertices stay fixed in absolute world coordinates per **D13**)
|
||||
//! and falls back to regenerating the affected blocks when
|
||||
//! preservation would violate any of:
|
||||
//!
|
||||
//! - I1 (resulting polygon is invalid),
|
||||
//! - the rotation threshold of \cref{sec:edit-handling}
|
||||
//! (`params.max_side_rotation`),
|
||||
//! - the area or frontage minimums (`min_area`, `min_frontage`).
|
||||
//!
|
||||
//! Buildings attached to surviving parcels are kept iff
|
||||
//! `BuildingFitCheck::fits_in` returns true post-deformation;
|
||||
//! otherwise the building is evicted.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use glam::DVec2;
|
||||
use slotmap::Key;
|
||||
|
||||
use crate::config::SubdivisionParams;
|
||||
use crate::error::ParcelError;
|
||||
use crate::geometry::{Polygon, EPS_GEOM};
|
||||
use crate::network::graph::FaceId;
|
||||
use crate::network::{NodeId, RoadGraph, RoadId};
|
||||
use crate::parcel::subdivide::subdivide_block;
|
||||
use crate::parcel::ParcelId;
|
||||
|
||||
use super::{Parcel, ParcelSet};
|
||||
|
||||
/// A road-network mutation that may rearrange surrounding parcels.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[non_exhaustive]
|
||||
pub enum RoadEdit {
|
||||
/// Move the position of an existing intersection.
|
||||
MoveNode {
|
||||
/// Target node.
|
||||
node: NodeId,
|
||||
/// New position, meters.
|
||||
to: DVec2,
|
||||
},
|
||||
/// Split a road segment by inserting a new node along it.
|
||||
SplitSegment {
|
||||
/// Road being split.
|
||||
road: RoadId,
|
||||
/// Position of the new node (must lie on the segment).
|
||||
at: DVec2,
|
||||
},
|
||||
/// Delete a road segment.
|
||||
DeleteSegment {
|
||||
/// Road being deleted.
|
||||
road: RoadId,
|
||||
},
|
||||
/// Insert a new road between two existing nodes.
|
||||
InsertSegment {
|
||||
/// Endpoint A.
|
||||
from: NodeId,
|
||||
/// Endpoint B.
|
||||
to: NodeId,
|
||||
},
|
||||
}
|
||||
|
||||
/// Outcome buckets for an edit application (spec §4.2).
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[must_use]
|
||||
pub struct EditOutcome {
|
||||
/// Parcels that survived deformation.
|
||||
pub deformed: Vec<ParcelId>,
|
||||
/// Parcels whose block was re-subdivided.
|
||||
pub regenerated: Vec<ParcelId>,
|
||||
/// Parcels removed by the edit.
|
||||
pub condemned: Vec<ParcelId>,
|
||||
/// Parcels newly created during regeneration.
|
||||
pub created: Vec<ParcelId>,
|
||||
/// Parcels whose building was evicted because it no longer fits.
|
||||
pub evicted_buildings: Vec<ParcelId>,
|
||||
}
|
||||
|
||||
/// Apply `edit` to `graph` and update `parcels` to match the new
|
||||
/// geometry.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`ParcelError::UnknownEntity`] if the edit references an
|
||||
/// id that is no longer present, or [`ParcelError::Resubdivide`] if
|
||||
/// re-subdivision of an affected block fails.
|
||||
pub fn apply_road_edit(
|
||||
parcels: &mut ParcelSet,
|
||||
graph: &mut RoadGraph,
|
||||
edit: RoadEdit,
|
||||
params: &SubdivisionParams,
|
||||
) -> Result<EditOutcome, ParcelError> {
|
||||
params.validate()?;
|
||||
let graph_before = graph.clone();
|
||||
apply_topology_mutation(graph, edit)?;
|
||||
graph.rebuild_topology()?;
|
||||
let mut outcome = EditOutcome::default();
|
||||
match edit {
|
||||
RoadEdit::MoveNode { node, .. } => {
|
||||
move_node_path(parcels, &graph_before, graph, node, params, &mut outcome)?;
|
||||
}
|
||||
RoadEdit::DeleteSegment { road } => {
|
||||
delete_segment_path(parcels, road, graph, params, &mut outcome)?;
|
||||
}
|
||||
RoadEdit::SplitSegment { .. } | RoadEdit::InsertSegment { .. } => {
|
||||
// Split/Insert preservation is milestone-0.3 work — fall
|
||||
// back to a regenerate of every affected face.
|
||||
let affected = roads_affected_by_old_id(&graph_before, edit);
|
||||
regenerate_path(parcels, graph, params, &affected, &mut outcome)?;
|
||||
}
|
||||
}
|
||||
Ok(outcome)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Move-node preserve path
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
fn move_node_path(
|
||||
parcels: &mut ParcelSet,
|
||||
graph_before: &RoadGraph,
|
||||
graph_after: &RoadGraph,
|
||||
node: NodeId,
|
||||
params: &SubdivisionParams,
|
||||
outcome: &mut EditOutcome,
|
||||
) -> Result<(), ParcelError> {
|
||||
// Collect roads incident to the moved node (those still in the
|
||||
// graph after the edit).
|
||||
let incident_roads: Vec<RoadId> = graph_after
|
||||
.road_endpoints()
|
||||
.filter_map(|(rid, a, b)| {
|
||||
if a == node || b == node {
|
||||
Some(rid)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// For each incident road, walk every parcel on it and try to
|
||||
// deform.
|
||||
let mut to_regenerate: BTreeSet<FaceId> = BTreeSet::new();
|
||||
for rid in &incident_roads {
|
||||
let parcel_ids: Vec<ParcelId> = parcels.parcels_on_road(*rid).collect::<Vec<_>>();
|
||||
for pid in parcel_ids {
|
||||
let result = match parcels.parcels.get_mut(pid) {
|
||||
Some(parcel) => {
|
||||
deform_parcel_after_road_move(parcel, *rid, graph_before, graph_after, params)
|
||||
}
|
||||
None => continue,
|
||||
};
|
||||
match result {
|
||||
DeformResult::Deformed { evicted_building } => {
|
||||
outcome.deformed.push(pid);
|
||||
if evicted_building {
|
||||
outcome.evicted_buildings.push(pid);
|
||||
}
|
||||
}
|
||||
DeformResult::Condemned => {
|
||||
let block = parcels.parcels.get(pid).map(|p| p.block);
|
||||
drop_parcel(parcels, pid);
|
||||
outcome.condemned.push(pid);
|
||||
if let Some(face) = block {
|
||||
to_regenerate.insert(face);
|
||||
}
|
||||
}
|
||||
DeformResult::Regenerate => {
|
||||
if let Some(p) = parcels.parcels.get(pid) {
|
||||
to_regenerate.insert(p.block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regenerate the blocks where any parcel asked for it.
|
||||
if !to_regenerate.is_empty() {
|
||||
// Collect all parcels in those blocks; mark them as
|
||||
// regenerated and drop them, then re-subdivide.
|
||||
let block_set = to_regenerate.clone();
|
||||
let pids_in_blocks: Vec<ParcelId> = parcels
|
||||
.parcels
|
||||
.iter()
|
||||
.filter(|(_, p)| block_set.contains(&p.block))
|
||||
.map(|(id, _)| id)
|
||||
.collect();
|
||||
for pid in &pids_in_blocks {
|
||||
outcome.regenerated.push(*pid);
|
||||
}
|
||||
for pid in pids_in_blocks {
|
||||
drop_parcel(parcels, pid);
|
||||
}
|
||||
// Re-subdivide each block.
|
||||
let blocks = crate::network::blocks::extract_blocks(graph_after);
|
||||
for (block_idx, block) in blocks.iter().enumerate() {
|
||||
if !to_regenerate.contains(&block.face_id()) {
|
||||
continue;
|
||||
}
|
||||
let new_parcels = subdivide_block(graph_after, block, params, block_idx)?;
|
||||
for parcel in new_parcels {
|
||||
let pid = parcels.insert(parcel);
|
||||
outcome.created.push(pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum DeformResult {
|
||||
Deformed { evicted_building: bool },
|
||||
Condemned,
|
||||
Regenerate,
|
||||
}
|
||||
|
||||
/// Attempt to deform `parcel` after the road geometry changed.
|
||||
/// Re-projects the frontage edge endpoints onto the new road
|
||||
/// segment; side and back vertices stay fixed (D13).
|
||||
fn deform_parcel_after_road_move(
|
||||
parcel: &mut Parcel,
|
||||
road: RoadId,
|
||||
graph_before: &RoadGraph,
|
||||
graph_after: &RoadGraph,
|
||||
params: &SubdivisionParams,
|
||||
) -> DeformResult {
|
||||
let Some((a, b)) = graph_after.road_nodes(road) else {
|
||||
return DeformResult::Condemned;
|
||||
};
|
||||
let (Some(pa_before), Some(pb_before), Some(pa_after), Some(pb_after)) = (
|
||||
graph_before.node_position(a),
|
||||
graph_before.node_position(b),
|
||||
graph_after.node_position(a),
|
||||
graph_after.node_position(b),
|
||||
) else {
|
||||
return DeformResult::Condemned;
|
||||
};
|
||||
let road_vec_before = pb_before - pa_before;
|
||||
let len_sq_before = road_vec_before.length_squared();
|
||||
if len_sq_before < EPS_GEOM * EPS_GEOM {
|
||||
return DeformResult::Regenerate;
|
||||
}
|
||||
let road_vec_after = pb_after - pa_after;
|
||||
|
||||
let n = parcel.polygon.len();
|
||||
let fi = parcel.frontage_edge_index;
|
||||
let mut new_verts: Vec<DVec2> = parcel.polygon.vertices().to_vec();
|
||||
let p_a = new_verts[fi];
|
||||
let p_b = new_verts[(fi + 1) % n];
|
||||
let t_a = (p_a - pa_before).dot(road_vec_before) / len_sq_before;
|
||||
let t_b = (p_b - pa_before).dot(road_vec_before) / len_sq_before;
|
||||
new_verts[fi] = pa_after + road_vec_after * t_a;
|
||||
new_verts[(fi + 1) % n] = pa_after + road_vec_after * t_b;
|
||||
|
||||
// Side rotation check before constructing the polygon (so we can
|
||||
// bail to Regenerate cheaply).
|
||||
let prev_idx = (fi + n - 1) % n;
|
||||
let next_idx = (fi + 2) % n;
|
||||
let old_side_in =
|
||||
(parcel.polygon.vertices()[fi] - parcel.polygon.vertices()[prev_idx]).normalize_or_zero();
|
||||
let new_side_in = (new_verts[fi] - new_verts[prev_idx]).normalize_or_zero();
|
||||
let old_side_out = (parcel.polygon.vertices()[next_idx]
|
||||
- parcel.polygon.vertices()[(fi + 1) % n])
|
||||
.normalize_or_zero();
|
||||
let new_side_out = (new_verts[next_idx] - new_verts[(fi + 1) % n]).normalize_or_zero();
|
||||
let rot_in = old_side_in.dot(new_side_in).clamp(-1.0, 1.0).acos();
|
||||
let rot_out = old_side_out.dot(new_side_out).clamp(-1.0, 1.0).acos();
|
||||
if rot_in > params.max_side_rotation || rot_out > params.max_side_rotation {
|
||||
return DeformResult::Regenerate;
|
||||
}
|
||||
|
||||
let Ok(new_poly) = Polygon::new(new_verts) else {
|
||||
return DeformResult::Regenerate;
|
||||
};
|
||||
|
||||
if new_poly.area() < params.min_area {
|
||||
return DeformResult::Condemned;
|
||||
}
|
||||
let v = new_poly.vertices();
|
||||
// Find the new frontage edge index — Polygon::new may have
|
||||
// reordered vertices if it had to flip orientation. We locate the
|
||||
// edge whose midpoint lies on the new road segment.
|
||||
let new_fi = match find_frontage_index(&new_poly, pa_after, pb_after) {
|
||||
Some(idx) => idx,
|
||||
None => return DeformResult::Regenerate,
|
||||
};
|
||||
let new_frontage = (v[(new_fi + 1) % v.len()] - v[new_fi]).length();
|
||||
if new_frontage < params.min_frontage {
|
||||
return DeformResult::Condemned;
|
||||
}
|
||||
|
||||
// Commit.
|
||||
parcel.polygon = new_poly;
|
||||
parcel.frontage_edge_index = new_fi;
|
||||
|
||||
// BuildingFitCheck eviction.
|
||||
let mut evicted = false;
|
||||
if parcel.building.is_some() {
|
||||
let fits = parcel.building.as_ref().is_some_and(|b| b.fits_in(parcel));
|
||||
if !fits {
|
||||
parcel.building = None;
|
||||
evicted = true;
|
||||
}
|
||||
}
|
||||
DeformResult::Deformed {
|
||||
evicted_building: evicted,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_frontage_index(polygon: &Polygon, road_a: DVec2, road_b: DVec2) -> Option<usize> {
|
||||
let road_dir = (road_b - road_a).normalize_or_zero();
|
||||
if road_dir.length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let road_normal = DVec2::new(-road_dir.y, road_dir.x);
|
||||
let v = polygon.vertices();
|
||||
let n = v.len();
|
||||
let tol = 100.0 * EPS_GEOM;
|
||||
let mut best: Option<(usize, f64)> = None;
|
||||
for i in 0..n {
|
||||
let p = v[i];
|
||||
let q = v[(i + 1) % n];
|
||||
let dp = (p - road_a).dot(road_normal).abs();
|
||||
let dq = (q - road_a).dot(road_normal).abs();
|
||||
if dp < tol && dq < tol {
|
||||
let edge_dir = (q - p).normalize_or_zero();
|
||||
if edge_dir.dot(road_dir).abs() > 0.5 {
|
||||
let len = (q - p).length();
|
||||
if best.is_none_or(|(_, blen)| len > blen) {
|
||||
best = Some((i, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
best.map(|(i, _)| i)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Delete-segment path: condemn + regenerate-block
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
fn delete_segment_path(
|
||||
parcels: &mut ParcelSet,
|
||||
road: RoadId,
|
||||
graph_after: &RoadGraph,
|
||||
params: &SubdivisionParams,
|
||||
outcome: &mut EditOutcome,
|
||||
) -> Result<(), ParcelError> {
|
||||
// Collect parcels with frontage on the deleted road; condemn
|
||||
// them. The block topology likely changed; regenerate every
|
||||
// block touched by any condemned parcel.
|
||||
let pids: Vec<ParcelId> = parcels.parcels_on_road(road).collect::<Vec<_>>();
|
||||
let mut affected_blocks: BTreeSet<FaceId> = BTreeSet::new();
|
||||
for pid in pids {
|
||||
if let Some(p) = parcels.parcels.get(pid) {
|
||||
affected_blocks.insert(p.block);
|
||||
}
|
||||
outcome.condemned.push(pid);
|
||||
drop_parcel(parcels, pid);
|
||||
}
|
||||
// Regenerate.
|
||||
let blocks = crate::network::blocks::extract_blocks(graph_after);
|
||||
for (block_idx, block) in blocks.iter().enumerate() {
|
||||
// After deletion, the face IDs may be different — regenerate
|
||||
// anything that was previously affected. The simplest
|
||||
// correct rule: regenerate any face that currently has no
|
||||
// parcels.
|
||||
let face = block.face_id();
|
||||
if parcels.by_block.get(&face).is_some_and(|v| !v.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
let new_parcels = subdivide_block(graph_after, block, params, block_idx)?;
|
||||
for parcel in new_parcels {
|
||||
let pid = parcels.insert(parcel);
|
||||
outcome.created.push(pid);
|
||||
}
|
||||
let _ = affected_blocks;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Regenerate-only fallback (Split, Insert)
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
fn regenerate_path(
|
||||
parcels: &mut ParcelSet,
|
||||
graph_after: &RoadGraph,
|
||||
params: &SubdivisionParams,
|
||||
affected_roads: &[RoadId],
|
||||
outcome: &mut EditOutcome,
|
||||
) -> Result<(), ParcelError> {
|
||||
let mut to_drop: Vec<ParcelId> = Vec::new();
|
||||
for rid in affected_roads {
|
||||
if let Some(ids) = parcels.by_road.get(rid) {
|
||||
to_drop.extend(ids.iter().copied());
|
||||
}
|
||||
}
|
||||
to_drop.sort();
|
||||
to_drop.dedup();
|
||||
for pid in &to_drop {
|
||||
outcome.condemned.push(*pid);
|
||||
}
|
||||
for pid in to_drop {
|
||||
drop_parcel(parcels, pid);
|
||||
}
|
||||
let blocks = crate::network::blocks::extract_blocks(graph_after);
|
||||
for (block_idx, block) in blocks.iter().enumerate() {
|
||||
let face = block.face_id();
|
||||
if parcels.by_block.get(&face).is_some_and(|v| !v.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
let new_parcels = subdivide_block(graph_after, block, params, block_idx)?;
|
||||
for parcel in new_parcels {
|
||||
let pid = parcels.insert(parcel);
|
||||
outcome.created.push(pid);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn roads_affected_by_old_id(graph: &RoadGraph, edit: RoadEdit) -> Vec<RoadId> {
|
||||
let mut roads = Vec::new();
|
||||
match edit {
|
||||
RoadEdit::MoveNode { node, .. } => {
|
||||
for (rid, a, b) in graph.road_endpoints() {
|
||||
if a == node || b == node {
|
||||
roads.push(rid);
|
||||
}
|
||||
}
|
||||
}
|
||||
RoadEdit::SplitSegment { road, .. } | RoadEdit::DeleteSegment { road } => {
|
||||
roads.push(road);
|
||||
}
|
||||
RoadEdit::InsertSegment { from, to } => {
|
||||
for (rid, a, b) in graph.road_endpoints() {
|
||||
if a == from || b == from || a == to || b == to {
|
||||
roads.push(rid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
roads
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Mutation helpers + parcel-set bookkeeping
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
fn apply_topology_mutation(graph: &mut RoadGraph, edit: RoadEdit) -> Result<(), ParcelError> {
|
||||
match edit {
|
||||
RoadEdit::MoveNode { node, to } => {
|
||||
let n = graph
|
||||
.nodes
|
||||
.get_mut(node)
|
||||
.ok_or(ParcelError::UnknownEntity)?;
|
||||
n.pos = to;
|
||||
graph.topology_valid = false;
|
||||
Ok(())
|
||||
}
|
||||
RoadEdit::DeleteSegment { road } => {
|
||||
graph.roads.remove(road).ok_or(ParcelError::UnknownEntity)?;
|
||||
graph.topology_valid = false;
|
||||
Ok(())
|
||||
}
|
||||
RoadEdit::SplitSegment { road, at } => {
|
||||
let (a, b) = graph.road_nodes(road).ok_or(ParcelError::UnknownEntity)?;
|
||||
graph.roads.remove(road);
|
||||
let m = graph.add_node(at);
|
||||
graph
|
||||
.add_road(a, m)
|
||||
.map_err(|_| ParcelError::InconsistentEdit("split a->m".into()))?;
|
||||
graph
|
||||
.add_road(m, b)
|
||||
.map_err(|_| ParcelError::InconsistentEdit("split m->b".into()))?;
|
||||
graph.topology_valid = false;
|
||||
Ok(())
|
||||
}
|
||||
RoadEdit::InsertSegment { from, to } => {
|
||||
graph
|
||||
.add_road(from, to)
|
||||
.map_err(|_| ParcelError::InconsistentEdit("insert".into()))?;
|
||||
graph.topology_valid = false;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_parcel(parcels: &mut ParcelSet, pid: ParcelId) {
|
||||
if let Some(p) = parcels.parcels.remove(pid) {
|
||||
if let Some(v) = parcels.by_block.get_mut(&p.block) {
|
||||
v.retain(|&x| x != pid);
|
||||
}
|
||||
if let Some(v) = parcels.by_road.get_mut(&p.frontage_road) {
|
||||
v.retain(|&x| x != pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn _unused_face_id() -> FaceId {
|
||||
FaceId::null()
|
||||
}
|
||||
213
road_parceling/src/parcel/mod.rs
Normal file
@ -0,0 +1,213 @@
|
||||
//! Parcel data model and subdivision/edit entry points (spec §3, §4).
|
||||
//!
|
||||
//! A [`Parcel`] is a simple polygon with exactly one frontage edge
|
||||
//! coincident with a road segment (invariant **I2**). Parcels are
|
||||
//! grouped by their containing block (face), and the whole crate's
|
||||
//! public output is a [`ParcelSet`].
|
||||
//!
|
||||
//! Subdivision and edit operations are exposed via the free
|
||||
//! functions [`subdivide_all`] and [`apply_road_edit`].
|
||||
|
||||
pub mod classify;
|
||||
pub mod deform;
|
||||
pub mod regularize;
|
||||
pub mod subdivide;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
use glam::DVec2;
|
||||
use slotmap::{new_key_type, SlotMap};
|
||||
|
||||
use crate::geometry::Polygon;
|
||||
use crate::network::graph::FaceId;
|
||||
use crate::network::RoadId;
|
||||
|
||||
pub use deform::{apply_road_edit, EditOutcome, RoadEdit};
|
||||
pub use subdivide::{subdivide_all, subdivide_all_with_stats, SubdivisionStats};
|
||||
|
||||
new_key_type! {
|
||||
/// Stable identifier for a [`Parcel`].
|
||||
pub struct ParcelId;
|
||||
}
|
||||
|
||||
/// Kind of a parcel boundary edge (spec §3.2).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum EdgeKind {
|
||||
/// Edge lies coincident with a road segment.
|
||||
Frontage,
|
||||
/// Edge is adjacent to the frontage edge in the parcel ring.
|
||||
Side,
|
||||
/// All other edges.
|
||||
Back,
|
||||
}
|
||||
|
||||
/// Trait that downstream code implements for buildings to participate
|
||||
/// in deform-time fit checks (spec §4.6).
|
||||
pub trait BuildingFitCheck: 'static {
|
||||
/// True iff the building still fits inside `parcel`.
|
||||
fn fits_in(&self, parcel: &Parcel) -> bool;
|
||||
}
|
||||
|
||||
/// Owning wrapper around a `BuildingFitCheck`. Stored on parcels via
|
||||
/// `Option<BuildingHandle>`.
|
||||
///
|
||||
/// Note: the spec describes `BuildingHandle` as "opaque". This crate
|
||||
/// implements it as a heap-allocated trait object so that the
|
||||
/// deformation pipeline can call `fits_in` without taking a callback
|
||||
/// from the user. Recorded as revision §11 (R1).
|
||||
pub struct BuildingHandle {
|
||||
inner: Box<dyn BuildingFitCheck>,
|
||||
}
|
||||
|
||||
impl BuildingHandle {
|
||||
/// Wrap a building implementation.
|
||||
#[must_use]
|
||||
pub fn new<B: BuildingFitCheck>(b: B) -> Self {
|
||||
Self { inner: Box::new(b) }
|
||||
}
|
||||
|
||||
/// Forward to the inner [`BuildingFitCheck::fits_in`].
|
||||
#[must_use]
|
||||
pub fn fits_in(&self, parcel: &Parcel) -> bool {
|
||||
self.inner.fits_in(parcel)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BuildingHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BuildingHandle").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
/// A single parcel.
|
||||
#[derive(Debug)]
|
||||
pub struct Parcel {
|
||||
pub(crate) polygon: Polygon,
|
||||
pub(crate) edge_kinds: Vec<EdgeKind>,
|
||||
pub(crate) frontage_road: RoadId,
|
||||
pub(crate) frontage_edge_index: usize,
|
||||
pub(crate) block: FaceId,
|
||||
pub(crate) building: Option<BuildingHandle>,
|
||||
}
|
||||
|
||||
impl Parcel {
|
||||
/// Vertex ring of the parcel polygon (CCW, not closed).
|
||||
#[must_use]
|
||||
pub fn vertices(&self) -> &[DVec2] {
|
||||
self.polygon.vertices()
|
||||
}
|
||||
|
||||
/// Polygon view.
|
||||
#[must_use]
|
||||
pub fn polygon(&self) -> &Polygon {
|
||||
&self.polygon
|
||||
}
|
||||
|
||||
/// Edge classification, parallel to `vertices()`.
|
||||
#[must_use]
|
||||
pub fn edge_kinds(&self) -> &[EdgeKind] {
|
||||
&self.edge_kinds
|
||||
}
|
||||
|
||||
/// The single road this parcel faces (invariant **I2**).
|
||||
#[must_use]
|
||||
pub fn frontage_road(&self) -> RoadId {
|
||||
self.frontage_road
|
||||
}
|
||||
|
||||
/// Endpoints of the frontage edge.
|
||||
#[must_use]
|
||||
pub fn frontage_edge(&self) -> (DVec2, DVec2) {
|
||||
let v = self.polygon.vertices();
|
||||
let i = self.frontage_edge_index;
|
||||
(v[i], v[(i + 1) % v.len()])
|
||||
}
|
||||
|
||||
/// Frontage length, meters.
|
||||
#[must_use]
|
||||
pub fn frontage_length(&self) -> f64 {
|
||||
let (a, b) = self.frontage_edge();
|
||||
(b - a).length()
|
||||
}
|
||||
|
||||
/// Parcel area, m².
|
||||
#[must_use]
|
||||
pub fn area(&self) -> f64 {
|
||||
self.polygon.area()
|
||||
}
|
||||
|
||||
/// Attach a building. Returns the previously-attached building, if
|
||||
/// any.
|
||||
pub fn attach_building(&mut self, b: BuildingHandle) -> Option<BuildingHandle> {
|
||||
self.building.replace(b)
|
||||
}
|
||||
|
||||
/// Detach (and return) the currently attached building, if any.
|
||||
pub fn detach_building(&mut self) -> Option<BuildingHandle> {
|
||||
self.building.take()
|
||||
}
|
||||
|
||||
/// Whether a building is currently attached.
|
||||
#[must_use]
|
||||
pub fn has_building(&self) -> bool {
|
||||
self.building.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
/// The output of `subdivide_all`: a stable-ID indexed collection of
|
||||
/// parcels, organized by their containing block.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ParcelSet {
|
||||
pub(crate) parcels: SlotMap<ParcelId, Parcel>,
|
||||
pub(crate) by_block: HashMap<FaceId, Vec<ParcelId>>,
|
||||
pub(crate) by_road: HashMap<RoadId, Vec<ParcelId>>,
|
||||
}
|
||||
|
||||
impl ParcelSet {
|
||||
/// Number of parcels.
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.parcels.len()
|
||||
}
|
||||
|
||||
/// True if there are no parcels.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.parcels.is_empty()
|
||||
}
|
||||
|
||||
/// Iterate over `(ParcelId, &Parcel)` pairs.
|
||||
pub fn iter(&self) -> impl Iterator<Item = (ParcelId, &Parcel)> {
|
||||
self.parcels.iter()
|
||||
}
|
||||
|
||||
/// Look up a parcel by id.
|
||||
#[must_use]
|
||||
pub fn get(&self, id: ParcelId) -> Option<&Parcel> {
|
||||
self.parcels.get(id)
|
||||
}
|
||||
|
||||
/// Look up a parcel mutably by id.
|
||||
pub fn get_mut(&mut self, id: ParcelId) -> Option<&mut Parcel> {
|
||||
self.parcels.get_mut(id)
|
||||
}
|
||||
|
||||
/// Iterate over the parcel ids within a single road's frontage.
|
||||
pub fn parcels_on_road(&self, road: RoadId) -> impl Iterator<Item = ParcelId> + '_ {
|
||||
self.by_road
|
||||
.get(&road)
|
||||
.into_iter()
|
||||
.flat_map(|v| v.iter().copied())
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, parcel: Parcel) -> ParcelId {
|
||||
let block = parcel.block;
|
||||
let road = parcel.frontage_road;
|
||||
let id = self.parcels.insert(parcel);
|
||||
self.by_block.entry(block).or_default().push(id);
|
||||
self.by_road.entry(road).or_default().push(id);
|
||||
id
|
||||
}
|
||||
}
|
||||
20
road_parceling/src/parcel/regularize.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! OBB-snapping regularization pass (spec §3.3).
|
||||
//!
|
||||
//! When `params.regularity > 0`, parcel side-edge vertices are
|
||||
//! linearly interpolated toward their oriented-bounding-box-snapped
|
||||
//! positions with weight `ρ`. At ρ=1 parcels become perfect
|
||||
//! road-aligned rectangles; at ρ=0 the raw subdivision is preserved.
|
||||
//!
|
||||
//! Status: **stub** for milestone 0.1. The default
|
||||
//! `SubdivisionParams::regularity = 0.0` makes this a no-op for now.
|
||||
//! Recorded as revision §11 (R3).
|
||||
|
||||
use crate::config::SubdivisionParams;
|
||||
use crate::parcel::Parcel;
|
||||
|
||||
/// Run the regularization pass over a single parcel in place. No-op
|
||||
/// while `params.regularity == 0.0` (the default).
|
||||
pub(crate) fn regularize_parcel(_parcel: &mut Parcel, _params: &SubdivisionParams) {
|
||||
// TODO(milestone-0.2): OBB-snap side vertices with weight ρ;
|
||||
// validate and revert on failure.
|
||||
}
|
||||
744
road_parceling/src/parcel/subdivide.rs
Normal file
@ -0,0 +1,744 @@
|
||||
//! Frontage-first block subdivision (spec §3.1, milestone 0.2).
|
||||
//!
|
||||
//! For each block face we:
|
||||
//!
|
||||
//! 1. Identify "real" corners — block-boundary vertices whose
|
||||
//! underlying graph node has degree ≥3, or degree 2 with a bend
|
||||
//! angle below 150°. Smooth continuations (collinear-roads case)
|
||||
//! are not real corners.
|
||||
//! 2. At each real corner, build a corner parcel: a parallelogram
|
||||
//! extending `frontage_width` along each adjacent block edge and
|
||||
//! closing diagonally inward. The longer adjacent edge becomes the
|
||||
//! parcel's frontage; the other road-adjacent edge is reclassified
|
||||
//! as `Side`. (See §11 D9–D11.)
|
||||
//! 3. For each block boundary edge, walk the *remaining* frontage
|
||||
//! (between the corner footprints, if any) at arc-length intervals
|
||||
//! of approximately `params.frontage_width`, extruding perpendicular
|
||||
//! to the block interior. No more bisector clipping — the corners
|
||||
//! take care of corner geometry up front.
|
||||
//!
|
||||
//! Determinism (invariant **I6**) is preserved: random jitter is
|
||||
//! drawn from a `ChaCha8Rng` whose seed is mixed from `params.seed`
|
||||
//! and the road-segment id; corner parcels are pure functions of
|
||||
//! geometry.
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use glam::DVec2;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
use slotmap::Key;
|
||||
|
||||
use crate::config::SubdivisionParams;
|
||||
use crate::error::SubdivisionError;
|
||||
use crate::geometry::{Polygon, EPS_GEOM};
|
||||
use crate::network::blocks::{extract_blocks, Block};
|
||||
use crate::network::graph::FaceId;
|
||||
use crate::network::{NodeId, RoadGraph, RoadId};
|
||||
|
||||
use super::classify::classify_edges;
|
||||
use super::regularize::regularize_parcel;
|
||||
use super::{Parcel, ParcelSet};
|
||||
|
||||
/// Per-phase timing collected by [`subdivide_all_with_stats`].
|
||||
///
|
||||
/// Phases are non-overlapping wall-clock spans. `total` is measured
|
||||
/// independently and may be slightly larger than the sum of the
|
||||
/// phases due to overhead between phases.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct SubdivisionStats {
|
||||
/// Number of bounded faces (blocks) extracted from the graph.
|
||||
pub block_count: usize,
|
||||
/// Total parcels produced across all blocks.
|
||||
pub parcel_count: usize,
|
||||
/// Time to (re)build the half-edge / DCEL topology if needed.
|
||||
pub topology_rebuild: Duration,
|
||||
/// Time to extract bounded faces into [`Block`] objects.
|
||||
pub block_extraction: Duration,
|
||||
/// Cumulative time spent in [`subdivide_block`] across all blocks.
|
||||
pub block_subdivide_total: Duration,
|
||||
/// Wall-clock total of [`subdivide_all_with_stats`].
|
||||
pub total: Duration,
|
||||
}
|
||||
|
||||
impl SubdivisionStats {
|
||||
/// Average parcels generated per second over the whole call.
|
||||
#[must_use]
|
||||
pub fn parcels_per_second(&self) -> f64 {
|
||||
let secs = self.total.as_secs_f64();
|
||||
if secs > 0.0 {
|
||||
self.parcel_count as f64 / secs
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Average wall-clock time per parcel, in microseconds.
|
||||
#[must_use]
|
||||
pub fn time_per_parcel_us(&self) -> f64 {
|
||||
if self.parcel_count > 0 {
|
||||
(self.total.as_nanos() as f64 / self.parcel_count as f64) / 1_000.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Subdivide every bounded face of `graph` into parcels.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a [`SubdivisionError`] if `params` is invalid, the graph
|
||||
/// is non-planar, or an internal geometric failure occurs.
|
||||
pub fn subdivide_all(
|
||||
graph: &RoadGraph,
|
||||
params: &SubdivisionParams,
|
||||
) -> Result<ParcelSet, SubdivisionError> {
|
||||
subdivide_all_with_stats(graph, params).map(|(p, _)| p)
|
||||
}
|
||||
|
||||
/// Subdivide every bounded face and return per-phase performance
|
||||
/// statistics alongside the parcel set.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Same as [`subdivide_all`].
|
||||
pub fn subdivide_all_with_stats(
|
||||
graph: &RoadGraph,
|
||||
params: &SubdivisionParams,
|
||||
) -> Result<(ParcelSet, SubdivisionStats), SubdivisionError> {
|
||||
params.validate()?;
|
||||
let mut stats = SubdivisionStats::default();
|
||||
let total_start = Instant::now();
|
||||
|
||||
let topo_start = Instant::now();
|
||||
let mut working: RoadGraph;
|
||||
let g_ref = if graph.topology_valid {
|
||||
graph
|
||||
} else {
|
||||
working = graph.clone();
|
||||
working.rebuild_topology()?;
|
||||
&working
|
||||
};
|
||||
stats.topology_rebuild = topo_start.elapsed();
|
||||
|
||||
let blocks_start = Instant::now();
|
||||
let blocks = extract_blocks(g_ref);
|
||||
stats.block_extraction = blocks_start.elapsed();
|
||||
stats.block_count = blocks.len();
|
||||
|
||||
let mut parcels = ParcelSet::default();
|
||||
for (block_idx, block) in blocks.iter().enumerate() {
|
||||
let block_start = Instant::now();
|
||||
let new = subdivide_block(g_ref, block, params, block_idx)?;
|
||||
stats.block_subdivide_total += block_start.elapsed();
|
||||
for parcel in new {
|
||||
parcels.insert(parcel);
|
||||
}
|
||||
}
|
||||
stats.parcel_count = parcels.len();
|
||||
stats.total = total_start.elapsed();
|
||||
Ok((parcels, stats))
|
||||
}
|
||||
|
||||
/// Subdivide a single block. Internal entry used both by
|
||||
/// `subdivide_all` and by `apply_road_edit`'s regenerate path.
|
||||
pub(crate) fn subdivide_block(
|
||||
graph: &RoadGraph,
|
||||
block: &Block,
|
||||
params: &SubdivisionParams,
|
||||
_block_idx: usize,
|
||||
) -> Result<Vec<Parcel>, SubdivisionError> {
|
||||
let n = block.polygon.len();
|
||||
if n < 3 {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let verts: Vec<DVec2> = block.polygon.vertices().to_vec();
|
||||
let face = block.face_id();
|
||||
|
||||
// Edge lengths (parallel to verts).
|
||||
let edge_lens: Vec<f64> = (0..n)
|
||||
.map(|i| (verts[(i + 1) % n] - verts[i]).length())
|
||||
.collect();
|
||||
|
||||
// Real-corner classification per vertex (D11). Acute corners
|
||||
// (interior angle < 60°) are skipped here — sliver-merge is
|
||||
// milestone 0.3 — so parcels there fall back to whatever the
|
||||
// regular walk produces (usually a malformed shape that triggers
|
||||
// I1 rejection during validation, but never a panic).
|
||||
let real_corner: Vec<bool> = (0..n)
|
||||
.map(|i| {
|
||||
if !is_real_corner(graph, block, i, params) {
|
||||
return false;
|
||||
}
|
||||
let v_prev = block.polygon.vertices()[(i + n - 1) % n];
|
||||
let v_curr = block.polygon.vertices()[i];
|
||||
let v_next = block.polygon.vertices()[(i + 1) % n];
|
||||
let t_in = (v_prev - v_curr).normalize_or_zero();
|
||||
let t_out = (v_next - v_curr).normalize_or_zero();
|
||||
let t_arrive = -t_in;
|
||||
let cross = t_arrive.x * t_out.y - t_arrive.y * t_out.x;
|
||||
let dot = t_arrive.dot(t_out);
|
||||
let turn = cross.atan2(dot);
|
||||
let interior = std::f64::consts::PI - turn;
|
||||
interior > 60.0_f64.to_radians()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Per-edge depth cap (block half-depth bound).
|
||||
let depth_caps = edge_depth_caps(&block.polygon);
|
||||
|
||||
let r_target = params.frontage_width;
|
||||
|
||||
// First pass: decide which adjacent road wins frontage at each
|
||||
// real corner. This drives both the corner geometry below and the
|
||||
// per-edge walk bounds.
|
||||
let mut frontage_on_next: Vec<bool> = vec![false; n];
|
||||
for i in 0..n {
|
||||
if !real_corner[i] {
|
||||
continue;
|
||||
}
|
||||
let prev_len = edge_lens[(i + n - 1) % n];
|
||||
let next_len = edge_lens[i];
|
||||
let prev_road = block.roads[(i + n - 1) % n];
|
||||
let next_road = block.roads[i];
|
||||
frontage_on_next[i] = if (next_len - prev_len).abs() < EPS_GEOM {
|
||||
// tie → deterministic by RoadId
|
||||
next_road.data().as_ffi() <= prev_road.data().as_ffi()
|
||||
} else {
|
||||
next_len > prev_len
|
||||
};
|
||||
}
|
||||
|
||||
let mut out: Vec<Parcel> = Vec::new();
|
||||
|
||||
// Build corner parcels.
|
||||
for i in 0..n {
|
||||
if !real_corner[i] {
|
||||
continue;
|
||||
}
|
||||
let v_curr = verts[i];
|
||||
let v_prev = verts[(i + n - 1) % n];
|
||||
let v_next = verts[(i + 1) % n];
|
||||
|
||||
let prev_road = block.roads[(i + n - 1) % n];
|
||||
let next_road = block.roads[i];
|
||||
|
||||
let t_in = (v_prev - v_curr).normalize_or_zero();
|
||||
let t_out = (v_next - v_curr).normalize_or_zero();
|
||||
if t_in.length_squared() < EPS_GEOM * EPS_GEOM
|
||||
|| t_out.length_squared() < EPS_GEOM * EPS_GEOM
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let prev_len = edge_lens[(i + n - 1) % n];
|
||||
let next_len = edge_lens[i];
|
||||
let r = r_target
|
||||
.min(prev_len * 0.5)
|
||||
.min(next_len * 0.5)
|
||||
.max(params.min_frontage * 0.5);
|
||||
if r < params.min_frontage * 0.5 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Inward normals.
|
||||
let n_out = DVec2::new(-t_out.y, t_out.x);
|
||||
let n_in = DVec2::new(t_in.y, -t_in.x);
|
||||
|
||||
// Two flavors of corner parcel, both with frontage = R on the
|
||||
// *winning* road and side2 = depth along the other:
|
||||
//
|
||||
// A. frontage on NEXT road: v0 → v0+t_out·R is frontage,
|
||||
// v0+t_in·depth → v0 is the side along the prev road.
|
||||
// B. frontage on PREV road: v0+t_in·R → v0 is frontage,
|
||||
// v0 → v0+t_out·depth is the side along the next road.
|
||||
let (frontage_road, polygon, frontage_idx, consume_next, consume_prev) =
|
||||
if frontage_on_next[i] {
|
||||
let perp_depth = params.depth.min(prev_len * 0.5);
|
||||
let v0 = v_curr;
|
||||
let v1 = v_curr + t_out * r;
|
||||
let v2 = v_curr + t_out * r + n_out * perp_depth;
|
||||
let v3 = v_curr + t_in * perp_depth;
|
||||
let Ok(p) = Polygon::new(vec![v0, v1, v2, v3]) else {
|
||||
continue;
|
||||
};
|
||||
(next_road, p, 0_usize, r, perp_depth)
|
||||
} else {
|
||||
let perp_depth = params.depth.min(next_len * 0.5);
|
||||
let v0 = v_curr;
|
||||
let v1 = v_curr + t_out * perp_depth;
|
||||
let v2 = v_curr + t_out * perp_depth + n_out * r;
|
||||
let v3 = v_curr + t_in * r;
|
||||
let Ok(p) = Polygon::new(vec![v0, v1, v2, v3]) else {
|
||||
continue;
|
||||
};
|
||||
// Frontage edge in CCW order is v3 → v0, i.e. edge 3.
|
||||
(prev_road, p, 3_usize, perp_depth, r)
|
||||
};
|
||||
// The variables `consume_next` and `consume_prev` propagate
|
||||
// out via the per-vertex helpers below.
|
||||
let _ = (consume_next, consume_prev, n_in);
|
||||
|
||||
// Clip to the block boundary so the parcel can never extend
|
||||
// past it. Required for non-rectangular blocks where the
|
||||
// R×depth rectangle would otherwise cross another block edge.
|
||||
let Some(polygon) = clip_polygon_to_block(&polygon, &block.polygon) else {
|
||||
continue;
|
||||
};
|
||||
if polygon.area() < params.min_area {
|
||||
continue;
|
||||
}
|
||||
let edge_kinds = classify_edges(polygon.len(), frontage_idx);
|
||||
|
||||
let mut parcel = Parcel {
|
||||
polygon,
|
||||
edge_kinds,
|
||||
frontage_road,
|
||||
frontage_edge_index: frontage_idx,
|
||||
block: face,
|
||||
building: None,
|
||||
};
|
||||
regularize_parcel(&mut parcel, params);
|
||||
out.push(parcel);
|
||||
}
|
||||
|
||||
// For each edge, walk between the corner footprints (if any) and
|
||||
// emit regular frontage parcels.
|
||||
for i in 0..n {
|
||||
let p = verts[i];
|
||||
let q = verts[(i + 1) % n];
|
||||
let road = block.roads[i];
|
||||
let edge_vec = q - p;
|
||||
let edge_len = edge_vec.length();
|
||||
if edge_len < params.min_frontage {
|
||||
continue;
|
||||
}
|
||||
let edge_dir = edge_vec / edge_len;
|
||||
let inward = DVec2::new(-edge_dir.y, edge_dir.x);
|
||||
|
||||
// Walk-bounds. The corner at vertex i (start of this edge)
|
||||
// consumes the corner's `r` along this edge (it's the corner's
|
||||
// *next* side). The corner at vertex i+1 (end of this edge)
|
||||
// consumes the corner's `perp_depth` along this edge (it's
|
||||
// *that* corner's *prev* side, i.e., its Side2 runs along
|
||||
// here for a depth-equivalent distance).
|
||||
let consume_at_start = if real_corner[i] {
|
||||
// Edge i is the *next* edge of corner at vertex i.
|
||||
// - frontage_on_next[i] true → consume R (frontage).
|
||||
// - frontage_on_next[i] false → consume depth (side2).
|
||||
if frontage_on_next[i] {
|
||||
corner_consume_short(&edge_lens, i, r_target, params)
|
||||
} else {
|
||||
corner_consume_long(&edge_lens, i, params)
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let next_v = (i + 1) % n;
|
||||
let consume_at_end = if real_corner[next_v] {
|
||||
// Edge i is the *prev* edge of corner at vertex (i+1).
|
||||
// - frontage_on_next[next_v] true → consume depth (side2 along prev).
|
||||
// - frontage_on_next[next_v] false → consume R (frontage on prev).
|
||||
if frontage_on_next[next_v] {
|
||||
corner_consume_long(&edge_lens, next_v, params)
|
||||
} else {
|
||||
corner_consume_short(&edge_lens, next_v, r_target, params)
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let t_start = consume_at_start;
|
||||
let t_end = edge_len - consume_at_end;
|
||||
if t_end - t_start < params.min_frontage {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut rng = rng_for_road(params.seed, road);
|
||||
let max_depth = depth_caps[i].min(params.depth + params.depth_variance.abs() + EPS_GEOM);
|
||||
let setback = params.setback.max(0.0);
|
||||
|
||||
// Place split positions between t_start and t_end.
|
||||
let splits = split_positions_between(t_start, t_end, params, &mut rng);
|
||||
|
||||
for k in 0..splits.len() - 1 {
|
||||
let t_a = splits[k];
|
||||
let t_b = splits[k + 1];
|
||||
if t_b - t_a < params.min_frontage - EPS_GEOM {
|
||||
continue;
|
||||
}
|
||||
let p_a = p + edge_dir * t_a;
|
||||
let p_b = p + edge_dir * t_b;
|
||||
let depth_jitter = params.depth_variance * (rng.gen::<f64>() * 2.0 - 1.0);
|
||||
let raw_depth = (params.depth + depth_jitter).max(params.min_frontage);
|
||||
let total_depth = (setback + raw_depth)
|
||||
.min(max_depth)
|
||||
.max(params.min_frontage * 0.5);
|
||||
if total_depth < params.min_frontage * 0.25 {
|
||||
continue;
|
||||
}
|
||||
let q_b = p_b + inward * total_depth;
|
||||
let q_a = p_a + inward * total_depth;
|
||||
|
||||
let Ok(raw_poly) = Polygon::new(vec![p_a, p_b, q_b, q_a]) else {
|
||||
continue;
|
||||
};
|
||||
// Clip to block boundary so parcels can never escape the
|
||||
// block (matters at acute corners and on non-rectangular
|
||||
// blocks).
|
||||
let Some(polygon) = clip_polygon_to_block(&raw_poly, &block.polygon) else {
|
||||
continue;
|
||||
};
|
||||
if polygon.area() < params.min_area {
|
||||
continue;
|
||||
}
|
||||
// After clipping, find the frontage edge — it's the one
|
||||
// that lies on the road segment within tolerance.
|
||||
let frontage_idx = match find_frontage_edge_after_clip(&polygon, p, q) {
|
||||
Some(idx) => idx,
|
||||
None => continue,
|
||||
};
|
||||
let frontage_len = {
|
||||
let v = polygon.vertices();
|
||||
(v[(frontage_idx + 1) % v.len()] - v[frontage_idx]).length()
|
||||
};
|
||||
if frontage_len < params.min_frontage {
|
||||
continue;
|
||||
}
|
||||
let edge_kinds = classify_edges(polygon.len(), frontage_idx);
|
||||
let mut parcel = Parcel {
|
||||
polygon,
|
||||
edge_kinds,
|
||||
frontage_road: road,
|
||||
frontage_edge_index: frontage_idx,
|
||||
block: face,
|
||||
building: None,
|
||||
};
|
||||
regularize_parcel(&mut parcel, params);
|
||||
out.push(parcel);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// True iff vertex `i` of the block is a "real corner" — graph degree
|
||||
/// ≥3, or degree 2 with a bend sharper than 150°. (D11.)
|
||||
fn is_real_corner(graph: &RoadGraph, block: &Block, i: usize, _params: &SubdivisionParams) -> bool {
|
||||
let n = block.polygon.len();
|
||||
let half_edge_id = block.boundary_edges[i];
|
||||
let Some(he) = graph.half_edges.get(half_edge_id) else {
|
||||
return false;
|
||||
};
|
||||
let node_id = he.origin;
|
||||
let Some(node) = graph.nodes.get(node_id) else {
|
||||
return false;
|
||||
};
|
||||
if node.outgoing.len() >= 3 {
|
||||
return true;
|
||||
}
|
||||
// Degree-2: bend test.
|
||||
let v_prev = block.polygon.vertices()[(i + n - 1) % n];
|
||||
let v_curr = block.polygon.vertices()[i];
|
||||
let v_next = block.polygon.vertices()[(i + 1) % n];
|
||||
let in_dir = (v_curr - v_prev).normalize_or_zero();
|
||||
let out_dir = (v_next - v_curr).normalize_or_zero();
|
||||
if in_dir.length_squared() < EPS_GEOM * EPS_GEOM
|
||||
|| out_dir.length_squared() < EPS_GEOM * EPS_GEOM
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let cos_turn = in_dir.dot(out_dir).clamp(-1.0, 1.0);
|
||||
let turn_angle = cos_turn.acos();
|
||||
// turn > 30° means interior < 150° = "real corner".
|
||||
turn_angle > 30.0_f64.to_radians()
|
||||
}
|
||||
|
||||
/// Iteratively clip `parcel` by each inward half-plane of `block`.
|
||||
/// Returns `None` if the result is empty or invalid. Correct for
|
||||
/// convex blocks; may over-clip mild concavities (acceptable for
|
||||
/// milestone 0.2).
|
||||
fn clip_polygon_to_block(parcel: &Polygon, block: &Polygon) -> Option<Polygon> {
|
||||
let mut current = parcel.clone();
|
||||
let block_verts = block.vertices();
|
||||
let n = block_verts.len();
|
||||
for i in 0..n {
|
||||
let a = block_verts[i];
|
||||
let b = block_verts[(i + 1) % n];
|
||||
let edge = b - a;
|
||||
let len = edge.length();
|
||||
if len < EPS_GEOM {
|
||||
continue;
|
||||
}
|
||||
let dir = edge / len;
|
||||
let inward = DVec2::new(-dir.y, dir.x);
|
||||
current = current.clip_half_plane(a, inward)?;
|
||||
}
|
||||
Some(current)
|
||||
}
|
||||
|
||||
/// Locate the polygon edge that lies on the road segment
|
||||
/// `(road_a, road_b)` within tolerance.
|
||||
fn find_frontage_edge_after_clip(polygon: &Polygon, road_a: DVec2, road_b: DVec2) -> Option<usize> {
|
||||
let road_dir = (road_b - road_a).normalize_or_zero();
|
||||
if road_dir.length_squared() < EPS_GEOM * EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let road_normal = DVec2::new(-road_dir.y, road_dir.x);
|
||||
let v = polygon.vertices();
|
||||
let n = v.len();
|
||||
let tol = 100.0 * EPS_GEOM;
|
||||
let mut best: Option<(usize, f64)> = None;
|
||||
for i in 0..n {
|
||||
let p = v[i];
|
||||
let q = v[(i + 1) % n];
|
||||
let dp = (p - road_a).dot(road_normal).abs();
|
||||
let dq = (q - road_a).dot(road_normal).abs();
|
||||
if dp < tol && dq < tol {
|
||||
let edge_dir = (q - p).normalize_or_zero();
|
||||
if edge_dir.dot(road_dir).abs() > 0.5 {
|
||||
let len = (q - p).length();
|
||||
if best.is_none_or(|(_, blen)| len > blen) {
|
||||
best = Some((i, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
best.map(|(i, _)| i)
|
||||
}
|
||||
|
||||
/// "Short" corner consumption — equal to the corner radius `R`,
|
||||
/// capped at half each adjacent edge.
|
||||
fn corner_consume_short(
|
||||
edge_lens: &[f64],
|
||||
i: usize,
|
||||
r_target: f64,
|
||||
params: &SubdivisionParams,
|
||||
) -> f64 {
|
||||
let n = edge_lens.len();
|
||||
let prev_len = edge_lens[(i + n - 1) % n];
|
||||
let next_len = edge_lens[i];
|
||||
r_target
|
||||
.min(prev_len * 0.5)
|
||||
.min(next_len * 0.5)
|
||||
.max(params.min_frontage * 0.5)
|
||||
}
|
||||
|
||||
/// "Long" corner consumption — equal to the parcel depth, capped at
|
||||
/// half each adjacent edge.
|
||||
fn corner_consume_long(edge_lens: &[f64], i: usize, params: &SubdivisionParams) -> f64 {
|
||||
let n = edge_lens.len();
|
||||
let prev_len = edge_lens[(i + n - 1) % n];
|
||||
let next_len = edge_lens[i];
|
||||
params
|
||||
.depth
|
||||
.min(prev_len * 0.5)
|
||||
.min(next_len * 0.5)
|
||||
.max(params.min_frontage * 0.5)
|
||||
}
|
||||
|
||||
/// Per-edge depth cap (half the perpendicular distance from edge
|
||||
/// midpoint to the next polygon edge along the inward normal).
|
||||
fn edge_depth_caps(poly: &Polygon) -> Vec<f64> {
|
||||
let verts = poly.vertices();
|
||||
let n = verts.len();
|
||||
let mut caps = Vec::with_capacity(n);
|
||||
for i in 0..n {
|
||||
let p = verts[i];
|
||||
let q = verts[(i + 1) % n];
|
||||
let edge = q - p;
|
||||
let len = edge.length();
|
||||
if len < EPS_GEOM {
|
||||
caps.push(0.0);
|
||||
continue;
|
||||
}
|
||||
let dir = edge / len;
|
||||
let inward = DVec2::new(-dir.y, dir.x);
|
||||
let mid = (p + q) * 0.5;
|
||||
let mut min_t = f64::INFINITY;
|
||||
for j in 0..n {
|
||||
if j == i {
|
||||
continue;
|
||||
}
|
||||
let a = verts[j];
|
||||
let b = verts[(j + 1) % n];
|
||||
if let Some(t) = ray_segment_distance(mid, inward, a, b) {
|
||||
if t > EPS_GEOM && t < min_t {
|
||||
min_t = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
caps.push(min_t * 0.5);
|
||||
}
|
||||
caps
|
||||
}
|
||||
|
||||
fn ray_segment_distance(origin: DVec2, dir: DVec2, a: DVec2, b: DVec2) -> Option<f64> {
|
||||
let v1 = origin - a;
|
||||
let v2 = b - a;
|
||||
let v3 = DVec2::new(-dir.y, dir.x);
|
||||
let denom = v2.dot(v3);
|
||||
if denom.abs() < EPS_GEOM {
|
||||
return None;
|
||||
}
|
||||
let t = v2.perp_dot(v1) / denom;
|
||||
let s = v1.dot(v3) / denom;
|
||||
if t >= 0.0 && (-EPS_GEOM..=1.0 + EPS_GEOM).contains(&s) {
|
||||
Some(t)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Split positions between [`start`, `end`] along an edge. Begins
|
||||
/// with `start` and ends with `end`.
|
||||
fn split_positions_between(
|
||||
start: f64,
|
||||
end: f64,
|
||||
params: &SubdivisionParams,
|
||||
rng: &mut ChaCha8Rng,
|
||||
) -> Vec<f64> {
|
||||
let mut splits: Vec<f64> = vec![start];
|
||||
let mut t = start;
|
||||
loop {
|
||||
let jitter = params.frontage_variance * (rng.gen::<f64>() * 2.0 - 1.0);
|
||||
let dt = (params.frontage_width + jitter).max(params.min_frontage);
|
||||
t += dt;
|
||||
if t >= end - params.min_frontage * 0.5 {
|
||||
break;
|
||||
}
|
||||
splits.push(t);
|
||||
}
|
||||
splits.push(end);
|
||||
splits
|
||||
}
|
||||
|
||||
fn rng_for_road(seed: u64, road: RoadId) -> ChaCha8Rng {
|
||||
let road_bits = road.data().as_ffi();
|
||||
let mixed = seed
|
||||
.wrapping_mul(0x9E37_79B9_7F4A_7C15)
|
||||
.wrapping_add(road_bits)
|
||||
.wrapping_mul(0xBF58_476D_1CE4_E5B9);
|
||||
ChaCha8Rng::seed_from_u64(mixed)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn _unused_node_id() -> NodeId {
|
||||
NodeId::null()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn _unused_face_id() -> FaceId {
|
||||
FaceId::null()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn rectangle_graph(w: f64, h: f64) -> RoadGraph {
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(w, 0.0));
|
||||
let c = g.add_node(DVec2::new(w, h));
|
||||
let d = g.add_node(DVec2::new(0.0, h));
|
||||
g.add_road(a, b).unwrap();
|
||||
g.add_road(b, c).unwrap();
|
||||
g.add_road(c, d).unwrap();
|
||||
g.add_road(d, a).unwrap();
|
||||
g.rebuild_topology().unwrap();
|
||||
g
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangle_subdivides_into_many_parcels() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let set = subdivide_all(&g, ¶ms).unwrap();
|
||||
assert!(set.len() > 8, "got {} parcels", set.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangle_parcels_have_one_frontage_each() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let set = subdivide_all(&g, ¶ms).unwrap();
|
||||
for (_, p) in set.iter() {
|
||||
let frontage_count = p
|
||||
.edge_kinds()
|
||||
.iter()
|
||||
.filter(|k| matches!(k, super::super::EdgeKind::Frontage))
|
||||
.count();
|
||||
assert_eq!(frontage_count, 1, "I2 violation");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangle_parcels_do_not_overlap() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let set = subdivide_all(&g, ¶ms).unwrap();
|
||||
let total_area: f64 = set.iter().map(|(_, p)| p.area()).sum();
|
||||
let block_area = 200.0 * 100.0;
|
||||
assert!(
|
||||
total_area <= block_area + 1e-3,
|
||||
"parcel areas {total_area} > block area {block_area}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deterministic_with_fixed_seed() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let a = subdivide_all(&g, ¶ms).unwrap();
|
||||
let b = subdivide_all(&g, ¶ms).unwrap();
|
||||
assert_eq!(a.len(), b.len());
|
||||
for ((_, p1), (_, p2)) in a.iter().zip(b.iter()) {
|
||||
assert_eq!(p1.vertices().len(), p2.vertices().len());
|
||||
for (v1, v2) in p1.vertices().iter().zip(p2.vertices().iter()) {
|
||||
assert!((v1.x - v2.x).abs() < 1e-12);
|
||||
assert!((v1.y - v2.y).abs() < 1e-12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_params_rejected() {
|
||||
let g = rectangle_graph(50.0, 50.0);
|
||||
let params = SubdivisionParams {
|
||||
frontage_width: -1.0,
|
||||
..SubdivisionParams::default()
|
||||
};
|
||||
let err = subdivide_all(&g, ¶ms).unwrap_err();
|
||||
assert!(matches!(err, SubdivisionError::InvalidParams(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangle_has_corner_parcels() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let set = subdivide_all(&g, ¶ms).unwrap();
|
||||
// Parcel at the (0, 0) corner: its polygon should contain the
|
||||
// origin (or a vertex right at it) and have 4 vertices.
|
||||
let near_origin = set
|
||||
.iter()
|
||||
.find(|(_, p)| p.vertices().iter().any(|v| v.length_squared() < 1.0))
|
||||
.map(|(_, p)| p.vertices().len());
|
||||
assert_eq!(
|
||||
near_origin,
|
||||
Some(4),
|
||||
"expected a 4-vertex corner parcel near the origin"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stats_report_nonzero_phases() {
|
||||
let g = rectangle_graph(200.0, 100.0);
|
||||
let params = SubdivisionParams::default();
|
||||
let (set, stats) = subdivide_all_with_stats(&g, ¶ms).unwrap();
|
||||
assert_eq!(stats.parcel_count, set.len());
|
||||
assert!(stats.block_count >= 1);
|
||||
assert!(stats.total > Duration::ZERO);
|
||||
assert!(stats.parcels_per_second() > 0.0);
|
||||
}
|
||||
}
|
||||
192
road_parceling/src/viz/mod.rs
Normal file
@ -0,0 +1,192 @@
|
||||
//! SVG visualization (spec §8). Feature-gated behind `viz`.
|
||||
//!
|
||||
//! `render_scene` writes a single graph + parcel set to an SVG using
|
||||
//! the color conventions of §8.2. `generate_all_figures` regenerates
|
||||
//! every figure listed in the journal.
|
||||
|
||||
pub mod svg_render;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
pub use svg_render::{render_scene, RenderOptions};
|
||||
|
||||
/// Regenerate every figure listed in spec §8.1, writing into
|
||||
/// `out_dir`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Propagates IO errors (`io::Error`) and subdivision errors. The
|
||||
/// IO error path is wrapped into a `Box<dyn Error>` to keep the
|
||||
/// signature simple.
|
||||
pub fn generate_all_figures(out_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use crate::{subdivide_all, RoadGraph, SubdivisionParams};
|
||||
use glam::DVec2;
|
||||
|
||||
std::fs::create_dir_all(out_dir)?;
|
||||
|
||||
// fig_01_grid_block: rectangular block subdivided.
|
||||
{
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(200.0, 0.0));
|
||||
let c = g.add_node(DVec2::new(200.0, 100.0));
|
||||
let d = g.add_node(DVec2::new(0.0, 100.0));
|
||||
g.add_road(a, b)?;
|
||||
g.add_road(b, c)?;
|
||||
g.add_road(c, d)?;
|
||||
g.add_road(d, a)?;
|
||||
g.rebuild_topology()?;
|
||||
let params = SubdivisionParams::default();
|
||||
let parcels = subdivide_all(&g, ¶ms)?;
|
||||
let svg = render_scene(&g, &parcels, &RenderOptions::default());
|
||||
std::fs::write(out_dir.join("fig_01_grid_block.svg"), svg)?;
|
||||
}
|
||||
|
||||
// fig_02_curved_road: parcels on a polyline-curved frontage. We
|
||||
// approximate "curved" by a 12-segment arc.
|
||||
{
|
||||
let mut g = RoadGraph::new();
|
||||
let arc_radius = 200.0_f64;
|
||||
let arc_segments = 8;
|
||||
let arc_half_angle = std::f64::consts::FRAC_PI_4;
|
||||
// Arc on the bottom: from (-r sin θ, -r cos θ) to (r sin θ, -r cos θ),
|
||||
// centered at (0, 0). Then a back rectangle to close the block.
|
||||
let mut arc_nodes = Vec::new();
|
||||
for i in 0..=arc_segments {
|
||||
let t = -arc_half_angle + (i as f64) * (2.0 * arc_half_angle) / (arc_segments as f64);
|
||||
let p = DVec2::new(arc_radius * t.sin(), -arc_radius * t.cos() + arc_radius);
|
||||
arc_nodes.push(g.add_node(p));
|
||||
}
|
||||
let depth = 50.0;
|
||||
let last = *arc_nodes.last().expect("non-empty");
|
||||
let first = arc_nodes[0];
|
||||
let pos_last = g.node_position(last).expect("present");
|
||||
let pos_first = g.node_position(first).expect("present");
|
||||
let back_right = g.add_node(pos_last + DVec2::new(0.0, depth));
|
||||
let back_left = g.add_node(pos_first + DVec2::new(0.0, depth));
|
||||
for i in 0..arc_segments {
|
||||
g.add_road(arc_nodes[i], arc_nodes[i + 1])?;
|
||||
}
|
||||
g.add_road(last, back_right)?;
|
||||
g.add_road(back_right, back_left)?;
|
||||
g.add_road(back_left, first)?;
|
||||
if g.rebuild_topology().is_ok() {
|
||||
let params = SubdivisionParams::default();
|
||||
if let Ok(parcels) = subdivide_all(&g, ¶ms) {
|
||||
let svg = render_scene(&g, &parcels, &RenderOptions::default());
|
||||
std::fs::write(out_dir.join("fig_02_curved_road.svg"), svg)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fig_04_y_intersection: three roads at 120°, surrounded by a
|
||||
// triangular outer perimeter so the three blocks are bounded.
|
||||
{
|
||||
use std::f64::consts::TAU;
|
||||
let mut g = RoadGraph::new();
|
||||
let center = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let r = 90.0_f64;
|
||||
let third = TAU / 3.0;
|
||||
let p1 = g.add_node(DVec2::new(r * 0.0_f64.cos(), r * 0.0_f64.sin()));
|
||||
let p2 = g.add_node(DVec2::new(r * third.cos(), r * third.sin()));
|
||||
let p3 = g.add_node(DVec2::new(r * (2.0 * third).cos(), r * (2.0 * third).sin()));
|
||||
g.add_road(center, p1)?;
|
||||
g.add_road(center, p2)?;
|
||||
g.add_road(center, p3)?;
|
||||
g.add_road(p1, p2)?;
|
||||
g.add_road(p2, p3)?;
|
||||
g.add_road(p3, p1)?;
|
||||
g.rebuild_topology()?;
|
||||
let params = SubdivisionParams::default();
|
||||
let parcels = subdivide_all(&g, ¶ms)?;
|
||||
let svg = render_scene(&g, &parcels, &RenderOptions::default());
|
||||
std::fs::write(out_dir.join("fig_04_y_intersection.svg"), svg)?;
|
||||
}
|
||||
|
||||
// fig_06a + fig_06b: a 200×100 rectangle, before and after a
|
||||
// node move that produces a mix of edit outcomes. Post-edit
|
||||
// parcels are colored by their `EditOutcome` category.
|
||||
{
|
||||
use crate::{apply_road_edit, RoadEdit};
|
||||
use std::collections::HashMap;
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(200.0, 0.0));
|
||||
let c = g.add_node(DVec2::new(200.0, 100.0));
|
||||
let d = g.add_node(DVec2::new(0.0, 100.0));
|
||||
g.add_road(a, b)?;
|
||||
g.add_road(b, c)?;
|
||||
g.add_road(c, d)?;
|
||||
g.add_road(d, a)?;
|
||||
g.rebuild_topology()?;
|
||||
let params = SubdivisionParams::default();
|
||||
let mut parcels = subdivide_all(&g, ¶ms)?;
|
||||
let svg_before = render_scene(&g, &parcels, &RenderOptions::default());
|
||||
std::fs::write(out_dir.join("fig_06a_road_edit_before.svg"), svg_before)?;
|
||||
|
||||
// Move node B (the bottom-right corner) right by 8 m. That's
|
||||
// big enough to drag the bottom-edge parcels' frontages but
|
||||
// small enough that none of them get condemned.
|
||||
let pos_b = g.node_position(b).unwrap_or(DVec2::ZERO);
|
||||
let outcome = apply_road_edit(
|
||||
&mut parcels,
|
||||
&mut g,
|
||||
RoadEdit::MoveNode {
|
||||
node: b,
|
||||
to: pos_b + DVec2::new(8.0, 0.0),
|
||||
},
|
||||
¶ms,
|
||||
)?;
|
||||
|
||||
let mut fills: HashMap<crate::ParcelId, String> = HashMap::new();
|
||||
for &pid in &outcome.deformed {
|
||||
fills.insert(pid, "#9fd99a".to_string()); // green
|
||||
}
|
||||
for &pid in &outcome.regenerated {
|
||||
fills.insert(pid, "#ffc070".to_string()); // orange
|
||||
}
|
||||
for &pid in &outcome.created {
|
||||
fills.insert(pid, "#7fc8ff".to_string()); // blue (created)
|
||||
}
|
||||
// Condemned parcels are gone; we paint the empty space red
|
||||
// by overlaying the rendering — but with the lite parcel
|
||||
// model we just note that condemned ids no longer exist in
|
||||
// `parcels`, so the rendering naturally shows nothing in
|
||||
// their place.
|
||||
let mut opts = RenderOptions::default();
|
||||
opts.parcel_fills = fills;
|
||||
let svg_after = render_scene(&g, &parcels, &opts);
|
||||
std::fs::write(out_dir.join("fig_06b_road_edit_after.svg"), svg_after)?;
|
||||
}
|
||||
|
||||
// fig_07_regularity_slider: same scene at ρ ∈ {0, 0.5, 1.0}.
|
||||
// For milestone 0.1 the regularization pass is a stub, so the
|
||||
// three panels are identical — we still emit the figure so the
|
||||
// journal compiles, with a TODO recorded in §11 (R3).
|
||||
{
|
||||
let mut g = RoadGraph::new();
|
||||
let a = g.add_node(DVec2::new(0.0, 0.0));
|
||||
let b = g.add_node(DVec2::new(180.0, 0.0));
|
||||
let c = g.add_node(DVec2::new(180.0, 110.0));
|
||||
let d = g.add_node(DVec2::new(0.0, 110.0));
|
||||
g.add_road(a, b)?;
|
||||
g.add_road(b, c)?;
|
||||
g.add_road(c, d)?;
|
||||
g.add_road(d, a)?;
|
||||
g.rebuild_topology()?;
|
||||
for (rho, suffix) in [(0.0, "rho_0_0"), (0.5, "rho_0_5"), (1.0, "rho_1_0")] {
|
||||
let params = SubdivisionParams {
|
||||
regularity: rho,
|
||||
..SubdivisionParams::default()
|
||||
};
|
||||
let parcels = subdivide_all(&g, ¶ms)?;
|
||||
let svg = render_scene(&g, &parcels, &RenderOptions::default());
|
||||
std::fs::write(
|
||||
out_dir.join(format!("fig_07_regularity_slider_{suffix}.svg")),
|
||||
svg,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
228
road_parceling/src/viz/svg_render.rs
Normal file
@ -0,0 +1,228 @@
|
||||
//! SVG rendering of a graph + parcel set.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use glam::DVec2;
|
||||
use svg::node::element::path::Data;
|
||||
use svg::node::element::{Group, Line, Path as SvgPath, Rectangle};
|
||||
use svg::Document;
|
||||
|
||||
use crate::network::RoadGraph;
|
||||
use crate::parcel::{EdgeKind, ParcelId, ParcelSet};
|
||||
|
||||
/// Knobs for the SVG renderer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RenderOptions {
|
||||
/// Pixels per meter.
|
||||
pub pixels_per_meter: f64,
|
||||
/// Padding around the scene, meters.
|
||||
pub margin_m: f64,
|
||||
/// Whether to draw vertex dots on roads.
|
||||
pub draw_nodes: bool,
|
||||
/// Per-parcel fill overrides — keyed by [`ParcelId`], values are
|
||||
/// SVG-compatible color strings. Used by the post-edit figures
|
||||
/// to paint each parcel by its [`EditOutcome`] category.
|
||||
pub parcel_fills: HashMap<ParcelId, String>,
|
||||
}
|
||||
|
||||
impl Default for RenderOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pixels_per_meter: 4.0,
|
||||
margin_m: 5.0,
|
||||
draw_nodes: true,
|
||||
parcel_fills: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the whole scene to an SVG `String`.
|
||||
#[must_use]
|
||||
pub fn render_scene(graph: &RoadGraph, parcels: &ParcelSet, opts: &RenderOptions) -> String {
|
||||
let bbox = compute_bbox(graph, parcels);
|
||||
let (min, max) = bbox;
|
||||
let m = opts.margin_m;
|
||||
let world_w = (max.x - min.x) + 2.0 * m;
|
||||
let world_h = (max.y - min.y) + 2.0 * m;
|
||||
let px_w = world_w * opts.pixels_per_meter;
|
||||
let px_h = world_h * opts.pixels_per_meter;
|
||||
|
||||
// World y is up, SVG y is down. Flip and translate via viewBox so
|
||||
// we can write coordinates in world units throughout.
|
||||
let view_min_x = min.x - m;
|
||||
let view_min_y = min.y - m;
|
||||
let view_w = world_w;
|
||||
let view_h = world_h;
|
||||
|
||||
// We use an inverted y by setting viewBox to a flipped rectangle,
|
||||
// then a transform on the root group that applies (1, -1) and a
|
||||
// y-translation.
|
||||
let view_box = format!("{view_min_x} {view_min_y} {view_w} {view_h}");
|
||||
|
||||
let bg = Rectangle::new()
|
||||
.set("x", view_min_x)
|
||||
.set("y", view_min_y)
|
||||
.set("width", view_w)
|
||||
.set("height", view_h)
|
||||
.set("fill", "#ffffff");
|
||||
|
||||
// Group with y-flip to put world +y up.
|
||||
let flip = Group::new().set(
|
||||
"transform",
|
||||
format!("translate(0, {}) scale(1, -1)", 2.0 * view_min_y + view_h),
|
||||
);
|
||||
|
||||
// Draw roads first (so frontage edges of parcels paint on top of
|
||||
// the road stroke and stay visible), then parcels, then nodes.
|
||||
let roads_layer = roads_group(graph);
|
||||
let parcels_layer = parcels_group(parcels, &opts.parcel_fills);
|
||||
let nodes_layer = if opts.draw_nodes {
|
||||
nodes_group(graph)
|
||||
} else {
|
||||
Group::new()
|
||||
};
|
||||
|
||||
let flip = flip.add(roads_layer).add(parcels_layer).add(nodes_layer);
|
||||
|
||||
Document::new()
|
||||
.set("viewBox", view_box)
|
||||
.set("width", px_w)
|
||||
.set("height", px_h)
|
||||
.set("xmlns", "http://www.w3.org/2000/svg")
|
||||
.add(bg)
|
||||
.add(flip)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn compute_bbox(graph: &RoadGraph, parcels: &ParcelSet) -> (DVec2, DVec2) {
|
||||
let mut min = DVec2::splat(f64::INFINITY);
|
||||
let mut max = DVec2::splat(f64::NEG_INFINITY);
|
||||
let mut update = |p: DVec2| {
|
||||
if p.x < min.x {
|
||||
min.x = p.x;
|
||||
}
|
||||
if p.y < min.y {
|
||||
min.y = p.y;
|
||||
}
|
||||
if p.x > max.x {
|
||||
max.x = p.x;
|
||||
}
|
||||
if p.y > max.y {
|
||||
max.y = p.y;
|
||||
}
|
||||
};
|
||||
for (_, _, _) in graph.road_endpoints() {
|
||||
// road_endpoints gives us ids; iterate nodes instead.
|
||||
}
|
||||
for nid in graph_node_ids(graph) {
|
||||
if let Some(p) = graph.node_position(nid) {
|
||||
update(p);
|
||||
}
|
||||
}
|
||||
for (_, parcel) in parcels.iter() {
|
||||
for &v in parcel.vertices() {
|
||||
update(v);
|
||||
}
|
||||
}
|
||||
if !min.x.is_finite() {
|
||||
// No content — fall back to a unit square.
|
||||
return (DVec2::ZERO, DVec2::splat(1.0));
|
||||
}
|
||||
(min, max)
|
||||
}
|
||||
|
||||
fn graph_node_ids(graph: &RoadGraph) -> Vec<crate::network::NodeId> {
|
||||
let mut seen = Vec::new();
|
||||
for (_, a, b) in graph.road_endpoints() {
|
||||
seen.push(a);
|
||||
seen.push(b);
|
||||
}
|
||||
seen.sort_by_key(|n| format!("{n:?}"));
|
||||
seen.dedup();
|
||||
seen
|
||||
}
|
||||
|
||||
fn parcels_group(parcels: &ParcelSet, overrides: &HashMap<ParcelId, String>) -> Group {
|
||||
let mut group = Group::new().set("id", "parcels");
|
||||
for (id, parcel) in parcels.iter() {
|
||||
let verts = parcel.vertices();
|
||||
if verts.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let mut data = Data::new().move_to((verts[0].x, verts[0].y));
|
||||
for v in &verts[1..] {
|
||||
data = data.line_to((v.x, v.y));
|
||||
}
|
||||
data = data.close();
|
||||
let (fill_color, fill_opacity) = match overrides.get(&id) {
|
||||
Some(c) => (c.clone(), 0.55_f64),
|
||||
None => ("#fff7c2".to_string(), 0.3_f64),
|
||||
};
|
||||
let fill = SvgPath::new()
|
||||
.set("d", data)
|
||||
.set("fill", fill_color)
|
||||
.set("fill-opacity", fill_opacity)
|
||||
.set("stroke", "none");
|
||||
group = group.add(fill);
|
||||
|
||||
let _ = id;
|
||||
// Stroke each edge by its kind.
|
||||
for (i, kind) in parcel.edge_kinds().iter().enumerate() {
|
||||
let a = verts[i];
|
||||
let b = verts[(i + 1) % verts.len()];
|
||||
let (color, dashed, width) = match kind {
|
||||
EdgeKind::Frontage => ("#1f5fb4", false, 0.9_f64),
|
||||
EdgeKind::Side => ("#6b6b6b", false, 0.4_f64),
|
||||
EdgeKind::Back => ("#bdbdbd", true, 0.4_f64),
|
||||
};
|
||||
let mut line = Line::new()
|
||||
.set("x1", a.x)
|
||||
.set("y1", a.y)
|
||||
.set("x2", b.x)
|
||||
.set("y2", b.y)
|
||||
.set("stroke", color)
|
||||
.set("stroke-width", width);
|
||||
if dashed {
|
||||
line = line.set("stroke-dasharray", "1.6,1.2");
|
||||
}
|
||||
group = group.add(line);
|
||||
}
|
||||
}
|
||||
group
|
||||
}
|
||||
|
||||
fn roads_group(graph: &RoadGraph) -> Group {
|
||||
let mut group = Group::new().set("id", "roads");
|
||||
for (_, a, b) in graph.road_endpoints() {
|
||||
let pa = graph.node_position(a);
|
||||
let pb = graph.node_position(b);
|
||||
if let (Some(pa), Some(pb)) = (pa, pb) {
|
||||
let line = Line::new()
|
||||
.set("x1", pa.x)
|
||||
.set("y1", pa.y)
|
||||
.set("x2", pb.x)
|
||||
.set("y2", pb.y)
|
||||
.set("stroke", "#000000")
|
||||
.set("stroke-width", 0.6_f64)
|
||||
.set("stroke-linecap", "round");
|
||||
group = group.add(line);
|
||||
}
|
||||
}
|
||||
group
|
||||
}
|
||||
|
||||
fn nodes_group(graph: &RoadGraph) -> Group {
|
||||
use svg::node::element::Circle;
|
||||
let mut group = Group::new().set("id", "nodes");
|
||||
for nid in graph_node_ids(graph) {
|
||||
if let Some(p) = graph.node_position(nid) {
|
||||
let c = Circle::new()
|
||||
.set("cx", p.x)
|
||||
.set("cy", p.y)
|
||||
.set("r", 0.7_f64)
|
||||
.set("fill", "#000000");
|
||||
group = group.add(c);
|
||||
}
|
||||
}
|
||||
group
|
||||
}
|
||||
1
road_parceling/target/.rustc_info.json
Normal file
@ -0,0 +1 @@
|
||||
{"rustc_fingerprint":4812792677330984170,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.92.0 (ded5c06cf 2025-12-08) (Homebrew)\nbinary: rustc\ncommit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234\ncommit-date: 2025-12-08\nhost: aarch64-apple-darwin\nrelease: 1.92.0\nLLVM version: 21.1.7\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/opt/homebrew/Cellar/rust/1.92.0\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""}},"successes":{}}
|
||||
1
road_parceling/target/.rustdoc_fingerprint.json
Normal file
@ -0,0 +1 @@
|
||||
{"rustc_vv":"rustc 1.92.0 (ded5c06cf 2025-12-08) (Homebrew)\nbinary: rustc\ncommit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234\ncommit-date: 2025-12-08\nhost: aarch64-apple-darwin\nrelease: 1.92.0\nLLVM version: 21.1.7\n"}
|
||||
3
road_parceling/target/CACHEDIR.TAG
Normal file
@ -0,0 +1,3 @@
|
||||
Signature: 8a477f597d28d172789f06886806bc55
|
||||
# This file is a cache directory tag created by cargo.
|
||||
# For information about cache directory tags see https://bford.info/cachedir/
|
||||
0
road_parceling/target/debug/.cargo-lock
Normal file
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
047e95b7d0e15acc
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\"]","declared_features":"[\"bitflags\", \"default\", \"parser\"]","target":15514848761019652899,"profile":8276155916380437441,"path":1381630239697283883,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/anes-9ee70e632c90772d/dep-lib-anes","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
53e3de259b22e5ee
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\"]","declared_features":"[\"bitflags\", \"default\", \"parser\"]","target":15514848761019652899,"profile":5347358027863023418,"path":1381630239697283883,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/anes-f7727b7c02c2c54f/dep-lib-anes","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
e6d4e801df4a56e6
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"std\"]","target":6165884447290141869,"profile":790325420539221616,"path":5326910857737216307,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/anstyle-71183a543eeda23e/dep-lib-anstyle","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
abd93f4afaf69924
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"std\"]","target":6165884447290141869,"profile":8255941854203129366,"path":5326910857737216307,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/anstyle-dee35890a12dd6ce/dep-lib-anstyle","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
3e0b4b221a4c2750
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[]","declared_features":"[]","target":6962977057026645649,"profile":3033921117576893,"path":4405214941553509729,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/autocfg-c7e245154ebc45d3/dep-lib-autocfg","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
3e6425f0d8f0397f
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"serde\", \"std\"]","target":1565461888733056401,"profile":5347358027863023418,"path":4377444822781387660,"deps":[[5692597712387868707,"bit_vec",false,2150889985839040455]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bit-set-4b2fefdf0afbe4cd/dep-lib-bit_set","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
8a2231a955bb0ff5
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"serde\", \"std\"]","target":1565461888733056401,"profile":8276155916380437441,"path":4377444822781387660,"deps":[[5692597712387868707,"bit_vec",false,1129808780249088941]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bit-set-a3f155482d8725e2/dep-lib-bit_set","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
ad43dd8219e3ad0f
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"borsh\", \"borsh_std\", \"default\", \"miniserde\", \"nanoserde\", \"serde\", \"serde_no_std\", \"serde_std\", \"std\"]","target":1886748672988989682,"profile":8276155916380437441,"path":17936763483328278557,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bit-vec-8893692845f45650/dep-lib-bit_vec","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
c787e1d40b7fd91d
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"borsh\", \"borsh_std\", \"default\", \"miniserde\", \"nanoserde\", \"serde\", \"serde_no_std\", \"serde_std\", \"std\"]","target":1886748672988989682,"profile":5347358027863023418,"path":17936763483328278557,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bit-vec-f19c8d0b3ed7fe20/dep-lib-bit_vec","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
a01b101bd3fcb932
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"std\"]","declared_features":"[\"arbitrary\", \"bytemuck\", \"example_generated\", \"serde\", \"serde_core\", \"std\"]","target":7691312148208718491,"profile":8276155916380437441,"path":5561816516557774638,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-63dd709ab55cd2cc/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
2b7eaa6178f77599
|
||||
@ -0,0 +1 @@
|
||||
{"rustc":12211934750107851607,"features":"[\"std\"]","declared_features":"[\"arbitrary\", \"bytemuck\", \"example_generated\", \"serde\", \"serde_core\", \"std\"]","target":7691312148208718491,"profile":5347358027863023418,"path":5561816516557774638,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-7fd589d26c2da380/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
@ -0,0 +1 @@
|
||||
This file has an mtime of when this was started.
|
||||
@ -0,0 +1 @@
|
||||
23047bf6a02ccfd9
|
||||