Reputation: 2937
I have an array of [CGRect]
.
CGRect has x, y, width, height
I also have a CGPoint
.
CGPoint has x, y.
How would i know which is the first frame in the array that is closest to the point?
I know how to do this with single values. But not with a x, y, width & height
Where do I begin? I am ok with just a description of what to do.
Upvotes: 1
Views: 521
Reputation:
You'll need to figure out what Rob asked. One option is signed distance comparison.
Video: Deriving the SDF of a Box
If multiple rectangles contain the point, the "closest" one will be the one whose closest edge to the point is farthest away, i.e. where the point is "more contained".
rects.min { [point = SIMD2(point)] in point.getSignedDistance(to: $0) }
public extension CGRect {
var center: CGPoint { .init(x: midX, y: midY) }
}
public protocol CGFloat2 {
var x: CGFloat { get }
var y: CGFloat { get }
}
extension CGPoint: CGFloat2 { }
extension CGSize: CGFloat2 {
public var x: CGFloat { width }
public var y: CGFloat { height }
}
import simd
public extension SIMD2 where Scalar == CGFloat.NativeType {
init<Float2: CGFloat2>(_ float2: Float2) {
self.init(x: float2.x, y: float2.y)
}
init(x: CGFloat, y: CGFloat) {
self.init(x: x.native, y: y.native)
}
/// Distance to the closest point on the rectangle's boundary.
/// - Note: Negative if inside the rectangle.
func getSignedDistance(to rect: CGRect) -> Scalar {
let distances =
abs( self - Self(rect.center) )
- Self(rect.size) / 2
return
all(sign(distances) .> 0)
? length(distances)
: distances.max()
}
}
public extension Sequence {
func min<Comparable: Swift.Comparable>(
by getComparable: (Element) throws -> Comparable
) rethrows -> Element? {
try self.min {
try getComparable($0) < getComparable($1)
}
}
}
Upvotes: 2