Quantcast

simple Celtic knot

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

simple Celtic knot

codifies
I ended up fudging this a bit but it basically makes a knot that mobius
(only 1 edge)

as is this will handily print with a layer height of 0.25mm an looks
really nice with higher $fn, leave it at 4 to see the mobius strip like
effect, prints fine with PETg, you will need very good fans to print
with PLA

it does look trivial but I posted it here as the physical end product
looks so nice and it did take a fair bit of tweaking...

Enjoy!

-------------snip!-------------

function knotAng(a,s) =
     [(sin(a)+(2*sin(2*a)))*s,
      (cos(a)-(2*cos(2*a)))*s,
      sin(3*a)*(s*1.5)];


// from wiki

// Find the unitary vector with direction v. Fails if v=[0,0,0].
function unit(v) = norm(v)>0 ? v/norm(v) : undef;
// Find the transpose of a rectangular matrix
function transpose(m) = // m is any rectangular matrix of objects
   [ for(j=[0:len(m[0])-1]) [ for(i=[0:len(m)-1]) m[i][j] ] ];
// The identity matrix with dimension n
function identity(n) = [for(i=[0:n-1]) [for(j=[0:n-1]) i==j ? 1 : 0] ];

// computes the rotation with minimum angle that brings a to b
// the code fails if a and b are opposed to each other
function rotate_from_to(a,b) =
     let( axis = unit(cross(a,b)) )
     axis*axis >= 0.99 ?
         transpose([unit(b), axis, cross(axis, unit(b))]) *
             [unit(a), axis, cross(axis, unit(a))] :
         identity(3);

STEP=4;
SCALE=14; // of overall knot
$fn=4; // use to select number of faces in the path profile

//union() // needed ?
for (a=[0:STEP:360]) {
   v = knotAng(a,SCALE) - knotAng(a+STEP,SCALE);
   v2 = knotAng(a+STEP,SCALE) - knotAng(a+STEP+STEP,SCALE);
   hull() {
     translate(knotAng(a,SCALE))
       multmatrix(rotate_from_to([0,0,1],v))
         rotate(a*1.25)  // fudge
           cylinder(r=SCALE/2,h=0.1,center=true);
     translate(knotAng(a+STEP,SCALE))
       multmatrix(rotate_from_to([0,0,1],v2))
         rotate((a*1.25)+STEP) // fudge
           cylinder(r=SCALE/2,h=0.1,center=true);

   }

}

translate([0,0,-1.35*(SCALE*1.5)]) cylinder(r=3*SCALE,h=2,$fn=128);






_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
ajs
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

ajs
thank you for sharing, I'm going to print up a few!

On Sun, Apr 9, 2017 at 5:03 AM, Mr C Camacho <[hidden email]> wrote:
I ended up fudging this a bit but it basically makes a knot that mobius (only 1 edge)

as is this will handily print with a layer height of 0.25mm an looks really nice with higher $fn, leave it at 4 to see the mobius strip like effect, prints fine with PETg, you will need very good fans to print with PLA

it does look trivial but I posted it here as the physical end product looks so nice and it did take a fair bit of tweaking...

Enjoy!

-------------snip!-------------

function knotAng(a,s) =
    [(sin(a)+(2*sin(2*a)))*s,
     (cos(a)-(2*cos(2*a)))*s,
     sin(3*a)*(s*1.5)];


// from wiki

// Find the unitary vector with direction v. Fails if v=[0,0,0].
function unit(v) = norm(v)>0 ? v/norm(v) : undef;
// Find the transpose of a rectangular matrix
function transpose(m) = // m is any rectangular matrix of objects
  [ for(j=[0:len(m[0])-1]) [ for(i=[0:len(m)-1]) m[i][j] ] ];
// The identity matrix with dimension n
function identity(n) = [for(i=[0:n-1]) [for(j=[0:n-1]) i==j ? 1 : 0] ];

// computes the rotation with minimum angle that brings a to b
// the code fails if a and b are opposed to each other
function rotate_from_to(a,b) =
    let( axis = unit(cross(a,b)) )
    axis*axis >= 0.99 ?
        transpose([unit(b), axis, cross(axis, unit(b))]) *
            [unit(a), axis, cross(axis, unit(a))] :
        identity(3);

STEP=4;
SCALE=14; // of overall knot
$fn=4; // use to select number of faces in the path profile

//union() // needed ?
for (a=[0:STEP:360]) {
  v = knotAng(a,SCALE) - knotAng(a+STEP,SCALE);
  v2 = knotAng(a+STEP,SCALE) - knotAng(a+STEP+STEP,SCALE);
  hull() {
    translate(knotAng(a,SCALE))
      multmatrix(rotate_from_to([0,0,1],v))
        rotate(a*1.25)  // fudge
          cylinder(r=SCALE/2,h=0.1,center=true);
    translate(knotAng(a+STEP,SCALE))
      multmatrix(rotate_from_to([0,0,1],v2))
        rotate((a*1.25)+STEP) // fudge
          cylinder(r=SCALE/2,h=0.1,center=true);

  }

}

translate([0,0,-1.35*(SCALE*1.5)]) cylinder(r=3*SCALE,h=2,$fn=128);






_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

MichaelAtOz
Administrator
Nice.
$fn needs to be multiple of 4.
Shame, as $fn=3 looks great apart from the misalignment...
Admin - PM me if you need anything,
or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.


The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
Does work with fn=3 you have to change the fudge multiple tho

For three sides it would be 1.33333

It needs changing in two places

It could be calculated if $fn was assigned from a "settings" variable called SIDES

Where the multiple would be 1+(1/SIDES) .... off the top of my head...

Three sides does look very effective but you will have to rotate the whole knot on the x and y axis slightly for it to sit on the base

Hope this helps
Chris

On 10 April 2017 01:55:31 BST, MichaelAtOz <oz.at.[hidden email]> wrote:
Nice.
$fn needs to be multiple of 4.
Shame, as $fn=3 looks great apart from the misalignment...



-----
Admin - PM me if you need anything, or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out!
--
View this message in context: http://forum.openscad.org/simple-Celtic-knot-tp21141p21152.html
Sent from the OpenSCAD mailing list archive at Nabble.com.



OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
In reply to this post by MichaelAtOz
okay he's for n sides while retaining its mobius quality - I *will* stop
playing with this now!

----snip-----

STEP=4; // fine in most cases
SCALE=14; // of overall knot
// three SIDES will need the whole model rotating to sit flat on base
SIDES=3; // number of sides in the profile 3 to 16 (unless printed very
large 16 should be plenty for printing)

$fn=SIDES; // use to select number of faces in the path profile

// calculates position in path a=angle s=scale
function knotAng(a,s) =
     [(sin(a)+(2*sin(2*a)))*s,
      (cos(a)-(2*cos(2*a)))*s,
      sin(3*a)*(s*1.5)];


// from wiki

// Find the unitary vector with direction v. Fails if v=[0,0,0].
function unit(v) = norm(v)>0 ? v/norm(v) : undef;
// Find the transpose of a rectangular matrix
function transpose(m) = // m is any rectangular matrix of objects
   [ for(j=[0:len(m[0])-1]) [ for(i=[0:len(m)-1]) m[i][j] ] ];
// The identity matrix with dimension n
function identity(n) = [for(i=[0:n-1]) [for(j=[0:n-1]) i==j ? 1 : 0] ];

// computes the rotation with minimum angle that brings a to b
// the code fails if a and b are opposed to each other
function rotate_from_to(a,b) =
     let( axis = unit(cross(a,b)) )
     axis*axis >= 0.99 ?
         transpose([unit(b), axis, cross(axis, unit(b))]) *
             [unit(a), axis, cross(axis, unit(a))] :
         identity(3);

for (a=[0:STEP:360]) {
   v = knotAng(a,SCALE) - knotAng(a+STEP,SCALE);
   v2 = knotAng(a+STEP,SCALE) - knotAng(a+STEP+STEP,SCALE);
   hull() {
     translate(knotAng(a,SCALE))
       multmatrix(rotate_from_to([0,0,1],v))
         rotate(a*(1+(1.0/SIDES)))  // fudge
           cylinder(r=SCALE/2,h=0.1,center=true);
     translate(knotAng(a+STEP,SCALE))
       multmatrix(rotate_from_to([0,0,1],v2))
         rotate((a*(1+(1.0/SIDES)))+STEP) // fudge
           cylinder(r=SCALE/2,h=0.1,center=true);
   }
}

//base
translate([0,0,-1.35*(SCALE*1.5)]) cylinder(r=3*SCALE,h=2,$fn=128);



On 10/04/17 01:55, MichaelAtOz wrote:

> Nice.
> $fn needs to be multiple of 4.
> Shame, as $fn=3 looks great apart from the misalignment...
>
>
>
> -----
> Admin - PM me if you need anything, or if I've done something stupid...
>
> Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.
>
> The TPP is no simple “trade agreement.”   Fight it! http://www.ourfairdeal.org/   time is running out!
> --
> View this message in context: http://forum.openscad.org/simple-Celtic-knot-tp21141p21152.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

Ronaldo
Nice design! I have already spent a lot of enjoyable time sweeping knots around a torus.

I found a small glitch in the matching between subsequent hulls:




which can be avoided with

        rotate((a+STEP)*1.25)

instead of

        rotate(a*(1.25)+STEP) // fudge





_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
nice catch, thats defo a coding error! fortunately its tiny enough to be well outside the resolution of most 3d printers....

On 10/04/17 19:32, Ronaldo Persiano wrote:
Nice design! I have already spent a lot of enjoyable time sweeping knots around a torus.

I found a small glitch in the matching between subsequent hulls:




which can be avoided with

        rotate((a+STEP)*1.25)

instead of

        rotate(a*(1.25)+STEP) // fudge






_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
In reply to this post by Ronaldo

On 10/04/17 19:32, Ronaldo Persiano wrote:
 > sweeping knots around a torus.

how do you mean? sounds interesting...


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

Ronaldo
codifies wrote
On 10/04/17 19:32, Ronaldo Persiano wrote:
 > sweeping knots around a torus.

how do you mean? sounds interesting...
Yes, it is indeed. You may want to take a look on it in wikipedia. The particular knot you have made is a knot(2,3):



In general in a knot(p,q), p is the number of turns the cord does around the torus and q the number of times the cord goes through the torus hole. I don't know how to change your definition of the knot path to include p and q. I have used another definition:

  function knot(phi,p,q) =
    [ ((r+d)*cos(q*phi) + R)*cos(p*phi),
      ((r+d)*cos(q*phi) + R)*sin(p*phi),
       (r+d)*sin(q*phi) ];
where:

d is the cord section radius
R is the torus major radius
r  is the torus minor radius

The control of the sweep twist is important to get a nice form. Your fudge does exactly that. In the image above I have used another twist value such that one face of the swept cord is facing the torus surface along all the path. Certainly there no Moebius strip with that twist.

If you are interested on that I can provide you my changes to your code with the twist control.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

Neon22
Personally I'd love to see p,q integrated into this code. I had a go but couldn't work it out.
The other problem I have with the existing code - is that the entire path doesn't align when it loops round to the start. I.e. except for a quad, the start and end faces are not twisted so as to align. Try $fn=5.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
I posted (here) a newer version where any value of SIDES creates the
correct twist

@Ronaldo I'd like to see it too, could you post it here for everyone ?


On 11/04/17 04:55, Neon22 wrote:

> Personally I'd love to see p,q integrated into this code. I had a go but
> couldn't work it out.
> The other problem I have with the existing code - is that the entire path
> doesn't align when it loops round to the start. I.e. except for a quad, the
> start and end faces are not twisted so as to align. Try $fn=5.
>
>
>
>
> --
> View this message in context: http://forum.openscad.org/simple-Celtic-knot-tp21141p21183.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

codifies
I've managed to implement the P/Q formula inside the knot script and
while it works, I can't replicate the original 2/3 knot that the
original script did.

That said I have made a very nice braided ring type object...

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

Ronaldo
In reply to this post by codifies
2017-04-11 5:16 GMT-03:00 Mr C Camacho <[hidden email]>:
@Ronaldo I'd like to see it too, could you post it here for everyone ?

Sorry for the delay in answering you. I have been struggling with trigonometric stuff trying to understand the specific parametrization of the knot 2,3 you have used in your celtic knot. It produces a far better shape the the parametrization I have been using. The effort was rewarding... at least for me. :)

I will consider here the celtic knot parametrization (CKP) in the following form without the scale parameters (they can be applied in the calling code):

function knot1(a) =  // CKP parametrization for knot 2,3
    [(sin(a)+(2*sin(2*a))),
     (cos(a)-(2*cos(2*a))),
     sin(3*a)];


and I will compare it with the traditional parametrization for knots p,q:

function knot2(a,p,q,R,r) =
    [ (r*cos(q*a) + R)*cos(p*a),
      (r*cos(q*a) + R)*sin(p*a),
       r*sin(q*a) ];

This parametrization may be rewritten to be clear that it is a knot on a circular torus:

function knot3(a,p,q,R,r) =
    let( t = [(r*cos(q*a) + R), 0, r*sin(q*a) ] ) // circle in XZ
    [ [ cos(p*a), sin(p*a), 0],
      [-sin(p*a), cos(p*a), 0],  // rotation in Z of p*a degrees
      [0,0,1] ] * t;


This parametrization is a rotation in Z with an angle p*a of a point 't' that also depends on 'a'. The expression of point t is itself a parametrization of a circle of radius 'r' on the XZ plane centered at the point [ R,0,0 ]. For 0<= a <= 360, the parametrization t does q turns on the circle and the rotation does p turns around Z axis. The net result will be a p,q knot on the surface of a circular torus with major radius 'R' and minor radius 'r'. The following image shows the knot 2,3 (also known as trefoil) computed with knot3():


​ 

In the image, a partial torus appears transparent and its transversal section highlighted in red. Note that the knot cord section center is on the torus surface.

However, the shape of the knot generated by knot1() is far better specially in the section it goes thought the torus hole.




Observe that the torus section of knot1() parametrization is not a circle anymore. If we get a good parametrization of this section we may rewrite knot1() in the form:

function knot1a(a) =
    let( t = section_parametrization(3*a) )
    [ [ cos(2*a), sin(2*a), 0],
      [-sin(2*a), cos(2*a), 0],  // rotation in Z of 2*a degrees
      [0,0,1] ] * t;

and then substitute p for 2 and q for 3 to get a general knot p,q with the good shape of knot1().

Here is where the trigonometric stuffs are handy. After many failed trials I have found the proper parametrization behind knot1().

function knot1b(a) =
    let( t = [ sin(3*a), cos(3*a) - 2, sin(3*a) ] ) // section parametrization
    [ [ cos(2*a), -sin(2*a), 0],
      [ sin(2*a),  cos(2*a), 0],  // rotation in z of 2*a degrees
      [0,0,1] ] *
      t;


This formulation is exactly equivalent to knot1() but it is now evident the p,q numbers in it. If we compare knot1b() with knot3 it is also evident that the section parametrization here is not a vertical section of the torus anymore. In fact, if we sweep just the section t, we get:



The torus transversal section is a slanted ellipsis!

Now, introducing p, q, R and r in the knot1b() we get our general form of knot1():

function knot4(a,p,q,R,r) =
    let( t = [ sin(q*a+alpha), cos(q*a+beta) - R, r*sin(q*a) ] ) // elliptical slanted section
    [ [ cos(p*a), -sin(p*a), 0],
      [ sin(p*a),  cos(p*a), 0],  // rotation in z of p*a degrees
      [0,0,1] ] * t;


With this formulation we may explore other knots like the cinquefoil (3,5) and its "dual" 5,3 :







Along of my multiple attempts to find knot4() expressions I have discovered new possibilities to define interesting parametrizations of p,q knots, like for instance the following interwoven basket:



This is a knot 5,8 we get with simple changes in knot4() introducing two more shape parameters:

function knot5(a,p,q,R,r,alpha,beta) =
    let( t = [ sin(q*a+alpha), cos(q*a+beta) - R, r*sin(q*a) ] ) // elliptical slanted transversal section
    [ [ cos(p*a), -sin(p*a), 0],
      [ sin(p*a),  cos(p*a), 0],  // rotation in z of p*a degrees
      [0,0,1] ] * t;

The phase parameters alpha and beta are angles that produce very different torus shapes. In the last basket-like knot I have used alpha=beta=60. In the following, we have p=7, q=11, alpha=80 and beta=50 with a different look




This same technique may be introduced in the definition of the circular knot3():

function knot6(a,p,q,R,r) =
    let( t = [(r*cos(q*a+alpha) + R), 0, r*sin(q*a) ] ) // circle in xz
    [ [ cos(p*a), sin(p*a), 0],
      [-sin(p*a), cos(p*a), 0],  // rotation in z of p*a degrees
      [0,0,1] ] * t;


to achieve other basket shapes:




with the same parameters (7,11,80,50).

All this open up infinite possibilities to shape torus knots: just define a suitable expression of t in knot5() !

That was a rather long message. I will leave the sweep aspects to another time.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

MichaelAtOz
Administrator
OK, I give up.
I can see how it gets a face pointing to the centre.

How are you calling knot() to get a shape to hull in the right direction, such as a three sided cylinder.
And I'm getting results that appear as if r was negligable, looking from the top its a circle.
Admin - PM me if you need anything,
or if I've done something stupid...

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work.
Obviously inclusion of works of previous authors is not included in the above.


The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: simple Celtic knot

Ronaldo
Michael,

To make my discussion clearer I have dropped all scales from knotAng(). To apply the my knot functions to @codifies code you should recode knotAng() as:

p = 7;
q = 11;
alpha = 80;
beta =50;
function knotAng(a,s) =
    [[s,0,0],[0,s,0],[0,0,s*1.5]]*knot4(a,p,q,2,1);

where you may use almost any of my knot functions instead of knot4(). Chose the values of p, q, alpha and beta at your will.

The second @codifies code possibly work for any case even with SIDES=3, but I haven't tested this. For higher values of p and/or q it is advisable to reduce the cylinder radius and the STEP size. In my examples I have used larger values for SIDES to get a rounded cord and less apparent twists.

I don't know what you mean by:
"I can see how it gets a face pointing to the centre."


2017-04-13 0:10 GMT-03:00 MichaelAtOz <[hidden email]>:
OK, I give up.
I can see how it gets a face pointing to the centre.

How are you calling knot() to get a shape to hull in the right direction,
such as a three sided cylinder.
And I'm getting results that appear as if r was negligable, looking from the
top its a circle.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Loading...