Merge pull request #869 from teyrana/fix/868/fin-tab-offset
[fixes #868] Fin tabs correctly adjust their location when the fin tab _length_ is changed.
This commit is contained in:
commit
affcc8b51f
@ -71,7 +71,7 @@ public class EllipticalFinSet extends FinSet {
|
|||||||
if (MathUtil.equals(this.length, length))
|
if (MathUtil.equals(this.length, length))
|
||||||
return;
|
return;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
validateFinTab();
|
validateFinTabLength();
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
}
|
}
|
||||||
|
|
||||||
tabHeight = newTabHeight;
|
tabHeight = newTabHeight;
|
||||||
|
validateFinTabHeight();
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,9 +291,15 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
|
|
||||||
tabLength = lengthRequest;
|
tabLength = lengthRequest;
|
||||||
|
|
||||||
|
setTabPosition();
|
||||||
|
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setTabPosition(){
|
||||||
|
this.tabPosition = this.tabOffsetMethod.getAsPosition(tabOffset, tabLength, length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* internally, set the internal offset and optionally validate tab
|
* internally, set the internal offset and optionally validate tab
|
||||||
*
|
*
|
||||||
@ -301,7 +307,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
*/
|
*/
|
||||||
public void setTabOffset( final double offsetRequest) {
|
public void setTabOffset( final double offsetRequest) {
|
||||||
tabOffset = offsetRequest;
|
tabOffset = offsetRequest;
|
||||||
tabPosition = tabOffsetMethod.getAsPosition( tabOffset, tabLength, length);
|
setTabPosition();
|
||||||
|
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
}
|
}
|
||||||
@ -316,7 +322,8 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
*/
|
*/
|
||||||
public void setTabOffsetMethod(final AxialMethod newPositionMethod) {
|
public void setTabOffsetMethod(final AxialMethod newPositionMethod) {
|
||||||
this.tabOffsetMethod = newPositionMethod;
|
this.tabOffsetMethod = newPositionMethod;
|
||||||
this.tabOffset = tabOffsetMethod.getAsOffset( tabPosition, tabLength, length);
|
this.tabOffset = this.tabOffsetMethod.getAsOffset(tabPosition, tabLength, length);
|
||||||
|
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,9 +345,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
return tabPosition + tabLength;
|
return tabPosition + tabLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateFinTab(){
|
public void validateFinTabPosition() {
|
||||||
this.tabPosition = this.tabOffsetMethod.getAsPosition(tabOffset, tabLength, length);
|
|
||||||
|
|
||||||
//check front bounds:
|
//check front bounds:
|
||||||
if (tabPosition < 0) {
|
if (tabPosition < 0) {
|
||||||
this.tabPosition = 0;
|
this.tabPosition = 0;
|
||||||
@ -350,6 +355,11 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
if (this.length < tabPosition) {
|
if (this.length < tabPosition) {
|
||||||
this.tabPosition = length;
|
this.tabPosition = length;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateFinTabLength() {
|
||||||
|
//System.err.println(String.format(" >> Fin Tab Length: %.6f @ %.6f", tabLength, tabOffset));
|
||||||
|
|
||||||
final double xTabBack = getTabTrailingEdge();
|
final double xTabBack = getTabTrailingEdge();
|
||||||
if (this.length < xTabBack) {
|
if (this.length < xTabBack) {
|
||||||
this.tabLength -= (xTabBack - this.length);
|
this.tabLength -= (xTabBack - this.length);
|
||||||
@ -357,6 +367,10 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
|
|
||||||
tabLength = Math.max(0, tabLength);
|
tabLength = Math.max(0, tabLength);
|
||||||
|
|
||||||
|
//System.err.println(String.format(" << Fin Tab Length: %.6f @ %.6f", tabLength, tabOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateFinTabHeight(){
|
||||||
// check tab height
|
// check tab height
|
||||||
if( null != getParent() ){
|
if( null != getParent() ){
|
||||||
// pulls the parent-body radius at the fin-tab reference point.
|
// pulls the parent-body radius at the fin-tab reference point.
|
||||||
@ -791,6 +805,7 @@ public abstract class FinSet extends ExternalComponent implements AxialPositiona
|
|||||||
this.totalVolume = Double.NaN;
|
this.totalVolume = Double.NaN;
|
||||||
this.cantRotation = null;
|
this.cantRotation = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.componentChanged(e);
|
super.componentChanged(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ public class FreeformFinSet extends FinSet {
|
|||||||
clampLastPoint();
|
clampLastPoint();
|
||||||
|
|
||||||
if (oldLength != this.length)
|
if (oldLength != this.length)
|
||||||
validateFinTab();
|
validateFinTabLength();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +77,9 @@ public class TrapezoidFinSet extends FinSet {
|
|||||||
if (length == r)
|
if (length == r)
|
||||||
return;
|
return;
|
||||||
length = Math.max(r, 0);
|
length = Math.max(r, 0);
|
||||||
validateFinTab();
|
setTabPosition();
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
|
||||||
|
fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getTipChord() {
|
public double getTipChord() {
|
||||||
|
@ -3,6 +3,7 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import net.sf.openrocket.material.Material;
|
import net.sf.openrocket.material.Material;
|
||||||
|
import net.sf.openrocket.util.TestRockets;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.position.*;
|
import net.sf.openrocket.rocketcomponent.position.*;
|
||||||
@ -92,7 +93,7 @@ public class FinSetTest extends BaseTestCase {
|
|||||||
fins.setTabOffsetMethod( methods[caseIndex]);
|
fins.setTabOffsetMethod( methods[caseIndex]);
|
||||||
|
|
||||||
//query
|
//query
|
||||||
double actShift = fins.getTabOffset();
|
final double actShift = fins.getTabOffset();
|
||||||
assertEquals(String.format("Offset doesn't match for: %s \n", methods[caseIndex].name()), expShift[caseIndex], actShift, EPSILON);
|
assertEquals(String.format("Offset doesn't match for: %s \n", methods[caseIndex].name()), expShift[caseIndex], actShift, EPSILON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,25 +104,61 @@ public class FinSetTest extends BaseTestCase {
|
|||||||
assertEquals("incorrect fin length:", 0.06, fins.getLength(), EPSILON);
|
assertEquals("incorrect fin length:", 0.06, fins.getLength(), EPSILON);
|
||||||
assertEquals("incorrect fin tab length:", 0.02, fins.getTabLength(), EPSILON);
|
assertEquals("incorrect fin tab length:", 0.02, fins.getTabLength(), EPSILON);
|
||||||
|
|
||||||
// TOP -> native(TOP)
|
{ // TOP -> native(TOP)
|
||||||
fins.setTabOffsetMethod(AxialMethod.TOP);
|
fins.setTabOffsetMethod(AxialMethod.TOP);
|
||||||
fins.setTabOffset(0.0);
|
fins.setTabOffset(0.0);
|
||||||
|
|
||||||
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabFrontEdge(), EPSILON);
|
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabFrontEdge(), EPSILON);
|
||||||
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Setting by TOP method failed!", 0.02, fins.getTabLength(), EPSILON);
|
||||||
// MIDDLE -> native
|
}
|
||||||
|
{ // MIDDLE -> native
|
||||||
fins.setTabOffsetMethod(AxialMethod.MIDDLE);
|
fins.setTabOffsetMethod(AxialMethod.MIDDLE);
|
||||||
fins.setTabOffset(0.0);
|
fins.setTabOffset(0.0);
|
||||||
assertEquals("Setting by TOP method failed!", 0.02, fins.getTabFrontEdge(), EPSILON);
|
assertEquals("Setting by MIDDLE method failed!", 0.02, fins.getTabFrontEdge(), EPSILON);
|
||||||
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
assertEquals("Setting by MIDDLE method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.02, fins.getTabLength(), EPSILON);
|
||||||
// BOTTOM -> native
|
}
|
||||||
|
{// BOTTOM -> native
|
||||||
fins.setTabOffsetMethod(AxialMethod.BOTTOM);
|
fins.setTabOffsetMethod(AxialMethod.BOTTOM);
|
||||||
fins.setTabOffset(0.0);
|
fins.setTabOffset(0.0);
|
||||||
|
|
||||||
assertEquals("Setting by TOP method failed!", 0.04, fins.getTabFrontEdge(), EPSILON);
|
assertEquals("Setting by BOTTOM method failed!", 0.04, fins.getTabFrontEdge(), EPSILON);
|
||||||
assertEquals("Setting by TOP method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
assertEquals("Setting by BOTTOM method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Setting by BOTTOM method failed!", 0.02, fins.getTabLength(), EPSILON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTabSetLength() {
|
||||||
|
final Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
|
||||||
|
final BodyTube body = (BodyTube)rocket.getChild(0).getChild(1);
|
||||||
|
assertEquals("incorrect body tube length:", 0.20, body.getLength(), EPSILON);
|
||||||
|
|
||||||
|
final FinSet fins = (FinSet)body.getChild(0);
|
||||||
|
fins.setTabHeight(0.01);
|
||||||
|
fins.setTabLength(0.02);
|
||||||
|
assertEquals("incorrect fin length:", 0.05, fins.getLength(), EPSILON);
|
||||||
|
assertEquals("incorrect fin tab height:", 0.01, fins.getTabHeight(), EPSILON);
|
||||||
|
assertEquals("incorrect fin tab length:", 0.02, fins.getTabLength(), EPSILON);
|
||||||
|
assertEquals("incorrect fin location", 0.015, fins.getTabFrontEdge(), EPSILON);
|
||||||
|
|
||||||
|
{ // MIDDLE -> native
|
||||||
|
fins.setTabOffsetMethod(AxialMethod.MIDDLE);
|
||||||
|
fins.setTabOffset(0.0);
|
||||||
|
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.015, fins.getTabFrontEdge(), EPSILON);
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.02, fins.getTabLength(), EPSILON);
|
||||||
|
|
||||||
|
fins.setTabLength(0.04);
|
||||||
|
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.005, fins.getTabFrontEdge(), EPSILON);
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Setting by MIDDLE method failed!", 0.04, fins.getTabLength(), EPSILON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -139,8 +176,8 @@ public class FinSetTest extends BaseTestCase {
|
|||||||
|
|
||||||
((TrapezoidFinSet)fins).setRootChord(0.08);
|
((TrapezoidFinSet)fins).setRootChord(0.08);
|
||||||
|
|
||||||
assertEquals("Front edge doesn't match after adjusting root chord...", 0.03, fins.getTabFrontEdge(), EPSILON);
|
|
||||||
assertEquals("Offset doesn't match after adjusting root chord....", 0.0, fins.getTabOffset(), EPSILON);
|
assertEquals("Offset doesn't match after adjusting root chord....", 0.0, fins.getTabOffset(), EPSILON);
|
||||||
|
assertEquals("Front edge doesn't match after adjusting root chord...", 0.03, fins.getTabFrontEdge(), EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user