snibgo's ImageMagick pages

Knots

We can draw pretty pictures of knots.

Some ropes below are drawn with the path command. See SVG 1.1: Paths for syntax detils.

Linked rings

We draw a red ring and a blue ring on a khaki background. We do this in an unusual way: draw a red ring on transparent background, clone this, make it blue, and merge the layers.

%IM%convert ^
  -size 400x400 ^
  xc:None ^
  -fill None ^
  -strokewidth 50 -stroke Red ^
  -draw "translate 200,200 circle 0,0 0,150" ^
  ( +clone ^
    -fill Blue -colorize 100 ^
    -repage +150+0 ^
  ) ^
  -background khaki -layers merge ^
  +repage ^
  kn_c1.png
kn_c1.png

We want the rings to intertwine. At the top we will leave the red ring under the blue. At the bottom, we will repaint the red over the blue. We do this by cloning the red layer and erasing the top half. By messing with the alpha channel, anywhere we draw an opaque colour becomes transparent.

-background Red -alpha Background is because the rectangle makes a line of transparent black. This may be a bug in IM from about v6.9.1-0. See forum post Transparent geometric shapes.

set NEGA=-channel alpha -negate +channel

%IM%convert ^
  -size 400x400 ^
  xc:None ^
  -fill None ^
  -strokewidth 50 -stroke Red ^
  -draw "translate 200,200 circle 0,0 0,150" ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -repage +150+0 ^
  ) ^
  ( -clone 0 ^
    -fill Red -strokewidth 0 ^
    %NEGA% ^
    -draw "rectangle 0,0 399,200" ^
    -background Red -alpha Background ^
    %NEGA% ^
  ) ^
  -background gray90 -layers merge ^
  +repage ^
  kn_c2.png
kn_c2.png

Now we do three rings. We draw red under green, green under blue, and blue under red. So the second red ring needs to be made transparent where the blue layer is fully transparent.

set BLUE_GEOM=+150+0

%IM%convert ^
  -size 500x500 ^
  xc:None ^
  -fill None ^
  -strokewidth 50 -stroke Red ^
  -draw "translate 250,250 circle 0,0 0,150" ^
  -background Black -alpha Background ^
  ( -clone 0 ^
    -fill Green -colorize 100 ^
    -repage +75+130 ^
  ) ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -repage %BLUE_GEOM% ^
  ) ^
  ( -clone 0 ^
    ( +clone ^
      -alpha Extract ^
      -fill #fff +opaque #000 ^
      -alpha Copy ^
    ) ^
    -geometry %BLUE_GEOM% ^
    -channel A ^
    -compose Multiply -composite ^
    +channel ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  +repage ^
  kn_c3.png
kn_c3.png

For setting transparency in the red, we don't actually use the blue image. The blue's alpha is exactly the same as the red's alpha, so we just clone that. On this copy, we make any partially-transparent pixels fully opaque. Otherwise, we get a halo of blue through the red ring.

This method is awkward, but easier than calculating intersecting points.

Shading

set SHADE_ROPE=^( +clone ^
    -fill #fff -colorize 100 -background #000 -alpha Background ^
    -morphology Distance Euclidean:7 ^
    -auto-level ^
    -function sinusoid 0.5,-90,0.5,0.5 ^
    -shade 120,45 ^
  ^) ^
  -compose Luminize -composite
%IM%convert ^
  -size 500x500 ^
  xc:None ^
  -fill None ^
  -strokewidth 50 -stroke Red ^
  -draw "translate 250,250 circle 0,0 0,150" ^
  -background Black -alpha Background ^
  %SHADE_ROPE% ^
  ( -clone 0 ^
    -fill Green -colorize 100 ^
    -repage +75+130 ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -repage %BLUE_GEOM% ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    ( +clone ^
      -alpha Extract ^
      -fill #fff +opaque #000 ^
      -alpha Copy ^
    ) ^
    -geometry %BLUE_GEOM% ^
    -channel A ^
    -compose Multiply -composite ^
    +channel ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  +repage ^
  kn_c4.png
kn_c4.pngjpg

This works only if the rope doesn't overlap itself.

set SPATH=M 50,50 ^
  c 50,0 250,100  100,100 ^
   -50,0  50,-100 100,-100

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  %SHADE_ROPE% ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_s1.png
kn_s1.png

A simple shade

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  ( +clone ^
    -fill #fff -colorize 100 -background #000 -flatten ^
    -shade 120,45 ^
  ) -alpha off -compose Luminize -composite -alpha on ^
  kn_s2.png
kn_s2.png

Blur, then shade

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  ( +clone ^
    -fill #fff -colorize 100 -background #000 -flatten ^
    -blur 0x3 ^
    -shade 120,45 ^
  ) -compose Luminize -composite ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_s3.png
kn_s3.png

Path is doubled

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 29 -stroke Black ^
  -draw "path '%SPATH%'" ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_s4.png
kn_s4.png

Path is trebled, with translations

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke White ^
  -draw "translate -2,-2 path '%SPATH%'" ^
  -strokewidth 25 -stroke Black ^
  -draw "translate 2,2 path '%SPATH%'" ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_s5.png
kn_s5.png

Splitting the path clarifies the crossover,
but introduces a new end (which could be erased).

set SPATH_A=M 50,50 ^
  c 50,0 250,100  100,100

set SPATH_B=M 150,150 ^
  c -50,0  50,-100 100,-100

%IM%convert ^
  -size 300x200 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke White ^
  -draw "translate -2,-2 path '%SPATH%'" ^
  -strokewidth 25 -stroke Black ^
  -draw "translate 2,2 path '%SPATH%'" ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH%'" ^
  -strokewidth 25 -stroke White ^
  -draw "translate -2,-2 path '%SPATH_B%'" ^
  -strokewidth 25 -stroke Black ^
  -draw "translate 2,2 path '%SPATH_B%'" ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%SPATH_B%'" ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_s6.png
kn_s6.png

Thumb knot

Three layers: red, blue, and red again. The second red layer is made transparent in a central vertical strip.

set TPATH=m 50,400 ^
  c 0,-100 60,-200  130,-200 ^
    60,0   60,50    110,50 ^
    60,0   100,-100 130,-200

%IM%convert ^
  -size 500x450 ^
  xc:None ^
  -fill None ^
  -strokewidth 25 -stroke Red ^
  -draw "path '%TPATH%'" ^
  %SHADE_ROPE% ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -flop ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    -region 100x450+200+0 ^
    -channel A -evaluate set 0 +channel ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_t1.png
kn_t1.png

Reef knot

As with the thumb knot, we have three layers: red, blue, and red again, and again the second red layer is made transparent in a central vertical strip.

set RPATH=m 50,500 ^
  c 0,-100 60,-200   130,-200 ^
    60,0   60,50     110,50 ^
    60,0   60,-150   0,-150 ^
   -60,0  -60,50    -110,50 ^
   -60,0  -130,-100 -130,-200

%IM%convert ^
  -size 500x550 ^
  xc:None ^
  -fill None ^
  -strokewidth 35 -stroke Red ^
  -draw "path '%RPATH%'" ^
  %SHADE_ROPE% ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -flop ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    %NEGA% ^
    -fill Red -strokewidth 0 -stroke Red ^
    -draw "rectangle 200,0 300,549" ^
    %NEGA% ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_r1.png

%IM%convert ^
  -size 500x550 ^
  xc:None ^
  -fill None ^
  -strokewidth 35 -stroke Red ^
  -draw "path '%RPATH%'" ^
  %SHADE_ROPE% ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -flop ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    -region 100x550+200+0 ^
    -channel A -evaluate set 0 +channel ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_r1.png
kn_r1.pngjpg

If we want to repeat the knot, we can first tweak the ends:

set RPATH2=m 130,500 ^
  c -70,0 -70,-200     0,-200 ^
    60,0   60,50     110,50 ^
    60,0   60,-150   0,-150 ^
   -60,0  -60,50    -110,50 ^
   -70,0  -70,-200     0,-200

%IM%convert ^
  -size 400x550 ^
  xc:None ^
  -fill None ^
  -strokewidth 35 -stroke Red ^
  -draw "path '%RPATH2%'" ^
  %SHADE_ROPE% ^
  ( -clone 0 ^
    -fill Blue -colorize 100 ^
    -flop ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    -region 100x550+150+0 ^
    -channel A -evaluate set 0 +channel ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_r2.png
kn_r2.pngjpg

The result can be cropped at y=400 and y=150, and the top will match up with the bottom. Then we rotate, clone and append:

%IM%convert ^
  kn_r2.png ^
  -crop x250+0+150 +repage ^
  -rotate 90 ^
  ( +clone ) +append ^
  kn_r3.png
kn_r3.pngjpg

Bowline

set B1PATH=m 375,700 ^
  c 0,0   -100,-300 -100,-400 ^
    0,-60   50,-150  -25,-150 ^
  -75,0    -25,60    -25,150 ^
    0,100    0,0     -20,200

set B2PATH=m 350,50 ^
  c -10,25    0,50 -100,150 ^
    -25,25 -125,100   0,100 ^
     80,0    80,-75   0,-75 ^
    -25,0   -25,0  -150,0

%IM%convert ^
  -size 500x750 ^
  -strokewidth 25 ^
  ( xc:None ^
    -fill None ^
    -stroke Red ^
    -draw "path '%B1PATH%'" ^
    %SHADE_ROPE% ^
  ) ^
  ( xc:None ^
    -fill None ^
    -stroke Blue ^
    -draw "path '%B2PATH%'" ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    %NEGA% ^
    -fill Red -strokewidth 0 -stroke Red ^
    -draw "rectangle 150,100 350,200" ^
    -draw "rectangle 150,270 350,350" ^
    %NEGA% ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_b1.png

%IM%convert ^
  -size 500x750 ^
  -strokewidth 25 ^
  ( xc:None ^
    -fill None ^
    -stroke Red ^
    -draw "path '%B1PATH%'" ^
    %SHADE_ROPE% ^
  ) ^
  ( xc:None ^
    -fill None ^
    -stroke Blue ^
    -draw "path '%B2PATH%'" ^
    %SHADE_ROPE% ^
  ) ^
  ( -clone 0 ^
    -region 200x100+150+100 ^
    -channel A -evaluate set 0 +channel ^
    -region 200x80+150+270 ^
    -channel A -evaluate set 0 +channel ^
    +region ^
  ) ^
  -background gray90 ^
  -compose Over -layers merge ^
  kn_b1.png
kn_b1.pngjpg

Ray-tracing

By their nature, knots have three dimensions. With care, IM can simulate the third dimension with shading and shadows, but a ray-tracer such as POV-Ray gives a better effect. The POV-Ray files are given below.

This has a white background, to show the shadow.

Removing it,
and including +UA on the command line,
would create a transparent background.

%POV% ^
  -D +A0.01 +W500 +H750 +FN16 ^
  +IreefT.pov +Okn_reefT_pov.png
kn_reefT_pov.pngjpg

Animations are useful for setting and checking the third dimension. This one also shows control points that are nominally on the curves.

for /L %%i in (0,1,35) do (
  set LZ=00000%%i
  set LZ=!LZ:~-6!

  for /F "usebackq" %%F in (`%IM%identify ^
    -format "%%[fx:%%i/36]" xc:`) do set CLK=%%F

  %POV% ^
    -D +A0.01 +W500 +H750 +FN16 +UA +k!CLK!^
    +IreefChk.pov +Okn_reefT_pov_!LZ!.png
)

%IM%convert ^
  -dispose Background kn_reefT_pov_*.png ^
  -layers coalesce -layers optimize ^
  -loop 0 ^
  kn_reef.gif

del kn_reefT_pov_*.png
kn_reef.gif

The background massively increases processing time.

For other uses of POV-Ray, see my page Cylinders: Beyond the simple.

Decorative borders

As shown above, we can append knots together to make a pattern. After appending, we can "+distort polar" to bend the pattern around corners. For example, the script braid.bat makes a pattern from semi-circles.

call ^
  %PICTBAT%braid.bat
kn_rtb.png

Scripts

For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.

braid.bat

set WH2=250
set /A WH=WH2+WH2

set THK2=60
set /A THK=%THK2%+%THK2%

set /A WHmTHK2=%WH%-%THK2%

set /A RAD=%WH2%-%THK2%
set /A WW=%WH%-%THK%


set /A TOP=60+%THK2%
set /A TOP=%WH2%*6/25+%THK2%
set /A BOT=%WH%-%TOP%

set /A X1=%WW%*1/3
set /A X2=%WW%*4/3

set /A D1=%WW%*2/3
set /A D2=%WW%*4/3

set /A SM_RAD=%THK%*4/5
set /A SM_WH=%THK%*8/5
set /A X1L=%X1%-%SM_RAD%
set /A X2L=%X2%-%SM_RAD%
set /A TOP_T=%TOP%-%SM_RAD%
set /A BOT_T=%BOT%-%SM_RAD%

set COL1=Red
set COL2=Lime
set COL3=Blue

set NEGA=-channel alpha -negate +channel

goto BadErase
%IM%convert ^
  -size %WW%x%WH% xc:None ^
  -fill None -stroke %COL1% -strokewidth %THK% ^
  -draw "path 'M0,%THK2% A%RAD%,%RAD% 0 0,1 %RAD%,%WH2% A%RAD%,%RAD% 0 0,0 %WW%,%WHmTHK2%'" ^
  ( +clone -flip ) +append ^
  ( -clone 0 -fill %COL2% -colorize 100 -roll +%D1%+0 ) ^
  ( -clone 0 -fill %COL3% -colorize 100 -roll +%D2%+0 ^
  ) ^
  ( -clone 0 -fill %COL1% -colorize 100 ^
    %NEGA% ^
    -fill Red -stroke None ^
    -draw "translate %X1%,%TOP% circle 0,0 0,%SM_RAD%" ^
    -draw "translate %X2%,%BOT% circle 0,0 0,%SM_RAD%" ^
    %NEGA% ^
  ) ^
  -background None -layers merge ^
  ( +clone ) +append ^
  kn_r.png
:BadErase

%IM%convert ^
  -size %WW%x%WH% xc:None ^
  -fill None -stroke %COL1% -strokewidth %THK% ^
  -draw "path 'M0,%THK2% A%RAD%,%RAD% 0 0,1 %RAD%,%WH2% A%RAD%,%RAD% 0 0,0 %WW%,%WHmTHK2%'" ^
  ( +clone -flip ) +append ^
  ( -clone 0 -fill %COL2% -colorize 100 -roll +%D1%+0 ) ^
  ( -clone 0 -fill %COL3% -colorize 100 -roll +%D2%+0 ^
  ) ^
  ( -clone 0 -fill %COL1% -colorize 100 ^
    -region %SM_WH%x%SM_WH%+%X1L%+%TOP_T% ^
    -channel A -evaluate set 0 +channel ^
    -region %SM_WH%x%SM_WH%+%X2L%+%BOT_T% ^
    -channel A -evaluate set 0 +channel ^
  ) ^
  -background None -layers merge ^
  ( +clone ) +append ^
  kn_r.png

set INRAD=300
set INRAD=250
set INRAD=%WH2%
set /A OUTRAD=%INRAD%+%WH%

%IM%convert ^
  kn_r.png ^
  ( +clone ) +append ^
  -flip -flop ^
  -virtual-pixel None +distort polar %OUTRAD%,%INRAD% ^
  +repage ^
  -crop 2x2@ +repage ^
  kn_r1.png

%IM%convert ^
  -gravity North ^
  kn_r1-0.png ^
  kn_r.png ^
  kn_r1-1.png ^
  -background None ^
  +append ^
  -write kn_rtop.png ^
  -flip -flop ^
  kn_rbot.png

%IM%convert ^
  kn_rtop.png ^
  kn_rbot.png ^
  -append ^
  -resize 30%% ^
  kn_rtb.png

POV-Ray files

reefT.pov

#declare RopeRad=20;

#include "knotPov.inc"

union {
  object { WhiteFloor }
  object { reef_knot
    rotate y*360*clock
  }
}

reefChk.pov

#include "knotPov.inc"

union {
  object { CheckerFloor }
  object { reef_knot_chk
    rotate y*360*clock
  }
}

knotPov.inc

#version 3.7;
global_settings { assumed_gamma 1.0 } 

#include "colors.inc"
#include "textures.inc"
#include "shapes.inc"
#include "metals.inc"
#include "glass.inc"
#include "woods.inc"         

camera {
   location <0, 0, -1000>
   // angle 45 // direction <0, 0,  1.7>
   right x*image_width/image_height
   look_at <0,0,0>
}

// Uncomment the area lights only if you've got lots of time.
#declare Dist=80.0;

light_source {< -600, +300, -900> color White*2
//     fade_distance Dist fade_power 2
   area_light <-40, 0, -40>, <40, 0, 40>, 3, 3
   adaptive 1
   jitter
}

//light_source {< -500, 250, -500> color White
//     fade_distance Dist fade_power 2
//   area_light <-40, 0, -40>, <40, 0, 40>, 3, 3
//   adaptive 1
//   jitter
//}

light_source {< 500, -100, -40> color Gray30
     fade_distance Dist fade_power 2
     area_light <-20, 0, -20>, <20, 0, 20>, 3, 3
     adaptive 1
     jitter
}
light_source {< 0, -1000,  0> color Gray30
     fade_distance Dist fade_power 2
//   area_light <-30, 0, -30>, <30, 0, 30>, 3, 3
//   adaptive 1
//   jitter
}

//sky_sphere {
//    pigment {
//        gradient y
//        color_map {
//            [0, 1  color Gray50 color Gray80]
//        }
//    }
//}

#declare M_Wood18B =
colour_map {
    [0.00 0.25   color rgbf < 0.50, 0.26, 0.12, 0.10>
                 color rgbf < 0.54, 0.29, 0.13, 0.20>]
    [0.25 0.40   color rgbf < 0.54, 0.29, 0.13, 0.20>
                 color rgbf < 0.55, 0.28, 0.10, 0.70>]
    [0.40 0.50   color rgbf < 0.55, 0.28, 0.10, 0.70>
                 color rgbf < 0.50, 0.23, 0.15, 0.95>]
    [0.50 0.70   color rgbf < 0.50, 0.23, 0.15, 0.95>
                 color rgbf < 0.56, 0.29, 0.17, 0.70>]
    [0.70 0.98   color rgbf < 0.56, 0.29, 0.17, 0.70>
                 color rgbf < 0.54, 0.29, 0.13, 0.20>]
    [0.98 1.00   color rgbf < 0.54, 0.29, 0.13, 0.20>
                 color rgbf < 0.50, 0.26, 0.12, 0.10>]
}


#declare Floor_Texture =
    texture { pigment { P_WoodGrain18A color_map { M_Wood18A }}}
    texture { pigment { P_WoodGrain12A color_map { M_Wood18B }}}
    texture {
        pigment { P_WoodGrain12B color_map { M_Wood18B }}
        finish { reflection 0.25 }
    }

#declare Floor =
plane { y,0
    texture { Floor_Texture
        scale 0.5
        rotate y*90
        rotate <10, 0, 15>
        translate z*4
    }
}

#declare WhiteFloor =
plane { z,0
  pigment { color White }
  translate z*200
}

#declare CheckerFloor =
plane { z,0
  pigment { checker color White, color Gray scale 100 }
  translate z*1000
}






#ifndef (RopeRad)
#declare RopeRad=5;
#end

#declare reef_a =
sphere_sweep {
  b_spline
  15,
  <375,-800,0>, RopeRad
  <375,-700,0>, RopeRad // on curve
  <325,-550,0>, RopeRad
  <265,-400,0>, RopeRad
  <265,-300,0>, RopeRad // on curve
  <265,-225,0>, RopeRad
  <310,-125,75>, RopeRad
  <250,-125,75>, RopeRad // on curve
  <190,-125,75>, RopeRad
  <225,-225,0>, RopeRad
  <225,-300,0>, RopeRad // on curve
  <225,-350,0>, RopeRad
  <225,-450,0>, RopeRad
  <205,-500,0>, RopeRad // on curve
  <195,-520,0>, RopeRad
  pigment { color <1, 0.25, 0.25> }
}

#declare reef_test_a =
union {
  sphere { <375,-700,0> 20 }
  sphere { <265,-300,0> 20 }
  sphere { <250,-125,75> 20 }
  sphere { <225,-300,0> 20 }
  sphere { <205,-500,0> 20 }
  pigment { color Red }
}

#declare reef_b =
sphere_sweep {
  b_spline
  18,
  <280,100,-50>, RopeRad
  <280,0,-50>, RopeRad // on curve
  <280,-25,-50>, RopeRad
  <280,-75,-50>, RopeRad
  <280,-125,-50>, RopeRad // on curve
  <270,-150,-50>, RopeRad
  <250,-175,100>, RopeRad
  <230,-200,100>, RopeRad // on curve
  <215,-250,125>, RopeRad
  <125,-300,-50>, RopeRad
  <250,-300,-50>, RopeRad // on curve
  <330,-300,-50>, RopeRad
  <330,-225,50>,  RopeRad
  <250,-225,50>,  RopeRad // on curve
  <225,-225,50>, RopeRad
  <225,-225,50>, RopeRad
  <100,-225,50>, RopeRad // on curve
  <150,-225,50>, RopeRad
  pigment { color rgb <0.25, 0.25, 1> }
}

#declare reef_test_b =
union {
  sphere { <280,0,-50> 20 }
  sphere { <280,-125,-50> 20 }
  sphere { <230,-200,100> 20 }
  sphere { <250,-300,-50> 20 }
  sphere { <250,-225,50> 20 }
  sphere { <100,-225,50> 20 }
  pigment { color Blue }
}

#declare reef_knot =
union {
  object { reef_a }
  object { reef_b }
  translate <-250,225,0>
}

#declare reef_knot_chk =
union {
  object { reef_a }
  object { reef_test_a }
  object { reef_b }
  object { reef_test_b }
  translate <-250,225,0>
}

All images on this page were created by the commands shown, using:

%IM%identify -version
Version: ImageMagick 6.9.5-3 Q16 x86 2016-07-22 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 180040629
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo flif freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib

... and POV-Ray 3.7, with "Render, On completion, Exit POV-Ray for Windows" ticked.

"POV-Ray" is a trademark of Persistence of Vision Raytracer Pty Ltd.

To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG to JPG.

Source file for this web page is knots.h1. To re-create this web page, run "procH1 knots".


This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.

Anyone is permitted to re-publish this page, but only for non-commercial use.

Anyone is permitted to link to this page, including for commercial use.


Page version v1.0 23-October-2014.

Page created 29-Dec-2016 12:16:09.

Copyright © 2016 Alan Gibson.