Core graphics 在CGPath上获取随机CGPoint
我有一个代表椭圆的CGPath。我想在路径上的任意点放置一个精灵节点。如何在该CGPath上获得一个随机CGPoint?谈到一个封闭的Core graphics 在CGPath上获取随机CGPoint,core-graphics,cgpoint,cgpath,Core Graphics,Cgpoint,Cgpath,我有一个代表椭圆的CGPath。我想在路径上的任意点放置一个精灵节点。如何在该CGPath上获得一个随机CGPoint?谈到一个封闭的CGPath并考虑一种快速方法来获得CGPath内无限多个点之间的随机点,首先我将其转换为Swift,如下: extension CGPath { func forEach(@noescape body: @convention(block) (CGPathElement) -> Void) { typealias Body = @c
CGPath
并考虑一种快速方法来获得CGPath
内无限多个点之间的随机点,首先我将其转换为Swift,如下:
extension CGPath {
func forEach(@noescape body: @convention(block) (CGPathElement) -> Void) {
typealias Body = @convention(block) (CGPathElement) -> Void
func callback(info: UnsafeMutablePointer<Void>, element: UnsafePointer<CGPathElement>) {
let body = unsafeBitCast(info, Body.self)
body(element.memory)
}
//print(sizeofValue(body))
let unsafeBody = unsafeBitCast(body, UnsafeMutablePointer<Void>.self)
CGPathApply(self, unsafeBody, callback)
}
func getPathElementsPoints() -> [CGPoint] {
var arrayPoints : [CGPoint]! = [CGPoint]()
self.forEach { element in
switch (element.type) {
case CGPathElementType.MoveToPoint:
arrayPoints.append(element.points[0])
case .AddLineToPoint:
arrayPoints.append(element.points[0])
case .AddQuadCurveToPoint:
arrayPoints.append(element.points[0])
arrayPoints.append(element.points[1])
case .AddCurveToPoint:
arrayPoints.append(element.points[0])
arrayPoints.append(element.points[1])
arrayPoints.append(element.points[2])
default: break
}
}
return arrayPoints
}
func spriteKitCenter() ->CGPoint {
let shape = SKShapeNode(path: self)
return CGPointMake(CGRectGetMidX(shape.frame),CGRectGetMidY(shape.frame))
}
func uiKitCenter() ->CGPoint {
let layer = CAShapeLayer()
layer.path = self
return CGPointMake(CGRectGetMidX(layer.frame),CGRectGetMidY(layer.frame))
}
}
这是主要的方法:
func getRandomPoint()->CGPoint {
let points = self.path!.getPathElementsPoints()
let center = self.path!.spriteKitCenter()
// divide the cgpath in triangles
var triangles = Array<Array<CGPoint>>()
for i in 0..<points.count-1 {
let triangle = [center,points[i],points[i+1]]
triangles.append(triangle)
}
let chooseTriangleNum = Int(arc4random()) % triangles.count
let chooseTriangle = triangles[chooseTriangleNum]
return getRandomPointInTriangle(chooseTriangle[0],bPoint: chooseTriangle[1],cPoint: chooseTriangle[2])
}
func getRandomPoint()->CGPoint{
设points=self.path!.getPathElementsPoints()
让center=self.path!.spriteKitCenter()
//将路径划分为三角形
变量三角形=数组()
因为我在0….原谅复活:)
以边界框为例,在两个相对的边上随机选取两个点(这应保证一条线穿过路径的某个点)
使用path.contains()遍历直线,以查找路径中的第一个点
这当然不是非常随机的,因为它忽略了“内部”循环,因此如果您想要更多随机性,请遍历整条线路并记录所有交叉点,然后选择一个随机交叉点
它仍然不是很随机,因为它更倾向于周边的“中心”点
下一次优化,也许您需要更快一点,而path.contains()并没有削减它
绘制屏幕外位图的路径(笔划,无填充),然后检查路径上是否有点,只需获取该点的颜色。这应该比path.contains()快得多.我见过的唯一一个不涉及supermath ^tm的解决方案是,用一条1的虚线划过路径,然后从划过的路径中推断出点。没有任何线索表明这是真的,或者仍然相关。你解决过这个问题吗?我只是有一些模糊的策略,如果椭圆是完美的圆形,就像一个时钟,那么我们很容易改变“起点”在创建椭圆时,只需使用旋转变换。在我目前的情况下,我的椭圆不是完全圆的,但可能通过一些调整它仍然可以工作…嗯…@Jonny我还没有解决它,但与你的想法类似,你可以创建一个圆,在0到2pi之间随机旋转,然后将其转换为椭圆,然后开始椭圆的点是随机的吗?我已经有一段时间没有讨论过这个问题了,所以我不记得“将它转换为椭圆”是不是一个东西。我用别人指出的另一种方法“解决”了它;我们可以在路径上画一条虚线,然后使用cgpathpapply(我想)迭代用于绘制虚线路径的所有绘制操作/元素。这有点复杂,但肯定有效。我们可以将这些操作的点用作椭圆路径上的点。这需要一些调整。你可能不会得到椭圆的无限随机点,只可能是这些点的起点,或者无论你如何调整它。大家好,有人解决了这个问题吗。我也有相同的术语,不同的形状,如正方形、菱形、钻石等。我想用相同的…请发布一个答案或一些有用的链接。谢谢大家。你能提供一些代码来配合这个答案吗?
func getRandomPoint()->CGPoint {
let points = self.path!.getPathElementsPoints()
let center = self.path!.spriteKitCenter()
// divide the cgpath in triangles
var triangles = Array<Array<CGPoint>>()
for i in 0..<points.count-1 {
let triangle = [center,points[i],points[i+1]]
triangles.append(triangle)
}
let chooseTriangleNum = Int(arc4random()) % triangles.count
let chooseTriangle = triangles[chooseTriangleNum]
return getRandomPointInTriangle(chooseTriangle[0],bPoint: chooseTriangle[1],cPoint: chooseTriangle[2])
}