Search code examples
maple

How to trace out a curve


I am working on a project dealing with closed curves. I want to trace out a curve swept out by a coordinate vector moves. Just to get the code down I'm trying to accomplish the goal using a circle. I am able to animate the motion of the vector with the following command

animate(arrow, [[cos(2*Pi*n/1000),sin(2*Pi*n/1000)], shape = arrow, 
        scaling = constrained], n=0..1000, frames = 100);

Is there a way to trace the circle that is swept out by this curve. Again my goal is to be able to do this for an arbitrary parameterized curve. Any help is greatly appreciated.


Solution

  • Here is a basic but verbose way to do it,

    restart;
    plots:-animate(plots:-display,
                   [ 'plots:-arrow([cos(2*Pi*n/1000),
                                    sin(2*Pi*n/1000)],
                                   shape = arrow)',
                     'plot([cos(2*Pi*nn/1000),
                            sin(2*Pi*nn/1000),nn=0..n])',
                     scaling = constrained ],
                   n=0..1000, frames = 30);
    

    enter image description here

    If that seems complicated then perhaps it's good to review Maple's evaluation rules for procedure calls. Maple normally evaluates the arguments before passing them to the procedure.

    But sometimes you don't want that evaluation to occur until, say, the procedure can provide a numeric value for a parameter in some argument. That is to say, sometimes you want to avoid premature evaluation of the arguments.

    The seq command deals with this by having so-called special-evaluation rules, where the evaluation of the argument is delayed unto the seq index variable takes on it individual values.

    The plots:-animate command allows you to deal with it by separating the main command from its arguments (which get passed separately, in a list). That is often adequate, but not when those arguments in the list also contain full calls to plotting commands which would not evaluate ok (ie. without error, up front) until the animating parameter gets its actual values.

    That is why I also used single right-quotes to delay the evaluation of the calls to plots:-arrow and plot in the example above. Those evaluations need to wait until the animating parameter n takes on its actual numeric values.

    And another, related approach is to create a procedure which accepts the animating parameter value and constructs a whole frame.

    F := proc(n)
           plots:-display(
             plots:-arrow([cos(2*Pi*n/1000),
                           sin(2*Pi*n/1000)],
                          shape = arrow),
             plot([cos(2*Pi*nn/1000),
                   sin(2*Pi*nn/1000),
                   nn=0..n]),
             scaling = constrained);
         end proc:
    

    This can be handy as it lets you test beforehand.

    F(307.2);
    

    enter image description here

    (I didn't bother to optimize F, but you could notice that the sin and cos calls happen twice, and instead do them just once inside the procedure and assign to local variables. That might make things easier when you go on to more involved parametric curves.)

    Now the calls to plots:-animate can be terse,

    plots:-animate(F, [ n ],
                   n=0..1000, frames = 30);
    

    The above produces the same animation as before.

    Here's another way, by constructing a list containing a sequence of all the frames.

    Note that, as written, evaluating F at unknown, unassigned name n produces an error.

    F(n);
      Error, (in plots/arrow) invalid input: plottools:-arrow
      expects its 3rd argument, pv, to be of type {Vector, list, 
      vector, complexcons, realcons}, but received 0.5000000000e-1* 
      (cos(0.6283185308e-2*n)^2+sin(0.6283185308e-2*n)^2)^(1/2)
    

    The error occurs because n does not have a numeric value.

    But the special-evaluation rules of the seq command allow us to proceed anyway, since it delays the evaluation of F(n) until n gets its values.

    # note termination with full colon, to suppress output
    S := [seq(F(n), n=0..1000, (1000-0)/(30-1))]:
    
    nops(S);  # check that we really got 30 frames
                         30
    
    plots:-display(S, insequence=true);
    

    That last command also displays the same 30-frame animation.