diff --git a/ChangeLog b/ChangeLog
index 3c5130611..7d9193c34 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2010-03-05 Sampo Niskanen
+
+ * [BUG] Fixed exception for fins with small root chord
+
+2010-02-26 Sampo Niskanen
+
+ * Simulation panel max.acceleration now from flight stage only
+
2010-02-17 Sampo Niskanen
* Released version 0.9.6
diff --git a/TODO b/TODO
index ec1e28876..b91d16abd 100644
--- a/TODO
+++ b/TODO
@@ -7,7 +7,7 @@ Must-have:
- Go through thrust curves and select best ones
- Updated splash screen
-
+- BUG: Invalid fin points possible when removing points
Maybe:
@@ -167,3 +167,5 @@ In 0.9.6:
exponential growth until time step is reached (t1 = 1.5*t0)
- Limit time step during while on launch rod
- Re-investigate 15% reduction of three-fin CNa
+In 0.9.7:
+- BUG: Simulation table max. acceleration takes into account parachute deceleration
diff --git a/doc/simulation-2.0.uml b/doc/simulation-2.0.uml
new file mode 100644
index 000000000..64b548228
--- /dev/null
+++ b/doc/simulation-2.0.uml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/simulation-2.0.umlclass b/doc/simulation-2.0.umlclass
new file mode 100644
index 000000000..eab546de0
--- /dev/null
+++ b/doc/simulation-2.0.umlclass
@@ -0,0 +1,479 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/html/favicon.ico b/html/favicon.ico
new file mode 100644
index 000000000..09c23f8f3
Binary files /dev/null and b/html/favicon.ico differ
diff --git a/pix-src/icon/icon-web.ico b/pix-src/icon/icon-web.ico
new file mode 100644
index 000000000..09c23f8f3
Binary files /dev/null and b/pix-src/icon/icon-web.ico differ
diff --git a/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java b/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java
index 11b8a52e4..9e8c91b1b 100644
--- a/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java
+++ b/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java
@@ -763,21 +763,32 @@ public class FinSetCalc extends RocketComponentCalc {
double lead = component.toRelative(Coordinate.NUL, parent)[0].x;
double trail = component.toRelative(new Coordinate(component.getLength()),
parent)[0].x;
+
+ /*
+ * The counting fails if the fin root chord is very small, in that case assume
+ * no other fin interference than this fin set.
+ */
+ if (trail-lead < 0.007) {
+ interferenceFinCount = component.getFinCount();
+ } else {
+ interferenceFinCount = 0;
+ for (RocketComponent c: parent.getChildren()) {
+ if (c instanceof FinSet) {
+ double finLead = c.toRelative(Coordinate.NUL, parent)[0].x;
+ double finTrail = c.toRelative(new Coordinate(c.getLength()), parent)[0].x;
- interferenceFinCount = 0;
- for (RocketComponent c: parent.getChildren()) {
- if (c instanceof FinSet) {
- double finLead = c.toRelative(Coordinate.NUL, parent)[0].x;
- double finTrail = c.toRelative(new Coordinate(c.getLength()), parent)[0].x;
- if ((finLead < trail - 0.005) && (finTrail > lead + 0.005)) {
- interferenceFinCount += ((FinSet)c).getFinCount();
+ // Compute overlap of the fins
+
+ if ((finLead < trail - 0.005) && (finTrail > lead + 0.005)) {
+ interferenceFinCount += ((FinSet)c).getFinCount();
+ }
}
}
}
-
if (interferenceFinCount < component.getFinCount()) {
throw new BugException("Counted " + interferenceFinCount + " parallel fins, " +
- "when component itself has " + component.getFinCount());
+ "when component itself has " + component.getFinCount() +
+ ", fin points=" + Arrays.toString(component.getFinPoints()));
}
}
return interferenceFinCount;
diff --git a/src/net/sf/openrocket/gui/main/ExceptionHandler.java b/src/net/sf/openrocket/gui/main/ExceptionHandler.java
index 8496ad5be..702c3025c 100644
--- a/src/net/sf/openrocket/gui/main/ExceptionHandler.java
+++ b/src/net/sf/openrocket/gui/main/ExceptionHandler.java
@@ -149,12 +149,18 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
return;
}
+ // Create the message
+ String msg = e.getClass().getSimpleName() + ": " + e.getMessage();
+ if (msg.length() > 90) {
+ msg = msg.substring(0, 80) + "...";
+ }
+
// Unknown Error
if (!(e instanceof Exception)) {
JOptionPane.showMessageDialog(null,
new Object[] {
"An unknown Java error occurred:",
- e.getMessage(),
+ msg,
"You should immediately close unnecessary design windows,
" +
"save any unsaved designs and restart OpenRocket!"
}, "Unknown Java error", JOptionPane.ERROR_MESSAGE);
@@ -162,13 +168,7 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
}
- // Normal exception, show question dialog
- String msg = e.getClass().getSimpleName() + ": " + e.getMessage();
- if (msg.length() > 90) {
- msg = msg.substring(0, 80) + "...";
- }
-
-
+ // Normal exception, show question dialog
int selection = JOptionPane.showOptionDialog(null, new Object[] {
"OpenRocket encountered an uncaught exception. This typically signifies " +
"a bug in the software.",
diff --git a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java
index 5f9e932f9..1cce5ce6b 100644
--- a/src/net/sf/openrocket/gui/main/SimulationEditDialog.java
+++ b/src/net/sf/openrocket/gui/main/SimulationEditDialog.java
@@ -750,34 +750,7 @@ public class SimulationEditDialog extends JDialog {
return noDataPanel();
}
-
- if (true)
- return new SimulationPlotPanel(simulation);
-
- JPanel panel = new JPanel(new MigLayout("fill"));
-
-
-
-
- JButton button = new JButton("test");
-
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- PlotConfiguration config = new PlotConfiguration();
- config.addPlotDataType(FlightDataBranch.TYPE_ALTITUDE);
- config.addPlotDataType(FlightDataBranch.TYPE_VELOCITY_Z);
- config.addPlotDataType(FlightDataBranch.TYPE_ACCELERATION_Z);
- config.addPlotDataType(FlightDataBranch.TYPE_ACCELERATION_TOTAL);
-
- config.setDomainAxisType(FlightDataBranch.TYPE_TIME);
-
- performPlot(config);
- }
- });
- panel.add(button);
-
- return panel;
+ return new SimulationPlotPanel(simulation);
}
diff --git a/src/net/sf/openrocket/gui/main/SimulationPanel.java b/src/net/sf/openrocket/gui/main/SimulationPanel.java
index e62c2aa6c..e52f20baf 100644
--- a/src/net/sf/openrocket/gui/main/SimulationPanel.java
+++ b/src/net/sf/openrocket/gui/main/SimulationPanel.java
@@ -323,6 +323,8 @@ public class SimulationPanel extends JPanel {
if (data==null)
return null;
+
+ // TODO: CRITICAL: Show getMaxAcceleration if branches not available!
return UnitGroup.UNITS_ACCELERATION.getDefaultUnit().toStringUnit(
data.getMaxAcceleration());
}
diff --git a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
index 05862f3d4..ab5bea0df 100644
--- a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
+++ b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
@@ -1,7 +1,9 @@
package net.sf.openrocket.rocketcomponent;
import java.util.ArrayList;
+import java.util.Arrays;
+import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
@@ -19,12 +21,8 @@ public class FreeformFinSet extends FinSet {
}
- public FreeformFinSet(Coordinate[] finpoints) {
- points.clear();
- for (Coordinate c: finpoints) {
- points.add(c);
- }
- this.length = points.get(points.size()-1).x - points.get(0).x;
+ public FreeformFinSet(Coordinate[] finpoints) throws IllegalFinPointException {
+ setPoints(finpoints);
}
/*
@@ -73,7 +71,13 @@ public class FreeformFinSet extends FinSet {
// Create the freeform fin set
Coordinate[] finpoints = finset.getFinPoints();
- freeform = new FreeformFinSet(finpoints);
+ try {
+ freeform = new FreeformFinSet(finpoints);
+ } catch (IllegalFinPointException e) {
+ throw new BugException("Illegal fin points when converting existing fin to " +
+ "freeform fin, fin=" + finset + " points="+Arrays.toString(finpoints),
+ e);
+ }
// Copy component attributes
freeform.copyFrom(finset);
@@ -134,6 +138,7 @@ public class FreeformFinSet extends FinSet {
if (index == 0 || index == points.size()-1) {
throw new IllegalFinPointException("cannot remove first or last point");
}
+ // TODO: CRITICAL: Can result in invalid fin points
points.remove(index);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@@ -144,7 +149,7 @@ public class FreeformFinSet extends FinSet {
}
public void setPoints(Coordinate[] p) throws IllegalFinPointException {
- if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].y != 0) {
+ if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].x < 0 || p[p.length-1].y != 0) {
throw new IllegalFinPointException("Start or end point illegal.");
}
for (int i=0; i < p.length-1; i++) {
diff --git a/src/net/sf/openrocket/simulation/FlightData.java b/src/net/sf/openrocket/simulation/FlightData.java
index 8d0307c6b..6a753447b 100644
--- a/src/net/sf/openrocket/simulation/FlightData.java
+++ b/src/net/sf/openrocket/simulation/FlightData.java
@@ -5,6 +5,7 @@ import java.util.List;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.util.MathUtil;
+import net.sf.openrocket.util.Pair;
public class FlightData {
@@ -128,6 +129,9 @@ public class FlightData {
return maxVelocity;
}
+ /**
+ * NOTE: This value will also contain any possible acceleration peak when opening a parachute!
+ */
public double getMaxAcceleration() {
return maxAcceleration;
}
@@ -161,7 +165,6 @@ public class FlightData {
FlightDataBranch branch = branches.get(0);
maxAltitude = branch.getMaximum(FlightDataBranch.TYPE_ALTITUDE);
maxVelocity = branch.getMaximum(FlightDataBranch.TYPE_VELOCITY_TOTAL);
- maxAcceleration = branch.getMaximum(FlightDataBranch.TYPE_ACCELERATION_TOTAL);
maxMachNumber = branch.getMaximum(FlightDataBranch.TYPE_MACH_NUMBER);
flightTime = branch.getLast(FlightDataBranch.TYPE_TIME);
@@ -177,6 +180,7 @@ public class FlightData {
if (time == null || altitude == null) {
timeToApogee = Double.NaN;
+ maxAcceleration = Double.NaN;
return;
}
int index = 0;
@@ -192,6 +196,13 @@ public class FlightData {
timeToApogee = time.get(index);
else
timeToApogee = Double.NaN;
+
+ // Max. acceleration (must be after apogee time)
+ if (branch.get(FlightDataBranch.TYPE_ACCELERATION_TOTAL) != null) {
+ maxAcceleration = calculateMaxAcceleration();
+ } else {
+ maxAcceleration = Double.NaN;
+ }
}
@@ -203,4 +214,41 @@ public class FlightData {
}
+
+ /**
+ * Find the maximum acceleration before apogee.
+ */
+ private double calculateMaxAcceleration() {
+
+ // End check at first recovery device deployment
+ double endTime = Double.MAX_VALUE;
+ FlightDataBranch branch = this.getBranch(0);
+ for (Pair event: branch.getEvents()) {
+ if (event.getV().getType() == FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT) {
+ if (event.getV().getTime() < endTime) {
+ endTime = event.getV().getTime();
+ }
+ }
+ }
+
+ List time = branch.get(FlightDataBranch.TYPE_TIME);
+ List acceleration = branch.get(FlightDataBranch.TYPE_ACCELERATION_TOTAL);
+
+ if (time == null || acceleration == null) {
+ return Double.NaN;
+ }
+
+ double max = 0;
+
+ for (int i=0; i= endTime) {
+ break;
+ }
+ double a = acceleration.get(i);
+ if (a > max)
+ max = a;
+ }
+
+ return max;
+ }
}
diff --git a/src/net/sf/openrocket/simulation/FlightDataBranch.java b/src/net/sf/openrocket/simulation/FlightDataBranch.java
index c80c268f1..54ef01ca4 100644
--- a/src/net/sf/openrocket/simulation/FlightDataBranch.java
+++ b/src/net/sf/openrocket/simulation/FlightDataBranch.java
@@ -426,4 +426,8 @@ public class FlightDataBranch {
public boolean isMutable() {
return mutable;
}
+
+
+
+
}
diff --git a/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java b/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java
index d09e90ab6..de97c9778 100644
--- a/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java
+++ b/test/net/sf/openrocket/rocketcomponent/ComponentCompareTest.java
@@ -71,7 +71,7 @@ public class ComponentCompareTest {
@Test
- public void testComponentSimilarity() {
+ public void testComponentSimilarity() throws IllegalFinPointException {
FinSet trap = new TrapezoidFinSet(
5, // fins
5.0, // root