多边形裁剪|Sutherland-Hodgman

此算法只能裁剪凸多边形

 

先看俩个例子

算法基本思想:

基本思想:一次用窗口的一条边来裁剪多边形。

算法的输入是以顶点序列表示的多边形,输出也是一个顶点序列,这些顶点能够构成一个或多个多边形。

处理对象:任意多边形。

窗口的任意一条边的所在直线(裁剪线)把窗口所在平面分成两部分:

可见一侧:包含窗口那部分

不可见一侧:不包含窗口那部分

l将每条线段的端点S, P与裁剪线比较之后,可以输出02个点:

(1) S, P都在可见一侧,输出顶点P

(2) S, P都在不可见一侧,输出0个顶点。

(3) S在可见一侧,P在不可见一侧,输出SP与裁剪线的交点I

(4) S在不可见一侧,P在可见一侧,输出SP与裁剪线的交点I顶点P

例如:

代码实现:

#include<iostream> 
using namespace std; 
  
const int MAX_POINTS = 20; 
  
//交点横坐标
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; 
}  
//返回交点纵坐标
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; 
} 
  
// 裁剪
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; 
    for (int i = 0; i < poly_size; i++) 
    { 
        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]; 
  
        int i_pos = (x2-x1) * (iy-y1) - (y2-y1) * (ix-x1); //标志
        int k_pos = (x2-x1) * (ky-y1) - (y2-y1) * (kx-x1); 
  
        // Case 1 
        if (i_pos < 0  && k_pos < 0) 
        { 
            new_points[new_poly_size][0] = kx; 
            new_points[new_poly_size][1] = ky; 
            new_poly_size++; 
        } 
  
        // Case 2
        else if (i_pos >= 0  && k_pos < 0) 
        { 
            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
        else if (i_pos < 0  && k_pos >= 0) 
        {        
            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 不添加点
        else
        { 
             
        } 
    } 
    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]; 
    } 
} 
  
void suthHodgClip(int poly_points[][2], int poly_size, 
                  int clipper_points[][2], int clipper_size) 
{ 
    for (int i=0; i<clipper_size; i++) 
    { 
        int k = (i+1) % clipper_size; 
  
        clip(poly_points, poly_size, clipper_points[i][0], 
             clipper_points[i][1], clipper_points[k][0], 
             clipper_points[k][1]); 
    } 
    for (int i=0; i < poly_size; i++) 
        cout << '(' << poly_points[i][0] << 
                ", " << poly_points[i][1] << ") "; 
} 
int main() 
{ 
    int poly_size = 3; 
    int poly_points[20][2] = {{100,150}, {200,250}, 
                              {300,200}}; 
    int clipper_size = 4; 
    int clipper_points[][2] = {{150,150}, {150,200}, 
                              {200,200}, {200,150} }; 
  
    //三角形裁剪区域
    /*int clipper_size = 3; 
    int clipper_points[][2] = {{100,300}, {300,300}, 
                                {200,100}};*/
    suthHodgClip(poly_points, poly_size, clipper_points, clipper_size); 
    return 0; 
} 

输出:

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

基于vs2010MFC实现

上图

 

 

 

其他图形学代码下载:https://download.csdn.net/download/qq_40310876/11222412

 

 

 

 

 

来源于中华女子学院山东分校赵晓峰的论文

 

 

  • 16
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值