From d23d25ed15ffb8910aa7f68b9e7525bd8cd6de6f Mon Sep 17 00:00:00 2001 From: Daniel_M_Williams Date: Sun, 16 Feb 2020 13:17:49 -0500 Subject: [PATCH 1/2] [fix] Fixes error when loading FinSet angles --- .../importt/AnglePositionSetter.java | 4 +- .../file/openrocket/savers/FinSetSaver.java | 2 +- .../sf/openrocket/rocketcomponent/FinSet.java | 52 ++++++++++--------- .../position/AnglePositionable.java | 6 +++ core/src/net/sf/openrocket/util/MathUtil.java | 11 ++-- .../rocketcomponent/FinSetTest.java | 20 ++++++- .../configdialog/EllipticalFinSetConfig.java | 4 +- .../configdialog/FreeformFinSetConfig.java | 4 +- .../configdialog/TrapezoidFinSetConfig.java | 4 +- 9 files changed, 69 insertions(+), 38 deletions(-) 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..749855850 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 @@ -78,13 +78,13 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab * 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; @@ -194,26 +194,33 @@ 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 (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 = Transformation.rotate_y(cantRadians).applyTransformation(t); t = new Transformation(length / 2, 0, 0).applyTransformation(t); cantRotation = t; } @@ -928,16 +935,15 @@ 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; fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } @@ -947,13 +953,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 Date: Sun, 16 Feb 2020 14:14:16 -0500 Subject: [PATCH 2/2] [fixes #565] Fixes display of canted fins --- .../sf/openrocket/rocketcomponent/FinSet.java | 48 ++++--- .../gui/rocketfigure/FinSetShapes.java | 126 +++--------------- 2 files changed, 45 insertions(+), 129 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index 749855850..33b6e0e2e 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -71,7 +71,7 @@ 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; /** @@ -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 @@ -210,19 +210,16 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab if (MathUtil.equals(clampedCant, this.cantRadians)) return; this.cantRadians = clampedCant; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } - - + public Transformation getCantRotation() { - if (cantRotation == null) { + 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(cantRadians).applyTransformation(t); - t = new Transformation(length / 2, 0, 0).applyTransformation(t); - cantRotation = t; + cantRotation = Transformation.rotate_y(cantRadians); } } return cantRotation; @@ -944,6 +941,13 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab 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); } @@ -1024,7 +1028,7 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab protected List copyFrom(RocketComponent c) { FinSet src = (FinSet) c; this.finCount = src.finCount; - this.finRotation = src.finRotation; + this.finRotationIncrement = src.finRotationIncrement; this.firstFinOffsetRadians = src.firstFinOffsetRadians; this.cantRadians = src.cantRadians; this.cantRotation = src.cantRotation; @@ -1230,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/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