mirror of
https://github.com/Krafpy/KSP-MGA-Planner.git
synced 2025-12-12 07:40:41 -08:00
Added solar system selector.
This commit is contained in:
@@ -10,7 +10,7 @@ solarSystem:
|
||||
planetFarSize: 0.05 # size of planet sprites
|
||||
satFarSize: 0.04 # size of satellites sprites
|
||||
satDispRadii: 10 # minimum display distance of satellites (in radii of the scaled semi major axis)
|
||||
spriteDispSOIMul: 18 # minimum display distance of sprites (in multiple of the SOI of the body to which they are attached)
|
||||
spriteDispSOIMul: 18 # minimum display distance of sprites (in multiple of the SOI of the body to which they are attached)
|
||||
mouseFocusDst: 25 # minimum distance to between body on screen and mouse to set focus (in pixels)
|
||||
soiOpacity: 0.3 # the opacity of SOI spheres
|
||||
|
||||
8
data/systems.yml
Normal file
8
data/systems.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
# File keeping track of the list of solar systems in this data folder
|
||||
|
||||
- name: Stock
|
||||
folderName: stock
|
||||
|
||||
# Template:
|
||||
# - name: New Solar System
|
||||
# folderName: new-solar-system
|
||||
91
dist/main/editor/editor.js
vendored
91
dist/main/editor/editor.js
vendored
@@ -1,3 +1,5 @@
|
||||
import { SolarSystem } from "../objects/system.js";
|
||||
import { CameraController } from "../objects/camera.js";
|
||||
import { FlybySequenceGenerator } from "../solvers/sequence-solver.js";
|
||||
import { TimeSelector } from "./time-selector.js";
|
||||
import { ErrorMessage } from "./error-msg.js";
|
||||
@@ -12,7 +14,32 @@ import { FlybySequence } from "../solvers/sequence.js";
|
||||
import { Trajectory } from "../solvers/trajectory.js";
|
||||
import { Selector } from "./selector.js";
|
||||
import { DiscreteRange } from "./range.js";
|
||||
export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
import { loadBodiesData, loadConfig } from "../utilities/data.js";
|
||||
export async function initEditorWithSystem(systems, systemIndex) {
|
||||
const canvas = document.getElementById("three-canvas");
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
const config = await loadConfig(systems[systemIndex].folderName);
|
||||
const camera = new THREE.PerspectiveCamera(config.rendering.fov, width / height, config.rendering.nearPlane, config.rendering.farPlane);
|
||||
const scene = new THREE.Scene();
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: canvas });
|
||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
const bodiesData = await loadBodiesData(systems[systemIndex].folderName);
|
||||
const system = new SolarSystem(bodiesData.sun, bodiesData.bodies, config);
|
||||
system.fillSceneObjects(scene, canvas);
|
||||
const controls = new CameraController(camera, canvas, system, config);
|
||||
controls.targetBody = system.sun;
|
||||
let stop = false;
|
||||
let stopLoop = () => stop = true;
|
||||
const loop = () => {
|
||||
if (!stop)
|
||||
requestAnimationFrame(loop);
|
||||
controls.update();
|
||||
system.update(controls);
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
requestAnimationFrame(loop);
|
||||
const systemTime = new TimeSelector("system", config);
|
||||
const updateSystemTime = () => {
|
||||
systemTime.validate();
|
||||
@@ -30,6 +57,10 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
originSelector.select(config.editor.defaultOrigin);
|
||||
const destSelector = new BodySelector("destination-selector", system);
|
||||
destSelector.select(config.editor.defaultDest);
|
||||
const systemSelector = new Selector("system-selector");
|
||||
const optionNames = systems.map(s => s.name);
|
||||
systemSelector.fill(optionNames);
|
||||
systemSelector.select(systemIndex);
|
||||
{
|
||||
const maxSwingBys = new IntegerInput("max-swingbys");
|
||||
const maxResonant = new IntegerInput("max-resonant-swingbys");
|
||||
@@ -40,9 +71,11 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
maxSwingBys.assertValidity();
|
||||
maxResonant.assertValidity();
|
||||
maxBackLegs.assertValidity();
|
||||
if (originSelector.body.attractor.id != destSelector.body.attractor.id)
|
||||
const depBody = originSelector.body;
|
||||
const destBody = destSelector.body;
|
||||
if (depBody.attractor.id != destBody.attractor.id)
|
||||
throw new Error("Origin and destination bodies must orbit the same body.");
|
||||
if (originSelector.body.id == destSelector.body.id)
|
||||
if (depBody.id == destBody.id)
|
||||
throw new Error("Same origin and destination bodies.");
|
||||
};
|
||||
const generator = new FlybySequenceGenerator(system, config);
|
||||
@@ -66,6 +99,7 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
};
|
||||
const generateSequences = async () => {
|
||||
paramsErr.hide();
|
||||
systemSelector.disable();
|
||||
try {
|
||||
sequenceSelector.disable();
|
||||
sequenceSelector.clear();
|
||||
@@ -81,6 +115,7 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
}
|
||||
finally {
|
||||
progressMsg.hide();
|
||||
systemSelector.enable();
|
||||
}
|
||||
};
|
||||
new SubmitButton("sequence-btn").click(() => generateSequences());
|
||||
@@ -108,6 +143,7 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
detailsSelector.disable();
|
||||
stepSlider.disable();
|
||||
const getSpan = (id) => document.getElementById(id);
|
||||
const getDiv = (id) => document.getElementById(id);
|
||||
const resultItems = {
|
||||
dateSpan: getSpan("maneuvre-date"),
|
||||
progradeDVSpan: getSpan("prograde-delta-v"),
|
||||
@@ -123,43 +159,41 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
inclinationSpan: getSpan("flyby-inclination"),
|
||||
detailsSelector: detailsSelector,
|
||||
stepSlider: stepSlider,
|
||||
maneuverDiv: document.getElementById("maneuvre-details"),
|
||||
flybyDiv: document.getElementById("flyby-details")
|
||||
maneuverDiv: getDiv("maneuvre-details"),
|
||||
flybyDiv: getDiv("flyby-details")
|
||||
};
|
||||
const resetFoundTrajectory = () => {
|
||||
systemTime.input(updateSystemTime);
|
||||
deltaVPlot.reveal();
|
||||
detailsSelector.clear();
|
||||
detailsSelector.disable();
|
||||
stepSlider.disable();
|
||||
if (trajectory) {
|
||||
if (trajectory)
|
||||
trajectory.remove();
|
||||
}
|
||||
systemTime.input(updateSystemTime);
|
||||
};
|
||||
const displayFoundTrajectory = () => {
|
||||
trajectory = new Trajectory(solver.bestSteps, system, config);
|
||||
trajectory.draw(canvas);
|
||||
trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
detailsSelector.select(0);
|
||||
detailsSelector.enable();
|
||||
stepSlider.enable();
|
||||
systemTime.input(() => {
|
||||
updateSystemTime();
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
});
|
||||
detailsSelector.select(0);
|
||||
detailsSelector.enable();
|
||||
stepSlider.enable();
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
console.log(solver.bestDeltaV);
|
||||
};
|
||||
const findTrajectory = async () => {
|
||||
paramsErr.hide();
|
||||
systemSelector.disable();
|
||||
try {
|
||||
let sequence;
|
||||
if (customSequence.value == "") {
|
||||
sequence = sequenceSelector.sequence;
|
||||
}
|
||||
else {
|
||||
if (customSequence.value != "")
|
||||
sequence = FlybySequence.fromString(customSequence.value, system);
|
||||
}
|
||||
else
|
||||
sequence = sequenceSelector.sequence;
|
||||
updateAltitudeRange(depAltitude, sequence.bodies[0]);
|
||||
const seqLen = sequence.length;
|
||||
updateAltitudeRange(destAltitude, sequence.bodies[seqLen - 1]);
|
||||
@@ -180,8 +214,33 @@ export function initEditor(controls, system, config, canvas, stopLoop) {
|
||||
paramsErr.show(err);
|
||||
console.error(err);
|
||||
}
|
||||
finally {
|
||||
systemSelector.enable();
|
||||
}
|
||||
};
|
||||
new SubmitButton("search-btn").click(() => findTrajectory());
|
||||
new StopButton("search-stop-btn").click(() => solver.cancel());
|
||||
systemSelector.change((_, index) => {
|
||||
stopLoop();
|
||||
deltaVPlot.destroy();
|
||||
detailsSelector.clear();
|
||||
resultItems.maneuvreNumber.innerHTML = "--";
|
||||
resultItems.endDateSpan.innerHTML = "--";
|
||||
resultItems.dateSpan.innerHTML = "--";
|
||||
resultItems.normalDVSpan.innerHTML = "--";
|
||||
resultItems.radialDVSpan.innerHTML = "--";
|
||||
resultItems.depDateSpan.innerHTML = "--";
|
||||
resultItems.totalDVSpan.innerHTML = "--";
|
||||
resultItems.periAltitudeSpan.innerHTML = "--";
|
||||
resultItems.inclinationSpan.innerHTML = "--";
|
||||
for (let i = scene.children.length - 1; i >= 0; i--) {
|
||||
scene.remove(scene.children[i]);
|
||||
}
|
||||
camera.remove();
|
||||
scene.remove();
|
||||
renderer.dispose();
|
||||
controls.dispose();
|
||||
initEditorWithSystem(systems, index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
3
dist/main/editor/plot.js
vendored
3
dist/main/editor/plot.js
vendored
@@ -58,6 +58,9 @@ export class EvolutionPlot {
|
||||
this._chart.data.datasets[0].data = [];
|
||||
this._chart.data.datasets[1].data = [];
|
||||
}
|
||||
destroy() {
|
||||
this._chart.destroy();
|
||||
}
|
||||
reveal() {
|
||||
this._container.hidden = false;
|
||||
}
|
||||
|
||||
6
dist/main/main.js
vendored
6
dist/main/main.js
vendored
@@ -1,12 +1,14 @@
|
||||
import { initPageWithSystem } from "./page.js";
|
||||
import { initEditorWithSystem } from "./editor/editor.js";
|
||||
import { loadSystemsList } from "./utilities/data.js";
|
||||
import { SpriteManager } from "./utilities/sprites.js";
|
||||
import { WorkerManager } from "./utilities/worker.js";
|
||||
window.onload = main;
|
||||
async function main() {
|
||||
const systems = await loadSystemsList();
|
||||
await SpriteManager.loadSpriteMaterials();
|
||||
const path = "dist/dedicated-workers/";
|
||||
WorkerManager.createPool(path + "trajectory-optimizer.js", "trajectory-optimizer");
|
||||
WorkerManager.createPool(path + "sequence-evaluator.js", "sequence-evaluator");
|
||||
WorkerManager.createWorker(path + "sequence-generator.js", "sequence-generator");
|
||||
initPageWithSystem();
|
||||
initEditorWithSystem(systems, 0);
|
||||
}
|
||||
|
||||
38
dist/main/page.js
vendored
38
dist/main/page.js
vendored
@@ -1,38 +0,0 @@
|
||||
import { initEditor } from "./editor/editor.js";
|
||||
import { SolarSystem } from "./objects/system.js";
|
||||
import { CameraController } from "./objects/camera.js";
|
||||
import { loadConfig, loadBodiesData } from "./utilities/data.js";
|
||||
export async function initPageWithSystem() {
|
||||
const canvas = document.getElementById("three-canvas");
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
const config = await loadConfig();
|
||||
const camera = new THREE.PerspectiveCamera(config.rendering.fov, width / height, config.rendering.nearPlane, config.rendering.farPlane);
|
||||
const scene = new THREE.Scene();
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: canvas });
|
||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
const bodiesData = await loadBodiesData();
|
||||
const system = new SolarSystem(bodiesData.sun, bodiesData.bodies, config);
|
||||
system.fillSceneObjects(scene, canvas);
|
||||
const controls = new CameraController(camera, canvas, system, config);
|
||||
controls.targetBody = system.sun;
|
||||
let stop = false;
|
||||
let stopLoop = () => stop = false;
|
||||
initEditor(controls, system, config, canvas, stopLoop);
|
||||
const loop = () => {
|
||||
controls.update();
|
||||
system.update(controls);
|
||||
renderer.render(scene, camera);
|
||||
if (!stop) {
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
export function clearWindow(scene) {
|
||||
for (let i = scene.children.length - 1; i >= 0; i--) {
|
||||
const obj = scene.children[i];
|
||||
scene.remove(obj);
|
||||
}
|
||||
}
|
||||
13
dist/main/utilities/data.js
vendored
13
dist/main/utilities/data.js
vendored
@@ -3,16 +3,21 @@ async function readTextFile(path) {
|
||||
const text = await response.text();
|
||||
return text;
|
||||
}
|
||||
export async function loadBodiesData() {
|
||||
const content = await readTextFile("./data/kspbodies.yml");
|
||||
export async function loadBodiesData(systemFolder) {
|
||||
const content = await readTextFile(`./data/${systemFolder}/bodies.yml`);
|
||||
const data = jsyaml.load(content);
|
||||
return {
|
||||
sun: data[0],
|
||||
bodies: data.slice(1)
|
||||
};
|
||||
}
|
||||
export async function loadConfig() {
|
||||
const content = await readTextFile("./data/config.yml");
|
||||
export async function loadConfig(systemFolder) {
|
||||
const content = await readTextFile(`./data/${systemFolder}/config.yml`);
|
||||
const config = jsyaml.load(content);
|
||||
return config;
|
||||
}
|
||||
export async function loadSystemsList() {
|
||||
const content = await readTextFile("./data/systems.yml");
|
||||
const systems = jsyaml.load(content);
|
||||
return systems;
|
||||
}
|
||||
|
||||
@@ -204,9 +204,9 @@
|
||||
<input type="number" value="0" name="system-hour" id="system-hour">
|
||||
</div>
|
||||
</div>
|
||||
<p id="data-update">
|
||||
Uses data displayed on <a href="https://wiki.kerbalspaceprogram.com/wiki/Main_Page">KSP's wiki</a> on summer 2021
|
||||
</p>
|
||||
<select id="system-selector" name="system-selector">
|
||||
<!-- filled by JS -->
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<canvas id="three-canvas" width="750" height="550"></canvas>
|
||||
|
||||
@@ -15,8 +15,47 @@ import { Trajectory } from "../solvers/trajectory.js";
|
||||
import { Selector } from "./selector.js";
|
||||
import { DiscreteRange } from "./range.js";
|
||||
import { OrbitingBody } from "../objects/body.js";
|
||||
import { loadBodiesData, loadConfig } from "../utilities/data.js";
|
||||
|
||||
export function initEditor(controls: CameraController, system: SolarSystem, config: Config, canvas: HTMLCanvasElement, stopLoop: () => void){
|
||||
|
||||
export async function initEditorWithSystem(systems: SolarSystemData[], systemIndex: number){
|
||||
const canvas = document.getElementById("three-canvas") as HTMLCanvasElement;
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
|
||||
const config = await loadConfig(systems[systemIndex].folderName);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
config.rendering.fov,
|
||||
width / height,
|
||||
config.rendering.nearPlane,
|
||||
config.rendering.farPlane
|
||||
);
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({antialias: true, canvas: canvas});
|
||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
|
||||
const bodiesData = await loadBodiesData(systems[systemIndex].folderName);
|
||||
const system = new SolarSystem(bodiesData.sun, bodiesData.bodies, config);
|
||||
system.fillSceneObjects(scene, canvas);
|
||||
|
||||
const controls = new CameraController(camera, canvas, system, config);
|
||||
controls.targetBody = system.sun;
|
||||
|
||||
let stop = false;
|
||||
let stopLoop = () => stop = true;
|
||||
|
||||
const loop = () => {
|
||||
if(!stop) requestAnimationFrame(loop);
|
||||
controls.update();
|
||||
system.update(controls);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
|
||||
// Setting up solar system time control
|
||||
const systemTime = new TimeSelector("system", config);
|
||||
const updateSystemTime = () => {
|
||||
systemTime.validate();
|
||||
@@ -40,6 +79,13 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
originSelector.select(config.editor.defaultOrigin);
|
||||
const destSelector = new BodySelector("destination-selector", system);
|
||||
destSelector.select(config.editor.defaultDest);
|
||||
|
||||
// Init the solar system selector
|
||||
const systemSelector = new Selector("system-selector");
|
||||
const optionNames = systems.map(s => s.name);
|
||||
systemSelector.fill(optionNames);
|
||||
systemSelector.select(systemIndex);
|
||||
// callback is configured later
|
||||
|
||||
{
|
||||
// Sequence generation parameters
|
||||
@@ -53,11 +99,14 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
maxSwingBys.assertValidity();
|
||||
maxResonant.assertValidity();
|
||||
maxBackLegs.assertValidity();
|
||||
|
||||
if(originSelector.body.attractor.id != destSelector.body.attractor.id)
|
||||
|
||||
const depBody = originSelector.body;
|
||||
const destBody = destSelector.body;
|
||||
|
||||
if(depBody.attractor.id != destBody.attractor.id)
|
||||
throw new Error("Origin and destination bodies must orbit the same body.");
|
||||
|
||||
if(originSelector.body.id == destSelector.body.id)
|
||||
|
||||
if(depBody.id == destBody.id)
|
||||
throw new Error("Same origin and destination bodies.");
|
||||
}
|
||||
|
||||
@@ -73,7 +122,6 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
const percent = Math.floor(100 * generator.progression / generator.totalFeasible);
|
||||
progressMsg.setMessage(`Evaluation sequences : ${percent}%`);
|
||||
};
|
||||
|
||||
const params = {
|
||||
departureId: originSelector.body.id,
|
||||
destinationId: destSelector.body.id,
|
||||
@@ -82,20 +130,19 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
maxResonant: maxResonant.value,
|
||||
maxBackLegs: maxBackLegs.value,
|
||||
};
|
||||
|
||||
const sequences = await generator.generateFlybySequences(params, onProgress);
|
||||
sequenceSelector.fillFrom(sequences);
|
||||
}
|
||||
|
||||
const generateSequences = async () => {
|
||||
paramsErr.hide();
|
||||
systemSelector.disable();
|
||||
try {
|
||||
sequenceSelector.disable();
|
||||
sequenceSelector.clear();
|
||||
progressMsg.enable(1000);
|
||||
|
||||
assertSequenceInputs();
|
||||
|
||||
assertSequenceInputs();
|
||||
await runSequenceGeneration();
|
||||
|
||||
sequenceSelector.enable();
|
||||
@@ -107,6 +154,7 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
|
||||
} finally {
|
||||
progressMsg.hide();
|
||||
systemSelector.enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +200,7 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
stepSlider.disable();
|
||||
|
||||
const getSpan = (id: string) => document.getElementById(id) as HTMLSpanElement;
|
||||
const getDiv = (id: string) => document.getElementById(id) as HTMLDivElement;
|
||||
|
||||
const resultItems = {
|
||||
dateSpan: getSpan("maneuvre-date"),
|
||||
@@ -161,29 +210,24 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
depDateSpan: getSpan("result-departure-date") ,
|
||||
totalDVSpan: getSpan("result-total-delta-v"),
|
||||
maneuvreNumber: getSpan("maneuvre-number"),
|
||||
|
||||
flybyNumberSpan: getSpan("flyby-number"),
|
||||
startDateSpan: getSpan("flyby-start-date"),
|
||||
endDateSpan: getSpan("flyby-end-date"),
|
||||
periAltitudeSpan: getSpan("flyby-periapsis-altitude"),
|
||||
inclinationSpan: getSpan("flyby-inclination"),
|
||||
|
||||
detailsSelector: detailsSelector,
|
||||
stepSlider: stepSlider,
|
||||
|
||||
maneuverDiv: document.getElementById("maneuvre-details") as HTMLDivElement,
|
||||
flybyDiv: document.getElementById("flyby-details") as HTMLDivElement
|
||||
maneuverDiv: getDiv("maneuvre-details"),
|
||||
flybyDiv: getDiv("flyby-details")
|
||||
};
|
||||
|
||||
const resetFoundTrajectory = () => {
|
||||
systemTime.input(updateSystemTime);
|
||||
deltaVPlot.reveal();
|
||||
detailsSelector.clear();
|
||||
detailsSelector.disable();
|
||||
stepSlider.disable();
|
||||
if(trajectory){
|
||||
trajectory.remove();
|
||||
}
|
||||
systemTime.input(updateSystemTime);
|
||||
if(trajectory) trajectory.remove();
|
||||
}
|
||||
|
||||
const displayFoundTrajectory = () => {
|
||||
@@ -191,15 +235,14 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
trajectory.draw(canvas);
|
||||
trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
|
||||
detailsSelector.select(0);
|
||||
detailsSelector.enable();
|
||||
stepSlider.enable();
|
||||
|
||||
systemTime.input(() => {
|
||||
updateSystemTime();
|
||||
//@ts-ignore
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
});
|
||||
detailsSelector.select(0);
|
||||
detailsSelector.enable();
|
||||
stepSlider.enable();
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
|
||||
console.log(solver.bestDeltaV);
|
||||
@@ -207,13 +250,13 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
|
||||
const findTrajectory = async () => {
|
||||
paramsErr.hide();
|
||||
systemSelector.disable();
|
||||
try {
|
||||
let sequence: FlybySequence;
|
||||
if(customSequence.value == ""){
|
||||
sequence = sequenceSelector.sequence;
|
||||
} else {
|
||||
if(customSequence.value != "")
|
||||
sequence = FlybySequence.fromString(customSequence.value, system);
|
||||
}
|
||||
else
|
||||
sequence = sequenceSelector.sequence;
|
||||
|
||||
updateAltitudeRange(depAltitude, sequence.bodies[0]);
|
||||
const seqLen = sequence.length;
|
||||
@@ -241,11 +284,41 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
if(err instanceof Error && err.message != "TRAJECTORY FINDER CANCELLED")
|
||||
paramsErr.show(err);
|
||||
console.error(err);
|
||||
} finally {
|
||||
|
||||
systemSelector.enable();
|
||||
}
|
||||
};
|
||||
|
||||
// Trajectory solver buttons
|
||||
new SubmitButton("search-btn").click(() => findTrajectory());
|
||||
new StopButton("search-stop-btn").click(() => solver.cancel());
|
||||
|
||||
// Configure the system selector callback
|
||||
systemSelector.change((_, index) => {
|
||||
stopLoop();
|
||||
deltaVPlot.destroy();
|
||||
detailsSelector.clear();
|
||||
|
||||
resultItems.maneuvreNumber.innerHTML = "--";
|
||||
resultItems.endDateSpan.innerHTML = "--";
|
||||
resultItems.dateSpan.innerHTML = "--";
|
||||
resultItems.normalDVSpan.innerHTML = "--";
|
||||
resultItems.radialDVSpan.innerHTML = "--";
|
||||
resultItems.depDateSpan.innerHTML = "--";
|
||||
resultItems.totalDVSpan.innerHTML = "--";
|
||||
resultItems.periAltitudeSpan.innerHTML = "--";
|
||||
resultItems.inclinationSpan.innerHTML = "--";
|
||||
|
||||
for(let i = scene.children.length - 1; i >= 0; i--){
|
||||
scene.remove(scene.children[i]);
|
||||
}
|
||||
camera.remove();
|
||||
scene.remove();
|
||||
renderer.dispose();
|
||||
controls.dispose();
|
||||
|
||||
initEditorWithSystem(systems, index);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
export class EvolutionPlot {
|
||||
private readonly _chart!: Chart;
|
||||
private readonly _container!: HTMLDivElement;
|
||||
private readonly _chart!: Chart;
|
||||
private readonly _container!: HTMLDivElement;
|
||||
|
||||
private static _instance: EvolutionPlot;
|
||||
|
||||
constructor(canvasId: string){
|
||||
const data = {
|
||||
@@ -75,6 +77,10 @@ export class EvolutionPlot {
|
||||
this._chart.data.datasets[1].data = [];
|
||||
}
|
||||
|
||||
public destroy(){
|
||||
this._chart.destroy();
|
||||
}
|
||||
|
||||
public reveal(){
|
||||
this._container.hidden = false;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
|
||||
/*import { SolarSystem } from "./objects/system.js";
|
||||
import { FlybySequenceGenerator } from "./solvers/sequence-solver.js";
|
||||
import { TrajectorySolver } from "./solvers/trajectory-solver.js";
|
||||
import { Trajectory } from "./solvers/trajectory.js";*/
|
||||
import { initPageWithSystem } from "./page.js";
|
||||
import { initEditorWithSystem } from "./editor/editor.js";
|
||||
import { loadSystemsList } from "./utilities/data.js";
|
||||
import { SpriteManager } from "./utilities/sprites.js";
|
||||
import { WorkerManager } from "./utilities/worker.js";
|
||||
|
||||
window.onload = main;
|
||||
|
||||
async function main(){
|
||||
const systems = await loadSystemsList();
|
||||
|
||||
await SpriteManager.loadSpriteMaterials();
|
||||
|
||||
const path = "dist/dedicated-workers/";
|
||||
@@ -17,5 +16,5 @@ async function main(){
|
||||
WorkerManager.createPool(path + "sequence-evaluator.js", "sequence-evaluator");
|
||||
WorkerManager.createWorker(path + "sequence-generator.js", "sequence-generator");
|
||||
|
||||
initPageWithSystem();
|
||||
initEditorWithSystem(systems, 0);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { initEditor } from "./editor/editor.js";
|
||||
import { SolarSystem } from "./objects/system.js";
|
||||
import { CameraController } from "./objects/camera.js";
|
||||
import { loadConfig, loadBodiesData } from "./utilities/data.js";
|
||||
|
||||
export async function initPageWithSystem(){
|
||||
const canvas = document.getElementById("three-canvas") as HTMLCanvasElement;
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
|
||||
const config = await loadConfig();
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
config.rendering.fov,
|
||||
width / height,
|
||||
config.rendering.nearPlane,
|
||||
config.rendering.farPlane
|
||||
);
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({antialias: true, canvas: canvas});
|
||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
|
||||
const bodiesData = await loadBodiesData();
|
||||
const system = new SolarSystem(bodiesData.sun, bodiesData.bodies, config);
|
||||
system.fillSceneObjects(scene, canvas);
|
||||
|
||||
const controls = new CameraController(camera, canvas, system, config);
|
||||
controls.targetBody = system.sun;
|
||||
|
||||
let stop = false;
|
||||
let stopLoop = () => stop = false;
|
||||
|
||||
initEditor(controls, system, config, canvas, stopLoop);
|
||||
|
||||
const loop = () => {
|
||||
controls.update();
|
||||
system.update(controls);
|
||||
renderer.render(scene, camera);
|
||||
if(!stop){
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
export function clearWindow(scene: THREE.Scene){
|
||||
for(let i = scene.children.length - 1; i >= 0; i--) {
|
||||
const obj = scene.children[i];
|
||||
scene.remove(obj);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ async function readTextFile(path: string){
|
||||
return text;
|
||||
}
|
||||
|
||||
export async function loadBodiesData(){
|
||||
const content = await readTextFile("./data/kspbodies.yml");
|
||||
export async function loadBodiesData(systemFolder: string){
|
||||
const content = await readTextFile(`./data/${systemFolder}/bodies.yml`);
|
||||
const data = jsyaml.load(content) as object[];
|
||||
return {
|
||||
sun: data[0] as ICelestialBody,
|
||||
@@ -13,8 +13,14 @@ export async function loadBodiesData(){
|
||||
};
|
||||
}
|
||||
|
||||
export async function loadConfig(){
|
||||
const content = await readTextFile("./data/config.yml");
|
||||
export async function loadConfig(systemFolder: string){
|
||||
const content = await readTextFile(`./data/${systemFolder}/config.yml`);
|
||||
const config = jsyaml.load(content) as Config;
|
||||
return config;
|
||||
}
|
||||
|
||||
export async function loadSystemsList(){
|
||||
const content = await readTextFile("./data/systems.yml");
|
||||
const systems = jsyaml.load(content) as SolarSystemData[];
|
||||
return systems;
|
||||
}
|
||||
14
src/types.d.ts
vendored
14
src/types.d.ts
vendored
@@ -322,4 +322,18 @@ type DetailsSelectorOption = {
|
||||
index: number,
|
||||
type: "maneuver" | "flyby",
|
||||
origin: number
|
||||
};
|
||||
|
||||
type EditorParameters = {
|
||||
controls: CameraController,
|
||||
system: SolarSystem,
|
||||
config: Config,
|
||||
canvas: HTMLCanvasElement,
|
||||
stopLoop: () => void,
|
||||
systems: SolarSystemData[]
|
||||
};
|
||||
|
||||
type SolarSystemData = {
|
||||
name: string;
|
||||
folderName: string;
|
||||
};
|
||||
16
style.css
16
style.css
@@ -60,18 +60,18 @@ strong
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#data-update
|
||||
{
|
||||
font-weight: bold;
|
||||
color: rgba(255, 255, 255, 0.459);
|
||||
}
|
||||
|
||||
#canvas-top-bar
|
||||
{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#canvas-top-bar .time-selector
|
||||
{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Editor forms styles */
|
||||
@@ -236,10 +236,10 @@ input[type="text"]::placeholder
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
#custom-sequence-group
|
||||
/*#custom-sequence-group
|
||||
{
|
||||
margin-top: 25px;
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Editor forms' action buttons */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user