转载acm几何基础(2)
判断两条线段是否相交:
矢量
如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果有向线段p1p2的起点p1在坐标的原点,则可以把它称为矢量p2
矢量的加减
设二维矢量 P = (x1, y1), Q = (x2, y2),则P + Q = (x1 + x2, y1 + y2), P - Q = (x1 - x2, y1 - y2),且有P + Q = Q + P, P - Q = -(Q - P)
矢量叉积
设矢量 P = (x1, y1), Q = (x2, y2),则P * Q = x1 * y2 - x2 * y1;其结果是一个由(0, 0), P, Q, P + Q所组成的平行四边形的 带符号的面积,P * Q = -(Q * P), P * (- Q) = -(P * Q)
叉积的一个非常重要的性质是可以通过它的符号来判断两矢量相互之间的顺逆时针关系:
若 P * Q > 0,则 P 在 Q的顺时针方向
若 P * Q < 0, 则 P 在 Q的逆时针方向
若 P * Q = 0,则 P 与 Q共线,但不确定P, Q的方向是否相同
折线段的拐向判断
如图,假设有折线段p0p1p2,要确定p1p2相对于p0p1是向左拐还是向右拐,可以通过计算(p2 - p0)*(p1 - p0)的符号来确定折线的拐向(点p2 - p0实际上就是向量p2,但这里要注意线段和矢量的区别)
判断点是否在线段上
设点 Q = (x, y), P1 = (x1, y1), P2 = (x2, y2),若(Q - P1)*(P2 - P1) = 0且min(x1, x2) <= x <= max(x1, x2) && min(y1, y2) <= y <= max(y1, y2),则点Q在线段P1P2上
判断两线段是否相交
1)快速排斥试验
设以线段 P1P2 为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,若R、T不相交,则两线段不可能相交
假设 P1 = (x1, y1), P2 = (x2, y2), Q1 = (x3, y3), Q2 = (x4, y4),设矩形R的x 坐标的最小边界为minRX = min(x1, x2),以此类推,将矩形表示为R = (minRX, minRY, maxRX, maxRY)的形式,若两矩形相交,则相交的部分构成了一个新的矩形F,如图所示,我们可以知道F的minFX = max(minRX, minTX), minFY = max(minRY, minTY), maxFX = min(maxRX, maxTX), maxFY = min(maxRY, maxTX),得到F的各个值之后,只要判断矩形F是否成立就知道R和T 到底有没有相交了,若minFX > maxFX或minFY > maxFy则F无法构成,RT不相交,否则RT相交
2)跨立试验
若 P1P2 跨立 Q1Q2,则 P1,P2 分别在 Q1Q2 所在直线的两端,则有(P1 - Q1)*(Q2 - Q1) * (Q2 - Q1)*(P2 - Q1) > 0,当(P1 - Q1)*(Q2 - Q1) = 0 时,说明(P1 - Q1)与(Q2 - Q1)共线,但由于已经经过快速排斥试验,所以Q1必为P1P2与 Q1Q2的交点,依然满足线段相交的条件,则跨立试验可改为:
当 (P1 - Q1)*(Q2 - Q1) * (Q2 - Q1)*(P2 - Q1) >= 0,则P1P2跨立Q1Q2,当Q1Q2也跨立P1P2的时候,则P1P2相交
(注意式子中被隔开的*代表两个叉积的值的相乘,而另外的两个*则代表计算矢量叉积)
判断线段与直线是否相交:
首先在直线上随便取两点做为线段l1;
再与线段L2进行判断,因为是直线所以现在只需判断L2是否跨立l1就行了。
代码如下:
bool inter_line(line l1,line l2)//判断直线与线段是否相交
{
return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0;
}
代码实现:
再这之前可以先去学下,C++的运算符重载部分
运算符重载详解 http://blog.chinaunix.NET/uid-21411227-id-1826759.html
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-8;
const double PI=acos(-1.0);
int sgn(double x)
{
if(fabs(x)<eps) return 0;
if(x < 0) return -1;
else return 1;
}
struct point
{
double x,y;
point(){}
point (double _x,double _y)
{
x=_x,y=_y;
}
point operator -(const point &b)const
{
return point(x-b.x,y-b.y);
}
point operator +(const point &b)const
{
return point (x+b.x,y+b.y);
}
double operator ^(const point &b)const //叉积
{
return x*b.y-y*b.x;
}
double operator *(const point &b)const //点积
{
return x*b.x+y*b.y;
}
void transxy(double B) //绕原点旋转角度B(弧度值),后的x,y
{
double tx=x,ty=y;
x= tx*cos(B) - ty*sin(B);
y= tx*sin(B) + ty*cos(B);
}
};
struct line//线
{
point s,e;
line(){}
line(point _s,point _e)
{
s=_s,e=_e;
}
};
double dist(point a,point b)//两点间距离
{
return sqrt((a-b)*(a-b));
}
bool inter(line l1,line l2)//判断线段相交
{
return max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0&&
sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e))<=0;
}
bool inter_line(line l1,line l2)//判断直线与线段是否相交
{
return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0;
}
int main()
{
double ax,ay,bx,by,cx,cy,dx,dy;
while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy)!=EOF)//分别输入两条线段的首尾端点
{
point k1(ax,ay);
point k2(bx,by);
point k3(cx,cy);
point k4(dx,dy);
line l1(k1,k2);
line l2(k3,k4);
if(inter(l1,l2))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
转载acm几何基础(2)的更多相关文章
- [转载]ACM(访问控制模型),Security Identifiers(SID),Security Descriptors(安全描述符),ACL(访问控制列表),Access Tokens(访问令牌)
对于<windows核心编程>中的只言片语无法驱散心中的疑惑.就让MSDN中的解释给我们一盏明灯吧.如果要很详细的介绍,还是到MSDN仔细的看吧,我只是大体用容易理解的语言描述一下. wi ...
- 转载 ACM训练计划
leetcode代码 利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode. ...
- [转载]ACM搜索算法总结(总结)
原文地址:ACM搜索算法总结(总结)作者:GreenHand 搜索是ACM竞赛中的常见算法,本文的主要内容就是分析它的 特点,以及在实际问题中如何合理的选择搜索方法,提高效率.文章的第一部分首先分析了 ...
- 转载- ACM常见的各种说法
from : http://blog.csdn.net/qq_15015129/article/details/52738184 1.答案错误 —— wrong answer 就是最常见的.这个没办法 ...
- 【转载】 从ACM会议看中国大陆计算机科学与国外的差距
ps: 这是一篇06年的文章,与今日的国内计算机行业学术圈环境简直是天翻地覆,很不错的history,值得mark下,今日的cs学术发展十号是坏不发表意见,但是history是值得对比,借鉴,思考 ...
- ACM之路(转载)
转载自:https://www.cnblogs.com/tianjintou/p/4139416.html 要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来. 适合自己的才是好的,有的人 ...
- 【转载】ACM总结
转自亲学长的总结 声明:本文是写给弱校ACM新手的一点总结,受自身水平和眼界所限,难免会有一些个人主观色彩,希望大牛指正 感谢@Wackysoft .@哇晴天 . @ 一切皆有可能1 的指教,现根据这 ...
- 北大ACM题库习题分类与简介(转载)
在百度文库上找到的,不知是哪位大牛整理的,真的很不错! zz题 目分类 Posted by fishhead at 2007-01-13 12:44:58.0 -------------------- ...
- 计算几何基础——矢量和叉积 && 叉积、线段相交判断、凸包(转载)
转载自 http://blog.csdn.net/william001zs/article/details/6213485 矢量 如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果 ...
随机推荐
- 7.2 java 类的定义和使用
/* * 类的定义: * 类是用来描述现实世界的事物的 * * 事物: * 属性 事物的描述信息 * 行为 事物能够做什么 * * 类是如何和事物进行对应的呢? * 类: * 成员变量 * 成员方法 ...
- 类 文件 右下角呈现 红色小圆圈,里面有一个J 标记
intellj(idea) 项目中类 文件 右下角呈现 红色小圆圈,里面有一个J 标记,表明此为 未设置为源文件,没有编译,本来应该是属于源文件的,结果现在没有被标记为源文件,也就没法编译了.
- list 的sublist 隐藏 bug
list A = new list(); list a = A.sublist(0,3); 假如对a进行增加或者删除 会 同样改变A里的值,即其实a仅仅是A的一个试图,而不是一个新的list 对象,所 ...
- Java中常用的七个阻塞队列介绍第一篇
Java中常用的七个阻塞队列介绍第一篇 在上一篇我们对Java中的队列分类做了简单的介绍.本文咱们主要来聊聊阻塞队列中的七个常用子类.这七个阻塞队列的学习步骤:先看源码,分析完源码之后,我们再来对每个 ...
- stand up meeting 12-2
今天因为各位组员组里项目原因没有集中在一起进行stand up meeting.但是士杰和天赋国庆分别对项目进度和前后端的结合进行的沟通. 针对后端部分,天赋完成了GetRankingData API ...
- Alpha Release Note 12/15/2015
内容提要: ******Personal Photo Experience可供您存放所有的私人照片,系统会自动整理内容,您可以借助搜索功能快速找到所需图片,同时过滤重复图片和低质量图片,给您全新的搜索 ...
- D - A Game with Traps-- codeforces 1260D A
题目大意: 一共有m个士兵,k个陷阱,时间为t,一个首领,这个首领需要在t时间内尽可能多的将士兵带到boos的面前, 第二行是每个士兵的灵敏度. 紧接着是k个陷阱,每个陷阱有l,,r,,d组成,l代表 ...
- Cyclic Nacklace 杭电3746
CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, ...
- Jwt认识与攻击
今天看到2018强网杯的题目,因此总结一下. Json Web Token Json Web Token简称jwt 那么怎么样可以让HTTP记住曾经发生的事情呢? 这里的选择可以很多:cookie,s ...
- ES6中的let关键字,有什么用呢?
来吧,开始本节的学习! ES6 给开发者带来很多令人激动的特性,其中let关键字就是其中之一. 那么,let关键字是什么东西? let 的用途 我们回想一下,我们平时在写代码的时候,用var来声明一个 ...