`

计算几何(一)——基础算法

 
阅读更多

待续 《计算几何资料》为提纲

1.

(1) 有向线段 : 如果一条线段的端点有次序之分,我们把这种线段称为有向线段(directed segment)。

(2) 矢量 :如果有向线段p1p2的起点p1在坐标原点,则称之为矢量(vector) p2

(3) (二维)矢量叉乘 : P=(x1,y1),  Q=(x2,y2) ==> P×Q

    随便的定义: 大小|x1  y1|, 方向右手法则

                                  |x2  y2|

    严格定义:(    将二维扩展到三维 P=(x1,y1,0), Q=(x2,y2,0)    )

                   P×Q=|i     j     k|=k*|x1  y1|

                              |x1  y1  0|      |x2  y2|

                              |x2  y2  0|

    P×Q>0,则P在Q的顺时针方向(指:Q沿顺时针方向相比沿逆时针方向更早到达P)

    P×Q<0,则P在Q的逆时针方向

    P×Q=0,则P和Q共线(同向或反向)

 

2. 折线段拐向 :利用二维矢量叉乘性质

 

3. “点”与“线段”关系

    设点Q,线段P1P2.

    点Q在线段上:共线(Q-P1)×(P2-P1)在P1,P2为对角顶点矩形内

 

2、3 代码:

#include<iostream>
using namespace std;

struct Point{
       double x;
       double y;
       Point(double a=0, double b=0){x=a;y=b;}
};

struct LineSeg{
       Point s;
       Point e;
       LineSeg(){}
       LineSeg(Point a, Point b){s=a;e=b;}
};

/*有向线段 dl<op,sp>×dl<op,ep>*/
double multiply(Point sp,Point ep,Point op) { 
  return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); 
}

/*点在线段上*/
bool ptOnLine(LineSeg l, Point p){
  return ( multiply(l.e, p, l.s)==0 &&
         (p.x-l.s.x)*(p.x-l.e.x)<=0 &&
         (p.y-l.s.y)*(p.y-l.e.y)<=0 );
}

int main(void){
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(2,2)), *new Point(1.5,1.5) )<<endl; //1
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(2,2)), *new Point(3,3) )<<endl;     //0
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(2,2)), *new Point(2,3) )<<endl;     //0
    
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(2,1)), *new Point(1.5,1) )<<endl;   //1
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(2,1)), *new Point(3,1) )<<endl;     //0
    
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(1,2)), *new Point(1,1.5) )<<endl;   //1
    cout<<ptOnLine( LineSeg(*new Point(1,1), *new Point(1,2)), *new Point(1,3) )<<endl;     //0
    
    system("pause");
    return 0;
}
 

12. “点”与“多边形”关系

(1)射线法——适用于任何多边形(凹凸),C:\Users\Administrator\Desktop\Test\计算几何\PointInPoly.cpp

    过此点向任意角度发一条射线,若与多边形的各条边交点个数之和为偶数,则此点在 多边形之外,否则在多边形之内。
    若有交点为多边形顶点则要另选一条射线重算

射线法代码:

#include<iostream>
#include<cmath>
using namespace std;

class CPoint{
public:
       CPoint(){this->x=x;this->y=y;}
       CPoint(double x, double y){
         this->x=x;
         this->y=y;
       }
       double x;
       double y;
};

//向右射线与线段关系:相交返回1,不相交返回0,在边上返回-1(-1时认为点在多边形内)
int IsIntersectant( CPoint ptStart, CPoint ptEnd, CPoint pd ){
  double tempx = 0;
  double tempy = 0;

  double startx = ptStart.x;   
  double starty = ptStart.y;
  double endx = ptEnd.x;   
  double endy = ptEnd.y;
 
  //横标范围[minX, maxX] 
  double maxX = startx;
  double minX = endx;
  if (startx<endx){
    minX = startx;
    maxX = endx;
  }
 
  //保证开始点在下(y坐标大),作为下端点
  if(starty<endy){
    double temp=starty;
    starty=endy;
    endy=temp;
   
    temp=startx;
    startx=endx;
    endx=temp;
  }
 
  //1. 没有交点 (特例一) 
  if((pd.y>starty && pd.y>endy) || (pd.y<starty && pd.y<endy)){
    //水平射线在该直线段的上下两端之外
    return 0;
  }
  if(pd.x>startx && pd.x>endx){
    //水平射线的起点在该直线段的右边
    return 0;
  }
 
  //2. 对于水平线段 : 在线段上返回-1,否则返回0 (特例二) 
  if (starty ==endy)
  {
    if (pd.x<=maxX&&pd.x>=minX)
      return -1;
    return 0;
  }
 
  //3. 非水平线段 
  //   3.1 (向右射线端点)pd在线段上: 通过三角形三边关系判断 
  tempx = pd.x - startx;
  tempy = pd.y - starty;
  double dStartToX = sqrt(tempx*tempx+tempy*tempy);
 
  tempx = pd.x - endx;
  tempy = pd.y - endy;
  double dXToEnd = sqrt(tempx*tempx+tempy*tempy);
 
  tempx = startx - endx;
  tempy = starty - endy;
  double dStarToEnd = sqrt(tempx*tempx+tempy*tempy);
 
  if (dStarToEnd == (dStartToX + dXToEnd)){
    return -1;
  }
  
  //   3.2 向右射线和线段不相交 
  //h_x记录点pd(x,y)引水平线与直线段所在直线的交点x坐标
  //注:直线两点式公式 (y-y1)/(y2-y1)=(x-x1)/(x2-x1),其中 x1≠x2, y1≠y2
  //          也可写作 y-y1=(y2-y1)/(x2-x1)*(x-x1),其中x1≠x2 
  double h_x=(pd.y-starty)*(endx-startx)/(endy-starty)+startx; //只需保证y1≠y2  
  if(pd.x>h_x){//pd点在交点的右边,则射线与线段不相交
    return 0;
  }
  
  //   3.3 向右射线和线段相交
  return 1;
}
 
/**点是否在多边形内 (射线法)*/
bool PtInPolygon( CPoint *ptList, int ptCount, CPoint pd ){
  if (ptCount<3){
    cout<<"注:多边形顶点至少有3个"<<endl; 
    return false;
  }
  
  int cross_num = 0;
  int iFlag = 0;
  //从点pd,向右引水平射线
 
  //除了末端点与首端点连接线,其他各条边的线段 -->与水平射线的交点和 cross_num
  for(int i=0;i<ptCount-1;i++)
  {
    iFlag = IsIntersectant(ptList[i], ptList[i+1], pd);
    if (iFlag < 0){
      return true;
    }else{
     cross_num += iFlag;
    }
  }
  //末端点与首端点连接线 --> 与水平射线的交点和 cross_num
  iFlag = IsIntersectant(ptList[ptCount-1], ptList[0], pd);
  if(iFlag < 0){
    return true;
  }else{
    cross_num += iFlag;
  }
 
  if(cross_num%2==1){
    //1. 交点个数为奇,则点在多边形内 
    return true;
  }else if(cross_num%2==0){
    //2. 交点个数为偶,则点不在多边形内 
    return false;
  }
  return false;
}

int main(void){   
    //如果先声明 CPoint ptList[5]; 必须提供无参构造函数 
    CPoint ptList[5]={CPoint(0,0),CPoint(2,0),CPoint(2,2),CPoint(1,1),CPoint(0,2)};
    int ptNum=5;
    
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(1,1))<<endl;     //1
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(0.5,1))<<endl;   //1
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(1.5,1.1))<<endl; //1
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(1,0))<<endl;     //1
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(1,1.5))<<endl;   //0
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(2.5,3))<<endl;   //0
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(-1,-1))<<endl;   //0
    cout<<PtInPolygon(ptList,ptNum,*new CPoint(2,2))<<endl;     //1
    
    system("pause");
    return 0;
}

 

(2)叉乘判别法——适用于凸多边形,见 http://www.cppblog.com/w2001/archive/2011/06/17/31694.html

     想象一个凸多边形,其每一个边都将整个2D屏幕划分成为左右两边,连接每一边的第一个端点和要测试的点得到一 个矢量v,将两个2维矢量扩展成3维的,然后将该边与v叉乘,判断结果3维矢量中Z分量的符号是否发生变化,进而推导出点是否处于凸多边形内外。这里要注 意的是,多边形顶点究竟是左手序还是右手序,这对具体判断方式有影响。

 

(3)累积角度法——适用于任何多边形(凹凸):
    过此点连接多边形的每一顶点,各相邻边角度(±)之和为360度 ,则此点在多边形内。否则为0度 ,在多边形外部。

 

  • 大小: 38.5 KB
分享到:
评论

相关推荐

    计算几何——算法分析与设计周培德.pdf

    《计算几何——算法分析与设计》是周培德教授撰写的一本深入探讨计算几何领域的专著。这本书详尽地阐述了计算几何的基本概念、核心算法以及在实际问题中的应用。计算几何是计算机科学的一个重要分支,它研究如何用...

    计算几何——算法分析与设计

    周培德所著的《计算几何——算法分析与设计》一书,是深入理解和掌握这一领域的经典教材。这本书由清华大学出版社出版,以PDG格式提供,可能是电子版或扫描版的形式。 计算几何的主要目标是解决几何问题,例如点、...

    计算几何——算法分析与设计.rar

    这个"计算几何——算法分析与设计.rar"压缩包很可能包含了一系列关于计算几何核心算法的详细讲解和实例分析。下面我们将深入探讨计算几何中的关键概念和算法。 1. **点、线、面的基本操作**:计算几何的基础是二...

    计算几何算法与应用计算几何算法与应用

    计算几何是计算机科学的一个重要分支,它涉及到数学、图形学和算法设计等多个领域。这个主题主要探讨如何使用算法来处理和解决与几何形状和空间结构相关的计算问题。在这个压缩包中,我们有“计算几何--算法与应用...

    计算几何——算法分析与设计_10192623

    在本资料"计算几何——算法分析与设计_10192623"中,我们将深入探讨这一主题,主要关注算法的设计和分析。下面,我们将详细阐述计算几何中的核心概念、关键算法以及它们在实际问题中的应用。 1. **基本概念**:计算...

    计算几何常用算法——点的基本算法

    在计算几何领域,点的基本算法是构建更复杂几何算法的基础。...计算几何的这些基础算法广泛应用于图形学、游戏开发、物理模拟、地图学等领域,理解并熟练掌握它们对于进行相关的计算和问题解决至关重要。

    计算几何算法讲解和源代码

    "计算几何算法讲解和源代码"这个资源集合可能是为了帮助开发者和学习者深入理解这一主题,通过实例和代码来教授各种计算几何算法。 1. **基础概念**:计算几何的基础概念包括点、线、面、多边形、曲线和曲面等基本...

    [转贴]计算几何(附:计算几何函数库)

    计算几何是一种应用广泛的数学分支,它涉及到几何形状的分析、构造和操作,通常与计算机科学中的算法和数据结构相结合。在计算机图形学、游戏开发、地理信息系统、机器人路径规划等领域,计算几何都有着至关重要的...

    分形几何——数学基础及其应用

    本书《分形几何——数学基础及其应用》(第二版)由英国数学家Kenneth Falconer编写,是一部经典的教材和参考资料。该书首次出版于2003年,并由John Wiley & Sons, Inc.出版。中文版由人民邮电出版社出版,译者为曾...

    计算几何——设计与制造

    《计算几何——设计与制造》这本书很可能深入探讨了以下几个核心知识点: 1. **几何建模**:这是计算几何的基础,用于创建和表示三维物体的数学模型。常见的几何建模方法包括线框建模、表面建模和实体建模,每种...

    计算几何与方法设计

    方法设计是计算几何中的一个重要环节,它涉及到如何有效地构建和优化算法,以提高计算效率和准确性。 在王晓东的《计算几何与方法设计》一书中,我们可以预见到作者会深入探讨计算几何的基本概念、理论和应用。这...

    周培德 计算几何 pdf

    《计算几何——算法分析与设计》一书由周培德教授编写,是计算机科学领域内的一部重要著作,尤其在几何算法的研究与教学方面具有深远的影响。计算几何作为一门研究如何在计算机上高效处理几何问题的学科,其核心在于...

    计算几何--算法与应用(第2版)(中文版).rar

    《计算几何——算法与应用(第2版)(中文版)》这本书很可能是对这一领域的深度探讨,提供了详细的理论基础和实用算法。 计算几何的主要知识点包括: 1. **基本概念**:首先,理解几何对象的基本属性和操作是至关...

    计算几何--算法与应用(第2版)

    《计算几何——算法与应用(第2版)》通过深入浅出的方式,介绍了计算几何领域的核心算法和技术,对于学习者而言是一本不可多得的好书。特别是对于三角剖分等关键技术的详细介绍,有助于读者更深入地理解计算几何的...

    计算机视觉——计算理论与算法基础

    本专题主要探讨的是计算机视觉的计算理论与算法基础,这是理解和开发计算机视觉系统的关键。 首先,我们要理解计算机视觉的基本目标:通过模拟人类视觉系统,使计算机能够解析、理解和解释图像或视频数据。这包括了...

    计算几何——三角形的相关计算

    计算几何是计算机科学中的一个重要分支,它涉及到二维和三维空间中的几何对象的算法处理。在这个领域,三角形是最基本的构建块,广泛应用于图形学、物理模拟、游戏开发以及各种数学问题的解决。本篇文章将深入探讨...

    计算机怎样解几何题:谈谈自动推理.pdf

    计算机解几何题是一个复杂的过程,它涉及到将人的逻辑思维和数学推理转换为计算机可识别和执行的程序。在《计算机怎样解几何题:谈谈自动推理》这本书中,作者探讨了这一主题,并详细说明了计算机如何运用其基本功能...

Global site tag (gtag.js) - Google Analytics