2012-03-11 24 views
8

Hãy nói rằng tôi có số n điểm xác định một bề mặt trên trục zspline bề mặt suy

f(x1,y1) = 10 
f(x2,y2) = 12 
f(x3,y3) = 5 
f(x4,y4) = 2 
... 
f(xn,yn) = 21 

bây giờ tôi muốn để có thể gần đúng f (x, y). Tôi đang tìm kiếm một thuật toán cho một tuyến tính và đặc biệt là một xấp xỉ spline. Một thuật toán ví dụ hoặc ít nhất một số con trỏ sẽ là tuyệt vời.

+0

Bài viết [wikipedia] [1] hơi khó khăn nhưng hãy thử ít nhất để xem phần ví dụ. [1]: http://en.wikipedia.org/wiki/Spline_interpolation –

+1

Bạn có phải là điểm kiểm soát x, y trên lưới thông thường không? –

+0

Đối với các chức năng của mẫu f (x, y), thông thường là giả định về dạng dữ liệu cơ bản (đa thức độ K, tổng N Gaussians, vv) và sau đó xác định các hệ số bằng các bình phương nhỏ nhất. Điều đó có hoạt động ở đây không? Bạn có biết gì về dữ liệu đại diện không? Nếu bạn thực sự muốn có một spline, sau đó NURBS http://en.wikipedia.org/wiki/NURBS có giá trị một cái nhìn. Chúng có các thuộc tính tốt để dựng hình.Xây dựng một tam giác Delaunay của các điểm (x, y) để có được cơ sở, trừ khi chúng nằm trên lưới thường xuyên. Để phù hợp với mặt phẳng, bạn sẽ muốn một hình vuông nhỏ nhất phù hợp. – Gene

Trả lời

1

Bạn có thể sử dụng điểm của mình làm điểm kiểm soát của bề mặt Bezier (hoặc Bspline), đặc biệt nếu (xi, yi) lấy mẫu hình chữ nhật trên mặt phẳng XY. Về mặt này, không có sự liên quan nào.

Bề mặt bạn sẽ nhận được sẽ nằm trong thân lồi của các điểm của bạn và sẽ giao nhau (nội suy) các điểm tại ranh giới {xi, yi}.

Nếu bạn muốn thử nghiệm, This forums posting dường như chứa mã đơn giản trong Matlab, và bạn có thể sử dụng GuIRIT làm như vậy nếu bạn không có Matlab (mặc dù nó đòi hỏi tìm ra các định dạng file của chương trình) .

+0

Việc thực hiện cuối cùng sẽ phải được trong ruby ​​- vì vậy Matlab không thực sự là một lựa chọn. Nhưng vấn đề thực sự là về một hình chữ nhật trong mặt phẳng XY. – tcurdt

+0

Tôi chưa bao giờ sử dụng Ruby, nhưng tôi chắc chắn có một gói Bezier/Bspline cho nó. – user1071136

4

Đây là một mô tả mơ hồ về cách tiếp cận để thực hiện phép tính xấp xỉ tuyến tính.

  1. Xác định Voronoi diagram điểm của bạn (ví tất cả các điểm trong mặt phẳng, tìm ra khu vực gần (x_i,y_i))
  2. Lấy kép này để có được những Delaunay triangulation: kết nối (x_i,y_i)(x_j,y_j) nếu có một đoạn thẳng của điểm sao cho (x_i,y_i)(x_j,y_j) bằng nhau (và gần hơn bất kỳ cặp nào khác).
  3. Trên mỗi hình tam giác, tìm mặt phẳng qua ba đỉnh. Đây là nội suy tuyến tính mà bạn cần.

Sau đây thực hiện hai bước đầu tiên bằng Python. Độ đều đặn của lưới của bạn có thể cho phép bạn tăng tốc độ mọi thứ (điều này cũng có thể làm hỏng hình tam giác).

import itertools 

""" Based on http://stackoverflow.com/a/1165943/2336725 """ 
def is_ccw(tri): 
    return ((tri[1][0]-tri[0][0])*(tri[1][1]+tri[0][1]) 
      + (tri[2][0]-tri[1][0])*(tri[2][1]+tri[1][1]) 
      + (tri[0][0]-tri[2][0])*(tri[0][1]+tri[2][1])) < 0 

def circumcircle_contains_point(triangle,point): 
    import numpy as np 
    matrix = np.array([ [p[0],p[1],p[0]**2+p[1]**2,1] for p in triangle+point ]) 
    return is_ccw(triangle) == (np.linalg.det(matrix) > 0) 

triangulation = set() 
""" 
A triangle is in the Delaunay triangulation if and only if its circumscribing 
circle contains no other point. This implementation is O(n^4). Faster methods 
are at http://en.wikipedia.org/wiki/Delaunay_triangulation 
""" 
for triangle in itertools.combinations(points,3): 
    triangle_empty = True 
    for point in points: 
     if point in triangle: 
      next 
     if circumcircle_contains_point(triangle,point): 
      triangle_empty = False 
      break 
    if triangle_empty: 
     triangulation.add(triangle) 
2

Nội suy trên dữ liệu 2D không đều không dễ dàng như vậy. Tôi biết không có sự tổng quát về spline đúng với 2D bất thường.

Bên cạnh các phương pháp dựa trên tam giác, bạn có thể xem Barnes (http://en.wikipedia.org/wiki/Barnes_interpolation) và Trọng số khoảng cách nghịch đảo (http://en.wikipedia.org/wiki/Inverse_distance_weighting), hoặc nói chung, RBF (http://en.wikipedia.org/wiki/Radial_basis_functions).

Nếu điểm của bạn được lan truyền không đồng nhất mạnh mẽ (cụm dày đặc), có thể cần thiết để làm cho kích thước của các chức năng thích ứng hoặc khu nghỉ mát gần đúng hơn là nội suy.

+0

Thực tế chúng không lây lan rất nhiều. Trường hợp xấu nhất tôi có lẽ thậm chí có thể sống với một nội suy tuyến tính nhưng sẽ thích một bề mặt mượt mà hơn. – tcurdt

+0

Âm thanh xấp xỉ giống như một góc thú vị. – tcurdt

+0

+1 cho các chức năng cơ sở hướng tâm. Tôi đã viết một bài báo một vài năm trở lại làm việc với các đối tượng này tổng quát hóa chức năng trên đa tạp. Chúng hoạt động rất tốt miễn là bạn không có các cụm dày đặc và số điểm n không quá lớn. (Nếu n không nhận được lớn, bạn muốn RBF của bạn để có hỗ trợ nhỏ gọn để ma trận liên quan là thưa thớt. Nhưng sau đó bạn cần phải sử dụng đại số tuyến tính thưa thớt để giữ cho nó mở rộng chấp nhận được.) Nice, nội suy mịn. –