diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java index 3dd43b81b..d29068f6c 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java @@ -294,6 +294,10 @@ class DocumentConfig { Reflection.findMethod(TubeFinSet.class, "setOuterRadius", double.class), "auto", Reflection.findMethod(TubeFinSet.class, "setOuterRadiusAutomatic", boolean.class))); + setters.put("TubeFinSet:instancecount", new IntSetter( + Reflection.findMethod(TubeFinSet.class, "setInstanceCount", int.class))); + setters.put("TubeFinSet:angleoffset", new AnglePositionSetter() ); + setters.put("TubeFinSet:radiusoffset", new RadiusPositionSetter() ); // InternalComponent - nothing diff --git a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java index aa9ad73ab..089107197 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java @@ -7,14 +7,16 @@ import java.util.List; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.preset.ComponentPreset.Type; +import net.sf.openrocket.rocketcomponent.position.AngleMethod; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialPositionable; +import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import net.sf.openrocket.startup.Application; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Transformation; -public class TubeFinSet extends ExternalComponent implements AxialPositionable { +public class TubeFinSet extends ExternalComponent implements RingInstanceable, AxialPositionable { private static final Translator trans = Application.getTranslator(); private final static double DEFAULT_RADIUS = 0.025; @@ -22,18 +24,20 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { private boolean autoRadius = true; // Radius chosen automatically based on parent component private double outerRadius = DEFAULT_RADIUS; protected double thickness = 0.002; - - protected int fins = 6; + private AngleMethod angleMethod = AngleMethod.FIXED; + protected RadiusMethod radiusMethod = RadiusMethod.RELATIVE; /** * Rotation angle of the first fin. Zero corresponds to the positive y-axis. */ - protected double rotation = 0; + private double firstFinOffsetRadians = 0; + + protected int fins = 6; /** * Rotation about the x-axis by angle this.rotation. */ - protected Transformation baseRotation = Transformation.rotate_x(rotation); + protected Transformation baseRotation = Transformation.IDENTITY; // initially, rotate by 0 radians. /** * Rotation about the x-axis by 2*PI/fins. @@ -167,7 +171,6 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { public int getFinCount() { return fins; } - @Override public boolean isAfter(){ @@ -195,7 +198,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { * @return The base rotation amount. */ public double getBaseRotation() { - return rotation; + return getAngleOffset(); } public double getFinRotation() { @@ -207,12 +210,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { * @param r The base rotation amount. */ public void setBaseRotation(double r) { - r = MathUtil.reduce180(r); - if (MathUtil.equals(r, rotation)) - return; - rotation = r; - baseRotation = Transformation.rotate_x(rotation); - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + setAngleOffset(r); } public Transformation getBaseRotationTransformation() { @@ -327,9 +325,9 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { RocketComponent s; s = this.getParent(); + double x = this.getPosition().x; while (s != null) { if (s instanceof SymmetricComponent) { - double x = this.getPosition().x; return ((SymmetricComponent) s).getRadius(x); } s = s.getParent(); @@ -337,4 +335,113 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { return 0; } + @Override + public int getInstanceCount() { + return getFinCount(); + } + + @Override + public void setInstanceCount(int newCount) { + setFinCount(newCount); + } + + @Override + public String getPatternName() { + return (this.getInstanceCount() + "-tubefin-ring"); + } + + @Override + public double getBoundingRadius() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setRadius(RadiusMethod method, double radius) { + // TODO Auto-generated method stub + + } + + @Override + public void setAngleOffset(double angleRadians) { + final double reducedAngle = MathUtil.reducePI(angleRadians); + if (MathUtil.equals(reducedAngle, firstFinOffsetRadians)) + return; + firstFinOffsetRadians = reducedAngle; + + if (MathUtil.equals(this.firstFinOffsetRadians, 0)) { + baseRotation = Transformation.IDENTITY; + } else { + baseRotation = Transformation.rotate_x(firstFinOffsetRadians); + } + + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + + @Override + public AngleMethod getAngleMethod() { + return this.angleMethod; + } + + @Override + public double getAngleOffset() { + return this.firstFinOffsetRadians; + } + + @Override + public void setAngleMethod(AngleMethod newAngleMethod) { + mutex.verify(); + this.angleMethod = newAngleMethod; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + + @Override + public double getInstanceAngleIncrement() { + return ( 2*Math.PI / getFinCount()); + } + + @Override + public double[] getInstanceAngles() { + final double angleIncrementRadians = getInstanceAngleIncrement(); + + double[] result = new double[getFinCount()]; + for (int finNumber=0; finNumber < getFinCount(); ++finNumber) { + double additionalOffset = angleIncrementRadians * finNumber; + result[finNumber] = MathUtil.reduce2PI(firstFinOffsetRadians + additionalOffset); + } + + return result; + } + + @Override + public Coordinate[] getInstanceOffsets() { + checkState(); + + final double bodyRadius = this.getBodyRadius(); + + // already includes the base rotation + final double[] angles = getInstanceAngles(); + + Coordinate[] toReturn = new Coordinate[this.fins]; + for (int instanceNumber = 0; instanceNumber < this.fins; instanceNumber++) { + final Coordinate raw = new Coordinate( 0, bodyRadius, 0); + final Coordinate rotated = Transformation.getAxialRotation(angles[instanceNumber]).transform(raw); + toReturn[instanceNumber] = rotated; + } + + return toReturn; + } + + @Override + public void setRadiusOffset(double radius) { + // TODO Auto-generated method stub + + } + + @Override + public void setRadiusMethod(RadiusMethod method) { + // TODO Auto-generated method stub + + } + } diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java index 721c9cde0..c13e156e4 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java @@ -318,13 +318,8 @@ public class ComponentRenderer { gl.glPushMatrix(); gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glRotated(fs.getBaseRotation() * (180.0 / Math.PI), 1, 0, 0); - for( int i = 0; i< fs.getFinCount(); i++ ) { - gl.glPushMatrix(); - gl.glTranslated(0, fs.getOuterRadius() + fs.getBodyRadius(), 0); - renderTube(gl, which, fs.getOuterRadius(), fs.getInnerRadius(), fs.getLength()); - gl.glPopMatrix(); - gl.glRotated(360.0 / fs.getFinCount(), 1, 0, 0); - } + gl.glTranslated(0, fs.getOuterRadius(), 0); + renderTube(gl, which, fs.getOuterRadius(), fs.getInnerRadius(), fs.getLength()); gl.glPopMatrix(); } diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java index 1b00fd5f4..7b124b55a 100644 --- a/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java +++ b/swing/src/net/sf/openrocket/gui/rocketfigure/TubeFinSetShapes.java @@ -35,13 +35,10 @@ public class TubeFinSetShapes extends RocketComponentShape { final double outerRadius = finSet.getOuterRadius(); final double length = finSet.getLength(); Coordinate[] locations = transformLocations(finSet, transformation); - Transformation finRotation = finSet.getFinRotationTransformation(); - Shape[] shapes = new Shape[finSet.getFinCount()]; - for (int i=0; i < shapes.length; i++) { - shapes[i] = new Rectangle2D.Double(locations[0].x, (locations[0].y-outerRadius), length, 2*outerRadius); - locations = finRotation.transform(locations); - } + Shape[] shapes = new Shape[] { + new Rectangle2D.Double(locations[0].x, (locations[0].y-outerRadius), length, 2*outerRadius) + }; return RocketComponentShape.toArray(shapes, component); } @@ -62,13 +59,10 @@ public class TubeFinSetShapes extends RocketComponentShape { final double outerRadius = finSet.getOuterRadius(); Coordinate[] locations = transformLocations(finSet, transformation); - Transformation finRotation = finSet.getFinRotationTransformation(); - Shape[] shapes = new Shape[finSet.getFinCount()]; - for (int i=0; i < shapes.length; i++) { - shapes[i] = new Ellipse2D.Double((locations[0].z - outerRadius), (locations[0].y - outerRadius), (2 * outerRadius), (2 * outerRadius)); - locations = finRotation.transform(locations); - } + Shape[] shapes = new Shape[] { + new Ellipse2D.Double((locations[0].z - outerRadius), (locations[0].y - outerRadius), (2 * outerRadius), (2 * outerRadius)) + }; return RocketComponentShape.toArray(shapes, component); } @@ -95,13 +89,12 @@ public class TubeFinSetShapes extends RocketComponentShape { private static Coordinate[] transformLocations(final TubeFinSet finSet, final Transformation transformation) { final double outerRadius = finSet.getOuterRadius(); final double bodyRadius = finSet.getBodyRadius(); - Coordinate[] locations = finSet.getComponentLocations(); - Transformation baseRotation = finSet.getBaseRotationTransformation(); + Coordinate[] locations = finSet.getInstanceLocations(); for (int i=0; i < locations.length; i++) { - Coordinate c = locations[i].add(0, (bodyRadius + outerRadius), 0); - c = transformation.linearTransform(c); - c = baseRotation.transform(c); + Coordinate c = locations[i].setX(0.); + c = c.sub(0, (bodyRadius - outerRadius), 0); + c = transformation.transform(c); locations[i] = c; }