半平面交模板,多边形内核面积模板

判断内核

//poj3335  半平面交 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
 
const double eps = 1e-8;
const int maxn = 105;
 
int dq[maxn], top, bot, pn, order[maxn], ln;
struct Point {
    double x, y;
} p[maxn];
 
struct Line {
    Point a, b;
    double angle;
} l[maxn];
 
int dblcmp(double k) {
    if (fabs(k) < eps) return 0;
    return k > 0 ? 1 : -1;
}
 
double multi(Point p0, Point p1, Point p2) {
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
 
bool cmp(int u, int v) {
    int d = dblcmp(l[u].angle-l[v].angle);
    if (!d) return dblcmp(multi(l[u].a, l[v].a, l[v].b)) < 0;
    return d < 0;
}
 
void getIntersect(Line l1, Line l2, Point& p) {
    double dot1,dot2;
    dot1 = multi(l2.a, l1.b, l1.a);
    dot2 = multi(l1.b, l2.b, l1.a);
    p.x = (l2.a.x * dot2 + l2.b.x * dot1) / (dot2 + dot1);
    p.y = (l2.a.y * dot2 + l2.b.y * dot1) / (dot2 + dot1);
}
 
bool judge(Line l0, Line l1, Line l2) {
    Point p;
    getIntersect(l1, l2, p);
    return dblcmp(multi(p, l0.a, l0.b)) > 0;
}
 
void addLine(double x1, double y1, double x2, double y2) {
    l[ln].a.x = x1; l[ln].a.y = y1;
    l[ln].b.x = x2; l[ln].b.y = y2;
    l[ln].angle = atan2(y2-y1, x2-x1);
    order[ln] = ln;
    ln++;
}
 
void halfPlaneIntersection() {
    int i, j;
    sort(order, order+ln, cmp);
    for (i = 1, j = 0; i < ln; i++)
        if (dblcmp(l[order[i]].angle-l[order[j]].angle) > 0)
            order[++j] = order[i];
    ln = j + 1;
    dq[0] = order[0];
    dq[1] = order[1];
    bot = 0;
    top = 1;
    for (i = 2; i < ln; i++) {
        while (bot < top && judge(l[order[i]], l[dq[top-1]], l[dq[top]])) top--;
        while (bot < top && judge(l[order[i]], l[dq[bot+1]], l[dq[bot]])) bot++;
        dq[++top] = order[i];
    }
    while (bot < top && judge(l[dq[bot]], l[dq[top-1]], l[dq[top]])) top--;
    while (bot < top && judge(l[dq[top]], l[dq[bot+1]], l[dq[bot]])) bot++;
}
 
bool isThereACore() {
    if (top-bot > 1) return true;
    return false;
}
int main()
{
    int t, i;
 
    scanf ("%d", &t);
    while (t--) {
        scanf ("%d", &pn);
        for (i = 0; i < pn; i++)
            scanf ("%lf%lf", &p[i].x, &p[i].y);
        //有方向 顺时针
        for (ln = i = 0; i < pn-1; i++)
            addLine(p[i].x, p[i].y, p[i+1].x, p[i+1].y);
        addLine(p[i].x, p[i].y, p[0].x, p[0].y);
        halfPlaneIntersection();
        if (isThereACore()) printf ("YES\n");
        else printf ("NO\n");
    }
    return 0;
}

 

求凸多边形内核面积

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <deque>

using namespace std;
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    db getP()const { return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
};
db cross(point k1,point k2){ return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
db rad(point k1,point k2){ return atan2(cross(k1,k2),dot(k1,k2));}
int compareangle(point k1,point k2){
    return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>0);
}
point getLL(point k1,point k2,point k3,point k4){
    db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
    return (k1*w2+k2*w1)/(w1+w2);
}
struct line{
    point p[2];
    line(point k1,point k2){p[0]=k1;p[1]=k2;}
    point &operator[](int k){ return p[k];}
    int include(point k){ return sign(cross(p[1]-p[0],k-p[0])>0);}
    point dir(){ return p[1]-p[0];}
};
point getLL(line k1,line k2){
    return getLL(k1[0],k1[1],k2[0],k2[1]);
}
int parallel(line k1,line k2){ return sign(cross(k1.dir(),k2.dir()))==0;}
int sameDir(line k1,line k2){
    return parallel(k1,k2)&&sign(dot(k1.dir(),k2.dir()))==1;
}
int operator <(line k1,line k2){
    if(sameDir(k1,k2))return k2.include(k1[0]);
    return compareangle(k1.dir(),k2.dir());
}
int checkpos(line k1,line k2,line k3){ return k3.include(getLL(k1,k2));}
vector<line> getHL(vector<line> &L){
    sort(L.begin(),L.end());deque<line> q;
    for(int i=0;i<L.size();i++){
        if(i&&sameDir(L[i],L[i-1]))continue;
        while (q.size()>1&&!checkpos(q[q.size()-2],q[q.size()-1],L[i]))q.pop_back();
        while (q.size()>1&&!checkpos(q[1],q[0],L[i]))q.pop_front();
        q.push_back(L[i]);
    }
    while (q.size()>2&&!checkpos(q[q.size()-2],q[q.size()-1],q[0]))q.pop_back();
    while (q.size()>2&&!checkpos(q[1],q[0],q[q.size()-1]))q.pop_front();
    vector<line> ans;for(int i=0;i<q.size();i++)ans.push_back(q[i]);
    return ans;
}
int t,n;
point p[1551];
bool cw(){//时针
    db s=0;
    for(int i=1;i<n-1;i++){
        s+=cross(p[i]-p[0],p[i+1]-p[0]);
    }
    return s>0;
}
vector<line>l;
int main(){
    scanf("%d",&t);
    while (t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        if(!cw())reverse(p,p+n);
        for(int i=0;i<n;i++){
            l.push_back(line(p[i],p[(i+1)%n]));
        }
        l=getHL(l);
        if(l.size()<3){
            printf("0.00\n");
        } else{
            vector<point> a;
            for(int i=0;i<l.size();i++){
                a.push_back(getLL(l[i],l[(i+1)%l.size()]));
            }
            db ans = 0;
            for(int i=1;i<a.size()-1;i++)
                ans+=cross(a[i]-a[0],a[i+1]-a[0]);
            ans/=2;
            printf("%.2f\n",ans);
        }
        l.clear();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值