diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/AnglePositionSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/AnglePositionSetter.java
index 06b6d97d2..4843f6872 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/AnglePositionSetter.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/AnglePositionSetter.java
@@ -20,9 +20,9 @@ class AnglePositionSetter implements Setter {
double pos;
try {
- pos = Double.parseDouble(value) * Math.PI / 180.0 ;
+ pos = Math.toRadians(Double.parseDouble(value));
} catch (NumberFormatException e) {
- warnings.add(String.format("Warning: invalid value radius position. value=%s class: %s", value, c.getClass().getCanonicalName() ));
+ warnings.add(String.format("Warning: invalid angle position. value=%s (degrees) class: %s", value, c.getClass().getCanonicalName() ));
return;
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/FinSetSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/FinSetSaver.java
index c7d5ded18..ef6c25212 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/FinSetSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/FinSetSaver.java
@@ -20,7 +20,7 @@ public class FinSetSaver extends ExternalComponentSaver {
elements.add("" + fins.getThickness() + "");
elements.add("" + fins.getCrossSection().name().toLowerCase(Locale.ENGLISH)
+ "");
- elements.add("" + (fins.getCantAngle() * 180.0 / Math.PI) + "");
+ elements.add("" + Math.toDegrees(fins.getCantAngle()) + "");
// Save fin tabs only if they exist (compatibility with file version < 1.1)
if (!MathUtil.equals(fins.getTabHeight(), 0) &&
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
index 54b8b683b..33b6e0e2e 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
@@ -35,7 +35,7 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
/**
* Maximum allowed cant of fins.
*/
- public static final double MAX_CANT = (15.0 * Math.PI / 180);
+ public static final double MAX_CANT_RADIANS = (15.0 * Math.PI / 180);
public enum CrossSection {
//// Square
@@ -71,20 +71,20 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
/**
* Rotation about the x-axis by 2*PI/fins.
*/
- private Transformation finRotation = Transformation.IDENTITY;
+ private Transformation finRotationIncrement = Transformation.IDENTITY;
/**
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
*/
private AngleMethod angleMethod = AngleMethod.RELATIVE;
- private double firstFinOffset = 0;
+ private double firstFinOffsetRadians = 0;
private Transformation baseRotation = Transformation.IDENTITY; // initially, rotate by 0 degrees.
/**
* Cant angle of fins.
*/
- private double cantAngle = 0;
+ private double cantRadians = 0;
/* Cached value: */
private Transformation cantRotation = null;
@@ -164,13 +164,13 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
n = 8;
finCount = n;
- finRotation = Transformation.rotate_x(2 * Math.PI / finCount);
+ finRotationIncrement = Transformation.rotate_x(2 * Math.PI / finCount);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
public Transformation getFinRotationTransformation() {
- return finRotation;
+ return finRotationIncrement;
}
@Override
@@ -194,28 +194,32 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
setAngleOffset(r);
}
+ /**
+ * @return angle current cant angle, in radians
+ */
public double getCantAngle() {
- return cantAngle;
+ return cantRadians;
}
- public void setCantAngle(double cant) {
- cant = MathUtil.clamp(cant, -MAX_CANT, MAX_CANT);
- if (MathUtil.equals(cant, cantAngle))
+ /**
+ *
+ * @param cant -- new cant angle, in radians
+ */
+ public void setCantAngle(final double newCantRadians) {
+ final double clampedCant = MathUtil.clamp(newCantRadians, -MAX_CANT_RADIANS, MAX_CANT_RADIANS);
+ if (MathUtil.equals(clampedCant, this.cantRadians))
return;
- this.cantAngle = cant;
+ this.cantRadians = clampedCant;
+
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
-
-
+
public Transformation getCantRotation() {
- if (cantRotation == null) {
- if (MathUtil.equals(cantAngle, 0)) {
+ if( null == cantRotation ) {
+ if (MathUtil.equals(this.cantRadians, 0)) {
cantRotation = Transformation.IDENTITY;
} else {
- Transformation t = new Transformation(-length / 2, 0, 0);
- t = Transformation.rotate_y(cantAngle).applyTransformation(t);
- t = new Transformation(length / 2, 0, 0).applyTransformation(t);
- cantRotation = t;
+ cantRotation = Transformation.rotate_y(cantRadians);
}
}
return cantRotation;
@@ -928,16 +932,22 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
@Override
public double getAngleOffset() {
- return firstFinOffset;
+ return firstFinOffsetRadians;
}
-
@Override
- public void setAngleOffset(double angle) {
- angle = MathUtil.reduce180(angle);
- if (MathUtil.equals(angle, firstFinOffset))
+ public void setAngleOffset(final double angleRadians) {
+ final double reducedAngle = MathUtil.reducePI(angleRadians);
+ if (MathUtil.equals(reducedAngle, firstFinOffsetRadians))
return;
- firstFinOffset = angle;
+ firstFinOffsetRadians = reducedAngle;
+
+ if (MathUtil.equals(this.firstFinOffsetRadians, 0)) {
+ baseRotation = Transformation.IDENTITY;
+ } else {
+ baseRotation = Transformation.rotate_x(firstFinOffsetRadians);
+ }
+
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@@ -947,13 +957,12 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
}
@Override
- public double[] getInstanceAngles(){
- final double baseAngle = getAngleOffset();
- final double incrAngle = getInstanceAngleIncrement();
+ public double[] getInstanceAngles() {
+ final double angleIncrementRadians = getInstanceAngleIncrement();
double[] result = new double[ getFinCount()];
- for( int i=0; i copyFrom(RocketComponent c) {
FinSet src = (FinSet) c;
this.finCount = src.finCount;
- this.finRotation = src.finRotation;
- this.firstFinOffset = src.firstFinOffset;
- this.cantAngle = src.cantAngle;
+ this.finRotationIncrement = src.finRotationIncrement;
+ this.firstFinOffsetRadians = src.firstFinOffsetRadians;
+ this.cantRadians = src.cantRadians;
this.cantRotation = src.cantRotation;
this.thickness = src.thickness;
this.crossSection = src.crossSection;
@@ -1066,7 +1075,6 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
}
/**
-<<<<<<< HEAD
* use this for calculating physical properties, and routine drawing
*
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
@@ -1226,22 +1234,22 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
checkState();
final double bodyRadius = this.getBodyRadius();
+
+ // already includes the base rotation
final double[] angles = getInstanceAngles();
- final Transformation localCantRotation = getCantRotation();
-
+ final Transformation localCantRotation = new Transformation(length / 2, 0, 0)
+ .applyTransformation(getCantRotation())
+ .applyTransformation(new Transformation(-length / 2, 0, 0));
+
Coordinate[] toReturn = new Coordinate[finCount];
for (int instanceNumber = 0; instanceNumber < finCount; instanceNumber++) {
- final double curY = bodyRadius * Math.cos(angles[instanceNumber]);
- final double curZ = bodyRadius * Math.sin(angles[instanceNumber]);
-
- final Coordinate naiveLocation = new Coordinate(0, curY, curZ);
-
- final Coordinate adjustedLocation = baseRotation.transform(localCantRotation.transform( naiveLocation));
-
- toReturn[instanceNumber] = adjustedLocation;
+ final Coordinate raw = new Coordinate( 0, bodyRadius, 0);
+ final Coordinate canted = localCantRotation.transform(raw);
+ final Coordinate rotated = Transformation.rotate_x(angles[instanceNumber]).transform(canted);
+ toReturn[instanceNumber] = rotated;
}
-
+
return toReturn;
}
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/position/AnglePositionable.java b/core/src/net/sf/openrocket/rocketcomponent/position/AnglePositionable.java
index 577b3bdf2..33831856b 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/position/AnglePositionable.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/position/AnglePositionable.java
@@ -2,8 +2,14 @@ package net.sf.openrocket.rocketcomponent.position;
public interface AnglePositionable {
+ /**
+ * @return angle to the first element, in radians
+ */
public double getAngleOffset();
+ /**
+ * @param new offset angle, in radians
+ */
public void setAngleOffset(final double angle);
public AngleMethod getAngleMethod( );
diff --git a/core/src/net/sf/openrocket/util/MathUtil.java b/core/src/net/sf/openrocket/util/MathUtil.java
index e1e986b24..ef6cc4956 100644
--- a/core/src/net/sf/openrocket/util/MathUtil.java
+++ b/core/src/net/sf/openrocket/util/MathUtil.java
@@ -211,10 +211,13 @@ public class MathUtil {
/**
* Reduce the angle x to the range 0 - 2*PI.
- * @param x Original angle.
+ *
+ * @deprecated function refers to units:degrees, but operates in units:radians. Please use 'MathUtil.reduce2PI'
+ * @param x Original angle.
* @return The equivalent angle in the range 0 ... 2*PI.
*/
- public static double reduce360(double x) {
+ @Deprecated
+ public static double reduce360(double x) {
double d = Math.floor(x / (2 * Math.PI));
return x - d * 2 * Math.PI;
}
@@ -224,9 +227,11 @@ public class MathUtil {
*
* Either -PI and PI might be returned, depending on the rounding function.
*
- * @param x Original angle.
+ * @deprecated function refers to units:degrees, but operates in units:radians. Please use 'MathUtil.reducePI'
+ * @param x Original angle.
* @return The equivalent angle in the range -PI ... PI.
*/
+ @Deprecated
public static double reduce180(double x) {
double d = Math.rint(x / (2 * Math.PI));
return x - d * 2 * Math.PI;
diff --git a/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java
index 3dd94dd5b..15a39a401 100644
--- a/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java
+++ b/core/test/net/sf/openrocket/rocketcomponent/FinSetTest.java
@@ -50,8 +50,24 @@ public class FinSetTest extends BaseTestCase {
fins.setFilletRadius(0.0);
- return fins;
- }
+ fins.setAngleMethod(AngleMethod.FIXED);
+ fins.setAngleOffset(Math.toRadians(90.0));
+
+ fins.setCantAngle(Math.toRadians(3.0));
+
+ return fins;
+ }
+
+ @Test
+ public void testAngleOffset() {
+ final FinSet fins = FinSetTest.createSimpleFin();
+
+ assertEquals("Angle Offset Doesn't match!", Math.PI/2, fins.getAngleOffset(), EPSILON);
+ assertEquals("Angle Offset Doesn't match!", 90.0, Math.toDegrees(fins.getAngleOffset()), EPSILON);
+
+ assertEquals("Cant angle doesn't match!", Math.PI/60, fins.getCantAngle(), EPSILON);
+ assertEquals("Cant angle doesn't match!", 3.0, Math.toDegrees(fins.getCantAngle()), EPSILON);
+ }
@Test
public void testTabLocation() {
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java
index e37ffa058..9e7fa4c68 100644
--- a/swing/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java
+++ b/swing/src/net/sf/openrocket/gui/configdialog/EllipticalFinSetConfig.java
@@ -69,14 +69,14 @@ public class EllipticalFinSetConfig extends FinSetConfig {
panel.add(label);
m = new DoubleModel(component, "CantAngle", UnitGroup.UNITS_ANGLE,
- -FinSet.MAX_CANT, FinSet.MAX_CANT);
+ -FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS);
spin = new JSpinner(m.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(m), "growx");
- panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT, FinSet.MAX_CANT)),
+ panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS)),
"w 100lp, wrap");
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java
index 37ccc6118..69f84d0a0 100644
--- a/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java
+++ b/swing/src/net/sf/openrocket/gui/configdialog/FreeformFinSetConfig.java
@@ -134,14 +134,14 @@ public class FreeformFinSetConfig extends FinSetConfig {
label.setToolTipText(trans.get("FreeformFinSetCfg.lbl.ttip.Fincant"));
panel.add(label);
- m = new DoubleModel(component, "CantAngle", UnitGroup.UNITS_ANGLE, -FinSet.MAX_CANT, FinSet.MAX_CANT);
+ m = new DoubleModel(component, "CantAngle", UnitGroup.UNITS_ANGLE, -FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS);
spin = new JSpinner(m.getSpinnerModel());
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin, "growx");
panel.add(new UnitSelector(m), "growx");
- panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT, FinSet.MAX_CANT)), "w 100lp, wrap 40lp");
+ panel.add(new BasicSlider(m.getSliderModel(-FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS)), "w 100lp, wrap 40lp");
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java
index 1035009c1..804d698e9 100644
--- a/swing/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java
+++ b/swing/src/net/sf/openrocket/gui/configdialog/TrapezoidFinSetConfig.java
@@ -75,14 +75,14 @@ public class TrapezoidFinSetConfig extends FinSetConfig {
label.setToolTipText(trans.get("TrapezoidFinSetCfg.lbl.ttip.Fincant"));
panel.add(label);
- final DoubleModel cantModel = new DoubleModel(component, "CantAngle", UnitGroup.UNITS_ANGLE, -FinSet.MAX_CANT, FinSet.MAX_CANT);
+ final DoubleModel cantModel = new DoubleModel(component, "CantAngle", UnitGroup.UNITS_ANGLE, -FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS);
final JSpinner cantSpinner = new JSpinner(cantModel.getSpinnerModel());
cantSpinner.setEditor(new SpinnerEditor(cantSpinner));
panel.add(cantSpinner, "growx");
panel.add(new UnitSelector(cantModel), "growx");
- panel.add(new BasicSlider(cantModel.getSliderModel(-FinSet.MAX_CANT, FinSet.MAX_CANT)),
+ panel.add(new BasicSlider(cantModel.getSliderModel(-FinSet.MAX_CANT_RADIANS, FinSet.MAX_CANT_RADIANS)),
"w 100lp, wrap");
}
diff --git a/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java b/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java
index 4fb738e9a..29d98a266 100644
--- a/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java
+++ b/swing/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java
@@ -30,7 +30,7 @@ public class FinSetShapes extends RocketComponentShape {
*/
final Transformation cantRotation = finset.getCantRotation();
- final Transformation compositeTransform = cantRotation.applyTransformation( transformation);
+ final Transformation compositeTransform = transformation.applyTransformation(cantRotation);
Coordinate finPoints[] = finset.getFinPoints();
Coordinate tabPoints[] = finset.getTabPoints();
@@ -117,47 +117,37 @@ public class FinSetShapes extends RocketComponentShape {
return new Shape[]{p};
}
-
- // TODO: LOW: Jagged shapes from back draw incorrectly.
private static Shape[] cantedShapesBack(FinSet finset,
Transformation transformation) {
- int i;
- int fins = finset.getFinCount();
+
double thickness = finset.getThickness();
- Transformation cantRotation = finset.getCantRotation();
-
Coordinate[] sidePoints;
Coordinate[] backPoints;
int maxIndex;
Coordinate[] points = finset.getFinPoints();
+
+ // this loop finds the index @ max-y, as visible from the back
for (maxIndex = points.length-1; maxIndex > 0; maxIndex--) {
if (points[maxIndex-1].y < points[maxIndex].y)
break;
}
-
- points = cantRotation.transform( points );
-// transformPoints(points,new Transformation(0,radius,0));
- points = transformation.transform( points );
-
+
+ Transformation cantTransform = finset.getCantRotation();
+ final Transformation compositeTransform = transformation.applyTransformation(cantTransform);
sidePoints = new Coordinate[points.length];
backPoints = new Coordinate[2*(points.length-maxIndex)];
- double sign;
- if (finset.getCantAngle() > 0) {
- sign = 1.0;
- } else {
- sign = -1.0;
- }
-
- // Calculate points for the side panel
- for (i=0; i < points.length; i++) {
+ double sign = Math.copySign(1.0, finset.getCantAngle());
+
+ // Calculate points for the visible side panel
+ for (int i=0; i < points.length; i++) {
sidePoints[i] = points[i].add(0,0,sign*thickness/2);
}
// Calculate points for the back portion
- i=0;
+ int i=0;
for (int j=points.length-1; j >= maxIndex; j--, i++) {
backPoints[i] = points[j].add(0,0,sign*thickness/2);
}
@@ -168,35 +158,24 @@ public class FinSetShapes extends RocketComponentShape {
// Generate shapes
Shape[] s;
if (thickness > 0.0005) {
-
- s = new Shape[fins*2];
- for (int fin=0; fin