version 1.1.9
authorplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 24 Nov 2011 19:19:39 +0000 (19:19 +0000)
committerplaa <plaa@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 24 Nov 2011 19:19:39 +0000 (19:19 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@208 180e2498-e6e9-4542-8430-84ac67f01cd8

26 files changed:
ChangeLog
README.TXT
ReleaseNotes
build.properties
src/net/sf/openrocket/gui/dialogs/AboutDialog.java
src/net/sf/openrocket/gui/main/SimulationEditDialog.java
src/net/sf/openrocket/gui/main/SimulationRunDialog.java
src/net/sf/openrocket/gui/plot/SimulationPlotPanel.java
src/net/sf/openrocket/gui/print/DesignReport.java
src/net/sf/openrocket/gui/print/PrintFigure.java
src/net/sf/openrocket/gui/print/PrintableContext.java
src/net/sf/openrocket/gui/print/PrintableNoseCone.java
src/net/sf/openrocket/gui/print/PrintableTransition.java
src/net/sf/openrocket/gui/scalefigure/RocketPanel.java
src/net/sf/openrocket/models/gravity/GravityModel.java
src/net/sf/openrocket/models/gravity/WGSGravityModel.java
src/net/sf/openrocket/simulation/AbstractSimulationStepper.java
src/net/sf/openrocket/util/GeodeticComputationStrategy.java
src/net/sf/openrocket/util/LineStyle.java
test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java [new file with mode: 0644]
test/net/sf/openrocket/util/GeodeticComputationStrategyTest.java
web/html/actions/updates.php
web/html/download.html
web/html/index.html
web/htp/htp.def
web/htp/news.htp

index b678d506a6af0408f9ec959cdf087eb4dbe0a09b..86aede34e6be7e0337cfc1ebda5e0bfa1cfa93f3 100644 (file)
--- a/ChangeLog
+++ b/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
 
index 6f969448908ca7d840664f09ed7432e7bc636ea8..c3c68458e9b120c94a4432847501a2d631e2e873 100644 (file)
@@ -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
 
index 140644ae3049b5e5b360cd904f139b5460aaf2b6..491e984690409cd5e6a6a7bd773e5935103aa88c 100644 (file)
@@ -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):
 -------------------------------
 
index 175fedc9b3547ea5278ad875a8b8afaaed8c0342..9a2cca35d05b3a5e1a5471de3baa6bfcc0df64dd 100644 (file)
@@ -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
index 9a10d9c345c1081ebed176ae9705f1d7ea55ca9f..5f42865ba83c18ccbcb164371ac6540b0abba7c9 100644 (file)
@@ -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>" +
index 00591c9462ac14d29fecfa2c0897a2ee022a56c2..92c2dac81aebc5a6d9c0a33b2c0c084338417346 100644 (file)
@@ -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);
        }
index fc4dc5af3ea49af0521b7aae9351026d4a900332..9ac4a3690f3c86fb9d3bd63d9295026bfed47576 100644 (file)
@@ -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") + " "));
index 898d7f67ae6d293439d5864b97577a9cac4ad872..f2afcae608ebcdc0b8de30052ef0fd60e1ea10d3 100644 (file)
@@ -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"));
                        
index d149b83cacdade4da3d9f6264040c7db830d8b7b..e0e22458f1865da0f14613816533087945d48404 100644 (file)
@@ -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;
-       }
-       
 }
index ae909269fbe4060e368adcc9fc32a9f6475fc32a..3f4655c6a1871a2b245f12fc94ccb62a8a2bedf3 100644 (file)
@@ -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();
+       }
 }
index 1f37435dae318219a381b115d450694ca34a81bc..4a5ddcacbfec91bc17938358082eb0b42973877a 100644 (file)
  */
 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();
+       }
+       
 }
index 77ea45b74b9c8d79c1cd951d07d0f02dae18d612..78afe6f052cb747358eb60d05b986a69412ea3f9 100644 (file)
@@ -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);
+               }
+       }
 }
index c8e6176131d919b184daefda09c236802e73b0ed..a70703daf9bf8ddfde945d30d12682b3182a8b44 100644 (file)
@@ -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);
+       }
+       
 }
index 60cc67b8ca209470a42811259ce4ec3adb21d7f8..8381313c4e5bddd6d2cf73b5daf1b086690422c8 100644 (file)
@@ -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>();
        
index 2c60b9b1543f8adbac741ca91e79fd2d0a8b9a76..6bee52a74bb10dea0bc786a852f860f7b646563b 100644 (file)
@@ -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
         */
index 253d4a41da504946169bc582f736e5b2514901ae..41fb5c233863cd2fc43a19c35ea1211c0bba2d4e 100644 (file)
@@ -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;
        }
index e971eed9a2a6150f23d8099eb36c55b4271dbc72..85be91201282613b629491f40c9f82eb53e1ca3d 100644 (file)
@@ -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
index 6f1fb53aa4dc425d893ebe7c17b6736325069f4a..f8a37a09dd5bc848966eb2bd98f71acf889b10f6 100644 (file)
@@ -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 earths 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 earths 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
index 2bb3af6d1765b294afe37458aeebe51f856b8421..fc2b4fdcb7ffca929b1792a1973935207f2ea483 100644 (file)
@@ -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;
        
diff --git a/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java b/test/net/sf/openrocket/models/gravity/WGSGravityModelTest.java
new file mode 100644 (file)
index 0000000..a0aea63
--- /dev/null
@@ -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);
+       }
+       
+}
index 72800d01f03c29c14e2a13159ff9fbfd690a0ec7..29efe41cd1aaf6bbcde5b99c3493793dbff3d001 100644 (file)
@@ -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
index 874b0cab28aebdfbce08afc27df5fceab2d4b879..6eb20b6cf17d969d1386f12103b19695429e7802 100644 (file)
@@ -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" .
     "";
index 90eed2a92f607a1d2848c545fce741d0b47c9ed7..86ca9fa125d69c56928212c771ad52ab2ff14a9c 100644 (file)
   <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.
     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>
         <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>
        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>
index ab701dd69b8eda8b7cc49b3fe9482b60cd5ff579..10a6cc204ee07d598a08d6bcb5473f25244598e2 100644 (file)
     <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>
     <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.
index cd4568d4a02f89bf7f15f4313fbae116014eaa04..be65ee3053fb1d12c61787f5861d74fed240b3b9 100644 (file)
@@ -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">
index 56db88da3b9f2ff8aef7a8f9a19c25565ade5e41..ae125a8c5515072628a5238aa1fc4cac836671de 100644 (file)
@@ -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>
 
     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>
 
   <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>