From 7b28923659b4f8efd8bb142949da885d944d6248 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sat, 19 Jan 2019 12:45:50 -0500 Subject: [PATCH 1/4] [fix] converts getActiveComponent calls to getAllComponents - this clears the 'using a deprecated function' warning - more importantly, this clarifies what exactly the caller needs at each call site --- .../rocketcomponent/FlightConfiguration.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index 32b1b18ac..e7a42cc74 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -172,9 +172,29 @@ public class FlightConfiguration implements FlightConfigurableParameter getAllComponents() { + Queue toProcess = new ArrayDeque(); + toProcess.offer(this.rocket); + + ArrayList toReturn = new ArrayList<>(); + + while (!toProcess.isEmpty()) { + RocketComponent comp = toProcess.poll(); + + toReturn.add(comp); + for (RocketComponent child : comp.getChildren()) { + if (!(child instanceof AxialStage)) { + toProcess.offer(child); + } + } + } + + return toReturn; + } // this method is deprecated because it ignores instancing of parent components (e.g. Strapons or pods ) - // if you're calling this method, you're probably not getting the numbers you expect. + // depending on your context, this may or may not be what you want. + // recomend migrating to either: `getAllComponents` or `getActiveInstances` @Deprecated public Collection getActiveComponents() { Queue toProcess = new ArrayDeque(this.getActiveStages()); From efabe817904b97b99475d73ee2f23a7f974b3641 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sat, 5 Jan 2019 18:09:39 -0500 Subject: [PATCH 2/4] [feat] FlightConfiguration may now generate an InstanceMap --- .../rocketcomponent/FlightConfiguration.java | 57 ++++++- .../rocketcomponent/InstanceContext.java | 59 +++++++ .../rocketcomponent/InstanceMap.java | 73 +++++++++ .../net/sf/openrocket/util/TestRockets.java | 3 +- .../FlightConfigurationTest.java | 151 +++++++++++++++++- .../rocketcomponent/RocketTest.java | 7 +- 6 files changed, 336 insertions(+), 14 deletions(-) create mode 100644 core/src/net/sf/openrocket/rocketcomponent/InstanceContext.java create mode 100644 core/src/net/sf/openrocket/rocketcomponent/InstanceMap.java diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index e7a42cc74..579abc876 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -4,6 +4,7 @@ import java.util.ArrayDeque; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Queue; import org.slf4j.Logger; @@ -18,6 +19,7 @@ import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Monitorable; +import net.sf.openrocket.util.Transformation; /** @@ -36,9 +38,9 @@ public class FlightConfiguration implements FlightConfigurableParameter getActiveStages() { List activeStages = new ArrayList<>(); @@ -554,14 +599,14 @@ public class FlightConfiguration implements FlightConfigurableParameter + * + */ +public class InstanceContext { + + // =========== Public Functions ======================== + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + + InstanceContext other = (InstanceContext) obj; + return (component.equals(other.component) && transform.equals(other.transform)); + } + + @Override + public int hashCode() { + return (int) (component.hashCode()); + } + + public InstanceContext(final RocketComponent _component, final boolean _active, final int _instanceNumber, final Transformation _transform) { + component = _component; + active = _active; + instanceNumber = _instanceNumber; + transform = _transform; + + } + + @Override + public String toString() { + return String.format("Context for %s #%d", component); + } + + public Coordinate getLocation() { + return transform.transform(Coordinate.ZERO); + } + + // =========== Instance Member Variables ======================== + + + // ==== public ==== + final public RocketComponent component; + final public boolean active; + final public int instanceNumber; + final public Transformation transform; + + // =========== Private Instance Functions ======================== + + +} + diff --git a/core/src/net/sf/openrocket/rocketcomponent/InstanceMap.java b/core/src/net/sf/openrocket/rocketcomponent/InstanceMap.java new file mode 100644 index 000000000..8e249f30d --- /dev/null +++ b/core/src/net/sf/openrocket/rocketcomponent/InstanceMap.java @@ -0,0 +1,73 @@ +package net.sf.openrocket.rocketcomponent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.openrocket.util.Transformation; + + +/** + * + * @author teyrana (aka Daniel Williams) + * + */ +public class InstanceMap extends HashMap> { + + // =========== Public Functions ======================== + + // public InstanceMap() {} + + public int count(final RocketComponent key) { + if(containsKey(key)){ + return get(key).size(); + }else { + return 0; + } + } + + public void emplace(final RocketComponent component, boolean active, int number, final Transformation xform) { + final RocketComponent key = component; + + if(!containsKey(component)) { + put(key, new ArrayList<>()); + } + + final InstanceContext context = new InstanceContext(component, active, number, xform); + get(key).add(context); + } + + public List getInstanceContexts(final RocketComponent key) { + return get(key); + } + + // this is primarily for debugging. + @Override + public String toString() { + StringBuffer buffer = new StringBuffer(); + int outerIndex = 0; + buffer.append(">> Printing InstanceMap:\n"); + for(Map.Entry> entry: entrySet() ) { + final RocketComponent key = entry.getKey(); + final ArrayList contexts = entry.getValue(); + buffer.append(String.format("....[% 2d]:[%s]\n", outerIndex, key.getName())); + outerIndex++; + + int innerIndex = 0; + for(InstanceContext ctxt: contexts ) { + buffer.append(String.format("........[@% 2d][% 2d] %s\n", innerIndex, ctxt.instanceNumber, ctxt.getLocation().toPreciseString())); + innerIndex++; + } + } + + return buffer.toString(); + } + + // =========== Instance Member Variables ======================== + + // =========== Private Instance Functions ======================== + + +} + diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java index fdd7b0061..0f025371e 100644 --- a/core/src/net/sf/openrocket/util/TestRockets.java +++ b/core/src/net/sf/openrocket/util/TestRockets.java @@ -32,7 +32,6 @@ import net.sf.openrocket.rocketcomponent.FinSet.CrossSection; import net.sf.openrocket.rocketcomponent.FlightConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfigurationId; import net.sf.openrocket.rocketcomponent.FreeformFinSet; -import net.sf.openrocket.rocketcomponent.IllegalFinPointException; import net.sf.openrocket.rocketcomponent.InnerTube; import net.sf.openrocket.rocketcomponent.InternalComponent; import net.sf.openrocket.rocketcomponent.LaunchLug; @@ -862,7 +861,7 @@ public class TestRockets { // ====== Payload Stage ====== // ====== ====== ====== ====== AxialStage payloadStage = new AxialStage(); - payloadStage.setName("Payload Fairing"); + payloadStage.setName("Payload Fairing Stage"); rocket.addChild(payloadStage); { diff --git a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java index 19e502124..b8a0a5875 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/FlightConfigurationTest.java @@ -5,14 +5,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import java.util.List; + import org.junit.Test; +import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.TestRockets; import net.sf.openrocket.util.BaseTestCase.BaseTestCase; public class FlightConfigurationTest extends BaseTestCase { - private final static double EPSILON = MathUtil.EPSILON*1E3; /** @@ -155,7 +157,6 @@ public class FlightConfigurationTest extends BaseTestCase { // test explicitly setting all stages active config.setAllStages(); - } /** @@ -326,5 +327,151 @@ public class FlightConfigurationTest extends BaseTestCase { assertThat("active motor count doesn't match: ", actualMotorCount, equalTo(expectedMotorCount)); } + @Test + public void testIterateComponents() { + Rocket rocket = TestRockets.makeFalcon9Heavy(); + FlightConfiguration selected = rocket.getSelectedConfiguration(); + selected.clearAllStages(); + selected.toggleStage(2); + + // vvvv Test Target vvvv + InstanceMap instances = selected.getActiveInstances(); + // ^^^^ Test Target ^^^^ + + // Payload Stage + final AxialStage coreStage = (AxialStage)rocket.getChild(1); + { // Core Stage + final List coreStageContextList = instances.getInstanceContexts(coreStage); + final InstanceContext coreStageContext = coreStageContextList.get(0); + assertThat(coreStageContext.component.getClass(), equalTo(AxialStage.class)); + assertThat(coreStageContext.component.getID(), equalTo(rocket.getChild(1).getID())); + assertThat(coreStageContext.component.getInstanceCount(), equalTo(1)); + + final Coordinate coreLocation = coreStageContext.getLocation(); + assertEquals(coreLocation.x, 0.564, EPSILON); + assertEquals(coreLocation.y, 0.0, EPSILON); + assertEquals(coreLocation.z, 0.0, EPSILON); + + //... skip uninteresting component + } + + // Booster Stage + { // instance #1 + final ParallelStage boosterStage = (ParallelStage)coreStage.getChild(0).getChild(0); + final List boosterStageContextList = instances.getInstanceContexts(boosterStage); + final InstanceContext boosterStage0Context = boosterStageContextList.get(0); + assertThat(boosterStage0Context.component.getClass(), equalTo(ParallelStage.class)); + assertThat(boosterStage0Context.component.getID(), equalTo(boosterStage.getID())); + assertThat(boosterStage0Context.instanceNumber, equalTo(0)); + { + final Coordinate loc = boosterStage0Context.getLocation(); + assertEquals(loc.x, 0.484, EPSILON); + assertEquals(loc.y, 0.077, EPSILON); + assertEquals(loc.z, 0.0, EPSILON); + } + + final InstanceContext boosterStage1Context = boosterStageContextList.get(1); + assertThat(boosterStage1Context.component.getClass(), equalTo(ParallelStage.class)); + assertThat(boosterStage1Context.component.getID(), equalTo(boosterStage.getID())); + assertThat(boosterStage1Context.instanceNumber, equalTo(1)); + { + final Coordinate loc = boosterStage1Context.getLocation(); + assertEquals(loc.x, 0.484, EPSILON); + assertEquals(loc.y, -0.077, EPSILON); + assertEquals(loc.z, 0.0, EPSILON); + } + + { // Booster Body: + final BodyTube boosterBody = (BodyTube)boosterStage.getChild(1); + final List boosterBodyContextList = instances.getInstanceContexts(boosterBody); + + // this is the instance number rocket-wide + final InstanceContext boosterBodyContext = boosterBodyContextList.get(1); + + // this is the instance number per-parent + assertThat(boosterBodyContext.instanceNumber, equalTo(0)); + + assertThat(boosterBodyContext.component.getClass(), equalTo(BodyTube.class)); + + final Coordinate bodyTubeLocation = boosterBodyContext.getLocation(); + assertEquals(bodyTubeLocation.x, 0.564, EPSILON); + assertEquals(bodyTubeLocation.y, -0.077, EPSILON); + assertEquals(bodyTubeLocation.z, 0.0, EPSILON); + + { // Booster::Motor Tubes ( x2 x4) + final InnerTube boosterMMT = (InnerTube)boosterBody.getChild(0); + final List mmtContextList = instances.getInstanceContexts(boosterMMT); + assertEquals(8, mmtContextList.size()); + + final InstanceContext motorTubeContext0 = mmtContextList.get(4); + assertThat(motorTubeContext0.component.getClass(), equalTo(InnerTube.class)); + assertThat(motorTubeContext0.instanceNumber, equalTo(0)); + final Coordinate motorTube0Location = motorTubeContext0.getLocation(); + assertEquals(motorTube0Location.x, 1.214, EPSILON); + assertEquals(motorTube0Location.y, -0.062, EPSILON); + assertEquals(motorTube0Location.z, -0.015, EPSILON); + + final InstanceContext motorTubeContext1 = mmtContextList.get(5); + assertThat(motorTubeContext1.component.getClass(), equalTo(InnerTube.class)); + assertThat(motorTubeContext1.instanceNumber, equalTo(1)); + final Coordinate motorTube1Location = motorTubeContext1.getLocation(); + assertEquals(motorTube1Location.x, 1.214, EPSILON); + assertEquals(motorTube1Location.y, -0.092, EPSILON); + assertEquals(motorTube1Location.z, -0.015, EPSILON); + + final InstanceContext motorTubeContext2 = mmtContextList.get(6); + assertThat(motorTubeContext2.component.getClass(), equalTo(InnerTube.class)); + assertThat(motorTubeContext2.instanceNumber, equalTo(2)); + final Coordinate motorTube2Location = motorTubeContext2.getLocation(); + assertEquals(motorTube2Location.x, 1.214, EPSILON); + assertEquals(motorTube2Location.y, -0.092, EPSILON); + assertEquals(motorTube2Location.z, 0.015, EPSILON); + + final InstanceContext motorTubeContext3 = mmtContextList.get(7); + assertThat(motorTubeContext3.component.getClass(), equalTo(InnerTube.class)); + assertThat(motorTubeContext3.instanceNumber, equalTo(3)); + final Coordinate motorTube3Location = motorTubeContext3.getLocation(); + assertEquals(motorTube3Location.x, 1.214, EPSILON); + assertEquals(motorTube3Location.y, -0.062, EPSILON); + assertEquals(motorTube3Location.z, 0.015, EPSILON); + + }{ // Booster::Fins::Instances ( x2 x3) + final FinSet fins = (FinSet)boosterBody.getChild(1); + final List finContextList = instances.getInstanceContexts(fins); + assertEquals(6, finContextList.size()); + + final InstanceContext boosterFinContext0 = finContextList.get(3); + assertThat(boosterFinContext0.component.getClass(), equalTo(TrapezoidFinSet.class)); + assertThat(boosterFinContext0.instanceNumber, equalTo(0)); + final Coordinate boosterFin0Location = boosterFinContext0.getLocation(); + assertEquals(boosterFin0Location.x, 1.044, EPSILON); + assertEquals(boosterFin0Location.y, -0.104223611, EPSILON); + assertEquals(boosterFin0Location.z, -0.027223611, EPSILON); + + final InstanceContext boosterFinContext1 = finContextList.get(4); + assertThat(boosterFinContext1.component.getClass(), equalTo(TrapezoidFinSet.class)); + assertThat(boosterFinContext1.instanceNumber, equalTo(1)); + final Coordinate boosterFin1Location = boosterFinContext1.getLocation(); + assertEquals(boosterFin1Location.x, 1.044, EPSILON); + assertEquals(boosterFin1Location.y, -0.03981186, EPSILON); + assertEquals(boosterFin1Location.z, -0.00996453, EPSILON); + + final InstanceContext boosterFinContext2 = finContextList.get(5); + assertThat(boosterFinContext2.component.getClass(), equalTo(TrapezoidFinSet.class)); + assertThat(boosterFinContext2.instanceNumber, equalTo(2)); + final Coordinate boosterFin2Location = boosterFinContext2.getLocation(); + assertEquals(boosterFin2Location.x, 1.044, EPSILON); + assertEquals(boosterFin2Location.y, -0.08696453, EPSILON); + assertEquals(boosterFin2Location.z, 0.03718814, EPSILON); + + } + + } + + } + } + } + + diff --git a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java index c26158c73..33dbd276f 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java @@ -7,7 +7,6 @@ import static org.junit.Assert.assertThat; import org.junit.Test; -import net.sf.openrocket.aerodynamics.FlightConditions; import net.sf.openrocket.rocketcomponent.position.AngleMethod; import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import net.sf.openrocket.util.Coordinate; @@ -35,12 +34,12 @@ public class RocketTest extends BaseTestCase { FlightConfigurationId fcid4 = config4.getId(); assertThat("fcids should match: ", config1.getId().key, equalTo(fcid4.key)); - assertThat("Configurations should be different: "+config1.toDebug()+"=?="+config4.toDebug(), config1.instanceNumber, not( config4.instanceNumber)); + assertThat("Configurations should be different: "+config1.toDebug()+"=?="+config4.toDebug(), config1.configurationInstanceId, not( config4.configurationInstanceId)); FlightConfiguration config5 = rkt2.getFlightConfiguration(config2.getId()); FlightConfigurationId fcid5 = config5.getId(); assertThat("fcids should match: ", config2.getId(), equalTo(fcid5)); - assertThat("Configurations should bef different match: "+config2.toDebug()+"=?="+config5.toDebug(), config2.instanceNumber, not( config5.instanceNumber)); + assertThat("Configurations should bef different match: "+config2.toDebug()+"=?="+config5.toDebug(), config2.configurationInstanceId, not( config5.configurationInstanceId)); } @@ -260,7 +259,7 @@ public class RocketTest extends BaseTestCase { loc = coreBody.getComponentLocations()[0]; assertEquals(coreBody.getName()+" offset is incorrect: ", 0.0, offset.x, EPSILON); assertEquals(coreBody.getName()+" location is incorrect: ", 0.564, loc.x, EPSILON); - + // ====== Booster Set Stage ====== // ====== ====== ====== ParallelStage boosters = (ParallelStage) coreBody.getChild(0); From 0711cb785bdc159a1a140d33492657b01a243b05 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sat, 19 Jan 2019 21:52:02 -0500 Subject: [PATCH 3/4] [fix] re-implements RocketRenderer-tree-code --- .../gui/figure3d/RocketRenderer.java | 51 ++++++++----------- .../gui/scalefigure/RocketPanel.java | 2 +- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java index 716900f56..d4f6f54ea 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java @@ -4,6 +4,7 @@ import java.awt.Point; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; import java.util.Set; import java.util.Vector; @@ -23,6 +24,8 @@ import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; +import net.sf.openrocket.rocketcomponent.InstanceMap; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.util.Coordinate; @@ -159,39 +162,29 @@ public abstract class RocketRenderer { private Collection getTreeGeometry( FlightConfiguration config){ System.err.println(String.format("==== Building tree geometry ====")); - return getTreeGeometry("", new ArrayList(), config, config.getRocket(), Transformation.IDENTITY); - } - - private Collection getTreeGeometry(String indent, Collection treeGeometry, FlightConfiguration config, RocketComponent comp, final Transformation parentTransform){ - final int instanceCount = comp.getInstanceCount(); - double[] instanceAngles = comp.getInstanceAngles(); - Coordinate[] instanceLocations = comp.getInstanceLocations(); - if( instanceLocations.length != instanceAngles.length ){ - throw new ArrayIndexOutOfBoundsException(String.format("lengths of location array (%d) and angle arrays (%d) differs! (in: %s) ", instanceLocations.length, instanceAngles.length, comp.getName())); - } + // input + final InstanceMap imap = config.getActiveInstances(); + + // output buffer + final Collection treeGeometry = new ArrayList(); + + for(Map.Entry> entry: imap.entrySet() ) { + final RocketComponent comp = entry.getKey(); + + final ArrayList contextList = entry.getValue(); + System.err.println(String.format("....[%s]", comp.getName())); - // iterate over the aggregated instances for the whole tree. - for( int instanceNumber = 0; instanceNumber < instanceCount; ++instanceNumber) { - Coordinate currentLocation = instanceLocations[instanceNumber]; - final double currentAngle = instanceAngles[instanceNumber]; - -// System.err.println( String.format("%s[ %s ]", indent, comp.getName())); -// System.err.println( String.format("%s :: %12.8g / %12.8g / %12.8g (m) @ %8.4g (rads) ", indent, currentLocation.x, currentLocation.y, currentLocation.z, currentAngle )); - - Transformation currentTransform = parentTransform - .applyTransformation( Transformation.getTranslationTransform( currentLocation)) - .applyTransformation( Transformation.rotate_x( currentAngle )); + for(InstanceContext context: contextList ) { + System.err.println(String.format("........[% 2d] %s", context.instanceNumber, context.getLocation().toPreciseString())); - - // recurse into inactive trees: allow active stages inside inactive stages - for(RocketComponent child: comp.getChildren()) { - getTreeGeometry(indent+" ", treeGeometry, config, child, currentTransform ); - } +// System.err.println( String.format("%s[ %s ]", indent, comp.getName())); +// System.err.println( String.format("%s :: %12.8g / %12.8g / %12.8g (m) @ %8.4g (rads) ", indent, currentLocation.x, currentLocation.y, currentLocation.z, currentAngle )); - Geometry geom = cr.getComponentGeometry( comp, currentTransform ); - geom.active = config.isComponentActive( comp ); - treeGeometry.add( geom ); + Geometry instanceGeometry = cr.getComponentGeometry( comp, context.transform ); + instanceGeometry.active = context.active; + treeGeometry.add( instanceGeometry ); + } } return treeGeometry; } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 8f0bd6208..c5c9f4968 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -620,7 +620,7 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change length = maxX - minX; } - for (RocketComponent c : curConfig.getActiveComponents()) { + for (RocketComponent c : curConfig.getAllComponents()) { if (c instanceof SymmetricComponent) { double d1 = ((SymmetricComponent) c).getForeRadius() * 2; double d2 = ((SymmetricComponent) c).getAftRadius() * 2; From 577b09c4e99b0bec04674643f02639cf3943f697 Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sun, 20 Jan 2019 14:46:57 -0500 Subject: [PATCH 4/4] [refactor] switched 2D figure rendering over to new, simpler system --- .../gui/print/PrintableNoseCone.java | 2 +- .../gui/rocketfigure/BodyTubeShapes.java | 18 ++-- .../gui/rocketfigure/FinSetShapes.java | 55 +++++------- .../gui/rocketfigure/LaunchLugShapes.java | 16 ++-- .../gui/rocketfigure/MassComponentShapes.java | 33 +++---- .../gui/rocketfigure/MassObjectShapes.java | 36 +++----- .../gui/rocketfigure/ParachuteShapes.java | 24 +++-- .../gui/rocketfigure/RailButtonShapes.java | 24 ++--- .../gui/rocketfigure/RingComponentShapes.java | 31 +++---- .../rocketfigure/RocketComponentShape.java | 13 +-- .../gui/rocketfigure/ShockCordShapes.java | 18 ++-- .../gui/rocketfigure/StreamerShapes.java | 16 ++-- .../SymmetricComponentShapes.java | 9 +- .../gui/rocketfigure/TransitionShapes.java | 50 +++++------ .../gui/rocketfigure/TubeFinSetShapes.java | 16 ++-- .../gui/rocketfigure/TubeShapes.java | 14 ++- .../gui/scalefigure/RocketFigure.java | 89 ++++++------------- 17 files changed, 180 insertions(+), 284 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/print/PrintableNoseCone.java b/swing/src/net/sf/openrocket/gui/print/PrintableNoseCone.java index 9b2068534..903506af7 100644 --- a/swing/src/net/sf/openrocket/gui/print/PrintableNoseCone.java +++ b/swing/src/net/sf/openrocket/gui/print/PrintableNoseCone.java @@ -58,7 +58,7 @@ public class PrintableNoseCone extends AbstractPrintable { */ @Override protected void draw(Graphics2D g2) { - RocketComponentShape[] compShapes = TransitionShapes.getShapesSide(target, Transformation.rotate_x(0d), new Coordinate(0,0,0), PrintUnit.METERS.toPoints(1)); + RocketComponentShape[] compShapes = TransitionShapes.getShapesSide(target, Transformation.IDENTITY, PrintUnit.METERS.toPoints(1)); if (compShapes != null && compShapes.length > 0) { Rectangle r = compShapes[0].shape.getBounds(); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/BodyTubeShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/BodyTubeShapes.java index 33ba2cc9c..09bb9d93e 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/BodyTubeShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/BodyTubeShapes.java @@ -4,15 +4,12 @@ import java.awt.Shape; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; public class BodyTubeShapes extends RocketComponentShape { - public static RocketComponentShape[] getShapesSide( - RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation){ + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { + BodyTube tube = (BodyTube)component; @@ -20,22 +17,19 @@ public class BodyTubeShapes extends RocketComponentShape { double radius = tube.getOuterRadius(); Shape[] s = new Shape[1]; - s[0] = TubeShapes.getShapesSide( transformation, componentAbsoluteLocation, length, radius ); + s[0] = TubeShapes.getShapesSide( transformation, length, radius ); return RocketComponentShape.toArray(s, component); } - public static RocketComponentShape[] getShapesBack( - RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { - + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { + BodyTube tube = (BodyTube)component; double radius = tube.getOuterRadius(); Shape[] s = new Shape[1]; - s[0] = TubeShapes.getShapesBack( transformation, componentAbsoluteLocation, radius); + s[0] = TubeShapes.getShapesBack( transformation, radius); return RocketComponentShape.toArray(s, component); } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java index daa18acd0..4fb738e9a 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.rocketcomponent.TrapezoidFinSet; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Transformation; @@ -15,11 +14,10 @@ import net.sf.openrocket.util.Transformation; public class FinSetShapes extends RocketComponentShape { - public static RocketComponentShape[] getShapesSide(RocketComponent component, - Transformation transformation, - Coordinate instanceAbsoluteLocation ){ + public static RocketComponentShape[] getShapesSide( final RocketComponent component, + final Transformation transformation){ final FinSet finset = (FinSet) component; - + // this supplied transformation includes: // - baseRotationTransformation // - mount-radius transformtion @@ -47,40 +45,37 @@ public class FinSetShapes extends RocketComponentShape { ArrayList shapeList = new ArrayList<>(); // Make fin polygon - shapeList.add(new RocketComponentShape(generatePath(instanceAbsoluteLocation, finPoints), finset)); + shapeList.add(new RocketComponentShape(generatePath(finPoints), finset)); // Make fin polygon - shapeList.add(new RocketComponentShape(generatePath(instanceAbsoluteLocation, tabPoints), finset)); + shapeList.add(new RocketComponentShape(generatePath(tabPoints), finset)); // Make fin polygon - shapeList.add(new RocketComponentShape(generatePath(instanceAbsoluteLocation, rootPoints), finset)); + shapeList.add(new RocketComponentShape(generatePath(rootPoints), finset)); return shapeList.toArray(new RocketComponentShape[0]); } - public static RocketComponentShape[] getShapesBack( - RocketComponent component, - Transformation transformation, - Coordinate location) { + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { FinSet finset = (FinSet) component; - + Shape[] toReturn; if (MathUtil.equals(finset.getCantAngle(), 0)) { - toReturn = uncantedShapesBack(finset, transformation, location); + toReturn = uncantedShapesBack(finset, transformation); } else { - toReturn = cantedShapesBack(finset, transformation, location); + toReturn = cantedShapesBack(finset, transformation); } return RocketComponentShape.toArray(toReturn, finset); } - private static Path2D.Float generatePath(final Coordinate c0, final Coordinate[] points){ + private static Path2D.Float generatePath(final Coordinate[] points){ Path2D.Float finShape = new Path2D.Float(); for( int i = 0; i < points.length; i++){ - Coordinate curPoint = c0.add(points[i]); + Coordinate curPoint = points[i]; if (i == 0) finShape.moveTo(curPoint.x, curPoint.y); else @@ -90,8 +85,7 @@ public class FinSetShapes extends RocketComponentShape { } private static Shape[] uncantedShapesBack(FinSet finset, - Transformation transformation, - Coordinate finFront) { + Transformation transformation) { double thickness = finset.getThickness(); double height = finset.getSpan(); @@ -110,13 +104,13 @@ public class FinSetShapes extends RocketComponentShape { Coordinate a; Path2D.Double p = new Path2D.Double(); - a = finFront.add( c[0] ); + a = c[0]; p.moveTo(a.z, a.y); - a = finFront.add( c[1] ); + a = c[1]; p.lineTo(a.z, a.y); - a = finFront.add( c[2] ); + a = c[2]; p.lineTo(a.z, a.y); - a = finFront.add( c[3] ); + a = c[3]; p.lineTo(a.z, a.y); p.closePath(); @@ -126,8 +120,7 @@ public class FinSetShapes extends RocketComponentShape { // TODO: LOW: Jagged shapes from back draw incorrectly. private static Shape[] cantedShapesBack(FinSet finset, - Transformation transformation, - Coordinate location) { + Transformation transformation) { int i; int fins = finset.getFinCount(); double thickness = finset.getThickness(); @@ -179,15 +172,15 @@ public class FinSetShapes extends RocketComponentShape { s = new Shape[fins*2]; for (int fin=0; fin= 0.0012) && (innerRadius > 0)) { // Draw outer and inner s = new Shape[] { - TubeShapes.getShapesSide(transformation, instanceAbsoluteLocation, length, outerRadius), - TubeShapes.getShapesSide(transformation, instanceAbsoluteLocation, length, innerRadius) + TubeShapes.getShapesSide(transformation, length, outerRadius), + TubeShapes.getShapesSide(transformation, length, innerRadius) }; } else { // Draw only outer s = new Shape[] { - TubeShapes.getShapesSide(transformation, instanceAbsoluteLocation, length, outerRadius) + TubeShapes.getShapesSide(transformation, length, outerRadius) }; } return RocketComponentShape.toArray( s, component); } - public static RocketComponentShape[] getShapesBack( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate instanceAbsoluteLocation) { - net.sf.openrocket.rocketcomponent.RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component; + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { + + RingComponent tube = (net.sf.openrocket.rocketcomponent.RingComponent)component; Shape[] s; double outerRadius = tube.getOuterRadius(); @@ -51,12 +46,12 @@ public class RingComponentShapes extends RocketComponentShape { if ((outerRadius-innerRadius >= 0.0012) && (innerRadius > 0)) { s = new Shape[] { - TubeShapes.getShapesBack(transformation, instanceAbsoluteLocation, outerRadius), - TubeShapes.getShapesBack(transformation, instanceAbsoluteLocation, innerRadius) + TubeShapes.getShapesBack(transformation, outerRadius), + TubeShapes.getShapesBack(transformation, innerRadius) }; }else { s = new Shape[] { - TubeShapes.getShapesBack(transformation, instanceAbsoluteLocation, outerRadius) + TubeShapes.getShapesBack(transformation, outerRadius) }; } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java b/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java index be1ccc916..29603ffc3 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/RocketComponentShape.java @@ -3,10 +3,8 @@ 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; @@ -51,20 +49,15 @@ public class RocketComponentShape { } - public static RocketComponentShape[] getShapesSide( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate instanceOffset) { + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { // 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 + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { + // no-op Application.getExceptionHandler().handleErrorCondition("ERROR: RocketComponent.getShapesBack called with " +component); return new RocketComponentShape[0]; diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java index 7387399b5..92962bf24 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/ShockCordShapes.java @@ -1,5 +1,6 @@ package net.sf.openrocket.gui.rocketfigure; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; @@ -11,10 +12,8 @@ import java.awt.geom.RoundRectangle2D; public class ShockCordShapes extends RocketComponentShape { - public static RocketComponentShape[] getShapesSide( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { + net.sf.openrocket.rocketcomponent.MassObject massObj = (net.sf.openrocket.rocketcomponent.MassObject)component; @@ -22,8 +21,7 @@ public class ShockCordShapes extends RocketComponentShape { double radius = massObj.getRadius(); double arc = Math.min(length, 2*radius) * 0.7; - - Coordinate start = transformation.transform( componentAbsoluteLocation); + Coordinate start = transformation.transform(Coordinate.ZERO); Shape[] s = new Shape[1]; s[0] = new RoundRectangle2D.Double(start.x,(start.y-radius), length,2*radius,arc,arc); @@ -32,17 +30,15 @@ public class ShockCordShapes extends RocketComponentShape { } - public static RocketComponentShape[] getShapesBack( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; double or = tube.getRadius(); Shape[] s = new Shape[1]; - Coordinate start = componentAbsoluteLocation; + Coordinate start = transformation.transform(Coordinate.ZERO); + s[0] = new Ellipse2D.Double((start.z-or),(start.y-or),2*or,2*or); // Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset)); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/StreamerShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/StreamerShapes.java index 480e8d958..bcd26b7ad 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/StreamerShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/StreamerShapes.java @@ -1,5 +1,6 @@ package net.sf.openrocket.gui.rocketfigure; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; @@ -11,10 +12,7 @@ import java.awt.geom.RoundRectangle2D; public class StreamerShapes extends RocketComponentShape { - public static RocketComponentShape[] getShapesSide( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation ) { + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { net.sf.openrocket.rocketcomponent.MassObject massObj = (net.sf.openrocket.rocketcomponent.MassObject)component; @@ -23,7 +21,7 @@ public class StreamerShapes extends RocketComponentShape { double arc = Math.min(length, 2*radius) * 0.7; Shape[] s = new Shape[1]; - Coordinate frontCenter = componentAbsoluteLocation; + Coordinate frontCenter = transformation.transform(Coordinate.ZERO); s[0] = new RoundRectangle2D.Double((frontCenter.x),(frontCenter.y-radius), length,2*radius,arc,arc); @@ -37,16 +35,14 @@ public class StreamerShapes extends RocketComponentShape { } - public static RocketComponentShape[] getShapesBack( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component; double or = tube.getRadius(); Shape[] s = new Shape[1]; - Coordinate center = componentAbsoluteLocation; + Coordinate center = transformation.transform(Coordinate.ZERO); + s[0] = new Ellipse2D.Double((center.z-or),(center.y-or),2*or,2*or); // Coordinate[] start = transformation.transform(tube.toAbsolute(instanceOffset)); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/SymmetricComponentShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/SymmetricComponentShapes.java index e03a94b4d..11efa0ebc 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/SymmetricComponentShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/SymmetricComponentShapes.java @@ -1,5 +1,6 @@ package net.sf.openrocket.gui.rocketfigure; +import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.SymmetricComponent; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -17,10 +18,8 @@ public class SymmetricComponentShapes extends RocketComponentShape { // TODO: LOW: Uses only first component of cluster (not currently clusterable) - public static RocketComponentShape[] getShapesSide( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { + SymmetricComponent c = (SymmetricComponent) component; @@ -79,7 +78,7 @@ public class SymmetricComponentShapes extends RocketComponentShape { //System.out.println("here"); final int len = points.size(); - Coordinate nose = componentAbsoluteLocation; + Coordinate nose = transformation.transform(Coordinate.ZERO); // TODO: LOW: curved path instead of linear Path2D.Double path = new Path2D.Double(); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/TransitionShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/TransitionShapes.java index e47db5fa2..be46b169e 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/TransitionShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/TransitionShapes.java @@ -12,24 +12,20 @@ import java.awt.geom.Path2D; public class TransitionShapes extends RocketComponentShape { - // TODO: LOW: Uses only first component of cluster (not currently clusterable). - - public static RocketComponentShape[] getShapesSide( - RocketComponent component, - Transformation transformation, - Coordinate instanceLocation) { - return getShapesSide(component, transformation, instanceLocation, 1.0); + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { + return getShapesSide(component, transformation, 1.0); } public static RocketComponentShape[] getShapesSide( - RocketComponent component, - Transformation transformation, - Coordinate instanceAbsoluteLocation, - final double scaleFactor) { + final RocketComponent component, + final Transformation transformation, + final double scaleFactor) { Transition transition = (Transition)component; + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + RocketComponentShape[] mainShapes; // Simpler shape for conical transition, others use the method from SymmetricComponent @@ -49,27 +45,28 @@ public class TransitionShapes extends RocketComponentShape { mainShapes = new RocketComponentShape[] { new RocketComponentShape( path, component) }; } else { - mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation, instanceAbsoluteLocation); + mainShapes = SymmetricComponentShapes.getShapesSide(component, transformation); } Shape foreShoulder=null, aftShoulder=null; int arrayLength = mainShapes.length; if (transition.getForeShoulderLength() > 0.0005) { - Coordinate foreTransitionShoulderCenter = instanceAbsoluteLocation.sub( transition.getForeShoulderLength(), 0, 0); - final Coordinate frontCenter = foreTransitionShoulderCenter; //transformation.transform( foreTransitionShoulderCenter); - final double length = transition.getForeShoulderLength(); - final double radius = transition.getForeShoulderRadius(); + final double shoulderLength = transition.getForeShoulderLength(); + final double shoulderRadius = transition.getForeShoulderRadius(); + final Transformation offsetTransform = Transformation.getTranslationTransform(-transition.getForeShoulderLength(), 0, 0); + final Transformation foreShoulderTransform = transformation.applyTransformation(offsetTransform); - foreShoulder = TubeShapes.getShapesSide( transformation, frontCenter, length, radius); + foreShoulder = TubeShapes.getShapesSide( foreShoulderTransform, shoulderLength, shoulderRadius); arrayLength++; } if (transition.getAftShoulderLength() > 0.0005) { - Coordinate aftTransitionShoulderCenter = instanceAbsoluteLocation.add( transition.getLength(), 0, 0); - final Coordinate frontCenter = aftTransitionShoulderCenter; //transformation.transform( aftTransitionShoulderCenter ); - final double length = transition.getAftShoulderLength(); - final double radius = transition.getAftShoulderRadius(); - aftShoulder = TubeShapes.getShapesSide(transformation, frontCenter, length, radius); + final double shoulderLength = transition.getAftShoulderLength(); + final double shoulderRadius = transition.getAftShoulderRadius(); + final Transformation offsetTransform = Transformation.getTranslationTransform(transition.getLength(), 0, 0); + final Transformation aftShoulderTransform = transformation.applyTransformation(offsetTransform); + + aftShoulder = TubeShapes.getShapesSide(aftShoulderTransform, shoulderLength, shoulderRadius); arrayLength++; } if (foreShoulder==null && aftShoulder==null) @@ -92,17 +89,14 @@ public class TransitionShapes extends RocketComponentShape { } - public static RocketComponentShape[] getShapesBack( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { - net.sf.openrocket.rocketcomponent.Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component; + Transition transition = (net.sf.openrocket.rocketcomponent.Transition)component; double r1 = transition.getForeRadius(); double r2 = transition.getAftRadius(); - Coordinate center = componentAbsoluteLocation; + final Coordinate center = transformation.transform(Coordinate.ZERO); Shape[] s = new Shape[2]; s[0] = new Ellipse2D.Double((center.z-r1),(center.y-r1),2*r1,2*r1); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java index 5d6b56323..f3eb9e8d3 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java @@ -4,18 +4,17 @@ import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.awt.geom.Rectangle2D; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.TubeFinSet; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; public class TubeFinSetShapes extends RocketComponentShape { - public static RocketComponentShape[] getShapesSide( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) { - net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; + TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; int fins = finset.getFinCount(); double length = finset.getLength(); @@ -47,12 +46,9 @@ public class TubeFinSetShapes extends RocketComponentShape { } - public static RocketComponentShape[] getShapesBack( - net.sf.openrocket.rocketcomponent.RocketComponent component, - Transformation transformation, - Coordinate componentAbsoluteLocation) { + public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) { - net.sf.openrocket.rocketcomponent.TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; + TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component; int fins = finset.getFinCount(); double outerradius = finset.getOuterRadius(); diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeShapes.java index 2bf1d3d85..ebd94cc88 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeShapes.java @@ -10,21 +10,19 @@ import net.sf.openrocket.util.Transformation; public class TubeShapes extends RocketComponentShape { - public static Shape getShapesSide( - Transformation transformation, - Coordinate instanceAbsoluteLocation, - final double length, final double radius ){ + public static Shape getShapesSide( final Transformation transformation, final double length, final double radius ){ + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); + return new Rectangle2D.Double((instanceAbsoluteLocation.x), //x - the X coordinate of the upper-left corner of the newly constructed Rectangle2D (instanceAbsoluteLocation.y-radius), // y - the Y coordinate of the upper-left corner of the newly constructed Rectangle2D length, // w - the width of the newly constructed Rectangle2D 2*radius); // h - the height of the newly constructed Rectangle2D } - public static Shape getShapesBack( - Transformation transformation, - Coordinate instanceAbsoluteLocation, - final double radius ) { + public static Shape getShapesBack( final Transformation transformation, final double radius ) { + + final Coordinate instanceAbsoluteLocation = transformation.transform(Coordinate.ZERO); return new Ellipse2D.Double((instanceAbsoluteLocation.z-radius), (instanceAbsoluteLocation.y-radius), 2*radius, 2*radius); } diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 2f6fab230..5775390a1 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -15,22 +15,21 @@ import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; -import java.util.Collection; import java.util.LinkedHashSet; +import java.util.Map.Entry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.openrocket.gui.figureelements.FigureElement; import net.sf.openrocket.gui.rocketfigure.RocketComponentShape; -import net.sf.openrocket.gui.scalefigure.RocketPanel.VIEW_TYPE; import net.sf.openrocket.gui.util.ColorConversion; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.rocketcomponent.ComponentAssembly; -import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; @@ -192,8 +191,7 @@ public class RocketFigure extends AbstractScaleFigure { updateCanvasSize(); updateTransform(); - figureShapes.clear(); - updateShapeTree( this.figureShapes, rocket, this.axialRotation, Coordinate.ZERO); + updateShapes(this.figureShapes); g2.transform(projection); @@ -336,60 +334,29 @@ public class RocketFigure extends AbstractScaleFigure { return l.toArray(new RocketComponent[0]); } - // NOTE: Recursive function - private ArrayList updateShapeTree( - ArrayList allShapes, // output parameter - final RocketComponent comp, - final Transformation parentTransform, - final Coordinate parentLocation){ + private void updateShapes(ArrayList allShapes) { + // source input + final FlightConfiguration config = rocket.getSelectedConfiguration(); + // allShapes is an output buffer -- it stores all the generated shapes + allShapes.clear(); + + for(Entry> entry: config.getActiveInstances().entrySet() ) { + final RocketComponent comp = entry.getKey(); + + final ArrayList contextList = entry.getValue(); - final int instanceCount = comp.getInstanceCount(); - Coordinate[] instanceLocations = comp.getInstanceLocations(); - instanceLocations = parentTransform.transform( instanceLocations ); - double[] instanceAngles = comp.getInstanceAngles(); - if( instanceLocations.length != instanceAngles.length ){ - throw new ArrayIndexOutOfBoundsException(String.format("lengths of location array (%d) and angle arrays (%d) differs! (in: %s) ", instanceLocations.length, instanceAngles.length, comp.getName())); - } - - // iterate over the aggregated instances *for the whole* tree. - for( int index = 0; instanceCount > index ; ++index ){ - final double currentAngle = instanceAngles[index]; - - Transformation currentTransform = parentTransform; - if( 0.00001 < Math.abs( currentAngle )) { - Transformation currentAngleTransform = Transformation.rotate_x( currentAngle ); - currentTransform = currentAngleTransform.applyTransformation( parentTransform ); - } - - Coordinate currentLocation = parentLocation.add( instanceLocations[index] ); - -// if(FinSet.class.isAssignableFrom(comp.getClass())) { -// System.err.println(String.format("@%s: %s -- inst: [%d/%d]", comp.getClass().getSimpleName(), comp.getName(), index+1, instanceCount)); -// -// // FlightConfiguration config = this.rocket.getSelectedConfiguration(); -// // System.err.println(String.format(" -- stage: %d, active: %b, config: (%d) %s", comp.getStageNumber(), config.isComponentActive(comp), config.instanceNumber, config.getId())); -// System.err.println(String.format(" -- %s + %s = %s", parentLocation.toString(), instanceLocations[index].toString(), currentLocation.toString())); -// if( 0.00001 < Math.abs( currentAngle )) { -// System.err.println(String.format(" -- at: %6.4f radians", currentAngle)); -// } -// } - - // generate shape for this component, if active - if( this.rocket.getSelectedConfiguration().isComponentActive( comp )){ - allShapes = addThisShape( allShapes, this.currentViewType, comp, currentLocation, currentTransform); - } - - // recurse into component's children - for( RocketComponent child: comp.getChildren() ){ - // draw a tree for each instance subcomponent - updateShapeTree( allShapes, child, currentTransform, currentLocation ); - } - } - - return allShapes; + for(InstanceContext context: contextList ) { + final Transformation currentTransform = this.axialRotation.applyTransformation(context.transform); + + // generate shape for this component, if active + if( context.active ) { + allShapes = addThisShape( allShapes, this.currentViewType, comp, currentTransform); + } + } + } } - + /** * Gets the shapes required to draw the component. * @@ -401,12 +368,11 @@ public class RocketFigure extends AbstractScaleFigure { ArrayList allShapes, // this is the output parameter final RocketPanel.VIEW_TYPE viewType, final RocketComponent component, - final Coordinate instanceOffset, final Transformation transformation) { Reflection.Method m; if(( component instanceof Rocket)||( component instanceof ComponentAssembly )){ - // no-op; no shapes here, either. + // no-op; no shapes here return allShapes; } @@ -414,12 +380,12 @@ public class RocketFigure extends AbstractScaleFigure { switch (viewType) { case SideView: m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesSide", - RocketComponent.class, Transformation.class, Coordinate.class); + RocketComponent.class, Transformation.class); break; case BackView: m = Reflection.findMethod(ROCKET_FIGURE_PACKAGE, component, ROCKET_FIGURE_SUFFIX, "getShapesBack", - RocketComponent.class, Transformation.class, Coordinate.class); + RocketComponent.class, Transformation.class); break; default: @@ -433,14 +399,13 @@ public class RocketFigure extends AbstractScaleFigure { } - RocketComponentShape[] returnValue = (RocketComponentShape[]) m.invokeStatic(component, transformation, instanceOffset); + RocketComponentShape[] returnValue = (RocketComponentShape[]) m.invokeStatic(component, transformation); for ( RocketComponentShape curShape : returnValue ){ allShapes.add( curShape ); } return allShapes; } - /** * Gets the bounds of the drawn subject in Model-Space