So you need a bit of math… In theory you need to draw a line from P3
to point X
which lies between P1
and P2
. The vector between P1
and X
is actually a projection of P3-P1
to a line described by P1
and P2
. So:
X = P1 + (P3-P1)*((P2-P1)/(|P2-P1|)) * ((P2-P1)/(|P2-P1|))
To use CGPoint
this could work:
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)
}
So in your case:
X = projectedPoint(P3, toLine:(P1, P2))
Now you simply draw a line between X
and P3
.
Or if you want it more function based the following should do. It should also be easy to port this to any system operating with 2D vectors which usually already includes all the provided functions:
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))
}
1
solved Draw Perpendicular line between two lines in iOS [closed]