Robin Dunn wrote:
> This brings up my question, which it looks like it not going to be easy
> to answer. What I would like to be able to do is draw a bunch of objects
> to a wxMemoryDC, each with a different color, and then use dc.GetPixel
> to find out the color of a point, and therefor the object that is there.
> The problem here is that wxColor assumes a 24 bit representation, so if
> your wxBitmap is not 24 bits, the colors are translated when drawn, and
> then back again when dc.GetPixel() is called. I thought I'd be OK if I
> specified depth = 24 when I create the wxBitmap, but now it sounds like
> that might not work. so far I have tested it on my Linux box, which is
> running at 24bpp, and it works very nicely.
Sounds like a pretty expensive way to do this. Why not just give the
objects the ability to specify if they intersect a point (a HitTest method)
and then just travers your list and use object that last returned true for
HitTest? Then you don't have to make any (expensive!) API calls at all.
Well, that depends on what you mean by expensive. It's "common wisdom"
that sometimes you trade memory for speed, and this is all the more true
with interpretted languages. Anyway, when I'm dealing with up to
thousands of objects, that might be fairly complex polylines or
polygons, looping through and computing a hit-test on each object could
be pretty darn slow. A point-in-polygon test is a fair bit of
computation (not very fast in Python), and unless I can find a niftier
algorythm, a point-on-a-line can be even worse.
What API calls here do you think are expensive? It could take a while to
draw to the bitmap, but once I've done that, all I need is a single
GetPixel() call, and a dictionary lookup to find the object hit. With my
tests, it works very fast. I compared it to a simple hit-test with 1600
rectangles, and it is noticably faster (on a 1.2Ghz PIV) with the bitmap
approach. It is fast enough to work well on a MouseMove event, and I
don't think the hit-test approach would be.
Also, I think it's kind of a nifty solution, as I don't have to write a
bunch of hit-test code for every kind of object I want to draw. I got
the idea from PySketch, which takes a much more expensive approach: at
each mouse click, it creates a dc and re-draws each item to see if it is
hit! My approach will take some memory (very cheep these days), but is
pretty darn fast.
All that been said, I do feel like I am majorly re-inventing the wheel
here. It frustrates me to no end that this kind of thing isn't built
into the API. I havn't check out Klass' wxCanvas for a while, maybe it's
time to do that, he has written a lot of code to solve these kinds of
problems. Another option is OpenGL, but as I don't need 3-d it seemed
overkill. Maybe not.
I am open to suggestions, it looks like the color-depth problem may kill
this approach anyway. Does anyone know of a good source of algorythms
for hit-tests and this kind of thing?
wxPallet will probably help for 8-bit depth, but I don't know if will be any
help for other depths...
8 bit won't help, as I only think this is a good idea because I may have
to deal with thousands of objects. I did a little more checking, and I
was wrong: wxEmptyBitmap(x,y,depth) only works if depth is -1 or the
current depth of your display. Interestingly, the call doesn't create
any sort of error, it just creates a bitmap that reports a size of -1,
ans for every GetPixel() call, I get some wierd number.
At the moment, what I have works for a depth of 24, and should work for
higher depths, though I havn't tested that yet.
-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