【问题标题】:Draw Perpendicular line between two lines in iOS [closed]在iOS中的两条线之间绘制垂直线[关闭]
【发布时间】:2019-09-06 10:35:42
【问题描述】:

我想在 P1 和 P2 之间画一条垂直线,对应于 P3。 我有 P1 和 P2,当我触摸 UIView 时,P3 会生成。 现在我想从 P3 画出对应于 P1 和 P2 的垂直线。

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    所以你需要一些数学知识...理论上你需要从P3 到点X 画一条线,它位于P1P2 之间。 P1X 之间的向量实际上是P3-P1P1P2 描述的直线的投影。所以:

    X = P1 + (P3-P1)*((P2-P1)/(|P2-P1|)) * ((P2-P1)/(|P2-P1|))
    

    要使用CGPoint,这可以工作:

    func projectedPoint(_ point: CGPoint, toLine line: (a: CGPoint, b: CGPoint)) -> CGPoint {
    
        guard line.a != line.b else { return .zero } // Not a line
    
        let direction: CGPoint = {
            // A direction of line with a distance of 1
            let a = line.a
            let b = line.b
            let subtraction = CGPoint(x: b.x - a.x, y: b.y - a.y)
            let distance = sqrt(subtraction.x*subtraction.x + subtraction.y*subtraction.y)
            return CGPoint(x: subtraction.x/distance, y: subtraction.y/distance)
        }()
    
        let projectionDistance: CGFloat = {
            let vector = CGPoint(x: point.x-line.a.x, y: point.y-line.a.y) // From A to POINT
            return vector.x*direction.x + vector.y*direction.y // A simple dot product
        }()
    
        return CGPoint(x: line.a.x + direction.x*projectionDistance, y: line.a.y + direction.y*projectionDistance)
    }
    

    所以在你的情况下:

    X = projectedPoint(P3, toLine:(P1, P2))
    

    现在您只需在XP3 之间画一条线。

    或者,如果您希望它具有更多基于以下功能的功能。将其移植到任何使用 2D 矢量运行的系统也应该很容易,这些系统通常已经包含所有提供的功能:

    func projectedPoint(_ point: CGPoint, toLine line: (a: CGPoint, b: CGPoint)) -> CGPoint {
    
        guard line.a != line.b else { return .zero } // Not a line
    
        func add(_ a: CGPoint, _ b: CGPoint) -> CGPoint { return CGPoint(x: a.x + b.x, y: a.y + b.y) }
        func subtract(_ a: CGPoint, _ b: CGPoint) -> CGPoint { return CGPoint(x: a.x - b.x, y: a.y - b.y) }
        func scale(_ a: CGPoint, _ b: CGFloat) -> CGPoint { return CGPoint(x: a.x*b, y: a.y*b) }
        func dot(_ a: CGPoint, _ b: CGPoint) -> CGFloat { return a.x*b.x + a.y*b.y }
        func length(_ a: CGPoint) -> CGFloat { return sqrt(a.x*a.x + a.y*a.y) }
        func normalize(_ a: CGPoint) -> CGPoint { return scale(a, 1.0/length(a)) }
    
        let direction: CGPoint = normalize(subtract(line.b, line.a))
        let projectionDistance = dot(subtract(point, line.a), direction)
    
        return add(line.a, scale(direction, projectionDistance))
    }
    

    【讨论】:

    • 感谢 Matic Oblak
    【解决方案2】:

    我相信这是一个几何问题。无论如何,给定一条被分割成 P1P2 的线,你想从名为 P3 的外部点画一条垂线。

    你可以找到垂线与P1P2的交点如下:

    设P1的坐标为(x1,y1),P2的坐标为(x2,y2),P3的坐标为(x3,y3),(x4,y4)的坐标为与直线相交的点。

    x4 和 y4 可以通过以下方式确定:

    k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / ((y2-y1)^2 + (x2-x1)^2)
    x4 = x3 - k * (y2-y1)
    y4 = y3 + k * (x2-x1)
    

    一旦确定了 x4 和 y4,您现在可以绘制从 P3 到 (x4,y4) 的垂线。

    这是几何;使用 UIKit 画线或获取点坐标是另一回事。

    【讨论】: