Hermite曲线与Bezier曲线的关系
結論
最近在研究3次樣條曲線。曲線由四個控制點控制,依次記為P0,P1,P2,P3。在繪制Hermite曲線的時候,發現如果令P0處的導數為3倍P1-P0,P3處的導數為3倍P3-P2,則P0,P1,P2,P3構成的Hermite曲線與P0,P1,P2,P3構成的Bezier曲線完全相同。
下面詳細分析說明這一點
分析
通用的三次Hermite曲線的參數表達式為
P(u)=P0(2u3?3u2+1)+P3(?2u3+3u2)+P0′(u3?2u2+u)+P3′(u3?u2)P(u)=P_0(2u^3-3u^2+1)+P_3(-2u^3+3u^2)+P'_0(u^3-2u^2+u)+P'_3(u^3-u^2)P(u)=P0?(2u3?3u2+1)+P3?(?2u3+3u2)+P0′?(u3?2u2+u)+P3′?(u3?u2)
剛剛我們說明了,如果P0′=3(P1?P0)P'_0=3(P_1-P_0)P0′?=3(P1??P0?),P3′=3(P3?P2)P'_3=3(P_3-P_2)P3′?=3(P3??P2?),那么上式又可以化為
P(u)=(u3?3u2+1)P0+(?2u3+3u2)P3+3(P1?P0)(u3?2u2+u)+3(P3?P2)(u3?u2)P(u)=(u^3-3u^2+1)P_0+(-2u^3+3u^2)P_3+3(P_1-P_0)(u^3-2u^2+u)+3(P_3-P_2)(u^3-u^2)P(u)=(u3?3u2+1)P0?+(?2u3+3u2)P3?+3(P1??P0?)(u3?2u2+u)+3(P3??P2?)(u3?u2)
整理一下可以得到
P(u)=(1?3u+3u2?u3)P0+(3u?6u2+3u3)P1+(3u2?3u3)P2+u3P3P(u)=(1-3u+3u^2-u^3)P_0+ (3u-6u^2+3u^3)P_1+(3u^2-3u^3)P_2+u^3P_3P(u)=(1?3u+3u2?u3)P0?+(3u?6u2+3u3)P1?+(3u2?3u3)P2?+u3P3?
P(u)=(1?u)3P0+3u(1?u)2P1+3u2(1?u)P2+u3P3P(u)=(1-u)^3P_0+3u(1-u)^2P_1+3u^2(1-u)P_2+u^3P_3P(u)=(1?u)3P0?+3u(1?u)2P1?+3u2(1?u)P2?+u3P3?
這正是三次Bezier曲線的公式
Demo演示
下面用OpenCV分別畫Hermite曲線和Bezier曲線,兩條曲線完全重合。
Demo演示代碼
#include <opencv2/opencv.hpp> #include <iostream> #include <vector> #include <cmath>using namespace std; using namespace cv;string mainwindow = "構造線";Point2d control_points[4]; int control_points_index = 0;int height = 600; int width = 800;Mat screen_mat;const double CHOOSE_THRESHOLD = 20;bool choose_flag = false; int choose_point;const int LINE_N = 1000; // 線段的個數,點數為LINE_N+1void on_mouse_handler(int event, int x, int y, int flag, void* param) /* x, y 的原點在左上角 */ {double dist;if (event == EVENT_LBUTTONDOWN){if (control_points_index < 4){control_points[control_points_index].x = x;control_points[control_points_index].y = y;control_points_index++;}else{for (int i = 0; i < 4; i++){dist = (control_points[i].x - x) * (control_points[i].x - x) + (control_points[i].y - y) * (control_points[i].y - y);if (dist < CHOOSE_THRESHOLD * CHOOSE_THRESHOLD){//cout << "Choose " << i << endl;choose_flag = true;choose_point = i;return;}}}}else if (event == EVENT_LBUTTONUP){choose_flag = false;}else if (event == EVENT_MOUSEMOVE){if (choose_flag){control_points[choose_point].x = x;control_points[choose_point].y = y;}} }void imag_update() {screen_mat = Mat::zeros(height, width, CV_8UC4);for (int i = 0; i < control_points_index; i++){drawMarker(screen_mat, control_points[i], Scalar(0, 0, 255, 255), MARKER_STAR, 5);}if (control_points_index == 4){Point2d v0, v1, v2, v3;Point2d bv0, bv1, bv2, bv3;//Hermitev0 = control_points[0];v1 = control_points[3];v2 = control_points[1] - control_points[0];v3 = control_points[3] - control_points[2];v2 = 3 * v2;v3 = 3 * v3;//Bezierbv0 = control_points[0];bv1 = control_points[1];bv2 = control_points[2];bv3 = control_points[3];Point2d p0 = control_points[0];Point2d bp0 = control_points[0];Point2d p1;Point2d bp1;double u;double c0, c1, c2, c3;double bc0, bc1, bc2, bc3;for (int i = 1; i < LINE_N; i++){u = i * 1.0 / LINE_N; c0 = 2 * u * u * u - 3 * u * u + 1;c1 = -2 * u * u * u + 3 * u * u;c2 = u * u * u - 2 * u * u + u;c3 = u * u * u - u * u;//Bezierbc0 = (1 - u) * (1 - u) * (1 - u);bc1 = 3 * u * (1 - u) * (1 - u);bc2 = 3 * u * u * (1 - u);bc3 = u * u * u;p1.x = v0.x * c0 + v1.x * c1 + v2.x * c2 + v3.x * c3;p1.y = v0.y * c0 + v1.y * c1 + v2.y * c2 + v3.y * c3;bp1.x = bv0.x * bc0 + bv1.x * bc1 + bv2.x * bc2 + bv3.x * bc3;bp1.y = bv0.y * bc0 + bv1.y * bc1 + bv2.y * bc2 + bv3.y * bc3;line(screen_mat, p0, p1, Scalar(0, 0, 255, 128), 1, LINE_AA);line(screen_mat, bp0, bp1, Scalar(0, 255, 0, 128), 1, LINE_AA);p0 = p1;bp0 = bp1;}}imshow(mainwindow, screen_mat); }void window_initialize() {namedWindow(mainwindow, WINDOW_AUTOSIZE);setMouseCallback(mainwindow, on_mouse_handler); }void main_loop() {/* Endless loop until ESC key pressed*/bool finished = false;int pressed_key = 0;while (!finished){imag_update();pressed_key = waitKey(10);if (pressed_key == 27) finished = true;} }int main() {window_initialize();main_loop();return 0; }總結
以上是生活随笔為你收集整理的Hermite曲线与Bezier曲线的关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用matplotlib,同时在多个fi
- 下一篇: 万向锁的简单数学解释