X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fnet%2Fsf%2Fopenrocket%2Frocketcomponent%2FFreeformFinSet.java;h=ce6402151bc646972bd055b34235c9e63f4cc378;hb=50f171ab51eae5c91117ebdc9b7a0d43d764ddb5;hp=1ea92caee2f879f7f3ea908885bebfd5018b8137;hpb=720d4935bc6bec453e6478ad5227356c626610a2;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java index 1ea92cae..ce640215 100644 --- a/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java +++ b/src/net/sf/openrocket/rocketcomponent/FreeformFinSet.java @@ -1,25 +1,34 @@ package net.sf.openrocket.rocketcomponent; -import java.util.ArrayList; -import java.util.List; - +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 { - private final List points = new ArrayList(); +public class FreeformFinSet extends FinSet { + private static final LogHelper log = Application.getLogger(); + + private ArrayList points = new ArrayList(); 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) throws IllegalFinPointException { + setPoints(finpoints); + } + + /* public FreeformFinSet(FinSet finset) { Coordinate[] finpoints = finset.getFinPoints(); this.copyFrom(finset); @@ -30,9 +39,77 @@ 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. + *

+ * 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) { + log.info("Converting " + finset.getComponentName() + " into freeform fin set"); + 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(); + 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() + + 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 index-1 and index. * The point is placed at the midpoint of the current segment. @@ -42,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); } @@ -55,16 +132,23 @@ public class FreeformFinSet extends FinSet { /** * Remove the fin point with the given index. The first and last fin points - * cannot be removed, and will cause an IllegalArgumentException + * cannot be removed, and will cause an IllegalFinPointException * if attempted. * * @param index the fin point index to remove + * @throws IllegalFinPointException if removing would result in invalid fin planform */ - public void removePoint(int index) { - if (index == 0 || index == points.size()-1) { - throw new IllegalArgumentException("cannot remove first or last point"); + @SuppressWarnings("unchecked") + public void removePoint(int index) throws IllegalFinPointException { + if (index == 0 || index == points.size() - 1) { + throw new IllegalFinPointException("cannot remove first or last point"); } - points.remove(index); + + ArrayList copy = (ArrayList) this.points.clone(); + copy.remove(index); + validate(copy); + this.points = copy; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } @@ -73,38 +157,26 @@ public class FreeformFinSet extends FinSet { return points.size(); } - public void setPoints(Coordinate[] p) { - if (p[0].x != 0 || p[0].y != 0 || p[p.length-1].y != 0) { - throw new IllegalArgumentException("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"); - } - } - if (p[i].z != 0) { - throw new IllegalArgumentException("z-coordinate not zero"); - } + public void setPoints(Coordinate[] points) throws IllegalFinPointException { + ArrayList list = new ArrayList(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 i to coordinates (x,y). *

* Note that this method enforces basic fin shape restrictions (non-negative y, * first and last point locations) silently, but throws an - * IllegalArgumentException if the point causes fin segments to - * intersect. The calling method should always catch this exception. + * IllegalFinPointException if the point causes fin segments to + * intersect. *

* Moving of the first point in the X-axis is allowed, but this actually moves * all of the other points the corresponding distance back. @@ -112,60 +184,62 @@ 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; - 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)) { - throw new IllegalArgumentException("segments intersect"); + 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)) { - throw new IllegalArgumentException("segments intersect"); + if (i != index && i != index + 1 && i != index + 2) { + if (intersects(x, y, x1, y1, px0, py0, px1, py1)) { + throw new IllegalFinPointException("segments intersect"); } } @@ -175,55 +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 + protected RocketComponent copyWithOriginalID() { + RocketComponent c = super.copyWithOriginalID(); + ((FreeformFinSet) c).points = (ArrayList) 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 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"); + } + } + } + }