From 74ec0be340baf06d63cdc0e81cfd45e79bc2fa48 Mon Sep 17 00:00:00 2001 From: Billy Olsen Date: Sun, 19 Jul 2020 14:52:25 -0700 Subject: [PATCH] Make TubeFinSet RingInstanceable Make the TubeFinSet RingInstanceable. This change updates the rendering of both the 2D and 3D views to handle the RingInstanceable shapes. This also updates the DocumentConfig to parse the new XML formats properly. Signed-off-by: Billy Olsen --- .../openrocket/importt/DocumentConfig.java | 4 + .../rocketcomponent/TubeFinSet.java | 135 ++++++++++++++++-- .../figure3d/geometry/ComponentRenderer.java | 9 +- .../gui/rocketfigure/TubeFinSetShapes.java | 27 ++-- 4 files changed, 137 insertions(+), 38 deletions(-) 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; }