POV-Ray : Newsgroups : povray.advanced-users : Smooth, continuous Bezier splines (again) : Re: Smooth, continuous Bezier splines (again) Server Time
5 Feb 2025 15:12:34 EST (-0500)
  Re: Smooth, continuous Bezier splines (again)  
From: Tor Olav Kristensen
Date: 29 Jan 2025 10:55:00
Message: <web.679a4e6d96675d9fdd186bde89db30a9@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "ingo" <nomail@nomail> wrote:
> > The bisect of the angles in the current lines are the normals to the handles in
> > that point. The handles should be equally long to get C1/G1 (?) continuity.
> >
> > I think, without testing,
>
> Yes, excellent idea.
>...

Hi Bill

The code below shows the results of what I think Ingo suggested.

--
Tor Olav
http://subcube.com
https://github.com/t-o-k


// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#version 3.7;

global_settings { assumed_gamma 1.0 }

#include "colors.inc"

default {
    texture {
        pigment { color White }
        finish {
            diffuse 0
            emission color White
        }
    }
}

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#macro CubicBezierFn(c0, c1, c2, c3)

    function(s) {
        0
        + pow(1 - s, 3)*c0
        + 3*pow(1 - s, 2)*s*c1
        + 3*(1 - s)*pow(s, 2)*c2
        + pow(s, 3)*c3
    }

#end // macro CubicBezierFn


#macro Plot(FnX, FnY, FnZ, NoOfSegments, Radius)

    #local dS = 1/NoOfSegments;

    union {
        #local S0 = 0;
        #local p0 = <FnX(S0), FnY(S0), FnZ(S0)>;
        // sphere { p0, Radius }
        #for (I, 0, NoOfSegments - 2)
            #local S1 = S0 + dS;
            #local p1 = <FnX(S1), FnY(S1), FnZ(S1)>;
            cylinder { p0, p1, Radius }
            sphere { p1, Radius }
            #local S0 = S1;
            #local p0 = p1;
        #end // for
        #local S1 = S0 + dS;
        #local p1 = <FnX(S1), FnY(S1), FnZ(S1)>;
        cylinder { p0, p1, Radius }
        // sphere { p1, Radius }
    }

#end // macro Plot

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#declare Debug = false;


#declare NoOfPoints = 9;
#declare Points =
    array[NoOfPoints] {
        <-0.297/2, -1.000, 0.000>,
        <-0.203/2, -0.500, 0.000>,
        <-0.115/2, -0.250, 0.000>,
        <-0.069/2, -0.125, 0.000>,
        < 0.000/2,  0.000, 0.000>
        <+0.069/2, -0.125, 0.000>,
        <+0.115/2, -0.250, 0.000>,
        <+0.203/2, -0.500, 0.000>,
        <+0.297/2, -1.000, 0.000>,
    }
;

#declare R = 0.006;

#if (true)
    union {
        #for (I, 0, NoOfPoints - 1)
            sphere { Points[I], R }
        #end // for
        pigment { color White }
    }
#end // if


#declare NoOfOrthogonalVectors = NoOfPoints - 1;
#declare OrthogonalVectors = array[NoOfOrthogonalVectors];
#for (I, 0, NoOfOrthogonalVectors - 1)
    #declare OrthogonalVectors[I] = vnormalize(vcross(Points[I+1] - Points[I],
z));
#end // for

#if (Debug)
    union {
        #for (I, 0, NoOfOrthogonalVectors - 1)
            cylinder {
                0*z, OrthogonalVectors[I], R/4
                translate (Points[I] + Points[I+1])/2
            }
        #end // for
        pigment { color Red }
    }
#end // if


#declare NoOfBisectingVectors = NoOfPoints;
#declare BisectingVectors = array[NoOfBisectingVectors];
#declare BisectingVectors[0] = OrthogonalVectors[0];
#for (I, 1, NoOfBisectingVectors - 2)
    #declare BisectingVectors[I] = vnormalize(OrthogonalVectors[I-1] +
OrthogonalVectors[I]);
#end // for
#declare BisectingVectors[NoOfBisectingVectors-1] =
OrthogonalVectors[NoOfOrthogonalVectors-1];

#if (Debug)
    union {
        #for (I, 0, NoOfBisectingVectors - 1)
            cylinder {
                0*z, BisectingVectors[I], R/4
                translate Points[I]
            }
        #end // for
        pigment { color Magenta }
    }
#end // if


#declare NoOfTangentVectors = NoOfBisectingVectors;
#declare TangentLengths =
    array[NoOfTangentVectors] {
        0.10,
        0.10,
        0.08,
        0.04,
        0.01,
        0.04,
        0.08,
        0.10,
        0.10
    }
;
#declare TangentVectors = array[NoOfTangentVectors];
#for (I, 0, NoOfTangentVectors - 1)
    #declare TangentVectors[I] = TangentLengths[I]*vcross(+z,
BisectingVectors[I]);
#end // for

#if (Debug)
    union {
        #for (I, 0, NoOfTangentVectors - 1)
            cylinder {
                0*z, +TangentVectors[I], R/4
                translate Points[I]
            }
            cylinder {
                0*z, -TangentVectors[I], R/4
                translate Points[I]
            }
        #end // for
        pigment { color Blue }
    }
#end // if


#declare NoOfSegments = 16;
#for (I, 0, NoOfPoints - 2)
    #declare pA = Points[I  ];
    #declare pB = Points[I  ] + TangentVectors[I  ];
    #declare pC = Points[I+1] - TangentVectors[I+1];
    #declare pD = Points[I+1];
    #if (Debug)
        union {
            // sphere { pA, R }
            sphere { pB, R }
            sphere { pC, R }
            // sphere { pD, R }
            pigment { color Blue }
        }
    #end // if
    object {
        Plot(
            CubicBezierFn(pA.x, pB.x, pC.x, pD.x),
            CubicBezierFn(pA.y, pB.y, pC.y, pD.y),
            CubicBezierFn(pA.z, pB.z, pC.z, pD.z),
            NoOfSegments,
            R/4
        )
        pigment { color Black }
        translate -1.0*z
    }
#end // for

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

background { color Gray40 }

#declare AR = image_width/image_height;

camera {
    orthographic
    location < 0.0, -0.5, -2.0>
    right AR*x
    up y
    direction z
    angle 30
}

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7


Post a reply to this message

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