/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package feuille.drawing.bspline; import java.awt.Graphics2D; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Trouvé sur le projet http://code.google.com/p/curvecreator/ * @author The Wingate 2940 */ public class BezierCurve extends Curve { public BezierCurve(Point2D startPoint) { getControlPoints().add(startPoint); } public BezierCurve(List<Point2D> controlPoints) { setControlPoints(controlPoints); } @Override public void paintCurve(Graphics2D g, int quality, boolean adaptive) { if(adaptive) { paintAdaptiveRendering(getControlPoints(), g, quality); } else { paintUniform(g, quality); } } private static double getMaxHeightByQuality(int quality) { if(quality == LOW_QUALITY) { return 10; } else if(quality == MEDIUM_QUALITY) { return 5; } else if(quality == HIGH_QUALITY) { return 0.1; } else { return 0.001; } } private static double getHeight(List<Point2D> curve) { if (curve.size() <= 2) { return 0; } Iterator<Point2D> i = curve.iterator(); Point2D startPoint = i.next(); Point2D endPoint = curve.get(curve.size() - 1); Line2D l = new Line2D.Double(startPoint, endPoint); double maxDistance = 0; while (i.hasNext()) { Point2D point = i.next(); double distance = l.ptLineDist(point); maxDistance = Math.max(distance, maxDistance); } return maxDistance; } public static LinkedList<Point2D> splitLeft(List<Point2D> points) { if (points.size() == 1) { return new LinkedList<Point2D>(points); } else { List<Point2D> l = new LinkedList<Point2D>(); Iterator<Point2D> i = points.iterator(); Point2D p1, p2; p1 = i.next(); do { p2 = i.next(); //dataräkninar!! Point2D n = new Point2D.Double(((p2.getX() - p1.getX()) / 2) + p1.getX(), ((p2.getY() - p1.getY()) / 2) + p1.getY()); l.add(n); p1 = p2; } while (i.hasNext()); LinkedList<Point2D> returned = splitLeft(l); returned.addFirst(points.get(0)); return returned; } } public static LinkedList<Point2D> splitRight(List<Point2D> points) { if (points.size() == 1) { return new LinkedList<Point2D>(points); } else { LinkedList<Point2D> l = new LinkedList<Point2D>(); Iterator<Point2D> i = points.iterator(); Point2D p1, p2; p1 = i.next(); do { p2 = i.next(); //dataräkninar!! Point2D n = new Point2D.Double(((p2.getX() - p1.getX()) / 2) + p1.getX(), ((p2.getY() - p1.getY()) / 2) + p1.getY()); l.add(n); p1 = p2; } while (i.hasNext()); LinkedList<Point2D> returned = splitRight(l); returned.addLast(points.get(points.size() - 1)); return returned; } } public static void paintAdaptiveRendering(List<Point2D> curve, Graphics2D g, int quality) { if (getHeight(curve) > getMaxHeightByQuality(quality)) { paintAdaptiveRendering(splitLeft(curve), g, quality); paintAdaptiveRendering(splitRight(curve), g, quality); } else { Line2D l = new Line2D.Double(curve.get(0), curve.get(curve.size() - 1)); g.draw(l); } } @Override public void addControlPoint(Point2D point) { getControlPoints().add(point); } @Override public void removeControlPoint(Point2D point) { if(getControlPoints().contains(point)) { if(getControlPoints().size() >= 2) { getControlPoints().remove(point); } } } @Override public boolean isValid() { if(getControlPoints().size() <= 1) { return false; } return true; } public void degreeElevation() { List<Point2D> cp = getControlPoints(); int n = cp.size() - 1; ArrayList<Point2D> ncp = new ArrayList<Point2D>(n + 2); // First is the same ncp.add(cp.get(0)); for (int i = 1; i < n + 1 /* dont go through the last one */; i++) { Point2D newPoint = new Point2D.Double( ((double) i / (n + 1)) * cp.get(i - 1).getX() + (1 - ((double) i / (n + 1))) * cp.get(i).getX(), ((double) i / (n + 1)) * cp.get(i - 1).getY() + (1 - ((double) i / (n + 1))) * cp.get(i).getY()); ncp.add(newPoint); } // last is the same ncp.add(cp.get(n)); setControlPoints(ncp); } private double[] getBasis(double t) { int n = getControlPoints().size() - 1; double[] basis = new double[n + 1]; for (int i = 0; i <= n; i++) { basis[i] = choose(n, i) * Math.pow(1 - t, n - i) * Math.pow(t, i); } return basis; } private void paintUniform(Graphics2D g, int quality) { int numPoints = quality * 2 * getControlPoints().size(); Point2D[] points = new Point2D[numPoints]; for (int currentPoint = 0; currentPoint < points.length; currentPoint++) { double u = ((1.0 / (points.length - 1)) * currentPoint); double N[] = getBasis(u); double x = 0, y = 0; for (int i = 0; i < getControlPoints().size(); i++) { Point2D control = getControlPoints().get(i); x += control.getX() * N[i]; y += control.getY() * N[i]; } points[currentPoint] = new Point2D.Double(x, y); } for (int i = 0; i < points.length - 1; i++) { Line2D l = new Line2D.Double(points[i], points[i + 1]); g.draw(l); } } private double choose(int n, int k) { return faculty(n) / (faculty(k) * faculty(n - k)); } private double faculty(int n) { double sum = 1; for (int i = 2; i <= n ; i++) { sum *= i; } return sum; } }