Chiều dài đường cong vòng cung Bezier


23

Xem thêm: câu hỏi tương tự trên Math.SE

Làm thế nào tôi có thể tìm thấy đường cong của đường cong Bezier? Ví dụ: đường cong Bezier tuyến tính có độ dài:

length = sqrt(pow(x[1] - x[0], 2) + pow(y[1] - y[0], 2));

Nhưng những gì về đường cong Bezier bậc hai, khối, hoặc n độ?

(Mục tiêu của tôi là ước tính độ phân giải lấy mẫu trước, vì vậy tôi không phải lãng phí thời gian để kiểm tra xem điểm tiếp theo có chạm vào điểm trước hay không.)


1
Bạn nên đặt lại câu hỏi để chỉ độ dài của đường cong, đó là một thuật ngữ đơn giản hơn (và có thể tìm kiếm).
Sparr

Tôi đề nghị đăng bài này lên toán, tôi chắc chắn một số gương mặt thông minh ở đó sẽ cho bạn câu trả lời bằng một trong số các phông chữ thông minh trên web: p
Tor Valamo

2
@Tor tôi đã làm (ngày hôm qua), nhưng tôi đã nói rằng nó rất phức tạp, và do đó không thực tế. [ math.stackexchange.com/q/12186/2736 ]
Mateen Ulhaq

Các đường cong / spline được cho là thay thế cho beziers và có các biểu thức arclength dạng đóng, nhưng tôi chưa biết nhiều về điều này. (Cố gắng tạo các điểm có khoảng cách bằng nhau dọc theo một đường cong.) Catenaries cũng có biểu thức độ dài cung dạng kín?
endolith

Câu trả lời:


9

Một cách đơn giản cho Beziers hình khối là chia đường cong thành N đoạn và tính tổng độ dài của các đoạn.

Tuy nhiên, ngay khi bạn cần độ dài chỉ một phần của đường cong (ví dụ: tối đa 30% chiều dài), tham số hóa độ dài cung sẽ xuất hiện. Tôi đã đăng một câu trả lời khá dài về một trong những câu hỏi của riêng tôi về Béziers, với mã mẫu đơn giản.


Tôi đang làm điều này cho LEGO Mindstorms NXT, có bộ xử lý thực sự yếu (48Mhz), vì vậy tôi cần tốc độ càng nhiều càng tốt. Tôi sẽ thực hiện phương pháp phân chia để bảo toàn tốc độ và làm cho nó đủ chính xác (để kết xuất "không theo thời gian thực"). Tôi cũng có một tùy chọn trong đó bạn có thể đặt giá trị của 1.0/t(được gọi resolution), vì vậy đó là "thời gian thực" (tốc độ tối đa 10 khung hình / giây trên NXT chậm). Mỗi lần lặp, t += resolutionvà một điểm / dòng mới được rút ra. Dù sao, cảm ơn cho ý tưởng.
Mateen Ulhaq

4

Trong khi tôi đang trả lời các câu trả lời bạn đã có, tôi muốn thêm một cơ chế xấp xỉ đơn giản nhưng mạnh mẽ mà bạn có thể sử dụng cho bất kỳ đường cong Bézier nào: Bạn liên tục chia nhỏ đường cong bằng cách sử dụng phân khu de Casteljau cho đến khoảng cách tối đa của các điểm kiểm soát của một đường cong phụ đến đường cơ sở của đường cong phụ nằm dưới một số epsilon không đổi . Trong trường hợp đó, đường cong phụ có thể được xấp xỉ bởi đường cơ sở của nó.

Trên thực tế, tôi tin rằng đây là cách tiếp cận thường được thực hiện khi một hệ thống con đồ họa phải vẽ đường cong Bézier. Nhưng đừng trích dẫn tôi về điều này, hiện tại tôi không có tài liệu tham khảo.

Trong thực tế, nó sẽ trông như thế này: (ngoại trừ ngôn ngữ là không liên quan)

public static Line[] toLineStrip(BezierCurve bezierCurve, double epsilon) {
    ArrayList<Line> lines = new ArrayList<Line>();

    Stack<BezierCurve> parts = new Stack<BezierCurve>();
    parts.push(bezierCurve);

    while (!parts.isEmpty()) {
        BezierCurve curve = parts.pop();
        if (distanceToBaseline(curve) < epsilon) {
            lines.add(new Line(curve.get(0), curve.get(1)));
        } else {
            parts.addAll(curve.split(0.5));
        }
    }

    return lines.toArray(new Line[0]);
}

Mặc dù đây là một cách tiếp cận tốt, tôi đã nghe nói về sự không ổn định về số ở các đường cong Bezier bậc cao, đòi hỏi một ý tưởng khác: chia các đường cong bậc cao thành các đường cong khối nhỏ hơn.
Mateen Ulhaq

Ngoài ra, nếu mục tiêu cuối cùng là ước tính chính xác, có thể là một ý tưởng tốt để ước tính với các ô vuông thay vì các đường để đảm bảo rằng chúng tôi không đánh giá thấp ước tính của chúng tôi tại các vị trí có độ cong cao.
Mateen Ulhaq

2

Độ dài vòng cung cho các đường cong Bezier chỉ là dạng đóng cho các đường thẳng và bậc hai. Đối với hình khối, nó không được đảm bảo để có một giải pháp khép kín. Lý do là độ dài cung được xác định bởi một tích phân triệt để, trong đó chỉ đóng cho đa thức bậc 2.

Chỉ để tham khảo: Độ dài của một Bezier bậc hai cho các điểm (a, p) (b, q) và (c, r) là

(a ^ 2 · (q ^ 2 - 2 · q · r + r ^ 2) + 2 · a · (r - q) · (b · (p - r) + c · (q - p)) + ( b · (p - r) + c · (q - p)) ^ 2) · LN ((√ (a ^ 2 - 2 · a · b + b ^ 2 + p ^ 2 - 2 · p · q + q ^ 2) · (a ^ 2 + 2 · a · (c - 2 · b) + 4 · b ^ 2 - 4 · b · c + c ^ 2 + (p - 2 · q + r) ^ 2) + a ^ 2 + a · (c - 3 · b) + 2 · b ^ 2 - b · c + (p - q) · (p - 2 · q + r)) / (√ (a ^ 2 + 2 · A · (c - 2 · b) + 4 · b ^ 2 - 4 · b · c + c ^ 2 + (p - 2 · q + r) ^ 2) · √ (b ^ 2 - 2 · b · c + c ^ 2 + q ^ 2 - 2 · q · r + r ^ 2) + a · (b - c) - 2 · b ^ 2 + 3 · b · c - c ^ 2 + (p - 2 · q + r) · (q - r))) / (a ​​^ 2 + 2 · a · (c - 2 · b) + 4 · b ^ 2 - 4 · b · c + c ^ 2 + (p - 2 · Q + r) ^ 2) ^ (3/2) + (√ (a ^ 2 - 2 · a · b + b ^ 2 + p ^ 2 - 2 · p · q + q ^ 2) · (a ^ 2 + a · (c - 3 · b) + 2 · b ^ 2 - b · c + (p - q) · (p - 2 · q + r)) - √ (b ^ 2 - 2 · b · c + c ^ 2 + q ^ 2 - 2 · q · r + r ^ 2) · (a · (b - c) - 2 · b ^ 2 + 3 · b · c - c ^ 2 + (p - 2 · q + r) · (q - r))) / (a ​​^ 2 + 2 · a · (c - 2 · b) + 4 · b ^ 2 - 4 · b · c + c ^ 2 + (p - 2 · Q + r) ^ 2)

Trong đó LN là logarit tự nhiên và ^ biểu thị sức mạnh và căn bậc hai.

Do đó, nên dễ dàng hơn và rẻ hơn xấp xỉ cung theo một số quy tắc khác, như đa giác hoặc sơ đồ tích hợp như quy tắc của Simpson, bởi vì căn bậc hai LN là các hoạt động đắt tiền.


2

Tôi đã tìm ra biểu thức đóng của độ dài cho Bezier 3 điểm (bên dưới). Tôi đã không cố gắng tạo ra một hình thức đóng cho hơn 4 điểm. Điều này rất có thể sẽ khó khăn hoặc phức tạp để đại diện và xử lý. Tuy nhiên, một kỹ thuật xấp xỉ bằng số như thuật toán tích hợp Runge-Kutta sẽ hoạt động khá tốt bằng cách tích hợp bằng công thức độ dài cung . Câu hỏi và trả lời của tôi về RK45 trên MSE có thể giúp triển khai RK45.

Dưới đây là một số mã Java cho chiều dài hồ quang của một 3 điểm Bezier, với các điểm a, b, và c.

    v.x = 2*(b.x - a.x);
    v.y = 2*(b.y - a.y);
    w.x = c.x - 2*b.x + a.x;
    w.y = c.y - 2*b.y + a.y;

    uu = 4*(w.x*w.x + w.y*w.y);

    if(uu < 0.00001)
    {
        return (float) Math.sqrt((c.x - a.x)*(c.x - a.x) + (c.y - a.y)*(c.y - a.y));
    }

    vv = 4*(v.x*w.x + v.y*w.y);
    ww = v.x*v.x + v.y*v.y;

    t1 = (float) (2*Math.sqrt(uu*(uu + vv + ww)));
    t2 = 2*uu+vv;
    t3 = vv*vv - 4*uu*ww;
    t4 = (float) (2*Math.sqrt(uu*ww));

    return (float) ((t1*t2 - t3*Math.log(t2+t1) -(vv*t4 - t3*Math.log(vv+t4))) / (8*Math.pow(uu, 1.5)));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.