diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index ddd624902..32b976d38 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -864,7 +864,7 @@ componentanalysisdlg.lbl.reflenght = Reference length:
componentanalysisdlg.lbl.refarea = Reference area:
!componentanalysisdlg.But.close =Close
componentanalysisdlg.TabStability.Col.Component = Component
-componentanalysisdlg.TOTAL = Total
+componentanalysisdlg.TOTAL = Total (Rocket)
componentanalysisdlg.noWarnings = No warnings.
! Custom Material dialog
diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeCalc.java
index d1875c9e4..3abd7aa30 100644
--- a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeCalc.java
+++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeCalc.java
@@ -14,73 +14,64 @@ public abstract class TubeCalc extends RocketComponentCalc {
private final static Logger log = LoggerFactory.getLogger(TubeFinSetCalc.class);
- // air density (standard conditions)
- private final double rho = 1.225; // kg/m^3
-
+ private final Tube tube;
private final double diameter;
private final double length;
protected final double innerArea;
private final double totalArea;
private final double frontalArea;
+ private final double epsilon;
public TubeCalc(RocketComponent component) {
super(component);
- Tube tube = (Tube)component;
+ tube = (Tube)component;
length = tube.getLength();
diameter = 2 * tube.getInnerRadius();
innerArea = Math.PI * MathUtil.pow2(tube.getInnerRadius());
totalArea = Math.PI * MathUtil.pow2(tube.getOuterRadius());
frontalArea = totalArea - innerArea;
+ epsilon = tube.getFinish().getRoughnessSize(); // roughness; note we don't maintain surface roughness of
+ // interior separately from exterior.
}
@Override
public double calculatePressureCD(FlightConditions conditions,
double stagnationCD, double baseCD, WarningSet warnings) {
-
- // These calculations come from a mix of theoretical and empirical
- // results, and are marked with (t) for theoretical and (e) for empirical.
- // The theoretical results should not be modified; the empirical can be adjusted
- // to better simulate real rockets as we get data.
-
- // For the sources of the empirical formulas, see Carello, Ivanov, and Mazza,
- // "Pressure drop in pipe lines for compressed air: comparison between experimental
- // and theoretical analysis", Transactions on Engineering Sciences vol 18,
- // ISSN 1743-35331998, 1998.
-
- // For the rockets for which we have data, the effect of the stagnation CD appears to be
- // overstated. This code multiplies it be a factor of 0.7 to better match experimental
- // data
// Need to check for tube inner area 0 in case of rockets using launch lugs with
- // an inner radius of 0 to emulate rail buttons (or just weird rockets, of course)
+ // an inner radius of 0 to emulate rail guides (or just weird rockets, of course)
+ double tubeCD = 0.0;
double deltap;
if (innerArea > MathUtil.EPSILON) {
- // Temperature
- final double T = conditions.getAtmosphericConditions().getTemperature();
-
- // Volume flow rate (t)
- final double Q = conditions.getVelocity() * innerArea;
+ // Current atmospheric conditions
+ final double p = conditions.getAtmosphericConditions().getPressure();
+ final double t = conditions.getAtmosphericConditions().getTemperature();
+ final double rho = conditions.getAtmosphericConditions().getDensity();
+ final double v = conditions.getVelocity();
// Reynolds number (note Reynolds number for the interior of a pipe is based on diameter,
// not length (t))
- final double Re = conditions.getVelocity() * diameter /
- conditions.getAtmosphericConditions().getKinematicViscosity();
+ final double Re = v * diameter / conditions.getAtmosphericConditions().getKinematicViscosity();
- // friction coefficient (for smooth tube interior) (e)
- final double lambda = 1/MathUtil.pow2(2 * Math.log(0.5625 * Math.pow(Re, 0.875)) - 0.8);
-
- // pressure drop (e)
- final double P0 = 100; // standard pressure
- final double T0 = 273.15; // standard temperature
- deltap = (lambda * 8 * length * rho * MathUtil.pow2(Q) * T * P0) /
- (MathUtil.pow2(Math.PI) * Math.pow(diameter, 5) * T0 * conditions.getAtmosphericConditions().getPressure());
- } else {
- deltap = 0.0;
+ // friction coefficient using Swamee-Jain equation
+ double f = 0.25/MathUtil.pow2(Math.log10((epsilon / (3.7 * diameter) + 5.74/Math.pow(Re, 0.9))));
+
+ // If we're supersonic, apply a correction
+ if (conditions.getMach() > 1) {
+ f = f / conditions.getBeta();
+ }
+
+ // pressure drop using Darcy-Weissbach equation
+ deltap = f * (length * rho * MathUtil.pow2(v)) / (2 * diameter);
+
+ // drag coefficient of tube interior from pressure drop
+ tubeCD = 2 * (deltap * innerArea) / (rho * MathUtil.pow2(v) * innerArea);
}
// convert to CD and return
- return (deltap * innerArea + 0.7 * stagnationCD * frontalArea) / conditions.getRefArea();
+ final double cd = (tubeCD * innerArea + 0.7*(stagnationCD + baseCD) * frontalArea) / conditions.getRefArea();
+ return cd;
}
}
diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java
index 642664ce5..a0b53cbfd 100644
--- a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java
+++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java
@@ -25,6 +25,8 @@ public class TubeFinSetCalc extends TubeCalc {
private static final double STALL_ANGLE = (20 * Math.PI / 180);
private final double[] poly = new double[6];
+
+ private final TubeFinSet tubes;
// parameters straight from configuration; we'll be grabbing them once
// so code is a bit shorter elsewhere
@@ -44,14 +46,14 @@ public class TubeFinSetCalc extends TubeCalc {
private final double cnaconst;
protected final WarningSet geometryWarnings = new WarningSet();
-
+
public TubeFinSetCalc(RocketComponent component) {
super(component);
if (!(component instanceof TubeFinSet)) {
throw new IllegalArgumentException("Illegal component type " + component);
}
- final TubeFinSet tubes = (TubeFinSet) component;
+ tubes = (TubeFinSet) component;
if (tubes.getTubeSeparation() > MathUtil.EPSILON) {
geometryWarnings.add(Warning.TUBE_SEPARATION);
@@ -75,37 +77,53 @@ public class TubeFinSetCalc extends TubeCalc {
// aspect ratio.
ar = 2 * innerRadius / chord;
+
+
+ // Some trigonometry...
+ // We need a triangle with the following three sides:
+ // d is from the center of the body tube to a tangent point on the tube fin
+ // outerRadius is from the center of the tube fin to the tangent point. Note that
+ // d and outerRadius are at right angles
+ // bodyRadius + outerRadius is from the center of the body tube to the center of the tube fin.
+ // This is the hypotenuse of the right triangle.
+
+ // Find length of d
+ final double d = Math.sqrt(MathUtil.pow2(bodyRadius + outerRadius) - MathUtil.pow2(outerRadius));
+
+ // Area of diamond formed by mirroring triangle on its hypotenuse (same area as rectangle
+ // formed by d and outerarea, but it *isn't* that rectangle)
+ double a = d * outerRadius;
+
+ // angle between outerRadius and bodyRadius+outerRadius
+ final double theta1 = Math.acos(outerRadius/(outerRadius + bodyRadius));
+
+ // area of arc from tube fin, doubled to get both halves of diamond
+ final double a1 = MathUtil.pow2(outerRadius) * theta1;
+
+ // angle between bodyRadius+outerRadius and d
+ final double theta2 = Math.PI/2.0 - theta1;
+
+ // area of arc from body tube. Doubled so we have area to remove from diamond
+ final double a2 = MathUtil.pow2(bodyRadius) * theta2;
+
+ // area of interstice for one tube fin
+ intersticeArea = (a - a1 - a2);
+
+ // for comparison, what's the area of a tube fin?
+ double tubeArea = MathUtil.pow2(outerRadius) * Math.PI;
// wetted area for friction drag calculation. We don't consider the inner surface of the tube;
// that affects the pressure drop through the tube and so (indirecctly) affects the pressure drag.
- // Area of the outer surface of tubes. Since roughly half
- // of the area is "masked" by the interstices between the tubes and the
- // body tube, only consider the other half of the area (so only multiplying by pi instead of 2*pi)
- final double outerArea = chord * Math.PI * outerRadius;
+ // Area of the outer surface of a tube, not including portion masked by interstice
+ final double outerArea = chord * 2.0 * (Math.PI - theta1) * outerRadius;
- // Surface area of the portion of the body tube masked by the tube fins, per tube
- final BodyTube parent = (BodyTube) tubes.getParent();
- final double maskedArea = chord * 2.0 * Math.PI * bodyRadius / tubeCount;
+ // Surface area of the portion of the body tube masked by the tube fin. We'll subtract it from
+ // the tube fin area rather than go in and change the body tube surface area calculation. If tube
+ // fin and body tube roughness aren't the same this will result in an inaccuracy.
+ final double maskedArea = chord * 2.0 * theta2 * bodyRadius;
wettedArea = outerArea - maskedArea;
- log.debug("wetted area of tube fins " + wettedArea);
-
- // frontal area of interstices between tubes for pressure drag calculation.
- // We'll treat them as a closed blunt object.
-
- // area of disk passing through tube fin centers
- final double tubeDiskArea = Math.PI * MathUtil.pow2(bodyRadius + outerRadius);
-
- // half of combined area of tube fin exteriors. Deliberately using the outer radius here since we
- // calculate pressure drag from the tube walls in TubeCalc
- final double tubeOuterArea = tubeCount * Math.PI * MathUtil.pow2(outerRadius) / 2.0;
-
- // body tube area
- final double bodyTubeArea = Math.PI * MathUtil.pow2(bodyRadius);
-
- // area of an interstice
- intersticeArea = (tubeDiskArea - tubeOuterArea - bodyTubeArea) / tubeCount;
// Precompute most of CNa. Equation comes from Ribner, "The ring airfoil in nonaxial
// flow", Journal of the Aeronautical Sciences 14(9) pp 529-530 (1947) equation (5).
@@ -246,10 +264,8 @@ public class TubeFinSetCalc extends TubeCalc {
@Override
public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings) {
- warnings.addAll(geometryWarnings);
+ final double frictionCD = componentCf * wettedArea / conditions.getRefArea();
- final double frictionCD = componentCf * wettedArea / conditions.getRefArea();
-
return frictionCD;
}
@@ -258,18 +274,10 @@ public class TubeFinSetCalc extends TubeCalc {
double stagnationCD, double baseCD, WarningSet warnings) {
warnings.addAll(geometryWarnings);
+
final double cd = super.calculatePressureCD(conditions, stagnationCD, baseCD, warnings) +
- (stagnationCD + baseCD) * intersticeArea / conditions.getRefArea();
-
+ (stagnationCD + baseCD) * intersticeArea / conditions.getRefArea();
+
return cd;
- }
-
- private static int calculateInterferenceFinCount(TubeFinSet component) {
- RocketComponent parent = component.getParent();
- if (parent == null) {
- throw new IllegalStateException("fin set without parent component");
- }
-
- return 3 * component.getFinCount();
}
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
index 5b737dae6..e8215e2c9 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java
@@ -550,4 +550,19 @@ public class BodyTube extends SymmetricComponent implements BoxBounded, MotorMou
// The motor config also has listeners, so clear them as well
getDefaultMotorConfig().clearConfigListeners();
}
+
+ /**
+ * The first time we add a TubeFinSet to the component tree, inherit the tube thickness from
+ * the parent body tube
+ */
+ @Override
+ public final void addChild(RocketComponent component, int index, boolean trackStage) {
+ super.addChild(component, index, trackStage);
+ if (component instanceof TubeFinSet) {
+ TubeFinSet finset = (TubeFinSet) component;
+ if (Double.isNaN(finset.getThickness())) {
+ finset.setThickness(getThickness());
+ }
+ }
+ }
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/EllipticalFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/EllipticalFinSet.java
index cc4d54455..400f68a57 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/EllipticalFinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/EllipticalFinSet.java
@@ -36,11 +36,18 @@ public class EllipticalFinSet extends FinSet {
@Override
public Coordinate[] getFinPoints() {
double len = MathUtil.max(length, 0.0001);
- Coordinate[] points = new Coordinate[POINTS];
+ Coordinate[] finPoints = new Coordinate[POINTS];
for (int i = 0; i < POINTS; i++) {
- points[i] = new Coordinate(POINT_X[i] * len, POINT_Y[i] * height);
+ finPoints[i] = new Coordinate(POINT_X[i] * len, POINT_Y[i] * height);
}
- return points;
+
+ // Set the start and end fin points the same as the root points (necessary for canted fins)
+ final Coordinate[] rootPoints = getRootPoints();
+ if (rootPoints.length > 1) {
+ finPoints[0] = finPoints[0].setX(rootPoints[0].x).setY(rootPoints[0].y);
+ finPoints[finPoints.length - 1] = finPoints[finPoints.length - 1].setX(rootPoints[rootPoints.length - 1].x).setY(rootPoints[rootPoints.length - 1].y);
+ }
+ return finPoints;
}
@Override
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
index ed675b502..227f9036a 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java
@@ -1025,14 +1025,14 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
*/
public Coordinate[] getRootPoints(final int maximumBodyDivisionCount) {
- if( null == parent){
+ if (parent == null) {
return new Coordinate[]{Coordinate.ZERO};
}
final Coordinate finLead = getFinFront();
final double xFinEnd = finLead.x + getLength();
- return getMountPoints( finLead.x, xFinEnd, -finLead.x, -finLead.y, maximumBodyDivisionCount);
+ return getMountPoints(finLead.x, xFinEnd, -finLead.x, -finLead.y, maximumBodyDivisionCount);
}
/**
@@ -1075,11 +1075,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
// for a simple body, one increment is perfectly accurate.
int divisionCount = 1;
- final SymmetricComponent body = (SymmetricComponent) getParent();
+ final SymmetricComponent parent = (SymmetricComponent) getParent();
final double intervalLength = xEnd - xStart;
// for anything more complicated, increase the count:
- if ((body instanceof Transition) && (((Transition)body).getShapeType() != Shape.CONICAL)) {
+ if ((!MathUtil.equals(getCantAngle(), 0)) || (parent instanceof Transition) && (((Transition)parent).getShapeType() != Shape.CONICAL)) {
// the maximum precision to enforce when calculating the areas of fins (especially on curved parent bodies)
final double xWidth = 0.0025; // width (in meters) of each individual iteration
divisionCount = (int) Math.ceil(intervalLength / xWidth);
@@ -1093,13 +1093,18 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
double xIncrement = intervalLength / divisionCount;
// Create the points: step through the radius of the parent
- double xCur = xStart;
+ double xCurr = xStart;
List points = new ArrayList<>();
for (int index = 0; index < divisionCount+1; index++) {
- double yCur = body.getRadius(xCur);
- points.add(new Coordinate(xCur, yCur));
+ double yCurr = parent.getRadius(xCurr);
- xCur += xIncrement;
+ // Account for the fin cant angle
+ final double dy = getFinCantYOffset(xStart, xEnd, xCurr);
+ yCurr += dy;
+
+ points.add(new Coordinate(xCurr, yCurr));
+
+ xCurr += xIncrement;
}
/*
@@ -1107,11 +1112,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
then we need to add an extra root point at the front of the parent. Same goes for the last point, but vice versa.
This ensures that fins are drawn correctly on transitions and nose cones (see GitHub issue #1021 for more info).
*/
- // Front fin point is outside the parent's bounds and last point is still within the parent's bounds
+ // Front fin point is outside the parent's bounds and last point is beyond the parent's fore end
if (xStart < 0 && xEnd > 0) {
points.add(1, new Coordinate(0, points.get(0).y));
}
- // End fin point is outside the parent's bounds and first point is still within the parent's bounds
+ // End fin point is beyond the parent's aft and first point is still before the parent's aft end
if (xEnd > parent.length && xStart < parent.length) {
final double x = parent.length;
final double y = points.get(points.size() - 1).y;
@@ -1122,8 +1127,8 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
// correct last point, if beyond a rounding error from body's end.
final int lastIndex = rootPoints.length - 1;
- if (Math.abs(rootPoints[lastIndex].x - body.getLength()) < MathUtil.EPSILON) {
- rootPoints[lastIndex] = rootPoints[lastIndex].setX(body.getLength()).setY(body.getAftRadius());
+ if (Math.abs(rootPoints[lastIndex].x - parent.getLength()) < MathUtil.EPSILON) {
+ rootPoints[lastIndex] = rootPoints[lastIndex].setX(parent.getLength());
}
// translate the points if needed
@@ -1138,6 +1143,51 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
return getMountPoints(xStart, xEnd, xOffset, yOffset, MAX_ROOT_DIVISIONS);
}
+ /**
+ * Returns a y offset that should be applied to the fin root point at the given x position to account for the fin cant.
+ * @param xStart The x position of the fin root point at the front of the fin.
+ * @param xEnd The x position of the fin root point at the back of the fin.
+ * @param xCurr The x position of the fin root point to calculate the y offset for.
+ * @return The y offset to apply to the fin root point at the given x position.
+ */
+ private double getFinCantYOffset(final double xStart, final double xEnd, double xCurr) {
+ final SymmetricComponent parent = (SymmetricComponent) getParent();
+ final double cantAngle = getCantAngle();
+
+ if (MathUtil.equals(cantAngle, 0) || (xStart > parent.length && xEnd > parent.length) || (xStart < 0 && xEnd < 0)) {
+ return 0;
+ }
+
+ // Limit the x position to the parent's bounds
+ double x = Math.max(xCurr, 0);
+ x = Math.min(x, parent.getLength());
+
+ // Determine the center of rotation
+ final double xCenter = (xStart + xEnd) / 2;
+
+ // Calculate the new x position after rotation
+ final double dx = x - xCenter; // Distance to the center of rotation
+ final double xCurr_rot = xCenter + dx * Math.abs(Math.cos(cantAngle)); // X coordinate after rotation
+
+ // Extend the root of the fin to touch the surface of the parent
+ final double radius_rot = parent.getRadius(xCurr_rot);
+ final double dz = Math.abs(Math.sin(cantAngle)) * dx;
+
+ final double dy;
+ if (dz >= radius_rot) {
+ dy = 0;
+ } else {
+ /*
+ Simplification of r^2 = (r-dy)^2 + dz^2, given that dz < r. (to derive this, draw
+ the cross-section of the body, which is just a circle, with a tangent line starting on the top of the circle
+ and reaching a distance dz. Use some Pythagorean theorem and bam, you got this equation.)
+ */
+ dy = radius_rot - Math.sqrt(Math.pow(radius_rot, 2) - Math.pow(dz, 2));
+ }
+
+ return -dy;
+ }
+
/**
* Return a list of coordinates defining the geometry of a single fin, including the parent's body points .
*/
diff --git a/core/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
index 99d901e93..169377c17 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java
@@ -392,7 +392,16 @@ public class FreeformFinSet extends FinSet {
@Override
public Coordinate[] getFinPoints() {
- return points.toArray(new Coordinate[0]);
+ Coordinate[] finPoints = points.toArray(new Coordinate[0]);
+
+ // Set the start and end fin points the same as the root points (necessary for canted fins)
+ final Coordinate[] rootPoints = getRootPoints();
+ if (rootPoints.length > 1) {
+ finPoints[0] = finPoints[0].setX(rootPoints[0].x).setY(rootPoints[0].y);
+ finPoints[finPoints.length - 1] = finPoints[finPoints.length - 1].setX(rootPoints[rootPoints.length - 1].x).setY(rootPoints[rootPoints.length - 1].y);
+ }
+
+ return finPoints;
}
@Override
diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java
index b4a4b91e2..cee08ffee 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java
@@ -7,8 +7,16 @@ import java.util.EventObject;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
+import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
+import net.sf.openrocket.aerodynamics.AerodynamicForces;
+import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
+import net.sf.openrocket.aerodynamics.FlightConditions;
+import net.sf.openrocket.logging.WarningSet;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.startup.Preferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -563,6 +571,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
public final double getOverrideMass() {
mutex.verify();
+ if (!isMassOverridden()) {
+ overrideMass = getComponentMass();
+ }
return overrideMass;
}
@@ -613,6 +624,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
checkState();
massOverridden = o;
+
+ // If mass not overridden, set override mass to the component mass
+ if (!massOverridden) {
+ overrideMass = getComponentMass();
+ }
+
updateChildrenMassOverriddenBy();
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
@@ -628,6 +645,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
public final Coordinate getOverrideCG() {
mutex.verify();
+ if (!isCGOverridden()) {
+ overrideCGX = getComponentCG().x;
+ }
return getComponentCG().setX(overrideCGX);
}
@@ -638,6 +658,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
public final double getOverrideCGX() {
mutex.verify();
+ if (!isCGOverridden()) {
+ overrideCGX = getComponentCG().x;
+ }
return overrideCGX;
}
@@ -688,10 +711,53 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
checkState();
cgOverridden = o;
+
+ // If CG not overridden, set override CG to the component CG
+ if (!cgOverridden) {
+ overrideCGX = getComponentCG().x;
+ }
+
updateChildrenCGOverriddenBy();
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
}
+ /**
+ * Calculates and returns the CD of the component.
+ * TODO: LOW: should this value be cached instead of recalculated every time?
+ * @param AOA angle of attack to use in the calculations (in radians)
+ * @param theta wind direction to use in the calculations (in radians)
+ * @param mach mach number to use in the calculations
+ * @param rollRate roll rate to use in the calculations (in radians per second)
+ * @return the CD of the component
+ */
+ public double getComponentCD(double AOA, double theta, double mach, double rollRate) {
+ Rocket rocket;
+ try {
+ rocket = getRocket();
+ } catch (IllegalStateException e) {
+ // This can happen due to a race condition when a loadFrom() action is performed of the rocket (after
+ // an undo operation) but the rocket is not yet fully loaded (the sustainer does not yet have the rocket as
+ // its parent => getRocket() will not return the rocket, but the sustainer). In that case, just return 0 and
+ // hope that a future call of this method will succeed.
+ return 0;
+ }
+ final FlightConfiguration configuration = rocket.getSelectedConfiguration();
+ FlightConditions conditions = new FlightConditions(configuration);
+ WarningSet warnings = new WarningSet();
+ AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator();
+
+ conditions.setAOA(AOA);
+ conditions.setTheta(theta);
+ conditions.setMach(mach);
+ conditions.setRollRate(rollRate);
+
+ Map aeroData = aerodynamicCalculator.getForceAnalysis(configuration, conditions, warnings);
+ AerodynamicForces forces = aeroData.get(this);
+ if (forces != null) {
+ return forces.getCD();
+ }
+ return 0;
+ }
/** Return the current override CD. The CD is not necessarily overridden.
*
@@ -699,6 +765,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
public final double getOverrideCD() {
mutex.verify();
+ if (!isCDOverridden()) {
+ Preferences preferences = Application.getPreferences();
+ overrideCD = getComponentCD(0, 0, preferences.getDefaultMach(), 0);
+ }
return overrideCD;
}
@@ -750,7 +820,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
listener.setCDOverridden(o);
}
- if(cdOverridden == o) {
+ if (cdOverridden == o) {
return;
}
checkState();
@@ -764,6 +834,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
if (isSubcomponentsOverriddenCD()) {
overrideSubcomponentsCD(o);
}
+
+ if (!cdOverridden) {
+ Preferences preferences = Application.getPreferences();
+ overrideCD = getComponentCD(0, 0, preferences.getDefaultMach(), 0);
+ }
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
@@ -2614,7 +2689,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
protected List copyFrom(RocketComponent src) {
checkState();
- List toInvalidate = new ArrayList();
+ List toInvalidate = new ArrayList<>();
if (this.parent != null) {
throw new UnsupportedOperationException("copyFrom called for non-root component, parent=" +
diff --git a/core/src/net/sf/openrocket/rocketcomponent/TrapezoidFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/TrapezoidFinSet.java
index afb7ee2d4..d7f63f434 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/TrapezoidFinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/TrapezoidFinSet.java
@@ -193,16 +193,25 @@ public class TrapezoidFinSet extends FinSet {
*/
@Override
public Coordinate[] getFinPoints() {
- List list = new ArrayList(4);
-
- list.add(Coordinate.NUL);
- list.add(new Coordinate(sweep, height));
+ List points = new ArrayList<>(4);
+
+ points.add(Coordinate.NUL);
+ points.add(new Coordinate(sweep, height));
if (tipChord > 0.0001) {
- list.add(new Coordinate(sweep + tipChord, height));
+ points.add(new Coordinate(sweep + tipChord, height));
+ }
+ points.add(new Coordinate(MathUtil.max(length, 0.0001), 0));
+
+ Coordinate[] finPoints = points.toArray(new Coordinate[0]);
+
+ // Set the start and end fin points the same as the root points (necessary for canted fins)
+ final Coordinate[] rootPoints = getRootPoints();
+ if (rootPoints.length > 1) {
+ finPoints[0] = finPoints[0].setX(rootPoints[0].x).setY(rootPoints[0].y);
+ finPoints[finPoints.length - 1] = finPoints[finPoints.length - 1].setX(rootPoints[rootPoints.length - 1].x).setY(rootPoints[rootPoints.length - 1].y);
}
- list.add(new Coordinate(MathUtil.max(length, 0.0001), 0));
- return list.toArray(new Coordinate[list.size()]);
+ return finPoints;
}
/**
diff --git a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java
index b5823989c..86e97e472 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java
@@ -24,7 +24,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
private boolean autoRadius = true; // Radius chosen automatically based on parent component
private double outerRadius = DEFAULT_RADIUS;
- protected double thickness = 0.002;
+ protected double thickness = Double.NaN;
private AngleMethod angleMethod = AngleMethod.FIXED;
protected RadiusMethod radiusMethod = RadiusMethod.RELATIVE;
@@ -49,7 +49,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
/**
- * New FinSet with given number of fins and given base rotation angle.
+ * New TubeFinSet with default values
* Sets the component relative position to POSITION_RELATIVE_BOTTOM,
* i.e. fins are positioned at the bottom of the parent component.
*/
@@ -146,6 +146,7 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
* Sets whether the radius is selected automatically or not.
*/
public void setOuterRadiusAutomatic(boolean auto) {
+
for (RocketComponent listener : configListeners) {
if (listener instanceof TubeFinSet) {
((TubeFinSet) listener).setOuterRadiusAutomatic(auto);
@@ -195,8 +196,9 @@ public class TubeFinSet extends Tube implements AxialPositionable, BoxBounded, R
if ((this.thickness == thickness))
return;
+
this.thickness = MathUtil.clamp(thickness, 0, getOuterRadius());
- fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
+ fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
clearPreset();
}
diff --git a/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java
index a5ced6bbb..20949593f 100644
--- a/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java
+++ b/core/test/net/sf/openrocket/rocketcomponent/FreeformFinSetTest.java
@@ -248,6 +248,141 @@ public class FreeformFinSetTest extends BaseTestCase {
}
+ @Test
+ public void testGenerateTrapezoidalPointsWithCant() {
+ final Rocket rkt = createTemplateRocket();
+ final Transition tailCone = (Transition) rkt.getChild(0).getChild(2);
+ final FreeformFinSet fins = createFinOnConicalTransition(tailCone);
+ fins.setCantAngle(Math.toRadians(15));
+
+ Coordinate[] actPoints = fins.getFinPoints();
+ Coordinate[] rootPoints = fins.getRootPoints();
+
+ final Coordinate[] expPoints = new Coordinate[] {
+ new Coordinate(0, -0.001683625, 0),
+ new Coordinate(0.4, 0.2, 0),
+ new Coordinate(0.4, -0.202224401, 0)
+ };
+
+ final Coordinate[] expRootPoints = new Coordinate[]{
+ new Coordinate(0, -0.001683625, 0),
+ new Coordinate(0.004, -0.003620824, 0),
+ new Coordinate(0.008, -0.005559077, 0),
+ new Coordinate(0.012, -0.00749839, 0),
+ new Coordinate(0.016, -0.009438771, 0),
+ new Coordinate(0.02, -0.011380227, 0),
+ new Coordinate(0.024, -0.013322767, 0),
+ new Coordinate(0.028, -0.015266398, 0),
+ new Coordinate(0.032, -0.017211128, 0),
+ new Coordinate(0.036, -0.019156966, 0),
+ new Coordinate(0.04, -0.021103918, 0),
+ new Coordinate(0.044, -0.023051993, 0),
+ new Coordinate(0.048, -0.0250012, 0),
+ new Coordinate(0.052, -0.026951546, 0),
+ new Coordinate(0.056, -0.028903041, 0),
+ new Coordinate(0.06, -0.030855692, 0),
+ new Coordinate(0.064, -0.032809508, 0),
+ new Coordinate(0.068, -0.034764497, 0),
+ new Coordinate(0.072, -0.036720669, 0),
+ new Coordinate(0.076, -0.038678032, 0),
+ new Coordinate(0.08, -0.040636596, 0),
+ new Coordinate(0.084, -0.042596368, 0),
+ new Coordinate(0.088, -0.044557359, 0),
+ new Coordinate(0.092, -0.046519577, 0),
+ new Coordinate(0.096, -0.048483032, 0),
+ new Coordinate(0.1, -0.050447733, 0),
+ new Coordinate(0.104, -0.052413689, 0),
+ new Coordinate(0.108, -0.054380911, 0),
+ new Coordinate(0.112, -0.056349408, 0),
+ new Coordinate(0.116, -0.05831919, 0),
+ new Coordinate(0.12, -0.060290266, 0),
+ new Coordinate(0.124, -0.062262648, 0),
+ new Coordinate(0.128, -0.064236344, 0),
+ new Coordinate(0.132, -0.066211365, 0),
+ new Coordinate(0.136, -0.068187722, 0),
+ new Coordinate(0.14, -0.070165425, 0),
+ new Coordinate(0.144, -0.072144484, 0),
+ new Coordinate(0.148, -0.074124911, 0),
+ new Coordinate(0.152, -0.076106716, 0),
+ new Coordinate(0.156, -0.07808991, 0),
+ new Coordinate(0.16, -0.080074505, 0),
+ new Coordinate(0.164, -0.082060511, 0),
+ new Coordinate(0.168, -0.08404794, 0),
+ new Coordinate(0.172, -0.086036803, 0),
+ new Coordinate(0.176, -0.088027112, 0),
+ new Coordinate(0.18, -0.090018879, 0),
+ new Coordinate(0.184, -0.092012115, 0),
+ new Coordinate(0.188, -0.094006834, 0),
+ new Coordinate(0.192, -0.096003045, 0),
+ new Coordinate(0.196, -0.098000763, 0),
+ new Coordinate(0.2, -0.1, 0),
+ new Coordinate(0.204, -0.102000768, 0),
+ new Coordinate(0.208, -0.104003079, 0),
+ new Coordinate(0.212, -0.106006948, 0),
+ new Coordinate(0.216, -0.108012386, 0),
+ new Coordinate(0.22, -0.110019407, 0),
+ new Coordinate(0.224, -0.112028025, 0),
+ new Coordinate(0.228, -0.114038253, 0),
+ new Coordinate(0.232, -0.116050104, 0),
+ new Coordinate(0.236, -0.118063594, 0),
+ new Coordinate(0.24, -0.120078734, 0),
+ new Coordinate(0.244, -0.122095541, 0),
+ new Coordinate(0.248, -0.124114028, 0),
+ new Coordinate(0.252, -0.126134209, 0),
+ new Coordinate(0.256, -0.1281561, 0),
+ new Coordinate(0.26, -0.130179716, 0),
+ new Coordinate(0.264, -0.132205071, 0),
+ new Coordinate(0.268, -0.134232181, 0),
+ new Coordinate(0.272, -0.136261062, 0),
+ new Coordinate(0.276, -0.138291728, 0),
+ new Coordinate(0.28, -0.140324197, 0),
+ new Coordinate(0.284, -0.142358484, 0),
+ new Coordinate(0.288, -0.144394605, 0),
+ new Coordinate(0.292, -0.146432578, 0),
+ new Coordinate(0.296, -0.148472418, 0),
+ new Coordinate(0.3, -0.150514143, 0),
+ new Coordinate(0.304, -0.152557769, 0),
+ new Coordinate(0.308, -0.154603316, 0),
+ new Coordinate(0.312, -0.156650799, 0),
+ new Coordinate(0.316, -0.158700236, 0),
+ new Coordinate(0.32, -0.160751647, 0),
+ new Coordinate(0.324, -0.16280505, 0),
+ new Coordinate(0.328, -0.164860462, 0),
+ new Coordinate(0.332, -0.166917903, 0),
+ new Coordinate(0.336, -0.168977392, 0),
+ new Coordinate(0.34, -0.171038948, 0),
+ new Coordinate(0.344, -0.173102591, 0),
+ new Coordinate(0.348, -0.175168341, 0),
+ new Coordinate(0.352, -0.177236218, 0),
+ new Coordinate(0.356, -0.179306243, 0),
+ new Coordinate(0.36, -0.181378435, 0),
+ new Coordinate(0.364, -0.183452818, 0),
+ new Coordinate(0.368, -0.18552941, 0),
+ new Coordinate(0.372, -0.187608235, 0),
+ new Coordinate(0.376, -0.189689315, 0),
+ new Coordinate(0.38, -0.191772671, 0),
+ new Coordinate(0.384, -0.193858326, 0),
+ new Coordinate(0.388, -0.195946303, 0),
+ new Coordinate(0.392, -0.198036625, 0),
+ new Coordinate(0.396, -0.200129317, 0),
+ new Coordinate(0.4, -0.202224401, 0)
+ };
+
+
+ assertEquals("Canted fin number of points doesn't match! ", expPoints.length, actPoints.length);
+ assertEquals("Canted root number of points doesn't match! ", expRootPoints.length, rootPoints.length);
+ for (int i = 0; i < expPoints.length; i++) {
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].x, actPoints[i].x, EPSILON);
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].y, actPoints[i].y, EPSILON);
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].z, actPoints[i].z, EPSILON);
+ }
+ for (int i = 0; i < expRootPoints.length; i++) {
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].x, rootPoints[i].x, EPSILON);
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].y, rootPoints[i].y, EPSILON);
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].z, rootPoints[i].z, EPSILON);
+ }
+ }
+
@Test
public void testFreeformCMComputation_trapezoidOnTube() {
final Rocket rkt = createTemplateRocket();
diff --git a/core/test/net/sf/openrocket/rocketcomponent/TrapezoidFinSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/TrapezoidFinSetTest.java
index d047b2eff..d60d97d61 100644
--- a/core/test/net/sf/openrocket/rocketcomponent/TrapezoidFinSetTest.java
+++ b/core/test/net/sf/openrocket/rocketcomponent/TrapezoidFinSetTest.java
@@ -1,6 +1,7 @@
package net.sf.openrocket.rocketcomponent;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertArrayEquals;
import org.junit.Test;
@@ -111,6 +112,71 @@ public class TrapezoidFinSetTest extends BaseTestCase {
}
}
+ @Test
+ public void testGenerateTrapezoidalPointsWithCant() {
+ final Rocket rkt = createSimpleTrapezoidalFin();
+ FinSet fins = (FinSet) rkt.getChild(0).getChild(0).getChild(0);
+ fins.setCantAngle(Math.toRadians(15));
+
+ // Fin length = 0.05
+ // Tab Length = 0.01
+ // +--+
+ // / \
+ // / \
+ // +---+--------+---+
+ //
+ Coordinate[] actPoints = fins.getFinPoints();
+ Coordinate[] rootPoints = fins.getRootPoints();
+
+ final Coordinate[] expPoints = new Coordinate[] {
+ new Coordinate(0.00, -0.00030189855, 0.00),
+ new Coordinate(0.02, 0.05, 0.00),
+ new Coordinate(0.04, 0.05, 0.00),
+ new Coordinate(0.06, -0.00030189855, 0.00)
+ };
+
+ final Coordinate[] expRootPoints = new Coordinate[] {
+ new Coordinate(0.0000, -0.000301899, 0.0000),
+ new Coordinate(0.0025, -0.000253617, 0.0000),
+ new Coordinate(0.0050, -0.000209555, 0.0000),
+ new Coordinate(0.0075, -0.000169706, 0.0000),
+ new Coordinate(0.0100, -0.000134064, 0.0000),
+ new Coordinate(0.0125, -0.000102627, 0.0000),
+ new Coordinate(0.0150, -0.000075389, 0.0000),
+ new Coordinate(0.0175, -0.000052348, 0.0000),
+ new Coordinate(0.0200, -0.000033499, 0.0000),
+ new Coordinate(0.0225, -0.000018842, 0.0000),
+ new Coordinate(0.0250, -0.000008374, 0.0000),
+ new Coordinate(0.0275, -0.000002093, 0.0000),
+ new Coordinate(0.0300, 0.0000, 0.0000),
+ new Coordinate(0.0325, -0.000002093, 0.0000),
+ new Coordinate(0.0350, -0.000008374, 0.0000),
+ new Coordinate(0.0375, -0.000018842, 0.0000),
+ new Coordinate(0.0400, -0.000033499, 0.0000),
+ new Coordinate(0.0425, -0.000052348, 0.0000),
+ new Coordinate(0.0450, -0.000075389, 0.0000),
+ new Coordinate(0.0475, -0.000102627, 0.0000),
+ new Coordinate(0.0500, -0.000134064, 0.0000),
+ new Coordinate(0.0525, -0.000169706, 0.0000),
+ new Coordinate(0.0550, -0.000209555, 0.0000),
+ new Coordinate(0.0575, -0.000253617, 0.0000),
+ new Coordinate(0.0600, -0.000301899, 0.0000)
+ };
+
+ assertEquals("Canted fin number of points doesn't match! ", expPoints.length, actPoints.length);
+ assertEquals("Canted root number of points doesn't match! ", expRootPoints.length, rootPoints.length);
+ for (int i = 0; i < expPoints.length; i++) {
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].x, actPoints[i].x, EPSILON);
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].y, actPoints[i].y, EPSILON);
+ assertEquals("Canted fin point [" + i + "] doesn't match! ", expPoints[i].z, actPoints[i].z, EPSILON);
+ }
+ for (int i = 0; i < expRootPoints.length; i++) {
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].x, rootPoints[i].x, EPSILON);
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].y, rootPoints[i].y, EPSILON);
+ assertEquals("Canted root point [" + i + "] doesn't match! ", expRootPoints[i].z, rootPoints[i].z, EPSILON);
+ }
+ }
+
@Test
public void testCGCalculation_simpleSquareFin() {
final Rocket rkt = createSimpleTrapezoidalFin();
diff --git a/swing/resources-src/datafiles/components-openrocket/Estes-legacy.orc b/swing/resources-src/datafiles/components-openrocket/Estes-legacy.orc
index f5f987563..bafec2db9 100644
--- a/swing/resources-src/datafiles/components-openrocket/Estes-legacy.orc
+++ b/swing/resources-src/datafiles/components-openrocket/Estes-legacy.orc
@@ -3,802 +3,802 @@
0.1
-
+
0.0
BULK
-
+
.060 Carbon Fiber
1400.0
BULK
-
+
.125 in Fiberglass/Honeycomb
461.33174592000006
BULK
-
+
.25 in Fiberglass/Honeycomb
235.47141198
BULK
-
+
1 in. Flat Elastic
0.015514109144
LINE
-
+
1 in. Tubular Nylon
0.044644918400000004
LINE
-
+
1.1 Ounce Rip Stop Nylon
0.05983056264534001
BULK
-
+
1.1 oz. Rip Stop Nylon
0.037350571446
SURFACE
-
+
1.3 oz. Ripstop Nylon (SkyAngle)
0.04407367430628
SURFACE
-
+
1.7 oz. Ripstop Nylon
0.057638523018492004
SURFACE
-
+
1.9 oz. Ripstop Nylon
0.06441875028216
SURFACE
-
+
1.9 oz. Ripstop Nylon (PML)
0.08788369752
SURFACE
-
+
1.9 oz. Ripstop Nylon (SkyAngle)
0.06441875028216
SURFACE
-
+
1/16 in. Aircraft Plywood
361.3765253
BULK
-
+
1/16 in. Braided Nylon
0.00102
LINE
-
+
1/16 in. Round Elastic
0.00183
LINE
-
+
1/2 in. Flat Elastic
0.003125144288
LINE
-
+
1/2 in. Tubular Kevlar
0.044644918400000004
LINE
-
+
1/2 in. Tubular Nylon
0.060870160920000006
BULK
-
+
1/32 in. Kevlar
6.590000000000001E-4
LINE
-
+
1/4 Aircraft Plywood
344.269
BULK
-
+
1/4 In. Flat Elastic
0.00402
LINE
-
+
1/4 in. Aircraft Plywood
344.2688068
BULK
-
+
1/4 in. Braided Nylon
0.06535533067200001
BULK
-
+
1/4 in. Tubular Kevlar
0.022322459200000002
LINE
-
+
1/8 Aircraft Plywood
337.541
BULK
-
+
1/8 in Birch Plywood (Revell)
640.7385360000001
BULK
-
+
1/8 in. Aircraft Plywood
672.7754628
BULK
-
+
1/8 in. Braided Nylon
0.03267766533600001
BULK
-
+
1/8 in. Flat Elastic
0.00205
LINE
-
+
1/8 in. Flat Rubber
0.00231
LINE
-
+
1/8 in. Tubular Kevlar
0.011161229600000001
LINE
-
+
100 lb Kevlar (Apogee 29505)
0.006359329969800001
BULK
-
+
100 lb. Kevlar
0.032837849970000006
BULK
-
+
100lb Kevlar (Apogee 29505)
0.006359329969800001
BULK
-
+
1500 lb. Kevlar
0.0959105496075
BULK
-
+
1500lb Kevlar (Apogee 29507)
0.0959105496075
BULK
-
+
260 lb. Elastic
0.0
BULK
-
+
3/16 Aircraft Plywood
344.2688068
BULK
-
+
3/16 in. Aircraft Plywood
344.2688068
BULK
-
+
3/4 in. Flat Elastic
0.01227735256
LINE
-
+
3/8 in. Flat Elastic
0.060870160920000006
BULK
-
+
3/8 in. Tubular Nylon
0.018602086537432
LINE
-
+
3/8 in. Tubular Nylon (SkyAngle)
0.018602086537432
LINE
-
+
3/8 inch Flat Elastic
0.060870160920000006
BULK
-
+
3/8 tubular nylon (SkyAngle)
2.9797705801314
BULK
-
+
30 Lb. Kevlar
1.78E-4
LINE
-
+
300 lb. Kevlar
0.01807843779324
BULK
-
+
300 lb. Kevlar (Apogee 29506)
0.01807843779324
BULK
-
+
300lb Kevlar (Apogee 29506)
0.01807843779324
BULK
-
+
4000 lb. nylon
0.0
BULK
-
+
5/64 in. Round Elastic
0.0024200000000000003
LINE
-
+
5/8 in. Tubular Nylon
0.022322459200000002
LINE
-
+
5/8 in. Tubular Nylon (SkyAngle)
0.022322459200000002
LINE
-
+
6000 lb. nylon
0.0
BULK
-
+
6oz & 2oz FG & Poster board
798.85
BULK
-
+
7/16 in. Flat Braided Kevlar
0.0502255332
LINE
-
+
70 Lb. Kevlar
3.3E-4
LINE
-
+
750 Lb. Kevlar
0.0030135319920000002
LINE
-
+
9/16 in. Tubular Nylon
0.0167418444
LINE
-
+
Acrylic (Cast)
1185.3662916
BULK
-
+
Aircraft plywood (Birch)
724.9956534840001
BULK
-
+
Aircraft plywood (LOC)
724.9956534840001
BULK
-
+
Aluminum
2698.9
BULK
-
+
Aluminum (Al)
2698.9
BULK
-
+
Aluminum 2024
2780.0
BULK
-
+
Aluminum 7075
2810.0
BULK
-
+
Ash
680.7846945000001
BULK
-
+
Balsa
128.1477072
BULK
-
+
Basswood
424.48928010000003
BULK
-
+
Beech
720.830853
BULK
-
+
Birch
680.7846945000001
BULK
-
+
Birch Plywood (Revell)
656.7569994
BULK
-
+
Blue Tube
1237.0
BULK
-
+
Blue Tube 2
1250.0
BULK
-
+
Brass
8553.8594556
BULK
-
+
Carbon Fiber
1400.0
BULK
-
+
Cardboard
688.7939262000001
BULK
-
+
Carpet String
3.2972000000000003E-4
LINE
-
+
Carpet String (Apogee 29500)
3.2972000000000003E-4
LINE
-
+
Cellulose Acetate Propionate
1199.7829086600002
BULK
-
+
Chalk (Fine)
1121.2924380000002
BULK
-
+
Composite Fin Material
634.3311506400001
BULK
-
+
Copper (cast)
8682.0071628
BULK
-
+
Copper (rolled)
8906.2656504
BULK
-
+
Cork (Solid)
240.27695100000003
BULK
-
+
Cottonwood
400.461585
BULK
-
+
Custom
0.0
BULK
-
+
Dyna-Wind Tubing
1210.0
BULK
-
+
Fiber
656.7569994
BULK
-
+
Fiberglass
1905.2360367960002
BULK
-
+
Fir (Douglas)
560.6462190000001
BULK
-
+
Fir (White)
400.461585
BULK
-
+
G10 (PML 0.062)
3.137448001464
SURFACE
-
+
G10 (PML 0.062)
0.07059977558916
BULK
-
+
G10 (PML 0.093)
5.022553313268
SURFACE
-
+
G10 (PML 0.125)
6.169435565904
SURFACE
-
+
G10 Fiberglass
2175.3073297200003
BULK
-
+
G10 Fiberglass (LOC)
1905.2360367960002
BULK
-
+
G10 Fiberglass Filament Wound
1934.0
BULK
-
+
G10 Fiberglass Filament Wound Tube
1820.0
BULK
-
+
G10 Phenolic
1905.2360367960002
BULK
-
+
G12 Fiberglass
0.0
BULK
-
+
Glassed Phenolic
1900.0
BULK
-
+
Gold (24 kt.)
19286.229933600003
BULK
-
+
Kevlar Thread (Apogee 29502)
8.858E-5
LINE
-
+
Kraft phenolic
943.4874942600001
BULK
-
+
Kraft phenolic (Glassed)
1153.329336
BULK
-
+
Lead (cast)
11341.072087200002
BULK
-
+
Lead (rolled)
11389.127477400001
BULK
-
+
Lead Shot
6727.75
BULK
-
+
Leather
945.0893406000001
BULK
-
+
Lexan
1218.0
BULK
-
+
Lite Plywood
352.40619480000004
BULK
-
+
Magna Phenolic
1100.0
BULK
-
+
Mail Tube Paper
800.0
BULK
-
+
Maple (Hard)
632.7293043000001
BULK
-
+
Mat Board 4-Ply
710.579
BULK
-
+
Mylar
1309.0
BULK
-
+
Nickel 200
8890.0
BULK
-
+
Nickel 400
8800.0
BULK
-
+
Nickel 600
8410.0
BULK
-
+
Nickel 625
8440.0
BULK
-
+
Nickel 718
8230.0
BULK
-
+
Nickel C276
8890.0
BULK
-
+
Nylon
1140.0
BULK
-
+
Oak (Brown)
720.830853
BULK
-
+
Oak (Red)
720.830853
BULK
-
+
Oak (White)
752.8677798000001
BULK
-
+
PVC
1300.6992280800002
BULK
-
+
Paper
608.7016092000001
BULK
-
+
Paper/2layers 8 oz. glass
1681.94
BULK
-
+
Pine (White Northern)
400.461585
BULK
-
+
Pine (White Western)
432.4985118000001
BULK
-
+
Plastic
920.0
BULK
-
+
Polycarbonate
1199.7829086600002
BULK
-
+
Polyethylene
920.0
BULK
-
+
Polyethylene LDPE
924.2653381800002
BULK
-
+
Polyethylene LDPE(0.051)
0.04713753224718001
SURFACE
-
+
Polystyrene PS
1049.2093527000002
BULK
-
+
Poplar (Yellow)
480.55390200000005
BULK
-
+
Quantum Tubing
1100.0
BULK
-
+
Rip stop nylon
0.06684999999999999
SURFACE
-
+
Rocketwood
529.089846102
BULK
-
+
Russian 1/8 in. Plywood
685.1
BULK
-
+
Silver
10460.056600200001
BULK
-
+
Spiral/Glassine
848.9785602000001
BULK
-
+
Spiral/Glassine-Thick
768.886
BULK
-
+
Spruce
448.51697520000005
BULK
-
+
Stainless steel 17-4PH
7600.0
BULK
-
+
Stainless steel 17-5PH
7800.0
BULK
-
+
Stainless steel 17-7PH
7800.0
BULK
-
+
Steel
7850.0
BULK
-
+
Steel 4130
7850.0
BULK
-
+
Steel 4340
7850.0
BULK
-
+
Sycamore
560.6462190000001
BULK
-
+
Titanium
4500.0
BULK
-
+
Urethane
847.0563445920002
BULK
-
+
Vulcanized Fiber
1250.0
BULK
-
+
lite ply
352.406186
BULK
diff --git a/swing/resources-src/datafiles/components-openrocket/LocPrecision-legacy.orc b/swing/resources-src/datafiles/components-openrocket/LocPrecision-legacy.orc
index ebfcdfbe6..bd15c1603 100644
--- a/swing/resources-src/datafiles/components-openrocket/LocPrecision-legacy.orc
+++ b/swing/resources-src/datafiles/components-openrocket/LocPrecision-legacy.orc
@@ -3,732 +3,732 @@
0.1
-
+
[material:.060 Carbon Fiber]
1400.0
BULK
-
+
[material:1 In. Flat Elastic]
0.015514109144
LINE
-
+
[material:1 in. tubular nylon]
0.044644918400000004
LINE
-
+
[material:1.1 Ounce Rip Stop Nylon]
0.037350571446
SURFACE
-
+
[material:1.3 oz. Ripstop Nylon (SkyAngle)]
0.04407367430628
SURFACE
-
+
[material:1.7 oz. Ripstop Nylon]
0.057638523018492004
SURFACE
-
+
[material:1.9 oz. Ripstop Nylon (PML)]
0.08788369752
SURFACE
-
+
[material:1.9 oz. Ripstop Nylon (SkyAngle)]
0.06441875028216
SURFACE
-
+
[material:1.9 oz. Ripstop Nylon]
0.06441875028216
SURFACE
-
+
[material:1/16 Aircraft Plywood]
361.3765253
BULK
-
+
[material:1/16 In. Braided Nylon]
0.00102
LINE
-
+
[material:1/16 In. Round Elastic]
0.00183
LINE
-
+
[material:1/16 in. Aircraft Plywood]
361.3765253
BULK
-
+
[material:1/2 In. Flat Elastic]
0.003125144288
LINE
-
+
[material:1/2 in. Tubular Nylon]
0.060870160920000006
BULK
-
+
[material:1/2 in. tubular kevlar]
0.044644918400000004
LINE
-
+
[material:1/32 In. Kevlar]
6.590000000000001E-4
LINE
-
+
[material:1/4 Aircraft Plywood]
344.2688068
BULK
-
+
[material:1/4 In. Flat Elastic]
0.00402
LINE
-
+
[material:1/4 in. Aircraft Plywood]
344.2688068
BULK
-
+
[material:1/4 in. tubular kevlar]
0.022322459200000002
LINE
-
+
[material:1/8 Aircraft Plywood]
337.5410523
BULK
-
+
[material:1/8 In. Braided Nylon]
0.03267766533600001
BULK
-
+
[material:1/8 In. Flat Elastic]
0.00205
LINE
-
+
[material:1/8 In. Flat Rubber]
0.00231
LINE
-
+
[material:1/8 in. Aircraft Plywood]
337.5410523
BULK
-
+
[material:1/8 in. Tubular Kevlar]
0.011161229600000001
LINE
-
+
[material:100 lb Kevlar (Apogee 29505)]
0.006359329969800001
BULK
-
+
[material:100lb Kevlar (Apogee 29505)]
3.9698E-4
LINE
-
+
[material:1500 lb Kevlar (Apogee 29507)]
0.0959105496075
BULK
-
+
[material:1500lb Kevlar (Apogee 29507)]
0.0059875
LINE
-
+
[material:260 lb. Elastic]
0.0
BULK
-
+
[material:3/16 Aircraft Plywood]
344.2688068
BULK
-
+
[material:3/16 in. Aircraft Plywood]
344.2688068
BULK
-
+
[material:3/4 In. Flat Elastic]
0.01227735256
LINE
-
+
[material:3/8 in. Flat Elastic]
0.0038
LINE
-
+
[material:3/8 in. Tubular Nylon (SkyAngle)]
0.18602086537432
LINE
-
+
[material:3/8 in. Tubular Nylon]
0.18602086537432
LINE
-
+
[material:3/8 inch Flat Elastic]
0.0038
LINE
-
+
[material:3/8 tubular nylon (SkyAngle)]
0.18602086537432
LINE
-
+
[material:30 Lb. Kevlar]
1.78E-4
LINE
-
+
[material:300 lb. Kevlar (Apogee 29506)]
0.01807843779324
BULK
-
+
[material:300lb Kevlar (Apogee 29506)]
0.001128609
LINE
-
+
[material:4000 lb. nylon]
0.0
BULK
-
+
[material:5/64 In. Round Elastic]
0.0024200000000000003
LINE
-
+
[material:5/8 Tubular nylon (SkyAngle)]
0.223224592
LINE
-
+
[material:5/8 in. Tubular Nylon (SkyAngle)]
0.223224592
LINE
-
+
[material:5/8 in. Tubular Nylon]
0.223224592
LINE
-
+
[material:6000 lb. nylon]
0.0
BULK
-
+
[material:6oz & 2oz FG & Poster board]
798.85
BULK
-
+
[material:7/16 in. Flat braided kevlar]
0.0502255332
LINE
-
+
[material:70 Lb. Kevlar]
3.3E-4
LINE
-
+
[material:9/16 In. Tubular Nylon]
0.0167418444
LINE
-
+
[material:Acrylic (Cast)]
1185.3662916
BULK
-
+
[material:Aircraft plywood (Birch)]
724.9956534840001
BULK
-
+
[material:Aircraft plywood (LOC)]
724.9956534840001
BULK
-
+
[material:Aluminum (Al)]
2698.9
BULK
-
+
[material:Aluminum 2024]
2780.0
BULK
-
+
[material:Aluminum 7075]
2810.0
BULK
-
+
[material:Ash]
680.7846945000001
BULK
-
+
[material:BadNoseMaterial]
128.147704
BULK
-
+
[material:Balsa]
128.1477072
BULK
-
+
[material:Basswood]
424.48928010000003
BULK
-
+
[material:Beech]
720.830853
BULK
-
+
[material:Birch]
680.7846945000001
BULK
-
+
[material:Blue Tube]
1237.0
BULK
-
+
[material:Brass]
8553.8594556
BULK
-
+
[material:Carbon Fiber]
1400.0
BULK
-
+
[material:Cardboard]
688.7939262000001
BULK
-
+
[material:Carpet String (Apogee 29500)]
3.2972000000000003E-4
LINE
-
+
[material:Cellulose Acetate Propionate]
1199.7829086600002
BULK
-
+
[material:Chalk (Fine)]
1121.2924380000002
BULK
-
+
[material:Copper (cast)]
8682.0071628
BULK
-
+
[material:Copper (rolled)]
8906.2656504
BULK
-
+
[material:Cork (Solid)]
240.27695100000003
BULK
-
+
[material:Cottonwood]
400.461585
BULK
-
+
[material:Epoxy]
1254.2456842200002
BULK
-
+
[material:Fiber]
656.7569994
BULK
-
+
[material:Fiberglass]
128.147704
BULK
-
+
[material:Fir (Douglas)]
560.6462190000001
BULK
-
+