Close

Torus knot OpenSCAD code​

RAERAE wrote 09/30/2021 at 11:30 • 5 min read • Like

//  File: torus_knot-XYZ3.scad                             

//  Author: DonEMitchell, Westcliffe, CO
//  Copyright DonEMitchell, Feb. 9, 2019

//  Description: A parameterized torus knot module using calculated XYZ coordinates.
//  Purpose: Generate a hulled-sequence (skinned) of spheres arranged along the path of a torus knot wound on a torus.  
//                                                               
//    Module parameters: (R)majorRadius, (r)minorRadius,
//      knotRevolutions(p), knotTwists(q)
//      stepDegrees, loopDia
//
//  Caveat:  The torus knot arc hulled-segments are looped from zero to 360, overlapping zero and 360 to close of the torus knot hull.

/// Calculate constant Phi and define pi:
Phi = pow(5,.5)*.5+.5;   // Φ = ϕ = 1.61803399 dot dot dot.
pi = 3.14159265;         // Π  = Π = 3.14159265 dot dot dot.

   /////////////////////////////////////////////////////////
  ///  Set module variables, torus and torus knot       ///
 ///  parameters to create a golden orthogonal knot**  ///
/////////////////////////////////////////////////////////

/// **A golden orthogonal knot has inner loops of the torus knot 
///   crossing the torus plane through the torus hole at a 90 degree
///   separation (orthogonal) from the angle of the outer loops 
///   crossing the torus plane.  The torus knot ratio (p,q) is any two 
///   neighboring numbers on the Fibonacci sequence, so the torus 
///   knot ratio is a Fibonacci approximation of the golden ratio.

///  Set p:q parameters as an adjacent pair of numbers
///  in the Fibonacci sequence:
///  p Divided by q approximates the golden ratio when
//      q = F(n) and
//      p = F(n+4)
// where F(n) equals the nth Fibonnacci number in the Fibonacci sequence.

p = 13; // Helical twists around the torus tube forming the torus surface.
q =  8; // Axial rotations (Z) radially sweeping in the X,Y plane.

///  Set the major radius and 'hole' radius of the torus
///  to powers of the golden ratio. 'Hole' radius = R - r.

R =     pow(Phi,4);    // Torus major radius.
r = R - pow(Phi,0);    // Torus minor radius.
// Fudge r a scooch to adjust torus to proper bury-depth of the knot into the torus.

/// Torus knot appearance parameters:
loopDia     = 2;       // Fatness of the torus knot loop. 
stepDegree  = 1;       // for-loop incrementing variable.
fnTorus     = 39;
fnTorusKnot = 4;    

phaseCount = 3;
// Default the module to a golden orthogonal torus knot.
module torusKnotXYZ(
        p           = 3, // Default parameter values 
        q           = 2,
        R           = 2.61803,
        r           = 2.236068,
        showTorus   = true,
        stepDegree  = 1/2,
        loopDia     = .125,
        fnTorus     = 39,// Face number of torus.
        fnTorusKnot = 4, // Face number for a square loop cross section.
        phaseCount  = 1
        ){

    phaseSeparation = 360/phaseCount;

    /// R:r Is the major:minor torus radii.
    /// p:q Is a ratio of poloidal rotations (around axis) over helical twists through hole.
    //scale([10,10,10])
    //difference(){
       /// A toroidal surface the knot helix winds upon:
        rotate_extrude($fn=fnTorus)
        translate([R,0,0])
        circle(r=r, $fn=fnTorus);
        
        // Build the torus knot.
        for(step=[0:stepDegree:360-stepDegree]) {
            for(phaseNumber=[0:phaseCount-1]){
                
                // Calculate two points of the knot, loop-wise.
                p1 = [ (R + r * cos(q*step)) * cos(p*step),
                       (R + r * cos(q*step)) * sin(p*step),
                       r * sin(q*step) ];

                step2 = step + stepDegree;
                p2 = [ (R + r * cos(q*step2)) * cos(p*step2),
                       (R + r * cos(q*step2)) * sin(p*step2),
                       r * sin(q*step2) ];

                // Rotate the knot points to their angular position around the axis of the hole.
                rotate([0,0,phaseNumber*phaseSeparation])
                color("Lime",1)
                hull(){
                    translate(p1) 
                    sphere(r=loopDia*1.4, $fn=fnTorusKnot);
                    
                    translate(p2) 
                    sphere(r=loopDia*1.4, $fn=fnTorusKnot);
                
                }
                // End iterated core.

            } // End for(phaseNumber).

        } // End for(s).

        // Build the contra torus knot.
        for(step=[0:stepDegree:360-stepDegree]) {
            for(phaseNumber=[0:phaseCount-1]){
                
                // Begin iterated core.
                p2 = [ (R + r * cos(q*step)) * cos(p*step),
                       (R + r * cos(q*step)) * sin(p*step),
                       r * sin(q*step) ];

                step2 = step + stepDegree;
                p1 = [ (R + r * cos(q*step2)) * cos(p*step2),
                       (R + r * cos(q*step2)) * sin(p*step2),
                   E    r * sin(q*step2) ];
                
                rotate([0,0,phaseNumber*phaseSeparation])
                // Join the points with a smooth hull.
                hull(){
                    translate(p1) 
                    sphere(r=loopDia, $fn=fnTorusKnot);
                    
                    translate(p2) 
                    sphere(r=loopDia, $fn=fnTorusKnot);
                }
                // End iterated core.

            } // End for(phaseNumber).

        } // End for(s).
    //} // End differnce(). Uncomment here and above to create a hollow in the torus.
}  // End module torusKnotXYZ().

// Call the torusKnotXYZ() module defined above.
torusKnotXYZ(q=q, p=p, R=R, r=r, loopDia=.2);

Like

Discussions