POV-Ray : Newsgroups : povray.binaries.images : Is there a spline solution out there? : Re: Is there a spline solution out there? Server Time
1 Oct 2024 22:27:32 EDT (-0400)
  Re: Is there a spline solution out there?  
From: Jerry Anning
Date: 13 Aug 2000 11:46:37
Message: <3996b314.586738@news.povray.org>
On Fri, 11 Aug 2000 14:27:58 -0400, "Greg M. Johnson"
<gre### [at] my-dejanewscom> wrote:

>Looks brilliant, but:
>0) I assume I need a defined array of Points, right?
>1) you didn't define Bias anywhere, and this gives me an error.
>2) how would I call the points from it??

>>
>> // begin partial code snippet
>> #macro Mxv(In, Mx)
>>   <max(In.x, Mx.x), max(In.y, Mx.y), max(In.z, Mx.z)>
>> #end
>>
>> #macro Mnv(In, Mn)
>>   <min(In.x, Mn.x), min(In.y, Mn.y), min(In.z, Mn.z)>
>> #end
>>
>> #declare Tau = array[4][4]
>>   {
>>     { (Bias - 1) * Tens, 2 - Bias * Tens, (1 - Bias) * Tens - 2, Bias
>> * Tens },
>>     { 2 * (1 - Bias) * Tens, (3 * Bias - 1) * Tens - 3, 3 - Tens,
>> -Bias * Tens },
>>     { (Bias - 1) * Tens, (1 - 2 * Bias) * Tens, Bias * Tens, 0 },
>>     { 0, 1, 0, 0 }
>>   }
>>
>> #macro Horn(Row, Pt)
>>   (T * ( T * (T * Tau[0][Row] + Tau[1][Row]) + Tau[2][Row]) +
>> Tau[3][Row]) * Pt
>> #end
>>
>> #macro Cerp(Pf)
>>   Horn(0, Points[Pf - 1]) + Horn(1, Points[Pf]) +
>>   Horn(2, Points[Pf + 1]) + Horn(3, Points[Pf + 2])
>> #end
>>
>> union
>>   {
>>     #declare Iter = 1;
>>     #while(Iter < Dim + 2 * Close)
>>       #declare Count = max(1, int(Fine * vlength(Points[Iter + 1] -
>> Points[Iter])));
>>       #declare Incr = 1 / Count;
>>       #declare T = 0;
>>       #while(T < 1)
>>         #declare Start = Mxv(Mnv(Cerp(Iter), <24 * Aspect, 24, 24>),
>>                          <-24 * Aspect, -24, 0>);
>>         #declare T = T + Incr;
>>         #declare End = Mxv(Mnv(Cerp(Iter), <24 * Aspect, 24, 24>),
>>                        <-24 * Aspect, -24, 0>);
>>         #declare End = ((End.x = Start.x) ? End + <.001, 0, 0> : End);
>>         sphere { Start, Width }
>>         cylinder { Start, End, Width }
>>
>>       #end
>>     #end
>>   }
>> // end partial code snippet

1) Yes, you declare and define Points - the array of control points
for the spline, not the points along it - before you call the macros.

2) Likewise, you declare and define Bias and Tens before you create
the Tau matrix.

3) Points, as I said, is the control point array, not an array of
output points.  Calling Cerp(Iter) gives the current output point.

I am a bit more coherent today, so here is a cleaned up  and expanded
version of the above code with some more explanation of the variables
and operation.  Note the additions.  The material I removed in this
version has to do with constraining the curve, adjusting the aspect
ratio of the output, dealing with closed curves and other things
irrelevant to the point.

Iter determines which pair of control points you are running the curve
between at the moment.

T determines how far along you are between those control points at the
moment.

The business with Fine and Count decide how many sphere and cylinder
pairs you will draw between each pair of control points.

If you just want to return points along the curve for later use, strip
off the union in the last section and remove the parts about End, and
the sphere and cylinder declarations.  Start will be a point along the
output curve.

 // begin partial code snippet

#declare Dim = 6;  // this means an array of 6 control points.

#declare Points = array[Dim]
 { <.1, .5, .9>, <.8, 2, 3> ...} // the control points.

#declare Bias = .5; // max curvature midway between control points

#declare Tens = .5; // curve halfway between loopy and linear
// these bias and tens settings look like a Catmull-Rom spline
// higher tens and bias close to 0 (or 1) makes the curve look like
// (almost) straight lines between the control points with rounded
// "corners" at the control points.  I think that fits your described
// requirements

#declare Fine = 10 // 10 is quick and dirty resolution, 50 or 100
// , say, would be much finer detail (but slower, of course)

#declare Type = "Tau" // type of spline you want.
// for comparison I am adding a matrix for a Beta spline
// (the C-code guys' suggested spline) - like Tau except
// it only approximates the control points instead of passing
// through them (like the difference between the Catmull-Rom
// and B-splines).  Use Type = "Beta" instead of Type = "Tau"

 #declare Tau = array[4][4]
   {
     { (Bias - 1) * Tens, 2 - Bias * Tens, (1 - Bias) * Tens - 2, Bias
 * Tens },
     { 2 * (1 - Bias) * Tens, (3 * Bias - 1) * Tens - 3, 3 - Tens,
-Bias * Tens },
     { (Bias - 1) * Tens, (1 - 2 * Bias) * Tens, Bias * Tens, 0 },
     { 0, 1, 0, 0 }
   }

 #declare Divi = Tens + 2 * (Bias * (Bias * (Bias + 2) + 2) + 1);

#declare Bet = array[4][4]
  {
    { -2 * Bias * Bias * Bias / Divi,
    		 2 * (Tens + (Bias * (Bias * (Bias + 1) + 1))) / Divi,
      -2 * (Tens + Bias * (Bias + 1) +1) / Divi, 2 / Divi },
    { 6 * Bias * Bias * Bias / Divi,
    		-3 * (Tens + 2 *(Bias * Bias * (Bias + 1))) / Divi,
      3 * (Tens + 2 * Bias * Bias) / Divi, 0 },
    { -6 * Bias * Bias * Bias / Divi,
    		6 * Bias * (Bias * Bias - 1) / Divi, 6 * Bias / Divi, 0 },
    { 2 * Bias * Bias * Bias / Divi, (Tens + 4 * Bias * (Bias + 1)) /
Divi,
    	  2 / Divi, 0 }
  }
  
#undef Divi
  
 #if(strcmp(Type, "Tau") = 0)
      #declare Use = Tau
 #else
      #if(strcmp(Type, "Beta") = 0)
         #declare Use = Bet
     #end
#end

#macro Horn(Row, Pt)
   (T * ( T * (T * Use[0][Row] + Use[1][Row]) + Use[2][Row]) +
 Use[3][Row]) * Pt
 #end

 #macro Cerp(Pf)
   Horn(0, Points[Pf - 1]) + Horn(1, Points[Pf]) +
   Horn(2, Points[Pf + 1]) + Horn(3, Points[Pf + 2])
 #end

 union // this union is the output curve
   {
     #declare Iter = 1;
     #while(Iter < Dim)
       #declare Count = max(1, int(Fine * vlength(Points[Iter + 1] -
 Points[Iter])));
       #declare Incr = 1 / Count;
       #declare T = 0;
       #while(T < 1)
         #declare Start = Cerp(Iter);
         #declare T = T + Incr;
         #declare End = Cerp(Iter);
         #declare End = ((End.x = Start.x) ? End + <.001, 0, 0> :
End); // this avoids a degenerate cylinder
         sphere { Start, Width }
         cylinder { Start, End, Width }

       #end
      #declare Iter = Iter + 1; // oops! I left this line out somehow
     #end
   }
 // end partial code snippet

Jerry Anning
clem "at" dhol "dot" org


Post a reply to this message

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