2

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).

enter image description here

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]]

enter image description here

Sumit
  • 15,912
  • 2
  • 31
  • 73

2 Answers2

3

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]

enter image description here

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.

Jason B.
  • 68,381
  • 3
  • 139
  • 286
1

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]]

enter image description here

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]}]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896