d3 / d3-geo-polygon

Clipping and geometric operations for spherical polygons.
https://d3.observablehq.cloud/d3-geo-polygon/
Other
113 stars 23 forks source link

Legacy UMD bundle not working for re-clipped projections #74

Closed Fil closed 3 weeks ago

Fil commented 3 weeks ago

Because we reexport some projections (say, geoGingery) under the same name, when combining the UMD bundles for d3-geo-polygon and d3-geo-projection, we get either the unclipped projection from d3-geo-projection (if it was loaded after d3-geo-polygon), or a recursion loop (if it was loaded before).

If someone really cannot upgrade their environment to ESM and must have a reclipped gingery, they will have to manually copy the code from https://github.com/d3/d3-geo-polygon/blob/main/src/reclip.js

For example:

<script src="https://cdn.jsdelivr.net/npm/d3-array@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-geo@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-geo-polygon@2"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-geo-projection@3"></script>
<script>

function reclip(projection, vertical = false) {
  const {lobes} = projection;
  function reset(projection) {
    const rotate = projection.rotate();
    const scale = projection.scale();
    const translate = projection.translate();
    projection.rotate([0, 0]).translate([0, 0]);
    projection.lobes = function (_) {
      return !arguments.length ? lobes() : reset(lobes(_));
    };

    projection.preclip((stream) => stream); // clipNone
    const R = 1 - 1e-7;
    const Rx = vertical ? 1 : R;
    let points = [];
    projection
      .stream({
        point(x, y) {
          points.push([x * Rx, y * R]);
        },
        lineStart() {},
        lineEnd() {},
        polygonStart() {},
        polygonEnd() {},
        sphere() {},
      })
      .sphere();

    projection.scale(scale);
    points = points.map(projection.invert);
    points.push(points[0]);

    return projection
      .rotate(rotate)
      .translate(translate)
      .preclip(d3.geoClipPolygon({ type: "Polygon", coordinates: [points] }));
  }
  return reset(projection);
}

const projection = reclip(d3.geoGingery());

</script>

I added a footnote to the README (and have no plans to spend more time on this).