Swift需求:实现方法获取圆角矩形/圆角正方形周边n个带角度的点
Swift实现圆角矩形周边等角度分布点的坐标与角度计算
核心思路
以圆角矩形的中心为极坐标原点,将0~2π的圆周均分为numberOfPoints个角度,对每个角度计算射线与圆角矩形边界的交点,同时保留该角度值。这种方法能近似实现类似Apple Watch界面的等角度分布效果,且逻辑简洁易实现。
完整实现代码
import CoreGraphics import SwiftUI // 若不需要SwiftUI的Angle,可替换为自定义弧度/角度类型 func getCoordinates(of numberOfPoints: Int, in roundedRect: CGRect, with cornerRadius: CGFloat) -> [(CGPoint, Angle)] { guard numberOfPoints > 0 else { return [] } let center = CGPoint(x: roundedRect.midX, y: roundedRect.midY) let halfWidth = roundedRect.width / 2 - cornerRadius let halfHeight = roundedRect.height / 2 - cornerRadius let twoPi = CGFloat.pi * 2 var result = [(CGPoint, Angle)]() for i in 0..<numberOfPoints { let radians = twoPi * CGFloat(i) / CGFloat(numberOfPoints) let angle = Angle(radians: radians) let dx = cos(radians) let dy = sin(radians) var intersectionPoint: CGPoint // 判断射线更靠近水平边还是垂直边 let horizontalRatio = abs(dx / halfWidth) let verticalRatio = abs(dy / halfHeight) if horizontalRatio >= verticalRatio { // 射线指向左右方向区域 let signX = dx >= 0 ? 1.0 : -1.0 let x = center.x + signX * halfWidth let y = center.y + (x - center.x) * (dy / dx) if y >= center.y - halfHeight && y <= center.y + halfHeight { // 交点在直边上 intersectionPoint = CGPoint(x: x, y: y) } else { // 交点在圆角上,确定对应角的圆心 let signY = y >= center.y ? 1.0 : -1.0 let cornerCenter = CGPoint(x: center.x + signX * halfWidth, y: center.y + signY * halfHeight) // 计算从圆角圆心指向射线方向的单位向量 let direction = CGPoint(x: dx, y: dy).normalized() intersectionPoint = CGPoint( x: cornerCenter.x + direction.x * cornerRadius, y: cornerCenter.y + direction.y * cornerRadius ) } } else { // 射线指向上下方向区域 let signY = dy >= 0 ? 1.0 : -1.0 let y = center.y + signY * halfHeight let x = center.x + (y - center.y) * (dx / dy) if x >= center.x - halfWidth && x <= center.x + halfWidth { // 交点在直边上 intersectionPoint = CGPoint(x: x, y: y) } else { // 交点在圆角上,确定对应角的圆心 let signX = x >= center.x ? 1.0 : -1.0 let cornerCenter = CGPoint(x: center.x + signX * halfWidth, y: center.y + signY * halfHeight) // 计算从圆角圆心指向射线方向的单位向量 let direction = CGPoint(x: dx, y: dy).normalized() intersectionPoint = CGPoint( x: cornerCenter.x + direction.x * cornerRadius, y: cornerCenter.y + direction.y * cornerRadius ) } } result.append((intersectionPoint, angle)) } return result } // 辅助扩展:将CGPoint转换为单位向量 extension CGPoint { func normalized() -> CGPoint { let length = sqrt(x*x + y*y) guard length != 0 else { return .zero } return CGPoint(x: x/length, y: y/length) } }
关键代码说明
- 边界判断:通过比较水平/垂直方向的比率,确定射线先接触直边还是圆角区域
- 直边交点计算:根据射线方向计算与矩形直边的交点,判断是否在合法范围内
- 圆角交点计算:若射线指向圆角区域,先确定对应圆角的圆心,再沿射线方向取半径长度的点作为交点
- 角度保留:直接使用均分后的弧度值创建
Angle,与返回的坐标一一对应
内容的提问来源于stack exchange,提问作者ixany
相关产品推荐
相关产品推荐

