7

Continuing from here, I would like to Texture lines with thickness. I tried using the normal and the binormal from FrenetSerretSystem as in the accepted answer, but the following approach seemed more stuccessful.

enter image description here

g = With[{b = .1}, 
Graphics[{Red, 
 Table[Disk[{c, #[[1]]}, #[[2]]/35] & /@ 
   Thread@{Table[Sin@x, {x, -1, 1, b}], 
     Table[PDF[NormalDistribution[0, .25], x], {x, -1, 1, 
       b}]}, {c, -1, 1, b}]}, Background -> White, 
PlotRangePadding -> 0]];
R = 1; f[x_] := Sin[x]
w[x_] := Normalize[{1, f'[x], 0}]
u[x_] := Normalize[Cross[w[x], {0, 0, 1}]]
v[x_] := Cross[w[x], u[x]]
ParametricPlot3D[{x, f[x], 0} + R Cos[t] u[x] (1 - x/(3 Pi)) + 
  R Sin[t] v[x] (1 - x/(3 Pi)), {x, 0, 3 Pi}, {t, 0, 2 Pi}, 
 PlotPoints -> 80, Mesh -> None, Boxed -> False, Axes -> False, 
 PlotStyle -> Texture[g], TextureCoordinateScaling -> True, 
 TextureCoordinateFunction -> Function[{x, y, z, u, t}, {u, t}], 
 ViewPoint -> {0.2, 4, 2}]

However, I would ideally like to be able to use graphics primitives. I tried with the simpler approach in Graphics3D but didn't get anywhere

Graphics3D[{Texture[g], CapForm[None], 
Tube[BSplineCurve[{{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}}], {.2, .1, .1, .01}]}, 
Boxed -> False]

enter image description here

I was wondering whether it was possible to feed it into BoundaryMeshRegion[] (as in @ J. M.'s ennui 's answer to the linked question) to then deal with it as a region? I tried DiscretizeGraphics but MMA told me Option VertexNormals is not set in Options[Tube].

I tried to interpolate the points as per here

pts = {{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}};
f = Interpolation[Transpose[{N@Range[0, 1, 1/(Length[pts] - 1)], pts}]];

but am struggling to find normal and binormal, even after looking here

pts = {{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}};
r = Interpolation[Transpose[{N@Range[0, 1, 1/(Length[pts] - 1)], pts}]];
t[t_] = Simplify[r'[t]/Norm[r'[t]], t \[Element] Reals];
n[t_] = Simplify[uT'[t]/Norm[uT'[t]], t \[Element] Reals];
bn[t_] = Simplify[Cross[r'[t], r''[t]]/Norm[Cross[r'[t], r''[t]]], t \[Element] Reals];

Having said all of the above, it would ultimately be nice to be able to vary the thickness as easily as one does in Tube[] though.

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
martin
  • 8,678
  • 4
  • 23
  • 70

2 Answers2

7

We can use new-in-12.1 directives (HalfToneShading,ToonShading, GoochShading, StipleShading etc) to texturize the surface of a Tube primitive:

Graphics3D[{HalftoneShading[Blue], CapForm[None], 
 Tube[BSplineCurve[{{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}}], {.2, .1, .1, .01}]},
 Boxed -> False, Lighting -> "Neutral"] 

enter image description here

We can use the function surfaceAppearance from this answer to control some shading parameters:

Graphics3D[{surfaceAppearance["Tiling" -> {5, 5}, 
   "FeatureColor" -> Blue, "UseScreenSpace" -> 1], CapForm[None], 
 Tube[BSplineCurve[{{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}}], {.2, .1, .1, .01}]},
 Boxed -> False, Lighting -> "Neutral"] 

enter image description here

Use surfaceAppearance["Tiling"->{3,3},"FeatureColor"->Blue,"UseScreenSpace"->1, "StepCount"->5,"LuminanceModifier"->0.1] to get

enter image description here

Update: It turns out, as of version 12.1, we can use SurfaceAppearance["TextureShading", Texture[img]] to use img to texture Tube primitives:

lena = ExampleData[{"TestImage", "Lena"}];

Graphics3D[{SurfaceAppearance["TextureShading", Texture[lena]], CapForm[None], Tube[BSplineCurve[{{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}}], {.5, .1, .1, .01}]}, Boxed -> False]

enter image description here

kglr
  • 394,356
  • 18
  • 477
  • 896
2

Using @J. M.'s ennui 's plotTube function from here

pts = {{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {3, 4, 1}};
f = Interpolation[Transpose[{N@Range[0, 1, 1/(Length[pts] - 1)], pts}]];
circ[u_, t_, v_] := v {Cos[u], Sin[u]} (1 - t);
plotTube[f[t], circ[u, t, .2], {t, 0, 1}, {u, 0, 2 \[Pi]}, PlotPoints -> {75, 45}]

enter image description here

Adding texture is now just a formality.

martin
  • 8,678
  • 4
  • 23
  • 70