Containment detection
I want my mouseDragged method to continuously drag a circle, while the circle remains within the bounds of a larger circe. When the smaller circle hits the circumference of the containing circle (i.e., the mouse moves outside the containing circle), the smaller circle can only be dragged around the containing circle's circumference.
Drag and drop methods are implemented in an NSView subclass. Circle properties are stored in a custom object currChar. currChar's draw method draws both dragging circle and containing circle. Circles are drawn as NSBezierPath ovals within rects. Problem is, I don't have enough knowledge of math to implement the containment algorithm. Can anyone help?
mouseDragged method:
Drag and drop methods are implemented in an NSView subclass. Circle properties are stored in a custom object currChar. currChar's draw method draws both dragging circle and containing circle. Circles are drawn as NSBezierPath ovals within rects. Problem is, I don't have enough knowledge of math to implement the containment algorithm. Can anyone help?
Code:
// center of containing circle is set in mouseDown method
base = NSMakePoint([currChar bounds].origin.x + 10,
[currChar bounds].origin.y+10);Code:
// center of circle to drag
NSPoint current = NSMakePoint([currChar bounds].origin.x + 10,
[currChar bounds].origin.y+10);
// location to drag circle
NSPoint pt = [self convertPoint:[theEvent locationInWindow]
fromView:nil];
// corner of NSRect for NSBezierPath
pt.x -= 10;
pt.y -= 10;
// check if distance between circle centers exceeds
// containing circle's radius, [currChar move]
if ( sqrt( (base.x - current.x)*(base.x - current.x) +
(base.y - current.y)*(base.y - current.y) )
>= ([currChar move]) ) {
// ?
// [self setNeedsDisplay:YES];
}
else {
[currChar setBounds:NSMakeRect(pt.x, pt.y, 20,20)];
[self setNeedsDisplay:YES];
}
The test you need is:
Is the distance between the centers of the circles greater than the difference of their radii?
If not, the small circle is inside the big one. Otherwise, you'll need to move the small circle back inside. Here's a vaguely relevant snippet, but bear in mind that it doesn't do exactly the same thing as you want to:
[SOURCECODE]
- (void)constrainMouseToCircleWithRadius: (float)radius centredOnX: (float)x Y: (float)y
{
mouseX -= x;
mouseY += y; // Different co-ordinate ststems.
float distSquared = mouseX*mouseX + mouseY*mouseY;
float radSquared = radius*radius;
if (distSquared > radSquared)
{
float scale = sqrt(radSquared / distSquared);
mouseX *= scale;
mouseY *= scale;
}
mouseX += x;
mouseY -= y;
}
[/SOURCECODE]
Ask again if I've been unclear.
Is the distance between the centers of the circles greater than the difference of their radii?
If not, the small circle is inside the big one. Otherwise, you'll need to move the small circle back inside. Here's a vaguely relevant snippet, but bear in mind that it doesn't do exactly the same thing as you want to:
[SOURCECODE]
- (void)constrainMouseToCircleWithRadius: (float)radius centredOnX: (float)x Y: (float)y
{
mouseX -= x;
mouseY += y; // Different co-ordinate ststems.
float distSquared = mouseX*mouseX + mouseY*mouseY;
float radSquared = radius*radius;
if (distSquared > radSquared)
{
float scale = sqrt(radSquared / distSquared);
mouseX *= scale;
mouseY *= scale;
}
mouseX += x;
mouseY -= y;
}
[/SOURCECODE]
Ask again if I've been unclear.

