StorymapperArrow/BasicShapes.js
2025-05-27 16:01:42 +02:00

138 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const distancePerDegreeLongitude = 111.320; // 2π×6378.1km/360
const distancePerDegreeLatitude = 110.574; // 2π×6356.75km/360
import * as turf from "@turf/turf";
import { toMercator, toWgs84 } from '@turf/projection';
/**
* @param {Object} center - The center point of the circle.
* @param {number} center.x
* @param {number} center.y
* @param {number} radius - The radius of the circle.
* @param {number} density - The number of points used to approximate the circle.
*
* @returns {Object} GeoJSON Feature representing the circle polygon.
*/
export function getCirclePolygon(center, radius, density = 64) {
const points = [];
const coords = {
latitude: center[1], // Latitude
longitude: center[0] // Longitude
};
const distanceX = radius / (distancePerDegreeLongitude * Math.cos(coords.latitude * Math.PI / 180));
const distanceY = radius / distancePerDegreeLatitude;
for (let i = 0; i < density; i++) {
const angle = (i / density) * Math.PI * 2;
const x = distanceX * Math.cos(angle);
const y = distanceY * Math.sin(angle);
points.push([coords.longitude + x, coords.latitude + y]);
}
// Close the circle by adding the first point again
points.push(points[0]);
return {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [points]
},
properties: {}
};
}
function getDistancePerDegreeLongitude(latitude) {
return 111.320 * Math.cos(latitude * Math.PI / 180);
}
/**
* @param {Object} center - The center point of the rectangle.
* @param {number} center.x
* @param {number} center.y
* @param {number} sideA - The length of the first side of the rectangle.
* @param {number} sideB - The length of the second side of the rectangle.
* @param {number} rotation - The angle (in radians) by which to rotate the rectangle.
*
* @returns {Object} GeoJSON Feature representing the rectangle polygon.
*/
export function getRectanglePolygon(center, width, height, rotation = 0) {
const widthMeters = width * 1000 ;
const heightMeters = height * 1000;
// 1. Střed převedeme do metrického systému (Web Mercator)
const centerMerc = toMercator(turf.point(center)).geometry.coordinates;
// 2. Vypočítáme rohy čtverce v metrech
const halfWidth = widthMeters / 2;
const halfHeight = heightMeters / 2;
let corners = [
[centerMerc[0] - halfWidth, centerMerc[1] + halfHeight], // topLeft
[centerMerc[0] + halfWidth, centerMerc[1] + halfHeight], // topRight
[centerMerc[0] + halfWidth, centerMerc[1] - halfHeight], // bottomRight
[centerMerc[0] - halfWidth, centerMerc[1] - halfHeight], // bottomLeft
];
// 3. Otočení (volitelně)
if (rotation !== 0) {
const rad = (rotation * Math.PI) / 180;
corners = corners.map(([x, y]) => rotateXY(x, y, centerMerc[0], centerMerc[1], rad));
}
// 4. Uzavřeme polygon a převedeme zpět do WGS84
corners.push(corners[0]);
const wgsCoords = corners.map(([x, y]) => toWgs84([x, y]));
return turf.polygon([wgsCoords]);
}
function rotateXY(x, y, cx, cy, angleRad) {
const dx = x - cx;
const dy = y - cy;
const cos = Math.cos(angleRad);
const sin = Math.sin(angleRad);
const rx = cx + dx * cos - dy * sin;
const ry = cy + dx * sin + dy * cos;
return [rx, ry];
}
/*
const [lon, lat] = center;
// Přepočet metrů na stupně:
const degLat = height / distancePerDegreeLatitude / 2;
const degLon = width / (distancePerDegreeLongitude * Math.cos(lat * Math.PI / 180)) / 2;
// Rohy bez rotace (v relative souřadnicích)
const corners = [
[-degLon, -degLat],
[ degLon, -degLat],
[ degLon, degLat],
[-degLon, degLat]
];
// Rotace a posun
const rotated = corners.map(([dx, dy]) => {
const x = dx;
const y = dy;
const rotatedX = x * Math.cos(rotation) - y * Math.sin(rotation);
const rotatedY = x * Math.sin(rotation) + y * Math.cos(rotation);
return [lon + rotatedX, lat + rotatedY];
});
// Uzavření polygonu
rotated.push(rotated[0]);
return {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [rotated]
},
properties: {}
};*/