简体   繁体   English

计算两个CGPoints之间的距离

[英]Calculate the distance between two CGPoints

i need to calculate the distance between two CGPoint s.我需要计算两个CGPoint之间的距离。 I refered this and this , but I don't get it.我提到了thisthis ,但我不明白。

Well, with stuff your refering too where is the full code:好吧,你也提到了完整的代码在哪里:

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]

The distance is the variable distance.距离是可变距离。

What is going on here:这里发生了什么:

  1. So first off we make two points...所以首先我们提出两点......
  2. Then we find the distance between x coordinates of the points.然后我们找到点的 x 坐标之间的距离。
  3. Now we find the distance between the y coordinates.现在我们找到 y 坐标之间的距离。
  4. These lengths are two sides of the triangle, infact they are the legs, time to find the hypotenuse which means after doing some math to rearragne c^2 = a^2 + b^2 we get the hypotenuse to equal sqrt((xDist^2) + (yDist^2)).这些长度是三角形的两条边,实际上它们是腿,是时候找到斜边了,这意味着在进行一些数学运算以重新排列 c^2 = a^2 + b^2 后,我们得到斜边等于 sqrt((xDist^ 2) + (yDist^2))。 xDist^2 = (xDist * xDist). xDist^2 = (xDist * xDist)。 And likewise: yDist^2 = (yDist * yDist)同样:yDist^2 = (yDist * yDist)

You can't really make a CGPoint be the distance, distance doesn't have an x and y component.你不能真正让 CGPoint 成为距离,距离没有 x 和 y 分量。 It is just 1 number.它只是1个数字。

If you think CGPoint is a unit of measurement (for example feet is a unit of measurement) it is not.如果您认为 CGPoint 是一个度量单位(例如英尺是一个度量单位),那么它不是。

I've had to do this by hand 10,000 times so I wrote a function for it and stuck it in my personal library that I always dump in at the beginning of a new program so I forget it's not cannon.我不得不手动完成 10,000 次,所以我为它编写了一个函数并将它放在我的个人库中,我总是在新程序开始时转储,所以我忘记了它不是大炮。

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

so you call it like this (say you want to know how far you moved your finger):所以你这样称呼它(假设你想知道你的手指移动了多远):

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

This is useful in movement functions as well for spot checking in a scrolling menu:这对于移动功能以及滚动菜单中的抽查很有用:

if([self distanceBetween:touchStart and:touchAt] > 20*scalePoints)
    isItATap = FALSE;

Set "isItATap" true in touchesBegan, put the above in touchesMoved, then you know the player moved their finger too far for the touch to be a "tap", so you can have it NOT select the object the player touched and instead scroll the object around.在 touchesBegan 中设置“isItATap”为真,将上面的内容放在 touchesMoved 中,然后你知道玩家将手指移动得太远以至于触摸不能成为“点击”,所以你可以让它不选择玩家触摸的对象,而是滚动周围的对象。

As for scale, that should be based on whether or not you have retina display and what size of a device you're on (divide by 2 for retina display since a physical distance of 5 "points" on a regular screen as the user's finger feels it will come up as 10 "pixels" on a retina display screen, since each point is 4 pixels, so you'll wind up with a situation where the player has a very hard time tapping on retina display (which is a common oversight)至于比例,这应该基于您是否有视网膜显示器以及您使用的设备尺寸(视网膜显示器除以 2,因为用户手指在常规屏幕上的物理距离为 5 个“点”感觉它会在视网膜显示屏上显示为 10 个“像素”,因为每个点都是 4 个像素,所以你最终会遇到这样一种情况,即玩家很难点击视网膜显示屏(这是一个常见的疏忽) )

Sounds like you probably want the vector from p1 to p2 (or difference ) rather than the distance.听起来您可能想要从 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}

Short Answer简答

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

Longer Explination更长的解释

If you have two points p1 and p2 it is obviously easy to find the difference between their height and width (eg ABS(p1.x - p2.x) ) but to find a true representation of their distance you really want the hypothenuse ( H below).如果你有两个点p1p2显然很容易找到它们的heightwidth之间的差异(例如ABS(p1.x - p2.x) )但是要找到它们距离的真实表示,你真的想要假设( H以下)。

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

Thankfully there is a built in macro for this: hypotf (or hypot for doubles ):值得庆幸的是有一个内置的宏这样的: hypotf (或hypot用于doubles ):

// Returns the hypothenuse (the distance between p1 & p2)
CGFloat dist = hypotf((p1.x-p2.x), (p1.y-p2.y));

(original reference ) (原文参考

In Swift, you can add an extension to CGPoint:在 Swift 中,您可以向 CGPoint 添加扩展:

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

and use it like this:并像这样使用它:

let distance = p1.distance(to: p2)

In Apple's sample projects, they use hypot.在 Apple 的示例项目中,他们使用了 hypot。 This returns hypothenuse (distance) between two points as explained in this answer .这将返回两点之间的假设(距离),如本答案中所述

extension CGPoint {

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

only this...只有这个...

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

where p1 and p2 are objects of CGPoint其中 p1 和 p2 是 CGPoint 的对象

Swift 4, Swift 3 solution 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))
        }
    }

Euclidean distance to another point with Vision api.使用 Vision api 到另一点的欧几里德距离

Starting from iOS 14 .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

I extended above function to count distance between two CGRects.我扩展了上面的函数来计算两个 CGRects 之间的距离。 I count it by counting distance between centers of CGRects and then substracting distance to boundaries of rectangles from their centers.我通过计算 CGRects 中心之间的距离来计算它,然后从它们的中心减去到矩形边界的距离。 I copied function counting intersection point between two lines from: https://www.hackingwithswift.com/example-code/core-graphics/how-to-calculate-the-point-where-two-lines-intersect我复制了两行之间的函数计数交点: https : //www.hackingwithswift.com/example-code/core-graphics/how-to-calculate-the-point-where-two-lines-intersect

   func distanceBetweenRectangles(r1: CGRect, r2: CGRect) -> CGFloat { // returns distance between boundaries of two rectangles or -1 if they intersect
    let midR1 = CGPoint(x: r1.midX, y: r1.midY)
    let midR2 = CGPoint(x: r2.midX, y: r2.midY)
    let midXDistance = abs(midR1.x - midR2.x)
    let midYDistance = abs(midR1.y - midR2.y)
    var result: CGFloat = 0
    if ((midXDistance < r1.width*0.5)&&(midYDistance < r1.height*0.5))||((midXDistance < r2.width*0.5)&&(midYDistance < r2.height*0.5)) {
        result = -1
    } else {
        let midDistance = distanceBetweenPoints(p1: midR1, p2: midR2)
        let rectCrossPoint1 = rectCross(rect: r1, start1: midR1, end1: midR2)
        let rectCrossPoint2 = rectCross(rect: r2, start1: midR1, end1: midR2)
        let boundR1Distance = distanceBetweenPoints(p1: rectCrossPoint1, p2: midR1)
        let boundR2Distance = distanceBetweenPoints(p1: rectCrossPoint2, p2: midR2)
        result = midDistance - boundR1Distance - boundR2Distance
    }
    return result
}

func distanceBetweenPoints(p1: CGPoint, p2: CGPoint) -> CGFloat { // counts distance between two points
    return sqrt(pow(p2.x-p1.x,2)+pow(p2.y-p1.y,2));
}

func rectCross(rect: CGRect, start1: CGPoint, end1: CGPoint) -> CGPoint { // returns point where line crosses rect or 0,0 if not
    var start2 = CGPoint(x: rect.minX, y: rect.minY)
    var end2 = CGPoint(x: rect.maxX, y: rect.minY)
    let point1 = linesCross(start1: start1, end1: end1, start2: start2, end2: end2)
    start2 = CGPoint(x: rect.maxX, y: rect.minY)
    end2 = CGPoint(x: rect.maxX, y: rect.maxY)
    let point2 = linesCross(start1: start1, end1: end1, start2: start2, end2: end2)
    start2 = CGPoint(x: rect.minX, y: rect.maxY)
    end2 = CGPoint(x: rect.maxX, y: rect.maxY)
    let point3 = linesCross(start1: start1, end1: end1, start2: start2, end2: end2)
    start2 = CGPoint(x: rect.minX, y: rect.minY)
    end2 = CGPoint(x: rect.minX, y: rect.maxY)
    let point4 = linesCross(start1: start1, end1: end1, start2: start2, end2: end2)
    
    if (point1.x > 0)&&(point1.y > 0) {
        return point1
    } else if (point2.x > 0)&&(point2.y > 0) {
        return point2
    } else if (point3.x > 0)&&(point3.y > 0) {
        return point3
    } else if (point4.x > 0)&&(point4.y > 0) {
        return point4
    }
    return CGPoint(x: 0, y: 0)
}

func linesCross(start1: CGPoint, end1: CGPoint, start2: CGPoint, end2: CGPoint) -> CGPoint { // returns point where two sections cross or 0,0, this function was copied from https://www.hackingwithswift.com/example-code/core-graphics/how-to-calculate-the-point-where-two-lines-intersect
    let delta1x = end1.x - start1.x
    let delta1y = end1.y - start1.y
    let delta2x = end2.x - start2.x
    let delta2y = end2.y - start2.y
    // create a 2D matrix from our vectors and calculate the determinant
    let determinant = delta1x * delta2y - delta2x * delta1y
    if abs(determinant) < 0.0001 {
        // if the determinant is effectively zero then the lines are parallel/colinear
        return CGPoint(x: 0, y: 0)
    }
    // if the coefficients both lie between 0 and 1 then we have an intersection
    let ab = ((start1.y - start2.y) * delta2x - (start1.x - start2.x) * delta2y) / determinant
    if ab > 0 && ab < 1 {
        let cd = ((start1.y - start2.y) * delta1x - (start1.x - start2.x) * delta1y) / determinant

        if cd > 0 && cd < 1 {
            // lines cross – figure out exactly where and return it
            let intersectX = start1.x + ab * delta1x
            let intersectY = start1.y + ab * delta1y
            return CGPoint(x: intersectX, y: intersectY)
        }
    }
    return CGPoint(x: 0, y: 0)
}
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()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM