Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-10056] CGRect contains rect, but intersection does not equal smaller rect #3519

Closed
swift-ci opened this issue Mar 7, 2019 · 3 comments
Closed

Comments

@swift-ci
Copy link
Contributor

swift-ci commented Mar 7, 2019

Previous ID SR-10056
Radar None
Original Reporter jumhyn (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Xcode Version 10.2 beta 3 (10P99q)

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee jumhyn (JIRA)
Priority Medium

md5: 3ba7df431b2e7957a85c6df66ae91cad

Issue Description:

Due to floating point arithmetic, `CGRect.intersection` can return some surprising results. Consider the following example:

let rect = CGRect(x: 100.33333333333333333333333, y: 0, width: 100, height: 100) let infinite = CGRect.infinite 
let intersection = infinite.intersection(rect) 
print(infinite.contains(rect)) // true 
print(intersection == rect) // false

This is a result of the fact that `rect.maxX - rect.minX != rect.width`. This could be mitigated by updating `CGRect.intersection(_🙂` to read as follows:

public func intersection(_ r2: CGRect) -> CGRect {
    if self.isNull || r2.isNull { return .null }

    let rect1 = self.standardized
    let rect2 = r2.standardized

    let rect1SpanH = rect1.minX...rect1.maxX
    let rect1SpanV = rect1.minY...rect1.maxY

    let rect2SpanH = rect2.minX...rect2.maxX
    let rect2SpanV = rect2.minY...rect2.maxY

    if !rect1SpanH.overlaps(rect2SpanH) || !rect1SpanV.overlaps(rect2SpanV) {
        return .null
    }

    let overlapH = rect1SpanH.clamped(to: rect2SpanH)
    let overlapV = rect1SpanV.clamped(to: rect2SpanV)

    let width: CGFloat
    if overlapH == rect1SpanH {
        width = rect1.width
    } else if overlapH == rect2SpanH {
        width = rect2.width
    } else {
        width = overlapH.upperBound - overlapH.lowerBound
    }

    let height: CGFloat
    if overlapV == rect1SpanV {
        height = rect1.height
    } else if overlapH == rect2SpanH {
        height = rect2.height
    } else {
        height = overlapV.upperBound - overlapV.lowerBound
    }

    return CGRect(x: overlapH.lowerBound,
                  y: overlapV.lowerBound,
                  width: width,
                  height: height)
}
@swift-ci
Copy link
Contributor Author

swift-ci commented Mar 7, 2019

Comment by Frederick Kellison-Linn (JIRA)

PR here: #1977

@AnnaZaks
Copy link
Mannequin

AnnaZaks mannequin commented Mar 8, 2019

+ @itaiferber, @parkera

@swift-ci
Copy link
Contributor Author

Comment by Frederick Kellison-Linn (JIRA)

PR merged. Resolving.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant