算法尝试(一)

一、判断两封闭单连通图形A和B关系:
  旋转法:取图形A内的任一点X,如果X是B内部的点,则说明A、B相交。否则,连接X和B的边界上点P作线段XP。从X出发,考察从线段XP,作状态(IA,IB),IA和IB非零与否分别表示在A和B的内部与否,初始时为(1, 0),经过A或B的边界分别使IA或IB翻转,如果出现(IA,IB)=(1,1)就说明A、B相交,否则说明A、B不相交。
二、判断一个点X是否在N边形内部:
  圆环染色法:以X为起点,多边形各端点Pi为终点得向量XPi(i=0,1,...,N-1)。此后顺序考察各向量过程中,用到两个运算:以内角为准,到对比向量va相对于vb是顺时针还是逆时针的运算,返回1代表顺时针,-1表示逆时针,该运算可用向量积实现;三向量中间向量是否在两侧向量所夹内角中的判断,记作cr,可用解析法实现。记向量组XPi为v[i]。算法如下(经初步验证):   
  bool inpvec(const vector *v, int n)
  {
    int cl;
    int s = 0;
    int i, p;
    for(i = 2, p = 1; i < n; i++)
      if(cr(v, i, p, s)) p++;
    return check(v, p, s);
  }
  
  bool cr(const vector *v, int ic, int io, int &s)
  {
    int g1 = v[ic].x * v[io].y - v[ic].y * v[io].x;
    int g2 = (v[ic].x - v[io].x) * v[0].y - (v[ic].y - v[io].y) * v[0].x;
    if(g1 < 0 && g2 >= 0 || g1 > 0 && g2 <= 0) return true;
    if(g1 == 0) return false;
  
    int dxc = v[ic].x * g2 - v[0].x * g1;
    int dxo = v[io].x * g2 - v[0].x * g1;
    int dyc = v[ic].y * g2 - v[0].y * g1;
    int dyo = v[io].y * g2 - v[0].y * g1;
  
    if(dxc < 0 && dxo > 0 || dxc > 0 && dxo < 0 || 
        dyc < 0 && dyo > 0 || dyc > 0 && dyo < 0)
      s += (g1 > 0)? 1 : -1;
  
    return ((dxc != 0 || dyc != 0) && (dxo != 0 || dyo != 0));
  }
  
  bool check(const vector *v, int p, int s)
  {
    int g1 = v[1].x * v[0].y - v[1].y * v[0].x;
    int g2 = v[0].x * v[p].y - v[0].y * v[p].x;
    bool sd = (g1 > 0 && g2 > 0) || (g1 < 0 && g2 < 0);
    return (s == 0 && sd ||s != 0 && !sd);
  }
   


posted @ 2005-08-27 18:00  quanben  阅读(404)  评论(0编辑  收藏  举报