Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / DesignReport.java
index e6290c3e906e6aee23db04d3ac7ad828c916457e..54c0f3eb8fa102bff8b7ec1f4e08d34335da1026 100644 (file)
@@ -6,13 +6,13 @@ package net.sf.openrocket.gui.print;
 import java.awt.Graphics2D;
 import java.io.IOException;
 import java.text.DecimalFormat;
+import java.util.List;
 
 import net.sf.openrocket.document.OpenRocketDocument;
 import net.sf.openrocket.document.Simulation;
 import net.sf.openrocket.gui.figureelements.FigureElement;
 import net.sf.openrocket.gui.figureelements.RocketInfo;
 import net.sf.openrocket.gui.scalefigure.RocketPanel;
-import net.sf.openrocket.gui.util.SwingPreferences;
 import net.sf.openrocket.logging.LogHelper;
 import net.sf.openrocket.masscalc.BasicMassCalculator;
 import net.sf.openrocket.masscalc.MassCalculator;
@@ -75,27 +75,33 @@ import com.itextpdf.text.pdf.PdfWriter;
  * </pre>
  */
 public class DesignReport {
-       
+
        /**
         * The logger.
         */
        private static final LogHelper log = Application.getLogger();
-       
-       /**
+    public static final double SCALE_FUDGE_FACTOR = 0.4d;
+
+    /**
         * The OR Document.
         */
        private OpenRocketDocument rocketDocument;
-       
+
        /**
         * A panel used for rendering of the design diagram.
         */
        final RocketPanel panel;
-       
+
        /**
         * The iText document.
         */
        protected Document document;
-       
+
+    /**
+     * The figure rotation.
+     */
+    private double rotation = 0d;
+
        /** The displayed strings. */
        private static final String STAGES = "Stages: ";
        private static final String MASS_WITH_MOTORS = "Mass (with motors): ";
@@ -121,19 +127,21 @@ public class DesignReport {
        private static final String LANDING_VELOCITY = "Landing Velocity";
        private static final String ROCKET_DESIGN = "Rocket Design";
        private static final double GRAVITY_CONSTANT = 9.80665d;
-       
+
        /**
         * Constructor.
         *
         * @param theRocDoc the OR document
         * @param theIDoc   the iText document
+     * @param figureRotation the angle the figure is rotated on the screen; printed report will mimic
         */
-       public DesignReport(OpenRocketDocument theRocDoc, Document theIDoc) {
+       public DesignReport(OpenRocketDocument theRocDoc, Document theIDoc, Double figureRotation) {
                document = theIDoc;
                rocketDocument = theRocDoc;
                panel = new RocketPanel(rocketDocument);
+        rotation = figureRotation;
        }
-       
+
        /**
         * Main entry point.  Prints the rocket drawing and design data.
         *
@@ -146,44 +154,38 @@ public class DesignReport {
                com.itextpdf.text.Rectangle pageSize = document.getPageSize();
                int pageImageableWidth = (int) pageSize.getWidth() - (int) pageSize.getBorderWidth() * 2;
                int pageImageableHeight = (int) pageSize.getHeight() / 2 - (int) pageSize.getBorderWidthTop();
-               
+
                PrintUtilities.addText(document, PrintUtilities.BIG_BOLD, ROCKET_DESIGN);
-               
+
                Rocket rocket = rocketDocument.getRocket();
                final Configuration configuration = rocket.getDefaultConfiguration().clone();
                configuration.setAllStages();
                PdfContentByte canvas = writer.getDirectContent();
-               
+
                final PrintFigure figure = new PrintFigure(configuration);
-               
+        figure.setRotation(rotation);
+
                FigureElement cp = panel.getExtraCP();
                FigureElement cg = panel.getExtraCG();
                RocketInfo text = panel.getExtraText();
-               
+
                double scale = paintRocketDiagram(pageImageableWidth, pageImageableHeight, canvas, figure, cp, cg);
-               
+
                canvas.beginText();
-               try {
-                       canvas.setFontAndSize(BaseFont.createFont(PrintUtilities.NORMAL.getFamilyname(), BaseFont.CP1252,
-                                                                                                               BaseFont.EMBEDDED), PrintUtilities.NORMAL_FONT_SIZE);
-               } catch (DocumentException e) {
-                       log.error("Could not set font.", e);
-               } catch (IOException e) {
-                       log.error("Could not create font.", e);
-               }
+               canvas.setFontAndSize(ITextHelper.getBaseFont(), PrintUtilities.NORMAL_FONT_SIZE);
                int figHeightPts = (int) (PrintUnit.METERS.toPoints(figure.getFigureHeight()) * 0.4 * (scale / PrintUnit.METERS
                                .toPoints(1)));
                final int diagramHeight = pageImageableHeight * 2 - 70 - (figHeightPts);
                canvas.moveText(document.leftMargin() + pageSize.getBorderWidthLeft(), diagramHeight);
                canvas.moveTextWithLeading(0, -16);
-               
+
                float initialY = canvas.getYTLM();
-               
+
                canvas.showText(rocketDocument.getRocket().getName());
-               
+
                canvas.newlineShowText(STAGES);
                canvas.showText("" + rocket.getStageCount());
-               
+
 
                if (configuration.hasMotors()) {
                        if (configuration.getStageCount() > 1) {
@@ -195,28 +197,29 @@ public class DesignReport {
                        canvas.newlineShowText(MASS_EMPTY);
                }
                canvas.showText(text.getMass(UnitGroup.UNITS_MASS.getDefaultUnit()));
-               
+
                canvas.newlineShowText(STABILITY);
                canvas.showText(text.getStability());
-               
+
                canvas.newlineShowText(CG);
                canvas.showText(text.getCg());
-               
+
                canvas.newlineShowText(CP);
                canvas.showText(text.getCp());
                canvas.endText();
-               
+
                try {
                        //Move the internal pointer of the document below that of what was just written using the direct byte buffer.
                        Paragraph paragraph = new Paragraph();
                        float finalY = canvas.getYTLM();
                        int heightOfDiagramAndText = (int) (pageSize.getHeight() - (finalY - initialY + diagramHeight));
-                       
+
                        paragraph.setSpacingAfter(heightOfDiagramAndText);
                        document.add(paragraph);
-                       
+
                        String[] motorIds = rocket.getMotorConfigurationIDs();
-                       
+            List<Simulation> simulations = rocketDocument.getSimulations();
+
                        for (int j = 0; j < motorIds.length; j++) {
                                String motorId = motorIds[j];
                                if (motorId != null) {
@@ -230,7 +233,8 @@ public class DesignReport {
                                        if (j > 1) {
                                                leading = 25;
                                        }
-                                       addFlightData(rocket, motorId, parent, leading);
+                    FlightData flight = findSimulation(motorId, simulations);
+                                       addFlightData(flight, rocket, motorId, parent, leading);
                                        addMotorData(rocket, motorId, parent);
                                        document.add(parent);
                                }
@@ -239,8 +243,8 @@ public class DesignReport {
                        log.error("Could not modify document.", e);
                }
        }
-       
-       
+
+
        /**
         * Paint a diagram of the rocket into the PDF document.
         *
@@ -261,28 +265,33 @@ public class DesignReport {
                theFigure.addRelativeExtra(theCp);
                theFigure.addRelativeExtra(theCg);
                theFigure.updateFigure();
-               
+
                double scale =
                                (thePageImageableWidth * 2.2) / theFigure.getFigureWidth();
-               
                theFigure.setScale(scale);
                /*
                 * page dimensions are in points-per-inch, which, in Java2D, are the same as pixels-per-inch; thus we don't need any conversion
                 */
                theFigure.setSize(thePageImageableWidth, thePageImageableHeight);
                theFigure.updateFigure();
-               
 
                final DefaultFontMapper mapper = new DefaultFontMapper();
                Graphics2D g2d = theCanvas.createGraphics(thePageImageableWidth, thePageImageableHeight * 2, mapper);
-               g2d.translate(20, 120);
-               
-               g2d.scale(0.4d, 0.4d);
+        final double halfFigureHeight = SCALE_FUDGE_FACTOR * theFigure.getFigureHeightPx()/2;
+        int y = PrintUnit.POINTS_PER_INCH;
+        //If the y dimension is negative, then it will potentially be drawn off the top of the page.  Move the origin
+        //to allow for this.
+        if (theFigure.getDimensions().getY() < 0.0d) {
+            y += (int)halfFigureHeight;
+        }
+        g2d.translate(20, y);
+
+               g2d.scale(SCALE_FUDGE_FACTOR, SCALE_FUDGE_FACTOR);
                theFigure.paint(g2d);
                g2d.dispose();
                return scale;
        }
-       
+
        /**
         * Add the motor data for a motor configuration to the table.
         *
@@ -291,41 +300,41 @@ public class DesignReport {
         * @param parent        the parent to which the motor data will be added
         */
        private void addMotorData(Rocket rocket, String motorId, final PdfPTable parent) {
-               
+
                PdfPTable motorTable = new PdfPTable(8);
                motorTable.setWidthPercentage(68);
                motorTable.setHorizontalAlignment(Element.ALIGN_LEFT);
-               
-               final PdfPCell motorCell = ITextHelper.createCell(MOTOR, PdfPCell.BOTTOM);
+
+               final PdfPCell motorCell = ITextHelper.createCell(MOTOR, PdfPCell.BOTTOM, PrintUtilities.SMALL);
                final int mPad = 10;
                motorCell.setPaddingLeft(mPad);
                motorTable.addCell(motorCell);
-               motorTable.addCell(ITextHelper.createCell(AVG_THRUST, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(BURN_TIME, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(MAX_THRUST, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(TOTAL_IMPULSE, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(THRUST_TO_WT, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(PROPELLANT_WT, PdfPCell.BOTTOM));
-               motorTable.addCell(ITextHelper.createCell(SIZE, PdfPCell.BOTTOM));
-               
+               motorTable.addCell(ITextHelper.createCell(AVG_THRUST, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(BURN_TIME, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(MAX_THRUST, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(TOTAL_IMPULSE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(THRUST_TO_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(PROPELLANT_WT, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+               motorTable.addCell(ITextHelper.createCell(SIZE, PdfPCell.BOTTOM, PrintUtilities.SMALL));
+
                DecimalFormat ttwFormat = new DecimalFormat("0.00");
-               
+
                MassCalculator massCalc = new BasicMassCalculator();
-               
+
                Configuration config = new Configuration(rocket);
                config.setMotorConfigurationID(motorId);
-               
+
                int totalMotorCount = 0;
                double totalPropMass = 0;
                double totalImpulse = 0;
                double totalTTW = 0;
-               
+
                int stage = 0;
                double stageMass = 0;
-               
+
                boolean topBorder = false;
                for (RocketComponent c : rocket) {
-                       
+
                        if (c instanceof Stage) {
                                config.setToStage(stage);
                                stage++;
@@ -334,26 +343,26 @@ public class DesignReport {
                                totalTTW = 0;
                                topBorder = true;
                        }
-                       
+
                        if (c instanceof MotorMount && ((MotorMount) c).isMotorMount()) {
                                MotorMount mount = (MotorMount) c;
-                               
+
                                if (mount.isMotorMount() && mount.getMotor(motorId) != null) {
                                        Motor motor = mount.getMotor(motorId);
                                        int motorCount = c.toAbsolute(Coordinate.NUL).length;
-                                       
+
 
                                        int border = Rectangle.NO_BORDER;
                                        if (topBorder) {
                                                border = Rectangle.TOP;
                                                topBorder = false;
                                        }
-                                       
+
                                        String name = motor.getDesignation();
                                        if (motorCount > 1) {
                                                name += " (" + Chars.TIMES + motorCount + ")";
                                        }
-                                       
+
                                        final PdfPCell motorVCell = ITextHelper.createCell(name, border);
                                        motorVCell.setPaddingLeft(mPad);
                                        motorTable.addCell(motorVCell);
@@ -365,21 +374,21 @@ public class DesignReport {
                                                        UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(motor.getMaxThrustEstimate()), border));
                                        motorTable.addCell(ITextHelper.createCell(
                                                        UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit(motor.getTotalImpulseEstimate()), border));
-                                       
+
                                        double ttw = motor.getAverageThrustEstimate() / (stageMass * GRAVITY_CONSTANT);
                                        motorTable.addCell(ITextHelper.createCell(
                                                        ttwFormat.format(ttw) + ":1", border));
-                                       
+
                                        double propMass = (motor.getLaunchCG().weight - motor.getEmptyCG().weight);
                                        motorTable.addCell(ITextHelper.createCell(
                                                        UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(propMass), border));
-                                       
+
                                        final Unit motorUnit = UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit();
                                        motorTable.addCell(ITextHelper.createCell(motorUnit.toString(motor.getDiameter()) +
                                                                                                                                "/" +
                                                                                                                                motorUnit.toString(motor.getLength()) + " " +
                                                                                                                                motorUnit.toString(), border));
-                                       
+
                                        // Sum up total count
                                        totalMotorCount += motorCount;
                                        totalPropMass += propMass * motorCount;
@@ -388,7 +397,7 @@ public class DesignReport {
                                }
                        }
                }
-               
+
                if (totalMotorCount > 1) {
                        int border = Rectangle.TOP;
                        final PdfPCell motorVCell = ITextHelper.createCell("Total:", border);
@@ -404,78 +413,67 @@ public class DesignReport {
                        motorTable.addCell(ITextHelper.createCell(
                                                UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(totalPropMass), border));
                        motorTable.addCell(ITextHelper.createCell("", border));
-                       
+
                }
-               
+
                PdfPCell c = new PdfPCell(motorTable);
                c.setBorder(PdfPCell.LEFT);
                c.setBorderWidthTop(0f);
                parent.addCell(c);
        }
-       
-       
+
+
        /**
-        * Add the motor data for a motor configuration to the table.
+        * Add the flight data for a simulation configuration to the table.
         *
+     * @param flight    the flight data for a single simulation
         * @param theRocket the rocket
         * @param motorId   a motor configuration id
-        * @param parent    the parent to which the motor data will be added
+        * @param parent    the parent to which the simulation flight data will be added
         * @param leading   the number of points for the leading
         */
-       private void addFlightData(final Rocket theRocket, final String motorId, final PdfPTable parent, int leading) {
-               
-               // Perform flight simulation
-               Rocket duplicate = theRocket.copyWithOriginalID();
-               FlightData flight = null;
-               try {
-                       Simulation simulation = ((SwingPreferences)Application.getPreferences()).getBackgroundSimulation(duplicate);
-                       simulation.getOptions().setMotorConfigurationID(motorId);
-                       simulation.simulate();
-                       flight = simulation.getSimulatedData();
-               } catch (SimulationException e1) {
-                       // Ignore
-               }
-               
-               // Output the flight data
+       private void addFlightData(final FlightData flight, final Rocket theRocket, final String motorId, final PdfPTable parent, int leading) {
+
+        // Output the flight data
                if (flight != null) {
                        try {
                                final Unit distanceUnit = UnitGroup.UNITS_DISTANCE.getDefaultUnit();
                                final Unit velocityUnit = UnitGroup.UNITS_VELOCITY.getDefaultUnit();
                                final Unit flightTimeUnit = UnitGroup.UNITS_FLIGHT_TIME.getDefaultUnit();
-                               
+
                                PdfPTable labelTable = new PdfPTable(2);
                                labelTable.setWidths(new int[] { 3, 2 });
                                final Paragraph chunk = ITextHelper.createParagraph(stripBrackets(
                                                        theRocket.getMotorConfigurationNameOrDescription(motorId)), PrintUtilities.BOLD);
                                chunk.setLeading(leading);
                                chunk.setSpacingAfter(3f);
-                               
+
                                document.add(chunk);
-                               
+
                                final PdfPCell cell = ITextHelper.createCell(ALTITUDE, 2, 2);
                                cell.setUseBorderPadding(false);
                                cell.setBorderWidthTop(0f);
                                labelTable.addCell(cell);
                                labelTable.addCell(ITextHelper.createCell(distanceUnit.toStringUnit(flight.getMaxAltitude()), 2, 2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(FLIGHT_TIME, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(flightTimeUnit.toStringUnit(flight.getFlightTime()), 2, 2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(TIME_TO_APOGEE, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(flightTimeUnit.toStringUnit(flight.getTimeToApogee()), 2, 2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(VELOCITY_OFF_PAD, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getLaunchRodVelocity()), 2, 2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(MAX_VELOCITY, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getMaxVelocity()), 2, 2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(DEPLOYMENT_VELOCITY, 2,2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getDeploymentVelocity()),2,2));
-                               
+
                                labelTable.addCell(ITextHelper.createCell(LANDING_VELOCITY, 2, 2));
                                labelTable.addCell(ITextHelper.createCell(velocityUnit.toStringUnit(flight.getGroundHitVelocity()), 2, 2));
-                               
+
                                //Add the table to the parent; have to wrap it in a cell
                                PdfPCell c = new PdfPCell(labelTable);
                                c.setBorder(PdfPCell.RIGHT);
@@ -487,8 +485,36 @@ public class DesignReport {
                        }
                }
        }
-       
-       /**
+
+    /**
+     * Locate the simulation based on the motor id.  Copy the simulation and execute it, then return the resulting
+     * flight data.
+     *
+     * @param motorId     the motor id corresponding to the simulation to find
+     * @param simulations the list of simulations currently associated with the rocket
+     *
+     * @return the flight data from the simulation for the specified motor id, or null if not found
+     */
+    private FlightData findSimulation(final String motorId, List<Simulation> simulations) {
+        // Perform flight simulation
+        FlightData flight = null;
+        try {
+            for (int i = 0; i < simulations.size(); i++) {
+                Simulation simulation =  simulations.get(i);
+                if (simulation.getOptions().getMotorConfigurationID().equals(motorId)) {
+                    simulation = simulation.copy();
+                    simulation.simulate();
+                    flight = simulation.getSimulatedData();
+                    break;
+                }
+            }
+        } catch (SimulationException e1) {
+            // Ignore
+        }
+        return flight;
+    }
+
+    /**
         * Strip [] brackets from a string.
         *
         * @param target the original string
@@ -498,7 +524,7 @@ public class DesignReport {
        private String stripBrackets(String target) {
                return stripLeftBracket(stripRightBracket(target));
        }
-       
+
        /**
         * Strip [ from a string.
         *
@@ -509,7 +535,7 @@ public class DesignReport {
        private String stripLeftBracket(String target) {
                return target.replace("[", "");
        }
-       
+
        /**
         * Strip ] from a string.
         *
@@ -520,5 +546,5 @@ public class DesignReport {
        private String stripRightBracket(String target) {
                return target.replace("]", "");
        }
-       
+
 }