+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)
+
+