feat(tooling): add star map SVG generator

Reproducible concentric-ring star map: Gateway at center, hop rings
radiating outward, sectors in cardinal wedges (N/E/S/W), alternating
band colors per sector, hop 15+ folded into final ring with fade-out
zone. Sol pinned due west.

Run: python3 tooling/generate-star-map-svg.py
Output: docs/diagrams/design/star-map-concentric.svg

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 11:05:34 +01:00
co-authored by Claude Opus 4.6
parent 172040fb5d
commit f9373be3ba
2 changed files with 1111 additions and 0 deletions
@@ -0,0 +1,778 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3200 3200" width="3200" height="3200">
<defs>
<radialGradient id="fadeEdge" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#0a0a1a" stop-opacity="0"/>
<stop offset="56.4%" stop-color="#0a0a1a" stop-opacity="0"/>
<stop offset="63.1%" stop-color="#0a0a1a" stop-opacity="1"/>
<stop offset="100%" stop-color="#0a0a1a" stop-opacity="1"/>
</radialGradient>
</defs>
<rect width="3200" height="3200" fill="#0a0a1a"/>
<path d="M 1507 1507 A 132 132 0 0 1 1693 1507 L 1655 1545 A 78 78 0 0 0 1545 1545 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1468 1468 A 187 187 0 0 1 1732 1468 L 1694 1506 A 133 133 0 0 0 1506 1506 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1429 1429 A 242 242 0 0 1 1771 1429 L 1733 1467 A 188 188 0 0 0 1467 1467 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1390 1390 A 297 297 0 0 1 1810 1390 L 1772 1428 A 243 243 0 0 0 1428 1428 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1351 1351 A 352 352 0 0 1 1849 1351 L 1811 1389 A 298 298 0 0 0 1389 1389 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1312 1312 A 407 407 0 0 1 1888 1312 L 1850 1350 A 353 353 0 0 0 1350 1350 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1273 1273 A 462 462 0 0 1 1927 1273 L 1888 1312 A 408 408 0 0 0 1312 1312 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1234 1234 A 517 517 0 0 1 1966 1234 L 1927 1273 A 463 463 0 0 0 1273 1273 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1196 1196 A 572 572 0 0 1 2004 1196 L 1966 1234 A 518 518 0 0 0 1234 1234 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1157 1157 A 627 627 0 0 1 2043 1157 L 2005 1195 A 573 573 0 0 0 1195 1195 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1118 1118 A 682 682 0 0 1 2082 1118 L 2044 1156 A 628 628 0 0 0 1156 1156 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1079 1079 A 737 737 0 0 1 2121 1079 L 2083 1117 A 683 683 0 0 0 1117 1117 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 1040 1040 A 792 792 0 0 1 2160 1040 L 2122 1078 A 738 738 0 0 0 1078 1078 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1001 1001 A 847 847 0 0 1 2199 1001 L 2161 1039 A 793 793 0 0 0 1039 1039 Z" fill="#1a2244" opacity="0.35"/>
<path d="M 962 962 A 902 902 0 0 1 2238 962 L 2200 1000 A 848 848 0 0 0 1000 1000 Z" fill="#1a2a55" opacity="0.35"/>
<path d="M 1693 1507 A 132 132 0 0 1 1693 1693 L 1655 1655 A 78 78 0 0 0 1655 1545 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 1732 1468 A 187 187 0 0 1 1732 1732 L 1694 1694 A 133 133 0 0 0 1694 1506 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 1771 1429 A 242 242 0 0 1 1771 1771 L 1733 1733 A 188 188 0 0 0 1733 1467 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 1810 1390 A 297 297 0 0 1 1810 1810 L 1772 1772 A 243 243 0 0 0 1772 1428 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 1849 1351 A 352 352 0 0 1 1849 1849 L 1811 1811 A 298 298 0 0 0 1811 1389 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 1888 1312 A 407 407 0 0 1 1888 1888 L 1850 1850 A 353 353 0 0 0 1850 1350 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 1927 1273 A 462 462 0 0 1 1927 1927 L 1888 1888 A 408 408 0 0 0 1888 1312 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 1966 1234 A 517 517 0 0 1 1966 1966 L 1927 1927 A 463 463 0 0 0 1927 1273 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 2004 1196 A 572 572 0 0 1 2004 2004 L 1966 1966 A 518 518 0 0 0 1966 1234 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 2043 1157 A 627 627 0 0 1 2043 2043 L 2005 2005 A 573 573 0 0 0 2005 1195 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 2082 1118 A 682 682 0 0 1 2082 2082 L 2044 2044 A 628 628 0 0 0 2044 1156 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 2121 1079 A 737 737 0 0 1 2121 2121 L 2083 2083 A 683 683 0 0 0 2083 1117 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 2160 1040 A 792 792 0 0 1 2160 2160 L 2122 2122 A 738 738 0 0 0 2122 1078 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 2199 1001 A 847 847 0 0 1 2199 2199 L 2161 2161 A 793 793 0 0 0 2161 1039 Z" fill="#1a2a1a" opacity="0.35"/>
<path d="M 2238 962 A 902 902 0 0 1 2238 2238 L 2200 2200 A 848 848 0 0 0 2200 1000 Z" fill="#1a331a" opacity="0.35"/>
<path d="M 1693 1693 A 132 132 0 0 1 1507 1693 L 1545 1655 A 78 78 0 0 0 1655 1655 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 1732 1732 A 187 187 0 0 1 1468 1732 L 1506 1694 A 133 133 0 0 0 1694 1694 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 1771 1771 A 242 242 0 0 1 1429 1771 L 1467 1733 A 188 188 0 0 0 1733 1733 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 1810 1810 A 297 297 0 0 1 1390 1810 L 1428 1772 A 243 243 0 0 0 1772 1772 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 1849 1849 A 352 352 0 0 1 1351 1849 L 1389 1811 A 298 298 0 0 0 1811 1811 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 1888 1888 A 407 407 0 0 1 1312 1888 L 1350 1850 A 353 353 0 0 0 1850 1850 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 1927 1927 A 462 462 0 0 1 1273 1927 L 1312 1888 A 408 408 0 0 0 1888 1888 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 1966 1966 A 517 517 0 0 1 1234 1966 L 1273 1927 A 463 463 0 0 0 1927 1927 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 2004 2004 A 572 572 0 0 1 1196 2004 L 1234 1966 A 518 518 0 0 0 1966 1966 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 2043 2043 A 627 627 0 0 1 1157 2043 L 1195 2005 A 573 573 0 0 0 2005 2005 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 2082 2082 A 682 682 0 0 1 1118 2082 L 1156 2044 A 628 628 0 0 0 2044 2044 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 2121 2121 A 737 737 0 0 1 1079 2121 L 1117 2083 A 683 683 0 0 0 2083 2083 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 2160 2160 A 792 792 0 0 1 1040 2160 L 1078 2122 A 738 738 0 0 0 2122 2122 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 2199 2199 A 847 847 0 0 1 1001 2199 L 1039 2161 A 793 793 0 0 0 2161 2161 Z" fill="#2a1a1a" opacity="0.35"/>
<path d="M 2238 2238 A 902 902 0 0 1 962 2238 L 1000 2200 A 848 848 0 0 0 2200 2200 Z" fill="#331a1a" opacity="0.35"/>
<path d="M 1507 1693 A 132 132 0 0 1 1507 1507 L 1545 1545 A 78 78 0 0 0 1545 1655 Z" fill="#332810" opacity="0.35"/>
<path d="M 1468 1732 A 187 187 0 0 1 1468 1468 L 1506 1506 A 133 133 0 0 0 1506 1694 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1429 1771 A 242 242 0 0 1 1429 1429 L 1467 1467 A 188 188 0 0 0 1467 1733 Z" fill="#332810" opacity="0.35"/>
<path d="M 1390 1810 A 297 297 0 0 1 1390 1390 L 1428 1428 A 243 243 0 0 0 1428 1772 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1351 1849 A 352 352 0 0 1 1351 1351 L 1389 1389 A 298 298 0 0 0 1389 1811 Z" fill="#332810" opacity="0.35"/>
<path d="M 1312 1888 A 407 407 0 0 1 1312 1312 L 1350 1350 A 353 353 0 0 0 1350 1850 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1273 1927 A 462 462 0 0 1 1273 1273 L 1312 1312 A 408 408 0 0 0 1312 1888 Z" fill="#332810" opacity="0.35"/>
<path d="M 1234 1966 A 517 517 0 0 1 1234 1234 L 1273 1273 A 463 463 0 0 0 1273 1927 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1196 2004 A 572 572 0 0 1 1196 1196 L 1234 1234 A 518 518 0 0 0 1234 1966 Z" fill="#332810" opacity="0.35"/>
<path d="M 1157 2043 A 627 627 0 0 1 1157 1157 L 1195 1195 A 573 573 0 0 0 1195 2005 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1118 2082 A 682 682 0 0 1 1118 1118 L 1156 1156 A 628 628 0 0 0 1156 2044 Z" fill="#332810" opacity="0.35"/>
<path d="M 1079 2121 A 737 737 0 0 1 1079 1079 L 1117 1117 A 683 683 0 0 0 1117 2083 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 1040 2160 A 792 792 0 0 1 1040 1040 L 1078 1078 A 738 738 0 0 0 1078 2122 Z" fill="#332810" opacity="0.35"/>
<path d="M 1001 2199 A 847 847 0 0 1 1001 1001 L 1039 1039 A 793 793 0 0 0 1039 2161 Z" fill="#2a2010" opacity="0.35"/>
<path d="M 962 2238 A 902 902 0 0 1 962 962 L 1000 1000 A 848 848 0 0 0 1000 2200 Z" fill="#332810" opacity="0.35"/>
<rect width="3200" height="3200" fill="url(#fadeEdge)"/>
<text x="1600.0" y="654.8" fill="#4488FF" font-size="18" font-family="monospace" text-anchor="middle" opacity="0.4">NORTH REACH</text>
<text x="1600.0" y="2563.2" fill="#FF4444" font-size="18" font-family="monospace" text-anchor="middle" opacity="0.4">SOUTH REACH</text>
<text x="2555.2" y="1606.0" fill="#44DD44" font-size="18" font-family="monospace" opacity="0.4">EAST REACH</text>
<text x="644.8" y="1606.0" fill="#FF8800" font-size="18" font-family="monospace" text-anchor="end" opacity="0.4">WEST REACH</text>
<line x1="1600.0" y1="1600.0" x2="1698.0" y2="1562.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1600.0" x2="1698.0" y2="1637.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1649.4" y1="1809.2" x2="1330.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1330.0" y1="1600.0" x2="1401.4" y2="1517.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1401.4" y1="1517.7" x2="1381.6" y2="1758.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1381.6" y1="1758.7" x2="1337.1" y2="1409.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1337.1" y1="1409.0" x2="1236.4" y2="1710.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1236.4" y1="1710.3" x2="1229.1" y2="1372.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1229.1" y1="1372.7" x2="1112.4" y2="1648.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1112.4" y1="1648.0" x2="1112.4" y2="1552.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1112.4" y1="1552.0" x2="1269.2" y2="1317.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.3" y1="1616.9" x2="1806.8" y2="1541.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1269.2" y1="1317.5" x2="1221.8" y2="1637.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1221.8" y1="1637.2" x2="1337.1" y2="1791.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1337.1" y1="1791.0" x2="1343.2" y2="1516.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1401.4" y1="1517.7" x2="1343.2" y2="1683.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1343.2" y1="1516.6" x2="1401.4" y2="1682.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1401.4" y1="1682.3" x2="1381.6" y2="1441.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1381.6" y1="1441.3" x2="1290.9" y2="1700.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1264.9" y1="1779.1" x2="1198.1" y2="1433.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1198.1" y1="1433.5" x2="1131.1" y2="1742.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1290.9" y1="1700.4" x2="1221.8" y2="1562.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1177.0" y1="1498.5" x2="1221.2" y2="1910.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1306.3" y2="1358.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1306.3" y1="1358.9" x2="1177.0" y2="1701.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1198.1" y1="1766.5" x2="1264.9" y2="1420.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1264.9" y1="1420.9" x2="1290.4" y2="1905.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1306.3" y1="1358.9" x2="1167.0" y2="1641.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2089.9" y1="1592.8" x2="2118.2" y2="1431.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1167.9" y1="1831.0" x2="1167.0" y2="1558.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2118.2" y1="1431.1" x2="2088.4" y2="1251.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2088.4" y1="1251.5" x2="2117.6" y2="1198.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1167.9" y1="1369.0" x2="1096.5" y2="1391.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1096.5" y1="1391.4" x2="1045.7" y2="1829.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1045.7" y1="1829.6" x2="994.9" y2="1349.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1641.0" y1="1754.7" x2="1750.9" y2="1753.2" stroke="#222240" stroke-width="0.5"/>
<line x1="994.9" y1="1349.3" x2="890.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="2117.6" y1="1198.6" x2="2117.6" y2="1114.0" stroke="#222240" stroke-width="0.5"/>
<line x1="890.0" y1="1600.0" x2="835.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="2275.3" y1="2065.1" x2="2026.3" y2="2235.2" stroke="#222240" stroke-width="0.5"/>
<line x1="2026.3" y1="2235.2" x2="1995.7" y2="2189.5" stroke="#222240" stroke-width="0.5"/>
<line x1="835.0" y1="1600.0" x2="780.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1995.7" y1="2189.5" x2="1965.0" y2="2143.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1965.0" y1="2143.9" x2="1934.4" y2="2098.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1934.4" y1="2098.2" x2="2062.3" y2="1888.6" stroke="#222240" stroke-width="0.5"/>
<line x1="2062.3" y1="1888.6" x2="2086.3" y2="1660.4" stroke="#222240" stroke-width="0.5"/>
<line x1="780.0" y1="1600.0" x2="842.2" y2="2037.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2086.3" y1="1660.4" x2="2034.5" y2="1620.8" stroke="#222240" stroke-width="0.5"/>
<line x1="842.2" y1="2037.5" x2="725.1" y2="1613.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1387.0" y1="1220.7" x2="1407.9" y2="1272.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1262.6" y1="1874.6" x2="1236.4" y2="1489.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1165.0" y1="1600.0" x2="1220.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="2030.6" y1="1662.0" x2="2045.8" y2="1396.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2034.5" y1="1579.5" x2="2084.3" y2="1525.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2045.8" y1="1396.5" x2="1977.1" y2="1383.2" stroke="#222240" stroke-width="0.5"/>
<line x1="2084.3" y1="1525.5" x2="2047.9" y2="1289.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2125.7" y1="1743.7" x2="2190.3" y2="1707.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2047.9" y1="1289.5" x2="2101.9" y2="1928.7" stroke="#222240" stroke-width="0.5"/>
<line x1="2101.9" y1="1928.7" x2="1674.1" y2="2139.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1977.1" y1="1383.2" x2="1922.0" y2="1398.3" stroke="#222240" stroke-width="0.5"/>
<line x1="2190.3" y1="1707.4" x2="2239.2" y2="1742.9" stroke="#222240" stroke-width="0.5"/>
<line x1="2239.2" y1="1742.9" x2="1349.9" y2="994.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1877.1" y1="1430.2" x2="1900.8" y2="1367.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1900.8" y1="1367.8" x2="1979.2" y2="1624.9" stroke="#222240" stroke-width="0.5"/>
<line x1="2089.9" y1="1592.8" x2="2144.8" y2="1586.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1674.1" y1="2139.9" x2="1670.5" y2="2084.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1349.9" y1="994.6" x2="1397.8" y2="1035.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1397.8" y1="1035.1" x2="1445.4" y2="1077.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2144.8" y1="1586.9" x2="2185.6" y2="1469.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1979.2" y1="1624.9" x2="1916.0" y2="1675.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1670.5" y1="2084.9" x2="1600.0" y2="2035.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1445.4" y1="1077.4" x2="1463.7" y2="1129.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1916.0" y1="1675.9" x2="1867.7" y2="1635.2" stroke="#222240" stroke-width="0.5"/>
<line x1="2022.8" y1="1497.9" x2="2022.7" y2="1702.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1924.0" y1="1574.5" x2="1966.6" y2="1499.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1966.6" y1="1499.9" x2="1996.0" y2="1419.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1996.0" y1="1419.9" x2="1972.7" y2="1674.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1972.7" y1="1674.1" x2="2011.0" y2="1742.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1877.1" y1="1769.8" x2="1849.4" y2="1703.3" stroke="#222240" stroke-width="0.5"/>
<line x1="2011.0" y1="1742.6" x2="2050.8" y2="1792.0" stroke="#222240" stroke-width="0.5"/>
<line x1="2050.8" y1="1792.0" x2="2069.5" y2="1459.7" stroke="#222240" stroke-width="0.5"/>
<line x1="2185.6" y1="1469.1" x2="2239.2" y2="1457.1" stroke="#222240" stroke-width="0.5"/>
<line x1="2069.5" y1="1459.7" x2="2011.3" y2="1458.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.0" y1="1578.8" x2="1849.4" y2="1496.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1849.4" y1="1496.7" x2="1916.0" y2="1524.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1229.1" y1="1827.3" x2="1131.1" y2="1457.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1965.9" y1="1835.2" x2="2019.4" y2="1853.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2019.4" y1="1853.4" x2="1939.7" y2="1173.8" stroke="#222240" stroke-width="0.5"/>
<line x1="2239.2" y1="1457.1" x2="2304.4" y2="1511.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1939.7" y1="1173.8" x2="1972.9" y2="1282.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1974.6" y1="1536.2" x2="2030.6" y2="1538.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2034.5" y1="1620.8" x2="2073.2" y2="1727.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1972.9" y1="1282.1" x2="1928.8" y2="1315.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1930.4" y1="849.5" x2="1753.6" y2="738.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1463.7" y1="1129.4" x2="1466.0" y2="1186.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1954.8" y1="1348.3" x2="1940.2" y2="1430.6" stroke="#222240" stroke-width="0.5"/>
<line x1="2304.4" y1="1511.0" x2="2365.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="2365.0" y1="1600.0" x2="2388.9" y2="1376.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1466.0" y1="1186.2" x2="1482.9" y2="1238.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1928.8" y1="1315.1" x2="1876.7" y2="1339.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1753.6" y1="738.6" x2="1876.0" y2="2430.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1876.0" y1="2430.3" x2="2235.6" y2="2201.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2235.6" y1="2201.4" x2="2358.6" y2="2036.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1940.2" y1="1430.6" x2="1900.3" y2="1475.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1876.7" y1="1339.6" x2="1847.1" y2="1388.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1482.9" y1="1238.5" x2="1502.7" y2="1289.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1900.3" y1="1475.6" x2="1867.7" y2="1564.8" stroke="#222240" stroke-width="0.5"/>
<line x1="2358.6" y1="2036.1" x2="2295.6" y2="1069.2" stroke="#222240" stroke-width="0.5"/>
<line x1="2295.6" y1="1069.2" x2="2174.2" y2="939.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1564.8" x2="1924.0" y2="1625.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2388.9" y1="1376.1" x2="1934.4" y2="791.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1979.2" y1="1575.1" x2="1995.5" y2="1781.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1847.1" y1="1388.9" x2="1814.2" y2="1435.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.2" y1="1435.6" x2="1773.0" y2="1472.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1934.4" y1="791.4" x2="2450.3" y2="1393.7" stroke="#222240" stroke-width="0.5"/>
<line x1="2174.2" y1="939.8" x2="2468.1" y2="1490.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1502.7" y1="1289.9" x2="1516.0" y2="1343.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2468.1" y1="1490.0" x2="2133.2" y2="2293.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1995.5" y1="1781.1" x2="1885.7" y2="1850.6" stroke="#222240" stroke-width="0.5"/>
<line x1="2450.3" y1="1393.7" x2="2392.7" y2="1229.5" stroke="#222240" stroke-width="0.5"/>
<line x1="2073.2" y1="1727.2" x2="1826.7" y2="2095.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1131.1" y1="1457.8" x2="1096.5" y2="1808.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1885.7" y1="1850.6" x2="1847.1" y2="1811.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1167.0" y1="1641.5" x2="1221.2" y2="1289.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1826.7" y1="2095.6" x2="1464.0" y2="2070.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1996.0" y1="1419.9" x2="2013.4" y2="1337.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1516.0" y1="1343.4" x2="1545.5" y2="1392.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="2035.0" x2="1572.6" y2="1979.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1847.1" y1="1811.1" x2="1814.2" y2="1764.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1972.7" y1="1674.1" x2="1900.3" y2="1724.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1959.8" y1="2009.3" x2="1979.3" y2="1910.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1940.8" y1="1768.1" x2="1928.8" y2="1884.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1096.5" y1="1808.6" x2="1045.7" y2="1370.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1532.0" y1="2085.3" x2="1514.9" y2="2138.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1572.6" y1="1979.0" x2="1576.0" y2="1924.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.2" y1="1764.4" x2="1775.8" y2="1723.7" stroke="#222240" stroke-width="0.5"/>
<line x1="2392.7" y1="1229.5" x2="2469.6" y2="1697.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1561.2" y1="1444.8" x2="1584.3" y2="1385.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1584.3" y1="1385.6" x2="1610.6" y2="1330.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1578.8" y1="1869.2" x2="1600.0" y2="1815.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1639.2" y1="1277.4" x2="1674.0" y2="1340.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1514.9" y1="2138.3" x2="1506.3" y2="2192.6" stroke="#222240" stroke-width="0.5"/>
<line x1="725.1" y1="1613.1" x2="829.4" y2="1185.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1578.8" y1="1869.2" x2="1465.0" y2="1895.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1584.3" y1="1385.6" x2="1642.5" y2="1333.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1979.3" y1="1910.2" x2="1641.6" y2="2033.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1674.0" y1="1340.3" x2="1628.1" y2="1386.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1465.0" y1="1895.6" x2="1492.9" y2="1964.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1320.9" y1="1933.7" x2="1351.2" y2="1887.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1351.2" y1="1887.2" x2="1424.3" y2="1873.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1628.1" y1="1386.8" x2="1704.6" y2="1351.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1704.6" y1="1351.1" x2="1486.2" y2="1355.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1775.4" y1="1805.3" x2="1812.8" y2="1845.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1642.5" y1="1333.4" x2="1603.3" y2="1275.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1900.3" y1="1724.4" x2="1959.8" y2="1722.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.3" y1="1873.4" x2="1458.9" y2="1830.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1812.8" y1="1845.6" x2="1663.0" y2="1862.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1663.0" y1="1862.5" x2="1686.7" y2="1796.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1045.7" y1="1370.4" x2="994.9" y2="1850.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1508.4" y1="1911.8" x2="1496.7" y2="1849.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1686.7" y1="1796.7" x2="1703.3" y2="1849.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1603.3" y1="1275.0" x2="1518.8" y2="1228.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1518.8" y1="1228.8" x2="1535.6" y2="1281.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1506.3" y1="2192.6" x2="1497.7" y2="2247.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1496.7" y1="1849.4" x2="1424.6" y2="1805.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1535.6" y1="1281.4" x2="1578.6" y2="1330.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1703.3" y1="1849.4" x2="1775.7" y2="1873.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1827.3" y1="1970.9" x2="1848.8" y2="1887.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1775.7" y1="1873.4" x2="1805.4" y2="1919.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1578.6" y1="1330.9" x2="1508.5" y2="1405.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1458.9" y1="1830.2" x2="1492.5" y2="1786.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1508.5" y1="1405.4" x2="1546.9" y2="1335.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1741.1" y1="1830.2" x2="1537.0" y2="1862.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1497.7" y1="2247.0" x2="1489.1" y2="2301.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1546.9" y1="1335.3" x2="1761.3" y2="1383.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1704.6" y1="1351.1" x2="1677.8" y2="1284.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1882.5" y1="1930.8" x2="1751.4" y2="2066.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1677.8" y1="1284.4" x2="1569.3" y2="1276.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1784.6" y1="1332.5" x2="1836.9" y2="1302.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1751.4" y1="2066.0" x2="1558.5" y2="2033.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1558.5" y1="2033.0" x2="1654.1" y2="1976.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1654.1" y1="1976.1" x2="1646.3" y2="1921.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1836.9" y1="1302.9" x2="1841.7" y2="1238.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1646.3" y1="1921.7" x2="1621.2" y2="1869.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1621.2" y1="1869.2" x2="1691.6" y2="1911.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1761.3" y1="1383.4" x2="1682.3" y2="1401.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.6" y1="1805.3" x2="1387.2" y2="1845.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1387.2" y1="1845.6" x2="1394.6" y2="1919.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1761.3" y1="1383.4" x2="1730.9" y2="1429.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1733.8" y1="1365.5" x2="1715.2" y2="1296.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1841.7" y1="1238.3" x2="1351.8" y2="1242.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1394.6" y1="1919.7" x2="1372.7" y2="1970.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1715.2" y1="1296.1" x2="1684.6" y2="1229.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1691.6" y1="1911.8" x2="1707.1" y2="1964.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1351.8" y1="1242.8" x2="1398.5" y2="1153.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1663.0" y1="1862.5" x2="1542.3" y2="1919.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1351.8" y1="1242.8" x2="1363.1" y2="1302.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1609.7" y1="1979.9" x2="1477.0" y2="2017.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1363.1" y1="1302.9" x2="1440.3" y2="1316.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1470.8" y1="1301.8" x2="1458.0" y2="1370.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1805.4" y1="1919.7" x2="1766.5" y2="2001.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1458.0" y1="1370.4" x2="1469.1" y2="1429.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1621.2" y1="1869.2" x2="1735.0" y2="1895.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1786.4" y1="1404.7" x2="1751.0" y2="1312.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1398.5" y1="1153.4" x2="1603.1" y2="1055.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1440.8" y1="1255.0" x2="1515.1" y2="1173.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1515.1" y1="1173.4" x2="1787.5" y2="1147.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1469.1" y1="1429.4" x2="1407.5" y2="1410.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1707.1" y1="1964.6" x2="1701.5" y2="2023.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1440.3" y1="1316.9" x2="1431.6" y2="1389.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1431.6" y1="1389.0" x2="1411.6" y2="1335.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1407.5" y1="1410.7" x2="1384.5" y2="1356.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1603.1" y1="1055.0" x2="1633.7" y2="1000.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1633.7" y1="1000.9" x2="1631.5" y2="945.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1411.6" y1="1335.2" x2="1815.5" y2="1356.7" stroke="#222240" stroke-width="0.5"/>
<line x1="2469.6" y1="1697.3" x2="2047.0" y2="847.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1220.0" x2="1684.9" y2="1173.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1735.0" y1="1895.6" x2="1757.9" y2="1945.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1558.5" y1="2033.0" x2="1601.3" y2="2090.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1766.5" y1="2001.9" x2="1888.0" y2="1996.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1477.0" y1="2017.2" x2="1398.8" y2="2046.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1751.0" y1="1312.2" x2="1764.9" y2="1257.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1609.7" y1="1979.9" x2="1433.5" y2="2001.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1631.5" y1="945.8" x2="1600.0" y2="890.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.3" y1="1873.4" x2="1442.1" y2="1945.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1372.7" y1="1970.9" x2="1312.0" y2="1996.4" stroke="#222240" stroke-width="0.5"/>
<line x1="2133.2" y1="2293.8" x2="2450.6" y2="1805.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1306.3" y1="1841.1" x2="1177.0" y2="1498.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1306.3" y1="1841.1" x2="1290.9" y2="1499.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1306.3" y1="1841.1" x2="1264.9" y2="1420.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1815.0" x2="1663.0" y2="1862.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1815.0" x2="1621.2" y2="1869.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1815.0" x2="1537.0" y2="1862.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1815.0" x2="1496.7" y2="1849.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1758.5" y1="1621.8" x2="1808.0" y2="1654.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1561.2" y1="1444.8" x2="1508.5" y2="1405.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1561.2" y1="1444.8" x2="1469.1" y2="1429.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1561.2" y1="1444.8" x2="1628.1" y2="1386.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1561.2" y1="1444.8" x2="1682.3" y2="1401.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1940.8" y1="1768.1" x2="1877.1" y2="1769.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1940.8" y1="1768.1" x2="2030.6" y2="1538.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1469.1" y1="1429.4" x2="1431.6" y2="1389.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1469.1" y1="1429.4" x2="1486.2" y2="1355.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1264.9" y2="1420.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1306.3" y2="1841.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1381.6" y2="1441.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1236.4" y2="1489.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.6" y1="1805.3" x2="1542.3" y2="1919.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.6" y1="1805.3" x2="1424.3" y2="1873.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.6" y1="1805.3" x2="1492.5" y2="1786.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1600.0" x2="1647.7" y2="1693.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1600.0" y1="1600.0" x2="1647.7" y2="1506.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1635.2" x2="1924.0" y2="1625.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1635.2" x2="1814.0" y2="1578.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1635.2" x2="1900.3" y2="1724.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1635.2" x2="1916.0" y2="1524.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1649.4" y1="1809.2" x2="1795.0" y2="1690.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1877.1" y1="1430.2" x2="1849.4" y2="1496.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1642.5" y1="1333.4" x2="1569.3" y2="1276.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1848.8" y1="1887.2" x2="1812.8" y2="1845.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1610.6" y1="1330.2" x2="1704.6" y2="1351.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1641.6" y1="2033.0" x2="1707.1" y2="1964.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1465.0" y1="1895.6" x2="1424.6" y2="1805.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1677.8" y1="1284.4" x2="1600.0" y2="1220.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1646.3" y1="1921.7" x2="1578.8" y2="1869.2" stroke="#222240" stroke-width="0.5"/>
<line x1="2022.7" y1="1702.7" x2="1966.6" y2="1499.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1867.7" y1="1564.8" x2="1814.0" y2="1578.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1647.7" y1="1693.6" x2="1591.2" y2="1759.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1652.1" y1="1448.7" x2="1698.0" y2="1562.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1641.0" y1="1754.7" x2="1758.4" y2="1577.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1808.0" y1="1654.5" x2="1746.1" y2="1665.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1795.0" y1="1690.5" x2="1814.3" y2="1616.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1607.6" y1="1440.2" x2="1647.7" y2="1506.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1720.9" y1="1777.8" x2="1721.5" y2="1704.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1691.6" y1="1468.8" x2="1793.1" y2="1505.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1698.0" y1="1637.6" x2="1561.2" y2="1444.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1685.6" y1="1735.2" x2="1730.9" y2="1429.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1691.6" y1="1468.8" x2="1686.7" y2="1796.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1746.1" y1="1665.2" x2="1492.5" y2="1786.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1723.7" y1="1498.5" x2="1773.0" y2="1472.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1758.4" y1="1577.6" x2="1814.0" y2="1578.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1440.3" y1="1316.9" x2="1407.9" y2="1272.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1275.0" y1="1600.0" x2="1220.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1900.3" y1="1475.6" x2="1955.1" y2="1464.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1628.1" y1="1386.8" x2="1401.4" y2="1682.3" stroke="#222240" stroke-width="0.5"/>
<line x1="1290.9" y1="1499.6" x2="1351.2" y2="1887.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1795.0" y1="1690.5" x2="1698.0" y2="1562.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1795.0" y1="1690.5" x2="1721.5" y2="1704.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1795.0" y1="1690.5" x2="1698.0" y2="1637.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1698.0" y1="1562.4" x2="1652.1" y2="1448.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1698.0" y1="1562.4" x2="1750.9" y2="1753.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1698.0" y1="1562.4" x2="1691.6" y2="1468.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1649.4" y1="1809.2" x2="1808.0" y2="1654.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1649.4" y1="1809.2" x2="1641.0" y2="1754.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1647.7" y1="1693.6" x2="1814.3" y2="1616.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1808.0" y1="1654.5" x2="1720.9" y2="1777.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1641.0" y1="1754.7" x2="1758.5" y2="1621.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1746.1" y1="1665.2" x2="1758.4" y2="1577.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1721.5" y1="1704.1" x2="1746.5" y2="1535.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1691.6" y1="1468.8" x2="1685.6" y2="1735.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1793.1" y1="1505.4" x2="1746.1" y2="1665.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1591.2" y1="1759.8" x2="1652.1" y2="1448.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.3" y1="1616.9" x2="1758.5" y2="1621.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1492.5" y1="1786.2" x2="1492.9" y2="1964.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1746.1" y1="1665.2" x2="1721.5" y2="1704.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1264.9" y1="1420.9" x2="1167.9" y2="1831.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1621.2" y1="1869.2" x2="1558.5" y2="2033.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1814.3" y1="1616.9" x2="1647.7" y2="1506.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1424.3" y1="1873.4" x2="1492.9" y2="1964.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1691.6" y1="1468.8" x2="1698.0" y2="1637.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1578.8" y1="1869.2" x2="1558.5" y2="2033.0" stroke="#222240" stroke-width="0.5"/>
<line x1="1641.0" y1="1754.7" x2="1698.0" y2="1637.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1545.5" y1="1392.0" x2="1561.2" y2="1444.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1464.0" y1="2070.8" x2="1517.3" y2="2027.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1532.0" y1="2085.3" x2="1517.3" y2="2027.1" stroke="#222240" stroke-width="0.5"/>
<line x1="2275.3" y1="2065.1" x2="2087.7" y2="1010.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1930.4" y1="849.5" x2="2087.7" y2="1010.6" stroke="#222240" stroke-width="0.5"/>
<line x1="2117.6" y1="1114.0" x2="2087.7" y2="1010.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1576.0" y1="1924.1" x2="1578.8" y2="1869.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1922.0" y1="1398.3" x2="1877.1" y2="1430.2" stroke="#222240" stroke-width="0.5"/>
<line x1="1535.7" y1="1974.5" x2="1517.3" y2="2027.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1965.9" y1="1835.2" x2="1940.8" y2="1768.1" stroke="#222240" stroke-width="0.5"/>
<line x1="1535.7" y1="1974.5" x2="1542.3" y2="1919.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1979.2" y1="1575.1" x2="1924.0" y2="1625.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1733.8" y1="1365.5" x2="1682.3" y2="1401.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1610.1" y1="1924.8" x2="1609.7" y2="1979.9" stroke="#222240" stroke-width="0.5"/>
<line x1="1610.1" y1="1924.8" x2="1537.0" y2="1862.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1167.9" y1="1369.0" x2="1167.0" y2="1641.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1916.0" y1="1811.1" x2="1877.1" y2="1769.8" stroke="#222240" stroke-width="0.5"/>
<line x1="1916.0" y1="1811.1" x2="2022.7" y2="1702.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1786.4" y1="1404.7" x2="1730.9" y2="1429.4" stroke="#222240" stroke-width="0.5"/>
<line x1="1264.9" y1="1779.1" x2="1290.9" y2="1499.6" stroke="#222240" stroke-width="0.5"/>
<line x1="1229.1" y1="1827.3" x2="1236.4" y2="1489.7" stroke="#222240" stroke-width="0.5"/>
<line x1="1440.8" y1="1255.0" x2="1569.3" y2="1276.5" stroke="#222240" stroke-width="0.5"/>
<line x1="1495.0" y1="1600.0" x2="1600.0" y2="1600.0" stroke="#222240" stroke-width="0.5"/>
<circle cx="1495.0" cy="1600.0" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1502.0" y="1603.0" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Sol</text>
<circle cx="1600.0" cy="1600.0" r="8" fill="#FFD700" opacity="1.0"/>
<text x="1610.0" y="1603.0" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Tau Ceti</text>
<circle cx="1757.9" cy="1945.7" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1337.1" cy="1791.0" r="3" fill="#FF8800" opacity="0.85"/>
<circle cx="1535.7" cy="1974.5" r="2" fill="#FF4444" opacity="0.85"/>
<circle cx="1916.0" cy="1675.9" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="1784.6" cy="1332.5" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1236.4" cy="1489.7" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1492.5" cy="1786.2" r="3" fill="#FF4444" opacity="0.85"/>
<text x="1497.5" y="1789.2" fill="#FF4444" font-size="7" font-family="monospace" opacity="1.00">GJ 1156</text>
<circle cx="1469.1" cy="1429.4" r="3" fill="#4488FF" opacity="0.4"/>
<text x="1474.1" y="1432.4" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.60">Wolf 359</text>
<circle cx="1698.0" cy="1637.6" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1705.0" y="1640.6" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">ACB</text>
<circle cx="1407.9" cy="1272.1" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="2144.8" cy="1586.9" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1558.5" cy="2033.0" r="2" fill="#FF4444" opacity="0.4"/>
<text x="1562.5" y="2036.0" fill="#FF4444" font-size="7" font-family="monospace" opacity="0.60">GJ 393</text>
<circle cx="1647.7" cy="1506.4" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1654.7" y="1509.4" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Ran</text>
<circle cx="1508.5" cy="1405.4" r="3" fill="#4488FF" opacity="0.7"/>
<text x="1513.5" y="1408.4" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.90">Guniibuu</text>
<circle cx="1464.0" cy="2070.8" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1715.2" cy="1296.1" r="3" fill="#4488FF" opacity="0.55"/>
<circle cx="1343.2" cy="1516.6" r="3" fill="#FF8800" opacity="0.85"/>
<circle cx="1096.5" cy="1391.4" r="2" fill="#FF8800" opacity="0.4"/>
<circle cx="1262.6" cy="1874.6" r="2" fill="#FF8800" opacity="1.0"/>
<circle cx="1979.2" cy="1575.1" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="1411.6" cy="1335.2" r="3" fill="#4488FF" opacity="0.55"/>
<circle cx="1633.7" cy="1000.9" r="2" fill="#4488FF" opacity="0.55"/>
<circle cx="1733.8" cy="1365.5" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1492.9" cy="1964.6" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="2030.6" cy="1538.4" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="1746.1" cy="1665.2" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1753.1" y="1668.2" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Tessera</text>
<circle cx="1351.8" cy="1242.8" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1508.4" cy="1911.8" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1167.9" cy="1831.0" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1610.1" cy="1924.8" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1751.0" cy="1312.2" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1407.5" cy="1410.7" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1198.1" cy="1766.5" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1096.5" cy="1808.6" r="2" fill="#FF8800" opacity="1.0"/>
<circle cx="1177.0" cy="1701.5" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="1746.5" cy="1535.6" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1753.5" y="1538.6" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Keid</text>
<circle cx="994.9" cy="1850.7" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1900.3" cy="1475.6" r="3" fill="#44DD44" opacity="0.7"/>
<circle cx="1610.6" cy="1330.2" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1751.4" cy="2066.0" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1977.1" cy="1383.2" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="2062.3" cy="1888.6" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1330.0" cy="1600.0" r="3" fill="#FF8800" opacity="0.55"/>
<circle cx="1888.0" cy="1996.4" r="2" fill="#FF4444" opacity="0.55"/>
<circle cx="1674.0" cy="1340.3" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1758.4" cy="1577.6" r="5" fill="#FFD700" opacity="0.55"/>
<text x="1765.4" y="1580.6" fill="#FFD700" font-size="9" font-family="monospace" opacity="0.75">Parallax</text>
<circle cx="1972.7" cy="1674.1" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="2239.2" cy="1457.1" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1639.2" cy="1277.4" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1877.1" cy="1430.2" r="3" fill="#44DD44" opacity="0.55"/>
<circle cx="1264.9" cy="1420.9" r="2" fill="#FF8800" opacity="0.55"/>
<text x="1268.9" y="1423.9" fill="#FF8800" font-size="7" font-family="monospace" opacity="0.75">GJ 357</text>
<circle cx="1290.9" cy="1700.4" r="3" fill="#FF8800" opacity="0.55"/>
<circle cx="1814.0" cy="1578.8" r="3" fill="#44DD44" opacity="0.55"/>
<text x="1819.0" y="1581.8" fill="#44DD44" font-size="7" font-family="monospace" opacity="0.75">GJ 34B</text>
<circle cx="1654.1" cy="1976.1" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1974.6" cy="1536.2" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1805.4" cy="1919.7" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1815.5" cy="1356.7" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1996.0" cy="1419.9" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="2069.5" cy="1459.7" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="1621.2" cy="1869.2" r="3" fill="#FF4444" opacity="0.7"/>
<text x="1626.2" y="1872.2" fill="#FF4444" font-size="7" font-family="monospace" opacity="0.90">GJ 1111</text>
<circle cx="1885.7" cy="1850.6" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2087.7" cy="1010.6" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1966.6" cy="1499.9" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1684.6" cy="1229.5" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="1965.9" cy="1835.2" r="2" fill="#44DD44" opacity="0.4"/>
<circle cx="1698.0" cy="1562.4" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1705.0" y="1565.4" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Sirius</text>
<circle cx="1900.8" cy="1367.8" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="1349.9" cy="994.6" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1764.9" cy="1257.6" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1954.8" cy="1348.3" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="1703.3" cy="1849.4" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1955.1" cy="1464.6" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1793.1" cy="1505.4" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1800.1" y="1508.4" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Lacaille</text>
<circle cx="1569.3" cy="1276.5" r="3" fill="#4488FF" opacity="0.4"/>
<circle cx="1939.7" cy="1173.8" r="2" fill="#44DD44" opacity="0.25"/>
<circle cx="1773.0" cy="1472.4" r="3" fill="#44DD44" opacity="0.4"/>
<text x="1778.0" y="1475.4" fill="#44DD44" font-size="7" font-family="monospace" opacity="0.60">EZ Aqr</text>
<circle cx="1506.3" cy="2192.6" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1670.5" cy="2084.9" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1440.3" cy="1316.9" r="3" fill="#4488FF" opacity="0.55"/>
<circle cx="1431.6" cy="1389.0" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1827.3" cy="1970.9" r="2" fill="#FF4444" opacity="0.85"/>
<circle cx="890.0" cy="1600.0" r="2" fill="#FF8800" opacity="0.25"/>
<circle cx="1934.4" cy="791.4" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1877.1" cy="1769.8" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="1131.1" cy="1742.2" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1775.4" cy="1805.3" r="3" fill="#FF4444" opacity="0.55"/>
<circle cx="1045.7" cy="1829.6" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="2185.6" cy="1469.1" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1686.7" cy="1796.7" r="3" fill="#FF4444" opacity="1.0"/>
<text x="1691.7" y="1799.7" fill="#FF4444" font-size="7" font-family="monospace" opacity="1.00">Altair</text>
<circle cx="1647.7" cy="1693.6" r="5" fill="#FFD700" opacity="0.4"/>
<text x="1654.7" y="1696.6" fill="#FFD700" font-size="9" font-family="monospace" opacity="0.60">Struve</text>
<circle cx="1979.3" cy="1910.2" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1721.5" cy="1704.1" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1728.5" y="1707.1" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Proxima Centauri</text>
<circle cx="1477.0" cy="2017.2" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1928.8" cy="1884.9" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2034.5" cy="1620.8" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1546.9" cy="1335.3" r="3" fill="#4488FF" opacity="0.4"/>
<circle cx="1959.8" cy="1722.1" r="2" fill="#44DD44" opacity="0.4"/>
<circle cx="1603.1" cy="1055.0" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="1601.3" cy="2090.0" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="2073.2" cy="1727.2" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1609.7" cy="1979.9" r="2" fill="#FF4444" opacity="0.55"/>
<circle cx="1458.9" cy="1830.2" r="3" fill="#FF4444" opacity="0.25"/>
<circle cx="1384.5" cy="1356.7" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1674.1" cy="2139.9" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1584.3" cy="1385.6" r="3" fill="#4488FF" opacity="0.55"/>
<text x="1589.3" y="1388.6" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.75">Achird</text>
<circle cx="2089.9" cy="1592.8" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="1940.2" cy="1430.6" r="2" fill="#44DD44" opacity="0.25"/>
<circle cx="1847.1" cy="1811.1" r="3" fill="#44DD44" opacity="0.55"/>
<circle cx="1600.0" cy="1815.0" r="3" fill="#FF4444" opacity="0.55"/>
<text x="1605.0" y="1818.0" fill="#FF4444" font-size="7" font-family="monospace" opacity="0.75">Lalande 21185</text>
<circle cx="1814.3" cy="1616.9" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1821.3" y="1619.9" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Nova Roma</text>
<circle cx="1535.6" cy="1281.4" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1424.3" cy="1873.4" r="3" fill="#FF4444" opacity="0.25"/>
<text x="1429.3" y="1876.4" fill="#FF4444" font-size="7" font-family="monospace" opacity="0.45">GJ 388</text>
<circle cx="1591.2" cy="1759.8" r="5" fill="#FFD700" opacity="0.4"/>
<text x="1598.2" y="1762.8" fill="#FFD700" font-size="9" font-family="monospace" opacity="0.60">Meridian</text>
<circle cx="2235.6" cy="2201.4" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="994.9" cy="1349.3" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="2388.9" cy="1376.1" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1720.9" cy="1777.8" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1727.9" y="1780.8" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Ross 128</text>
<circle cx="1685.6" cy="1735.2" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1692.6" y="1738.2" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Barnard's Star</text>
<circle cx="1691.6" cy="1468.8" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1698.6" y="1471.8" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Cygni B</text>
<circle cx="1995.5" cy="1781.1" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2365.0" cy="1600.0" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1701.5" cy="2023.0" r="2" fill="#FF4444" opacity="0.25"/>
<circle cx="2117.6" cy="1198.6" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1814.2" cy="1764.4" r="3" fill="#44DD44" opacity="0.25"/>
<circle cx="1165.0" cy="1600.0" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1642.5" cy="1333.4" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1381.6" cy="1758.7" r="3" fill="#FF8800" opacity="0.7"/>
<circle cx="1545.5" cy="1392.0" r="3" fill="#AA44FF" opacity="0.4"/>
<text x="1550.5" y="1395.0" fill="#AA44FF" font-size="7" font-family="monospace" opacity="0.60">GJ 892</text>
<circle cx="2392.7" cy="1229.5" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="2011.0" cy="1742.6" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1841.7" cy="1238.3" r="2" fill="#4488FF" opacity="0.55"/>
<circle cx="1775.7" cy="1873.4" r="3" fill="#FF4444" opacity="0.25"/>
<circle cx="2034.5" cy="1579.5" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1578.8" cy="1869.2" r="3" fill="#FF4444" opacity="0.7"/>
<text x="1583.8" y="1872.2" fill="#FF4444" font-size="7" font-family="monospace" opacity="0.90">GJ 54.1</text>
<circle cx="1442.1" cy="1945.7" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1532.0" cy="2085.3" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1826.7" cy="2095.6" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1641.0" cy="1754.7" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1648.0" y="1757.7" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Renaissance</text>
<circle cx="1167.0" cy="1558.5" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1995.7" cy="2189.5" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1398.8" cy="2046.8" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1445.4" cy="1077.4" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1381.6" cy="1441.3" r="3" fill="#FF8800" opacity="0.55"/>
<circle cx="1922.0" cy="1398.3" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="2047.9" cy="1289.5" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1965.0" cy="2143.9" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1433.5" cy="2001.9" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="2011.3" cy="1458.3" r="2" fill="#44DD44" opacity="0.4"/>
<circle cx="2358.6" cy="2036.1" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1131.1" cy="1457.8" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="1470.8" cy="1301.8" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1735.0" cy="1895.6" r="3" fill="#FF4444" opacity="0.85"/>
<circle cx="1463.7" cy="1129.4" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1045.7" cy="1370.4" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1320.9" cy="1933.7" r="2" fill="#FF4444" opacity="0.55"/>
<circle cx="1306.3" cy="1358.9" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1753.6" cy="738.6" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="2133.2" cy="2293.8" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="1847.1" cy="1388.9" r="3" fill="#44DD44" opacity="0.7"/>
<circle cx="1401.4" cy="1682.3" r="3" fill="#FF8800" opacity="0.4"/>
<text x="1406.4" y="1685.3" fill="#FF8800" font-size="7" font-family="monospace" opacity="0.60">Ross 154</text>
<circle cx="1372.7" cy="1970.9" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1397.8" cy="1035.1" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="1561.2" cy="1444.8" r="3" fill="#4488FF" opacity="0.25"/>
<text x="1566.2" y="1447.8" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.45">Cairn</text>
<circle cx="1707.1" cy="1964.6" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1928.8" cy="1315.1" r="2" fill="#44DD44" opacity="0.85"/>
<circle cx="780.0" cy="1600.0" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1758.5" cy="1621.8" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1765.5" y="1624.8" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Vargr</text>
<circle cx="1387.2" cy="1845.6" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1221.8" cy="1562.8" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="1761.3" cy="1383.4" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1167.9" cy="1369.0" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1516.0" cy="1343.4" r="3" fill="#AA44FF" opacity="0.4"/>
<circle cx="1646.3" cy="1921.7" r="3" fill="#FF4444" opacity="0.55"/>
<circle cx="1876.7" cy="1339.6" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1600.0" cy="890.0" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="2125.7" cy="1743.7" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1691.6" cy="1911.8" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1229.1" cy="1372.7" r="2" fill="#FF8800" opacity="0.4"/>
<circle cx="1576.0" cy="1924.1" r="3" fill="#AA44FF" opacity="0.7"/>
<circle cx="1750.9" cy="1753.2" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1757.9" y="1756.2" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Arbour</text>
<circle cx="1198.1" cy="1433.5" r="2" fill="#FF8800" opacity="1.0"/>
<circle cx="1704.6" cy="1351.1" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1466.0" cy="1186.2" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1940.8" cy="1768.1" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1401.4" cy="1517.7" r="3" fill="#FF8800" opacity="0.7"/>
<text x="1406.4" y="1520.7" fill="#FF8800" font-size="7" font-family="monospace" opacity="0.90">GJ 664</text>
<circle cx="1537.0" cy="1862.5" r="3" fill="#FF4444" opacity="0.85"/>
<circle cx="1518.8" cy="1228.8" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="1269.2" cy="1317.5" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1876.0" cy="2430.3" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1458.0" cy="1370.4" r="3" fill="#4488FF" opacity="0.55"/>
<circle cx="1394.6" cy="1919.7" r="2" fill="#FF4444" opacity="0.85"/>
<circle cx="1972.9" cy="1282.1" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2239.2" cy="1742.9" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1306.3" cy="1841.1" r="2" fill="#FF8800" opacity="0.25"/>
<circle cx="1486.2" cy="1355.1" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="1497.7" cy="2247.0" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1603.3" cy="1275.0" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1849.4" cy="1496.7" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="1496.7" cy="1849.4" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1578.6" cy="1330.9" r="3" fill="#4488FF" opacity="0.7"/>
<circle cx="1641.6" cy="2033.0" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="1600.0" cy="1220.0" r="2" fill="#4488FF" opacity="1.0"/>
<circle cx="1398.5" cy="1153.4" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="2450.6" cy="1805.2" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1489.1" cy="2301.3" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1979.2" cy="1624.9" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2190.3" cy="1707.4" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1812.8" cy="1845.6" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="1482.9" cy="1238.5" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="2019.4" cy="1853.4" r="2" fill="#44DD44" opacity="0.4"/>
<circle cx="1424.6" cy="1805.3" r="3" fill="#FF4444" opacity="0.85"/>
<text x="1429.6" y="1808.3" fill="#FF4444" font-size="7" font-family="monospace" opacity="1.00">GJ 566B</text>
<circle cx="1652.1" cy="1448.7" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1659.1" y="1451.7" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Groombridge</text>
<circle cx="2101.9" cy="1928.7" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="2295.6" cy="1069.2" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1916.0" cy="1811.1" r="2" fill="#44DD44" opacity="0.55"/>
<circle cx="1337.1" cy="1409.0" r="3" fill="#FF8800" opacity="0.7"/>
<circle cx="2450.3" cy="1393.7" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1848.8" cy="1887.2" r="2" fill="#FF4444" opacity="0.4"/>
<circle cx="1220.0" cy="1600.0" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="2026.3" cy="2235.2" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1343.2" cy="1683.4" r="3" fill="#FF8800" opacity="0.85"/>
<circle cx="1290.4" cy="1905.5" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="2086.3" cy="1660.4" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1275.0" cy="1600.0" r="3" fill="#FF8800" opacity="0.85"/>
<text x="1280.0" y="1603.0" fill="#FF8800" font-size="7" font-family="monospace" opacity="1.00">GJ 832</text>
<circle cx="2088.4" cy="1251.5" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1177.0" cy="1498.5" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1867.7" cy="1564.8" r="3" fill="#44DD44" opacity="0.4"/>
<circle cx="1849.4" cy="1703.3" r="3" fill="#44DD44" opacity="0.55"/>
<circle cx="1514.9" cy="2138.3" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1515.1" cy="1173.4" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1167.0" cy="1641.5" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="1572.6" cy="1979.0" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="1924.0" cy="1574.5" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="1795.0" cy="1690.5" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1802.0" y="1693.5" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Bastion</text>
<circle cx="1867.7" cy="1635.2" r="3" fill="#44DD44" opacity="0.7"/>
<text x="1872.7" y="1638.2" fill="#44DD44" font-size="7" font-family="monospace" opacity="0.90">GJ 566A</text>
<circle cx="1959.8" cy="2009.3" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1766.5" cy="2001.9" r="2" fill="#FF4444" opacity="0.25"/>
<circle cx="1628.1" cy="1386.8" r="3" fill="#4488FF" opacity="0.55"/>
<text x="1633.1" y="1389.8" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.75">GJ 661A</text>
<circle cx="1787.5" cy="1147.3" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1786.4" cy="1404.7" r="3" fill="#4488FF" opacity="0.4"/>
<circle cx="2275.3" cy="2065.1" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1363.1" cy="1302.9" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="2050.8" cy="1792.0" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1112.4" cy="1552.0" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="2469.6" cy="1697.3" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="1542.3" cy="1919.8" r="3" fill="#FF4444" opacity="0.85"/>
<circle cx="1775.8" cy="1723.7" r="3" fill="#44DD44" opacity="0.55"/>
<text x="1780.8" y="1726.7" fill="#44DD44" font-size="7" font-family="monospace" opacity="0.75">GJ 4274</text>
<circle cx="1741.1" cy="1830.2" r="3" fill="#FF4444" opacity="0.7"/>
<circle cx="2022.8" cy="1497.9" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1677.8" cy="1284.4" r="3" fill="#4488FF" opacity="0.85"/>
<circle cx="2047.0" cy="847.8" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1808.0" cy="1654.5" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1815.0" y="1657.5" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Kensho</text>
<circle cx="1290.9" cy="1499.6" r="3" fill="#FF8800" opacity="0.7"/>
<circle cx="2030.6" cy="1662.0" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1502.7" cy="1289.9" r="3" fill="#AA44FF" opacity="0.55"/>
<circle cx="1264.9" cy="1779.1" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="2118.2" cy="1431.1" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1465.0" cy="1895.6" r="3" fill="#FF4444" opacity="0.25"/>
<circle cx="829.4" cy="1185.4" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1221.8" cy="1637.2" r="2" fill="#FF8800" opacity="0.4"/>
<circle cx="2468.1" cy="1490.0" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1649.4" cy="1809.2" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1656.4" y="1812.2" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Aurelius</text>
<circle cx="1221.2" cy="1289.1" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1723.7" cy="1498.5" r="3" fill="#44DD44" opacity="0.25"/>
<text x="1728.7" y="1501.5" fill="#44DD44" font-size="7" font-family="monospace" opacity="0.45">1221-DXP9</text>
<circle cx="1730.9" cy="1429.4" r="3" fill="#4488FF" opacity="0.7"/>
<text x="1735.9" y="1432.4" fill="#4488FF" font-size="7" font-family="monospace" opacity="0.90">82 G. Eri</text>
<circle cx="1112.4" cy="1648.0" r="2" fill="#FF8800" opacity="0.4"/>
<circle cx="1836.9" cy="1302.9" r="2" fill="#4488FF" opacity="0.85"/>
<circle cx="1236.4" cy="1710.3" r="2" fill="#FF8800" opacity="0.55"/>
<circle cx="1312.0" cy="1996.4" r="2" fill="#FF4444" opacity="0.4"/>
<circle cx="2045.8" cy="1396.5" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1600.0" cy="2035.0" r="2" fill="#AA44FF" opacity="0.25"/>
<circle cx="1682.3" cy="1401.4" r="3" fill="#4488FF" opacity="0.85"/>
<text x="1687.3" y="1404.4" fill="#4488FF" font-size="7" font-family="monospace" opacity="1.00">GJ 780</text>
<circle cx="1229.1" cy="1827.3" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1814.2" cy="1435.6" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="1440.8" cy="1255.0" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1882.5" cy="1930.8" r="2" fill="#FF4444" opacity="0.55"/>
<circle cx="1221.2" cy="1910.9" r="2" fill="#FF8800" opacity="0.7"/>
<circle cx="1806.8" cy="1541.3" r="5" fill="#FFD700" opacity="0.85"/>
<text x="1813.8" y="1544.3" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Lu Ban</text>
<circle cx="1934.4" cy="2098.2" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="2013.4" cy="1337.0" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="1663.0" cy="1862.5" r="3" fill="#FF4444" opacity="0.25"/>
<circle cx="1387.0" cy="1220.7" r="2" fill="#AA44FF" opacity="0.4"/>
<circle cx="1930.4" cy="849.5" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1517.3" cy="2027.1" r="2" fill="#AA44FF" opacity="0.85"/>
<circle cx="835.0" cy="1600.0" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="1684.9" cy="1173.4" r="2" fill="#4488FF" opacity="0.7"/>
<circle cx="1351.2" cy="1887.2" r="2" fill="#FF4444" opacity="0.7"/>
<circle cx="2022.7" cy="1702.7" r="2" fill="#44DD44" opacity="0.7"/>
<circle cx="2084.3" cy="1525.5" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1631.5" cy="945.8" r="2" fill="#4488FF" opacity="0.55"/>
<circle cx="2304.4" cy="1511.0" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="725.1" cy="1613.1" r="2" fill="#FF8800" opacity="0.4"/>
<circle cx="1916.0" cy="1524.1" r="3" fill="#44DD44" opacity="0.7"/>
<circle cx="842.2" cy="2037.5" r="2" fill="#FF8800" opacity="0.85"/>
<circle cx="2117.6" cy="1114.0" r="2" fill="#AA44FF" opacity="0.7"/>
<circle cx="1607.6" cy="1440.2" r="5" fill="#FFD700" opacity="1.0"/>
<text x="1614.6" y="1443.2" fill="#FFD700" font-size="9" font-family="monospace" opacity="1.00">Prometheus</text>
<circle cx="1924.0" cy="1625.5" r="3" fill="#44DD44" opacity="0.85"/>
<circle cx="2174.2" cy="939.8" r="2" fill="#AA44FF" opacity="0.55"/>
<circle cx="1900.3" cy="1724.4" r="3" fill="#44DD44" opacity="1.0"/>
<text x="30" y="28" fill="#999" font-size="16" font-family="monospace" font-weight="bold">THE SETTLED REACH</text>
<circle cx="35" cy="48" r="5" fill="#FFD700"/>
<text x="46" y="52" fill="#FFD700" font-size="10" font-family="monospace">core</text>
<circle cx="35" cy="68" r="5" fill="#4488FF"/>
<text x="46" y="72" fill="#4488FF" font-size="10" font-family="monospace">north_reach</text>
<circle cx="35" cy="88" r="5" fill="#FF4444"/>
<text x="46" y="92" fill="#FF4444" font-size="10" font-family="monospace">south_reach</text>
<circle cx="35" cy="108" r="5" fill="#44DD44"/>
<text x="46" y="112" fill="#44DD44" font-size="10" font-family="monospace">east_reach</text>
<circle cx="35" cy="128" r="5" fill="#FF8800"/>
<text x="46" y="132" fill="#FF8800" font-size="10" font-family="monospace">west_reach</text>
<circle cx="35" cy="148" r="5" fill="#AA44FF"/>
<text x="46" y="152" fill="#AA44FF" font-size="10" font-family="monospace">deep_frontier</text>
<text x="30" y="178" fill="#555" font-size="9" font-family="monospace">rings = hop distance from Gateway (center)</text>
<text x="30" y="192" fill="#444" font-size="8" font-family="monospace">outer ring = hop 15+ (deep frontier fade)</text>
<text x="30" y="206" fill="#444" font-size="8" font-family="monospace">opacity = settlement wave (bright=ancient, dim=recent)</text>
</svg>

After

Width:  |  Height:  |  Size: 65 KiB

+333
View File
@@ -0,0 +1,333 @@
#!/usr/bin/env python3
"""Generate concentric-ring star map SVG from star-map.json and systems.db.
Usage: python3 tooling/generate-star-map-svg.py [output.svg]
Default output: docs/diagrams/design/star-map-concentric.svg
"""
import json, sqlite3, math, sys, os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(SCRIPT_DIR)
STARMAP_PATH = os.path.join(ROOT, 'docs/design/star-map.json')
DB_PATH = os.path.join(ROOT, 'server/data/systems.db')
DEFAULT_OUTPUT = os.path.join(ROOT, 'docs/diagrams/design/star-map-concentric.svg')
output_path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_OUTPUT
# --- Load data ---
with open(STARMAP_PATH) as f:
starmap = json.load(f)
db = sqlite3.connect(DB_PATH)
sectors = dict(db.execute('SELECT system_id, geographic_sector FROM star_systems').fetchall())
names_raw = dict(db.execute('SELECT system_id, system_name FROM star_systems').fetchall())
waves = dict(db.execute('SELECT s.system_id, h.settlement_wave FROM star_systems s JOIN system_history h ON s.system_id = h.system_id').fetchall())
hops_db = dict(db.execute('SELECT system_id, hop_distance_from_gateway FROM system_gates').fetchall())
names = {}
for sid, n in names_raw.items():
names[sid] = n if n and 'PLACEHOLDER' not in n else sid
adj = {}
for n in starmap['nodes']:
adj[n['system_id']] = []
for e in starmap['edges']:
adj.setdefault(e[0], []).append(e[1])
adj.setdefault(e[1], []).append(e[0])
hop_groups = {}
for n in starmap['nodes']:
sid = n['system_id']
h = hops_db.get(sid, 99)
hop_groups.setdefault(h, []).append(sid)
apertures = {}
for n in starmap['nodes']:
apertures[n['system_id']] = n.get('aperture_count', 1)
max_hop = max(hop_groups.keys())
# Collapse hops 15+ into a single ring
FOLD_HOP = 15
folded_nodes = []
for h in list(hop_groups.keys()):
if h >= FOLD_HOP:
folded_nodes.extend(hop_groups.pop(h))
if folded_nodes:
hop_groups[FOLD_HOP] = list(dict.fromkeys(
hop_groups.get(FOLD_HOP, []) + folded_nodes
))
max_display_hop = FOLD_HOP
# --- Layout parameters ---
width, height = 3200, 3200
cx, cy = width / 2, height / 2
# Ring radii — hop 15+ gets a wider band
RING_STEP = 55
RING_BASE = 50
ring_radius = {}
for h in range(max_display_hop + 1):
if h == 0:
ring_radius[h] = 0
else:
ring_radius[h] = RING_STEP * h + RING_BASE
# Band half-widths (how thick each ring band is)
NORMAL_BAND = 27
FOLD_BAND = NORMAL_BAND # same width as normal rings
FADE_BAND = NORMAL_BAND * 4 # empty fade zone beyond the last ring
# 90-degree wedges, no gaps, centered on cardinals
sector_wedge_center = {
'north_reach': -math.pi / 2,
'east_reach': 0,
'south_reach': math.pi / 2,
'west_reach': math.pi,
}
wedge_half = math.pi / 4 # 45 degrees each side = 90 total
# Sol override: force to due west (angle = pi)
SOL_ID = 'GJ 0'
# --- Sector colors ---
node_colors = {
'core': '#FFD700',
'north_reach': '#4488FF',
'south_reach': '#FF4444',
'east_reach': '#44DD44',
'west_reach': '#FF8800',
'deep_frontier': '#AA44FF'
}
# Ring band colors per sector (two alternating shades)
band_colors = {
'north_reach': ('#1a2244', '#1a2a55'),
'east_reach': ('#1a2a1a', '#1a331a'),
'south_reach': ('#2a1a1a', '#331a1a'),
'west_reach': ('#2a2010', '#332810'),
}
wave_opacity = {
'origin': 1.0, 'wave_1': 1.0, 'wave_2': 0.85, 'wave_3': 0.7,
'wave_4': 0.55, 'wave_5': 0.4, 'unsettled': 0.25
}
# --- Placement ---
positions = {}
for sid in hop_groups.get(0, []):
positions[sid] = (cx, cy)
def parent_angle(sid, h):
# For folded nodes, parents can be at any hop < FOLD_HOP
threshold = min(h, FOLD_HOP)
parents = [nb for nb in adj.get(sid, []) if hops_db.get(nb, 99) < threshold and nb in positions]
if parents:
avg_x = sum(positions[p][0] for p in parents) / len(parents)
avg_y = sum(positions[p][1] for p in parents) / len(parents)
return math.atan2(avg_y - cy, avg_x - cx)
return 0
for h in range(1, max_display_hop + 1):
nodes = hop_groups.get(h, [])
if not nodes:
continue
r = ring_radius[h]
# For the fold ring, spiral nodes counter-clockwise by their actual hop
# Nodes at higher real hops get placed slightly further out
is_fold = (h == FOLD_HOP)
# Bucket by sector
buckets = {}
for sid in nodes:
s = sectors.get(sid, 'deep_frontier')
buckets.setdefault(s, []).append(sid)
placed = []
# Cardinal sectors: strict wedge placement
for sector_name, center_angle in sector_wedge_center.items():
bucket = buckets.get(sector_name, [])
if not bucket:
continue
if is_fold:
# Sort by actual hop distance (higher = further in spiral), then parent angle
bucket.sort(key=lambda s: (hops_db.get(s, 99), parent_angle(s, h)))
else:
bucket.sort(key=lambda s: parent_angle(s, h))
n = len(bucket)
lo = center_angle - wedge_half
hi = center_angle + wedge_half
for i, sid in enumerate(bucket):
angle = lo + (hi - lo) * (i + 0.5) / n
placed.append((angle, sid))
# Core: place near parents
for sid in buckets.get('core', []):
pa = parent_angle(sid, h)
placed.append((pa, sid))
# Deep frontier: assign to nearest cardinal wedge
for sid in buckets.get('deep_frontier', []):
pa = parent_angle(sid, h)
best_sector = min(sector_wedge_center.items(),
key=lambda sc: min(abs(pa - sc[1]),
abs(pa - sc[1] + 2*math.pi),
abs(pa - sc[1] - 2*math.pi)))
center = best_sector[1]
lo = center - wedge_half
hi = center + wedge_half
clamped = max(lo + 0.02, min(hi - 0.02, pa))
placed.append((clamped, sid))
# Sol override
for i, (angle, sid) in enumerate(placed):
if sid == SOL_ID:
placed[i] = (math.pi, sid)
break
# Sort and resolve overlaps
placed.sort()
min_gap = 2 * math.pi / (len(placed) + 1) * 0.7
for _ in range(30):
moved = False
for i in range(len(placed)):
j = (i + 1) % len(placed)
a1 = placed[i][0]
a2 = placed[j][0]
diff = a2 - a1
if j == 0:
diff += 2 * math.pi
if diff < min_gap:
nudge = (min_gap - diff) / 2
placed[i] = (a1 - nudge, placed[i][1])
placed[j] = (a2 + nudge, placed[j][1])
moved = True
if not moved:
break
for angle, sid in placed:
if is_fold:
# Subtle counter-clockwise spiral by real hop distance
real_hop = hops_db.get(sid, FOLD_HOP)
hop_frac = (real_hop - FOLD_HOP) / max(max_hop - FOLD_HOP, 1)
spiral_offset = -hop_frac * 0.12
x = cx + r * math.cos(angle + spiral_offset)
y = cy + r * math.sin(angle + spiral_offset)
else:
x = cx + r * math.cos(angle)
y = cy + r * math.sin(angle)
positions[sid] = (x, y)
# --- SVG rendering ---
svg = []
svg.append(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width} {height}" width="{width}" height="{height}">')
# Defs for the fade gradient beyond the last ring
svg.append('<defs>')
fade_start = ring_radius[FOLD_HOP] + FOLD_BAND # outer edge of last ring
fade_end = fade_start + FADE_BAND # end of fade zone
start_pct = fade_start / (width / 2) * 100
end_pct = min(fade_end / (width / 2) * 100, 100)
svg.append(f'<radialGradient id="fadeEdge" cx="50%" cy="50%" r="50%">')
svg.append(f' <stop offset="0%" stop-color="#0a0a1a" stop-opacity="0"/>')
svg.append(f' <stop offset="{start_pct:.1f}%" stop-color="#0a0a1a" stop-opacity="0"/>')
svg.append(f' <stop offset="{end_pct:.1f}%" stop-color="#0a0a1a" stop-opacity="1"/>')
svg.append(f' <stop offset="100%" stop-color="#0a0a1a" stop-opacity="1"/>')
svg.append('</radialGradient>')
svg.append('</defs>')
svg.append(f'<rect width="{width}" height="{height}" fill="#0a0a1a"/>')
# Alternating sector band rings
for sector_name, center_angle in sector_wedge_center.items():
lo = center_angle - wedge_half
hi = center_angle + wedge_half
c1, c2 = band_colors[sector_name]
for h in range(1, max_display_hop + 1):
band = NORMAL_BAND
r_inner = ring_radius[h] - band
r_outer = ring_radius[h] + band
if r_inner < 0:
r_inner = 0
color = c1 if h % 2 == 0 else c2
opacity = 0.35
x1_out = cx + r_outer * math.cos(lo)
y1_out = cy + r_outer * math.sin(lo)
x2_out = cx + r_outer * math.cos(hi)
y2_out = cy + r_outer * math.sin(hi)
x1_in = cx + r_inner * math.cos(hi)
y1_in = cy + r_inner * math.sin(hi)
x2_in = cx + r_inner * math.cos(lo)
y2_in = cy + r_inner * math.sin(lo)
svg.append(f'<path d="M {x1_out:.0f} {y1_out:.0f} A {r_outer} {r_outer} 0 0 1 {x2_out:.0f} {y2_out:.0f} '
f'L {x1_in:.0f} {y1_in:.0f} A {r_inner} {r_inner} 0 0 0 {x2_in:.0f} {y2_in:.0f} Z" '
f'fill="{color}" opacity="{opacity}"/>')
# Fade overlay on outer edge
svg.append(f'<rect width="{width}" height="{height}" fill="url(#fadeEdge)"/>')
# Cardinal labels — placed in the fade zone
label_r = ring_radius[FOLD_HOP] + FOLD_BAND + FADE_BAND * 0.4
svg.append(f'<text x="{cx}" y="{cy - label_r}" fill="#4488FF" font-size="18" font-family="monospace" text-anchor="middle" opacity="0.4">NORTH REACH</text>')
svg.append(f'<text x="{cx}" y="{cy + label_r + 18}" fill="#FF4444" font-size="18" font-family="monospace" text-anchor="middle" opacity="0.4">SOUTH REACH</text>')
svg.append(f'<text x="{cx + label_r + 10}" y="{cy + 6}" fill="#44DD44" font-size="18" font-family="monospace" opacity="0.4">EAST REACH</text>')
svg.append(f'<text x="{cx - label_r - 10}" y="{cy + 6}" fill="#FF8800" font-size="18" font-family="monospace" text-anchor="end" opacity="0.4">WEST REACH</text>')
# Edges
for e in starmap['edges']:
if e[0] in positions and e[1] in positions:
x1, y1 = positions[e[0]]
x2, y2 = positions[e[1]]
svg.append(f'<line x1="{x1:.1f}" y1="{y1:.1f}" x2="{x2:.1f}" y2="{y2:.1f}" stroke="#222240" stroke-width="0.5"/>')
# Nodes
for n in starmap['nodes']:
sid = n['system_id']
if sid not in positions:
continue
x, y = positions[sid]
sector = sectors.get(sid, 'deep_frontier')
color = node_colors.get(sector, '#AA44FF')
wave = waves.get(sid, 'wave_3')
hop = hops_db.get(sid, 99)
opacity = wave_opacity.get(wave, 0.5)
nr = 8 if sid == 'GJ 71' else (5 if sector == 'core' else (3 if hop <= 5 else 2))
svg.append(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="{nr}" fill="{color}" opacity="{opacity}"/>')
name = names.get(sid, sid)
ap = apertures.get(sid, 1)
if sector == 'core' or ap >= 5 or hop <= 3:
fs = 9 if sector == 'core' else 7
svg.append(f'<text x="{x+nr+2:.1f}" y="{y+3:.1f}" fill="{color}" font-size="{fs}" '
f'font-family="monospace" opacity="{min(opacity+0.2,1):.2f}">{name}</text>')
# Legend
lx, ly = 30, 40
svg.append(f'<text x="{lx}" y="{ly-12}" fill="#999" font-size="16" font-family="monospace" font-weight="bold">THE SETTLED REACH</text>')
ly += 8
for sector, color in node_colors.items():
svg.append(f'<circle cx="{lx+5}" cy="{ly}" r="5" fill="{color}"/>')
svg.append(f'<text x="{lx+16}" y="{ly+4}" fill="{color}" font-size="10" font-family="monospace">{sector}</text>')
ly += 20
ly += 10
svg.append(f'<text x="{lx}" y="{ly}" fill="#555" font-size="9" font-family="monospace">rings = hop distance from Gateway (center)</text>')
ly += 14
svg.append(f'<text x="{lx}" y="{ly}" fill="#444" font-size="8" font-family="monospace">outer ring = hop 15+ (deep frontier fade)</text>')
ly += 14
svg.append(f'<text x="{lx}" y="{ly}" fill="#444" font-size="8" font-family="monospace">opacity = settlement wave (bright=ancient, dim=recent)</text>')
svg.append('</svg>')
with open(output_path, 'w') as f:
f.write('\n'.join(svg))
print(f'Written to {output_path}')
print(f'{len(positions)} nodes, {len(starmap["edges"])} edges')
print(f'Hops 0-{FOLD_HOP-1} individual, {FOLD_HOP}+ folded ({len(hop_groups.get(FOLD_HOP, []))} nodes)')