1 package net.sf.openrocket.gui.rocketfigure;
4 import java.awt.geom.Path2D;
6 import net.sf.openrocket.util.Coordinate;
7 import net.sf.openrocket.util.MathUtil;
8 import net.sf.openrocket.util.Transformation;
11 public class FinSetShapes extends RocketComponentShapes {
13 // TODO: LOW: Clustering is ignored (FinSet cannot currently be clustered)
15 public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
16 Transformation transformation) {
17 net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
20 int fins = finset.getFinCount();
21 Transformation cantRotation = finset.getCantRotation();
22 Transformation baseRotation = finset.getBaseRotationTransformation();
23 Transformation finRotation = finset.getFinRotationTransformation();
25 Coordinate c[] = finset.getFinPoints();
28 // TODO: MEDIUM: sloping radius
29 double radius = finset.getBodyRadius();
31 // Translate & rotate the coordinates
32 for (int i=0; i<c.length; i++) {
33 c[i] = cantRotation.transform(c[i]);
34 c[i] = baseRotation.transform(c[i].add(0,radius,0));
39 Shape[] s = new Shape[fins];
40 for (int fin=0; fin<fins; fin++) {
45 p = new Path2D.Float();
46 for (int i=0; i<c.length; i++) {
47 a = transformation.transform(finset.toAbsolute(c[i])[0]);
49 p.moveTo(a.x*S, a.y*S);
51 p.lineTo(a.x*S, a.y*S);
56 // Rotate fin coordinates
57 for (int i=0; i<c.length; i++)
58 c[i] = finRotation.transform(c[i]);
64 public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component,
65 Transformation transformation) {
67 net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
69 if (MathUtil.equals(finset.getCantAngle(),0))
70 return uncantedShapesBack(finset, transformation);
72 return cantedShapesBack(finset, transformation);
77 private static Shape[] uncantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
78 Transformation transformation) {
80 int fins = finset.getFinCount();
81 double radius = finset.getBodyRadius();
82 double thickness = finset.getThickness();
83 double height = finset.getSpan();
85 Transformation baseRotation = finset.getBaseRotationTransformation();
86 Transformation finRotation = finset.getFinRotationTransformation();
89 // Generate base coordinates for a single fin
90 Coordinate c[] = new Coordinate[4];
91 c[0]=new Coordinate(0,radius,-thickness/2);
92 c[1]=new Coordinate(0,radius,thickness/2);
93 c[2]=new Coordinate(0,height+radius,thickness/2);
94 c[3]=new Coordinate(0,height+radius,-thickness/2);
96 // Apply base rotation
97 transformPoints(c,baseRotation);
100 Shape[] s = new Shape[fins];
101 for (int fin=0; fin<fins; fin++) {
106 p = new Path2D.Double();
107 a = transformation.transform(finset.toAbsolute(c[0])[0]);
108 p.moveTo(a.z*S, a.y*S);
109 a = transformation.transform(finset.toAbsolute(c[1])[0]);
110 p.lineTo(a.z*S, a.y*S);
111 a = transformation.transform(finset.toAbsolute(c[2])[0]);
112 p.lineTo(a.z*S, a.y*S);
113 a = transformation.transform(finset.toAbsolute(c[3])[0]);
114 p.lineTo(a.z*S, a.y*S);
118 // Rotate fin coordinates
119 transformPoints(c,finRotation);
126 // TODO: LOW: Jagged shapes from back draw incorrectly.
127 private static Shape[] cantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
128 Transformation transformation) {
130 int fins = finset.getFinCount();
131 double radius = finset.getBodyRadius();
132 double thickness = finset.getThickness();
134 Transformation baseRotation = finset.getBaseRotationTransformation();
135 Transformation finRotation = finset.getFinRotationTransformation();
136 Transformation cantRotation = finset.getCantRotation();
138 Coordinate[] sidePoints;
139 Coordinate[] backPoints;
142 Coordinate[] points = finset.getFinPoints();
143 for (maxIndex = points.length-1; maxIndex > 0; maxIndex--) {
144 if (points[maxIndex-1].y < points[maxIndex].y)
148 transformPoints(points,cantRotation);
149 transformPoints(points,new Transformation(0,radius,0));
150 transformPoints(points,baseRotation);
153 sidePoints = new Coordinate[points.length];
154 backPoints = new Coordinate[2*(points.length-maxIndex)];
156 if (finset.getCantAngle() > 0) {
162 // Calculate points for the side panel
163 for (i=0; i < points.length; i++) {
164 sidePoints[i] = points[i].add(0,0,sign*thickness/2);
167 // Calculate points for the back portion
169 for (int j=points.length-1; j >= maxIndex; j--, i++) {
170 backPoints[i] = points[j].add(0,0,sign*thickness/2);
172 for (int j=maxIndex; j <= points.length-1; j++, i++) {
173 backPoints[i] = points[j].add(0,0,-sign*thickness/2);
178 if (thickness > 0.0005) {
180 s = new Shape[fins*2];
181 for (int fin=0; fin<fins; fin++) {
183 s[2*fin] = makePolygonBack(sidePoints,finset,transformation);
184 s[2*fin+1] = makePolygonBack(backPoints,finset,transformation);
186 // Rotate fin coordinates
187 transformPoints(sidePoints,finRotation);
188 transformPoints(backPoints,finRotation);
194 for (int fin=0; fin<fins; fin++) {
195 s[fin] = makePolygonBack(sidePoints,finset,transformation);
196 transformPoints(sidePoints,finRotation);
206 private static void transformPoints(Coordinate[] array, Transformation t) {
207 for (int i=0; i < array.length; i++) {
208 array[i] = t.transform(array[i]);
212 private static Shape makePolygonBack(Coordinate[] array, net.sf.openrocket.rocketcomponent.FinSet finset,
217 p = new Path2D.Float();
218 for (int i=0; i < array.length; i++) {
219 Coordinate a = t.transform(finset.toAbsolute(array[i])[0]);
221 p.moveTo(a.z*S, a.y*S);
223 p.lineTo(a.z*S, a.y*S);
230 /* Side painting with thickness:
232 Coordinate c[] = new Coordinate[8];
234 c[0]=new Coordinate(0-position*rootChord,radius,thickness/2);
235 c[1]=new Coordinate(rootChord-position*rootChord,radius,thickness/2);
236 c[2]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,thickness/2);
237 c[3]=new Coordinate(sweep-position*rootChord,height+radius,thickness/2);
239 c[4]=new Coordinate(0-position*rootChord,radius,-thickness/2);
240 c[5]=new Coordinate(rootChord-position*rootChord,radius,-thickness/2);
241 c[6]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,-thickness/2);
242 c[7]=new Coordinate(sweep-position*rootChord,height+radius,-thickness/2);
245 rot = Transformation.rotate_x(rotation);
246 for (int i=0; i<8; i++)
247 c[i] = rot.transform(c[i]);
250 Shape[] s = new Shape[fins*6];
251 rot = Transformation.rotate_x(2*Math.PI/fins);
253 for (int fin=0; fin<fins; fin++) {
258 p = new Path2D.Float();
259 a = finset.toAbsolute(c[0]);
260 p.moveTo(a.x(), a.y());
261 a = finset.toAbsolute(c[1]);
262 p.lineTo(a.x(), a.y());
263 a = finset.toAbsolute(c[2]);
264 p.lineTo(a.x(), a.y());
265 a = finset.toAbsolute(c[3]);
266 p.lineTo(a.x(), a.y());
271 p = new Path2D.Float();
272 a = finset.toAbsolute(c[4]);
273 p.moveTo(a.x(), a.y());
274 a = finset.toAbsolute(c[5]);
275 p.lineTo(a.x(), a.y());
276 a = finset.toAbsolute(c[6]);
277 p.lineTo(a.x(), a.y());
278 a = finset.toAbsolute(c[7]);
279 p.lineTo(a.x(), a.y());
284 for (int i=0; i<4; i++) {
285 a = finset.toAbsolute(c[i]);
286 b = finset.toAbsolute(c[i+4]);
287 s[fin*6+2+i] = new Line2D.Float((float)a.x(),(float)a.y(),(float)b.x(),(float)b.y());
290 // Rotate fin coordinates
291 for (int i=0; i<8; i++)
292 c[i] = rot.transform(c[i]);