+class ScaledTextBox(TextObjectMixin, DrawObject):
+ """
+ This class creates a TextBox object that is scaled when zoomed. It is
+ placed at the coordinates, x,y.
+
+ If the Width parameter is defined, the text will be wrapped to the width given.
+
+ A Box can be drawn around the text, be specifying:
+ LineWidth and/or FillColor
+
+ A space(margin) can be put all the way around the text, be specifying:
+ the PadSize argument in world coordinates.
+
+ The spacing between lines can be adjusted with the:
+ LineSpacing argument.
+
+ The "Position" argument is a two character string, indicating where
+ in relation to the coordinates the Box 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 The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ Size is the size of the font in world coordinates.
+
+ Family:
+ Font family, a generic way of referring to fonts without
+ specifying actual facename. One of:
+ wx.DEFAULT: Chooses a default font.
+ wx.DECORATIVE: A decorative font.
+ wx.ROMAN: A formal, serif font.
+ wx.SCRIPT: A handwriting font.
+ wx.SWISS: A sans-serif font.
+ wx.MODERN: A fixed pitch font.
+ NOTE: these are only as good as the wxWindows defaults, which aren't so good.
+ Style:
+ One of wx.NORMAL, wx.SLANT and wx.ITALIC.
+ Weight:
+ One of wx.NORMAL, wx.LIGHT and wx.BOLD.
+ Underlined:
+ The value can be True or False. At present this may have an an
+ effect on Windows only.
+
+ Alternatively, you can set the kw arg: Font, to a wx.Font, and the
+ above will be ignored. The size of the font you specify will be
+ ignored, but the rest of its attributes will be preserved.
+
+ The size will scale as the drawing is zoomed.
+
+ Bugs/Limitations:
+
+ As fonts are scaled, they do end up a little different, so you don't
+ get exactly the same picture as you scale up and down, but it's
+ pretty darn close.
+
+ On wxGTK1 on my Linux system, at least, using a font of over about
+ 1000 pts. brings the system to a halt. It's the Font Server using
+ huge amounts of memory. My work around is to max the font size to
+ 1000 points, so it won't scale past there. GTK2 uses smarter font
+ drawing, so that may not be an issue in future versions, so feel
+ free to test. Another smarter way to do it would be to set a global
+ zoom limit at that point.
+
+ The hit-test is done on the entire box. This could be made
+ optional, but I haven't gotten around to it.
+
+ """
+
+ def __init__(self, String,
+ Point,
+ Size,
+ Color = "Black",
+ BackgroundColor = None,
+ LineColor = 'Black',
+ LineStyle = 'Solid',
+ LineWidth = 1,
+ Width = None,
+ PadSize = None,
+ Family = wx.MODERN,
+ Style = wx.NORMAL,
+ Weight = wx.NORMAL,
+ Underlined = False,
+ Position = 'tl',
+ Alignment = "left",
+ Font = None,
+ LineSpacing = 1.0,
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ self.XY = N.array(Point, N.float)
+ self.Size = Size
+ self.Color = Color
+ self.BackgroundColor = BackgroundColor
+ self.LineColor = LineColor
+ self.LineStyle = LineStyle
+ self.LineWidth = LineWidth
+ self.Width = Width
+ if PadSize is None: # the default is just a little bit of padding
+ self.PadSize = Size/10.0
+ else:
+ self.PadSize = float(PadSize)
+ self.Family = Family
+ self.Style = Style
+ self.Weight = Weight
+ self.Underlined = Underlined
+ self.Alignment = Alignment.lower()
+ self.LineSpacing = float(LineSpacing)
+ self.Position = Position
+
+ if not Font:
+ self.FaceName = ''
+ else:
+ self.FaceName = Font.GetFaceName()
+ self.Family = Font.GetFamily()
+ self.Style = Font.GetStyle()
+ self.Underlined = Font.GetUnderlined()
+ self.Weight = Font.GetWeight()
+
+ # Experimental max font size value on wxGTK2: this works OK on
+ # my system. If it's a lot larger, there is a crash, with the
+ # message:
+ #
+ # The application 'FloatCanvasDemo.py' lost its
+ # connection to the display :0.0; most likely the X server was
+ # shut down or you killed/destroyed the application.
+ #
+ # Windows and OS-X seem to be better behaved in this regard.
+ # They may not draw it, but they don't crash either!
+
+ self.MaxFontSize = 1000
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ self.String = String
+ self.LayoutText()
+ self.CalcBoundingBox()
+
+ self.SetPen(LineColor,LineStyle,LineWidth)
+ self.SetBrush(BackgroundColor, "Solid")
+
+
+ def WrapToWidth(self):
+ dc = wx.MemoryDC()
+ bitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
+ DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to.
+ ScaleFactor = float(self.Size) / DrawingSize
+ Width = (self.Width - 2*self.PadSize) / ScaleFactor #Width to wrap to
+ self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ NewStrings = []
+ for s in self.Strings:
+ #beginning = True
+ text = s.split(" ")
+ text.reverse()
+ LineLength = 0
+ NewText = text[-1]
+ del text[-1]
+ while text:
+ w = dc.GetTextExtent(' ' + text[-1])[0]
+ if LineLength + w <= Width:
+ NewText += ' '
+ NewText += text[-1]
+ LineLength = dc.GetTextExtent(NewText)[0]
+ else:
+ NewStrings.append(NewText)
+ NewText = text[-1]
+ LineLength = dc.GetTextExtent(text[-1])[0]
+ del text[-1]
+ NewStrings.append(NewText)
+ self.Strings = NewStrings
+
+ def ReWrap(self, Width):
+ self.Width = Width
+ self.LayoutText()
+
+ def LayoutText(self):
+ """
+
+ Calculates the positions of the words of text.
+
+ This isn't exact, as fonts don't scale exactly.
+ To help this, the position of each individual word
+ is stored separately, so that the general layout stays
+ the same in world coordinates, as the fonts scale.
+
+ """
+ self.Strings = self.String.split("\n")
+ if self.Width:
+ self.WrapToWidth()
+
+ dc = wx.MemoryDC()
+ bitmap = wx.EmptyBitmap(1, 1)
+ dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
+
+ DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to.
+ ScaleFactor = float(self.Size) / DrawingSize
+
+ self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ TextHeight = dc.GetTextExtent("X")[1]
+ SpaceWidth = dc.GetTextExtent(" ")[0]
+ LineHeight = TextHeight * self.LineSpacing
+
+ LineWidths = N.zeros((len(self.Strings),), N.float)
+ y = 0
+ Words = []
+ AllLinePoints = []
+
+ for i, s in enumerate(self.Strings):
+ LineWidths[i] = 0
+ LineWords = s.split(" ")
+ LinePoints = N.zeros((len(LineWords),2), N.float)
+ for j, word in enumerate(LineWords):
+ if j > 0:
+ LineWidths[i] += SpaceWidth
+ Words.append(word)
+ LinePoints[j] = (LineWidths[i], y)
+ w = dc.GetTextExtent(word)[0]
+ LineWidths[i] += w
+ y -= LineHeight
+ AllLinePoints.append(LinePoints)
+ TextWidth = N.maximum.reduce(LineWidths)
+ self.Words = Words
+
+ if self.Width is None:
+ BoxWidth = TextWidth * ScaleFactor + 2*self.PadSize
+ else: # use the defined Width
+ BoxWidth = self.Width
+ Points = N.zeros((0,2), N.float)
+
+ for i, LinePoints in enumerate(AllLinePoints):
+ ## Scale to World Coords.
+ LinePoints *= (ScaleFactor, ScaleFactor)
+ if self.Alignment == 'left':
+ LinePoints[:,0] += self.PadSize
+ elif self.Alignment == 'center':
+ LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor)/2.0
+ elif self.Alignment == 'right':
+ LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor-self.PadSize)
+ Points = N.concatenate((Points, LinePoints))
+
+ BoxHeight = -(Points[-1,1] - (TextHeight * ScaleFactor)) + 2*self.PadSize
+ #(x,y) = self.ShiftFun(self.XY[0], self.XY[1], BoxWidth, BoxHeight, world=1)
+ Points += (0, -self.PadSize)
+ self.Points = Points
+ self.BoxWidth = BoxWidth
+ self.BoxHeight = BoxHeight
+ self.CalcBoundingBox()
+
+ def CalcBoundingBox(self):
+
+ """
+
+ Calculates the Bounding Box
+
+ """
+
+ w, h = self.BoxWidth, self.BoxHeight
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world=1)
+ self.BoundingBox = BBox.asBBox(((x, y-h ),(x + w, y)))
+
+ def GetBoxRect(self):
+ wh = (self.BoxWidth, self.BoxHeight)
+ xy = (self.BoundingBox[0,0], self.BoundingBox[1,1])
+
+ return (xy, wh)
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ xy, wh = self.GetBoxRect()
+
+ Points = self.Points + xy
+ Points = WorldToPixel(Points)
+ xy = WorldToPixel(xy)
+ wh = ScaleWorldToPixel(wh) * (1,-1)
+
+ # compute the font size:
+ Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length
+ ## Check to see if the font size is large enough to blow up the X font server
+ ## If so, limit it. Would it be better just to not draw it?
+ ## note that this limit is dependent on how much memory you have, etc.
+ Size = min(Size, self.MaxFontSize)
+
+ self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName)
+ dc.SetFont(self.Font)
+ dc.SetTextForeground(self.Color)
+ dc.SetBackgroundMode(wx.TRANSPARENT)
+
+ # Draw The Box
+ if (self.LineStyle and self.LineColor) or self.BackgroundColor:
+ dc.SetBrush(self.Brush)
+ dc.SetPen(self.Pen)
+ dc.DrawRectanglePointSize(xy , wh)
+
+ # Draw the Text
+ dc.DrawTextList(self.Words, Points)
+
+ # Draw the hit box.
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(xy, wh)
+
+class Bitmap(TextObjectMixin, DrawObject, ):
+ """
+ This class creates a bitmap object, placed at the coordinates,
+ x,y. the "Position" argument is a two charactor string, indicating
+ where in relation to the coordinates the bitmap 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 The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ The size is fixed, and does not scale with the drawing.
+
+ """
+
+ def __init__(self,Bitmap,XY,
+ Position = 'tl',
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Bitmap = Bitmap
+ elif type(Bitmap) == wx._core.Image:
+ self.Bitmap = wx.BitmapFromImage(Bitmap)
+
+ # Note the BB is just the point, as the size in World coordinates is not fixed
+ self.BoundingBox = BBox.asBBox( (XY,XY) )
+
+ self.XY = XY
+
+ (self.Width, self.Height) = self.Bitmap.GetWidth(), self.Bitmap.GetHeight()
+ self.ShiftFun = self.ShiftFunDict[Position]
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ XY = WorldToPixel(self.XY)
+ XY = self.ShiftFun(XY[0], XY[1], self.Width, self.Height)
+ dc.DrawBitmapPoint(self.Bitmap, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (self.Width, self.Height) )
+
+class ScaledBitmap(TextObjectMixin, DrawObject, ):
+ """
+
+ This class creates a bitmap object, placed at the coordinates, XY,
+ of Height, H, in World coorsinates. The width is calculated from the
+ aspect ratio of the bitmap.
+
+ the "Position" argument is a two charactor string, indicating
+ where in relation to the coordinates the bitmap 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 The
+ position refers to the position relative to the text itself. It
+ defaults to "tl" (top left).
+
+ The size scales with the drawing
+
+ """
+
+ def __init__(self,
+ Bitmap,
+ XY,
+ Height,
+ Position = 'tl',
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Image = Bitmap.ConvertToImage()
+ elif type(Bitmap) == wx._core.Image:
+ self.Image = Bitmap
+
+ self.XY = XY
+ self.Height = Height
+ (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight()
+ self.Width = self.bmpWidth / self.bmpHeight * Height
+ self.ShiftFun = self.ShiftFunDict[Position]
+ self.CalcBoundingBox()
+ self.ScaledBitmap = None
+ self.ScaledHeight = None
+
+ def CalcBoundingBox(self):
+ ## this isn't exact, as fonts don't scale exactly.
+ w, h = self.Width, self.Height
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+ self.BoundingBox = BBox.asBBox( ( (x, y-h ), (x + w, y) ) )
+
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ XY = WorldToPixel(self.XY)
+ H = ScaleWorldToPixel(self.Height)[0]
+ W = H * (self.bmpWidth / self.bmpHeight)
+ if (self.ScaledBitmap is None) or (H <> self.ScaledHeight) :
+ self.ScaledHeight = H
+ Img = self.Image.Scale(W, H)
+ self.ScaledBitmap = wx.BitmapFromImage(Img)
+
+ XY = self.ShiftFun(XY[0], XY[1], W, H)
+ dc.DrawBitmapPoint(self.ScaledBitmap, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (W, H) )
+
+class ScaledBitmap2(TextObjectMixin, DrawObject, ):
+ """
+
+ An alternative scaled bitmap that only scaled the required amount of
+ the main bitmap when zoomed in: EXPERIMENTAL!
+
+ """
+
+ def __init__(self,
+ Bitmap,
+ XY,
+ Height,
+ Width=None,
+ Position = 'tl',
+ InForeground = False):
+
+ DrawObject.__init__(self,InForeground)
+
+ if type(Bitmap) == wx._gdi.Bitmap:
+ self.Image = Bitmap.ConvertToImage()
+ elif type(Bitmap) == wx._core.Image:
+ self.Image = Bitmap
+
+ self.XY = N.array(XY, N.float)
+ self.Height = Height
+ (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight()
+ self.bmpWH = N.array((self.bmpWidth, self.bmpHeight), N.int32)
+ ## fixme: this should all accommodate different scales for X and Y
+ if Width is None:
+ self.BmpScale = float(self.bmpHeight) / Height
+ self.Width = self.bmpWidth / self.BmpScale
+ self.WH = N.array((self.Width, Height), N.float)
+ ##fixme: should this have a y = -1 to shift to y-up?
+ self.BmpScale = self.bmpWH / self.WH
+
+ print "bmpWH:", self.bmpWH
+ print "Width, Height:", self.WH
+ print "self.BmpScale", self.BmpScale
+ self.ShiftFun = self.ShiftFunDict[Position]
+ self.CalcBoundingBox()
+ self.ScaledBitmap = None # cache of the last existing scaled bitmap
+
+ def CalcBoundingBox(self):
+ ## this isn't exact, as fonts don't scale exactly.
+ w,h = self.Width, self.Height
+ x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
+ self.BoundingBox = BBox.asBBox( ((x, y-h ), (x + w, y)) )
+
+ def WorldToBitmap(self, Pw):
+ """
+ computes bitmap coords from World coords
+ """
+ delta = Pw - self.XY
+ Pb = delta * self.BmpScale
+ Pb *= (1, -1) ##fixme: this may only works for Yup projection!
+ ## and may only work for top left position
+
+ return Pb.astype(N.int_)
+
+ def _DrawEntireBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+ """
+ this is pretty much the old code
+
+ Scales and Draws the entire bitmap.
+
+ """
+ XY = WorldToPixel(self.XY)
+ H = ScaleWorldToPixel(self.Height)[0]
+ W = H * (self.bmpWidth / self.bmpHeight)
+ if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (0, 0, self.bmpWidth, self.bmpHeight, W, H) ):
+ #if True: #fixme: (self.ScaledBitmap is None) or (H <> self.ScaledHeight) :
+ self.ScaledHeight = H
+ print "Scaling to:", W, H
+ Img = self.Image.Scale(W, H)
+ bmp = wx.BitmapFromImage(Img)
+ self.ScaledBitmap = ((0, 0, self.bmpWidth, self.bmpHeight , W, H), bmp)# this defines the cached bitmap
+ else:
+ print "Using Cached bitmap"
+ bmp = self.ScaledBitmap[1]
+ XY = self.ShiftFun(XY[0], XY[1], W, H)
+ dc.DrawBitmapPoint(bmp, XY, True)
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XY, (W, H) )
+
+ def _DrawSubBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
+ """
+ Subsets just the part of the bitmap that is visible
+ then scales and draws that.
+
+ """
+ BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+ BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld))
+
+ XYs = WorldToPixel(self.XY)
+ # figure out subimage:
+ # fixme: this should be able to be done more succinctly!
+
+ if BBbitmap[0,0] < 0:
+ Xb = 0
+ elif BBbitmap[0,0] > self.bmpWH[0]: # off the bitmap
+ Xb = 0
+ else:
+ Xb = BBbitmap[0,0]
+ XYs[0] = 0 # draw at origin
+
+ if BBbitmap[0,1] < 0:
+ Yb = 0
+ elif BBbitmap[0,1] > self.bmpWH[1]: # off the bitmap
+ Yb = 0
+ ShouldDraw = False
+ else:
+ Yb = BBbitmap[0,1]
+ XYs[1] = 0 # draw at origin
+
+ if BBbitmap[1,0] < 0:
+ #off the screen -- This should never happen!
+ Wb = 0
+ elif BBbitmap[1,0] > self.bmpWH[0]:
+ Wb = self.bmpWH[0] - Xb
+ else:
+ Wb = BBbitmap[1,0] - Xb
+
+ if BBbitmap[1,1] < 0:
+ # off the screen -- This should never happen!
+ Hb = 0
+ ShouldDraw = False
+ elif BBbitmap[1,1] > self.bmpWH[1]:
+ Hb = self.bmpWH[1] - Yb
+ else:
+ Hb = BBbitmap[1,1] - Yb
+
+ FullHeight = ScaleWorldToPixel(self.Height)[0]
+ scale = FullHeight / self.bmpWH[1]
+ Ws = int(scale * Wb + 0.5) # add the 0.5 to round
+ Hs = int(scale * Hb + 0.5)
+ if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (Xb, Yb, Wb, Hb, Ws, Ws) ):
+ Img = self.Image.GetSubImage(wx.Rect(Xb, Yb, Wb, Hb))
+ Img.Rescale(Ws, Hs)
+ bmp = wx.BitmapFromImage(Img)
+ self.ScaledBitmap = ((Xb, Yb, Wb, Hb, Ws, Ws), bmp)# this defines the cached bitmap
+ #XY = self.ShiftFun(XY[0], XY[1], W, H)
+ #fixme: get the shiftfun working!
+ else:
+ print "Using cached bitmap"
+ ##fixme: The cached bitmap could be used if the one needed is the same scale, but
+ ## a subset of the cached one.
+ bmp = self.ScaledBitmap[1]
+ dc.DrawBitmapPoint(bmp, XYs, True)
+
+ if HTdc and self.HitAble:
+ HTdc.SetPen(self.HitPen)
+ HTdc.SetBrush(self.HitBrush)
+ HTdc.DrawRectanglePointSize(XYs, (Ws, Hs) )
+
+ def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
+ BBworld = BBox.asBBox(self._Canvas.ViewPortBB)
+ ## first see if entire bitmap is displayed:
+ if BBworld.Inside(self.BoundingBox):
+ print "Drawing entire bitmap with old code"
+ self._DrawEntireBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+ return None
+ elif BBworld.Overlaps(self.BoundingBox):
+ #BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld))
+ print "Drawing a sub-bitmap"
+ self._DrawSubBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc)
+ else:
+ print "Not Drawing -- no part of image is showing"
+
+class DotGrid:
+ """
+ An example of a Grid Object -- it is set on teh FloatCAnvas with one of:
+
+ FloatCanvas.GridUnder = Grid
+ FloatCanvas.GridOver = Grid
+
+ It will be drawn every time, regardless of the viewport.
+
+ In its _Draw method, it computes what to draw, given the ViewPortBB
+ of the Canvas it's being drawn on.
+
+ """
+ def __init__(self, Spacing, Size = 2, Color = "Black", Cross=False, CrossThickness = 1):
+
+ self.Spacing = N.array(Spacing, N.float)
+ self.Spacing.shape = (2,)
+ self.Size = Size
+ self.Color = Color
+ self.Cross = Cross
+ self.CrossThickness = CrossThickness
+
+ def CalcPoints(self, Canvas):
+ ViewPortBB = Canvas.ViewPortBB
+
+ Spacing = self.Spacing
+
+ minx, miny = N.floor(ViewPortBB[0] / Spacing) * Spacing
+ maxx, maxy = N.ceil(ViewPortBB[1] / Spacing) * Spacing
+
+ ##fixme: this could use vstack or something with numpy
+ x = N.arange(minx, maxx+Spacing[0], Spacing[0]) # making sure to get the last point
+ y = N.arange(miny, maxy+Spacing[1], Spacing[1]) # an extra is OK
+ Points = N.zeros((len(y), len(x), 2), N.float)
+ x.shape = (1,-1)
+ y.shape = (-1,1)
+ Points[:,:,0] += x
+ Points[:,:,1] += y
+ Points.shape = (-1,2)
+
+ return Points
+
+ def _Draw(self, dc, Canvas):
+ Points = self.CalcPoints(Canvas)
+
+ Points = Canvas.WorldToPixel(Points)
+
+ dc.SetPen(wx.Pen(self.Color,self.CrossThickness))
+
+ if self.Cross: # Use cross shaped markers
+ #Horizontal lines
+ LinePoints = N.concatenate((Points + (self.Size,0),Points + (-self.Size,0)),1)
+ dc.DrawLineList(LinePoints)
+ # Vertical Lines
+ LinePoints = N.concatenate((Points + (0,self.Size),Points + (0,-self.Size)),1)
+ dc.DrawLineList(LinePoints)
+ pass
+ else: # use dots
+ ## Note: this code borrowed from Pointset -- itreally shouldn't be repeated here!.
+ if self.Size <= 1:
+ dc.DrawPointList(Points)
+ elif self.Size <= 2:
+ dc.DrawPointList(Points + (0,-1))
+ dc.DrawPointList(Points + (0, 1))
+ dc.DrawPointList(Points + (1, 0))
+ dc.DrawPointList(Points + (-1,0))
+ else:
+ dc.SetBrush(wx.Brush(self.Color))
+ radius = int(round(self.Size/2))
+ ##fixme: I really should add a DrawCircleList to wxPython
+ if len(Points) > 100:
+ xy = Points
+ xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Size ), 1 )
+ dc.DrawEllipseList(xywh)
+ else:
+ for xy in Points:
+ dc.DrawCircle(xy[0],xy[1], radius)
+
+