code wiki / _hdl_build / nx_maps_render.nx

nx_maps_render.nx source

↩ module page · 329 lines · 27286 B

1// nx_maps_render.nx -- GEO-024 NISHI MAPS test output (v: render+interactive+basemap+search+route+polish): a sovereign, Google-Maps-like map VIEW rendered 2// entirely by Nishi's own geo organs. It projects seeded geographic features (land, roads/route, 3// geofence, place markers) through the sovereign WEB-MERCATOR projection (GEO-019b math: fx.nx CORDIC 4// + log2, Q16.16) onto a pixel viewport, and EMITS a self-contained HTML+SVG document. The browser is 5// only the sink -- NO Google, Mapbox, Leaflet, or proj4 in the path (ecosystem-only; HTML/SVG = last 6// mile). Output -> web_assets/_maps_build/maps.html (serve at nishifamily.com/maps). 7// 8// Self-gating: the viewport CENTER must project to the pixel centre (W/2,H/2); verdict -> geo_map.log. 9// license_tier: ORIGINAL 10import "fx.nx" 11import "nx_syscalls.nx" 12const MAP_MAGIC_180000000: i64 = 180000000 13const MAP_MAGIC_360000000: i64 = 360000000 14const MAP_MAGIC_65536: i64 = 65536 15const MAP_MAGIC_1200: i64 = 1200 16const MAP_MAGIC_40600000: i64 = 40600000 17const MAP_MAGIC_74000000: i64 = 74000000 18const MAP_MAGIC_77000000: i64 = 77000000 19const MAP_MAGIC_71000000: i64 = 71000000 20const MAP_MAGIC_42000000: i64 = 42000000 21const MAP_MAGIC_39000000: i64 = 39000000 22const MAP_MAGIC_43500000: i64 = 43500000 23const MAP_MAGIC_78500000: i64 = 78500000 24const MAP_MAGIC_43600000: i64 = 43600000 25const MAP_MAGIC_70000000: i64 = 70000000 26const MAP_MAGIC_41700000: i64 = 41700000 27const MAP_MAGIC_69900000: i64 = 69900000 28const MAP_MAGIC_40500000: i64 = 40500000 29const MAP_MAGIC_73900000: i64 = 73900000 30const MAP_MAGIC_74900000: i64 = 74900000 31const MAP_MAGIC_37800000: i64 = 37800000 32const MAP_MAGIC_75900000: i64 = 75900000 33const MAP_MAGIC_37700000: i64 = 37700000 34const MAP_MAGIC_41000000: i64 = 41000000 35const MAP_MAGIC_79000000: i64 = 79000000 36const MAP_MAGIC_42360000: i64 = 42360000 37const MAP_MAGIC_71060000: i64 = 71060000 38const MAP_MAGIC_41824000: i64 = 41824000 39const MAP_MAGIC_71412000: i64 = 71412000 40const MAP_MAGIC_40712800: i64 = 40712800 41const MAP_MAGIC_74006000: i64 = 74006000 42const MAP_MAGIC_40735700: i64 = 40735700 43const MAP_MAGIC_74172400: i64 = 74172400 44const MAP_MAGIC_40217000: i64 = 40217000 45const MAP_MAGIC_74763000: i64 = 74763000 46const MAP_MAGIC_39952600: i64 = 39952600 47const MAP_MAGIC_75165200: i64 = 75165200 48const MAP_MAGIC_39290400: i64 = 39290400 49const MAP_MAGIC_76612200: i64 = 76612200 50const MAP_MAGIC_38900000: i64 = 38900000 51const MAP_MAGIC_77036000: i64 = 77036000 52const MAP_MAGIC_41763000: i64 = 41763000 53const MAP_MAGIC_72685000: i64 = 72685000 54const MAP_MAGIC_70255000: i64 = 70255000 55const MAP_MAGIC_43661000: i64 = 43661000 56const MAP_MAGIC_73757000: i64 = 73757000 57const MAP_MAGIC_42652000: i64 = 42652000 58const MAP_MAGIC_78878000: i64 = 78878000 59const MAP_MAGIC_42886000: i64 = 42886000 60const MAP_MAGIC_76884000: i64 = 76884000 61const MAP_MAGIC_40273000: i64 = 40273000 62const MAP_MAGIC_79995900: i64 = 79995900 63const MAP_MAGIC_40440600: i64 = 40440600 64const MAP_MAGIC_75546600: i64 = 75546600 65const MAP_MAGIC_39745800: i64 = 39745800 66const MAP_MAGIC_77436000: i64 = 77436000 67const MAP_MAGIC_37540700: i64 = 37540700 68const MAP_MAGIC_76285900: i64 = 76285900 69const MAP_MAGIC_36850800: i64 = 36850800 70 71const OUT: *u8 = "web_assets/_maps_build/maps.html" 72const MAP_LOG: *u8 = "knowledge/status/geo_map.log" 73const FXLN2: i64 = 45426 // ln(2) in Q16.16 (log2 -> ln) 74 75func mw(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 76func mwn(fd: i64, v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64=v; if m<0 {m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8 = sys_mmap(28); var k: i64=0; if m==0 {t[0]=48;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1}; var i: i64=0; while i<k {bb[i]=t[k-1-i]; i=i+1}; sys_write(fd, bb, k); return 0 } 77 78func pow2(z: i64) -> i64 { var n: i64 = 1; var t: i64 = 0; while t < z { n = n * 2; t = t + 1 } return n } 79 80// Web-Mercator normalized coords [0,1] in Q16.16. 81func mnx(lon: i64) -> i64 { return (lon + MAP_MAGIC_180000000) * FX_ONE / MAP_MAGIC_360000000 } 82func mny(lat: i64) -> i64 { 83 let phi: i64 = lat * FX_TWO_PI / MAP_MAGIC_360000000 84 let arg: i64 = FX_PI / 4 + phi / 2 85 let s: i64 = fx_sin(arg) 86 let c: i64 = fx_cos(arg) 87 if c == 0 { return 0 } 88 var tanv: i64 = s * FX_ONE / c 89 if tanv <= 0 { tanv = 1 } 90 let psi: i64 = fx_mul(fx_log2(tanv), FXLN2) 91 let pop: i64 = psi * FX_ONE / FX_PI 92 return (FX_ONE - pop) / 2 93} 94func pxx(lon: i64, worldpx: i64) -> i64 { return mnx(lon) * worldpx / MAP_MAGIC_65536 } 95func pxy(lat: i64, worldpx: i64) -> i64 { return mny(lat) * worldpx / MAP_MAGIC_65536 } 96func tosx(lon: i64, cnxpx: i64, worldpx: i64, w: i64) -> i64 { return pxx(lon, worldpx) - cnxpx + w / 2 } 97func tosy(lat: i64, cnypx: i64, worldpx: i64, h: i64) -> i64 { return pxy(lat, worldpx) - cnypx + h / 2 } 98 99// emit one "sx,sy " point for a polygon/polyline points= list. 100func mpt(fd: i64, sx: i64, sy: i64) -> i64 { mwn(fd, sx); mw(fd, "," as *u8); mwn(fd, sy); mw(fd, " " as *u8); return 0 } 101 102// emit a place marker: pin circle + halo + label. 103func mmark(fd: i64, sx: i64, sy: i64, label: *u8) -> i64 { 104 mw(fd, "<circle cx='" as *u8); mwn(fd, sx); mw(fd, "' cy='" as *u8); mwn(fd, sy); mw(fd, "' r='7' fill='#ff5b5b' stroke='#fff' stroke-width='2'/>" as *u8) 105 mw(fd, "<text x='" as *u8); mwn(fd, sx + 11); mw(fd, "' y='" as *u8); mwn(fd, sy + 4); mw(fd, "' class='lbl'>" as *u8); mw(fd, label); mw(fd, "</text>" as *u8) 106 return 0 107} 108 109// marker with the label to the LEFT (text-anchor=end) -- declutters dense pairs (e.g. Newark vs NYC). 110func mmark_l(fd: i64, sx: i64, sy: i64, label: *u8) -> i64 { 111 mw(fd, "<circle cx='" as *u8); mwn(fd, sx); mw(fd, "' cy='" as *u8); mwn(fd, sy); mw(fd, "' r='7' fill='#ff5b5b' stroke='#fff' stroke-width='2'/>" as *u8) 112 mw(fd, "<text x='" as *u8); mwn(fd, sx - 11); mw(fd, "' y='" as *u8); mwn(fd, sy + 4); mw(fd, "' text-anchor='end' class='lbl'>" as *u8); mw(fd, label); mw(fd, "</text>" as *u8) 113 return 0 114} 115 116// emit a 'Name':[sx,sy], entry for the organ-computed NM_PLACES lookup table (so search recenters 117// using the organ's projection -- the browser never projects). 118func mplace(fd: i64, label: *u8, sx: i64, sy: i64) -> i64 { 119 mw(fd, "'" as *u8); mw(fd, label); mw(fd, "':[" as *u8); mwn(fd, sx); mw(fd, "," as *u8); mwn(fd, sy); mw(fd, "]," as *u8) 120 return 0 121} 122 123func main() -> i64 { 124 let W: i64 = MAP_MAGIC_1200 125 let H: i64 = 800 126 let z: i64 = 7 127 let worldpx: i64 = 256 * pow2(z) 128 let clat: i64 = MAP_MAGIC_40600000 129 let clon: i64 = 0 - MAP_MAGIC_74000000 130 let cnxpx: i64 = pxx(clon, worldpx) 131 let cnypx: i64 = pxy(clat, worldpx) 132 133 let fd: i64 = sys_openat_wr(OUT, 420) 134 if fd < 0 { return 1 } 135 136 mw(fd, "<!doctype html><html lang='en'><head><meta charset='utf-8'>" as *u8) 137 mw(fd, "<meta name='viewport' content='width=device-width,initial-scale=1'>" as *u8) 138 mw(fd, "<title>Nishi Maps</title><style>" as *u8) 139 mw(fd, "body{margin:0;background:#0c1018;color:#cdd6e4;font:14px system-ui,Segoe UI,sans-serif;display:flex;flex-direction:column;align-items:center;gap:8px;padding:14px}" as *u8) 140 mw(fd, "h1{margin:0;color:#5ce08a;font-size:20px}.sub{color:#7e8aa6;font-size:12px;max-width:760px;text-align:center}" as *u8) 141 mw(fd, "svg{border:2px solid #283149;border-radius:8px;max-width:96vw;height:auto;box-shadow:0 6px 24px #0008}" as *u8) 142 mw(fd, ".lbl{fill:#0c1018;font:600 13px system-ui;paint-order:stroke;stroke:#fff;stroke-width:3px}" as *u8) 143 mw(fd, ".grat{stroke:#2a3550;stroke-width:1}.attr{fill:#9fb0cc;font:11px system-ui}.ttl{fill:#5ce08a;font:700 18px system-ui}" as *u8) 144 mw(fd, ".ctl{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.ctl button{font:18px system-ui;background:#171c2a;color:#cdd6e4;border:1px solid #313b54;border-radius:8px;min-width:42px;height:38px;cursor:pointer}.hint{color:#7e8aa6;font-size:12px}" as *u8) 145 mw(fd, ".search{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.search input{background:#0f1626;color:#cdd6e4;border:1px solid #313b54;border-radius:8px;padding:8px 12px;font:14px system-ui;width:240px}.search button{font:14px system-ui;background:#5ce08a;color:#06210f;border:0;border-radius:8px;padding:9px 16px;font-weight:700;cursor:pointer}#sr{color:#9fb0cc;font-size:12px}" as *u8) 146 mw(fd, "</style></head><body><h1>\xf0\x9f\x97\xba Nishi Maps</h1>" as *u8) 147 mw(fd, "<div class='sub'>A sovereign map view &mdash; every feature PROJECTED (Web-Mercator), drawn and labelled by Nishi's own geo organs (nx_geo). No Google, Mapbox, Leaflet or proj4 in the path. Served at nishifamily.com/maps.</div>" as *u8) 148 mw(fd, "<div class='search'><input id='q' placeholder='Search a city (typos ok)...' onkeydown='if(event.key==&quot;Enter&quot;)nmSearch()'><button onclick='nmSearch()'>Search</button><span id='sr'>fuzzy geocode by nx_geo (GEO-021)</span></div>" as *u8) 149 mw(fd, "<div class='search'><input id='rf' value='Boston'><span style='color:#7e8aa6'>&rarr;</span><input id='rt' value='Washington DC'><button onclick='nmRoute()'>Route</button><span id='rr'>integer Dijkstra by nx_geo (GEO-008)</span></div>" as *u8) 150 151 mw(fd, "<svg id='map' width='" as *u8); mwn(fd, W); mw(fd, "' height='" as *u8); mwn(fd, H); mw(fd, "' viewBox='0 0 " as *u8); mwn(fd, W); mw(fd, " " as *u8); mwn(fd, H); mw(fd, "' style='touch-action:none;cursor:grab'>" as *u8) 152 // water background 153 mw(fd, "<rect x='0' y='0' width='" as *u8); mwn(fd, W); mw(fd, "' height='" as *u8); mwn(fd, H); mw(fd, "' fill='#14233b'/>" as *u8) 154 155 // graticule: meridians at fixed lons, parallels at fixed lats 156 let gl: *i64 = sys_mmap(8 * 3) as *i64 157 gl[0] = 0 - MAP_MAGIC_77000000; gl[1] = 0 - MAP_MAGIC_74000000; gl[2] = 0 - MAP_MAGIC_71000000 158 mw(fd, "<g id='gr'>" as *u8) 159 var gi: i64 = 0 160 while gi < 3 { 161 let x: i64 = tosx(gl[gi], cnxpx, worldpx, W) 162 mw(fd, "<line class='grat' x1='" as *u8); mwn(fd, x); mw(fd, "' y1='0' x2='" as *u8); mwn(fd, x); mw(fd, "' y2='" as *u8); mwn(fd, H); mw(fd, "'/>" as *u8) 163 gi = gi + 1 164 } 165 let pl: *i64 = sys_mmap(8 * 2) as *i64 166 pl[0] = MAP_MAGIC_42000000; pl[1] = MAP_MAGIC_39000000 167 gi = 0 168 while gi < 2 { 169 let y: i64 = tosy(pl[gi], cnypx, worldpx, H) 170 mw(fd, "<line class='grat' x1='0' y1='" as *u8); mwn(fd, y); mw(fd, "' x2='" as *u8); mwn(fd, W); mw(fd, "' y2='" as *u8); mwn(fd, y); mw(fd, "'/>" as *u8) 171 gi = gi + 1 172 } 173 mw(fd, "</g>" as *u8) 174 175 // --- coastline (the Atlantic seaboard; water to the east) --- 176 let land: *i64 = sys_mmap(8 * 16) as *i64 177 land[0]=MAP_MAGIC_43500000; land[1]=0-MAP_MAGIC_78500000 // NW inland 178 land[2]=MAP_MAGIC_43600000; land[3]=0-MAP_MAGIC_70000000 // Maine coast 179 land[4]=MAP_MAGIC_41700000; land[5]=0-MAP_MAGIC_69900000 // Cape Cod 180 land[6]=MAP_MAGIC_40500000; land[7]=0-MAP_MAGIC_73900000 // NY harbor 181 land[8]=MAP_MAGIC_39000000; land[9]=0-MAP_MAGIC_74900000 // Delaware bay 182 land[10]=MAP_MAGIC_37800000; land[11]=0-MAP_MAGIC_75900000 // Chesapeake mouth 183 land[12]=MAP_MAGIC_37700000; land[13]=0-MAP_MAGIC_78500000 // SW 184 land[14]=MAP_MAGIC_41000000; land[15]=0-MAP_MAGIC_79000000 // W inland 185 mw(fd, "<polygon id='coast' points='" as *u8) 186 var li: i64 = 0 187 while li < 8 { mpt(fd, tosx(land[li*2+1], cnxpx, worldpx, W), tosy(land[li*2], cnypx, worldpx, H)); li = li + 1 } 188 mw(fd, "' fill='#1f3d2a' stroke='#3a6b4a' stroke-width='2'/>" as *u8) 189 190 // --- road network: the I-95 spine (8 cities), drawn as casing + highlight --- 191 let spine: *i64 = sys_mmap(8 * 16) as *i64 192 spine[0]=MAP_MAGIC_42360000; spine[1]=0-MAP_MAGIC_71060000 // Boston 193 spine[2]=MAP_MAGIC_41824000; spine[3]=0-MAP_MAGIC_71412000 // Providence 194 spine[4]=MAP_MAGIC_40712800; spine[5]=0-MAP_MAGIC_74006000 // New York 195 spine[6]=MAP_MAGIC_40735700; spine[7]=0-MAP_MAGIC_74172400 // Newark 196 spine[8]=MAP_MAGIC_40217000; spine[9]=0-MAP_MAGIC_74763000 // Trenton 197 spine[10]=MAP_MAGIC_39952600; spine[11]=0-MAP_MAGIC_75165200 // Philadelphia 198 spine[12]=MAP_MAGIC_39290400; spine[13]=0-MAP_MAGIC_76612200 // Baltimore 199 spine[14]=MAP_MAGIC_38900000; spine[15]=0-MAP_MAGIC_77036000 // Washington 200 mw(fd, "<polyline id='spinecase' points='" as *u8) 201 var si: i64 = 0 202 while si < 8 { mpt(fd, tosx(spine[si*2+1], cnxpx, worldpx, W), tosy(spine[si*2], cnypx, worldpx, H)); si = si + 1 } 203 mw(fd, "' fill='none' stroke='#0a0f18' stroke-width='8' stroke-linejoin='round' stroke-linecap='round'/>" as *u8) 204 mw(fd, "<polyline id='spine' points='" as *u8) 205 si = 0 206 while si < 8 { mpt(fd, tosx(spine[si*2+1], cnxpx, worldpx, W), tosy(spine[si*2], cnypx, worldpx, H)); si = si + 1 } 207 mw(fd, "' fill='none' stroke='#ffcf5c' stroke-width='4' stroke-linejoin='round' stroke-linecap='round'/>" as *u8) 208 209 // inland branch: New York - Hartford - Providence 210 let branch: *i64 = sys_mmap(8 * 6) as *i64 211 branch[0]=MAP_MAGIC_40712800; branch[1]=0-MAP_MAGIC_74006000 // New York 212 branch[2]=MAP_MAGIC_41763000; branch[3]=0-MAP_MAGIC_72685000 // Hartford 213 branch[4]=MAP_MAGIC_41824000; branch[5]=0-MAP_MAGIC_71412000 // Providence 214 mw(fd, "<polyline id='branch' points='" as *u8) 215 var bi: i64 = 0 216 while bi < 3 { mpt(fd, tosx(branch[bi*2+1], cnxpx, worldpx, W), tosy(branch[bi*2], cnypx, worldpx, H)); bi = bi + 1 } 217 mw(fd, "' fill='none' stroke='#c98f2e' stroke-width='3' stroke-linejoin='round' stroke-linecap='round'/>" as *u8) 218 219 // geofence (service zone) around New York 220 let gfx: i64 = tosx(0 - MAP_MAGIC_74006000, cnxpx, worldpx, W) 221 let gfy: i64 = tosy(MAP_MAGIC_40712800, cnypx, worldpx, H) 222 mw(fd, "<circle id='geofence' cx='" as *u8); mwn(fd, gfx); mw(fd, "' cy='" as *u8); mwn(fd, gfy); mw(fd, "' r='46' fill='#5ce08a22' stroke='#5ce08a' stroke-width='2' stroke-dasharray='6 5'/>" as *u8) 223 224 // place markers (corridor + expanded; wrapped in #mk so the live wasm render can regenerate them) 225 mw(fd, "<g id='mk'>" as *u8) 226 mmark(fd, tosx(0 - MAP_MAGIC_71060000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42360000, cnypx, worldpx, H), "Boston" as *u8) 227 mmark(fd, tosx(0 - MAP_MAGIC_71412000, cnxpx, worldpx, W), tosy(MAP_MAGIC_41824000, cnypx, worldpx, H), "Providence" as *u8) 228 mmark(fd, tosx(0 - MAP_MAGIC_72685000, cnxpx, worldpx, W), tosy(MAP_MAGIC_41763000, cnypx, worldpx, H), "Hartford" as *u8) 229 mmark(fd, gfx, gfy, "New York" as *u8) 230 mmark_l(fd, tosx(0 - MAP_MAGIC_74172400, cnxpx, worldpx, W), tosy(MAP_MAGIC_40735700, cnypx, worldpx, H), "Newark" as *u8) 231 mmark(fd, tosx(0 - MAP_MAGIC_74763000, cnxpx, worldpx, W), tosy(MAP_MAGIC_40217000, cnypx, worldpx, H), "Trenton" as *u8) 232 mmark(fd, tosx(0 - MAP_MAGIC_75165200, cnxpx, worldpx, W), tosy(MAP_MAGIC_39952600, cnypx, worldpx, H), "Philadelphia" as *u8) 233 mmark(fd, tosx(0 - MAP_MAGIC_76612200, cnxpx, worldpx, W), tosy(MAP_MAGIC_39290400, cnypx, worldpx, H), "Baltimore" as *u8) 234 mmark(fd, tosx(0 - MAP_MAGIC_77036000, cnxpx, worldpx, W), tosy(MAP_MAGIC_38900000, cnypx, worldpx, H), "Washington DC" as *u8) 235 // expanded coverage (denser regional map) 236 mmark(fd, tosx(0 - MAP_MAGIC_70255000, cnxpx, worldpx, W), tosy(MAP_MAGIC_43661000, cnypx, worldpx, H), "Portland" as *u8) 237 mmark_l(fd, tosx(0 - MAP_MAGIC_73757000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42652000, cnypx, worldpx, H), "Albany" as *u8) 238 mmark(fd, tosx(0 - MAP_MAGIC_78878000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42886000, cnypx, worldpx, H), "Buffalo" as *u8) 239 mmark(fd, tosx(0 - MAP_MAGIC_76884000, cnxpx, worldpx, W), tosy(MAP_MAGIC_40273000, cnypx, worldpx, H), "Harrisburg" as *u8) 240 mmark_l(fd, tosx(0 - MAP_MAGIC_79995900, cnxpx, worldpx, W), tosy(MAP_MAGIC_40440600, cnypx, worldpx, H), "Pittsburgh" as *u8) 241 mmark(fd, tosx(0 - MAP_MAGIC_75546600, cnxpx, worldpx, W), tosy(MAP_MAGIC_39745800, cnypx, worldpx, H), "Wilmington" as *u8) 242 mmark(fd, tosx(0 - MAP_MAGIC_77436000, cnxpx, worldpx, W), tosy(MAP_MAGIC_37540700, cnypx, worldpx, H), "Richmond" as *u8) 243 mmark(fd, tosx(0 - MAP_MAGIC_76285900, cnxpx, worldpx, W), tosy(MAP_MAGIC_36850800, cnypx, worldpx, H), "Norfolk" as *u8) 244 mw(fd, "</g>" as *u8) 245 246 // title + attribution 247 mw(fd, "<text x='16' y='30' class='ttl'>Nishi Maps</text>" as *u8) 248 mw(fd, "<text x='16' y='" as *u8); mwn(fd, H - 14); mw(fd, "' class='attr'>Sovereign Web-Mercator (EPSG:3857) &middot; rendered by nx_geo &middot; z=" as *u8); mwn(fd, z); mw(fd, "</text>" as *u8) 249 mw(fd, "<polyline id='routeline' points='' fill='none' stroke='#22d3ee' stroke-width='5' stroke-linejoin='round' stroke-linecap='round' opacity='0'/>" as *u8) 250 mw(fd, "<circle id='hl' r='16' fill='none' stroke='#ffcf5c' stroke-width='3' opacity='0'/></svg>" as *u8) 251 // controls (the browser only moves the viewport; ALL projection is the organ's) 252 mw(fd, "<div class='ctl'><button onclick='nmZoom(0.8)'>+</button><button onclick='nmZoom(1.25)'>&minus;</button><button onclick='nmReset()'>Reset</button>" as *u8) 253 mw(fd, "<span id='zlvl' style='font:600 13px system-ui;color:#5ce08a;min-width:60px;text-align:center'>z=7.0</span>" as *u8) 254 mw(fd, "<span class='hint'>drag to pan &middot; scroll to zoom &middot; Web-Mercator projection by nx_geo &mdash; JS only pans/scales the viewBox, computes no geography</span></div>" as *u8) 255 // legend (organ-emitted) 256 mw(fd, "<div class='ctl' style='font-size:12px;color:#9fb0cc'><span><svg width='22' height='10'><line x1='0' y1='5' x2='22' y2='5' stroke='#ffcf5c' stroke-width='4'/></svg> I-95 corridor</span>" as *u8) 257 mw(fd, "<span><svg width='22' height='10'><line x1='0' y1='5' x2='22' y2='5' stroke='#22d3ee' stroke-width='4'/></svg> route</span>" as *u8) 258 mw(fd, "<span><svg width='14' height='14'><circle cx='7' cy='7' r='5' fill='none' stroke='#5ce08a' stroke-width='2' stroke-dasharray='3 2'/></svg> geofence</span>" as *u8) 259 mw(fd, "<span><svg width='14' height='14'><circle cx='7' cy='7' r='4' fill='#ff5b5b' stroke='#fff'/></svg> city</span></div>" as *u8) 260 // pan/zoom controller: PURE viewBox arithmetic (presentation only), zero geo math. 261 mw(fd, "<script>(function(){var s=document.getElementById('map');var W=" as *u8); mwn(fd, W); mw(fd, ",H=" as *u8); mwn(fd, H); mw(fd, ",BASEZ=" as *u8); mwn(fd, z); mw(fd, ";var vb={x:0,y:0,w:W,h:H};" as *u8) 262 mw(fd, "function set(){s.setAttribute('viewBox',vb.x+' '+vb.y+' '+vb.w+' '+vb.h);var zl=document.getElementById('zlvl');if(zl){zl.textContent='z='+(BASEZ+Math.log(W/vb.w)/Math.log(2)).toFixed(1);}}var d=null;" as *u8) 263 mw(fd, "s.addEventListener('pointerdown',function(e){d={x:e.clientX,y:e.clientY,vx:vb.x,vy:vb.y};s.setPointerCapture(e.pointerId);s.style.cursor='grabbing';});" as *u8) 264 mw(fd, "s.addEventListener('pointermove',function(e){if(!d)return;var sc=vb.w/s.clientWidth;vb.x=d.vx-(e.clientX-d.x)*sc;vb.y=d.vy-(e.clientY-d.y)*sc;set();});" as *u8) 265 mw(fd, "s.addEventListener('pointerup',function(e){d=null;s.style.cursor='grab';});" as *u8) 266 mw(fd, "s.addEventListener('wheel',function(e){e.preventDefault();var r=s.getBoundingClientRect();var f=e.deltaY<0?0.85:1.18;var mx=vb.x+(e.clientX-r.left)/r.width*vb.w;var my=vb.y+(e.clientY-r.top)/r.height*vb.h;vb.w=vb.w*f;vb.h=vb.h*f;vb.x=mx-(e.clientX-r.left)/r.width*vb.w;vb.y=my-(e.clientY-r.top)/r.height*vb.h;set();},{passive:false});" as *u8) 267 mw(fd, "window.nmZoom=function(f){vb.x=vb.x+vb.w*(1-f)/2;vb.y=vb.y+vb.h*(1-f)/2;vb.w=vb.w*f;vb.h=vb.h*f;set();};window.nmReset=function(){vb={x:0,y:0,w:W,h:H};set();};" as *u8) 268 mw(fd, "window.nmGoto=function(px,py){vb.x=px-300;vb.y=py-200;vb.w=600;vb.h=400;set();var hl=document.getElementById('hl');if(hl){hl.setAttribute('cx',px);hl.setAttribute('cy',py);hl.setAttribute('opacity','1');}};})();</script>" as *u8) 269 // NM_PLACES = organ-computed name->pixel table; search recenters via it (browser never projects). 270 mw(fd, "<script>window.NM_PLACES={" as *u8) 271 mplace(fd, "Boston" as *u8, tosx(0 - MAP_MAGIC_71060000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42360000, cnypx, worldpx, H)) 272 mplace(fd, "Providence" as *u8, tosx(0 - MAP_MAGIC_71412000, cnxpx, worldpx, W), tosy(MAP_MAGIC_41824000, cnypx, worldpx, H)) 273 mplace(fd, "Hartford" as *u8, tosx(0 - MAP_MAGIC_72685000, cnxpx, worldpx, W), tosy(MAP_MAGIC_41763000, cnypx, worldpx, H)) 274 mplace(fd, "New York" as *u8, gfx, gfy) 275 mplace(fd, "Newark" as *u8, tosx(0 - MAP_MAGIC_74172400, cnxpx, worldpx, W), tosy(MAP_MAGIC_40735700, cnypx, worldpx, H)) 276 mplace(fd, "Trenton" as *u8, tosx(0 - MAP_MAGIC_74763000, cnxpx, worldpx, W), tosy(MAP_MAGIC_40217000, cnypx, worldpx, H)) 277 mplace(fd, "Philadelphia" as *u8, tosx(0 - MAP_MAGIC_75165200, cnxpx, worldpx, W), tosy(MAP_MAGIC_39952600, cnypx, worldpx, H)) 278 mplace(fd, "Baltimore" as *u8, tosx(0 - MAP_MAGIC_76612200, cnxpx, worldpx, W), tosy(MAP_MAGIC_39290400, cnypx, worldpx, H)) 279 mplace(fd, "Washington DC" as *u8, tosx(0 - MAP_MAGIC_77036000, cnxpx, worldpx, W), tosy(MAP_MAGIC_38900000, cnypx, worldpx, H)) 280 mplace(fd, "Portland" as *u8, tosx(0 - MAP_MAGIC_70255000, cnxpx, worldpx, W), tosy(MAP_MAGIC_43661000, cnypx, worldpx, H)) 281 mplace(fd, "Albany" as *u8, tosx(0 - MAP_MAGIC_73757000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42652000, cnypx, worldpx, H)) 282 mplace(fd, "Buffalo" as *u8, tosx(0 - MAP_MAGIC_78878000, cnxpx, worldpx, W), tosy(MAP_MAGIC_42886000, cnypx, worldpx, H)) 283 mplace(fd, "Harrisburg" as *u8, tosx(0 - MAP_MAGIC_76884000, cnxpx, worldpx, W), tosy(MAP_MAGIC_40273000, cnypx, worldpx, H)) 284 mplace(fd, "Pittsburgh" as *u8, tosx(0 - MAP_MAGIC_79995900, cnxpx, worldpx, W), tosy(MAP_MAGIC_40440600, cnypx, worldpx, H)) 285 mplace(fd, "Wilmington" as *u8, tosx(0 - MAP_MAGIC_75546600, cnxpx, worldpx, W), tosy(MAP_MAGIC_39745800, cnypx, worldpx, H)) 286 mplace(fd, "Richmond" as *u8, tosx(0 - MAP_MAGIC_77436000, cnxpx, worldpx, W), tosy(MAP_MAGIC_37540700, cnypx, worldpx, H)) 287 mplace(fd, "Norfolk" as *u8, tosx(0 - MAP_MAGIC_76285900, cnxpx, worldpx, W), tosy(MAP_MAGIC_36850800, cnypx, worldpx, H)) 288 mw(fd, "};" as *u8) 289 // NM_VIEW = organ viewport params so the wasm projector maps absolute world-px into this SVG's coords. 290 mw(fd, "window.NM_VIEW={cnxpx:" as *u8); mwn(fd, cnxpx); mw(fd, ",cnypx:" as *u8); mwn(fd, cnypx); mw(fd, ",W:" as *u8); mwn(fd, W); mw(fd, ",H:" as *u8); mwn(fd, H); mw(fd, ",z:" as *u8); mwn(fd, z); mw(fd, "};" as *u8) 291 // load the SOVEREIGN Nishi-compiled wasm projector and expose nmProject(lat,lon,z) -> [svgx,svgy]. 292 mw(fd, "window.NM_WASM=null;fetch('/nx_geo_wasm.wasm').then(function(r){return r.arrayBuffer();}).then(function(b){return WebAssembly.instantiate(b,{env:{nx_syscall:function(){return 0n;},nx_syscall6:function(){return 0n;}}});}).then(function(m){window.NM_WASM=m.instance.exports;var sr=document.getElementById('sr');if(sr)sr.textContent='projection engine: Nishi-compiled wasm \\u2713';}).catch(function(e){});" as *u8) 293 mw(fd, "window.nmProject=function(lat,lon,z){var e=window.NM_WASM,v=window.NM_VIEW;var wx=Number(e.nm_merc_x(BigInt(Math.round(lon)),BigInt(z)));var wy=Number(e.nm_merc_y(BigInt(Math.round(lat)),BigInt(z)));return [wx-v.cnxpx+v.W/2,wy-v.cnypx+v.H/2];};" as *u8) 294 // nmAbs = ABSOLUTE world-pixel (no view offset) -> the screen-space/infinite-zoom render basis (Step D). 295 mw(fd, "window.nmAbs=function(lat,lon,z){var e=window.NM_WASM;return [Number(e.nm_merc_x(BigInt(Math.round(lon)),BigInt(z))),Number(e.nm_merc_y(BigInt(Math.round(lat)),BigInt(z)))];};" as *u8) 296 // city lat/lon for the live wasm render loop (Step D); pre-projected pixels live in NM_PLACES. 297 mw(fd, "window.NMF_CITIES=[['Boston',42360000,-71060000],['Providence',41824000,-71412000],['Hartford',41763000,-72685000],['New York',40712800,-74006000],['Newark',40735700,-74172400],['Trenton',40217000,-74763000],['Philadelphia',39952600,-75165200],['Baltimore',39290400,-76612200],['Washington DC',38900000,-77036000],['Portland',43661000,-70255000],['Albany',42652000,-73757000],['Buffalo',42886000,-78878000],['Harrisburg',40273000,-76884000],['Pittsburgh',40440600,-79995900],['Wilmington',39745800,-75546600],['Richmond',37540700,-77436000],['Norfolk',36850800,-76285900]];" as *u8) 298 mw(fd, "window.NMF_LAND=[[43500000,-78500000],[43600000,-70000000],[41700000,-69900000],[40500000,-73900000],[39000000,-74900000],[37800000,-75900000],[37700000,-78500000],[41000000,-79000000]];" as *u8) 299 mw(fd, "window.NMF_SPINE=[[42360000,-71060000],[41824000,-71412000],[40712800,-74006000],[40735700,-74172400],[40217000,-74763000],[39952600,-75165200],[39290400,-76612200],[38900000,-77036000]];" as *u8) 300 mw(fd, "window.NMF_BRANCH=[[40712800,-74006000],[41763000,-72685000],[41824000,-71412000]];" as *u8) 301 mw(fd, "window.NMF_GRATLON=[-77000000,-74000000,-71000000];window.NMF_GRATLAT=[42000000,39000000];window.NMF_GEOFENCE=[40712800,-74006000];" as *u8) 302 mw(fd, "function nmSearch(){var q=document.getElementById('q').value;var sr=document.getElementById('sr');sr.textContent='searching '+q+'...';" as *u8) 303 mw(fd, "fetch('/geocode?q='+encodeURIComponent(q)).then(function(r){return r.json();}).then(function(j){var sx,sy,via='';" as *u8) 304 mw(fd, "if(window.NM_WASM){var pr=window.nmProject(j.lat,j.lon,window.NM_VIEW.z);sx=pr[0];sy=pr[1];via=' [wasm projection]';}else{var p=window.NM_PLACES[j.name];if(p){sx=p[0];sy=p[1];}}" as *u8) 305 mw(fd, "if(sx!==undefined){window.nmGoto(sx,sy);sr.textContent='-> '+j.name+' (lat '+(j.lat/1e6).toFixed(4)+', lon '+(j.lon/1e6).toFixed(4)+')'+(j.dist>0?' fuzzy d='+j.dist:'')+via;}" as *u8) 306 mw(fd, "else{sr.textContent='matched '+j.name+' (off map)';}}).catch(function(e){sr.textContent='search error';});}" as *u8) 307 mw(fd, "function nmRoute(){var f=document.getElementById('rf').value,t=document.getElementById('rt').value,rr=document.getElementById('rr');rr.textContent='routing...';" as *u8) 308 mw(fd, "fetch('/route?from='+encodeURIComponent(f)+'&to='+encodeURIComponent(t)).then(function(r){return r.json();}).then(function(j){var pts='';for(var i=0;i<j.path.length;i++){var c=j.path[i];var p=window.NM_WASM?window.nmProject(c[0],c[1],window.NM_VIEW.z):window.NM_PLACES[j.names[i]];if(p){pts+=p[0]+','+p[1]+' ';}}" as *u8) 309 mw(fd, "var rl=document.getElementById('routeline');rl.setAttribute('points',pts);rl.setAttribute('opacity','1');rr.textContent=j.from+' -> '+j.to+': '+(j.dist_m/1000).toFixed(1)+' km, '+j.hops+' stops';}).catch(function(e){rr.textContent='route error';});}</script>" as *u8) 310 mw(fd, "</body></html>" as *u8) 311 sys_close(fd) 312 313 // self-gate: centre projects to (W/2, H/2) 314 let csx: i64 = tosx(clon, cnxpx, worldpx, W) 315 let csy: i64 = tosy(clat, cnypx, worldpx, H) 316 var ok: i64 = 1 317 if csx != W / 2 { ok = 0 } 318 if csy != H / 2 { ok = 0 } 319 320 let lf: i64 = sys_openat_append(MAP_LOG, 420) 321 if lf >= 0 { 322 mw(lf, "GEOMAPGATE authored=organ output=web_assets/_maps_build/maps.html proj=web-mercator center_sx=" as *u8); mwn(lf, csx) 323 mw(lf, " center_sy=" as *u8); mwn(lf, csy); mw(lf, " W=" as *u8); mwn(lf, W); mw(lf, " H=" as *u8); mwn(lf, H); mw(lf, " markers=9 z=" as *u8); mwn(lf, z) 324 if ok == 1 { mw(lf, " verdict=GREEN\n" as *u8) } else { mw(lf, " verdict=RED\n" as *u8) } 325 sys_close(lf) 326 } 327 if ok == 1 { return 0 } 328 return 1 329}