2016.2.18 水污染管理 [计算几何] [三角剖分]

【问题描述】
作为水污染管理部门的一名雇员,你需要监控那些被有意无倒入河流、湖 作为水污染管理部门的一名雇员,你需要监控那些被有意无倒入河流、湖 作为水污染管理部门的一名雇员,你需要监控那些被有意无倒入河流、湖 泊和海洋的污染物。你其中一项工作就是估计对不 泊和海洋的污染物。你其中一项工作就是估计对不 同的水生态系统(珊 同的水生态系统(珊 瑚礁、产卵地等)造成的影响。
这里写图片描述
你计算所使用的模型已经在图 1中被说明。海岸线(图 中被说明。海岸线(图 中被说明。海岸线(图 1中的水平直线)为 中的水平直线)为 x轴,污染源位于原点 轴,污染源位于原点 (0, 0)(0, 0) 。污染的蔓延呈半圆形,多边代表了被波及生态 。污染的蔓延呈半圆形,多边代表了被波及生态 。污染的蔓延呈半圆形,多边代表了被波及生态 系统。
你需要计算出生态被污染的面积,也就是图中深蓝色部分

【输入格式】
第一行为两个整数 ��,��,��表示了多边形的顶点个数, ��表示了污染区域的半径;
接下来 ��行,每包含两个整数 行,每包含两个整数 ����,����,表示每个顶点的坐标以逆时针顺序 ,表示每个顶点的坐标以逆时针顺序 ,表示每个顶点的坐标以逆时针顺序 给出; 数据保证多边形不自交或触及身,没有顶点会位于圆弧上。

【输出格式】
输出多边形被圆心位于原点、半径为 ��的半圆覆盖面积。 答案的绝对误差不得超过 10−3。

【样例输入】
6 10
-8 2
8 2
8 14
0 14
0 6
-8 14

【样例输出】
101.576437872

【数据规模与约定】
对于100%的数据 ,1≤n≤100,1≤r≤10^3,−1500≤xi≤1500,0≤yi≤1500。


三角形剖分,计算多边形面积的变式,最后把叉积的和加起来之后要去绝对值! 因为方向是随便定的!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
const int INF=0x3f3f3f3f;
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){ }
};
typedef Point Vector;
Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p);}
Vector operator / (Vector A,double p){ return Vector(A.x/p,A.y/p);}
const double eps=1e-10;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x>0?1:-1;
}
bool operator == (const Vector &v1,const Vector &v2)
{
    return dcmp(v1.x-v2.x)==0 && dcmp(v1.y-v2.y)==0;
}
double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y; }
double Length(Vector A){ return sqrt(Dot(A,A)); }
double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x; }
double Angle(Vector A,Vector B){ return acos(Dot(A,B)/Length(A)/Length(B));}

int R,n;
Point O=Point(0,0);
Vector v0=Vector(0,0);
bool on_line(Point P1,Point P2,Point P3)
{
    return Cross(P1-P2,P2-P3)==v0?true:false;
}
double get_sector_area(Vector v1,Vector v2,double R)
{
    double alpha=Angle(v1,v2);
    return R*R*alpha/2;
}
Point get_circle_intersection(Point A,Point B)//ANS.x is between A and B 
{
    if(A.x==B.x) return Point(A.x,sqrt(R*R-A.x*A.x));//important ! special judge!
    double k=(A.y-B.y)/(A.x-B.x);
    double b=A.y-k*A.x;
    double a1=k*k+1.0,a2=2.0*k*b,a3=b*b-R*R;
    double delta=a2*a2-4.0*a1*a3;
    delta=sqrt(delta);
    double x1=(-a2+delta)/2/a1;
    double x2=(-a2-delta)/2/a1;
    if(dcmp(A.x-x1)*dcmp(B.x-x1)<0) return Point(x1,k*x1+b);
    if(dcmp(A.x-x2)*dcmp(B.x-x2)<0) return Point(x2,k*x2+b);
    if(dcmp(A.x-x1)*dcmp(B.x-x1)==0) return Point(x1,k*x1+b);// = needed! the case of segistration!!
    else return Point(x2,k*x2+b);
}
void get_line_intersection(Point A,Point B,Point &C,Point &D)
{
    double k=(A.y-B.y)/(A.x-B.x);
    double b=A.y-k*A.x;
    double a1=k*k+1.0,a2=2.0*k*b,a3=b*b-R*R;
    double delta=a2*a2-4.0*a1*a3;
    delta=sqrt(delta);
    double x1=(-a2+delta)/2/a1;
    double x2=(-a2-delta)/2/a1;
    C=Point(x1,k*x1+b);
    D=Point(x2,k*x2+b);
    if((A.x<=B.x&&C.x>D.x)||(A.x>B.x&&C.x<=D.x))  swap(C,D);
}
double get_in_tri(Point A,Point B)//A is in, B is out
{
    Vector v1=A-O,v2=B-O;
    Point C=get_circle_intersection(A,B);
    Point D=get_circle_intersection(B,O);
    Vector v3=C-O;
    Vector v4=D-O;
    double s1=Cross(v1,v3)/2;
    double sign=Cross(v3,v4);
    double s2=get_sector_area(v3,v4,R);
    if(sign*s2<0) s2*=-1;//important!! each time need to make sure the same operator!!
    return s1+s2;
}
double get_out_tri(Point A,Point B)
{
    Vector v1=A-O,v2=B-O;
    Point C=get_circle_intersection(A,O);
    Point D=get_circle_intersection(A,B);
    Vector v3=C-O;
    Vector v4=D-O;
    double s1=Cross(v4,v2)/2;
    double sign=Cross(v3,v4);
    double s2=get_sector_area(v3,v4,R);
    if(sign*s2<0) s2*=-1;//important!! each time need to make sure the same operator!!
    return s1+s2;
}
double get_in_out_tri(Point A,Point B)
{
    Vector v1=A-O,v2=B-O;
    double len1=Length(v1),len2=Length(v2);
    if(len1<=len2) return get_in_tri(A,B);
    else return get_out_tri(A,B);
}
double get_area(Point A,Point B)
{
    if(on_line(A,B,O)) return 0;
    Vector v1=A-O,v2=B-O;
    double len11=Length(v1),len22=Length(v2);
    int len1=dcmp(len11-R);
    int len2=dcmp(len22-R);
    if(len1<=0&&len2<=0)
    {
        double ret=Cross(v1,v2)/2;
        return ret;
    }
    if((len1<=0&&len2>0)||(len1>0&&len2<=0)) return get_in_out_tri(A,B);
    if(len1>0&&len2>0)
    {
        Vector vab=B-A,vao=v1*-1;
        double d=fabs(Cross(vao,vab)/Length(vab));
        if(dcmp(d-R)>=0)
        {
            double tmp=get_sector_area(v1,v2,R);
            double cross=Cross(v1,v2);
            if(cross*tmp<0) tmp*=-1.0;
            return tmp;
        }
        else
        {
            Point C,D;
            get_line_intersection(A,B,C,D);
            if(((C.x<A.x&&C.x<B.x)||(C.x>B.x&&C.x>A.x)))
            {
                double cross=Cross(v1,v2);
                double tmp=get_sector_area(v1,v2,R);
                if(tmp*cross<0) tmp*=-1.0;
                return tmp;
            }
            double sum=get_in_out_tri(A,C)+get_in_out_tri(D,B);
            sum+=Cross(C-O,D-O)/2;
            return sum;
        }
    }
    cout<<"Error!"<<endl; // default
    return INT_MIN/2;
}
int main()
{
    freopen("kao.in","r",stdin);
    freopen("kao.out","w",stdout);
    cin>>n>>R;
    double area=0.0;
    Point org;
    scanf("%lf%lf",&org.x,&org.y);
    Point last=org;
    for(int i=1;i<n;i++)
    {
        Point now;
        scanf("%lf%lf",&now.x,&now.y);
        area+=get_area(last,now);
        last=now;
    }
    area+=get_area(last,org);
    if(dcmp(area)==0) area=0.0;
    printf("%.7lf\n",area);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值