POV-Ray : Newsgroups : povray.general : 2D function to 3D tube : Re: 2D function to 3D tube Server Time
5 May 2024 17:17:51 EDT (-0400)
  Re: 2D function to 3D tube  
From: Tor Olav Kristensen
Date: 24 Dec 2022 23:50:00
Message: <web.63a7d53a560d6168a47c74b589db30a9@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "Droj" <803### [at] drojde> wrote:
>
> > > I will try to do some fine tuning as the heart curve still has an inconsistency
> > > where the dip is.
>
> Yeah - not sure if that's the math or the macro.
> It seems to be right at the beginning of the curve, so maybe instead of going
> from 0 - 2pi, maybe start at pi/180 and see if that trims off the cruft.
>...

My suspicion is that this is caused by a problem with the Paramcalc
macro in meshmaker.inc (The SimpleMesh macro in the code below does
not seem to have this problem.)

The code below also shows an alternative way to make the final
functions for the "tube".

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

#version 3.7;

global_settings { assumed_gamma 1.0 }

#include "functions.inc"  // For f_r()
#include "colors.inc"

#declare TAU = 2*pi;

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

#macro SimpleMesh(FnX, FnY, FnZ, MinU, MaxU, MinV, MaxV, SizeI, SizeJ)

    #local SpanU = MaxU - MinU;
    #local SpanV = MaxV - MinV;
    #local LastI = SizeI - 1;
    #local LastJ = SizeJ - 1;
    #local Vertices = array[SizeI][SizeJ];
    #for (I, 0, LastI)
        // #local U = MinU + I/LastI*DU;
        #local S = I/LastI;
        #local U = MinU + S*SpanU;
        // #local U = FnU(I/LastI);
        #for (J, 0, LastJ)
            // #local V = MinV + I/LastJ*DV;
            // #local V = FnU(J/LastJ);
            #local T = J/LastJ;
            #local V = MinV + T*SpanV;
            #local Vertices[I][J] =
                <FnX(U, V), FnY(U, V), FnZ(U, V)>
            ;
        #end // for
    #end // for

    mesh {
        #for (I, 0, LastI - 1)
            #for (J, 0, LastJ - 1)
                #local p00 = Vertices[I  ][J  ];
                #local p01 = Vertices[I  ][J+1];
                #local p10 = Vertices[I+1][J  ];
                #local p11 = Vertices[I+1][J+1];
                triangle { p00, p10, p11 }
                triangle { p11, p01, p00 }
            #end // for
        #end // for
    }

#end // macro SimpleMesh

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

// Heart curve from https://www.frassek.org
// 0 <= u <= TAU

// Parametric functions for Heart curve and their derivatives:

#declare FnX =
    function(u) {
        16*pow(sin(u), 3)
    }
;
#declare DFnX =
    function(u) {
        48*pow(sin(u), 2)*cos(u)
    }
;

#declare FnY =
    function(u) {
        13*cos(u) - 5*cos(2*u) - 2*cos(3*u) - cos(4*u)
    }
;
#declare DFnY =
    function(u) {
        -13*sin(u) + 10*sin(2*u) + 6*sin(3*u) + 4*sin(4*u)
    }
;

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

#declare Nil = 1e-3;

#declare R = 1.2;


// Rotation angle of cross section of tube

#declare AngleFn =
    function(u) {
        atan2(DFnY(u), DFnX(u)) + pi/2
    }
;

union {
    SimpleMesh(
        function(u, v) { R*cos(v)*cos(AngleFn(u)) + FnX(u) },
        function(u, v) { R*cos(v)*sin(AngleFn(u)) + FnY(u) },
        function(u, v) { R*sin(v) },
        0 + Nil, TAU - Nil,
        0 + Nil, TAU - Nil,
        200, 16
    )
    sphere { <FnX(0/2*TAU), FnY(0/2*TAU), 0>, R }
    sphere { <FnX(1/2*TAU), FnY(1/2*TAU), 0>, R }
    pigment { color Gray50 + Yellow/4 }
    translate -20*x
}


// Normalized component functions for the tangent vector

#declare N_DFnX =
    function(u) {
        DFnX(u)/f_r(DFnX(u), DFnY(u), 0)
    }
;
#declare N_DFnY =
    function(u) {
        DFnY(u)/f_r(DFnX(u), DFnY(u), 0)
    }
;

union {
    SimpleMesh(
        function(u, v) { -R*cos(v)*N_DFnY(u) + FnX(u) },
        function(u, v) { +R*cos(v)*N_DFnX(u) + FnY(u) },
        function(u, v) { +R*sin(v) },
        0 + Nil, TAU - Nil,
        0 + Nil, TAU - Nil,
        200, 16
    )
    sphere { <FnX(0/2*TAU), FnY(0/2*TAU), 0>, R }
    sphere { <FnX(1/2*TAU), FnY(1/2*TAU), 0>, R }
    pigment { color Gray50 + Cyan/4 }
    translate +20*x
}

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

background { color rgb <0.04, 0.02, 0.06> }

light_source {
    -15*x
    color Gray50 + Red/2
    shadowless
}

light_source {
    -15*y
    color Gray50 + Green/2
    shadowless
}

light_source {
    -15*z
    color Gray50 + Blue/2
    shadowless
}

#declare AR = image_width/image_height;

camera {
   orthographic
   location -100*z
   direction z
   right AR*x
   up y
   sky y
   angle 45
}

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

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


Post a reply to this message

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