Swi*_*yJD 2 arrays cgpoint ios swift
我有一组 CGPoints:
let points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)]
Run Code Online (Sandbox Code Playgroud)
我想做的是找到 CGPoints 的中心。所以我可以将一个对象放置在所有点的中心。如果这是一个整数数组,我会像这样减少数组:
points.reduce(0, +)
Run Code Online (Sandbox Code Playgroud)
然后除以数组总数以获得平均值。但由于它的 CGPoints 这不起作用。关于如何实现这一目标有什么想法吗?
Farhad 回答了有关如何平均所有这些数据点的问题。(+1)
\n\n但这真的是你想要的吗?考虑:
\n\n\n\n该凸形状由蓝点定义,但所有这些点的平均值是红点。但 \xe2\x80\x99 并不真正位于形状的中心。它是倾斜的,因为顶部附近有五个数据点,下面只有两个数据点。这个凸形状很好地说明了问题,但是\xe2\x80\x99不需要凸形状才能体现这个问题。数据点分布不相对均匀的任何情况都可以体现这种行为。
\n\n绿点是多边形的质心。您可以看到它落在边界框中心(上图中的十字准线)下方,就像您\xe2\x80\x99d 所期望的那样。对于简单的形状,这可能是放置标签的更好位置。可以按下式计算:
\n\nextension Array where Element == CGPoint {\n /// Calculate signed area.\n ///\n /// See https://en.wikipedia.org/wiki/Centroid#Of_a_polygon\n ///\n /// - Returns: The signed area\n\n func signedArea() -> CGFloat {\n if isEmpty { return .zero }\n\n var sum: CGFloat = 0\n for (index, point) in enumerated() {\n let nextPoint: CGPoint\n if index < count-1 {\n nextPoint = self[index+1]\n } else {\n nextPoint = self[0]\n }\n\n sum += point.x * nextPoint.y - nextPoint.x * point.y\n }\n\n return sum / 2\n }\n\n /// Calculate centroid\n ///\n /// See https://en.wikipedia.org/wiki/Centroid#Of_a_polygon\n ///\n /// - Note: If the area of the polygon is zero (e.g. the points are collinear), this returns `nil`.\n ///\n /// - Parameter points: Unclosed points of polygon.\n /// - Returns: Centroid point.\n\n func centroid() -> CGPoint? {\n if isEmpty { return nil }\n\n let area = signedArea()\n if area == 0 { return nil }\n\n var sumPoint: CGPoint = .zero\n\n for (index, point) in enumerated() {\n let nextPoint: CGPoint\n if index < count-1 {\n nextPoint = self[index+1]\n } else {\n nextPoint = self[0]\n }\n\n let factor = point.x * nextPoint.y - nextPoint.x * point.y\n sumPoint.x += (point.x + nextPoint.x) * factor\n sumPoint.y += (point.y + nextPoint.y) * factor\n }\n\n return sumPoint / 6 / area\n }\n\n func mean() -> CGPoint? {\n if isEmpty { return nil }\n\n return reduce(.zero, +) / CGFloat(count)\n }\n}\n\nextension CGPoint {\n static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {\n CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)\n }\n\n static func - (lhs: CGPoint, rhs: CGPoint) -> CGPoint {\n CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)\n }\n\n static func / (lhs: CGPoint, rhs: CGFloat) -> CGPoint {\n CGPoint(x: lhs.x / rhs, y: lhs.y / rhs)\n }\n\n static func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint {\n CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n你\xe2\x80\x99d 计算质心如下:
\n\nlet points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)]\n .map(CGPoint.init)\n\nguard let point = points.centroid() else { return }\nRun Code Online (Sandbox Code Playgroud)\n\nFWIW,对于复杂的凹形形状,即使质心也不是最佳的。请参阅找到不规则形状多边形的“视觉”中心的最快方法是什么?
\n