views:

57

answers:

1
+1  A: 

The following method should do the trick. If you spot anything weird in it feel free to point it out.

- (CGFloat)distanceBetweenRect:(CGRect)rect andPoint:(CGPoint)point
{
    // first of all, we check if point is inside rect. If it is, distance is zero
    if (CGRectContainsPoint(rect, point)) return 0.f;

    // next we see which point in rect is closest to point
    CGPoint closest = rect.origin;
    if (rect.origin.x + rect.size.width < point.x)
        closest.x += rect.size.width; // point is far right of us
    else if (point.x > rect.origin.x) 
        closest.x = point.x; // point above or below us
    if (rect.origin.y + rect.size.height < point.y) 
        closest.y += rect.size.height; // point is far below us
    else if (point.y > rect.origin.y)
        closest.y = point.y; // point is straight left or right

    // we've got a closest point; now pythagorean theorem
    // distance^2 = [closest.x,y - closest.x,point.y]^2 + [closest.x,point.y - point.x,y]^2
    // i.e. [closest.y-point.y]^2 + [closest.x-point.x]^2
    CGFloat a = powf(closest.y-point.y, 2.f);
    CGFloat b = powf(closest.x-point.x, 2.f);
    return sqrtf(a + b);
}

Example output:

CGPoint p = CGPointMake(12,12);

CGRect a = CGRectMake(5,5,10,10);
CGRect b = CGRectMake(13,11,10,10);
CGRect c = CGRectMake(50,1,10,10);
NSLog(@"distance p->a: %f", [self distanceBetweenRect:a andPoint:p]);
// 2010-08-24 13:36:39.506 app[4388:207] distance p->a: 0.000000
NSLog(@"distance p->b: %f", [self distanceBetweenRect:b andPoint:p]);
// 2010-08-24 13:38:03.149 app[4388:207] distance p->b: 1.000000
NSLog(@"distance p->c: %f", [self distanceBetweenRect:c andPoint:p]);
// 2010-08-24 13:39:52.148 app[4388:207] distance p->c: 38.013157

There might be more optimized versions out there, so might be worth digging more.

The following method determines the distance between two CGPoints.

- (CGFloat)distanceBetweenPoint:(CGPoint)a andPoint:(CGPoint)b
{
    CGFloat a2 = powf(a.x-b.x, 2.f);
    CGFloat b2 = powf(a.y-b.y, 2.f);
    return sqrtf(a2 + b2)
}

Update: removed fabsf(); -x^2 is the same as x^2, so it's unnecessary.

Update 2: added distanceBetweenPoint:andPoint: method too, for completeness.

Kalle
Ok, this is getting interesting. Let me post a bit of code that converts the objects CGPoint into the coordinates of the UIScrollView so that Kalle's code should work. I've noticed some strange behavior...
Jordan
Happy to Report, SOVLED! I was using [subview convertPoint:subview.frame.origin toView:self]; instead of [[subview superview] convertPoint:subview.frame.origin toView:self];Back to my original code and all worked fine. But you helped me track done the mistake. Perfect! Thanks Kalle!! I owe you one!
Jordan
Great to hear :) Out of curiosity, how did you originally solve it?
Kalle
Here's how I solved it earlier, however because I didn't have the right "view", the numbers were off. I like you're approach better though. -(CGFloat)distanceBetweenPoints:(CGPoint)pt1 and:(CGPoint)pt2{ CGFloat xdist = pt2.x - pt1.x; CGFloat ydist = pt2.y - pt1.y; CGFloat distance = sqrt((xdist * xdist) + (ydist * ydist)); return distance;}
Jordan
Ahh, yeah with the wrong view, any method will give weird results. :P I think you probably don't need to go quite as far as I did, since your app is about tapping on pins; it doesn't seem to need that kind of accuracy.
Kalle