mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
feat: completed orbit management
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
"short_name": "DCS Olympus",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./images/favicons/android-chrome-192x192.png",
|
||||
"src": "images/favicons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "./images/favicons/android-chrome-512x512.png",
|
||||
"src": "images/favicons/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
|
||||
34
frontend/react/src/map/markers/arrowmarker.ts
Normal file
34
frontend/react/src/map/markers/arrowmarker.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { DivIcon, LatLng } from "leaflet";
|
||||
import { CustomMarker } from "../markers/custommarker";
|
||||
import { SVGInjector } from "@tanem/svg-injector";
|
||||
|
||||
export class ArrowMarker extends CustomMarker {
|
||||
#bearing: number = 0;
|
||||
|
||||
constructor(latlng: LatLng) {
|
||||
super(latlng, { interactive: true, draggable: false });
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(
|
||||
new DivIcon({
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
className: "leaflet-arrow-marker",
|
||||
})
|
||||
);
|
||||
var div = document.createElement("div");
|
||||
var img = document.createElement("img");
|
||||
img.src = "images/others/arrow.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
div.classList.add("ol-arrow-icon");
|
||||
div.append(img);
|
||||
this.getElement()?.appendChild(div);
|
||||
}
|
||||
|
||||
setBearing(bearing: number) {
|
||||
this.#bearing = bearing;
|
||||
let img = this.getElement()?.querySelector("svg");
|
||||
if (img) img.style.transform = `rotate(${bearing}rad)`;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ export class ExplosionMarker extends CustomMarker {
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-explosion-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = "./images/markers/explosion.svg";
|
||||
img.src = "images/markers/explosion.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -28,7 +28,7 @@ export class SmokeMarker extends CustomMarker {
|
||||
el.classList.add("ol-smoke-icon");
|
||||
el.setAttribute("data-color", this.#color);
|
||||
var img = document.createElement("img");
|
||||
img.src = "./images/markers/smoke.svg";
|
||||
img.src = "images/markers/smoke.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -60,7 +60,7 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
var unitIcon = document.createElement("div");
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = `./images/units/map/${/*TODO getApp().getMap().getOptions().AWACSMode ? "awacs" :*/ "normal"}/${this.#coalition}/${blueprint.markerFile ?? blueprint.category}.svg`;
|
||||
img.src = `images/units/map/${/*TODO getApp().getMap().getOptions().AWACSMode ? "awacs" :*/ "normal"}/${this.#coalition}/${blueprint.markerFile ?? blueprint.category}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute("data-rotate-to-heading", false);
|
||||
@@ -78,7 +78,7 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
if (this.#headingHandle) {
|
||||
var handle = document.createElement("div");
|
||||
var handleImg = document.createElement("img");
|
||||
handleImg.src = "/images/others/arrow.svg";
|
||||
handleImg.src = "images/others/arrow.svg";
|
||||
handleImg.onload = () => SVGInjector(handleImg);
|
||||
handle.classList.add("heading-handle");
|
||||
el.append(handle);
|
||||
|
||||
@@ -253,4 +253,14 @@ path.leaflet-interactive:focus {
|
||||
|
||||
.pointer-cursor {
|
||||
cursor: url("/images/cursors/pointer.svg") 13 5, auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ol-arrow-icon svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.ol-arrow-icon svg path {
|
||||
fill: #FFFFFFAA;
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export class Airbase extends CustomMarker {
|
||||
el.classList.add("airbase-icon");
|
||||
el.setAttribute("data-object", "airbase");
|
||||
|
||||
this.#img.src = "./images/markers/airbase.svg";
|
||||
this.#img.src = "images/markers/airbase.svg";
|
||||
this.#img.onload = () => SVGInjector(this.#img);
|
||||
el.appendChild(this.#img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -23,7 +23,7 @@ export class Bullseye extends CustomMarker {
|
||||
el.classList.add("bullseye-icon");
|
||||
el.setAttribute("data-object", "bullseye");
|
||||
var img = document.createElement("img");
|
||||
img.src = "./images/markers/bullseye.svg";
|
||||
img.src = "images/markers/bullseye.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -488,6 +488,12 @@ export class ServerManager {
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
setRacetrack(ID: number, length: number, latlng: LatLng, bearing: number, callback: CallableFunction = () => {}) {
|
||||
var command = { ID: ID, location: latlng, bearing: bearing, length: length };
|
||||
var data = { setRacetrack: command };
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
setAdvancedOptions(
|
||||
ID: number,
|
||||
isActiveTanker: boolean,
|
||||
|
||||
@@ -94,7 +94,7 @@ export function LoginModal(props: { open: boolean }) {
|
||||
max-md:border-none
|
||||
`}
|
||||
>
|
||||
<img src="./images/splash/1.jpg" className={`
|
||||
<img src="images/splash/1.jpg" className={`
|
||||
contents-center w-full object-cover opacity-[7%]
|
||||
`}></img>
|
||||
<div
|
||||
@@ -154,7 +154,7 @@ export function LoginModal(props: { open: boolean }) {
|
||||
`}
|
||||
>
|
||||
<span className="size-[80px] min-w-14">
|
||||
<img src="./images/olympus-500x500.png" className={`
|
||||
<img src="images/olympus-500x500.png" className={`
|
||||
flex w-full
|
||||
`}></img>
|
||||
</span>
|
||||
@@ -360,7 +360,7 @@ export function LoginModal(props: { open: boolean }) {
|
||||
>
|
||||
<Card className="flex">
|
||||
<img
|
||||
src="./images/splash/1.jpg"
|
||||
src="images/splash/1.jpg"
|
||||
className={`
|
||||
h-[40%] max-h-[120px] contents-center w-full rounded-md
|
||||
object-cover
|
||||
@@ -385,7 +385,7 @@ export function LoginModal(props: { open: boolean }) {
|
||||
</Card>
|
||||
<Card className="flex">
|
||||
<img
|
||||
src="./images/splash/1.jpg"
|
||||
src="images/splash/1.jpg"
|
||||
className={`
|
||||
h-[40%] max-h-[120px] contents-center w-full rounded-md
|
||||
object-cover
|
||||
|
||||
@@ -75,7 +75,7 @@ export function Header() {
|
||||
dark:border-gray-800 dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
<img src="./images/icon.png" className={`my-auto h-10 w-10 rounded-md p-0`}></img>
|
||||
<img src="images/icon.png" className={`my-auto h-10 w-10 rounded-md p-0`}></img>
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
className={`
|
||||
|
||||
@@ -479,12 +479,12 @@ export function UnitSpawnMenu(props: {
|
||||
/>
|
||||
|
||||
<div className={`relative mr-3 h-[60px] w-[60px]`}>
|
||||
<img className="absolute" ref={compassRef} onMouseDown={handleMouseDown} src={"/images/others/arrow_background.png"}></img>
|
||||
<img className="absolute" ref={compassRef} onMouseDown={handleMouseDown} src={"images/others/arrow_background.png"}></img>
|
||||
<img
|
||||
className="absolute left-0"
|
||||
ref={compassRef}
|
||||
onMouseDown={handleMouseDown}
|
||||
src={"/images/others/arrow.png"}
|
||||
src={"images/others/arrow.png"}
|
||||
style={{
|
||||
width: "60px",
|
||||
height: "60px",
|
||||
|
||||
@@ -65,7 +65,7 @@ export function ServerOverlay() {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<img src="./images/olympus-500x500.png" className={`
|
||||
<img src="images/olympus-500x500.png" className={`
|
||||
absolute right-4 top-4 ml-auto flex h-24
|
||||
`}></img>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
computeBearingRangeString,
|
||||
adjustBrightness,
|
||||
bearingAndDistanceToLatLng,
|
||||
mToNm,
|
||||
} from "../other/utils";
|
||||
import { CustomMarker } from "../map/markers/custommarker";
|
||||
import { SVGInjector } from "@tanem/svg-injector";
|
||||
@@ -67,12 +66,14 @@ import {
|
||||
UnitSelectedEvent,
|
||||
UnitUpdatedEvent,
|
||||
} from "../events";
|
||||
import { CoalitionAreaHandle } from "../map/coalitionarea/coalitionareahandle";
|
||||
import { ArrowMarker } from "../map/markers/arrowmarker";
|
||||
|
||||
const bearingStrings = ["north", "north-east", "east", "south-east", "south", "south-west", "west", "north-west", "north"];
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: "./images/markers/marker-icon.png",
|
||||
shadowUrl: "./images/markers/marker-shadow.png",
|
||||
iconUrl: "images/markers/marker-icon.png",
|
||||
shadowUrl: "images/markers/marker-shadow.png",
|
||||
iconAnchor: [13, 41],
|
||||
});
|
||||
|
||||
@@ -171,9 +172,11 @@ export abstract class Unit extends CustomMarker {
|
||||
#detectionMethods: number[] = [];
|
||||
#trailPositions: LatLng[] = [];
|
||||
#trailPolylines: Polyline[] = [];
|
||||
#racetrackPolylines: Polyline[] = [new Polyline([]), new Polyline([])];
|
||||
#racetrackArcs: Polyline[] = [new Polyline([]), new Polyline([])];
|
||||
#anchorMarkers: Marker[];
|
||||
#racetrackPolylines: Polyline[] = [];
|
||||
#racetrackArcs: Polyline[] = [];
|
||||
#racetrackAnchorMarkers: CoalitionAreaHandle[] = [new CoalitionAreaHandle(new LatLng(0, 0)), new CoalitionAreaHandle(new LatLng(0, 0))];
|
||||
#racetrackArrow: ArrowMarker = new ArrowMarker(new LatLng(0, 0));
|
||||
#inhibitRacetrackDraw: boolean = false;
|
||||
|
||||
/* Inputs timers */
|
||||
#debounceTimeout: number | null = null;
|
||||
@@ -323,7 +326,7 @@ export abstract class Unit extends CustomMarker {
|
||||
getRaceTrackLength() {
|
||||
return this.#racetrackLength;
|
||||
}
|
||||
getRaceTrackAnchor() {
|
||||
getRaceTrackAnchor() {
|
||||
return this.#racetrackAnchor;
|
||||
}
|
||||
getRaceTrackBearing() {
|
||||
@@ -343,7 +346,7 @@ export abstract class Unit extends CustomMarker {
|
||||
this.ID = ID;
|
||||
|
||||
this.#pathPolyline = new Polyline([], {
|
||||
color: colors.STEEL_BLUE,
|
||||
color: colors.OLYMPUS_BLUE,
|
||||
weight: 3,
|
||||
opacity: 0.5,
|
||||
smoothFactor: 1,
|
||||
@@ -375,6 +378,33 @@ export abstract class Unit extends CustomMarker {
|
||||
bubblingMouseEvents: false,
|
||||
});
|
||||
|
||||
this.#racetrackPolylines = [
|
||||
new Polyline([], { color: colors.OLYMPUS_BLUE, weight: 3, opacity: 0.5, smoothFactor: 1 }),
|
||||
new Polyline([], { color: colors.OLYMPUS_BLUE, weight: 3, opacity: 0.5, smoothFactor: 1 }),
|
||||
];
|
||||
|
||||
this.#racetrackArcs = [
|
||||
new Polyline([], { color: colors.OLYMPUS_BLUE, weight: 3, opacity: 0.5, smoothFactor: 1 }),
|
||||
new Polyline([], { color: colors.OLYMPUS_BLUE, weight: 3, opacity: 0.5, smoothFactor: 1 }),
|
||||
];
|
||||
|
||||
this.#racetrackAnchorMarkers[0].on("drag", (e: any) => {
|
||||
this.#inhibitRacetrackDraw = true;
|
||||
this.#drawRacetrack();
|
||||
});
|
||||
|
||||
this.#racetrackAnchorMarkers[1].on("drag", (e: any) => {
|
||||
this.#inhibitRacetrackDraw = true;
|
||||
this.#drawRacetrack();
|
||||
});
|
||||
|
||||
this.#racetrackAnchorMarkers[0].on("dragend", (e: any) => {
|
||||
this.#applyRacetrackEdit();
|
||||
});
|
||||
this.#racetrackAnchorMarkers[1].on("dragend", (e: any) => {
|
||||
this.#applyRacetrackEdit();
|
||||
});
|
||||
|
||||
/* Leaflet events listeners */
|
||||
this.on("mouseup", (e: any) => this.#onMouseUp(e));
|
||||
this.on("mousedown", (e: any) => this.#onMouseDown(e));
|
||||
@@ -767,6 +797,8 @@ export abstract class Unit extends CustomMarker {
|
||||
|
||||
/* Trigger events after all (de-)selecting has been done */
|
||||
selected ? UnitSelectedEvent.dispatch(this) : UnitDeselectedEvent.dispatch(this);
|
||||
|
||||
this.#inhibitRacetrackDraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1339,6 +1371,10 @@ export abstract class Unit extends CustomMarker {
|
||||
if (!this.#human) getApp().getServerManager().setShotsIntensity(this.ID, shotsIntensity);
|
||||
}
|
||||
|
||||
setRacetrack(length: number, anchor: LatLng, bearing: number, callback: () => void) {
|
||||
if (!this.#human) getApp().getServerManager().setRacetrack(this.ID, length, anchor, bearing, callback);
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
onAdd(map: Map): this {
|
||||
super.onAdd(map);
|
||||
@@ -1687,13 +1723,18 @@ export abstract class Unit extends CustomMarker {
|
||||
for (let WP in this.#activePath) {
|
||||
var destination = this.#activePath[WP];
|
||||
var frozen = this.#pathMarkers[parseInt(WP)].options["freeze"];
|
||||
if (!this.#pathMarkers[parseInt(WP)].options["freeze"]) {
|
||||
if (!frozen) {
|
||||
this.#pathMarkers[parseInt(WP)].setLatLng([destination.lat, destination.lng]);
|
||||
}
|
||||
points.push(new LatLng(destination.lat, destination.lng));
|
||||
this.#pathPolyline.setLatLngs(points);
|
||||
}
|
||||
|
||||
/* Add racetrack anchor to the path, but only if we are an active tanker or AWACS */
|
||||
if (this.getState() !== UnitState.IDLE && (this.getIsActiveAWACS() || this.getIsActiveTanker()))
|
||||
points.push(this.#racetrackAnchor);
|
||||
|
||||
this.#pathPolyline.setLatLngs(points);
|
||||
|
||||
if (points.length == 1) this.#clearPath();
|
||||
} else {
|
||||
this.#clearPath();
|
||||
@@ -1712,63 +1753,100 @@ export abstract class Unit extends CustomMarker {
|
||||
|
||||
#drawRacetrack() {
|
||||
let groundspeed = this.#speed;
|
||||
|
||||
|
||||
// Determine racetrack length
|
||||
let racetrackLength = this.#racetrackLength;
|
||||
if (racetrackLength === 0) {
|
||||
if (this.getIsActiveTanker())
|
||||
racetrackLength = nmToM(50);
|
||||
else
|
||||
racetrackLength = this.#desiredSpeed * 30;
|
||||
if (this.getIsActiveTanker())
|
||||
racetrackLength = nmToM(50); // Default length for active tanker
|
||||
else racetrackLength = this.#desiredSpeed * 30; // Default length based on desired speed
|
||||
}
|
||||
|
||||
// Calculate the radius of the racetrack turns
|
||||
const radius = Math.pow(groundspeed, 2) / 9.81 / Math.tan(deg2rad(22.5));
|
||||
const point1 = this.#racetrackAnchor;
|
||||
const point2 = bearingAndDistanceToLatLng(point1.lat, point1.lng, this.#racetrackBearing, racetrackLength);
|
||||
|
||||
let point1;
|
||||
let point2;
|
||||
|
||||
// Determine the anchor points of the racetrack
|
||||
if (!this.#inhibitRacetrackDraw) {
|
||||
point1 = this.#racetrackAnchor;
|
||||
point2 = bearingAndDistanceToLatLng(point1.lat, point1.lng, this.#racetrackBearing, racetrackLength);
|
||||
} else {
|
||||
point1 = this.#racetrackAnchorMarkers[0].getLatLng();
|
||||
point2 = this.#racetrackAnchorMarkers[1].getLatLng();
|
||||
this.#racetrackBearing = deg2rad(bearing(point1.lat, point1.lng, point2.lat, point2.lng, false));
|
||||
this.#racetrackLength = point1.distanceTo(point2);
|
||||
}
|
||||
|
||||
// Calculate the other points of the racetrack
|
||||
const point3 = bearingAndDistanceToLatLng(point2.lat, point2.lng, this.#racetrackBearing - deg2rad(90), radius * 2);
|
||||
const point4 = bearingAndDistanceToLatLng(point1.lat, point1.lng, this.#racetrackBearing - deg2rad(90), radius * 2);
|
||||
const pointArrow = bearingAndDistanceToLatLng(point1.lat, point1.lng, this.#racetrackBearing, racetrackLength / 2);
|
||||
|
||||
// Calculate the centers of the racetrack turns
|
||||
const center1 = bearingAndDistanceToLatLng(point2.lat, point2.lng, this.#racetrackBearing - deg2rad(90), radius);
|
||||
const center2 = bearingAndDistanceToLatLng(point1.lat, point1.lng, this.#racetrackBearing - deg2rad(90), radius);
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackPolylines[0])) {
|
||||
this.#racetrackPolylines[0] = new Polyline([point1, point2]);
|
||||
this.#racetrackPolylines[0].addTo(getApp().getMap());
|
||||
} else {
|
||||
this.#racetrackPolylines[0].setLatLngs([point1, point2]);
|
||||
}
|
||||
// Draw or update the straight segments of the racetrack
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackPolylines[0])) this.#racetrackPolylines[0].addTo(getApp().getMap());
|
||||
this.#racetrackPolylines[0].setLatLngs([point1, point2]);
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackPolylines[1])) {
|
||||
this.#racetrackPolylines[1] = new Polyline([point3, point4]);
|
||||
this.#racetrackPolylines[1].addTo(getApp().getMap());
|
||||
} else {
|
||||
this.#racetrackPolylines[1].setLatLngs([point3, point4]);
|
||||
}
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackPolylines[1])) this.#racetrackPolylines[1].addTo(getApp().getMap());
|
||||
this.#racetrackPolylines[1].setLatLngs([point3, point4]);
|
||||
|
||||
const arc1Points: LatLng[] = [];
|
||||
const arc2Points: LatLng[] = [];
|
||||
|
||||
// Calculate the points for the racetrack arcs
|
||||
for (let theta = 0; theta <= 180; theta += 5) {
|
||||
arc1Points.push(bearingAndDistanceToLatLng(center1.lat, center1.lng, this.#racetrackBearing + deg2rad(theta - 90), radius));
|
||||
arc2Points.push(bearingAndDistanceToLatLng(center2.lat, center2.lng, this.#racetrackBearing + deg2rad(theta + 90), radius));
|
||||
}
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackArcs[0])) {
|
||||
this.#racetrackArcs[0] = new Polyline(arc1Points);
|
||||
this.#racetrackArcs[0].addTo(getApp().getMap());
|
||||
} else {
|
||||
this.#racetrackArcs[0].setLatLngs(arc1Points);
|
||||
// Draw or update the racetrack arcs
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackArcs[0])) this.#racetrackArcs[0].addTo(getApp().getMap());
|
||||
this.#racetrackArcs[0].setLatLngs(arc1Points);
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackArcs[1])) this.#racetrackArcs[1].addTo(getApp().getMap());
|
||||
|
||||
this.#racetrackArcs[1].setLatLngs(arc2Points);
|
||||
|
||||
// Update the positions of the racetrack anchor markers
|
||||
this.#racetrackAnchorMarkers[0].setLatLng(point1);
|
||||
this.#racetrackAnchorMarkers[1].setLatLng(point2);
|
||||
|
||||
// Add the racetrack anchor markers to the map if they are not already present
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackAnchorMarkers[0])) {
|
||||
this.#racetrackAnchorMarkers[0].addTo(getApp().getMap());
|
||||
}
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackArcs[1])) {
|
||||
this.#racetrackArcs[1] = new Polyline(arc2Points);
|
||||
this.#racetrackArcs[1].addTo(getApp().getMap());
|
||||
} else {
|
||||
this.#racetrackArcs[1].setLatLngs(arc2Points);
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackAnchorMarkers[1])) {
|
||||
this.#racetrackAnchorMarkers[1].addTo(getApp().getMap());
|
||||
}
|
||||
|
||||
if (!getApp().getMap().hasLayer(this.#racetrackArrow)) {
|
||||
this.#racetrackArrow.addTo(getApp().getMap());
|
||||
}
|
||||
this.#racetrackArrow.setLatLng(pointArrow);
|
||||
this.#racetrackArrow.setBearing(this.#racetrackBearing);
|
||||
}
|
||||
|
||||
#clearRacetrack() {
|
||||
this.#racetrackPolylines.forEach((polyline) => getApp().getMap().removeLayer(polyline));
|
||||
this.#racetrackArcs.forEach((arc) => getApp().getMap().removeLayer(arc));
|
||||
this.#racetrackAnchorMarkers.forEach((marker) => getApp().getMap().removeLayer(marker));
|
||||
this.#racetrackArrow.removeFrom(getApp().getMap());
|
||||
}
|
||||
|
||||
#applyRacetrackEdit() {
|
||||
const point1 = this.#racetrackAnchorMarkers[0].getLatLng();
|
||||
const point2 = this.#racetrackAnchorMarkers[1].getLatLng();
|
||||
const racetrackLength = point1.distanceTo(point2);
|
||||
const racetrackBearing = deg2rad(bearing(point1.lat, point1.lng, point2.lat, point2.lng, false));
|
||||
this.setRacetrack(racetrackLength, this.#racetrackAnchorMarkers[0].getLatLng(), racetrackBearing, () => {
|
||||
this.#inhibitRacetrackDraw = false;
|
||||
});
|
||||
}
|
||||
|
||||
#drawContacts() {
|
||||
|
||||
Reference in New Issue
Block a user