View Raw SPL
/*****************************************************************************
*                                                                            *
*   CUT.SPL      Copyright (C) 1998-2017 DSP Development Corporation         *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Cuts displayed contents of a Window into the current Window *
*                                                                            *
*   Revisions:    8 Jun 1998  RRR  Creation                                  *
*                16 Nov 2006  RRR  Optional cutxy parameter for y range      *
*                22 May 2012  RRR  Optional zeropad to pad end points        *
*                17 Sep 2017  RRR  refactor for big data speedup             *
*                                                                            *
*****************************************************************************/

#if @HELP_CUT

    CUT

    Purpose: Cuts the displayed contents of a Window

    Syntax:  CUT(win, cutxy, zeropad)

              win    - A window

              cutxy  - Optional. An integer, 1: cut using both the x and y
                       displayed range, 0: cut using the x range only (default).

             zeropad - Optional. An integer, 1: pad beginning and/or end
                       points with zeros if cut range beyond the series
                       size, 0: limit cut range to series extent (default).

    Returns: A series or array

    Example:
             W1: gnorm(1000, 1/1000);setx(.2, .5)
             W2: cut(W1)

             W2 contains the data actually displayed in W1.

    Example:
             W1: gnorm(1000, 1/1000);sety(-0.5, 1.5)
             W2: cut(W1)
             W3: cut(W1, 1)

             W2 contains the same data as W1, but W3 contains the Y extracted
             portion of the data displayed in W1. The Y values of W3 range
             from -0.5 to 1.5.

    Example:
             W1: gnorm(1000, 1/1000);setx(-0.5, 1.5)
             W2: cut(W1, 0, 0)
             W3: cut(W1, 0, 1)

             W2 contains the same data as W1 because the dislayed data
             is longer than the extent of W1. However, W3 pads the starting
             and ending values with zeros to produce a series that extends
             from -0.5 to 1.5.

    Remarks:
             Cut works properly on arrays and images.

             The ZEROPAD option only applies to series.

    See Also:
             Extract
             Setvport
#endif


/* extract the displayed portion of a series */
cut(win, cutxy, zeropad)
{
        local s;

        if (argc < 3)
        {
                if (argc < 2)
                {
                        if (argc < 1)
                        {
                                win = refwindow(w0);
                        }

                        cutxy = 0;
                }

                zeropad = 0;
        }
        
        s = wincut(win, cutxy, zeropad);
        
        return(s);
}


wincut(win, cutxy, zeropad)
{
        local nr, nc, s;

        if (not(iswindow(win)))
        {
                error("cut - requires Window");
        }

        (nr, nc) = size(win);

        if (nc > 1)
        {
                /* stripchart */
                if (isstripchart(win))
                {
                        s = wincut_stripchart(win, cutxy, zeropad, nr, nc);
                }
                else if (isxy(win) && nc == 2)
                {
                        /* XY */
                        s = wincut_xy(win, cutxy, zeropad, nr, nc);
                }
                else if (isxyz(win))
                {
                        /* XYZ */
                        s = wincut_xy(win, 1, zeropad, nr, nc);
                }
                else
                {
                        /* array */
                        s = wincut_array(win, cutxy, zeropad, nr, nc);
                }
        }
        else
        {
                s = wincut_interval(win, cutxy, zeropad, nr, nc);
        }

        return(s);
}


/* lo to hi */
wincut_swap(a, b)
{
        if (a > b)
        {
                return(b, a);
        }
        else
        {
                return(a, b);
        }
}


/* cut XY series */
wincut_xy(win, cutxy, zeropad, nr, nc)
{
        local ixl, ixr, s = {};

        if (nc > 1)
        {
                /* delete x values out of window range */
                x   = xvals(win);
                ixl = getxl(win);
                ixr = getxr(win);
                        
                (ixl, ixr) = wincut_swap(ixl, ixr);
                s = delete(win, x < ixl || x > ixr);

                if (cutxy)
                {
                        /* delete y values out of window range */
                        y   = yvals(s);
                        ixl = getyb(win);
                        ixr = getyt(win);
                                
                        (ixl, ixr) = wincut_swap(ixl, ixr);

                        s = delete(s, y < ixl || y > ixr);
                }
        }

        return(s);
}


/* cut array */
wincut_array(win, cutxy, zeropad, nr, nc)
{
        local ixl, ixr, tmp, s = {};

        if (nc > 1)
        {
                ixl = xtoidx(win, getxl(win), 1);
                ixr = xtoidx(win, getxr(win), 1);

                iyb = castint(ceil( (getyb(win) - yoffset(win)) / deltay(win)) + 1);
                iyt = castint(floor((getyt(win) - yoffset(win)) / deltay(win)) + 1);

                if (iyb < 1)  iyb = 1;
                if (iyb > nc) iyb = nc;

                if (iyt < 1)  iyt = 1;
                if (iyt > nc) iyt = nc;

                (iyb, iyt) = wincut_swap(iyb, iyt);

                if (ixl == ixr && ixr < nr) ixr++;
                if (iyb == iyt && iyt < nc) iyt++;

                s  = win[ixl..ixr, iyb..iyt];
        }

        return(s);
}


/* cut interval series */
wincut_interval(win, cutxy, zeropad, nr, nc)
{
        local ixl, ixr, s = {};

        if (nr > 0)
        {
                /* map left and right to indices */
                ixl = xtoidx(win, getxl(win), not(zeropad));
                ixr = xtoidx(win, getxr(win), not(zeropad));

                /* extract */
                s = extract(win, ixl, ixr - ixl + 1);
        
                if (cutxy)
                {
                        /* clip y values */
                        ixl = getyb(win);
                        ixr = getyt(win);
                        
                        (ixl, ixr) = wincut_swap(ixl, ixr);

                        s = clip(s, ixr, ixl);
                }
        }

        return(s);
}


/* cut stripchart */
wincut_stripchart(win, cutxy, zeropad, nr, nc)
{
        local s;

        /* reset autoranging */
        setxauto(w0, -1, -1);
        setyauto(w0, -1, -1);

        if (nc == numitems(win))
        {
                /* all traces are interval */
                s = wincut_interval(win, cutxy, zeropad, nr, nc);
        }
        else
        {
                s = wincut_xy(win, cutxy, zeropad, nr, nc);
        }

        return(s);
}