假设我有一个CGPoints
数组,如何检查它们是否产生直线?
例如,想象一个网格。假设我在网格上绘制了所有的点,如何检查所有的点是水平,垂直还是对角线?
答案 0 :(得分:0)
一种方法是为您的点计算Line of Best Fit,以确定它们是否在一条线上。
func pointsFormALine(_ points: [CGPoint]) -> Bool {
// helper function to test if CGFloat is close enough to zero
// to be considered zero
func isZero(_ f: CGFloat) -> Bool {
let epsilon: CGFloat = 0.00001
return abs(f) < epsilon
}
// variables for computing linear regression
var sumXX: CGFloat = 0 // sum of X^2
var sumXY: CGFloat = 0 // sum of X * Y
var sumX: CGFloat = 0 // sum of X
var sumY: CGFloat = 0 // sum of Y
for point in points {
sumXX += point.x * point.x
sumXY += point.x * point.y
sumX += point.x
sumY += point.y
}
// n is the number of points
let n = CGFloat(points.count)
// compute numerator and denominator of the slope
let num = n * sumXY - sumX * sumY
let den = n * sumXX - sumX * sumX
// is the line vertical or horizontal?
if isZero(num) || isZero(den) {
return true
}
// calculate slope of line
let m = num / den
// calculate the y-intercept
let b = (sumY - m * sumX) / n
print("y = \(m)x + \(b)")
// check fit by summing the squares of the errors
var error: CGFloat = 0
for point in points {
// apply equation of line y = mx + b to compute predicted y
let predictedY = m * point.x + b
error += pow(predictedY - point.y, 2)
}
return isZero(error)
}
测试:
pointsFormALine([CGPoint(x: 1, y: 2), CGPoint(x: 2, y: 4), CGPoint(x: 5, y: 10)]) // true
pointsFormALine([CGPoint(x: 1, y: 2), CGPoint(x: 1, y: 4), CGPoint(x: 1, y: 10)]) // true
pointsFormALine([CGPoint(x: 1, y: 2), CGPoint(x: 2, y: 2), CGPoint(x: 5, y: 2)]) // true
pointsFormALine([CGPoint(x: 1, y: 2), CGPoint(x: 2, y: 1), CGPoint(x: 2, y: 2)]) // false