2011-11-22 57 views
8

Tôi đang làm việc trên một trò chơi trong canvas HTML5.Đường cong Bezier luôn có cùng độ dài

Tôi muốn vẽ đường cong hình tròn khối hình chữ S giữa hai điểm, nhưng tôi đang tìm cách tính toán tọa độ của các điểm điều khiển sao cho bản thân đường cong luôn có cùng độ dài bất kể khoảng cách đó bao nhiêu cho đến khi nó đạt đến điểm mà đường cong trở thành một đường thẳng.

+0

Có quan trọng mà các dòng này là chính xác độ dài giống nhau, hoặc chỉ là nó được cho không khi bắt đầu và điểm kết thúc được gần gũi hơn? – idanzalz

+0

mức độ của bezier (bao nhiêu điểm?) Là nó khối? (4 điểm - bắt đầu, kết thúc và 2 ở giữa) – idanzalz

+0

Một giải pháp nhanh chóng và bẩn là xây dựng nó như một vấn đề tối ưu hóa: Chia đường cong thành một chuỗi các đoạn thẳng và giảm thiểu sự khác biệt giữa tổng chiều dài phân đoạn đường thẳng và độ dài không đổi mong muốn, wrt các điểm kiểm soát miễn phí. Bạn có thể sử dụng các thuật toán như gradient gốc http://en.wikipedia.org/wiki/Gradient_descent cho việc này. Nhưng một giải pháp phân tích sẽ đẹp hơn. – Rulle

Trả lời

2

Điều này có thể giải quyết được bằng số. Tôi giả sử bạn có một bezier khối với 4 điểm kiểm soát. tại mỗi bước bạn có điểm đầu tiên (P0) và cuối cùng (P3), và bạn muốn tính P1 và P2 sao cho tổng chiều dài là không đổi.

Thêm ràng buộc này loại bỏ một mức độ tự do để chúng tôi có 1 trái (bắt đầu bằng 4, xác định điểm cuối (-2) và độ dài không đổi là -1). Vì vậy, bạn cần phải quyết định về điều đó.

Đường cong bezier là đa thức được xác định từ 0 đến 1, bạn cần tích hợp trên căn bậc hai của tổng các phần tử (2d?). cho một bezier khối, điều này có nghĩa là một sqrt của một đa thức 6 độ, mà wolfram không biết làm thế nào để giải quyết. Nhưng nếu bạn có tất cả các điểm điều khiển khác của bạn đã biết (hoặc biết đến một phụ thuộc vào một số ràng buộc khác), bạn có thể có một bảng lưu các giá trị được tính toán trước cho ràng buộc đó.

+0

Thực sự điều này có đơn giản không? Nếu tôi hiểu vấn đề một cách chính xác, chúng ta có một đường cong bezier (x (t), y (t)) trong đó x và y là đa thức bậc ba. Giả sử chúng dẫn xuất, dx/dt (t) = P (t) và dy/dt (t) = Q (t), đó là các đa thức bậc hai. Sau đó, chúng tôi muốn tích hợp chiều dài vòng cung ds = sqrt (dx^2 + dy^2) dt = sqrt (P (t)^2 + Q (t)^2) dt. Tôi không biết làm thế nào cứng là tích hợp các biểu thức căn bậc hai của đa thức bậc bốn nhưng có lẽ phần mềm toán học như Mathematica có thể làm được. – Rulle

+0

đúng, tôi đã tính sai. Tôi sẽ chỉnh sửa – idanzalz

+1

Thoạt nhìn, nó xuất hiện với tôi rằng việc tích hợp căn bậc hai của quartic đó sẽ là Hard. – Harold

2

Có thực sự cần thiết rằng đường cong là đường cong bezier không? Lắp hai vòng cung tròn có tổng chiều dài không đổi là dễ dàng hơn nhiều. Và bạn sẽ luôn nhận được hình chữ S.

Fitting của hai cung tròn:

Fitting two circles

Hãy D là khoảng cách Euclide giữa các điểm cuối. Hãy để C là độ dài không đổi mà chúng tôi muốn. Tôi nhận được biểu thức sau đây cho b (rút ra trong hình ảnh):

b = sqrt(D*sin(C/4)/4 - (D^2)/16) 

tôi đã không kiểm tra nếu nó là đúng vì vậy nếu ai đó có được một cái gì đó khác nhau, để lại nhận xét.

CHỈNH SỬA: Bạn cũng nên xem xét giải pháp âm mà tôi thu được khi giải phương trình và kiểm tra phương trình nào là chính xác.

b = -sqrt(D*sin(C/4)/4 - (D^2)/16) 
+0

Tôi nghĩ câu hỏi được yêu cầu cho một thứ khác, tức là khi điểm kết thúc rất gần, anh ấy muốn S là WIDEST. như tôi hiểu anh ta muốn mô phỏng một sợi dây dài cố định giữa các điểm cuối, vì vậy giải pháp này sẽ không hoạt động – idanzalz

+1

Bạn có thể cải thiện phương pháp này, bằng cách vẽ một nửa hình bầu dục. để vẽ hình bầu dục, bạn có thể vẽ một vòng tròn và sau đó sử dụng tỷ lệ không đồng đều để làm cho hình bầu dục. Tuy nhiên, tôi nghĩ rằng chu vi hình bầu dục cũng không phân tích vì vậy chúng tôi trở lại hình vuông – idanzalz

0

Dưới đây là một ví dụ làm việc trong SVG đó là gần để sửa:
http://phrogz.net/svg/constant-length-bezier.xhtml

enter image description here

Tôi thực nghiệm xác định rằng khi các thiết bị đầu cuối đang lên nhau tay nắm nên
mong muốnLength × cos (30 °)
cách xa các tay cầm; và (tất nhiên) khi các điểm kết thúc ở khoảng cách lớn nhất của chúng, các tay cầm phải nằm trên đỉnh của nhau.Âm mưu tất cả các điểm lý tưởng trông loại như một hình elip:

Graph showing actual points compared to ellipse

Dòng màu xanh là phương trình lý tưởng thực tế, trong khi dòng màu đỏ ở trên là một hình elip gần giống lý tưởng. Sử dụng phương trình cho hình elip (như ví dụ trên của tôi) cho phép các dòng để có được khoảng 9% quá dài ở giữa.

Dưới đây là đoạn mã JavaScript có liên quan:

// M is the MoveTo command in SVG (the first point on the path) 
// C is the CurveTo command in SVG: 
// C.x is the end point of the path 
// C.x1 is the first control point 
// C.x2 is the second control point 
function makeFixedLengthSCurve(path,length){ 
    var dx = C.x - M.x, dy = C.y - M.y; 
    var len = Math.sqrt(dx*dx+dy*dy); 
    var angle = Math.atan2(dy,dx); 
    if (len >= length){ 
    C.x = M.x + 100 * Math.cos(angle); 
    C.y = M.y + 100 * Math.sin(angle); 
    C.x1 = M.x; C.y1 = M.y; 
    C.x2 = C.x; C.y2 = C.y; 
    }else{ 
    // Ellipse of major axis length and minor axis length*cos(30°) 
    var a = length, b = length*Math.cos(30*Math.PI/180); 
    var handleDistance = Math.sqrt(b*b * (1 - len*len/(a*a))); 
    C.x1 = M.x + handleDistance * Math.sin(angle); 
    C.y1 = M.y - handleDistance * Math.cos(angle); 
    C.x2 = C.x - handleDistance * Math.sin(angle); 
    C.y2 = C.y + handleDistance * Math.cos(angle); 
    } 
} 
+0

Có lẽ bảng tra cứu có thể được xây dựng từ dữ liệu được xác định bằng thực nghiệm? – Harold

+0

@Harold Đúng hoặc một phép tính xấp xỉ tuyến tính từng phần đơn giản. Tuy nhiên, tôi vẫn đang tìm [câu trả lời đúng về mặt toán học] (http://math.stackexchange.com/questions/85003/equation-for-control-point-distance-for-fixed-length-cubic-bezier-path -với-spe). – Phrogz

+1

Một [mục tiêu cao quý] (http://ressalva.files.wordpress.com/2011/06/yak_crop2.png). Trong thời gian đó, một giải pháp gần đúng có lẽ sẽ có giá trị đối với tác giả của bản sao cắt dây vải canvas HTML5. ;) – Harold

Các vấn đề liên quan