SplineCurve.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <common/SplineCurve.h>
00022 
00023 //
00024 // This code is taken from 
00025 // http://astronomy.swin.edu.au/~pbourke/curves/spline/
00026 // with some changes to make it less reliant on fixed c arrays
00027 //
00028 
00029 /*
00030    Calculate the blending value, this is done recursively.
00031    
00032    If the numerator and denominator are 0 the expression is 0.
00033    If the deonimator is 0 the expression is 0
00034 */
00035 static fixed splineBlend(int k,int t,int *u,fixed v)
00036 {
00037    fixed value;
00038 
00039    if (t == 1) {
00040       if ((v > u[k]) && (v < u[k+1]))
00041          value = 1;
00042       else
00043          value = 0;
00044    } else {
00045       if ((u[k+t-1] == u[k]) && (u[k+t] == u[k+1]))
00046          value = 0;
00047       else if (u[k+t-1] == u[k]) 
00048          value = (fixed(u[k+t]) - v) / (u[k+t] - u[k+1]) * splineBlend(k+1,t-1,u,v);
00049       else if (u[k+t] == u[k+1])
00050          value = (v - u[k]) / (u[k+t-1] - u[k]) * splineBlend(k,t-1,u,v);
00051      else
00052          value = (v - u[k]) / (u[k+t-1] - u[k]) * splineBlend(k,t-1,u,v) + 
00053                  (fixed(u[k+t]) - v) / (u[k+t] - u[k+1]) * splineBlend(k+1,t-1,u,v);
00054    }
00055    return(value);
00056 }
00057 
00058 /*
00059    This returns the point "output" on the spline curve.
00060    The parameter "v" indicates the position, it ranges from 0 to n-t+2
00061    
00062 */
00063 static void splinePoint(int *u,int n,int t,fixed v, 
00064         std::vector<FixedVector> &control, FixedVector &output)
00065 {
00066    output[0] = 0;
00067    output[1] = 0;
00068    output[2] = 0;
00069 
00070    for (int k=0;k<=n;k++) {
00071       fixed b = splineBlend(k,t,u,v);
00072       output[0] += (control[k])[0] * b;
00073       output[1] += (control[k])[1] * b;
00074       output[2] += (control[k])[2] * b;
00075    }
00076 }
00077 
00078 /*
00079    The positions of the subintervals of v and breakpoints, the position
00080    on the curve are called knots. Breakpoints can be uniformly defined
00081    by setting u[j] = j, a more useful series of breakpoints are defined
00082    by the function below. This set of breakpoints localises changes to
00083    the vicinity of the control point being modified.
00084 */
00085 static void splineKnots(int *u,int n,int t)
00086 {
00087    int j;
00088 
00089    for (j=0;j<=n+t;j++) {
00090       if (j < t)
00091          u[j] = 0;
00092       else if (j <= n)
00093          u[j] = j - t + 1;
00094       else if (j > n)
00095          u[j] = n - t + 2;      
00096    }
00097 }
00098 
00099 /*-------------------------------------------------------------------------
00100    Create all the points along a spline curve
00101    Control points "inp", "n" of them.
00102    Knots "knots", degree "t".
00103    Ouput curve "outp", "res" of them.
00104 */
00105 static void splineCurve(std::vector<FixedVector> &inp_list,
00106         int n,int *knots,int t, 
00107         std::vector<FixedVector> &outp_list,int res)
00108 {
00109    int i;
00110    fixed interval,increment;
00111 
00112    interval = fixed(true, 10);
00113    increment = fixed(n - t + 2) / fixed(res - 1);
00114    for (i=0;i<=res-1;i++) {
00115 
00116            FixedVector outp;
00117       splinePoint(knots,n,t,interval,inp_list,outp);
00118           outp_list.push_back(outp);
00119       interval += increment;
00120    }
00121    outp_list[res-1] = inp_list[n];
00122 }
00123 
00124 void SplineCurve::generate(
00125                 std::vector<FixedVector> &inPoints, 
00126                 std::vector<FixedVector> &outPoints,
00127                 int resolution,
00128                 int polynomials)
00129 {
00130         int N = int(inPoints.size()) - 1;
00131         int T = polynomials;
00132         int *knots = new int[N + T + 1];
00133         
00134         splineKnots(knots,N,T);
00135         splineCurve(inPoints,N,knots,T,outPoints,resolution);
00136 
00137         delete [] knots;
00138 }

Generated on Mon Feb 16 15:14:49 2009 for Scorched3D by  doxygen 1.5.3