【Swift】平面座標系である点がある線分上にあるかを評価する方法
解説
タイトルの通りです。
環境:Xcode12.5.1
import Foundation
struct RectangularCoordinateSystemPoint {
let x: Double
let y: Double
init(_ x: Double, _ y: Double) {
self.x = x
self.y = y
}
}
extension RectangularCoordinateSystemPoint {
// A--P-B という関係なら AP + PB < AB は成り立たないことを用いる
// ※ ここで AP + PB = AB で評価すると Double の端数で等式が成り立たなくなるので .ulpOfOne を用いる
func isIncludeLineSegment(consistingOf endPoint: (a: RectangularCoordinateSystemPoint, b: RectangularCoordinateSystemPoint)) -> Bool {
let distanceToA = self.distance(to: endPoint.a)
let distanceToB = self.distance(to: endPoint.b)
let distanceAB = endPoint.a.distance(to: endPoint.b)
return distanceToA + distanceToB - distanceAB < .ulpOfOne
}
func distance(to target: RectangularCoordinateSystemPoint) -> Double {
return sqrt(self.diffX(to: target) * self.diffX(to: target) + self.diffY(to: target) * self.diffY(to: target)) // 二乗はpow()でもよいがDouble型の指定があるため使いづらいため敬遠
}
func diffX(to target: RectangularCoordinateSystemPoint) -> Double {
return self.x - target.x
}
func diffY(to target: RectangularCoordinateSystemPoint) -> Double {
return self.y - target.y
}
}
extension RectangularCoordinateSystemPoint {
// 別の評価方法(問題があるかもしれません)
func isIncludeLineSegmentOther(consistingOf endPoint: (a: RectangularCoordinateSystemPoint, b: RectangularCoordinateSystemPoint)) -> Bool {
if (endPoint.a.x <= self.x && self.x <= endPoint.b.x) || (endPoint.b.x <= self.x && self.x <= endPoint.a.x) {
if (endPoint.a.y <= self.y && self.y <= endPoint.b.y) || (endPoint.b.y <= self.y && self.y <= endPoint.a.y) {
if (self.y * (endPoint.a.x - endPoint.b.x)) + (endPoint.a.y * (endPoint.b.x - self.x)) + (endPoint.b.y * (self.x - endPoint.a.x)) == 0 {
// 点Pが線分AB上にある
return true
}
}
}
return false
}
}
/// テスト
/// y = 2x + 1
/// 5点列挙:(0, 1), (1, 3), (2,5), (3,7), (4,8)
/// (1,3) と (3, 7) の線分で考える
let point01 = RectangularCoordinateSystemPoint(0,1)
let point13 = RectangularCoordinateSystemPoint(1,3)
let point25 = RectangularCoordinateSystemPoint(2,5)
let point37 = RectangularCoordinateSystemPoint(3,7)
let point48 = RectangularCoordinateSystemPoint(4,8)
let point00 = RectangularCoordinateSystemPoint(0,0) // 直線上にないその他の点
/// isIncludeLineSegmentでのテスト
print(point01.isIncludeLineSegment(consistingOf: (point13, point37))) // false
print(point13.isIncludeLineSegment(consistingOf: (point13, point37))) // true
print(point25.isIncludeLineSegment(consistingOf: (point13, point37))) // true
print(point37.isIncludeLineSegment(consistingOf: (point13, point37))) // true
print(point48.isIncludeLineSegment(consistingOf: (point13, point37))) // false
print(point00.isIncludeLineSegment(consistingOf: (point13, point37))) // false
/// isIncludeLineSegmentOtherでのテスト
print(point01.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // false
print(point13.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // true
print(point25.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // true
print(point37.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // true
print(point48.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // false
print(point00.isIncludeLineSegmentOther(consistingOf: (point13, point37))) // false
Author And Source
この問題について(【Swift】平面座標系である点がある線分上にあるかを評価する方法), 我々は、より多くの情報をここで見つけました https://qiita.com/sugurutakahashi12345/items/59cc6366da15aeb00c43著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .