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