半平面交

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Game_Acm/article/details/82624087
//符号判断
int sgn( double x )
{
    if ( fabs(x)<eps ) return 0;
    if ( x<0 ) return -1;
    if ( x>0 ) return  1;
}
//点类定义
struct Point
{
    double x,y;
    Point(){}
    Point( double _x , double _y )
    {
        x = _x; y = _y;
    }
    Point operator -( const Point&b )const
    {
        return Point( x-b.x , y-b.y );
    }
    Point operator +( const Point&b )const
    {
        return Point( x+b.x , y+b.y );
    }
    double operator ^( const Point&b )const
    {
        return x*b.y-y*b.x;
    }
    double operator *( const Point&b )const
    {
        return x*b.x+y*b.y;
    }
};
//多边形面积计算
double CalcArea( Point p[] , int n )
{
    double res = 0;
    for ( int i=0 ; i<n ; i++ )
        res += p[i]^p[i+1];
    if ( res<0 ) res = -res;
    return 0.5*res;
}
//两点确定直线方程
void  Get_equation( Point p1 , Point p2 , double &a , double &b , double &c )
{
    a = p2.y-p1.y;
    b = p1.x-p2.x;
    c = p2.x*p1.y-p1.x*p2.y;
}
//求交点
Point Intersection( Point p1 , Point p2 , double &a , double &b , double &c )
{
    double u = fabs(a*p1.x+b*p1.y+c);
    double v = fabs(a*p2.x+b*p2.y+c);
    Point t;
    t.x = (p1.x*v+p2.x*u)/(u+v);
    t.y = (p1.y*v+p2.y*u)/(u+v);
    return t;
}
Point tp[110];
void Cut( double a , double b , double c , Point p[] , int &cnt )
{
    int tmp = 0;
    for ( int i=1 ; i<=cnt ; i++ )
    {
        //逆时针写法,顺时针写法a*p[i].x+b*p[i].y+c>-eps
        if(a*p[i].x+b*p[i].y+c<eps) tp[++tmp] = p[i];
        else
        {
            //逆时针写法,顺时针写法a*p[i-1].x+b*p[i-1].y+c>eps
            if ( a*p[i-1].x+b*p[i-1].y+c<-eps )
                tp[++tmp] = Intersection( p[i-1] , p[i] , a , b , c );
            //逆时针写法,顺时针写法a*p[i+1].x+b*p[i+1].y+c>eps
            if ( a*p[i+1].x+b*p[i+1].y+c<-eps )
                tp[++tmp] = Intersection( p[i] , p[i+1] , a , b , c );
        }
    }
    for ( int i=1 ; i<=tmp ; i++ ) p[i] = tp[i];
    p[0] = p[tmp],p[tmp+1] = p[1],cnt = tmp;
}
int n; Point s[110],p[110];
bool solve()
{
    //逆时针写法,顺时针改成顺时针
    p[1] = Point( -inf , -inf );
    p[2] = Point( +inf , -inf );
    p[3] = Point( +inf , +inf );
    p[4] = Point( -inf , +inf );
    p[0] = p[4];
    p[5] = p[1];
    int cnt = 4;
    for ( int i=n-1 ; i>=0 ; i-- )
    {
        //两点转方程
        double a,b,c; Get_equation( s[i] , s[(i-1+n)%n] , a , b , c );
        if ( sgn(a)==0&&sgn(b)==0 )
        {
            //逆时针写法,顺时针写法sgn(c)<=0
            if ( sgn(c)>=0 ) return false;
            else continue;
        }
        Cut( a , b , c , p , cnt );
    }
    //判核写法,若判唯一解(要求最后多边形面积>0)
    if ( cnt==0 ) return false;
    else return true;
}

猜你喜欢

转载自blog.csdn.net/Game_Acm/article/details/82624087