From e9146a35d4d29be61a6cdaeabe36a57f0819a3d6 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sun, 23 Jul 2023 02:18:33 +0200 Subject: [PATCH] Move flight data secondary data copying to constructor --- .../src/net/sf/openrocket/file/CSVExport.java | 53 +------- .../BasicEventSimulationEngine.java | 2 +- .../simulation/FlightDataBranch.java | 119 +++++++++++++----- .../openrocket/gui/plot/SimulationPlot.java | 20 +-- 4 files changed, 92 insertions(+), 102 deletions(-) diff --git a/core/src/net/sf/openrocket/file/CSVExport.java b/core/src/net/sf/openrocket/file/CSVExport.java index 5e6a59419..886ebc235 100644 --- a/core/src/net/sf/openrocket/file/CSVExport.java +++ b/core/src/net/sf/openrocket/file/CSVExport.java @@ -11,7 +11,6 @@ import java.util.List; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.simulation.FlightData; import net.sf.openrocket.simulation.FlightDataBranch; import net.sf.openrocket.simulation.FlightDataType; @@ -75,7 +74,7 @@ public class CSVExport { writer.println(); } - writeData(writer, simulation, branch, fields, units, fieldSeparator, decimalPlaces, isExponentialNotation, + writeData(writer, branch, fields, units, fieldSeparator, decimalPlaces, isExponentialNotation, eventComments, commentStarter); @@ -90,60 +89,17 @@ public class CSVExport { } } - private static void writeData(PrintWriter writer, Simulation simulation, FlightDataBranch branch, + private static void writeData(PrintWriter writer, FlightDataBranch branch, FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces, boolean isExponentialNotation, boolean eventComments, String commentStarter) { - final FlightData data = simulation.getSimulatedData(); - final int stageNr = data.getStageNr(branch); - AxialStage stage = simulation.getRocket().getStage(stageNr); - // Time variable List time = branch.get(FlightDataType.TYPE_TIME); - // Extra stages don't contain all the simulation data. Instead, the data is stored in the sustainer stage - // (since the data is the same for all stages until there is separation). - // For CSV export however, we want to copy the data from the sustainer stage to the extra stage. - boolean copySustainerData = stageNr > 0 && time != null && time.get(0) > 0; - FlightDataBranch sustainerBranch = null; - Double firstBranchTime = null; - int lastSustainerIndex = 0; - if (copySustainerData) { - firstBranchTime = time.get(0); - sustainerBranch = data.getBranch(0); - List sustainerTime = sustainerBranch.get(FlightDataType.TYPE_TIME); - - if (sustainerTime != null) { - for (int i = 0; i < sustainerTime.size(); i++) { - if (sustainerTime.get(i) >= firstBranchTime) { - lastSustainerIndex = i - 1; - break; - } - } - - List timeToCopy = sustainerTime.subList(0, lastSustainerIndex + 1); - time.addAll(0, timeToCopy); - } - } - // Number of data points int n = time != null ? time.size() : branch.getLength(); // Flight events in occurrence order List events = branch.getEvents(); - if (copySustainerData) { - List sustainerEvents = sustainerBranch.getEvents(); - - // Copy all events from the sustainer that belong to this stage - for (FlightEvent event : sustainerEvents) { - // Stage separation is present both in the sustainer data and extra stage data (don't really know why...) - if (event.getType() == FlightEvent.Type.STAGE_SEPARATION) { - continue; - } - if (stage == event.getSource() || stage.containsChild(event.getSource())) { - events.add(event); - } - } - } Collections.sort(events); int eventPosition = 0; @@ -151,11 +107,6 @@ public class CSVExport { List> fieldValues = new ArrayList<>(); for (FlightDataType t : fields) { List values = branch.get(t); - if (copySustainerData) { - List sustainerValues = sustainerBranch.get(t); - List valuesToCopy = sustainerValues.subList(0, lastSustainerIndex + 1); - values.addAll(0, valuesToCopy); - } fieldValues.add(values); } diff --git a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java index ffdb3c2fa..be9fd8bc6 100644 --- a/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java +++ b/core/src/net/sf/openrocket/simulation/BasicEventSimulationEngine.java @@ -489,7 +489,7 @@ public class BasicEventSimulationEngine implements SimulationEngine { SimulationStatus boosterStatus = new SimulationStatus(currentStatus); // Prepare the new simulation branch - boosterStatus.setFlightData(new FlightDataBranch(boosterStage.getName(), currentStatus.getFlightData())); + boosterStatus.setFlightData(new FlightDataBranch(boosterStage.getName(), boosterStage, currentStatus.getFlightData())); boosterStatus.getFlightData().addEvent(event); // Mark the current status as having dropped the current stage and all stages below it diff --git a/core/src/net/sf/openrocket/simulation/FlightDataBranch.java b/core/src/net/sf/openrocket/simulation/FlightDataBranch.java index e2547e4c4..270431deb 100644 --- a/core/src/net/sf/openrocket/simulation/FlightDataBranch.java +++ b/core/src/net/sf/openrocket/simulation/FlightDataBranch.java @@ -6,6 +6,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.Monitorable; import net.sf.openrocket.util.Mutable; @@ -30,11 +31,10 @@ public class FlightDataBranch implements Monitorable { /** The name of this flight data branch. */ private final String branchName; - private final Map> values = - new LinkedHashMap>(); + private final Map> values = new LinkedHashMap<>(); - private final Map maxValues = new HashMap(); - private final Map minValues = new HashMap(); + private final Map maxValues = new HashMap<>(); + private final Map minValues = new HashMap<>(); /** * time for the rocket to reach apogee if the flight had been no recovery deployment @@ -77,23 +77,19 @@ public class FlightDataBranch implements Monitorable { } /** - * Make a flight data branch with one data point copied from its parent. Intended for use + * Make a flight data branch with all data points copied from its parent. Intended for use * when creating a new branch upon stage separation, so the data at separation is present * in both branches (and if the new branch has an immediate exception, it can be plotted) + * + * @param branchName the name of the new branch. + * @param srcComponent the component that is the source of the new branch. + * @param parent the parent branch to copy data from. */ - public FlightDataBranch(String branchName, FlightDataBranch parent) { + public FlightDataBranch(String branchName, RocketComponent srcComponent, FlightDataBranch parent) { this.branchName = branchName; - // need to have at least one type to set up values - values.put(FlightDataType.TYPE_TIME, new ArrayList()); - minValues.put(FlightDataType.TYPE_TIME, Double.NaN); - maxValues.put(FlightDataType.TYPE_TIME, Double.NaN); - - // copy all values into new FlightDataBranch - this.addPoint(); - for (FlightDataType t : parent.getTypes()) { - this.setValue(t, parent.getLast(t)); - } + // Copy all the values from the parent + copyValuesFromBranch(parent, srcComponent); } /** @@ -115,12 +111,27 @@ public class FlightDataBranch implements Monitorable { public void addPoint() { mutable.check(); - for (FlightDataType t : values.keySet()) { - values.get(t).add(Double.NaN); + for (FlightDataType type : values.keySet()) { + sanityCheckValues(type, Double.NaN); + values.get(type).add(Double.NaN); } modID++; } - + + private void sanityCheckValues(FlightDataType type, Double value) { + ArrayList list = values.get(type); + + if (list == null) { + list = new ArrayList<>(); + int n = getLength(); + for (int i = 0; i < n; i++) { + list.add(Double.NaN); + } + values.put(type, list); + minValues.put(type, value); + maxValues.put(type, value); + } + } /** * Set the value for a specific data type at the latest point. New variable types can be @@ -132,20 +143,10 @@ public class FlightDataBranch implements Monitorable { */ public void setValue(FlightDataType type, double value) { mutable.check(); - + + sanityCheckValues(type, value); ArrayList list = values.get(type); - if (list == null) { - list = new ArrayList(); - int n = getLength(); - for (int i = 0; i < n; i++) { - list.add(Double.NaN); - } - values.put(type, list); - minValues.put(type, value); - maxValues.put(type, value); - } - if (list.size() > 0) { list.set(list.size() - 1, value); } @@ -161,7 +162,44 @@ public class FlightDataBranch implements Monitorable { } modID++; } - + + /** + * Clears all the current values in the branch and copies the values from the given branch. + * @param srcBranch the branch to copy values from + * @param srcComponent the component that is the source of this branch (used for copying events) + */ + private void copyValuesFromBranch(FlightDataBranch srcBranch, RocketComponent srcComponent) { + this.values.clear(); + + // Need to have at least one type to set up values + values.put(FlightDataType.TYPE_TIME, new ArrayList<>()); + minValues.put(FlightDataType.TYPE_TIME, Double.NaN); + maxValues.put(FlightDataType.TYPE_TIME, Double.NaN); + + if (srcBranch == null) { + return; + } + + // Copy flight data + for (int i = 0; i < srcBranch.getLength(); i++) { + this.addPoint(); + for (FlightDataType type : srcBranch.getTypes()) { + this.setValue(type, srcBranch.getByIndex(type, i)); + } + } + + // Copy flight events belonging to this branch + List sustainerEvents = srcBranch.getEvents(); + for (FlightEvent event : sustainerEvents) { + // Stage separation is already added elsewhere, so don't copy it over (otherwise you have a duplicate) + if (event.getType() == FlightEvent.Type.STAGE_SEPARATION) { + continue; + } + if (srcComponent != null && (srcComponent == event.getSource() || srcComponent.containsChild(event.getSource()))) { + events.add(event); + } + } + } /** * Return the branch name. @@ -203,6 +241,23 @@ public class FlightDataBranch implements Monitorable { return null; return list.clone(); } + + /** + * Return the value of the specified type at the specified index. + * @param type the variable type + * @param index the data index of the value + * @return the value at the specified index + */ + public Double getByIndex(FlightDataType type, int index) { + if (index < 0 || index >= getLength()) { + throw new IllegalArgumentException("Index out of bounds"); + } + ArrayList list = values.get(type); + if (list == null) { + return null; + } + return list.get(index); + } /** * Return the last value of the specified type in the branch, or NaN if the type is diff --git a/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java b/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java index 57f45c09c..e30b01646 100644 --- a/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java +++ b/swing/src/net/sf/openrocket/gui/plot/SimulationPlot.java @@ -192,9 +192,8 @@ public class SimulationPlot { } data[axis].addSeries(series); } - // For each of the secondary branches, we use data from branch 0 for the earlier times + // Secondary branches for (int branchIndex = 1; branchIndex < branchCount; branchIndex++) { - FlightDataBranch primaryBranch = simulation.getSimulatedData().getBranch(0); FlightDataBranch thisBranch = simulation.getSimulatedData().getBranch(branchIndex); // Ignore empty branches @@ -206,25 +205,10 @@ public class SimulationPlot { continue; } - // Get first time index used in secondary branch; - double firstSampleTime = thisBranch.get(FlightDataType.TYPE_TIME).get(0); - XYSeries series = new XYSeries(seriesCount++, false, true); series.setDescription(thisBranch.getBranchName() + ": " + name); - // Copy the first points from the primaryBranch. - List primaryT = primaryBranch.get(FlightDataType.TYPE_TIME); - List primaryx = primaryBranch.get(domainType); - List primaryy = primaryBranch.get(type); - - for (int j = 0; j < primaryT.size(); j++) { - if (primaryT.get(j) >= firstSampleTime) { - break; - } - series.add(domainUnit.toUnit(primaryx.get(j)), unit.toUnit(primaryy.get(j))); - } - - // Now copy all the data from the secondary branch + // Copy all the data from the secondary branch List plotx = thisBranch.get(domainType); List ploty = thisBranch.get(type);