POV-Ray : Newsgroups : povray.advanced-users : Curve calculation : Re: Curve calculation Server Time
30 Jul 2024 14:19:27 EDT (-0400)
  Re: Curve calculation  
From: Jerry Anning
Date: 23 May 1999 14:13:06
Message: <37483454.2444563@news.povray.org>
On Sun, 23 May 1999 15:54:15 +0300, Lewis <nle### [at] netvisionnetil>
wrote:

>I'm starting to work on a nice little macro project (you'll see when
>it's done). I need to be able to calculate a path using only several
>points on it. For example, I get the coordinates of points A, B and C. I
>want to calculate a position on a path that goes through A, B and C,
>that is SMOOTH. That is, the path bends smoothly from A to C, going
>through B, without sudden turns. I should be able to specify what level
>of "bendness" I want, that is how smooth the path will be. It isn't as
>easy as I thought in the beggining.

I wrote a little tutorial once on the subject, but I can't find it.
In the meantime, here is an old project that may put you on the right
track.  It plays with several spline types.  It has bugs - in
particular, the Kochanek-Bartels part doesn't work - but the other
spline types you would want for this project are fine.  If you have to
pass through every given point, use the Cardinal spline and adjust
tension to control smoothness or the Tau spline, where you can also
adjust bias to control how close to which end of the segment the max
curvature is.  Play with it.  You can get better smoothness at the
cost of passing near, not through some points, by using the tensed B
spline or the Beta (tensed and biased B) spline.  You should be able
to extract the ideas you need from this.

// Begin POV code

// Loop.pov - Produces a reference image of the given point set

#version 3.1;

// Do not touch these declares
#declare Crosseye = 2 / 3;
#declare  Regular = 4 / 3;
#declare Square = 1;
#declare Crosssquare = 1 / 2;
#declare Straight = <  0,  0, 0>;
#declare   Crossl = <  0,  1, 0>;
#declare   Crossr = <  0, -1, 0>;

// Use these declares to change the image
#declare Method = 0;
  // 0 for ordinary image or crosseye video
  // 1 for blue-red image
#declare Aspect = Regular;
  // Regular for 800x600 plain or blue-red image
  // Crosseye for 800x600 crosseye video
  // Square for 600x600 plain or blue-red image
  // Crosssquare for 600x600 crosseye video
#declare Angle = Straight;
  // Straight for plain or blue-red image
  // Crossl for left half of crosseye video image
  // Crossr for right half of crosseye video image
#declare File = "Goofy.pts"
  // Name of file containing points (in quotes)
#declare Fine = 10;
  // How smooth image should be.  10 is fairly rough, 50 is very
smooth (but slow)
#declare Width = 2;
  // How thick loop should be
#declare Tens = .25;
  // Tension for Cardinal, Tau, Beta, Tensed B-spline or
Kochanek-Bartels spline
#declare Bias = .75;
  // Bias for Tau, Beta or Kochanek-Bartels spline
#declare Cont = 0;
	// Continuity for Kochanek-Bartels spline
#declare Type = "Kochbar"
  // (should be in quotes)
  // Catmull for Catmull-Rom spline
  // Cardinal for Cardinal spline
  // Tau for Tau spline
  // Bezier for Bezier spline
  // Bspline for B-spline
  // Beta for Beta spline
  // Tbspline for Tensed b-spline
  // Kochbar for Kochanek-Bartels spline
#declare Elev = 0;
  // Elevation (in degrees)
#declare Azim = 0;
  // Azimuth (in degrees)
#declare Close = 1;
	// 0 means "do not close the loop"
	// 1 means "close the loop
#declare Show = 1;
  // 1 means "show control points"
  // 0 means "do not show control points"

// Do not touch declares past this point
#declare White = color rgb <1, 1, 1>;
#declare Black = color rgb <0, 0, 0>;
#declare Red = color rgbt <1, 0, 0, .9>;
#declare Blue = color rgbt <0, 0, 1, .9>;

#declare Shine =
finish
  {
      specular 1.000
     roughness 0.030
       ambient 0.000
       diffuse 1.000
  }
  
#declare Curvtex =
texture
  {
    pigment { color Black }
    finish { Shine }
  }
  
#declare Curvtexr =
texture
  {
    pigment { color Red }
  }
  
#declare Curvtexb =
texture
  {
    pigment { color Blue }
  }

global_settings { assumed_gamma 1.0 } 

camera { up <0, 1, 0> right <Aspect, 0, 0> 
  location <0, 0, -50> look_at <0, 0, 0> rotate Angle}

light_source { <0, 0, -20> color White * 3 }

sky_sphere { pigment { color White } }

#fopen Ptlist File read

#read(Ptlist, Dim)

#declare Ptemp = array[Dim]

#declare Iter = 0;
#while(Iter < Dim)
  #read(Ptlist, Temp)
  #declare Ptemp[Iter] = Temp;
  #undef Temp
  #declare Iter = Iter + 1;
#end

#fclose Ptlist

#declare Points = array[Dim + 2 * (Close + 1)]

#declare Points[0] = ((Close = 0) ? Ptemp[Dim -1] : Ptemp[Dim - 2]);
#if(Close = 1)
	#declare Points[1] = Ptemp[Dim - 1];
#end
#declare Points[Dim + (Close + 1)] = Ptemp[0];
#if(Close = 1)
	#declare Points[Dim + 3] = Ptemp[1];
#end

#declare Iter = 0;
#while(Iter < Dim)
  #declare Points[Iter + (Close + 1)] = Ptemp[Iter];
  #declare Iter = Iter + 1;
#end

#undef Ptemp

#declare Sum = <0, 0, 0>;
#declare Iter = Close + 1;
#while(Iter < Dim + (Close + 1))
  #declare Sum = Sum + Points[Iter];
  #declare Iter = Iter + 1;
#end

#declare Centroid = Sum / Dim;

#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 Iter = 0;
#while(Iter < Dim + 2 * (Close + 1))
  #declare Points[Iter] = Points[Iter] - Centroid;
  #declare Points[Iter] = vrotate(Points[Iter], <0, Elev, 0>);
  #declare Points[Iter] = vrotate(Points[Iter], <-Azim, 0, 0>);
  #declare Points[Iter] = Points[Iter] + Centroid;
  #declare Iter = Iter + 1;
#end

#declare Sum = <0, 0, 0>;
#declare Min = <1, 1, 1>;
#declare Max = <0, 0, 0>;

#declare Iter = Close +1;
#while(Iter < Dim + (Close + 1))
  #declare Sum = Sum + Points[Iter];
  #declare Min = Mnv(Min, Points[Iter]);
  #declare Max = Mxv(Max, Points[Iter]);
  #declare Iter = Iter + 1;
#end

#declare Centroid = Sum / Dim;
#declare Centroid = <Centroid.x, Centroid.y, 0>;
#declare Diff = Max - Min;
#declare Iter = 0;
#while(Iter < Dim + 2 * (Close + 1))
  #declare Points[Iter] = Mxv(Mnv((Points[Iter] * <42 * Aspect, 42,
21> / Diff - 
                          (1 + Centroid) * <21 * Aspect, 21, 0>),
                          <21 * Aspect, 21, 21>), <-21 * Aspect, -21,
0>);
  #if(Show = 1)
    sphere { Points[Iter], Width * 1.2 texture { pigment { color rgb
             ((Iter = Close + 1) ? <1, 1, 0> : <0, 1, 0>) } }
             scale ((Iter = Close + 1) ? 1.2 : 1) }
  #end
  #declare Iter = Iter + 1;
#end

#declare Cat = array[4][4]
  {
    { -0.5,  1.5, -1.5,  0.5 },
    {  1.0, -2.5,  2.0, -0.5 },
    { -0.5,  0.0,  0.5,  0.0 },
    {  0.0,  1.0,  0.0,  0.0 }
  }

#declare Car = array[4][4]
  {
    { -Tens, 2 - Tens, Tens - 2, Tens },
    { 2 * Tens, Tens - 3, 3 - 2 * Tens, -Tens },
    { -Tens, 0, Tens, 0 }
    { 0, 1, 0, 0 }
  }
  
#declare Bsp = array[4][4]
  {
    { -1 / 6, 1 / 2, -1 / 2, 1 / 6 },
    { 1 / 2, -1, 1 / 2, 0 },
    { -1 / 2, 0, 1 / 2, 0 },
    { 1 / 6, 2 / 3, 1 / 6, 0 }
  }
  
#declare Tbs = array[4][4]
  {
    { -Tens / 6, 2 - 1.5 * Tens, 1.5 * Tens - 2, Tens / 6 },
    { Tens / 2, 2 * Tens - 3, 3 - 2.5 * Tens, 0 },
    { -Tens / 2, 0, Tens / 2, 0 },
    { Tens / 6, 1 - Tens / 3, Tens / 6, 0 }
  }
  
#declare Bez = array[4][4]
  {
    { -1, 3, -3, 1 },
    { 3, -6, 3, 0 },
    { -3, 3, 0, 0 },
    { 1, 0, 0, 0 }
  }
  
#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
  
#declare Mult = (1 - Tens) / 2;

#declare Alpha = Mult * (1 - Bias) * (1 - Cont);
#declare Beta = Mult * (1 + Bias) * (1 + Cont);
#declare Gamma = Mult * (1 - Bias) * (1 + Cont);
#declare Delta = Mult * (1 + Bias) * (1 - Cont);

#undef Mult

#declare Kbs = array[4][4]
	{
		{ -Beta, -Alpha + Beta -Delta + 2, Alpha -Gamma + Delta -2, Gamma
},
		{ 2 * Beta, 2 * (Alpha - Beta) + Delta + 3, -2 * Alpha + Gamma -
Delta + 3,
			-Gamma },
		{ -Beta, -Alpha + Beta, Alpha, 0 },
		{ 0, 1, 0, 0 }
	}
	
#undef Alpha
#undef Beta
#undef Gamma
#undef Delta
  
#if(strcmp(Type, "Cardinal") = 0)
  #declare Use = Car
#else
  #if(strcmp(Type, "Bspline") = 0)
    #declare Use = Bsp
  #else
    #if(strcmp(Type, "Tbspline") = 0)
      #declare Use = Tbs
    #else
      #if(strcmp(Type, "Bezier") = 0)
        #declare Use = Bez
      #else
        #if(strcmp(Type, "Tau") = 0)
          #declare Use = Tau
        #else
          #if(strcmp(Type, "Beta") = 0)
            #declare Use = Bet
          #else
          		#if(strcmp(Type, "Kochbar") = 0)
          			#declare Use = Kbs
          		#else
            		#declare Use = Cat
            	#end
          #end
        #end
      #end
    #end
  #end
#end

#declare T = 0;

#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

#declare Loop =
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
      #declare Iter = Iter + ((strcmp(Type, "Bezier") = 0) ? 3 :
                             ((strcmp(Type, "Kochbar") = 0) ? 3 : 1
));
    #end
  }
  
#if (Method = 1)
  object { Loop texture { Curvtexr } }
#else
  object { Loop texture { Curvtex } }
#end

#if (Method = 1)
  object { Loop texture { Curvtexb } translate <.75 * Width, 0, -.001>
} 
#end

// End POV Code

// Begin sample point file

8,
<.25, .25, .25>,
<.33, .25, .25>,
<.66, .75, .75>,
<.75, .75, .75>,
<.75, .66, .66>,
<.25, .33, .33>,
<.10, .10, .10>,
<.5, .5, .5>

// End sample point file


Jerry Anning
clem "at" dhol "dot" com


Post a reply to this message

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