[Drawkit] Hit testing at high scale factor
Graham Cox
graham.cox at bigpond.com
Fri Jun 27 17:17:32 PDT 2008
Hi Brad,
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.
>
> Oddly, this is not a problem for control points, only the selection
> and movement of the bulk paths. I've traveled down the hit test
> chain, and it looks like the appropriate transformed view
> coordinates are being used all the way down. The object bounds are
> giving me some weird results, in that they are showing a bounds of
> 6.0 points for the small paths and objects we're working with, when
> the bounds should be around 0.12 points or lower. There are some
> 6.0 point constants in DKKnob, but I checked that and it appears to
> be scaling properly to the small sizes. In any case, the bounds
> should just be the start of the hit test, with the actual testing
> done by lower-level items.
>
> This weirdness happens with both custom DKDrawablePath subclasses as
> well as DKDrawablePath itself. I haven't tried DKDrawableShape to
> see how it responds.
>
I certainly see what you're talking about. I'll look into it.
One thing that might help you is to turn on some simple debugging aids
built in to DK. You can display the bounding box for a drawable and
other things. The easiest way to do this is to add a debug menu to
your app whose items target First Responder (nil) and the following
actions:
- (IBAction) toggleShowBBox:(id) sender;
- (IBAction) toggleClipToBBox:(id) sender;
- (IBAction) toggleShowPartcodes:(id) sender;
- (IBAction) toggleShowTargets:(id) sender;
This ends up targeting a single selected object, so you can toggle
these attributes for an individual item in the drawing.
> Also, the point DKDrawablePath subclass seems to have a weird
> selection behavior that may be related to this. When you move the
> selection box over the point, it will be selected, but as you grow
> the box to a certain size, the point will become deselected. If you
> shrink the box, it will become selected again. This is less
> noticeable on the DKDrawablePaths, but I still see some inaccuracies
> in when the paths are selected by the box and when they are not.
This is easier to explain. When the selection rect touches an object,
it uses one hit test, but when it fully encloses it, it uses a
different one (faster). I suspect when it transitions to the second
test it's not sensing the hit. How it works is that it intersects the
bounds of the object with the selection rect. If the resulting rect is
equal to the bounds, it knows that the selection rect fully surrounds
the bounds and so it *must* be selected, without having to perform the
more expensive bitmap test. So if your object is returning an
incorrect bounds, this simpler test might fail.
The solution probably lies in your -bounds method. You likely need to
override this for your point object because the inherited method may
not be adequate. I also see that the bounds calculated by
DKDrawablePath is far too big at large scales (this might have a
bearing on the other problem), so this looks like the area to focus on.
I'll investigate and let you know what else I find.
cheers, Graham
More information about the Drawkit
mailing list