Final Project files for mBed development.

Dependencies:   m3pi mbed

user-gui.py

Committer:
lsaristo
Date:
2014-12-19
Revision:
46:a3b9c0fe8f36
Parent:
36:f25de790ea0b

File content as of revision 46:a3b9c0fe8f36:

#!/usr/bin/python
""""

NOTE: A substantial portion of this code was taken from Dave Michell's
example illustrating how to draw on a Python-generated canvas. All credit
for those portions of the code belong to him. Below is the header from the
original document written by him.
    
# Start origin header ########################

Paint program by Dave Michell.

Subject: tkinter "paint" example
From: Dave Mitchell <davem@magnet.com>
To: python-list@cwi.nl
Date: Fri, 23 Jan 1998 12:18:05 -0500 (EST)

  Not too long ago (last week maybe?) someone posted a request
for an example of a paint program using Tkinter. Try as I might
I can't seem to find it in the archive, so i'll just post mine
here and hope that the person who requested it sees this!

  All this does is put up a canvas and draw a smooth black line
whenever you have the mouse button down, but hopefully it will
be enough to start with.. It would be easy enough to add some
options like other shapes or colors...

                                                yours,
                                                dave mitchell
                                                davem@magnet.com
    
# End original header #########################
    
"""
from Tkinter import *
import os
import sys
import re

"""paint.py: not exactly a paint program. just a smooth line drawing demo."""

TEMP_FILE = "canvas-temp.ps"
OUTPUT_FILE = "test.ps"
b1 = "up"
xold, yold = None, None
height = 600
width = 600

class popupWindow(object):
    def __init__(self,master):
        top=self.top=Toplevel(master)
        self.l=Label(top,text="Resize Window")
        self.l.pack()
        self.h=Label(top,text="Height");
        self.h.pack()
        self.e=Entry(top)
        self.e.pack()
        self.w=Label(top,text="Width");
        self.w.pack()
        self.f=Entry(top);
        self.f.pack()
        self.b=Button(top,text='Ok',command=self.cleanup)
        self.b.pack()
        self.master = master
    def cleanup(self):
        global height
        global width
        h = self.e.get()
        w = self.f.get()
        self.top.destroy()
        self.master.geometry(h+"x"+w)
        height = h
        width = w

def loop():
    root = Tk()
    root.geometry("%dx%d" % (height,width))
    root.title("RoboCanvas")
    drawing_area = Canvas(root)
    drawing_area.pack(fill=BOTH,expand=1)
    drawing_area.bind("<Motion>", motion)
    drawing_area.bind("<ButtonPress-1>", b1down)
    drawing_area.bind("<ButtonRelease-1>", b1up)

    menubar = Menu(root)
    control_menu = Menu(root);
    control_menu.add_command(label="Deploy       ", \
        command=lambda p=drawing_area: build(p));
    control_menu.add_command(label="Clear Canvas",\
        command=lambda p=drawing_area: p.delete('all'))
    control_menu.add_command(label="Resize Canvas", command=lambda p=root:\
        resize(root));
    control_menu.add_separator()
    control_menu.add_command(label="Exit", command=lambda p=root: root.quit())
    menubar.add_cascade(label="Control", menu=control_menu);
    root.config(menu=menubar);
    message = Label(root, text="Press and hold with the mouse to draw");
    message.pack(side=BOTTOM)
    root.mainloop()

def resize(root):
    """ Resize the root window and expand the canvas to fill """
    ans = popupWindow(root);

def build(canvas):
    """
    This function is indended to be called from the drawing canvas after
    the drawing is complete and the user wishes to push it to the robot.
    This function must send (somehow) the appropriate information to the 
    robot to make the drawing happen.
    """
    gen_postscript(canvas)

def gen_postscript(canvas):
    """ Make a postscript capture of the canvas """
    
    # Get lineto and moveto data from standard postscript output. 
    l = []
    canvas.update()
    canvas.postscript(file=TEMP_FILE);
    f = open(TEMP_FILE, "r")
    for line in f.readlines():
        if 'lineto' in line or 'moveto' in line:
            l.append(line)
    f.close()

    # Filter the moves list
    output = filter_moves(l)

    # Write filtered output to the new canvas file.
    l = l[5:]
    f = open(OUTPUT_FILE, "w");
    f.write(str(height) + "/" + str(width)+"\n");
    for line in output:
        f.write(line);
    f.close()
    os.remove(TEMP_FILE);

def filter_moves(moves):
    """ Return a processed list of moves """

    filtered_moves = list(moves)[5:]
    output_list = []

    prev = filtered_moves[0]
    output_list.append(prev)    # Write the first moveto always.
    prev = filtered_moves[1]
    output_list.append(prev)

    for move in filtered_moves[2:]:
        x_coord = move.split()[0]
        x_coord_prev = prev.split()[0]
        y_coord = move.split()[1]
        y_coord_prev = prev.split()[1]

        # Remove redundant moveto's
        if x_coord != x_coord_prev or y_coord != y_coord_prev:
            output_list.append(move)
            prev = move
            
    # Flatten on x-coordinate
    filtered_moves = list(output_list)
    output_list = [filtered_moves.pop(0)]
    prev = filtered_moves.pop(0)
    prev_s = prev.split()
    prev_y = prev_s[1]
    prev_x = prev_s[0]
    while filtered_moves:
        move = filtered_moves.pop(0)
        move_s = move.split()
        move_x = move_s[0]
        move_y = move_s[1]
        move_c = move_s[2]
        
        if move_c == 'moveto':
            output_list.append(prev)
            prev = None
            output_list.append(move)
            continue

        if prev and move_x == prev_x:
            prev = move
            prev_y = move_y
            continue
        if prev: output_list.append(prev)
        prev = move
        prev_s = prev.split()
        prev_y = prev_s[1]
        prev_x = prev_s[0]
    if prev: output_list.append(prev)

    # Flatten on y-coordinate   
    filtered_moves = list(output_list)
    output_list = [filtered_moves.pop(0)]
    prev = filtered_moves.pop(0)
    prev_s = prev.split()
    prev_y = prev_s[1]
    prev_x = prev_s[0]
    while filtered_moves:
        move = filtered_moves.pop(0)
        move_s = move.split()
        move_x = move_s[0]
        move_y = move_s[1]
        move_c = move_s[2]
        
        if move_c == 'moveto':
            output_list.append(prev)
            prev = None
            output_list.append(move)
            continue
        
        if prev and move_y == prev_y:
            prev_x = move_x
            prev = move
            continue
        if prev: output_list.append(prev)
        prev = move
        prev_s = prev.split()
        prev_y = prev_s[1]
        prev_x = prev_s[0]
    if prev: output_list.append(prev)

    x0 = 0
    y0 = 0
    f_output_list = list()
    i = 0
    to_app = ""
    while i < len(output_list)-1:
        line1 = output_list[i].split(' ')
        line2 = output_list[i+1].split(' ')
        x1 = int(line1[0])
        x2 = int(line2[0])
        y1 = int(line1[1])
        y2 = int(line2[1])
        if line1[2] == line2[2] and dist(x0,y0,x1,y1) <= 20\
                and dist(x1,y1,x2,y2) <= 20:
            i += 1
            to_app = "%d %d %s" % (x2,y2,line1[2])
        else:
            x0 = x1
            y0 = y1
            if to_app != "":
                f_output_list.append(to_app)
                to_app = ""
            else:
                f_output_list.append(output_list[i])
            i += 1
    f_output_list.append(output_list[len(output_list)-1])
    print "Raw Numbers: ", moves
    print "--------------------------------------------"
    print "Filtered: ", f_output_list
    return f_output_list

def dist(x1,y1,x2,y2):
    return ((x2-x1)**2 + (y2-y1)**2)**.5

def b1down(event):
    global b1
    b1 = "down"           # you only want to draw when the button is down
                          # because "Motion" events happen -all the time-

def b1up(event):
    global b1, xold, yold
    b1 = "up"
    xold = None           # reset the line when you let go of the button
    yold = None

def motion(event):
    if b1 == "down":
        global xold, yold
        if xold is not None and yold is not None:
            event.widget.create_line(xold,yold,event.x,event.y,smooth=TRUE)
        xold = event.x
        yold = event.y

def main():
    """ Main program entry point """
    loop()

if __name__ == "__main__":
    main()