Message Boards Message Boards

Seeking 3D rendering of 2D Lissajous curve

Posted 3 years ago

Hello everyone,

First, some background. I was introduced to Mathematica some 30 years ago back in graduate school, and have been in awe of it ever since. However, I've never actually used it.

Recently, I've been working with my daughter on a graphic design project. What we want is to create a logo using a Lissajous curve, and it occurred to me that Mathematica would probably be the perfect tool to help here. But the challenge here is primarily graphical, not mathematical. Even the online tool allows a simple drawing:

https://demonstrations.wolfram.com/LissajousFigures/

But what I want is a much richer 3-D effect. But I'm not talking about 3-D Lissajous curves. Let me explain. As you change the phase of a 2-D Lissajous, it appears to rotate in space around a vertical central axis. The result is that a portion of the curve appears to be in the foreground and a portion in the background. But when all the lines are drawn with equal weight, that's very hard to visualize.

Now, the online tool has a "length" parameter that appears to turn the line into sort of a "flat ribbon", which is very cool, and is also an effect I might like to incorporate:

lissajous concept

But this is not providing any front/back depth.

What I would like to have is one or more parameters that allow the "front" portion of the curve to be fatter and darker, while the "rear" portion of the curve is dimmer and follows the rules of perspective to become lighter "weight".

Furthermore, if I can be a little greedy, I'd like to be able to render the curve with a lighting/shadow effect. The best example I could find online is this, understanding that it's not a Lissajous:

shaded (non-lissajous) curve

And finally, if I can then create a GIF by animating the phase over time, that would be truly fantastic.

But the shading and GIF requests are secondary to the front/back depth effect portion of my request.

I apologize in advance that I'm a complete novice to Mathematica, so your help is greatly appreciated!

Thanks very much!

Dave

POSTED BY: Dave K
9 Replies
Posted 3 years ago

As to why the compiler didn't complain when I tried to execute the ParametricPlot3D code with the Lissajous3D definition missing, I have no idea :-)

Thought it might be helpful to comment on this. There isn't really a compiler in the common sense, and there is nothing directly analogous to static type checking. ParametricPlot3D was given two parameters and their ranges. It was given a "function" (an expression that looked like what you might think of as a function) that was being applied to those two parameters. That function (Lissajous3D), however, didn't have any rewrite/evaluation rules associated with it (because you hadn't evaluated the SetDelayed expression that "defined" the Lissajous3D "function"). So, ParametricPlot3D was just left with a bunch of stuff that it didn't know how to interpret as a plot, and so the resulting output just looked empty.

POSTED BY: Eric Rimbey
Posted 3 years ago

Oh, I forgot to comment on animation. I wasn't confident enough in what you wanted to try animating it, but creating an animation is fairly easy. You just create a list of the individual "frames" and apply ListAnimate to it. Or you can parameterize how each frame is created, and use Animate. Maybe just rotating the plot (or even just rotating the ViewPoint) will get you what you want. Or maybe it's the Lissajous parameters themselves that you want to vary. Creating the frames you want will be the main challenge--animating them is a cinch.

POSTED BY: Eric Rimbey
Posted 3 years ago

Here's an approach.

  • Make the Lissajous curve wrap around a cylinder (I'm assuming this will give the 3D shape you want, but if you're wanting something else, like an over-under knot type pattern, then this won't work--but something else will :) )
  • Use ParametricPlot3D
  • Use two parameters in the plot to create a ribbon
  • Use lighting or other styling to enhance the 3D effect.

Here's an example output: enter image description here

Here is the code for the ParametricPlot3D:

ParametricPlot3D[
 Lissajous3D[1, 1, 3, Pi/3][t, s],
 {s, 0, .1}, {t, 0, 2 Pi},
 ViewPoint -> Front,
 ViewProjection -> "Orthographic",
 ColorFunction -> (White &),
 MeshStyle -> None,
 PlotPoints -> {20, 60},
 Lighting -> {{"Point", Blue, {0, -5, 0}}, {"Point", 
    Green, {3, -5, 0}}},
 Axes -> False]

You can see the options I've used, and hopefully that will get you started. The documentation for each option should help you figure out how to get your preferred appearance.

Here's the definition for the Lissajous3D function:

Lissajous3D[cx_, cy_, w_, d_][t_, s_] := {cx Sin[t w + d], cx Cos[t w + d], cy Sin[t] + Rescale[cx Cos[t w + d], {-1, 1}, {s, .5 s}]}

The x and z coordinates plot the 2d lissajous, and the y coordinate the front/back distance as if it was wrapping around a cylinder. This may not be the exact 3d shape you want, but hopefully it'll get you started. You can switch the coordinates to change the orientation.

POSTED BY: Eric Rimbey
Posted 3 years ago

Thanks for this amazing reply!

At the risk of fearing that I'm wasting your valuable expertise on a newbie question, I'm not clear on where to apply this code in Mathematica. I tried:

File > New > Package/Script > WolframScript Script

and then pasted the contents in and pressed "Run All Code", but nothing happens. I realize the "right" approach here would be to start from the ground up and learn Mathematica, but if you can quick-start me, then I may be able to pull this off...!

Thanks in advance!

POSTED BY: Dave K
Posted 3 years ago

Oh, sorry, I assumed too much.

If you're running Mathematica, you can just open a new notebook (File -> New -> Notebook). Copy the Lissajous3D code above, and paste it into the notebook. What you should have at that point is an Input cell. You'll see a bracket at the right side. With the cursor anywhere in that cell, tap Shift+Return. It won't produce any output, but it will have evaluated that code so that Lissajous3D is available to use like any other function. The cursor should now be below that cell. You can also just click anywhere in the whitespace below the cell to make sure. Now copy the whole ParametricPlot3D expression. Paste it into your Mathematica notebook. Again, with the cursor anywhere in this new cell, tap Shift+Return. This time it should output the plot, and it should look like the picture I pasted above. You can now tweak things in the ParametricPlot3D cell (don't need a new cell), and Shift+Return again.You can also tweak the Lissajous3D definition and Shift+Return that cell, and the next time you Shift+Return the ParametricPlot3D cell, it will use the updated definition.

POSTED BY: Eric Rimbey
Posted 3 years ago

Here's the message I've been trying to send for days but keeps giving the error. I finally figured it out. I believe it didn't like the emoji I had placed inline. Ugh!


Got it, thanks! I ended up finding a couple tutorials online that got me past the initial hurdles of "what in the world is a notebook?" (lol) and the secret of SHIFT-ENTER.

As to why the compiler didn't complain when I tried to execute the ParametricPlot3D code with the Lissajous3D definition missing, I have no idea :-)

Anyway, I think we can agree that this is officially "jumping into the deep end", and not the "Hello, World" first project that newbies would be tackling.

Meanwhile, I have an update. I've spent a while reverse engineering and playing with your code, documenting, and "manipulating" (pasted below and attached):

Lissajous3D[cx_, cy_, w_, d_, p_][t_, s_] := {cx Sin[t w + d], 
  cx Cos[t w + d], cy Sin[t] + Rescale[cx Cos[t w + d], {-1, 1},
    {s, p s}]}  

Manipulate[ParametricPlot3D[
   Lissajous3D[
    1, 1,                    (*overall aspect ratio *)

    w,                          (*vertical nodes*)
    \[Phi],        \
                   (*phase*)

    p]                            (*perspective: front/
   back ribbon thickness ratio *)
   [t, s],
        {s, 0, smax},    (*ribbon thickness *)
   {t, 0, 
   tmax},    (*period around cylinder*)
   ViewPoint -> Front,
   ViewProjection -> "Orthographic",
   ColorFunction -> (White &),
   MeshStyle -> None,
   PlotPoints -> {10, 60}, (*resolution??*)

  Lighting -> {{"Point", Blue, {0, -5, 0}}, {"Point", 
         Green, {-3, -5, 0}}},
   Axes -> ax]
 ,
 {{w,      1,         "vertical frequency"}, 1, 10, 
  Appearance -> "Labeled"},
 {{\[Phi],      Pi/4, "relative phase"}, 0, 2 Pi, 
  Appearance -> "Labeled"}, Delimiter ,
 {{smax, .1,      "ribbon thickness"}, .01, .3, 
  Appearance -> "Labeled"},
 {{tmax, 2 Pi,   "tmax"}, 0, 8 Pi, Appearance -> "Labeled"},
 {{p,     .25,      "perspective"}, 1, .1, Appearance -> "Labeled"},
 {{ax,   False, "show axes"}, {True, False}}
 ]

Before I get any further with graphical details, the main limitation is that this Lissajous function only allows control over the vertical frequency, not the horizontal frequency. Specifically, the "t" for the two parametric functions needs to be independent. I tried splitting that out (code not shown, because it doesn't work), but things don't look right.

Do you know how to fix that without breaking the 3D features we have here?

Thanks again!

Dave

p.s. Happy New Year!

Attachments:
POSTED BY: Dave K
Posted 3 years ago

I believe that it already does handle vertical and horizontal "frequencies". It just might be hard to see with examples you've tried. In the way I defined the lissajous function, the w argument is basically the ratio of the vertical and horizontal "frequencies". There are some subtleties here, because if it's not rational, then the curve doesn't "close", and if you don't extend your tmax far enough, you might not be getting enough "cycles" of the curve to see all of the "bumps". Also, the view angle can make it easier or harder to see.

For example, using my original definition, execute this:

ParametricPlot3D[
 Lissajous3D[1, 1, 4/3, Pi/3][t, s], {s, 0, .1}, {t, 0, 6 Pi}, 
 ViewPoint -> Front, ViewProjection -> "Orthographic", 
 ColorFunction -> (White &), MeshStyle -> None, 
 PlotPoints -> {20, 60}, 
 Lighting -> {{"Point", Blue, {0, -5, 0}}, {"Point", 
    Green, {3, -5, 0}}}, Axes -> False]

Then execute this:

ParametricPlot3D[
 Lissajous3D[1, 1, 3/4, Pi/2][t, s], {s, 0, .1}, {t, 0, 8 Pi}, 
 ViewPoint -> Front, ViewProjection -> "Orthographic", 
 ColorFunction -> (White &), MeshStyle -> None, 
 PlotPoints -> {20, 60}, 
 Lighting -> {{"Point", Blue, {0, -5, 0}}, {"Point", 
    Green, {3, -5, 0}}}, Axes -> False]

So, what you could do in your Manipulate is have a slider for vertical frequency and another for horizontal frequency (use new variable names for these--e.g. hf, vf-- and get rid of w), and then in the Lissajous3D expression, replace w with vf/hf.

POSTED BY: Eric Rimbey
Posted 3 years ago

First of all, THANKS AGAIN!

I had tried varying "w" through a bunch of values, and only ever got one "loop" at the top. But I guess I didn't try the right values!

I tried what you said, and it got me my vertical/horizontal nodes. I've attached my latest version, for the record. With that working, I'm going to go back to your original color and perspective parameters, and see how close I can get to the "3D" effect I was looking for.

Then I'll report back!

Attachments:
POSTED BY: Dave K
Posted 3 years ago

Okay, my apologies. I figured it out. There was no output because I had not pasted the Lissajous function definition in. After I did that (ahead of the other code) and then pressed shift-ENTER, I got the plot.

Progress! lol.

Let me try to experiment with this and get back to you.

Thanks!

POSTED BY: Updating Name
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract