Merge pull request #621 from wolsen/fix-tube-fin-display

Fix TubeFinSet 2D rendering
This commit is contained in:
Daniel Williams 2020-07-25 23:15:22 -04:00 committed by GitHub
commit 6b609809e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 178 additions and 82 deletions

View File

@ -294,6 +294,10 @@ class DocumentConfig {
Reflection.findMethod(TubeFinSet.class, "setOuterRadius", double.class),
"auto",
Reflection.findMethod(TubeFinSet.class, "setOuterRadiusAutomatic", boolean.class)));
setters.put("TubeFinSet:instancecount", new IntSetter(
Reflection.findMethod(TubeFinSet.class, "setInstanceCount", int.class)));
setters.put("TubeFinSet:angleoffset", new AnglePositionSetter() );
setters.put("TubeFinSet:radiusoffset", new RadiusPositionSetter() );
// InternalComponent - nothing

View File

@ -7,14 +7,17 @@ import java.util.List;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.ComponentPreset.Type;
import net.sf.openrocket.rocketcomponent.position.AngleMethod;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BoundingBox;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Transformation;
public class TubeFinSet extends ExternalComponent implements AxialPositionable {
public class TubeFinSet extends ExternalComponent implements AxialPositionable, BoxBounded, RingInstanceable {
private static final Translator trans = Application.getTranslator();
private final static double DEFAULT_RADIUS = 0.025;
@ -22,18 +25,20 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
private boolean autoRadius = true; // Radius chosen automatically based on parent component
private double outerRadius = DEFAULT_RADIUS;
protected double thickness = 0.002;
protected int fins = 6;
private AngleMethod angleMethod = AngleMethod.FIXED;
protected RadiusMethod radiusMethod = RadiusMethod.RELATIVE;
/**
* Rotation angle of the first fin. Zero corresponds to the positive y-axis.
*/
protected double rotation = 0;
private double firstFinOffsetRadians = 0;
protected int fins = 6;
/**
* Rotation about the x-axis by angle this.rotation.
*/
protected Transformation baseRotation = Transformation.rotate_x(rotation);
protected Transformation baseRotation = Transformation.IDENTITY; // initially, rotate by 0 radians.
/**
* Rotation about the x-axis by 2*PI/fins.
@ -64,7 +69,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
}
/**
* Return the outer radius of the body tube.
* Return the outer radius of the tube-fin
*
* @return the outside radius of the tube
*/
@ -100,7 +105,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
}
/**
* Set the outer radius of the body tube. If the radius is less than the wall thickness,
* Set the outer radius of the tube-fin. If the radius is less than the wall thickness,
* the wall thickness is decreased accordingly of the value of the radius.
* This method sets the automatic radius off.
*
@ -168,7 +173,6 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
return fins;
}
@Override
public boolean isAfter(){
return false;
@ -195,7 +199,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
* @return The base rotation amount.
*/
public double getBaseRotation() {
return rotation;
return getAngleOffset();
}
public double getFinRotation() {
@ -207,12 +211,7 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
* @param r The base rotation amount.
*/
public void setBaseRotation(double r) {
r = MathUtil.reduce180(r);
if (MathUtil.equals(r, rotation))
return;
rotation = r;
baseRotation = Transformation.rotate_x(rotation);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
setAngleOffset(r);
}
public Transformation getBaseRotationTransformation() {
@ -316,6 +315,14 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
return bounds;
}
@Override
public BoundingBox getInstanceBoundingBox() {
BoundingBox box = new BoundingBox();
box.update(new Coordinate(0, -outerRadius, -outerRadius));
box.update(new Coordinate(length, outerRadius, outerRadius));
return box;
}
/**
* Return the radius of the BodyComponent the fin set is situated on. Currently
* only supports SymmetricComponents and returns the radius at the starting point of the
@ -327,9 +334,9 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
RocketComponent s;
s = this.getParent();
double x = this.getPosition().x;
while (s != null) {
if (s instanceof SymmetricComponent) {
double x = this.getPosition().x;
return ((SymmetricComponent) s).getRadius(x);
}
s = s.getParent();
@ -337,4 +344,113 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
return 0;
}
@Override
public int getInstanceCount() {
return getFinCount();
}
@Override
public void setInstanceCount(int newCount) {
setFinCount(newCount);
}
@Override
public String getPatternName() {
return (this.getInstanceCount() + "-tubefin-ring");
}
@Override
public double getBoundingRadius() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRadius(RadiusMethod method, double radius) {
// TODO Auto-generated method stub
}
@Override
public void setAngleOffset(double angleRadians) {
final double reducedAngle = MathUtil.reducePI(angleRadians);
if (MathUtil.equals(reducedAngle, firstFinOffsetRadians))
return;
firstFinOffsetRadians = reducedAngle;
if (MathUtil.equals(this.firstFinOffsetRadians, 0)) {
baseRotation = Transformation.IDENTITY;
} else {
baseRotation = Transformation.rotate_x(firstFinOffsetRadians);
}
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override
public AngleMethod getAngleMethod() {
return this.angleMethod;
}
@Override
public double getAngleOffset() {
return this.firstFinOffsetRadians;
}
@Override
public void setAngleMethod(AngleMethod newAngleMethod) {
mutex.verify();
this.angleMethod = newAngleMethod;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override
public double getInstanceAngleIncrement() {
return ( 2*Math.PI / getFinCount());
}
@Override
public double[] getInstanceAngles() {
final double angleIncrementRadians = getInstanceAngleIncrement();
double[] result = new double[getFinCount()];
for (int finNumber=0; finNumber < getFinCount(); ++finNumber) {
double additionalOffset = angleIncrementRadians * finNumber;
result[finNumber] = MathUtil.reduce2PI(firstFinOffsetRadians + additionalOffset);
}
return result;
}
@Override
public Coordinate[] getInstanceOffsets() {
checkState();
final double bodyRadius = this.getBodyRadius();
// already includes the base rotation
final double[] angles = getInstanceAngles();
Coordinate[] toReturn = new Coordinate[this.fins];
for (int instanceNumber = 0; instanceNumber < this.fins; instanceNumber++) {
final Coordinate raw = new Coordinate( 0, bodyRadius, 0);
final Coordinate rotated = Transformation.getAxialRotation(angles[instanceNumber]).transform(raw);
toReturn[instanceNumber] = rotated;
}
return toReturn;
}
@Override
public void setRadiusOffset(double radius) {
// TODO Auto-generated method stub
}
@Override
public void setRadiusMethod(RadiusMethod method) {
// TODO Auto-generated method stub
}
}

View File

@ -317,15 +317,8 @@ public class ComponentRenderer {
private void renderTubeFins(GL2 gl, TubeFinSet fs, Surface which) {
gl.glPushMatrix();
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
System.out.println(fs.getBaseRotation());
gl.glRotated(fs.getBaseRotation() * (180.0 / Math.PI), 1, 0, 0);
for( int i = 0; i< fs.getFinCount(); i++ ) {
gl.glPushMatrix();
gl.glTranslated(0, fs.getOuterRadius() + fs.getBodyRadius(), 0);
renderTube(gl, which, fs.getOuterRadius(), fs.getInnerRadius(), fs.getLength());
gl.glPopMatrix();
gl.glRotated(360.0 / fs.getFinCount(), 1, 0, 0);
}
gl.glTranslated(0, fs.getOuterRadius(), 0);
renderTube(gl, which, fs.getOuterRadius(), fs.getInnerRadius(), fs.getLength());
gl.glPopMatrix();
}

View File

@ -10,72 +10,55 @@ import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Transformation;
/**
* The TubeFinSetShapes is used for retrieving shapes of the TubeFins on a
* Rocket from multiple view points. The returned shapes will be translated
* and transformed to the correct locations for rendering the rocket in the
* 2D view space.
*/
public class TubeFinSetShapes extends RocketComponentShape {
/**
* Returns an array of RocketcomponentShapes that describe the shape of
* the TubeFinSet when viewed from the side of the rocket. TubeFins will
* appear as a Rectangle from the side view
*
* @param component the TubeFinSet to get the shapes for
* @param transformation the transformation to apply to the shapes
* @return an array of RocketComponentShapes that are used to draw the TubeFinSet from the side.
*/
public static RocketComponentShape[] getShapesSide( final RocketComponent component, final Transformation transformation) {
final TubeFinSet finSet = (TubeFinSet) component;
final double outerRadius = finSet.getOuterRadius();
final double length = finSet.getLength();
final Coordinate location = transformation.transform(new Coordinate(0, outerRadius, 0));
TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
final Shape[] shapes = new Shape[] {
new Rectangle2D.Double(location.x, (location.y-outerRadius), length, 2*outerRadius)
};
int fins = finset.getFinCount();
double length = finset.getLength();
double outerRadius = finset.getOuterRadius();
double bodyRadius = finset.getBodyRadius();
// old version - Oct, 19 2015
//Coordinate[] instanceOffsets = new Coordinate[]{ transformation.transform( componentAbsoluteLocation )};
//instanceOffsets = component.shiftCoordinates(instanceOffsets);
// new version
Coordinate[] start = transformation.transform( component.getLocations());
Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation();
// Translate & rotate the coordinates
for (int i=0; i<start.length; i++) {
start[i] = baseRotation.transform(transformation.transform(start[i].add(0,bodyRadius+outerRadius,0)));
}
//start = baseRotation.transform(start);
Shape[] s = new Shape[fins];
for (int i=0; i<fins; i++) {
s[i] = new Rectangle2D.Double(start[0].x,(start[0].y-outerRadius),length,2*outerRadius);
start = finRotation.transform(start);
}
return RocketComponentShape.toArray(s, component);
return RocketComponentShape.toArray(shapes, component);
}
/**
* Returns an array of RocketComponentShapes that describe the shape of
* the TubeFinSet when viewed from the rear or the rocket. TubeFins will
* appear as an Ellipse/Circle from the back view.
*
* @param component the TubeFinSet to get the shapes for
* @param transformation the transformation to apply to the shapes
* @return an array of RocketComponentShapes that are used to draw the
* TubeFinSet from the back
*/
public static RocketComponentShape[] getShapesBack( final RocketComponent component, final Transformation transformation) {
final TubeFinSet finSet = (TubeFinSet) component;
final double outerRadius = finSet.getOuterRadius();
final Coordinate location = transformation.transform(new Coordinate(0, outerRadius, 0));
TubeFinSet finset = (net.sf.openrocket.rocketcomponent.TubeFinSet)component;
final Shape[] shapes = new Shape[] {
new Ellipse2D.Double((location.z - outerRadius), (location.y - outerRadius), (2 * outerRadius), (2 * outerRadius))
};
int fins = finset.getFinCount();
double outerradius = finset.getOuterRadius();
double bodyradius = finset.getBodyRadius();
// old version - Oct, 19 2015
//Coordinate[] instanceOffsets = new Coordinate[]{ transformation.transform( componentAbsoluteLocation )};
//instanceOffsets = component.shiftCoordinates(instanceOffsets);
// new version
Coordinate[] start = transformation.transform( component.getLocations());
Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation();
// Translate & rotate the coordinates
for (int i=0; i<start.length; i++) {
start[i] = baseRotation.transform(transformation.transform(start[i].add(0,bodyradius+outerradius,0)));
}
Shape[] s = new Shape[fins];
for (int i=0; i < fins; i++) {
s[i] = new Ellipse2D.Double((start[0].z-outerradius),(start[0].y-outerradius),2*outerradius,2*outerradius);
start = finRotation.transform(start);
}
return RocketComponentShape.toArray(s, component);
return RocketComponentShape.toArray(shapes, component);
}
}