我有一个代表椭圆的CGPath。我想在该路径上的随机点放置一个精灵节点。如何在CGPath上获得随机CGPoint?
答案 0 :(得分:1)
谈到一个已关闭的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))
}
}
我使用了我的irregulars多边形的跟随方法,它基于三角形,所以如果你使用弧线,一些曲线部分将丢失(如果你有任何建议评论,请不要感激) :
CGPath
边界点(构成我路径的元素)CGPath
这是三角形方法:
func getRandomPointInTriangle (aPoint:CGPoint,bPoint:CGPoint,cPoint:CGPoint)->CGPoint {
var randomA = CGFloat(Float(arc4random()) / Float(UINT32_MAX))
var randomB = CGFloat(Float(arc4random()) / Float(UINT32_MAX))
if (randomA + randomB > 1) {
randomA = 1-randomA
randomB = 1-randomB
}
let randomC = 1-randomA-randomB
let rndX = (randomA*aPoint.x)+(randomB*bPoint.x)+(randomC*cPoint.x)
let rndY = (randomA*aPoint.y)+(randomB*bPoint.y)+(randomC*cPoint.y)
return CGPointMake(rndX,rndY)
}
这是主要方法:
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])
}
答案 1 :(得分:0)
原谅复活:)
取边界框并在两个相对的边上挑选两个随机点(这应该保证一条线穿过路径的某个点。
使用path.contains()走线,找到路径中的第一个点。
当然这不是随机的,因为它忽略了'内部'循环,所以如果你想要更随机,走完整行并记录所有的交叉点,然后选择一个随机的交叉点。
它仍然不是很随机,因为它有利于周边更多的“中心”点。
接下来的优化,也许你需要更快一些,而path.contains()并没有削减它。
将您的路径绘制到屏幕外位图(笔触,无填充),然后检查点是否在路径上,您只需要获得该点的颜色。这应该比path.contains()快很多。