updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / rocketcomponent / FreeformFinSet.java
index 1ea92caee2f879f7f3ea908885bebfd5018b8137..d5275db88857c1072153fb7f326fa3047e0a87c6 100644 (file)
@@ -1,14 +1,13 @@
 package net.sf.openrocket.rocketcomponent;
 
 import java.util.ArrayList;
-import java.util.List;
 
 import net.sf.openrocket.util.Coordinate;
 
 
 public class FreeformFinSet extends FinSet {
 
-       private final List<Coordinate> points = new ArrayList<Coordinate>();
+       private ArrayList<Coordinate> points = new ArrayList<Coordinate>();
        
        public FreeformFinSet() {
                points.add(Coordinate.NUL);
@@ -19,7 +18,16 @@ public class FreeformFinSet extends FinSet {
                this.length = 0.05;
        }
        
-       
+
+       public FreeformFinSet(Coordinate[] finpoints) {
+               points.clear();
+               for (Coordinate c: finpoints) {
+                       points.add(c);
+               }
+               this.length = points.get(points.size()-1).x - points.get(0).x;
+       }
+
+       /*
        public FreeformFinSet(FinSet finset) {
                Coordinate[] finpoints = finset.getFinPoints();
                this.copyFrom(finset);
@@ -30,8 +38,69 @@ public class FreeformFinSet extends FinSet {
                }
                this.length = points.get(points.size()-1).x - points.get(0).x;
        }
+       */
        
        
+       /**
+        * Convert an existing fin set into a freeform fin set.  The specified
+        * fin set is taken out of the rocket tree (if any) and the new component
+        * inserted in its stead.
+        * <p>
+        * The specified fin set should not be used after the call!
+        * 
+        * @param finset        the fin set to convert.
+        * @return                      the new freeform fin set.
+        */
+       public static FreeformFinSet convertFinSet(FinSet finset) {
+               final RocketComponent root = finset.getRoot();
+               FreeformFinSet freeform;
+               
+               try {
+                       if (root instanceof Rocket) {
+                               ((Rocket)root).freeze();
+                       }
+
+                       // Get fin set position and remove fin set
+                       final RocketComponent parent = finset.getParent();
+                       final int position;
+                       if (parent != null) {
+                               position = parent.getChildPosition(finset);
+                               parent.removeChild(position);
+                       } else {
+                               position = -1;
+                       }
+
+                       
+                       // Create the freeform fin set
+                       Coordinate[] finpoints = finset.getFinPoints();
+                       freeform = new FreeformFinSet(finpoints);
+
+                       // Copy component attributes
+                       freeform.copyFrom(finset);
+                       
+                       // Set name
+                       final String componentTypeName = finset.getComponentName();
+                       final String name = freeform.getName();
+
+                       if (name.startsWith(componentTypeName)) {
+                               freeform.setName(freeform.getComponentName() + 
+                                               name.substring(componentTypeName.length()));
+                       }
+
+                       // Add freeform fin set to parent
+                       if (parent != null) {
+                               parent.addChild(freeform, position);
+                       }
+
+               } finally {
+                       if (root instanceof Rocket) {
+                               ((Rocket)root).thaw();
+                       }
+               }
+               return freeform;
+       }
+
+       
        
        /**
         * Add a fin point between indices <code>index-1</code> and <code>index</code>.
@@ -59,10 +128,11 @@ public class FreeformFinSet extends FinSet {
         * if attempted.
         * 
         * @param index   the fin point index to remove
+        * @throws IllegalFinPointException if removing the first or last fin point was attempted.
         */
-       public void removePoint(int index) {
+       public void removePoint(int index) throws IllegalFinPointException {
                if (index == 0  ||  index == points.size()-1) {
-                       throw new IllegalArgumentException("cannot remove first or last point");
+                       throw new IllegalFinPointException("cannot remove first or last point");
                }
                points.remove(index);
                fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
@@ -73,19 +143,19 @@ public class FreeformFinSet extends FinSet {
                return points.size();
        }
        
-       public void setPoints(Coordinate[] p) {
+       public void setPoints(Coordinate[] p) throws IllegalFinPointException {
                if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].y != 0) {
-                       throw new IllegalArgumentException("Start or end point illegal.");
+                       throw new IllegalFinPointException("Start or end point illegal.");
                }
                for (int i=0; i < p.length-1; i++) {
                        for (int j=i+2; j < p.length-1; j++) {
                                if (intersects(p[i].x, p[i].y, p[i+1].x, p[i+1].y,
                                                       p[j].x, p[j].y, p[j+1].x, p[j+1].y)) {
-                                       throw new IllegalArgumentException("segments intersect");
+                                       throw new IllegalFinPointException("segments intersect");
                                }
                        }
                        if (p[i].z != 0) {
-                               throw new IllegalArgumentException("z-coordinate not zero");
+                               throw new IllegalFinPointException("z-coordinate not zero");
                        }
                }
                
@@ -112,8 +182,10 @@ public class FreeformFinSet extends FinSet {
         * @param index the point index to modify.
         * @param x             the x-coordinate.
         * @param y             the y-coordinate.
+        * @throws IllegalFinPointException     if the specified fin point would cause intersecting
+        *                                                                      segments
         */
-       public void setPoint(int index, double x, double y) {
+       public void setPoint(int index, double x, double y) throws IllegalFinPointException {
                if (y < 0)
                        y = 0;
                
@@ -160,12 +232,12 @@ public class FreeformFinSet extends FinSet {
                        
                        if (i != index-1 && i != index && i != index+1) {
                                if (intersects(x0,y0,x,y,px0,py0,px1,py1)) {
-                                       throw new IllegalArgumentException("segments intersect");
+                                       throw new IllegalFinPointException("segments intersect");
                                }
                        }
                        if (i != index && i != index+1 && i != index+2) {
                                if (intersects(x,y,x1,y1,px0,py0,px1,py1)) {
-                                       throw new IllegalArgumentException("segments intersect");
+                                       throw new IllegalFinPointException("segments intersect");
                                }
                        }
                        
@@ -226,4 +298,13 @@ public class FreeformFinSet extends FinSet {
                return "Freeform fin set";
        }
 
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public RocketComponent copy() {
+               RocketComponent c = super.copy();
+               ((FreeformFinSet)c).points = (ArrayList<Coordinate>) this.points.clone();
+               return c;
+       }
+
 }