Cohen Sutherland Clipping 科恩-萨瑟兰算法 代码

主要用该算法解决直线在区间内的截取

理论部分可参考: https://www.cnblogs.com/fortunely/p/17739080.html

代码实现:

1、 区域划分

// CODING SCHEME
//
//        |   ABOVE    |
//        |    0x08    |
//  1001  |    1000    |  1010
//    ----+------------+----
//  LEFT  |   INSIDE   |  RIGHT
//  0x01  |  2D RANGE  |  0x02
//        |            |
//  0001  |    0000    |  0010
//    ----+------------+----
//        |   BELOW    |
//  0101  |    0x04    |  0110
//        |    0100    |

#define RANGE_INSIDE     0
#define RANGE_LEFT   0x01
#define RANGE_RIGHT  0x02
#define RANGE_BELOW  0x04
#define RANGE_ABOVE  0x08

顶部首位为1,底部第二位为1,右边第3位为1,左边第4位为1 。
按照井字形划分为9个区域;

2、定义区域结构体

typedef struct Range_
{
  float x_min;
  float x_max;
  float y_min;
  float y_max;
} Range;

3、定义线段

typedef struct Point_
{
  float x;
  float y;
} Point;

typedef struct Line_
{
  Point P1;
  Point P2;
} Line;

4、计算点落在区域内

uint_8 get_region_code(Range const * range,Point const * point){
  uint_32 result_region = VOX_ROI_INSIDE; 
  if (point->x < range->x_min){        
    result_region |= VOX_ROI_BIT_LEFT;
  }else if (point->x > range->x_max){   
    result_region |= VOX_ROI_BIT_RIGHT;
  }

  if (point->y < range->y_min){        
    result_region |= VOX_ROI_BIT_BELOW;
  }else if (point->y > range->y_max){  
    result_region |= VOX_ROI_BIT_ABOVE;
  }
  return (uint_8) result_region;
}

5、Cohen Sutherland Clipping 科恩-萨瑟兰算法

bool LineSegmentInOrIntersectRangeBox(const Range* range_box,Line* line_segment){

  uint_8   p1_in_region;
  uint_8   p2_in_region;
  bool result = false;

  if((range_box == NULL) || (line_segment == NULL)) return result;

  p1_in_region  = get_region_code(range_box, &line_segment->P1_st);
  p2_in_region  = get_region_code( range_box, &line_segment->P2_st );
  // Trivial case 1: one of the points is inside the rectangle
  if(p1_in_region == VOX_ROI_INSIDE && p2_in_region == VOX_ROI_INSIDE){
    result = false;
  }else if (
    ((p1_in_region | p2_in_region) == (VOX_ROI_BIT_ABOVE | VOX_ROI_BIT_BELOW)) || // trivial case 3 - horizontal crossing: one point is LEFT, one point is RIGHT
    ((p1_in_region | p2_in_region) == (VOX_ROI_BIT_RIGHT | VOX_ROI_BIT_LEFT )) ||  // trivial case 4 - vertical crossing: one point is ABOVE, one point is BELOW
    ((p1_in_region | p2_in_region) == (VOX_ROI_BIT_ABOVE | VOX_ROI_BIT_BELOW | VOX_ROI_BIT_RIGHT | VOX_ROI_BIT_LEFT )) ){ //diagonal crossing
    result = true;
  }else{
    float tmp_x, tmp_y;
    point P0, P1; 
    if (line_segment->P1.x <= line_segment->P2.x){
      P0 = line_segment->P1;
      P1 = line_segment->P2;
    }else{
      P0 = line_segment->P2;
      P1 = line_segment->P1;
    }
    if (((p1_in_region | p2_in_region) & (UInt8)VOX_ROI_BIT_LEFT) != (UInt8)VOX_ROI_INSIDE){
      tmp_y = (P1.y - P0.y) * (range_box->x_min - P0.x) / (P1.x - P0.x);
      tmp_y += P0_st.Y_f32;

      if ((tmp_y > range_box->y_min) && (tmp_y < range_box->y_max)){
        result = true;
      }
    }

    if (((p1_in_region | p2_in_region) & (UInt8)VOX_ROI_BIT_RIGHT) != (UInt8)VOX_ROI_INSIDE){
      tmp_y = (P1.y - P0.y) * (range_box->x_max - P0.x) / (P1.x - P0.x);
      tmp_y += P0.Y_f32;

      if ((tmp_y > range_box->y_min) && (tmp_y < range_box->y_max)){
        result = true;
      }
    }

    if (((p1_in_region | p2_in_region) & (UInt8)VOX_ROI_BIT_ABOVE) != (UInt8)VOX_ROI_INSIDE){
      tmp_x = (P1.X_f32 - P0.X_f32) * (range_box->YMax_f32 - P0.Y_f32) / P1.Y_f32 - P0.Y_f32;
      tmp_x += P0_st.X_f32;

      if ((tmp_x > range_box->XMin_f32) && (tmp_x < range_box->XMax_f32)){
        result = true;
      }
    }

    if (((p1_in_region | p2_in_region) & (UInt8)VOX_ROI_BIT_BELOW) != (UInt8)VOX_ROI_INSIDE)
    {
      tmp_x = (P1.x - P0.x) * (range_box->y_min - P0.y) / (P1.y - P0.y);
      tmp_x += P0.x;

      if ((tmp_x > range_box->x_min) && (tmp_x < range_box->x_max)){
        result = true;
      }
    }
  }
  return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值