Skip to content

Commit

Permalink
40% faster turf-area (#2520)
Browse files Browse the repository at this point in the history
* Merge pull request #1387 from pirxpilot:area

* Fix optimized ringArea

* Regen nearest-neighbor-analysis

* Add rest of out tests

* update turf-area benchmark
  • Loading branch information
AminoffZ committed Nov 14, 2023
1 parent a5f1495 commit c8b37e8
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 50 deletions.
2 changes: 1 addition & 1 deletion packages/turf-area/bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const fixtures = fs.readdirSync(directory).map((filename) => {
/**
* Benmark Results
*
* polygon x 3,240,248 ops/sec ±0.91% (90 runs sampled)
* polygon x 8,510,024 ops/sec ±0.28% (96 runs sampled)
*/

// Define benchmark
Expand Down
73 changes: 36 additions & 37 deletions packages/turf-area/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ function polygonArea(coords: any) {
return total;
}

/**
* @private
* A constant factor used to compute the area of a polygon.
* It's derived from the square of the Earth's radius divided by 2.
*
* @type {number}
*/
const FACTOR = (earthRadius * earthRadius) / 2;

/**
* @private
* A constant used for converting degrees to radians.
* Represents the ratio of PI to 180.
*
* @type {number}
*/
const PI_OVER_180 = Math.PI / 180;

/**
* @private
* Calculate the approximate area of the polygon were it projected onto the earth.
Expand All @@ -80,46 +98,27 @@ function polygonArea(coords: any) {
* @param {Array<Array<number>>} coords Ring Coordinates
* @returns {number} The approximate signed geodesic area of the polygon in square meters.
*/
function ringArea(coords: number[][]) {
let p1;
let p2;
let p3;
let lowerIndex;
let middleIndex;
let upperIndex;
let i;
let total = 0;
function ringArea(coords: number[][]): number {
const coordsLength = coords.length;

if (coordsLength > 2) {
for (i = 0; i < coordsLength; i++) {
if (i === coordsLength - 2) {
// i = N-2
lowerIndex = coordsLength - 2;
middleIndex = coordsLength - 1;
upperIndex = 0;
} else if (i === coordsLength - 1) {
// i = N-1
lowerIndex = coordsLength - 1;
middleIndex = 0;
upperIndex = 1;
} else {
// i = 0 to N-3
lowerIndex = i;
middleIndex = i + 1;
upperIndex = i + 2;
}
p1 = coords[lowerIndex];
p2 = coords[middleIndex];
p3 = coords[upperIndex];
total += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
}
if (coordsLength <= 2) return 0;
let total = 0;

total = (total * earthRadius * earthRadius) / 2;
let i = 0;
while (i < coordsLength) {
const lower = coords[i];
const middle = coords[i + 1 === coordsLength ? 0 : i + 1];
const upper =
coords[i + 2 >= coordsLength ? (i + 2) % coordsLength : i + 2];

const lowerX = lower[0] * PI_OVER_180;
const middleY = middle[1] * PI_OVER_180;
const upperX = upper[0] * PI_OVER_180;

total += (upperX - lowerX) * Math.sin(middleY);

i++;
}
return total;
}

function rad(num: number) {
return (num * Math.PI) / 180;
return total * FACTOR;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1211,10 +1211,10 @@
"units": "kilometers",
"arealUnits": "kilometers²",
"observedMeanDistance": 1.6516270145942438,
"expectedMeanDistance": 25.461470908340697,
"nearestNeighborIndex": 0.06486769835646855,
"expectedMeanDistance": 25.46147090834068,
"nearestNeighborIndex": 0.0648676983564686,
"numberOfPoints": 150,
"zScore": -21.910362919163752
"zScore": -21.91036291916375
}
},
"geometry": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1220,10 +1220,10 @@
"units": "kilometers",
"arealUnits": "kilometers²",
"observedMeanDistance": 7.363991103875287,
"expectedMeanDistance": 25.37702057977424,
"nearestNeighborIndex": 0.29018343901823007,
"expectedMeanDistance": 25.377020579774225,
"nearestNeighborIndex": 0.29018343901823024,
"numberOfPoints": 151,
"zScore": -16.68650889595032
"zScore": -16.686508895950315
}
},
"geometry": {
Expand Down
6 changes: 3 additions & 3 deletions packages/turf-nearest-neighbor-analysis/test/out/random.json
Original file line number Diff line number Diff line change
Expand Up @@ -1217,10 +1217,10 @@
"units": "kilometers",
"arealUnits": "kilometers²",
"observedMeanDistance": 1.6516270145942438,
"expectedMeanDistance": 1.5869473002517003,
"nearestNeighborIndex": 1.0407573171032742,
"expectedMeanDistance": 1.5869473002516816,
"nearestNeighborIndex": 1.0407573171032865,
"numberOfPoints": 150,
"zScore": 0.9549532272328554
"zScore": 0.9549532272331418
}
},
"geometry": {
Expand Down
6 changes: 3 additions & 3 deletions packages/turf-nearest-neighbor-analysis/test/out/squares.json
Original file line number Diff line number Diff line change
Expand Up @@ -1473,10 +1473,10 @@
"units": "kilometers",
"arealUnits": "kilometers²",
"observedMeanDistance": 4.986280150858801,
"expectedMeanDistance": 2.496567669388766,
"nearestNeighborIndex": 1.997254154973332,
"expectedMeanDistance": 2.4965676693887655,
"nearestNeighborIndex": 1.9972541549733325,
"numberOfPoints": 56,
"zScore": 14.27679589626176
"zScore": 14.276795896261763
}
},
"geometry": {
Expand Down

0 comments on commit c8b37e8

Please sign in to comment.