Cardinal Splines in GDI Plus

Tue, 11 Mar 2008 22:09:43 -0400 - Author:
A cardinal spline is one way to draw curves on a computer screen. This function I wrote today and tested is a rewrite of the DrawCurve/DrawClosedCurve method that draws cardinal splines with cubic Bézier curves supported by many graphics packages.

  public static void DrawCurve(Graphics g, PointF[] pts, double tension, bool closefigure){
 int i;
 double x0,x1,y0,y1;
 int numpoints=pts.Length;
 tension/=3;
 for(i=0;i<numpoints;i++){
  int prev=i-1;
  int thispt=i;
  int next1=i+1;
  int next2=i+2;
  if(thispt==0 && closefigure)
   prev=numpoints-1;
  if(thispt==numpoints-2 && closefigure)
   next2=0;
  if(thispt==numpoints-1){
   if(!closefigure)break;
   next1=0;
   next2=1;
  }
  if(prev<0){
   // At start of curve
   ASSERT(thispt==0);
   x0=pts[thispt].X+(pts[next1].X-pts[thispt].X)*tension;
   y0=pts[thispt].Y+(pts[next1].Y-pts[thispt].Y)*tension;
  } else {
   x0=pts[thispt].X+(pts[next1].X-pts[prev].X)*tension;
   y0=pts[thispt].Y+(pts[next1].Y-pts[prev].Y)*tension;
  }
  if(next2>=numpoints){
   // At end of curve
   x1=pts[next1].X+(pts[thispt].X-pts[next1].X)*tension;
   y1=pts[next1].Y+(pts[thispt].Y-pts[next1].Y)*tension;  
  } else {
   x1=pts[next1].X-(pts[next2].X-pts[thispt].X)*tension;
   y1=pts[next1].Y-(pts[next2].Y-pts[thispt].Y)*tension;
  }
  g.DrawBezier(Pens.Black,(float)pts[thispt].X,(float)pts[thispt].Y,
    (float)x0,(float)y0,(float)x1,(float)y1,(float)pts[next1].X,(float)pts[next1].Y);
 }
  }