Skip to content

Commit 0628607

Browse files
committed
Avoid flipping the hole in the walkthrough curtain
(closes #1674)
1 parent 09dcacf commit 0628607

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

modules/ui/intro/UiCurtain.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Extent, numClamp, vecAdd } from '@rapid-sdk/math';
1+
import { Extent, numClamp, vecAdd, vecLength } from '@rapid-sdk/math';
22
import { easeLinear } from 'd3-ease';
33
import { selection, select } from 'd3-selection';
44
import * as Polyclip from 'polyclip-ts';
@@ -232,7 +232,30 @@ export class UiCurtain {
232232

233233
const clipped = Polyclip.intersection([extentPolygon], [mapPolygon]);
234234
if (clipped?.length) {
235-
this._revealPolygon = clipped[0][0]; // Polyclip returns a multipolygon
235+
// Polyclip returns a MultiPolygon with outer ring wound "counterclockwise".
236+
// However it assumes that the input is GeoJSON, which has a coordinate system
237+
// where +y goes up. So when we work in screen coordinates where +y goes down,
238+
// we actually get a "clockwise" result and need to reverse it.
239+
const ring = clipped[0][0].reverse();
240+
241+
// Pick the point closest to the top-left corner to start the ring - Rapid#1674
242+
const len = ring.length - 1; // ring is closed, can skip last one
243+
let minDist = Infinity;
244+
let minIndex = 0;
245+
246+
for (let i = 0; i < len; i++) {
247+
const dist = vecLength(ring[i], [0, 0]);
248+
if (dist < minDist) {
249+
minDist = dist;
250+
minIndex = i;
251+
}
252+
}
253+
this._revealPolygon = [];
254+
for (let i = 0; i < len; i++) {
255+
const fromIndex = (i + minIndex) % len;
256+
this._revealPolygon[i] = ring[fromIndex];
257+
}
258+
this._revealPolygon.push(this._revealPolygon[0]); // close ring
236259
}
237260

238261
// A D3-selector selector or a DOMElement (in screen coordinates)

0 commit comments

Comments
 (0)