1. 程式人生 > >計算幾何 點到線段的距離 點在簡單多邊形內 點到凸多邊形的距離

計算幾何 點到線段的距離 點在簡單多邊形內 點到凸多邊形的距離

#include <bits/stdc++.h>
using namespace std;

struct point_t {
    double x,y;
};
double cross(point_t const &O,point_t const &A,point_t const &B){
	double xOA = A.x - O.x;
	double yOA = A.y - O.y;
	double xOB = B.x - O.x;
	double yOB = B.y - O.y;
	return xOA * yOB - xOB * yOA;
}
double PointTOline( point_t const&a,point_t const&b,point_t const&p){
    double ap_ab = (b.x - a.x)*(p.x - a.x)+(b.y - a.y)*(p.y - a.y);//cross( a , p , b );
    if ( ap_ab <= 0 )
        return sqrt( (p.x-a.x)*(p.x-a.x) + (p.y-a.y)*(p.y-a.y) );

    double d2 = ( b.x - a.x ) * ( b.x - a.x ) + ( b.y-a.y ) * ( b.y-a.y ) ;
    if ( ap_ab >= d2 ) return sqrt( (p.x - b.x )*( p.x - b.x ) + ( p.y - b.y )*( p.y - b.y ) ) ;

    double r = ap_ab / d2;
    double px = a.x + ( b.x - a.x ) *r;
    double py = a.y + ( b.y - a.y ) *r;
    return sqrt( (p.x - px)*(p.x - px) + (p.y - py)*(p.y - py) );
}

bool isOnline( point_t const&a,point_t const&b, point_t const&po ){
    return po.x >= min( a.x , b.x ) &&
           po.x <= max( a.x , b.x ) &&
           po.y >= min( a.y , b.y ) &&
           po.y <= max( a.y , b.y ) &&
           ( po.x - a.x ) * ( b.y - a.y ) == ( po.y - a.y ) * ( b.x - a.x );
}
bool isInSimple( point_t * p ,int n , point_t const&po ){
    p[n] = p[0];
    bool flag = 0;
    int tmp;
    for ( int i = 0; i < n;++i ){
        if ( isOnline( p[i] , p[i+1] , po ) ) return true;
        if ( p[i].y == p[i+1].y ) continue;
        p[i].y < p[i+1].y ? tmp = i+1 : tmp = i ;
        if ( po.y == p[tmp].y && po.x < p[tmp].x ) flag ^= 1;
        p[i].y > p[i+1].y ? tmp = i+1 : tmp = i ;
        if ( po.y == p[tmp].y && po.x < p[tmp].x ) continue ;

        if ( po.x < max( p[i].x , p[i+1].x ) &&
             po.y > min( p[i].y , p[i+1].y ) &&
             po.y < max( p[i].y , p[i+1].y ) ) flag ^= 1;
    }
    return flag;
}

point_t p[120];
int main(){
    int n;
    while(cin>>n && n){
        point_t po;    
        cin>>po.x>>po.y;
        for (int i = 0;i < n;++i)
            cin>>p[i].x>>p[i].y;

        if ( isInSimple( p , n , po ) ) {
            cout <<"0.00"<<endl;
            continue;
        }
        double ans = PointTOline( p[0],p[1],po );
        p[n] = p[0];
        for (int i = 1;i < n ;++i)
            ans = min( ans, PointTOline(p[i] , p[i+1] , po) );
        cout <<ans<<endl;
    }
    return 0;
}