LAM Mapping Lab Solutions

From PkalTides Wiki
Jump to: navigation, search

--Thiebaut (talk) 14:24, 27 October 2014 (EDT)




Back to LAM Page


Solution Program for Part 1


from graphics111 import *
 
MAXWIDTH  = 600
MAXHEIGHT = 400
 
class Car:
    def __init__(self, x, y, w, h, color ):
        self._body = Rectangle( x, y, w, h, color )
        self._w1   = Wheel( x+w//4, y+h, w//4 )
        self._w2   = Wheel( x+3*w//4, y+h, w//4 )
 
    def draw( self, canvas ):
        self._body.draw( canvas )
        self._w1.draw( canvas )
        self._w2.draw( canvas )
 
    def move( self, canvas, dx, dy ):
        self._body.move( canvas, dx, dy )
        self._w1.move( canvas, dx, dy )
        self._w2.move( canvas, dx, dy )
 
def mouseEvent( win, canvas, x, y ):
    global menu, car
    button = menu.buttonClicked( x, y )
 
    if button == None:
        # create a circle centered on mouse coordinates
        # give it a color that depends on the location (for fun)
        c1 = Circle( x, y, 20, (x%256, y%256, (x+y)%256 ) )
        c1.draw( canvas )
        return
 
    if button == "LeftArrow":
        #print( "left-arrow clicked!" )
        car.move( canvas, -10, 0 )
        return
 
    if button == "RightArrow":
        #print( "right-arrow clicked!" )
        car.move( canvas, 10, 0 )
        return
 
    if button == "Minus":
        print( "minus clicked!" )
        return
 
    if button == "Plus":
        print( "plus clicked!" )
        return    
 
def main():
    global menu, car
 
    win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
    canvas = win.canvas()
    canvas.setCallbackFunction( mouseEvent )    
 
    menu = Menu()
    menu.draw( canvas )
 
    car = Car( 100, 100, 50, 20, (250, 250, 0) )
    car.draw( canvas )
 
    win.wait()
    win.close()
 
main()


Solution Programs for Part 2


Creating the Map


This is definitely more involved than what you had to do, but contains all the elements you had to put together.

# MapDigitizer.py
# D. Thiebaut
#
# This program imports the file SmithMapSmall.gif and displays it on the canvas.
# The user then must use the + symbol in the menu to start the digitization, which
# first asks the user to enter the name of the building.  The user then clicks on vertices
# of the building's outline to record their coordinates.  When the user has gone around the
# full building, she clicks on the minus symbol of the menu.   The program then writes the
# csv representation of the building to a file called buildings.csv.
#
 
from graphics111 import *
 
MAXWIDTH = 700    # the dimensions of the gif image
MAXHEIGHT = 836 
 
## call-back function.
# mouseEvent(): called by the graphics library whenever
# a mouse event is captured.
# win: a reference to the main graphics window
# canvas: a reference to the canvas
# x, y: the coordinates (in pixels) of the mouse click.
# (the top-left corner is 0,0)
def mouseEvent( win, canvas, x, y ):
 
    # global variables shared with main()
    global menu           # the menu top-left of the canvas
    global buildingList   # list of building coordinates
    global csvFileName    # name of the file where building csv info stored
 
    # ask menu is mouse was clicked on one of its buttons
    button = menu.buttonClicked( x, y )
 
    # mouse not clicked on menu item.  Add x, y coords to the
    # current building list.
    if button == None:
        buildingList.append( x )
        buildingList.append( y )
 
        # show some fun feedback for user
        if len( buildingList ) >=7 :
            canvas.setColor( 200, 130, 199 )
            canvas.drawPolygon( buildingList[1:] )
 
        return
 
    # nothing to do for left or right arrow
    if button == "LeftArrow" or button == "RightArrow":
        return
 
    # if plus button clicked, start a new list for a new
    # building.  Get a new name and start the list.
    if button == "Plus":
        rawName = input( "Building name? " ).strip()
 
        # capitalize the name
        name = ""
        for word in rawName.strip().split():
            name += word.capitalize()+ " "
 
        # start new list
        buildingList = [ name.strip() ]
        return    
 
    # if minus button, transform the list into csv line and
    # append to file.
    if button == "Minus":
        for i in range( 1, len( buildingList ) ):
            buildingList[i] = str( buildingList[i] )
        file = open( csvFileName, "a" )
        file.write( ", ".join( buildingList ) + "\n" )
        file.close()
        return
 
 
# ========================================================
#                       Main Program
# Declares globals shared with call-back function
# Creates a window and gets access to its canvas
# Displays a map on the canvas
# Draws a menu in top left corner
# Waits for for mouse events.
# ========================================================
def main():
    # list of variables shared with the call-back function
    global menu
    global buildingList
    global csvFileName
 
    # the two files (located in same directory).
    # gif contains map, csv contains output of program
    csvFileName = "buildings.csv"        
    gifFileName = "SmithMapSmall.gif"
 
    # open the window and get access to its canvas
    win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
    canvas = win.canvas()
    canvas.setCallbackFunction( mouseEvent )
 
    # put gif image on canvas    
    photo = tk.PhotoImage( file=gifFileName )
    canvas._tkcanvas.create_image(0,0, image=photo, anchor = tk.NW )
 
    # add a menu to the window
    menu = Menu()
    menu.draw( canvas )
 
    # wait and respond to events, or comment out and make the program
    # stop as soon as car disappears.
    win.wait()
    win.close()
 
main()


Reading and Drawing the Digitized Map

SmithMapLab12.png


from graphics111 import *
 
 
MAXWIDTH = 800
MAXHEIGHT = 800
 
 
def main():
    win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
    canvas = win.canvas()
 
    file = open( "smithMap.csv", "r" )
 
    for line in file:
        name = line.split( "," )[0].strip()
        coords = line.split( "," )[1:]
        for i in range( len( coords ) ):
            coords[i] = int( coords[i].strip() )
        p = Polygon( coords, (250, 250, 10 ) )
        p.draw( canvas )
        canvas.drawText( coords[0], coords[1], name )
 
    file.close()
 
    win.wait()
    win.close()
 
main()







And if you are interested in a tightly packed program, barely readable, but spanning very few lines, here's the minimalist version:

from graphics111 import *
 
 
MAXWIDTH = 800
MAXHEIGHT = 800
 
 
def main():
    win = GraphicsWindow(MAXWIDTH, MAXHEIGHT)
    canvas = win.canvas()
 
    for line in open( "smithMap.csv", "r" ):
        Polygon( [int(k) for k in line.split( "," )[1:] ], (250, 250, 10 ) ).draw( canvas )
        canvas.drawText( int( line.split( "," )[1] ),
                         int( line.split( "," )[2] ),
                         line.split( "," )[0].strip() )
 
    win.wait()
    win.close()
 
main()