Skip to content

Instantly share code, notes, and snippets.

@rcholic
Forked from calosth/UIView+Intersection.swift
Created September 8, 2022 22:59
Show Gist options
  • Select an option

  • Save rcholic/ce036f9eb9e958facf99608d9076c7ba to your computer and use it in GitHub Desktop.

Select an option

Save rcholic/ce036f9eb9e958facf99608d9076c7ba to your computer and use it in GitHub Desktop.

Revisions

  1. @calosth calosth revised this gist Mar 13, 2019. 1 changed file with 20 additions and 18 deletions.
    38 changes: 20 additions & 18 deletions UIView+Intersection.swift
    Original file line number Diff line number Diff line change
    @@ -1,38 +1,40 @@

    import UIKit

    // Conform the `Polygon` protocol to specify the vertexs of the polygon.
    // Conform the `Polygon` protocol to specify the vertices of the polygon.
    protocol Polygon {
    var vertexs: [CGPoint] { get }
    var vertices: [CGPoint] { get }
    }

    // UIView conforms the protocol `Polygon` to specified the vertexs of the rectangle.
    // UIView conforms the protocol `Polygon` to specified the vertices of the rectangle.
    extension UIView: Polygon {
    var vertexs: [CGPoint] {
    var vertices: [CGPoint] {

    var point: CGPoint = CGPoint(x: bounds.midX, y: bounds.midY)

    point.x = -point.x
    point.y = -point.y
    var vertexA = __CGPointApplyAffineTransform(point, transform)
    var vertexA = point.applying(transform)
    vertexA.x += center.x
    vertexA.y += center.y

    point.x = -point.x;
    var vertexB = __CGPointApplyAffineTransform(point, transform)
    var vertexB = point.applying(transform)
    vertexB.x += center.x
    vertexB.y += center.y

    point.y = -point.y;
    var vertexC = __CGPointApplyAffineTransform(point, transform)
    var vertexC = point.applying(transform)
    vertexC.x += center.x
    vertexC.y += center.y

    point.x = -point.x;
    var vertexD = __CGPointApplyAffineTransform(point, transform)
    var vertexD = point.applying(transform)
    vertexD.x += center.x
    vertexD.y += center.y




    return [vertexA, vertexB, vertexC, vertexD]
    }

    @@ -45,16 +47,16 @@ extension UIView: Polygon {
    let polygonA = self
    let polygonB = view2

    return intersects(polygonA: polygonA, polygonB: polygonB)
    return UIView.intersects(polygonA: polygonA, polygonB: polygonB)
    }

    private func intersects(polygonA: Polygon, polygonB: Polygon) -> Bool {
    private static func intersects(polygonA: Polygon, polygonB: Polygon) -> Bool {

    for polygon in [polygonA, polygonB] {
    for index in 0..<polygon.vertexs.count {
    let nextIndex = (index + 1) % polygon.vertexs.count
    let point1 = polygon.vertexs[index]
    let point2 = polygon.vertexs[nextIndex]
    for index in 0..<polygon.vertices.count {
    let nextIndex = (index + 1) % polygon.vertices.count
    let point1 = polygon.vertices[index]
    let point2 = polygon.vertices[nextIndex]

    let normal = CGPoint(x: -(point2.y - point1.y), y: point2.x - point1.x)

    @@ -69,13 +71,13 @@ extension UIView: Polygon {

    return true
    }


    private func projectionOf(_ polygon: Polygon, with normal: CGPoint) -> (minP: CGFloat, maxP: CGFloat) {

    private static func projectionOf(_ polygon: Polygon, with normal: CGPoint) -> (minP: CGFloat, maxP: CGFloat) {
    var minProjection: CGFloat = .infinity
    var maxProjection: CGFloat = -.infinity

    for point in polygon.vertexs {
    for point in polygon.vertices {
    let projection: CGFloat = point.x * normal.x + point.y * normal.y

    if projection > maxProjection {
  2. @calosth calosth revised this gist Feb 27, 2019. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions UIView+Intersection.swift
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@

    import UIKit

    // Conform the `Polygon` protocol to specify the vertexs of the polygon.
    protocol Polygon {
    var vertexs: [CGPoint] { get }
    @@ -32,9 +35,6 @@ extension UIView: Polygon {

    return [vertexA, vertexB, vertexC, vertexD]
    }
    }

    extension UIView {

    /// Returns whether two views intersect.
    ///
  3. @calosth calosth revised this gist Feb 26, 2019. No changes.
  4. @calosth calosth revised this gist Feb 24, 2019. 1 changed file with 61 additions and 68 deletions.
    129 changes: 61 additions & 68 deletions UIView+Intersection.swift
    Original file line number Diff line number Diff line change
    @@ -1,54 +1,60 @@
    extension UIView {

    /// Given detects collision between the receiver and a given view
    /// - Parameter view2: the view to compare with
    public func intersectsWith(_ view2: UIView) -> Bool {
    // Conform the `Polygon` protocol to specify the vertexs of the polygon.
    protocol Polygon {
    var vertexs: [CGPoint] { get }
    }

    // UIView conforms the protocol `Polygon` to specified the vertexs of the rectangle.
    extension UIView: Polygon {
    var vertexs: [CGPoint] {

    let polygonA = convertToPolygon(self)
    let polygonB = convertToPolygon(view2)
    var point: CGPoint = CGPoint(x: bounds.midX, y: bounds.midY)

    return intersects(polygonA: polygonA, polygonB: polygonB)
    }

    private struct Polygon {
    var points: [CGPoint] = []
    point.x = -point.x
    point.y = -point.y
    var vertexA = __CGPointApplyAffineTransform(point, transform)
    vertexA.x += center.x
    vertexA.y += center.y

    /// Create a 2D rectangle polygon
    init(vertexA: CGPoint, vertexB: CGPoint, vertexC: CGPoint, vertexD: CGPoint) {
    points.append(vertexA)
    points.append(vertexB)
    points.append(vertexC)
    points.append(vertexD)
    }
    point.x = -point.x;
    var vertexB = __CGPointApplyAffineTransform(point, transform)
    vertexB.x += center.x
    vertexB.y += center.y

    }
    point.y = -point.y;
    var vertexC = __CGPointApplyAffineTransform(point, transform)
    vertexC.x += center.x
    vertexC.y += center.y

    point.x = -point.x;
    var vertexD = __CGPointApplyAffineTransform(point, transform)
    vertexD.x += center.x
    vertexD.y += center.y

    return [vertexA, vertexB, vertexC, vertexD]
    }
    }

    extension UIView {

    private func projectionOf(_ polygon: Polygon, with normal: CGPoint) -> (minP: CGFloat, maxP: CGFloat) {
    var minProjection: CGFloat = .infinity
    var maxProjection: CGFloat = -.infinity
    /// Returns whether two views intersect.
    ///
    /// - Parameter view2: The view to test the intersaction with this view.
    /// - Returns: `true` if the specified views intersect, otherwise `false`
    func intersectsWith(_ view2: UIView) -> Bool {

    for point in polygon.points {
    let projection: CGFloat = point.x * normal.x + point.y * normal.y

    if projection > maxProjection {
    maxProjection = projection
    }

    if projection < minProjection {
    minProjection = projection
    }
    }
    let polygonA = self
    let polygonB = view2

    return (minProjection, maxProjection)
    return intersects(polygonA: polygonA, polygonB: polygonB)
    }

    private func intersects(polygonA: Polygon, polygonB: Polygon) -> Bool {

    for polygon in [polygonA, polygonB] {
    for index in 0..<polygon.points.count {
    let nextIndex = (index + 1) % polygon.points.count
    let point1 = polygon.points[index]
    let point2 = polygon.points[nextIndex]
    for index in 0..<polygon.vertexs.count {
    let nextIndex = (index + 1) % polygon.vertexs.count
    let point1 = polygon.vertexs[index]
    let point2 = polygon.vertexs[nextIndex]

    let normal = CGPoint(x: -(point2.y - point1.y), y: point2.x - point1.x)

    @@ -63,38 +69,25 @@ extension UIView {

    return true
    }


    private func convertToPolygon(_ view: UIView) -> Polygon {
    let transform = view.transform
    var point: CGPoint = CGPoint(x: view.bounds.midX, y: view.bounds.midY)

    point.x = -point.x
    point.y = -point.y
    var tL = __CGPointApplyAffineTransform(point, transform)
    tL.x += view.center.x
    tL.y += view.center.y

    point.x = -point.x;
    var tR = __CGPointApplyAffineTransform(point, transform)
    tR.x += view.center.x
    tR.y += view.center.y

    point.y = -point.y;
    var bR = __CGPointApplyAffineTransform(point, transform)
    bR.x += view.center.x
    bR.y += view.center.y
    private func projectionOf(_ polygon: Polygon, with normal: CGPoint) -> (minP: CGFloat, maxP: CGFloat) {
    var minProjection: CGFloat = .infinity
    var maxProjection: CGFloat = -.infinity

    point.x = -point.x;
    var bL = __CGPointApplyAffineTransform(point, transform)
    bL.x += view.center.x
    bL.y += view.center.y
    for point in polygon.vertexs {
    let projection: CGFloat = point.x * normal.x + point.y * normal.y

    if projection > maxProjection {
    maxProjection = projection
    }

    if projection < minProjection {
    minProjection = projection
    }
    }

    let polygon = Polygon(vertexA: tL,
    vertexB: tR,
    vertexC: bR,
    vertexD: bL)
    return (minProjection, maxProjection)

    return polygon
    }

    }
  5. @calosth calosth revised this gist Feb 19, 2019. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions UIView+Intersection.swift
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    extension UIView {

    /// Given detects collision between the receiver and a given view
    /// - Parameter view2: the view to compare with
    public func intersectsWith(_ view2: UIView) -> Bool {

    let polygonA = convertToPolygon(self)
  6. @calosth calosth renamed this gist Feb 19, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  7. @calosth calosth revised this gist Feb 19, 2019. 1 changed file with 0 additions and 3 deletions.
    3 changes: 0 additions & 3 deletions UIView+Intersetion.swift
    Original file line number Diff line number Diff line change
    @@ -38,10 +38,7 @@ extension UIView {
    }
    }


    return (minProjection, maxProjection)


    }

    private func intersects(polygonA: Polygon, polygonB: Polygon) -> Bool {
  8. @calosth calosth revised this gist Feb 19, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion UIView+Intersetion.swift
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    extension UIView {

    /// Given detects collision between the receiver and a given view
    func intersectsWith(_ view2: UIView) -> Bool {
    public func intersectsWith(_ view2: UIView) -> Bool {

    let polygonA = convertToPolygon(self)
    let polygonB = convertToPolygon(view2)
  9. @calosth calosth created this gist Feb 19, 2019.
    102 changes: 102 additions & 0 deletions UIView+Intersetion.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    extension UIView {

    /// Given detects collision between the receiver and a given view
    func intersectsWith(_ view2: UIView) -> Bool {

    let polygonA = convertToPolygon(self)
    let polygonB = convertToPolygon(view2)

    return intersects(polygonA: polygonA, polygonB: polygonB)
    }

    private struct Polygon {
    var points: [CGPoint] = []

    /// Create a 2D rectangle polygon
    init(vertexA: CGPoint, vertexB: CGPoint, vertexC: CGPoint, vertexD: CGPoint) {
    points.append(vertexA)
    points.append(vertexB)
    points.append(vertexC)
    points.append(vertexD)
    }

    }

    private func projectionOf(_ polygon: Polygon, with normal: CGPoint) -> (minP: CGFloat, maxP: CGFloat) {
    var minProjection: CGFloat = .infinity
    var maxProjection: CGFloat = -.infinity

    for point in polygon.points {
    let projection: CGFloat = point.x * normal.x + point.y * normal.y

    if projection > maxProjection {
    maxProjection = projection
    }

    if projection < minProjection {
    minProjection = projection
    }
    }


    return (minProjection, maxProjection)


    }

    private func intersects(polygonA: Polygon, polygonB: Polygon) -> Bool {

    for polygon in [polygonA, polygonB] {
    for index in 0..<polygon.points.count {
    let nextIndex = (index + 1) % polygon.points.count
    let point1 = polygon.points[index]
    let point2 = polygon.points[nextIndex]

    let normal = CGPoint(x: -(point2.y - point1.y), y: point2.x - point1.x)

    let (minProjectionA, maxProjectionA) = projectionOf(polygonA, with: normal)
    let (minProjectionB, maxProjectionB) = projectionOf(polygonB, with: normal)

    if maxProjectionA < minProjectionB || maxProjectionB < minProjectionA {
    return false
    }
    }
    }

    return true
    }

    private func convertToPolygon(_ view: UIView) -> Polygon {
    let transform = view.transform
    var point: CGPoint = CGPoint(x: view.bounds.midX, y: view.bounds.midY)

    point.x = -point.x
    point.y = -point.y
    var tL = __CGPointApplyAffineTransform(point, transform)
    tL.x += view.center.x
    tL.y += view.center.y

    point.x = -point.x;
    var tR = __CGPointApplyAffineTransform(point, transform)
    tR.x += view.center.x
    tR.y += view.center.y

    point.y = -point.y;
    var bR = __CGPointApplyAffineTransform(point, transform)
    bR.x += view.center.x
    bR.y += view.center.y

    point.x = -point.x;
    var bL = __CGPointApplyAffineTransform(point, transform)
    bL.x += view.center.x
    bL.y += view.center.y

    let polygon = Polygon(vertexA: tL,
    vertexB: tR,
    vertexC: bR,
    vertexD: bL)

    return polygon
    }

    }