[Large] Refactored RocketFigure drawing code to enable moving components by offset

This commit is contained in:
Daniel_M_Williams 2015-06-25 11:22:58 -04:00
parent 5e96288896
commit 56dec21824
18 changed files with 427 additions and 196 deletions

View File

@ -0,0 +1,24 @@
package net.sf.openrocket.rocketcomponent;
import net.sf.openrocket.util.Coordinate;
/**
* This interface is used to signal that the implementing interface contains multiple instances of its components.
* (Note: not all implementations replicate their children, but that is design intention.)
*
* @author teyrana ( Daniel Williams, equipoise@gmail.com )
*
*/
public interface MultipleComponent {
public int getInstanceCount();
// location of each instance relative to the component
// center-to-center vectors
public Coordinate[] getInstanceOffsets();
}

View File

@ -2,11 +2,12 @@ package net.sf.openrocket.rocketcomponent;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Coordinate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class Stage extends ComponentAssembly implements FlightConfigurableComponent, OutsideComponent { public class Stage extends ComponentAssembly implements FlightConfigurableComponent, MultipleComponent, OutsideComponent {
static final Translator trans = Application.getTranslator(); static final Translator trans = Application.getTranslator();
private static final Logger log = LoggerFactory.getLogger(Stage.class); private static final Logger log = LoggerFactory.getLogger(Stage.class);
@ -18,8 +19,8 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
private double radialPosition_m = 0; private double radialPosition_m = 0;
private double rotation_rad = 0; private double rotation_rad = 0;
private int count = 2; private int count = 1;
private double separationAngle = Math.PI; private double angularSeparation = Math.PI;
public Stage() { public Stage() {
@ -84,9 +85,12 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
this.relativePosition = Position.BOTTOM; this.relativePosition = Position.BOTTOM;
this.position = 0; this.position = 0;
} }
if (this.outside) { if (!this.outside) {
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); this.count = 1;
} }
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
} }
@Override @Override
@ -98,7 +102,7 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
public void setCount(final int _count) { public void setCount(final int _count) {
mutex.verify(); mutex.verify();
this.count = _count; this.count = _count;
this.separationAngle = Math.PI * 2 / this.count; this.angularSeparation = Math.PI * 2 / this.count;
if (this.outside) { if (this.outside) {
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
@ -183,7 +187,26 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
} }
} }
@Override
public int getInstanceCount() {
return this.count;
}
@Override
public Coordinate[] getInstanceOffsets() {
Coordinate[] toReturn = new Coordinate[this.count];
double radius = this.radialPosition_m;
double angle0 = this.angularPosition_rad;
double angleIncr = this.angularSeparation;
double thisAngle = angle0;
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
toReturn[instanceNumber] = new Coordinate(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
thisAngle += angleIncr;
}
return toReturn;
}
} }

View File

@ -1,8 +1,10 @@
package net.sf.openrocket.gui.print; package net.sf.openrocket.gui.print;
import net.sf.openrocket.gui.print.visitor.PageFitPrintStrategy; import net.sf.openrocket.gui.print.visitor.PageFitPrintStrategy;
import net.sf.openrocket.gui.rocketfigure.RocketComponentShape;
import net.sf.openrocket.gui.rocketfigure.TransitionShapes; import net.sf.openrocket.gui.rocketfigure.TransitionShapes;
import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Transformation; import net.sf.openrocket.util.Transformation;
import java.awt.Graphics2D; import java.awt.Graphics2D;
@ -56,14 +58,14 @@ public class PrintableNoseCone extends AbstractPrintable<NoseCone> {
*/ */
@Override @Override
protected void draw(Graphics2D g2) { protected void draw(Graphics2D g2) {
Shape[] shapes = TransitionShapes.getShapesSide(target, Transformation.rotate_x(0d), PrintUnit.METERS.toPoints(1)); RocketComponentShape[] compShapes = TransitionShapes.getShapesSide(target, Transformation.rotate_x(0d), new Coordinate(0,0,0), PrintUnit.METERS.toPoints(1));
if (shapes != null && shapes.length > 0) { if (compShapes != null && compShapes.length > 0) {
Rectangle r = shapes[0].getBounds(); Rectangle r = compShapes[0].shape.getBounds();
g2.translate(r.getHeight() / 2, 0); g2.translate(r.getHeight() / 2, 0);
g2.rotate(Math.PI / 2); g2.rotate(Math.PI / 2);
for (Shape shape : shapes) { for (RocketComponentShape shape : compShapes) {
g2.draw(shape); g2.draw(shape.shape);
} }
g2.rotate(-Math.PI / 2); g2.rotate(-Math.PI / 2);
} }

View File

@ -8,38 +8,43 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
public class BodyTubeShapes extends RocketComponentShapes { public class BodyTubeShapes extends RocketComponentShape {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.BodyTube tube = (net.sf.openrocket.rocketcomponent.BodyTube)component; net.sf.openrocket.rocketcomponent.BodyTube tube = (net.sf.openrocket.rocketcomponent.BodyTube)component;
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getOuterRadius(); double radius = tube.getOuterRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Rectangle2D.Double(start[i].x*S,(start[i].y-radius)*S, s[i] = new Rectangle2D.Double(start[i].x*S,(start[i].y-radius)*S,
length*S,2*radius*S); length*S,2*radius*S);
} }
return s;
return RocketComponentShape.toArray(s, component);
} }
public static RocketComponentShape[] getShapesBack(
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) { Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.BodyTube tube = (net.sf.openrocket.rocketcomponent.BodyTube)component; net.sf.openrocket.rocketcomponent.BodyTube tube = (net.sf.openrocket.rocketcomponent.BodyTube)component;
double or = tube.getOuterRadius(); double or = tube.getOuterRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s;
return RocketComponentShape.toArray(s, component);
} }

View File

@ -8,16 +8,18 @@ import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Transformation; import net.sf.openrocket.util.Transformation;
public class FinSetShapes extends RocketComponentShapes { public class FinSetShapes extends RocketComponentShape {
// TODO: LOW: Clustering is ignored (FinSet cannot currently be clustered) // TODO: LOW: Clustering is ignored (FinSet cannot currently be clustered)
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component; net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
int fins = finset.getFinCount(); int finCount = finset.getFinCount();
Transformation cantRotation = finset.getCantRotation(); Transformation cantRotation = finset.getCantRotation();
Transformation baseRotation = finset.getBaseRotationTransformation(); Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation(); Transformation finRotation = finset.getFinRotationTransformation();
@ -36,8 +38,8 @@ public class FinSetShapes extends RocketComponentShapes {
// Generate shapes // Generate shapes
Shape[] s = new Shape[fins]; RocketComponentShape[] rcs = new RocketComponentShape[ finCount];
for (int fin=0; fin<fins; fin++) { for (int fin=0; fin<finCount; fin++) {
Coordinate a; Coordinate a;
Path2D.Float p; Path2D.Float p;
@ -52,26 +54,32 @@ public class FinSetShapes extends RocketComponentShapes {
} }
p.closePath(); p.closePath();
s[fin] = p; rcs[fin] = new RocketComponentShape( p, finset);
// Rotate fin coordinates // Rotate fin coordinates
for (int i=0; i<finPoints.length; i++) for (int i=0; i<finPoints.length; i++)
finPoints[i] = finRotation.transform(finPoints[i]); finPoints[i] = finRotation.transform(finPoints[i]);
} }
return s; return rcs;
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component; net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
Shape[] toReturn;
if (MathUtil.equals(finset.getCantAngle(),0)) if (MathUtil.equals(finset.getCantAngle(),0)){
return uncantedShapesBack(finset, transformation); toReturn = uncantedShapesBack(finset, transformation);
else }else{
return cantedShapesBack(finset, transformation); toReturn = cantedShapesBack(finset, transformation);
}
return RocketComponentShape.toArray( toReturn, finset);
} }

View File

@ -8,37 +8,45 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
public class LaunchLugShapes extends RocketComponentShapes { public class LaunchLugShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.LaunchLug lug = (net.sf.openrocket.rocketcomponent.LaunchLug)component; net.sf.openrocket.rocketcomponent.LaunchLug lug = (net.sf.openrocket.rocketcomponent.LaunchLug)component;
double length = lug.getLength(); double length = lug.getLength();
double radius = lug.getOuterRadius(); double radius = lug.getOuterRadius();
Coordinate[] start = transformation.transform(lug.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(lug.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Rectangle2D.Double(start[i].x*S,(start[i].y-radius)*S, s[i] = new Rectangle2D.Double(start[i].x*S,(start[i].y-radius)*S,
length*S,2*radius*S); length*S,2*radius*S);
} }
return s;
return RocketComponentShape.toArray(s, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.LaunchLug lug = (net.sf.openrocket.rocketcomponent.LaunchLug)component; net.sf.openrocket.rocketcomponent.LaunchLug lug = (net.sf.openrocket.rocketcomponent.LaunchLug)component;
double or = lug.getOuterRadius(); double or = lug.getOuterRadius();
Coordinate[] start = transformation.transform(lug.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(lug.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s;
return RocketComponentShape.toArray(s, component);
} }
} }

View File

@ -13,10 +13,13 @@ import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Transformation; import net.sf.openrocket.util.Transformation;
public class MassComponentShapes extends RocketComponentShapes { public class MassComponentShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
net.sf.openrocket.rocketcomponent.MassComponent.MassComponentType type = ((net.sf.openrocket.rocketcomponent.MassComponent)component).getMassComponentType(); net.sf.openrocket.rocketcomponent.MassComponent.MassComponentType type = ((net.sf.openrocket.rocketcomponent.MassComponent)component).getMassComponentType();
@ -24,7 +27,7 @@ public class MassComponentShapes extends RocketComponentShapes {
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getRadius(); double radius = tube.getRadius();
double arc = Math.min(length, 2*radius) * 0.7; double arc = Math.min(length, 2*radius) * 0.7;
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
@ -57,23 +60,26 @@ public class MassComponentShapes extends RocketComponentShapes {
case MASSCOMPONENT: case MASSCOMPONENT:
} }
return s; return RocketComponentShape.toArray(s, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius(); double or = tube.getRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s; return RocketComponentShape.toArray(s, component);
} }
private static Shape[] addAltimeterSymbol(Shape[] baseShape){ private static Shape[] addAltimeterSymbol(Shape[] baseShape){

View File

@ -8,16 +8,18 @@ import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Transformation; import net.sf.openrocket.util.Transformation;
public class MassObjectShapes extends RocketComponentShapes { public class MassObjectShapes extends RocketComponentShape {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getRadius(); double radius = tube.getRadius();
double arc = Math.min(length, 2*radius) * 0.7; double arc = Math.min(length, 2*radius) * 0.7;
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
@ -25,23 +27,26 @@ public class MassObjectShapes extends RocketComponentShapes {
length*S,2*radius*S,arc*S,arc*S); length*S,2*radius*S,arc*S,arc*S);
} }
return s; return RocketComponentShape.toArray(s, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius(); double or = tube.getRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s; return RocketComponentShape.toArray(s, component);
} }
} }

View File

@ -10,39 +10,45 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
public class ParachuteShapes extends RocketComponentShapes { public class ParachuteShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getRadius(); double radius = tube.getRadius();
double arc = Math.min(length, 2*radius) * 0.7; double arc = Math.min(length, 2*radius) * 0.7;
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S, s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S,
length*S,2*radius*S,arc*S,arc*S); length*S,2*radius*S,arc*S,arc*S);
} }
return addSymbol(s); return RocketComponentShape.toArray( addSymbol(s), component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius(); double or = tube.getRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s; return RocketComponentShape.toArray( s, component);
} }
private static Shape[] addSymbol(Shape[] baseShape){ private static Shape[] addSymbol(Shape[] baseShape){

View File

@ -9,10 +9,13 @@ import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Transformation; import net.sf.openrocket.util.Transformation;
public class RingComponentShapes extends RocketComponentShapes { public class RingComponentShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component; net.sf.openrocket.rocketcomponent.RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component;
Shape[] s; Shape[] s;
@ -21,7 +24,7 @@ public class RingComponentShapes extends RocketComponentShapes {
double ir = tube.getInnerRadius(); double ir = tube.getInnerRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
if ((or-ir >= 0.0012) && (ir > 0)) { if ((or-ir >= 0.0012) && (ir > 0)) {
// Draw outer and inner // Draw outer and inner
@ -40,11 +43,11 @@ public class RingComponentShapes extends RocketComponentShapes {
length*S,2*or*S); length*S,2*or*S);
} }
} }
return s; return RocketComponentShape.toArray( s, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) { Transformation transformation) {
net.sf.openrocket.rocketcomponent.RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component; net.sf.openrocket.rocketcomponent.RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component;
Shape[] s; Shape[] s;
@ -71,7 +74,7 @@ public class RingComponentShapes extends RocketComponentShapes {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
} }
return s; return RocketComponentShape.toArray( s, component);
} }
} }

View File

@ -0,0 +1,83 @@
package net.sf.openrocket.gui.rocketfigure;
import java.awt.Shape;
import net.sf.openrocket.gui.scalefigure.RocketFigure;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LineStyle;
import net.sf.openrocket.util.Transformation;
/**
* A catch-all, no-operation drawing component.
*/
public class RocketComponentShape {
protected static final double S = RocketFigure.EXTRA_SCALE;
final public boolean hasShape;
final public Shape shape;
final public net.sf.openrocket.util.Color color;
final public LineStyle lineStyle;
final public RocketComponent component;
protected RocketComponentShape(){
this.hasShape = false;
this.shape = null;
this.color = null;
this.lineStyle = null;
this.component=null;
}
public RocketComponentShape( final Shape _shape, final RocketComponent _comp){
this.shape = _shape;
this.color = _comp.getColor();
this.lineStyle = _comp.getLineStyle();
this.component = _comp;
if( null == _shape ){
this.hasShape = false;
}else{
this.hasShape = true;
}
}
public RocketComponent getComponent(){
return this.component;
}
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
// no-op
Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesSide called with "
+ component);
return new RocketComponentShape[0];
}
public static RocketComponentShape[] getShapesBack(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) { // no-op
Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesBack called with "
+component);
return new RocketComponentShape[0];
}
public static RocketComponentShape[] toArray( final Shape[] shapeArray, final RocketComponent rc){
RocketComponentShape[] toReturn = new RocketComponentShape[ shapeArray.length];
for ( int curShapeIndex=0;curShapeIndex<shapeArray.length; curShapeIndex++){
Shape curShape = shapeArray[curShapeIndex ];
toReturn[curShapeIndex] = new RocketComponentShape( curShape, rc);
}
return toReturn;
}
}

View File

@ -1,35 +0,0 @@
package net.sf.openrocket.gui.rocketfigure;
import java.awt.Shape;
import net.sf.openrocket.gui.scalefigure.RocketFigure;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Transformation;
/**
* A catch-all, no-operation drawing component.
*/
public class RocketComponentShapes {
protected static final double S = RocketFigure.EXTRA_SCALE;
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation t) {
// no-op
Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesSide called with "
+ component);
return new Shape[0];
}
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation t) {
// no-op
Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesBack called with "
+component);
return new Shape[0];
}
}

View File

@ -9,39 +9,45 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
public class ShockCordShapes extends RocketComponentShapes { public class ShockCordShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getRadius(); double radius = tube.getRadius();
double arc = Math.min(length, 2*radius) * 0.7; double arc = Math.min(length, 2*radius) * 0.7;
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S, s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S,
length*S,2*radius*S,arc*S,arc*S); length*S,2*radius*S,arc*S,arc*S);
} }
return addSymbol(s); return RocketComponentShape.toArray( addSymbol(s), component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius(); double or = tube.getRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s; return RocketComponentShape.toArray( s, component);
} }
private static Shape[] addSymbol(Shape[] baseShape){ private static Shape[] addSymbol(Shape[] baseShape){

View File

@ -9,39 +9,45 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
public class StreamerShapes extends RocketComponentShapes { public class StreamerShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double length = tube.getLength(); double length = tube.getLength();
double radius = tube.getRadius(); double radius = tube.getRadius();
double arc = Math.min(length, 2*radius) * 0.7; double arc = Math.min(length, 2*radius) * 0.7;
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S, s[i] = new RoundRectangle2D.Double(start[i].x*S,(start[i].y-radius)*S,
length*S,2*radius*S,arc*S,arc*S); length*S,2*radius*S,arc*S,arc*S);
} }
return addSymbol(s); return RocketComponentShape.toArray(addSymbol(s), component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius(); double or = tube.getRadius();
Coordinate[] start = transformation.transform(tube.toAbsolute(new Coordinate(0,0,0))); Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset));
Shape[] s = new Shape[start.length]; Shape[] s = new Shape[start.length];
for (int i=0; i < start.length; i++) { for (int i=0; i < start.length; i++) {
s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S); s[i] = new Ellipse2D.Double((start[i].z-or)*S,(start[i].y-or)*S,2*or*S,2*or*S);
} }
return s; return RocketComponentShape.toArray(s, component);
} }
private static Shape[] addSymbol(Shape[] baseShape){ private static Shape[] addSymbol(Shape[] baseShape){

View File

@ -9,7 +9,7 @@ import java.awt.geom.Path2D;
import java.util.ArrayList; import java.util.ArrayList;
public class SymmetricComponentShapes extends RocketComponentShapes { public class SymmetricComponentShapes extends RocketComponentShape {
private static final int MINPOINTS = 91; private static final int MINPOINTS = 91;
private static final double ACCEPTABLE_ANGLE = Math.cos(7.0 * Math.PI / 180.0); private static final double ACCEPTABLE_ANGLE = Math.cos(7.0 * Math.PI / 180.0);
@ -17,13 +17,19 @@ public class SymmetricComponentShapes extends RocketComponentShapes {
// TODO: LOW: Uses only first component of cluster (not currently clusterable) // TODO: LOW: Uses only first component of cluster (not currently clusterable)
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
return getShapesSide(component, transformation, S); Transformation transformation,
Coordinate instanceOffset) {
return getShapesSide(component, transformation, instanceOffset, S);
} }
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation, final double scaleFactor) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset,
final double scaleFactor) {
net.sf.openrocket.rocketcomponent.SymmetricComponent c = (net.sf.openrocket.rocketcomponent.SymmetricComponent) component; net.sf.openrocket.rocketcomponent.SymmetricComponent c = (net.sf.openrocket.rocketcomponent.SymmetricComponent) component;
int i; int i;
@ -94,7 +100,7 @@ public class SymmetricComponentShapes extends RocketComponentShapes {
//s[len] = path; //s[len] = path;
//return s; //return s;
return new Shape[] { path }; return new RocketComponentShape[] { new RocketComponentShape(path, component) };
} }
private static boolean angleAcceptable(Coordinate v1, Coordinate v2, Coordinate v3) { private static boolean angleAcceptable(Coordinate v1, Coordinate v2, Coordinate v3) {

View File

@ -10,20 +10,25 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
public class TransitionShapes extends RocketComponentShapes { public class TransitionShapes extends RocketComponentShape {
// TODO: LOW: Uses only first component of cluster (not currently clusterable). // TODO: LOW: Uses only first component of cluster (not currently clusterable).
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
return getShapesSide(component, transformation, S); Transformation transformation,
Coordinate instanceOffset) {
return getShapesSide(component, transformation, instanceOffset, S);
} }
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesSide(
Transformation transformation, final double scaleFactor) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset,
final double scaleFactor) {
net.sf.openrocket.rocketcomponent.Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component; net.sf.openrocket.rocketcomponent.Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component;
Shape[] mainShapes; RocketComponentShape[] mainShapes;
// Simpler shape for conical transition, others use the method from SymmetricComponent // Simpler shape for conical transition, others use the method from SymmetricComponent
if (transition.getType() == Transition.Shape.CONICAL) { if (transition.getType() == Transition.Shape.CONICAL) {
@ -31,7 +36,7 @@ public class TransitionShapes extends RocketComponentShapes {
double r1 = transition.getForeRadius(); double r1 = transition.getForeRadius();
double r2 = transition.getAftRadius(); double r2 = transition.getAftRadius();
Coordinate start = transformation.transform(transition. Coordinate start = transformation.transform(transition.
toAbsolute(Coordinate.NUL)[0]); toAbsolute(instanceOffset)[0]);
Path2D.Float path = new Path2D.Float(); Path2D.Float path = new Path2D.Float();
path.moveTo(start.x* scaleFactor, r1* scaleFactor); path.moveTo(start.x* scaleFactor, r1* scaleFactor);
@ -40,9 +45,9 @@ public class TransitionShapes extends RocketComponentShapes {
path.lineTo(start.x* scaleFactor, -r1* scaleFactor); path.lineTo(start.x* scaleFactor, -r1* scaleFactor);
path.closePath(); path.closePath();
mainShapes = new Shape[] { path }; mainShapes = new RocketComponentShape[] { new RocketComponentShape( path, component) };
} else { } else {
mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation, scaleFactor); mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation, instanceOffset, scaleFactor);
} }
Rectangle2D.Double shoulder1=null, shoulder2=null; Rectangle2D.Double shoulder1=null, shoulder2=null;
@ -71,7 +76,7 @@ public class TransitionShapes extends RocketComponentShapes {
int i; int i;
for (i=0; i < mainShapes.length; i++) { for (i=0; i < mainShapes.length; i++) {
shapes[i] = mainShapes[i]; shapes[i] = mainShapes[i].shape;
} }
if (shoulder1 != null) { if (shoulder1 != null) {
shapes[i] = shoulder1; shapes[i] = shoulder1;
@ -80,21 +85,27 @@ public class TransitionShapes extends RocketComponentShapes {
if (shoulder2 != null) { if (shoulder2 != null) {
shapes[i] = shoulder2; shapes[i] = shoulder2;
} }
return shapes; return RocketComponentShape.toArray( shapes, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component; net.sf.openrocket.rocketcomponent.Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component;
double r1 = transition.getForeRadius(); double r1 = transition.getForeRadius();
double r2 = transition.getAftRadius(); double r2 = transition.getAftRadius();
Coordinate center = instanceOffset;
// adjust center heree... somehow
Shape[] s = new Shape[2]; Shape[] s = new Shape[2];
s[0] = new Ellipse2D.Double(-r1*S,-r1*S,2*r1*S,2*r1*S); s[0] = new Ellipse2D.Double(-r1*S,-r1*S,2*r1*S,2*r1*S);
s[1] = new Ellipse2D.Double(-r2*S,-r2*S,2*r2*S,2*r2*S); s[1] = new Ellipse2D.Double(-r2*S,-r2*S,2*r2*S,2*r2*S);
return s; return RocketComponentShape.toArray(s, component);
} }

View File

@ -8,10 +8,13 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
public class TubeFinSetShapes extends RocketComponentShapes { public class TubeFinSetShapes extends RocketComponentShape {
public static RocketComponentShape[] getShapesSide(
net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
int fins = finset.getFinCount(); int fins = finset.getFinCount();
@ -19,7 +22,7 @@ public class TubeFinSetShapes extends RocketComponentShapes {
double outerradius = finset.getOuterRadius(); double outerradius = finset.getOuterRadius();
double bodyradius = finset.getBodyRadius(); double bodyradius = finset.getBodyRadius();
Coordinate[] start = finset.toAbsolute(new Coordinate(0,0,0)); Coordinate[] start = finset.toAbsolute(instanceOffset);
Transformation baseRotation = finset.getBaseRotationTransformation(); Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation(); Transformation finRotation = finset.getFinRotationTransformation();
@ -36,19 +39,22 @@ public class TubeFinSetShapes extends RocketComponentShapes {
s[i] = new Rectangle2D.Double(start[0].x*S,(start[0].y-outerradius)*S,length*S,2*outerradius*S); s[i] = new Rectangle2D.Double(start[0].x*S,(start[0].y-outerradius)*S,length*S,2*outerradius*S);
start = finRotation.transform(start); start = finRotation.transform(start);
} }
return s; return RocketComponentShape.toArray(s, component);
} }
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, public static RocketComponentShape[] getShapesBack(
Transformation transformation) { net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation,
Coordinate instanceOffset) {
net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
int fins = finset.getFinCount(); int fins = finset.getFinCount();
double outerradius = finset.getOuterRadius(); double outerradius = finset.getOuterRadius();
double bodyradius = finset.getBodyRadius(); double bodyradius = finset.getBodyRadius();
Coordinate[] start = finset.toAbsolute(new Coordinate(0,0,0)); Coordinate[] start = finset.toAbsolute( instanceOffset);
Transformation baseRotation = finset.getBaseRotationTransformation(); Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation(); Transformation finRotation = finset.getFinRotationTransformation();
@ -63,7 +69,7 @@ public class TubeFinSetShapes extends RocketComponentShapes {
s[i] = new Ellipse2D.Double((start[0].z-outerradius)*S,(start[0].y-outerradius)*S,2*outerradius*S,2*outerradius*S); s[i] = new Ellipse2D.Double((start[0].z-outerradius)*S,(start[0].y-outerradius)*S,2*outerradius*S,2*outerradius*S);
start = finRotation.transform(start); start = finRotation.transform(start);
} }
return s; return RocketComponentShape.toArray(s, component);
} }

View File

@ -25,7 +25,10 @@ import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.MultipleComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.gui.rocketfigure.RocketComponentShape;
import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.gui.scalefigure.RocketPanel;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BugException;
@ -71,9 +74,8 @@ public class RocketFigure extends AbstractScaleFigure {
/* /*
* figureComponents contains the corresponding RocketComponents of the figureShapes * figureComponents contains the corresponding RocketComponents of the figureShapes
*/ */
private final ArrayList<Shape> figureShapes = new ArrayList<Shape>(); private final ArrayList<RocketComponentShape> figureShapes = new ArrayList<RocketComponentShape>();
private final ArrayList<RocketComponent> figureComponents =
new ArrayList<RocketComponent>();
private double minX = 0, maxX = 0, maxR = 0; private double minX = 0, maxX = 0, maxR = 0;
// Figure width and height in SI-units and pixels // Figure width and height in SI-units and pixels
@ -180,20 +182,11 @@ public class RocketFigure extends AbstractScaleFigure {
@Override @Override
public void updateFigure() { public void updateFigure() {
figureShapes.clear(); figureShapes.clear();
figureComponents.clear();
calculateSize(); calculateSize();
Rocket theRocket = configuration.getRocket();
// Get shapes for all active components Coordinate zero = new Coordinate(0,0,0);
for (RocketComponent c : configuration) { getShapeTree( figureShapes, theRocket, zero);
Shape[] s = getShapes( this.currentViewType, c, this.transformation);
for (int i = 0; i < s.length; i++) {
figureShapes.add(s[i]);
figureComponents.add(c);
}
}
System.err.println(" updating the RocketFigure."); System.err.println(" updating the RocketFigure.");
repaint(); repaint();
@ -298,8 +291,8 @@ public class RocketFigure extends AbstractScaleFigure {
// Draw all shapes // Draw all shapes
for (int i = 0; i < figureShapes.size(); i++) { for (int i = 0; i < figureShapes.size(); i++) {
RocketComponent c = figureComponents.get(i); RocketComponentShape rcs = figureShapes.get(i);
Shape s = figureShapes.get(i); RocketComponent c = rcs.getComponent();
boolean selected = false; boolean selected = false;
// Check if component is in the selection // Check if component is in the selection
@ -311,13 +304,13 @@ public class RocketFigure extends AbstractScaleFigure {
} }
// Set component color and line style // Set component color and line style
net.sf.openrocket.util.Color color = c.getColor(); net.sf.openrocket.util.Color color = rcs.color;
if (color == null) { if (color == null) {
color = Application.getPreferences().getDefaultColor(c.getClass()); color = Application.getPreferences().getDefaultColor(c.getClass());
} }
g2.setColor(ColorConversion.toAwtColor(color)); g2.setColor(ColorConversion.toAwtColor(color));
LineStyle style = c.getLineStyle(); LineStyle style = rcs.lineStyle;
if (style == null) if (style == null)
style = Application.getPreferences().getDefaultLineStyle(c.getClass()); style = Application.getPreferences().getDefaultLineStyle(c.getClass());
@ -337,7 +330,7 @@ public class RocketFigure extends AbstractScaleFigure {
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE); RenderingHints.VALUE_STROKE_NORMALIZE);
} }
g2.draw(s); g2.draw(rcs.shape);
} }
@ -424,13 +417,78 @@ public class RocketFigure extends AbstractScaleFigure {
LinkedHashSet<RocketComponent> l = new LinkedHashSet<RocketComponent>(); LinkedHashSet<RocketComponent> l = new LinkedHashSet<RocketComponent>();
for (int i = 0; i < figureShapes.size(); i++) { for (int i = 0; i < figureShapes.size(); i++) {
if (figureShapes.get(i).contains(p)) RocketComponentShape rcs = this.figureShapes.get(i);
l.add(figureComponents.get(i)); if (rcs.shape.contains(p))
l.add(rcs.component);
} }
return l.toArray(new RocketComponent[0]); return l.toArray(new RocketComponent[0]);
} }
// NOTE: Recursive function
private void getShapeTree(
ArrayList<RocketComponentShape> allShapes, // this is the output parameter
final RocketComponent comp,
final Coordinate parentOffset){
RocketPanel.VIEW_TYPE viewType = this.currentViewType;
Transformation viewTransform = this.transformation;
// TODO: Implement actual locations in the components
Coordinate componentLocation = new Coordinate(comp.getPositionValue(),0,0);
if( comp instanceof MultipleComponent ){
MultipleComponent multi = (MultipleComponent)comp;
int instanceCount;
instanceCount = multi.getInstanceCount();
// get m instance locations
Coordinate[] instanceOffsets = multi.getInstanceOffsets();
assert(false);
assert( instanceOffsets.length == instanceCount );
// replicate n children m times each
int childCount = comp.getChildCount();
ArrayList<RocketComponentShape> childrenToReplicate = new ArrayList<RocketComponentShape>();
for ( int instanceNumber = 0; instanceNumber < instanceCount; instanceNumber++ ){
childrenToReplicate.clear();
Coordinate curInstanceOffset = componentLocation.add( instanceOffsets[instanceNumber] );
// get n children shapes toReplicate
for ( int childNumber = 0; childNumber < childCount; childNumber++ ){
RocketComponent curChildComp = comp.getChild( childNumber);
getShapeTree( childrenToReplicate, curChildComp, curInstanceOffset);
}
for ( RocketComponentShape curShape : childrenToReplicate ){
allShapes.add( curShape);
}
}
}else{
if( comp instanceof Rocket){
// the Rocket doesn't have any graphics to get.
// Noop
}else{
// for most RocketComponents
// TODO: HIGH: TEST that getThisShape will actually relocate by the given offset
RocketComponentShape[] childShapes = getThisShape( viewType, comp, parentOffset, viewTransform);
for ( RocketComponentShape curShape : childShapes ){
allShapes.add( curShape );
}
}
// recurse to each child
for( RocketComponent child: comp.getChildren() ){
getShapeTree( allShapes, child, parentOffset);
}
}
return;
}
/** /**
* Gets the shapes required to draw the component. * Gets the shapes required to draw the component.
@ -439,32 +497,32 @@ public class RocketFigure extends AbstractScaleFigure {
* @param params * @param params
* @return * @return
*/ */
private static Shape[] getShapes(final RocketPanel.VIEW_TYPE type, final RocketComponent component, final Transformation transformation) { private static RocketComponentShape[] getThisShape(final RocketPanel.VIEW_TYPE viewType, final RocketComponent component, final Coordinate instanceOffset, final Transformation transformation) {
Reflection.Method m; Reflection.Method m;
// Find the appropriate method // Find the appropriate method
switch (type) { switch (viewType) {
case SideView: case SideView:
m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesSide", m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesSide",
RocketComponent.class, Transformation.class); RocketComponent.class, Transformation.class, Coordinate.class);
break; break;
case BackView: case BackView:
m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesBack", m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesBack",
RocketComponent.class, Transformation.class); RocketComponent.class, Transformation.class, Coordinate.class);
break; break;
default: default:
throw new BugException("Unknown figure type = " + type); throw new BugException("Unknown figure type = " + viewType);
} }
if (m == null) { if (m == null) {
Application.getExceptionHandler().handleErrorCondition("ERROR: Rocket figure paint method not found for " Application.getExceptionHandler().handleErrorCondition("ERROR: Rocket figure paint method not found for "
+ component); + component);
return new Shape[0]; return new RocketComponentShape[0];
} }
return (Shape[]) m.invokeStatic(component, transformation); return (RocketComponentShape[]) m.invokeStatic(component, transformation, instanceOffset);
} }