Initial commit
[debian/openrocket] / src / net / sf / openrocket / gui / rocketfigure / FinSetShapes.java
diff --git a/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java b/src/net/sf/openrocket/gui/rocketfigure/FinSetShapes.java
new file mode 100644 (file)
index 0000000..3d874a2
--- /dev/null
@@ -0,0 +1,296 @@
+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 c[] = finset.getFinPoints();
+
+               
+               // TODO: MEDIUM: sloping radius
+               double radius = finset.getBodyRadius();
+               
+               // Translate & rotate the coordinates
+               for (int i=0; i<c.length; i++) {
+                       c[i] = cantRotation.transform(c[i]);
+                       c[i] = baseRotation.transform(c[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<c.length; i++) {
+                               a = transformation.transform(finset.toAbsolute(c[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<c.length; i++)
+                               c[i] = finRotation.transform(c[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]);
+               }
+               
+        */
+}