2

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[0] == y[0] == z[0] == 10}, {x, y, z}, {t, 0, 100}, 
MaxSteps -> ∞];

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

Export["Chan-Lee.stl", DiscretizeGraphics[curve]]
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
arax
  • 1,831
  • 12
  • 16

2 Answers2

6

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[[2]], t[[2]] - t[[1]], 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[].)

For your specific example:

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[0] == y[0] == z[0] == 10}, {x, y, z}, {t, 0, 100}]]

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

TubeMesh[path, CirclePoints[0.5, 20]]

a meshed tube

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.

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

Example

RegionQ @ Cylinder[]

True

RegionPlot3D @ Cylinder[]

Output

cylinder

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

example 2

e.doroskevic
  • 5,959
  • 1
  • 13
  • 32
  • But that way I could only get disconnected cylinders – arax Jun 16 '16 at 09: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 09:29
  • 1
    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 09: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 09:38