[fixes #471] Refactoring FreeformFinSet to accept root points outside of the base. (which generates bridge-points on-load)

This commit is contained in:
Daniel_M_Williams 2018-11-18 18:12:01 -05:00
parent 151a4d864d
commit 72c6f1d64d
2 changed files with 757 additions and 411 deletions

View File

@ -20,10 +20,11 @@ public class FreeformFinSet extends FinSet {
private static final Logger log = LoggerFactory.getLogger(FreeformFinSet.class);
private static final Translator trans = Application.getTranslator();
public static final double MIN_ROOT_CHORD=0.01; // enforce this to prevent erroneous 'intersection' exceptions.
private List<Coordinate> points = new ArrayList<>();
private static final double SNAP_SMALLER_THAN = 1e-6;
private static final double IGNORE_SMALLER_THAN = 1e-12;
public FreeformFinSet() {
points.add(Coordinate.ZERO);
points.add(new Coordinate(0.025, 0.05));
@ -33,10 +34,6 @@ public class FreeformFinSet extends FinSet {
this.length = 0.05;
}
public FreeformFinSet(Coordinate[] finpoints) {
setPoints(finpoints);
}
/**
* Convert an existing fin set into a freeform fin set. The specified
* fin set is taken out of the rocket tree (if any) and the new component
@ -68,8 +65,9 @@ public class FreeformFinSet extends FinSet {
}
// Create the freeform fin set
Coordinate[] finpoints = finset.getFinPoints();
freeform = new FreeformFinSet(finpoints);
Coordinate[] finPoints = finset.getFinPoints();
freeform = new FreeformFinSet();
freeform.setPoints(Arrays.asList(finPoints));
freeform.setAxialOffset(finset.getAxialMethod(), finset.getAxialOffset());
// Copy component attributes
@ -148,22 +146,18 @@ public class FreeformFinSet extends FinSet {
return points.size();
}
/**
* The first point is assumed to be at the origin. If it isn't, it will be moved there.
*
* @param newPoints new fin points ; replaces previous fin points
/** 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);
newPoints = translatePoints( newPoints, -p0.x, -p0.y);
}
ArrayList<Coordinate> newList = new ArrayList<>(Arrays.asList( newPoints));
setPoints( newList );
setPoints(new ArrayList<>(Arrays.asList(newPoints)));
}
/**
* The first point is assumed to be at the origin. If it isn't, it will be moved there.
*
@ -172,16 +166,22 @@ public class FreeformFinSet extends FinSet {
public void setPoints( List<Coordinate> newPoints) {
// copy the old points, in case validation fails
List<Coordinate> copy = new ArrayList<>(this.points);
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()){
// on error, reset to the old points
this.points = copy;
}
this.length = points.get(points.size() - 1).x;
fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE);
}
@ -223,62 +223,19 @@ public class FreeformFinSet extends FinSet {
* @param yRequest the y-coordinate.
*/
public void setPoint(final int index, final double xRequest, final double yRequest) {
final SymmetricComponent body = (SymmetricComponent)getParent();
final int lastPointIndex = this.points.size() - 1;
final double xFinEnd = points.get(lastPointIndex).x;
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 = -xFinStart; // x-offset from fin to body; fin-frame
// initial guess at these values; further checks follow.
double xAgreed = xRequest;
double yAgreed = yRequest;
// clamp x coordinates:
// within bounds, and consistent with the rest of the fin (at this time).
if(null != this.getParent()) {
if (0 == index) {
// restrict the first point to be between the parent's start, and the last fin point
xAgreed = Math.max( xBodyStart, Math.min( xAgreed, xFinEnd - MIN_ROOT_CHORD ));
}else if( lastPointIndex == index ){
// restrict the last point to be between the first fin point, and the parent's end length.
xAgreed = Math.max( MIN_ROOT_CHORD, Math.min( xAgreed, xBodyStart + body.getLength()));
}
// adjust y-value to be consistent with body
final double yBody_atPoint= body.getRadius( xFinStart + xAgreed) - yFinStart;
if (index == 0 || index == lastPointIndex) {
// for the first and last points: set y-value to *exactly* match parent body:
yAgreed = yBody_atPoint;
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 {
// for all other points, merely insist that the point is outside the body...
yAgreed = Math.max( yAgreed, yBody_atPoint);
// interior points can never change the
points.set(index, new Coordinate(xRequest, yRequest));
clampInteriorPoint(index);
}
// if moving either begin or end points, we'll probably have to update the position, as well.
final AxialMethod locationMethod = getAxialMethod();
final double priorXOffset = getAxialOffset();
if( 0 == index){
movePoints( xAgreed);
this.length = points.get( lastPointIndex ).x;
if( AxialMethod.TOP == locationMethod){
setAxialOffset( AxialMethod.TOP, priorXOffset + xAgreed );
}else if(AxialMethod.MIDDLE == locationMethod){
setAxialOffset( AxialMethod.MIDDLE, priorXOffset + xAgreed/2 );
}
}else if( lastPointIndex == index ){
points.set(index, new Coordinate( xAgreed, yAgreed ));
this.length = xAgreed;
if( AxialMethod.MIDDLE == locationMethod){
setAxialOffset( AxialMethod.MIDDLE, priorXOffset + (xAgreed - xFinEnd)/2 );
}else if(AxialMethod.BOTTOM== locationMethod){
setAxialOffset( AxialMethod.BOTTOM, priorXOffset + (xAgreed - xFinEnd) );
}
}else{
points.set(index, new Coordinate( xAgreed, yAgreed ));
}
// this maps the last index and the next-to-last-index to the same 'testIndex'
@ -292,11 +249,11 @@ public class FreeformFinSet extends FinSet {
fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE);
}
private void movePoints( final double delta_x){
private void movePoints(final double delta_x, final double delta_y) {
// skip 0th index -- it's the local origin and is always (0,0)
for (int index = 1; index < points.size(); ++index) {
final Coordinate oldPoint = this.points.get(index);
final Coordinate newPoint = oldPoint.sub( delta_x, 0.0f, 0.0f);
final Coordinate newPoint = oldPoint.add(delta_x, delta_y, 0.0f);
points.set(index, newPoint);
}
}
@ -322,7 +279,6 @@ public class FreeformFinSet extends FinSet {
return trans.get("FreeformFinSet.FreeformFinSet");
}
@SuppressWarnings("unchecked")
@Override
protected RocketComponent copyWithOriginalID() {
RocketComponent c = super.copyWithOriginalID();
@ -354,70 +310,154 @@ public class FreeformFinSet extends FinSet {
@Override
public void update() {
final int lastPointIndex = this.points.size() - 1;
this.length = points.get(lastPointIndex).x;
this.setAxialOffset(this.axialMethod, this.axialOffset);
clampFirstPoint();
clampInteriorPoints();
clampLastPoint();
if(null != this.getParent()) {
clampFirstPoint(points.get(0));
for(int i=1; i < points.size()-1; i++) {
clampInteriorPoint(i);
}
clampLastPoint(null);
validateFinTab();
}
// if we translate the points, correct the first point, because it may be inconsistent
private void clampFirstPoint(){
double xFinStart = getAxialFront(); // x @ fin start, body frame
final double xFinOffset = getAxialOffset();
if( 0 > xFinStart ){
setAxialOffset( xFinOffset - xFinStart);
}
}
private void clampInteriorPoints(){
if( null == this.parent ){
// this is bad, but seems to only occur during unit tests.
return;
}
final SymmetricComponent symmetricParent = (SymmetricComponent)this.getParent();
private void clampFirstPoint(final Coordinate newPoint) {
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
// omit end points index
for( int index=1; index < (points.size()-1); ++index){
final Coordinate oldPoint = this.points.get( index);
double xDelta;
double yDelta;
final double yBody = symmetricParent.getRadius( oldPoint.x + finFront.x);
final double yFinPoint = finFront.y+ oldPoint.y;
if( yBody > yFinPoint ){
final Coordinate newPoint = oldPoint.setY( yBody - finFront.y );
points.set( index, newPoint);
}
}
}
// if we translate the points, the final point may become inconsistent
private void clampLastPoint(){
if( null == this.parent ){
// this is bad, but seems to only occur during unit tests.
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));
}
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));
}
}
private void clampLastPoint(final Coordinate prior) {
final SymmetricComponent body = (SymmetricComponent) getParent();
// clamp the final x coord to the end of the parent body.
final int lastPointIndex = points.size() - 1;
final Coordinate oldPoint = points.get( lastPointIndex);
final double xFinStart_body = getAxialFront(); // x @ fin start, body frame
final double xBodyEnd_fin = body.getLength() - xFinStart_body;
final double xFinStart = getAxialFront(); // x of fin start, body-frame
final double yFinStart = body.getRadius(xFinStart); // y of fin start, body-frame
double x_clamped = Math.min( oldPoint.x, xBodyEnd_fin);
double y_clamped = body.getRadius( x_clamped+xFinStart_body) - body.getRadius( xFinStart_body);
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
int lastIndex = points.size() - 1;
final Coordinate cur = points.get(lastIndex);
double xDelta=0;
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));
}
points.set( lastPointIndex, new Coordinate( x_clamped, y_clamped, 0));
//System.err.println(String.format(".... @[-1]//C: delta = %f", xDelta));
}
if(IGNORE_SMALLER_THAN < Math.abs(xDelta)) {
lastIndex = points.size()-1;
this.length = points.get(lastIndex).x;
if (AxialMethod.MIDDLE == getAxialMethod()) {
setAxialOffset(AxialMethod.MIDDLE, getAxialOffset() + xDelta / 2);
} else if (AxialMethod.BOTTOM == getAxialMethod()) {
setAxialOffset(AxialMethod.BOTTOM, getAxialOffset() + xDelta);
}
}
}
private boolean validate() {
@ -442,7 +482,8 @@ public class FreeformFinSet extends FinSet {
// 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("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));
@ -453,7 +494,8 @@ public class FreeformFinSet extends FinSet {
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("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;
}
@ -493,8 +535,6 @@ public class FreeformFinSet extends FinSet {
/**
* Check if the line segment from targetIndex to targetIndex+1 intersects with any other part of the fin.
*
*
*
* @return true if an intersection was found
*/
private boolean intersects(final int targetIndex) {
@ -503,21 +543,29 @@ public class FreeformFinSet extends FinSet {
}
// (pre-check the indices above.)
Point2D.Double p1 = new Point2D.Double( points.get(targetIndex).x, points.get(targetIndex).y);
Point2D.Double p2 = new Point2D.Double( points.get(targetIndex+1).x, points.get(targetIndex+1).y);
Line2D.Double targetLine = new Line2D.Double( p1, p2);
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);
final Line2D.Double targetLine = new Line2D.Double(pt1, pt2);
for (int comparisonIndex = 0; comparisonIndex < (points.size()-1); ++comparisonIndex ) {
for (int comparisonIndex = targetIndex+1; comparisonIndex < (points.size() - 1); ++comparisonIndex) {
if (2 > Math.abs(targetIndex - comparisonIndex)) {
// a line segment will trivially not intersect with itself
// nor can adjacent line segments intersect with each other, because they share a common endpoint.
continue;
}
final Point2D.Double pc1 = new Point2D.Double(points.get(comparisonIndex).x, points.get(comparisonIndex).y); // p1
final Point2D.Double pc2 = new Point2D.Double(points.get(comparisonIndex + 1).x, points.get(comparisonIndex + 1).y); // p2
Line2D.Double comparisonLine = new Line2D.Double( points.get(comparisonIndex).x, points.get(comparisonIndex).y, // p1
points.get(comparisonIndex+1).x, points.get(comparisonIndex+1).y); // p2
// special case for when the first and last points are co-located.
if((0==targetIndex)&&(points.size()==comparisonIndex+2)&&(IGNORE_SMALLER_THAN > Math.abs(pt1.distance(pc2)))){
continue;
}
final Line2D.Double comparisonLine = new Line2D.Double(pc1, pc2);
if (targetLine.intersectsLine(comparisonLine)) {
log.error(String.format("Found intersection at %d-%d and %d-%d", targetIndex, targetIndex+1, comparisonIndex, comparisonIndex+1));
log.error(String.format(" between (%g, %g) => (%g, %g)", pt1.x, pt1.y, pt2.x, pt2.y));
log.error(String.format(" and (%g, %g) => (%g, %g)", pc1.x, pc1.y, pc2.x, pc2.y));
return true;
}
}

View File

@ -117,7 +117,7 @@ public class FreeformFinSetTest extends BaseTestCase {
new Coordinate( 0.0, 0.0),
new Coordinate( 0.4, 1.0),
new Coordinate( 0.6, 1.0),
new Coordinate( 0.8, 0.9)
new Coordinate( 0.8, 0.9) // y-value should be automaticaly adjusted to snap to body
};
fins.setPoints(points);
@ -325,6 +325,8 @@ public class FreeformFinSetTest extends BaseTestCase {
assertEquals(Shape.ELLIPSOID, body.getType());
assertEquals(1.0, body.getLength(), EPSILON);
assertEquals(AxialMethod.TOP, fins.getAxialMethod());
assertEquals(0.02, fins.getAxialOffset(), EPSILON);
assertEquals(0.8, fins.getLength(), EPSILON);
final Coordinate[] finPoints = fins.getFinPoints();
assertEquals(4, finPoints.length);
@ -425,30 +427,6 @@ public class FreeformFinSetTest extends BaseTestCase {
assertEquals(0.8, added.y, 0.1);
}
@Test
public void testSetPoint_firstPoint_boundsCheck() throws IllegalFinPointException {
// more transitions trigger more complicated positioning math:
Rocket rkt = createTemplateRocket();
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(0).getChild(0);
final int startIndex = 0;
final int lastIndex = fins.getPointCount()-1;
// assert pre-conditions
assertEquals( 1, fins.getFinCount());
assertEquals( 3, lastIndex);
fins.setPoint( startIndex, -1, -1);
final Coordinate act_p_0 = fins.getFinPoints()[0];
{ // first point x is restricted to the front of the parent body:
assertEquals( 0.0, act_p_0.x, EPSILON);
assertEquals( AxialMethod.TOP, fins.getAxialMethod() );
assertEquals( 0.0, fins.getAxialOffset(), EPSILON);
}
{// first point y is restricted to the body
assertEquals( 0.0, act_p_0.y, EPSILON);
}
}
@Test
public void testSetFirstPoint() throws IllegalFinPointException {
// more transitions trigger more complicated positioning math:
@ -458,7 +436,6 @@ public class FreeformFinSetTest extends BaseTestCase {
final Coordinate[] initialPoints = fins.getFinPoints();
// assert pre-conditions:
assertEquals(0.4, fins.getAxialFront(), EPSILON);
assertEquals(0.4, fins.getLength(), EPSILON);
assertEquals(initialPoints[0], Coordinate.ZERO);
assertEquals(initialPoints[1], new Coordinate(0.4, 0.2));
@ -466,48 +443,146 @@ public class FreeformFinSetTest extends BaseTestCase {
assertEquals(1.0, finMount.getLength(), EPSILON);
assertEquals(0.8, finMount.getRadius(fins.getAxialFront()), EPSILON);
// for a fin at these positions:
final AxialMethod[] inputMethods = { AxialMethod.TOP, AxialMethod.TOP, AxialMethod.MIDDLE, AxialMethod.MIDDLE, AxialMethod.BOTTOM, AxialMethod.BOTTOM};
final double[] inputOffsets = { 0.1, 0.1, 0.0, 0.0, 0.0, 0.0};
// move first by this delta...
final double[] xDelta = { 0.2, -0.2, 0.1, -0.1, 0.1, -0.1};
// and check against these expected values:
final double[] expectedFinStartx = { 0.3, 0.0, 0.4, 0.2, 0.7, 0.5};
final double[] expectedFinStarty = { 0.85, 1.0, 0.8, 0.9, 0.65, 0.75};
final double[] expectedFinLength = { 0.2, 0.5, 0.3, 0.5, 0.3, 0.5};
final double[] expectedFinOffset = { 0.3, 0.0, 0.05, -0.05, 0.0, 0.0};
final double[] expectedMidpointOffset = { 0.2, 0.5, 0.3, 0.5, 0.3, 0.5};
final double[] expectedFinalPointOffset = { 0.2, 0.5, 0.3, 0.5, 0.3, 0.5};
for( int caseIndex=0; caseIndex < inputMethods.length; ++caseIndex ){
// this builds a string to describe this particular iteration, and provide useful output, should it fail.
StringBuilder buf = new StringBuilder();
buf.append(String.format("\n## For Case #%d: [%s]@%4.2f \n", caseIndex, inputMethods[caseIndex].name(), inputOffsets[caseIndex]));
buf.append(String.format(" >> setting initial point to: ( %6.4f, %6.4f) \n", xDelta[caseIndex], 0.0f));
final String dump = buf.toString();
fins.setAxialOffset( inputMethods[caseIndex], inputOffsets[caseIndex]);
{ // case 1:
fins.setAxialOffset( AxialMethod.TOP, 0.1);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( 0, xDelta[caseIndex], 0.1f);
fins.setPoint( 0, 0.2, 0.1f);
// ^^^^ function under test ^^^^
//System.err.println(String.format("@[%d]:", caseIndex));
//System.err.println(fins.toDebugDetail());
assertEquals("Fin front not updated as expected..."+dump, expectedFinStartx[caseIndex], fins.getAxialFront(), EPSILON);
assertEquals("Fin front not updated as expected..."+dump, expectedFinStarty[caseIndex], fins.getFinFront().y, EPSILON);
assertEquals(0.3, fins.getFinFront().x, EPSILON);
assertEquals(0.85, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals("Middle fin point has moved!: "+dump, expectedMidpointOffset[caseIndex], postPoints[1].x, EPSILON);
assertEquals("Final fin point has moved!: "+dump, expectedFinalPointOffset[caseIndex], postPoints[2].x, EPSILON);
assertEquals(postPoints.length, 3);
assertEquals("Fin offset not updated as expected..."+dump, expectedFinOffset[caseIndex], fins.getAxialOffset(), EPSILON);
assertEquals("Fin length not updated as expected..."+dump, expectedFinLength[caseIndex], fins.getLength(), EPSILON);
// middle point:
assertEquals(0.2, postPoints[1].x, EPSILON);
assertEquals(0.3, postPoints[1].y, EPSILON);
assertEquals(0.3f, fins.getAxialOffset(), EPSILON);
assertEquals(0.2f, fins.getLength(), EPSILON);
}{ // case 2:
fins.setAxialOffset( AxialMethod.TOP, 0.1);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( 0, -0.2, 0.1f);
// ^^^^ function under test ^^^^
assertEquals(0.0, fins.getFinFront().x, EPSILON);
assertEquals(1.0, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 4);
// pseudo-front point
assertEquals(-0.1, postPoints[1].x, EPSILON);
assertEquals(0.05, postPoints[1].y, EPSILON);
assertEquals(0.5, postPoints[2].x, EPSILON);
assertEquals(0.15, postPoints[2].y, EPSILON);
assertEquals(0.0f, fins.getAxialOffset(), EPSILON);
assertEquals(0.5f, fins.getLength(), EPSILON);
}{ // case 3:
fins.setAxialOffset( AxialMethod.MIDDLE, 0.0);
fins.setPoints(initialPoints);
assertEquals(0.3, fins.getFinFront().x, EPSILON);
// vvvv function under test vvvv
fins.setPoint( 0, 0.1, 0.1f);
// ^^^^ function under test ^^^^
assertEquals(0.4, fins.getFinFront().x, EPSILON);
assertEquals(0.8, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid-point
assertEquals(0.3, postPoints[1].x, EPSILON);
assertEquals(0.25, postPoints[1].y, EPSILON);
assertEquals(0.3, postPoints[2].x, EPSILON);
assertEquals(-0.15, postPoints[2].y, EPSILON);
assertEquals(0.05f, fins.getAxialOffset(), EPSILON);
assertEquals(0.3f, fins.getLength(), EPSILON);
}{ // case 4:
fins.setAxialOffset( AxialMethod.MIDDLE, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( 0, -0.1, 0.1f);
// ^^^^ function under test ^^^^
assertEquals(0.2, fins.getFinFront().x, EPSILON);
assertEquals(0.9, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid point
assertEquals(0.5, postPoints[1].x, EPSILON);
//assertEquals(0.15, postPoints[1].y, EPSILON);
assertEquals(0.5, postPoints[2].x, EPSILON);
//assertEquals(0.15, postPoints[2].y, EPSILON);
assertEquals(-0.05f, fins.getAxialOffset(), EPSILON);
assertEquals(0.5f, fins.getLength(), EPSILON);
}{ // case 5:
fins.setAxialOffset( AxialMethod.BOTTOM, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( 0, 0.1, 0.1f);
// ^^^^ function under test ^^^^
assertEquals(0.7, fins.getFinFront().x, EPSILON);
assertEquals(0.65, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid-point
assertEquals(0.3, postPoints[1].x, EPSILON);
//assertEquals(0.05, postPoints[1].y, EPSILON);
assertEquals(0.3, postPoints[2].x, EPSILON);
//assertEquals(0.15, postPoints[2].y, EPSILON);
assertEquals(0.0f, fins.getAxialOffset(), EPSILON);
assertEquals(0.3f, fins.getLength(), EPSILON);
}{ // case 6:
fins.setAxialOffset( AxialMethod.BOTTOM, 0.0);
fins.setPoints(initialPoints);
assertEquals(3, fins.getPointCount());
// vvvv function under test vvvv
fins.setPoint( 0, -0.1, 0.1f);
// ^^^^ function under test ^^^^
assertEquals(0.5, fins.getFinFront().x, EPSILON);
assertEquals(0.75, fins.getFinFront().y, EPSILON);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(3, postPoints.length);
// mid-point
assertEquals(0.5, postPoints[1].x, EPSILON);
assertEquals(0.15, postPoints[1].y, EPSILON);
assertEquals(0.5, postPoints[2].x, EPSILON);
assertEquals(-0.25, postPoints[2].y, EPSILON);
assertEquals(0.0f, fins.getAxialOffset(), EPSILON);
assertEquals(0.5f, fins.getLength(), EPSILON);
}
}
@Test
@ -516,140 +591,297 @@ public class FreeformFinSetTest extends BaseTestCase {
Transition finMount = (Transition) rkt.getChild(0).getChild(2);
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
final Coordinate[] initialPoints = fins.getFinPoints();
final int lastIndex = initialPoints.length - 1;
final double xf = initialPoints[lastIndex].x;
// assert pre-conditions:
assertEquals(0.4, fins.getLength(), EPSILON);
assertEquals(0.4, fins.getAxialFront(), EPSILON);
assertEquals(initialPoints[0], Coordinate.ZERO);
assertEquals(initialPoints[1], new Coordinate(0.4, 0.2));
assertEquals(initialPoints[2], new Coordinate(0.4, -0.2));
assertEquals(1.0, finMount.getLength(), EPSILON);
assertEquals(0.8, finMount.getRadius(fins.getAxialFront()), EPSILON);
final int lastIndex = initialPoints.length - 1;
// set to these positions
final AxialMethod[] inputMethods = {AxialMethod.TOP, AxialMethod.TOP, AxialMethod.MIDDLE, AxialMethod.MIDDLE, AxialMethod.BOTTOM, AxialMethod.BOTTOM};
final double[] inputOffsets = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
// set first point to this location...
final double[] xDelta= { 0.1, -0.1, 0.1, -0.1, 0.1, -0.1};
// and check against these expected values:
final double[] expectedFinStartx = { 0.0, 0.0, 0.3, 0.3, 0.6, 0.6};
final double[] expectedFinStarty = { 1.0, 1.0, 0.85, 0.85, 0.7, 0.7};
final double[] expectedFinOffset = { 0.0, 0.0, 0.05, -0.05, 0.0, -0.1};
final double[] expectedFinalPointOffset = { 0.5, 0.3, 0.5, 0.3, 0.4, 0.3};
for( int caseIndex=0; caseIndex < inputMethods.length; ++caseIndex ){
final double xRequest = initialPoints[lastIndex].x + xDelta[caseIndex];
final double yRequest = Double.NaN; // irrelevant; will be clamped to the body regardless
// this builds a string to describe this particular iteration, and provide useful output, should it fail.
StringBuilder buf = new StringBuilder();
buf.append(String.format("\n## For Case #%d: [%s]@%4.2f \n", caseIndex, inputMethods[caseIndex].name(), inputOffsets[caseIndex]));
buf.append(String.format(" >> setting last point to: ( %6.4f, %6.4f) \n", xRequest, yRequest));
final String dump = buf.toString();
fins.setAxialOffset( inputMethods[caseIndex], inputOffsets[caseIndex]);
{ // case 1:
fins.setAxialOffset( AxialMethod.TOP, 0.1);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xRequest, yRequest);
fins.setPoint( lastIndex, xf+0.2, -0.3f);
// ^^^^ function under test ^^^^
// System.err.println(String.format("@[%d]:", caseIndex));
// System.err.println(fins.toDebugDetail());
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
assertEquals("Fin offset not updated as expected..."+dump, expectedFinOffset[caseIndex], fins.getAxialOffset(), EPSILON);
assertEquals("Fin front not updated as expected..."+dump, expectedFinStartx[caseIndex], fins.getAxialFront(), EPSILON);
assertEquals("Fin front not updated as expected..."+dump, expectedFinStarty[caseIndex], fins.getFinFront().y, EPSILON);
// middle point:
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// last point:
assertEquals(0.6, postPoints[2].x, EPSILON);
assertEquals(-0.3, postPoints[2].y, EPSILON);
assertEquals(0.1, fins.getFinFront().x, EPSILON);
assertEquals(0.95, fins.getFinFront().y, EPSILON);
assertEquals(0.6, fins.getLength(), EPSILON);
}{ // case 2:
fins.setAxialOffset( AxialMethod.TOP, 0.1);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xf - 0.2, 0.1f);
// ^^^^ function under test ^^^^
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals("Middle fin point has moved!: "+dump, initialPoints[1].x, postPoints[1].x, EPSILON);
assertEquals("Final fin point has moved!: "+dump, expectedFinalPointOffset[caseIndex], postPoints[2].x, EPSILON);
assertEquals("Fin length not updated as expected..."+dump, expectedFinalPointOffset[caseIndex], fins.getLength(), EPSILON);
assertEquals(postPoints.length, 3);
// middle point:
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// last point:
assertEquals(0.2, postPoints[2].x, EPSILON);
assertEquals(-0.1, postPoints[2].y, EPSILON);
assertEquals(0.1, fins.getFinFront().x, EPSILON);
assertEquals(0.95, fins.getFinFront().y, EPSILON);
assertEquals(0.2f, fins.getLength(), EPSILON);
}{ // case 3:
fins.setAxialOffset( AxialMethod.MIDDLE, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xf + 0.1, 0.1f);
// ^^^^ function under test ^^^^
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid-point
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// last point
assertEquals(0.5, postPoints[2].x, EPSILON);
assertEquals(-0.25, postPoints[2].y, EPSILON);
assertEquals(0.3, fins.getFinFront().x, EPSILON);
assertEquals(0.85, fins.getFinFront().y, EPSILON);
assertEquals(0.05, fins.getAxialOffset(), EPSILON);
assertEquals(0.5, fins.getLength(), EPSILON);
}{ // case 4:
fins.setAxialOffset( AxialMethod.MIDDLE, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xf - 0.1, 0.1f);
// ^^^^ function under test ^^^^
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid point
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// last point
assertEquals(0.3, postPoints[2].x, EPSILON);
assertEquals(-0.15, postPoints[2].y, EPSILON);
assertEquals(0.3, fins.getFinFront().x, EPSILON);
assertEquals(0.85, fins.getFinFront().y, EPSILON);
assertEquals(-0.05, fins.getAxialOffset(), EPSILON);
assertEquals(0.3, fins.getLength(), EPSILON);
}{ // case 5:
fins.setAxialOffset( AxialMethod.BOTTOM, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xf + 0.1, 0.1f);
// ^^^^ function under test ^^^^
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 4);
// mid-point
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// pseudo last point
assertEquals(0.5, postPoints[2].x, EPSILON);
assertEquals(0.1, postPoints[2].y, EPSILON);
// last point
assertEquals(0.4, postPoints[3].x, EPSILON);
assertEquals(-0.2, postPoints[3].y, EPSILON);
assertEquals(0.6, fins.getFinFront().x, EPSILON);
assertEquals(0.7, fins.getFinFront().y, EPSILON);
assertEquals(0.0, fins.getAxialOffset(), EPSILON);
assertEquals(0.4f, fins.getLength(), EPSILON);
}{ // case 6:
fins.setAxialOffset( AxialMethod.BOTTOM, 0.0);
fins.setPoints(initialPoints);
// vvvv function under test vvvv
fins.setPoint( lastIndex, xf - 0.1, 0.1f);
// ^^^^ function under test ^^^^
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// mid-point
assertEquals(0.4, postPoints[1].x, EPSILON);
assertEquals(0.2, postPoints[1].y, EPSILON);
// last point
assertEquals(0.3, postPoints[2].x, EPSILON);
assertEquals(-0.15, postPoints[2].y, EPSILON);
assertEquals(0.6, fins.getFinFront().x, EPSILON);
assertEquals(0.7, fins.getFinFront().y, EPSILON);
assertEquals(-0.1, fins.getAxialOffset(), EPSILON);
assertEquals(0.3, fins.getLength(), EPSILON);
}
}
@Test
public void testSetInteriorPoint() {
final Rocket rkt = createTemplateRocket();
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
{ // preconditions // initial points
final Coordinate[] initialPoints = fins.getFinPoints();
assertEquals(initialPoints[0], Coordinate.ZERO);
assertEquals(initialPoints[1], new Coordinate(0.4, 0.2));
assertEquals(initialPoints[2], new Coordinate(0.4, -0.2));
assertEquals(0.4, fins.getLength(), EPSILON);
}{ // preconditions // mount
Transition finMount = (Transition) rkt.getChild(0).getChild(2);
assertEquals(0.4, fins.getFinFront().x, EPSILON);
assertEquals(0.8, fins.getFinFront().y, EPSILON);
assertEquals(0.8, finMount.getRadius(fins.getAxialFront()), EPSILON);
assertEquals(AxialMethod.TOP, fins.getAxialMethod());
assertEquals(0.4, fins.getAxialOffset(), EPSILON);
}{ // test target
final Coordinate p1 = fins.getFinPoints()[1];
// vvvv function under test vvvv
fins.setPoint( 1, p1.x + 0.1, p1.y + 0.1f);
// ^^^^ function under test ^^^^
}{ // postconditions
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(postPoints.length, 3);
// middle point:
assertEquals(0.5, postPoints[1].x, EPSILON);
assertEquals(0.3, postPoints[1].y, EPSILON);
// last point:
assertEquals(0.4, postPoints[2].x, EPSILON);
assertEquals(-0.2, postPoints[2].y, EPSILON);
assertEquals(0.4, fins.getLength(), EPSILON);
assertEquals(0.4, fins.getFinFront().x, EPSILON);
assertEquals(0.8, fins.getFinFront().y, EPSILON);
}
}
@Test
public void testSetAllPoints() {
final Rocket rkt = createTemplateRocket();
final AxialStage stage = (AxialStage) rkt.getChild(0);
{ // setup // mount
BodyTube body = new BodyTube(0.0, 1.0, 0.002);
body.setName("Phantom Body Tube");
body.setOuterRadiusAutomatic(true);
stage.addChild(body, 2);
assertEquals(1.0, body.getOuterRadius(), EPSILON);
assertEquals(0.0, body.getLength(), EPSILON);
FreeformFinSet fins = new FreeformFinSet();
fins.setFinCount(4);
Coordinate[] points = new Coordinate[]{
new Coordinate(0.0, 0.0),
new Coordinate(-0.0508, 0.007721),
new Coordinate(0.0, 0.01544),
new Coordinate(0.0254, 0.007721),
new Coordinate(1.1e-4, 0.0) // final point is within the testing thresholds :/
};
fins.setPoints(points);
body.addChild(fins);
}{ // postconditions
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
final Coordinate[] postPoints = fins.getFinPoints();
assertEquals(6, postPoints.length);
// p1
assertEquals(-0.0508, postPoints[1].x, EPSILON);
assertEquals(0.007721, postPoints[1].y, EPSILON);
// p2
assertEquals(0.0, postPoints[2].x, EPSILON);
assertEquals(0.01544, postPoints[2].y, EPSILON);
// p3
assertEquals(0.0254, postPoints[3].x, EPSILON);
assertEquals(0.007721, postPoints[3].y, EPSILON);
// p4
assertEquals(0.00011, postPoints[4].x, EPSILON);
assertEquals(0.0, postPoints[4].y, EPSILON);
// p/last: generated by loading code:
assertEquals(0.0, postPoints[5].x, EPSILON);
assertEquals(0.0, postPoints[5].y, EPSILON);
assertEquals(0.0, fins.getLength(), EPSILON);
assertEquals(0.0, fins.getFinFront().x, EPSILON);
assertEquals(1.0, fins.getFinFront().y, EPSILON);
}
}
@Test
public void testSetFirstPoint_testNonIntersection() {
final Rocket rkt = createTemplateRocket();
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
final FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
final Transition mount = (Transition) rkt.getChild(0).getChild(2);
assertEquals( 1, fins.getFinCount());
final int lastIndex = fins.getPointCount()-1;
assertEquals( 2, lastIndex);
final double initialOffset = fins.getAxialOffset();
assertEquals( 0.4, initialOffset, EPSILON); // pre-condition
assertEquals( 3, fins.getPointCount());
assertEquals( AxialMethod.TOP, fins.getAxialMethod());
assertEquals( 0.4, fins.getAxialOffset(), EPSILON); // pre-condition
assertEquals( 1.0, mount.getLength(), EPSILON);
final double attemptedDelta = 0.6;
fins.setPoint( 0, attemptedDelta, 0);
// fin offset: 0.4 -> 0.59 (just short of prev fin end)
// fin end: 0.4 ~> min root chord
// vv Test Target vv
fins.setPoint( 0, 0.6, 0);
// ^^ Test Target ^^
assertEquals(fins.getFinPoints()[ 0], Coordinate.ZERO);
// setting the first point actually offsets the whole fin by that amount:
final double expFinOffset = 0.79;
final double expFinOffset = 1.0;
assertEquals("Resultant fin offset does not match!", expFinOffset, fins.getAxialOffset(), EPSILON);
// SHOULD NOT CHANGE (in this case):
Coordinate actualLastPoint = fins.getFinPoints()[ lastIndex];
assertEquals("last point did not adjust correctly: ", FreeformFinSet.MIN_ROOT_CHORD, actualLastPoint.x, EPSILON);
assertEquals("last point did not adjust correctly: ", -0.005, actualLastPoint.y, EPSILON); // magic number
assertEquals("New fin length is wrong: ", FreeformFinSet.MIN_ROOT_CHORD, fins.getLength(), EPSILON);
}
@Test
public void testSetLastPoint_TubeBody() throws IllegalFinPointException {
Rocket rkt = createTemplateRocket();
// combine the simple case with the complicated to ensure that the simple case is
// flagged, tested, and debugged before running the more complicated case...
{ // setting points on a Tube Body is the simpler case. Test this first:
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(1).getChild(0);
// verify preconditions
assertEquals(AxialMethod.BOTTOM, fins.getAxialMethod());
assertEquals(0.0, fins.getAxialOffset(), EPSILON);
// last point is restricted to the body
final int lastIndex = fins.getPointCount()-1;
final Coordinate expectedFinalPoint = new Coordinate( 1.0, 0.0, 0.0);
// vvvv function under test vvvv
fins.setPoint( lastIndex, 10.0, Double.NaN);
// ^^^^ function under test ^^^^
Coordinate actualFinalPoint = fins.getFinPoints()[lastIndex];
assertEquals( expectedFinalPoint.x, actualFinalPoint.x, EPSILON);
assertEquals( expectedFinalPoint.y, actualFinalPoint.y, EPSILON);
}
{ // a transitions will trigger more complicated positioning math:
FreeformFinSet fins = (FreeformFinSet) rkt.getChild(0).getChild(2).getChild(0);
final int lastIndex = fins.getPointCount()-1;
Coordinate expectedLastPoint;
Coordinate actualLastPoint;
{ // this is where the point starts off at:
actualLastPoint = fins.getFinPoints()[lastIndex];
assertEquals( 0.4, actualLastPoint.x, EPSILON);
assertEquals( -0.2, actualLastPoint.y, EPSILON);
}
{ // (1): move point within bounds
// move last point, and verify that its y-value is still clamped to the body ( at the new location)
expectedLastPoint = new Coordinate( 0.6, -0.3, 0.0);
fins.setPoint(lastIndex, 0.6, 0.0); // w/ incorrect y-val. The function should correct the y-value as above.
actualLastPoint = fins.getFinPoints()[lastIndex];
assertEquals( expectedLastPoint.x, actualLastPoint.x, EPSILON);
assertEquals( expectedLastPoint.y, actualLastPoint.y, EPSILON);
}
}
assertEquals( 3, fins.getPointCount());
Coordinate actualLastPoint = fins.getFinPoints()[2];
assertEquals("last point did not adjust correctly: ", 0f, actualLastPoint.x, EPSILON);
assertEquals("last point did not adjust correctly: ", 0f, actualLastPoint.y, EPSILON);
assertEquals("New fin length is wrong: ", 0.0, fins.getLength(), EPSILON);
}
@Test
@ -785,7 +1017,7 @@ public class FreeformFinSetTest extends BaseTestCase {
}
@Test
public void testForNonIntersection() {
public void testForIntersection_false() {
final Rocket rkt = new Rocket();
final AxialStage stg = new AxialStage();
rkt.addChild(stg);
@ -814,7 +1046,7 @@ public class FreeformFinSetTest extends BaseTestCase {
}
@Test
public void testForIntersection() {
public void testForIntersection_true() {
final Rocket rkt = new Rocket();
final AxialStage stg = new AxialStage();
rkt.addChild(stg);
@ -849,6 +1081,53 @@ public class FreeformFinSetTest extends BaseTestCase {
assertThat( "Fin Set failed to detect an intersection! ", p1.y, not(equalTo(initPoints[1].y)));
}
@Test
public void testForIntersectionAtFirstLast() {
final Rocket rkt = new Rocket();
final AxialStage stg = new AxialStage();
rkt.addChild(stg);
BodyTube body = new BodyTube(2.0, 0.01);
stg.addChild(body);
//
// An obviously intersecting fin:
// [2] +---+ [1]
// | /
// | /
// [0]|/ [3]
// +---+-----+---+
// = +x =>
FreeformFinSet fins = new FreeformFinSet();
fins.setFinCount(1);
Coordinate[] initPoints = new Coordinate[] {
new Coordinate(0, 0),
new Coordinate(0, 1),
new Coordinate(1, 1),
new Coordinate(0, 0)
};
// this line throws an exception?
fins.setPoints(initPoints);
body.addChild(fins);
final Coordinate[] finPoints = fins.getFinPoints();
// p0
assertEquals("incorrect body points! ", 0., finPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", 0., finPoints[0].y, EPSILON);
// p1
assertEquals("incorrect body points! ", 0., finPoints[1].x, EPSILON);
assertEquals("incorrect body points! ", 1., finPoints[1].y, EPSILON);
// p2
assertEquals("incorrect body points! ", 1., finPoints[2].x, EPSILON);
assertEquals("incorrect body points! ", 1., finPoints[2].y, EPSILON);
// pf
assertEquals("incorrect body points! ", 0., finPoints[3].x, EPSILON);
assertEquals("incorrect body points! ", 0., finPoints[3].y, EPSILON);
}
@Test
public void testWildmanVindicatorShape() throws Exception {
@ -956,17 +1235,63 @@ public class FreeformFinSetTest extends BaseTestCase {
final Coordinate finFront = fins.getFinFront();
final Coordinate[] finPoints = fins.getFinPoints();
// translate from fin-frame to body-frame
final Coordinate[] finPointsFromBody = FinSet.translatePoints( fins.getFinPoints(), finFront.x, finFront.y );
final Coordinate expectedStartPoint = finPointsFromBody[0];
final Coordinate expectedEndPoint = finPointsFromBody[ finPoints.length-1];
{ // body points (relative to body)
final Coordinate[] bodyPoints = fins.getBodyPoints();
{ // fin points (relative to fin) // preconditions
assertEquals(4, finPoints.length);
assertEquals("incorrect body points! ", 0f, finPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", 0f, finPoints[0].y, EPSILON);
assertEquals("incorrect body points! ", 0.8, finPoints[3].x, EPSILON);
// ?? SMOKING GUN:
// ?? is this y-value of the fin not getting snapped to the body?
assertEquals(body.getRadius(0.8+finFront.x) - finFront.y, finPoints[3].y, EPSILON);
assertEquals("incorrect body points! ", 0.78466912, finPoints[3].y, EPSILON);
}{ // body points (relative to fin)
final Coordinate[] rootPoints = fins.getRootPoints();
assertEquals(101, rootPoints.length);
final int lastIndex = 100;
// trivial, and uninteresting:
assertEquals("incorrect body points! ", expectedStartPoint.x, bodyPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", expectedStartPoint.y, bodyPoints[0].y, EPSILON);
assertEquals("incorrect body points! ", finPoints[0].x, rootPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", finPoints[0].y, rootPoints[0].y, EPSILON);
// n.b.: This should match EXACTLY the end point of the fin. (in fin coordinates)
assertEquals("incorrect body points! ", finPoints[finPoints.length -1].x, rootPoints[lastIndex].x, EPSILON);
assertEquals("incorrect body points! ", finPoints[finPoints.length -1].y, rootPoints[lastIndex].y, EPSILON);
{// the tests within this scope is are rather fragile, and may break for reasons other than bugs :(
// the number of points is somewhat arbitrary, but if this test fails, the rest *definitely* will.
assertEquals("Method is generating how many points? ", 101, rootPoints.length );
final int[] testIndices = { 2, 5, 61, 88};
final double[] expectedX = { 0.016, 0.04, 0.488, 0.704};
for( int testCase = 0; testCase < testIndices.length; testCase++){
final int testIndex = testIndices[testCase];
assertEquals(String.format("Root points @ %d :: x coordinate mismatch!", testIndex),
expectedX[testCase], rootPoints[testIndex].x, EPSILON);
assertEquals(String.format("Root points @ %d :: y coordinate mismatch!", testIndex),
body.getRadius(rootPoints[testIndex].x + finFront.x) - finFront.y, rootPoints[testIndex].y, EPSILON);
}
}
}{ // body points (relative to body)
// translate from fin-frame to body-frame
final Coordinate[] finPointsFromBody = FinSet.translatePoints( fins.getFinPoints(), finFront.x, finFront.y );
final Coordinate[] bodyPoints = fins.getBodyPoints();
assertEquals(101, bodyPoints.length);
final Coordinate expectedEndPoint = finPointsFromBody[ finPoints.length-1];
// trivial, and uninteresting:
assertEquals("incorrect body points! ", finPointsFromBody[0].x, bodyPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", finPointsFromBody[0].y, bodyPoints[0].y, EPSILON);
// n.b.: This should match EXACTLY the end point of the fin. (in fin coordinates)
assertEquals("incorrect body points! ", expectedEndPoint.x, bodyPoints[bodyPoints.length-1].x, EPSILON);
@ -988,33 +1313,6 @@ public class FreeformFinSetTest extends BaseTestCase {
}
}
}
{ // body points (relative to fin)
final Coordinate[] rootPoints = fins.getRootPoints();
// trivial, and uninteresting:
assertEquals("incorrect body points! ", finPoints[0].x, rootPoints[0].x, EPSILON);
assertEquals("incorrect body points! ", finPoints[0].y, rootPoints[0].y, EPSILON);
// n.b.: This should match EXACTLY the end point of the fin. (in fin coordinates)
assertEquals("incorrect body points! ", finPoints[finPoints.length-1].x, rootPoints[rootPoints.length-1].x, EPSILON);
assertEquals("incorrect body points! ", finPoints[finPoints.length-1].y, rootPoints[rootPoints.length-1].y, EPSILON);
{// the tests within this scope is are rather fragile, and may break for reasons other than bugs :(
// the number of points is somewhat arbitrary, but if this test fails, the rest *definitely* will.
assertEquals("Method is generating how many points? ", 101, rootPoints.length );
final int[] testIndices = { 2, 5, 61, 88};
final double[] expectedX = { 0.016, 0.04, 0.488, 0.704};
for( int testCase = 0; testCase < testIndices.length; testCase++){
final int testIndex = testIndices[testCase];
assertEquals(String.format("Root points @ %d :: x coordinate mismatch!", testIndex),
expectedX[testCase], rootPoints[testIndex].x, EPSILON);
assertEquals(String.format("Root points @ %d :: y coordinate mismatch!", testIndex),
body.getRadius(rootPoints[testIndex].x + finFront.x) - finFront.y, rootPoints[testIndex].y, EPSILON);
}
}
}
}
@Test