A spline factory instance
/* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ //package no.geosoft.cc.geometry.spline; /** * A spline factory instance. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ public class SplineFactory { /** * Create a Bezier spline based on the given control points. * The generated curve starts in the first control point and ends * in the last control point. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...). * @param nParts Number of parts to divide each leg into. * @return Spline (x0,y0,z0,x1,y1,z1,...). */ public static double[] createBezier (double[] controlPoints, int nParts) { Spline spline = new BezierSpline (controlPoints, nParts); return spline.generate(); } /** * Create a cubic spline based on the given control points. * The generated curve starts in the first control point and ends * in the last control point. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...). * @param nParts Number of parts to divide each leg into. * @return Spline (x0,y0,z0,x1,y1,z1,...). */ public static double[] createCubic (double[] controlPoints, int nParts) { Spline spline = new CubicSpline (controlPoints, nParts); return spline.generate(); } /** * Create a Catmull-Rom spline based on the given control points. * The generated curve starts in the first control point and ends * in the last control point. * Im addition, the curve intersects all the control points. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...). * @param nParts Number of parts to divide each leg into. * @return Spline (x0,y0,z0,x1,y1,z1,...). */ public static double[] createCatmullRom (double[] controlPoints, int nParts) { Spline spline = new CatmullRomSpline (controlPoints, nParts); return spline.generate(); } /** * Testing the spline package. * * @param args Not used. */ public static void main (String[] args) { double[] c = new double[12]; c[0] = 0.0; // x0 c[1] = 0.0; // y0 c[2] = 0.0; // z0 c[3] = 1.0; // x1 c[4] = 1.0; // y1 c[5] = 0.0; // z1 c[6] = 2.0; // x2 c[7] = -1.0; // y2 c[8] = 0.0; // z2 c[9] = 10.0; // x3 c[10] = 0.0; // y3 c[11] = 0.0; // z3 double[] spline1 = SplineFactory.createBezier (c, 20); double[] spline2 = SplineFactory.createCubic (c, 20); double[] spline3 = SplineFactory.createCatmullRom (c, 20); System.out.println ("-- Bezier"); for (int i = 0; i < spline1.length; i+=3) System.out.println (spline1[i] + "," + spline1[i+1] + "," + spline1[i+2]); System.out.println ("-- Cubic"); for (int i = 0; i < spline2.length; i+=3) System.out.println (spline2[i] + "," + spline2[i+1] + "," + spline2[i+2]); System.out.println ("-- Catmull-Rom"); for (int i = 0; i < spline3.length; i+=3) System.out.println (spline3[i] + "," + spline3[i+1] + "," + spline3[i+2]); } } /* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ //package no.geosoft.cc.geometry.spline; /** * An abstract class defining a general spline object. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ abstract class Spline { protected double controlPoints_[]; protected int nParts_; abstract double[] generate(); } /* * (C) 2004 - Geotechnical Software Services * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ //package no.geosoft.cc.geometry.spline; /** * A Bezier spline object. Use the SplineFactory class to create * splines of this type. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ class BezierSpline extends Spline { /** * Construct a bezier spline. Package local; Use the SplineFactory * to create splines of this type. The control points are used according * to the definition of Bezier splines. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...) * @param nParts Number of parts in generated spline. */ BezierSpline (double controlPoints[], int nParts) { controlPoints_ = controlPoints; nParts_ = nParts; } /** * Generate this spline. * * @return Coordinates of the spline (x0,y0,z0,x1,y1,z1,...) */ double[] generate() { if (controlPoints_.length < 9) { double[] copy = new double[controlPoints_.length]; System.arraycopy (controlPoints_, 0, copy, 0, controlPoints_.length); return copy; } int n = controlPoints_.length / 3; int length = (n - 3) * nParts_ + 1; double spline[] = new double[length * 3]; p (0, 0, controlPoints_, spline, 0); int index = 3; for (int i = 0; i < n - 3; i += 3) { for (int j = 1; j <= nParts_; j++) { p (i, j / (double) nParts_, controlPoints_, spline, index); index += 3; } } return spline; } private void p (int i, double t, double cp[], double spline[], int index) { double x = 0.0; double y = 0.0; double z = 0.0; int k = i; for (int j = 0; j <= 3; j++) { double b = blend (j, t); x += b * cp[k++]; y += b * cp[k++]; z += b * cp[k++]; } spline[index + 0] = x; spline[index + 1] = y; spline[index + 2] = z; } private double blend (int i, double t) { if (i == 0) return (1 - t) * (1 - t) * (1 - t); else if (i == 1) return 3 * t * (1 - t) * (1 - t); else if (i == 2) return 3 * t * t * (1 - t); else return t * t * t; } } /* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ //package no.geosoft.cc.geometry.spline; /** * A cubic spline object. Use the SplineFactory class to create * splines of this type. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ class CubicSpline extends Spline { /** * Construct a cubic spline. Package local; Use the SplineFactory * to create splines of this type. The control points are used according * to the definition of cubic splines. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...) * @param nParts Number of parts in generated spline. */ CubicSpline (double controlPoints[], int nParts) { initialize (controlPoints, nParts); } protected void initialize (double controlPoints[], int nParts) { nParts_ = nParts; // Endpoints are added three times to get them include in the // generated array controlPoints_ = new double[controlPoints.length + 12]; System.arraycopy (controlPoints, 0, controlPoints_, 6, controlPoints.length); controlPoints_[0] = controlPoints_[6]; controlPoints_[1] = controlPoints_[7]; controlPoints_[2] = controlPoints_[8]; controlPoints_[3] = controlPoints_[6]; controlPoints_[4] = controlPoints_[7]; controlPoints_[5] = controlPoints_[8]; controlPoints_[controlPoints_.length - 3] = controlPoints_[controlPoints_.length - 9]; controlPoints_[controlPoints_.length - 2] = controlPoints_[controlPoints_.length - 8]; controlPoints_[controlPoints_.length - 1] = controlPoints_[controlPoints_.length - 7]; controlPoints_[controlPoints_.length - 6] = controlPoints_[controlPoints_.length - 9]; controlPoints_[controlPoints_.length - 5] = controlPoints_[controlPoints_.length - 8]; controlPoints_[controlPoints_.length - 4] = controlPoints_[controlPoints_.length - 7]; } /** * Generate this spline. * * @return Coordinates of the spline (x0,y0,z0,x1,y1,z1,...) */ double[] generate() { int n = controlPoints_.length / 3; int length = (n - 3) * nParts_ + 1; double spline[] = new double[length * 3]; p (2, 0, controlPoints_, spline, 0); int index = 3; for (int i = 2; i < n - 1; i++) { for (int j = 1; j <= nParts_; j++) { p (i, j / (double) nParts_, controlPoints_, spline, index); index += 3; } } return spline; } private void p (int i, double t, double cp[], double spline[], int index) { double x = 0.0; double y = 0.0; double z = 0.0; int k = (i - 2) * 3; for (int j = -2; j <= 1; j++) { // TODO: Precompute blending matrix double b = blend (j, t); x += b * cp[k++]; y += b * cp[k++]; z += b * cp[k++]; } spline[index + 0] = x; spline[index + 1] = y; spline[index + 2] = z; } protected double blend (int i, double t) { if (i == -2) return (((-t + 3) * t - 3) * t + 1) / 6; else if (i == -1) return (((3 * t - 6) * t) * t + 4) / 6; else if (i == 0) return (((-3 * t + 3) * t + 3) * t + 1) / 6; else return (t * t * t) / 6; } } /* * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ //package no.geosoft.cc.geometry.spline; /** * A Catmull-Rom spline object. Use the SplineFactory class to create * splines of this type. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ class CatmullRomSpline extends CubicSpline { /** * Construct a Catmull-Rom spline. Package local; Use the SplineFactory * to create splines of this type. The control points are used according * to the definition of Catmull-Rom splines. * * @param controlPoints Control points of spline (x0,y0,z0,x1,y1,z1,...) * @param nParts Number of parts in generated spline. */ CatmullRomSpline (double controlPoints[], int nParts) { super (controlPoints, nParts); } protected void initialize (double controlPoints[], int nParts) { nParts_ = nParts; // Endpoints are added twice to force in the generated array controlPoints_ = new double[controlPoints.length + 6]; System.arraycopy (controlPoints, 0, controlPoints_, 3, controlPoints.length); controlPoints_[0] = controlPoints_[3]; controlPoints_[1] = controlPoints_[4]; controlPoints_[2] = controlPoints_[5]; controlPoints_[controlPoints_.length - 3] = controlPoints_[controlPoints_.length - 6]; controlPoints_[controlPoints_.length - 2] = controlPoints_[controlPoints_.length - 5]; controlPoints_[controlPoints_.length - 1] = controlPoints_[controlPoints_.length - 4]; } protected double blend (int i, double t) { if (i == -2) return ((-t + 2) * t - 1) * t / 2; else if (i == -1) return (((3 * t - 5) * t) * t + 2) / 2; else if (i == 0) return ((-3 * t + 4) * t + 1) * t / 2; else return ((t - 1) * t * t) / 2; } }
1. | Move the curve control point and redraw the curve | ||
2. | Draw curve with mouse | ||
3. | Curve with QuadCurve2D | ||
4. | Spline 2D | ||
5. | Interpolates given points by a bezier curve | ||
6. | A class that models a Cubic-Bezier curve |