View Raw SPL
/*****************************************************************************
*                                                                            *
*   ROTATE2D.SPL Copyright (C) 2021 DSP Development Corporation              *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Rotates a 2D plot                                           *
*                                                                            *
*   Revisions:    9 Nov 2021  RRR  Creation                                  *
*                                                                            *
*****************************************************************************/

#include 

#if @HELP_ROTATE2D

    ROTATE2D

    Purpose: Rotates a series or 2D plot.

    Syntax:  ROTATE2D(s, a, xc, yc)

               s - Optional. The input series. Defaults to the series in
                   the current window.

               a - Optional. A real, the rotation angle in degrees. Defaults
                   to 45.0.

              xc - Optional. A real, the X rotation center. Defaults to 0.0.

              yc - Optional. A real, the Y rotation center. Defaults to 0.0.

    Returns: An XY series, the rotated plot.

    Example:
             W1: gsin(1000, 1/1000, 4);rotate2d(30)

             W1 contains a 4 Hz sinewave. The data is rotated by 30 degrees.

    Example:
             W1: gsin(1000, 1/1000, 4)
             W2: rotate2d(w1, 30)

             W1 contains a 4 Hz sinewave.

             W2 rotates the data in W1 by 30 degrees.

    Example:
             W1: gsin(1000, 1/1000, 4)
             W2: w1;overp(rotate2d(w1, 45, 0.0, 0.0));setx(-2, 2);sety(-2, 2);setaspect(1)
             W3: w1;overp(rotate2d(w1, 45, 0.5, 0.0));setx(-2, 2);sety(-2, 2);setaspect(1)
             W4: w1;overp(rotate2d(w1, 45, 1.0, 0.0));setx(-2, 2);sety(-2, 2);setaspect(1)

             W2 rotates the data in W1 by 45 degrees about the first point.
             W3 rotates the data in W1 by 45 degrees about the middle point.
             W4 rotates the data in W1 by 45 degrees about the last point.

    Example:
             W1: gsin(1000, 1/1000, 4)
             W2: rotate2d(w1,  45, 0.5, 0.0)
             W3: rotate2d(w2, -45, 0.5, 0.0)

             W2 rotates the data in W1 by 45 degrees about the middle point.

             W3 rotates the data back to the original orientation.
             
             Note the data in W1 is an interval series and the data in
             W2 and W3 are XY series.

    Remarks:
             The rotation angle is specified in degrees and the rotation
             direction is clockwise.

    See Also:
             Rotate3d
#endif


/* rotate a 2D plot */
rotate2d(s, a, xc, yc)
{
        local x, y, t, sr;

        (s, a, xc, yc) = rotate2d_parse_args(s, a, xc, yc);

        /* rotation angle in radians */
        t = a * pi / 180;

        /* rotation about xc, yc */
        x = (xvals(s) - xc) * cos(t) - (yvals(s) - yc) * sin(t) + xc;
        y = (xvals(s) - xc) * sin(t) + (yvals(s) - yc) * cos(t) + yc;

        /* XY */
        sr = xy(x, y);

        /* units */
        sethunits(sr, gethunits(s));
        setvunits(sr, getvunits(s));

        return(sr);
}

rotate2d_parse_args(argv)
{
        local s = {}, a = {}, xc = {}, yc = {};

        loop (j = 1..argc)
        {
                if (not(IS_ARG_UNSPECIFIED(getargv(j))))
                {
                        if (isarray(getargv(j)))
                        {
                                s = getargv(j);
                        }
                        else if (isempty(a))
                        {
                                a = getargv(j);
                        }
                        else if (isempty(xc))
                        {
                                xc = getargv(j);
                        }
                        else if (isempty(yc))
                        {
                                yc = getargv(j);
                        }
                }
        }

        if (isempty(s))
        {
                s = refseries(w0);
        }

        if (isempty(a))
        {
                a = 45;
        }

        if (isempty(xc))
        {
                xc = 0;
        }

        if (isempty(yc))
        {
                yc = 0
        }
        
        return(s, a, xc, yc);
}