3

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.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
bobthechemist
  • 19,693
  • 4
  • 52
  • 138

2 Answers2

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

Mathematica graphics

Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
3

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

tube with a single cap

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574