From 5fdb8554aa59432924c6cf2cf4e8c178c5856deb Mon Sep 17 00:00:00 2001 From: student Date: Wed, 11 Apr 2018 17:06:20 -0400 Subject: Update --- CSMath/src/bezier/geom/Bezier.java | 219 +++++++++++++++++++++++++++ CSMath/src/bezier/geom/BezierProperties.java | 84 ++++++++++ CSMath/src/bezier/geom/Matrix.java | 55 +++++++ CSMath/src/bezier/geom/TDHPoint.java | 85 +++++++++++ CSMath/src/bezier/geom/TDPoint.java | 111 ++++++++++++++ 5 files changed, 554 insertions(+) create mode 100644 CSMath/src/bezier/geom/Bezier.java create mode 100644 CSMath/src/bezier/geom/BezierProperties.java create mode 100644 CSMath/src/bezier/geom/Matrix.java create mode 100644 CSMath/src/bezier/geom/TDHPoint.java create mode 100644 CSMath/src/bezier/geom/TDPoint.java (limited to 'CSMath/src/bezier/geom') diff --git a/CSMath/src/bezier/geom/Bezier.java b/CSMath/src/bezier/geom/Bezier.java new file mode 100644 index 0000000..46f1476 --- /dev/null +++ b/CSMath/src/bezier/geom/Bezier.java @@ -0,0 +1,219 @@ +package bezier.geom; + +import java.util.ArrayList; +import java.util.List; + +import bezier.transforms.TDHIdentity; +import bezier.transforms.TDHTransform; + +/** + * Represents a bezier curve. + */ +public class Bezier { + /** + * The control points of the curve. + */ + public final List controls; + + /** + * The display properties for the curve. + */ + public BezierProperties data; + + /** + * Create a new bezier curve from a set of control points. + * + * @param points + * The control points to use. + */ + public Bezier(TDPoint... points) { + data = new BezierProperties(); + + controls = new ArrayList<>(); + + for (TDPoint punkt : points) { + controls.add(punkt); + } + } + + /** + * Do a scaled evaluation of the curve. + * + * @param t + * The value to evaluate at. + * @return The point on the curve, scaled by the curves scaling factor. + */ + public TDPoint scaleEval(double t) { + return eval(t).multiply(data.scale); + } + + /** + * Do a scaled evaluation of the curve. + * + * @param t + * The value to evaluate at. + */ + public TDPoint eval(double t) { + if (controls.isEmpty()) + return new TDPoint(0, 0); + + TDPoint punkt = evalIntern(t, controls.size() - 1, 0); + + return punkt; + } + + /* + * Recursive evaluation of bezier curve. + */ + private TDPoint evalIntern(double t, int j, int k) { + /* + * Base case. + */ + if (j <= 0) { + return controls.get(k); + } + + /* + * Get the two component points. + */ + TDPoint l = evalIntern(t, j - 1, k); + TDPoint r = evalIntern(t, j - 1, k + 1); + + /* + * Adjust them by parameter value + */ + l = l.multiply(1 - t); + r = r.multiply(t); + + /* + * Give back their sum + */ + return TDPoint.add(l, r); + } + + /** + * Split a curve into two curves at a specific point. + * + * @param t + * The point to split the curve at. + * @return The two curves, split at that point. + */ + public Bezier[] decompose(double t) { + Bezier[] curves = new Bezier[2]; + + { + /* + * Get the first curve. + */ + TDPoint[] points = new TDPoint[controls.size()]; + for (int i = 0; i < points.length; i++) { + points[i] = evalIntern(t, i, 0); + } + curves[0] = new Bezier(points); + } + + { + /* + * Get the second curve. + */ + TDPoint[] points = new TDPoint[controls.size()]; + for (int i = 0; i < points.length; i++) { + points[i] = evalIntern(t, (points.length - 1) - i, i); + } + curves[1] = new Bezier(points); + } + + return curves; + } + + /** + * Get the bounding box for this curves control points. + * + * @return The bounding box for the control points. + */ + public TDPoint[] extrema() { + return extrema(new TDHIdentity()); + } + + /** + * Get the bounding box for a transformed version of this curves control points. + * + * @param transform + * The transform to apply to the control points. + * @return The bounding box for the transformed control points. + */ + public TDPoint[] extrema(TDHTransform transform) { + TDPoint[] box = new TDPoint[4]; + + double xMin = Double.MAX_VALUE, xMax = Double.MIN_VALUE; + double yMin = Double.MAX_VALUE, yMax = Double.MIN_VALUE; + + for (TDPoint punkt1 : controls) { + /* + * Get transformed point + */ + TDPoint punkt = punkt1.multiply(data.scale); + punkt = transform.transform(punkt.toTDHPoint()).toTDPoint(); + + /* + * Set min/max x vals + */ + if (punkt.x < xMin) { + xMin = punkt.x; + } + if (punkt.x > xMax) { + xMax = punkt.x; + } + + /* + * Set min/max y vals + */ + if (punkt.y < yMin) { + yMin = punkt.y; + } + if (punkt.y > yMax) { + yMax = punkt.y; + } + } + + /* + * Create returned points. + */ + box[0] = new TDPoint(xMin, yMin); + box[1] = new TDPoint(xMax, yMin); + box[2] = new TDPoint(xMax, yMax); + box[3] = new TDPoint(xMin, yMax); + + return box; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((controls == null) ? 0 : controls.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Bezier other = (Bezier) obj; + if (controls == null) { + if (other.controls != null) + return false; + } else if (!controls.equals(other.controls)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("Bezier [controls=%s]", controls); + } +} \ No newline at end of file diff --git a/CSMath/src/bezier/geom/BezierProperties.java b/CSMath/src/bezier/geom/BezierProperties.java new file mode 100644 index 0000000..1b5443d --- /dev/null +++ b/CSMath/src/bezier/geom/BezierProperties.java @@ -0,0 +1,84 @@ +package bezier.geom; + +import java.awt.Color; + +public class BezierProperties { + /** + * The number of separate points to graph from the curve. + */ + public int parts = 100; + + /** + * The multiplier to apply to coordinates. + */ + public double scale = 5; + + /** + * The colors for varying parts of the curve. + */ + public Color curveColor = Color.BLACK; + public Color pointColor = Color.RED; + public Color boxColor = Color.GREEN; + + public BezierProperties() { + } + + public BezierProperties(int parts, double scale, Color curveColor, Color pointColor, Color boxColor) { + this.parts = parts; + this.scale = scale; + this.curveColor = curveColor; + this.pointColor = pointColor; + this.boxColor = boxColor; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((boxColor == null) ? 0 : boxColor.hashCode()); + result = prime * result + ((curveColor == null) ? 0 : curveColor.hashCode()); + result = prime * result + parts; + result = prime * result + ((pointColor == null) ? 0 : pointColor.hashCode()); + long temp; + temp = Double.doubleToLongBits(scale); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BezierProperties other = (BezierProperties) obj; + if (boxColor == null) { + if (other.boxColor != null) + return false; + } else if (!boxColor.equals(other.boxColor)) + return false; + if (curveColor == null) { + if (other.curveColor != null) + return false; + } else if (!curveColor.equals(other.curveColor)) + return false; + if (parts != other.parts) + return false; + if (pointColor == null) { + if (other.pointColor != null) + return false; + } else if (!pointColor.equals(other.pointColor)) + return false; + if (Double.doubleToLongBits(scale) != Double.doubleToLongBits(other.scale)) + return false; + return true; + } + + @Override + public String toString() { + return "BezierProperties [parts=" + parts + ", scale=" + scale + ", curveColor=" + curveColor + ", pointColor=" + + pointColor + ", boxColor=" + boxColor + "]"; + } +} \ No newline at end of file diff --git a/CSMath/src/bezier/geom/Matrix.java b/CSMath/src/bezier/geom/Matrix.java new file mode 100644 index 0000000..a728a02 --- /dev/null +++ b/CSMath/src/bezier/geom/Matrix.java @@ -0,0 +1,55 @@ +package bezier.geom; + +public class Matrix { + public final double[][] mat; + + public Matrix(double[][] mat) { + this.mat = mat; + } + + public Matrix add(Matrix m) { + return add(m.mat); + } + + public double[] scalarMultiply(double[] vec) { + double[] ret = new double[vec.length]; + + for(int i = 0; i < mat[0].length; i++) { + for(int j = 0; j < mat.length; j++) { + ret[i] += mat[i][j] * vec[j]; + } + } + + return ret; + } + + public Matrix add(double[][] matr) { + double[][] ret = new double[mat.length][mat[0].length]; + + for(int i = 0; i < mat.length; i++) { + for(int j = 0; j < mat[0].length; j++) { + ret[i][j] = mat[i][j] + matr[i][j]; + } + } + + return new Matrix(ret); + } + + public Matrix multiply(Matrix m) { + return multiply(m.mat); + } + + public Matrix multiply(double[][] matr) { + double[][] ret = new double[mat.length][matr[0].length]; + + for (int i = 0; i < mat.length; i++) { + for (int j = 0; j < matr[0].length; j++) { + for (int k = 0; k < matr.length; k++) { + ret[i][j] += mat[i][k] * matr[k][j]; + } + } + } + + return new Matrix(ret); + } +} diff --git a/CSMath/src/bezier/geom/TDHPoint.java b/CSMath/src/bezier/geom/TDHPoint.java new file mode 100644 index 0000000..40553a9 --- /dev/null +++ b/CSMath/src/bezier/geom/TDHPoint.java @@ -0,0 +1,85 @@ +package bezier.geom; + +/** + * A two-dimensional homogeneous point. + * + * @author bjculkin + * + */ +public class TDHPoint extends TDPoint { + /** + * The homogeneous coordinate for the point. + */ + public final double z; + + /** + * Create a new two-dimensional homogeneous point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + * @param z + * The homogeneous coordinate. + */ + public TDHPoint(double x, double y, double z) { + super(x, y); + + this.z = z; + } + + /** + * Create a new two-dimensional homogeneous point. + * + * The homogeneous coordinate is set to 1. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + */ + public TDHPoint(double x, double y) { + this(x, y, 1); + } + + /** + * Convert this point to a plain two-dimensional point. + * + * @return A two-dimensional version of this point. + */ + public TDPoint toTDPoint() { + /* + * Convert back down by dividing each coordinate by the homogeneous value. + */ + return new TDPoint(x / z, y / z); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + long temp; + temp = Double.doubleToLongBits(z); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + TDHPoint other = (TDHPoint) obj; + if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z)) + return false; + return true; + } + + @Override + public String toString() { + return "TDHPoint [z=" + z + ", x=" + x + ", y=" + y + "]"; + } +} \ No newline at end of file diff --git a/CSMath/src/bezier/geom/TDPoint.java b/CSMath/src/bezier/geom/TDPoint.java new file mode 100644 index 0000000..8074461 --- /dev/null +++ b/CSMath/src/bezier/geom/TDPoint.java @@ -0,0 +1,111 @@ +package bezier.geom; + +/** + * Represents a two-dimensional point. + * + * @author bjculkin + * + */ +public class TDPoint { + /** + * The x coordinate. + */ + public final double x; + + /** + * The y coordinate. + */ + public final double y; + + /** + * Create a new two-dimensional point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + */ + public TDPoint(double x, double y) { + this.x = x; + this.y = y; + } + + /** + * Create a new two-dimensional point. + * + * @param x + * The x coordinate. + * @param y + * The y coordinate. + * @return A point with those coordinates. + */ + public static TDPoint p2(double x, double y) { + return new TDPoint(x, y); + } + + /** + * Return a new scaled point. + * + * @param s + * The amount to scale by. + * @return A point scaled by the specified amount. + */ + public TDPoint multiply(double s) { + return p2(x * s, y * s); + } + + /** + * Add two points together. + * + * @param p1 + * The first point to add. + * @param p2 + * The second point to add. + * @return The sum of the points. + */ + public static TDPoint add(TDPoint p1, TDPoint p2) { + return p2(p1.x + p2.x, p1.y + p2.y); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TDPoint other = (TDPoint) obj; + if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) + return false; + if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) + return false; + return true; + } + + @Override + public String toString() { + return "TDPoint [x=" + x + ", y=" + y + "]"; + } + + /** + * Convert this point to a two-dimensional homogeneous point. + * + * @return A homogeneous version of this point. + */ + public TDHPoint toTDHPoint() { + return new TDHPoint(x, y); + } +} \ No newline at end of file -- cgit v1.2.3