Skip to content

Commit 41e1199

Browse files
committed
CoreGraphics: add support for intersection
This adds the `intersection` and `intersects` methods to `Rect`.
1 parent bb89adf commit 41e1199

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

Sources/SwiftWin32/CG/Rect.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,25 @@ public struct Rect {
173173
height: standardized.size.height)
174174
}
175175

176+
/// Returns the intersection of two rectangles.
177+
public func intersection(_ rect: Rect) -> Rect {
178+
guard !self.isNull, !rect.isNull else { return .null }
179+
let lhs: Rect = self.standardized, rhs: Rect = rect.standardized
180+
181+
let origin: Point = Point(x: max(lhs.minX, rhs.minX),
182+
y: max(lhs.minY, rhs.minY))
183+
let size: Size = Size(width: min(lhs.maxX, rhs.maxX) - origin.x,
184+
height: min(lhs.maxY, rhs.maxY) - origin.y)
185+
guard size.width > 0, size.height > 0 else { return .null }
186+
return Rect(origin: origin, size: size)
187+
}
188+
176189
// MARK - Checking Characteristics
177190

191+
/// Returns whether two rectangles intersect.
192+
public func intersects(_ rect: Rect) -> Bool {
193+
return !intersection(rect).isEmpty
194+
}
178195

179196
/// Returns whether a rectangle has zero width or height, or is a null
180197
/// rectangle.

Tests/CoreGraphicsTests/CoreGraphicsTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,50 @@ final class CoreGraphicsTests: XCTestCase {
159159
Rect(x: -28.0, y: -28.0, width: 24.0, height: 24.0))
160160
}
161161

162+
func testRectIntersection() {
163+
let r1: Rect = Rect(x: 0, y: 0, width: 100, height: 100)
164+
let r2: Rect = Rect(x: 25, y: 25, width: 50, height: 50)
165+
let r3: Rect = Rect(x: 75, y: 75, width: 50, height: 50)
166+
let r4: Rect = Rect(x: 125, y: 125, width: 50, height: 50)
167+
let r5: Rect = Rect(x: 75, y: 75, width: -50, height: -50)
168+
169+
// concentric overlap
170+
XCTAssertEqual(r1.intersection(r2),
171+
Rect(x: 25, y: 25, width: 50, height: 50))
172+
173+
// communitivity
174+
XCTAssertEqual(r1.intersection(r2), r2.intersection(r1))
175+
176+
// partial overlap
177+
XCTAssertEqual(r1.intersection(r3),
178+
Rect(x: 75, y: 75, width: 25, height: 25))
179+
180+
// no overlap
181+
XCTAssertTrue(r1.intersection(r4).isNull)
182+
183+
// non-standard
184+
XCTAssertEqual(r5.intersection(r1),
185+
Rect(x: 25, y: 25, width: 50, height: 50))
186+
XCTAssertEqual(r1.intersection(r5),
187+
Rect(x: 25, y: 25, width: 50, height: 50))
188+
}
189+
190+
func testRectIntersects() {
191+
let r1: Rect = Rect(x: 0, y: 0, width: 100, height: 100)
192+
let r2: Rect = Rect(x: 25, y: 25, width: 50, height: 50)
193+
let r3: Rect = Rect(x: 75, y: 75, width: 50, height: 50)
194+
let r4: Rect = Rect(x: 125, y: 125, width: 50, height: 50)
195+
196+
XCTAssertTrue(r1.intersects(r2))
197+
XCTAssertTrue(r2.intersects(r1))
198+
199+
XCTAssertTrue(r1.intersects(r3))
200+
XCTAssertTrue(r3.intersects(r1))
201+
202+
XCTAssertFalse(r1.intersects(r4))
203+
XCTAssertFalse(r4.intersects(r1))
204+
}
205+
162206
static var allTests = [
163207
("testAffineTransformIdentity", testAffineTransformIdentity),
164208
("testAffineTransformIdentityIsIdentity", testAffineTransformIdentityIsIdentity),
@@ -170,5 +214,7 @@ final class CoreGraphicsTests: XCTestCase {
170214
("testRectStandardizing", testRectStandardizing),
171215
("testRectIntegral", testRectIntegral),
172216
("testRectInsetBy", testRectInsetBy),
217+
("testRectIntersection", testRectIntersection),
218+
("testRectIntersects", testRectIntersects),
173219
]
174220
}

0 commit comments

Comments
 (0)