Jak znaleźć odległość między dwoma punktami CG?


84

Kiedy wykonujemy multitouch dwoma palcami w UIScrollView, otrzymujemy dwa punkty CG. Chcę znaleźć odległość między nimi. Następnie, gdy ponownie zrobimy szczypanie (wewnątrz lub na zewnątrz), wtedy znowu otrzymamy dwa punkty. Następnie po ponownym znalezieniu odległości między tymi dwoma punktami chcę zdecydować, czy uszczypnąłem, czy wyciągnąłem. Jeśli uszczypnąłem, na pewno nowa odległość będzie mniejsza i odwrotnie.

Ale nie wiesz, jak znaleźć dokładny pomiar odległości między 2 punktami w celu porównania? Czy ktoś ma o tym pojęcie?


Zobacz moją odpowiedź dla Swift 4, która pokazuje do 5 różnych sposobów na znalezienie odległości między dwoma CGPoints.
Imanou Petit

Odpowiedzi:


125

Odległość między p1a p2:

CGFloat xDist = (p2.x - p1.x);
CGFloat yDist = (p2.y - p1.y);
CGFloat distance = sqrt(xDist * xDist + yDist * yDist);

Wstaw funkcję:

func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
    let xDist = a.x - b.x
    let yDist = a.y - b.y
    return CGFloat(sqrt(xDist * xDist + yDist * yDist))
}

Wstęp: twierdzenie Pitagorasa

Jeśli chcesz tylko obliczyć, czy odległość między punktami rośnie, czy maleje, możesz pominąć funkcję sqrt (), która przyspieszy ją trochę.


32
Czy nie ma na to wygodnej metody?
SpacyRicochet

22
Aksjomat # 1 geometrii obliczeniowej: jeśli porównujesz odległości, nie ma potrzeby ponoszenia kosztu operacji sqrt ().
QED

4
@SpaceyRicochet istnieją metody hypotf i ccpDistance. Zobacz odpowiedzi poniżej.
rmp251

@QED Czy wartość przed obliczeniem pierwiastka kwadratowego ma nazwę lub znaczenie wykraczające poza pośredni krok obliczania odległości?
allenh

@AllenHumphreys nie ma nic bardziej poetyckiego niż kwadrat do kwadratu .
QED,

188

Możesz użyć funkcji hypot()lub hypotf()do obliczenia przeciwprostokątnej. Biorąc pod uwagę dwa punkty p1i p2:

CGFloat distance = hypotf(p1.x - p2.x, p1.y - p2.y);

I to wszystko.


4
jeśli używasz swift to odległość = hypotf (Float (p1.x) - Float (p2.x), Float (p1.y) - Float (p2.y))
nwales

6
masz na myślilet distance = hypotf(Float(p1.x - p2.x), Float(p1.y - p2.y))
przeciętny Joe

6
masz na myśli let distance = hypot(p1.x - p2.x, p1.y - p2.y)od Swift 2.1
Cemen

Ta funkcja jest właściwie powodem, dla którego szukałem tego pytania.
kelin

30

Dla szybkich użytkowników

extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        return sqrt(pow(x - point.x, 2) + pow(y - point.y, 2))
    }
}

To naprawdę fajne rozwiązanie! Działa w porządku!
gundrabur

15

W Swift 4 możesz wybrać jeden z 5 następujących kodów Playground, aby uzyskać odległość między dwoma CGPointinstancjami.


1. Korzystanie z sqrt(_:)funkcji Darwina

import CoreGraphics

func distance(from lhs: CGPoint, to rhs: CGPoint) -> CGFloat {
    let xDistance = lhs.x - rhs.x
    let yDistance = lhs.y - rhs.y
    return sqrt(xDistance * xDistance + yDistance * yDistance)
}

let point1 = CGPoint(x: -10, y: -100)
let point2 = CGPoint(x: 30, y: 600)

distance(from: point1, to: point2) // 701.141925718324

2. Za pomocą CGFloat squareRoot()metody

import CoreGraphics

func distance(from lhs: CGPoint, to rhs: CGPoint) -> CGFloat {
    let xDistance = lhs.x - rhs.x
    let yDistance = lhs.y - rhs.y
    return (xDistance * xDistance + yDistance * yDistance).squareRoot()
}

let point1 = CGPoint(x: -10, y: -100)
let point2 = CGPoint(x: 30, y: 600)

distance(from: point1, to: point2) // 701.141925718324

3. Stosowanie CGFloat squareRoot()metody i pow(_:_:)funkcji Core Graphics

import CoreGraphics

func distance(from lhs: CGPoint, to rhs: CGPoint) -> CGFloat {
    return (pow(lhs.x - rhs.x, 2) + pow(lhs.y - rhs.y, 2)).squareRoot()
}

let point1 = CGPoint(x: -10, y: -100)
let point2 = CGPoint(x: 30, y: 600)

distance(from: point1, to: point2) // 701.141925718324

4. Korzystanie z hypot(_:_:)funkcji Core Graphics

import CoreGraphics

func distance(from lhs: CGPoint, to rhs: CGPoint) -> CGFloat {
    return hypot(lhs.x - rhs.x, lhs.y - rhs.y)
}

let point1 = CGPoint(x: -10, y: -100)
let point2 = CGPoint(x: 30, y: 600)

distance(from: point1, to: point2) // 701.141925718324

5. Wykorzystanie hypot(_:_:)funkcji i CGFloat distance(to:)metody Core Graphics

import CoreGraphics

func distance(from lhs: CGPoint, to rhs: CGPoint) -> CGFloat {
    return hypot(lhs.x.distance(to: rhs.x), lhs.y.distance(to: rhs.y))
}

let point1 = CGPoint(x: -10, y: -100)
let point2 = CGPoint(x: 30, y: 600)

distance(from: point1, to: point2) // 701.141925718324

1
Działa również w Swift 3.
ThisClark,

12
-(float)distanceFrom:(CGPoint)point1 to:(CGPoint)point2
{
CGFloat xDist = (point2.x - point1.x);
CGFloat yDist = (point2.y - point1.y);
return sqrt((xDist * xDist) + (yDist * yDist));
}

Jeśli używasz cocos2d

float distance = ccpDistance(point1, point2);

2
Wygląda na to, że ccpDistance jest częścią cocos2d, a nie częścią core. Włączenie go w celu uniknięcia twierdzenia Pitagorasa jest prawdopodobnie przesadą.
Vox,

3

Napisałem to, często go używam:

- (float) distanceBetween : (CGPoint) p1 and: (CGPoint) p2
{
    return sqrt(pow(p2.x-p1.x,2)+pow(p2.y-p1.y,2));
}

Zadzwoń tak:

float distanceMoved = [self distanceBetween touchStart and: touchEnd];

Zwykle używam cocos2d, ale nadal używam własnej funkcji do niektórych rzeczy, ponieważ kiedy się uczyłem, napisałem kilka własnych funkcji dla prostych rzeczy, zamiast szukać "oficjalnych" funkcji wyższego rzędu, a ponadto nie jestem wielki fan funkcji (vars, vars), wolę [self functions vars and: vars]


1
czy nie powinno to być sqrt (pow (p2.x-p1.x, 2) + pow (p2.y-p1.y, 2))? drugie wystąpienie p2.y zastąpiło p1.y.
Sanjay Chaudhry,

0
#define rw_pointOffset(point1, point2) CGPointMake(point2.x - point1.x, point2.y - point1.y)
#define rw_pointDistance(point1, point2) sqrtf( powf(point2.x - point1.x, 2.0f) + powf(point2.y - point1.y, 2.0f))

I tak z tego korzystasz:

CGPoint offset = rw_pointOffset(view1.center, view2.center);
float distance = rw_pointDistance(view1.center, view2.center);

0

Jeśli chcesz znaleźć bezwzględną wartość odległości między dwoma punktami, możesz użyć (dla Cocos2d):

float distance = abs(ccpDistance(point1, point2));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.