如何在iOS/MacOS平台使用Swift计算CGPath与CGRect的相交点

适用平台:iOS 及 MacOS
实现方案
因为需求对结果精度要求不高,这里提供实现成本最低的采样法方案,代码兼容Swift开发,无需引入额外依赖:
核心实现代码
import CoreGraphics /// 计算规则矩形和圆形的两个交点 /// - Parameters: /// - circleCenter: 圆形的圆心坐标 /// - radius: 圆形的半径 /// - rect: 目标矩形 /// - Returns: 两个交点,无相交时返回nil func getRectCircleIntersections(circleCenter: CGPoint, radius: CGFloat, rect: CGRect) -> (p1: CGPoint, p2: CGPoint)? { // 前置判断:两个图形的包围盒不相交直接返回 let circleBounds = CGRect( x: circleCenter.x - radius, y: circleCenter.y - radius, width: radius * 2, height: radius * 2 ) guard circleBounds.intersects(rect) else { return nil } let accuracy: CGFloat = 0.5 // 精度值可自行调整,数值越小精度越高 var resultPoints = [CGPoint]() // 遍历矩形四条边的采样点 let edgePoints = [ // 上边缘 stride(from: rect.minX, through: rect.maxX, by: accuracy).map { CGPoint(x: $0, y: rect.minY) }, // 下边缘 stride(from: rect.minX, through: rect.maxX, by: accuracy).map { CGPoint(x: $0, y: rect.maxY) }, // 左边缘 stride(from: rect.minY, through: rect.maxY, by: accuracy).map { CGPoint(x: rect.minX, y: $0) }, // 右边缘 stride(from: rect.minY, through: rect.maxY, by: accuracy).map { CGPoint(x: rect.maxX, y: $0) } ].flatMap { $0 } for point in edgePoints { // 计算当前点到圆心的距离 let distance = hypot(point.x - circleCenter.x, point.y - circleCenter.y) // 误差范围匹配设置的精度 if abs(distance - radius) < accuracy { resultPoints.append(point) if resultPoints.count == 2 { break } } } guard resultPoints.count >= 2 else { return nil } return (resultPoints[0], resultPoints[1]) }
调用示例
// 示例参数 let circleCenter = CGPoint(x: 100, y: 100) let radius: CGFloat = 50 let rect = CGRect(x: 50, y: 70, width: 100, height: 60) if let intersections = getRectCircleIntersections(circleCenter: circleCenter, radius: radius, rect: rect) { print("交点1:\(intersections.p1),交点2:\(intersections.p2)") }
如果你的场景必须基于转换后的CGPath对象计算,也可以用CoreGraphics自带的路径相交判断能力,配合上面的采样逻辑即可实现,不需要额外做贝塞尔曲线的解析。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

