Adds tube fin sets to fin marking guide.

Creates a guide if and only if a fin set or tube fin set exists. Allows for multiple fin and/or tube fin sets and multiple launch lugs and/or rail buttons. But, not without overlaping labels when dissimilar components and/or similar components with dissimilar names have the same rotation.
This commit is contained in:
hcraigmiller 2022-04-13 23:48:27 -07:00
parent 507dbb7c36
commit 60bb0a925e

View File

@ -22,17 +22,19 @@ import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.TubeFinSet;
import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.RailButton;
import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application; 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 * This is the core Swing representation of a fin marking guide. It can handle multiple fin and/or tube fin sets
* different body tubes. One marking guide will be created for any body tube that has a finset. If a tube has multiple * on the same or different body tubes. One marking guide will be created for each body tube that has a fin set.
* finsets, then they are combined onto one marking guide. It also includes launch lug marking line(s) if lugs are * If a tube has multiple fin and/or tube fin sets, then they are combined onto one marking guide. It also includes
* present. If (and only if) a launch lug exists, then the word 'Front' is affixed to the leading edge of the guide to * launch lugs and/or rail button marking line(s) if lugs or buttons are present. If (and only if) a launch lug and/or
* give orientation. * rail button exists, then the word 'Front' is affixed to the leading edge of the guide to give orientation.
* <p/> * <p/>
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
@ -77,13 +79,14 @@ public class FinMarkingGuide extends JPanel {
private static final int MARGIN = (int) PrintUnit.INCHES.toPoints(0.25f); private static final int MARGIN = (int) PrintUnit.INCHES.toPoints(0.25f);
/** /**
* The height (circumference) of the biggest body tube with a finset. * The height (circumference) of the biggest body tube with a fin and/or tube fin set.
*/ */
private int maxHeight = 0; private int maxHeight = 0;
/** /**
* A map of body tubes, to a list of components that contains finsets and launch lugs. * A map of body tubes, to a list of components that contain fin and/or tube fin sets and launch lugs and/or
*/ * rail buttons.
* */
private Map<BodyTube, java.util.List<ExternalComponent>> markingGuideItems; private Map<BodyTube, java.util.List<ExternalComponent>> markingGuideItems;
/** /**
@ -100,11 +103,12 @@ public class FinMarkingGuide extends JPanel {
} }
/** /**
* Initialize the marking guide class by iterating over a rocket and finding all finsets. * Initialize the marking guide class by iterating over a rocket and finding all fin and/or tube fin sets.
* *
* @param component the root rocket component - this is iterated to find all finset and launch lugs * @param component the root rocket component - this is iterated to find all fin and/or tube fin sets and
* launch lugs and/or rail buttons.
* *
* @return a map of body tubes to lists of finsets and launch lugs. * @return a map of body tubes to lists of fin and/or tube fin sets and launch lugs and/or rail buttons.
*/ */
private Map<BodyTube, java.util.List<ExternalComponent>> init(Rocket component) { private Map<BodyTube, java.util.List<ExternalComponent>> init(Rocket component) {
Iterator<RocketComponent> iter = component.iterator(false); Iterator<RocketComponent> iter = component.iterator(false);
@ -119,7 +123,9 @@ public class FinMarkingGuide extends JPanel {
if (next instanceof BodyTube) { if (next instanceof BodyTube) {
current = (BodyTube) next; current = (BodyTube) next;
} }
else if (next instanceof FinSet || next instanceof LaunchLug) {
// IF Existence of FinSet or TubeFinSet or LaunchLug or RailButton
else if (next instanceof FinSet || next instanceof TubeFinSet || next instanceof LaunchLug || next instanceof RailButton) {
java.util.List<ExternalComponent> list = results.get(current); java.util.List<ExternalComponent> list = results.get(current);
if (list == null && current != null) { if (list == null && current != null) {
list = new ArrayList<ExternalComponent>(); list = new ArrayList<ExternalComponent>();
@ -201,7 +207,7 @@ public class FinMarkingGuide extends JPanel {
* | | + + * | | + +
* | | + + * | | + +
* | | + + * | | + +
* | | +<------Launch Lug --------->+ * | | +<------Launch Guide-------->+
* | | + + * | | + +
* | | + + * | | + +
* | | + + * | | + +
@ -217,8 +223,8 @@ public class FinMarkingGuide extends JPanel {
* yLLOffset is computed from the difference between the base rotation of the fin and the radial direction of the * yLLOffset is computed from the difference between the base rotation of the fin and the radial direction of the
* lug. * lug.
* *
* Note: There is a current limitation that a tube with multiple launch lugs may not render the lug lines * Note: There is a current limitation that a tube with multiple launch lugs and/or rail buttons may not render
* correctly. * the lug and/or button lines correctly.
* </pre> * </pre>
* *
* @param g the Graphics context * @param g the Graphics context
@ -258,6 +264,8 @@ public class FinMarkingGuide extends JPanel {
//fin1: 42 fin2: 25 //fin1: 42 fin2: 25
for (ExternalComponent externalComponent : componentList) { for (ExternalComponent externalComponent : componentList) {
// BEGIN If FinSet instance
if (externalComponent instanceof FinSet) { if (externalComponent instanceof FinSet) {
FinSet fins = (FinSet) externalComponent; FinSet fins = (FinSet) externalComponent;
int finCount = fins.getFinCount(); int finCount = fins.getFinCount();
@ -285,6 +293,39 @@ public class FinMarkingGuide extends JPanel {
// } // }
} }
} }
// END If FinSet instance
// BEGIN If TubeFinSet instance
if (externalComponent instanceof TubeFinSet) {
TubeFinSet fins = (TubeFinSet) externalComponent;
int finCount = fins.getFinCount();
double baseAngularSpacing = (TWO_PI / finCount);
double baseAngularOffset = fins.getBaseRotation();
//Draw the fin marking lines.
for (int fin = 0; fin < finCount; fin++) {
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;
}
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);
// }
}
}
// END If TubeFinSet instance
// BEGIN If LaunchLug instance
else if (externalComponent instanceof LaunchLug) { else if (externalComponent instanceof LaunchLug) {
LaunchLug lug = (LaunchLug) externalComponent; LaunchLug lug = (LaunchLug) externalComponent;
double angle = lug.getAngleOffset() - radialOrigin; double angle = lug.getAngleOffset() - radialOrigin;
@ -296,13 +337,29 @@ public class FinMarkingGuide extends JPanel {
g2.drawString(lug.getName(), x + (width / 3), (int) yLLOffset - 2); g2.drawString(lug.getName(), x + (width / 3), (int) yLLOffset - 2);
} }
// END If LaunchLug instance
// BEGIN If RailButton instance
else if (externalComponent instanceof RailButton) {
RailButton button = (RailButton) externalComponent;
double angle = button.getAngleOffset() - 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(button.getName(), x + (width / 3), (int) yLLOffset - 2);
}
// END If RailButton instance
} }
//Only if the tube has a lug or multiple finsets does the orientation of the marking guide matter. So print 'Front'. // Only if the tube has a lug or button or multiple fin and/or tube fin sets does the orientation of
// the marking guide matter. So print 'Front'.
if (hasMultipleComponents) { if (hasMultipleComponents) {
drawFrontIndication(g2, x, y, 0, (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. // At most, two marking guides horizontally. After that, move down and back to the left margin.
column++; column++;
if (column % 2 == 0) { if (column % 2 == 0) {
x = MARGIN; x = MARGIN;
@ -316,7 +373,7 @@ public class FinMarkingGuide extends JPanel {
} }
/** /**
* This function finds a origin in radians for the template so no component is on the template seam. * This function finds an origin in radians for the template so no component is on the template seam.
* *
* If no fin or launch lug is at 0.0 radians, then the origin is 0. If there is one, then half the distance * 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. * between the two are taken.
@ -329,14 +386,18 @@ public class FinMarkingGuide extends JPanel {
ArrayList<Double> positions = new ArrayList<Double>(3 * components.size()); ArrayList<Double> positions = new ArrayList<Double>(3 * components.size());
for (ExternalComponent component : components) { for (ExternalComponent component : components) {
if (component instanceof LaunchLug) { if (component instanceof LaunchLug) { // Instance of LaunchLug
double componentPosition = ((LaunchLug) component).getAngleOffset(); double componentPosition = ((LaunchLug) component).getAngleOffset();
positions.add(makeZeroTwoPi(componentPosition)); positions.add(makeZeroTwoPi(componentPosition));
} }
if (component instanceof FinSet) { if (component instanceof RailButton) { // Instance of RailButton
double componentPosition = ((RailButton) component).getAngleOffset();
positions.add(makeZeroTwoPi(componentPosition));
}
if (component instanceof FinSet) { // Instance of FinSet
FinSet fins = (FinSet) component; FinSet fins = (FinSet) component;
double basePosition = fins.getBaseRotation(); double basePosition = fins.getBaseRotation();
double angle = TWO_PI / fins.getFinCount(); double angle = TWO_PI / fins.getFinCount();
@ -345,6 +406,16 @@ public class FinMarkingGuide extends JPanel {
basePosition += angle; basePosition += angle;
} }
} }
if (component instanceof TubeFinSet) { // Instance of TubeFinSet
TubeFinSet fins = (TubeFinSet) 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;
}
}
} }
Collections.sort(positions); Collections.sort(positions);
@ -386,17 +457,20 @@ public class FinMarkingGuide extends JPanel {
} }
/** /**
* Determines if the list contains a FinSet. * Determine if the list contains a FinSet or TubeFinSet.
* *
* @param list a list of ExternalComponent * @param list a list of ExternalComponent
* *
* @return true if the list contains at least one FinSet * @return true if the list contains at least one FinSet or TubeFinSet
*/ */
private boolean hasFins(List<ExternalComponent> list) { private boolean hasFins(List<ExternalComponent> list) {
for (ExternalComponent externalComponent : list) { for (ExternalComponent externalComponent : list) {
if (externalComponent instanceof FinSet) { if (externalComponent instanceof FinSet) { // ACTION Existence of FinSet
return true; return true;
} }
if (externalComponent instanceof TubeFinSet) { // ACTION Existence of TubeFinSet
return true;
}
} }
return false; return false;
} }