Skip to content

Commit

Permalink
clipPoint
Browse files Browse the repository at this point in the history
clipPoint = false is applied to all polyhedrals when the clip polygon covers (almost) the whole sphere

closes #4
  • Loading branch information
Fil committed Jun 16, 2024
1 parent d8e3737 commit b4f3646
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 23 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ const projection = d3.geoEquirectangular()

## API Reference

<a name="geoClipPolygon" href="#geoClipPolygon">#</a> d3.<b>geoClipPolygon</b>(<i>polygon</i>) · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/clip/polygon.js), [Examples](https://observablehq.com/@mbostock/spherical-clipping)
<a name="geoClipPolygon" href="#geoClipPolygon">#</a> d3.<b>geoClipPolygon</b>(<i>polygon</i>[, <i>options</i>]) · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/clip/polygon.js), [Examples](https://observablehq.com/@mbostock/spherical-clipping)

Given a GeoJSON *polygon* or *multipolygon*, returns a clip function suitable for [_projection_.preclip](https://github.com/d3/d3-geo#preclip).
Given a GeoJSON *polygon* or *multipolygon*, returns a clip function suitable for [_projection_.preclip](https://github.com/d3/d3-geo#preclip). The *options* argument is an optional object with (currently) one key: **clipPoint**. Set it to false to avoid clipping points.

<a name="polygon" href="#polygon">#</a> clip.<b>polygon</b>()

Expand All @@ -58,6 +58,8 @@ d3-geo-polygon adds polygon clipping to the polyhedral and interrupted projectio

Defines a new polyhedral projection. The *tree* is a spanning tree of polygon face nodes; each *node* is assigned a *node*.transform matrix. The *face* function returns the appropriate *node* for a given *lambda* and *phi* in radians.

Polyhedral projections’ default **clipPoint** option depends on whether the clipping polygon covers the whole sphere. When the polygon’s area is almost complete (larger than 4π minus .1 steradian), clipPoint is set to false, and all point geometries are displayed, even if they (technically) fall outside the clipping polygon. For smaller polygons, clipPoint defaults to true, thus hiding points outside the clipping region.

<a href="#geoPolyhedral_tree" name="geoPolyhedral_tree">#</a> <i>polyhedral</i>.<b>tree</b>() returns the spanning tree of the polyhedron, from which one can infer the faces’ centers, polygons, shared edges etc.

<a href="#geoPolyhedralButterfly" name="geoPolyhedralButterfly">#</a> d3.<b>geoPolyhedralButterfly</b>() · [Source](https://github.com/d3/d3-geo-polygon/blob/main/src/polyhedral/butterfly.js)
Expand Down
4 changes: 2 additions & 2 deletions src/clip/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {epsilon, halfPi} from "../math.js";
import polygonContains from "../polygonContains.js";
import {merge} from "d3-array";

export default function(pointVisible, clipLine, interpolate, start, sort) {
export default function(pointVisible, clipLine, interpolate, start, sort, {clipPoint = false} = {}) {
if (typeof sort === "undefined") sort = compareIntersection;

return function(sink) {
Expand Down Expand Up @@ -47,7 +47,7 @@ export default function(pointVisible, clipLine, interpolate, start, sort) {
};

function point(lambda, phi) {
if (pointVisible(lambda, phi)) sink.point(lambda, phi);
if ((!clipPoint && !ring) || pointVisible(lambda, phi)) sink.point(lambda, phi);
}

function pointLine(lambda, phi) {
Expand Down
19 changes: 6 additions & 13 deletions src/clip/polygon.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@ import polygonContains from "../polygonContains.js";
const clipNone = (stream) => stream;

// clipPolygon
export default function(geometry) {
export default function (geometry, options) {
function clipGeometry(geometry) {
let polygons;

if (geometry.type === "MultiPolygon") {
polygons = geometry.coordinates;
} else if (geometry.type === "Polygon") {
polygons = [geometry.coordinates];
} else {
return clipNone;
}

const clips = polygons.map((polygon) => {
if (geometry.type === "Polygon") geometry = {type: "MultiPolygon", coordinates: [geometry.coordinates]};
if (geometry.type !== "MultiPolygon") return clipNone;
const clips = geometry.coordinates.map((polygon) => {
polygon = polygon.map(ringRadians);
const pointVisible = visible(polygon);
const segments = ringSegments(polygon[0]); // todo holes?
Expand All @@ -28,7 +20,8 @@ export default function(geometry) {
clipLine(segments, pointVisible),
interpolate(segments, polygon),
polygon[0][0],
clipPolygonSort
clipPolygonSort,
options
);
});

Expand Down
11 changes: 6 additions & 5 deletions src/polyhedral/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {geoBounds as bounds, geoCentroid as centroid, geoInterpolate as interpolate, geoProjection as projection} from "d3-geo";
import {geoArea, geoBounds as bounds, geoCentroid as centroid, geoInterpolate as interpolate, geoProjection as projection} from "d3-geo";
import clipPolygon from "../clip/polygon.js";
import {abs, degrees, epsilon, radians} from "../math.js";
import matrix, {multiply, inverse} from "./matrix.js";
Expand Down Expand Up @@ -78,10 +78,11 @@ export default function(tree, face) {
const proj = projection(forward);

// run around the mesh of faces and stream all vertices to create the clipping polygon
const polygon = [];
outline({point: function(lambda, phi) { polygon.push([lambda, phi]); }}, tree);
polygon.push(polygon[0]);
proj.preclip(clipPolygon({ type: "Polygon", coordinates: [ polygon ] }));
const p = [];
const geometry = {type: "MultiPolygon", coordinates: [[p]]};
outline({point: (lambda, phi) => p.push([lambda, phi])}, tree);
p.push(p[0]);
proj.preclip(clipPolygon(geometry, {clipPoint: geoArea(geometry) < 4 * Math.PI - 0.1}));
proj.tree = function() { return tree; };

return proj;
Expand Down
55 changes: 54 additions & 1 deletion test/snapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { geoHomolosineRaw } from "d3-geo-projection";
import {
geoAirocean,
geoBerghaus,
geoClipPolygon,
geoCox,
geoCahillKeyes,
geoComplexLog,
Expand Down Expand Up @@ -33,7 +34,7 @@ import {
const width = 960;
const height = 500;

async function renderWorld(projection, { extent, clip = false } = {}) {
async function renderWorld(projection, { points, extent, clip = false } = {}) {
const graticule = geoGraticule();
const outline =
extent === undefined
Expand Down Expand Up @@ -66,6 +67,12 @@ async function renderWorld(projection, { extent, clip = false } = {}) {
path(outline);
context.strokeStyle = "#000";
context.stroke();
if (points) {
context.beginPath();
path({type: "MultiPoint", coordinates: points});
context.fillStyle = "steelblue";
context.fill();
}
return canvas;
}

Expand Down Expand Up @@ -279,3 +286,49 @@ export async function rhombicHalf2() {
.fitSize([960, 500], { type: "Sphere" })
);
}

// https://github.com/d3/d3-geo-polygon/issues/4
export async function clipPointWorld() {
return renderWorld(geoRhombic(), {points: [
[0, 0],
[10 - 0.0001, 0],
[10 + 0.0001, 0],
[10, -10],
[10, -20],
]});
}
export async function clipPointTrue() {
const projection = geoRhombic();
const polygon = projection.preclip().polygon();
projection.preclip(geoClipPolygon(polygon, {clipPoint: true}));
return renderWorld(projection, {points: [
[0, 0],
[10 - 0.0001, 0],
[10 + 0.0001, 0],
[10, -10],
[10, -20],
]});
}
export async function clipPointSmall() {
const projection = geoRhombic().parents([-1, 0, 6, 2, 1, 9, 11, 3, 4, 8, 6, 10]);
return renderWorld(projection, {points: [
[0, 0],
[10 - 0.0001, 0],
[10 + 0.0001, 0],
[10, -10],
[10, -20],
]});
}
export async function clipPointFalse() {
const projection = geoRhombic();
projection.preclip(geoClipPolygon(
geoRhombic().parents([-1, 0, 6, 2, 1, 9, 11, 3, 4, 8, 6, 10]).preclip().polygon(), {clipPoint: false})
);
return renderWorld(projection, {points: [
[0, 0],
[10 - 0.0001, 0],
[10 + 0.0001, 0],
[10, -10],
[10, -20],
]});
}
Binary file added test/snapshots/clipPointFalse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/clipPointSmall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/clipPointTrue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/clipPointWorld.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b4f3646

Please sign in to comment.