# How to apply DiscretizeGraphics to a tube? [duplicate]

I want to export the numerical solution of the Chan-Lee oscillator as an STL file so that I could print it out. But when I expanded the curve into a tube, DiscretizeGraphics recognizes it as an empty region. How could I somehow fill the tube and make it a discretizable solid?

My code:

α = 5; β = -10; δ = -.38;
s = NDSolve[{α x[t] - y[t] z[t] ==
D[x[t], t], β y[t] + x[t] z[t] ==
D[y[t], t], δ z[t] + x[t] y[t]/3 == D[z[t], t],
x == y == z == 10}, {x, y, z}, {t, 0, 100},
MaxSteps -> ∞];

ps = Table[{x[t] - y[t]/Sqrt, y[t], z[t]} /. First[s], {t, 0,
100, .1}];
curve = Graphics3D[Tube[BSplineCurve[ps], .5]];

Export["Chan-Lee.stl", DiscretizeGraphics[curve]]


## marked as duplicate by J. M. is away♦Jul 2 '16 at 13:01

• Use Cylinder instead – e.doroskevic Jun 16 '16 at 9:10
• Possible solution (work-around): (9258), (11452) – Mr.Wizard Jun 16 '16 at 10:06

A possible workaround (brought up by the Wizard in the comments) involves the use of some of the functions from this previous answer. In particular, you will need orthogonalDirections[], extend[], and crossSection[] from that answer, along with these two additional functions for generating a suitable MeshRegion[] object:

MakeTriangleMesh[vl_List, opts___] := Module[{dims = Most[Dimensions[vl]]},
MeshRegion[Apply[Join, vl], Triangle /@ Flatten[
Apply[{Append[Reverse[#1], Last[#2]], Prepend[#2, First[#1]]} &,
Partition[Partition[Range[Times @@ dims], Last[dims]],
{2, 2}, {1, 1}], {2}], 2], opts]] /; ArrayDepth[vl] == 3

TubeMesh[path_?MatrixQ, cs : (_Integer | _?MatrixQ), opts___] :=
MakeTriangleMesh[FoldList[Function[{p, t}, With[{o = orthogonalDirections[t]},
extend[#, t[], t[] - t[], o] & /@ p]],
crossSection[path, 1., cs],
Partition[path, 3, 1, {1, 2}, {}]], opts]


(The observant will notice that these are only slight modifications of the previous routines MakePolygons[] and TubePolygons[].)

With[{α = 5, β = -10, δ = -.38},
{xx, yy, zz} = NDSolveValue[{α x[t] - y[t] z[t] == x'[t],
β y[t] + x[t] z[t] == y'[t],
δ z[t] + x[t] y[t]/3 == z'[t],
x == y == z == 10}, {x, y, z}, {t, 0, 100}]]

path = Transpose[{{1/Sqrt, -1/Sqrt, 0}, {0, 1, 0}, {0, 0, 1}} .
Through[{xx, yy, zz}["ValuesOnGrid"]]];

TubeMesh[path, CirclePoints[0.5, 20]] Note that the result is an open tube (equivalent to using CapForm[None] with Tube[]); the equivalent of using CapForm["Round"] is slightly trickier to do.

• I might try to come up with the "rounded ends" version later, but not now. – J. M. is away Jun 16 '16 at 10:57

Example

RegionQ @ Cylinder[]


True

RegionPlot3D @ Cylinder[]


Output RegionQ @ Tube[{{0, 0, 0}, {1, 1, 1}}]


False

RegionPlot3D @ Tube[{{0, 0, 0}, {1, 1, 1}}]


Output

{Tube[{{0,0,0},{1,1,1}}]} is not a valid region to plot.

EDIT

In order to achieve region look-a-like Tube, see implementation below.

Example

region = Fold[RegionUnion,
Ball[#1, #3], {Cylinder[{#1, #2}, #3], Ball[#2, #3]}] & [{0, 0,
0}, {10, 0, 0}, 1]


Output

RegionQ @ region


True

RegionPlot3D @ region • But that way I could only get disconnected cylinders – arax Jun 16 '16 at 9:24
• You can always use RegionUnion to build-up the region in interest. I would also recommend to look at Fold you might find it useful. – e.doroskevic Jun 16 '16 at 9:29
• Sorry I wasn't being clear. I meant to say that the join between two adjacent cylinders won't be rounded like Tube, and it's not that trivial to come up with a proper joining function suitable for display & printing. – arax Jun 16 '16 at 9:34
• No worries! Yes, I do appreciate the fact that you won't get the rounded top and the bottom when using a Cylinder. You could manipulate it further and construct a region using Ball and Cylinder this would allow you to get rounded top and bottom. – e.doroskevic Jun 16 '16 at 9:38