POV-Ray : Newsgroups : povray.text.scene-files : Cubic splines - test file : Cubic splines - "spline_tools.inc" Server Time
5 Jul 2024 10:33:21 EDT (-0400)
  Cubic splines - "spline_tools.inc"  
From: Nikodemus Siivola
Date: 19 May 2001 09:39:37
Message: <3b067799@news.povray.org>
// see question in p.a-u

/*
 Spline type codes:
 linear  <0,0,0>
 quadratic   <0,0,1>
 cubic   <0,0,2>
 bezier  <0,0,3>
*/

#macro Make_spline (Type, Controls)
 #local D = dimension_size(Controls,1);
 #local Spline = array [D+1]
 // Tagging the spline by type
 #if (!strcmp(Type, "linear_spline"))
  #if (D<2)
   #debug "Error: Make_spline macro - linear_spline requires a minimum of 2
control points.\n"
  #else
   #declare Spline[0] = <0,0,0>;
  #end
 #end
 #if (!strcmp(Type, "quadratic_spline"))
  #if (D<3)
   #debug "Error: Make_spline macro - quadratic_spline requires a minimum
of 3 control points.\n"
  #else
   #declare Spline[0] = <-100,0,1>;
   #local Controls = Controls
   #declare Controls[0] = 2*Controls[1]-Controls[0];
  #end
 #end
 #if (!strcmp(Type, "cubic_spline"))
  #if (D<4)
   #debug "Error: Make_spline macro - cubic_spline requires a minimum of 4
control points.\n"
  #else
   #declare Spline[0] = <-100,0,2>;
  #end
 #end
 #if (!strcmp(Type, "bezier_spline"))
  #if (D<4)
   #debug "Error: Make_spline macro - bezier_spline requires a minimum of 4
control points.\n"
  #else
   #declare Spline[0] = <0,0,3>;
  #end
 #end
 // Creating the new array
 #local I = 1;
 #while (I<D+1)
  #declare Spline[I] = Controls[I-1];
  #declare I = I + 1;
 #end
 Spline // Return
#end // Make_spline


#macro Evaluate_linear_spline (T,D,Spline)
 #switch (T)
  #case (0)
   #local Pos_v = Spline[1];
   #break
  #case (1)
   #local Pos_v = Spline[D];
   #break
  #else
   #local N = D-1;   // number of segments
   #local L = 1/N;   // segment size
   #local I = div(T,L)+1; // segment index
   #local S = mod(T,L)/L; // position in segment
   #local Pos_v = (Spline[I+1]-Spline[I])*S+Spline[I];
 #end // switch
 Pos_v // Return
#end // Evaluate_linear_spline


#macro Evaluate_quadratic_spline (T,D,Spline)
 #local N = D-2;   // number of segments
 #local L = 1/N;   // segment size
 #if (T=1)
  #local I = N;
  #local S = 1; // position in segment
 #else
  #local I = div(T,L)+1;
  #local S = mod(T,L)/L; // position in segment
 #end
 #local S2 = S*S;
 #local R0 = Spline[I];
 #local R1 = Spline[I+1];
 #local R2 = Spline[I+2];
 #local P0 = 2*R1-R0;
 #local Pos_v = (1-2*S+S2)*R1 + (2*S-2*S2)*P0 + S2*R2;
 Pos_v // return
#end // Evaluate_quadratic_spline


#macro Evaluate_cubic_spline (T,D,Spline)
 #local N = D-3;   // number of segments
 #local L = 1/N;   // segment size
 #if (T=1)
  #local I = N;
  #local S = 1; // position in segment
 #else
  #local I = div(T,L)+1;
  #local S = mod(T,L)/L; // position in segment
 #end
 #local S2 = S*S;
 #local S3 = S*S*S;
 #local C0 = Spline[I];
 #local C1 = Spline[I+3];
 #local R1 = Spline[I+1];
 #local R2 = Spline[I+2];
 #local T0 = R1-C0;
 #local T1 = C1-R2;
 #local Pos_v = (1-3*S2+2*S3)*R1 + (3*S2-2*S3)*R2 + (S-2*S2+S3)*T0 +
(-S2+S3)*T1;
 Pos_v // return
#end // Evaluate_cubic_spline


#macro Evaluate_bezier_spline (T,D,Spline)
 #local N = D-3;   // number of segments
 #local L = 1/N;   // segment size
 #if (T=1)
  #local I = N;
  #local S = 1; // position in segment
 #else
  #local I = div(T,L)+1;
  #local S = mod(T,L)/L; // position in segment
 #end
  #local S2 = S*S;
  #local S3 = S*S*S;
  #local A = 1/6;
  #local C1 = Spline[I];
  #local C2 = Spline[I+1];
  #local C3 = Spline[I+2];
  #local C4 = Spline[I+3];
  #local Pos_v = A*(1-3*S+3*S2-S3)*C1 + A*(4-6*S2+3*S3)*C2 +
A*(1+3*S+3*S2-3*S3)*C3 + A*S3*C4;
 Pos_v // return
#end // Evaluate_bezier_spline


#macro Eval_spline (T, Spline)
 #local D = dimension_size(Spline,1)-1; // number of points defining the
spline
 #switch (Spline[0].z)
 #case (0)
  #local Pos_v = Evaluate_linear_spline (T,D,Spline);
  #break
 #case (1)
  #local Pos_v = Evaluate_quadratic_spline (T,D,Spline);
  #break
 #case (2)
  #local Pos_v = Evaluate_cubic_spline (T,D,Spline);
  #break
 #case (3)
  #local Pos_v = Evaluate_bezier_spline (T,D,Spline);
  #break
 #else
  #debug "Error: Eval_spline macro could not identify spline type."
 #end
 Pos_v // return
#end // Eval_spline


#macro Sample_spline (N, Spline)
 #local Sample = array[N]
 #local Step = 1/(N-1);
 #local I = 0;
 #while (I<N)
  #declare Sample[I] = Eval_spline (I*Step, Spline);
  #declare I = I + 1;
 #end
 Sample // return
#end // Sample_spline


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.