多边形裁剪

#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;
vector<Point>a,b;

Mat src;
Mat dst;
Point pre_pt ,fir_pt;
Point cur_pt ;
double xmin,xmax,ymin,ymax,k;
int flag;

void check(int num){
    pre_pt=Point(-1,-1);
    
    if(num==4){//上侧
        for(auto i:a){
            if(pre_pt.x==-1){
                pre_pt=i;
            }
            else{
                cur_pt=i;
                if(pre_pt.y>=ymin&&cur_pt.y<ymin){
                    k=(double)(cur_pt.y-ymin)*(double)(cur_pt.x-pre_pt.x)/(double)(cur_pt.y-pre_pt.y);
                    b.push_back(Point(cur_pt.x-k,ymin));
                }
                if(pre_pt.y>=ymin&&cur_pt.y>=ymin){
                    b.push_back(cur_pt);
                }
                if(pre_pt.y<ymin&&cur_pt.y>=ymin){
                    k=(double)(cur_pt.y-ymin)*(double)(cur_pt.x-pre_pt.x)/(double)(cur_pt.y-pre_pt.y);
                    b.push_back(Point(cur_pt.x-k,ymin));
                    b.push_back(cur_pt);
                }
                pre_pt=i;
            }
        }
    }
    
    if(num==3){//右侧
        for(auto i:a){
            if(pre_pt.x==-1){
                pre_pt=i;
            }
            else{
                cur_pt=i;
                if(pre_pt.x<xmax&&cur_pt.x>=xmax){
                    k=(double)(cur_pt.x-xmax)*(double)(cur_pt.y-pre_pt.y)/(double)(cur_pt.x-pre_pt.x);
                    b.push_back(Point(xmax,cur_pt.y-k));
                }
                if(pre_pt.x<=xmax&&cur_pt.x<=xmax){
                    b.push_back(cur_pt);
                }
                if(pre_pt.x>=xmax&&cur_pt.x<xmax){
                    k=(double)(cur_pt.x-xmax)*(double)(cur_pt.y-pre_pt.y)/(double)(cur_pt.x-pre_pt.x);
                    b.push_back(Point(xmax,cur_pt.y-k));
                    b.push_back(cur_pt);
                }
                pre_pt=i;
            }
        }
    }
    
    if(num==2){//下侧
        for(auto i:a){
            if(pre_pt.x==-1){
                pre_pt=i;
            }
            else{
                cur_pt=i;
                if(pre_pt.y<ymax&&cur_pt.y>=ymax){
                    k=(double)(cur_pt.y-ymax)*(double)(cur_pt.x-pre_pt.x)/(double)(cur_pt.y-pre_pt.y);
                    b.push_back(Point(cur_pt.x-k,ymax));
                }
                if(pre_pt.y<=ymax&&cur_pt.y<=ymax){
                    b.push_back(cur_pt);
                }
                if(pre_pt.y>=ymax&&cur_pt.y<ymax){
                    k=(double)(cur_pt.y-ymax)*(double)(cur_pt.x-pre_pt.x)/(double)(cur_pt.y-pre_pt.y);
                    b.push_back(Point(cur_pt.x-k,ymax));
                    b.push_back(cur_pt);
                }
                pre_pt=i;
            }
        }
    }
    
    if(num==1){//左侧
        for(auto i:a){
            if(pre_pt.x==-1){
                pre_pt=i;
            }
            else{
                cur_pt=i;
                if(pre_pt.x<xmin&&cur_pt.x>=xmin){
                    k=(double)(cur_pt.x-xmin)*(double)(cur_pt.y-pre_pt.y)/(double)(cur_pt.x-pre_pt.x);
                    b.push_back(Point(xmin,cur_pt.y-k));
                    b.push_back(cur_pt);
                }
                if(pre_pt.x>=xmin&&cur_pt.x>=xmin){
                    b.push_back(cur_pt);
                }
                if(pre_pt.x>=xmin&&cur_pt.x<xmin){
                    k=(double)(cur_pt.x-xmin)*(double)(cur_pt.y-pre_pt.y)/(double)(cur_pt.x-pre_pt.x);
                    b.push_back(Point(xmin,cur_pt.y-k));
                }
                pre_pt=i;
            }
        }
    }
}

void Sutherland_Hodgman(){
    For(i,1,4){
        check(i);
        a.clear();
        for(auto j:b) a.push_back(j);
        a.push_back(b[0]);
        b.clear();
    }
    pre_pt=Point(-1,-1);
    //dst.copyTo(src);
    for(auto i:a){
        if(pre_pt.x==-1){
            pre_pt=i;
        }
        else{
            cur_pt=i;
            line(src, pre_pt, cur_pt, Scalar(255, 0, 0), 4, 8, 0);
            imshow("Sutherland-Hodgman", src);
            pre_pt=i;
        }
    }
}

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("Sutherland-Hodgman", 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("Sutherland-Hodgman", src);
        }
        if(cnt==n){
            a.push_back(fir_pt);
            line(src, cur_pt, fir_pt, Scalar(0, 255,0), 2, 4, 0);
            imshow("Sutherland-Hodgman", src);
            Sutherland_Hodgman();
            return;
        }
    }
}
 
int main(){
    cout<<"请输入多边形的顶点数"<<endl;
    cin>>n;
    if(n<3){
        cout<<"至少需要三个顶点哦😊"<<endl;
        return 0;
    }
    namedWindow("Sutherland-Hodgman", WINDOW_AUTOSIZE);
    src=Mat(1000, 1000, CV_8UC3, Scalar(0));
    xmax=ymax=600;
    xmin=ymin=200;
    rectangle(src,Rect(200,200,400,400),Scalar(255,255,255),2,1,0);
    src.copyTo(dst);
    setMouseCallback("Sutherland-Hodgman", on_mouse, 0);
    imshow("Sutherland-Hodgman", src);
    waitKey(0);
    return 0;
}

 

posted @ 2020-09-06 10:42  WeiAR  阅读(262)  评论(0编辑  收藏  举报