.nornir/assets/maptrait-layers.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 640" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0b1c2e"/>
<stop offset="1" stop-color="#06111d"/>
</linearGradient>
<linearGradient id="chip" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#14384f"/>
<stop offset="1" stop-color="#0e2a3e"/>
</linearGradient>
<linearGradient id="layer" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#173d57"/>
<stop offset="1" stop-color="#0c2438"/>
</linearGradient>
<linearGradient id="render" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#1c4a3a"/>
<stop offset="1" stop-color="#0d2a20"/>
</linearGradient>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 z" fill="#6fd0c0"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="640" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1">
<line x1="0" y1="70" x2="1180" y2="70"/>
<line x1="0" y1="586" x2="1180" y2="586"/>
</g>
<text x="40" y="46" fill="#dff3ee" font-size="26" font-weight="700">The selectable Map trait — one MapLayer, all maps</text>
<text x="40" y="63" fill="#7fa8bd" font-size="13">facett-map/src/layer.rs · consolidation design §3.1 · renderer is source-agnostic</text>
<!-- SELECTABLE + STACKABLE sources (left) -->
<text x="60" y="118" fill="#9fd6ea" font-size="14" font-weight="700">SELECTABLE · STACKABLE sources</text>
<g font-size="14">
<g>
<rect x="60" y="132" width="300" height="58" rx="9" fill="url(#layer)" stroke="#2b6f8f"/>
<text x="80" y="158" fill="#eaf6ff" font-weight="700">WaysLayer "osm-streets"</text>
<text x="80" y="178" fill="#8fbdd0" font-size="12">OSM GeoParquet via facett-osm (no re-parse)</text>
<circle cx="338" cy="150" r="7" fill="#5fd08a"/><text x="330" y="184" fill="#5fd08a" font-size="10">on</text>
</g>
<g>
<rect x="60" y="204" width="300" height="58" rx="9" fill="url(#layer)" stroke="#2b6f8f"/>
<text x="80" y="230" fill="#eaf6ff" font-weight="700">WaysLayer "trafikverket-roads"</text>
<text x="80" y="250" fill="#8fbdd0" font-size="12">same type, different id — selectable at runtime</text>
<circle cx="338" cy="222" r="7" fill="#5fd08a"/><text x="330" y="256" fill="#5fd08a" font-size="10">on</text>
</g>
<g>
<rect x="60" y="276" width="300" height="58" rx="9" fill="url(#layer)" stroke="#2b6f8f"/>
<text x="80" y="302" fill="#eaf6ff" font-weight="700">PointsLayer "korp-hits"</text>
<text x="80" y="322" fill="#8fbdd0" font-size="12">a korp collector's geo output overlay</text>
<circle cx="338" cy="294" r="7" fill="#5fd08a"/><text x="330" y="328" fill="#5fd08a" font-size="10">on</text>
</g>
<g>
<rect x="60" y="348" width="300" height="46" rx="9" fill="#132436" stroke="#274b60" stroke-dasharray="4 3"/>
<text x="80" y="376" fill="#7b9fb2" font-weight="700">… any MapLayer (toggle = select data)</text>
</g>
</g>
<!-- trait seam -->
<text x="470" y="118" fill="#9fd6ea" font-size="14" font-weight="700">trait MapLayer</text>
<rect x="440" y="132" width="220" height="262" rx="10" fill="url(#chip)" stroke="#2f7ea0"/>
<g font-size="12.5" fill="#cfe8f4">
<text x="458" y="160">id() · kind()</text>
<text x="458" y="184">features(&MapView)</text>
<text x="458" y="204" fill="#7fb0c6" font-size="11">→ Vec<DrawFeature> (culled)</text>
<text x="458" y="230">style()</text>
<text x="458" y="254">enabled() / set_enabled()</text>
<line x1="458" y1="268" x2="642" y2="268" stroke="#1f5570"/>
<text x="458" y="292" fill="#a7d9ec">DrawFeature =</text>
<text x="458" y="312" fill="#8fbdd0" font-size="11">{ id, geom, color, width, fill, z }</text>
<text x="458" y="334" fill="#8fbdd0" font-size="11">geom: Point|Line|Polygon|Label</text>
<text x="458" y="366" fill="#6fd0c0" font-size="11">NOT source structs → renderer stays generic</text>
</g>
<!-- camera -->
<text x="720" y="118" fill="#9fd6ea" font-size="14" font-weight="700">MapView camera (rotatable)</text>
<rect x="720" y="132" width="180" height="120" rx="10" fill="url(#chip)" stroke="#2f7ea0"/>
<g font-size="12.5" fill="#cfe8f4">
<text x="738" y="158">center · zoom</text>
<text x="738" y="182" fill="#ffd98a">bearing_deg</text>
<text x="738" y="204" fill="#ffd98a">tilt_deg</text>
<text x="738" y="228" fill="#8fbdd0" font-size="11">the car-nav feel</text>
</g>
<!-- renderer -->
<text x="720" y="290" fill="#9fd6ea" font-size="14" font-weight="700">MapFacet · one shared renderer</text>
<rect x="720" y="304" width="380" height="150" rx="10" fill="url(#render)" stroke="#3a9070"/>
<g font-size="12.5" fill="#d6f2e6">
<text x="740" y="332">enabled_features() — cull → project → z-sort</text>
<text x="740" y="358" fill="#a9dcc7" font-size="11">polygons < lines < points < labels</text>
<text x="740" y="384">ui() paints via MapView::project (rotated + tilted)</text>
<text x="740" y="408" fill="#a9dcc7" font-size="11">MapTheme: day/night · crisp hierarchy · tilt-shade</text>
<text x="740" y="434" fill="#7fe0b8" font-size="11">→ egui frame · bench: facett.map.layer_frame</text>
</g>
<!-- flows -->
<g fill="none" stroke="#6fd0c0" stroke-width="2" marker-end="url(#arrow)">
<path d="M360 161 H438"/>
<path d="M360 233 H438"/>
<path d="M360 305 C 400 305, 410 268, 438 268"/>
<path d="M660 240 C 690 240, 695 300, 718 320"/>
<path d="M810 252 V 302"/>
</g>
<text x="40" y="616" fill="#5f8298" font-size="12">OSM streets + Trafikverket overlay + korp collector layers → one trait, one renderer, one rotatable flat map (better than a Garmin navigator).</text>
</svg>