swift nub
swift nub

Reputation: 2937

How to find out which CGRect is closest from array?

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

Answers (1)

user652038
user652038

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

Related Questions