Skip to content

Commit c8b37e8

Browse files
authored
40% faster turf-area (#2520)
* Merge pull request #1387 from pirxpilot:area * Fix optimized ringArea * Regen nearest-neighbor-analysis * Add rest of out tests * update turf-area benchmark
1 parent a5f1495 commit c8b37e8

File tree

6 files changed

+49
-50
lines changed

6 files changed

+49
-50
lines changed

packages/turf-area/bench.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const fixtures = fs.readdirSync(directory).map((filename) => {
1717
/**
1818
* Benmark Results
1919
*
20-
* polygon x 3,240,248 ops/sec ±0.91% (90 runs sampled)
20+
* polygon x 8,510,024 ops/sec ±0.28% (96 runs sampled)
2121
*/
2222

2323
// Define benchmark

packages/turf-area/index.ts

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,24 @@ function polygonArea(coords: any) {
6767
return total;
6868
}
6969

70+
/**
71+
* @private
72+
* A constant factor used to compute the area of a polygon.
73+
* It's derived from the square of the Earth's radius divided by 2.
74+
*
75+
* @type {number}
76+
*/
77+
const FACTOR = (earthRadius * earthRadius) / 2;
78+
79+
/**
80+
* @private
81+
* A constant used for converting degrees to radians.
82+
* Represents the ratio of PI to 180.
83+
*
84+
* @type {number}
85+
*/
86+
const PI_OVER_180 = Math.PI / 180;
87+
7088
/**
7189
* @private
7290
* Calculate the approximate area of the polygon were it projected onto the earth.
@@ -80,46 +98,27 @@ function polygonArea(coords: any) {
8098
* @param {Array<Array<number>>} coords Ring Coordinates
8199
* @returns {number} The approximate signed geodesic area of the polygon in square meters.
82100
*/
83-
function ringArea(coords: number[][]) {
84-
let p1;
85-
let p2;
86-
let p3;
87-
let lowerIndex;
88-
let middleIndex;
89-
let upperIndex;
90-
let i;
91-
let total = 0;
101+
function ringArea(coords: number[][]): number {
92102
const coordsLength = coords.length;
93103

94-
if (coordsLength > 2) {
95-
for (i = 0; i < coordsLength; i++) {
96-
if (i === coordsLength - 2) {
97-
// i = N-2
98-
lowerIndex = coordsLength - 2;
99-
middleIndex = coordsLength - 1;
100-
upperIndex = 0;
101-
} else if (i === coordsLength - 1) {
102-
// i = N-1
103-
lowerIndex = coordsLength - 1;
104-
middleIndex = 0;
105-
upperIndex = 1;
106-
} else {
107-
// i = 0 to N-3
108-
lowerIndex = i;
109-
middleIndex = i + 1;
110-
upperIndex = i + 2;
111-
}
112-
p1 = coords[lowerIndex];
113-
p2 = coords[middleIndex];
114-
p3 = coords[upperIndex];
115-
total += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
116-
}
104+
if (coordsLength <= 2) return 0;
105+
let total = 0;
117106

118-
total = (total * earthRadius * earthRadius) / 2;
107+
let i = 0;
108+
while (i < coordsLength) {
109+
const lower = coords[i];
110+
const middle = coords[i + 1 === coordsLength ? 0 : i + 1];
111+
const upper =
112+
coords[i + 2 >= coordsLength ? (i + 2) % coordsLength : i + 2];
113+
114+
const lowerX = lower[0] * PI_OVER_180;
115+
const middleY = middle[1] * PI_OVER_180;
116+
const upperX = upper[0] * PI_OVER_180;
117+
118+
total += (upperX - lowerX) * Math.sin(middleY);
119+
120+
i++;
119121
}
120-
return total;
121-
}
122122

123-
function rad(num: number) {
124-
return (num * Math.PI) / 180;
123+
return total * FACTOR;
125124
}

packages/turf-nearest-neighbor-analysis/test/out/random-large-study-area.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,10 +1211,10 @@
12111211
"units": "kilometers",
12121212
"arealUnits": "kilometers²",
12131213
"observedMeanDistance": 1.6516270145942438,
1214-
"expectedMeanDistance": 25.461470908340697,
1215-
"nearestNeighborIndex": 0.06486769835646855,
1214+
"expectedMeanDistance": 25.46147090834068,
1215+
"nearestNeighborIndex": 0.0648676983564686,
12161216
"numberOfPoints": 150,
1217-
"zScore": -21.910362919163752
1217+
"zScore": -21.91036291916375
12181218
}
12191219
},
12201220
"geometry": {

packages/turf-nearest-neighbor-analysis/test/out/random-outlier.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,10 +1220,10 @@
12201220
"units": "kilometers",
12211221
"arealUnits": "kilometers²",
12221222
"observedMeanDistance": 7.363991103875287,
1223-
"expectedMeanDistance": 25.37702057977424,
1224-
"nearestNeighborIndex": 0.29018343901823007,
1223+
"expectedMeanDistance": 25.377020579774225,
1224+
"nearestNeighborIndex": 0.29018343901823024,
12251225
"numberOfPoints": 151,
1226-
"zScore": -16.68650889595032
1226+
"zScore": -16.686508895950315
12271227
}
12281228
},
12291229
"geometry": {

packages/turf-nearest-neighbor-analysis/test/out/random.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,10 +1217,10 @@
12171217
"units": "kilometers",
12181218
"arealUnits": "kilometers²",
12191219
"observedMeanDistance": 1.6516270145942438,
1220-
"expectedMeanDistance": 1.5869473002517003,
1221-
"nearestNeighborIndex": 1.0407573171032742,
1220+
"expectedMeanDistance": 1.5869473002516816,
1221+
"nearestNeighborIndex": 1.0407573171032865,
12221222
"numberOfPoints": 150,
1223-
"zScore": 0.9549532272328554
1223+
"zScore": 0.9549532272331418
12241224
}
12251225
},
12261226
"geometry": {

packages/turf-nearest-neighbor-analysis/test/out/squares.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,10 +1473,10 @@
14731473
"units": "kilometers",
14741474
"arealUnits": "kilometers²",
14751475
"observedMeanDistance": 4.986280150858801,
1476-
"expectedMeanDistance": 2.496567669388766,
1477-
"nearestNeighborIndex": 1.997254154973332,
1476+
"expectedMeanDistance": 2.4965676693887655,
1477+
"nearestNeighborIndex": 1.9972541549733325,
14781478
"numberOfPoints": 56,
1479-
"zScore": 14.27679589626176
1479+
"zScore": 14.276795896261763
14801480
}
14811481
},
14821482
"geometry": {

0 commit comments

Comments
 (0)