All, no clean code

This commit is contained in:
Tomas Richtar
2025-05-27 16:01:42 +02:00
parent 93601754d8
commit 3129ec1fea
9 changed files with 1637 additions and 24 deletions

740
Map.js Normal file
View File

@@ -0,0 +1,740 @@
mapboxgl.accessToken = 'pk.eyJ1Ijoib3V0ZG9vcm1hcHBpbmdjb21wYW55IiwiYSI6ImNqYmh3cDdjYzNsMnozNGxsYzlvMmk2bTYifQ.QqcZ4LVoLWnXafXdjZxnZg';
const map = new mapboxgl.Map({
container: 'map',
center: [20, 80],
zoom: 4
});
import * as turf from "@turf/turf";
import { getArrowPolygon } from "./Arrow.js";
import { ARROW_BODY_STYLE_CONSTANT, ARROW_BODY_STYLE_LINEAR, ARROW_BODY_STYLE_EXPONENTIAL } from "./Arrow.js";
import { getCirclePolygon } from "./BasicShapes.js";
import { getRectanglePolygon } from "./BasicShapes.js";
import { getFrontline } from "./Frontline.js";
import { LEFT_SIDE, RIGHT_SIDE, BOTH_SIDES } from "./Frontline.js";
// Polygon merge using Turf library
import {mergeTurfPolygons} from "./Polygon.js";
import {addTurfPolygonToMerge} from "./Polygon.js";
import {toTurfPolygon} from "./Polygon.js";
const circleCenter = {x:320, y:180};
const circleRadius = 70;
const circleDensity = 15;
const circleCenterB = {x:400, y:280};
const circleRadiusB = 70;
const circleDensityB = 15;
const rectangleCenter= {x:100, y:300};
const rectangleSideA = 70;
const rectangleSideB = 200;
const rectangleRotation = 40;
const frontlinePointsA = [
{ x: 120, y: 400 },
{ x: 200, y: 100 },
{ x: 350, y: 200 },
{ x: 350, y: 400 },
{ x: 450, y: 480 },
{ x: 550, y: 440 },
{ x: 600, y: 300 },
];
const frontlinePointsB = [
{ x: 420, y: 280 },
{ x: 430, y: 380 },
{ x: 500, y: 400 },
{ x: 520, y: 300 },
];
const frontlinePointsC = [
{ x: 450, y: 200 },
{ x: 500, y: 250 },
{ x: 550, y: 250 },
{ x: 550, y: 200 }
];
const frontlineDataA = {
points: frontlinePointsA,
splineStep: 0.08,
spacing: 10,
offsetDistance: 10,
protrusionLength: 15,
protrusionStartSize: 5,
protrusionEndSize: 2,
protrusionGap: 20,
style: LEFT_SIDE,
};
const frontlineDataB = {
points: frontlinePointsB,
splineStep: 0.02,
spacing: 10,
offsetDistance: 10,
protrusionLength: 15,
protrusionStartSize: 5,
protrusionEndSize: 5,
protrusionGap: 20,
style: RIGHT_SIDE,
};
const frontlineDataC = {
points: frontlinePointsC,
splineStep: 0.02,
spacing: 10,
offsetDistance: 10,
protrusionLength: 15,
protrusionStartSize: 5,
protrusionEndSize: 0,
protrusionGap: 20,
style: BOTH_SIDES,
};
/*
const arrowPolygonA = getArrowPolygon(arrowDataA, styleA, arrowHeadDataA);
const arrowPolygonB = getArrowPolygon(arrowDataB, styleB, arrowHeadDataB);
const arrowPolygonC = getArrowPolygon(arrowDataC, styleC);
const circlePolygon = getCirclePolygon(circleCenter, circleRadius, circleDensity);
const circlePolygonB = getCirclePolygon(circleCenterB, circleRadiusB, circleDensityB);
const rectanglePolygon = getRectanglePolygon(rectangleCenter, rectangleSideA, rectangleSideB, rectangleRotation);
const mergedTurfPoly = mergeTurfPolygons(arrowPolygonA, arrowPolygonC);
const mergedTurfPolyAll = addTurfPolygonToMerge(mergedTurfPoly, arrowPolygonB);
const mergedTurfPolyRectangle = addTurfPolygonToMerge(mergedTurfPolyAll, rectanglePolygon);
const mergedRectangle = mergeTurfPolygons(circlePolygon, circlePolygonB);
const rectanglePoly = getRectanglePolygon(circleCenter, rectangleSideA, rectangleSideB, rectangleRotation*-1);
const rectangleToTurfPoly = toTurfPolygon(rectanglePoly);
const frontlinePolygonA = getFrontline(frontlineDataA);
let frontlinePolygonMergedA = mergeTurfPolygons(frontlinePolygonA.body,frontlinePolygonA.protrusions[0]);
for (let i = 1; i < frontlinePolygonA.protrusions.length; i++)
{
frontlinePolygonMergedA = addTurfPolygonToMerge(frontlinePolygonMergedA, frontlinePolygonA.protrusions[i]);
}
const frontlinePolygonB = getFrontline(frontlineDataB);
let frontlinePolygonMergedB = mergeTurfPolygons(frontlinePolygonB.body,frontlinePolygonB.protrusions[0]);
for (let i = 1; i < frontlinePolygonB.protrusions.length; i++)
{
frontlinePolygonMergedB = addTurfPolygonToMerge(frontlinePolygonMergedB, frontlinePolygonB.protrusions[i]);
}
const frontlinePolygonC = getFrontline(frontlineDataC);
let frontlinePolygonMergedLeft = mergeTurfPolygons(frontlinePolygonC.bodyLeft, frontlinePolygonC.protrusionsLeft[0]);
for (let i = 1; i < frontlinePolygonC.protrusionsLeft.length; i++) {
frontlinePolygonMergedLeft = addTurfPolygonToMerge(frontlinePolygonMergedLeft, frontlinePolygonC.protrusionsLeft[i]);
}
let frontlinePolygonMergedRight = mergeTurfPolygons(frontlinePolygonC.bodyRight, frontlinePolygonC.protrusionsRight[0]);
for (let i = 1; i < frontlinePolygonC.protrusionsRight.length; i++) {
frontlinePolygonMergedRight = addTurfPolygonToMerge(frontlinePolygonMergedRight, frontlinePolygonC.protrusionsRight[i]);
}*/
//const circleGeoJSON = getCircleGeoJSON({x: 20, y: 80}, 2, 50, map);
const pointsB = [
{ x: 70, y: 38 },
{ x: 71, y: 45},
{ x: 65, y: 50 },
{ x: 70, y: 53}
];
const arrowDataB = {
points: pointsB,
splineStep: 0.01,
spacing: 0.01,
offsetDistance: 1
};
const styleB = {
calculation: ARROW_BODY_STYLE_LINEAR,
range: 1,
minValue: 0.1
};
const arrowHeadDataB = {
widthArrow: 1,
lengthArrow: 1
};
const arrowPolygonB = getArrowPolygon(arrowDataB, styleB, arrowHeadDataB);
const pointsC= [
{ x: 50, y: 38 },
{ x: 51, y: 45},
{ x: 45, y: 50 },
{ x: 48, y: 55}
];
const arrowDataC = {
points: pointsC,
splineStep: 0.02,
spacing: 1,
offsetDistance: 1
};
const styleC = {
calculation: ARROW_BODY_STYLE_LINEAR,
range: 1,
minValue: 0.1
};
const arrowHeadDataC = {
widthArrow: 1,
lengthArrow: 1
};
const arrowPolygonC = getArrowPolygon(arrowDataC, styleC, arrowHeadDataC);
const points = [
{ x: 80, y: 20 },
{ x: 81, y: 22},
{ x: 82, y: 28 },
{ x: 81, y: 30},
{ x: 80, y: 20}
];
// Turf polygon
const turfPolygon = turf.polygon([[
[20, 80],
[22, 81],
[28, 82],
[30, 81],
[20, 80]
]]);
const pointsA= [
{ x: 80, y: 38 },
{ x: 81, y: 45},
{ x: 75, y: 50 },
{ x: 78, y: 55}
];
const arrowDataA = {
points: pointsA,
splineStep: 0.2,
spacing: 3,
offsetDistance: 1
};
const styleA = {
calculation: ARROW_BODY_STYLE_LINEAR,
range: 1,
minValue: 0.1
};
const arrowHeadDataA = {
widthArrow: 1,
lengthArrow: 1
};
const arrowPolygonA = getArrowPolygon(arrowDataA, styleA, arrowHeadDataA);
const latLonGrid = generateLatLonGrid(5);
function createIsoscelesTriangle(center, baseLengthMeters, heightMeters, bearing = 0) {
const halfBase = baseLengthMeters / 2;
// Výpočet bodů základny (levý a pravý bod)
const leftBase = turf.destination(center, halfBase, bearing - 90, { units: 'meters' });
const rightBase = turf.destination(center, halfBase, bearing + 90, { units: 'meters' });
// Výpočet vrcholu trojúhelníku směr daný bearing (nahoru např. 0°)
const apex = turf.destination(center, heightMeters, bearing, { units: 'meters' });
const triangle = turf.polygon([[
leftBase.geometry.coordinates,
rightBase.geometry.coordinates,
apex.geometry.coordinates,
leftBase.geometry.coordinates // Uzavření polygonu
]]);
return triangle;
}
function cubicInterpolate(p, x) {
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
}
function interpolatePointsCatmullRom(points, segments = 10) {
if (points.length < 2) return points;
const extended = [points[0], ...points, points[points.length - 1]];
const interpolated = [];
for (let i = 1; i < extended.length - 2; i++) {
for (let j = 0; j < segments; j++) {
const t = j / segments;
const lon = cubicInterpolate([extended[i - 1][0], extended[i][0], extended[i + 1][0], extended[i + 2][0]], t);
const lat = cubicInterpolate([extended[i - 1][1], extended[i][1], extended[i + 1][1], extended[i + 2][1]], t);
interpolated.push([lon, lat]);
}
}
interpolated.push(points[points.length - 1]);
return interpolated;
}
function computeSideOffsets(points, offsetMeters) {
const left = [];
const right = [];
for (let i = 1; i < points.length; i++) {
const prev = points[i - 1];
const curr = points[i];
const bearing = turf.bearing(turf.point(prev), turf.point(curr));
const leftOffset = turf.destination(turf.point(curr), offsetMeters, bearing - 90, { units: 'meters' });
const rightOffset = turf.destination(turf.point(curr), offsetMeters, bearing + 90, { units: 'meters' });
left.push(leftOffset.geometry.coordinates);
right.push(rightOffset.geometry.coordinates);
}
return { left, right };
}
function createIsoscelesTriangleCoords(center, baseLengthMeters, heightMeters, bearing) {
const halfBase = baseLengthMeters / 2;
const left = turf.destination(center, halfBase, bearing - 90, { units: 'meters' }).geometry.coordinates;
const right = turf.destination(center, halfBase, bearing + 90, { units: 'meters' }).geometry.coordinates;
const tip = turf.destination(center, heightMeters, bearing, { units: 'meters' }).geometry.coordinates;
console.log("Aktuální bod:", left);
console.log("Aktuální bod:", right);
console.log("Aktuální bod:", tip);
return [left, right, tip];
}
function drawArrowPolygon(map, basePoints, offset = 10000) {
const smooth = interpolatePointsCatmullRom(basePoints, 20);
const { leftSidePoints, rightSidePoints } = computeSidesWGS84(smooth, offset);
console.log("Aktuální bod:", tip);
const end = smooth[smooth.length - 1];
const prev = smooth[smooth.length - 2];
const bearing = turf.bearing(turf.point(prev), turf.point(end));
const triangleCoords = createIsoscelesTriangleCoords(turf.point(end), offset * 2, offset * 3, bearing);
const polygonCoords = [
...leftSidePoints,
...triangleCoords,
...rightSidePoints.reverse(),
leftSidePoints[0]
];
const fullPolygon = turf.polygon([[...polygonCoords]]);
map.addSource("arrow-shape", {
type: "geojson",
data: fullPolygon
});
map.addLayer({
id: "arrow-shape",
type: "fill",
source: "arrow-shape",
paint: {
"fill-color": "#ff0000",
"fill-opacity": 0.7
}
});
}
function computeSidesWGS84(points, offsetDistanceMeters = 1000) {
const leftSidePoints = [];
const rightSidePoints = [];
for (let i = 1; i < points.length; i++) {
const prev = points[i - 1];
const curr = points[i];
const bearing = turf.bearing(turf.point(prev), turf.point(curr));
const leftBearing = bearing - 90;
const rightBearing = bearing + 90;
const leftPoint = turf.destination(turf.point(curr), offsetDistanceMeters, leftBearing, { units: 'meters' });
const rightPoint = turf.destination(turf.point(curr), offsetDistanceMeters, rightBearing, { units: 'meters' });
leftSidePoints.push(leftPoint.geometry.coordinates);
rightSidePoints.push(rightPoint.geometry.coordinates);
}
// První bod
const first = points[0];
const second = points[1];
const initialBearing = turf.bearing(turf.point(first), turf.point(second));
const leftInitial = turf.destination(turf.point(first), offsetDistanceMeters, initialBearing - 90, { units: 'meters' });
const rightInitial = turf.destination(turf.point(first), offsetDistanceMeters, initialBearing + 90, { units: 'meters' });
leftSidePoints.unshift(leftInitial.geometry.coordinates);
rightSidePoints.unshift(rightInitial.geometry.coordinates);
console.log("Aktuální bod:", leftSidePoints);
console.log("Aktuální bod:", rightSidePoints);
return {
leftSidePoints,
rightSidePoints
};
}
function drawSideLines(map, sides, prefix = "arrow-side") {
map.addSource(`${prefix}-left`, {
type: "geojson",
data: turf.lineString(sides.leftSidePoints)
});
map.addLayer({
id: `${prefix}-left`,
type: "line",
source: `${prefix}-left`,
paint: {
"line-color": "blue",
"line-width": 2
}
});
map.addSource(`${prefix}-right`, {
type: "geojson",
data: turf.lineString(sides.rightSidePoints)
});
map.addLayer({
id: `${prefix}-right`,
type: "line",
source: `${prefix}-right`,
paint: {
"line-color": "green",
"line-width": 2
}
});
}
function drawSmoothLineThroughPoints(map, points, lineId = "smooth-line") {
const smoothPoints = interpolatePointsCatmullRom(points, 20);
const line = turf.lineString(smoothPoints);
map.addSource(lineId, {
type: "geojson",
data: line
});
map.addLayer({
id: lineId,
type: "line",
source: lineId,
paint: {
"line-color": "red",
"line-width": 3
}
});
// Boční linie
const sides = computeSidesWGS84(smoothPoints, 10000); // 10 km offset
drawSideLines(map, sides, lineId + "-sides");
// Šipka na konci
const lastPoint = smoothPoints[smoothPoints.length - 1];
const secondLastPoint = smoothPoints[smoothPoints.length - 2];
const bearing = turf.bearing(turf.point(secondLastPoint), turf.point(lastPoint));
const triangle = createIsoscelesTriangle(turf.point(lastPoint), 60000, 80000, bearing); // 20km základna, 30km výška
map.addSource(lineId + "-arrow", {
type: "geojson",
data: triangle
});
map.addLayer({
id: lineId + "-arrow",
type: "fill",
source: lineId + "-arrow",
paint: {
"fill-color": "#ff0000",
"fill-opacity": 0.7
}
});
}
map.on('load', () => {
const points = [
[14.42076, 50.08804], // Praha
[15.0, 50.0],
[16.3725, 48.2082], // Vídeň
[17.0, 49.0],
[13.4050, 52.52] // Berlín
];
function createIsoscelesTriangle(center, baseLengthMeters, heightMeters, bearing = 0) {
const halfBase = baseLengthMeters / 2;
const leftBase = turf.destination(center, halfBase, bearing - 90, { units: 'meters' });
const rightBase = turf.destination(center, halfBase, bearing + 90, { units: 'meters' });
const apex = turf.destination(center, heightMeters, bearing, { units: 'meters' });
return turf.polygon([[
leftBase.geometry.coordinates,
rightBase.geometry.coordinates,
apex.geometry.coordinates,
leftBase.geometry.coordinates
]]);
}
const center = turf.point([52.95, 69.95]); // výchozí střed základny
// Vytvoř polygon trojúhelníku
const triangle = createIsoscelesTriangle(center, 40000, 100000, 10); // 2 km základna, 1 km výška, směr 0° (na sever)
map.addSource("triangle", {
type: "geojson",
data: triangle
});
map.addLayer({
id: "triangle",
type: "fill",
source: "triangle",
paint: {
"fill-color": "purple",
"fill-opacity": 0.5
}
});
map.addLayer({
id: "triangle-outline",
type: "line",
source: "triangle",
paint: {
"line-color": "#000",
"line-width": 2
}
});
map.addSource("latLonGrid", {
type: "geojson",
data: latLonGrid
});
map.addLayer({
id: "latLonGrid",
type: "line",
source: "latLonGrid",
layout: {},
paint: {
"line-color": "#888",
"line-width": 1,
"line-opacity": 0.5
}
});
// Generuj GeoJSON pro kruh
const circleGeoJSON = getCirclePolygon([20, 80], 120, 20);
const circle = turf.circle([20, 80], 120000, { units: "meters", steps: 64 });
const rectangleGeoJSON = getRectanglePolygon([20, 80], 2200, 2200);
const fsdafds = toTurfPolygon(points);
const arrowBGeoJSON = toTurfPolygon(arrowPolygonB);
const arrowCGeoJSON = toTurfPolygon(arrowPolygonC);
const arrowAGeoJSON = toTurfPolygon(arrowPolygonA);
//console.log(JSON.stringify(arrowAGeoJSON, null, 2));
// Arrow
// Přidání GeoJSON jako zdroj
map.addSource("arrowPolygonA", {
type: "geojson",
data: arrowAGeoJSON
});
// Vrstva pro výplň polygonu
map.addLayer({
id: "arrowPolygonA",
type: "fill",
source: "arrowPolygonA",
layout: {},
paint: {
"fill-color": "pink",
"fill-opacity": 0.6
}
});
// Vrstva pro obrys polygonu
map.addLayer({
id: "arrowPolygonA-outline",
type: "line",
source: "arrowPolygonA",
paint: {
"line-color": "#000",
"line-width": 3
}
});
// Arrow
// Přidání GeoJSON jako zdroj
map.addSource("arrowPolygonB", {
type: "geojson",
data: arrowBGeoJSON
});
// Vrstva pro výplň polygonu
map.addLayer({
id: "arrowPolygonB",
type: "fill",
source: "arrowPolygonB",
layout: {},
paint: {
"fill-color": "yellow",
"fill-opacity": 0.6
}
});
// Vrstva pro obrys polygonu
map.addLayer({
id: "arrowPolygonB-outline",
type: "line",
source: "arrowPolygonB",
paint: {
"line-color": "#000",
"line-width": 3
}
});
// Arrow
// Přidání GeoJSON jako zdroj
map.addSource("arrowPolygonC", {
type: "geojson",
data: arrowCGeoJSON
});
// Vrstva pro výplň polygonu
map.addLayer({
id: "arrowPolygonC",
type: "fill",
source: "arrowPolygonC",
layout: {},
paint: {
"fill-color": "yellow",
"fill-opacity": 0.6
}
});
// Vrstva pro obrys polygonu
map.addLayer({
id: "arrowPolygonC-outline",
type: "line",
source: "arrowPolygonC",
paint: {
"line-color": "#000",
"line-width": 3
}
});
// CIRCLE
// Přidání GeoJSON jako zdroj
map.addSource("circlePolygon", {
"type": "geojson",
"data": circleGeoJSON
});
// Přidání vrstvy pro vykreslení polygonu
map.addLayer({
"id": "circlePolygon",
"type": "fill",
"source": "circlePolygon",
"layout": {},
"paint": {
"fill-color": "blue",
"fill-opacity": 0.6
}
});
// Přidání outline pro polygon
map.addLayer({
"id": "circlePolygon-outline",
"type": "line",
"source": "circlePolygon",
"paint": {
"line-color": "#000",
"line-width": 3
}
});
// RECTANGLE
map.addSource("rectanglePolygon", {
"type": "geojson",
"data": rectangleGeoJSON
});
// Přidání vrstvy pro vykreslení polygonu
map.addLayer({
"id": "rectanglePolygon",
"type": "fill",
"source": "rectanglePolygon",
"layout": {},
"paint": {
"fill-color": "red",
"fill-opacity": 0.6
}
});
// Přidání outline pro polygon
map.addLayer({
"id": "rectanglePolygon-outline",
"type": "line",
"source": "rectanglePolygon",
"paint": {
"line-color": "#000",
"line-width": 3
}
});
});
function generateLatLonGrid(step = 10) {
const features = [];
// Rovnoběžky (latitudes)
for (let lat = -80; lat <= 80; lat += step) {
features.push({
type: "Feature",
geometry: {
type: "LineString",
coordinates: Array.from({ length: 37 }, (_, i) => [-180 + i * 10, lat])
},
properties: {
type: "latitude",
value: lat
}
});
}
// Poledníky (longitudes)
for (let lon = -180; lon <= 180; lon += step) {
features.push({
type: "Feature",
geometry: {
type: "LineString",
coordinates: Array.from({ length: 17 }, (_, i) => [lon, -80 + i * 10])
},
properties: {
type: "longitude",
value: lon
}
});
}
return {
type: "FeatureCollection",
features
};
}