Containment detection

Post: #1
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?
// center of containing circle is set in mouseDown method
base = NSMakePoint([currChar bounds].origin.x + 10,
                                [currChar bounds].origin.y+10);
mouseDragged method:
// 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]

    // 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];
Quote this message in a reply
Post: #2
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:

- (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;

Ask again if I've been unclear.
Quote this message in a reply
Post Reply