Skip to content

Commit 5262c3d

Browse files
committed
Extract code into hasMultipleOuterRings()
1 parent 66741c3 commit 5262c3d

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

src/expression/evaluation_context.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Color} from './values';
22
import type {FormattedSection} from './types/formatted';
33
import type {GlobalProperties, Feature, FeatureState} from './index';
44
import {ICanonicalTileID} from '../tiles_and_coordinates';
5-
import {calculateSignedArea} from '../util/classify_rings';
5+
import {hasMultipleOuterRings} from '../util/classify_rings';
66

77
const geometryTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
88
const simpleGeometryType = {
@@ -63,18 +63,10 @@ class EvaluationContext {
6363
if (geometryType !== 'Polygon') {
6464
return `Multi${geometryType}`;
6565
}
66-
// Following https://github.com/mapbox/vector-tile-js/blob/77851380b63b07fd0af3d5a3f144cc86fb39fdd1/lib/vectortilefeature.js#L197
67-
for (let i = 0, ccw; i < len; i++) {
68-
const area = calculateSignedArea(geom[i]);
69-
if (area === 0) continue;
70-
if (ccw === undefined) {
71-
ccw = area < 0;
72-
} else if (ccw === area < 0) {
73-
// Same direction as the first ring -> a second outer ring
74-
return 'MultiPolygon';
75-
}
66+
if (hasMultipleOuterRings(geom)) {
67+
return 'MultiPolygon';
7668
}
77-
return geometryType;
69+
return 'Polygon';
7870
}
7971

8072
geometry() {

src/util/classify_rings.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function compareAreas(a: {area: number}, b: {area: number}) {
6060
* @param ring - Exterior or interior ring
6161
* @returns Signed area
6262
*/
63-
export function calculateSignedArea(ring: Point2D[]): number {
63+
function calculateSignedArea(ring: Point2D[]): number {
6464
let sum = 0;
6565
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
6666
p1 = ring[i];
@@ -69,3 +69,27 @@ export function calculateSignedArea(ring: Point2D[]): number {
6969
}
7070
return sum;
7171
}
72+
73+
/**
74+
* Returns if there are multiple outer rings.
75+
* The first ring is a outer ring. Its direction, cw or ccw, defines the direction of outer rings.
76+
*
77+
* @param rings - List of rings
78+
* @returns Are there multiple outer rings
79+
*/
80+
export function hasMultipleOuterRings(rings: Point2D[][]): boolean {
81+
// Following https://github.com/mapbox/vector-tile-js/blob/77851380b63b07fd0af3d5a3f144cc86fb39fdd1/lib/vectortilefeature.js#L197
82+
const len = rings.length;
83+
for (let i = 0, direction; i < len; i++) {
84+
const area = calculateSignedArea(rings[i]);
85+
if (area === 0) continue;
86+
if (direction === undefined) {
87+
// Keep the direction of the first ring
88+
direction = area < 0;
89+
} else if (direction === area < 0) {
90+
// Same direction as the first ring -> a second outer ring
91+
return true;
92+
}
93+
}
94+
return false;
95+
}

0 commit comments

Comments
 (0)