2011-12-19 19 views
6

Tôi đang cố vẽ đồ thị bằng cách sử dụng Cubic Hermite Splines. Tôi lấy mã đơn giản để làm như vậy từ trang interpolation methods này.Splite khối Hermite hành xử lạ

Đây là mã của tôi:

private float HermiteInterpolate(float y0, float y1, float y2, float y3, float mu) 
{ 
    var mu2 = mu * mu; 

    var a0 = -0.5f * y0 + 1.5f * y1 - 1.5f * y2 + 0.5f * y3; 
    var a1 = y0 - 2.5f * y1 + 2f * y2 - 0.5f * y3; 
    var a2 = -0.5f * y0 + 0.5f * y2; 
    var a3 = y1; 

    return (a0 * mu * mu2) + (a1 * mu2) + (a2 * mu) + a3; 
} 

Với dữ liệu này (giá trị y, 0-1, x-giá trị được phân bố đều 0-21):

0, 0.09448819, 0.1102362, 0.1338583, 0.1811024, 0.2283465 ,0.3543307, 0.4645669, 0.480315, 0.480315, 0.527559, 0.527559, 0.527559, 0.527559, 0.527559, 0.527559, 0.6062992, 0.6377953, 0.6377953, 0.6377953, 0.7480315

Và đây là kết quả:

Hermite Graph

Vấn đề là, tại một số khu vực của biểu đồ, đường đi xuống dưới. Nhìn vào dữ liệu, nó không bao giờ giảm. Tôi không biết liệu thuật toán có được thực hiện hay không, nhưng đối với những gì tôi đang làm, tôi muốn các dòng không bao giờ đi xuống (và nếu tôi vẽ đồ thị bằng tay, tôi sẽ không bao giờ làm cho chúng hướng xuống dưới) .

Vì vậy,

  • Có điều gì sai với đồ họa?
  • Thuật toán có được thực hiện không? Nếu vậy, có một nơi mà điều này không xảy ra?
  • Tôi đã thử nội suy cosin, nhưng không thích cách nó được bật ra.

Dưới đây là các chức năng đồ họa thực tế:

public void DrawGraph(IList<float> items) 
{ 
    for (var x = 0; x < Width; x++) 
    { 
     var percentThrough = (float)x/(float)Width; 
     var itemIndexRaw = items.Count * percentThrough; 
     var itemIndex = (int)Math.Floor(itemIndexRaw); 

     var item = items[itemIndex]; 
     var previousItem = (itemIndex - 1) < 0 ? item : items[itemIndex - 1]; 
     var nextItem = (itemIndex + 1) >= items.Count ? item : items[itemIndex + 1]; 
     var nextNextItem = (itemIndex + 2) >= items.Count ? nextItem : items[itemIndex + 2]; 

     var itemMu = FractionalPart(itemIndexRaw); 

     var pointValue = HermiteInterpolate(previousItem, item, nextItem, nextNextItem, itemMu); 

     WritePixel(x, (int)(pointValue * Height) - 1, (1 - FractionalPart(pointValue)), false); 
     WritePixel(x, (int)(pointValue * Height), 1.0f, false); 
     WritePixel(x, (int)(pointValue * Height) + 1, FractionalPart(pointValue), false); 
    } 
} 
+0

Xin chào Snea, tôi đang cố gắng hiểu cách hoạt động của Cubic Hermite Spline. Bạn có thể cho tôi biết cách bạn gọi phương thức HermiteInterpolate của bạn không? – Doro

Trả lời

10

Hành vi này là bình thường.

Phương pháp nội suy áp đặt một số điều kiện liên tục để cung cấp cho sự xuất hiện của một đường cong trơn tru. Đối với nội suy Hermite, không có điều kiện rằng đường cong nội suy thông qua một chuỗi các giá trị gia tăng cũng phải tăng lên ở khắp mọi nơi, và vì vậy đôi khi bạn nhận được hiệu ứng bạn hiển thị ở đây.

Có một cái gì đó gọi là monotone cubic interpolation làm những gì bạn muốn: nếu các điểm dữ liệu đang tăng lên, đường cong nội suy cũng sẽ tăng ở mọi nơi.

+1

Tuyệt vời! Bây giờ tôi chỉ cần tìm ra để giải thích tất cả các bước như mã. – Snea