精华内容
下载资源
问答
  • 多边形是由若干线段围成的封闭图形,使用长方形裁剪多边形得到的结果应该仍然是一个多边形,一个封闭的图形 之前我们学习了Liang-Barsky直线裁剪算法,但是如果仅重复的利用直线段的裁剪方法进行裁剪,很可能无法...

    多边形是由若干线段围成的封闭图形,使用长方形裁剪多边形得到的结果应该仍然是一个多边形,一个封闭的图形

    之前我们学习了Liang-Barsky直线裁剪算法,但是如果仅重复的利用直线段的裁剪方法进行裁剪,很可能无法得到期望的图形结果,无法得到一个封闭的多边形

    采用逐边裁剪算法:
    依次使用窗口的四条边框直线对多边形进行分布裁剪,先用一条边框直线对整个多边形进行裁剪,得到一个或者若干个新的多边形,再用第二条边框直线对新产生的多边形进行裁剪…依次类推知道四条边框直线都裁剪完,整个多边形的裁剪过程结束

    步骤:

    • 把待裁剪多边形的各个顶点按照一定的方向有次序的组成有序的顶点序列(p1,p2,pn),相继连接相邻两个顶点(p1p2,p2p3,p3p4,pnp1)即为组成多边形的n条边。该顶点序列就是待处理的输入量
    • 对输入的顶点序列进行处理,结果是产生一组新的顶点序列,然后输出该组新的顶点序列,该新的顶点序列表示了由M条边组成的新的多边形
    • 把输入的顶点序列作为新的输入量,再次输入进行处理,这样处理三次

    如何处理:

    • 对于给定的顶点序列,依次检验顶点序列中每个顶点pi (i=1,2,n) ,处于裁剪边框可见侧的顶点被放入新的顶点序列中,处于裁剪边框不可见侧的顶点被删除
    • 还要检测pi和他的前一个顶点pi-1点是否处于裁剪边框的同侧(认为p1的前一个顶点是pn),如果不再同一侧的话,要求出裁剪边框与直线段pipi-1的交点并把该交点作为新的顶点列入到新顶点序列中输出
    • 我们设多边形的任意一条边起点为s,终点为e。给定的矩形有可见侧和不可见侧
      在这里插入图片描述
    • 则线段SE和裁剪线有四种位置关系:
      端点SE都在不可见侧,则没有输出;SE都在可见侧,输出端点E;端点S在可见侧,端点E在不可见侧,则输出线段SE与裁剪线的交点C;端点S在不可见侧,端点E在可见侧,则输出线段SE与裁剪线的交点C和端点E
    #include<GL/glut.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<time.h>
    using namespace std;
    const int window_width = 800, window_height = 600;
    char op;
    struct point
    {
     float x, y;
     point() {}
     point(float tempx, float tempy)
      :x(tempx), y(tempy) {}
     bool operator < (const point& a)const
     {
      return x < a.x;
     }
    };
    struct EDGE
    {
     float bx, by, ex, ey;
     EDGE() {}
     EDGE(float bxx, float byy, float exx, float eyy)
      :bx(bxx), by(byy), ex(exx), ey(eyy) {}
    };
    map<float, map<float, int> > vis;
    vector<point> input_vertice;
    vector<point> output_vertice;
    float intersect_point_color[3] = { 1,0,0 };
    float polygon_point_color[3] = { 0,0,1 };
    EDGE left(200, 500, 200, 200);
    EDGE bottom(200, 200, 500, 200);
    EDGE right(500, 200, 500, 500);
    EDGE top(500, 500, 200, 500);
    void draw_rec()
    {
     glColor3f(1.0, 1.0, 0.0);
     glLineWidth(2.0f);
     glBegin(GL_LINES);
     glVertex2f(::left.bx, ::left.by); glVertex2f(::left.ex, ::left.ey);
     glVertex2f(bottom.bx, bottom.by); glVertex2f(bottom.ex, bottom.ey);
     glVertex2f(::right.bx, ::right.by); glVertex2f(::right.ex, ::right.ey);
     glVertex2f(top.bx, top.by); glVertex2f(top.ex, top.ey);
     glEnd();
     glFlush();
    }
    bool inside(point& pt, EDGE ClipBoundary)//判断点是否可见
    {
     if (ClipBoundary.ex > ClipBoundary.bx)
     {
      if (pt.y >= ClipBoundary.by)//裁剪边为窗口下边沿
       return true;
     }
     else if (ClipBoundary.ex < ClipBoundary.bx)
     {
      if (pt.y <= ClipBoundary.by)//裁剪边为窗口上边沿
       return true;
     }
     else if (ClipBoundary.ey > ClipBoundary.by)//裁剪边为窗口右边沿
     {
      if (pt.x <= ClipBoundary.bx)
       return true;
     }
     else if (ClipBoundary.ey < ClipBoundary.by)//裁剪边为窗口左边沿
     {
      if (pt.x >= ClipBoundary.bx)
       return true;
     }
     return false;
    }
    void intersect(point& s, point& p, EDGE ClipBoundary, point& intersect_pt)//直线段SP和边界求交,返回交点
    {
     if (ClipBoundary.by == ClipBoundary.ey)//水平裁剪边界
     {
      intersect_pt.y = ClipBoundary.by;
      //x=起点的横坐标+dy/sp斜率
      intersect_pt.x = s.x + (ClipBoundary.by - s.y) * (p.x - s.x) / (p.y - s.y);
     }
     else//垂直裁剪边界
     {
      intersect_pt.x = ClipBoundary.bx;
      intersect_pt.y = s.y + (ClipBoundary.bx - s.x) * (p.y - s.y) / (p.x - s.x);
     }
    }
    void draw_a_point(float x, float y, float color[])
    {
     glPointSize(5.0f);
     glBegin(GL_POINTS);
     glColor3fv(color);
     glVertex2f(x, y);
     glEnd();
     glFlush();
    }
    void SutherlandHodgmanClip(EDGE ClipBoundary)
    {
     point s, p, ip;
     output_vertice.clear();
     s = input_vertice[input_vertice.size() - 1];//首尾
     for (int j = 0; j < input_vertice.size(); j++)
     {
      p = input_vertice[j];
      cout << "s" << s.x << "  " << s.y << endl;
      cout << "p" << p.x << "  " << p.y << endl;
      if (inside(p, ClipBoundary))//p在内
      {
       if (inside(s, ClipBoundary))//sp都在窗口内
       {
        //output(p);
        output_vertice.push_back(p);
       }
       else//p在里面 s不在
       {
        intersect(s, p, ClipBoundary, ip);
        output_vertice.push_back(ip);
        output_vertice.push_back(p);
       }
      }
      else//s在外面
      {
       if (inside(s, ClipBoundary))//s在窗口内p在窗口外
       {
        intersect(s, p, ClipBoundary, ip);
        //output(ip);
        output_vertice.push_back(ip);
       }
       //sp都在外面则无输出
      }
      s = p;
     }
     input_vertice = output_vertice;//这次的输出作为下一次的输入,input_vertice和output_vertice是全局变量
    }
    void draw_line_point(float x, float y)
    {
     vis[x][y]++;
     glPointSize(2.5f);
     glBegin(GL_POINTS);
     if (vis[x][y] % 2 == 0)//访问偶数次,涂白色
     {
      glColor3f(1, 1, 1);
      glVertex2f(x, y);
     }
     else
     {
      glColor3f(1, 0, 0);//奇数次,涂红色
      glVertex2f(x, y);
     }
     glEnd();
     glFlush();
    }
    void display() {
     glClear(GL_COLOR_BUFFER_BIT);  
     glColor3f(1.0f, 0.0f, 0.0f);
     glFlush(); 
    }
    void mymouse(int button, int state, int x, int y)
    {
     glClearColor(1, 1, 1, 1);
     //bool flag = 0;
     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
     {
      if (op == 32)
      {
       glClear(GL_COLOR_BUFFER_BIT);
       draw_rec();
       input_vertice.clear();
       op = 'a';
      }
      draw_a_point(x, window_height - y, polygon_point_color);
      point p(x, window_height - y);
      input_vertice.push_back(p);
      cout << "多边形顶点" << input_vertice.size() << ":(" << x << ", " << window_height - y << ")" << endl;
     }
     if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
     {
      glLineWidth(2.0f);
      glBegin(GL_LINES);
      glColor3fv(polygon_point_color);
      for (int i = 0; i < input_vertice.size(); i++)
      {
       if (i == input_vertice.size() - 1)
       {
        glVertex2f(input_vertice[0].x, input_vertice[0].y);
        glVertex2f(input_vertice[i].x, input_vertice[i].y);
       }
       else
       {
        glVertex2f(input_vertice[i].x, input_vertice[i].y);
        glVertex2f(input_vertice[i + 1].x, input_vertice[i + 1].y);
       }
      }
      glEnd();
      glFlush();
     }
    }
    void keyboard(unsigned char key, int x, int y)
    {
     if (key == 32)
     {
      op = 32;
      SutherlandHodgmanClip(::left);
      SutherlandHodgmanClip(bottom);
      SutherlandHodgmanClip(::right);
      SutherlandHodgmanClip(top);
      glLineWidth(4.0f);
      glBegin(GL_LINES);
      glColor3fv(intersect_point_color);
      for (int i = 0; i < output_vertice.size(); i++)
      {
       if (i == output_vertice.size() - 1)
       {
        glVertex2f(output_vertice[0].x, output_vertice[0].y);
        glVertex2f(output_vertice[i].x, output_vertice[i].y);
       }
       else
       {
        glVertex2f(output_vertice[i].x, output_vertice[i].y);
        glVertex2f(output_vertice[i + 1].x, output_vertice[i + 1].y);
       }
      }
      glEnd();
      glFlush();
     }
    }
    int main(int argc, char* argv[])
    {
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RED);
     glutInitWindowPosition(50, 50);
     glutInitWindowSize(window_width, window_height);
     glutCreateWindow("固定矩形窗口裁剪交互式多边形");
     cout << "左键画点\n右键连接成窗口\n按空格裁剪\n" << endl;
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluOrtho2D(0, window_width, 0, window_height);
     glClearColor(1, 1, 1, 1);
     glClear(GL_COLOR_BUFFER_BIT);
     draw_rec();
     glutMouseFunc(mymouse);
     glutKeyboardFunc(keyboard);
     glutDisplayFunc(&display);
     glutMainLoop();
     return 0;
    }
    展开全文
  • 文章目录裁剪不包含凹多边形的代码裁剪包含凹多边形的代码 裁剪不包含凹多边形的代码 #include<gl/glut.h> #include<iostream> #include<algorithm> #include<vector> #include<map> ...

    其他计算机图形学实验见 链接

    裁剪不包含凹多边形的代码

    #include<gl/glut.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<time.h>
    using namespace std;
    const int window_width = 800, window_height = 600;
    struct point
    {
    	float x, y;
    	point() {}
    	point(float xx, float yy)
    		:x(xx), y(yy) {}
    
    	bool operator < (const point& a)const
    	{
    		return x < a.x;
    	}
    };
    struct EDGE//Edge
    {
    	float bx, by, ex, ey;
    	EDGE() {}
    	EDGE(float bxx, float byy, float exx, float eyy)
    		:bx(bxx), by(byy), ex(exx), ey(eyy) {}
    };
    map<point, int> vis;
    vector<point> input_vertice;
    vector<point> output_vertice;
    float intersect_point_color[3] = { 1,0,0 };
    float polygon_point_color[3] = { 0,0,1 };
    EDGE left(200, 450, 200, 200);
    EDGE bottom(200, 200, 600, 200);
    EDGE right(600, 200, 600, 450);
    EDGE top(600, 450, 200, 450);
    
    void draw_a_point(float x, float y, float color[]);
    bool inside(point& pt, EDGE ClipBoundary);//判断点是否可见
    void intersect(point& s, point& p, EDGE ClipBoundary, point& intersect_pt);//直线段SP和边界求交,返回交点
    void SutherlandHodgmanClip(EDGE ClipBoundary, int in_len, int& out_len);
    //void output(point pt)
    //{
    //	//draw_a_point(pt.x, pt.y, intersect_point_color);
    //	output_vertice.push_back(pt);
    //	//cout << "output_vertice" << output_vertice.size() << ": (" << pt.x << ", " << pt.y << ")" << endl;
    //}
    void mymouse(int button, int state, int x, int y);
    void keyboard(unsigned char key, int x, int y);
    
    int main(int argc, char* argv[])
    {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RED);
    	glutInitWindowPosition(50, 50);
    	glutInitWindowSize(window_width, window_height);
    	glutCreateWindow("固定矩形窗口裁剪交互式多边形");
    	cout << "左键画点\n右键连接成窗口\n按空格裁剪\n" << endl;
    
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(0, window_width, 0, window_height);
    
    	glClearColor(1, 1, 1, 1);
    	glClear(GL_COLOR_BUFFER_BIT);
    
    	//画出边界
    	glColor3f(0, 1, 0);
    	glLineWidth(2.0f);
    	glBegin(GL_LINES);
    	glVertex2f(::left.bx, ::left.by); glVertex2f(::left.ex, ::left.ey);
    	glVertex2f(bottom.bx, bottom.by); glVertex2f(bottom.ex, bottom.ey);
    	glVertex2f(::right.bx, ::right.by); glVertex2f(::right.ex, ::right.ey);
    	glVertex2f(top.bx, top.by); glVertex2f(top.ex, top.ey);
    	glEnd();
    	glFlush();
    
    	glutMouseFunc(&mymouse);
    	glutKeyboardFunc(&keyboard);
    
    	glutMainLoop();
    	return 0;
    }
    
    bool inside(point& pt, EDGE ClipBoundary)//判断点是否可见
    {
    	if (ClipBoundary.ex > ClipBoundary.bx)
    	{
    		if (pt.y >= ClipBoundary.by)//裁剪边为窗口下边沿
    			return true;
    	}
    	else if (ClipBoundary.ex < ClipBoundary.bx)
    	{
    		if (pt.y <= ClipBoundary.by)//裁剪边为窗口上边沿
    			return true;
    	}
    	else if (ClipBoundary.ey > ClipBoundary.by)//裁剪边为窗口右边沿
    	{
    		if (pt.x <= ClipBoundary.bx)
    			return true;
    	}
    	else if (ClipBoundary.ey < ClipBoundary.by)//裁剪边为窗口左边沿
    	{
    		if (pt.x >= ClipBoundary.bx)
    			return true;
    	}
    	return false;
    }
    
    void intersect(point& s, point& p, EDGE ClipBoundary, point& intersect_pt)//直线段SP和边界求交,返回交点
    {
    	if (ClipBoundary.by == ClipBoundary.ey)//水平裁剪边界
    	{
    		intersect_pt.y = ClipBoundary.by;
    		//x=起点的横坐标+dy/sp斜率
    		intersect_pt.x = s.x + (ClipBoundary.by - s.y) * (p.x - s.x) / (p.y - s.y);
    	}
    	else//垂直裁剪边界
    	{
    		intersect_pt.x = ClipBoundary.bx;
    		intersect_pt.y = s.y + (ClipBoundary.bx - s.x) * (p.y - s.y) / (p.x - s.x);
    	}
    }
    
    void SutherlandHodgmanClip(EDGE ClipBoundary)
    {
    	point s, p, ip;
    	output_vertice.clear();
    	s = input_vertice[input_vertice.size() - 1];//首尾
    
    	for (int j = 0; j < input_vertice.size(); j++)
    	{
    		p = input_vertice[j];
    		if (inside(p, ClipBoundary))//p在内
    		{
    			if (inside(s, ClipBoundary))//sp都在窗口内
    			{
    				//output(p);
    				output_vertice.push_back(p);
    
    				//map<point, int>::iterator it = vis.find(p);
    				//if (it == vis.end())//没找到
    				//	vis[p] = 1;
    				//else
    				//	vis[p]++;
    			}
    			else//p在里面 s不在
    			{
    				intersect(s, p, ClipBoundary, ip);
    				//output(ip);
    				//output(p); 
    				output_vertice.push_back(ip);
    				output_vertice.push_back(p);
    
    				//map<point, int>::iterator it = vis.find(p);
    				//if (it == vis.end())//没找到
    				//	vis[p] = 1;
    				//else
    				//	vis[p]++;
    
    				//it = vis.find(ip);
    				//if (it == vis.end())//没找到
    				//	vis[ip] = 1;
    				//else
    				//	vis[ip]++;
    			}
    		}
    		else//s在外面
    		{
    			if (inside(s, ClipBoundary))//s在窗口内p在窗口外
    			{
    				intersect(s, p, ClipBoundary, ip);
    
    				//output(ip);
    				output_vertice.push_back(ip);
    				//map<point, int>::iterator it = vis.find(ip);
    				//if (it == vis.end())//没找到
    				//	vis[ip] = 1;
    				//else
    				//	vis[ip]++;
    			}
    			//sp都在外面则无输出
    		}
    		s = p;
    	}
    	input_vertice = output_vertice;//这次的输出作为下一次的输入,input_vertice和output_vertice是全局变量
    }
    
    void draw_a_point(float x, float y, float color[])
    {
    	glPointSize(5.0f);
    	glBegin(GL_POINTS);
    	glColor3fv(color);
    	glVertex2f(x, y);
    	glEnd();
    	glFlush();
    }
    
    void mymouse(int button, int state, int x, int y)
    {
    	glClearColor(1, 1, 1, 1);
    	//bool flag = 0;
    
    	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    	{
    		draw_a_point(x, window_height - y, polygon_point_color);
    		point p(x, window_height - y);
    		input_vertice.push_back(p);
    		cout << "多边形顶点" << input_vertice.size() << ":(" << x << ", " << window_height - y << ")" << endl;
    	}
    
    	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    	{
    			glLineWidth(2.0f);
    			glBegin(GL_LINES);
    			glColor3fv(polygon_point_color);
    			for (int i = 0; i < input_vertice.size(); i++)
    			{
    				if (i == input_vertice.size() - 1)
    				{
    					glVertex2f(input_vertice[0].x, input_vertice[0].y);
    					glVertex2f(input_vertice[i].x, input_vertice[i].y);
    				}
    				else
    				{
    					glVertex2f(input_vertice[i].x, input_vertice[i].y);
    					glVertex2f(input_vertice[i + 1].x, input_vertice[i + 1].y);
    				}
    			}
    			glEnd();
    			glFlush();
    	}
    }
    
    void keyboard(unsigned char key, int x, int y)
    {
    	if (key == 32)
    	{
    		SutherlandHodgmanClip(::left);
    		SutherlandHodgmanClip(bottom);
    		SutherlandHodgmanClip(::right);
    		SutherlandHodgmanClip(top);
    
    		glLineWidth(4.0f);
    		glBegin(GL_LINE_LOOP);
    		glColor3fv(intersect_point_color);
    		for (int i = 0; i < output_vertice.size(); i++)
    		{//draw_a_point(output_vertice[i].x, output_vertice[i].y, intersect_point_color);
    			glVertex2f(output_vertice[i].x, output_vertice[i].y);
    		}
    		glEnd();
    		glFlush();
    
    	}
    }
    
    

    裁剪包含凹多边形的代码

    #include<gl/glut.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<time.h>
    using namespace std;
    const int window_width = 800, window_height = 600;
    struct point
    {
    	float x, y;
    	point() {}
    	point(float xx, float yy)
    		:x(xx), y(yy) {}
    
    	bool operator < (const point& a)const
    	{
    		return x < a.x;
    	}
    };
    struct EDGE//Edge
    {
    	float bx, by, ex, ey;
    	EDGE() {}
    	EDGE(float bxx, float byy, float exx, float eyy)
    		:bx(bxx), by(byy), ex(exx), ey(eyy) {}
    };
    map<float, map<float, int> > vis;
    vector<point> input_vertice;
    vector<point> output_vertice;
    float intersect_point_color[3] = { 1,0,0 };
    float polygon_point_color[3] = { 0,0,1 };
    EDGE left(200, 450, 200, 200);
    EDGE bottom(200, 200, 600, 200);
    EDGE right(600, 200, 600, 450);
    EDGE top(600, 450, 200, 450);
    
    void draw_a_point(float x, float y, float color[]);
    bool inside(point& pt, EDGE ClipBoundary);//判断点是否可见
    void intersect(point& s, point& p, EDGE ClipBoundary, point& intersect_pt);//直线段SP和边界求交,返回交点
    void SutherlandHodgmanClip(EDGE ClipBoundary, int in_len, int& out_len);
    void mymouse(int button, int state, int x, int y);
    void keyboard(unsigned char key, int x, int y);
    void draw_line_point(float x, float y);
    void bresenham1(GLint x1, GLint y1, GLint x2, GLint y2);
    
    int main(int argc, char* argv[])
    {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RED);
    	glutInitWindowPosition(50, 50);
    	glutInitWindowSize(window_width, window_height);
    	glutCreateWindow("固定矩形窗口裁剪交互式多边形");
    	cout << "左键画点\n右键连接成窗口\n按空格裁剪\n" << endl;
    
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(0, window_width, 0, window_height);
    
    	glClearColor(1, 1, 1, 1);
    	glClear(GL_COLOR_BUFFER_BIT);
    
    	//画出边界
    	glColor3f(0, 1, 0);
    	glLineWidth(2.0f);
    	glBegin(GL_LINES);
    	glVertex2f(::left.bx, ::left.by); glVertex2f(::left.ex, ::left.ey);
    	glVertex2f(bottom.bx, bottom.by); glVertex2f(bottom.ex, bottom.ey);
    	glVertex2f(::right.bx, ::right.by); glVertex2f(::right.ex, ::right.ey);
    	glVertex2f(top.bx, top.by); glVertex2f(top.ex, top.ey);
    	glEnd();
    	glFlush();
    
    	glutMouseFunc(&mymouse);
    	glutKeyboardFunc(&keyboard);
    
    	glutMainLoop();
    	return 0;
    }
    
    bool inside(point& pt, EDGE ClipBoundary)//判断点是否可见
    {
    	if (ClipBoundary.ex > ClipBoundary.bx)
    	{
    		if (pt.y >= ClipBoundary.by)//裁剪边为窗口下边沿
    			return true;
    	}
    	else if (ClipBoundary.ex < ClipBoundary.bx)
    	{
    		if (pt.y <= ClipBoundary.by)//裁剪边为窗口上边沿
    			return true;
    	}
    	else if (ClipBoundary.ey > ClipBoundary.by)//裁剪边为窗口右边沿
    	{
    		if (pt.x <= ClipBoundary.bx)
    			return true;
    	}
    	else if (ClipBoundary.ey < ClipBoundary.by)//裁剪边为窗口左边沿
    	{
    		if (pt.x >= ClipBoundary.bx)
    			return true;
    	}
    	return false;
    }
    
    void intersect(point& s, point& p, EDGE ClipBoundary, point& intersect_pt)//直线段SP和边界求交,返回交点
    {
    	if (ClipBoundary.by == ClipBoundary.ey)//水平裁剪边界
    	{
    		intersect_pt.y = ClipBoundary.by;
    		//x=起点的横坐标+dy/sp斜率
    		intersect_pt.x = s.x + (ClipBoundary.by - s.y) * (p.x - s.x) / (p.y - s.y);
    	}
    	else//垂直裁剪边界
    	{
    		intersect_pt.x = ClipBoundary.bx;
    		intersect_pt.y = s.y + (ClipBoundary.bx - s.x) * (p.y - s.y) / (p.x - s.x);
    	}
    }
    
    void bresenham1(GLint x1, GLint y1, GLint x2, GLint y2)
    {
    	//glClear(GL_COLOR_BUFFER_BIT);
    
    	draw_line_point(x1, y1);
    
    	int dx = abs(x1 - x2);
    	int dy = abs(y1 - y2);
    	int flag = 0;//表示当前斜率k的绝对值是否大于1
    	if (dx == 0 && dy == 0)
    		return;
    
    	if (dy > dx)//斜率绝对值大于1
    	{
    		flag = 1;
    		//横纵坐标轴互换,将x视作y,将y视作x,所有坐标都需要互换
    		swap(x1, y1);
    		swap(x2, y2);
    		swap(dx, dy);
    	}
    
    	//确定步长tx,ty,斜率为正或为负,且只考虑左/右上or左/右下,左/右边的情况不加步长即可
    	int tx = x2 > x1 ? 1 : -1;
    	int ty = y2 > y1 ? 1 : -1;
    
    	//确定下一个点的坐标x,y
    	int x = x1 + 1;
    	int y = y1;
    
    	//dt和ds由迭代公式推出。dt是右上的点,ds是右边的点
    	int dt = 2 * (dy - dx);
    	int ds = 2 * dy;
    
    	//判别式的值d=2k*dx-dx = 2*dy-dx
    	int d = 2 * dy - dx;
    
    	while (x != x2)
    	{
    		if (d >= 0)//选T点(右上的点
    		{
    			//d(i+1) = d(i) + 2(dy - dx)
    			d += dt;
    			y += ty;
    		}
    		else//选S点,y方向不加步长
    		{
    			//d(i+1) = d(i) + 2*dy
    			d += ds;
    		}
    
    		if (flag)//斜率大于1
    		{
    			draw_line_point(y, x);
    		}
    		else
    		{
    			draw_line_point(x, y);
    		}
    		x += tx;//x增加步长
    	}
    }
    
    void SutherlandHodgmanClip(EDGE ClipBoundary)
    {
    	point s, p, ip;
    	output_vertice.clear();
    	s = input_vertice[input_vertice.size() - 1];//首尾
    
    	for (int j = 0; j < input_vertice.size(); j++)
    	{
    		p = input_vertice[j];
    		if (inside(p, ClipBoundary))//p在内
    		{
    			if (inside(s, ClipBoundary))//sp都在窗口内
    			{
    				//output(p);
    				output_vertice.push_back(p);
    			}
    			else//p在里面 s不在
    			{
    				intersect(s, p, ClipBoundary, ip);
    				//output(ip);
    				//output(p); 
    				output_vertice.push_back(ip);
    				output_vertice.push_back(p);
    
    			}
    		}
    		else//s在外面
    		{
    			if (inside(s, ClipBoundary))//s在窗口内p在窗口外
    			{
    				intersect(s, p, ClipBoundary, ip);
    
    				//output(ip);
    				output_vertice.push_back(ip);
    			}
    			//sp都在外面则无输出
    		}
    		s = p;
    	}
    	input_vertice = output_vertice;//这次的输出作为下一次的输入,input_vertice和output_vertice是全局变量
    }
    
    void draw_a_point(float x, float y, float color[])
    {
    	glPointSize(5.0f);
    	glBegin(GL_POINTS);
    	glColor3fv(color);
    	glVertex2f(x, y);
    	glEnd();
    	glFlush();
    }
    
    void draw_line_point(float x, float y)
    {
    	vis[x][y]++;
    	glPointSize(2.5f);
    	glBegin(GL_POINTS);
    	if (vis[x][y] % 2 == 0)//访问偶数次,涂白色
    	{
    		glColor3f(1, 1, 1);
    		glVertex2f(x, y);
    	}
    	else
    	{
    		glColor3f(1, 0, 0);//奇数次,涂红色
    		glVertex2f(x, y);
    	}
    
    	glEnd();
    	glFlush();
    }
    
    void mymouse(int button, int state, int x, int y)
    {
    	glClearColor(1, 1, 1, 1);
    	//bool flag = 0;
    
    	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    	{
    		draw_a_point(x, window_height - y, polygon_point_color);
    		point p(x, window_height - y);
    		input_vertice.push_back(p);
    		cout << "多边形顶点" << input_vertice.size() << ":(" << x << ", " << window_height - y << ")" << endl;
    	}
    
    	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    	{
    		glLineWidth(2.0f);
    		glBegin(GL_LINES);
    		glColor3fv(polygon_point_color);
    		for (int i = 0; i < input_vertice.size(); i++)
    		{
    			if (i == input_vertice.size() - 1)
    			{
    				glVertex2f(input_vertice[0].x, input_vertice[0].y);
    				glVertex2f(input_vertice[i].x, input_vertice[i].y);
    			}
    			else
    			{
    				glVertex2f(input_vertice[i].x, input_vertice[i].y);
    				glVertex2f(input_vertice[i + 1].x, input_vertice[i + 1].y);
    			}
    		}
    		glEnd();
    		glFlush();
    	}
    }
    
    void keyboard(unsigned char key, int x, int y)
    {
    	if (key == 32)
    	{
    		SutherlandHodgmanClip(::left);
    		SutherlandHodgmanClip(bottom);
    		SutherlandHodgmanClip(::right);
    		SutherlandHodgmanClip(top);
    
    		glLineWidth(4.0f);
    		glBegin(GL_LINE_LOOP);
    		glColor3fv(intersect_point_color);
    		for (int i = 0; i < output_vertice.size() - 1; i++)
    		{
    			bresenham1(output_vertice[i].x, output_vertice[i].y, output_vertice[i + 1].x, output_vertice[i + 1].y);
    		}
    		bresenham1(output_vertice[0].x, output_vertice[0].y, output_vertice[output_vertice.size() - 1].x, output_vertice[output_vertice.size() - 1].y);
    
    		glEnd();
    		glFlush();
    
    	}
    }
    
    展开全文
  • Weiler Atherton 任意多边形裁剪 Sutherland Hodgeman 算法解决了裁剪窗口为凸多边形窗口的问题 但一些应用需要涉及 任意多边形窗口含凹多边形窗口的裁剪 Weiler-Atherton 多边形裁剪算法正是满足这种要 求的算法 一...
  • 多边形裁剪算法

    2015-04-19 15:30:10
    多边形裁剪算法,还不错,学到挺多的,共享给大家看看
  • 直线裁剪 多边形裁剪

    2012-12-02 15:32:58
    图形学实验,用VC++实现直线裁剪和多边形裁剪
  • 多边形裁剪,多边形裁剪,多边形裁剪,VC实现
  • opengl 图形学 直线和多边形裁剪 C++
  • 一、裁剪单个多边形 import numpy as np import cv2 # 读取图像 img = cv2.imread("dog.jpg") # 坐标点points pts = np.array([[10, 10], [15, 0], [35, 8], [100, 20], [300, 45], [280, 100], [350, 230], [30,...

    一、裁剪单个多边形

    import numpy as np
    import cv2
    
    # 读取图像
    img = cv2.imread("dog.jpg")
    # 坐标点points
    pts = np.array([[10, 10], [15, 0], [35, 8], [100, 20], [300, 45], [280, 100], [350, 230], [30, 200]])
    pts = np.array([pts])
    # 和原始图像一样大小的0矩阵,作为mask
    mask = np.zeros(img.shape[:2], np.uint8)
    # 在mask上将多边形区域填充为白色
    cv2.polylines(mask, pts, 1, 255)    # 描绘边缘
    cv2.fillPoly(mask, pts, 255)    # 填充
    # 逐位与,得到裁剪后图像,此时是黑色背景
    dst = cv2.bitwise_and(img, img, mask=mask)
    # 添加白色背景
    bg = np.ones_like(img, np.uint8) * 255
    cv2.bitwise_not(bg, bg, mask=mask)  # bg的多边形区域为0,背景区域为255
    dst_white = bg + dst
    
    cv2.imwrite("mask.jpg", mask)
    cv2.imwrite("dst.jpg", dst)
    cv2.imwrite("dst_white.jpg", dst_white)
    

    裁剪结果:

    原图:

    mask:

    裁剪后:

     

    二、裁剪多个多边形

    已有多组坐标点pts,代表着多个多边形区域。

    思路:对每组坐标点都在mask上进行相同的操作即可。这里就不重复写了。

    三、裁剪镂空多边形

    已有多组坐标点pts,其中一组表示最外层多边形,其余的表示镂空区域多边形。

    思路1:对于最外层多边形在mask上进行白色填充(255);对于镂空区域多边形在mask上进行黑色填充(0)即可。(推荐)

    思路2:对每个多边形区域都生成一个mask,用原图分别进行裁剪,然后做图像减法,最后再添加白色背景即可。这里就不重复写了。

    展开全文
  • Turf.js中提供了一中多边形的裁剪方法是使用多边形去裁剪多边形,但是如果实际工作中需要使用到线去裁剪多边形却无法满足。 http://turfjs.org/docs#bboxClip 这边文章使用turf.js的基本方法,在...

    简述

    在gis系统中 经常会用到一些裁剪的方法,首先推荐一个非常好用的空间分析JavaScript库–Turf.js,不仅功能强大、使用简单,同时处理速度也很快。
    Turf.js中提供了一中多边形的裁剪方法是使用多边形去裁剪多边形,但是如果实际工作中需要使用到线去裁剪多边形却无法满足。
    http://turfjs.org/docs#bboxClip
    这边文章使用turf.js的基本方法,在此基础上构建了线裁剪多边形的方法。
    点击可查看在线demo

    算法原理

    (一)单个polygon的裁剪

    相交要求:线与多边形有且只有两个交点,且可以将多边形分成两部分
    1. 计算多边形与线的两个交点并根据交点将多边形分割成两条线
    image1
    2. 将分割的两条线根据切割点与切割线进行拼接,分别组成两个多边形,(需要注意的是线的方向性问题)
    image2

    (二)环多边形的裁剪

    相交要求:线与多边形有且只有两个交点,且可以将多边形分成两部分,同时切割线不可与内环相交
    注:在geojson数据中外部多边形的顺序为顺时针,环内部多边形顺序为逆时针
    1. 将环多边形拆分成内环和外环
    image3
    2. 对外环多边形通过切割线进行裁剪 方法同(一)

    1. 组合切割后的外环多边形和内环多边形:(通过判断内环多边形在那一个切割多边形内部从而判断如何进行组合还原)
      image4

    (三)MultiPolygon多边形的裁剪

    相交要求:切割线只能与MultiPolygon中的一个Polygon有两个交点
    1. 拆分MultiPolygon分割为多个Polygon
    2. 根据切割线与多边形的相交情况,对有两个交点的多边形进行进行切割
    image5
    3. 将分割后的多边形与不参与切割的多边形合并组成要素集进行返回即可

    项目地址

    github:https://github.com/FWC1994/clip-polygon

    展开全文
  • 多边形裁剪

    2018-12-07 10:34:36
    自己写的多边形裁剪算法(计算机图形学作业),鼠标左键拖拉改变多边形的顶点坐标实现拖动,鼠标右键拖动实现裁剪窗口的拖动,点击裁剪按钮实现裁剪功能,点击清空缓存按钮实现清空裁剪以便进行下一次的裁剪
  • 逐次多边形裁剪算法算法的思想发窗口四条边界单一逐次对多边形进行裁剪,每次用窗口的一条边界(包括延长线)对要裁剪的多边形进行裁剪,裁剪时,顺序地测试多边形各顶点,保留边界内侧的顶点,删除外侧的顶点,同时,...
  • 逐边裁剪法实现多边形裁剪

    千次阅读 2019-07-22 16:18:57
    已经处理退化边的多边形裁剪算法 //编译环境:Visual C++ 6.0,EasyX_20190219(beta) #include<graphics.h> #include<conio.h> #include<iostream> #define max 30 using namespace std; //设置...
  • 算法步骤:(1)确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax)。(2)从y=ymin到y=ymax,每次用一条扫描线进行填充。填充过程可分为四个步骤:a.求交:计算扫描线与多边形各边的交点;b...
  • UI效果: 直角的八边形 与圆角的八边形   RoundCornerLayout 代码: import android.content.Context; import android.graphics.Canvas; import android.graphics.Color;...import android.graph...
  • 基于MFC的VC++程序,实现基于Weiler-Atherton算法,能使完成任意形状的多边形剪裁。详细功能描述见程序内标注说明。 This is a VC++ program, which implements the cutting function of ramdom polygons, based on...
  • 左裁剪 右裁剪 下裁剪 上裁剪
  • 本资源包含了Cohen-Sutherland算法、Liang-Barsky算法实现直线段裁剪以及自创的多边形裁剪(老师都没查出BUG)的cpp源代码和实验报告。重点是多边形裁剪,400多行代码,最终实现了任意多边形裁剪,下载即可运行
  • openGL-多边形裁剪算法

    千次阅读 2018-03-24 14:58:04
    综述:这里只是简单记录了部分实现思想。该部分代码不具备实际使用功能。 考虑使用4把刀分别裁剪一个图形。核心思想是,有一个点在扫描整个图形的边界。在扫描过程中,如果从刀的内侧(需要自己定义)到刀的外侧...
  • 图形学多边形的裁剪,在屏幕客户区绘制多边形(可以用鼠标绘制或直接给定坐标),用代码绘制“裁剪窗口”(也可以使用鼠标绘制裁减窗口)按下“鼠标右键”按钮,利用sutherland-Hodgman算法对多边形进行裁剪,用不同...
  • OpenGL实现的用凸多边去裁剪任意多边形的算法,手动画出直线,VS2008工程
  • 基于VC++6.0中MFC的计算机图形学程序,实现了画点画线画多边形多边形的裁剪填充消隐,二、三维图形变换(对称,镜像,拉伸,放大缩小,动画等等)
  • PCL裁剪之多边形裁剪

    2019-05-25 21:31:00
    PCL自带的裁剪方法,本人就不作介绍了,具体详见本人之间的博客https://www.cnblogs.com/z-web-2017/p/10187556.html,此处主要是对之前裁剪方法存在的不足进行完善,加入视点方向进行投影。保证相机转动时,投影...
  • 五、多边形裁剪多边形裁剪算法的输出应该是裁剪后的多边形边界的【定点序列】!5.1Sutherland—Hodgeman多边形裁剪——>【分而治之】基本思想:将多边形边界作为一个整体,每次用窗口的一条边对要裁剪的多边形和...
  • 在 pycharm 加 pyqt5环境中开发,python实现Sutherland-Hodge 逐次裁剪法(多边形裁剪)。 有优美的 UI界面
  • 基于MFC的计算机图形学中点裁剪算法多边形裁剪算法
  • python多边形裁剪

    千次阅读 2018-05-24 19:51:02
    python多边形裁剪
  • 多边形裁剪 在实际问题中,我们往往需要处理的是用矩形裁剪一个多边形,找到多边形落在屏幕区域内的部分。如下图: 一般有两种算法来处理多边形裁剪问题:Sutherland-Hodgeman算法和Weiler-Atherton算法。 下面...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,012
精华内容 6,404
关键字:

如何剪多边形