# How to add color to a knot

Is there a way to use a colorscheme to a KnotData image?

One way is probably convert it to a parametric form and then use Colorfunction with ParametricPlot3D. The method is described in J.M.'s answer to How to create a new “person curve”?. Although it seems to have some problems with Trefoil.

Is there any simpler way to do this?

In summary, I want to use (say) Colorfunction->Hue with the output of KnotData["Trefoil"].

Using J.M.'s method

FourierCurve[x_, m_, t_, tol_: 0.01] := Module[{rat = Rationalize[#, tol] &, fc},
fc = Take[Chop[Fourier[x, FourierParameters -> {-1, 1}]],
Min[m, Ceiling[Length[x]/2]]];
2 rat[Abs[fc]].Cos[Pi (2 Range[0, Length[fc] - 1] t - rat[Arg[fc]/Pi])]]

{f[t_], g[t_], h[t_]} = FourierCurve[#, 20, t] & /@
KnotData["FigureEight", "SpaceCurve"]["ValuesOnGrid"];

ParametricPlot3D[{f[t], g[t], h[t]}, {t, 0, 1}, Axes -> None,
Boxed -> False, Method -> {"TubePoints" -> 20},
ColorFunction -> "Rainbow", ViewPoint -> Top] /.
Line[pts_, rest___] :> Tube[pts, 1/8, rest]


It works nicely with "FigureEight", "SolomonSeal", "Stevedore". (There is a small hole in the red region which can be fixed by adjusting the PlotRange). When I try with "Trefoil", it returns

Fourier::fftl: Argument Sin[ValuesOnGrid]+2 Sin[2 ValuesOnGrid] is not a non-empty list or rectangular array of numeric quantities. >>

Using Tube works with the data, but coloring is not very flexible in that case.

Graphics3D[Tube[(KnotData["Trefoil", "SpaceCurve"][#])
& /@ Range[0, 2.1 Pi, Pi/50], 0.1]] • "it seems" - can you include a picture and corresponding code to show why you think it's unsatisfactory? Apr 13, 2016 at 12:36
• Thanks @J.M. for the comment. I often forget to put tea bag in my tea :) Apr 13, 2016 at 13:22
• The reason it doesn't work on "Trefoil" is that actual trigonometric expressions are used for "SpaceCurve" instead of interpolating functions as with the other knots. Apr 13, 2016 at 13:53
• a way to color Tube is to use VertexColors: e.g., Graphics3D[ Tube[KnotData["Trefoil", "SpaceCurve"] /@ #, 0.1, VertexColors -> Hue /@ #]] &@Range[0, 2 Pi, Pi/50]
– kglr
Apr 13, 2016 at 19:44

In this case, the KnotData evaluates directly to a parametric curve,

KnotData["Trefoil", "SpaceCurve"]
(* {Sin[#1] + 2 Sin[2 #1], Cos[#1] - 2 Cos[2 #1], -Sin[3 #1]} & *)


so that no sampling is necessary.

ParametricPlot3D[
KnotData["Trefoil", "SpaceCurve"][t], {t, 0, 2 \[Pi]},
PlotRange -> All, Axes -> None, Boxed -> False, ViewPoint -> Top,
ColorFunction -> "Rainbow"] /.
Line[pts_, rest__] :> Tube[pts, 1/8, rest] Of course, this was true for "FigureEight" as well. But the difference is that "FigureEight" like many of the KnotData objects, is only stored as an interpolating function. Since "Trefoil" is not an interpolating function, it does not have the "ValuesOnGrid" property.

• …and in fact the reason I used FourierCurve[] on all the other knots was precisely because I wanted simple(?) trigonometric expressions for them like with "Trefoil". Apr 13, 2016 at 14:26

We can use Tube as graphics directive in ParametricPlot3D:

ParametricPlot3D[
KnotData["Trefoil", "SpaceCurve"][t], {t, 0, 2 π},
PlotRange -> All, Axes -> False, Boxed -> False,
ColorFunction -> "Rainbow",
PlotStyle -> Tube[.2]] ParametricPlot3D[{KnotData["Trefoil", "SpaceCurve"][t],
KnotData["SolomonSeal", "SpaceCurve"][t],
KnotData["FigureEight", "SpaceCurve"][t]},
{t, 0, 2 π},
PlotRange -> All, Axes -> False, Boxed -> False,
ColorFunction -> (ColorData["Rainbow"] @ #4 &),
PlotStyle -> {Tube[.25], Tube[.15], Tube[.1]}] 