目前,我试图做多贝济耶有等距点。 我目前使用三次插值找到了点,但因为贝济耶的方式工作,一些地区比其他人更密集,因为可变距离的证明总值纹理映射。 有没有办法通过的距离,而不是按百分比来找到一个贝塞尔曲线点? 此外,是否有可能将其扩展到多个连接的曲线?
Answer 1:
P_0和P_3(立方形式)之间的距离,是的,但我想你知道,是直线前进。
曲线上的距离仅仅是弧长:
图1 http://www.codecogs.com/eq.latex?%5Cint_%7Bt_0%7D%5E%7Bt_1%7D%20%7B%20|P'(t)|%20dt
哪里:
图2 http://www.codecogs.com/eq.latex?P%27(t)%20=%20[%7Bx%27,y%27,z%27%7D]%20=%20[% 7B%5Cfrac%7Bdx(t)的%7D%7Bdt%7D,%5Cfrac%7Bdy(t)的%7D%7Bdt%7D,%5Cfrac%7Bdz(t)的%7D%7Bdt%7D%7D]
(见休息)
大概,你必须T_0 = 0,T_1 = 1.0,和DZ(T)= 0(2D平面)。
Answer 2:
这就是所谓的“弧长”参数。 我以前写了一个关于这个几年纸:
http://www.saccade.com/writing/graphics/RE-PARAM.PDF
我们的想法是预先计算“参数”曲线,并评估通过的曲线。
Answer 3:
我知道这是一个老问题,但我最近就遇到了这个问题,并创建了一个UIBezierPath
extention解决一个X
坐标给出Y
协调,反之亦然。 写在迅速。
https://github.com/rkotzy/RKBezierMath
extension UIBezierPath {
func solveBezerAtY(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, y: CGFloat) -> [CGPoint] {
// bezier control points
let C0 = start.y - y
let C1 = point1.y - y
let C2 = point2.y - y
let C3 = end.y - y
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = C3 - 3.0*C2 + 3.0*C1 - C0
let B = 3.0*C2 - 6.0*C1 + 3.0*C0
let C = 3.0*C1 - 3.0*C0
let D = C0
let roots = solveCubic(A, b: B, c: C, d: D)
var result = [CGPoint]()
for root in roots {
if (root >= 0 && root <= 1) {
result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
}
}
return result
}
func solveBezerAtX(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, x: CGFloat) -> [CGPoint] {
// bezier control points
let C0 = start.x - x
let C1 = point1.x - x
let C2 = point2.x - x
let C3 = end.x - x
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = C3 - 3.0*C2 + 3.0*C1 - C0
let B = 3.0*C2 - 6.0*C1 + 3.0*C0
let C = 3.0*C1 - 3.0*C0
let D = C0
let roots = solveCubic(A, b: B, c: C, d: D)
var result = [CGPoint]()
for root in roots {
if (root >= 0 && root <= 1) {
result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
}
}
return result
}
func solveCubic(a: CGFloat?, var b: CGFloat, var c: CGFloat, var d: CGFloat) -> [CGFloat] {
if (a == nil) {
return solveQuadratic(b, b: c, c: d)
}
b /= a!
c /= a!
d /= a!
let p = (3 * c - b * b) / 3
let q = (2 * b * b * b - 9 * b * c + 27 * d) / 27
if (p == 0) {
return [pow(-q, 1 / 3)]
} else if (q == 0) {
return [sqrt(-p), -sqrt(-p)]
} else {
let discriminant = pow(q / 2, 2) + pow(p / 3, 3)
if (discriminant == 0) {
return [pow(q / 2, 1 / 3) - b / 3]
} else if (discriminant > 0) {
let x = crt(-(q / 2) + sqrt(discriminant))
let z = crt((q / 2) + sqrt(discriminant))
return [x - z - b / 3]
} else {
let r = sqrt(pow(-(p/3), 3))
let phi = acos(-(q / (2 * sqrt(pow(-(p / 3), 3)))))
let s = 2 * pow(r, 1/3)
return [
s * cos(phi / 3) - b / 3,
s * cos((phi + CGFloat(2) * CGFloat(M_PI)) / 3) - b / 3,
s * cos((phi + CGFloat(4) * CGFloat(M_PI)) / 3) - b / 3
]
}
}
}
func solveQuadratic(a: CGFloat, b: CGFloat, c: CGFloat) -> [CGFloat] {
let discriminant = b * b - 4 * a * c;
if (discriminant < 0) {
return []
} else {
return [
(-b + sqrt(discriminant)) / (2 * a),
(-b - sqrt(discriminant)) / (2 * a)
]
}
}
private func crt(v: CGFloat) -> CGFloat {
if (v<0) {
return -pow(-v, 1/3)
}
return pow(v, 1/3)
}
private func bezierOutputAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGPoint {
// bezier control points
let C0 = start
let C1 = point1
let C2 = point2
let C3 = end
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)
let D = C0
return CGPointMake(((A.x*t+B.x)*t+C.x)*t+D.x, ((A.y*t+B.y)*t+C.y)*t+D.y)
}
// TODO: - future implementation
private func tangentAngleAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGFloat {
// bezier control points
let C0 = start
let C1 = point1
let C2 = point2
let C3 = end
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)
return atan2(3.0*A.y*t*t + 2.0*B.y*t + C.y, 3.0*A.x*t*t + 2.0*B.x*t + C.x)
}
}
文章来源: Equidistant points across Bezier curves