79718262

Date: 2025-07-29 07:45:19
Score: 1
Natty:
Report link

You're trying to uncover all the hidden parcels (polygons) on an ArcGIS map. Click anywhere, and the site gives you back the geometry + attributes for the parcel under your cursor and not much more.

The real problem: How do you systematically discover every polygonal region, given only this point-and-click interface?

What you get on each click (simplified):

{
  "geometryType": "esriGeometryPolygon",
  "features": [{
    "attributes": { "ADDRESS": "..." },
    "geometry": { "rings": [ [[x1, y1], [x2, y2], ..., [xN, yN]] ] }
  }]
}
(rings form a loop so [x1,y1] == [xN, yN]

Each probe gives you the entire geometry (the ring) of a parcel, as an ArcGIS' Polygon type. Coords are Web Mercator (not lat/lon), so units are big, but you don’t need to brute-force every possible point.

Set a reasonable stride, maybe half the smallest parcel size, and walk the map. Every time you hit a new parcel, save its geometry and skip future probes that land inside it. CPU cycles are cheap; spamming server requests is not.

Here's a toy demo using a simple sweep method: We step through the grid, probe each point, and color new parcels as they're found. Real-world ArcGIS geometries (with rings, holes, etc.) are trickier, but you get the idea.

function createRandomMap(width, height, N, svg) {
  svg.innerHTML = "";
  const points = Array.from({
    length: N
  }, () => [
    Math.random() * width,
    Math.random() * height,
  ]);
  const delaunay = d3.Delaunay.from(points);
  const voronoi = delaunay.voronoi([0, 0, width, height]);
  const polygons = [];
  const svgPolys = [];
  for (let i = 0; i < N; ++i) {
    const poly = voronoi.cellPolygon(i);
    polygons.push(poly);
    const el = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
    el.setAttribute('points', poly.map(([x, y]) => `${x},${y}`).join(' '));
    el.setAttribute('fill', '#fff');
    el.setAttribute('stroke', '#222');
    el.setAttribute('stroke-width', 1);
    svg.appendChild(el);
    svgPolys.push(el);
  }
  return [polygons, svgPolys];
}

// https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
function pointInPolygon(polygon, [x, y]) {
  let inside = false;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const [xi, yi] = polygon[i];
    const [xj, yj] = polygon[j];
    if (
      ((yi > y) !== (yj > y)) &&
      (x < ((xj - xi) * (y - yi)) / (yj - yi) + xi)
    ) inside = !inside;
  }
  return inside;
}

async function discoverParcels(polygons, svgPolys, width, height) {
  const discovered = new Set();
  const paletteGreens = t => `hsl(${100 + 30 * t}, 60%, ${40 + 25 * t}%)`;
  for (let y = 0; y < height; ++y) {
    for (let x = 0; x < width; ++x) {
      for (let i = 0; i < polygons.length; ++i) {
        if (!discovered.has(i) && pointInPolygon(polygons[i], [x + 0.5, y + 0.5])) {
          discovered.add(i);
          svgPolys[i].setAttribute('fill', paletteGreens(i / polygons.length));
          await new Promise(r => setTimeout(r, 100));
          break;
        }
      }
    }
  }
}

const width = 150,
  height = 150,
  N = 115;
const svg = document.getElementById('voronoi');
async function autoRunLoop() {
  while (true) {
    let polygons, svgPolys;
    [polygons, svgPolys] = createRandomMap(width, height, N, svg);
    await discoverParcels(polygons, svgPolys, width, height);
    await new Promise(r => setTimeout(r, 2000));
  }
}
autoRunLoop();
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://cdn.jsdelivr.net/npm/d3-delaunay@6"></script>
  <style>
    body {
      background: white;
    }
  </style>
</head>

<body>
  <svg id="voronoi" width="150" height="150"></svg>
</body>

</html>

Reasons:
  • Blacklisted phrase (1): How do you
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Low reputation (1):
Posted by: koal44