demo to match. Also fixed some deprecation warnings. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@27049 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			1356 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1356 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import wx
 | 
						|
 | 
						|
from Numeric import array,Float,cos,pi,sum,minimum,maximum,Int32
 | 
						|
from time import clock, sleep
 | 
						|
import types
 | 
						|
import os        
 | 
						|
 | 
						|
ID_ZOOM_IN_BUTTON = wx.NewId()
 | 
						|
ID_ZOOM_OUT_BUTTON = wx.NewId()
 | 
						|
ID_ZOOM_TO_FIT_BUTTON = wx.NewId()
 | 
						|
ID_MOVE_MODE_BUTTON = wx.NewId()
 | 
						|
ID_TEST_BUTTON = wx.NewId()
 | 
						|
 | 
						|
ID_ABOUT_MENU = wx.NewId()          
 | 
						|
ID_EXIT_MENU  = wx.NewId() 
 | 
						|
ID_ZOOM_TO_FIT_MENU = wx.NewId()
 | 
						|
ID_DRAWTEST_MENU = wx.NewId()
 | 
						|
ID_DRAWMAP_MENU = wx.NewId()
 | 
						|
ID_CLEAR_MENU = wx.NewId()
 | 
						|
 | 
						|
ID_TEST = wx.NewId()
 | 
						|
 | 
						|
 | 
						|
### These are some functions for bitmaps of icons.
 | 
						|
import cPickle, zlib
 | 
						|
 | 
						|
def GetHandData():
 | 
						|
    return cPickle.loads(zlib.decompress(
 | 
						|
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
 | 
						|
\x01\xc8S\xb6t\x06A(\x1f\x0b\xa0\xa9\x8c\x9e\x1e6\x19\xa0\xa8\x1e\x88\xd4C\
 | 
						|
\x97\xd1\x83\xe8\x80 \x9c2zh\xa6\xc1\x11X\n\xab\x8c\x02\x8a\x0cD!\x92\x12\
 | 
						|
\x98\x8c\x1e\x8a\x8b\xd1d\x14\xf4\x90%\x90LC\xf6\xbf\x1e\xba\xab\x91%\xd0\
 | 
						|
\xdc\x86C\x06\xd9m\xe8!\xaa\x87S\x86\x1a1\xa7\x07\x00v\x0f[\x17' ))
 | 
						|
 | 
						|
def GetHandBitmap():
 | 
						|
    return wx.BitmapFromXPMData(GetHandData())
 | 
						|
 | 
						|
#----------------------------------------------------------------------
 | 
						|
def GetPlusData():
 | 
						|
    return cPickle.loads(zlib.decompress(
 | 
						|
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
 | 
						|
\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=l2`\r\
 | 
						|
\xe82HF\xe9a\xc8\xe8\xe9A\x9c@\x8a\x0c\x0e\xd3p\xbb\x00\x8f\xab\xe1>\xd5\xd3\
 | 
						|
\xc3\x15:P)l!\n\x91\xc2\x1a\xd6`)\xec\xb1\x00\x92\xc2\x11?\xb8e\x88\x8fSt\
 | 
						|
\x19=\x00\x82\x16[\xf7' ))
 | 
						|
 | 
						|
def GetPlusBitmap():
 | 
						|
    return wx.BitmapFromXPMData(GetPlusData())
 | 
						|
 | 
						|
#----------------------------------------------------------------------
 | 
						|
def GetMinusData():
 | 
						|
    return cPickle.loads(zlib.decompress(
 | 
						|
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
 | 
						|
\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=\xa2e\
 | 
						|
\x10\x16@\x99\xc82zz\x10\'\x90"\x83\xc34r\xdc\x86\xf0\xa9\x9e\x1e\xae\xd0\
 | 
						|
\x81Ja\x0bQ\x88\x14\xd6\xb0\x06Ka\x8f\x05\x90\x14\x8e\xf8\xc1-C|\x9c\xa2\xcb\
 | 
						|
\xe8\x01\x00\xed\x0f[\x87' ))
 | 
						|
 | 
						|
def GetMinusBitmap():
 | 
						|
    return wx.BitmapFromXPMData(GetMinusData())
 | 
						|
 | 
						|
## This is a bunch of stuff for implimenting interactive use: catching
 | 
						|
## when objects are clicked on by the mouse, etc. I've made a start, so if
 | 
						|
## you are interesed in making that work, let me know, I may have gotten
 | 
						|
## it going by then
 | 
						|
 | 
						|
#### I probably want a full set of events someday:
 | 
						|
## #### mouse over, right click, left click mouse up etc, etc.
 | 
						|
## ##FLOATCANVAS_EVENT_LEFT_DOWN = wx.NewEventType()
 | 
						|
## ##FLOATCANVAS_EVENT_LEFT_UP = wx.NewEventType()
 | 
						|
## ##FLOATCANVAS_EVENT_RIGHT_DOWN = wx.NewEventType()
 | 
						|
## ##FLOATCANVAS_EVENT_RIGHT_UP = wx.NewEventType()
 | 
						|
## ##FLOATCANVAS_EVENT_MOUSE_OVER = wx.NewEventType()
 | 
						|
 | 
						|
##WXFLOATCANVASEVENT = wx.NewEventType()
 | 
						|
 | 
						|
##def EVT_WXFLOATCANVASEVENT( window, function ): 
 | 
						|
 | 
						|
##    """Your documentation here""" 
 | 
						|
 | 
						|
##    window.Connect( -1, -1, WXFLOATCANVASEVENT, function ) 
 | 
						|
 | 
						|
##class wxFloatCanvasObjectEvent(wx.PyCommandEvent):
 | 
						|
##    def __init__(self, WindowID,Object):
 | 
						|
##        wx.PyCommandEvent.__init__(self, WXFLOATCANVASEVENT, WindowID)
 | 
						|
##        self.Object = Object
 | 
						|
 | 
						|
##    def Clone( self ): 
 | 
						|
##        self.__class__( self.GetId() ) 
 | 
						|
 | 
						|
##class ColorGenerator:
 | 
						|
 | 
						|
##    """ An instance of this class generates a unique color each time
 | 
						|
##    GetNextColor() is called. Someday I will use a proper Python
 | 
						|
##    generator for this class.
 | 
						|
 | 
						|
##    The point of this generator is for the hit-test bitmap, each object
 | 
						|
##    needs to be a unique color. Also, each system can be running a
 | 
						|
##    different number of colors, and it doesn't appear to be possible to
 | 
						|
##    have a wxMemDC with a different colordepth as the screen so this
 | 
						|
##    generates colors far enough apart that they can be distinguished on
 | 
						|
##    a 16bit screen. Anything less than 16bits won't work.
 | 
						|
##    """
 | 
						|
 | 
						|
##    def __init__(self,depth = 16):
 | 
						|
##        self.r = 0
 | 
						|
##        self.g = 0
 | 
						|
##        self.b = 0
 | 
						|
##        if depth == 16:
 | 
						|
##            self.step = 8
 | 
						|
##        elif depth >= 24:
 | 
						|
##            self.step = 1
 | 
						|
##        else:
 | 
						|
##            raise "ColorGenerator does not work with depth = %s"%depth
 | 
						|
 | 
						|
##    def GetNextColor(self):
 | 
						|
##        step = self.step
 | 
						|
##        ##r,g,b = self.r,self.g,self.b
 | 
						|
##        self.r += step
 | 
						|
##        if self.r > 255:
 | 
						|
##            self.r = step
 | 
						|
##            self.g += step
 | 
						|
##            if self.g > 255:
 | 
						|
##                self.g = step
 | 
						|
##                self.b += step
 | 
						|
##                if self.b > 255:
 | 
						|
##                    ## fixme: this should be a derived exception
 | 
						|
##                    raise "Too many objects for HitTest"
 | 
						|
##        return (self.r,self.g,self.b)
 | 
						|
 | 
						|
 | 
						|
class draw_object:
 | 
						|
        """
 | 
						|
        This is the base class for all the objects that can be drawn.
 | 
						|
        
 | 
						|
        each object has the following properties; (incomplete)
 | 
						|
        
 | 
						|
        BoundingBox :  is of the form: array((min_x,min_y),(max_x,max_y)) 
 | 
						|
        Pen
 | 
						|
        Brush
 | 
						|
 | 
						|
        """
 | 
						|
 | 
						|
        def __init__(self,Foreground  = 0):
 | 
						|
            self.Foreground = Foreground
 | 
						|
 | 
						|
            self._Canvas = None
 | 
						|
 | 
						|
        # I pre-define all these as class variables to provide an easier
 | 
						|
        # interface, and perhaps speed things up by caching all the Pens
 | 
						|
        # and Brushes, although that may not help, as I think wx now
 | 
						|
        # does that on it's own. Send me a note if you know!
 | 
						|
 | 
						|
        BrushList = {
 | 
						|
                ( None,"Transparent")  : wx.TRANSPARENT_BRUSH,
 | 
						|
                ("Blue","Solid")       : wx.BLUE_BRUSH,
 | 
						|
                ("Green","Solid")      : wx.GREEN_BRUSH,
 | 
						|
                ("White","Solid")      : wx.WHITE_BRUSH,
 | 
						|
                ("Black","Solid")      : wx.BLACK_BRUSH,
 | 
						|
                ("Grey","Solid")       : wx.GREY_BRUSH,
 | 
						|
                ("MediumGrey","Solid") : wx.MEDIUM_GREY_BRUSH,
 | 
						|
                ("LightGrey","Solid")  : wx.LIGHT_GREY_BRUSH,
 | 
						|
                ("Cyan","Solid")       : wx.CYAN_BRUSH,
 | 
						|
                ("Red","Solid")        : wx.RED_BRUSH
 | 
						|
                        }
 | 
						|
        PenList = {
 | 
						|
                (None,"Transparent",1)   : wx.TRANSPARENT_PEN,
 | 
						|
                ("Green","Solid",1)      : wx.GREEN_PEN,
 | 
						|
                ("White","Solid",1)      : wx.WHITE_PEN,
 | 
						|
                ("Black","Solid",1)      : wx.BLACK_PEN,
 | 
						|
                ("Grey","Solid",1)       : wx.GREY_PEN,
 | 
						|
                ("MediumGrey","Solid",1) : wx.MEDIUM_GREY_PEN,
 | 
						|
                ("LightGrey","Solid",1)  : wx.LIGHT_GREY_PEN,
 | 
						|
                ("Cyan","Solid",1)       : wx.CYAN_PEN,
 | 
						|
                ("Red","Solid",1)        : wx.RED_PEN
 | 
						|
                }
 | 
						|
        
 | 
						|
        FillStyleList = {
 | 
						|
                "Transparent"    : wx.TRANSPARENT,
 | 
						|
                "Solid"          : wx.SOLID,
 | 
						|
                "BiDiagonalHatch": wx.BDIAGONAL_HATCH,
 | 
						|
                "CrossDiagHatch" : wx.CROSSDIAG_HATCH,
 | 
						|
                "FDiagonal_Hatch": wx.FDIAGONAL_HATCH,
 | 
						|
                "CrossHatch"     : wx.CROSS_HATCH,
 | 
						|
                "HorizontalHatch": wx.HORIZONTAL_HATCH,
 | 
						|
                "VerticalHatch"  : wx.VERTICAL_HATCH
 | 
						|
                }
 | 
						|
        
 | 
						|
        LineStyleList = {
 | 
						|
                "Solid"      : wx.SOLID,
 | 
						|
                "Transparent": wx.TRANSPARENT,
 | 
						|
                "Dot"        : wx.DOT,
 | 
						|
                "LongDash"   : wx.LONG_DASH,
 | 
						|
                "ShortDash"  : wx.SHORT_DASH,
 | 
						|
                "DotDash"    : wx.DOT_DASH,
 | 
						|
                }
 | 
						|
        
 | 
						|
        def SetBrush(self,FillColor,FillStyle):
 | 
						|
            if FillColor is None or FillStyle is None:
 | 
						|
                self.Brush = wx.TRANSPARENT_BRUSH
 | 
						|
                self.FillStyle = "Transparent"
 | 
						|
            else:
 | 
						|
                if not self.BrushList.has_key((FillColor,FillStyle)):
 | 
						|
                    self.BrushList[(FillColor,FillStyle)] = wx.Brush(FillColor,self.FillStyleList[FillStyle])
 | 
						|
                self.Brush = self.BrushList[(FillColor,FillStyle)]
 | 
						|
                
 | 
						|
        def SetPen(self,LineColor,LineStyle,LineWidth):
 | 
						|
            if (LineColor is None) or (LineStyle is None):
 | 
						|
                self.Pen = wx.TRANSPARENT_PEN
 | 
						|
                self.LineStyle = 'Transparent'
 | 
						|
            else:
 | 
						|
                if not self.PenList.has_key((LineColor,LineStyle,LineWidth)):
 | 
						|
                    self.PenList[(LineColor,LineStyle,LineWidth)] = wx.Pen(LineColor,LineWidth,self.LineStyleList[LineStyle])
 | 
						|
                self.Pen = self.PenList[(LineColor,LineStyle,LineWidth)]
 | 
						|
 | 
						|
        def SetPens(self,LineColors,LineStyles,LineWidths):
 | 
						|
            """
 | 
						|
            This method used when an object could have a list of pens, rather than just one
 | 
						|
            It is used for LineSet, and perhaps others in the future.
 | 
						|
 | 
						|
            fixme: this is really kludgy, there has got to be a better way!
 | 
						|
            
 | 
						|
            """
 | 
						|
 | 
						|
            length = 1
 | 
						|
            if type(LineColors) == types.ListType:
 | 
						|
                length = len(LineColors)
 | 
						|
            else:
 | 
						|
                LineColors = [LineColors]
 | 
						|
 | 
						|
            if type(LineStyles) == types.ListType:
 | 
						|
                length = len(LineStyles)
 | 
						|
            else:
 | 
						|
                LineStyles = [LineStyles]
 | 
						|
 | 
						|
            if type(LineWidths) == types.ListType:
 | 
						|
                length = len(LineWidths)
 | 
						|
            else:
 | 
						|
                LineWidths = [LineWidths]
 | 
						|
 | 
						|
            if length > 1:
 | 
						|
                if len(LineColors) == 1:
 | 
						|
                    LineColors = LineColors*length
 | 
						|
                if len(LineStyles) == 1:
 | 
						|
                    LineStyles = LineStyles*length
 | 
						|
                if len(LineWidths) == 1:
 | 
						|
                    LineWidths = LineWidths*length
 | 
						|
 | 
						|
            self.Pens = []
 | 
						|
            for (LineColor,LineStyle,LineWidth) in zip(LineColors,LineStyles,LineWidths):
 | 
						|
                if LineColor is None or LineStyle is None:
 | 
						|
                    self.Pens.append(wx.TRANSPARENT_PEN)
 | 
						|
                    # what's this for?> self.LineStyle = 'Transparent'
 | 
						|
                if not self.PenList.has_key((LineColor,LineStyle,LineWidth)):
 | 
						|
                    Pen = wx.Pen(LineColor,LineWidth,self.LineStyleList[LineStyle])
 | 
						|
                    self.Pens.append(Pen)
 | 
						|
                else:
 | 
						|
                    self.Pens.append(self.PenList[(LineColor,LineStyle,LineWidth)])
 | 
						|
            if length == 1:
 | 
						|
                self.Pens = self.Pens[0]
 | 
						|
 | 
						|
        def PutInBackground(self):
 | 
						|
            if self._Canvas and self.Foreground:
 | 
						|
                self._Canvas._TopDrawList.remove(self)
 | 
						|
                self._Canvas._DrawList.append(self)
 | 
						|
                self._Canvas._BackgroundDirty = 1
 | 
						|
                self.Foreground = 0
 | 
						|
 | 
						|
        def PutInForeground(self):
 | 
						|
            if self._Canvas and (not self.Foreground):
 | 
						|
                self._Canvas._TopDrawList.append(self)
 | 
						|
                self._Canvas._DrawList.remove(self)
 | 
						|
                self._Canvas._BackgroundDirty = 1
 | 
						|
                self.Foreground = 1
 | 
						|
            
 | 
						|
        
 | 
						|
class Polygon(draw_object):
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    The Polygon class takes a list of 2-tuples, or a NX2 NumPy array of
 | 
						|
    point coordinates.  so that Points[N][0] is the x-coordinate of
 | 
						|
    point N and Points[N][1] is the y-coordinate or Points[N,0] is the
 | 
						|
    x-coordinate of point N and Points[N,1] is the y-coordinate for
 | 
						|
    arrays.
 | 
						|
 | 
						|
    """
 | 
						|
    def __init__(self,Points,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
        self.Points = array(Points,Float)
 | 
						|
        self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
        self.FillColor = FillColor
 | 
						|
        self.FillStyle = FillStyle
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
        self.SetBrush(FillColor,FillStyle)
 | 
						|
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        Points = WorldToPixel(self.Points)
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        dc.SetBrush(self.Brush)
 | 
						|
        #dc.DrawPolygon(map(lambda x: (x[0],x[1]), Points.tolist()))
 | 
						|
        dc.DrawPolygon(Points)
 | 
						|
 | 
						|
class PolygonSet(draw_object):
 | 
						|
    """
 | 
						|
    The PolygonSet class takes a Geometry.Polygon object.
 | 
						|
    so that Points[N] = (x1,y1) and Points[N+1] = (x2,y2). N must be an even number!
 | 
						|
    
 | 
						|
    it creates a set of line segments, from (x1,y1) to (x2,y2)
 | 
						|
    
 | 
						|
    """
 | 
						|
    
 | 
						|
    def __init__(self,PolySet,LineColors,LineStyles,LineWidths,FillColors,FillStyles,Foreground = 0):
 | 
						|
        draw_object.__init__(self, Foreground)
 | 
						|
 | 
						|
        ##fixme: there should be some error checking for everything being the right length.
 | 
						|
 | 
						|
        
 | 
						|
        self.Points = array(Points,Float)
 | 
						|
        self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
 | 
						|
        self.LineColors = LineColors
 | 
						|
        self.LineStyles = LineStyles
 | 
						|
        self.LineWidths = LineWidths
 | 
						|
        self.FillColors = FillColors
 | 
						|
        self.FillStyles = FillStyles
 | 
						|
 | 
						|
        self.SetPens(LineColors,LineStyles,LineWidths)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        Points = WorldToPixel(self.Points)
 | 
						|
        Points.shape = (-1,4)
 | 
						|
        dc.DrawLineList(Points,self.Pens)
 | 
						|
 
 | 
						|
 | 
						|
class Line(draw_object):
 | 
						|
    """
 | 
						|
    The Line class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
 | 
						|
    so that Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate
 | 
						|
    or  Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays.
 | 
						|
 | 
						|
    It will draw a straight line if there are two points, and a polyline if there are more than two.
 | 
						|
 | 
						|
    """
 | 
						|
    def __init__(self,Points,LineColor,LineStyle,LineWidth,Foreground = 0):
 | 
						|
        draw_object.__init__(self, Foreground)
 | 
						|
 | 
						|
        self.Points = array(Points,Float)
 | 
						|
        self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
 | 
						|
    def SetPoints(self,Points):
 | 
						|
        self.Points = Points
 | 
						|
        self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
        if self._Canvas:
 | 
						|
            # It looks like this shouldn't be private
 | 
						|
            self._Canvas.BoundingBoxDirty = 1
 | 
						|
            
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        Points = WorldToPixel(self.Points)
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        #dc.DrawLines(map(lambda x: (x[0],x[1]), Points.tolist()))
 | 
						|
        dc.DrawLines(Points)
 | 
						|
 | 
						|
 | 
						|
class LineSet(draw_object):
 | 
						|
    """
 | 
						|
    The LineSet class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
 | 
						|
    so that Points[N] = (x1,y1) and Points[N+1] = (x2,y2). N must be an even number!
 | 
						|
    
 | 
						|
    it creates a set of line segments, from (x1,y1) to (x2,y2)
 | 
						|
    
 | 
						|
    """
 | 
						|
    
 | 
						|
    def __init__(self,Points,LineColors,LineStyles,LineWidths,Foreground = 0):
 | 
						|
        draw_object.__init__(self, Foreground)
 | 
						|
 | 
						|
        NumLines = len(Points) / 2
 | 
						|
        ##fixme: there should be some error checking for everything being the right length.
 | 
						|
 | 
						|
        
 | 
						|
        self.Points = array(Points,Float)
 | 
						|
        self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
 | 
						|
        self.LineColors = LineColors
 | 
						|
        self.LineStyles = LineStyles
 | 
						|
        self.LineWidths = LineWidths
 | 
						|
 | 
						|
        self.SetPens(LineColors,LineStyles,LineWidths)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        Points = WorldToPixel(self.Points)
 | 
						|
        Points.shape = (-1,4)
 | 
						|
        dc.DrawLineList(Points,self.Pens)
 | 
						|
 
 | 
						|
 | 
						|
class PointSet(draw_object):
 | 
						|
        """
 | 
						|
        The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
 | 
						|
        so that Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate
 | 
						|
        or  Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays.
 | 
						|
        
 | 
						|
        Each point will be drawn the same color and Diameter. The Diameter is in screen points,
 | 
						|
        not world coordinates.
 | 
						|
        
 | 
						|
        """
 | 
						|
        def __init__(self,Points,Color,Diameter,Foreground = 0):
 | 
						|
            draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
            self.Points = array(Points,Float)
 | 
						|
            self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
 | 
						|
            self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
            
 | 
						|
            self.Color = Color
 | 
						|
            self.Diameter = Diameter
 | 
						|
            
 | 
						|
            self.SetPen(Color,"Solid",1)
 | 
						|
            self.SetBrush(Color,"Solid")
 | 
						|
 | 
						|
        def SetPoints(self,Points):
 | 
						|
            self.Points = Points
 | 
						|
            self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
 | 
						|
            if self._Canvas:
 | 
						|
                # It looks like this shouldn't be private
 | 
						|
                self._Canvas.BoundingBoxDirty = 1
 | 
						|
            
 | 
						|
        def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
            dc.SetPen(self.Pen)
 | 
						|
            Points = WorldToPixel(self.Points)
 | 
						|
            if self.Diameter <= 1:
 | 
						|
                dc.DrawPointList(Points)
 | 
						|
            elif self.Diameter <= 2:
 | 
						|
                # A Little optimization for a diameter2 - point
 | 
						|
                dc.DrawPointList(Points)
 | 
						|
                dc.DrawPointList(Points + (1,0))
 | 
						|
                dc.DrawPointList(Points + (0,1))
 | 
						|
                dc.DrawPointList(Points + (1,1))
 | 
						|
            else:
 | 
						|
                dc.SetBrush(self.Brush)
 | 
						|
                radius = int(round(self.Diameter/2))
 | 
						|
                for (x,y) in Points:
 | 
						|
                    dc.DrawEllipse((x - radius), (y - radius), self.Diameter, self.Diameter)
 | 
						|
 | 
						|
 | 
						|
                    
 | 
						|
class Dot(draw_object):
 | 
						|
    """
 | 
						|
    The Dot class takes an x.y coordinate pair, and the Diameter of the circle.
 | 
						|
    The Diameter is in pixels, so it won't change with zoom.
 | 
						|
 | 
						|
    Also Fill and line data
 | 
						|
 | 
						|
    """
 | 
						|
    def __init__(self,x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
        self.X = x
 | 
						|
        self.Y = y
 | 
						|
        self.Diameter = Diameter
 | 
						|
        # NOTE: the bounding box does not include the diameter of the dot, as that is in pixel coords.
 | 
						|
        # If this is  a problem, perhaps you should use a circle, instead!
 | 
						|
        self.BoundingBox = array(((x,y),(x,y)),Float)
 | 
						|
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
        self.FillColor = FillColor
 | 
						|
        self.FillStyle = FillStyle
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
        self.SetBrush(FillColor,FillStyle)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        dc.SetBrush(self.Brush)
 | 
						|
        radius = int(round(self.Diameter/2))
 | 
						|
        (X,Y) = WorldToPixel((self.X,self.Y))
 | 
						|
        dc.DrawEllipse((X - radius), (Y - radius), self.Diameter, self.Diameter)
 | 
						|
 | 
						|
 | 
						|
class Rectangle(draw_object):
 | 
						|
    def __init__(self,x,y,width,height,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
        self.X = x
 | 
						|
        self.Y = y
 | 
						|
        self.Width = width
 | 
						|
        self.Height = height
 | 
						|
        self.BoundingBox = array(((x,y),(x+width,y+height)),Float)
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
        self.FillColor = FillColor
 | 
						|
        self.FillStyle = FillStyle
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
        self.SetBrush(FillColor,FillStyle)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        (X,Y) = WorldToPixel((self.X,self.Y))
 | 
						|
        (Width,Height) = ScaleFunction((self.Width,self.Height))
 | 
						|
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        dc.SetBrush(self.Brush)
 | 
						|
        dc.DrawRectangle(X,Y, Width,Height)
 | 
						|
 | 
						|
class Ellipse(draw_object):
 | 
						|
    def __init__(self,x,y,width,height,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
        self.X = x
 | 
						|
        self.Y = y
 | 
						|
        self.Width = width
 | 
						|
        self.Height = height
 | 
						|
        self.BoundingBox = array(((x,y),(x+width,y+height)),Float)
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
        self.FillColor = FillColor
 | 
						|
        self.FillStyle = FillStyle
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
        self.SetBrush(FillColor,FillStyle)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        (X,Y) = WorldToPixel((self.X,self.Y))
 | 
						|
        (Width,Height) = ScaleFunction((self.Width,self.Height))
 | 
						|
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        dc.SetBrush(self.Brush)
 | 
						|
        dc.DrawEllipse(X,Y, Width,Height)
 | 
						|
 | 
						|
class Circle(draw_object):
 | 
						|
    def __init__(self,x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
        self.X = x
 | 
						|
        self.Y = y
 | 
						|
        self.Diameter = Diameter
 | 
						|
        self.BoundingBox = array(((x-Diameter/2,y-Diameter/2),(x+Diameter/2,y+Diameter/2)),Float)
 | 
						|
        self.LineColor = LineColor
 | 
						|
        self.LineStyle = LineStyle
 | 
						|
        self.LineWidth = LineWidth
 | 
						|
        self.FillColor = FillColor
 | 
						|
        self.FillStyle = FillStyle
 | 
						|
 | 
						|
        self.SetPen(LineColor,LineStyle,LineWidth)
 | 
						|
        self.SetBrush(FillColor,FillStyle)
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        (X,Y) = WorldToPixel((self.X,self.Y))
 | 
						|
        (Diameter,dummy) = ScaleFunction((self.Diameter,self.Diameter))
 | 
						|
 | 
						|
        dc.SetPen(self.Pen)
 | 
						|
        dc.SetBrush(self.Brush)
 | 
						|
        dc.DrawEllipse(X-Diameter/2,Y-Diameter/2, Diameter,Diameter)
 | 
						|
 | 
						|
class Text(draw_object):
 | 
						|
    """
 | 
						|
 | 
						|
    This class creates a text object, placed at the coordinates,
 | 
						|
    x,y. the "Position" argument is a two charactor string, indicating
 | 
						|
    where in relation to the coordinates the string should be oriented.
 | 
						|
 | 
						|
    The first letter is:  t, c, or b, for top, center and bottom
 | 
						|
    The second letter is: l, c, or r, for left, center and right
 | 
						|
 | 
						|
    I've provided arguments for Family, Style, and Weight of font, but
 | 
						|
    have not yet implimented them, so all text is:  wx.SWISS, wx.NORMAL, wx.NORMAL.
 | 
						|
    I'd love it if someone would impliment that!
 | 
						|
 | 
						|
    The size is fixed, and does not scale with the drawing.
 | 
						|
 | 
						|
    """
 | 
						|
    
 | 
						|
    def __init__(self,String,x,y,Size,ForeGround,BackGround,Family,Style,Weight,Underline,Position,Foreground = 0):
 | 
						|
        draw_object.__init__(self,Foreground)
 | 
						|
 | 
						|
        self.String = String
 | 
						|
        self.Size = Size
 | 
						|
 | 
						|
        self.ForeGround = ForeGround
 | 
						|
        if BackGround is None:
 | 
						|
            self.BackGround = None
 | 
						|
        else:
 | 
						|
            self.BackGround = BackGround
 | 
						|
        self.Family = Family
 | 
						|
        self.Style  = Style
 | 
						|
        self.Weight = Weight
 | 
						|
        self.Underline = Underline
 | 
						|
        self.Position = Position
 | 
						|
        # fixme: this should use the passed in parameters!
 | 
						|
        self.Font = wx.Font(Size, wx.MODERN, wx.NORMAL, wx.NORMAL, Underline, )
 | 
						|
 | 
						|
        self.BoundingBox = array(((x,y),(x,y)),Float)
 | 
						|
 | 
						|
        self.X = x
 | 
						|
        self.Y = y
 | 
						|
        self.x_shift = None
 | 
						|
        self.y_shift = None
 | 
						|
 | 
						|
    def _Draw(self,dc,WorldToPixel,ScaleFunction):
 | 
						|
        (X,Y) = WorldToPixel((self.X,self.Y))
 | 
						|
        dc.SetFont(self.Font)
 | 
						|
        dc.SetTextForeground(self.ForeGround)
 | 
						|
        if self.BackGround:
 | 
						|
            dc.SetBackgroundMode(wx.SOLID)
 | 
						|
            dc.SetTextBackground(self.BackGround)
 | 
						|
        else:
 | 
						|
            dc.SetBackgroundMode(wx.TRANSPARENT)
 | 
						|
 | 
						|
        # compute the shift, and adjust the coordinates, if neccesary
 | 
						|
        # This had to be put in here, becsuse there is no wx.DC during __init__
 | 
						|
        if self.x_shift is None or self.y_shift is None:
 | 
						|
            if self.Position == 'tl':
 | 
						|
                x_shift,y_shift = 0,0
 | 
						|
            else:
 | 
						|
                (w,h) = dc.GetTextExtent(self.String)
 | 
						|
                if self.Position[0] == 't':
 | 
						|
                    y_shift = 0
 | 
						|
                elif self.Position[0] == 'c':
 | 
						|
                    y_shift = h/2
 | 
						|
                elif self.Position[0] == 'b':
 | 
						|
                    y_shift = h
 | 
						|
                else:
 | 
						|
                    ##fixme: this should be a real derived exception
 | 
						|
                    raise "Invalid value for Text Object Position Attribute"
 | 
						|
                if self.Position[1] == 'l':
 | 
						|
                    x_shift = 0
 | 
						|
                elif self.Position[1] == 'c':
 | 
						|
                    x_shift = w/2
 | 
						|
                elif self.Position[1] == 'r':
 | 
						|
                    x_shift = w
 | 
						|
                else:
 | 
						|
                    ##fixme: this should be a real derived exception
 | 
						|
                    raise "Invalid value for Text Object Position Attribute"
 | 
						|
            self.x_shift = x_shift
 | 
						|
            self.y_shift = y_shift
 | 
						|
        dc.DrawText(self.String, X-self.x_shift, Y-self.y_shift)
 | 
						|
 | 
						|
 | 
						|
#---------------------------------------------------------------------------
 | 
						|
    
 | 
						|
class FloatCanvas(wx.Panel):
 | 
						|
    """
 | 
						|
    FloatCanvas.py
 | 
						|
 | 
						|
    This is a high level window for drawing maps and anything else in an
 | 
						|
    arbitrary coordinate system.
 | 
						|
 | 
						|
    The goal is to provide a convenient way to draw stuff on the screen
 | 
						|
    without having to deal with handling OnPaint events, converting to pixel
 | 
						|
    coordinates, knowing about wxWindows brushes, pens, and colors, etc. It
 | 
						|
    also provides virtually unlimited zooming and scrolling
 | 
						|
 | 
						|
    I am using it for two things:
 | 
						|
    1) general purpose drawing in floating point coordinates
 | 
						|
    2) displaying map data in Lat-long coordinates
 | 
						|
 | 
						|
    If the projection is set to None, it will draw in general purpose
 | 
						|
    floating point coordinates. If the projection is set to 'FlatEarth', it
 | 
						|
    will draw a FlatEarth projection, centered on the part of the map that
 | 
						|
    you are viewing. You can also pass in your own projection function.
 | 
						|
 | 
						|
    It is double buffered, so re-draws after the window is uncovered by something
 | 
						|
    else are very quick.
 | 
						|
 | 
						|
    It relies on NumPy, which is needed for speed
 | 
						|
 | 
						|
    Bugs and Limitations:
 | 
						|
        Lots: patches, fixes welcome
 | 
						|
 | 
						|
    For Map drawing: It ignores the fact that the world is, in fact, a
 | 
						|
    sphere, so it will do strange things if you are looking at stuff near
 | 
						|
    the poles or the date line. so far I don't have a need to do that, so I
 | 
						|
    havn't bothered to add any checks for that yet.
 | 
						|
 | 
						|
    Zooming:
 | 
						|
    I have set no zoom limits. What this means is that if you zoom in really 
 | 
						|
    far, you can get integer overflows, and get wierd results. It
 | 
						|
    doesn't seem to actually cause any problems other than wierd output, at
 | 
						|
    least when I have run it.
 | 
						|
 | 
						|
    Speed:
 | 
						|
    I have done a couple of things to improve speed in this app. The one
 | 
						|
    thing I have done is used NumPy Arrays to store the coordinates of the
 | 
						|
    points of the objects. This allowed me to use array oriented functions
 | 
						|
    when doing transformations, and should provide some speed improvement
 | 
						|
    for objects with a lot of points (big polygons, polylines, pointsets).
 | 
						|
 | 
						|
    The real slowdown comes when you have to draw a lot of objects, because
 | 
						|
    you have to call the wx.DC.DrawSomething call each time. This is plenty
 | 
						|
    fast for tens of objects, OK for hundreds of objects, but pretty darn
 | 
						|
    slow for thousands of objects.
 | 
						|
 | 
						|
    The solution is to be able to pass some sort of object set to the DC
 | 
						|
    directly. I've used DC.DrawPointList(Points), and it helped a lot with
 | 
						|
    drawing lots of points. I havn't got a LineSet type object, so I havn't
 | 
						|
    used DC.DrawLineList yet. I'd like to get a full set of DrawStuffList()
 | 
						|
    methods implimented, and then I'd also have a full set of Object sets
 | 
						|
    that could take advantage of them. I hope to get to it some day.
 | 
						|
 | 
						|
    Copyright: Christopher Barker
 | 
						|
 | 
						|
    License: Same as wxPython
 | 
						|
 | 
						|
    Please let me know if you're using this!!!
 | 
						|
 | 
						|
    Contact me at:
 | 
						|
 | 
						|
    Chris.Barker@noaa.gov
 | 
						|
 | 
						|
    """ 
 | 
						|
    
 | 
						|
    def __init__(self, parent, id = -1,
 | 
						|
                 size = wx.DefaultSize,
 | 
						|
                 ProjectionFun = None,
 | 
						|
                 BackgroundColor = "WHITE",
 | 
						|
                 Debug = 0,
 | 
						|
                 EnclosingFrame = None,
 | 
						|
                 UseToolbar = 1,
 | 
						|
                 UseBackground = 0,
 | 
						|
                 UseHitTest = 0):
 | 
						|
 | 
						|
        wx.Panel.__init__( self, parent, id, wx.DefaultPosition, size)
 | 
						|
 | 
						|
        if ProjectionFun == 'FlatEarth':
 | 
						|
            self.ProjectionFun = self.FlatEarthProjection 
 | 
						|
        elif type(ProjectionFun) == types.FunctionType:
 | 
						|
            self.ProjectionFun = ProjectionFun 
 | 
						|
        elif ProjectionFun is None:
 | 
						|
            self.ProjectionFun = lambda x=None: array( (1,1), Float)
 | 
						|
        else:
 | 
						|
            raise('Projectionfun must be either: "FlatEarth", None, or a function that takes the ViewPortCenter and returns a MapProjectionVector')
 | 
						|
 | 
						|
        self.UseBackground = UseBackground
 | 
						|
        self.UseHitTest = UseHitTest
 | 
						|
 | 
						|
        self.NumBetweenBlits = 40
 | 
						|
 | 
						|
        ## you can have a toolbar with buttons for zoom-in, zoom-out and
 | 
						|
        ## move.  If you don't use the toolbar, you should provide your
 | 
						|
        ## own way of navigating the canvas
 | 
						|
        if UseToolbar:
 | 
						|
            ## Create the vertical sizer for the toolbar and Panel
 | 
						|
            box = wx.BoxSizer(wx.VERTICAL)
 | 
						|
            box.Add(self.BuildToolbar(), 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)
 | 
						|
            
 | 
						|
            self.DrawPanel = wx.Window(self,-1,wx.DefaultPosition,wx.DefaultSize,wx.SUNKEN_BORDER)
 | 
						|
            box.Add(self.DrawPanel,1,wx.GROW)
 | 
						|
            
 | 
						|
            box.Fit(self)
 | 
						|
            self.SetAutoLayout(True)
 | 
						|
            self.SetSizer(box)
 | 
						|
        else:
 | 
						|
            self.DrawPanel = self
 | 
						|
 | 
						|
        self.DrawPanel.BackgroundBrush = wx.Brush(BackgroundColor,wx.SOLID)
 | 
						|
 | 
						|
        self.Debug = Debug
 | 
						|
 | 
						|
        self.EnclosingFrame = EnclosingFrame
 | 
						|
        
 | 
						|
        wx.EVT_PAINT(self.DrawPanel, self.OnPaint)
 | 
						|
        wx.EVT_SIZE(self.DrawPanel, self.OnSize)
 | 
						|
        
 | 
						|
        wx.EVT_LEFT_DOWN(self.DrawPanel, self.LeftButtonEvent)
 | 
						|
        wx.EVT_LEFT_UP(self.DrawPanel, self.LeftButtonEvent)
 | 
						|
        wx.EVT_RIGHT_DOWN(self.DrawPanel, self.RightButtonEvent)
 | 
						|
        wx.EVT_MOTION(self.DrawPanel,    self.LeftButtonEvent)
 | 
						|
        
 | 
						|
        
 | 
						|
        self._DrawList = []
 | 
						|
        if self.UseBackground:
 | 
						|
            self._TopDrawList = []
 | 
						|
        self.BoundingBox = None
 | 
						|
        self.BoundingBoxDirty = 0
 | 
						|
        self.ViewPortCenter= array( (0,0), Float)
 | 
						|
        
 | 
						|
        self.MapProjectionVector = array( (1,1), Float) # No Projection to start!
 | 
						|
        self.TransformVector = array( (1,-1), Float) # default Transformation
 | 
						|
        
 | 
						|
        self.Scale = 1
 | 
						|
 | 
						|
        self.GUIMode = None
 | 
						|
        self.StartRBBox = None
 | 
						|
        self.PrevRBBox = None
 | 
						|
        self.StartMove = None
 | 
						|
        self.PrevMoveBox = None
 | 
						|
        # called just to make sure everything is initialized
 | 
						|
        if wx.Platform != "__WXMAC__":
 | 
						|
        	self.OnSize(None)
 | 
						|
 | 
						|
        
 | 
						|
    def BuildToolbar(self):
 | 
						|
        tb = wx.ToolBar(self,-1)
 | 
						|
        self.ToolBar = tb
 | 
						|
        
 | 
						|
        tb.SetToolBitmapSize((23,23))
 | 
						|
        
 | 
						|
        tb.AddTool(ID_ZOOM_IN_BUTTON, GetPlusBitmap(), isToggle=True,shortHelpString = "Zoom In")
 | 
						|
        wx.EVT_TOOL(self, ID_ZOOM_IN_BUTTON, self.SetMode)
 | 
						|
        
 | 
						|
        tb.AddTool(ID_ZOOM_OUT_BUTTON, GetMinusBitmap(), isToggle=True,shortHelpString = "Zoom Out")
 | 
						|
        wx.EVT_TOOL(self, ID_ZOOM_OUT_BUTTON, self.SetMode)
 | 
						|
        
 | 
						|
        tb.AddTool(ID_MOVE_MODE_BUTTON, GetHandBitmap(), isToggle=True,shortHelpString = "Move")
 | 
						|
        wx.EVT_TOOL(self, ID_MOVE_MODE_BUTTON, self.SetMode)
 | 
						|
        
 | 
						|
        tb.AddSeparator()
 | 
						|
        
 | 
						|
        tb.AddControl(wx.Button(tb, ID_ZOOM_TO_FIT_BUTTON, "Zoom To Fit",wx.DefaultPosition, wx.DefaultSize))
 | 
						|
        wx.EVT_BUTTON(self, ID_ZOOM_TO_FIT_BUTTON, self.ZoomToFit)
 | 
						|
 | 
						|
        tb.Realize()
 | 
						|
        return tb
 | 
						|
 | 
						|
    def SetMode(self,event):
 | 
						|
        for id in [ID_ZOOM_IN_BUTTON,ID_ZOOM_OUT_BUTTON,ID_MOVE_MODE_BUTTON]:
 | 
						|
            self.ToolBar.ToggleTool(id,0)
 | 
						|
        self.ToolBar.ToggleTool(event.GetId(),1)
 | 
						|
        if event.GetId() == ID_ZOOM_IN_BUTTON:
 | 
						|
            self.SetGUIMode("ZoomIn")
 | 
						|
        elif event.GetId() == ID_ZOOM_OUT_BUTTON:
 | 
						|
            self.SetGUIMode("ZoomOut")
 | 
						|
        elif event.GetId() == ID_MOVE_MODE_BUTTON:
 | 
						|
            self.SetGUIMode("Move")
 | 
						|
 | 
						|
    
 | 
						|
    def SetGUIMode(self,Mode):
 | 
						|
        if Mode in ["ZoomIn","ZoomOut","Move",None]:
 | 
						|
            self.GUIMode = Mode
 | 
						|
        else:
 | 
						|
            raise "Not a valid Mode"
 | 
						|
            
 | 
						|
    def FlatEarthProjection(self,CenterPoint):
 | 
						|
        return array((cos(pi*CenterPoint[1]/180),1),Float)
 | 
						|
        
 | 
						|
    def LeftButtonEvent(self,event):
 | 
						|
        if self.EnclosingFrame:
 | 
						|
            if event.Moving:
 | 
						|
                position = self.PixelToWorld((event.GetX(),event.GetY()))
 | 
						|
                self.EnclosingFrame.SetStatusText("%8.3f, %8.3f"%tuple(position))
 | 
						|
        if self.GUIMode:
 | 
						|
            if self.GUIMode == "ZoomIn":
 | 
						|
                if event.LeftDown():
 | 
						|
                    self.StartRBBox = (event.GetX(),event.GetY())
 | 
						|
                    self.PrevRBBox = None
 | 
						|
                elif event.Dragging() and event.LeftIsDown() and self.StartRBBox:
 | 
						|
                    x0,y0 = self.StartRBBox
 | 
						|
                    x1,y1 = event.GetX(),event.GetY()
 | 
						|
                    w, h = abs(x1-x0),abs(y1-y0)
 | 
						|
                    w = max(w,int(h*self.AspectRatio))
 | 
						|
                    h = int(w/self.AspectRatio)
 | 
						|
                    x_c, y_c = (x0+x1)/2 , (y0+y1)/2
 | 
						|
                    dc = wx.ClientDC(self.DrawPanel)
 | 
						|
                    dc.BeginDrawing()
 | 
						|
                    dc.SetPen(wx.Pen('WHITE', 2,wx.SHORT_DASH))
 | 
						|
                    dc.SetBrush(wx.TRANSPARENT_BRUSH)
 | 
						|
                    dc.SetLogicalFunction(wx.XOR)
 | 
						|
                    if self.PrevRBBox:
 | 
						|
                        dc.DrawRectangle(*self.PrevRBBox)
 | 
						|
                    dc.DrawRectangle(x_c-w/2,y_c-h/2,w,h)
 | 
						|
                    self.PrevRBBox = (x_c-w/2,y_c-h/2,w,h)
 | 
						|
                    dc.EndDrawing()
 | 
						|
                    
 | 
						|
                elif event.LeftUp() and self.StartRBBox :
 | 
						|
                    self.PrevRBBox = None
 | 
						|
                    EndRBBox = (event.GetX(),event.GetY())
 | 
						|
                    StartRBBox = self.StartRBBox
 | 
						|
                    # if mouse has moved less that ten pixels, don't use the box.
 | 
						|
                    if abs(StartRBBox[0] - EndRBBox[0]) > 10 and abs(StartRBBox[1] - EndRBBox[1]) > 10:
 | 
						|
                        EndRBBox = self.PixelToWorld(EndRBBox)
 | 
						|
                        StartRBBox = self.PixelToWorld(StartRBBox)
 | 
						|
                        BB = array(((min(EndRBBox[0],StartRBBox[0]), min(EndRBBox[1],StartRBBox[1])),
 | 
						|
                                    (max(EndRBBox[0],StartRBBox[0]), max(EndRBBox[1],StartRBBox[1]))),Float)
 | 
						|
                        self.ZoomToBB(BB)
 | 
						|
                    else:
 | 
						|
                        Center = self.PixelToWorld(StartRBBox)
 | 
						|
                        self.Zoom(1.5,Center)
 | 
						|
                    self.StartRBBox = None
 | 
						|
                    
 | 
						|
            if self.GUIMode == "ZoomOut":
 | 
						|
                if event.LeftDown():
 | 
						|
                    Center = self.PixelToWorld((event.GetX(),event.GetY()))
 | 
						|
                    self.Zoom(1/1.5,Center)
 | 
						|
            elif self.GUIMode == "Move":
 | 
						|
                if event.LeftDown():
 | 
						|
                    self.StartMove = array((event.GetX(),event.GetY()))
 | 
						|
                    self.PrevMoveBox = None
 | 
						|
                elif event.Dragging() and event.LeftIsDown() and self.StartMove:
 | 
						|
                    x_1,y_1 = event.GetX(),event.GetY()
 | 
						|
                    w, h = self.PanelSize
 | 
						|
                    x_tl, y_tl = x_1 - self.StartMove[0], y_1 - self.StartMove[1]
 | 
						|
                    dc = wx.ClientDC(self.DrawPanel)
 | 
						|
                    dc.BeginDrawing()
 | 
						|
                    dc.SetPen(wx.Pen('WHITE', 1,))
 | 
						|
                    dc.SetBrush(wx.TRANSPARENT_BRUSH)
 | 
						|
                    dc.SetLogicalFunction(wx.XOR)
 | 
						|
                    if self.PrevMoveBox:
 | 
						|
                        dc.DrawRectangle(*self.PrevMoveBox)
 | 
						|
                    dc.DrawRectangle(x_tl,y_tl,w,h)
 | 
						|
                    self.PrevMoveBox = (x_tl,y_tl,w,h)
 | 
						|
                    dc.EndDrawing()
 | 
						|
                  
 | 
						|
                elif event.LeftUp() and self.StartMove:
 | 
						|
                    self.PrevMoveBox = None
 | 
						|
                    StartMove = self.StartMove
 | 
						|
                    EndMove = array((event.GetX(),event.GetY()))
 | 
						|
                    if sum((StartMove-EndMove)**2) > 16:
 | 
						|
                        self.Move(StartMove-EndMove,'Pixel')
 | 
						|
                    self.StartMove = None
 | 
						|
                    
 | 
						|
    def RightButtonEvent(self,event):
 | 
						|
        if self.GUIMode:
 | 
						|
            if self.GUIMode == "ZoomIn":
 | 
						|
                Center = self.PixelToWorld((event.GetX(),event.GetY()))
 | 
						|
                self.Zoom(1/1.5,Center)
 | 
						|
            elif self.GUIMode == "ZoomOut":
 | 
						|
                Center = self.PixelToWorld((event.GetX(),event.GetY()))
 | 
						|
                self.Zoom(1.5,Center)
 | 
						|
            else:
 | 
						|
                event.Skip()
 | 
						|
        event.Skip()
 | 
						|
                
 | 
						|
    def MakeNewBuffers(self):
 | 
						|
        # Make new offscreen bitmap:
 | 
						|
        self._Buffer = wx.EmptyBitmap(self.PanelSize[0],self.PanelSize[1])
 | 
						|
        if self.UseBackground:
 | 
						|
            self._BackBuffer = wx.EmptyBitmap(self.PanelSize[0],self.PanelSize[1])
 | 
						|
            self._BackgroundDirty = 1
 | 
						|
        else:
 | 
						|
            pass
 | 
						|
                
 | 
						|
    def OnSize(self,event):
 | 
						|
        self.PanelSize  = array(self.DrawPanel.GetClientSizeTuple(),Int32)
 | 
						|
        try:
 | 
						|
            self.AspectRatio = self.PanelSize[0]/self.PanelSize[1]
 | 
						|
        except ZeroDivisionError:
 | 
						|
            self.AspectRatio = 1.0
 | 
						|
        self.MakeNewBuffers()
 | 
						|
        self.Draw()
 | 
						|
        
 | 
						|
    def OnPaint(self, event):
 | 
						|
        #dc = wx.BufferedPaintDC(self.DrawPanel, self._Buffer)
 | 
						|
        dc = wx.PaintDC(self.DrawPanel)
 | 
						|
        dc.DrawBitmap(self._Buffer, 0,0)
 | 
						|
 | 
						|
    def Draw(self):
 | 
						|
        """
 | 
						|
        The Draw method gets pretty complicated because of all the buffers
 | 
						|
 | 
						|
        There is a main buffer set up to double buffer the screen, so
 | 
						|
        you can get quick re-draws when the window gets uncovered.
 | 
						|
 | 
						|
        If self.UseBackground is set, and an object is set up with the
 | 
						|
        "ForeGround" flag, then it gets drawn to the screen after blitting
 | 
						|
        the background. This is done so that you can have a complicated
 | 
						|
        background, but have something changing on the foreground,
 | 
						|
        without having to wait for the background to get re-drawn. This
 | 
						|
        can be used to support simple animation, for instance.
 | 
						|
        
 | 
						|
        """
 | 
						|
        if self.Debug: start = clock()
 | 
						|
        ScreenDC =  wx.ClientDC(self.DrawPanel)
 | 
						|
        ViewPortWorld = ( self.PixelToWorld((0,0)), self.PixelToWorld(self.PanelSize) )
 | 
						|
        ViewPortBB = array( ( minimum.reduce(ViewPortWorld), maximum.reduce(ViewPortWorld) ) )
 | 
						|
        if self.UseBackground:
 | 
						|
            dc = wx.MemoryDC()
 | 
						|
            dc.SelectObject(self._BackBuffer)
 | 
						|
            dc.SetBackground(self.DrawPanel.BackgroundBrush)
 | 
						|
            if self._DrawList:
 | 
						|
                if  self._BackgroundDirty:
 | 
						|
                    dc.BeginDrawing()
 | 
						|
                    dc.Clear()
 | 
						|
                    i = 0
 | 
						|
                    for Object in self._DrawList:
 | 
						|
                        if self.BBCheck(Object.BoundingBox,ViewPortBB):
 | 
						|
                            #print "object is in Bounding Box"
 | 
						|
                            i+=1
 | 
						|
                            Object._Draw(dc,self.WorldToPixel,self.ScaleFunction)
 | 
						|
                            if i % self.NumBetweenBlits == 0:
 | 
						|
                                w,h = self.PanelSize
 | 
						|
                                ScreenDC.Blit(0, 0, w,h, dc, 0, 0)
 | 
						|
                    dc.EndDrawing()
 | 
						|
            else:
 | 
						|
                dc.Clear()
 | 
						|
            self._BackgroundDirty = 0
 | 
						|
            dc.SelectObject(self._Buffer)
 | 
						|
            dc.BeginDrawing()
 | 
						|
            ##Draw Background on Main Buffer:
 | 
						|
            dc.DrawBitmap(self._BackBuffer,0,0)
 | 
						|
            #Draw the OnTop stuff
 | 
						|
            i = 0
 | 
						|
            for Object in self._TopDrawList:
 | 
						|
                i+=1
 | 
						|
                Object._Draw(dc,self.WorldToPixel,self.ScaleFunction)
 | 
						|
                if i % self.NumBetweenBlits == 0:
 | 
						|
                    w, h = self.PanelSize
 | 
						|
                    ScreenDC.Blit(0, 0, w,h, dc, 0, 0)
 | 
						|
            dc.EndDrawing()
 | 
						|
        else: # not using a Background DC
 | 
						|
            dc = wx.MemoryDC()
 | 
						|
            dc.SelectObject(self._Buffer)
 | 
						|
            dc.SetBackground(self.DrawPanel.BackgroundBrush)
 | 
						|
            if self._DrawList:
 | 
						|
                dc.BeginDrawing()
 | 
						|
                dc.Clear()
 | 
						|
                i = 0
 | 
						|
                for Object in self._DrawList:
 | 
						|
                    if self.BBCheck(Object.BoundingBox,ViewPortBB):
 | 
						|
                        #print "object is in Bounding Box"
 | 
						|
                        i+=1
 | 
						|
                        Object._Draw(dc,self.WorldToPixel,self.ScaleFunction)
 | 
						|
                        if i % self.NumBetweenBlits == 0:
 | 
						|
                            w, h = self.PanelSize
 | 
						|
                            ScreenDC.Blit(0, 0, w, h, dc, 0, 0)
 | 
						|
                dc.EndDrawing()
 | 
						|
            else:
 | 
						|
                dc.Clear()
 | 
						|
        # now refresh the screen
 | 
						|
        #ScreenDC.DrawBitmap(self._Buffer,0,0) #NOTE: uisng DrawBitmap didn't work right on MSW
 | 
						|
        w, h = self.PanelSize
 | 
						|
        ScreenDC.Blit(0, 0, w, h, dc, 0, 0)
 | 
						|
 | 
						|
        # If the canvas is in the middle of a zoom or move, the Rubber Band box needs to be re-drawn
 | 
						|
        if self.PrevRBBox:
 | 
						|
            ScreenDC.SetPen(wx.Pen('WHITE', 2,wx.SHORT_DASH))
 | 
						|
            ScreenDC.SetBrush(wx.TRANSPARENT_BRUSH)
 | 
						|
            ScreenDC.SetLogicalFunction(wx.XOR)
 | 
						|
            ScreenDC.DrawRectangle(*self.PrevRBBox)
 | 
						|
        elif self.PrevMoveBox:
 | 
						|
            ScreenDC.SetPen(wx.Pen('WHITE', 1,))
 | 
						|
            ScreenDC.SetBrush(wx.TRANSPARENT_BRUSH)
 | 
						|
            ScreenDC.SetLogicalFunction(wx.XOR)
 | 
						|
            ScreenDC.DrawRectangle(*self.PrevMoveBox)
 | 
						|
        if self.Debug: print "Drawing took %f seconds of CPU time"%(clock()-start)
 | 
						|
 | 
						|
    def BBCheck(self, BB1, BB2):
 | 
						|
        """
 | 
						|
 | 
						|
        BBCheck(BB1, BB2) returns True is the Bounding boxes intesect, False otherwise
 | 
						|
 | 
						|
        """
 | 
						|
        if ( (BB1[1,0] > BB2[0,0]) and (BB1[0,0] < BB2[1,0]) and
 | 
						|
             (BB1[1,1] > BB2[0,1]) and (BB1[0,1] < BB2[1,1]) ):
 | 
						|
            return True
 | 
						|
        else:
 | 
						|
            return False
 | 
						|
 | 
						|
    def Move(self,shift,CoordType):
 | 
						|
        """
 | 
						|
        move the image in the window.
 | 
						|
 | 
						|
        shift is an (x,y) tuple, specifying the amount to shift in each direction
 | 
						|
 | 
						|
        It can be in any of three coordinates: Panel, Pixel, World,
 | 
						|
        specified by the CoordType parameter
 | 
						|
 | 
						|
        Panel coordinates means you want to shift the image by some
 | 
						|
        fraction of the size of the displaed image
 | 
						|
 | 
						|
        Pixel coordinates means you want to shift the image by some number of pixels
 | 
						|
 | 
						|
        World coordinates meand you want to shift the image by an amount
 | 
						|
        in Floating point world coordinates
 | 
						|
 | 
						|
        """
 | 
						|
        
 | 
						|
        shift = array(shift,Float)
 | 
						|
        if CoordType == 'Panel':# convert from panel coordinates
 | 
						|
            shift = shift * array((-1,1),Float) *self.PanelSize/self.TransformVector
 | 
						|
        elif CoordType == 'Pixel': # convert from pixel coordinates
 | 
						|
            shift = shift/self.TransformVector
 | 
						|
        elif CoordType == 'World': # No conversion
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            raise 'CoordType must be either "Panel", "Pixel", or "World"'
 | 
						|
            
 | 
						|
        self.ViewPortCenter = self.ViewPortCenter + shift 
 | 
						|
        self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
 | 
						|
        self.TransformVector = array((self.Scale,-self.Scale),Float)* self.MapProjectionVector
 | 
						|
        self._BackgroundDirty = 1
 | 
						|
        self.Draw()
 | 
						|
        
 | 
						|
    def Zoom(self,factor,center = None):
 | 
						|
    
 | 
						|
        """
 | 
						|
        Zoom(factor, center) changes the amount of zoom of the image by factor.
 | 
						|
        If factor is greater than one, the image gets larger.
 | 
						|
        If factor is less than one, the image gets smaller.
 | 
						|
        
 | 
						|
        Center is a tuple of (x,y) coordinates of the center of the viewport, after zooming.
 | 
						|
        If center is not given, the center will stay the same.
 | 
						|
        
 | 
						|
        """
 | 
						|
        self.Scale = self.Scale*factor
 | 
						|
        if center:
 | 
						|
            self.ViewPortCenter = array(center,Float)
 | 
						|
        self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
 | 
						|
        self.TransformVector = array((self.Scale,-self.Scale),Float)* self.MapProjectionVector
 | 
						|
        self._BackgroundDirty = 1
 | 
						|
        self.Draw()
 | 
						|
        
 | 
						|
    def ZoomToFit(self,event):
 | 
						|
        self.ZoomToBB()
 | 
						|
        
 | 
						|
    def ZoomToBB(self,NewBB = None,DrawFlag = 1):
 | 
						|
 | 
						|
        """
 | 
						|
 | 
						|
        Zooms the image to the bounding box given, or to the bounding
 | 
						|
        box of all the objects on the canvas, if none is given.
 | 
						|
 | 
						|
        """
 | 
						|
        
 | 
						|
        if NewBB:
 | 
						|
            BoundingBox = NewBB
 | 
						|
        else:
 | 
						|
            if self.BoundingBoxDirty:
 | 
						|
                self._ResetBoundingBox()
 | 
						|
            BoundingBox = self.BoundingBox
 | 
						|
        if BoundingBox:
 | 
						|
            self.ViewPortCenter = array(((BoundingBox[0,0]+BoundingBox[1,0])/2,
 | 
						|
                                                                     (BoundingBox[0,1]+BoundingBox[1,1])/2 ),Float)
 | 
						|
            self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter)
 | 
						|
            # Compute the new Scale
 | 
						|
            BoundingBox = BoundingBox * self.MapProjectionVector
 | 
						|
            try:
 | 
						|
                self.Scale = min((self.PanelSize[0]  / (BoundingBox[1,0]-BoundingBox[0,0])),
 | 
						|
                                        (self.PanelSize[1] / (BoundingBox[1,1]-BoundingBox[0,1])))*0.95
 | 
						|
            except ZeroDivisionError: # this will happen if the BB has zero width or height
 | 
						|
                try: #width
 | 
						|
                    self.Scale = (self.PanelSize[0]  / (BoundingBox[1,0]-BoundingBox[0,0]))*0.95
 | 
						|
                except ZeroDivisionError:
 | 
						|
                    try: # height
 | 
						|
                        self.Scale = (self.PanelSize[1]  / (BoundingBox[1,1]-BoundingBox[0,1]))*0.95
 | 
						|
                    except ZeroDivisionError: #zero size! (must be a single point)
 | 
						|
                        self.Scale = 1
 | 
						|
                        
 | 
						|
            self.TransformVector = array((self.Scale,-self.Scale),Float)* self.MapProjectionVector
 | 
						|
            if DrawFlag:
 | 
						|
                self._BackgroundDirty = 1
 | 
						|
                self.Draw()
 | 
						|
                
 | 
						|
    def RemoveObjects(self,Objects):
 | 
						|
        for Object in Objects:
 | 
						|
            self.RemoveObject(Object,ResetBB = 0)
 | 
						|
        self.BoundingBoxDirty = 1
 | 
						|
        
 | 
						|
    def RemoveObject(self,Object,ResetBB = 1):
 | 
						|
        if Object.Foreground:
 | 
						|
            self._TopDrawList.remove(Object)
 | 
						|
        else:
 | 
						|
            self._DrawList.remove(Object)
 | 
						|
            self._BackgroundDirty = 1
 | 
						|
 | 
						|
        if ResetBB:
 | 
						|
            self.BoundingBoxDirty = 1
 | 
						|
 | 
						|
    def Clear(self, ResetBB = True):
 | 
						|
        self._DrawList = []
 | 
						|
        if self.UseBackground:
 | 
						|
            self._TopDrawList = []
 | 
						|
            self._BackgroundDirty = 1
 | 
						|
        if ResetBB:
 | 
						|
            self._ResetBoundingBox()
 | 
						|
 | 
						|
    def _AddBoundingBox(self,NewBB):
 | 
						|
        if self.BoundingBox is None:
 | 
						|
            self.BoundingBox = NewBB
 | 
						|
            self.ZoomToBB(NewBB,DrawFlag = 0)
 | 
						|
        else:
 | 
						|
            self.BoundingBox = array(((min(self.BoundingBox[0,0],NewBB[0,0]),
 | 
						|
                                       min(self.BoundingBox[0,1],NewBB[0,1])),
 | 
						|
                                      (max(self.BoundingBox[1,0],NewBB[1,0]),
 | 
						|
                                       max(self.BoundingBox[1,1],NewBB[1,1]))),Float)
 | 
						|
    def _ResetBoundingBox(self):
 | 
						|
        # NOTE: could you remove an item without recomputing the entire bounding box?
 | 
						|
        self.BoundingBox = None
 | 
						|
        if self._DrawList:
 | 
						|
            self.BoundingBox = self._DrawList[0].BoundingBox
 | 
						|
        for Object in self._DrawList[1:]:
 | 
						|
            self._AddBoundingBox(Object.BoundingBox)
 | 
						|
        if self.UseBackground:
 | 
						|
            for Object in self._TopDrawList:
 | 
						|
                self._AddBoundingBox(Object.BoundingBox)
 | 
						|
        if self.BoundingBox is None:
 | 
						|
            self.ViewPortCenter= array( (0,0), Float)
 | 
						|
            self.TransformVector = array( (1,-1), Float)
 | 
						|
            self.MapProjectionVector = array( (1,1), Float)			
 | 
						|
            self.Scale = 1
 | 
						|
        self.BoundingBoxDirty = 0
 | 
						|
 | 
						|
    def PixelToWorld(self,Points):
 | 
						|
        """
 | 
						|
        Converts coordinates from Pixel coordinates to world coordinates.
 | 
						|
        
 | 
						|
        Points is a tuple of (x,y) coordinates, or a list of such tuples, or a NX2 Numpy array of x,y coordinates.
 | 
						|
        
 | 
						|
        """
 | 
						|
        return  (((array(Points,Float) - (self.PanelSize/2))/self.TransformVector) + self.ViewPortCenter)
 | 
						|
        
 | 
						|
    def WorldToPixel(self,Coordinates):
 | 
						|
        """
 | 
						|
        This function will get passed to the drawing functions of the objects,
 | 
						|
        to transform from world to pixel coordinates.
 | 
						|
        Coordinates should be a NX2 array of (x,y) coordinates, or
 | 
						|
        a 2-tuple, or sequence of 2-tuples.
 | 
						|
        """
 | 
						|
        return  (((array(Coordinates,Float) - self.ViewPortCenter)*self.TransformVector)+(self.PanelSize/2)).astype('i')
 | 
						|
        
 | 
						|
    def ScaleFunction(self,Lengths):
 | 
						|
        """
 | 
						|
        This function will get passed to the drawing functions of the objects,
 | 
						|
        to Change a length from world to pixel coordinates.
 | 
						|
        
 | 
						|
        Lengths should be a NX2 array of (x,y) coordinates, or
 | 
						|
        a 2-tuple, or sequence of 2-tuples.
 | 
						|
        """
 | 
						|
        return  (array(Lengths,Float)*self.TransformVector).astype('i')
 | 
						|
        
 | 
						|
            
 | 
						|
    ## This is a set of methods that add objects to the Canvas. It kind
 | 
						|
    ## of seems like a lot of duplication, but I wanted to be able to
 | 
						|
    ## instantiate the draw objects separatley form adding them, but
 | 
						|
    ## also to be able to do add one oin one step. I'm open to better
 | 
						|
    ## ideas...
 | 
						|
    def AddRectangle(self,x,y,width,height,
 | 
						|
                                     LineColor = "Black",
 | 
						|
                                     LineStyle = "Solid",
 | 
						|
                                     LineWidth    = 1,
 | 
						|
                                     FillColor    = None,
 | 
						|
                                     FillStyle    = "Solid",
 | 
						|
                                     Foreground = 0):
 | 
						|
        Object = Rectangle(x,y,width,height,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddEllipse(self,x,y,width,height,
 | 
						|
                                     LineColor = "Black",
 | 
						|
                                     LineStyle = "Solid",
 | 
						|
                                     LineWidth    = 1,
 | 
						|
                                     FillColor    = None,
 | 
						|
                                     FillStyle    = "Solid",
 | 
						|
                                     Foreground = 0):
 | 
						|
        Object = Ellipse(x,y,width,height,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddCircle(self,x,y,Diameter,
 | 
						|
                                     LineColor = "Black",
 | 
						|
                                     LineStyle = "Solid",
 | 
						|
                                     LineWidth    = 1,
 | 
						|
                                     FillColor    = None,
 | 
						|
                                     FillStyle    = "Solid",
 | 
						|
                                     Foreground = 0):
 | 
						|
        Object = Circle(x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddDot(self,x,y,Diameter,
 | 
						|
                                     LineColor = "Black",
 | 
						|
                                     LineStyle = "Solid",
 | 
						|
                                     LineWidth    = 1,
 | 
						|
                                     FillColor    = None,
 | 
						|
                                     FillStyle    = "Solid",
 | 
						|
                                     Foreground = 0):
 | 
						|
        Object = Dot(x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddPolygon(self,Points,
 | 
						|
                               LineColor = "Black",
 | 
						|
                               LineStyle = "Solid",
 | 
						|
                               LineWidth    = 1,
 | 
						|
                               FillColor    = None,
 | 
						|
                               FillStyle    = "Solid",
 | 
						|
                                     Foreground = 0):
 | 
						|
    
 | 
						|
        Object = Polygon(Points,LineColor,LineStyle,LineWidth,FillColor,FillStyle,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddLine(self,Points,
 | 
						|
                            LineColor = "Black",
 | 
						|
                            LineStyle = "Solid",
 | 
						|
                            LineWidth    = 1,
 | 
						|
                                     Foreground = 0):
 | 
						|
    
 | 
						|
        Object = Line(Points,LineColor,LineStyle,LineWidth,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
 | 
						|
    def AddLineSet(self,Points,
 | 
						|
                   LineColors = "Black",
 | 
						|
                   LineStyles = "Solid",
 | 
						|
                   LineWidths = 1,
 | 
						|
                   Foreground = 0):
 | 
						|
    
 | 
						|
        Object = LineSet(Points,LineColors,LineStyles,LineWidths,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
 | 
						|
    def AddPointSet(self,Points,
 | 
						|
                                    Color = "Black",
 | 
						|
                                    Diameter = 1,
 | 
						|
                                     Foreground = 0):
 | 
						|
        
 | 
						|
        Object = PointSet(Points,Color,Diameter,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddText(self,String,x,y,
 | 
						|
                            Size = 20,
 | 
						|
                            ForeGround = 'Black',
 | 
						|
                            BackGround = None,
 | 
						|
                            Family = 'Swiss',
 | 
						|
                            Style = 'Normal',
 | 
						|
                            Weight = 'Normal',
 | 
						|
                            Underline = 0,
 | 
						|
                            Position = 'tl',
 | 
						|
                                     Foreground = 0):
 | 
						|
        Object = Text(String,x,y,Size,ForeGround,BackGround,Family,Style,Weight,Underline,Position,Foreground)
 | 
						|
        self.AddObject(Object)
 | 
						|
        return Object
 | 
						|
        
 | 
						|
    def AddObject(self,obj):
 | 
						|
        # put in a reference to the Canvas, so remove and other stuff can work
 | 
						|
        obj._Canvas = self
 | 
						|
        if  obj.Foreground and self.UseBackground:
 | 
						|
            self._TopDrawList.append(obj)
 | 
						|
        else:
 | 
						|
            self._DrawList.append(obj)
 | 
						|
            self._backgrounddirty = 1
 | 
						|
        self._AddBoundingBox(obj.BoundingBox)
 | 
						|
        return None
 | 
						|
        
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |