hdu 1154
2015-09-19 21:47
323 查看
给出两个点所在直线 然后求出直线和多边形的交线长度
先求出直线和多边形的交点,然后对线段进行排序,肯定是直线上的点。
然后求出相邻两点间的中间点 ,假如中间点在多边形内,那么这个线段就在多边形内。
然后计算这个长度即可
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <algorithm> using namespace std; const double eps=1e-8; const int maxn=1e3+5; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y) {} }; typedef Point VC; VC operator +(VC A,VC B){return VC(A.x+B.x,A.y+B.y);} VC operator -(VC A,VC B) {return VC(A.x-B.x,A.y-B.y);} bool operator < (const Point& a,const Point& b) {return a.x<b.x||(a.x==b.x&&a.x<b.y);} int dcmp(double x){return (fabs(x)<eps)?0:(x<0?-1:1);} bool operator == (const Point& a,const Point& b){return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;} double Dot(VC A,VC B) {return A.x*B.x+A.y*B.y;} double Length(VC A) {return sqrt(Dot(A,A));} double Cross(VC A,VC B){return A.x*B.y-A.y*B.x;} int cmp(Point a, Point b)///毁一生啊 { if(dcmp(a.x - b.x)==0) return a.y < b.y; return a.x < b.x; } double cross(Point o,Point a,Point b) { return (a.x-o.x)*(b.y-o.y) - (b.x-o.x)*(a.y-o.y);} /* 前提假设a、b、x共线 返回: x在seg(a,b)内:-1 x在seg(a,b)上:0 x在seg(a,b)外:1 */ int btw(Point x, Point a, Point b) { return dcmp(Dot(a-x, b-x)); } ///判断点p在线段a1a2上,共线+逆向 有错 好像是直线 bool OnSegment(Point p,Point a1,Point a2)///含端点 矢量夹角差距<=90 为正 { if(p==a1||p==a2) return 1; return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;///重合点也算 } /** 和segCross(...)类似 只是ab为直线,cd为线段 */ int segLineCross(Point a, Point b, Point c, Point d, Point &p) { double s1, s2; int d1, d2; d1 = dcmp(s1=Cross(c-a,b-a)); d2 = dcmp(s2=Cross(d-a,b-a)); if((d1^d2)==-2) { p.x = (c.x*s2-d.x*s1)/(s2-s1); p.y = (c.y*s2-d.y*s1)/(s2-s1); return 1; } if(d1==0 || d2==0) return 2; return 0; } /** * 判断点p是否在任意多边形p[] 其中点按找顺时针 输入中 * 0外,1内,2边上 */ int PointInPolygon(Point cp,Point p[],int n) { int k,d1,d2,wn=0; p =p[0]; for(int i=0;i<n;i++) { if(OnSegment(cp,p[i],p[i+1])) return 2; k=dcmp(Cross(p[i+1]-p[i],cp-p[i])); d1=dcmp(p[i+0].y-cp.y); d2=dcmp(p[i+1].y-cp.y); if(k>0&&d1<=0&&d2>0)wn++; if(k<0&&d2<=0&&d1>0)wn--; } return wn!=0; } void pri(Point p[],int n) { printf("-->%d\n",n); for(int i=0;i<n;i++) printf("%f %f\n",p[i].x,p[i].y); } double cal(Point p1,Point p2,Point p[],int n) { Point pointset[10*maxn]; int len=0; p =p[0]; for(int i=0;i<n;i++) { Point ans; int k=segLineCross(p1,p2,p[i],p[i+1],ans); if(k==1) pointset[len++]=ans; if(k==2) { //printf("=====\n"); if(dcmp(cross(p[i],p1,p2))==0) pointset[len++]=p[i]; } } len=unique(pointset,pointset+len)-pointset; sort(pointset,len+pointset,cmp);///少了 //pri(pointset,len); double sum=0; for(int i=0;i<len-1;i++) { Point mid=Point((pointset[i].x+pointset[i+1].x)/2,(pointset[i].y+pointset[i+1].y)/2); if(PointInPolygon(mid,p,n)) sum+=Length(pointset[i]-pointset[i+1]); } return sum; } int main() { int n,m; Point p[maxn]; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; for(int i=0;i<n;i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } for(int i=0;i<m;i++) { Point a,b; scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); printf("%.3f\n",cal(a,b,p,n)); } } return 0; }
先求出直线和多边形的交点,然后对线段进行排序,肯定是直线上的点。
然后求出相邻两点间的中间点 ,假如中间点在多边形内,那么这个线段就在多边形内。
然后计算这个长度即可
相关文章推荐
- 常用类demo--【J2SE】
- aps.net session全面介绍(生命周期,超时时间)
- 《Machine Learning -- Andrew Ng》之 Overfitting
- 百度网盘4.1.0汇编修改删除文件时的对话框
- Learn-OpenGL基础书籍推荐
- test5.11
- jsp用过滤器解决中文乱码
- 某经典截图软件的爆破方法:
- 初入职场之心态和为人处世
- 初入职场必备技能
- Android Intent分享文件|分享图片|分享文字|功能的实现
- DELL服务器引导光盘下载
- 伪代码的写法(转载)
- The Suspects(并查集求节点数)
- Mac下配置OpenSSL
- System Mechanic汇编破解笔记
- Java 多线程同步的五种方法
- 剑指offer-对称的二叉树
- 安卓中常用的shape,selector,layer-list
- 根据文字内容和设定maxSize计算文字的width、height