交互B样条
#include<opencv2/core/core.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/opencv.hpp> #include<bits/stdc++.h> #define For(i,a,b) for(int i=a;i<=b;++i) using namespace cv; using namespace std; int n,cnt,k;//k阶,k-1次 vector<Point2f>a,b; double t[11100]; Mat src; Mat dst; Point2f pre_pt ,fir_pt,temp; Point2f cur_pt ; double xmin,xmax,ymin,ymax,eps=1e-7; int flag; double N(int i,int k,double tt){ if(k==1){ if(tt-t[i]>eps && t[i+1]-tt>eps) return 1.0; return 0; } else{ return (tt-t[i])/ (fabs(t[i+k-1]-t[i])<eps?1.0:t[i+k-1]-t[i]) + (t[i+k]-tt)/ (fabs(t[i+k]-t[i+1])<eps?1.0:(t[i+k]-t[i+1])) * N(i+1,k-1,tt); } } // void B_spline(){ // n--;//0~(n+k) 起始点和终点的重复度都是k ,b样条定义域为[k-1,n+1] // For(i,k,n) t[i]=t[i-1]+1.0/(double)((n+1) - (k-1)); // For(i,n+1,n+k) t[i]=1.0; // For(j,k-1,n){ // for(double tt=t[j];t[j+1]-tt>eps;tt+=0.0001){ // temp.x=0; // temp.y=0; // for(int i=j;i>=j-k+1;i--){ // temp.x+=( (tt-t[i]) / (fabs(t[i+k-1]-t[i])<eps?1.0:t[i+k-1]-t[i]) * a[i].x + (t[i+k-1]-tt) / (fabs(t[i+k-1]-t[i])<eps?1.0:t[i+k-1]-t[i]) * a[i-1].x ) * N(i,k-1,tt); // temp.y+=((tt-t[i])/ (fabs(t[i+k-1]-t[i])<eps?1.0:t[i+k-1]-t[i]) * a[i].y+(t[i+k-1]-tt)/ (fabs(t[i+k-1]-t[i])<eps?1.0:t[i+k-1]-t[i]) * a[i-1].y) * N(i,k-1,tt); // } // circle(src, temp, 1, Scalar(255,255,255), FILLED, 0); // } // } // // imshow("B_spline", src); // } void B_spline(){ n--;//0~(n+k) 起始点和终点的重复度都是k ,b样条定义域为[k-1,n+1] For(i,k,n) t[i]=t[i-1]+1.0/(double)((n+1) - (k-1)); For(i,n+1,n+k) t[i]=1.0; For(j,k-1,n){ for(double tt=t[j];t[j+1]-tt>eps;tt+=0.0001){ b=a; For(r,1,k-1){ for(int i=j;i>=j-k+r+1;i--){ b[i]= (tt-t[i]) / (fabs(t[i+k-r]-t[i])<eps?1.0:t[i+k-r]-t[i]) * b[i] + (t[i+k-r]-tt) / (fabs(t[i+k-r]-t[i])<eps?1.0:t[i+k-r]-t[i]) * b[i-1]; } } circle(src, b[j], 1, Scalar(255,255,255), FILLED, 0); } } imshow("B_spline", src); } void on_mouse(int event, int x, int y, int flags, void* ustc){ if (event == EVENT_LBUTTONDOWN){ cnt++; a.push_back(Point(x,y)); if(cnt==1){ pre_pt=Point(x,y); fir_pt=pre_pt; circle(src, fir_pt, 4, Scalar(255,255,255), FILLED, 0); imshow("B_spline", src); } if(cnt>1&&cnt<=n){ cur_pt=Point(x,y); circle(src, cur_pt, 4, Scalar(255,255,255), FILLED, 0); line(src, pre_pt, cur_pt, Scalar(0, 255,0), 2, 4, 0); pre_pt=cur_pt; imshow("B_spline", src); } if(cnt==n){ B_spline(); return; } } } void add(int event, int x, int y, int flags, void* ustc){ if (event == EVENT_LBUTTONDOWN){ a.push_back(Point(x,y)); dst.copyTo(src); cnt=0; for(auto i:a){ if(++cnt==1){ circle(src, i, 4, Scalar(255,255,255), FILLED, 0); } else{ circle(src, i, 4, Scalar(255,255,255), FILLED, 0); line(src, pre_pt, i, Scalar(0, 255,0), 2, 4, 0); } pre_pt=i; } B_spline(); return ; } } void init(){ while(1){ cin>>flag; switch (flag){ case 1:{ //从0开始搭建B样条 cout<<"请输入控制顶点的个数"<<endl; cin>>n; while(n<3){ cout<<"个数不能小于3呀😁,请重新输入"<<endl; cin>>n; } cout<<"请输入阶数"<<endl; cin>>k; imshow("B_spline", src); cnt=0; setMouseCallback("B_spline", on_mouse, 0); int kikk=-1; while(kikk != 27){ kikk=waitKey(0); cout<<kikk<<endl; if(kikk==27){ break; } } // if(waitkey(0)=='q') break; break; } case 2:{ //删除最后一个点.. if(n==3){ cout<<"不能再删除啦,再删除都快没了..."<<endl; } else{ a.pop_back(); dst.copyTo(src); cnt=0; for(auto i:a){ if(++cnt==1){ circle(src, i, 4, Scalar(255,255,255), FILLED, 0); } else{ circle(src, i, 4, Scalar(255,255,255), FILLED, 0); line(src, pre_pt, i, Scalar(0, 255,0), 2, 4, 0); } pre_pt=i; } imshow("B_spline", src); B_spline(); } break; } case 3:{ //在最后添加一个点 imshow("B_spline", src); setMouseCallback("B_spline", add, 0); } } } } int main(){ namedWindow("B_spline", WINDOW_AUTOSIZE); src=Mat(1000, 1000, CV_8UC3, Scalar(0)); src.copyTo(dst); init(); //setMouseCallback("B_spline", on_mouse, 0); imshow("B_spline", src); waitKey(0); return 0; }