Core graphics 在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上获得一个随机CGPoint?

谈到一个封闭的
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])
}