PDA

View Full Version : how to implement :isPointInPath



akaiwall
03-31-2009, 11:09 PM
hey, buddies:

I am currently involved in a project of implementing a canvas element supporting for our browser.
in our last version we use gdi+ library to draw stuff , here in this version , we changed to use OpenVG.

i encountered a problem when i want to implement a function as : isPointInPath.
The detailed definition defined in html5 protocol is as below:

The isPointInPath(x, y) method must return true if the point given by the x and y coordinates passed to the method, when treated as coordinates in the canvas coordinate space unaffected by the current transformation, is inside the current path as determined by the non-zero winding number rule; and must return false otherwise. Points on the path itself are considered to be inside the path. If either of the arguments is infinite or NaN, then the method must return false.

In GDI+ library, the class region provides a similar function like isVisible which checks whether a specific
point locates inside the region . then you can create a region with your path then call this member function
to easily get the result.

but here in OpenVG there is no such a easy way to do that. as least , there is no region.

my first thought is to fill the Path to a temporary buffer-like surface ( masklayer? vgimage? i'm still not sure yet.)
then read the pixel value of that point to check the result. It seem to work ,although i not yet try it.

however , it is really ineffective and memory-consuming, especally at some occasions with intensive calls to the isPointInPath.
It seems to be a fundmental problem in computer graphics , yet im a beginner about that.

I wonder if there is a better algorithemic approch to handle this problem using the existing OpenVG functions.

Ivo Moravec
04-01-2009, 08:57 AM
Hmm...

There is no OpenVG API commands that can do that. At least I can't think of another way get the functionality you desire. Rendering into a offscreen buffer (make sure to turn off anti-aliasing) is probably the only way (try an EGL pbuffer if available [be careful rendering into a mask layer - I don't think there is a way to directly read back from a masklayer or the alphamask]).

I assume vgPathBounds() is not accurate enough for you in all cases?
Still - might be useful to find out if it's good enough for some of the cases. I mean it's really import to know if it's in the path or just the region near the path? I would imagine that for a lot of uses, it should be sufficient.

In any event, you should probably call vgPathBounds() to determine whether you need the more computationally intensive full test in either case. Also, since your path data really shouldn't be changing all that much - especially if it's in a computationally expensive task - you should probably buffer the result of any path rendering you do, and simply read back the correct pixel location from the buffer if a rendering of the path already exists. While a bit of a memory hog, this should be pretty fast. If memory becomes an issue, try seeing if you can get away with a rough approximation by scaling down the render by a factor of 2 or 4 (vgScale()) [the scaling should speed up the render too].

One of the problems here preventing this is how OpenVG thinks about paths.
In OpenVG a path is neither stroked nor filled until a draw call, so askinig whether a point is inside the path could be taken to mean several thing known only at draw time - which draw mode to use?, which fill rule?, stroke width?, join styles?, etc. The parameters that define the shape of the path are simply not gauranteed to be set up correctly until the draw call. This is why calls like vgPathBounds() and vgTransformedPathBounds() cannot take into acount things like miter joins and line widths, and instead define their operation on a hypotheical filled path where it makes no difference.