Updated FloatCanvas code from Chris

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@45725 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2007-05-01 05:55:19 +00:00
parent 94356f539a
commit 3f4ec51e47
9 changed files with 2359 additions and 1186 deletions

View File

@@ -1,27 +1,18 @@
#!/usr/bin/env python
#print "running:", wx.__version__
##First, make sure Numeric or numarray can be imported.
try: try:
import Numeric import numpy as N
import RandomArray import numpy.random as RandomArray
haveNumeric = True haveNumpy = True
#print "Using numpy, version:", N.__version__
except ImportError: except ImportError:
# Numeric isn't there, let's try numarray # numpy isn't there
try: haveNumpy = False
import numarray as Numeric errorText = (
import numarray.random_array as RandomArray "The FloatCanvas requires the numpy module, version 1.* \n\n"
haveNumeric = True "You can get info about it at:\n"
except ImportError: "http://numpy.scipy.org/\n\n"
# numarray isn't there either )
haveNumeric = False
errorText = (
"The FloatCanvas requires either the Numeric or numarray module\n\n"
"You can get them at:\n"
"http://sourceforge.net/projects/numpy\n\n"
"NOTE: The Numeric module is substantially faster than numarray for this\n"
"purpose, if you have lots of objects\n"
)
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -100,7 +91,10 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
item = draw_menu.Append(-1, "&Arrows","Run a test of Arrows") item = draw_menu.Append(-1, "&Arrows","Run a test of Arrows")
self.Bind(wx.EVT_MENU, self.ArrowTest, item) self.Bind(wx.EVT_MENU, self.ArrowTest, item)
item = draw_menu.Append(-1, "&Hide","Run a test of the Show() Hide() Show() and methods") item = draw_menu.Append(-1, "&ArrowLine Test","Run a test of drawing Arrow Lines")
self.Bind(wx.EVT_MENU, self.ArrowLineTest, item)
item = draw_menu.Append(-1, "&Hide","Run a test of hiding and showing objects")
self.Bind(wx.EVT_MENU, self.HideTest, item) self.Bind(wx.EVT_MENU, self.HideTest, item)
MenuBar.Append(draw_menu, "&Tests") MenuBar.Append(draw_menu, "&Tests")
@@ -122,9 +116,11 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
# Add the Canvas # Add the Canvas
self.Canvas = NavCanvas.NavCanvas(self, NC = NavCanvas.NavCanvas(self,
Debug = 0, Debug = 0,
BackgroundColor = "DARK SLATE BLUE") BackgroundColor = "DARK SLATE BLUE")
self.Canvas = NC.Canvas # reference the contained FloatCanvas
self.MsgWindow = wx.TextCtrl(self, wx.ID_ANY, self.MsgWindow = wx.TextCtrl(self, wx.ID_ANY,
"Look Here for output from events\n", "Look Here for output from events\n",
@@ -135,13 +131,14 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
##Create a sizer to manage the Canvas and message window ##Create a sizer to manage the Canvas and message window
MainSizer = wx.BoxSizer(wx.VERTICAL) MainSizer = wx.BoxSizer(wx.VERTICAL)
MainSizer.Add(self.Canvas, 4, wx.EXPAND) MainSizer.Add(NC, 4, wx.EXPAND)
MainSizer.Add(self.MsgWindow, 1, wx.EXPAND | wx.ALL, 5) MainSizer.Add(self.MsgWindow, 1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(MainSizer) self.SetSizer(MainSizer)
wx.EVT_CLOSE(self, self.OnCloseWindow) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove ) self.Canvas.Bind(FloatCanvas.EVT_MOTION, self.OnMove)
self.Canvas.Bind(FloatCanvas.EVT_MOUSEWHEEL, self.OnWheel)
self.EventsAreBound = False self.EventsAreBound = False
@@ -161,56 +158,39 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
def BindAllMouseEvents(self): def BindAllMouseEvents(self):
if not self.EventsAreBound: if not self.EventsAreBound:
## Here is how you catch FloatCanvas mouse events ## Here is how you catch FloatCanvas mouse events
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, self.OnLeftDown ) self.Canvas.Bind(FloatCanvas.EVT_LEFT_DOWN, self.OnLeftDown)
FloatCanvas.EVT_LEFT_UP(self.Canvas, self.OnLeftUp ) self.Canvas.Bind(FloatCanvas.EVT_LEFT_UP, self.OnLeftUp)
FloatCanvas.EVT_LEFT_DCLICK(self.Canvas, self.OnLeftDouble ) self.Canvas.Bind(FloatCanvas.EVT_LEFT_DCLICK, self.OnLeftDouble)
FloatCanvas.EVT_MIDDLE_DOWN(self.Canvas, self.OnMiddleDown ) self.Canvas.Bind(FloatCanvas.EVT_MIDDLE_DOWN, self.OnMiddleDown)
FloatCanvas.EVT_MIDDLE_UP(self.Canvas, self.OnMiddleUp ) self.Canvas.Bind(FloatCanvas.EVT_MIDDLE_UP, self.OnMiddleUp)
FloatCanvas.EVT_MIDDLE_DCLICK(self.Canvas, self.OnMiddleDouble ) self.Canvas.Bind(FloatCanvas.EVT_MIDDLE_DCLICK, self.OnMiddleDouble)
FloatCanvas.EVT_RIGHT_DOWN(self.Canvas, self.OnRightDown ) self.Canvas.Bind(FloatCanvas.EVT_RIGHT_DOWN, self.OnRightDown)
FloatCanvas.EVT_RIGHT_UP(self.Canvas, self.OnRightUp ) self.Canvas.Bind(FloatCanvas.EVT_RIGHT_UP, self.OnRightUp)
FloatCanvas.EVT_RIGHT_DCLICK(self.Canvas, self.OnRightDouble ) self.Canvas.Bind(FloatCanvas.EVT_RIGHT_DCLICK, self.OnRightDouble)
FloatCanvas.EVT_MOUSEWHEEL(self.Canvas, self.OnWheel )
self.EventsAreBound = True self.EventsAreBound = True
def UnBindAllMouseEvents(self): def UnBindAllMouseEvents(self):
## Here is how you unbind FloatCanvas mouse events ## Here is how you unbind FloatCanvas mouse events
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_LEFT_DOWN)
FloatCanvas.EVT_LEFT_UP(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_LEFT_UP)
FloatCanvas.EVT_LEFT_DCLICK(self.Canvas, None) self.Canvas.Unbind(FloatCanvas.EVT_LEFT_DCLICK)
FloatCanvas.EVT_MIDDLE_DOWN(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_MIDDLE_DOWN)
FloatCanvas.EVT_MIDDLE_UP(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_MIDDLE_UP)
FloatCanvas.EVT_MIDDLE_DCLICK(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_MIDDLE_DCLICK)
FloatCanvas.EVT_RIGHT_DOWN(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_RIGHT_DOWN)
FloatCanvas.EVT_RIGHT_UP(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_RIGHT_UP)
FloatCanvas.EVT_RIGHT_DCLICK(self.Canvas, None ) self.Canvas.Unbind(FloatCanvas.EVT_RIGHT_DCLICK)
FloatCanvas.EVT_MOUSEWHEEL(self.Canvas, None )
FloatCanvas.EVT_LEFT_DOWN(self.Canvas, None )
FloatCanvas.EVT_LEFT_UP(self.Canvas, None )
FloatCanvas.EVT_LEFT_DCLICK(self.Canvas, None)
FloatCanvas.EVT_MIDDLE_DOWN(self.Canvas, None )
FloatCanvas.EVT_MIDDLE_UP(self.Canvas, None )
FloatCanvas.EVT_MIDDLE_DCLICK(self.Canvas, None )
FloatCanvas.EVT_RIGHT_DOWN(self.Canvas, None )
FloatCanvas.EVT_RIGHT_UP(self.Canvas, None )
FloatCanvas.EVT_RIGHT_DCLICK(self.Canvas, None )
FloatCanvas.EVT_MOUSEWHEEL(self.Canvas, None )
self.EventsAreBound = False self.EventsAreBound = False
def PrintCoords(self,event): def PrintCoords(self,event):
#print "coords are: %s"%(event.Coords,)
#print "pixel coords are: %s\n"%(event.GetPosition(),)
self.Log("coords are: %s"%(event.Coords,)) self.Log("coords are: %s"%(event.Coords,))
self.Log("pixel coords are: %s\n"%(event.GetPosition(),)) self.Log("pixel coords are: %s\n"%(event.GetPosition(),))
@@ -256,7 +236,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.PrintCoords(event) self.PrintCoords(event)
def OnRightUp(self, event): def OnRightUp(self, event):
self.Log("RightDown") self.Log("RightUp")
self.PrintCoords(event) self.PrintCoords(event)
def OnRightDouble(self, event): def OnRightDouble(self, event):
@@ -278,6 +258,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Updates the status bar with the world coordinates Updates the status bar with the world coordinates
""" """
self.SetStatusText("%.2f, %.2f"%tuple(event.Coords)) self.SetStatusText("%.2f, %.2f"%tuple(event.Coords))
event.Skip()
def OnAbout(self, event): def OnAbout(self, event):
dlg = wx.MessageDialog(self, dlg = wx.MessageDialog(self,
@@ -293,8 +274,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
def Clear(self,event = None): def Clear(self,event = None):
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
self.Canvas.ClearAll() self.Canvas.InitAll()
self.Canvas.SetProjectionFun(None)
self.Canvas.Draw() self.Canvas.Draw()
def OnQuit(self,event): def OnQuit(self,event):
@@ -304,7 +284,12 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Destroy() self.Destroy()
def DrawTest(self,event=None): def DrawTest(self,event=None):
wx.GetApp().Yield() """
This demo draws a few of everything
"""
wx.GetApp().Yield(True)
Range = (-10,10) Range = (-10,10)
colors = self.colors colors = self.colors
@@ -312,8 +297,12 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.BindAllMouseEvents() self.BindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None) #
## these set the limits for how much you can zoom in and out
Canvas.MinScale = 14
Canvas.MaxScale = 500
############# Random tests of everything ############## ############# Random tests of everything ##############
@@ -417,6 +406,18 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
LineColor = colors[random.randint(0,len(colors)-1)], LineColor = colors[random.randint(0,len(colors)-1)],
ArrowHeadAngle = random.uniform(20,90)) ArrowHeadAngle = random.uniform(20,90))
# ArrowLines
for i in range(5):
points = []
for j in range(random.randint(2,10)):
point = (random.randint(Range[0],Range[1]),random.randint(Range[0],Range[1]))
points.append(point)
lw = random.randint(1,10)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
Canvas.AddArrowLine(points, LineWidth = lw, LineColor = colors[cl], ArrowHeadSize= 16)
Canvas.ZoomToBB() Canvas.ZoomToBB()
def TestAnimation(self,event=None): def TestAnimation(self,event=None):
@@ -429,15 +430,13 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
having to re-draw the whole background. having to re-draw the whole background.
""" """
wx.GetApp().Yield() wx.GetApp().Yield(True)
Range = (-10,10) Range = (-10,10)
self.Range = Range self.Range = Range
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.InitAll()
Canvas.ClearAll()
Canvas.SetProjectionFun(None)
## Random tests of everything: ## Random tests of everything:
colors = self.colors colors = self.colors
@@ -543,14 +542,13 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Timer.Start(self.FrameDelay) self.Timer.Start(self.FrameDelay)
#print "Did %i frames in %f seconds"%(N, (time.time() - start) ) #print "Did %i frames in %f seconds"%(N, (time.time() - start) )
def TestHitTest(self,event=None): def TestHitTest(self, event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
#Add a Hit-able rectangle #Add a Hit-able rectangle
w, h = 60, 20 w, h = 60, 20
@@ -558,7 +556,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
dx = 80 dx = 80
dy = 40 dy = 40
x, y = 20, 20 x, y = 20, 20
FontSize = 8 FontSize = 10
#Add one that is not HitAble #Add one that is not HitAble
Canvas.AddRectangle((x,y), (w, h), LineWidth = 2) Canvas.AddRectangle((x,y), (w, h), LineWidth = 2)
@@ -709,7 +707,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
R.Name = color R.Name = color
R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver) R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver)
R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave) R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave)
Canvas.AddText("Mouse ENter&Leave", (x, y), Size = FontSize, Position = "bl") Canvas.AddText("Mouse Enter&Leave", (x, y), Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, (x, y+h), Size = FontSize, Position = "tl") Canvas.AddText(R.Name, (x, y+h), Size = FontSize, Position = "tl")
x = 20 x = 20
@@ -722,7 +720,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
x += dx x += dx
color = "SEA GREEN" color = "SEA GREEN"
Points = Numeric.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), Numeric.Float) Points = N.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), N.float_)
R = Canvas.AddPolygon(Points, LineWidth = 2, FillColor = color) R = Canvas.AddPolygon(Points, LineWidth = 2, FillColor = color)
R.Name = color + " Polygon" R.Name = color + " Polygon"
R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHitRight) R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHitRight)
@@ -731,7 +729,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
x += dx x += dx
color = "Red" color = "Red"
Points = Numeric.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), Numeric.Float) Points = N.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), N.float_)
R = Canvas.AddPointSet(Points, Diameter = 4, Color = color) R = Canvas.AddPointSet(Points, Diameter = 4, Color = color)
R.Name = "PointSet" R.Name = "PointSet"
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.PointSetGotHit) R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.PointSetGotHit)
@@ -755,7 +753,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
x += dx x += dx
color = "Cyan" color = "Cyan"
Point = (x + w/2, y) Point = (x + w/2, y)
#Points = Numeric.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), Numeric.Float) #Points = N.array(( (x, y), (x, y+2.*h/3), (x+w, y+h), (x+w, y+h/2.), (x + 2.*w/3, y+h/2.), (x + 2.*w/3,y) ), N.float_)
R = Canvas.AddSquarePoint(Point, Size = 8, Color = color) R = Canvas.AddSquarePoint(Point, Size = 8, Color = color)
R.Name = "SquarePoint" R.Name = "SquarePoint"
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHit) R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHit)
@@ -766,13 +764,12 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Canvas.ZoomToBB() self.Canvas.ZoomToBB()
def TestHitTestForeground(self,event=None): def TestHitTestForeground(self,event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
#Add a Hitable rectangle #Add a Hitable rectangle
w, h = 60, 20 w, h = 60, 20
@@ -871,13 +868,14 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
def TestText(self, event= None): def TestText(self, event= None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.BindAllMouseEvents() self.BindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
DefaultSize = 12
Point = (3, 0) Point = (3, 0)
## Add a non-visible rectangle, just to get a Bounding Box ## Add a non-visible rectangle, just to get a Bounding Box
@@ -889,29 +887,29 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
# Text # Text
String = "Some text" String = "Some text"
self.Canvas.AddText("Top Left",Point,Size = 14,Color = "Yellow",BackgroundColor = "Blue", Position = "tl") self.Canvas.AddText("Top Left",Point,Size = DefaultSize,Color = "Yellow",BackgroundColor = "Blue", Position = "tl")
self.Canvas.AddText("Bottom Left",Point,Size = 14,Color = "Cyan",BackgroundColor = "Black",Position = "bl") self.Canvas.AddText("Bottom Left",Point,Size = DefaultSize,Color = "Cyan",BackgroundColor = "Black",Position = "bl")
self.Canvas.AddText("Top Right",Point,Size = 14,Color = "Black",BackgroundColor = "Cyan",Position = "tr") self.Canvas.AddText("Top Right",Point,Size = DefaultSize,Color = "Black",BackgroundColor = "Cyan",Position = "tr")
self.Canvas.AddText("Bottom Right",Point,Size = 14,Color = "Blue",BackgroundColor = "Yellow",Position = "br") self.Canvas.AddText("Bottom Right",Point,Size = DefaultSize,Color = "Blue",BackgroundColor = "Yellow",Position = "br")
Canvas.AddPointSet((Point), Color = "White", Diameter = 2) Canvas.AddPointSet((Point), Color = "White", Diameter = 2)
Point = (3, 2) Point = (3, 2)
Canvas.AddPointSet((Point), Color = "White", Diameter = 2) Canvas.AddPointSet((Point), Color = "White", Diameter = 2)
self.Canvas.AddText("Top Center",Point,Size = 14,Color = "Black",Position = "tc") self.Canvas.AddText("Top Center",Point,Size = DefaultSize,Color = "Black",Position = "tc")
self.Canvas.AddText("Bottom Center",Point,Size = 14,Color = "White",Position = "bc") self.Canvas.AddText("Bottom Center",Point,Size = DefaultSize,Color = "White",Position = "bc")
Point = (3, 4) Point = (3, 4)
Canvas.AddPointSet((Point), Color = "White", Diameter = 2) Canvas.AddPointSet((Point), Color = "White", Diameter = 2)
self.Canvas.AddText("Center Right",Point,Size = 14,Color = "Black",Position = "cr") self.Canvas.AddText("Center Right",Point,Size = DefaultSize,Color = "Black",Position = "cr")
self.Canvas.AddText("Center Left",Point,Size = 14,Color = "Black",Position = "cl") self.Canvas.AddText("Center Left",Point,Size = DefaultSize,Color = "Black",Position = "cl")
Point = (3, -2) Point = (3, -2)
Canvas.AddPointSet((Point), Color = "White", Diameter = 2) Canvas.AddPointSet((Point), Color = "White", Diameter = 2)
self.Canvas.AddText("Center Center", self.Canvas.AddText("Center Center",
Point, Size = 14, Point, Size = DefaultSize,
Color = "Black", Color = "Black",
Position = "cc") Position = "cc")
@@ -927,18 +925,17 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Canvas.AddText("ROMAN ITALIC BOLD Font", (-10, -5), Family = wx.ROMAN, Weight=wx.BOLD, Style=wx.ITALIC) self.Canvas.AddText("ROMAN ITALIC BOLD Font", (-10, -5), Family = wx.ROMAN, Weight=wx.BOLD, Style=wx.ITALIC)
# NOTE: this font exists on my Linux box..who knows were else you'll find it! # NOTE: this font exists on my Linux box..who knows were else you'll find it!
Font = wx.Font(20, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "zapf chancery") Font = wx.Font(20, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "helvetica")
self.Canvas.AddText("zapf chancery Font", (-10, -6), Font = Font) self.Canvas.AddText("Helvetica Italic", (-10, -6), Font = Font)
self.Canvas.ZoomToBB() self.Canvas.ZoomToBB()
def TestScaledText(self, event= None): def TestScaledText(self, event= None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.BindAllMouseEvents() self.BindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
Point = (0, 0) Point = (0, 0)
@@ -977,24 +974,23 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.AddPointSet((x,0), Color = "White", Diameter = 4) Canvas.AddPointSet((x,0), Color = "White", Diameter = 4)
# NOTE: this font exists on my Linux box..who knows were else you'll find it! # NOTE: this font exists on my OS-X.who knows were else you'll find it!
Point = (-100, 50) Point = (-100, 50)
Font = wx.Font(12, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "zapf chancery") Font = wx.Font(12, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "helvetica")
T = self.Canvas.AddScaledText("zapf chancery Font", Point, Size = 20, Font = Font, Position = 'bc') T = self.Canvas.AddScaledText("Helvetica Italic", Point, Size = 20, Font = Font, Position = 'bc')
Point = (-50, -50) Point = (-50, -50)
Font = wx.Font(12, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "bookman") Font = wx.Font(12, wx.DEFAULT, wx.ITALIC, wx.NORMAL, False, "times")
T = self.Canvas.AddScaledText("Bookman Font", Point, Size = 8, Font = Font) T = self.Canvas.AddScaledText("Times Font", Point, Size = 8, Font = Font)
self.Canvas.ZoomToBB() self.Canvas.ZoomToBB()
def TestScaledTextBox(self, event= None): def TestScaledTextBox(self, event= None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
Point = (45,40) Point = (45,40)
Box = Canvas.AddScaledTextBox("A Two Line\nString", Box = Canvas.AddScaledTextBox("A Two Line\nString",
@@ -1010,7 +1006,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.ROMAN, Family = wx.ROMAN,
Style = wx.NORMAL, Style = wx.NORMAL,
Weight = wx.NORMAL, Weight = wx.NORMAL,
Underline = False, Underlined = False,
Position = 'br', Position = 'br',
Alignment = "left", Alignment = "left",
InForeground = False) InForeground = False)
@@ -1058,7 +1054,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.TELETYPE, Family = wx.TELETYPE,
Style = wx.NORMAL, Style = wx.NORMAL,
Weight = wx.NORMAL, Weight = wx.NORMAL,
Underline = False, Underlined = False,
Position = 'cr', Position = 'cr',
Alignment = "left", Alignment = "left",
InForeground = False) InForeground = False)
@@ -1076,7 +1072,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.TELETYPE, Family = wx.TELETYPE,
Style = wx.NORMAL, Style = wx.NORMAL,
Weight = wx.NORMAL, Weight = wx.NORMAL,
Underline = False, Underlined = False,
Position = 'cl', Position = 'cl',
Alignment = "left", Alignment = "left",
InForeground = False) InForeground = False)
@@ -1097,7 +1093,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.TELETYPE, Family = wx.TELETYPE,
Style = wx.NORMAL, Style = wx.NORMAL,
Weight = wx.NORMAL, Weight = wx.NORMAL,
Underline = False, Underlined = False,
Position = 'tc', Position = 'tc',
Alignment = "left", Alignment = "left",
InForeground = False) InForeground = False)
@@ -1115,7 +1111,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.TELETYPE, Family = wx.TELETYPE,
Style = wx.NORMAL, Style = wx.NORMAL,
Weight = wx.NORMAL, Weight = wx.NORMAL,
Underline = False, Underlined = False,
Position = 'bc', Position = 'bc',
Alignment = "left", Alignment = "left",
InForeground = False) InForeground = False)
@@ -1143,7 +1139,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Family = wx.ROMAN, Family = wx.ROMAN,
Alignment = "right" Alignment = "right"
) )
Point = Numeric.array((100, -20), Numeric.Float) Point = N.array((100, -20), N.float_)
Box = Canvas.AddScaledTextBox("Here is even more auto wrapped text. This time the line spacing is set to 0.8. \n\nThe Padding is set to 0.", Box = Canvas.AddScaledTextBox("Here is even more auto wrapped text. This time the line spacing is set to 0.8. \n\nThe Padding is set to 0.",
Point, Point,
Size = 3, Size = 3,
@@ -1157,8 +1153,8 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
) )
Canvas.AddPoint(Point, "Red", 2) Canvas.AddPoint(Point, "Red", 2)
Point = Numeric.array((0, -40), Numeric.Float) Point = N.array((0, -40), N.float_)
# Point = Numeric.array((0, 0), Numeric.Float) # Point = N.array((0, 0), N.float_)
for Position in ["tl", "bl", "tr", "br"]: for Position in ["tl", "bl", "tr", "br"]:
# for Position in ["br"]: # for Position in ["br"]:
Box = Canvas.AddScaledTextBox("Here is a\nfour liner\nanother line\nPosition=%s"%Position, Box = Canvas.AddScaledTextBox("Here is a\nfour liner\nanother line\nPosition=%s"%Position,
@@ -1176,7 +1172,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
) )
Canvas.AddPoint(Point, "Red", 4) Canvas.AddPoint(Point, "Red", 4)
Point = Numeric.array((-20, 60), Numeric.Float) Point = N.array((-20, 60), N.float_)
Box = Canvas.AddScaledTextBox("Here is some\ncentered\ntext", Box = Canvas.AddScaledTextBox("Here is some\ncentered\ntext",
Point, Point,
Size = 4, Size = 4,
@@ -1192,7 +1188,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
LineSpacing = 0.8 LineSpacing = 0.8
) )
Point = Numeric.array((-20, 20), Numeric.Float) Point = N.array((-20, 20), N.float_)
Box = Canvas.AddScaledTextBox("Here is some\nright aligned\ntext", Box = Canvas.AddScaledTextBox("Here is some\nright aligned\ntext",
Point, Point,
Size = 4, Size = 4,
@@ -1207,7 +1203,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
LineSpacing = 0.8 LineSpacing = 0.8
) )
Point = Numeric.array((100, -60), Numeric.Float) Point = N.array((100, -60), N.float_)
Box = Canvas.AddScaledTextBox("Here is some auto wrapped text. This time it is centered, rather than right aligned.\n\nThe Padding is set to 2.", Box = Canvas.AddScaledTextBox("Here is some auto wrapped text. This time it is centered, rather than right aligned.\n\nThe Padding is set to 2.",
Point, Point,
Size = 3, Size = 3,
@@ -1230,13 +1226,12 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Log("I'm the TextBox") self.Log("I'm the TextBox")
def TestBitmap(self, event= None): def TestBitmap(self, event= None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
Canvas.AddRectangle((10, 20), Canvas.AddRectangle((10, 20),
(400, 100), (400, 100),
LineWidth = 3, LineWidth = 3,
@@ -1295,16 +1290,17 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Canvas.ZoomToBB() self.Canvas.ZoomToBB()
def DrawMap(self,event = None): def DrawMap(self,event = None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
import os, time import os, time
self.Canvas.InitAll()
self.Canvas.SetProjectionFun("FlatEarth")
self.BindAllMouseEvents() self.BindAllMouseEvents()
## Test of Actual Map Data ## Test of Actual Map Data
self.Canvas.ClearAll()
self.Canvas.SetProjectionFun("FlatEarth")
#start = time.clock() #start = time.clock()
self.Log("Loading Map from a File") self.Log("Loading Map from a File")
wx.GetApp().Yield() # so log text will get displayed now. wx.GetApp().Yield(True) # so log text will get displayed now.
Shorelines = self.Read_MapGen(os.path.join("data",'world.dat'),stats = 0) Shorelines = self.Read_MapGen(os.path.join("data",'world.dat'),stats = 0)
#print "It took %f seconds to load %i shorelines"%(time.clock() - start,len(Shorelines) ) #print "It took %f seconds to load %i shorelines"%(time.clock() - start,len(Shorelines) )
#start = time.clock() #start = time.clock()
@@ -1316,17 +1312,17 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
#print "It took %f seconds to draw %i shorelines"%(time.clock() - start,len(Shorelines) ) #print "It took %f seconds to draw %i shorelines"%(time.clock() - start,len(Shorelines) )
def LineTest(self,event = None): def LineTest(self,event = None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
import os, time import os, time
# import random # import random
colors = self.colors colors = self.colors
Range = (-10,10) Range = (-10,10)
## Test of drawing lots of lines ## Test of drawing lots of lines
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None) #start = time.clock()
#start = time.clock()
linepoints = [] linepoints = []
linecolors = [] linecolors = []
linewidths = [] linewidths = []
@@ -1345,17 +1341,44 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.ZoomToBB() Canvas.ZoomToBB()
#print "It took %f seconds to draw %i lines"%(time.clock() - start,len(linepoints) ) #print "It took %f seconds to draw %i lines"%(time.clock() - start,len(linepoints) )
def ArrowLineTest(self,event = None):
wx.GetApp().Yield(True)
Canvas = self.Canvas
Canvas.InitAll()
# import os, time
## import random
Range = (-100,100)
colors = self.colors
# Lines
for i in range(5):
points = []
for j in range(random.randint(2,10)):
point = (random.randint(Range[0],Range[1]),random.randint(Range[0],Range[1]))
points.append(point)
lw = random.randint(1,4)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
al = random.randint(8,20)
aa = random.randint(20,90)
Canvas.AddArrowLine(points,
LineWidth = lw,
LineColor = colors[cl],
ArrowHeadSize = al,
ArrowHeadAngle = aa)
Canvas.ZoomToBB()
def SpeedTest(self,event=None): def SpeedTest(self,event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
BigRange = (-1000,1000) BigRange = (-1000,1000)
colors = self.colors colors = self.colors
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
# Pointset # Pointset
coords = [] coords = []
for i in range(1000): for i in range(1000):
@@ -1369,7 +1392,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.ZoomToBB() Canvas.ZoomToBB()
def PropertiesChangeTest(self,event=None): def PropertiesChangeTest(self,event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
Range = (-10,10) Range = (-10,10)
colors = self.colors colors = self.colors
@@ -1377,9 +1400,8 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
self.ColorObjectsAll = [] self.ColorObjectsAll = []
self.ColorObjectsLine = [] self.ColorObjectsLine = []
self.ColorObjectsColor = [] self.ColorObjectsColor = []
@@ -1512,13 +1534,14 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Canvas.Draw(Force = True) self.Canvas.Draw(Force = True)
def ArrowTest(self,event=None): def ArrowTest(self,event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None) Canvas.MinScale = 15
Canvas.MaxScale = 30
# put in a rectangle to get a bounding box # put in a rectangle to get a bounding box
Canvas.AddRectangle((0,0), (20,20), LineColor = None) Canvas.AddRectangle((0,0), (20,20), LineColor = None)
@@ -1534,16 +1557,18 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.AddText("Clickable Arrow", (4,18), Position = "bc") Canvas.AddText("Clickable Arrow", (4,18), Position = "bc")
Arrow = Canvas.AddArrow((4,18), 80, Direction = 90 ,LineWidth = 3, LineColor = "Red", ArrowHeadAngle = 30) Arrow = Canvas.AddArrow((4,18), 80, Direction = 90 ,LineWidth = 3, LineColor = "Red", ArrowHeadAngle = 30)
Arrow.HitLineWidth = 6
Arrow.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.ArrowClicked) Arrow.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.ArrowClicked)
Canvas.AddText("Changable Arrow", (16,4), Position = "cc") Canvas.AddText("Changable Arrow: try clicking it", (16,4), Position = "tc")
self.RotArrow = Canvas.AddArrow((16,4), 80, Direction = 0 ,LineWidth = 3, LineColor = "Green", ArrowHeadAngle = 30) self.RotArrow = Canvas.AddArrow((16,4), 80, Direction = 0 ,LineWidth = 3, LineColor = "Green", ArrowHeadAngle = 30)
self.RotArrow.HitLineWidth = 6
self.RotArrow.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RotateArrow) self.RotArrow.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RotateArrow)
Canvas.ZoomToBB() Canvas.ZoomToBB()
def ArrowClicked(self,event): def ArrowClicked(self,event):
print "The Arrow was Clicked" self.Log("The Arrow was Clicked")
def RotateArrow(self,event): def RotateArrow(self,event):
##print "The Changeable Arrow was Clicked" ##print "The Changeable Arrow was Clicked"
@@ -1557,13 +1582,12 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
self.Canvas.Draw(Force = True) self.Canvas.Draw(Force = True)
def HideTest(self, event=None): def HideTest(self, event=None):
wx.GetApp().Yield() wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
Range = (-10,10) Range = (-10,10)
# Create a couple random Polygons # Create a couple random Polygons
@@ -1616,22 +1640,32 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
def HidePoly(self, Button): def HidePoly(self, Button):
Poly = Button.HidePoly Poly = Button.HidePoly
if Poly.Visible: if Poly.Visible:
Poly.Hide() Poly.Visible = False
Button.SetText(Button.String.replace("Hide","Show")) Button.SetText(Button.String.replace("Hide","Show"))
else: else:
Poly.Show() Poly.Visible = True
Button.SetText(Button.String.replace("Show", "Hide")) Button.SetText(Button.String.replace("Show", "Hide"))
self.Canvas.Draw(True) self.Canvas.Draw(True)
def TempTest(self, event= None): def TempTest(self, event= None):
wx.GetApp().Yield() """
This is the start of a poly editor test, but it's not complete
so you can only run it through a command line flag:
python FloatCanvasDemo.py --temp
"""
wx.GetApp().Yield(True)
self.UnBindAllMouseEvents() self.UnBindAllMouseEvents()
Canvas = self.Canvas Canvas = self.Canvas
Canvas.ClearAll() Canvas.InitAll()
Canvas.SetProjectionFun(None)
Range = (-10,10) Range = (-10,10)
# Create a random Polygon # Create a random Polygon
@@ -1654,7 +1688,6 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.ZoomToBB() Canvas.ZoomToBB()
def SelectPoly(self, Object): def SelectPoly(self, Object):
print "In SelectPoly"
Canvas = self.Canvas Canvas = self.Canvas
if Object is self.SelectedPoly: if Object is self.SelectedPoly:
pass pass
@@ -1673,7 +1706,7 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
Canvas.Draw() Canvas.Draw()
def SelectPointHit(self, Point): def SelectPointHit(self, Point):
print "Point Num: %i Hit"%Point.VerticeNum self.Log("Point Num: %i Hit"%Point.VerticeNum)
self.SelectedPoint = Point self.SelectedPoint = Point
def Read_MapGen(self, filename, stats = 0,AllLines=0): def Read_MapGen(self, filename, stats = 0,AllLines=0):
@@ -1697,11 +1730,11 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
for line in data: for line in data:
if line: if line:
if line == "# -b": #New segment beginning if line == "# -b": #New segment beginning
if segment: Shorelines.append(Numeric.array(segment)) if segment: Shorelines.append(N.array(segment))
segment = [] segment = []
else: else:
segment.append(map(float,string.split(line))) segment.append(map(float,string.split(line)))
if segment: Shorelines.append(Numeric.array(segment)) if segment: Shorelines.append(N.array(segment))
if stats: if stats:
NumSegments = len(Shorelines) NumSegments = len(Shorelines)
@@ -1728,13 +1761,16 @@ def BuildDrawFrame(): # this gets called when needed, rather than on import
if __name__ == "__main__": if __name__ == "__main__":
# running stand alone, Use wxversion:
# import wxversion
# wxversion.select("2.6")
# wxversion.select("2.8")
import wx import wx
# check options: # check options:
import sys, getopt import sys, getopt
optlist, args = getopt.getopt(sys.argv[1:],'l',["local", optlist, args = getopt.getopt(sys.argv[1:],'l',["all",
"all",
"text", "text",
"map", "map",
"stext", "stext",
@@ -1747,40 +1783,15 @@ if __name__ == "__main__":
"temp", "temp",
"props", "props",
"arrow", "arrow",
"arrowline",
"hide"]) "hide"])
if not haveNumeric: if not haveNumpy:
raise ImportError(errorText) raise ImportError(errorText)
StartUpDemo = "all" # the default StartUpDemo = "all" # the default
for opt in optlist: if optlist:
if opt[0] == "--all": StartUpDemo = optlist[0][0][2:]
StartUpDemo = "all"
elif opt[0] == "--text":
StartUpDemo = "text"
elif opt[0] == "--map":
StartUpDemo = "map"
elif opt[0] == "--stext":
StartUpDemo = "stext"
elif opt[0] == "--stextbox":
StartUpDemo = "stextbox"
elif opt[0] == "--bitmap":
StartUpDemo = "bitmap"
elif opt[0] == "--hit":
StartUpDemo = "hit"
elif opt[0] == "--hitf":
StartUpDemo = "hitf"
elif opt[0] == "--animate":
StartUpDemo = "animate"
elif opt[0] == "--speed":
StartUpDemo = "speed"
elif opt[0] == "--temp":
StartUpDemo = "temp"
elif opt[0] == "--props":
StartUpDemo = "props"
elif opt[0] == "--arrow":
StartUpDemo = "arrow"
elif opt[0] == "--hide":
StartUpDemo = "hide"
class DemoApp(wx.App): class DemoApp(wx.App):
""" """
@@ -1844,6 +1855,7 @@ if __name__ == "__main__":
frame.Show() frame.Show()
## check to see if the demo is set to start in a particular mode. ## check to see if the demo is set to start in a particular mode.
## fixme: should this be in a dict instead?
if StartUpDemo == "text": if StartUpDemo == "text":
frame.TestText() frame.TestText()
elif StartUpDemo == "stext": elif StartUpDemo == "stext":
@@ -1859,25 +1871,20 @@ if __name__ == "__main__":
elif StartUpDemo == "hit": elif StartUpDemo == "hit":
frame.TestHitTest() frame.TestHitTest()
elif StartUpDemo == "hitf": elif StartUpDemo == "hitf":
"starting TestHitTestForeground"
frame.TestHitTestForeground() frame.TestHitTestForeground()
elif StartUpDemo == "animate": elif StartUpDemo == "animate":
"starting TestAnimation"
frame.TestAnimation() frame.TestAnimation()
elif StartUpDemo == "speed": elif StartUpDemo == "speed":
"starting SpeedTest"
frame.SpeedTest() frame.SpeedTest()
elif StartUpDemo == "temp": elif StartUpDemo == "temp":
"starting temp Test"
frame.TempTest() frame.TempTest()
elif StartUpDemo == "props": elif StartUpDemo == "props":
"starting PropertiesChange Test"
frame.PropertiesChangeTest() frame.PropertiesChangeTest()
elif StartUpDemo == "arrow": elif StartUpDemo == "arrow":
"starting arrow Test"
frame.ArrowTest() frame.ArrowTest()
elif StartUpDemo == "arrowline":
frame.ArrowLineTest()
elif StartUpDemo == "hide": elif StartUpDemo == "hide":
"starting Hide Test"
frame.HideTest() frame.HideTest()
return True return True
@@ -1889,14 +1896,14 @@ else:
# It's not running stand-alone, set up for wxPython demo. # It's not running stand-alone, set up for wxPython demo.
# don't neeed wxversion here. # don't neeed wxversion here.
import wx import wx
if not haveNumeric: if not haveNumpy:
## TestPanel and runTest used for integration into wxPython Demo ## TestPanel and runTest used for integration into wxPython Demo
class TestPanel(wx.Panel): class TestPanel(wx.Panel):
def __init__(self, parent, log): def __init__(self, parent, log):
self.log = log self.log = log
wx.Panel.__init__(self, parent, -1) wx.Panel.__init__(self, parent, -1)
import images from wx.lib.floatcanvas.ScreenShot import getScreenShotBitmap
note1 = wx.StaticText(self, -1, errorText) note1 = wx.StaticText(self, -1, errorText)
note2 = wx.StaticText(self, -1, "This is what the FloatCanvas can look like:") note2 = wx.StaticText(self, -1, "This is what the FloatCanvas can look like:")
@@ -1904,7 +1911,7 @@ else:
S.Add((10, 10), 1) S.Add((10, 10), 1)
S.Add(note1, 0, wx.ALIGN_CENTER) S.Add(note1, 0, wx.ALIGN_CENTER)
S.Add(note2, 0, wx.ALIGN_CENTER | wx.BOTTOM, 4) S.Add(note2, 0, wx.ALIGN_CENTER | wx.BOTTOM, 4)
S.Add(wx.StaticBitmap(self,-1,images.getFloatCanvasBitmap()),0,wx.ALIGN_CENTER) S.Add(wx.StaticBitmap(self,-1,getScreenShotBitmap()),0,wx.ALIGN_CENTER)
S.Add((10, 10), 1) S.Add((10, 10), 1)
self.SetSizer(S) self.SetSizer(S)
self.Layout() self.Layout()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,347 @@
"""
Module that holds the GUI modes used by FloatCanvas
Note that this can only be imported after a wx.App() has been created.
This approach was inpired by Christian Blouin, who also wrote the initial
version of the code.
"""
import wx
## fixme: events should live in their own module, so all of FloatCanvas
## wouldn't have to be imported here.
import FloatCanvas, Resources
import numpy as N
## create all the Cursors, so they don't need to be created each time.
if "wxMac" in wx.PlatformInfo: # use 16X16 cursors for wxMac
HandCursor = wx.CursorFromImage(Resources.getHand16Image())
GrabHandCursor = wx.CursorFromImage(Resources.getGrabHand16Image())
img = Resources.getMagPlus16Image()
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
MagPlusCursor = wx.CursorFromImage(img)
img = Resources.getMagMinus16Image()
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
MagMinusCursor = wx.CursorFromImage(img)
else: # use 24X24 cursors for GTK and Windows
HandCursor = wx.CursorFromImage(Resources.getHandImage())
GrabHandCursor = wx.CursorFromImage(Resources.getGrabHandImage())
img = Resources.getMagPlusImage()
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
MagPlusCursor = wx.CursorFromImage(img)
img = Resources.getMagMinusImage()
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
MagMinusCursor = wx.CursorFromImage(img)
class GUIBase:
"""
Basic Mouse mode and baseclass for other GUImode.
This one does nothing with any event
"""
def __init__(self, parent):
self.parent = parent
Cursor = wx.NullCursor
# Handlers
def OnLeftDown(self, event):
pass
def OnLeftUp(self, event):
pass
def OnLeftDouble(self, event):
pass
def OnRightDown(self, event):
pass
def OnRightUp(self, event):
pass
def OnRightDouble(self, event):
pass
def OnMiddleDown(self, event):
pass
def OnMiddleUp(self, event):
pass
def OnMiddleDouble(self, event):
pass
def OnWheel(self, event):
pass
def OnMove(self, event):
pass
def UpdateScreen(self):
"""
Update gets called if the screen has been repainted in the middle of a zoom in
so the Rubber Band Box can get updated
"""
pass
class GUIMouse(GUIBase):
"""
Mouse mode checks for a hit test, and if nothing is hit,
raises a FloatCanvas mouse event for each event.
"""
Cursor = wx.NullCursor
# Handlers
def OnLeftDown(self, event):
EventType = FloatCanvas.EVT_FC_LEFT_DOWN
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnLeftUp(self, event):
EventType = FloatCanvas.EVT_FC_LEFT_UP
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnLeftDouble(self, event):
EventType = FloatCanvas.EVT_FC_LEFT_DCLICK
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnMiddleDown(self, event):
EventType = FloatCanvas.EVT_FC_MIDDLE_DOWN
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnMiddleUp(self, event):
EventType = FloatCanvas.EVT_FC_MIDDLE_UP
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnMiddleDouble(self, event):
EventType = FloatCanvas.EVT_FC_MIDDLE_DCLICK
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnRightDown(self, event):
EventType = FloatCanvas.EVT_FC_RIGHT_DOWN
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnRightUp(self, event):
EventType = FloatCanvas.EVT_FC_RIGHT_UP
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnRightDouble(self, event):
EventType = FloatCanvas.EVT_FC_RIGHT_DCLICK
if not self.parent.HitTest(event, EventType):
self.parent._RaiseMouseEvent(event, EventType)
def OnWheel(self, event):
EventType = FloatCanvas.EVT_FC_MOUSEWHEEL
self.parent._RaiseMouseEvent(event, EventType)
def OnMove(self, event):
## The Move event always gets raised, even if there is a hit-test
self.parent.MouseOverTest(event)
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
class GUIMove(GUIBase):
Cursor = HandCursor
GrabCursor = GrabHandCursor
def __init__(self, parent):
GUIBase.__init__(self, parent)
self.StartMove = None
self.PrevMoveXY = None
def OnLeftDown(self, event):
self.parent.SetCursor(self.GrabCursor)
self.parent.CaptureMouse()
self.StartMove = N.array( event.GetPosition() )
self.PrevMoveXY = (0,0)
def OnLeftUp(self, event):
if self.StartMove is not None:
StartMove = self.StartMove
EndMove = N.array(event.GetPosition())
DiffMove = StartMove-EndMove
if N.sum(DiffMove**2) > 16:
self.parent.MoveImage(DiffMove, 'Pixel')
self.StartMove = None
self.parent.SetCursor(self.Cursor)
def OnMove(self, event):
# Allways raise the Move event.
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
if event.Dragging() and event.LeftIsDown() and not self.StartMove is None:
xy1 = N.array( event.GetPosition() )
wh = self.parent.PanelSize
xy_tl = xy1 - self.StartMove
dc = wx.ClientDC(self.parent)
dc.BeginDrawing()
x1,y1 = self.PrevMoveXY
x2,y2 = xy_tl
w,h = self.parent.PanelSize
##fixme: This sure could be cleaner!
if x2 > x1 and y2 > y1:
xa = xb = x1
ya = yb = y1
wa = w
ha = y2 - y1
wb = x2- x1
hb = h
elif x2 > x1 and y2 <= y1:
xa = x1
ya = y1
wa = x2 - x1
ha = h
xb = x1
yb = y2 + h
wb = w
hb = y1 - y2
elif x2 <= x1 and y2 > y1:
xa = x1
ya = y1
wa = w
ha = y2 - y1
xb = x2 + w
yb = y1
wb = x1 - x2
hb = h - y2 + y1
elif x2 <= x1 and y2 <= y1:
xa = x2 + w
ya = y1
wa = x1 - x2
ha = h
xb = x1
yb = y2 + h
wb = w
hb = y1 - y2
dc.SetPen(wx.TRANSPARENT_PEN)
dc.SetBrush(self.parent.BackgroundBrush)
dc.DrawRectangle(xa, ya, wa, ha)
dc.DrawRectangle(xb, yb, wb, hb)
self.PrevMoveXY = xy_tl
if self.parent._ForeDrawList:
dc.DrawBitmapPoint(self.parent._ForegroundBuffer,xy_tl)
else:
dc.DrawBitmapPoint(self.parent._Buffer,xy_tl)
dc.EndDrawing()
def OnWheel(self, event):
"""
By default, zoom in/out by a 0.1 factor per Wheel event.
"""
if event.GetWheelRotation() < 0:
self.parent.Zoom(0.9)
else:
self.parent.Zoom(1.1)
class GUIZoomIn(GUIBase):
Cursor = MagPlusCursor
def __init__(self, parent):
GUIBase.__init__(self, parent)
self.StartRBBox = None
self.PrevRBBox = None
def OnLeftDown(self, event):
self.StartRBBox = N.array( event.GetPosition() )
self.PrevRBBox = None
self.parent.CaptureMouse()
def OnLeftUp(self, event):
#if self.parent.HasCapture():
# self.parent.ReleaseMouse()
if event.LeftUp() and not self.StartRBBox is None:
self.PrevRBBox = None
EndRBBox = event.GetPosition()
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.parent.PixelToWorld(EndRBBox)
StartRBBox = self.parent.PixelToWorld(StartRBBox)
BB = N.array(((min(EndRBBox[0],StartRBBox[0]),
min(EndRBBox[1],StartRBBox[1])),
(max(EndRBBox[0],StartRBBox[0]),
max(EndRBBox[1],StartRBBox[1]))),N.float_)
self.parent.ZoomToBB(BB)
else:
Center = self.parent.PixelToWorld(StartRBBox)
self.parent.Zoom(1.5,Center)
self.StartRBBox = None
def OnMove(self, event):
# Allways raise the Move event.
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
if event.Dragging() and event.LeftIsDown() and not (self.StartRBBox is None):
xy0 = self.StartRBBox
xy1 = N.array( event.GetPosition() )
wh = abs(xy1 - xy0)
wh[0] = max(wh[0], int(wh[1]*self.parent.AspectRatio))
wh[1] = int(wh[0] / self.parent.AspectRatio)
xy_c = (xy0 + xy1) / 2
dc = wx.ClientDC(self.parent)
dc.BeginDrawing()
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.PrevRBBox:
dc.DrawRectanglePointSize(*self.PrevRBBox)
self.PrevRBBox = ( xy_c - wh/2, wh )
dc.DrawRectanglePointSize( *self.PrevRBBox )
dc.EndDrawing()
def UpdateScreen(self):
"""
Update gets called if the screen has been repainted in the middle of a zoom in
so the Rubber Band Box can get updated
"""
if self.PrevRBBox is not None:
dc = wx.ClientDC(self.parent)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
dc.DrawRectanglePointSize(*self.PrevRBBox)
def OnRightDown(self, event):
self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
def OnWheel(self, event):
if event.GetWheelRotation() < 0:
self.parent.Zoom(0.9)
else:
self.parent.Zoom(1.1)
class GUIZoomOut(GUIBase):
Cursor = MagMinusCursor
def OnLeftDown(self, event):
self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
def OnRightDown(self, event):
self.parent.Zoom(1.5, event.GetPosition(), centerCoords="pixel")
def OnWheel(self, event):
if event.GetWheelRotation() < 0:
self.parent.Zoom(0.9)
else:
self.parent.Zoom(1.1)
def OnMove(self, event):
# Allways raise the Move event.
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)

View File

@@ -4,18 +4,9 @@ A Panel that includes the FloatCanvas and Navigation controls
""" """
import wx import wx
import FloatCanvas, Resources import FloatCanvas, Resources
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_POINTER_BUTTON = wx.NewId()
#---------------------------------------------------------------------------
class NavCanvas(wx.Panel): class NavCanvas(wx.Panel):
""" """
NavCanvas.py NavCanvas.py
@@ -23,96 +14,80 @@ class NavCanvas(wx.Panel):
This is a high level window that encloses the FloatCanvas in a panel This is a high level window that encloses the FloatCanvas in a panel
and adds a Navigation toolbar. and adds a Navigation toolbar.
Copyright: Christopher Barker) """
License: Same as the version of wxPython you are using it with def __init__(self,
parent,
Please let me know if you're using this!!! id = wx.ID_ANY,
size = wx.DefaultSize,
Contact me at: **kwargs): # The rest just get passed into FloatCanvas
wx.Panel.__init__(self, parent, id, size=size)
Chris.Barker@noaa.gov
"""
def __init__(self, parent, id = -1,
size = wx.DefaultSize,
**kwargs): # The rest just get passed into FloatCanvas
wx.Panel.__init__( self, parent, id, wx.DefaultPosition, size)
self.BuildToolbar()
## Create the vertical sizer for the toolbar and Panel ## Create the vertical sizer for the toolbar and Panel
box = wx.BoxSizer(wx.VERTICAL) box = wx.BoxSizer(wx.VERTICAL)
box.Add(self.BuildToolbar(), 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4) box.Add(self.ToolBar, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)
self.Canvas = FloatCanvas.FloatCanvas( self, wx.NewId(),
size = wx.DefaultSize,
**kwargs)
box.Add(self.Canvas,1,wx.GROW)
box.Fit(self) self.Canvas = FloatCanvas.FloatCanvas(self, **kwargs)
self.SetSizer(box) box.Add(self.Canvas, 1, wx.GROW)
self.SetSizerAndFit(box)
import GUIMode # here so that it doesn't get imported before wx.App()
self.GUIZoomIn = GUIMode.GUIZoomIn(self.Canvas)
self.GUIZoomOut = GUIMode.GUIZoomOut(self.Canvas)
self.GUIMove = GUIMode.GUIMove(self.Canvas)
self.GUIMouse = GUIMode.GUIMouse(self.Canvas)
# default to Mouse mode # default to Mouse mode
self.ToolBar.ToggleTool(ID_POINTER_BUTTON,1) self.ToolBar.ToggleTool(self.PointerTool.GetId(), True)
self.Canvas.SetMode("Mouse") self.Canvas.SetMode(self.GUIMouse)
return None return None
def __getattr__(self, name):
"""
Delegate all extra methods to the Canvas
"""
attrib = getattr(self.Canvas, name)
## add the attribute to this module's dict for future calls
self.__dict__[name] = attrib
return attrib
def BuildToolbar(self): def BuildToolbar(self):
tb = wx.ToolBar(self,-1) tb = wx.ToolBar(self)
self.ToolBar = tb self.ToolBar = tb
tb.SetToolBitmapSize((24,24)) tb.SetToolBitmapSize((24,24))
tb.AddTool(ID_POINTER_BUTTON, Resources.getPointerBitmap(), isToggle=True, shortHelpString = "Pointer")
wx.EVT_TOOL(self, ID_POINTER_BUTTON, self.SetToolMode)
tb.AddTool(ID_ZOOM_IN_BUTTON, Resources.getMagPlusBitmap(), isToggle=True, shortHelpString = "Zoom In") self.PointerTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getPointerBitmap(), shortHelp = "Pointer")
wx.EVT_TOOL(self, ID_ZOOM_IN_BUTTON, self.SetToolMode) self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIMouse), self.PointerTool)
tb.AddTool(ID_ZOOM_OUT_BUTTON, Resources.getMagMinusBitmap(), isToggle=True, shortHelpString = "Zoom Out") self.ZoomInTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getMagPlusBitmap(), shortHelp = "Zoom In")
wx.EVT_TOOL(self, ID_ZOOM_OUT_BUTTON, self.SetToolMode) self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIZoomIn), self.ZoomInTool)
tb.AddTool(ID_MOVE_MODE_BUTTON, Resources.getHandBitmap(), isToggle=True, shortHelpString = "Move") self.ZoomOutTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getMagMinusBitmap(), shortHelp = "Zoom Out")
wx.EVT_TOOL(self, ID_MOVE_MODE_BUTTON, self.SetToolMode) self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIZoomOut), self.ZoomOutTool)
self.MoveTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getHandBitmap(), shortHelp = "Move")
self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIMove), self.MoveTool)
tb.AddSeparator() tb.AddSeparator()
tb.AddControl(wx.Button(tb, ID_ZOOM_TO_FIT_BUTTON, "Zoom To Fit",wx.DefaultPosition, wx.DefaultSize)) self.ZoomButton = wx.Button(tb, label="Zoom To Fit")
wx.EVT_BUTTON(self, ID_ZOOM_TO_FIT_BUTTON, self.ZoomToFit) tb.AddControl(self.ZoomButton)
self.ZoomButton.Bind(wx.EVT_BUTTON, self.ZoomToFit)
tb.Realize() tb.Realize()
S = tb.GetSize() ## fixme: remove this when the bug is fixed!
tb.SetSizeHints(S[0],S[1]) wx.CallAfter(self.HideShowHack) # this required on wxPython 2.8.3 on OS-X
return tb return tb
def SetToolMode(self,event): def HideShowHack(self):
for id in [ID_ZOOM_IN_BUTTON, ##fixme: remove this when the bug is fixed!
ID_ZOOM_OUT_BUTTON, """
ID_MOVE_MODE_BUTTON, Hack to hide and show button on toolbar to get around OS-X bug on
ID_POINTER_BUTTON]: wxPython2.8 on OS-X
self.ToolBar.ToggleTool(id,0) """
self.ToolBar.ToggleTool(event.GetId(),1) self.ZoomButton.Hide()
if event.GetId() == ID_ZOOM_IN_BUTTON: self.ZoomButton.Show()
self.Canvas.SetMode("ZoomIn")
elif event.GetId() == ID_ZOOM_OUT_BUTTON:
self.Canvas.SetMode("ZoomOut")
elif event.GetId() == ID_MOVE_MODE_BUTTON:
self.Canvas.SetMode("Move")
elif event.GetId() == ID_POINTER_BUTTON:
self.Canvas.SetMode("Mouse")
def SetMode(self, Mode):
self.Canvas.SetMode(Mode)
def ZoomToFit(self,Event): def ZoomToFit(self,Event):
self.Canvas.ZoomToBB() self.Canvas.ZoomToBB()
self.Canvas.SetFocus() # Otherwise the focus stays on the Button, and wheel events are lost.

View File

@@ -0,0 +1,170 @@
"""
A Bounding Box object and assorted utilities , subclassed from a numpy array
"""
import numpy as N
class BBox(N.ndarray):
"""
A Bounding Box object:
Takes Data as an array. Data is any python sequence that can be turned into a
2x2 numpy array of floats:
[[MinX, MinY ],
[MaxX, MaxY ]]
It is a subclass of numpy.ndarray, so for the most part it can be used as
an array, and arrays that fit the above description can be used in its place.
Usually created by the factory functions:
asBBox
and
fromPoints
"""
def __new__(subtype, data):
"""
Takes Data as an array. Data is any python sequence that can be turned into a
2x2 numpy array of floats:
[[MinX, MinY ],
[MaxX, MaxY ]]
You don't usually call this directly. BBox objects are created with the factory functions:
asBBox
and
fromPoints
"""
arr = N.array(data, N.float)
arr.shape = (2,2)
if arr[0,0] > arr[1,0] or arr[0,1] > arr[1,1]:
# note: zero sized BB OK.
raise ValueError("BBox values not aligned: \n minimum values must be less that maximum values")
return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
def Overlaps(self, BB):
"""
Overlap(BB):
Tests if the given Bounding Box overlaps with this one.
Returns True is the Bounding boxes overlap, False otherwise
If they are just touching, returns True
"""
if ( (self[1,0] >= BB[0,0]) and (self[0,0] <= BB[1,0]) and
(self[1,1] >= BB[0,1]) and (self[0,1] <= BB[1,1]) ):
return True
else:
return False
def Inside(self, BB):
"""
Inside(BB):
Tests if the given Bounding Box is entirely inside this one.
Returns True if it is entirely inside, or touching the
border.
Returns False otherwise
"""
if ( (BB[0,0] >= self[0,0]) and (BB[1,0] <= self[1,0]) and
(BB[0,1] >= self[0,1]) and (BB[1,1] <= self[1,1]) ):
return True
else:
return False
def Merge(self, BB):
"""
Joins this bounding box with the one passed in, maybe making this one bigger
"""
if BB[0,0] < self[0,0]: self[0,0] = BB[0,0]
if BB[0,1] < self[0,1]: self[0,1] = BB[0,1]
if BB[1,0] > self[1,0]: self[1,0] = BB[1,0]
if BB[1,1] > self[1,1]: self[1,1] = BB[1,1]
### This could be used for a make BB from a bunch of BBs
#~ def _getboundingbox(bboxarray): # lrk: added this
#~ # returns the bounding box of a bunch of bounding boxes
#~ upperleft = N.minimum.reduce(bboxarray[:,0])
#~ lowerright = N.maximum.reduce(bboxarray[:,1])
#~ return N.array((upperleft, lowerright), N.float)
#~ _getboundingbox = staticmethod(_getboundingbox)
## Save the ndarray __eq__ for internal use.
Array__eq__ = N.ndarray.__eq__
def __eq__(self, BB):
"""
__eq__(BB) The equality operator
A == B if and only if all the entries are the same
"""
return N.all(self.Array__eq__(BB))
def asBBox(data):
"""
returns a BBox object.
If object is a BBox, it is returned unaltered
If object is a numpy array, a BBox object is returned that shares a
view of the data with that array
"""
if isinstance(data, BBox):
return data
arr = N.asarray(data, N.float)
return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
def fromPoints(Points):
"""
fromPoints (Points).
reruns the bounding box of the set of points in Points. Points can
be any python object that can be turned into a numpy NX2 array of Floats.
If a single point is passed in, a zero-size Bounding Box is returned.
"""
Points = N.asarray(Points, N.float).reshape(-1,2)
arr = N.vstack( (Points.min(0), Points.max(0)) )
return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr)
def fromBBArray(BBarray):
"""
Builds a BBox object from an array of Bounding Boxes.
The resulting Bounding Box encompases all the included BBs.
The BBarray is in the shape: (Nx2x2) where BBarray[n] is a 2x2 array that represents a BBox
"""
#upperleft = N.minimum.reduce(BBarray[:,0])
#lowerright = N.maximum.reduce(BBarray[:,1])
# BBarray = N.asarray(BBarray, N.float).reshape(-1,2)
# arr = N.vstack( (BBarray.min(0), BBarray.max(0)) )
BBarray = N.asarray(BBarray, N.float).reshape(-1,2,2)
arr = N.vstack( (BBarray[:,0,:].min(0), BBarray[:,1,:].max(0)) )
return asBBox(arr)
#return asBBox( (upperleft, lowerright) ) * 2

View File

@@ -0,0 +1,354 @@
"""
Test code for the BBox Object
"""
import unittest
from BBox import *
class testCreator(unittest.TestCase):
def testCreates(self):
B = BBox(((0,0),(5,5)))
self.failUnless(isinstance(B, BBox))
def testType(self):
B = N.array(((0,0),(5,5)))
self.failIf(isinstance(B, BBox))
def testDataType(self):
B = BBox(((0,0),(5,5)))
self.failUnless(B.dtype == N.float)
def testShape(self):
B = BBox((0,0,5,5))
self.failUnless(B.shape == (2,2))
def testShape2(self):
self.failUnlessRaises(ValueError, BBox, (0,0,5) )
def testShape3(self):
self.failUnlessRaises(ValueError, BBox, (0,0,5,6,7) )
def testArrayConstruction(self):
A = N.array(((4,5),(10,12)), N.float_)
B = BBox(A)
self.failUnless(isinstance(B, BBox))
def testMinMax(self):
self.failUnlessRaises(ValueError, BBox, (0,0,-1,6) )
def testMinMax2(self):
self.failUnlessRaises(ValueError, BBox, (0,0,1,-6) )
def testMinMax(self):
# OK to have a zero-sized BB
B = BBox(((0,0),(0,5)))
self.failUnless(isinstance(B, BBox))
def testMinMax2(self):
# OK to have a zero-sized BB
B = BBox(((10.0,-34),(10.0,-34.0)))
self.failUnless(isinstance(B, BBox))
def testMinMax3(self):
# OK to have a tiny BB
B = BBox(((0,0),(1e-20,5)))
self.failUnless(isinstance(B, BBox))
def testMinMax4(self):
# Should catch tiny difference
self.failUnlessRaises(ValueError, BBox, ((0,0), (-1e-20,5)) )
class testAsBBox(unittest.TestCase):
def testPassThrough(self):
B = BBox(((0,0),(5,5)))
C = asBBox(B)
self.failUnless(B is C)
def testPassThrough2(self):
B = (((0,0),(5,5)))
C = asBBox(B)
self.failIf(B is C)
def testPassArray(self):
# Different data type
A = N.array( (((0,0),(5,5))) )
C = asBBox(A)
self.failIf(A is C)
def testPassArray2(self):
# same data type -- should be a view
A = N.array( (((0,0),(5,5))), N.float_ )
C = asBBox(A)
A[0,0] = -10
self.failUnless(C[0,0] == A[0,0])
class testIntersect(unittest.TestCase):
def testSame(self):
B = BBox(((-23.5, 456),(56, 532.0)))
C = BBox(((-23.5, 456),(56, 532.0)))
self.failUnless(B.Overlaps(C) )
def testUpperLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (0, 12),(10, 32.0) ) )
self.failUnless(B.Overlaps(C) )
def testUpperRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (12, 12),(25, 32.0) ) )
self.failUnless(B.Overlaps(C) )
def testLowerRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (12, 5),(25, 15) ) )
self.failUnless(B.Overlaps(C) )
def testLowerLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 5),(8.5, 15) ) )
self.failUnless(B.Overlaps(C) )
def testBelow(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 5),(8.5, 9.2) ) )
self.failIf(B.Overlaps(C) )
def testAbove(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 25.001),(8.5, 32) ) )
self.failIf(B.Overlaps(C) )
def testLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (4, 8),(4.95, 32) ) )
self.failIf(B.Overlaps(C) )
def testRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (17.1, 8),(17.95, 32) ) )
self.failIf(B.Overlaps(C) )
def testInside(self):
B = BBox( ( (-15, -25),(-5, -10) ) )
C = BBox( ( (-12, -22), (-6, -8) ) )
self.failUnless(B.Overlaps(C) )
def testOutside(self):
B = BBox( ( (-15, -25),(-5, -10) ) )
C = BBox( ( (-17, -26), (3, 0) ) )
self.failUnless(B.Overlaps(C) )
def testTouch(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (15, 8),(17.95, 32) ) )
self.failUnless(B.Overlaps(C) )
def testCorner(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (15, 25),(17.95, 32) ) )
self.failUnless(B.Overlaps(C) )
def testZeroSize(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (15, 25),(15, 25) ) )
self.failUnless(B.Overlaps(C) )
def testZeroSize2(self):
B = BBox( ( (5, 10),(5, 10) ) )
C = BBox( ( (15, 25),(15, 25) ) )
self.failIf(B.Overlaps(C) )
def testZeroSize3(self):
B = BBox( ( (5, 10),(5, 10) ) )
C = BBox( ( (0, 8),(10, 12) ) )
self.failUnless(B.Overlaps(C) )
def testZeroSize4(self):
B = BBox( ( (5, 1),(10, 25) ) )
C = BBox( ( (8, 8),(8, 8) ) )
self.failUnless(B.Overlaps(C) )
class testEquality(unittest.TestCase):
def testSame(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(B == C)
def testIdentical(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(B == B)
def testNotSame(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = BBox( ( (1.0, 2.0), (5.0, 10.1) ) )
self.failIf(B == C)
def testWithArray(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(B == C)
def testWithArray2(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(C == B)
def testWithArray2(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = N.array( ( (1.01, 2.0), (5.0, 10.0) ) )
self.failIf(C == B)
class testInside(unittest.TestCase):
def testSame(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(B.Inside(C))
def testPoint(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = BBox( ( (3.0, 4.0), (3.0, 4.0) ) )
self.failUnless(B.Inside(C))
def testPointOutside(self):
B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
C = BBox( ( (-3.0, 4.0), (0.10, 4.0) ) )
self.failIf(B.Inside(C))
def testUpperLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (0, 12),(10, 32.0) ) )
self.failIf(B.Inside(C) )
def testUpperRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (12, 12),(25, 32.0) ) )
self.failIf(B.Inside(C) )
def testLowerRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (12, 5),(25, 15) ) )
self.failIf(B.Inside(C) )
def testLowerLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 5),(8.5, 15) ) )
self.failIf(B.Inside(C) )
def testBelow(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 5),(8.5, 9.2) ) )
self.failIf(B.Inside(C) )
def testAbove(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (-10, 25.001),(8.5, 32) ) )
self.failIf(B.Inside(C) )
def testLeft(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (4, 8),(4.95, 32) ) )
self.failIf(B.Inside(C) )
def testRight(self):
B = BBox( ( (5, 10),(15, 25) ) )
C = BBox( ( (17.1, 8),(17.95, 32) ) )
self.failIf(B.Inside(C) )
class testFromPoints(unittest.TestCase):
def testCreate(self):
Pts = N.array( ((5,2),
(3,4),
(1,6),
), N.float_ )
B = fromPoints(Pts)
#B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) )
self.failUnless(B[0,0] == 1.0 and
B[0,1] == 2.0 and
B[1,0] == 5.0 and
B[1,1] == 6.0
)
def testCreateInts(self):
Pts = N.array( ((5,2),
(3,4),
(1,6),
) )
B = fromPoints(Pts)
self.failUnless(B[0,0] == 1.0 and
B[0,1] == 2.0 and
B[1,0] == 5.0 and
B[1,1] == 6.0
)
def testSinglePoint(self):
Pts = N.array( (5,2), N.float_ )
B = fromPoints(Pts)
self.failUnless(B[0,0] == 5.0 and
B[0,1] == 2.0 and
B[1,0] == 5.0 and
B[1,1] == 2.0
)
def testListTuples(self):
Pts = [ (3, 6.5),
(13, 43.2),
(-4.32, -4),
(65, -23),
(-0.0001, 23.432),
]
B = fromPoints(Pts)
self.failUnless(B[0,0] == -4.32 and
B[0,1] == -23.0 and
B[1,0] == 65.0 and
B[1,1] == 43.2
)
class testMerge(unittest.TestCase):
A = BBox( ((-23.5, 456), (56, 532.0)) )
B = BBox( ((-20.3, 460), (54, 465 )) )# B should be completely inside A
C = BBox( ((-23.5, 456), (58, 540.0)) )# up and to the right or A
D = BBox( ((-26.5, 12), (56, 532.0)) )
def testInside(self):
C = self.A.copy()
C.Merge(self.B)
self.failUnless(C == self.A)
def testFullOutside(self):
C = self.B.copy()
C.Merge(self.A)
self.failUnless(C == self.A)
def testUpRight(self):
A = self.A.copy()
A.Merge(self.C)
self.failUnless(A[0] == self.A[0] and A[1] == self.C[1])
def testDownLeft(self):
A = self.A.copy()
A.Merge(self.D)
self.failUnless(A[0] == self.D[0] and A[1] == self.A[1])
class testBBarray(unittest.TestCase):
BBarray = N.array( ( ((-23.5, 456), (56, 532.0)),
((-20.3, 460), (54, 465 )),
((-23.5, 456), (58, 540.0)),
((-26.5, 12), (56, 532.0)),
),
dtype=N.float)
print BBarray
BB = asBBox( ((-26.5, 12.), ( 58. , 540.)) )
def testJoin(self):
BB = fromBBArray(self.BBarray)
self.failUnless(BB == self.BB, "Wrong BB was created. It was:\n%s \nit should have been:\n%s"%(BB, self.BB))
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,115 @@
"""
Part of the floatcanvas.Utilities package.
This module contains assorted GUI-related utilities that can be used
with FloatCanvas
So far, they are:
RubberBandBox: used to draw a RubberBand Box on the screen
"""
import wx
from floatcanvas import FloatCanvas
class RubberBandBox:
"""
Class to provide a rubber band box that can be drawn on a Window
"""
def __init__(self, Canvas, CallBack, Tol=5):
"""
To initialize:
RubberBandBox(Canvas, CallBack)
Canvas: the FloatCanvas you want the Rubber band box to be used on
CallBack: is the method you want called when the mouse is
released. That method will be called, passing in a rect
parameter, where rect is: (Point, WH) of the rect in
world coords.
Tol: The tolerance for the smallest rectangle allowed. defaults
to 5. In pixels
Methods:
Enable() : Enables the Rubber Band Box (Binds the events)
Disable() : Enables the Rubber Band Box (Unbinds the events)
Attributes:
CallBack: The callback function, if it's replaced you need to
call Enable() again.
"""
self.Canvas = Canvas
self.CallBack = CallBack
self.Tol = Tol
self.Drawing = False
self.RBRect = None
self.StartPointWorld = None
return None
def Enable(self):
"""
Called when you want the rubber band box to be enabled
"""
# bind events:
self.Canvas.Bind(FloatCanvas.EVT_MOTION, self.OnMove )
self.Canvas.Bind(FloatCanvas.EVT_LEFT_DOWN, self.OnLeftDown)
self.Canvas.Bind(FloatCanvas.EVT_LEFT_UP, self.OnLeftUp )
def Disable(self):
"""
Called when you don't want the rubber band box to be enabled
"""
# unbind events:
self.Canvas.Unbind(FloatCanvas.EVT_MOTION)
self.Canvas.Unbind(FloatCanvas.EVT_LEFT_DOWN)
self.Canvas.Unbind(FloatCanvas.EVT_LEFT_UP)
def OnMove(self, event):
if self.Drawing:
x, y = self.StartPoint
Cornerx, Cornery = event.GetPosition()
w, h = ( Cornerx - x, Cornery - y)
if abs(w) > self.Tol and abs(h) > self.Tol:
# draw the RB box
dc = wx.ClientDC(self.Canvas)
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetLogicalFunction(wx.XOR)
if self.RBRect:
dc.DrawRectangle(*self.RBRect)
self.RBRect = (x, y, w, h )
dc.DrawRectangle(*self.RBRect)
event.Skip() # skip so that other events can catch these
def OnLeftDown(self, event):
# Start drawing
self.Drawing = True
self.StartPoint = event.GetPosition()
self.StartPointWorld = event.Coords
def OnLeftUp(self, event):
# Stop Drawing
if self.Drawing:
self.Drawing = False
if self.RBRect:
WH = event.Coords - self.StartPointWorld
wx.CallAfter(self.CallBack, (self.StartPointWorld, WH))
self.RBRect = None
self.StartPointWorld = None

View File

@@ -0,0 +1,7 @@
"""
__init__ for the floatcanvas Utilities package
"""
pass

View File

@@ -29,8 +29,7 @@ It is double buffered, so re-draws after the window is uncovered by
something else are very quick. something else are very quick.
It relies on NumPy, which is needed for speed (maybe, I haven't profiled It relies on NumPy, which is needed for speed (maybe, I haven't profiled
it). It will also use numarray, if you don't have Numeric, but it is properly) and convenience.
slower.
Bugs and Limitations: Lots: patches, fixes welcome Bugs and Limitations: Lots: patches, fixes welcome
@@ -93,6 +92,6 @@ Chris.Barker@noaa.gov
""" """
__version__ = "0.9.10" __version__ = "0.9.18a"