PseudoDC 1.0

Yeah, the clipping in there now only clips objects if they are
completely off-screen so you can have lots of off-screen objects without
incurring too much overhead. If you have lots of objects on the screen
(even if many are not visible due to overdraw) then it slows down a lot.
However, even then the drawing speed is much faster than in Python and
comparable to using DrawXXXList functions. The problem with my demo and
high densities it that I issue a Refresh() every 50ms (or as fast as the
timer can run). If the re-draw time goes above 50ms then the events
stack up and it just draws over and over as fast as it can. If you
disable the timer or set the timer rate to say 200ms then it shouldn't
eat up the CPU constantly. I doubt anyone will actually use this for
animation. I was just trying to show that objects can be moved around
without being redrawn. I might see if I can think of something besides
animation to show the TranslateID. The easiest would be to allow the
user to drag things around but that requires the hit testing I haven't
written yet :slight_smile:

I don't expect there is anything simple that can be done to make
high-overdraw situations faster. Any limitations at this point are due
to speed limits of using a wx.DC for drawing rather than overhead of
Python or PseudoDC. Something like an OpenGL dc with a wx.DC interface
could use a Z-buffer to limit overdraw and thus not draw stuff that is
covered up. Besides it would be much faster anyway due to better
hardware acceleration of openGL. Other then that, I'm not sure anything
could be done.

Just to show one real-world application, I attached a screen-shot of the
application I mentioned that's using this. All the controls in the
center scrolled window are being drawn using a PseudoDC except the
scrollbars. So with a large number of objects with close to full
coverage of a window, the PseudoDC is still able to give very smooth
scrolling.

-Paul

···

-----Original Message-----
From: Robin Dunn [mailto:robin@alldunn.com]
Sent: Tuesday, June 20, 2006 6:22 PM
To: wxPython-dev@lists.wxwidgets.org
Subject: Re: [wxPython-dev] PseudoDC 1.0

Lanier, Paul wrote:

Hey Robin,

I've finally got what I think is a good initial version of the

PseudoDC.

Attached is the .cpp/.h/.i and PseudoDC.py which is a demo that fits
in the existing wxPython demo framework. In addition to the demo,
I've fiddled around with it some just to make sure that every method
actually works. Also, I've already using this in an application of
mine that is being used by several people where I work.

I do already have a few things I plan to add in the future:
- Object level hit testing to easily match (x,y) with an object id.
- Methods to manipulate the Z order of objects

Also, I didn't mirror every method from wx.DC because not all the
methods are useful in a recorded list. The attached file diff.out is
a list of all the methods not mirrored. If you think I should add
something then let me know. In addition to not mirroring some
methods, a few methods had return values that aren't supported in
PseudoDC since I won't know the return value until the list is played

back.

Let me know if you need something else. I did all my testing with
2.6.3.2 so the .i file I have is in that style.

Looks good. However I noticed that when the density of visible objects
increases then so does the CPU overhead when drawing the items. For
example, setting the demo parameters like this:

W = 1000
H = 1000
SHAPE_COUNT = 1000

will max out the CPU on my Linux box. So much so in fact that all of
the time is spend servicing the timer and other events are not being
sent. but if I increase the width and height to 10000 (thus greatly
lowering the object density) then it does fine. So I wonder if you can
think of any additional strategies for optimizations that would fit in
with what you have so far?

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-dev-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-dev-help@lists.wxwidgets.org

Paul,

I've taken a quick look at your sample code. I'm not set up to compile wxPython at the moment, so I haven't actually tested it.

I think you had mentioned when you first started this project that you thought it might be useful in FloatCanvas. Indeed it might.

However, there is one key issue. The whole point of FloatCanvas is that the user can work in arbitrary floating point coordinates, and then can view the images zoomed or scrolled as they wish. As a result, it's not very common to need to re-draw everything, but at the same zoom and scroll level.

Scrolling:
It looks like you have handled the scrolling part, as you can specify a clipping rectangle. Is this automated for drawing to to a DC that is smaller than the area used? -- though I guess there is an issue with where the origin is. I haven't used a ScrolledWindow for ages, but I guess that that PrepareDC takes care of that. However, it may be more flexible to be able to provide a "origin" that tells the PseudoDC how much to shift the coordinates, so you could use int with things other than a ScrolledWindow. It could then set up the clipping rect itself to fit the DC it is drawing to.

Setting the clipping Rect explicitly would be good too, as sometimes you know that you don't need to re-draw the entire Window. I've run into this with FloatCanvas, but haven't addressed that yet -- it always re-draws the whole window when it needs to re-draw any of it.

By the way, do you keep track of the bounding box of each object, so that you can not bother to draw objects that are well out of bounds?

Zooming:
This doesn't appear to be handled at all by PseudoDC. Key here for FloatCanvas is that zooming can be a common operation. As a result, I haven't even bothered to cache the pixel coords of an object. Rather, I just re-calculate the zoomed coordinates whenever I draw the object.

Between that zoom and the shift, it's one 2 multiplies and two additions per point. Also, objects with a dimension, like width, need to scale the width. That's just a multiply.

At this point, I'm using numpy to do those calculation, and I think they go faster than the drawing calls themselves. However, for maximum performance, I've been thinking of going to C++, and doing the scaling, shifting and drawing all in C++. As you've done much of that work for PseudoDC, I wonder if you'd consider adding the zooming bit too.

The catch is that this is C++, and now everything changes to Floating Point coordinates. Of course, you can overload the methods, but that's a bit of a pain in the wrappers.

So is all this worth it? I wrote a bunch of the DrawXXXList code, and found that it was well worth if for simple stuff, like Points, and maybe lines, but for more complex objects, the extra Python function call overhead was swamped by the time it took to draw anyway.

Have you done any profiling? Is PseudoDC significantly faster than just looping through the objects in Python and drawing them?

Thanks,

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov