Spaces:
Runtime error
Runtime error
File size: 5,365 Bytes
66f237b 8c93eed 7e40962 8c93eed a5e71eb 2f322ce 66f237b 2f322ce 66f237b a5e71eb 66f237b 2f322ce 66f237b 2f322ce a5e71eb 66f237b a5e71eb 1d6d0dd c2a5a36 2f322ce c2a5a36 1d6d0dd c2a5a36 1d6d0dd c2a5a36 1d6d0dd c2a5a36 1d6d0dd c2a5a36 1d6d0dd 5e62073 59275a8 c2a5a36 1d6d0dd c2a5a36 a5e71eb 5e62073 59275a8 5e62073 a5e71eb 59275a8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import LatLon from 'geodesy/latlon-spherical.js';
// Haversine-based geodesic interpolator
function generateGeodesicPoints(lat1, lon1, lat2, lon2, numPoints = 512) {
/**
* Generates a series of points along the geodesic path between two geographic coordinates, using Haversine function.
* @returns {Array} An array of points, each represented as [latitude, longitude].
*/
const toRad = deg => deg * Math.PI / 180;
const toDeg = rad => rad * 180 / Math.PI;
const 蠁1 = toRad(lat1);
const 位1 = toRad(lon1);
const 蠁2 = toRad(lat2);
const 位2 = toRad(lon2);
const 螖 = 2 * Math.asin(
Math.sqrt(
Math.sin((蠁2 - 蠁1) / 2) ** 2 +
Math.cos(蠁1) * Math.cos(蠁2) *
Math.sin((位2 - 位1) / 2) ** 2
)
);
if (螖 === 0) return [[lat1, lon1]];
const sin螖 = Math.sin(螖);
const points = [];
for (let i = 0; i <= numPoints; i++) {
const f = i / numPoints;
const A = Math.sin((1 - f) * 螖) / sin螖;
const B = Math.sin(f * 螖) / sin螖;
const x = A * Math.cos(蠁1) * Math.cos(位1) + B * Math.cos(蠁2) * Math.cos(位2);
const y = A * Math.cos(蠁1) * Math.sin(位1) + B * Math.cos(蠁2) * Math.sin(位2);
const z = A * Math.sin(蠁1) + B * Math.sin(蠁2);
const 蠁i = Math.atan2(z, Math.sqrt(x * x + y * y));
const 位i = Math.atan2(y, x);
points.push([toDeg(蠁i), toDeg(位i)]);
}
return points;
}
function calculatePolygonArea(coords) {
if (!coords || coords.length < 3) return { area: 0, perimeter: 0 };
let area = 0;
let perimeter = 0;
const latlonPoints = coords.map(c => new LatLon(c[0], c[1]));
for (let i = 0; i < latlonPoints.length; i++) {
const p1 = latlonPoints[i];
const p2 = latlonPoints[(i + 1) % latlonPoints.length];
perimeter += p1.distanceTo(p2); // in meters
}
area = LatLon.areaOf(latlonPoints); // in square meters
return { "area":area, "perimeter": perimeter };
}
function getPolygonCentroid(points) {
// Simple centroid calculation for small polygons
let x = 0, y = 0, n = points.length;
points.forEach(([lat, lon]) => { x += lat; y += lon; });
return [x / n, y / n];
}
function formatArea(area, unit = 'sqm', format = "normal") {
if (typeof area !== 'number' || isNaN(area)) {
console.log('Invalid area input:', area);
return 'Invalid area';
}
let value;
switch (unit) {
case "km2":
value = area / 1e6;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' km虏';
case "ha":
value = area / 1e4;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' ha';
case "acres":
value = area / 4046.8564224;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' acres';
case "mi2":
value = area / 2589988.110336;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' mi虏';
case "sqft":
value = area * 10.76391041671;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' ft虏';
case "sqm":
default:
value = area;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' m虏';
}
}
function formatPerimeter(perimeter, unit = 'sqm', format = "normal") {
if (typeof perimeter !== 'number' || isNaN(perimeter)) {
console.log('Invalid perimeter input:', perimeter);
return 'Invalid perimeter';
}
let value;
switch (unit) {
case "km2":
case "ha":
value = perimeter / 1000;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' km';
case "mi2":
value = perimeter / 1609.344;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' mi';
case "sqft":
value = perimeter * 3.280839895013123; // meters to feet
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' ft';
case "m2":
default:
value = perimeter;
return (format === "scientific" ? value.toExponential(2) : value.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })) + ' m';
}
}
export {generateGeodesicPoints, calculatePolygonArea, getPolygonCentroid, formatArea, formatPerimeter}; |