From 7d19427d18ecb0df31ff7deada06340f047df847 Mon Sep 17 00:00:00 2001 From: Krafpy Date: Mon, 16 Aug 2021 13:39:41 +0200 Subject: [PATCH] Recompile and moved files. --- dist/main/editor/editor.js | 2 +- dist/main/editor/time-selector.js | 2 +- dist/main/editor/time.js | 65 ----- dist/main/main.js | 2 +- dist/main/objects/sequence.js | 17 -- dist/main/objects/trajectory.js | 159 ----------- dist/main/solvers/sequence-solver.js | 2 +- dist/main/solvers/sequence.js | 61 ----- dist/main/solvers/trajectory.js | 288 ++++++++++---------- dist/main/{objects => utilities}/time.js | 0 src/main/editor/editor.ts | 4 +- src/main/editor/sequence-selector.ts | 2 +- src/main/editor/time-selector.ts | 2 +- src/main/main.ts | 2 +- src/main/solvers/sequence-solver.ts | 2 +- src/main/{objects => solvers}/sequence.ts | 4 +- src/main/solvers/trajectory-solver.ts | 2 +- src/main/{objects => solvers}/trajectory.ts | 6 +- src/main/{objects => utilities}/time.ts | 0 19 files changed, 164 insertions(+), 458 deletions(-) delete mode 100644 dist/main/editor/time.js delete mode 100644 dist/main/objects/sequence.js delete mode 100644 dist/main/objects/trajectory.js rename dist/main/{objects => utilities}/time.js (100%) rename src/main/{objects => solvers}/sequence.ts (87%) rename src/main/{objects => solvers}/trajectory.ts (98%) rename src/main/{objects => utilities}/time.ts (100%) diff --git a/dist/main/editor/editor.js b/dist/main/editor/editor.js index 87bdb33..c952556 100644 --- a/dist/main/editor/editor.js +++ b/dist/main/editor/editor.js @@ -8,7 +8,7 @@ import { EvolutionPlot } from "./plot.js"; import { ProgressMessage } from "./progress-msg.js"; import { SequenceSelector } from "./sequence-selector.js"; import { SubmitButton, StopButton } from "./buttons.js"; -import { Trajectory } from "../objects/trajectory.js"; +import { Trajectory } from "../solvers/trajectory.js"; import { Selector } from "./selector.js"; import { DiscreteRange } from "./range.js"; export function initEditor(controls, system, config, canvas) { diff --git a/dist/main/editor/time-selector.js b/dist/main/editor/time-selector.js index 758bc63..cf5371b 100644 --- a/dist/main/editor/time-selector.js +++ b/dist/main/editor/time-selector.js @@ -1,4 +1,4 @@ -import { TimeAndDate } from "../objects/time.js"; +import { TimeAndDate } from "../utilities/time.js"; export class TimeSelector { constructor(namePrefix, config, autoValidate = false) { this.config = config; diff --git a/dist/main/editor/time.js b/dist/main/editor/time.js deleted file mode 100644 index 26931e8..0000000 --- a/dist/main/editor/time.js +++ /dev/null @@ -1,65 +0,0 @@ -export class TimeSelector { - constructor(namePrefix, config, autoValidate = false) { - this.config = config; - this.yearInput = document.getElementById(`${namePrefix}-year`); - this.dayInput = document.getElementById(`${namePrefix}-day`); - this.hourInput = document.getElementById(`${namePrefix}-hour`); - this.selector = document.getElementById(`${namePrefix}-time`); - if (autoValidate) { - this.selector.onchange = () => this.validate(); - } - } - get date() { - const { hoursPerDay, daysPerYear } = this.config.time; - const timeElapsed = this.validate(); - const days = timeElapsed.year * daysPerYear + timeElapsed.day; - const hours = days * hoursPerDay + timeElapsed.hour; - const date = hours * 3600; - return date; - } - change(action) { - this.selector.onchange = () => action(); - } - validate() { - const { hoursPerDay, daysPerYear } = this.config.time; - let year = parseInt(this.yearInput.value); - let day = parseInt(this.dayInput.value); - let hour = parseInt(this.hourInput.value); - if (isNaN(year) || isNaN(day) || isNaN(hour)) { - this.yearInput.value = "1"; - this.dayInput.value = "1"; - this.hourInput.value = "0"; - return { year: 0, day: 0, hour: 0 }; - } - year -= 1; - day -= 1; - const hpd = Math.round(hoursPerDay); - const dpy = Math.round(daysPerYear); - if (hour >= 0) { - day += Math.floor(hour / hpd); - } - else if (day > 0) { - day -= Math.floor((hpd - hour) / hpd); - hour = hpd - ((-hour) % hpd); - } - hour %= hpd; - if (day >= 0) { - year += Math.floor(day / dpy); - } - else if (year > 0) { - year -= Math.floor((dpy - day) / dpy); - day = dpy - ((-day) % dpy); - } - day %= dpy; - year = Math.max(0, year); - day = Math.max(0, day); - hour = Math.max(0, hour); - const timeElapsed = { year: year, day: day, hour: hour }; - year += 1; - day += 1; - this.yearInput.value = year.toString(); - this.dayInput.value = day.toString(); - this.hourInput.value = hour.toString(); - return timeElapsed; - } -} diff --git a/dist/main/main.js b/dist/main/main.js index 7097469..a5118d8 100644 --- a/dist/main/main.js +++ b/dist/main/main.js @@ -2,7 +2,7 @@ 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"; -import { Trajectory } from "./objects/trajectory.js"; +import { Trajectory } from "./solvers/trajectory.js"; window.onload = main; async function main() { const canvas = document.getElementById("three-canvas"); diff --git a/dist/main/objects/sequence.js b/dist/main/objects/sequence.js deleted file mode 100644 index 52da042..0000000 --- a/dist/main/objects/sequence.js +++ /dev/null @@ -1,17 +0,0 @@ -export class FlybySequence { - constructor(system, ids, cost) { - this.ids = ids; - this.cost = cost; - this.bodies = []; - for (const id of ids) { - this.bodies.push(system.bodyFromId(id)); - } - this.length = this.bodies.length; - const getSubstr = (i) => this.bodies[i].name.substring(0, 2); - let str = getSubstr(0); - for (let i = 1; i < this.length; i++) { - str += "-" + getSubstr(i); - } - this.seqString = str; - } -} diff --git a/dist/main/objects/trajectory.js b/dist/main/objects/trajectory.js deleted file mode 100644 index 80be70f..0000000 --- a/dist/main/objects/trajectory.js +++ /dev/null @@ -1,159 +0,0 @@ -import { createOrbitPoints, createLine, createSprite } from "../utilities/geometry.js"; -import { Orbit } from "./orbit.js"; -import { TimeAndDate } from "./time.js"; -export class Trajectory { - constructor(steps, system, config) { - this.steps = steps; - this.system = system; - this.config = config; - this.orbits = []; - this._objects = []; - this._maneuvres = []; - for (const { orbitElts, attractorId } of this.steps) { - const attractor = this.system.bodyFromId(attractorId); - const orbit = Orbit.fromOrbitalElements(orbitElts, attractor, config.orbit); - this.orbits.push(orbit); - } - } - static preloadArrowMaterial() { - const textureLoader = new THREE.TextureLoader(); - const loaded = (texture) => { - this.arrowMaterial = new THREE.SpriteMaterial({ - map: texture - }); - }; - textureLoader.load("sprites/arrow-512.png", loaded); - } - draw(resolution) { - this._createTrajectoryArcs(resolution); - this._createManeuvreSprites(); - this._calculateManeuvresDetails(); - } - _createTrajectoryArcs(resolution) { - const { lineWidth } = this.config.orbit; - const { samplePoints } = this.config.trajectoryDraw; - const { scale } = this.config.rendering; - for (let i = 0; i < this.orbits.length; i++) { - const orbit = this.orbits[i]; - const { beginAngle, endAngle } = this.steps[i]; - const orbitPoints = createOrbitPoints(orbit, samplePoints, scale, beginAngle, endAngle); - const color = new THREE.Color(`hsl(${i * 35 % 360}, 100%, 85%)`); - const orbitLine = createLine(orbitPoints, resolution, { - color: color.getHex(), - linewidth: lineWidth, - }); - const group = this.system.objectsOfBody(orbit.attractor.id); - group.add(orbitLine); - this._objects.push(orbitLine); - } - } - _createManeuvreSprites() { - const { maneuvreArrowSize } = this.config.trajectoryDraw; - const { scale } = this.config.rendering; - for (const step of this.steps) { - if (step.maneuvre) { - const group = this.system.objectsOfBody(step.attractorId); - const sprite = createSprite(Trajectory.arrowMaterial, 0xFFFFFF, false, maneuvreArrowSize); - const { x, y, z } = step.maneuvre.manoeuvrePosition; - sprite.position.set(x, y, z); - sprite.position.multiplyScalar(scale); - group.add(sprite); - this._objects.push(sprite); - } - } - } - _calculateManeuvresDetails() { - for (let i = 0; i < this.steps.length; i++) { - const step = this.steps[i]; - const { maneuvre } = step; - if (maneuvre) { - const orbit = this.orbits[i]; - const progradeDir = new THREE.Vector3(maneuvre.progradeDir.x, maneuvre.progradeDir.y, maneuvre.progradeDir.z); - const normalDir = orbit.normal.clone(); - const radialDir = progradeDir.clone(); - radialDir.cross(normalDir); - const deltaV = new THREE.Vector3(maneuvre.deltaVToPrevStep.x, maneuvre.deltaVToPrevStep.y, maneuvre.deltaVToPrevStep.z); - const details = { - stepIndex: i, - dateMET: step.dateOfStart - this.steps[0].dateOfStart, - progradeDV: progradeDir.dot(deltaV), - normalDV: normalDir.dot(deltaV), - radialDV: radialDir.dot(deltaV) - }; - this._maneuvres.push(details); - } - } - } - fillResultControls(maneuvreSelector, resultSpans, stepSlider, systemTime) { - const depDate = new TimeAndDate(this.steps[0].dateOfStart, this.config.time); - resultSpans.totalDVSpan.innerHTML = this._totalDeltaV.toFixed(1); - resultSpans.depDateSpan.innerHTML = depDate.stringYDHMS("hms", "date"); - resultSpans.depDateSpan.onclick = () => { - systemTime.time.dateSeconds = depDate.dateSeconds; - systemTime.update(); - systemTime.onChange(); - }; - stepSlider.setMinMax(0, this.steps.length - 1); - stepSlider.input((index) => this._displayStepsUpTo(index)); - stepSlider.value = this.steps.length - 1; - const selectorOptions = []; - for (let i = 0; i < this._maneuvres.length; i++) { - const details = this._maneuvres[i]; - const step = this.steps[details.stepIndex]; - const context = step.maneuvre.context; - if (context.type == "ejection") { - const startBodyName = this.system.bodyFromId(step.attractorId).name; - const optionName = `${i + 1}: ${startBodyName} escape`; - selectorOptions.push(optionName); - } - else { - const originName = this.system.bodyFromId(context.originId).name; - const targetName = this.system.bodyFromId(context.targetId).name; - const optionName = `${i + 1}: ${originName}-${targetName} DSM`; - selectorOptions.push(optionName); - } - } - maneuvreSelector.fill(selectorOptions); - maneuvreSelector.change((_, index) => { - const details = this._maneuvres[index]; - const dateEMT = new TimeAndDate(details.dateMET, this.config.time); - resultSpans.dateSpan.innerHTML = dateEMT.stringYDHMS("hm", "elapsed"); - resultSpans.progradeDVSpan.innerHTML = details.progradeDV.toFixed(1); - resultSpans.normalDVSpan.innerHTML = details.normalDV.toFixed(1); - resultSpans.radialDVSpan.innerHTML = details.radialDV.toFixed(1); - resultSpans.maneuvreNumber.innerHTML = (index + 1).toString(); - resultSpans.dateSpan.onclick = () => { - systemTime.time.dateSeconds = depDate.dateSeconds + dateEMT.dateSeconds; - systemTime.update(); - systemTime.onChange(); - }; - }); - } - _displayStepsUpTo(index) { - for (let i = 0; i < this.steps.length; i++) { - const orbitLine = this._objects[i]; - orbitLine.visible = i <= index; - } - const spritesStart = this.steps.length; - for (let i = 0; i < this._maneuvres.length; i++) { - const visible = this._objects[this._maneuvres[i].stepIndex].visible; - this._objects[spritesStart + i].visible = visible; - } - } - get _totalDeltaV() { - let total = 0; - for (const details of this._maneuvres) { - const x = details.progradeDV; - const y = details.normalDV; - const z = details.radialDV; - total += new THREE.Vector3(x, y, z).length(); - } - return total; - } - remove() { - for (const object of this._objects) { - if (object.parent) - object.parent.remove(object); - } - } -} diff --git a/dist/main/solvers/sequence-solver.js b/dist/main/solvers/sequence-solver.js index bd55a57..bc881d4 100644 --- a/dist/main/solvers/sequence-solver.js +++ b/dist/main/solvers/sequence-solver.js @@ -1,6 +1,6 @@ import { ComputeWorker, WorkerPool } from "../utilities/worker.js"; import { shuffleArray } from "../utilities/array.js"; -import { FlybySequence } from "../objects/sequence.js"; +import { FlybySequence } from "./sequence.js"; export class FlybySequenceGenerator { constructor(system, config) { this.system = system; diff --git a/dist/main/solvers/sequence.js b/dist/main/solvers/sequence.js index b3150e1..52da042 100644 --- a/dist/main/solvers/sequence.js +++ b/dist/main/solvers/sequence.js @@ -1,5 +1,3 @@ -import { ComputeWorker, WorkerPool } from "../utilities/worker.js"; -import { shuffleArray } from "../utilities/array.js"; export class FlybySequence { constructor(system, ids, cost) { this.ids = ids; @@ -17,62 +15,3 @@ export class FlybySequence { this.seqString = str; } } -export class FlybySequenceGenerator { - constructor(system, config) { - this.system = system; - this.config = config; - this.totalFeasible = 0; - this._workerPool = new WorkerPool("dedicated-workers/sequence-evaluator.js", this.config); - this._workerPool.initialize({ system: this.system.data, config: this.config }); - this._sequenceWorker = new ComputeWorker("dedicated-workers/sequence-generator.js"); - this._sequenceWorker.initialize(this.config); - } - cancel() { - this._workerPool.cancel(); - } - async generateFlybySequences(params, onProgress) { - const toHigherOrbit = params.destinationId > params.departureId; - const departureBody = this.system.bodyFromId(params.departureId); - const allowedBodies = this._getAllowedBodies(departureBody, params, toHigherOrbit); - const feasibleSet = await this._generateFeasibleSet(allowedBodies, params); - this.totalFeasible = feasibleSet.length; - const evaluations = await this._evaluateSequences(feasibleSet, onProgress); - evaluations.sort((a, b) => a.cost - b.cost); - const { maxPropositions } = this.config.flybySequence; - const sequences = []; - for (let i = 0; i < Math.min(maxPropositions, evaluations.length); i++) { - const result = evaluations[i]; - const sequence = new FlybySequence(this.system, feasibleSet[result.seq], result.cost); - sequences.push(sequence); - } - return sequences; - } - _getAllowedBodies(departureBody, params, toHigherOrbit) { - const allowedBodies = []; - for (const body of departureBody.attractor.orbiters) { - if ((toHigherOrbit && body.id <= params.destinationId) || - (!toHigherOrbit && body.id >= params.destinationId)) { - allowedBodies.push(body.id); - } - } - return allowedBodies; - } - _generateFeasibleSet(allowedBodies, params) { - return this._sequenceWorker.run({ bodies: allowedBodies, params: params }); - } - async _evaluateSequences(sequences, onProgress) { - shuffleArray(sequences); - const { splitLimit } = this.config.flybySequence; - const costs = await this._workerPool.runPoolChunked(sequences, splitLimit, onProgress); - const evaluations = []; - for (let i = 0; i < sequences.length; i++) { - if (costs[i] != undefined) { - evaluations.push({ seq: i, cost: costs[i] }); - } - } - return evaluations; - } - get progression() { - return this._workerPool.totalProgress; - } -} diff --git a/dist/main/solvers/trajectory.js b/dist/main/solvers/trajectory.js index 2cf1f2f..82f001b 100644 --- a/dist/main/solvers/trajectory.js +++ b/dist/main/solvers/trajectory.js @@ -1,151 +1,159 @@ -import { mergeArrayChunks } from "../utilities/array.js"; -import { WorkerPool } from "../utilities/worker.js"; -export class TrajectorySolver { - constructor(system, config, plot) { +import { createOrbitPoints, createLine, createSprite } from "../utilities/geometry.js"; +import { Orbit } from "../objects/orbit.js"; +import { TimeAndDate } from "../utilities/time.js"; +export class Trajectory { + constructor(steps, system, config) { + this.steps = steps; this.system = system; this.config = config; - this.plot = plot; - this.popSize = 0; - this.dim = 0; - this._cancelled = false; - this._running = false; - this._population = []; - this._deltaVs = []; - this._numChunks = 0; - this._chunkIndices = []; - this._workerPool = new WorkerPool("dedicated-workers/trajectory-optimizer.js", this.config); - this._workerPool.initialize({ system: this.system.data, config: this.config }); - } - _initPlot() { - this.plot.clearPlot(); - } - _updatePlot(iteration) { - const { best, mean } = this._getBestMeanDeltaV; - this.plot.addIterationData(iteration, mean, best); - } - cancel() { - if (this._running) - this._cancelled = true; - } - _checkCancellation() { - if (this._cancelled) { - this._cancelled = false; - this._running = false; - throw "TRAJECTORY FINDER CANCELLED"; + this.orbits = []; + this._objects = []; + this._maneuvres = []; + for (const { orbitElts, attractorId } of this.steps) { + const attractor = this.system.bodyFromId(attractorId); + const orbit = Orbit.fromOrbitalElements(orbitElts, attractor, config.orbit); + this.orbits.push(orbit); } } - async searchOptimalTrajectory(sequence, startDateMin, startDateMax) { - this._running = true; - this._initPlot(); - this._calculatePopulationSizes(sequence); - this._calculatePopulationChunks(); - await this._createStartPopulation(sequence, startDateMin, startDateMax); - return; - this._updatePlot(0); - this._checkCancellation(); - for (let i = 0; i < 50; i++) { - await this._generateNextPopulation(); - this._updatePlot(1 + i); - this._checkCancellation(); - } - this._running = false; - } - async _createStartPopulation(sequence, startDateMin, startDateMax) { - const agentSettings = { - startDateMin: startDateMin, - startDateMax: startDateMax, - dim: this.dim - }; - const inputs = this._firstGenerationInputs(sequence, agentSettings); - const results = await this._workerPool.runPool(inputs); - console.log(results); - return; - const { population, deltaVs } = this._mergeResultsChunks(results); - this._population = population; - this._deltaVs = deltaVs; - } - _calculatePopulationChunks() { - const { splitLimit } = this.config.trajectorySearch; - const numChunks = this._workerPool.optimizeUsedWorkersCount(this.popSize, splitLimit); - const chunkSize = Math.floor(this.popSize / numChunks); - const chunkIndices = [0, chunkSize - 1]; - for (let i = 2; i < numChunks * 2; i += 2) { - const start = chunkIndices[i - 1] + 1; - const end = start + chunkSize; - chunkIndices.push(start, end); - } - chunkIndices[numChunks * 2 - 1] = this.popSize - 1; - this._numChunks = numChunks; - this._chunkIndices = chunkIndices; - } - _calculatePopulationSizes(sequence) { - const swingBys = sequence.length - 2; - this.dim = 4 * swingBys + 6; - this.popSize = 10 * this.dim; - } - async _generateNextPopulation() { - const inputs = this._nextGenerationInputs(); - const results = await this._workerPool.runPool(inputs); - const { population, deltaVs } = this._mergeResultsChunks(results); - this._population = population; - this._deltaVs = deltaVs; - } - _mergeResultsChunks(results) { - const popChunks = []; - const dVChunks = []; - for (let i = 0; i < this._numChunks; i++) { - popChunks.push(results[i].popChunk); - dVChunks.push(results[i].fitChunk); - } - return { - population: mergeArrayChunks(popChunks), - deltaVs: mergeArrayChunks(dVChunks) - }; - } - _firstGenerationInputs(sequence, agentSettings) { - const inputs = []; - for (let i = 0; i < this._numChunks; i++) { - const { start, end } = this._chunkStartEnd(i); - inputs.push({ - start: true, - chunkStart: start, - chunkEnd: end, - sequence: sequence.ids, - agentSettings: agentSettings + static preloadArrowMaterial() { + const textureLoader = new THREE.TextureLoader(); + const loaded = (texture) => { + this.arrowMaterial = new THREE.SpriteMaterial({ + map: texture }); - } - return inputs; + }; + textureLoader.load("sprites/arrow-512.png", loaded); } - _nextGenerationInputs() { - const inputs = []; - for (let i = 0; i < this._numChunks; i++) { - const { start, end } = this._chunkStartEnd(i); - inputs[i] = { - population: this._population, - deltaVs: this._deltaVs, - chunkStart: start, - chunkEnd: end + draw(resolution) { + this._createTrajectoryArcs(resolution); + this._createManeuvreSprites(); + this._calculateManeuvresDetails(); + } + _createTrajectoryArcs(resolution) { + const { lineWidth } = this.config.orbit; + const { samplePoints } = this.config.trajectoryDraw; + const { scale } = this.config.rendering; + for (let i = 0; i < this.orbits.length; i++) { + const orbit = this.orbits[i]; + const { beginAngle, endAngle } = this.steps[i]; + const orbitPoints = createOrbitPoints(orbit, samplePoints, scale, beginAngle, endAngle); + const color = new THREE.Color(`hsl(${i * 35 % 360}, 100%, 85%)`); + const orbitLine = createLine(orbitPoints, resolution, { + color: color.getHex(), + linewidth: lineWidth, + }); + const group = this.system.objectsOfBody(orbit.attractor.id); + group.add(orbitLine); + this._objects.push(orbitLine); + } + } + _createManeuvreSprites() { + const { maneuvreArrowSize } = this.config.trajectoryDraw; + const { scale } = this.config.rendering; + for (const step of this.steps) { + if (step.maneuvre) { + const group = this.system.objectsOfBody(step.attractorId); + const sprite = createSprite(Trajectory.arrowMaterial, 0xFFFFFF, false, maneuvreArrowSize); + const { x, y, z } = step.maneuvre.manoeuvrePosition; + sprite.position.set(x, y, z); + sprite.position.multiplyScalar(scale); + group.add(sprite); + this._objects.push(sprite); + } + } + } + _calculateManeuvresDetails() { + for (let i = 0; i < this.steps.length; i++) { + const step = this.steps[i]; + const { maneuvre } = step; + if (maneuvre) { + const orbit = this.orbits[i]; + const progradeDir = new THREE.Vector3(maneuvre.progradeDir.x, maneuvre.progradeDir.y, maneuvre.progradeDir.z); + const normalDir = orbit.normal.clone(); + const radialDir = progradeDir.clone(); + radialDir.cross(normalDir); + const deltaV = new THREE.Vector3(maneuvre.deltaVToPrevStep.x, maneuvre.deltaVToPrevStep.y, maneuvre.deltaVToPrevStep.z); + const details = { + stepIndex: i, + dateMET: step.dateOfStart - this.steps[0].dateOfStart, + progradeDV: progradeDir.dot(deltaV), + normalDV: normalDir.dot(deltaV), + radialDV: radialDir.dot(deltaV) + }; + this._maneuvres.push(details); + } + } + } + fillResultControls(maneuvreSelector, resultSpans, stepSlider, systemTime) { + const depDate = new TimeAndDate(this.steps[0].dateOfStart, this.config.time); + resultSpans.totalDVSpan.innerHTML = this._totalDeltaV.toFixed(1); + resultSpans.depDateSpan.innerHTML = depDate.stringYDHMS("hms", "date"); + resultSpans.depDateSpan.onclick = () => { + systemTime.time.dateSeconds = depDate.dateSeconds; + systemTime.update(); + systemTime.onChange(); + }; + stepSlider.setMinMax(0, this.steps.length - 1); + stepSlider.input((index) => this._displayStepsUpTo(index)); + stepSlider.value = this.steps.length - 1; + const selectorOptions = []; + for (let i = 0; i < this._maneuvres.length; i++) { + const details = this._maneuvres[i]; + const step = this.steps[details.stepIndex]; + const context = step.maneuvre.context; + if (context.type == "ejection") { + const startBodyName = this.system.bodyFromId(step.attractorId).name; + const optionName = `${i + 1}: ${startBodyName} escape`; + selectorOptions.push(optionName); + } + else { + const originName = this.system.bodyFromId(context.originId).name; + const targetName = this.system.bodyFromId(context.targetId).name; + const optionName = `${i + 1}: ${originName}-${targetName} DSM`; + selectorOptions.push(optionName); + } + } + maneuvreSelector.fill(selectorOptions); + maneuvreSelector.change((_, index) => { + const details = this._maneuvres[index]; + const dateEMT = new TimeAndDate(details.dateMET, this.config.time); + resultSpans.dateSpan.innerHTML = dateEMT.stringYDHMS("hm", "elapsed"); + resultSpans.progradeDVSpan.innerHTML = details.progradeDV.toFixed(1); + resultSpans.normalDVSpan.innerHTML = details.normalDV.toFixed(1); + resultSpans.radialDVSpan.innerHTML = details.radialDV.toFixed(1); + resultSpans.maneuvreNumber.innerHTML = (index + 1).toString(); + resultSpans.dateSpan.onclick = () => { + systemTime.time.dateSeconds = depDate.dateSeconds + dateEMT.dateSeconds; + systemTime.update(); + systemTime.onChange(); }; - } - return inputs; + }); } - _chunkStartEnd(index) { - return { - start: this._chunkIndices[index * 2], - end: this._chunkIndices[index * 2 + 1] - }; - } - get _getBestMeanDeltaV() { - let mean = 0; - let best = Infinity; - for (const dv of this._deltaVs) { - mean += dv; - best = Math.min(best, dv); + _displayStepsUpTo(index) { + for (let i = 0; i < this.steps.length; i++) { + const orbitLine = this._objects[i]; + orbitLine.visible = i <= index; + } + const spritesStart = this.steps.length; + for (let i = 0; i < this._maneuvres.length; i++) { + const visible = this._objects[this._maneuvres[i].stepIndex].visible; + this._objects[spritesStart + i].visible = visible; + } + } + get _totalDeltaV() { + let total = 0; + for (const details of this._maneuvres) { + const x = details.progradeDV; + const y = details.normalDV; + const z = details.radialDV; + total += new THREE.Vector3(x, y, z).length(); + } + return total; + } + remove() { + for (const object of this._objects) { + if (object.parent) + object.parent.remove(object); } - mean /= this.popSize; - return { - mean: mean, - best: best - }; } } diff --git a/dist/main/objects/time.js b/dist/main/utilities/time.js similarity index 100% rename from dist/main/objects/time.js rename to dist/main/utilities/time.js diff --git a/src/main/editor/editor.ts b/src/main/editor/editor.ts index 4f5c4e6..8c69716 100644 --- a/src/main/editor/editor.ts +++ b/src/main/editor/editor.ts @@ -10,8 +10,8 @@ import { EvolutionPlot } from "./plot.js"; import { ProgressMessage } from "./progress-msg.js"; import { SequenceSelector } from "./sequence-selector.js"; import { SubmitButton, StopButton } from "./buttons.js"; -import { FlybySequence } from "../objects/sequence.js"; -import { Trajectory } from "../objects/trajectory.js"; +import { FlybySequence } from "../solvers/sequence.js"; +import { Trajectory } from "../solvers/trajectory.js"; import { Selector } from "./selector.js"; import { DiscreteRange } from "./range.js"; diff --git a/src/main/editor/sequence-selector.ts b/src/main/editor/sequence-selector.ts index 5c6be3f..18426f1 100644 --- a/src/main/editor/sequence-selector.ts +++ b/src/main/editor/sequence-selector.ts @@ -1,4 +1,4 @@ -import { FlybySequence } from "../objects/sequence.js"; +import { FlybySequence } from "../solvers/sequence.js"; import { Selector } from "./selector.js"; export class SequenceSelector extends Selector { diff --git a/src/main/editor/time-selector.ts b/src/main/editor/time-selector.ts index 7b571ff..deeb8b7 100644 --- a/src/main/editor/time-selector.ts +++ b/src/main/editor/time-selector.ts @@ -1,4 +1,4 @@ -import { TimeAndDate } from "../objects/time.js"; +import { TimeAndDate } from "../utilities/time.js"; export class TimeSelector { readonly time!: TimeAndDate; diff --git a/src/main/main.ts b/src/main/main.ts index b2e9bcc..74b239e 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -2,7 +2,7 @@ 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"; -import { Trajectory } from "./objects/trajectory.js"; +import { Trajectory } from "./solvers/trajectory.js"; window.onload = main; diff --git a/src/main/solvers/sequence-solver.ts b/src/main/solvers/sequence-solver.ts index 8f9b909..7ae5bd9 100644 --- a/src/main/solvers/sequence-solver.ts +++ b/src/main/solvers/sequence-solver.ts @@ -2,7 +2,7 @@ import { OrbitingBody } from "../objects/body.js"; import { SolarSystem } from "../objects/system.js"; import { ComputeWorker, WorkerPool } from "../utilities/worker.js"; import { shuffleArray } from "../utilities/array.js"; -import { FlybySequence } from "../objects/sequence.js"; +import { FlybySequence } from "./sequence.js"; export class FlybySequenceGenerator { private readonly _workerPool!: WorkerPool; diff --git a/src/main/objects/sequence.ts b/src/main/solvers/sequence.ts similarity index 87% rename from src/main/objects/sequence.ts rename to src/main/solvers/sequence.ts index 6c0a03d..460a4a7 100644 --- a/src/main/objects/sequence.ts +++ b/src/main/solvers/sequence.ts @@ -1,5 +1,5 @@ -import { OrbitingBody } from "./body"; -import { SolarSystem } from "./system"; +import { OrbitingBody } from "../objects/body"; +import { SolarSystem } from "../objects/system"; export class FlybySequence { public readonly bodies!: OrbitingBody[]; diff --git a/src/main/solvers/trajectory-solver.ts b/src/main/solvers/trajectory-solver.ts index 8929f57..8cc0490 100644 --- a/src/main/solvers/trajectory-solver.ts +++ b/src/main/solvers/trajectory-solver.ts @@ -2,7 +2,7 @@ import { EvolutionPlot } from "../editor/plot.js"; import { SolarSystem } from "../objects/system.js"; import { mergeArrayChunks } from "../utilities/array.js"; import { WorkerPool } from "../utilities/worker.js"; -import { FlybySequence } from "../objects/sequence.js"; +import { FlybySequence } from "./sequence.js"; export class TrajectorySolver { private readonly _workerPool!: WorkerPool; diff --git a/src/main/objects/trajectory.ts b/src/main/solvers/trajectory.ts similarity index 98% rename from src/main/objects/trajectory.ts rename to src/main/solvers/trajectory.ts index e3666ca..fe79616 100644 --- a/src/main/objects/trajectory.ts +++ b/src/main/solvers/trajectory.ts @@ -2,9 +2,9 @@ import { DiscreteRange } from "../editor/range.js"; import { Selector } from "../editor/selector.js"; import { TimeSelector } from "../editor/time-selector.js"; import { createOrbitPoints, createLine, createSprite } from "../utilities/geometry.js"; -import { Orbit } from "./orbit.js"; -import { SolarSystem } from "./system.js"; -import { TimeAndDate } from "./time.js"; +import { Orbit } from "../objects/orbit.js"; +import { SolarSystem } from "../objects/system.js"; +import { TimeAndDate } from "../utilities/time.js"; export class Trajectory { public readonly orbits: Orbit[] = []; diff --git a/src/main/objects/time.ts b/src/main/utilities/time.ts similarity index 100% rename from src/main/objects/time.ts rename to src/main/utilities/time.ts