DGP - merged printing support from branch
[debian/openrocket] / src / net / sf / openrocket / rocketcomponent / FreeformFinSet.java
index 05862f3d4384e98593927d20f0d4ba4702411b6c..ce6402151bc646972bd055b34235c9e63f4cc378 100644 (file)
@@ -1,32 +1,33 @@
 package net.sf.openrocket.rocketcomponent;
 
-import java.util.ArrayList;
-
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.util.BugException;
 import net.sf.openrocket.util.Coordinate;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 
-public class FreeformFinSet extends FinSet {
 
+public class FreeformFinSet extends FinSet {
+       private static final LogHelper log = Application.getLogger();
+       
        private ArrayList<Coordinate> points = new ArrayList<Coordinate>();
        
        public FreeformFinSet() {
                points.add(Coordinate.NUL);
-               points.add(new Coordinate(0.025,0.05));
-               points.add(new Coordinate(0.075,0.05));
-               points.add(new Coordinate(0.05,0));
+               points.add(new Coordinate(0.025, 0.05));
+               points.add(new Coordinate(0.075, 0.05));
+               points.add(new Coordinate(0.05, 0));
                
                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(Coordinate[] finpoints) throws IllegalFinPointException {
+               setPoints(finpoints);
        }
-
+       
        /*
        public FreeformFinSet(FinSet finset) {
                Coordinate[] finpoints = finset.getFinPoints();
@@ -39,8 +40,8 @@ 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
@@ -52,14 +53,15 @@ public class FreeformFinSet extends FinSet {
         * @return                      the new freeform fin set.
         */
        public static FreeformFinSet convertFinSet(FinSet finset) {
+               log.info("Converting " + finset.getComponentName() + " into freeform fin set");
                final RocketComponent root = finset.getRoot();
                FreeformFinSet freeform;
                
                try {
                        if (root instanceof Rocket) {
-                               ((Rocket)root).freeze();
+                               ((Rocket) root).freeze();
                        }
-
+                       
                        // Get fin set position and remove fin set
                        final RocketComponent parent = finset.getParent();
                        final int position;
@@ -69,39 +71,45 @@ public class FreeformFinSet extends FinSet {
                        } else {
                                position = -1;
                        }
-
                        
+
                        // Create the freeform fin set
                        Coordinate[] finpoints = finset.getFinPoints();
-                       freeform = new FreeformFinSet(finpoints);
-
+                       try {
+                               freeform = new FreeformFinSet(finpoints);
+                       } catch (IllegalFinPointException e) {
+                               throw new BugException("Illegal fin points when converting existing fin to " +
+                                               "freeform fin, fin=" + finset + " points=" + Arrays.toString(finpoints),
+                                               e);
+                       }
+                       
                        // 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() + 
+                               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();
+                               ((Rocket) root).thaw();
                        }
                }
                return freeform;
        }
-
        
        
+
        /**
         * Add a fin point between indices <code>index-1</code> and <code>index</code>.
         * The point is placed at the midpoint of the current segment.
@@ -111,12 +119,12 @@ public class FreeformFinSet extends FinSet {
        public void addPoint(int index) {
                double x0, y0, x1, y1;
                
-               x0 = points.get(index-1).x;
-               y0 = points.get(index-1).y;
+               x0 = points.get(index - 1).x;
+               y0 = points.get(index - 1).y;
                x1 = points.get(index).x;
                y1 = points.get(index).y;
                
-               points.add(index, new Coordinate((x0+x1)/2, (y0+y1)/2));
+               points.add(index, new Coordinate((x0 + x1) / 2, (y0 + y1) / 2));
                // adding a point within the segment affects neither mass nor aerodynamics
                fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
        }
@@ -128,13 +136,19 @@ 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.
+        * @throws IllegalFinPointException if removing would result in invalid fin planform
         */
+       @SuppressWarnings("unchecked")
        public void removePoint(int index) throws IllegalFinPointException {
-               if (index == 0  ||  index == points.size()-1) {
+               if (index == 0 || index == points.size() - 1) {
                        throw new IllegalFinPointException("cannot remove first or last point");
                }
-               points.remove(index);
+               
+               ArrayList<Coordinate> copy = (ArrayList<Coordinate>) this.points.clone();
+               copy.remove(index);
+               validate(copy);
+               this.points = copy;
+               
                fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
        }
        
@@ -143,31 +157,19 @@ public class FreeformFinSet extends FinSet {
                return points.size();
        }
        
-       public void setPoints(Coordinate[] p) throws IllegalFinPointException {
-               if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].y != 0) {
-                       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 IllegalFinPointException("segments intersect");
-                               }
-                       }
-                       if (p[i].z != 0) {
-                               throw new IllegalFinPointException("z-coordinate not zero");
-                       }
+       public void setPoints(Coordinate[] points) throws IllegalFinPointException {
+               ArrayList<Coordinate> list = new ArrayList<Coordinate>(points.length);
+               for (Coordinate p : points) {
+                       list.add(p);
                }
+               validate(list);
+               this.points = list;
                
-               points.clear();
-               for (Coordinate c: p) {
-                       points.add(c);
-               }
-               this.length = p[p.length-1].x;
+               this.length = points[points.length - 1].x;
                fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
        }
        
-
+       
        /**
         * Set the point at position <code>i</code> to coordinates (x,y).
         * <p>
@@ -189,54 +191,54 @@ public class FreeformFinSet extends FinSet {
                if (y < 0)
                        y = 0;
                
-               double x0,y0,x1,y1;
+               double x0, y0, x1, y1;
                
                if (index == 0) {
                        
                        // Restrict point
-                       x = Math.min(x, points.get(points.size()-1).x);
+                       x = Math.min(x, points.get(points.size() - 1).x);
                        y = 0;
                        x0 = Double.NaN;
                        y0 = Double.NaN;
                        x1 = points.get(1).x;
                        y1 = points.get(1).y;
                        
-               } else if (index == points.size()-1) {
+               } else if (index == points.size() - 1) {
                        
                        // Restrict point
                        x = Math.max(x, 0);
                        y = 0;
-                       x0 = points.get(index-1).x;
-                       y0 = points.get(index-1).y;
+                       x0 = points.get(index - 1).x;
+                       y0 = points.get(index - 1).y;
                        x1 = Double.NaN;
                        y1 = Double.NaN;
                        
                } else {
                        
-                       x0 = points.get(index-1).x;
-                       y0 = points.get(index-1).y;
-                       x1 = points.get(index+1).x;
-                       y1 = points.get(index+1).y;
+                       x0 = points.get(index - 1).x;
+                       y0 = points.get(index - 1).y;
+                       x1 = points.get(index + 1).x;
+                       y1 = points.get(index + 1).y;
                        
                }
                
-               
-               
+
+
                // Check for intersecting
                double px0, py0, px1, py1;
                px0 = 0;
                py0 = 0;
-               for (int i=1; i < points.size(); i++) {
+               for (int i = 1; i < points.size(); i++) {
                        px1 = points.get(i).x;
                        py1 = points.get(i).y;
                        
-                       if (i != index-1 && i != index && i != index+1) {
-                               if (intersects(x0,y0,x,y,px0,py0,px1,py1)) {
+                       if (i != index - 1 && i != index && i != index + 1) {
+                               if (intersects(x0, y0, x, y, px0, py0, px1, py1)) {
                                        throw new IllegalFinPointException("segments intersect");
                                }
                        }
-                       if (i != index && i != index+1 && i != index+2) {
-                               if (intersects(x,y,x1,y1,px0,py0,px1,py1)) {
+                       if (i != index && i != index + 1 && i != index + 2) {
+                               if (intersects(x, y, x1, y1, px0, py0, px1, py1)) {
                                        throw new IllegalFinPointException("segments intersect");
                                }
                        }
@@ -247,64 +249,93 @@ public class FreeformFinSet extends FinSet {
                
                if (index == 0) {
                        
-                       System.out.println("Set point zero to x:"+x);
-                       for (int i=1; i < points.size(); i++) {
+                       System.out.println("Set point zero to x:" + x);
+                       for (int i = 1; i < points.size(); i++) {
                                Coordinate c = points.get(i);
                                points.set(i, c.setX(c.x - x));
                        }
                        
                } else {
                        
-                       points.set(index,new Coordinate(x,y));
+                       points.set(index, new Coordinate(x, y));
                        
                }
-               if (index == 0 || index == points.size()-1) {
-                       this.length = points.get(points.size()-1).x;
+               if (index == 0 || index == points.size() - 1) {
+                       this.length = points.get(points.size() - 1).x;
                }
                fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
        }
        
        
-       
+
        private boolean intersects(double ax0, double ay0, double ax1, double ay1,
                        double bx0, double by0, double bx1, double by1) {
                
-               double d = ((by1-by0)*(ax1-ax0) - (bx1-bx0)*(ay1-ay0));
+               double d = ((by1 - by0) * (ax1 - ax0) - (bx1 - bx0) * (ay1 - ay0));
                
-               double ua = ((bx1-bx0)*(ay0-by0) - (by1-by0)*(ax0-bx0)) / d;
-               double ub = ((ax1-ax0)*(ay0-by0) - (ay1-ay0)*(ax0-bx0)) / d;
+               double ua = ((bx1 - bx0) * (ay0 - by0) - (by1 - by0) * (ax0 - bx0)) / d;
+               double ub = ((ax1 - ax0) * (ay0 - by0) - (ay1 - ay0) * (ax0 - bx0)) / d;
                
                return (ua >= 0) && (ua <= 1) && (ub >= 0) && (ub <= 1);
        }
        
-
+       
        @Override
        public Coordinate[] getFinPoints() {
                return points.toArray(new Coordinate[0]);
        }
-
+       
        @Override
        public double getSpan() {
                double max = 0;
-               for (Coordinate c: points) {
+               for (Coordinate c : points) {
                        if (c.y > max)
                                max = c.y;
                }
                return max;
        }
-
+       
        @Override
        public String getComponentName() {
                return "Freeform fin set";
        }
-
-
+       
+       
        @SuppressWarnings("unchecked")
        @Override
-       public RocketComponent copy() {
-               RocketComponent c = super.copy();
-               ((FreeformFinSet)c).points = (ArrayList<Coordinate>) this.points.clone();
+       protected RocketComponent copyWithOriginalID() {
+               RocketComponent c = super.copyWithOriginalID();
+               ((FreeformFinSet) c).points = (ArrayList<Coordinate>) this.points.clone();
                return c;
        }
-
+       
+    /**
+     * Accept a visitor to this FreeformFinSet in the component hierarchy.
+     * 
+     * @param theVisitor  the visitor that will be called back with a reference to this FreeformFinSet
+     */    
+    @Override
+    public void accept(ComponentVisitor theVisitor) {
+        theVisitor.visit(this);
+    }
+       
+       private void validate(ArrayList<Coordinate> points) throws IllegalFinPointException {
+               final int n = points.size();
+               if (points.get(0).x != 0 || points.get(0).y != 0 ||
+                               points.get(n - 1).x < 0 || points.get(n - 1).y != 0) {
+                       throw new IllegalFinPointException("Start or end point illegal.");
+               }
+               for (int i = 0; i < n - 1; i++) {
+                       for (int j = i + 2; j < n - 1; j++) {
+                               if (intersects(points.get(i).x, points.get(i).y, points.get(i + 1).x, points.get(i + 1).y,
+                                                               points.get(j).x, points.get(j).y, points.get(j + 1).x, points.get(j + 1).y)) {
+                                       throw new IllegalFinPointException("segments intersect");
+                               }
+                       }
+                       if (points.get(i).z != 0) {
+                               throw new IllegalFinPointException("z-coordinate not zero");
+                       }
+               }
+       }
+       
 }