Parametrize a circle as a tube?

5

1

I have this code:

Show[ContourPlot3D[{y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8},
  Mesh -> {Range[-4, 6], Range[-9, 1], Range[-2, 8]},
  Axes -> True, AxesLabel -> {x, y, z},
  Ticks -> {Range[-4, 6, 1], Range[-9, 1, 1], Range[-2, 8, 1]}
  ],
 ParametricPlot3D[{3 Cos[φ] + 1, 0, 3 Sin[φ] + 3}, {φ, 
   0, 2 π},
  PlotStyle -> {Thickness[.02], Red}],
 Graphics3D[{Sphere[{1, -4, 3}, 5]}],
 ViewPoint -> {5, 5, 5}]

Which produces this image.

my plot

I have a couple of questions.

  1. The intersection of the sphere with center at $(1,-4,3)$ and radius $5$ with the $xz$ plane is a circle with equation $(x-1)^2+(z-3)^2=9$. I parametrized the circle as $x=3\cos\phi+1$, $y=0$, and $z=3\sin\phi+3$, then used ParametricPlot3D to add it to my picture. Anybody have a simple way of plotting the circle without my parametrization?

  2. How can I add my circle so it looks like a tube?

David

Posted 2015-05-22T21:23:02.177

Reputation: 14 143

A related question. – J. M.'s ennui – 2015-05-23T02:31:38.870

Answers

5

cf[x_, y_, z_] := Plus @@ (({x, y, z} - {1, -4, 3})^2);
opts = {ViewPoint -> {5, 5, 5}, Axes -> True, AxesLabel -> {x, y, z}, 
   Ticks -> {Range[-4, 6, 1], Range[-9, 1, 1], Range[-2, 8, 1]}, ImageSize -> 300};

BoundaryStyle

Use BoundaryStyle->{{1,2}->Directive[Red, Tube@@#&]} (or BoundaryStyle -> {{1, 2} -> Directive[Red, # /. Line -> Tube &]}) to make the boundary between the sphere and the plane rendered as a red tube.

cp = ContourPlot3D[{cf[x, y, z]== 25,  y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle -> {Directive[Blue, Opacity[0.5]], Directive[Pink, Opacity[0.5]]}, 
  BoundaryStyle -> {1 -> None, 2 -> None, {1, 2} -> Directive[Red, Tube @@ # &]}, 
  Mesh -> None, Evaluate@opts]

Mathematica graphics

cp2 = ContourPlot3D[{y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle ->None, Mesh -> {Range[-4, 6], Range[-9, 1], Range[-2, 8]}];

Show[cp, cp2]

Mathematica graphics

MeshFunctions

cp3 = ContourPlot3D[cf[x, y, z] == 25, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle -> Opacity[.5, Blue], 
  MeshFunctions -> {Function[{x, y, z}, y]}, Mesh -> {{0}}, 
  MeshStyle -> Directive[Red, Tube @@ # &], Evaluate@opts]

or MeshStyle -> Directive[Red, # /. Line -> Tube &], gives

Mathematica graphics

cp4 = ContourPlot3D[{y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle -> Opacity[.5, Red], 
  Mesh -> {Range[-4, 6], Range[-9, 1], Range[-2, 8]}];

Show[cp3, cp4]

Mathematica graphics

Notes: Two undocumented tricks are used in the above methods. The BoundaryStyle trick first appeared on this site in this answer by Daniel Lichtblau linked by @Guesswhoitis in the comments. It also features a second undocumented trick: using functions as style directives. On this second trick see this page for relevant links.

Post-processing

Alternatively, you can post-process the ContourPlot3D output to change Line to Tube.

ContourPlot3D[{cf[x, y, z] == 25, y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle -> {Directive[Blue, Opacity[0.5]], Directive[Pink, Opacity[0.5]]}, 
  Mesh -> None, BoundaryStyle -> {1 -> None, 2 -> None, {1, 2} -> Red}, 
  Evaluate@opts] /. Line -> Tube

ContourPlot3D[cf[x, y, z] == 25, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
  ContourStyle -> Opacity[.5, Blue], MeshFunctions -> {Function[{x, y, z}, y]}, 
  Mesh -> {{0}}, MeshStyle -> Red, Evaluate@opts] /. Line -> Tube

to get the same pictures as above.

Update:

How would you use this code to make the tube larger?

This is easiest with the post-processing approach: simply change /. Line->Tube to /. Line -> (Tube[#, .3]&).

With the first and second approaches, I expected that Directive[Red, Tube[#, .3]& @@ # &] would work, but it doesn't. However, Directive[Red, Module[{tt = Tube[#, .3] &}, tt @@ # &]] works. It seems that, somehow, with another layer of function evaluation it gets too deep for Directive to process the primitive properly.

Alternatively, you can define a tube primitive function tubeF outside, and use it inside Directive:

ClearAll[tubeF]
tubeF[col_: Red, rad_: .1] := Module[{tf = Tube[#, rad] &}, Directive[col, tf @@ # &]];

Row[ContourPlot3D[{cf[x, y, z] == 25, y == 0}, {x, -4, 6}, {y, -9, 1}, {z, -2, 8}, 
    ContourStyle -> {Directive[Blue, Opacity[0.5]], Directive[Pink, Opacity[0.5]]},
    BoundaryStyle -> {1->None, 2->None, {1, 2}->#}, Mesh -> None, Evaluate@opts] & /@ 
 {tubeF[], tubeF[Orange, .3], tubeF[Purple, .5]}]

enter image description here

Row[ContourPlot3D[cf[x, y, z] == 25, {x, -4, 6}, {y, -9, 1}, {z, -2, 8},
    ContourStyle -> Opacity[.5, Blue], MeshFunctions -> {Function[{x, y, z}, y]}, 
    Mesh -> {{0}}, MeshStyle -> #, Evaluate@opts] & /@
  {tubeF[], tubeF[Orange, .3], tubeF[Purple, .5]}]

enter image description here

kglr

Posted 2015-05-22T21:23:02.177

Reputation: 302 076

First time I've seen something like: BoundaryStyle -> {1 -> None, 2 -> None, {1, 2} -> Directive[Red, Tube @@ # &]}. I'm assuming that 1 means the first contour, 2 means the second contour, and {1,2} means the intersection of the first and second contours. Where is this explained in the documentation? I went to BoundaryStyle, but did not find an example of this. – David – 2015-05-23T02:43:39.077

A second question regarding Tube @@ # &. Now, I looked up @@ for the fiftieth time and it replaces the head of expression by Tube. What is the head of the expression before it is replaced with Tube? Is there some sort of minimal example that would explain this? – David – 2015-05-23T02:53:23.087

@David. thank you the accept. As you discovered it is an undocumented trick. I updated with links to relevant answers that used the two undocumented methods. Re Tube@@#&, in this case, it replaces Line with Tube. See also the examples here.

– kglr – 2015-05-23T08:29:51.020

How would you use this code to make the tube larger? I have read an example in the documentation: Graphics3D[Tube[{{0, 0, 0}, {1, 1, 1}}, .1]]. But if I use Directive[Red, Tube @@ # &], how do I add the size increase? – David – 2015-05-24T00:45:39.707

@David, Defining tube = Tube[#, .3] & before ContourPlot3D is invoked and using Directive[Red, tube @@ # &] or Directive[Red, # /. Line -> tube &] works. (I thought Directive[Red, Tube[#, .3]& @@ # &] would work, but it doesn't.) – kglr – 2015-05-24T10:57:02.090

... you can also use Module to define tube locally: Module[{tube = Tube[#, .3] &}, ContourPlot3D[{cf[x, y, z] == 25, y == 0}, ...] – kglr – 2015-05-24T10:58:57.563

Alternatively, you can use post-processing to change Tube radius: ContourPlot3D[....] /. Tube->(Tube[#,.3]&) – kglr – 2015-05-24T11:04:08.283

4

Just using a slightly different approach and using the derived circle and interpreting question as generating a torus from the circle of intersection between sphere and x-z plane:

s = ParametricPlot3D[
   5 {Sin[u] Cos[v], Sin[u] Sin[v], Cos[u]} + {1, -4, 3}, {u, 0, 
    Pi}, {v, 0, 2 Pi}, 
   RegionFunction -> Function[{x, y, z, u, v}, y <= 0], Mesh -> None];
t[r_, p_, b_] := 
  ParametricPlot3D[
   p + b {Cos[u], 0, Sin[u]} + 
    r Cos[v] {Cos[u], 0, Sin[u]} + {0, r Sin[v], 0}, {u, 0, 
    2 Pi}, {v, 0, 2 Pi}, Mesh -> False, PlotStyle -> Red];
Manipulate[
 Show[s, t[r, {1, 0, 3}, 3], Boxed -> False, Axes -> False, 
  Background -> Black, PlotRange -> All], {r, Range[0.05, 0.5, 0.05]}]

enter image description here

ubpdqn

Posted 2015-05-22T21:23:02.177

Reputation: 53 491

Thanks. Nice animation. I used a piece of your code to ask another question. See: http://mathematica.stackexchange.com/questions/84163/mathematicas-viewpoint-versus-matlabs-view-command.

– David – 2015-05-23T03:17:43.063