objective-c - 修剪 CGRect 内的直线(2 个 CGPoint)

标签 objective-c swift math cgrect cgpoint

给定一个 CGRect 和一条用 2 个 CGPoint 创建的线,有没有办法找到该线与矩形相交的坐标?

enter image description here

从上图中:我想要实现的是将矩形外部的点替换为与矩形边框相交的红点。

简而言之,我正在寻找一种在矩形内修剪线条的方法。

这是一个数学问题,但我想知道如果可能的话如何使用基础来解决这个问题。

根据最新评论: 看来 Core Graphics 在这个过程中并不能真正提供帮助。我可以在 Swift 中转换的任何其他提示或公式吗?

最佳答案

类似这样的东西(经过轻微测试),基于 How do you detect where two line segments intersect?

import CoreGraphics

let rect = CGRect(x: 10, y: 10, width: 100, height: 100)

let point1 = CGPoint(x: 200, y: 200)
let point2 = CGPoint(x: 20, y: 20)

struct LineSegment {
    var point1: CGPoint
    var point2: CGPoint

    func intersection(with line: LineSegment) -> CGPoint? {
        // We'll use Gavin's interpretation of LeMothe:
        // https://stackoverflow.com/a/1968345/97337

        let p0_x = self.point1.x
        let p0_y = self.point1.y
        let p1_x = self.point2.x
        let p1_y = self.point2.y

        let p2_x = line.point1.x
        let p2_y = line.point1.y
        let p3_x = line.point2.x
        let p3_y = line.point2.y

        let s1_x = p1_x - p0_x
        let s1_y = p1_y - p0_y
        let s2_x = p3_x - p2_x
        let s2_y = p3_y - p2_y

        let denom = (-s2_x * s1_y + s1_x * s2_y)

        // Make sure the lines aren't parallel
        guard denom != 0 else { return nil } // parallel

        let s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / denom
        let t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / denom

        // We've parameterized these lines as "origin + scale*vector"
        // (s is the "scale" along one line, t is the "scale" along the other.
        // At scale=0, we're at the origin at scale=1, we're at the terminus.
        // Make sure we crossed between those. For more on what I mean by
        // "parameterized" and why we go from 0 to 1, look up Bezier curves.
        // We're just making a 1-dimentional Bezier here.
        guard (0...1).contains(s) && (0...1).contains(t) else { return nil }

        // Collision detected
        return CGPoint(x: p0_x + (t * s1_x), y: p0_y + (t * s1_y))
    }
}

extension CGRect {    
    var edges: [LineSegment] {
        return [
            LineSegment(point1: CGPoint(x: minX, y: minY), point2: CGPoint(x: minX, y: maxY)),
            LineSegment(point1: CGPoint(x: minX, y: minY), point2: CGPoint(x: maxX, y: minY)),
            LineSegment(point1: CGPoint(x: minX, y: maxY), point2: CGPoint(x: maxX, y: maxY)),
            LineSegment(point1: CGPoint(x: maxX, y: minY), point2: CGPoint(x: maxX, y: maxY)),
        ]
    }

    func intersection(with line: LineSegment) -> CGPoint? {

    // Let's be super-simple here and require that one point be in the box and one point be outside,
    // then we can ignore lots of corner cases
        guard contains(line.point1) && !contains(line.point2) ||
            contains(line.point2) && !contains(line.point1) else { return nil }

        // There are four edges. We might intersect with any of them (we know
        // we intersect with exactly one, based on the previous guard.
        // We could do a little math and figure out which one it has to be,
        // but the `if` would be really tedious, so let's just check them all.
        for edge in edges {
            if let p = edge.intersection(with: line) {
                return p
            }
        }

        return nil
    }
}

rect.intersection(with: LineSegment(point1: point1, point2: point2))

关于objective-c - 修剪 CGRect 内的直线(2 个 CGPoint),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42143786/

相关文章:

ios - 为什么在 XCode 调试器中使用 "Step over"功能会隐藏本应强大的弱属性的问题

c# - 两个数字之间的差异

c++ - 优化稀疏矩阵中的对数熵计算

javascript - 如何计算给定数字的ln?

ios - 当我们点击 iOS slider 菜单上的特定单元格时,如何显示可展开的单元格?

swift - 从异步后台任务设置 UIProgressView

c# - 用于 Unity 的 Objective C iOS 插件

ios - 从 UIToolbar 子类切换 View Controller

php - 从本地主机 :8888 in objective c using json 获取数据时出现问题

swift - 在协议(protocol)扩展中将方法标记为 final