2D Graphics GUI Java

/*
 * 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 Jacob Dreyer
 */   
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 Jacob Dreyer
 */   
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 Jacob Dreyer
 */   
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 Jacob Dreyer
 */   
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 Jacob Dreyer
 */   
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;
  }
}