बेजियर घटता में समतुल्य बिंदु

Currently, I'm attempting to make multiple beziers have equidistant points. I'm currently using cubic interpolation to find the points, but because the way beziers work some areas are more dense than others and proving gross for texture mapping because of the variable distance. Is there a way to find points on a bezier by distance rather than by percentage? Furthermore, is it possible to extend this to multiple connected curves?

0
ro fr bn
math.stackexchange.com/a/61796/589 भी देखें।
जोड़ा लेखक lhf, स्रोत

3 उत्तर

P_0 और P_3 (क्यूबिक रूप में) के बीच की दूरी, हां, लेकिन मुझे लगता है कि आप जानते थे कि, सीधे आगे है।

वक्र पर दूरी सिर्फ चाप लंबाई है:

fig 1 http://www.codecogs.com/eq.latex?%5Cint_%7Bt_0%7D%5E%7Bt_1%7D%20%7B%20|P'(t)|%20dt

कहा पे:

fig 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 (2 डी विमान) होगा।

0
जोड़ा
इस प्रकार आप पैरामीटर दिए गए आर्क लंबाई को पाते हैं, लेकिन समतुल्य बिंदुओं को ढूंढने के लिए इस फ़ंक्शन के विपरीत की आवश्यकता होती है। एक से दूसरे तक हो जाना तुच्छ नहीं है। @ क्रिस्टियन रोमो: आपने यह कैसे किया? मेरा मतलब है, आप केवल बाइनरी खोज का उपयोग कर सकते हैं, लेकिन यह बहुत धीमा होगा (जो भी मैं करने की कोशिश कर रहा हूं, वैसे भी)।
जोड़ा लेखक CromTheDestroyer, स्रोत

इसे "आर्क लंबाई" पैरामीटरकरण कहा जाता है। मैंने कई सालों पहले इस बारे में एक पेपर लिखा था:

http://www.saccade.com/writing/graphics/RE-PARAM.PDF

विचार "पैरामीटर" वक्र को पूर्व-गणना करना है, और इसके माध्यम से वक्र का मूल्यांकन करना है।

0
जोड़ा
एनयूआरबी का उपयोग करने से मदद नहीं मिलेगी, मौलिक समस्या एक जैसी है। पेपर का अंत मूल के साथ पुनः पैरामीटरकरण वक्र लिखने की एक विधि दिखाता है। यह आर्क-लम्बा पैरामीटर के साथ एक नया वक्र उत्पन्न करता है, लेकिन वक्र अधिक होने पर ऑर्डर देता है, इसलिए यह मूल्यांकन करने में धीमा है।
जोड़ा लेखक J. Peterson, स्रोत
कागज को पूरी तरह से अभी तक नहीं पढ़ा है। लेकिन मैं यह पूछना चाहता हूं कि वक्र को परिभाषित करने का बेहतर तरीका है जिसे पहले "रूपांतरित" करने की आवश्यकता नहीं होगी। जैसे क्या आप जानते हैं कि क्या मैं सभी पथ/घटता को परिभाषित करने के लिए NURBS का उपयोग करता हूं, क्या यह तेजी से समतुल्य चाप लंबाई parametrization का समर्थन करेगा? या शायद कुछ और रास्ता? संपादित करें: तेजी से मेरा मतलब है सीपीयू या जीपीयू का उपयोग करना।
जोड़ा लेखक Ciantic, स्रोत

मुझे पता है कि यह एक पुराना सवाल है लेकिन मैंने हाल ही में इस समस्या में भाग लिया और एक UI समन्वय के लिए हल करने के लिए UIBezierPath विस्तार को बनाया वाई समन्वय दिया गया और बनाम बनाम। तेजी से लिखा है।

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)
}

}
0
जोड़ा