Square spiral with matplotlib (1)

Today, at work, a friend asked me to make a simple program to draw “square spiral based on an input number”. You can see the result below:

It’s implemented in python using matplotlib to pot the square spiral. First we look for each edge to be drawn with calc_spiral:

def calc_spiral( p_num_edges ):
    """Function to calculate each edge to draw."""
    values = range( p_num_edges, -1, -1 )

    state = True # if true x-axis if false y-axis
    direction = True # if true + if false -
    c = 0 # counter used to know when direction should change
    lx = 0 # last x-axis value
    ly = 0 # last y-axis value

    # Each item on the list ( segments ) contains:
    # ( Axis, Origin point in axis, end point in axis,
    # Value of opposite axis, Drawing direction )
    segments = [ ]

    for i in range( len( values ) ):
        # change direction each two iterations
        if c % 2 == 0: direction = not direction
            if state: # if x-axis
                # added or subtracted according to the direction
                if not direction:
                    nlx = lx + values[ i ]
                else:
                    nlx = lx - values[ i ]
                v = ( "x", lx, nlx, ly, direction )
                lx = nlx
            else: # if y-axis
                # added or subtracted according to the direction
                if not direction:
                    nly = ly + values[ i ]
                else:
                    nly = ly - values[ i ]
                v = ( "y", ly, nly, lx, direction )
                ly = nly
            segments.append( v )
        # change axis each iteration
        state = not state
        c += 1

    return segments

Calling this function we get a list of edges which look like:

[ ('x', 0, 4, 0, False), ('y', 0, 3, 4, False),
('x', 4, 2, 3, True), ('y', 3, 2, 2, True),
('x', 2, 2, 2, False) ]

Each item represents an edge of the square spiral: axis, origin point, end point, actual opposite axis value, direction (on direction True means positive increment, False negative).

(Sure it can be made more clean and optimal).

Gotten edges to draw we call draw_spiral to clear our plot and draw the spiral:

def draw_spiral( self, p_segments, p_num_edges ):
    """Function used to draw segments on chart."""
    # Clear axes from previous drawing
    self.__axes.cla()
    # Draw each segment taking care about it's axis and direction
    for item in p_segments:
        if item[ 0 ] == "x":
            if not item[ 4 ]:
                xv = range( item[ 1 ], item[ 2 ] + 1, 1 )
            else:
                xv = range( item[ 1 ], item[ 2 ] - 1, -1 )
            yv = map( lambda _ : item[ 3 ], xv )
        elif item[ 0 ] == "y":
            if not item[ 4 ]:
                yv = range( item[ 1 ], item[ 2 ] + 1, 1 )
            else:
                yv = range( item[ 1 ], item[ 2 ] - 1, -1 )
            xv = map( lambda _ : item[ 3 ], yv )
        self.__axes.plot( xv, yv )

    # Set axis limits and draw
    m = float( p_num_edges ) + 1
    self.__axes.axes.set_xlim( [ -1.0, m ] )
    self.__axes.axes.set_ylim( [ -1.0, m ] )
    self.__fig.canvas.draw()

Note that in this function the figure, canvas and axis are not initialized. That’s because they’re initialized on creating the main container widget.

The complete source file is here.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: