我想找到一个优雅的解决方案,以给定一个点列表来识别矩形的角(我确定将定义一个矩形)。
假设我们有以下CGPoint
数组:
var points:[CGPoint] = []
points.append(CGPoint(x:1, y:0)) //TL
points.append(CGPoint(x:3, y:0)) //TR
points.append(CGPoint(x:1, y:2)) //BL
points.append(CGPoint(x:3, y:2)) //BR
要理解TopLeft拐角处在索引0处,Top Right处在索引1处等等,哪一种是一种优雅的解决方案?
我可以多次遍历该数组并使用比较来找到它……您可以考虑使用sort
或filter
来获得更好的解决方案吗?
编辑:请注意,点数组是无序的。我没有确切的顺序。
答案 0 :(得分:2)
您可以使用map / reduce实现相对简单的语法。假设:
var points: [CGPoint] = []
points.append(CGPoint(x: 3, y: 6))
points.append(CGPoint(x: 4, y: 6))
points.append(CGPoint(x: 4, y: 2))
points.append(CGPoint(x: 3, y: 2))
然后,您可以:
let minX = points.map { $0.x } .reduce(points[0].x) { min($0,$1) }
此时minX =3。您也可以使用sorted(by:)
let minX = points.sorted { $0.x < $1.x }.first!.x
两者都具有处理由点构建的任何形状的优点。 Matt还建议在数组上使用min(),如下所示:
let minX = points.min { $0.x < $1.x }!.x
我想这很干净。
哦,还有更多的书籍……如果要在很多地方将点转换为CGRect,则可以创建一个CGRect扩展名:
extension CGRect {
init(from points: [CGPoint]) {
let xAxis = points.sorted { $0.x < $1.x }
let yAxis = points.sorted { $0.y < $1.y }
self.init(x: xAxis.first!.x, y: yAxis.first!.y, width: xAxis.last!.x - xAxis.first!.x, height: yAxis.last!.y - yAxis.first!.y)
}
}
然后您可以将其用于:
let rect = CGRect(from: points)
// rect.minX
干杯!
答案 1 :(得分:1)
这些是Core Graphics结构,因此请Core Graphics帮助您。从任意点到任意其他点以任意顺序构造路径,并要求其边界框。现在,您有了一个CGRect,其角点就是您的点,但是现在您知道了哪个是角点,并将它们与您的角点进行匹配是微不足道的。
示例:
var points:[CGPoint] = []
points.append(CGPoint(x:1, y:0)) //TL
points.append(CGPoint(x:3, y:0)) //TR
points.append(CGPoint(x:1, y:2)) //BL
points.append(CGPoint(x:3, y:2)) //BR
let path = CGMutablePath()
path.move(to: points[0])
for ix in 1...3 {path.addLine(to: points[ix])}
let rect = path.boundingBox
答案是CGRect(x:1.0, y:0.0, width:2.0, height:2.0)
,现在您知道它的minX
,minY
,maxX
和maxY
,可以轻松地将其匹配到您的原始分数
无论提供点的顺序如何,您都会得到相同的结果。