Merge pull request #506 from teyrana/fix_498_neg_inertia
Fixes #498 - Refactor of FreeformFinSet[Test]
This commit is contained in:
commit
090caed29e
@ -439,17 +439,25 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
* 5. Return twice that since there is a fillet on each side of the fin.
|
||||
*/
|
||||
protected Coordinate calculateFilletVolumeCentroid() {
|
||||
if((null == this.parent) || (!SymmetricComponent.class.isAssignableFrom(this.parent.getClass()))){
|
||||
return Coordinate.ZERO;
|
||||
}
|
||||
Coordinate[] mountPoints = this.getRootPoints();
|
||||
if( null == mountPoints ){
|
||||
// if( null == mountPoints ){
|
||||
// return Coordinate.ZERO;
|
||||
// }
|
||||
|
||||
final SymmetricComponent sym = (SymmetricComponent) this.parent;
|
||||
|
||||
final Coordinate finLead = getFinFront();
|
||||
final double xFinEnd = finLead.x + getLength();
|
||||
final Coordinate[] rootPoints = getMountPoints( finLead.x, xFinEnd, -finLead.x, -finLead.y);
|
||||
if (0 == rootPoints.length) {
|
||||
return Coordinate.ZERO;
|
||||
}
|
||||
|
||||
final SymmetricComponent sym = (SymmetricComponent) this.parent;
|
||||
if (!SymmetricComponent.class.isInstance(this.parent)) {
|
||||
return Coordinate.ZERO;
|
||||
}
|
||||
|
||||
Coordinate filletVolumeCentroid = Coordinate.ZERO;
|
||||
|
||||
Coordinate prev = mountPoints[0];
|
||||
for (int index = 1; index < mountPoints.length; index++) {
|
||||
final Coordinate cur = mountPoints[index];
|
||||
@ -470,7 +478,7 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
|
||||
if (finCount == 1) {
|
||||
Transformation rotation = Transformation.rotate_x( getAngleOffset());
|
||||
return rotation.transform(filletVolumeCentroid);
|
||||
@ -496,10 +504,9 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
for( int index = 1; index < points.length; index++){
|
||||
Coordinate cur = points[index];
|
||||
|
||||
// calculate marginal area
|
||||
final double delta_x = (cur.x - prev.x);
|
||||
final double y_avg = (cur.y + prev.y)*0.5;
|
||||
|
||||
// calculate marginal area
|
||||
double area_increment = delta_x*y_avg;
|
||||
if( MathUtil.equals( 0, area_increment)){
|
||||
prev = cur;
|
||||
@ -534,20 +541,17 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
// relto: fin
|
||||
final double xTabFront_fin = getTabFrontEdge();
|
||||
final double xTabTrail_fin = getTabTrailingEdge();
|
||||
|
||||
final double xFinFront_body = this.getAxialFront();
|
||||
|
||||
final Coordinate finFront = getFinFront();
|
||||
final double xFinFront_body = finFront.x;
|
||||
final double xTabFront_body = xFinFront_body + xTabFront_fin;
|
||||
final double xTabTrail_body = xFinFront_body + xTabTrail_fin;
|
||||
|
||||
// always returns x coordinates relTo fin front:
|
||||
Coordinate[] upperCurve = getMountInterval( xTabFront_body, xTabTrail_body );
|
||||
// locate relative to fin/body centerline
|
||||
upperCurve = translatePoints( upperCurve, -xFinFront_body, 0.0);
|
||||
|
||||
Coordinate[] lowerCurve = translateToCenterline( getTabPoints());
|
||||
|
||||
// get body points, relTo fin front / centerline);
|
||||
final Coordinate[] upperCurve = getMountPoints( xTabFront_body, xTabTrail_body, -xFinFront_body, 0);
|
||||
final Coordinate[] lowerCurve = translateToCenterline( getTabPoints());
|
||||
final Coordinate[] tabPoints = combineCurves( upperCurve, lowerCurve);
|
||||
|
||||
|
||||
return calculateCurveIntegral( tabPoints );
|
||||
}
|
||||
|
||||
@ -559,27 +563,23 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the 2-dimensional area-centroid of a single fin.
|
||||
*
|
||||
* Located from the leading end of the fin root.
|
||||
* The coordinate contains an x,y coordinate of the centroid, relative to the parent-body-centerline
|
||||
* The weight contains the area of the fin.
|
||||
*
|
||||
* @return area centroid coordinates (weight is the area)
|
||||
*/
|
||||
|
||||
/*
|
||||
* The coordinate contains an x,y coordinate of the centroid, relative to the parent-body-centerline
|
||||
*/
|
||||
private Coordinate calculateSinglePlanformCentroid(){
|
||||
final Coordinate finFront = getFinFront();
|
||||
|
||||
final Coordinate[] upperCurve = getFinPoints();
|
||||
final Coordinate[] lowerCurve = getRootPoints();
|
||||
final Coordinate finLead = getFinFront();
|
||||
final double xFinTrail = finLead.x+getLength();
|
||||
|
||||
final Coordinate[] upperCurve = translatePoints(getFinPoints(), 0, finLead.y);
|
||||
final Coordinate[] lowerCurve = getMountPoints( finLead.x, xFinTrail, -finLead.x, 0);
|
||||
final Coordinate[] totalCurve = combineCurves( upperCurve, lowerCurve);
|
||||
|
||||
Coordinate planformCentroid = calculateCurveIntegral( totalCurve );
|
||||
|
||||
final Coordinate planformCentroid = calculateCurveIntegral( totalCurve );
|
||||
|
||||
// return as a position relative to fin-root
|
||||
return planformCentroid.add(0., finFront.y, 0);
|
||||
return planformCentroid;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -592,15 +592,15 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
* @return combined curve
|
||||
*/
|
||||
private Coordinate[] combineCurves( final Coordinate[] c1, final Coordinate[] c2){
|
||||
Coordinate[] combined = new Coordinate[ c1.length + c2.length - 1];
|
||||
Coordinate[] combined = new Coordinate[ c1.length + c2.length];
|
||||
|
||||
// copy the first array to the start of the return array...
|
||||
System.arraycopy(c1, 0, combined, 0, c1.length);
|
||||
|
||||
Coordinate[] revCurve = reverse( c2);
|
||||
int writeIndex = c1.length; // start directly after previous array
|
||||
int writeCount = revCurve.length - 1; // write all-but-first
|
||||
System.arraycopy(revCurve, 1, combined, writeIndex, writeCount);
|
||||
int writeCount = revCurve.length;
|
||||
System.arraycopy(revCurve, 0, combined, writeIndex, writeCount);
|
||||
|
||||
return combined;
|
||||
}
|
||||
@ -813,7 +813,12 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
// by default, assume a flat base
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a copied list of the given input, translated by the delta
|
||||
*
|
||||
* @return List of XY-coordinates.
|
||||
*/
|
||||
protected static Coordinate[] translatePoints( final Coordinate[] inp, final double x_delta , final double y_delta){
|
||||
Coordinate[] returnPoints = new Coordinate[inp.length];
|
||||
for( int index=0; index < inp.length; ++index){
|
||||
@ -823,8 +828,23 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
}
|
||||
return returnPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a copied list of the given input, translated by the delta
|
||||
*
|
||||
* @return List of XY-coordinates.
|
||||
*/
|
||||
protected static ArrayList<Coordinate> translatePoints( final ArrayList<Coordinate> inp, final Coordinate delta){
|
||||
final ArrayList<Coordinate> returnPoints = new ArrayList<>();
|
||||
returnPoints.ensureCapacity(inp.size());
|
||||
|
||||
for( Coordinate c: inp ){
|
||||
returnPoints.add(c.add(delta));
|
||||
}
|
||||
|
||||
return returnPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of X,Y coordinates defining the geometry of a single fin tab.
|
||||
* The origin is the leading root edge, and the tab height (or 'depth') is
|
||||
@ -1037,22 +1057,23 @@ 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
|
||||
*/
|
||||
public Coordinate[] getMountPoints() {
|
||||
if( null == parent){
|
||||
return null;
|
||||
}
|
||||
|
||||
return getMountInterval(0., parent.getLength());
|
||||
|
||||
return getMountPoints(0., parent.getLength(), 0,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* used to get body points for the profile design view
|
||||
*
|
||||
* @return points representing the fin-root points, relative to ( x: fin-front, y: fin-root-radius )
|
||||
* @return points representing the fin-root points, relative to ( x: fin-front, y: centerline ) i.e. relto: fin Component reference point
|
||||
*/
|
||||
public Coordinate[] getRootPoints(){
|
||||
if( null == parent){
|
||||
@ -1060,16 +1081,25 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
}
|
||||
|
||||
final Coordinate finLead = getFinFront();
|
||||
final double finTailX = finLead.x + getLength();
|
||||
final double xFinEnd = finLead.x + getLength();
|
||||
|
||||
final Coordinate[] bodyPoints = getMountInterval( finLead.x, finTailX);
|
||||
|
||||
return translatePoints(bodyPoints, -finLead.x, -finLead.y);
|
||||
return getMountPoints( finLead.x, xFinEnd, -finLead.x, -finLead.y);
|
||||
}
|
||||
|
||||
|
||||
private Coordinate[] getMountInterval( final double xStart, final double xEnd ) {
|
||||
// System.err.println(String.format(" .... >> mount interval/x: ( %g, %g)]", xStart, xEnd));
|
||||
/**
|
||||
* used to get calculate body profile points:
|
||||
*
|
||||
* @param xStart - xStart, in Mount-frame
|
||||
* @param xEnd - xEnd, in Mount-frame
|
||||
* @param xOffset - x-Offset to apply to returned points
|
||||
* @param yOffset - y-Offset to apply to returned points
|
||||
*
|
||||
* @return points representing the mount's points
|
||||
*/
|
||||
private Coordinate[] getMountPoints(final double xStart, final double xEnd, final double xOffset, final double yOffset) {
|
||||
if( null == parent){
|
||||
return new Coordinate[]{Coordinate.ZERO};
|
||||
}
|
||||
|
||||
// for a simple bodies, one increment is perfectly accurate.
|
||||
int divisionCount = 1;
|
||||
@ -1104,15 +1134,24 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
if( body.getLength()-0.000001 < points[lastIndex].x) {
|
||||
points[lastIndex] = points[lastIndex].setX(body.getLength()).setY(body.getAftRadius());
|
||||
}
|
||||
|
||||
|
||||
if( 0.0000001 < (Math.abs(xOffset) + Math.abs(yOffset))){
|
||||
points = translatePoints(points, xOffset, yOffset);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
// for debugging. You can safely delete this method
|
||||
public static String getPointDescr( final Coordinate[] points, final String name, final String indent){
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
buf.append(String.format("%s >> %s: %d points\n", indent, name, points.length));
|
||||
return getPointDescr(Arrays.asList(points), name, indent);
|
||||
}
|
||||
|
||||
// for debugging. You can safely delete this method
|
||||
public static String getPointDescr( final List<Coordinate> points, final String name, final String indent){
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
buf.append(String.format("%s >> %s: %d points\n", indent, name, points.size()));
|
||||
int index =0;
|
||||
for( Coordinate c : points ){
|
||||
buf.append( String.format( indent+" ....[%2d] (%6.4g, %6.4g)\n", index, c.x, c.y));
|
||||
@ -1128,8 +1167,8 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
||||
buf.append( getPointDescr( this.getFinPoints(), "Fin Points", ""));
|
||||
|
||||
if (null != parent) {
|
||||
buf.append( getPointDescr( this.getMountPoints(0, parent.getLength(), 0, 0), "Body Points", ""));
|
||||
buf.append( getPointDescr( this.getRootPoints(), "Root Points", ""));
|
||||
buf.append( getPointDescr( this.getMountPoints(), "Mount Points", ""));
|
||||
}
|
||||
|
||||
if( ! this.isTabTrivial() ) {
|
||||
|
@ -22,7 +22,7 @@ public class FreeformFinSet extends FinSet {
|
||||
// this class uses certain features of 'ArrayList' which are not implemented in other 'List' implementations.
|
||||
private ArrayList<Coordinate> points = new ArrayList<>();
|
||||
|
||||
private static final double SNAP_SMALLER_THAN = 1e-6;
|
||||
private static final double SNAP_SMALLER_THAN = 5e-3;
|
||||
private static final double IGNORE_SMALLER_THAN = 1e-12;
|
||||
|
||||
public FreeformFinSet() {
|
||||
@ -133,7 +133,7 @@ public class FreeformFinSet extends FinSet {
|
||||
ArrayList<Coordinate> copy = new ArrayList<>(this.points);
|
||||
|
||||
this.points.remove(index);
|
||||
if (!validate()) {
|
||||
if (intersects()) {
|
||||
// if error, rollback.
|
||||
this.points = copy;
|
||||
}
|
||||
@ -149,12 +149,6 @@ public class FreeformFinSet extends FinSet {
|
||||
/** maintained just for backwards compatibility:
|
||||
*/
|
||||
public void setPoints(Coordinate[] newPoints) {
|
||||
// move to zero, if applicable
|
||||
if( ! Coordinate.ZERO.equals(newPoints[0])) {
|
||||
final Coordinate p0 = newPoints[0];
|
||||
newPoints = translatePoints( newPoints, -p0.x, -p0.y);
|
||||
}
|
||||
|
||||
setPoints(new ArrayList<>(Arrays.asList(newPoints)));
|
||||
}
|
||||
|
||||
@ -164,43 +158,29 @@ public class FreeformFinSet extends FinSet {
|
||||
* @param newPoints New points to set as the exposed edges of the fin
|
||||
*/
|
||||
public void setPoints( ArrayList<Coordinate> newPoints) {
|
||||
|
||||
final Coordinate delta = newPoints.get(0).multiply(-1);
|
||||
if( IGNORE_SMALLER_THAN < delta.length2()){
|
||||
newPoints = translatePoints( newPoints, delta);
|
||||
}
|
||||
|
||||
// copy the old points, in case validation fails
|
||||
ArrayList<Coordinate> copy = new ArrayList<>(this.points);
|
||||
final ArrayList<Coordinate> pointsCopy = new ArrayList<>(this.points);
|
||||
final double lengthCopy = this.length;
|
||||
|
||||
this.points = newPoints;
|
||||
this.length = newPoints.get(newPoints.size() -1).x;
|
||||
|
||||
|
||||
update();
|
||||
|
||||
//StackTraceElement[] stacktrack = Thread.currentThread().getStackTrace();
|
||||
if("Canard fins, mounted to transition".equals(this.getName())) {
|
||||
log.error(String.format("starting to set %d points @ %s", newPoints.size(), this.getName()), new NullPointerException());
|
||||
System.err.println( toDebugDetail());
|
||||
}
|
||||
|
||||
if( ! validate()){
|
||||
|
||||
if( intersects()){
|
||||
// on error, reset to the old points
|
||||
this.points = copy;
|
||||
this.points = pointsCopy;
|
||||
this.length = lengthCopy;
|
||||
}
|
||||
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE);
|
||||
}
|
||||
|
||||
private double y_body(final double x) {
|
||||
return y_body(x, 0.0);
|
||||
}
|
||||
|
||||
private double y_body(final double x_target, final double x_ref) {
|
||||
final SymmetricComponent sym = (SymmetricComponent) getParent();
|
||||
return (sym.getRadius(x_target) - sym.getRadius(x_ref));
|
||||
}
|
||||
|
||||
public void setPointRelToFin(final int index, final double x_request_fin, final double y_request_fin) throws IllegalFinPointException {
|
||||
final double x_finStart_body = getAxialFront(); // x @ fin start, body frame
|
||||
final double y_finStart_body = y_body(x_finStart_body);
|
||||
|
||||
setPoint(index, x_request_fin + x_finStart_body, y_request_fin + y_finStart_body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the point at position <code>i</code> to coordinates (x,y).
|
||||
* <p>
|
||||
@ -225,19 +205,16 @@ public class FreeformFinSet extends FinSet {
|
||||
public void setPoint(final int index, final double xRequest, final double yRequest) {
|
||||
|
||||
if(null != this.getParent()) {
|
||||
if (0 == index) {
|
||||
clampFirstPoint(new Coordinate(xRequest, yRequest));
|
||||
} else if ((this.points.size() - 1) == index) {
|
||||
Coordinate priorPoint = points.get(index);
|
||||
points.set(index, new Coordinate(xRequest, yRequest));
|
||||
clampLastPoint(priorPoint);
|
||||
} else {
|
||||
// interior points can never change the
|
||||
points.set(index, new Coordinate(xRequest, yRequest));
|
||||
clampInteriorPoint(index);
|
||||
final Coordinate prior = points.get(index);
|
||||
points.set(index, new Coordinate(xRequest, yRequest));
|
||||
|
||||
if((points.size() - 1) == index){
|
||||
clampLastPoint(xRequest-prior.x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
update();
|
||||
|
||||
// this maps the last index and the next-to-last-index to the same 'testIndex'
|
||||
int testIndex = Math.min(index, (points.size() - 2));
|
||||
if (intersects(testIndex)) {
|
||||
@ -245,24 +222,24 @@ public class FreeformFinSet extends FinSet {
|
||||
log.error(String.format("ERROR: found an intersection while setting fin point #%d to [%6.4g, %6.4g] <body frame> : ABORTING setPoint(..) !! ", index, xRequest, yRequest));
|
||||
return;
|
||||
}
|
||||
|
||||
fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE);
|
||||
}
|
||||
|
||||
private void movePoints(final double delta_x, final double delta_y) {
|
||||
// skip 0th index -- it's the local origin and is always (0,0)
|
||||
// zero-out 0th index -- it's the local origin and is always (0,0)
|
||||
points.set(0, Coordinate.ZERO);
|
||||
|
||||
for (int index = 1; index < points.size(); ++index) {
|
||||
final Coordinate oldPoint = this.points.get(index);
|
||||
final Coordinate newPoint = oldPoint.add(delta_x, delta_y, 0.0f);
|
||||
points.set(index, newPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Coordinate[] getFinPoints() {
|
||||
return points.toArray(new Coordinate[0]);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getSpan() {
|
||||
double max = 0;
|
||||
@ -287,237 +264,114 @@ public class FreeformFinSet extends FinSet {
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAxialOffset(final AxialMethod newAxialMethod, final double newOffsetRequest) {
|
||||
super.setAxialOffset(newAxialMethod, newOffsetRequest);
|
||||
|
||||
if (null != parent) {
|
||||
// if the new position would cause fin overhang, only allow movement up to the end of the parent component.
|
||||
// N.B. if you want a fin to overhang, add & adjust interior points.
|
||||
final double backOverhang = getAxialOffset(AxialMethod.BOTTOM);
|
||||
if (0 < backOverhang) {
|
||||
final double newOffset = newOffsetRequest - backOverhang;
|
||||
super.setAxialOffset(newAxialMethod, newOffset);
|
||||
}
|
||||
final double frontOverhang = getAxialFront();
|
||||
if (0 > frontOverhang) {
|
||||
final double newOffset = newOffsetRequest - frontOverhang;
|
||||
super.setAxialOffset(newAxialMethod, newOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.length = points.get(points.size() -1).x - points.get(0).x;
|
||||
this.setAxialOffset(this.axialMethod, this.axialOffset);
|
||||
|
||||
|
||||
if(null != this.getParent()) {
|
||||
clampFirstPoint(points.get(0));
|
||||
clampFirstPoint();
|
||||
|
||||
for(int i=1; i < points.size()-1; i++) {
|
||||
clampInteriorPoint(i);
|
||||
}
|
||||
|
||||
clampLastPoint(null);
|
||||
clampLastPoint();
|
||||
|
||||
validateFinTab();
|
||||
}
|
||||
}
|
||||
|
||||
private void clampFirstPoint(final Coordinate newPoint) {
|
||||
|
||||
private void clampFirstPoint() {
|
||||
final SymmetricComponent body = (SymmetricComponent) getParent();
|
||||
|
||||
|
||||
final Coordinate finFront = getFinFront();
|
||||
final double xFinFront = finFront.x; // x of fin start, body-frame
|
||||
final double yFinFront = finFront.y; // y of fin start, body-frame
|
||||
final double xBodyStart = -getAxialFront(); // x-offset from start-to-start; fin-frame
|
||||
|
||||
final Coordinate p0 = points.get(0);
|
||||
|
||||
double xDelta;
|
||||
double yDelta;
|
||||
if( ! Coordinate.ZERO.equals(p0)){
|
||||
double xDelta = p0.x;
|
||||
double xTrail = points.get(points.size() - 1).x;
|
||||
if(xDelta > xTrail){
|
||||
xDelta = xTrail;
|
||||
}
|
||||
double yDelta = body.getRadius(xFinFront + xDelta) - yFinFront;
|
||||
|
||||
if(IGNORE_SMALLER_THAN > Math.abs(newPoint.x)){
|
||||
return;
|
||||
}else if (xBodyStart > newPoint.x) {
|
||||
// attempt to place point in front of the start of the body
|
||||
|
||||
// delta for new zeroth point
|
||||
xDelta = xBodyStart;
|
||||
yDelta = body.getForeRadius() - yFinFront;
|
||||
points.set(0, newPoint);
|
||||
points.add(0, Coordinate.ZERO);
|
||||
movePoints(-xDelta, -yDelta);
|
||||
|
||||
//System.err.println(String.format(".... @[0]//A: delta= %f, %f", xDelta, yDelta));
|
||||
|
||||
}else if (xFinFront > body.getLength()) {
|
||||
final double xNew = body.getLength();
|
||||
final double yNew = yFinFront - body.getAftRadius();
|
||||
points.set(0, points.set(0, new Coordinate(xNew, yNew)));
|
||||
|
||||
xDelta = xNew - xFinFront;
|
||||
yDelta = yNew - yFinFront;
|
||||
movePoints(-xDelta, -yDelta);
|
||||
//System.err.println(String.format(".... @[0]//B: delta= %f, %f", xDelta, yDelta));
|
||||
|
||||
}else {
|
||||
// distance to move the entire fin by:
|
||||
xDelta = newPoint.x;
|
||||
yDelta = body.getRadius(xFinFront + xDelta) - yFinFront;
|
||||
movePoints(-xDelta, -yDelta);
|
||||
|
||||
//System.err.println(String.format(".... @[0]//C: delta= %f, %f", xDelta, yDelta));
|
||||
if(AxialMethod.TOP == getAxialMethod()) {
|
||||
this.axialOffset = axialOffset + xDelta;
|
||||
this.position = this.position.add(xDelta, 0, 0);
|
||||
} else if (AxialMethod.MIDDLE == getAxialMethod()) {
|
||||
this.axialOffset = axialOffset + xDelta / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final int lastIndex = points.size()-1;
|
||||
this.length = points.get(lastIndex).x;
|
||||
|
||||
if (AxialMethod.TOP == getAxialMethod()) {
|
||||
setAxialOffset(AxialMethod.TOP, getAxialOffset() + xDelta);
|
||||
} else if (AxialMethod.MIDDLE == getAxialMethod()) {
|
||||
setAxialOffset(AxialMethod.MIDDLE, getAxialOffset() + xDelta / 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void clampInteriorPoint(final int index) {
|
||||
final SymmetricComponent sym = (SymmetricComponent) this.getParent();
|
||||
|
||||
final double xPrior = points.get(index).x;
|
||||
final double yPrior = points.get(index).y;
|
||||
|
||||
final Coordinate finFront = getFinFront();
|
||||
final double xFinFront = finFront.x; // x of fin start, body-frame
|
||||
final double yFinFront = finFront.y; // y of fin start, body-frame
|
||||
|
||||
final double yBody = sym.getRadius(xPrior + xFinFront) - yFinFront;
|
||||
|
||||
// ensure that an interior point is outside of its mounting body:
|
||||
if (yBody > yPrior) {
|
||||
points.set(index, points.get(index).setY(yBody));
|
||||
|
||||
final double xBodyFront = -xFinFront;
|
||||
final double xBodyBack = xBodyFront + sym.getLength();
|
||||
|
||||
final double xPrior = points.get(index).x;
|
||||
final double yPrior = points.get(index).y;
|
||||
|
||||
if((xBodyFront <= xPrior ) && ( xPrior <= xBodyBack )) {
|
||||
final double yBody = sym.getRadius(xPrior + xFinFront) - yFinFront;
|
||||
|
||||
// ensure that an interior point is outside of its mounting body:
|
||||
if (yBody > yPrior) {
|
||||
points.set(index, points.get(index).setY(yBody));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void clampLastPoint(final Coordinate prior) {
|
||||
private void clampLastPoint() {
|
||||
clampLastPoint(0);
|
||||
}
|
||||
|
||||
private void clampLastPoint(final double xDelta) {
|
||||
final SymmetricComponent body = (SymmetricComponent) getParent();
|
||||
|
||||
final double xFinStart = getAxialFront(); // x of fin start, body-frame
|
||||
final double yFinStart = body.getRadius(xFinStart); // y of fin start, body-frame
|
||||
|
||||
final double xBodyStart = -getAxialFront(); // x-offset from start-to-start; fin-frame
|
||||
final double xBodyEnd = xBodyStart + body.getLength(); /// x-offset from start-to-body; fin-frame
|
||||
|
||||
|
||||
final Coordinate finFront = getFinFront();
|
||||
final double xFinStart = finFront.x; // x of fin start, body-frame
|
||||
final double yFinStart = finFront.y; // y of fin start, body-frame
|
||||
|
||||
int lastIndex = points.size() - 1;
|
||||
final Coordinate cur = points.get(lastIndex);
|
||||
final Coordinate last = points.get(lastIndex);
|
||||
|
||||
double xDelta=0;
|
||||
double yBody = body.getRadius(xFinStart + last.x) - yFinStart;
|
||||
double yDelta = yBody - last.y;
|
||||
if( IGNORE_SMALLER_THAN < Math.abs(yDelta)){
|
||||
// i.e. if it delta is close enough above OR is inside the body. In either case, snap it to the body.
|
||||
|
||||
if (xBodyEnd < cur.x) {
|
||||
if(SNAP_SMALLER_THAN > Math.abs(xBodyEnd - cur.x)){
|
||||
points.set( lastIndex, new Coordinate(xBodyEnd, body.getAftRadius() - yFinStart));
|
||||
}else {
|
||||
// the last point is placed after the end of the mount-body
|
||||
points.add(new Coordinate(xBodyEnd, body.getAftRadius() - yFinStart));
|
||||
}
|
||||
|
||||
if(null != prior) {
|
||||
xDelta = xBodyEnd - prior.x;
|
||||
}else{
|
||||
xDelta = xBodyEnd - cur.x;
|
||||
}
|
||||
//System.err.println(String.format(".... @[-1]//A: delta= %f", xDelta));
|
||||
|
||||
}else if (cur.x < 0) {
|
||||
// the last point is positioned ahead of the first point.
|
||||
points.set(lastIndex, Coordinate.ZERO);
|
||||
|
||||
xDelta = cur.x;
|
||||
|
||||
//System.err.println(String.format(".... @[-1]//B: delta= %f", xDelta));
|
||||
|
||||
} else {
|
||||
if(null != prior) {
|
||||
xDelta = cur.x - prior.x;
|
||||
}
|
||||
double yBody = body.getRadius(xFinStart + cur.x) - yFinStart;
|
||||
if(IGNORE_SMALLER_THAN < Math.abs(yBody - cur.y)) {
|
||||
// for the first and last points: set y-value to *exactly* match parent body:
|
||||
points.set(lastIndex, new Coordinate(cur.x, yBody));
|
||||
|
||||
}
|
||||
|
||||
|
||||
//System.err.println(String.format(".... @[-1]//C: delta = %f", xDelta));
|
||||
// => set y-value to *exactly* match parent body:
|
||||
points.set(lastIndex, new Coordinate(last.x, yBody));
|
||||
}
|
||||
|
||||
if(IGNORE_SMALLER_THAN < Math.abs(xDelta)) {
|
||||
lastIndex = points.size()-1;
|
||||
|
||||
if( IGNORE_SMALLER_THAN < Math.abs(xDelta)) {
|
||||
this.length = points.get(lastIndex).x;
|
||||
|
||||
if (AxialMethod.MIDDLE == getAxialMethod()) {
|
||||
setAxialOffset(AxialMethod.MIDDLE, getAxialOffset() + xDelta / 2);
|
||||
this.axialOffset = axialOffset + xDelta/2;
|
||||
} else if (AxialMethod.BOTTOM == getAxialMethod()) {
|
||||
setAxialOffset(AxialMethod.BOTTOM, getAxialOffset() + xDelta);
|
||||
this.axialOffset = axialOffset + xDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validate() {
|
||||
final Coordinate firstPoint = this.points.get(0);
|
||||
if (firstPoint.x != 0 || firstPoint.y != 0) {
|
||||
log.error("Start point illegal -- not located at (0,0): " + firstPoint + " (" + getName() + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
final Coordinate lastPoint = this.points.get(points.size() - 1);
|
||||
if (lastPoint.x < 0) {
|
||||
log.error("End point illegal: end point starts in front of start point: " + lastPoint.x);
|
||||
return false;
|
||||
}
|
||||
|
||||
// the last point *is* restricted to be on the surface of its owning component:
|
||||
SymmetricComponent symBody = (SymmetricComponent) this.getParent();
|
||||
if (null != symBody) {
|
||||
final double startOffset = this.getAxialFront();
|
||||
final Coordinate finStart = new Coordinate(startOffset, symBody.getRadius(startOffset));
|
||||
|
||||
// campare x-values
|
||||
final Coordinate finAtLast = lastPoint.add(finStart);
|
||||
if (symBody.getLength() < finAtLast.x) {
|
||||
log.error("End point falls after parent body ends: [" + symBody.getName() + "]. Exception: ",
|
||||
new IllegalFinPointException("Fin ends after its parent body \"" + symBody.getName() + "\". Ignoring."));
|
||||
log.error(String.format(" ..fin position: (x: %12.10f via: %s)", this.axialOffset, this.axialMethod.name()));
|
||||
log.error(String.format(" ..Body Length: %12.10f finLength: %12.10f", symBody.getLength(), this.getLength()));
|
||||
log.error(String.format(" ..fin endpoint: (x: %12.10f, y: %12.10f)", finAtLast.x, finAtLast.y));
|
||||
return false;
|
||||
}
|
||||
|
||||
// compare the y-values
|
||||
final Coordinate bodyAtLast = finAtLast.setY(symBody.getRadius(finAtLast.x));
|
||||
if (0.0001 < Math.abs(finAtLast.y - bodyAtLast.y)) {
|
||||
String numbers = String.format("finStart=(%6.2g,%6.2g) // fin_end=(%6.2g,%6.2g) // body=(%6.2g,%6.2g)", finStart.x, finStart.y, finAtLast.x, finAtLast.y, bodyAtLast.x, bodyAtLast.y);
|
||||
log.error("End point does not touch its parent body [" + symBody.getName() + "]. exception: ",
|
||||
new IllegalFinPointException("End point does not touch its parent body! Expected: " + numbers));
|
||||
log.error(" .." + numbers);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersects()) {
|
||||
log.error("found intersection in finset points!");
|
||||
return false;
|
||||
}
|
||||
|
||||
final int lastIndex = points.size() - 1;
|
||||
final List<Coordinate> pts = this.points;
|
||||
for (int i = 0; i < lastIndex; i++) {
|
||||
if (pts.get(i).z != 0) {
|
||||
log.error("z-coordinate not zero");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if *any* of the fin-point line segments intersects with another.
|
||||
*
|
||||
@ -541,7 +395,7 @@ public class FreeformFinSet extends FinSet {
|
||||
if ((points.size() - 2) < targetIndex) {
|
||||
throw new IndexOutOfBoundsException("request validate of non-existent fin edge segment: " + targetIndex + "/" + points.size());
|
||||
}
|
||||
|
||||
|
||||
// (pre-check the indices above.)
|
||||
final Point2D.Double pt1 = new Point2D.Double(points.get(targetIndex).x, points.get(targetIndex).y);
|
||||
final Point2D.Double pt2 = new Point2D.Double(points.get(targetIndex + 1).x, points.get(targetIndex + 1).y);
|
||||
|
@ -348,8 +348,10 @@ public class Transition extends SymmetricComponent {
|
||||
*/
|
||||
@Override
|
||||
public double getRadius(double x) {
|
||||
if (x < 0 || x > length)
|
||||
return 0;
|
||||
if ( x < 0 )
|
||||
return getForeRadius();
|
||||
if ( x > length)
|
||||
return getAftRadius();
|
||||
|
||||
double r1 = getForeRadius();
|
||||
double r2 = getAftRadius();
|
||||
|
@ -318,7 +318,6 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
FlightConfiguration emptyConfig = rocket.getEmptyConfiguration();
|
||||
rocket.setSelectedConfiguration( emptyConfig.getFlightConfigurationID() );
|
||||
|
||||
|
||||
double expInertia;
|
||||
RocketComponent cc;
|
||||
double compInertia;
|
||||
@ -326,30 +325,24 @@ public class MassCalculatorTest extends BaseTestCase {
|
||||
// ====== Payload Stage ======
|
||||
// ====== ====== ====== ======
|
||||
{
|
||||
expInertia = 3.1698055283e-5;
|
||||
cc= rocket.getChild(0).getChild(0);
|
||||
compInertia = cc.getRotationalInertia();
|
||||
assertEquals(cc.getName()+" Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
expInertia = 1.79275e-5;
|
||||
compInertia = cc.getLongitudinalInertia();
|
||||
assertEquals(cc.getName()+" Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
|
||||
cc= rocket.getChild(0).getChild(1);
|
||||
expInertia = 7.70416e-5;
|
||||
compInertia = cc.getRotationalInertia();
|
||||
assertEquals(cc.getName()+" Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
expInertia = 8.06940e-5;
|
||||
compInertia = cc.getLongitudinalInertia();
|
||||
assertEquals(cc.getName()+" Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
|
||||
cc= rocket.getChild(0).getChild(2);
|
||||
expInertia = 1.43691e-5;
|
||||
compInertia = cc.getRotationalInertia();
|
||||
assertEquals(cc.getName()+" Rotational MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
expInertia = 7.30265e-6;
|
||||
compInertia = cc.getLongitudinalInertia();
|
||||
assertEquals(cc.getName()+" Longitudinal MOI calculated incorrectly: ", expInertia, compInertia, EPSILON);
|
||||
final AxialStage payloadStage = (AxialStage) rocket.getChild(0);
|
||||
|
||||
// Component: Nose Cone
|
||||
final NoseCone payloadNose = (NoseCone) payloadStage.getChild(0);
|
||||
assertEquals(payloadNose.getName()+" Rotational MOI calculated incorrectly: ", 3.508155e-5, payloadNose.getRotationalInertia(), EPSILON);
|
||||
assertEquals(payloadNose.getName()+" Longitudinal MOI calculated incorrectly: ", 2.0400578477e-6, payloadNose.getLongitudinalInertia(), EPSILON);
|
||||
|
||||
// Component: Payload BodyTube
|
||||
final BodyTube payloadBody = (BodyTube)payloadStage.getChild(1);
|
||||
assertEquals(payloadBody.getName()+" Rotational MOI calculated incorrectly: ", 7.70416e-5, payloadBody.getRotationalInertia(), EPSILON);
|
||||
assertEquals(payloadBody.getName()+" Longitudinal MOI calculated incorrectly: ", 8.06940e-5, payloadBody.getLongitudinalInertia(), EPSILON);
|
||||
|
||||
// Component: Payload Trailing Transition
|
||||
final Transition payloadTail = (Transition) payloadStage.getChild(2);
|
||||
assertEquals(payloadTail.getName()+" Rotational MOI calculated incorrectly: ", 1.43691e-5, payloadTail.getRotationalInertia(), EPSILON);
|
||||
assertEquals(payloadTail.getName()+" Longitudinal MOI calculated incorrectly: ", 7.30265e-6, payloadTail.getLongitudinalInertia(), EPSILON);
|
||||
|
||||
// Component: Interstage
|
||||
cc= rocket.getChild(0).getChild(3);
|
||||
expInertia = 4.22073e-5;
|
||||
compInertia = cc.getRotationalInertia();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -424,12 +424,7 @@ public class FreeformFinSetConfig extends FinSetConfig {
|
||||
|
||||
Point2D.Double point = getCoordinates(event);
|
||||
finset.setPoint(dragIndex, point.x, point.y);
|
||||
|
||||
final double bodyFront = -finset.getAxialFront();
|
||||
if(0 == dragIndex && bodyFront > point.x){
|
||||
dragIndex = 1;
|
||||
}
|
||||
|
||||
|
||||
updateFields();
|
||||
}
|
||||
|
||||
@ -447,6 +442,7 @@ public class FreeformFinSetConfig extends FinSetConfig {
|
||||
if ( 0 < clickIndex) {
|
||||
// if ctrl+click, delete point
|
||||
try {
|
||||
Point2D.Double point = getCoordinates(event);
|
||||
finset.removePoint(clickIndex);
|
||||
} catch (IllegalFinPointException ignore) {
|
||||
log.error("Ignoring IllegalFinPointException while dragging, dragIndex=" + dragIndex + ". This is likely an internal error.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user