// 封存日期:2020.10.11
// 修改內容:
// 1. 將大部分的功能移至 Rectangular
// 2. 移除對 Vector2D 的依賴
// ------------------------------------
/*
* ⭐️ required:
* - 🅿️ Vector2D
*/
import SwiftUI // for CGRect
import VectorSpace // for 🅿️ Vector2D
// 🌀CGRect
extension CGRect {
/* ------- ⭐️ Points ------- */
/// # Key Points of a CGRect
/// - Example: `.top`, `.bottom`, `.center`, ...
public enum KeyPoint: CaseIterable {
case topLeft, top, topRight
case left, center, right
case bottomLeft, bottom, bottomRight
}
// `rect.point(at: .top) == rect.top`
public func point(at position: KeyPoint) -> CGPoint {
switch position {
case .topLeft : return topLeft
case .top : return top
case .topRight : return topRight
case .left : return left
case .center : return center
case .right : return right
case .bottomLeft : return bottomLeft
case .bottom : return bottom
case .bottomRight: return bottomRight
}
}
// rect.top, ...
public var top : CGPoint { CGPoint(x: midX, y: minY) }
public var bottom : CGPoint { CGPoint(x: midX, y: maxY) }
public var left : CGPoint { CGPoint(x: minX, y: midY) }
public var right : CGPoint { CGPoint(x: maxX, y: midY) }
public var center : CGPoint { CGPoint(x: midX, y: midY) }
public var bottomLeft : CGPoint { CGPoint(x: minX, y: maxY) }
public var bottomRight: CGPoint { CGPoint(x: maxX, y: maxY) }
public var topLeft : CGPoint { CGPoint(x: minX, y: minY) }
public var topRight : CGPoint { CGPoint(x: maxX, y: minY) }
/// 4 corners of a rect
public var corners: [CGPoint] { [bottomLeft, bottomRight, topRight, topLeft] }
/// # Relative Point
/// a point relative to the rectangle's width and height
/// ## Examples
/// - `rect.point(0,0) == rect.topLeft`
/// - `rect.point(1,1) == rect.bottomRight`
public func point(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
let u = topRight - topLeft // 🅿️ Vector2D
let v = bottomLeft - topLeft
let w = x * u + y * v
return topLeft + w
}
/// ## Examples
/// - `rect[1,0] == rect.topRight`
/// - `rect[0,1] == rect.bottomLeft`
public subscript(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
point(x, y)
}
/* ------- ⭐️ Dimensions ------- */
/// side length of the rect.
public var minSide: CGFloat { min(width, height) }
public var maxSide: CGFloat { max(width, height) }
/* ------- ⭐️ Initializers ------- */
/// CGRect(x,y,w,h)
public init(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) {
self.init(x: x, y: y, width: width, height: height)
}
/// draws a `CGRect` from a corner to another corner.
/// `CGRect(from: A, to: B)`
public init(from p1: CGPoint, to p2: CGPoint) {
let x = min(p1.x, p2.x)
let y = min(p1.y, p2.y)
let w = abs(p1.x - p2.x)
let h = abs(p1.y - p2.y)
self.init(x: x, y: y, width: w, height: h)
}
/// draws a `CGRect` with center and a corner.
/// - `CGRect(center: A, corner: B)`
public init(center p1: CGPoint, corner p2: CGPoint) {
self.init(from: p2, to: 2 * p1 - p2) // 🅿️ Vector2D
}
/* ------ Modifiers -------- */
/// - turn a `CGRect` into `Path`
public var path: Path { Path(self) }
}