zoukankan      html  css  js  c++  java
  • 计算几何HPI

    This article is made by Jason-Cow.
    Welcome to reprint.
    But please post the article's address.

     

    在线笛卡尔坐标系绘图网站

    核心思想

      1.积角排序

      2.双端队列维护半平面交

    木有啦~~

     1 int HPI(L*l,int n,D*ans){
     2   int head,tail,m=0;D*P=new D[n];L*q=new L[n];
     3   sort(l+1,l+n+1),q[head=tail=0]=l[1];
     4   for(int i=2;i<=n;i++){
     5     while(head<tail && !Left(l[i],P[tail-1]))tail--;
     6     while(head<tail && !Left(l[i],P[head]))  head++;
     7     q[++tail]=l[i];//双端队列<( ̄3 ̄)>
     8     if(fabs(Cross(q[tail].v,q[tail-1].v))<eps){
     9       tail--;//判断Cross(q[tail].v,q[tail-1].v)==0♪(^∇^*)
    10       if(Left(q[tail],l[i].P))q[tail]=l[i];
    11     }
    12     if(head<tail)P[tail-1]=Intersect(q[tail-1],q[tail]);
    13   }
    14   while(head<tail && !Left(q[head],P[tail-1]))tail--;
    15   if(tail-head<=1)return 0;
    16   P[tail]=Intersect(q[tail],q[head]);
    17   for(int i=head;i<=tail;i++)ans[++m]=P[i];
    18   return m;
    19 }

    多边形相关

    db Area(D*R,int n){
        db S=0.0;
        for(int i=1;i<n;i++)S+=Cross(R[i]-R[1],R[i+1]-R[1]);
        return S/2;
    }
    
    db Length(D*R,int n){
        db C=0.0;
        for(int i=2;i<=n;i++)C+=Dis(R[i],R[i-1]);
        return C+Dis(R[n],R[1]);
    }

    主程序

     1 L l[500];D A[500];
     2 int main(){
     3   for(int n;scanf("%d",&n)&&n;){
     4     for(int i=1;i<=n;i++){
     5       db a,b,c,d;
     6       scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
     7       D A(a,b),B(c,d);
     8       l[i]=L(A,B-A);
     9     }
    10     int m=HPI(l,n,A);
    11     cout<<"m="<<m<<endl;
    12     for(int i=1;i<=m;i++)printf("(%.4lf,%.4lf)\n",A[i].x,A[i].y);
    13     printf("S=%.2lf\n",Area(A,m));
    14     printf("C=%.2lf\n",Length(A,m));
    15   }
    16   return 0;
    17 }

    读入,如图(橙、红、蓝、绿)

    4
    2 1 1 2
    1 2 0 1
    1 0 2 1
    0 1 1 0

    输出

    m=4
    (0.0000,1.0000)
    (1.0000,0.0000)
    (2.0000,1.0000)
    (1.0000,2.0000)
    S=2.00
    C=5.66

    读入

    6
    1 2 0 1
    0 1.8 0.8 0.2
    0 1 1 0
    1 0 2 1
    3 0 1 2
    0.6 1.6 0 0.7

    输出

    m=6
    (0.6000,1.6000)
    (0.3143,1.1714)
    (0.8000,0.2000)
    (1.0000,0.0000)
    (2.0000,1.0000)
    (1.0000,2.0000)
    S=1.76
    C=5.28

    完整代码

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <vector>
      7 #include <cmath>
      8 #include <queue>
      9 #include <map>
     10 #include <set>
     11 using namespace std;
     12 #define sqr(x) ((x)*(x))
     13 #define RG register
     14 #define op operator
     15 #define IL inline
     16 typedef double db;
     17 typedef bool bl;
     18 const db pi=acos(-1.0),eps=1e-10;
     19 struct D{
     20   db x,y;
     21   D(db x=0.0,db y=0.0):x(x),y(y){}
     22 };
     23 typedef D V;//不知道什么鬼,emacs 将 operator -> op 会萎掉  对!不!齐!
     24 bl operator<(D A,D B){return A.x<B.x||(A.x==B.x&&A.y<B.y);}
     25 V operator+(V A,V B){return V(A.x+B.x,A.y+B.y);}
     26 V operator-(V A,V B){return V(A.x-B.x,A.y-B.y);}
     27 V operator*(V A,db N){return V(A.x*N,A.y*N);}
     28 V operator/(V A,db N){return V(A.x/N,A.y/N);}
     29 
     30 db Ang(db x){return(x*180.0/pi);}
     31 db Rad(db x){return(x*pi/180.0);}
     32 V Rotate(V A,db a){return V(A.x*cos(a)-A.y*sin(a),A.x*sin(a)+A.y*cos(a));}
     33 db Dis(D A,D B){return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));}
     34 db Cross(V A,V B){return A.x*B.y-A.y*B.x;}
     35 
     36 db Area(D*R,int n){
     37     db S=0.0;
     38     for(int i=1;i<n;i++)S+=Cross(R[i]-R[1],R[i+1]-R[1]);
     39     return S/2;
     40 }
     41 
     42 db Length(D*R,int n){
     43     db C=0.0;
     44     for(int i=2;i<=n;i++)C+=Dis(R[i],R[i-1]);
     45     return C+Dis(R[n],R[1]);
     46 }
     47 
     48 struct L{
     49   D P,v;
     50   db a;
     51   L(){}
     52   L(D P,V v):P(P),v(v){a=atan2(v.y,v.x);}
     53   bool operator<(const L x)const{return a<x.a;}
     54 };
     55 
     56 D Intersect(L a,L b){
     57   V u=a.P-b.P;
     58   return a.P+a.v*(Cross(b.v,u)/Cross(a.v,b.v));
     59 }
     60 
     61 bool Left(L l,D A){
     62   return Cross(l.v,A-l.P)>0;
     63 }
     64 
     65 int HPI(L*l,int n,D*ans){
     66   int head,tail,m=0;D*P=new D[n];L*q=new L[n];
     67   sort(l+1,l+n+1),q[head=tail=0]=l[1];
     68   for(int i=2;i<=n;i++){
     69     while(head<tail && !Left(l[i],P[tail-1]))tail--;
     70     while(head<tail && !Left(l[i],P[head]))  head++;
     71     q[++tail]=l[i];//双端队列<( ̄3 ̄)>
     72     if(fabs(Cross(q[tail].v,q[tail-1].v))<eps){
     73       tail--;//判断Cross(q[tail].v,q[tail-1].v)==0♪(^∇^*)
     74       if(Left(q[tail],l[i].P))q[tail]=l[i];
     75     }
     76     if(head<tail)P[tail-1]=Intersect(q[tail-1],q[tail]);
     77   }
     78   while(head<tail && !Left(q[head],P[tail-1]))tail--;
     79   if(tail-head<=1)return 0;
     80   P[tail]=Intersect(q[tail],q[head]);
     81   for(int i=head;i<=tail;i++)ans[++m]=P[i];
     82   return m;
     83 }
     84 
     85 L l[500];
     86 D A[500];
     87 int main(){
     88   cout<<4*sqrt(2)<<endl;
     89   for(int n;scanf("%d",&n)&&n;){
     90     for(int i=1;i<=n;i++){
     91       db a,b,c,d;
     92       scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
     93       D A(a,b),B(c,d);
     94       l[i]=L(A,B-A);
     95     }
     96     int m=HPI(l,n,A);
     97     cout<<"m="<<m<<endl;for(int i=1;i<=m;i++)printf("(%.4lf,%.4lf)\n",A[i].x,A[i].y);
     98     printf("S=%.2lf\n",Area(A,m));
     99     printf("C=%.2lf\n",Length(A,m));
    100   }
    101   return 0;
    102 }
    HPI
    ~~Jason_liu O(∩_∩)O
  • 相关阅读:
    vs2005视频教程 之 文件管理系统(一)视频教程[视频]
    空间不够了,郁闷!
    一些web开发中常用的、做成cs文件的js代码 搜刮来的
    电子科大实训感想
    深入继承 抽象类和接口
    vs2005视频教程 之 自定义服务器控件(下) [视频]
    vs2005视频教程 之 文件管理系统(二)视频教程[视频]
    功能超强的用户管理系统数据库结构
    vs2005视频教程 之 抽象类和接口 三 [视频]
    vs2005入门 .Net2.0视频教程 之 创建读取文本文件[视频]
  • 原文地址:https://www.cnblogs.com/JasonCow/p/6617752.html
Copyright © 2011-2022 走看看