X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=core%2Fsrc%2Fnet%2Fsf%2Fopenrocket%2Fgui%2Fprint%2Fvisitor%2FCenteringRingStrategy.java;fp=core%2Fsrc%2Fnet%2Fsf%2Fopenrocket%2Fgui%2Fprint%2Fvisitor%2FCenteringRingStrategy.java;h=1df756997d30bd397ce6953746e2954189ad54c4;hb=9349577cdfdff682b2aabd6daa24fdc3a7449b58;hp=0000000000000000000000000000000000000000;hpb=30ba0a882f0c061176ba14dbf86d3d6fad096c02;p=debian%2Fopenrocket 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..1df75699 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/print/visitor/CenteringRingStrategy.java @@ -0,0 +1,270 @@ +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.PrintUnit; +import net.sf.openrocket.gui.print.PrintableCenteringRing; +import net.sf.openrocket.logging.LogHelper; +import net.sf.openrocket.rocketcomponent.CenteringRing; +import net.sf.openrocket.rocketcomponent.InnerTube; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.ArrayList; + +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()); + } + } + } + + /** + * Find the inner tubes that are physically supported by the given centering ring. Note that this only looks for + * motor mount tubes that are siblings to the centering ring. + * + * @param rc the centering ring, for which all motor mount tubes that run through it are located. + * + * @return the list of tubes found + */ + private List findMotorMount(CenteringRing rc) { + RocketComponent parent = rc.getParent(); + List siblings = parent.getChildren(); + + List mounts = new ArrayList(); + for (RocketComponent rocketComponents : siblings) { + if (rocketComponents != rc) { + if (rocketComponents instanceof InnerTube) { + InnerTube it = (InnerTube) rocketComponents; + if (overlaps(rc, it)) { + mounts.add(it); + } + } + } + } + + return mounts; + } + + /** + * Determine if the centering ring physically overlaps with the inner tube. + * + * @param one the centering ring + * @param two the inner body tube + * + * @return true if the two physically intersect, from which we infer that the centering ring supports the tube + */ + private boolean overlaps(CenteringRing one, InnerTube two) { + final double crTopPosition = one.asPositionValue(RocketComponent.Position.ABSOLUTE, one.getParent()); + final double mmTopPosition = two.asPositionValue(RocketComponent.Position.ABSOLUTE, two.getParent()); + final double crBottomPosition = one.getLength() + crTopPosition; + final double mmBottomPosition = two.getLength() + mmTopPosition; + + if (crTopPosition >= mmTopPosition && crTopPosition <= mmBottomPosition) { + return true; + } + if (crBottomPosition >= mmTopPosition && crBottomPosition <= mmBottomPosition) { + return true; + } + return false; + } + + /** + * 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 = PrintableCenteringRing.create(component, findMotorMount(component)); + + java.awt.Dimension size = pfs.getSize(); + final Dimension pageSize = getPageSize(); + if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) { + pageFitPrint.addComponent(pfs); + } + else { + int off = (int) (PrintUnit.POINTS_PER_INCH * 0.3f); + pfs.setPrintOffset(off, off); + BufferedImage image = (BufferedImage) pfs.createImage(); + ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()), + document, writer, image); + document.newPage(); + } + } + 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. + */ + public static class Dimension { + /** + * Width, in points. + */ + public float width; + /** + * Height, in points. + */ + public float height; + /** + * Breadth, in points. + */ + public float breadth = 0f; + + /** + * Constructor. + * + * @param w width + * @param h height + */ + public Dimension(float w, float h) { + width = w; + height = h; + } + + /** + * Constructor. + * + * @param w width + * @param h height + * @param b breadth; optionally used to represent radius + */ + public Dimension(float w, float h, float b) { + width = w; + height = h; + breadth = b; + } + + /** + * Get the width. + * + * @return the width + */ + public float getWidth() { + return width; + } + + /** + * Get the height. + * + * @return the height + */ + public float getHeight() { + return height; + } + + /** + * Get the breadth. + * + * @return the breadth + */ + public float getBreadth() { + return breadth; + } + } +}