Merge pull request #38 from kruland2607/bug-print-fin-template
Fix bug with fin marking guide. If a rocket has some split fins
This commit is contained in:
		
						commit
						3eccae0fc7
					
				@ -1,15 +1,5 @@
 | 
			
		||||
package net.sf.openrocket.gui.print;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.l10n.Translator;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.BodyTube;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.ExternalComponent;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.FinSet;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.Rocket;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
 | 
			
		||||
import net.sf.openrocket.startup.Application;
 | 
			
		||||
 | 
			
		||||
import javax.swing.JPanel;
 | 
			
		||||
import java.awt.BasicStroke;
 | 
			
		||||
import java.awt.Color;
 | 
			
		||||
import java.awt.Graphics;
 | 
			
		||||
@ -21,12 +11,22 @@ import java.awt.geom.Path2D;
 | 
			
		||||
import java.awt.image.BufferedImage;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import javax.swing.JPanel;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.l10n.Translator;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.BodyTube;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.ExternalComponent;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.FinSet;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.Rocket;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
 | 
			
		||||
import net.sf.openrocket.startup.Application;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This is the core Swing representation of a fin marking guide.  It can handle multiple fin sets on the same or
 | 
			
		||||
 * different body tubes. One marking guide will be created for any body tube that has a finset.  If a tube has multiple
 | 
			
		||||
@ -63,6 +63,7 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
	 * 2 PI radians (represents a circle).
 | 
			
		||||
	 */
 | 
			
		||||
	public final static double TWO_PI = 2 * Math.PI;
 | 
			
		||||
	public final static double PI = Math.PI;
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * The I18N translator.
 | 
			
		||||
@ -178,37 +179,37 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
	 *   |
 | 
			
		||||
	 *   |                                        |
 | 
			
		||||
	 *   P                                        v
 | 
			
		||||
     *   a      ---                 +----------------------------+  ------------
 | 
			
		||||
     *   g<------^-- x ------------>+                            +       ^
 | 
			
		||||
     *   e       |                  +                            +       |
 | 
			
		||||
     *           |                  +                            +     baseYOffset
 | 
			
		||||
     *   E       |                  +                            +       v
 | 
			
		||||
     *   d       |                  +<----------Fin------------->+ -------------
 | 
			
		||||
	 *   a      ---                 +----------------------------+  <- radialOrigin (in radians)
 | 
			
		||||
	 *   g<------^-- x ------------>+                            +
 | 
			
		||||
	 *   e       |                  +                            +
 | 
			
		||||
	 *           |                  +                            +
 | 
			
		||||
	 *   E       |                  +                            +
 | 
			
		||||
	 *   d       |                  +<----------Fin------------->+ <- y+ (finRadialPosition - radialOrigin) / TWO_PI * circumferenceInPoints
 | 
			
		||||
	 *   g       |                  +                            +
 | 
			
		||||
	 *   e       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
     *   |       |                  +                            +   baseSpacing
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
     *   |       |                  +<----------Fin------------->+  --------------
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +<----------Fin------------->+
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   | circumferenceInPoints    +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
     *   |       |                  +                            +    baseSpacing
 | 
			
		||||
     *   |       |                  +<------Launch Lug --------->+           -----
 | 
			
		||||
     *   |       |                  +                            +                 \
 | 
			
		||||
     *   |       |                  +                            +                 + yLLOffset
 | 
			
		||||
     *   |       |                  +                            +                 /
 | 
			
		||||
     *   |       |                  +<----------Fin------------->+  --------------
 | 
			
		||||
     *   |       |                  +                            +       ^
 | 
			
		||||
     *   |       |                  +                            +       |
 | 
			
		||||
     *   |       |                  +                            +    baseYOffset
 | 
			
		||||
     *   |       v                  +                            +       v
 | 
			
		||||
     *   |      ---                 +----------------------------+  --------------
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +<------Launch Lug --------->+
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +<----------Fin------------->+
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       |                  +                            +
 | 
			
		||||
	 *   |       v                  +                            +
 | 
			
		||||
	 *   |      ---                 +----------------------------+ <- radialOrigin + TWO_PI
 | 
			
		||||
	 *
 | 
			
		||||
	 *                              |<-------- width ----------->|
 | 
			
		||||
	 *
 | 
			
		||||
@ -250,53 +251,33 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
				
 | 
			
		||||
				drawMarkingGuide(g2, x, y, (int) Math.ceil(circumferenceInPoints), width);
 | 
			
		||||
				
 | 
			
		||||
                //Sort so that fins always precede lugs
 | 
			
		||||
                sort(componentList);
 | 
			
		||||
				double radialOrigin = findRadialOrigin(componentList);
 | 
			
		||||
				
 | 
			
		||||
				boolean hasMultipleComponents = componentList.size() > 1;
 | 
			
		||||
				
 | 
			
		||||
                double baseSpacing = 0d;
 | 
			
		||||
                double baseYOrigin = 0;
 | 
			
		||||
                double finRadial = 0d;
 | 
			
		||||
                int yFirstFin = y;
 | 
			
		||||
                int yLastFin = y;
 | 
			
		||||
                boolean firstFinSet = true;
 | 
			
		||||
 | 
			
		||||
				//fin1: 42  fin2: 25
 | 
			
		||||
				for (ExternalComponent externalComponent : componentList) {
 | 
			
		||||
					if (externalComponent instanceof FinSet) {
 | 
			
		||||
						FinSet fins = (FinSet) externalComponent;
 | 
			
		||||
						int finCount = fins.getFinCount();
 | 
			
		||||
                        int offset = 0;
 | 
			
		||||
                        baseSpacing = (circumferenceInPoints / finCount);
 | 
			
		||||
                        double baseRotation = fins.getBaseRotation();
 | 
			
		||||
                        if (!firstFinSet) {
 | 
			
		||||
                            //Adjust the rotation to a positive number.
 | 
			
		||||
                            while (baseRotation < 0) {
 | 
			
		||||
                                baseRotation += TWO_PI / finCount;
 | 
			
		||||
                            }
 | 
			
		||||
                            offset = computeYOffset(y, circumferenceInPoints, baseSpacing, baseYOrigin, finRadial, baseRotation);
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            //baseYOrigin is the distance from the top of the marking guide to the first fin of the first fin set.
 | 
			
		||||
                            //This measurement is used to base all subsequent finsets and lugs off of.
 | 
			
		||||
                            baseYOrigin = baseSpacing / 2;
 | 
			
		||||
                            offset = (int) (baseYOrigin) + y;
 | 
			
		||||
                            firstFinSet = false;
 | 
			
		||||
                        }
 | 
			
		||||
                        yFirstFin = y;
 | 
			
		||||
                        yLastFin = y;
 | 
			
		||||
                        finRadial = baseRotation;
 | 
			
		||||
 | 
			
		||||
						double baseAngularSpacing = (TWO_PI / finCount);
 | 
			
		||||
						double baseAngularOffset = fins.getBaseRotation();
 | 
			
		||||
						//Draw the fin marking lines.
 | 
			
		||||
						for (int fin = 0; fin < finCount; fin++) {
 | 
			
		||||
                            if (fin > 0) {
 | 
			
		||||
                                offset += baseSpacing;
 | 
			
		||||
                                yLastFin = offset;
 | 
			
		||||
							double angle = baseAngularOffset + fin * baseAngularSpacing - radialOrigin;
 | 
			
		||||
							// Translate angle into pixels using a linear transformation:
 | 
			
		||||
							// radialOrigin -> y
 | 
			
		||||
							// radialOrigin + TWO_PI -> y + circumferenceInPoints
 | 
			
		||||
							
 | 
			
		||||
							while (angle < 0) {
 | 
			
		||||
								angle += TWO_PI;
 | 
			
		||||
							}
 | 
			
		||||
                            else {
 | 
			
		||||
                                yFirstFin = offset;
 | 
			
		||||
							while (angle > TWO_PI) {
 | 
			
		||||
								angle -= TWO_PI;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							int offset = (int) Math.round(y + angle / TWO_PI * circumferenceInPoints);
 | 
			
		||||
							
 | 
			
		||||
							drawDoubleArrowLine(g2, x, offset, x + width, offset);
 | 
			
		||||
							//   if (hasMultipleComponents) {
 | 
			
		||||
							g2.drawString(externalComponent.getName(), x + (width / 3), offset - 2);
 | 
			
		||||
@ -305,16 +286,11 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
					}
 | 
			
		||||
					else if (externalComponent instanceof LaunchLug) {
 | 
			
		||||
						LaunchLug lug = (LaunchLug) externalComponent;
 | 
			
		||||
                        double yLLOffset = (lug.getRadialDirection() - finRadial) / TWO_PI;
 | 
			
		||||
                        //The placement of the lug line must respect the boundary of the outer marking guide.  In order
 | 
			
		||||
                        //to do that, place it above or below either the top or bottom fin line, based on the difference
 | 
			
		||||
                        //between their rotational directions.
 | 
			
		||||
                        if (yLLOffset < 0) {
 | 
			
		||||
                            yLLOffset = yLLOffset * circumferenceInPoints + yLastFin;
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            yLLOffset = yLLOffset * circumferenceInPoints + yFirstFin;
 | 
			
		||||
						double angle = lug.getRadialDirection() - radialOrigin;
 | 
			
		||||
						while (angle < 0) {
 | 
			
		||||
							angle += TWO_PI;
 | 
			
		||||
						}
 | 
			
		||||
						int yLLOffset = (int) Math.round(y + angle / TWO_PI * circumferenceInPoints);
 | 
			
		||||
						drawDoubleArrowLine(g2, x, (int) yLLOffset, x + width, (int) yLLOffset);
 | 
			
		||||
						g2.drawString(lug.getName(), x + (width / 3), (int) yLLOffset - 2);
 | 
			
		||||
						
 | 
			
		||||
@ -322,7 +298,7 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
				}
 | 
			
		||||
				//Only if the tube has a lug or multiple finsets does the orientation of the marking guide matter. So print 'Front'.
 | 
			
		||||
				if (hasMultipleComponents) {
 | 
			
		||||
                    drawFrontIndication(g2, x, y, (int) baseSpacing, (int) circumferenceInPoints, width);
 | 
			
		||||
					drawFrontIndication(g2, x, y, 0, (int) circumferenceInPoints, width);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				//At most, two marking guides horizontally.  After that, move down and back to the left margin.
 | 
			
		||||
@ -339,31 +315,73 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
     * Compute the y offset for the next fin line.
 | 
			
		||||
	 * This function finds a origin in radians for the template so no component is on the template seam.
 | 
			
		||||
	 * 
 | 
			
		||||
     * @param y                     the top margin
 | 
			
		||||
     * @param circumferenceInPoints the circumference (height) of the guide
 | 
			
		||||
     * @param baseSpacing           the circumference / fin count
 | 
			
		||||
     * @param baseYOrigin           the offset from the top of the guide to the first fin of the first fin set drawn
 | 
			
		||||
     * @param prevBaseRotation      the rotation of the previous finset
 | 
			
		||||
     * @param baseRotation          the rotation of the current finset
 | 
			
		||||
	 * If no fin or launch lug is at 0.0 radians, then the origin is 0.  If there is one, then half the distance
 | 
			
		||||
	 * between the two are taken.
 | 
			
		||||
	 * 
 | 
			
		||||
     * @return number of points from the top of the marking guide to the line to be drawn
 | 
			
		||||
	 * @param components
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
    private int computeYOffset(int y, double circumferenceInPoints, double baseSpacing, double baseYOrigin, double prevBaseRotation, double baseRotation) {
 | 
			
		||||
        int offset;
 | 
			
		||||
        double finRadialDifference = (baseRotation - prevBaseRotation) / TWO_PI;
 | 
			
		||||
        //If the fin line would be off the top of the marking guide, then readjust.
 | 
			
		||||
        if (baseYOrigin + finRadialDifference * circumferenceInPoints < 0) {
 | 
			
		||||
            offset = (int) (baseYOrigin + baseSpacing + finRadialDifference * circumferenceInPoints) + y;
 | 
			
		||||
	private double findRadialOrigin(List<ExternalComponent> components) {
 | 
			
		||||
		
 | 
			
		||||
		ArrayList<Double> positions = new ArrayList<Double>(3 * components.size());
 | 
			
		||||
		
 | 
			
		||||
		for (ExternalComponent component : components) {
 | 
			
		||||
			
 | 
			
		||||
			if (component instanceof LaunchLug) {
 | 
			
		||||
				double componentPosition = ((LaunchLug) component).getRadialDirection();
 | 
			
		||||
				
 | 
			
		||||
				positions.add(makeZeroTwoPi(componentPosition));
 | 
			
		||||
			}
 | 
			
		||||
        else if (baseYOrigin - finRadialDifference * circumferenceInPoints > 0) {
 | 
			
		||||
            offset = (int) (finRadialDifference * circumferenceInPoints + baseYOrigin) + y;
 | 
			
		||||
			
 | 
			
		||||
			if (component instanceof FinSet) {
 | 
			
		||||
				FinSet fins = (FinSet) component;
 | 
			
		||||
				double basePosition = fins.getBaseRotation();
 | 
			
		||||
				double angle = TWO_PI / fins.getFinCount();
 | 
			
		||||
				for (int i = fins.getFinCount(); i > 0; i--) {
 | 
			
		||||
					positions.add(makeZeroTwoPi(basePosition));
 | 
			
		||||
					basePosition += angle;
 | 
			
		||||
				}
 | 
			
		||||
        else {
 | 
			
		||||
            offset = (int) (finRadialDifference * circumferenceInPoints - baseYOrigin) + y;
 | 
			
		||||
			}
 | 
			
		||||
        return offset;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		Collections.sort(positions);
 | 
			
		||||
		
 | 
			
		||||
		Double[] pos = positions.toArray(new Double[0]);
 | 
			
		||||
		
 | 
			
		||||
		if (pos.length == 1) {
 | 
			
		||||
			
 | 
			
		||||
			return makeZeroTwoPi(pos[0] + PI);
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		double biggestDistance = TWO_PI - pos[pos.length - 1] + pos[0];
 | 
			
		||||
		double center = makeZeroTwoPi(pos[0] - biggestDistance / 2.0);
 | 
			
		||||
		
 | 
			
		||||
		for (int i = 1; i < pos.length; i++) {
 | 
			
		||||
			
 | 
			
		||||
			double d = pos[i] - pos[i - 1];
 | 
			
		||||
			if (d > biggestDistance) {
 | 
			
		||||
				biggestDistance = d;
 | 
			
		||||
				center = makeZeroTwoPi(pos[i - 1] + biggestDistance / 2.0);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return center;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static double makeZeroTwoPi(double value) {
 | 
			
		||||
		
 | 
			
		||||
		double v = value;
 | 
			
		||||
		while (v < 0) {
 | 
			
		||||
			v += TWO_PI;
 | 
			
		||||
		}
 | 
			
		||||
		while (v > TWO_PI) {
 | 
			
		||||
			v -= TWO_PI;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return v;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
@ -382,26 +400,6 @@ public class FinMarkingGuide extends JPanel {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    /**
 | 
			
		||||
     * Sort a list of ExternalComponent in-place. Forces FinSets to precede Launch Lugs.
 | 
			
		||||
     *
 | 
			
		||||
     * @param componentList a list of ExternalComponent
 | 
			
		||||
     */
 | 
			
		||||
    private void sort(List<ExternalComponent> componentList) {
 | 
			
		||||
        Collections.sort(componentList, new Comparator<ExternalComponent>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public int compare(ExternalComponent o1, ExternalComponent o2) {
 | 
			
		||||
                if (o1 instanceof FinSet) {
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
                if (o2 instanceof FinSet) {
 | 
			
		||||
                    return 1;
 | 
			
		||||
                }
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Draw the marking guide outline.
 | 
			
		||||
	 *
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user