答案 0 :(得分:1)
我相信这是一个几何问题。无论如何,给定一条被分割为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绘制线或获取点的坐标是另一回事。
答案 1 :(得分:1)
因此,您需要一点数学...从理论上讲,您需要从P3
到X
到P1
和P2
之间的一点画一条线。 P1
和X
之间的向量实际上是P3-P1
到P1
和P2
描述的线的投影。所以:
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))
现在,您只需在X
和P3
之间划一条线即可。
或者,如果您希望它具有更多功能,则应执行以下操作。将它移植到任何使用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))
}