From 009dc2abf055b37b8281a2bc7c944ae17df3adf8 Mon Sep 17 00:00:00 2001 From: rodinia814 Date: Thu, 24 May 2012 23:28:58 +0000 Subject: [PATCH] Printable Centering Ring templates. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@721 180e2498-e6e9-4542-8430-84ac67f01cd8 --- core/resources/l10n/messages.properties | 1 + ...Transition.java => AbstractPrintable.java} | 24 +- .../gui/print/OpenRocketPrintable.java | 26 ++- .../openrocket/gui/print/PrintController.java | 220 ++++++++++-------- .../gui/print/PrintableCenteringRing.java | 104 +++++++++ .../gui/print/PrintableNoseCone.java | 31 ++- .../gui/print/PrintableTransition.java | 70 +++--- .../print/visitor/CenteringRingStrategy.java | 188 +++++++++++++++ .../gui/print/visitor/TransitionStrategy.java | 22 +- 9 files changed, 486 insertions(+), 200 deletions(-) rename core/src/net/sf/openrocket/gui/print/{AbstractPrintableTransition.java => AbstractPrintable.java} (82%) create mode 100644 core/src/net/sf/openrocket/gui/print/PrintableCenteringRing.java create mode 100644 core/src/net/sf/openrocket/gui/print/visitor/CenteringRingStrategy.java diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 5b44f44b..c7a472bb 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -1356,6 +1356,7 @@ OpenRocketPrintable.Transitiontemplates = Transition templates OpenRocketPrintable.Noseconetemplates = Nose Cone templates OpenRocketPrintable.Finmarkingguide = Fin marking guide OpenRocketPrintable.DesignReport = Design Report +OpenRocketPrintable.Centeringringtemplates = Centering Ring templates OpenRocketDocument.Redo = Redo OpenRocketDocument.Undo = Undo diff --git a/core/src/net/sf/openrocket/gui/print/AbstractPrintableTransition.java b/core/src/net/sf/openrocket/gui/print/AbstractPrintable.java similarity index 82% rename from core/src/net/sf/openrocket/gui/print/AbstractPrintableTransition.java rename to core/src/net/sf/openrocket/gui/print/AbstractPrintable.java index bb1d1240..739a7d91 100644 --- a/core/src/net/sf/openrocket/gui/print/AbstractPrintableTransition.java +++ b/core/src/net/sf/openrocket/gui/print/AbstractPrintable.java @@ -1,16 +1,18 @@ package net.sf.openrocket.gui.print; -import net.sf.openrocket.rocketcomponent.Transition; - -import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; -public abstract class AbstractPrintableTransition extends PrintableComponent { +public abstract class AbstractPrintable extends PrintableComponent { + /** + * A thin stroke. + */ + public final static BasicStroke thinStroke = new BasicStroke(1.0f); + /** - * The stroke of the transition arc. + * A thick stroke. */ - private final static BasicStroke thinStroke = new BasicStroke(1.0f); + public final static BasicStroke thickStroke = new BasicStroke(4.0f); /** * The X margin. @@ -21,14 +23,14 @@ public abstract class AbstractPrintableTransition extends PrintableComponent { * The Y margin. */ protected int marginY = (int) PrintUnit.INCHES.toPoints(0.25f); - + /** * Constructor. Initialize this printable with the component to be printed. * * @param isDoubleBuffered a boolean, true for double-buffering * @param transition the component to be printed */ - public AbstractPrintableTransition(boolean isDoubleBuffered, Transition transition) { + public AbstractPrintable(boolean isDoubleBuffered, T transition) { init(transition); } @@ -39,7 +41,7 @@ public abstract class AbstractPrintableTransition extends PrintableComponent { * * @param component the transition component */ - protected abstract void init(Transition component); + protected abstract void init(T component); /** * Draw the component onto the graphics context. @@ -47,12 +49,12 @@ public abstract class AbstractPrintableTransition extends PrintableComponent { * @param g2 the graphics context */ protected abstract void draw(Graphics2D g2); - + /** * Returns a generated image of the transition. 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 + * @return an awt image of the transition */ public Image createImage() { int width = getWidth() + marginX; diff --git a/core/src/net/sf/openrocket/gui/print/OpenRocketPrintable.java b/core/src/net/sf/openrocket/gui/print/OpenRocketPrintable.java index 456495f3..5bfd924c 100644 --- a/core/src/net/sf/openrocket/gui/print/OpenRocketPrintable.java +++ b/core/src/net/sf/openrocket/gui/print/OpenRocketPrintable.java @@ -22,29 +22,31 @@ public enum OpenRocketPrintable { NOSE_CONE_TEMPLATE("OpenRocketPrintable.Noseconetemplates", false, 3), // Transition Templates TRANSITION_TEMPLATE("OpenRocketPrintable.Transitiontemplates", false, 4), + // Centering Ring Templates + CENTERING_RING_TEMPLATE("OpenRocketPrintable.Centeringringtemplates", false, 5), // Finset shape - FIN_TEMPLATE("OpenRocketPrintable.Fintemplates", true, 5), + FIN_TEMPLATE("OpenRocketPrintable.Fintemplates", true, 6), // Fin marking guide. - FIN_MARKING_GUIDE("OpenRocketPrintable.Finmarkingguide", false, 6); - + FIN_MARKING_GUIDE("OpenRocketPrintable.Finmarkingguide", false, 7); + private static final Translator trans = Application.getTranslator(); - + /** * The description - will be displayed in the JTree. */ private String description; - + /** * Flag that indicates if the enum value is different depending upon stage. */ private boolean stageSpecific; - + /** * The order of the item as it appears in the printed document. */ private int order; - + /** * Constructor. * @@ -57,7 +59,7 @@ public enum OpenRocketPrintable { stageSpecific = staged; order = idx; } - + /** * Get the description of this printable. * @@ -66,7 +68,7 @@ public enum OpenRocketPrintable { public String getDescription() { return trans.get(description); } - + /** * Answers if this enum value has different meaning depending upon the stage. * @@ -75,7 +77,7 @@ public enum OpenRocketPrintable { public boolean isStageSpecific() { return stageSpecific; } - + /** * Answer the print order. This is relative to other enum values. No two enum values will have the same print * order value. @@ -85,7 +87,7 @@ public enum OpenRocketPrintable { public int getPrintOrder() { return order; } - + /** * Look up an enum value based on the description. * @@ -102,7 +104,7 @@ public enum OpenRocketPrintable { } return null; } - + /** * Get a list of ordered enum values that do not have stage affinity. * diff --git a/core/src/net/sf/openrocket/gui/print/PrintController.java b/core/src/net/sf/openrocket/gui/print/PrintController.java index 64d2b4d7..4088de70 100644 --- a/core/src/net/sf/openrocket/gui/print/PrintController.java +++ b/core/src/net/sf/openrocket/gui/print/PrintController.java @@ -12,9 +12,10 @@ import com.itextpdf.text.pdf.PdfBoolean; import com.itextpdf.text.pdf.PdfName; import com.itextpdf.text.pdf.PdfWriter; import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.gui.print.visitor.PageFitPrintStrategy; +import net.sf.openrocket.gui.print.visitor.CenteringRingStrategy; import net.sf.openrocket.gui.print.visitor.FinMarkingGuideStrategy; import net.sf.openrocket.gui.print.visitor.FinSetPrintStrategy; +import net.sf.openrocket.gui.print.visitor.PageFitPrintStrategy; import net.sf.openrocket.gui.print.visitor.PartsDetailVisitorStrategy; import net.sf.openrocket.gui.print.visitor.TransitionStrategy; @@ -28,108 +29,121 @@ import java.util.Set; * file. */ public class PrintController { - - /** - * Print the selected components to a PDF document. - * - * @param doc the OR document - * @param toBePrinted the user chosen items to print - * @param outputFile the file being written to - * @param settings the print settings + + /** + * Print the selected components to a PDF document. + * + * @param doc the OR document + * @param toBePrinted the user chosen items to print + * @param outputFile the file being written to + * @param settings the print settings * @param rotation the angle the rocket figure is rotated - */ - public void print(OpenRocketDocument doc, Iterator toBePrinted, OutputStream outputFile, - PrintSettings settings, double rotation) { - - Document idoc = new Document(getSize(settings)); - PdfWriter writer = null; - try { - writer = PdfWriter.getInstance(idoc, outputFile); - writer.setStrictImageSequence(true); - - writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE); - writer.addViewerPreference(PdfName.PICKTRAYBYPDFSIZE, PdfBoolean.PDFTRUE); - try { - idoc.open(); - Thread.sleep(1000); - } catch (InterruptedException e) { - } - - // Used to combine multiple components onto fewer sheets of paper - PageFitPrintStrategy pageFitPrint = new PageFitPrintStrategy(idoc, writer); - - while (toBePrinted.hasNext()) { - PrintableContext printableContext = toBePrinted.next(); - - Set stages = printableContext.getStageNumber(); - - switch (printableContext.getPrintable()) { - case DESIGN_REPORT: - DesignReport dp = new DesignReport(doc, idoc, rotation); - dp.writeToDocument(writer); - idoc.newPage(); - break; - case FIN_TEMPLATE: - final FinSetPrintStrategy finWriter = new FinSetPrintStrategy(idoc, writer, stages, pageFitPrint); - finWriter.writeToDocument(doc.getRocket()); - break; - case PARTS_DETAIL: - final PartsDetailVisitorStrategy detailVisitor = new PartsDetailVisitorStrategy(idoc, writer, stages); - detailVisitor.writeToDocument(doc.getRocket()); - detailVisitor.close(); - idoc.newPage(); - break; - case TRANSITION_TEMPLATE: - final TransitionStrategy tranWriter = new TransitionStrategy(idoc, writer, stages, pageFitPrint); - tranWriter.writeToDocument(doc.getRocket(), false); - idoc.newPage(); - break; - - case NOSE_CONE_TEMPLATE: - final TransitionStrategy coneWriter = new TransitionStrategy(idoc, writer, stages, pageFitPrint); - coneWriter.writeToDocument(doc.getRocket(), true); - idoc.newPage(); - break; - - case FIN_MARKING_GUIDE: - final FinMarkingGuideStrategy fmg = new FinMarkingGuideStrategy(idoc, writer); - fmg.writeToDocument(doc.getRocket()); - idoc.newPage(); - break; + */ + public void print(OpenRocketDocument doc, Iterator toBePrinted, OutputStream outputFile, + PrintSettings settings, double rotation) { + + Document idoc = new Document(getSize(settings)); + PdfWriter writer = null; + try { + writer = PdfWriter.getInstance(idoc, outputFile); + writer.setStrictImageSequence(true); + + writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE); + writer.addViewerPreference(PdfName.PICKTRAYBYPDFSIZE, PdfBoolean.PDFTRUE); + try { + idoc.open(); + Thread.sleep(1000); + } + catch (InterruptedException e) { + } + + // Used to combine multiple components onto fewer sheets of paper + PageFitPrintStrategy pageFitPrint = new PageFitPrintStrategy(idoc, writer); + + while (toBePrinted.hasNext()) { + PrintableContext printableContext = toBePrinted.next(); + + Set stages = printableContext.getStageNumber(); + + switch (printableContext.getPrintable()) { + case DESIGN_REPORT: + DesignReport dp = new DesignReport(doc, idoc, rotation); + dp.writeToDocument(writer); + idoc.newPage(); + break; + case FIN_TEMPLATE: + final FinSetPrintStrategy finWriter = new FinSetPrintStrategy(idoc, writer, stages, pageFitPrint); + finWriter.writeToDocument(doc.getRocket()); + break; + case PARTS_DETAIL: + final PartsDetailVisitorStrategy detailVisitor = new PartsDetailVisitorStrategy(idoc, writer, stages); + detailVisitor.writeToDocument(doc.getRocket()); + detailVisitor.close(); + idoc.newPage(); + break; + case TRANSITION_TEMPLATE: + final TransitionStrategy tranWriter = new TransitionStrategy(idoc, writer, stages, pageFitPrint); + tranWriter.writeToDocument(doc.getRocket(), false); + idoc.newPage(); + break; + + case NOSE_CONE_TEMPLATE: + final TransitionStrategy coneWriter = new TransitionStrategy(idoc, writer, stages, pageFitPrint); + coneWriter.writeToDocument(doc.getRocket(), true); + idoc.newPage(); + break; + + case CENTERING_RING_TEMPLATE: + final CenteringRingStrategy crWriter = new CenteringRingStrategy(idoc, writer, stages, + pageFitPrint); + crWriter.writeToDocument(doc.getRocket()); + idoc.newPage(); + break; + + case FIN_MARKING_GUIDE: + final FinMarkingGuideStrategy fmg = new FinMarkingGuideStrategy(idoc, writer); + fmg.writeToDocument(doc.getRocket()); + idoc.newPage(); + break; + } + } + // Write out parts that we are going to combine onto single sheets of paper + pageFitPrint.writeToDocument(doc.getRocket()); + idoc.newPage(); + + //Stupid iText throws a really nasty exception if there is no data when close is called. + if (writer.getCurrentDocumentSize() <= 140) { + writer.setPageEmpty(false); + } + writer.close(); + idoc.close(); + } + catch (DocumentException e) { + } + catch (ExceptionConverter ec) { + } + finally { + if (outputFile != null) { + try { + outputFile.close(); + } + catch (IOException e) { } - } - // Write out parts that we are going to combine onto single sheets of paper - pageFitPrint.writeToDocument(doc.getRocket()); - idoc.newPage(); - - //Stupid iText throws a really nasty exception if there is no data when close is called. - if (writer.getCurrentDocumentSize() <= 140) { - writer.setPageEmpty(false); - } - writer.close(); - idoc.close(); - } catch (DocumentException e) { - } catch (ExceptionConverter ec) { - } finally { - if (outputFile != null) { - try { - outputFile.close(); - } catch (IOException e) { - } - } - } - } - - /** - * Get the correct paper size from the print settings. - * - * @param settings the print settings - * @return the paper size - */ - private Rectangle getSize(PrintSettings settings) { - PaperSize size = settings.getPaperSize(); - PaperOrientation orientation = settings.getPaperOrientation(); - return orientation.orient(size.getSize()); - } - + } + } + } + + /** + * Get the correct paper size from the print settings. + * + * @param settings the print settings + * + * @return the paper size + */ + private Rectangle getSize(PrintSettings settings) { + PaperSize size = settings.getPaperSize(); + PaperOrientation orientation = settings.getPaperOrientation(); + return orientation.orient(size.getSize()); + } + } diff --git a/core/src/net/sf/openrocket/gui/print/PrintableCenteringRing.java b/core/src/net/sf/openrocket/gui/print/PrintableCenteringRing.java new file mode 100644 index 00000000..08d3f12c --- /dev/null +++ b/core/src/net/sf/openrocket/gui/print/PrintableCenteringRing.java @@ -0,0 +1,104 @@ +package net.sf.openrocket.gui.print; + +import net.sf.openrocket.rocketcomponent.CenteringRing; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Ellipse2D; + +/** + * This class creates a renderable centering ring. It depends only on AWT/Swing and can be called from other + * actors (like iText handlers) to render the centering ring on different graphics contexts. + */ +public class PrintableCenteringRing extends AbstractPrintable { + /** + * If the component to be drawn is a centering ring, save a reference to it. + */ + private CenteringRing target; + + /** + * The X margin. + */ + protected int marginX = (int) PrintUnit.INCHES.toPoints(0.25f); + + /** + * The Y margin. + */ + protected int marginY = (int) PrintUnit.INCHES.toPoints(0.25f); + + /** + * The line length of the cross hairs. + */ + private final int lineLength = 10; + + /** + * Construct a printable nose cone. + * + * @param theRing the component to print + */ + public PrintableCenteringRing(CenteringRing theRing) { + super(false, theRing); + } + + /** + * @param component the centering ring component + */ + @Override + protected void init(final CenteringRing component) { + + target = component; + + double radius = target.getOuterRadius(); + setSize((int) PrintUnit.METERS.toPoints(2 * radius) + marginX, + (int) PrintUnit.METERS.toPoints(2 * radius) + marginY); + } + + /** + * Draw a centering ring. + * + * @param g2 the graphics context + */ + @Override + protected void draw(Graphics2D g2) { + double radius = PrintUnit.METERS.toPoints(target.getOuterRadius()); + + Color original = g2.getBackground(); + double x = marginX; + double y = marginY; + Shape outerCircle = new Ellipse2D.Double(x, y, radius * 2, radius * 2); + g2.setColor(Color.lightGray); + g2.fill(outerCircle); + g2.setColor(Color.black); + g2.draw(outerCircle); + x += radius; + y += radius; + + double innerRadius = PrintUnit.METERS.toPoints(target.getInnerRadius()); + Shape innerCircle = new Ellipse2D.Double(x - innerRadius, y - innerRadius, innerRadius * 2, innerRadius * 2); + g2.setColor(original); + g2.fill(innerCircle); + g2.setColor(Color.black); + g2.draw(innerCircle); + + drawCross(g2, (int) x, (int) y, lineLength, lineLength); + } + + /** + * Draw the center cross-hair. + * + * @param g the graphics context + * @param x the x coordinate of the center point + * @param y the y coordinate of the center point + * @param width the width in pixels of the horizontal hair + * @param height the width in pixels of the vertical hair + */ + private void drawCross(Graphics g, int x, int y, int width, int height) { + g.setColor(Color.black); + ((Graphics2D) g).setStroke(thinStroke); + g.drawLine(x - width / 2, y, x + width / 2, y); + g.drawLine(x, y - height / 2, x, y + height / 2); + } + +} diff --git a/core/src/net/sf/openrocket/gui/print/PrintableNoseCone.java b/core/src/net/sf/openrocket/gui/print/PrintableNoseCone.java index 614aa35d..17f07230 100644 --- a/core/src/net/sf/openrocket/gui/print/PrintableNoseCone.java +++ b/core/src/net/sf/openrocket/gui/print/PrintableNoseCone.java @@ -1,38 +1,33 @@ package net.sf.openrocket.gui.print; -import java.awt.Graphics; +import net.sf.openrocket.gui.rocketfigure.TransitionShapes; +import net.sf.openrocket.rocketcomponent.NoseCone; +import net.sf.openrocket.util.Transformation; + import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; -import java.awt.print.PageFormat; -import java.awt.print.Printable; -import java.awt.print.PrinterException; -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; +public class PrintableNoseCone extends AbstractPrintable { -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) { + public PrintableNoseCone(NoseCone noseCone) { super(false, noseCone); } - + @Override - protected void init(Transition component) { - - target = (NoseCone) component; + protected void init(NoseCone component) { + + target = component; double radius = target.getForeRadius(); if (radius < target.getAftRadius()) { radius = target.getAftRadius(); @@ -40,7 +35,7 @@ public class PrintableNoseCone extends AbstractPrintableTransition { setSize((int) PrintUnit.METERS.toPoints(2 * radius) + marginX, (int) PrintUnit.METERS.toPoints(target.getLength() + target.getAftShoulderLength()) + marginY); } - + /** * Draw a nose cone. * @@ -49,7 +44,7 @@ public class PrintableNoseCone extends AbstractPrintableTransition { @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 + getOffsetX(), marginY + getOffsetY()); diff --git a/core/src/net/sf/openrocket/gui/print/PrintableTransition.java b/core/src/net/sf/openrocket/gui/print/PrintableTransition.java index fbe67692..4a2d6d81 100644 --- a/core/src/net/sf/openrocket/gui/print/PrintableTransition.java +++ b/core/src/net/sf/openrocket/gui/print/PrintableTransition.java @@ -1,18 +1,14 @@ package net.sf.openrocket.gui.print; +import net.sf.openrocket.rocketcomponent.Transition; + import java.awt.BasicStroke; -import java.awt.Graphics; 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 java.awt.print.PageFormat; -import java.awt.print.Printable; -import java.awt.print.PrinterException; - -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 @@ -22,8 +18,8 @@ import net.sf.openrocket.rocketcomponent.Transition; * Note: Currently nose cones are only supported by drawing the 2D projection of the profile. A more useful approach * may be to draw a myriahedral projection that can be cut out and bent to form the shape. */ -public class PrintableTransition extends AbstractPrintableTransition { - +public class PrintableTransition extends AbstractPrintable { + /** * Dashed array value. */ @@ -35,38 +31,38 @@ public class PrintableTransition extends AbstractPrintableTransition { 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. * @@ -75,13 +71,13 @@ public class PrintableTransition extends AbstractPrintableTransition { 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; @@ -91,19 +87,19 @@ public class PrintableTransition extends AbstractPrintableTransition { 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; @@ -114,23 +110,23 @@ public class PrintableTransition extends AbstractPrintableTransition { 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); @@ -138,21 +134,21 @@ public class PrintableTransition extends AbstractPrintableTransition { 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; @@ -160,13 +156,13 @@ public class PrintableTransition extends AbstractPrintableTransition { 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. * @@ -183,7 +179,7 @@ public class PrintableTransition extends AbstractPrintableTransition { g2.rotate(Math.toRadians(theta)); g2.translate(-x, -y); } - + /** * Draw a transition. * @@ -203,9 +199,9 @@ public class PrintableTransition extends AbstractPrintableTransition { circleCenterY, new Line2D.Float(-tick4X, 0, -tick4X, -8), theta); - + g2.setStroke(dashed); g2.draw(glueTab1); } - + } diff --git a/core/src/net/sf/openrocket/gui/print/visitor/CenteringRingStrategy.java b/core/src/net/sf/openrocket/gui/print/visitor/CenteringRingStrategy.java new file mode 100644 index 00000000..5241c228 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/print/visitor/CenteringRingStrategy.java @@ -0,0 +1,188 @@ +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.PdfWriter; +import net.sf.openrocket.gui.print.AbstractPrintable; +import net.sf.openrocket.gui.print.ITextHelper; +import net.sf.openrocket.gui.print.PrintableCenteringRing; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.rocketcomponent.CenteringRing; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.startup.Application; + +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.Set; + +/** + * A strategy for printing a centering ring to iText. + */ +public class CenteringRingStrategy { + + /** + * The logger. + */ + private static final LogHelper log = Application.getLogger(); + + /** + * The iText document. + */ + protected Document document; + + /** + * The direct iText writer. + */ + protected PdfWriter writer; + + /** + * The stages selected. + */ + protected Set stages; + + /** + * Strategy for fitting multiple components onto a page. + */ + protected PageFitPrintStrategy pageFitPrint; + + /** + * Constructor. + * + * @param doc The iText document + * @param theWriter The direct iText writer + * @param theStagesToVisit The stages to be visited by this strategy + */ + public CenteringRingStrategy(Document doc, PdfWriter theWriter, Set theStagesToVisit, PageFitPrintStrategy pageFit) { + document = doc; + writer = theWriter; + stages = theStagesToVisit; + pageFitPrint = pageFit; + } + + /** + * Recurse through the given rocket component. + * + * @param root the root component; all children will be visited recursively + */ + public void writeToDocument(final RocketComponent root) { + List rc = root.getChildren(); + goDeep(rc); + } + + + /** + * Recurse through the given rocket component. + * + * @param theRc an array of rocket components; all children will be visited recursively + */ + protected void goDeep(final List theRc) { + for (RocketComponent rocketComponent : theRc) { + if (rocketComponent instanceof CenteringRing) { + render((CenteringRing) rocketComponent); + } + else if (rocketComponent.getChildCount() > 0) { + goDeep(rocketComponent.getChildren()); + } + } + } + + /** + * The core behavior of this visitor. + * + * @param component the object to extract info about; a graphical image of the centering ring shape is drawn to the + * document + */ + private void render(final CenteringRing component) { + try { + AbstractPrintable pfs; + pfs = new PrintableCenteringRing(component); + + java.awt.Dimension size = pfs.getSize(); + final Dimension pageSize = getPageSize(); + if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) { + pageFitPrint.addComponent(pfs); + } + else { + BufferedImage image = (BufferedImage) pfs.createImage(); + ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()), + document, writer, image); + } + } + catch (DocumentException e) { + log.error("Could not render the centering ring.", e); + } + } + + /** + * 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; + } + + /** + * Get the dimensions of the paper page. + * + * @return an internal Dimension + */ + protected Dimension getPageSize() { + return new Dimension(document.getPageSize().getWidth(), + document.getPageSize().getHeight()); + } + + /** + * Convenience class to model a dimension. + */ + class Dimension { + /** + * Width, in points. + */ + public float width; + /** + * Height, in points. + */ + public float height; + + /** + * Constructor. + * + * @param w width + * @param h height + */ + public Dimension(float w, float h) { + width = w; + height = h; + } + + /** + * Get the width. + * + * @return the width + */ + public float getWidth() { + return width; + } + + /** + * Get the height. + * + * @return the height + */ + public float getHeight() { + return height; + } + } +} diff --git a/core/src/net/sf/openrocket/gui/print/visitor/TransitionStrategy.java b/core/src/net/sf/openrocket/gui/print/visitor/TransitionStrategy.java index bd450455..4752b3a7 100644 --- a/core/src/net/sf/openrocket/gui/print/visitor/TransitionStrategy.java +++ b/core/src/net/sf/openrocket/gui/print/visitor/TransitionStrategy.java @@ -3,9 +3,8 @@ 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.AbstractPrintableTransition; +import net.sf.openrocket.gui.print.AbstractPrintable; import net.sf.openrocket.gui.print.ITextHelper; import net.sf.openrocket.gui.print.PrintableNoseCone; import net.sf.openrocket.gui.print.PrintableTransition; @@ -15,7 +14,6 @@ import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.startup.Application; -import java.awt.*; import java.awt.image.BufferedImage; import java.util.List; import java.util.Set; @@ -103,9 +101,9 @@ public class TransitionStrategy { */ private void render(final Transition component) { try { - AbstractPrintableTransition pfs; + AbstractPrintable pfs; if (component instanceof NoseCone) { - pfs = new PrintableNoseCone(component); + pfs = new PrintableNoseCone((NoseCone)component); } else { pfs = new PrintableTransition(component); } @@ -143,20 +141,6 @@ public class TransitionStrategy { return wRatio <= 1.0d && hRatio <= 1.0d; } - /** - * Print the transition. - * - * @param theTransition the printable transition - */ - /*private void printOnOnePage(final AbstractPrintableTransition theTransition) { - Dimension d = getPageSize(); - PdfContentByte cb = writer.getDirectContent(); - Graphics2D g2 = cb.createGraphics(d.width, d.height); - theTransition.print(g2); - g2.dispose(); - document.newPage(); - }*/ - /** * Get the dimensions of the paper page. * -- 2.47.2