version 1.1.9
This commit is contained in:
parent
d82a370dd4
commit
ab9bf0bce3
10
ChangeLog
10
ChangeLog
@ -1,6 +1,14 @@
|
||||
2011-11-24 Sampo Niskanen
|
||||
|
||||
* Released version 1.1.9
|
||||
|
||||
2011-11-18 Doug Pedrick
|
||||
|
||||
* Printable Fin Marking Guides, Transitions, and Nose Cones (simple projection only)
|
||||
* Printable Fin Marking Guides, Transitions, and Nose Cones
|
||||
|
||||
2011-10-20 Sampo Niskanen
|
||||
|
||||
* [BUG] NPE if plot data type is not present
|
||||
|
||||
2011-10-11 Sampo Niskanen
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
OpenRocket - an Open Source model rocket simulator
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (C) 2007-2010 Sampo Niskanen
|
||||
Copyright (C) 2007-2011 Sampo Niskanen
|
||||
|
||||
|
||||
For license information see the file LICENSE.TXT.
|
||||
@ -25,5 +25,8 @@ Contributions have been made by:
|
||||
--------------------------------
|
||||
|
||||
Sampo Niskanen, main developer
|
||||
Doug Pedrick, support for reading RockSim designs
|
||||
Doug Pedrick, support for reading RockSim designs, printing
|
||||
Richard Graham, geodetic computations
|
||||
Boris du Reau, internationalization
|
||||
Tripoli France, Tripoli Spain, Stefan Lobas / ERIG, translations
|
||||
|
||||
|
||||
10
ReleaseNotes
10
ReleaseNotes
@ -1,3 +1,13 @@
|
||||
OpenRocket 1.1.9 (2011-11-24):
|
||||
-------------------------------
|
||||
|
||||
This release calculates rocket flight in real-world coordinates and
|
||||
takes into account geodetic effects (including coriolis effect) thanks
|
||||
to work by Richard Graham. Printing of transitions, nose cone
|
||||
profiles and fin marking guides is available thanks to Doug Pedrick.
|
||||
It also contains some usability features and bug fixes.
|
||||
|
||||
|
||||
OpenRocket 1.1.8 (2011-08-25):
|
||||
-------------------------------
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
# The OpenRocket build version
|
||||
|
||||
build.version=1.1.9pre
|
||||
build.version=1.1.9
|
||||
|
||||
|
||||
# The source of the package. When building a package for a specific
|
||||
|
||||
@ -30,7 +30,8 @@ public class AboutDialog extends JDialog {
|
||||
"<font size=\"+1\"><b>OpenRocket has been developed by:</b></font><br><br>" +
|
||||
"Sampo Niskanen (main developer)<br>" +
|
||||
"Doug Pedrick (RockSim file format, printing)<br>" +
|
||||
"Boris du Reau (internationalization, translation lead)<br><br>" +
|
||||
"Boris du Reau (internationalization, translation lead)<br>" +
|
||||
"Richard Graham (geodetic computations)<br><br>" +
|
||||
"<b>Translations by:</b><br><br>" +
|
||||
"Tripoli France (French)<br>" +
|
||||
"Stefan Lobas / ERIG e.V. (German)<br>" +
|
||||
|
||||
@ -88,8 +88,6 @@ public class SimulationEditDialog extends JDialog {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
|
||||
|
||||
// FIXME: NPE if FlightDataType has disappeared
|
||||
|
||||
public SimulationEditDialog(Window parent, Simulation s) {
|
||||
this(parent, s, 0);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ public class SimulationRunDialog extends JDialog {
|
||||
//// Simulation time:
|
||||
panel.add(new JLabel(trans.get("SimuRunDlg.lbl.Simutime") + " "), "gapright para");
|
||||
timeLabel = new JLabel("");
|
||||
panel.add(timeLabel, "growx, wrap rel");
|
||||
panel.add(timeLabel, "growx, wmin 200lp, wrap rel");
|
||||
|
||||
//// Altitude:
|
||||
panel.add(new JLabel(trans.get("SimuRunDlg.lbl.Altitude") + " "));
|
||||
|
||||
@ -118,8 +118,6 @@ public class SimulationPlotPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Bugs when expected branch is not present
|
||||
|
||||
configurationSelector.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
@ -189,7 +187,7 @@ public class SimulationPlotPanel extends JPanel {
|
||||
|
||||
typeSelectorPanel = new JPanel(new MigLayout("gapy rel"));
|
||||
JScrollPane scroll = new JScrollPane(typeSelectorPanel);
|
||||
this.add(scroll, "spany 2, height 10px, grow 100, gapright para");
|
||||
this.add(scroll, "spany 2, height 10px, wmin 400lp, grow 100, gapright para");
|
||||
|
||||
|
||||
//// Flight events
|
||||
@ -379,10 +377,6 @@ public class SimulationPlotPanel extends JPanel {
|
||||
private JComboBox axisSelector;
|
||||
|
||||
|
||||
public PlotTypeSelector(int index, FlightDataType type) {
|
||||
this(index, type, null, -1);
|
||||
}
|
||||
|
||||
public PlotTypeSelector(int plotIndex, FlightDataType type, Unit unit, int position) {
|
||||
super(new MigLayout("ins 0"));
|
||||
|
||||
|
||||
@ -6,9 +6,6 @@ package net.sf.openrocket.gui.print;
|
||||
import java.awt.Graphics2D;
|
||||
import java.io.IOException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
@ -152,7 +149,7 @@ public class DesignReport {
|
||||
PrintUtilities.addText(document, PrintUtilities.BIG_BOLD, ROCKET_DESIGN);
|
||||
|
||||
Rocket rocket = rocketDocument.getRocket();
|
||||
final Configuration configuration = rocket.getDefaultConfiguration();
|
||||
final Configuration configuration = rocket.getDefaultConfiguration().clone();
|
||||
configuration.setAllStages();
|
||||
PdfContentByte canvas = writer.getDirectContent();
|
||||
|
||||
@ -219,8 +216,6 @@ public class DesignReport {
|
||||
|
||||
String[] motorIds = rocket.getMotorConfigurationIDs();
|
||||
|
||||
List<Double> stageMasses = getStageMasses(rocket);
|
||||
|
||||
for (int j = 0; j < motorIds.length; j++) {
|
||||
String motorId = motorIds[j];
|
||||
if (motorId != null) {
|
||||
@ -244,29 +239,6 @@ public class DesignReport {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the motor list for all motor mounts.
|
||||
*
|
||||
* @param theRocket the rocket object
|
||||
* @param theMid the motor id
|
||||
*
|
||||
* @return a list of Motor
|
||||
*/
|
||||
private List<Motor> getMotorList(final Rocket theRocket, final String theMid) {
|
||||
Iterator<RocketComponent> components = theRocket.iterator();
|
||||
final List<Motor> motorList = new ArrayList<Motor>();
|
||||
while (components.hasNext()) {
|
||||
RocketComponent rocketComponent = components.next();
|
||||
if (rocketComponent instanceof MotorMount) {
|
||||
MotorMount mm = (MotorMount) rocketComponent;
|
||||
final Motor motor = mm.getMotor(theMid);
|
||||
if (motor != null) {
|
||||
motorList.add(motor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return motorList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint a diagram of the rocket into the PDF document.
|
||||
@ -545,27 +517,4 @@ public class DesignReport {
|
||||
return target.replace("]", "");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of cumulative stage masses. The latter masses include the mass
|
||||
* of the upper stages as well.
|
||||
*
|
||||
* @param rocket the rocket
|
||||
* @return a list containing the cumulative stage masses
|
||||
*/
|
||||
private List<Double> getStageMasses(final Rocket rocket) {
|
||||
List<Double> masses = new ArrayList<Double>();
|
||||
int stages = rocket.getStageCount();
|
||||
|
||||
Configuration config = new Configuration(rocket);
|
||||
MassCalculator calc = new BasicMassCalculator();
|
||||
|
||||
for (int i = 0; i < stages; i++) {
|
||||
config.setToStage(i);
|
||||
masses.add(calc.getCG(config, MassCalcType.NO_MOTORS).weight);
|
||||
}
|
||||
|
||||
return masses;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,23 +11,24 @@ import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
* to fit in the width of the chosen page size.
|
||||
*/
|
||||
public class PrintFigure extends RocketFigure {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration the configuration
|
||||
*/
|
||||
public PrintFigure (final Configuration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
protected double computeTy (int heightPx) {
|
||||
super.computeTy(heightPx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setScale (final double theScale) {
|
||||
this.scale = theScale; //dpi/0.0254*scaling;
|
||||
updateFigure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param configuration the configuration
|
||||
*/
|
||||
public PrintFigure(final Configuration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double computeTy(int heightPx) {
|
||||
super.computeTy(heightPx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setScale(final double theScale) {
|
||||
this.scale = theScale; //dpi/0.0254*scaling;
|
||||
updateFigure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,113 +4,118 @@
|
||||
*/
|
||||
package net.sf.openrocket.gui.print;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Instances of this class are meant to keep track of what the user has selected to be printed.
|
||||
*/
|
||||
public class PrintableContext implements Comparable<PrintableContext>, Iterable<PrintableContext> {
|
||||
|
||||
/**
|
||||
* The stage number. May be null for printables that have no stage meaning.
|
||||
*/
|
||||
private Set<Integer> stageNumber;
|
||||
|
||||
/**
|
||||
* The type of thing to be printed.
|
||||
*/
|
||||
private OpenRocketPrintable printable;
|
||||
|
||||
/**
|
||||
* Sort of a reverse map that tracks each type of printable item and the stages for which that item is to be printed.
|
||||
*/
|
||||
private final Map<OpenRocketPrintable, Set<Integer>> previous = new TreeMap<OpenRocketPrintable, Set<Integer>>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public PrintableContext () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param theStageNumber the stage number of the printable; may be null if not applicable
|
||||
* @param thePrintable the type of the thing to be printed
|
||||
*
|
||||
* @throws IllegalArgumentException thrown if thePrintable.isStageSpecific
|
||||
*/
|
||||
private PrintableContext (final Set<Integer> theStageNumber, final OpenRocketPrintable thePrintable)
|
||||
throws IllegalArgumentException {
|
||||
if (thePrintable.isStageSpecific() && theStageNumber == null) {
|
||||
throw new IllegalArgumentException("A stage number must be provided when a printable is stage specific.");
|
||||
}
|
||||
stageNumber = theStageNumber;
|
||||
printable = thePrintable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a type of printable to a stage (number).
|
||||
*
|
||||
* @param theStageNumber the stage number
|
||||
* @param thePrintable the printable to associate with the stage
|
||||
*/
|
||||
public void add (final Integer theStageNumber, final OpenRocketPrintable thePrintable) {
|
||||
Set<Integer> stages = previous.get(thePrintable);
|
||||
if (stages == null) {
|
||||
stages = new TreeSet<Integer>();
|
||||
previous.put(thePrintable, stages);
|
||||
}
|
||||
if (theStageNumber != null) {
|
||||
stages.add(theStageNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/** PrintableContext iterator. */
|
||||
public Iterator<PrintableContext> iterator () {
|
||||
return new Iterator<PrintableContext>() {
|
||||
|
||||
Iterator<OpenRocketPrintable> keyIter = previous.keySet().iterator();
|
||||
|
||||
@Override
|
||||
public boolean hasNext () {
|
||||
return keyIter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintableContext next () {
|
||||
final OpenRocketPrintable key = keyIter.next();
|
||||
return new PrintableContext(previous.get(key), key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove () {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stage number, if it's applicable to the printable.
|
||||
*
|
||||
* @return the stage number
|
||||
*/
|
||||
public Set<Integer> getStageNumber () {
|
||||
return stageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the printable.
|
||||
*
|
||||
* @return the printable
|
||||
*/
|
||||
public OpenRocketPrintable getPrintable () {
|
||||
return printable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo (final PrintableContext other) {
|
||||
return this.printable.getPrintOrder() - other.printable.getPrintOrder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The stage number. May be null for printables that have no stage meaning.
|
||||
*/
|
||||
private Set<Integer> stageNumber;
|
||||
|
||||
/**
|
||||
* The type of thing to be printed.
|
||||
*/
|
||||
private OpenRocketPrintable printable;
|
||||
|
||||
/**
|
||||
* Sort of a reverse map that tracks each type of printable item and the stages for which that item is to be printed.
|
||||
*/
|
||||
private final Map<OpenRocketPrintable, Set<Integer>> previous = new TreeMap<OpenRocketPrintable, Set<Integer>>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public PrintableContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param theStageNumber the stage number of the printable; may be null if not applicable
|
||||
* @param thePrintable the type of the thing to be printed
|
||||
*
|
||||
* @throws IllegalArgumentException thrown if thePrintable.isStageSpecific
|
||||
*/
|
||||
private PrintableContext(final Set<Integer> theStageNumber, final OpenRocketPrintable thePrintable)
|
||||
throws IllegalArgumentException {
|
||||
if (thePrintable.isStageSpecific() && theStageNumber == null) {
|
||||
throw new IllegalArgumentException("A stage number must be provided when a printable is stage specific.");
|
||||
}
|
||||
stageNumber = theStageNumber;
|
||||
printable = thePrintable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a type of printable to a stage (number).
|
||||
*
|
||||
* @param theStageNumber the stage number
|
||||
* @param thePrintable the printable to associate with the stage
|
||||
*/
|
||||
public void add(final Integer theStageNumber, final OpenRocketPrintable thePrintable) {
|
||||
Set<Integer> stages = previous.get(thePrintable);
|
||||
if (stages == null) {
|
||||
stages = new TreeSet<Integer>();
|
||||
previous.put(thePrintable, stages);
|
||||
}
|
||||
if (theStageNumber != null) {
|
||||
stages.add(theStageNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/** PrintableContext iterator. */
|
||||
@Override
|
||||
public Iterator<PrintableContext> iterator() {
|
||||
return new Iterator<PrintableContext>() {
|
||||
|
||||
Iterator<OpenRocketPrintable> keyIter = previous.keySet().iterator();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return keyIter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintableContext next() {
|
||||
final OpenRocketPrintable key = keyIter.next();
|
||||
return new PrintableContext(previous.get(key), key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stage number, if it's applicable to the printable.
|
||||
*
|
||||
* @return the stage number
|
||||
*/
|
||||
public Set<Integer> getStageNumber() {
|
||||
return stageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the printable.
|
||||
*
|
||||
* @return the printable
|
||||
*/
|
||||
public OpenRocketPrintable getPrintable() {
|
||||
return printable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final PrintableContext other) {
|
||||
return this.printable.getPrintOrder() - other.printable.getPrintOrder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,56 +1,59 @@
|
||||
package net.sf.openrocket.gui.print;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
|
||||
import net.sf.openrocket.gui.rocketfigure.TransitionShapes;
|
||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
import net.sf.openrocket.util.Transformation;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class PrintableNoseCone extends AbstractPrintableTransition {
|
||||
|
||||
/**
|
||||
* If the component to be drawn is a nose cone, save a reference to it.
|
||||
*/
|
||||
private NoseCone target;
|
||||
|
||||
/**
|
||||
* Construct a printable nose cone.
|
||||
*
|
||||
* @param noseCone the component to print
|
||||
*/
|
||||
public PrintableNoseCone(Transition noseCone) {
|
||||
super(false, noseCone);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Transition component) {
|
||||
|
||||
target = (NoseCone) component;
|
||||
double radius = target.getForeRadius();
|
||||
if (radius < target.getAftRadius()) {
|
||||
radius = target.getAftRadius();
|
||||
}
|
||||
setSize((int) PrintUnit.METERS.toPoints(2 * radius) + marginX,
|
||||
(int) PrintUnit.METERS.toPoints(target.getLength() + target.getAftShoulderLength()) + marginY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a nose cone.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
*/
|
||||
protected void draw(Graphics2D g2) {
|
||||
Shape[] shapes = TransitionShapes.getShapesSide(target, Transformation.rotate_x(0d), PrintUnit.METERS.toPoints(1));
|
||||
|
||||
if (shapes != null && shapes.length > 0) {
|
||||
Rectangle r = shapes[0].getBounds();
|
||||
g2.translate(marginX + r.getHeight() / 2, marginY);
|
||||
g2.rotate(Math.PI / 2);
|
||||
for (Shape shape : shapes) {
|
||||
g2.draw(shape);
|
||||
}
|
||||
g2.rotate(-Math.PI / 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the component to be drawn is a nose cone, save a reference to it.
|
||||
*/
|
||||
private NoseCone target;
|
||||
|
||||
/**
|
||||
* Construct a printable nose cone.
|
||||
*
|
||||
* @param noseCone the component to print
|
||||
*/
|
||||
public PrintableNoseCone(Transition noseCone) {
|
||||
super(false, noseCone);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Transition component) {
|
||||
|
||||
target = (NoseCone) component;
|
||||
double radius = target.getForeRadius();
|
||||
if (radius < target.getAftRadius()) {
|
||||
radius = target.getAftRadius();
|
||||
}
|
||||
setSize((int) PrintUnit.METERS.toPoints(2 * radius) + marginX,
|
||||
(int) PrintUnit.METERS.toPoints(target.getLength() + target.getAftShoulderLength()) + marginY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a nose cone.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
*/
|
||||
@Override
|
||||
protected void draw(Graphics2D g2) {
|
||||
Shape[] shapes = TransitionShapes.getShapesSide(target, Transformation.rotate_x(0d), PrintUnit.METERS.toPoints(1));
|
||||
|
||||
if (shapes != null && shapes.length > 0) {
|
||||
Rectangle r = shapes[0].getBounds();
|
||||
g2.translate(marginX + r.getHeight() / 2, marginY);
|
||||
g2.rotate(Math.PI / 2);
|
||||
for (Shape shape : shapes) {
|
||||
g2.draw(shape);
|
||||
}
|
||||
g2.rotate(-Math.PI / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
package net.sf.openrocket.gui.print;
|
||||
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
|
||||
/**
|
||||
* This class allows for a Transition to be printable. It does so by decorating an existing transition (which will not be
|
||||
* modified) and rendering it within a JPanel. The JPanel is not actually visualized on a display, but instead renders
|
||||
@ -18,188 +19,189 @@ import java.awt.geom.Point2D;
|
||||
* may be to draw a myriahedral projection that can be cut out and bent to form the shape.
|
||||
*/
|
||||
public class PrintableTransition extends AbstractPrintableTransition {
|
||||
|
||||
/**
|
||||
* Dashed array value.
|
||||
*/
|
||||
private final static float dash1[] = {4.0f};
|
||||
/**
|
||||
* The dashed stroke for glue tab.
|
||||
*/
|
||||
private final static BasicStroke dashed = new BasicStroke(1.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_MITER,
|
||||
10.0f, dash1, 0.0f);
|
||||
|
||||
/**
|
||||
* The layout is an outer arc, an inner arc, and two lines one either endpoints that connect the arcs.
|
||||
* Most of the math involves transposing geometric cartesian coordinates to the Java AWT coordinate system.
|
||||
*/
|
||||
private Path2D gp;
|
||||
|
||||
/**
|
||||
* The glue tab.
|
||||
*/
|
||||
private Path2D glueTab1;
|
||||
|
||||
/**
|
||||
* The alignment marks.
|
||||
*/
|
||||
private Line2D tick1, tick2;
|
||||
|
||||
/**
|
||||
* The x coordinates for the two ticks drawn at theta degrees.
|
||||
*/
|
||||
private int tick3X, tick4X;
|
||||
|
||||
/**
|
||||
* The angle, in degrees.
|
||||
*/
|
||||
private float theta;
|
||||
|
||||
/**
|
||||
* The x,y coordinates for where the virtual circle center is located.
|
||||
*/
|
||||
private int circleCenterX, circleCenterY;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param transition the transition to print
|
||||
*/
|
||||
public PrintableTransition(Transition transition) {
|
||||
super(false, transition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Transition component) {
|
||||
|
||||
double r1 = component.getAftRadius();
|
||||
double r2 = component.getForeRadius();
|
||||
|
||||
//Regardless of orientation, we have the convention of R1 as the smaller radius. Flip if different.
|
||||
if (r1 > r2) {
|
||||
r1 = r2;
|
||||
r2 = component.getAftRadius();
|
||||
}
|
||||
double len = component.getLength();
|
||||
double v = r2 - r1;
|
||||
double tmp = Math.sqrt(v * v + len * len);
|
||||
double factor = tmp / v;
|
||||
|
||||
theta = (float) (360d * v / tmp);
|
||||
|
||||
int r1InPoints = (int) PrintUnit.METERS.toPoints(r1 * factor);
|
||||
int r2InPoints = (int) PrintUnit.METERS.toPoints(r2 * factor);
|
||||
|
||||
int x = marginX;
|
||||
int tabOffset = 35;
|
||||
int y = tabOffset + marginY;
|
||||
|
||||
Arc2D.Double outerArc = new Arc2D.Double();
|
||||
Arc2D.Double innerArc = new Arc2D.Double();
|
||||
|
||||
//If the arcs are more than 3/4 of a circle, then assume the height (y) is the same as the radius of the bigger arc.
|
||||
if (theta >= 270) {
|
||||
y += r2InPoints;
|
||||
}
|
||||
//If the arc is between 1/2 and 3/4 of a circle, then compute the actual height based upon the angle and radius
|
||||
//of the bigger arc.
|
||||
else if (theta >= 180) {
|
||||
double thetaRads = Math.toRadians(theta - 180);
|
||||
y += (int) ((Math.cos(thetaRads) * r2InPoints) * Math.tan(thetaRads));
|
||||
}
|
||||
|
||||
circleCenterY = y;
|
||||
circleCenterX = r2InPoints + x;
|
||||
|
||||
//Create the larger arc.
|
||||
outerArc.setArcByCenter(circleCenterX, circleCenterY, r2InPoints, 180, theta, Arc2D.OPEN);
|
||||
|
||||
//Create the smaller arc.
|
||||
innerArc.setArcByCenter(circleCenterX, circleCenterY, r1InPoints, 180, theta, Arc2D.OPEN);
|
||||
|
||||
//Create the line between the start of the larger arc and the start of the smaller arc.
|
||||
Path2D.Double line = new Path2D.Double();
|
||||
line.setWindingRule(Path2D.WIND_NON_ZERO);
|
||||
line.moveTo(x, y);
|
||||
final int width = r2InPoints - r1InPoints;
|
||||
line.lineTo(width + x, y);
|
||||
|
||||
//Create the line between the endpoint of the larger arc and the endpoint of the smaller arc.
|
||||
Path2D.Double closingLine = new Path2D.Double();
|
||||
closingLine.setWindingRule(Path2D.WIND_NON_ZERO);
|
||||
Point2D innerArcEndPoint = innerArc.getEndPoint();
|
||||
closingLine.moveTo(innerArcEndPoint.getX(), innerArcEndPoint.getY());
|
||||
Point2D outerArcEndPoint = outerArc.getEndPoint();
|
||||
closingLine.lineTo(outerArcEndPoint.getX(), outerArcEndPoint.getY());
|
||||
|
||||
//Add all shapes to the polygon path.
|
||||
gp = new Path2D.Float(GeneralPath.WIND_EVEN_ODD, 4);
|
||||
gp.append(line, false);
|
||||
gp.append(outerArc, false);
|
||||
gp.append(closingLine, false);
|
||||
gp.append(innerArc, false);
|
||||
|
||||
//Create the glue tab.
|
||||
glueTab1 = new Path2D.Float(GeneralPath.WIND_EVEN_ODD, 4);
|
||||
glueTab1.moveTo(x, y);
|
||||
glueTab1.lineTo(x + tabOffset, y - tabOffset);
|
||||
glueTab1.lineTo(width + x - tabOffset, y - tabOffset);
|
||||
glueTab1.lineTo(width + x, y);
|
||||
|
||||
//Create tick marks for alignment, 1/4 of the width in from either edge
|
||||
int fromEdge = width / 4;
|
||||
final int tickLength = 8;
|
||||
//Upper left
|
||||
tick1 = new Line2D.Float(x + fromEdge, y, x + fromEdge, y + tickLength);
|
||||
//Upper right
|
||||
tick2 = new Line2D.Float(x + width - fromEdge, y, x + width - fromEdge, y + tickLength);
|
||||
|
||||
tick3X = r2InPoints - fromEdge;
|
||||
tick4X = r1InPoints + fromEdge;
|
||||
|
||||
setSize(gp.getBounds().width, gp.getBounds().height + tabOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw alignment marks on an angle.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
* @param x the center of the circle's x coordinate
|
||||
* @param y the center of the circle's y
|
||||
* @param line the line to draw
|
||||
* @param theta the angle
|
||||
*/
|
||||
private void drawAlignmentMarks(Graphics2D g2, int x, int y, Line2D.Float line, float theta) {
|
||||
g2.translate(x, y);
|
||||
g2.rotate(Math.toRadians(-theta));
|
||||
g2.draw(line);
|
||||
g2.rotate(Math.toRadians(theta));
|
||||
g2.translate(-x, -y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a transition.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
*/
|
||||
protected void draw(Graphics2D g2) {
|
||||
//Render it.
|
||||
g2.draw(gp);
|
||||
g2.draw(tick1);
|
||||
g2.draw(tick2);
|
||||
drawAlignmentMarks(g2, circleCenterX,
|
||||
circleCenterY,
|
||||
new Line2D.Float(-tick3X, 0, -tick3X, -8),
|
||||
theta);
|
||||
drawAlignmentMarks(g2, circleCenterX,
|
||||
circleCenterY,
|
||||
new Line2D.Float(-tick4X, 0, -tick4X, -8),
|
||||
theta);
|
||||
|
||||
g2.setStroke(dashed);
|
||||
g2.draw(glueTab1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dashed array value.
|
||||
*/
|
||||
private final static float dash1[] = { 4.0f };
|
||||
/**
|
||||
* The dashed stroke for glue tab.
|
||||
*/
|
||||
private final static BasicStroke dashed = new BasicStroke(1.0f,
|
||||
BasicStroke.CAP_BUTT,
|
||||
BasicStroke.JOIN_MITER,
|
||||
10.0f, dash1, 0.0f);
|
||||
|
||||
/**
|
||||
* The layout is an outer arc, an inner arc, and two lines one either endpoints that connect the arcs.
|
||||
* Most of the math involves transposing geometric cartesian coordinates to the Java AWT coordinate system.
|
||||
*/
|
||||
private Path2D gp;
|
||||
|
||||
/**
|
||||
* The glue tab.
|
||||
*/
|
||||
private Path2D glueTab1;
|
||||
|
||||
/**
|
||||
* The alignment marks.
|
||||
*/
|
||||
private Line2D tick1, tick2;
|
||||
|
||||
/**
|
||||
* The x coordinates for the two ticks drawn at theta degrees.
|
||||
*/
|
||||
private int tick3X, tick4X;
|
||||
|
||||
/**
|
||||
* The angle, in degrees.
|
||||
*/
|
||||
private float theta;
|
||||
|
||||
/**
|
||||
* The x,y coordinates for where the virtual circle center is located.
|
||||
*/
|
||||
private int circleCenterX, circleCenterY;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param transition the transition to print
|
||||
*/
|
||||
public PrintableTransition(Transition transition) {
|
||||
super(false, transition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Transition component) {
|
||||
|
||||
double r1 = component.getAftRadius();
|
||||
double r2 = component.getForeRadius();
|
||||
|
||||
//Regardless of orientation, we have the convention of R1 as the smaller radius. Flip if different.
|
||||
if (r1 > r2) {
|
||||
r1 = r2;
|
||||
r2 = component.getAftRadius();
|
||||
}
|
||||
double len = component.getLength();
|
||||
double v = r2 - r1;
|
||||
double tmp = Math.sqrt(v * v + len * len);
|
||||
double factor = tmp / v;
|
||||
|
||||
theta = (float) (360d * v / tmp);
|
||||
|
||||
int r1InPoints = (int) PrintUnit.METERS.toPoints(r1 * factor);
|
||||
int r2InPoints = (int) PrintUnit.METERS.toPoints(r2 * factor);
|
||||
|
||||
int x = marginX;
|
||||
int tabOffset = 35;
|
||||
int y = tabOffset + marginY;
|
||||
|
||||
Arc2D.Double outerArc = new Arc2D.Double();
|
||||
Arc2D.Double innerArc = new Arc2D.Double();
|
||||
|
||||
//If the arcs are more than 3/4 of a circle, then assume the height (y) is the same as the radius of the bigger arc.
|
||||
if (theta >= 270) {
|
||||
y += r2InPoints;
|
||||
}
|
||||
//If the arc is between 1/2 and 3/4 of a circle, then compute the actual height based upon the angle and radius
|
||||
//of the bigger arc.
|
||||
else if (theta >= 180) {
|
||||
double thetaRads = Math.toRadians(theta - 180);
|
||||
y += (int) ((Math.cos(thetaRads) * r2InPoints) * Math.tan(thetaRads));
|
||||
}
|
||||
|
||||
circleCenterY = y;
|
||||
circleCenterX = r2InPoints + x;
|
||||
|
||||
//Create the larger arc.
|
||||
outerArc.setArcByCenter(circleCenterX, circleCenterY, r2InPoints, 180, theta, Arc2D.OPEN);
|
||||
|
||||
//Create the smaller arc.
|
||||
innerArc.setArcByCenter(circleCenterX, circleCenterY, r1InPoints, 180, theta, Arc2D.OPEN);
|
||||
|
||||
//Create the line between the start of the larger arc and the start of the smaller arc.
|
||||
Path2D.Double line = new Path2D.Double();
|
||||
line.setWindingRule(Path2D.WIND_NON_ZERO);
|
||||
line.moveTo(x, y);
|
||||
final int width = r2InPoints - r1InPoints;
|
||||
line.lineTo(width + x, y);
|
||||
|
||||
//Create the line between the endpoint of the larger arc and the endpoint of the smaller arc.
|
||||
Path2D.Double closingLine = new Path2D.Double();
|
||||
closingLine.setWindingRule(Path2D.WIND_NON_ZERO);
|
||||
Point2D innerArcEndPoint = innerArc.getEndPoint();
|
||||
closingLine.moveTo(innerArcEndPoint.getX(), innerArcEndPoint.getY());
|
||||
Point2D outerArcEndPoint = outerArc.getEndPoint();
|
||||
closingLine.lineTo(outerArcEndPoint.getX(), outerArcEndPoint.getY());
|
||||
|
||||
//Add all shapes to the polygon path.
|
||||
gp = new Path2D.Float(GeneralPath.WIND_EVEN_ODD, 4);
|
||||
gp.append(line, false);
|
||||
gp.append(outerArc, false);
|
||||
gp.append(closingLine, false);
|
||||
gp.append(innerArc, false);
|
||||
|
||||
//Create the glue tab.
|
||||
glueTab1 = new Path2D.Float(GeneralPath.WIND_EVEN_ODD, 4);
|
||||
glueTab1.moveTo(x, y);
|
||||
glueTab1.lineTo(x + tabOffset, y - tabOffset);
|
||||
glueTab1.lineTo(width + x - tabOffset, y - tabOffset);
|
||||
glueTab1.lineTo(width + x, y);
|
||||
|
||||
//Create tick marks for alignment, 1/4 of the width in from either edge
|
||||
int fromEdge = width / 4;
|
||||
final int tickLength = 8;
|
||||
//Upper left
|
||||
tick1 = new Line2D.Float(x + fromEdge, y, x + fromEdge, y + tickLength);
|
||||
//Upper right
|
||||
tick2 = new Line2D.Float(x + width - fromEdge, y, x + width - fromEdge, y + tickLength);
|
||||
|
||||
tick3X = r2InPoints - fromEdge;
|
||||
tick4X = r1InPoints + fromEdge;
|
||||
|
||||
setSize(gp.getBounds().width, gp.getBounds().height + tabOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw alignment marks on an angle.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
* @param x the center of the circle's x coordinate
|
||||
* @param y the center of the circle's y
|
||||
* @param line the line to draw
|
||||
* @param theta the angle
|
||||
*/
|
||||
private void drawAlignmentMarks(Graphics2D g2, int x, int y, Line2D.Float line, float theta) {
|
||||
g2.translate(x, y);
|
||||
g2.rotate(Math.toRadians(-theta));
|
||||
g2.draw(line);
|
||||
g2.rotate(Math.toRadians(theta));
|
||||
g2.translate(-x, -y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a transition.
|
||||
*
|
||||
* @param g2 the graphics context
|
||||
*/
|
||||
@Override
|
||||
protected void draw(Graphics2D g2) {
|
||||
//Render it.
|
||||
g2.draw(gp);
|
||||
g2.draw(tick1);
|
||||
g2.draw(tick2);
|
||||
drawAlignmentMarks(g2, circleCenterX,
|
||||
circleCenterY,
|
||||
new Line2D.Float(-tick3X, 0, -tick3X, -8),
|
||||
theta);
|
||||
drawAlignmentMarks(g2, circleCenterX,
|
||||
circleCenterY,
|
||||
new Line2D.Float(-tick4X, 0, -tick4X, -8),
|
||||
theta);
|
||||
|
||||
g2.setStroke(dashed);
|
||||
g2.draw(glueTab1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -109,7 +109,6 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
||||
|
||||
|
||||
private SimulationWorker backgroundSimulationWorker = null;
|
||||
private boolean dirty = false;
|
||||
|
||||
private List<ChangeListener> listeners = new ArrayList<ChangeListener>();
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
package net.sf.openrocket.models.gravity;
|
||||
|
||||
//import net.sf.openrocket.util.Monitorable;
|
||||
import net.sf.openrocket.util.Monitorable;
|
||||
import net.sf.openrocket.util.WorldCoordinate;
|
||||
|
||||
/**
|
||||
* An interface to modelling gravitational acceleration.
|
||||
* An interface for modeling gravitational acceleration.
|
||||
*
|
||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||
*/
|
||||
public interface GravityModel extends Monitorable {
|
||||
|
||||
/**
|
||||
* Compute the gravity at a given world coordinate
|
||||
* Compute the gravitational acceleration at a given world coordinate
|
||||
*
|
||||
* @param wc the world coordinate location
|
||||
* @return gravitational acceleration in m/s/s
|
||||
*/
|
||||
|
||||
@ -4,7 +4,7 @@ import net.sf.openrocket.util.MathUtil;
|
||||
import net.sf.openrocket.util.WorldCoordinate;
|
||||
|
||||
/**
|
||||
* A gravity model based on the WGS84 elipsoid.
|
||||
* A gravity model based on the WGS84 ellipsoid.
|
||||
*
|
||||
* @author Richard Graham <richard@rdg.cc>
|
||||
*/
|
||||
@ -44,7 +44,7 @@ public class WGSGravityModel implements GravityModel {
|
||||
// Apply correction due to altitude. Note this assumes a spherical earth, but it is a small correction
|
||||
// so it probably doesn't really matter. Also does not take into account gravity of the atmosphere, again
|
||||
// correction could be done but not really necessary.
|
||||
double g_alt = g_0 * Math.pow(WorldCoordinate.REARTH / (WorldCoordinate.REARTH + wc.getAltitude()), 2);
|
||||
double g_alt = g_0 * MathUtil.pow2(WorldCoordinate.REARTH / (WorldCoordinate.REARTH + wc.getAltitude()));
|
||||
|
||||
return g_alt;
|
||||
}
|
||||
|
||||
@ -93,8 +93,6 @@ public abstract class AbstractSimulationStepper implements SimulationStepper {
|
||||
}
|
||||
|
||||
// Compute conditions
|
||||
//double altitude = status.getRocketPosition().z + status.getSimulationConditions().getLaunchAltitude();
|
||||
//gravity = status.getSimulationConditions().getGravityModel().getGravity(altitude);
|
||||
gravity = status.getSimulationConditions().getGravityModel().getGravity(status.getRocketWorldPosition());
|
||||
|
||||
// Call post-listener
|
||||
|
||||
@ -54,7 +54,7 @@ public enum GeodeticComputationStrategy {
|
||||
double newAlt = location.getAltitude() + delta.z;
|
||||
|
||||
// bearing (in radians, clockwise from north);
|
||||
// d/R is the angular distance (in radians), where d is the distance traveled and R is the earth’s radius
|
||||
// d/R is the angular distance (in radians), where d is the distance traveled and R is the earth's radius
|
||||
double d = MathUtil.hypot(delta.x, delta.y);
|
||||
|
||||
// Check for zero movement before computing bearing
|
||||
@ -99,7 +99,7 @@ public enum GeodeticComputationStrategy {
|
||||
double newAlt = location.getAltitude() + delta.z;
|
||||
|
||||
// bearing (in radians, clockwise from north);
|
||||
// d/R is the angular distance (in radians), where d is the distance traveled and R is the earth’s radius
|
||||
// d/R is the angular distance (in radians), where d is the distance traveled and R is the earth's radius
|
||||
double d = MathUtil.hypot(delta.x, delta.y);
|
||||
|
||||
// Check for zero movement before computing bearing
|
||||
|
||||
@ -25,10 +25,6 @@ public enum LineStyle {
|
||||
DASHDOT("LineStyle.Dash-dotted", new float[] { 8f, 3f, 2f, 3f });
|
||||
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
static {
|
||||
System.out.println("*** LineStyle initialized trans:" + trans + " ***");
|
||||
System.err.println("*** LineStyle initialized ***");
|
||||
}
|
||||
private final String name;
|
||||
private final float[] dashes;
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package net.sf.openrocket.models.gravity;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import net.sf.openrocket.util.WorldCoordinate;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class WGSGravityModelTest {
|
||||
|
||||
private WGSGravityModel model = new WGSGravityModel();
|
||||
|
||||
@Test
|
||||
public void testSurfaceGravity() {
|
||||
// Equator
|
||||
test(0, 0, 0, 9.780);
|
||||
// Mid-latitude
|
||||
test(45, 0, 0, 9.806);
|
||||
// Mid-latitude
|
||||
test(45, 99, 0, 9.806);
|
||||
// South pole
|
||||
test(-90, 0, 0, 9.832);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAltitudeEffect() {
|
||||
test(45, 0, -100, 9.806);
|
||||
test(45, 0, 0, 9.806);
|
||||
test(45, 0, 10, 9.806);
|
||||
test(45, 0, 100, 9.806);
|
||||
test(45, 0, 1000, 9.803);
|
||||
test(45, 0, 10000, 9.775);
|
||||
test(45, 0, 100000, 9.505);
|
||||
}
|
||||
|
||||
private void test(double lat, double lon, double alt, double g) {
|
||||
WorldCoordinate wc = new WorldCoordinate(lat, lon, alt);
|
||||
assertEquals(g, model.getGravity(wc), 0.001);
|
||||
assertEquals(g, model.getGravity(wc), 0.001);
|
||||
}
|
||||
|
||||
}
|
||||
@ -45,6 +45,7 @@ public class GeodeticComputationStrategyTest {
|
||||
|
||||
|
||||
// Test zero movement
|
||||
System.out.println("\nTesting zero movement");
|
||||
testAddCoordinate(50.0, 20.0, 0, 123, 50.0, 20.0, false);
|
||||
|
||||
|
||||
@ -55,22 +56,27 @@ public class GeodeticComputationStrategyTest {
|
||||
|
||||
// Long distance NE over England, crosses Greenwich meridian
|
||||
// 50 03N 005 42W to 58 38N 003 04E is 1109km at 027 16'07"
|
||||
System.out.println("\nTesting 1109km NE over England");
|
||||
testAddCoordinate(50 + 3 * min, -5 - 42 * min, 1109000, 27 + 16 * min + 7 * sec, 58 + 38 * min, 3 + 4 * min, false);
|
||||
|
||||
// SW over Brazil
|
||||
// -10N -60E to -11N -61E is 155.9km at 224 25'34"
|
||||
System.out.println("\nTesting 155km SW over Brazil");
|
||||
testAddCoordinate(-10, -60, 155900, 224 + 25 * min + 34 * sec, -11, -61, true);
|
||||
|
||||
// NW over the 180 meridian
|
||||
// 63N -179E to 63 01N 179E is 100.9km at 271 56'34"
|
||||
System.out.println("\nTesting 100km NW over 180 meridian");
|
||||
testAddCoordinate(63, -179, 100900, 271 + 56 * min + 34 * sec, 63 + 1 * min, 179, true);
|
||||
|
||||
// NE near the north pole
|
||||
// 89 50N 0E to 89 45N 175E is 46.29 km at 003 00'01"
|
||||
System.out.println("\nTesting 46km NE near north pole");
|
||||
testAddCoordinate(89 + 50 * min, 0, 46290, 3 + 0 * min + 1 * sec, 89 + 45 * min, 175, false);
|
||||
|
||||
// S directly over south pole
|
||||
// -89 50N 12E to -89 45N 192E is 46.33km at 180 00'00"
|
||||
System.out.println("\nTesting 46km directly over south pole ");
|
||||
testAddCoordinate(-89 - 50 * min, 12, 46330, 180, -89 - 45 * min, -168, false);
|
||||
|
||||
}
|
||||
@ -103,20 +109,20 @@ public class GeodeticComputationStrategyTest {
|
||||
|
||||
// Test WGS84
|
||||
/*
|
||||
* TODO: Since the example values are computed using a spherical earth approximation,
|
||||
* the WGS84 method will have significantly larger errors. The tolerance should be
|
||||
* increased correspondingly.
|
||||
* Note: Since the example values are computed using a spherical earth approximation,
|
||||
* the WGS84 method will have significantly larger errors. A tolerance of 1% accommodates
|
||||
* all cases except the NE flight near the north pole, where the ellipsoidal effect is
|
||||
* the greatest.
|
||||
*/
|
||||
//tolerance = ...
|
||||
tolerance = 0.04 * distance / 111325;
|
||||
System.out.println("\nWGS84 tolerance: " + tolerance);
|
||||
result = GeodeticComputationStrategy.WGS84.addCoordinate(result, coord);
|
||||
result = GeodeticComputationStrategy.WGS84.addCoordinate(wc, coord);
|
||||
|
||||
System.out.println("Difference Lat: " + Math.abs(finalLatitude - result.getLatitudeDeg()));
|
||||
System.out.println("Difference Lon: " + Math.abs(finalLongitude - result.getLongitudeDeg()));
|
||||
// FIXME: Re-enable these when they function
|
||||
// assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
|
||||
// assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
|
||||
// assertEquals(1000.0, result.getAltitude(), 0.0);
|
||||
assertEquals(finalLatitude, result.getLatitudeDeg(), tolerance);
|
||||
assertEquals(finalLongitude, result.getLongitudeDeg(), tolerance);
|
||||
assertEquals(1000.0, result.getAltitude(), 0.0);
|
||||
|
||||
|
||||
// Test FLAT
|
||||
|
||||
@ -80,21 +80,33 @@ header("Content-type: text/plain");
|
||||
$version = $_GET["version"];
|
||||
$updates = "";
|
||||
|
||||
$unstable = "1.1.8";
|
||||
$unstable = "1.1.9";
|
||||
$stable = "1.0.0";
|
||||
|
||||
if (preg_match("/^1\.1\.7/", $version)) {
|
||||
if (preg_match("/^1\.1\.8/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"6: Additional template printing\n" .
|
||||
"5: Geodetic computations\n" .
|
||||
"4: Bug fixes\n" .
|
||||
"";
|
||||
} else if (preg_match("/^1\.1\.7/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"6: Additional template printing\n" .
|
||||
"5: Geodetic computations\n" .
|
||||
"4: Bug fixes\n" .
|
||||
"";
|
||||
} else if (preg_match("/^1\.1\.6/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"8: Automatic rocket design optimization\n" .
|
||||
"6: Additional template printing\n" .
|
||||
"5: Geodetic computations\n" .
|
||||
"";
|
||||
} else if (preg_match("/^1\.1\.5/", $version)) {
|
||||
$updates = "Version: " . $unstable . "\n" .
|
||||
"8: Automatic rocket design optimization\n" .
|
||||
"6: Initial localization support\n" .
|
||||
"6: Additional template printing\n" .
|
||||
"5: Geodetic computations\n" .
|
||||
"5: Scaling support\n" .
|
||||
"4: Bug fixes\n" .
|
||||
"";
|
||||
|
||||
@ -48,6 +48,18 @@
|
||||
<div class="content">
|
||||
<div class="news">
|
||||
<h2>Recent news:</h2>
|
||||
<p><span class="date">24.11.2011:</span> Version 1.1.9 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>For this version Richard Graham has implemented geodetic
|
||||
computation methods, which take into account the curvature of the
|
||||
Earth and the coriolis effect. The computation method is selected
|
||||
by the <em>Geodetic calculations</em> option in the simulation
|
||||
options. It's not <em>(yet)</em> a full spherical computation model, but
|
||||
should be accurate enough for almost all sub-orbital needs.</p>
|
||||
<p>Doug Pedrick has also enhanced the printing system with the
|
||||
ability to print fin positioning guides, transition templates and
|
||||
nose cone profiles. Other smaller enhancements and bug fixes are
|
||||
also included.</p>
|
||||
<p><span class="date">25.8.2011:</span> Version 1.1.8 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release contains bug fixes to the optimization methods.
|
||||
@ -66,16 +78,6 @@
|
||||
easy to optimize against particulars of the simulation methods,
|
||||
instead of true physical phenomena. Always keep common sense at
|
||||
hand and take the results with a grain of salt.</p>
|
||||
<p><span class="date">22.7.2011:</span> Version 1.1.6 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release includes initial localization support and
|
||||
translations to French, German and Spanish. This is thanks to the
|
||||
great work of Boris du Reau, and the teams from Tripoli France,
|
||||
Tripoli Spain and ERIG e.V. If you prefer to use some other
|
||||
language than the system default, you can select the language on
|
||||
the "Options" tab of the preferences dialog.</p>
|
||||
<p>The release also includes design scaling support and numerous bug
|
||||
fixes.</p>
|
||||
</div>
|
||||
<div class="contentholder">
|
||||
<h2>Ready packages</h2>
|
||||
@ -94,13 +96,13 @@
|
||||
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /></a>
|
||||
</div>
|
||||
<div class="downloadbox">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.8/OpenRocket-1.1.8.jar/download">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.9/OpenRocket-1.1.9.jar/download">
|
||||
<strong>Download now!</strong>
|
||||
<span>OpenRocket-1.1.8.jar</span>
|
||||
<span>OpenRocket-1.1.9.jar</span>
|
||||
</a>
|
||||
<span class="alternative">
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.8/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.8/OpenRocket-1.1.8-src.zip/download">Source code</a>
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.9/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.9/OpenRocket-1.1.9-src.zip/download">Source code</a>
|
||||
</span>
|
||||
</div>
|
||||
<h3>Stable release</h3>
|
||||
@ -117,7 +119,7 @@
|
||||
Windows) by double-clicking the package icon. No installation is
|
||||
required.</p>
|
||||
<p>From the command line OpenRocket can be started by
|
||||
<span class="command">java -jar OpenRocket-1.1.8.jar</span></p>
|
||||
<span class="command">java -jar OpenRocket-1.1.9.jar</span></p>
|
||||
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
|
||||
@ -49,12 +49,12 @@
|
||||
<h2>Introduction</h2>
|
||||
<div class="rightpane">
|
||||
<div class="downloadbox">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.8/OpenRocket-1.1.8.jar/download">
|
||||
<a class="main" href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.9/OpenRocket-1.1.9.jar/download">
|
||||
<strong>Download now!</strong>
|
||||
<span>OpenRocket-1.1.8.jar</span>
|
||||
<span>OpenRocket-1.1.9.jar</span>
|
||||
</a>
|
||||
<span class="alternative">
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.8/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="https://sourceforge.net/projects/openrocket/files/openrocket/1.1.9/ReleaseNotes/view">Release notes</a> |
|
||||
<a href="download.html">Other versions</a>
|
||||
</span>
|
||||
</div>
|
||||
@ -68,7 +68,7 @@
|
||||
<a href="http://sourceforge.net/donate/index.php?group_id=260357"><img src="project-support.jpg" width="88" height="32" alt="Support This Project" /> </a>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>OpenRocket</strong> is an free, fully featured model
|
||||
<p><strong>OpenRocket</strong> is a free, fully featured model
|
||||
rocket simulator that allows you to design and simulate your
|
||||
rockets before actually building and flying them.</p>
|
||||
<p>The main features include:</p>
|
||||
@ -96,6 +96,18 @@
|
||||
<div class="clear"></div>
|
||||
<div class="news">
|
||||
<h2>News</h2>
|
||||
<p><span class="date">24.11.2011:</span> Version 1.1.9 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>For this version Richard Graham has implemented geodetic
|
||||
computation methods, which take into account the curvature of the
|
||||
Earth and the coriolis effect. The computation method is selected
|
||||
by the <em>Geodetic calculations</em> option in the simulation
|
||||
options. It's not <em>(yet)</em> a full spherical computation model, but
|
||||
should be accurate enough for almost all sub-orbital needs.</p>
|
||||
<p>Doug Pedrick has also enhanced the printing system with the
|
||||
ability to print fin positioning guides, transition templates and
|
||||
nose cone profiles. Other smaller enhancements and bug fixes are
|
||||
also included.</p>
|
||||
<p><span class="date">25.8.2011:</span> Version 1.1.8 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
<p>This release contains bug fixes to the optimization methods.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<set stableversion="1.0.0">
|
||||
<set developmentversion="1.1.8">
|
||||
<set developmentversion="1.1.9">
|
||||
<set version="${developmentversion}">
|
||||
|
||||
<def name="downloadbox">
|
||||
|
||||
@ -9,6 +9,21 @@
|
||||
|
||||
<!--- Remember to move the position of "onlyrecent" below! --->
|
||||
|
||||
<p><span class="date">24.11.2011:</span> Version 1.1.9 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
<p>For this version Richard Graham has implemented geodetic
|
||||
computation methods, which take into account the curvature of the
|
||||
Earth and the coriolis effect. The computation method is selected
|
||||
by the <em>Geodetic calculations</em> option in the simulation
|
||||
options. It's not <em>(yet)</em> a full spherical computation model, but
|
||||
should be accurate enough for almost all sub-orbital needs.</p>
|
||||
|
||||
<p>Doug Pedrick has also enhanced the printing system with the
|
||||
ability to print fin positioning guides, transition templates and
|
||||
nose cone profiles. Other smaller enhancements and bug fixes are
|
||||
also included.</p>
|
||||
|
||||
<p><span class="date">25.8.2011:</span> Version 1.1.8 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
@ -33,6 +48,10 @@
|
||||
instead of true physical phenomena. Always keep common sense at
|
||||
hand and take the results with a grain of salt.</p>
|
||||
|
||||
|
||||
<if not onlyrecent><!--- Older items not shown on download page: --->
|
||||
|
||||
|
||||
<p><span class="date">22.7.2011:</span> Version 1.1.6 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
@ -46,10 +65,6 @@
|
||||
<p>The release also includes design scaling support and numerous bug
|
||||
fixes.</p>
|
||||
|
||||
|
||||
<if not onlyrecent><!--- Older items not shown on download page: --->
|
||||
|
||||
|
||||
<p><span class="date">10.6.2011:</span> Version 1.1.5 is
|
||||
<a href="download.html">released</a>!</p>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user