diff --git a/packages/turf-area/bench.js b/packages/turf-area/bench.js index 75c9e2995c..5daa8ac15e 100644 --- a/packages/turf-area/bench.js +++ b/packages/turf-area/bench.js @@ -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 diff --git a/packages/turf-area/index.ts b/packages/turf-area/index.ts index 8277d15303..d6bbfd1257 100644 --- a/packages/turf-area/index.ts +++ b/packages/turf-area/index.ts @@ -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. @@ -80,46 +98,27 @@ function polygonArea(coords: any) { * @param {Array>} 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; } diff --git a/packages/turf-nearest-neighbor-analysis/test/out/random-large-study-area.json b/packages/turf-nearest-neighbor-analysis/test/out/random-large-study-area.json index cc35013876..f66a328005 100644 --- a/packages/turf-nearest-neighbor-analysis/test/out/random-large-study-area.json +++ b/packages/turf-nearest-neighbor-analysis/test/out/random-large-study-area.json @@ -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": { diff --git a/packages/turf-nearest-neighbor-analysis/test/out/random-outlier.json b/packages/turf-nearest-neighbor-analysis/test/out/random-outlier.json index 9bf4d0d698..5425cbb31f 100644 --- a/packages/turf-nearest-neighbor-analysis/test/out/random-outlier.json +++ b/packages/turf-nearest-neighbor-analysis/test/out/random-outlier.json @@ -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": { diff --git a/packages/turf-nearest-neighbor-analysis/test/out/random.json b/packages/turf-nearest-neighbor-analysis/test/out/random.json index dc651e0471..78a0fb25c1 100644 --- a/packages/turf-nearest-neighbor-analysis/test/out/random.json +++ b/packages/turf-nearest-neighbor-analysis/test/out/random.json @@ -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": { diff --git a/packages/turf-nearest-neighbor-analysis/test/out/squares.json b/packages/turf-nearest-neighbor-analysis/test/out/squares.json index 745478f8fe..66efc1a2ad 100644 --- a/packages/turf-nearest-neighbor-analysis/test/out/squares.json +++ b/packages/turf-nearest-neighbor-analysis/test/out/squares.json @@ -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": {