mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
refactor: separate Overpass and installation services
This commit is contained in:
1 parent
781613fbb8
commit
213edd80ce
14 files changed
+1455
-841
No files matched your search
@@ -0,0 +1,92 @@
|
||||
import { OVERPASS_SIMPLIFY_MIN_BYTES, OVERPASS_SIMPLIFY_MIN_POINTS, OVERPASS_SIMPLIFY_TOLERANCE_DEG } from './constants.js';
|
||||
|
||||
/** Iterative Douglas-Peucker on [{lat,lon},...] (planar-degree approx — fine at
|
||||
* the ~44 m tolerance used here). Endpoints always kept. */
|
||||
function douglasPeucker(points, toleranceDeg) {
|
||||
const n = points.length;
|
||||
if (n <= 2) return points;
|
||||
const keep = new Uint8Array(n);
|
||||
keep[0] = 1;
|
||||
keep[n - 1] = 1;
|
||||
const stack = [[0, n - 1]];
|
||||
while (stack.length) {
|
||||
const [a, b] = stack.pop();
|
||||
if (b - a < 2) continue;
|
||||
const ax = points[a].lon;
|
||||
const ay = points[a].lat;
|
||||
const vx = points[b].lon - ax;
|
||||
const vy = points[b].lat - ay;
|
||||
const c2 = vx * vx + vy * vy;
|
||||
let worst = -1;
|
||||
let worstDist = toleranceDeg;
|
||||
for (let i = a + 1; i < b; i++) {
|
||||
const wx = points[i].lon - ax;
|
||||
const wy = points[i].lat - ay;
|
||||
let d;
|
||||
if (c2 === 0) {
|
||||
d = Math.hypot(wx, wy);
|
||||
} else {
|
||||
const t = Math.max(0, Math.min(1, (vx * wx + vy * wy) / c2));
|
||||
d = Math.hypot(wx - t * vx, wy - t * vy);
|
||||
}
|
||||
if (d > worstDist) {
|
||||
worstDist = d;
|
||||
worst = i;
|
||||
}
|
||||
}
|
||||
if (worst >= 0) {
|
||||
keep[worst] = 1;
|
||||
stack.push([a, worst], [worst, b]);
|
||||
}
|
||||
}
|
||||
const out = [];
|
||||
for (let i = 0; i < n; i++) if (keep[i]) out.push(points[i]);
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Simplify one element's geometry array in place if it is big enough. */
|
||||
function simplifyElementGeometry(el, minPoints, toleranceDeg) {
|
||||
if (Array.isArray(el?.geometry) && el.geometry.length >= minPoints) {
|
||||
el.geometry = douglasPeucker(el.geometry, toleranceDeg);
|
||||
}
|
||||
if (Array.isArray(el?.members)) {
|
||||
for (const member of el.members) {
|
||||
if (Array.isArray(member?.geometry) && member.geometry.length >= minPoints) {
|
||||
member.geometry = douglasPeucker(member.geometry, toleranceDeg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side geometry simplification for large Overpass `out geom` payloads.
|
||||
* Region/state boundary pivots return multi-MB coastline rings whose fidelity
|
||||
* nothing downstream needs (the client re-simplifies for draw); decimating them
|
||||
* HERE shrinks the disk cache, the wire, and client parse time — and is what
|
||||
* makes the raised read cap safe. Anything unparseable or below the thresholds
|
||||
* passes through byte-identical. Exported for tests (opts override thresholds).
|
||||
*
|
||||
* @param {string} bodyText - Raw upstream JSON body.
|
||||
* @returns {string} Possibly-simplified JSON body.
|
||||
*/
|
||||
function simplifyOverpassPayloadBody(bodyText, opts = {}) {
|
||||
const minBytes = opts.minBytes ?? OVERPASS_SIMPLIFY_MIN_BYTES;
|
||||
const minPoints = opts.minPoints ?? OVERPASS_SIMPLIFY_MIN_POINTS;
|
||||
const toleranceDeg = opts.toleranceDeg ?? OVERPASS_SIMPLIFY_TOLERANCE_DEG;
|
||||
if (typeof bodyText !== 'string' || bodyText.length < minBytes) return bodyText;
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(bodyText);
|
||||
} catch {
|
||||
return bodyText;
|
||||
}
|
||||
if (!Array.isArray(data?.elements)) return bodyText;
|
||||
for (const el of data.elements) simplifyElementGeometry(el, minPoints, toleranceDeg);
|
||||
try {
|
||||
return JSON.stringify(data);
|
||||
} catch {
|
||||
return bodyText;
|
||||
}
|
||||
}
|
||||
|
||||
export { simplifyOverpassPayloadBody };
|
||||
Reference in new issue
Block a user