多边形裁剪| Sutherland–Hodgman算法

给出了一个凸多边形和一个凸裁剪区域。任务是使用Sutherland–Hodgman算法剪裁多边形边。输入是以多边形顶点的形式输入的 顺时针顺序 .

null

例如:

Input : Polygon : (100,150), (200,250), (300,200)
        Clipping Area : (150,150), (150,200), (200,200), 
                            (200,150) i.e. a Square    
Output : (150, 162) (150, 200) (200, 200) (200, 174) 
sutherland-hodgman-example-11

Example 2
Input : Polygon : (100,150), (200,250), (300,200)
        Clipping Area : (100,300), (300,300), (200,100) 
Output : (242, 185) (166, 166) (150, 200) (200, 250) (260, 220) 
sutherland-hodgman-example-22

算法概述:

Consider each edge e of clipping Area  and do following:
   a) Clip given polygon against e.

如何根据剪裁区域的边缘进行剪裁? 将(剪裁区域的)边无限延伸以创建边界,并使用该边界剪裁所有顶点。生成的新顶点列表将以顺时针方式传递到剪辑多边形的下一条边,直到所有边都已使用。

给定多边形的任意给定边与当前剪切边e之间存在四种可能的情况。

  1. 两个顶点都在内部: 只有第二个顶点被添加到输出列表中
  2. 第一个顶点在外部,第二个顶点在内部: 边与剪辑边界的交点和第二个顶点都将添加到输出列表中
  3. 第一个顶点在内侧,第二个顶点在外侧: 只有边与剪辑边界的交点才会添加到输出列表中
  4. 两个顶点都在外部: 没有顶点添加到输出列表中

sutherland-hodgman-example-1

在实现算法之前,需要讨论两个子问题:-

决定一个点是在裁剪器多边形的内部还是外部 如果裁剪器多边形的顶点是按顺时针顺序给定的,则所有位于该多边形上的点 右侧 其中一条修剪器边位于该多边形内。这可以使用以下公式计算: Formula-for-position-of-point

查找边与剪辑边界的交点的步骤 如果每条直线(1,2和3,4)的两个点已知,则可以使用以下公式计算它们的交点:- Formula-for-point-of-intersection

// C++ program for implementing Sutherland–Hodgman
// algorithm for polygon clipping
#include<iostream>
using namespace std;
const int MAX_POINTS = 20;
// Returns x-value of point of intersection of two
// lines
int x_intersect( int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
int num = (x1*y2 - y1*x2) * (x3-x4) -
(x1-x2) * (x3*y4 - y3*x4);
int den = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4);
return num/den;
}
// Returns y-value of point of intersection of
// two lines
int y_intersect( int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
int num = (x1*y2 - y1*x2) * (y3-y4) -
(y1-y2) * (x3*y4 - y3*x4);
int den = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4);
return num/den;
}
// This functions clips all the edges w.r.t one clip
// edge of clipping area
void clip( int poly_points[][2], int &poly_size,
int x1, int y1, int x2, int y2)
{
int new_points[MAX_POINTS][2], new_poly_size = 0;
// (ix,iy),(kx,ky) are the co-ordinate values of
// the points
for ( int i = 0; i < poly_size; i++)
{
// i and k form a line in polygon
int k = (i+1) % poly_size;
int ix = poly_points[i][0], iy = poly_points[i][1];
int kx = poly_points[k][0], ky = poly_points[k][1];
// Calculating position of first point
// w.r.t. clipper line
int i_pos = (x2-x1) * (iy-y1) - (y2-y1) * (ix-x1);
// Calculating position of second point
// w.r.t. clipper line
int k_pos = (x2-x1) * (ky-y1) - (y2-y1) * (kx-x1);
// Case 1 : When both points are inside
if (i_pos < 0  && k_pos < 0)
{
//Only second point is added
new_points[new_poly_size][0] = kx;
new_points[new_poly_size][1] = ky;
new_poly_size++;
}
// Case 2: When only first point is outside
else if (i_pos >= 0  && k_pos < 0)
{
// Point of intersection with edge
// and the second point is added
new_points[new_poly_size][0] = x_intersect(x1,
y1, x2, y2, ix, iy, kx, ky);
new_points[new_poly_size][1] = y_intersect(x1,
y1, x2, y2, ix, iy, kx, ky);
new_poly_size++;
new_points[new_poly_size][0] = kx;
new_points[new_poly_size][1] = ky;
new_poly_size++;
}
// Case 3: When only second point is outside
else if (i_pos < 0  && k_pos >= 0)
{
//Only point of intersection with edge is added
new_points[new_poly_size][0] = x_intersect(x1,
y1, x2, y2, ix, iy, kx, ky);
new_points[new_poly_size][1] = y_intersect(x1,
y1, x2, y2, ix, iy, kx, ky);
new_poly_size++;
}
// Case 4: When both points are outside
else
{
//No points are added
}
}
// Copying new points into original array
// and changing the no. of vertices
poly_size = new_poly_size;
for ( int i = 0; i < poly_size; i++)
{
poly_points[i][0] = new_points[i][0];
poly_points[i][1] = new_points[i][1];
}
}
// Implements Sutherland–Hodgman algorithm
void suthHodgClip( int poly_points[][2], int poly_size,
int clipper_points[][2], int clipper_size)
{
//i and k are two consecutive indexes
for ( int i=0; i<clipper_size; i++)
{
int k = (i+1) % clipper_size;
// We pass the current array of vertices, it's size
// and the end points of the selected clipper line
clip(poly_points, poly_size, clipper_points[i][0],
clipper_points[i][1], clipper_points[k][0],
clipper_points[k][1]);
}
// Printing vertices of clipped polygon
for ( int i=0; i < poly_size; i++)
cout << '(' << poly_points[i][0] <<
", " << poly_points[i][1] << ") " ;
}
//Driver code
int main()
{
// Defining polygon vertices in clockwise order
int poly_size = 3;
int poly_points[20][2] = {{100,150}, {200,250},
{300,200}};
// Defining clipper polygon vertices in clockwise order
// 1st Example with square clipper
int clipper_size = 4;
int clipper_points[][2] = {{150,150}, {150,200},
{200,200}, {200,150} };
// 2nd Example with triangle clipper
/*int clipper_size = 3;
int clipper_points[][2] = {{100,300}, {300,300},
{200,100}};*/
//Calling the clipping function
suthHodgClip(poly_points, poly_size, clipper_points,
clipper_size);
return 0;
}


输出:

(150, 162) (150, 200) (200, 200) (200, 174)

相关文章: 线裁剪|集1(科恩-萨瑟兰算法) 计算机图形学中的点裁剪算法

本文由 纳巴内特·罗伊 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享