1 package net.sf.openrocket.rocketcomponent;
3 import java.util.ArrayList;
6 import net.sf.openrocket.util.Coordinate;
9 public class FreeformFinSet extends FinSet {
11 private final List<Coordinate> points = new ArrayList<Coordinate>();
13 public FreeformFinSet() {
14 points.add(Coordinate.NUL);
15 points.add(new Coordinate(0.025,0.05));
16 points.add(new Coordinate(0.075,0.05));
17 points.add(new Coordinate(0.05,0));
23 public FreeformFinSet(FinSet finset) {
24 Coordinate[] finpoints = finset.getFinPoints();
25 this.copyFrom(finset);
28 for (Coordinate c: finpoints) {
31 this.length = points.get(points.size()-1).x - points.get(0).x;
37 * Add a fin point between indices <code>index-1</code> and <code>index</code>.
38 * The point is placed at the midpoint of the current segment.
40 * @param index the fin point before which to add the new point.
42 public void addPoint(int index) {
43 double x0, y0, x1, y1;
45 x0 = points.get(index-1).x;
46 y0 = points.get(index-1).y;
47 x1 = points.get(index).x;
48 y1 = points.get(index).y;
50 points.add(index, new Coordinate((x0+x1)/2, (y0+y1)/2));
51 // adding a point within the segment affects neither mass nor aerodynamics
52 fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
57 * Remove the fin point with the given index. The first and last fin points
58 * cannot be removed, and will cause an <code>IllegalArgumentException</code>
61 * @param index the fin point index to remove
62 * @throws IllegalFinPointException if removing the first or last fin point was attempted.
64 public void removePoint(int index) throws IllegalFinPointException {
65 if (index == 0 || index == points.size()-1) {
66 throw new IllegalFinPointException("cannot remove first or last point");
69 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
73 public int getPointCount() {
77 public void setPoints(Coordinate[] p) throws IllegalFinPointException {
78 if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].y != 0) {
79 throw new IllegalFinPointException("Start or end point illegal.");
81 for (int i=0; i < p.length-1; i++) {
82 for (int j=i+2; j < p.length-1; j++) {
83 if (intersects(p[i].x, p[i].y, p[i+1].x, p[i+1].y,
84 p[j].x, p[j].y, p[j+1].x, p[j+1].y)) {
85 throw new IllegalFinPointException("segments intersect");
89 throw new IllegalFinPointException("z-coordinate not zero");
94 for (Coordinate c: p) {
97 this.length = p[p.length-1].x;
98 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
103 * Set the point at position <code>i</code> to coordinates (x,y).
105 * Note that this method enforces basic fin shape restrictions (non-negative y,
106 * first and last point locations) silently, but throws an
107 * <code>IllegalArgumentException</code> if the point causes fin segments to
108 * intersect. The calling method should always catch this exception.
110 * Moving of the first point in the X-axis is allowed, but this actually moves
111 * all of the other points the corresponding distance back.
113 * @param index the point index to modify.
114 * @param x the x-coordinate.
115 * @param y the y-coordinate.
116 * @throws IllegalFinPointException if the specified fin point would cause intersecting
119 public void setPoint(int index, double x, double y) throws IllegalFinPointException {
128 x = Math.min(x, points.get(points.size()-1).x);
132 x1 = points.get(1).x;
133 y1 = points.get(1).y;
135 } else if (index == points.size()-1) {
140 x0 = points.get(index-1).x;
141 y0 = points.get(index-1).y;
147 x0 = points.get(index-1).x;
148 y0 = points.get(index-1).y;
149 x1 = points.get(index+1).x;
150 y1 = points.get(index+1).y;
156 // Check for intersecting
157 double px0, py0, px1, py1;
160 for (int i=1; i < points.size(); i++) {
161 px1 = points.get(i).x;
162 py1 = points.get(i).y;
164 if (i != index-1 && i != index && i != index+1) {
165 if (intersects(x0,y0,x,y,px0,py0,px1,py1)) {
166 throw new IllegalFinPointException("segments intersect");
169 if (i != index && i != index+1 && i != index+2) {
170 if (intersects(x,y,x1,y1,px0,py0,px1,py1)) {
171 throw new IllegalFinPointException("segments intersect");
181 System.out.println("Set point zero to x:"+x);
182 for (int i=1; i < points.size(); i++) {
183 Coordinate c = points.get(i);
184 points.set(i, c.setX(c.x - x));
189 points.set(index,new Coordinate(x,y));
192 if (index == 0 || index == points.size()-1) {
193 this.length = points.get(points.size()-1).x;
195 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
200 private boolean intersects(double ax0, double ay0, double ax1, double ay1,
201 double bx0, double by0, double bx1, double by1) {
203 double d = ((by1-by0)*(ax1-ax0) - (bx1-bx0)*(ay1-ay0));
205 double ua = ((bx1-bx0)*(ay0-by0) - (by1-by0)*(ax0-bx0)) / d;
206 double ub = ((ax1-ax0)*(ay0-by0) - (ay1-ay0)*(ax0-bx0)) / d;
208 return (ua >= 0) && (ua <= 1) && (ub >= 0) && (ub <= 1);
213 public Coordinate[] getFinPoints() {
214 return points.toArray(new Coordinate[0]);
218 public double getSpan() {
220 for (Coordinate c: points) {
228 public String getComponentName() {
229 return "Freeform fin set";