半平面交 求多边形内核问题
2015-07-22 22:33
162 查看
多边形的内核可以理解为:
在多边形找到一块区域,使这块区域中的任何一个点都能够和多边形上的任意一点相连而不受到多边形上其他边的阻挡
也可以抽象的理解为在这块区域中任意位置放一个旋转摄像头,这个摄像头可以监控多边形的整个区域
多边形内核是否存在可以利用半平面交的思想去求解
将多边形上的每一条边作为逆时针顺序的射线,在每一条线左侧的就是可行区域
譬如:
比如这个多边形
View Code
在多边形找到一块区域,使这块区域中的任何一个点都能够和多边形上的任意一点相连而不受到多边形上其他边的阻挡
也可以抽象的理解为在这块区域中任意位置放一个旋转摄像头,这个摄像头可以监控多边形的整个区域
多边形内核是否存在可以利用半平面交的思想去求解
将多边形上的每一条边作为逆时针顺序的射线,在每一条线左侧的就是可行区域
譬如:
比如这个多边形
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; #define N 1505 #define ll long long #define eps 1e-9 int dcmp(double x) { if(fabs(x)<eps) return 0; else return x<0?-1:1; } struct Point{ double x,y; Point(double x=0 , double y=0):x(x),y(y){} }p , poly ; typedef Point Vector; struct Line{ Point p; Vector v; double ang; Line(){} Line(Point p , Vector v):p(p),v(v){ang = atan2(v.y , v.x);} bool operator<(const Line &m) const{ return dcmp(ang-m.ang)<0; } }line ; Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);} Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);} Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);} Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);} double Cross(Vector a , Vector b){return a.x*b.y-a.y*b.x;} bool OnLeft(Line L , Point P) { return dcmp(Cross(L.v , P-L.p))>=0; } Point GetIntersection(Line a , Line b) { Vector u = a.p-b.p; double t = Cross(b.v , u)/Cross(a.v , b.v); return a.p+a.v*t; } int HalfplaneIntersection(Line *L , int n , Point *poly) { sort(L , L+n); int first , last; Point *p = new Point ; Line *q = new Line ; q[first=last=0] = L[0]; for(int i=1 ; i<n ; i++){ while(first<last && !OnLeft(L[i] , p[last-1])) last--; while(first<last && !OnLeft(L[i] , p[first])) first++; q[++last] = L[i]; if(fabs(Cross(q[last].v , q[last-1].v))<eps){ last--; if(OnLeft(q[last] , L[i].p)) q[last]=L[i]; } if(first < last) p[last-1] = GetIntersection(q[last-1] , q[last]); } while(first<last && !OnLeft(q[first] , p[last-1])) last--; if(last-first<=1) return 0; p[last] = GetIntersection(q[last] , q[first]); int m=0; for(int i=first ; i<=last ; i++) poly[m++] = p[i]; return m; } double calArea(Point *p , int n) { if(!n) return 0; double ret = 0; for(int i=2 ; i<n ; i++){ ret += Cross(p[i-1]-p[0],p[i]-p[0]); } return ret/2; } int main() { // freopen("in.txt" , "r" , stdin); int T , n ; scanf("%d" , &T); while(T--) { scanf("%d" , &n); for(int i=0 ; i<n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y); p = p[0]; for(int i=0 ; i<n ; i++) line[i] = Line(p[i] , p[i]-p[i+1]); int cnt = HalfplaneIntersection(line , n , poly); printf("%.2f\n" , calArea(poly , cnt)); } }
View Code
相关文章推荐
- 每天一个linux命令(8):cp 命令
- Javaweb传参乱码
- WPF使用DEV之TreeListControl---父子节点关系
- linux下动态库的编写和调用
- 如何计算一个结构体所占内存空间大小
- 基于51单片机的NRF24L01的使用笔记
- TCP/UDP简易通信
- 导入java项目时出现红色叹号问题的解决
- 搭建基于PHP的www服务器
- WorldWind源码剖析系列:挂件类Widgets
- Gartner:2015年SIEM(安全信息与事件管理)市场分析
- JS_XML
- 流、文件、目录操作
- linux安装
- ECShop 调用自定义广告
- WorldWind源码剖析系列:图层管理器按钮类LayerManagerButton和菜单条类MenuBar
- 【观澜电脑】--维修电脑原创文章大汇总
- U-BOOT的两个阶段启动过程与第二阶段的board_init_f和board_init_r
- 04-树5. File Transfer (25)
- java 设计模式 动态代理