CyrusBeck

本文介绍了一种基于Cyrus-Beck算法的二维线段与凸多边形裁剪方法,并提供了具体的C++实现代码。该算法通过计算射线与多边形边界线的交点来确定线段的有效部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include "myglbase.h"
#include "glut.h"
#include "vector"
#include "iostream"
using namespace  std;

class Line2Segment
{
 public:
  Point2 first ;
  Point2 second ;

  Vector2 norm()
  {
   Vector2 c = second - first ;
   Vector2 normalVector = c.GetNormalVector();
   return normalVector;
  }

  Line2Segment()
  {
   first.x=first.y=0;
   second.x=second.y=0;
  }

  Line2Segment(Point2  first,Point2  second)
  {
   this->first = first;
   this->second = second;
  }

  Line2Segment(Line2Segment& line2)
  {
   first = line2.first;
   second = line2.second;
  }
};

class Line2
{
 public:
  Point2 pt ;
  Vector2 norm;

  Line2()
  {
   pt.x=pt.y=0;
   norm.x=0;
   norm.y=0;
  }
  Line2(Point2 pt,Vector2 norm)
  {
   this->pt=pt;
   this->norm=norm;
  }
  Line2(const Line2& line2)
  {
   pt=line2.pt;
   norm = line2.norm;
  }

};
class Line2List
{
 public:
  vector<Line2> line;

  int num()
  {
   return line.size();
  }

  void push_back(Line2 newLine)
  {
   line.push_back(newLine);
  }
  Line2& operator[](int index)
  {
   if ((unsigned int)index >= line.size())  //注意size是unsigned int
   {
    throw "Out of range in  Line2List";
   }
   return line[index];
  }
};

 

int chopCI(double&tIn,double&tOut,double number,double denom)
{
 double tHit ;
 if(denom < 0) //射线是射入
 {
  tHit = number / denom ;
  if (tHit > tOut)
  {
   return 0 ;
  }
  else if(tHit>tIn)
  {
   tIn = tHit;
  }
 }
 else if(denom > 0)
 {
  tHit =  number / denom;
  if (tHit<tIn)
  {
   return 0 ;
  }
  if (tHit<tOut)
  {
   tOut = tHit;
  }
 }
 else if(number<=0) //denom为0,射线与直线平行
 {
  return 0 ;   //在外半空间
 }

 return 1;
}


//线段和凸多边形的交点 (二维)
int CyrusBeckClip(Line2Segment& seg,Line2List& L)
{
 double number,denom;
 double tIn = 0.0,tOut = 1.0 ;  //候选区间为[0,1]
 Vector2 c, tmp ;
 c = seg.first-seg.second; //直线的参数表示 R(t)=A+c*tHit
 for (int i=0;i<L.num();i++)
 {
  //利用公式 tHit=n*(B-A)/(n*c)  其中A和c是目的直线参数表示,B和n是另一条直线点法向量
   tmp = L.line[i].pt - seg.first;
   number = L.line[i].norm * tmp ;
   denom = L.line[i].norm * c ;
   if (!chopCI(number,denom,tIn,tOut))
   {
    return 0  ; //提前结束
   }
 }

 //注意tIn和tOut都是基于A+c*tHit ;所以在计算seg截点时,先计算seg.second;
 //否则,A的值,即seg.first就变化了
 if(tOut <1.0)
 {
  //书上做法
//   seg.second.x = seg.first.x + c.x * tOut ;
//   seg.second.y = seg.first.y + c.y * tOut ;
  //我已经对操作符进行了重载了
  seg.second = seg.first + c * tOut;

 }
 if (tIn>0.0)
 {
  //书上做法
//   seg.first.x = seg.first.x + c.x * tIn ;
//   seg.first.y = seg.first.y + c.y * tIn ;
  //我已经对操作符重载
  seg.first = seg.first + c * tIn;
 }
 return 1;
}


int main()
{
 return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值