[Drawkit] Hit testing at high scale factor
Graham Cox
graham.cox at bigpond.com
Fri Jun 27 22:59:51 PDT 2008
>
> On 28 Jun 2008, at 8:34 am, Brad Larson wrote:
>
>> I've been experiencing a glitch with hit testing that I can't seem
>> to track down and thought I'd check to see if there was an obvious
>> solution to it. What I'm experiencing is that when I click to the
>> up and left of an object, I select it, even though I'm a ways away
>> from the object. This happens in a square starting a the object
>> and going up and to the left. It does not occur below or to the
>> right of the object. From logging positions, it looks like the hit
>> testing is marking a hit in a region up to 1.0 points to the left
>> and up of the object. That is, any click within that region is a
>> hit on the object. At the high scale factors (~500) we use for our
>> micron units, this can be a significant distance and really
>> complicate object selection.
OK, I found the main problem. In DKDrawableObject, -pointHitsPath: is
using a test rect of size {1,1}. At very high zooms that's way too
large, resulting in a "point" becoming quite a substantial rect that
is likely to extend significantly to the right and below the actual
point being tested. That's why clicking above and to the left of the
object was counting as a hit.
The fix is easy:
- (BOOL) pointHitsPath:(NSPoint) p
{
if( NSPointInRect( p, [self bounds]))
{
NSRect pr = NSMakeRect( p.x, p.y, 1e-4, 1e-4 );
return [self rectHitsPath:pr];
}
return NO;
}
Basically the size of the test rect is made very small, so the
precision is much greater. I'm not sure how small this should be but
the 1e-4 seems pretty precise and still works OK at the macro scale.
Going to 1e-6 stops working, so the optimum is probably somewhere
between the two. I suppose also to be really pedantic the test rect
should be centred on the point not dangling below/right.
>
> I'll investigate and let you know what else I find.
I also found that at very high zooms the bounds calculations are
frequently way too generous, mostly because of outsetting rects by 0.5
in a few places which of course at high zooms becomes a very large
amount. This isn't a major problem as hit testing only uses the bounds
for a first pass rejection, but it should be fixed (and is, in my
copy). The excess bounds will also be allowing too much drawing to
occur which, if you have many very small objects in your field of
view, could be slower than it need be.
Note that the debugging bounds display I mentioned also insets by 0.5,
so at these scales will be much less useful. I've fixed that too.
cheers, Graham
More information about the Drawkit
mailing list