Initial commit
[debian/openrocket] / src / net / sf / openrocket / gui / rocketfigure / FinSetShapes.java
1 package net.sf.openrocket.gui.rocketfigure;
2
3 import java.awt.Shape;
4 import java.awt.geom.Path2D;
5
6 import net.sf.openrocket.util.Coordinate;
7 import net.sf.openrocket.util.MathUtil;
8 import net.sf.openrocket.util.Transformation;
9
10
11 public class FinSetShapes extends RocketComponentShapes {
12
13         // TODO: LOW:  Clustering is ignored (FinSet cannot currently be clustered)
14
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;
18
19                 
20                 int fins = finset.getFinCount();
21                 Transformation cantRotation = finset.getCantRotation();
22                 Transformation baseRotation = finset.getBaseRotationTransformation();
23                 Transformation finRotation = finset.getFinRotationTransformation();
24                 
25                 Coordinate c[] = finset.getFinPoints();
26
27                 
28                 // TODO: MEDIUM: sloping radius
29                 double radius = finset.getBodyRadius();
30                 
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));
35                 }
36                 
37                 
38                 // Generate shapes
39                 Shape[] s = new Shape[fins];
40                 for (int fin=0; fin<fins; fin++) {
41                         Coordinate a;
42                         Path2D.Float p;
43
44                         // Make polygon
45                         p = new Path2D.Float();
46                         for (int i=0; i<c.length; i++) {
47                                 a = transformation.transform(finset.toAbsolute(c[i])[0]);
48                                 if (i==0)
49                                         p.moveTo(a.x*S, a.y*S);
50                                 else
51                                         p.lineTo(a.x*S, a.y*S);                 
52                         }
53                         p.closePath();
54                         s[fin] = p;
55
56                         // Rotate fin coordinates
57                         for (int i=0; i<c.length; i++)
58                                 c[i] = finRotation.transform(c[i]);
59                 }
60                 
61                 return s;
62         }
63         
64         public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, 
65                         Transformation transformation) {
66
67                 net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
68
69                 if (MathUtil.equals(finset.getCantAngle(),0))
70                         return uncantedShapesBack(finset, transformation);
71                 else
72                         return cantedShapesBack(finset, transformation);
73                 
74         }
75         
76         
77         private static Shape[] uncantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
78                         Transformation transformation) {
79                 
80                 int fins = finset.getFinCount();
81                 double radius = finset.getBodyRadius();
82                 double thickness = finset.getThickness();
83                 double height = finset.getSpan();
84                 
85                 Transformation baseRotation = finset.getBaseRotationTransformation();
86                 Transformation finRotation = finset.getFinRotationTransformation();
87                 
88
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);
95
96                 // Apply base rotation
97                 transformPoints(c,baseRotation);
98                 
99                 // Generate shapes
100                 Shape[] s = new Shape[fins];
101                 for (int fin=0; fin<fins; fin++) {
102                         Coordinate a;
103                         Path2D.Double p;
104
105                         // Make polygon
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); 
115                         p.closePath();
116                         s[fin] = p;
117
118                         // Rotate fin coordinates
119                         transformPoints(c,finRotation);
120                 }
121                 
122                 return s;
123         }
124         
125         
126         // TODO: LOW:  Jagged shapes from back draw incorrectly.
127         private static Shape[] cantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
128                         Transformation transformation) {
129                 int i;
130                 int fins = finset.getFinCount();
131                 double radius = finset.getBodyRadius();
132                 double thickness = finset.getThickness();
133                 
134                 Transformation baseRotation = finset.getBaseRotationTransformation();
135                 Transformation finRotation = finset.getFinRotationTransformation();
136                 Transformation cantRotation = finset.getCantRotation();
137
138                 Coordinate[] sidePoints;
139                 Coordinate[] backPoints;
140                 int maxIndex;
141
142                 Coordinate[] points = finset.getFinPoints();
143                 for (maxIndex = points.length-1; maxIndex > 0; maxIndex--) {
144                         if (points[maxIndex-1].y < points[maxIndex].y)
145                                 break;
146                 }
147                 
148                 transformPoints(points,cantRotation);
149                 transformPoints(points,new Transformation(0,radius,0));
150                 transformPoints(points,baseRotation);
151                 
152                 
153                 sidePoints = new Coordinate[points.length];
154                 backPoints = new Coordinate[2*(points.length-maxIndex)];
155                 double sign;
156                 if (finset.getCantAngle() > 0) {
157                         sign = 1.0;
158                 } else {
159                         sign = -1.0;
160                 }                       
161                         
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);
165                 }
166
167                 // Calculate points for the back portion
168                 i=0;
169                 for (int j=points.length-1; j >= maxIndex; j--, i++) {
170                         backPoints[i] = points[j].add(0,0,sign*thickness/2);
171                 }
172                 for (int j=maxIndex; j <= points.length-1; j++, i++) {
173                         backPoints[i] = points[j].add(0,0,-sign*thickness/2);
174                 }
175                 
176                 // Generate shapes
177                 Shape[] s;
178                 if (thickness > 0.0005) {
179                         
180                         s = new Shape[fins*2];
181                         for (int fin=0; fin<fins; fin++) {
182                                 
183                                 s[2*fin] = makePolygonBack(sidePoints,finset,transformation);
184                                 s[2*fin+1] = makePolygonBack(backPoints,finset,transformation);
185                                 
186                                 // Rotate fin coordinates
187                                 transformPoints(sidePoints,finRotation);
188                                 transformPoints(backPoints,finRotation);
189                         }
190                         
191                 } else {
192                         
193                         s = new Shape[fins];
194                         for (int fin=0; fin<fins; fin++) {
195                                 s[fin] = makePolygonBack(sidePoints,finset,transformation);
196                                 transformPoints(sidePoints,finRotation);
197                         }
198                         
199                 }
200                 
201                 return s;
202         }
203         
204         
205         
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]);
209                 }
210         }
211         
212         private static Shape makePolygonBack(Coordinate[] array, net.sf.openrocket.rocketcomponent.FinSet finset, 
213                         Transformation t) {
214                 Path2D.Float p;
215
216                 // Make polygon
217                 p = new Path2D.Float();
218                 for (int i=0; i < array.length; i++) {
219                         Coordinate a = t.transform(finset.toAbsolute(array[i])[0]);
220                         if (i==0)
221                                 p.moveTo(a.z*S, a.y*S);
222                         else
223                                 p.lineTo(a.z*S, a.y*S);                 
224                 }
225                 p.closePath();
226                 return p;
227         }
228         
229         
230         /*  Side painting with thickness:
231
232                 Coordinate c[] = new Coordinate[8];
233                 
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);
238                 
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);
243                 
244                 if (rotation != 0) {
245                         rot = Transformation.rotate_x(rotation);
246                         for (int i=0; i<8; i++)
247                                 c[i] = rot.transform(c[i]);
248                 }
249                 
250                 Shape[] s = new Shape[fins*6];
251                 rot = Transformation.rotate_x(2*Math.PI/fins);
252                 
253                 for (int fin=0; fin<fins; fin++) {
254                         Coordinate a,b;
255                         Path2D.Float p;
256
257                         // First polygon
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()); 
267                         p.closePath();
268                         s[fin*6] = p;
269                         
270                         // Second polygon
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()); 
280                         p.closePath();
281                         s[fin*6+1] = p;
282                         
283                         // Single lines
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());
288                         }
289
290                         // Rotate fin coordinates
291                         for (int i=0; i<8; i++)
292                                 c[i] = rot.transform(c[i]);
293                 }
294                 
295          */
296 }