Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

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;   } }