create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / rocketfigure / SymmetricComponentShapes.java
1 package net.sf.openrocket.gui.rocketfigure;
2
3 import net.sf.openrocket.util.Coordinate;
4 import net.sf.openrocket.util.MathUtil;
5 import net.sf.openrocket.util.Transformation;
6
7 import java.awt.*;
8 import java.awt.geom.Path2D;
9 import java.util.ArrayList;
10
11
12 public class SymmetricComponentShapes extends RocketComponentShapes {
13         private static final int MINPOINTS = 91;
14         private static final double ACCEPTABLE_ANGLE = Math.cos(7.0 * Math.PI / 180.0);
15         
16         // TODO: HIGH: adaptiveness sucks, remove it.
17         
18         // TODO: LOW: Uses only first component of cluster (not currently clusterable)
19
20     public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
21                                         Transformation transformation) {
22         return getShapesSide(component, transformation, S);
23     }
24
25     public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
26                                         Transformation transformation, final double scaleFactor) {
27                 net.sf.openrocket.rocketcomponent.SymmetricComponent c = (net.sf.openrocket.rocketcomponent.SymmetricComponent) component;
28                 int i;
29                 
30                 final double delta = 0.0000001;
31                 double x;
32                 
33                 ArrayList<Coordinate> points = new ArrayList<Coordinate>();
34                 x = delta;
35                 points.add(new Coordinate(x, c.getRadius(x), 0));
36                 for (i = 1; i < MINPOINTS - 1; i++) {
37                         x = c.getLength() * i / (MINPOINTS - 1);
38                         points.add(new Coordinate(x, c.getRadius(x), 0));
39                         //System.out.println("Starting with x="+x);
40                 }
41                 x = c.getLength() - delta;
42                 points.add(new Coordinate(x, c.getRadius(x), 0));
43                 
44
45                 i = 0;
46                 while (i < points.size() - 2) {
47                         if (angleAcceptable(points.get(i), points.get(i + 1), points.get(i + 2)) ||
48                                         points.get(i + 1).x - points.get(i).x < 0.001) { // 1mm
49                                 i++;
50                                 continue;
51                         }
52                         
53                         // Split the longer of the areas
54                         int n;
55                         if (points.get(i + 2).x - points.get(i + 1).x > points.get(i + 1).x - points.get(i).x)
56                                 n = i + 1;
57                         else
58                                 n = i;
59                         
60                         x = (points.get(n).x + points.get(n + 1).x) / 2;
61                         points.add(n + 1, new Coordinate(x, c.getRadius(x), 0));
62                 }
63                 
64
65                 //System.out.println("Final points: "+points.size());
66                 
67                 final int len = points.size();
68                 
69                 for (i = 0; i < len; i++) {
70                         points.set(i, c.toAbsolute(points.get(i))[0]);
71                 }
72                 
73                 /*   Show points:
74                 Shape[] s = new Shape[len+1];
75                 final double d=0.001;
76                 for (i=0; i<len; i++) {
77                         s[i] = new Ellipse2D.Double(points.get(i).x()-d/2,points.get(i).y()-d/2,d,d);
78                 }
79                 */
80
81                 //System.out.println("here");
82                 
83                 // TODO: LOW: curved path instead of linear
84                 Path2D.Double path = new Path2D.Double();
85                 path.moveTo(points.get(len - 1).x * scaleFactor, points.get(len - 1).y * scaleFactor);
86                 for (i = len - 2; i >= 0; i--) {
87                         path.lineTo(points.get(i).x * scaleFactor, points.get(i).y * scaleFactor);
88                 }
89                 for (i = 0; i < len; i++) {
90                         path.lineTo(points.get(i).x * scaleFactor, -points.get(i).y * scaleFactor);
91                 }
92                 path.lineTo(points.get(len - 1).x * scaleFactor, points.get(len - 1).y * scaleFactor);
93                 path.closePath();
94                 
95                 //s[len] = path;
96                 //return s;
97                 return new Shape[] { path };
98         }
99         
100         private static boolean angleAcceptable(Coordinate v1, Coordinate v2, Coordinate v3) {
101                 return (cosAngle(v1, v2, v3) > ACCEPTABLE_ANGLE);
102         }
103         
104         /*
105          * cosAngle = v1.v2 / |v1|*|v2| = v1.v2 / sqrt(v1.v1*v2.v2)
106          */
107         private static double cosAngle(Coordinate v1, Coordinate v2, Coordinate v3) {
108                 double cos;
109                 double len;
110                 cos = Coordinate.dot(v1.sub(v2), v2.sub(v3));
111                 len = MathUtil.safeSqrt(v1.sub(v2).length2() * v2.sub(v3).length2());
112                 return cos / len;
113         }
114 }