KerbalCalculations/src/gui/targetorbit.ts
2026-03-30 15:10:50 +02:00

112 lines
4.3 KiB
TypeScript

import type { Body } from "../calculations/constants";
import { extrapolateTrajectory, type OrbitalCoordinates } from "../calculations/orbit-calculations";
import type { ChangingStorageValue } from "../storage";
import { getCoordinatesFromParameters, getOrbitFromParameters, type OrbitalParameters } from "./common";
import { ManoeuvresGui } from "./manoeuvres";
import { OrbitalParametersGui } from "./orbit";
import type { FindBestTransferMessage, ProgressMessage } from "./worker";
export class TargetOrbitGui {
currentTime: ChangingStorageValue<number>;
body: ChangingStorageValue<Body>;
startingOrbitalParameters: ChangingStorageValue<OrbitalParameters>;
targetOrbitalParameters: ChangingStorageValue<OrbitalParameters>;
parentDiv: HTMLDivElement;
orbitGui: OrbitalParametersGui;
manoeuvresGui: ManoeuvresGui;
worker: Worker | null;
constructor(currentTime: ChangingStorageValue<number>, body: ChangingStorageValue<Body>, startingOrbitalParameters: ChangingStorageValue<OrbitalParameters>, targetOrbitalParameters: ChangingStorageValue<OrbitalParameters>) {
this.worker = null;
this.currentTime = currentTime;
this.body = body;
this.startingOrbitalParameters = startingOrbitalParameters;
this.targetOrbitalParameters = targetOrbitalParameters;
this.orbitGui = new OrbitalParametersGui(this.targetOrbitalParameters, "orbit");
this.manoeuvresGui = new ManoeuvresGui(true);
this.parentDiv = document.createElement("div");
let targetOrbitHeader = document.createElement("h3");
targetOrbitHeader.appendChild(document.createTextNode("Target orbit:"));
this.parentDiv.appendChild(targetOrbitHeader);
this.parentDiv.appendChild(this.orbitGui.parentDiv);
let searchButton = document.createElement("button");
searchButton.appendChild(document.createTextNode("Search for cheapest transfer"));
this.parentDiv.appendChild(searchButton);
let foundTransferHeader = document.createElement("h3");
foundTransferHeader.appendChild(document.createTextNode("Found transfer:"));
this.parentDiv.appendChild(foundTransferHeader);
this.parentDiv.appendChild(this.manoeuvresGui.parentDiv);
searchButton.addEventListener("click", () => {
if (this.worker !== null) {
this.worker.terminate();
this.worker = null;
searchButton.innerHTML = "Search for cheapest transfer";
} else {
searchButton.innerHTML = "Cancel search";
let currentTime = this.currentTime.getCurrentValue();
let startingOrbitalParameters = this.startingOrbitalParameters.getCurrentValue();
let targetOrbitalParameters = this.targetOrbitalParameters.getCurrentValue();
let body = this.body.getCurrentValue();
let startingCoordinates: OrbitalCoordinates | null = getCoordinatesFromParameters(startingOrbitalParameters, body);
let targetOrbit = getOrbitFromParameters(targetOrbitalParameters, body.radius);
let startingTime = Math.max(currentTime, startingOrbitalParameters.currentTimeAtReading);
if (startingTime > startingOrbitalParameters.currentTimeAtReading) {
let addedTime = startingTime - startingOrbitalParameters.currentTimeAtReading;
startingCoordinates = extrapolateTrajectory(addedTime, startingCoordinates, body);
}
if (startingCoordinates) {
this.worker = new Worker(new URL('./worker.ts', import.meta.url), {type: 'module'});
this.worker.addEventListener("message", event => {
let transferResponse = event.data as ProgressMessage;
if (transferResponse) {
if (transferResponse.finished) {
searchButton.innerHTML = "Search for cheapest transfer";
this.worker = null;
}
if (transferResponse.bestTransfer) {
transferResponse.bestTransfer.firstManoeuvre.time += currentTime;
transferResponse.bestTransfer.secondManoeuvre.time += currentTime;
}
this.manoeuvresGui.displayProgress(transferResponse);
}
});
let workerMessage: FindBestTransferMessage = {
type: "FindBestTransfer",
startingSituation: startingCoordinates,
targetOrbit: targetOrbit,
body: body
};
this.worker.postMessage(workerMessage);
} else {
let progressMessage: ProgressMessage = {
type: "ProgressMessage",
percentDone: 100,
finished: true,
bestDeltaV: null,
bestTransfer: null
};
this.manoeuvresGui.displayProgress(progressMessage);
}
}
});
}
}