扫描线填充多边形
#include<opencv2/core/core.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/opencv.hpp> #include<bits/stdc++.h> #define N 1000010 #define For(i,a,b) for(int i=a;i<=b;++i) using namespace cv; using namespace std; int n,cnt,flag; int x[10],y[10]; vector<Point>a; Mat src; Mat dst; Point pre_pt ,fir_pt; Point cur_pt ; double ymin=1000000.0,ymax=-1.0,k,eps=1e-7; struct node{ double x; double dx; int ymax; node *next; }*NET[N],*AET; void push(double x,double dx,int ymax,int ymin){ node *p; p=new node(); p->x=x; p->dx=dx; p->ymax=ymax; if(NET[ymin]==0) NET[ymin]=p; else{ p->next=NET[ymin]->next; NET[ymin]->next=p; } } void polygon(){ AET=new node(); For(i,0,a.size()-1){ ymax=max(ymax,(double)a[i].y); ymin=min(ymin,(double)a[i].y); } For(i,0,a.size()-1){ For(j,-1,2){ x[j+1] = a[(i + j + a.size()) % a.size()].x; y[j+1] = a[(i + j + a.size()) % a.size()].y; } if(y[1] == y[2]) continue; if((y[2]>y[1] && y[1]>y[0]) || (y[1]>y[2] && y[2]>y[3])){ push((double)(y[1]>y[2]?x[2]:x[1])+(double)(x[1]-x[2])/(double)(y[1]-y[2]),(double)(x[1]-x[2])/(double)(y[1]-y[2]),max(y[1],y[2]),min(y[1],y[2])+1); } else push((double)(y[1]>y[2]?x[2]:x[1]),(double)(x[1]-x[2])/(double)(y[1]-y[2]),max(y[1],y[2]),min(y[1],y[2])); } For(i,ymin,ymax){ node *p; for(node *j=NET[i]; j; j=j->next){ p=AET; node *temp=new node(); while(p->next){ if(j->x > p->next->x ||(j->x == p->next->x && j->dx - p->next->dx > eps)){ p=p->next; continue; } break; } temp->x=j->x; temp->dx=j->dx; temp->ymax=j->ymax; temp->next=p->next; p->next=temp; } for(node *j=AET->next;j && j->next;j=j->next->next){ For(k,j->x,j->next->x){ circle(src, Point(k,i), 1.5, Scalar(0, 255, 0), FILLED, 0); } } p=AET; while(p->next){ if(p->next->ymax == i){ p->next=p->next->next; } else p = p->next; } p=AET; while(p->next){ p->next->x += p->next->dx; p = p->next; } } imshow("扫描线填充多边形", 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; imshow("扫描线填充多边形", src); } if(cnt>1&&cnt<=n){ cur_pt=Point(x,y); line(src, pre_pt, cur_pt, Scalar(0, 255,0), 2, 4, 0); pre_pt=cur_pt; imshow("扫描线填充多边形", src); } if(cnt==n){ a.push_back(fir_pt); line(src, cur_pt, fir_pt, Scalar(0, 255,0), 2, 4, 0); imshow("扫描线填充多边形", src); polygon(); return; } } } int main(){ cout<<"请输入多边形的顶点数"<<endl; cin>>n; if(n<3){ cout<<"至少需要三个顶点哦😊"<<endl; return 0; } namedWindow("扫描线填充多边形", WINDOW_AUTOSIZE); src=Mat(1000, 1000, CV_8UC3, Scalar(0)); src.copyTo(dst); setMouseCallback("扫描线填充多边形", on_mouse, 0); imshow("扫描线填充多边形", src); waitKey(0); return 0; }