1 package net.sf.openrocket.gui.rocketfigure;
3 import net.sf.openrocket.util.Coordinate;
4 import net.sf.openrocket.util.MathUtil;
5 import net.sf.openrocket.util.Transformation;
8 import java.awt.geom.Path2D;
9 import java.util.ArrayList;
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);
16 // TODO: HIGH: adaptiveness sucks, remove it.
18 // TODO: LOW: Uses only first component of cluster (not currently clusterable)
20 public static Shape[] getShapesSide(net.sf.openrocket.rocketcomponent.RocketComponent component,
21 Transformation transformation) {
22 return getShapesSide(component, transformation, S);
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;
30 final double delta = 0.0000001;
33 ArrayList<Coordinate> points = new ArrayList<Coordinate>();
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);
41 x = c.getLength() - delta;
42 points.add(new Coordinate(x, c.getRadius(x), 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
53 // Split the longer of the areas
55 if (points.get(i + 2).x - points.get(i + 1).x > points.get(i + 1).x - points.get(i).x)
60 x = (points.get(n).x + points.get(n + 1).x) / 2;
61 points.add(n + 1, new Coordinate(x, c.getRadius(x), 0));
65 //System.out.println("Final points: "+points.size());
67 final int len = points.size();
69 for (i = 0; i < len; i++) {
70 points.set(i, c.toAbsolute(points.get(i))[0]);
74 Shape[] s = new Shape[len+1];
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);
81 //System.out.println("here");
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);
89 for (i = 0; i < len; i++) {
90 path.lineTo(points.get(i).x * scaleFactor, -points.get(i).y * scaleFactor);
92 path.lineTo(points.get(len - 1).x * scaleFactor, points.get(len - 1).y * scaleFactor);
97 return new Shape[] { path };
100 private static boolean angleAcceptable(Coordinate v1, Coordinate v2, Coordinate v3) {
101 return (cosAngle(v1, v2, v3) > ACCEPTABLE_ANGLE);
105 * cosAngle = v1.v2 / |v1|*|v2| = v1.v2 / sqrt(v1.v1*v2.v2)
107 private static double cosAngle(Coordinate v1, Coordinate v2, Coordinate v3) {
110 cos = Coordinate.dot(v1.sub(v2), v2.sub(v3));
111 len = MathUtil.safeSqrt(v1.sub(v2).length2() * v2.sub(v3).length2());