计算两个CGPoint之间的距离

35

我需要计算两个 CGPoint 之间的距离。我参考了 这篇文章这篇问答,但是我还是弄不明白。


3
距离是一个标量值,而不是一个点。 - Jim Buck
“CGPoint中的距离”是什么意思?一个点代表一个无限小的位置。距离不能用点来衡量。在两个点之间有无限多的点。 - albertamg
11个回答

55

好的,关于你所提到的内容,这是完整的代码:

CGPoint p2; //[1]
CGPoint p1;
//Assign the coord of p2 and p1...
//End Assign...
CGFloat xDist = (p2.x - p1.x); //[2]
CGFloat yDist = (p2.y - p1.y); //[3]
CGFloat distance = sqrt((xDist * xDist) + (yDist * yDist)); //[4]

这里的距离是变量距离。

接下来发生了什么:

  1. 首先我们创建两个点...
  2. 然后找到这些点之间的x坐标距离。
  3. 现在找到y坐标之间的距离。
  4. 这些长度是三角形的两条边,实际上它们是腿,现在需要找到斜边,这意味着进行一些数学运算来重新排列c ^ 2 = a ^ 2 + b ^ 2,我们得到斜边等于sqrt((xDist ^ 2)+(yDist ^ 2))。 xDist ^ 2 =(xDist * xDist)。同样:yDist ^ 2 =(yDist * yDist)

不能将CGPoint作为距离,距离没有x和y分量。它只是一个数字。

如果您认为CGPoint是一种度量单位(例如英尺是一种度量单位),那就不是。


在数学中,两点之间的距离为:d = sqrt((x2-x1)^2 + (y2-y1)^2); 而且,在数学中我们有:(x-y)^2 = xx - 2xy + yy; 而不是xx - yy。所以你的计算是错误的!还是我错了? - Houcine
2
@Houcine:(x-y)^2 ≠ (x^2 - y^2)。它们不是相同的。发布Wolfram Alpha链接没有起作用,但如果你去Wolfram alpha并键入这两个方程式,你会看到它们之间有差异。 - Dair
2
我的数学老师总是教我用2和1做简单的测试来检查你的数学。让X为2,Y为1:2^2 - 1^2 = 4-1 = 3。(2-1)^2 = 1^2 = 1。1 != 3,所以(x-y)^2 != (x^2 - y^2)。 - redux

24

简短回答

CGPoint p1, p2; // Having two points
CGFloat distance = hypotf((p1.x-p2.x), (p1.y-p2.y));

更详细的解释

如果有两个点p1p2,很容易找到它们之间的高度宽度差异(例如:ABS(p1.x - p2.x)),但要找到它们距离的真实表示,你需要使用直角三角形的斜边长度(如下所示的H)。

 p1
  |\  
  | \  
  |  \ H
  |   \
  |    \
  |_ _ _\
         p2

幸运的是,这里有一个内置的宏可以实现这一点:hypotf(或者对于doubles,使用hypot):

// Returns the hypothenuse (the distance between p1 & p2)
CGFloat dist = hypotf((p1.x-p2.x), (p1.y-p2.y));
(原始参考资料

22
在Swift中,您可以为CGPoint添加一个扩展:
extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        return sqrt(pow((point.x - x), 2) + pow((point.y - y), 2))
    }
}

然后像这样使用它:

let distance = p1.distance(to: p2)

最迅捷的方式。应该是这个问题的答案。 - Błażej
1
除非在Swift推出之前就提出了这个问题,否则ObjC的答案应该被接受。 - koen

21

我曾经手动地做了一万次,所以我写了一个函数,并将其放在我的个人库中,每次开始新程序时都会导入,所以我忘记它不是标准的。

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

所以你可以这样调用它(比如你想知道你移动手指的距离):

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

这在移动功能中非常有用,也可用于滚动菜单中的点检查:
if([self distanceBetween:touchStart and:touchAt] > 20*scalePoints)
    isItATap = FALSE;

在touchesBegan中将"isItATap"设置为真,将上述放到touchesMoved中,那么你就知道玩家移动手指时触摸点离"tap"太远了,所以你可以不选择玩家所触碰的对象,而是滚动该对象。
至于缩放,应该基于是否有视网膜显示屏以及您使用的设备大小(对视网膜显示屏除以2,因为常规屏幕上5个“点”的物理距离在视网膜显示屏上用户手指感觉相当于10个“像素”,因为每个点是4个像素,所以你会发现在视网膜显示屏上,玩家很难进行轻击(这是一个常见的疏忽))。

1
无论如何,Redux,你的代码都不会正常工作。return sqrt(pow(p2.x-p1.x,2)+pow(p2.y-p2.y,2)); 我确定应该是这样的; return sqrt(pow(p2.x-p1.x,2)+pow(p2.y-p1.y,2)); - Yucel_K
返回类型应该是CGFloat,以便与ARM64良好地配合使用。 - Graham Perks
1
在 Swift 中,func distanceBetween(point p1:CGPoint, andPoint p2:CGPoint) -> CGFloat { return sqrt(pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2)) } 表示计算两点之间的距离。 - NSRover
编译器可能会为您进行优化,但通常乘法比调用 pow 更有效率。由于这是一个经常使用的小纯函数,将其制作成 C 函数而不是 Objective-C 消息也会更好。 - Justin Meiners

20
听起来你可能想要从p1到p2的向量(或者说是差向量)而不是距离。
const CGPoint p1 = {10, 10};
const CGPoint p2 = {510, 310};

const CGPoint diff = {p2.x - p1.x, p2.y - p1.y} // == (CGPoint){500, 300}

6
在苹果的示例项目中,它们使用 hypot。如此可以计算出两个点之间的直角边(距离),具体解释可以参考这个答案
extension CGPoint {

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

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

2

仅此而已...

    float distance = ccpLength(ccpSub(p1,p2));

p1和p2分别是CGPoint对象


1
以上使用的是Cocos2D函数,不是iOS本地函数。 - Kaolin Fire
2
问题是关于Box2d的,基本上应用程序与cocos2d集成:P - mohitdream4u

1

Swift 4,Swift 3解决方案

 extension CGPoint {
        static func distanceBetween(point p1: CGPoint,
                                    andPoint p2: CGPoint) -> CGFloat {
            return sqrt(pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2))
        }
    }

1

欧几里得距离用于Vision API中的另一点。

iOS 14开始。


import Vision

extension CGPoint {
        
    public func distance(to point: CGPoint) -> Double {
        VNPoint(location: self).distance(VNPoint(location: point))
    }
}


print(CGPoint(x: 1, y: 1).distance(to: .zero)) // 1.4142135623730951


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接