# Creating a tube with custom caps

I need a tube with only one end capped. I can do this relatively easily with:

monoTube[{pt1_, pt2_}, r_] := {
EdgeForm[None],
Cylinder[{pt1, pt2}, r],
Sphere[pt2, r]}


I would also like the entire object to have the length EuclideanDistance[pt1, pt2], which means I really need a pt3 lying on the object's path that is closer to pt1 than pt2 is by the distance r. While I know this is a simple vector operation, I do not know how to do it properly.

monoTube [{pt1_, pt2_}, r_] := {EdgeForm[None], Cylinder[{pt1, pt2}, r], Sphere[pt2, r]}
monoTube1[{pt1_, pt2_}, r_] :=
With[{s = (Norm[pt2 - pt1] - r) Normalize[pt2 - pt1] +  pt1},
{EdgeForm[None], Cylinder[{pt1, s}, r], Sphere[s, r]}]

Graphics3D[{monoTube [{{0, 0, -1}, {0, 0, 1}}, 1],
monoTube1[{{2, 0, -1}, {2, 0, 1}}, 1]}, Axes -> True] • That's what I'm looking for; clearly, I need to crack open a linear algebra book. – bobthechemist Aug 21 '15 at 23:29

Use two Tube[]s:

monoTube[{p1_?VectorQ, p2_?VectorQ}, r_?NumericQ] :=
Module[{h = 1 + \$MachineEpsilon^(3/4), pm, t},
t = r/EuclideanDistance[p1, p2];
pm = t p1 + (1 - t) p2;
{{CapForm[None], Tube[{p1, pm}, r]},
Tube[{t h p1 + (1 - t h) p2, pm}, {0, r}]}]

Graphics3D[monoTube[{{0, 0, 0}, {-1, 1, 1}}, 0.1]] • Neat idea. I did not know one could obtain pm the way you have. Do you know why h is needed? – bobthechemist Aug 21 '15 at 23:27
• @bob, prolly should've linked to this to begin with. :) – J. M.'s technical difficulties Aug 22 '15 at 0:18