create changelog entry
[debian/openrocket] / core / 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 finPoints[] = finset.getFinPointsWithTab();
26                 
27                 
28                 // TODO: MEDIUM: sloping radius
29                 double radius = finset.getBodyRadius();
30                 
31                 // Translate & rotate the coordinates
32                 for (int i=0; i<finPoints.length; i++) {
33                         finPoints[i] = cantRotation.transform(finPoints[i]);
34                         finPoints[i] = baseRotation.transform(finPoints[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<finPoints.length; i++) {
47                                 a = transformation.transform(finset.toAbsolute(finPoints[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                         
54                         p.closePath();
55                         s[fin] = p;
56
57                         // Rotate fin coordinates
58                         for (int i=0; i<finPoints.length; i++)
59                                 finPoints[i] = finRotation.transform(finPoints[i]);
60                 }
61                 
62                 return s;
63         }
64         
65         public static Shape[] getShapesBack(net.sf.openrocket.rocketcomponent.RocketComponent component, 
66                         Transformation transformation) {
67
68                 net.sf.openrocket.rocketcomponent.FinSet finset = (net.sf.openrocket.rocketcomponent.FinSet)component;
69
70                 if (MathUtil.equals(finset.getCantAngle(),0))
71                         return uncantedShapesBack(finset, transformation);
72                 else
73                         return cantedShapesBack(finset, transformation);
74                 
75         }
76         
77         
78         private static Shape[] uncantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
79                         Transformation transformation) {
80                 
81                 int fins = finset.getFinCount();
82                 double radius = finset.getBodyRadius();
83                 double thickness = finset.getThickness();
84                 double height = finset.getSpan();
85                 
86                 Transformation baseRotation = finset.getBaseRotationTransformation();
87                 Transformation finRotation = finset.getFinRotationTransformation();
88                 
89
90                 // Generate base coordinates for a single fin
91                 Coordinate c[] = new Coordinate[4];
92                 c[0]=new Coordinate(0,radius,-thickness/2);
93                 c[1]=new Coordinate(0,radius,thickness/2);
94                 c[2]=new Coordinate(0,height+radius,thickness/2);
95                 c[3]=new Coordinate(0,height+radius,-thickness/2);
96
97                 // Apply base rotation
98                 transformPoints(c,baseRotation);
99                 
100                 // Generate shapes
101                 Shape[] s = new Shape[fins];
102                 for (int fin=0; fin<fins; fin++) {
103                         Coordinate a;
104                         Path2D.Double p;
105
106                         // Make polygon
107                         p = new Path2D.Double();
108                         a = transformation.transform(finset.toAbsolute(c[0])[0]);
109                         p.moveTo(a.z*S, a.y*S);
110                         a = transformation.transform(finset.toAbsolute(c[1])[0]);
111                         p.lineTo(a.z*S, a.y*S);                 
112                         a = transformation.transform(finset.toAbsolute(c[2])[0]);
113                         p.lineTo(a.z*S, a.y*S);                 
114                         a = transformation.transform(finset.toAbsolute(c[3])[0]);
115                         p.lineTo(a.z*S, a.y*S); 
116                         p.closePath();
117                         s[fin] = p;
118
119                         // Rotate fin coordinates
120                         transformPoints(c,finRotation);
121                 }
122                 
123                 return s;
124         }
125         
126         
127         // TODO: LOW:  Jagged shapes from back draw incorrectly.
128         private static Shape[] cantedShapesBack(net.sf.openrocket.rocketcomponent.FinSet finset,
129                         Transformation transformation) {
130                 int i;
131                 int fins = finset.getFinCount();
132                 double radius = finset.getBodyRadius();
133                 double thickness = finset.getThickness();
134                 
135                 Transformation baseRotation = finset.getBaseRotationTransformation();
136                 Transformation finRotation = finset.getFinRotationTransformation();
137                 Transformation cantRotation = finset.getCantRotation();
138
139                 Coordinate[] sidePoints;
140                 Coordinate[] backPoints;
141                 int maxIndex;
142
143                 Coordinate[] points = finset.getFinPoints();
144                 for (maxIndex = points.length-1; maxIndex > 0; maxIndex--) {
145                         if (points[maxIndex-1].y < points[maxIndex].y)
146                                 break;
147                 }
148                 
149                 transformPoints(points,cantRotation);
150                 transformPoints(points,new Transformation(0,radius,0));
151                 transformPoints(points,baseRotation);
152                 
153                 
154                 sidePoints = new Coordinate[points.length];
155                 backPoints = new Coordinate[2*(points.length-maxIndex)];
156                 double sign;
157                 if (finset.getCantAngle() > 0) {
158                         sign = 1.0;
159                 } else {
160                         sign = -1.0;
161                 }                       
162                         
163                 // Calculate points for the side panel
164                 for (i=0; i < points.length; i++) {
165                         sidePoints[i] = points[i].add(0,0,sign*thickness/2);
166                 }
167
168                 // Calculate points for the back portion
169                 i=0;
170                 for (int j=points.length-1; j >= maxIndex; j--, i++) {
171                         backPoints[i] = points[j].add(0,0,sign*thickness/2);
172                 }
173                 for (int j=maxIndex; j <= points.length-1; j++, i++) {
174                         backPoints[i] = points[j].add(0,0,-sign*thickness/2);
175                 }
176                 
177                 // Generate shapes
178                 Shape[] s;
179                 if (thickness > 0.0005) {
180                         
181                         s = new Shape[fins*2];
182                         for (int fin=0; fin<fins; fin++) {
183                                 
184                                 s[2*fin] = makePolygonBack(sidePoints,finset,transformation);
185                                 s[2*fin+1] = makePolygonBack(backPoints,finset,transformation);
186                                 
187                                 // Rotate fin coordinates
188                                 transformPoints(sidePoints,finRotation);
189                                 transformPoints(backPoints,finRotation);
190                         }
191                         
192                 } else {
193                         
194                         s = new Shape[fins];
195                         for (int fin=0; fin<fins; fin++) {
196                                 s[fin] = makePolygonBack(sidePoints,finset,transformation);
197                                 transformPoints(sidePoints,finRotation);
198                         }
199                         
200                 }
201                 
202                 return s;
203         }
204         
205         
206         
207         private static void transformPoints(Coordinate[] array, Transformation t) {
208                 for (int i=0; i < array.length; i++) {
209                         array[i] = t.transform(array[i]);
210                 }
211         }
212         
213         private static Shape makePolygonBack(Coordinate[] array, net.sf.openrocket.rocketcomponent.FinSet finset, 
214                         Transformation t) {
215                 Path2D.Float p;
216
217                 // Make polygon
218                 p = new Path2D.Float();
219                 for (int i=0; i < array.length; i++) {
220                         Coordinate a = t.transform(finset.toAbsolute(array[i])[0]);
221                         if (i==0)
222                                 p.moveTo(a.z*S, a.y*S);
223                         else
224                                 p.lineTo(a.z*S, a.y*S);                 
225                 }
226                 p.closePath();
227                 return p;
228         }
229         
230         
231         /*  Side painting with thickness:
232
233                 Coordinate c[] = new Coordinate[8];
234                 
235                 c[0]=new Coordinate(0-position*rootChord,radius,thickness/2);
236                 c[1]=new Coordinate(rootChord-position*rootChord,radius,thickness/2);
237                 c[2]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,thickness/2);
238                 c[3]=new Coordinate(sweep-position*rootChord,height+radius,thickness/2);
239                 
240                 c[4]=new Coordinate(0-position*rootChord,radius,-thickness/2);
241                 c[5]=new Coordinate(rootChord-position*rootChord,radius,-thickness/2);
242                 c[6]=new Coordinate(sweep+tipChord-position*rootChord,height+radius,-thickness/2);
243                 c[7]=new Coordinate(sweep-position*rootChord,height+radius,-thickness/2);
244                 
245                 if (rotation != 0) {
246                         rot = Transformation.rotate_x(rotation);
247                         for (int i=0; i<8; i++)
248                                 c[i] = rot.transform(c[i]);
249                 }
250                 
251                 Shape[] s = new Shape[fins*6];
252                 rot = Transformation.rotate_x(2*Math.PI/fins);
253                 
254                 for (int fin=0; fin<fins; fin++) {
255                         Coordinate a,b;
256                         Path2D.Float p;
257
258                         // First polygon
259                         p = new Path2D.Float();
260                         a = finset.toAbsolute(c[0]);
261                         p.moveTo(a.x(), a.y());
262                         a = finset.toAbsolute(c[1]);
263                         p.lineTo(a.x(), a.y());                 
264                         a = finset.toAbsolute(c[2]);
265                         p.lineTo(a.x(), a.y());                 
266                         a = finset.toAbsolute(c[3]);
267                         p.lineTo(a.x(), a.y()); 
268                         p.closePath();
269                         s[fin*6] = p;
270                         
271                         // Second polygon
272                         p = new Path2D.Float();
273                         a = finset.toAbsolute(c[4]);
274                         p.moveTo(a.x(), a.y());
275                         a = finset.toAbsolute(c[5]);
276                         p.lineTo(a.x(), a.y());                 
277                         a = finset.toAbsolute(c[6]);
278                         p.lineTo(a.x(), a.y());                 
279                         a = finset.toAbsolute(c[7]);
280                         p.lineTo(a.x(), a.y()); 
281                         p.closePath();
282                         s[fin*6+1] = p;
283                         
284                         // Single lines
285                         for (int i=0; i<4; i++) {
286                                 a = finset.toAbsolute(c[i]);
287                                 b = finset.toAbsolute(c[i+4]);
288                                 s[fin*6+2+i] = new Line2D.Float((float)a.x(),(float)a.y(),(float)b.x(),(float)b.y());
289                         }
290
291                         // Rotate fin coordinates
292                         for (int i=0; i<8; i++)
293                                 c[i] = rot.transform(c[i]);
294                 }
295                 
296          */
297 }