Click a CurveShape on a canvas

The complaint was my method “took too long” because a Bezier Curve is a time-based equation… Yet the proposed solutions attempt to look at the color of pixels? How does this not have to do as much if not more calculations to figure out what pixels to look at? Not to mention, the shape has to be either on the screen, or redrawn in a graphics context… allowances would probably have to be made for Retina/HDPI…

Considering it bound by a rectangle doesn’t give you the answer, it simply indicates if you should bother looking for an answer or not. The question was “point on a curve”, not the same as “point in an enclosed space”…

I won’t mention the math is different if it is an ARC, vs Quad Bezier, vs

C’mon Dave, do you need me to explain how picking a colour off a single pixel is quicker than iterating through a huge loop with loads of maths inside? :slight_smile:

The colour profile affects images that don’t come anywhere near being displayed on the screen? That is genius :frowning: shakes fist at mac :wink:

Yes AABB is the quickest way to narrow down which curve to look at if there curves are nowhere near overlapping.

You could always convert this code:

You’ll probably need:

https://forum.xojo.com/29743-fp-plugin-8-0/0

I’m no maths guy, so good luck with that :slight_smile:

MacOS has:

https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

see “Doing Hit-Detection on a Path” at the bottom of that page.

Windows has:

https://msdn.microsoft.com/en-us/library/ms969920.aspx?f=255&MSPPError=-2147217396

See “Hit Testing Bézier Curves” about 2/3 the way down.

Julian… please do…
the correct way to handle an object is NOT by its visual representation… (I’ll bet the need for scaling (ie. zooming in/out) has not been considered)… nor the accuracy of various resolution display devices, color-spaces et’al.
You admit you are not “a math guy”… well I am (at least well above average)…
but then this isn’t my project, and like so many other suggestions, I can’t make you or anyone else use them…
but I don’t offer them lightly… that was the result of weeks of research to solve EXACTLY the problem the OP is facing… and it works, it works well, it works quickly, it works based on the geometry of the object, not the visual representation, therefore scale is not a factor in the answer (other than mapping the mouse to the coodinate space of the object)

not to mention your links just support my statements :slight_smile:

Color calibration and matching
In order to make what you see on screen be the same color as what you get in print etc colors are run through a device profile that will alter that to be the right color so it matches
You used to be able to set a device to use uncalibrated and unprofiled colors
Not sure if you still can

If you have multiple uncalibrated monitors and drag something from one to another does the color appear to change ?
With calibrated monitors this doesnt (at least not here on my 3 monitors)
Yay color profiles !

[quote=334819:@Dave S]Julian… please do…
the correct way to handle an object is NOT by its visual representation[/quote]

Tell that to all the game makers that use pixel perfect collision detection, I drew you a picture as I didn’t want to waste time writing 1000 words…

ok… we shall agree to disagree…
not sure what you little movie shows or doen’t

[quote=334842:@Dave S]ok… we shall agree to disagree…
not sure what you little movie shows or doen’t[/quote]

I’m not disagreeing with you, I’m just providing an alternate solution.

I’ve explained the principle and drawn you a picture, sorry if you still don’t understand :slight_smile:

I understand… and totally disagree with mining the pixels of a picture to determine the mathematical relationship between a curve and a point (mouse)…

and the movie proves and disproves nothing… as you didn’t indicate the behind the scenes
my Snapdragon draws things that look exactly like what you showed… and basically it moves ONE point (which is already known)

[quote=334873:@Dave S]I understand… and totally disagree with mining the pixels of a picture to determine the mathematical relationship between a curve and a point (mouse)…

and the movie proves and disproves nothing… as you didn’t indicate the behind the scenes
my Snapdragon draws things that look exactly like what you showed… and basically it moves ONE point (which is already known)[/quote]

Cool, you’re welcome to disagree if you wish, whatever method you choose is up to you :slight_smile:

The mathematical relationship between a curve and a point (mouse) isn’t what Edwin wanted, he doesn’t want to know how far down the line he’s clicked or which segment he’s clicked on, he just wants to know what curve is clicked on when he pressed the mouse.

Here’s a “proof of concept” that took less than 60 minutes to put together (never used half of this stuff before, so it took longer that it should have).

https://www.dropbox.com/s/5qdd702bpnbfstd/BezierPick.xojo_binary_project?dl=1

Using this method will work for any shape you throw at it for up to 24bit’s worth of unique items (approx 16.7m), I’m guessing that is plenty.

I’m not saying its the best way or the most memory efficient, but its a totally valid and usable method of performing what Edwin required from his original post.

Now here’s the rub:

Its faster than iterating through the curves, it wont slow down the more curves you have on the image and it’ll work for any type or number of segments on the curve, it’ll even work for other types of objects! extra fancy :wink:

The only overhead is that you double your picture allocation for the “hit mask” to check against and you draw twice (once to actual and once to the hit mask)

So, back to the original question you had about the concept:

Lets say there’s 10 curves in close proximity and you click slightly off the line, all I have to do is:

Mask.Graphics.Pixel(x, y)

Vs

worst case 5000 iterations of a loop (500 iterations * 10 curves to check)

A mathematical relationship is actually what I prefer. But using a “hit-mask” is a good second option to get what I need. And about memory consumption… there are ways of putting the images on a budget:
Say, I store all the data needed to draw the curves in an in-memory database. All the curves appear to be in a rectangular bounding box.
When I click the canvas, I use a select statement to only get the curves where my point overlaps these bounding boxes. This way I don’t have to iterate through all the objects on my canvas. Only the ones that are near my clicked point.
Then I iterate through the recordsets and create picture objects with the size of the bounding box of that object (curve). I draw the curve using the data in that recordset. Of course, I will use a thick pen size, to get some tolerance.
In my select statement, I set the order part on getting the last line created first.
Finally, I get the pixel data of the area where I clicked. Black = no hit… not black = hit.

Because the hit-mask is smaller, only the size of the bounding box, I need to offset the hit-mask’s pixel position.

But again, a mathematical solution would be more efficient. Because I only have to enter the right values: Curve start and enpoints + controlpoints + mouseposition. But I have no clue what formula I need to use.

I think that the hit-mask solution is the way that works best for my project.