package net.sf.openrocket.gui.rocketfigure;
import java.awt.Shape;
import java.awt.geom.Path2D;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Transformation;
public class FinSetShapes extends RocketComponentShapes {
// TODO: LOW: Clustering is ignored (FinSet cannot currently be clustered)
public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
int fins = finset.getFinCount();
Transformation cantRotation = finset.getCantRotation();
Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation();
Coordinate finPoints[] = finset.getFinPointsWithTab();
// TODO: MEDIUM: sloping radius
double radius = finset.getBodyRadius();
// Translate & rotate the coordinates
for (int i=0; i<finPoints.length; i++) {
finPoints[i] = cantRotation.transform(finPoints[i]);
finPoints[i] = baseRotation.transform(finPoints[i].add(0,radius,0));
}
// Generate shapes
Shape[] s = new Shape[fins];
for (int fin=0; fin<fins; fin++) {
Coordinate a;
Path2D.Float p;
// Make polygon
p = new Path2D.Float();
for (int i=0; i<finPoints.length; i++) {
a = transformation.transform(finset.toAbsolute(finPoints[i])[0]);
if (i==0)
p.moveTo(a.x*S, a.y*S);
else
p.lineTo(a.x*S, a.y*S);
}
p.closePath();
s[fin] = p;
// Rotate fin coordinates
for (int i=0; i<finPoints.length; i++)
finPoints[i] = finRotation.transform(finPoints[i]);
}
return s;
}
public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
Transformation transformation) {
net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
if (MathUtil.equals(finset.getCantAngle(),0))
return uncantedShapesBack(finset, transformation);
else
return cantedShapesBack(finset, transformation);
}
private static Shape[] uncantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
Transformation transformation) {
int fins = finset.getFinCount();
double radius = finset.getBodyRadius();
double thickness = finset.getThickness();
double height = finset.getSpan();
Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation();
// Generate base coordinates for a single fin
Coordinate c[] = new Coordinate[4];
c[0]=new Coordinate(0,radius,-thickness/2);
c[1]=new Coordinate(0,radius,thickness/2);
c[2]=new Coordinate(0,height+radius,thickness/2);
c[3]=new Coordinate(0,height+radius,-thickness/2);
// Apply base rotation
transformPoints(c,baseRotation);
// Generate shapes
Shape[] s = new Shape[fins];
for (int fin=0; fin<fins; fin++) {
Coordinate a;
Path2D.Double p;
// Make polygon
p = new Path2D.Double();
a = transformation.transform(finset.toAbsolute(c[0])[0]);
p.moveTo(a.z*S, a.y*S);
a = transformation.transform(finset.toAbsolute(c[1])[0]);
p.lineTo(a.z*S, a.y*S);
a = transformation.transform(finset.toAbsolute(c[2])[0]);
p.lineTo(a.z*S, a.y*S);
a = transformation.transform(finset.toAbsolute(c[3])[0]);
p.lineTo(a.z*S, a.y*S);
p.closePath();
s[fin] = p;
// Rotate fin coordinates
transformPoints(c,finRotation);
}
return s;
}
// TODO: LOW: Jagged shapes from back draw incorrectly.
private static Shape[] cantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
Transformation transformation) {
int i;
int fins = finset.getFinCount();
double radius = finset.getBodyRadius();
double thickness = finset.getThickness();
Transformation baseRotation = finset.getBaseRotationTransformation();
Transformation finRotation = finset.getFinRotationTransformation();
Transformation cantRotation = finset.getCantRotation();
Coordinate[] sidePoints;
Coordinate[] backPoints;
int maxIndex;
Coordinate[] points = finset.getFinPoints();
for (maxIndex = points.length-1; maxIndex > 0; maxIndex--) {
if (points[maxIndex-1].y < points[maxIndex].y)
break;
}
transformPoints(points,cantRotation);
transformPoints(points,new Transformation(0,radius,0));
transformPoints(points,baseRotation);
sidePoints = new Coordinate[points.length];
backPoints = new Coordinate[2*(points.length-maxIndex)];
double sign;
if (finset.getCantAngle() > 0) {
sign = 1.0;
} else {
sign = -1.0;
}
// Calculate points for the side panel
for (i=0; i < points.length; i++) {
sidePoints[i] = points[i].add(0,0,sign*thickness/2);
}
// Calculate points for the back portion
i=0;
for (int j=points.length-1; j >= maxIndex; j--, i++) {
backPoints[i] = points[j].add(0,0,sign*thickness/2);
}
for (int j=maxIndex; j <= points.length-1; j++, i++) {
backPoints[i] = points[j].add(0,0,-sign*thickness/2);
}
// Generate shapes
Shape[] s;
if (thickness > 0.0005) {
s = new Shape[fins*2];
for (int fin=0; fin<fins; fin++) {
s[2*fin] = makePolygonBack(sidePoints,finset,transformation);
s[2*fin+1] = makePolygonBack(backPoints,finset,transformation);
// Rotate fin coordinates
transformPoints(sidePoints,finRotation);
transformPoints(backPoints,finRotation);
}
} else {
s = new Shape[fins];
for (int fin=0; fin<fins; fin++) {
s[fin] = makePolygonBack(sidePoints,finset,transformation);
transformPoints(sidePoints,finRotation);
}
}
return s;
}
private static void transformPoints(Coordinate[] array, Transformation t) {
for (int i=0; i < array.length; i++) {
array[i] = t.transform(array[i]);
}
}
private static Shape makePolygonBack(Coordinate[] array, net.sf.openrocket.rocketcomponent.FinSet finset,
Transformation t) {
Path2D.Float p;
// Make polygon
p = new Path2D.Float();
for (int i=0; i < array.length; i++) {
Coordinate a = t.transform(finset.toAbsolute(array[i])[0]);
if (i==0)
p.moveTo(a.z*S, a.y*S);
else
p.lineTo(a.z*S, a.y*S);
}
p.closePath();
return p;
}
/* Side painting with thickness:
Coordinate c[] = new Coordinate[8];
c[0]=new Coordinate(0-position*rootChord,radius,thickness/2);
c[1]=new Coordinate(rootChord-position*rootChord,radius,thickness/2);
c[2]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,thickness/2);
c[3]=new Coordinate(sweep-position*rootChord,height+radius,thickness/2);
c[4]=new Coordinate(0-position*rootChord,radius,-thickness/2);
c[5]=new Coordinate(rootChord-position*rootChord,radius,-thickness/2);
c[6]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,-thickness/2);
c[7]=new Coordinate(sweep-position*rootChord,height+radius,-thickness/2);
if (rotation != 0) {
rot = Transformation.rotate_x(rotation);
for (int i=0; i<8; i++)
c[i] = rot.transform(c[i]);
}
Shape[] s = new Shape[fins*6];
rot = Transformation.rotate_x(2*Math.PI/fins);
for (int fin=0; fin<fins; fin++) {
Coordinate a,b;
Path2D.Float p;
// First polygon
p = new Path2D.Float();
a = finset.toAbsolute(c[0]);
p.moveTo(a.x(), a.y());
a = finset.toAbsolute(c[1]);
p.lineTo(a.x(), a.y());
a = finset.toAbsolute(c[2]);
p.lineTo(a.x(), a.y());
a = finset.toAbsolute(c[3]);
p.lineTo(a.x(), a.y());
p.closePath();
s[fin*6] = p;
// Second polygon
p = new Path2D.Float();
a = finset.toAbsolute(c[4]);
p.moveTo(a.x(), a.y());
a = finset.toAbsolute(c[5]);
p.lineTo(a.x(), a.y());
a = finset.toAbsolute(c[6]);
p.lineTo(a.x(), a.y());
a = finset.toAbsolute(c[7]);
p.lineTo(a.x(), a.y());
p.closePath();
s[fin*6+1] = p;
// Single lines
for (int i=0; i<4; i++) {
a = finset.toAbsolute(c[i]);
b = finset.toAbsolute(c[i+4]);
s[fin*6+2+i] = new Line2D.Float((float)a.x(),(float)a.y(),(float)b.x(),(float)b.y());
}
// Rotate fin coordinates
for (int i=0; i<8; i++)
c[i] = rot.transform(c[i]);
}
*/
}