参考文献
B样条曲线
给定
n+m+1
个平面或空间顶点
Pi(i=0,1,…,n+m)
,称为
n
次参数曲线段:
Gi,n(t)=1n!∑j=0n−i(−1)jCjn+1(t+n−i−j)nt∈[0,1] , i=0,1,…,n
二次B样条曲线
取
n=2
,则有二次B样条曲线的基函数如下:
⎧⎩⎨⎪⎪⎪⎪G0,2(t)=12(t−1)2G1,2(t)=12(−2t2+2t+1)G2,2(t)=12t2
二次B样条曲线段 P0,2(t)=∑2i=0PiGi,2(t) 是一段抛物线。二次B样条曲线的矩阵表示为:
P0,2(t)=12[1tt2]⎡⎣⎢1−2112−2001⎤⎦⎥⎡⎣⎢P0P1P2⎤⎦⎥ t∈[0,1]
端点位置:
P0,2(0)=12(P0+P1)P0,2(1)=12(P1+P2)
代码实现
#include <stdio.h>
#include <opencv2\opencv.hpp>
#include <time.h>
using namespace cv;
void generatePointArray(int * x, int * y, int size, int minX, int maxX, int minY, int maxY)
{
srand((unsigned int) time(0));
int bandX = maxX - minX;
int bandY = maxY - minY;
int i;
for (i = 0; i < size; i++) {
x[i] = rand() % bandX + minX;
y[i] = rand() % bandY + minY;
}
}
void drawPointWithLine(Mat & board, int * x, int * y, int size)
{
if (size < 1)
return;
circle(board, Point(x[0], y[0]), 2, Scalar(255, 0, 0), 1, CV_AA);
int i;
for (i = 1; i < size; i++) {
line(board, Point(x[i-1], y[i-1]), Point(x[i], y[i]), Scalar(0, 255, 0), 1, CV_AA);
circle(board, Point(x[i], y[i]), 2, Scalar(255, 0, 0), 1, CV_AA);
}
}
void BSpline(Mat & board, int * x, int * y, int size)
{
if (size != 3)
return;
double t, delta = 1/100.0;
int px = 0, py = 0;
for (t = 0; t <= 1.0; t += delta) {
/*** core code ***/
double g0 = 0.5*(t - 1)*(t - 1);
double g1 = 0.5*(-2*t*t + 2*t + 1);
double g2 = 0.5*t*t;
int _x = (int) (x[0]*g0 + x[1]*g1 + x[2]*g2);
int _y = (int) (y[0]*g0 + y[1]*g1 + y[2]*g2);
/*****************/
if (t == 0)
circle(board, Point(_x, _y), 2, Scalar(0, 0, 255), 1, CV_AA);
else
line(board, Point(px, py), Point(_x, _y), Scalar(0, 128, 255), 1, CV_AA);
px = _x;
py = _y;
}
if (t != 1.0)
circle(board, Point((x[1] + x[2]) / 2, (y[1] + y[2]) / 2), 2, Scalar(0, 0, 255), 1, CV_AA);
}
int main(int argc, char* argv[])
{
int boardWidth = 400, boardHeight = 300;
Mat board = Mat(boardHeight, boardWidth, CV_8UC3);
memset(board.data, 255, boardHeight*boardWidth*3);
int x[5], y[5];
generatePointArray(x, y, 5, 0, boardWidth, 0, boardHeight);
drawPointWithLine(board, x, y, 5);
int i;
for (i = 0; i < 3; i++)
BSpline(board, x+i, y+i, 3);
imshow("B-Spline", board);
waitKey(0);
return 0;
}
结果1:
结果2: