# CGRect

## 目前版本

{% tabs %}
{% tab title="🌀  CGRect" %}

```swift
/*
 * ⭐️ required: 
 *    - 🅿️ Rectangular
 */

import SwiftUI       // for CGRect

// 🌀CGRect + Rectangular
extension CGRect: Rectangular { }

// 🌀CGRect + convenience inits
extension CGRect {
    
    /// 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)
    }
    
    /// rect from one corner to another.
    /// `CGRect(from: A, to: B)`
    public init(from p1: CGPoint, to p2: CGPoint) {
        let x = p1.x
        let y = p1.y
        let w = p2.x - p1.x
        let h = p2.y - p1.y
        self.init(x: x, y: y, width: w, height: h)
    }
    
    /// rect with center and corner.
    /// - `CGRect(center: A, corner: B)`
    public init(center: CGPoint, corner: CGPoint) {
        let x = corner.x
        let y = corner.y
        let dx = center.x - corner.x
        let dy = center.y - corner.y
        self.init(x: x, y: y, width: 2 * dx, height: 2 * dy)
    }
    
    /* ------ Modifiers -------- */
    
    /// - turn a `CGRect` into `Path` 
    public var path: Path { Path(self) }
    
}
```

{% endtab %}

{% tab title="💈 範例" %}

```swift
import SwiftUI
// ⭐️ required: 🌀CGPoint+Vector2D, 🌀CGRect

// points
let A = CGPoint(40, 40)
let B = CGPoint(80, 70)

// rects
let rect1 = CGRect(from: A, to: B)       // origin: (40,40), size:(30,40)
let rect2 = CGRect(center: A, corner: B) // origin: ( 0,10), size:(60,80)
    
// instance members
rect1.point(0.5, 0.5)  // (60, 55)
rect2.point(1,1)       // (80, 70)
rect2.bottomRight      // (80, 70)
rect2.corners          // [(0,70), (80,70), (80,10), (0,10)]

// subscript
let p    = CGPoint(1,2)                       // 🌀CGPoint
let size = CGSize(20, 20)                     // 🌀CGSize
let rect = CGRect(origin: p, size: size / 2)  // 🌀CGSize + 🅿️Vector2D

rect[ 0, 0]   // (  1,   2)
rect[ 1, 0]   // ( 11,   2)
rect[ 0, 1]   // (  1,  12)
rect[ 2, 1]   // ( 21,  12)
rect[-2,-2]   // (-19, -18)
```

{% endtab %}

{% tab title="👨‍🦳 " %}

* [🌀 Rectangular](/ios/custom/package/geometrykit/frame.md)
  {% endtab %}

{% tab title="👶 " %}

* [🌀 GeometryProxy](/ios/swiftui/view/measure/geometryproxy/geometryproxy.md)
  {% endtab %}

{% tab title="👥  相關" %}

* [🌀 GeometryProxy](/ios/swiftui/view/measure/geometryproxy/geometryproxy.md)
* [📦  GeometryReader](/ios/swiftui/view/measure/geometryreader.md)
* [Calling Types As Functions](/ios/features/callasfunction.md)
  {% endtab %}

{% tab title="🍎 " %}

* CoreGraphics  ⟩  [CGRect](https://developer.apple.com/documentation/coregraphics/cgrect)
* CoreGraphics  ⟩  [CGPoint](https://developer.apple.com/documentation/coregraphics/cgpoint?language=occ)
  {% endtab %}

{% tab title="✏️  紀錄" %}

* 2020.09.30：➕ added .**path**&#x20;
* 2020.10.08：\
  ➕ .**maxSide** \
  ✏️ ~~minLength~~ ➝ **minSide**\
  ➕ **CGRect**(x, y, w, h)\
  ➕ **subscript**: rect\[x, y]
  {% endtab %}
  {% endtabs %}

## 修改記錄

{% tabs %}
{% tab title="✏️  紀錄 " %}

* 2020.09.30：➕ added .**path**&#x20;
* 2020.10.08：\
  ➕ .**maxSide** \
  ✏️ ~~minLength~~ ➝ **minSide**\
  ➕ **CGRect**(x, y, w, h)\
  ➕ **subscript**: rect\[x, y]
* ➊ 2020.10.11：將大部分的功能移至 [Rectangular](/ios/custom/package/geometrykit/frame.md)
  {% endtab %}

{% tab title="➊" %}

```swift
// 封存日期：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) }
    
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/swift/scope/framework/built-in-frameworks/core-graphics/cgrect+ext.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
