]> git.gag.com Git - debian/openrocket/commitdiff
DGP - fixes to allow printing a fin template across multiple pages
authorrodinia814 <rodinia814@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 14 Sep 2010 04:07:28 +0000 (04:07 +0000)
committerrodinia814 <rodinia814@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 14 Sep 2010 04:07:28 +0000 (04:07 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/branches/printing@84 180e2498-e6e9-4542-8430-84ac67f01cd8

src/net/sf/openrocket/gui/print/DesignReport.java
src/net/sf/openrocket/gui/print/ITextHelper.java
src/net/sf/openrocket/gui/print/PrintableFinSet.java
src/net/sf/openrocket/gui/print/visitor/FinSetVisitorStrategy.java

index 3f36e12e667fc3f216abc2fde9f91bdae364fa37..36f9c200e5ef447bdd3741ab4b0dc6a6269af272 100644 (file)
@@ -250,25 +250,27 @@ public class DesignReport extends BaseVisitorStrategy {
     /**
      * Add the motor data for a motor configuration to the table.
      *
-     * @param motors a motor configuration's list of motors
-     * @param parent the parent to which the motor data will be added
+     * @param motors       a motor configuration's list of motors
+     * @param parent       the parent to which the motor data will be added
+     * @param stageWeights the stageWeights of each stage, in order
      */
-    private void addMotorData (List<Motor> motors, final PdfPTable parent, List<Double> weight) {
+    private void addMotorData (List<Motor> motors, final PdfPTable parent, List<Double> stageWeights) {
 
-        PdfPTable motorTable = new PdfPTable(7);
+        PdfPTable motorTable = new PdfPTable(8);
         motorTable.setWidthPercentage(68);
         motorTable.setHorizontalAlignment(Element.ALIGN_LEFT);
 
         final PdfPCell motorCell = ITextHelper.createCell("Motor", PdfPCell.BOTTOM);
-        final int mPad = 12;
+        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 Weight", PdfPCell.BOTTOM));
-        motorTable.addCell(ITextHelper.createCell("Dimensions", 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));
 
         DecimalFormat df = new DecimalFormat("#,##0.0#");
         for (int i = 0; i < motors.size(); i++) {
@@ -277,6 +279,8 @@ public class DesignReport extends BaseVisitorStrategy {
                 border = Rectangle.NO_BORDER;
             }
             Motor motor = motors.get(i);
+            double motorWeight = (motor.getLaunchCG().weight - motor.getEmptyCG().weight) * 1000;  //convert to grams
+
             final PdfPCell motorVCell = ITextHelper.createCell(motor.getDesignation(), border);
             motorVCell.setPaddingLeft(mPad);
             motorTable.addCell(motorVCell);
@@ -292,9 +296,13 @@ public class DesignReport extends BaseVisitorStrategy {
             motorTable.addCell(ITextHelper.createCell(df.format(motor.getTotalImpulseEstimate()) + " " + UnitGroup
                     .UNITS_IMPULSE
                     .getDefaultUnit().toString(), border));
-            double ttw = motor.getAverageThrustEstimate() / getStageWeight(weight, i);
+            double ttw = motor.getAverageThrustEstimate() / (getStageWeight(stageWeights, i) + (motor
+                    .getLaunchCG().weight * 9.80665));
             motorTable.addCell(ITextHelper.createCell(df.format(ttw) + ":1", border));
 
+            motorTable.addCell(ITextHelper.createCell(df.format(motorWeight) + " " + UnitGroup.UNITS_MASS
+                    .getDefaultUnit().toString(), border));
+
             final Unit motorUnit = UnitGroup.UNITS_MOTOR_DIMENSIONS
                     .getDefaultUnit();
             motorTable.addCell(ITextHelper.createCell(motorUnit.toString(motor.getDiameter()) +
@@ -429,7 +437,6 @@ public class DesignReport extends BaseVisitorStrategy {
         rocket.accept(new ComponentVisitor(svs));
         svs.close();
         List<Double> stages = svs.getStages();
-        //TODO: Add in motor mass
         for (int i = 0; i < stages.size(); i++) {
             Double stage = stages.get(i);
             stages.set(i, stage * 9.80665);
index 890c76e74f62ffa055e16043f2b3fc3b7b615669..47276e6a732e3462f737cb0dea8b1babe42c13a3 100644 (file)
@@ -4,22 +4,41 @@
 package net.sf.openrocket.gui.print;
 
 import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
 import com.itextpdf.text.Font;
 import com.itextpdf.text.Paragraph;
 import com.itextpdf.text.Phrase;
 import com.itextpdf.text.Rectangle;
+import com.itextpdf.text.pdf.PdfContentByte;
 import com.itextpdf.text.pdf.PdfPCell;
 import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
 
 /**
  * A bunch of helper methods for creating iText components.
  */
 public final class ITextHelper {
 
+    /**
+     * Create a cell for an iText table.
+     *
+     * @return a cell with bottom border
+     */
     public static PdfPCell createCell () {
         return createCell(Rectangle.BOTTOM);
     }
 
+    /**
+     * Create a cell for an iText table with the given border location.
+     *
+     * @param border the border location
+     *
+     * @return a cell with given border
+     */
     public static PdfPCell createCell (int border) {
         PdfPCell result = new PdfPCell();
         result.setBorder(border);
@@ -27,6 +46,13 @@ public final class ITextHelper {
         return result;
     }
 
+    /**
+     * Create a cell whose contents are a table.  No border.
+     *
+     * @param table the table to insert into the cell
+     *
+     * @return the cell containing a table
+     */
     public static PdfPCell createCell (PdfPTable table) {
         PdfPCell result = new PdfPCell();
         result.setBorder(PdfPCell.NO_BORDER);
@@ -35,33 +61,86 @@ public final class ITextHelper {
         return result;
     }
 
+    /**
+     * Create a cell whose contents are the given string. No border.  Standard PrintUtilities.NORMAL font.
+     *
+     * @param v the text of the cell.
+     *
+     * @return the cell containing the text
+     */
     public static PdfPCell createCell (String v) {
-        return createCell(v, Rectangle.NO_BORDER);
+        return createCell(v, Rectangle.NO_BORDER, PrintUtilities.NORMAL);
     }
-    
+
+    /**
+     * Create a cell whose contents are the given string , rendered with the given font.  No border.
+     *
+     * @param v    the text of the cell
+     * @param font the font
+     *
+     * @return the cell containing the text
+     */
     public static PdfPCell createCell (String v, Font font) {
-        return createCell(v, font);
+        return createCell(v, Rectangle.NO_BORDER, font);
     }
 
+    /**
+     * Create a cell whose contents are the given string with specified left and right padding (spacing).
+     *
+     * @param v        the text of the cell
+     * @param leftPad  the number of points to precede the text
+     * @param rightPad the number of points to follow the text
+     *
+     * @return the cell containing the text
+     */
     public static PdfPCell createCell (String v, int leftPad, int rightPad) {
-        PdfPCell c = createCell(v, Rectangle.NO_BORDER);
+        PdfPCell c = createCell(v, Rectangle.NO_BORDER, PrintUtilities.NORMAL);
         c.setPaddingLeft(leftPad);
         c.setPaddingRight(rightPad);
         return c;
     }
 
+    /**
+     * Create a cell whose contents are the given string with the given border.  Uses NORMAL font.
+     *
+     * @param v      the text of the cell
+     * @param border the border type
+     *
+     * @return the cell containing the text
+     */
     public static PdfPCell createCell (String v, int border) {
+        return createCell(v, border, PrintUtilities.NORMAL);
+    }
+
+    /**
+     * Complete create cell - fully qualified.  Create a cell whose contents are the given string with the given border
+     * and font.
+     *
+     * @param v      the text of the cell
+     * @param border the border type
+     * @param font   the font
+     *
+     * @return the cell containing the text
+     */
+    public static PdfPCell createCell (String v, int border, Font font) {
         PdfPCell result = new PdfPCell();
         result.setBorder(border);
         Chunk c = new Chunk();
-        c.setFont(new Font(Font.FontFamily.HELVETICA, PrintUtilities.NORMAL_FONT_SIZE));
+        c.setFont(font);
         c.append(v);
         result.addElement(c);
         return result;
     }
 
+    /**
+     * Create a phrase with the given text and font.
+     *
+     * @param text the text
+     * @param font the font
+     *
+     * @return an iText phrase
+     */
     public static Phrase createPhrase (String text, Font font) {
-
         Phrase p = new Phrase();
         final Chunk chunk = new Chunk(text);
         chunk.setFont(font);
@@ -69,12 +148,26 @@ public final class ITextHelper {
         return p;
     }
 
+    /**
+     * Create a phrase with the given text.
+     *
+     * @param text the text
+     *
+     * @return an iText phrase
+     */
     public static Phrase createPhrase (String text) {
         return createPhrase(text, PrintUtilities.NORMAL);
     }
 
+    /**
+     * Create a paragraph with the given text and font.
+     *
+     * @param text the text
+     * @param font the font
+     *
+     * @return an iText paragraph
+     */
     public static Paragraph createParagraph (String text, Font font) {
-
         Paragraph p = new Paragraph();
         final Chunk chunk = new Chunk(text);
         chunk.setFont(font);
@@ -82,7 +175,69 @@ public final class ITextHelper {
         return p;
     }
 
+    /**
+     * Create a paragraph with the given text and using NORMAL font.
+     *
+     * @param text the text
+     *
+     * @return an iText paragraph
+     */
     public static Paragraph createParagraph (String text) {
         return createParagraph(text, PrintUtilities.NORMAL);
     }
+
+    /**
+     * Break a large image up into page-size pieces and output each page in order to an iText document.  The image is
+     * overlayed with an matrix of pages running from left to right until the right side of the image is reached. Then
+     * the next 'row' of pages is output from left to right, and so on.
+     *
+     * @param pageSize a rectangle that defines the bounds of the page size
+     * @param doc      the iText document
+     * @param writer   the underlying content writer
+     * @param image    the source image
+     *
+     * @throws DocumentException thrown if the document could not be written
+     */
+    public static void renderImageAcrossPages (Rectangle pageSize, Document doc, PdfWriter writer, java.awt.Image image)
+            throws DocumentException {
+        // 4/10 of an inch margin
+        final int margin = (int) (PrintUnit.POINTS_PER_INCH * 0.4f);
+        float wPage = pageSize.getWidth() - 2 * margin;
+        float hPage = pageSize.getHeight() - 2 * margin;
+
+        float wImage = image.getWidth(null);
+        float hImage = image.getHeight(null);
+
+        java.awt.Rectangle crop = new java.awt.Rectangle(0, 0, (int) Math.min(wPage, wImage), (int) Math.min(hPage,
+                                                                                                             hImage));
+        PdfContentByte content = writer.getDirectContent();
+
+        double adjust;
+        while (true) {
+            BufferedImage subImage = ((BufferedImage) image).getSubimage((int) crop.getX(), (int) crop.getY(),
+                                                                         (int) crop.getWidth(), (int) crop.getHeight());
+
+            Graphics2D g2 = content.createGraphics(wPage, hPage);
+            g2.drawImage(subImage, margin - 1, margin - 1, null);
+            g2.dispose();
+            doc.newPage();
+            final int newX = (int) (crop.getWidth() + crop.getX());
+            if (newX < wImage) {
+                adjust = Math.min(wImage - newX, wPage);
+                crop = new java.awt.Rectangle(newX, (int) crop.getY(), (int) adjust,
+                                              (int) crop.getHeight());
+            }
+            else {
+                final int newY = (int) (crop.getHeight() + crop.getY());
+                if (newY < hImage) {
+                    adjust = Math.min(hImage - newY, hPage);
+                    crop = new java.awt.Rectangle(0, newY, (int) Math.min(wPage, wImage), (int) adjust);
+                }
+                else {
+                    break;
+                }
+            }
+        }
+    }
+
 }
\ No newline at end of file
index 6f82423c42608339881cdf9326994e31d340b4a4..56992fdcec5aef55f5ef8141473a235d2469d05e 100644 (file)
@@ -24,11 +24,6 @@ import java.awt.print.PrinterException;
  */
 public class PrintableFinSet extends JPanel implements Printable {
 
-    /**
-     * The actual fin set being printed.
-     */
-    private FinSet finset;
-
     /**
      * The object that represents the shape (outline) of the fin.  This gets drawn onto the Swing component.
      */
@@ -37,29 +32,38 @@ public class PrintableFinSet extends JPanel implements Printable {
     /**
      * The margin.
      */
-    private final int margin = 20;
-    
+    private final int margin = 10;
+
     /**
      * Constructor.
      *
      * @param fs the finset to print
      */
     public PrintableFinSet (FinSet fs) {
+        this(fs.getFinPointsWithTab());
+    }
+
+    /**
+     * Construct a fin set from a set of points.
+     *
+     * @param points an array of points.
+     */
+    public PrintableFinSet (Coordinate[] points) {
         super(false);
-        finset = fs;
-        init();
+        init(points);
         setBackground(Color.white);
     }
 
     /**
      * Initialize the fin set polygon and set the size of the component.
+     *
+     * @param points an array of points.
      */
-    private void init () {
-        Coordinate[] points = finset.getFinPointsWithTab();
+    private void init (Coordinate[] points) {
 
         polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, points.length);
         polygon.moveTo(0, 0);
-        
+
         int minX = 0;
         int minY = 0;
         int maxX = 0;
@@ -75,13 +79,13 @@ public class PrintableFinSet extends JPanel implements Printable {
             polygon.lineTo(x, y);
         }
         polygon.closePath();
-        
-        setSize(maxX-minX+ margin, maxY-minY+ margin);
+
+        setSize(maxX - minX + margin, maxY - minY + margin);
     }
 
     /**
      * From the java.awt.print.Printable interface.
-     * 
+     * <p/>
      * Prints the page at the specified index into the specified {@link java.awt.Graphics} context in the specified
      * format. A <code>PrinterJob</code> calls the <code>Printable</code> interface to request that a page be rendered
      * into the context specified by <code>graphics</code>.  The format of the page to be drawn is specified by
@@ -90,6 +94,8 @@ public class PrintableFinSet extends JPanel implements Printable {
      * <code>Graphics</code> class or subclass implements the {@link java.awt.print.PrinterGraphics} interface to
      * provide additional information.  If the <code>Printable</code> object aborts the print job then it throws a
      * {@link java.awt.print.PrinterException}.
+     * <p/>
+     * Note: This is not currently used in OpenRocket.  It's only here for reference.
      *
      * @param graphics   the context into which the page is drawn
      * @param pageFormat the size and orientation of the page being drawn
@@ -114,15 +120,14 @@ public class PrintableFinSet extends JPanel implements Printable {
     }
 
     /**
-     * 
-     * Returns a generated image of the fin set.  May then be used wherever AWT images can be used, or
-     * converted to another image/picture format and used accordingly.
-     * 
+     * Returns a generated image of the fin set.  May then be used wherever AWT images can be used, or converted to
+     * another image/picture format and used accordingly.
+     *
      * @return an awt image of the fin set
      */
     public Image createImage () {
-        int width = getWidth();
-        int height = getHeight();
+        int width = getWidth() + margin;
+        int height = getHeight() + margin;
         // Create a buffered image in which to draw 
         BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
         // Create a graphics contents on the buffered image 
@@ -148,7 +153,7 @@ public class PrintableFinSet extends JPanel implements Printable {
         super.paintComponent(g);
         Graphics2D g2d = (Graphics2D) g;
 
-        g2d.translate(margin +5, margin +15);
+        g2d.translate(margin, margin);
         g2d.setPaint(TemplateProperties.getFillColor());
         g2d.fill(polygon);
         g2d.setPaint(TemplateProperties.getLineColor());
index 8711039af801bbaf346f8106522cebd0c6d577fc..112ddb86c9643e26ca261864a8652a89cdb249d6 100644 (file)
@@ -4,8 +4,11 @@
 package net.sf.openrocket.gui.print.visitor;
 
 import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Rectangle;
 import com.itextpdf.text.pdf.PdfContentByte;
 import com.itextpdf.text.pdf.PdfWriter;
+import net.sf.openrocket.gui.print.ITextHelper;
 import net.sf.openrocket.gui.print.PrintableFinSet;
 import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
 import net.sf.openrocket.rocketcomponent.FinSet;
@@ -13,6 +16,7 @@ import net.sf.openrocket.rocketcomponent.FreeformFinSet;
 import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
 
 import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
 import java.util.Set;
 
 /**
@@ -22,7 +26,7 @@ public class FinSetVisitorStrategy extends BaseVisitorStrategy {
 
     /**
      * Constructor.
-     * 
+     *
      * @param doc              The iText document
      * @param theWriter        The direct iText writer
      * @param theStagesToVisit The stages to be visited by this strategy
@@ -30,7 +34,7 @@ public class FinSetVisitorStrategy extends BaseVisitorStrategy {
     public FinSetVisitorStrategy (Document doc, PdfWriter theWriter, Set<Integer> theStagesToVisit) {
         super(doc, theWriter, theStagesToVisit);
     }
-    
+
     /**
      * {@inheritDoc}
      */
@@ -57,20 +61,62 @@ public class FinSetVisitorStrategy extends BaseVisitorStrategy {
 
     /**
      * The core behavior of this visitor.
-     * 
-     * @param visitable  the object to extract info about; a graphical image of the fin shape is drawn to the document
+     *
+     * @param visitable the object to extract info about; a graphical image of the fin shape is drawn to the document
      */
     private void doVisit (final FinSet visitable) {
         if (shouldVisitStage(visitable.getStageNumber())) {
-            PrintableFinSet pfs = new PrintableFinSet(visitable);
+            try {
+                PrintableFinSet pfs = new PrintableFinSet(visitable);
 
-            net.sf.openrocket.gui.print.visitor.Dimension d = getPageSize();
-            PdfContentByte cb = writer.getDirectContent();
-            Graphics2D g2 = cb.createGraphics(d.width, d.height);
-            pfs.print(g2);
-            g2.dispose();
-            document.newPage();
+                java.awt.Dimension finSize = pfs.getSize();
+                final Dimension pageSize = getPageSize();
+                if (fitsOnOnePage(pageSize, finSize.getWidth(), finSize.getHeight())) {
+                    printOnOnePage(pfs);
+                }
+                else {
+                    BufferedImage image = (BufferedImage) pfs.createImage();
+                    ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
+                                                       document, writer, image);
+                }
+            }
+            catch (DocumentException e) {
+                e.printStackTrace();
+            }
         }
     }
+
+    /**
+     * Determine if the image will fit on the given page.
+     *
+     * @param pageSize the page size
+     * @param wImage   the width of the thing to be printed
+     * @param hImage   the height of the thing to be printed
+     *
+     * @return true if the thing to be printed will fit on a single page
+     */
+    private boolean fitsOnOnePage (Dimension pageSize, double wImage, double hImage) {
+        double wPage = pageSize.getWidth();
+        double hPage = pageSize.getHeight();
+
+        int wRatio = (int) Math.ceil(wImage / wPage);
+        int hRatio = (int) Math.ceil(hImage / hPage);
+
+        return wRatio <= 1.0d && hRatio <= 1.0d;
+    }
+
+    /**
+     * Print the fin set.
+     *
+     * @param thePfs the printable fin set
+     */
+    private void printOnOnePage (final PrintableFinSet thePfs) {
+        Dimension d = getPageSize();
+        PdfContentByte cb = writer.getDirectContent();
+        Graphics2D g2 = cb.createGraphics(d.width, d.height);
+        thePfs.print(g2);
+        g2.dispose();
+        document.newPage();
+    }
 }