逆时针方向

给定3个点,构造出从同一起点的两条线段,判断两条线段的关系
这个关系包括逆时针、顺时针、重合,其中重合又包括点在线段正上方、正下方情况!

图示

图中都是以p0为源点,p0p1为基准线,判断p0p2相对p0p1的位置关系!

怎么只通过3个点的坐标来判断呢?

我们还是以向量的形式,运用向量的知识进行判断,需要用到向量的内积、外积知识不了解点击下方链接!

内积、外积知识

首线上面这些问题都可以归结到判断是否是逆时针方向问题!

判断逆时针

向量a、b的外积模为 |axb|=|a|x|b|sinθ,0<θ<180° sinθ>0,也就是从向量a出发逆时针旋转θ(右手螺旋定则),0<θ<180°时我们可以看出向量b在向量a的逆时针方向!

通过上述描述,我们可以运用向量的外积模,如果外积模>0,则向量b在向量a的时针方向!

判断顺时针

有了上面的铺垫,想必大家一目了然,也就是向量外积模小于0,θ>180°的时候向量b在向量a的顺时针方向!

图示

正下方

正下方情况也就是θ=180°的时候,这个时候外积|a|x|b|sinθ=0,并且正上方的θ=0°,外积也为0。

如何判断在θ=0°,是在正上方还是正下方呢?

我们引入向量的另一个知识内积,内积公式为a·b=|a|x|b|cosθ,
当θ=180°时,cosθ=-1,当θ=0°时cosθ=1,所以如果为与正下方向量的内积应该小于0!

正上方
那么位于正上方是不是内积大于0呢?

答案是否定的!!!

为什么呢?

我们看最后一种情况,点位于线段内的情况,这种情况的内积也满足θ=0°,内积>0所以无法判断是在正上方!!!

究竟如何判定呢?

其实非常简单,当位于正上方时,向量b的模是大于向量a的模的!也就是向量b长于向量a!

图示

我们只要对向量a、b进行取模比较长度即可!

点在线段上

点在线段上就非常简单,首先外积等于0,内积大于0,只要b的模小于a的模就可以满足点在线段上!

(代码中,只要不满足前4中情况就是点在线段上)

实现代码

#include <bits/stdc++.h>using namespace std;class Point
{public:double x,y;Point(double x=0,double y=0):x(x),y(y) {}//向量大小(取模)double abs(){return sqrt(norm());}//向量范数(模的平方)double norm(){return x*x+y*y;}
};typedef Point Vector;//向量内积
double dot(Vector a,Vector b)
{return a.x*b.x+a.y*b.y;
}//向量外积
double cross(Vector a,Vector b)
{return a.x*b.y-a.y*b.x;
}//逆时针方向string ccw(Point p0,Point p1,Point p2)
{Vector a(p1.x-p0.x,p1.y-p0.y);Vector b(p2.x-p0.x,p2.y-p0.y);//逆时针-->顺时针-->p2在p0正下方-->p2在p1正上方-->p2在p0,p1线段上if(cross(a,b)>0) return"逆时针方向";if(cross(a,b)<0) return "顺时针方向";if(dot(a,b)<0) return"p2在p0正下方";if(a.norm()<b.norm()) return "p2在p1正上方";return "p2在线段p0p1上";
}
int main()
{int t;int x0,y0,x1,y1;cin>>x0>>y0>>x1>>y1;cin>>t;//t组测试数据int x2,y2;while(t--){cin>>x2>>y2;Point p0(x0,y0);Point p1(x1,y1);Point p2(x2,y2);cout<<ccw(p0,p1,p2)<<endl;}return 0;
}

测试用例

输入

0 0 2 0
5
-1 1
-1 -1
-1 0
0 0
3 0

输出

逆时针
顺时针
正下方
线段中间
正下方

相交判断

有了逆时针的铺垫,判断相交就格外容易。

首先给大家列出相交的几种情况
图示一

(重合我们也算作相交)
如何把相交的判断和逆时针关联起来呢?

我们可以拿出一条线段,取出一个端点,与另一条线段构成两个向量,进而判断这两个向量的关系,再拿出另外一个点,构成两个向量判断关系!如果满足:
另一条线段的两个端点分别位于当前线段的顺时针和逆时针方向”,则两条线段相交

我们拿图中第一组例子进行图解

所以我们将判断逆时针方法改为返回值为int类型,并进行如下操作

const int Counter_ClockWise=1;//逆时针
const int ClockWise=-1;//顺时针
const int Online_Back=2;//p2在p1p0正下方
const int Online_Front=-2;//p2在p1p0正上方
const int On_Segment=0;//在线段上

如果满足ccw(p3,p4,p1)*ccw(p3,p4,p2)<0,并且ccw(p1,p2,p3)*ccw(p1,p2,p4)<0,也就是满足一个顺时针一个逆时针,则两条线段相交!

如果只满足一组可以达到同样的效果么?

也就是两条线段只拿出一条进行判断!

显然是不行的!
图示二

显然这组样例也满足,一个顺时针,一个逆时针,但是两个线段并不相交!

我们来讨论ccw()返回值为的情况

ccw返回值为0,就是3个点有一个点在线段上,所以放到判断线段相交,其中一个线段的端点在另外一个线段上(图示一第3种情况)那么这两条线段必然相交!

所以我们在ccw()<0的基础上,加上等于0

最终我们的判断代码为
(ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0)

对于一个点在正上方,一个点在正下方的情况
图示

在代码中同样设置了正上方返回-2,正下方返回2,也同样满足ccw<0

宇宙无敌之判断之线段相交完整代码

#include <bits/stdc++.h>using namespace std;
const int Counter_ClockWise=1;//逆时针
const int ClockWise=-1;//顺时针
const int Online_Back=2;//p2在p1p0正下方
const int Online_Front=-2;//p2在p1p0正上方
const int On_Segment=0;//在线段上class Point
{public:double x,y;Point(double x=0,double y=0):x(x),y(y) {}//向量大小double abs(){return sqrt(norm());}//向量范数double norm(){return x*x+y*y;}bool operator<(const Point &p) const{return x!=p.x?x<p.x:y<p.y;}bool operator==(const Point &p)const{return x-p.x<1e-10&&y-p.y<1e-10;}};typedef Point Vector;//向量内积
double dot(Vector a,Vector b)
{return a.x*b.x+a.y*b.y;
}//向量外积
double cross(Vector a,Vector b)
{return a.x*b.y-a.y*b.x;
}//逆时针方向int ccw(Point p0,Point p1,Point p2)
{Vector a(p1.x-p0.x,p1.y-p0.y);Vector b(p2.x-p0.x,p2.y-p0.y);//逆时针-->顺时针-->p2在p0正下方-->p2在p1正上方-->p2在p0,p1线段上if(cross(a,b)>0) return Counter_ClockWise;if(cross(a,b)<0) return ClockWise;if(dot(a,b)<0) return Online_Back;if(a.norm()<b.norm()) return Online_Front;return On_Segment;
}
//判断线段相交bool intersect(Point p1,Point p2,Point p3,Point p4)
{return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);}
int main()
{int t;cin>>t;//t组测试数据int x1,y1,x2,y2,x3,y3,x4,y4;while(t--){cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;Point p1(x1,y1);Point p2(x2,y2);Point p3(x3,y3);Point p4(x4,y4);cout<<intersect(p1,p2,p3,p4)<<endl;}return 0;
}

测试用例

输入

3
0 0 3 0 1 1 2 -1
0 0 3 0 3 1 3 -1
0 0 3 0 3 -2 5 0

输出

1
1
0

线段的逆时针方向(顺时针、正上方、正下方、线段上)、相交判断(图解)相关推荐

  1. 将maximo工具栏图标放置在正上方

    maximo7.6工具栏的图标在左侧,要想将工具栏移到正上方,在系统属性mxe.webclient.showOnToolbar中添加事件名称,以逗号进行分隔.

  2. 各种体+把Σ的上标打到正上方+箭头加东西+矩阵+圆圈+向量各种箭头+头上加一点

    文章目录 最花的花体 各种体 把Σ的上标打到正上方 箭头丧面加东西 latex输入矩阵 圆圈 加向量 头上加一点 我感觉啊csdn的编辑器已经暗自导入这些包了! 符号找不到点这里哦 最花的花体 \us ...

  3. R语言ggplot2可视化散点图、并以与y=0为界绘制基于散点包围的多边形(ploygon)、对于y=0坐标轴的上方和下方的多边形分别使用不同的颜色进行填充

    R语言ggplot2可视化散点图.并以与y=0为界绘制基于散点包围的多边形(ploygon).对于y=0坐标轴的上方和下方的多边形分别使用不同的颜色进行填充 目录

  4. 使用Pitstop批量删除pdf中书页上方和下方的文字

    在网上下载的pdf教材,很多都被公众号或者什么组织打上了水印以及在页面上方和下方(页眉页脚)处添加一些广告信息,有些甚至会干扰阅读,这篇文章就是处理页眉页脚处的广告信息的.博主也是在试了很多种方法后才 ...

  5. 什么样呢软件能测试你的车歪不歪,如何判断车身正不正,车斜怎么调整方向

    在驾考的时候,通常是科目二才比较严格地要求车身要摆正,而科目三很少会说车身正不正的问题.而在日常行驶中,如何判断车身正不正的方法是三点一线法,用眼光和道路远方去判断和调整车身. 如何判断车身正不正 首 ...

  6. 车内看车头正不正技巧_车内看车头正不正技巧,判断车头正不正看雨刷

    对于不少初学者来说,开车难在如何在车内看车头正不正,有些教练会建议看雨刷来判断车头正不正,这能不能行呢?下面我们来看一下判断车头正不正技巧. 看雨刷来判断车头正不正没有问题,通过雨刷与路面标识作为对比 ...

  7. zoj 1010 (线段相交判断+多边形求面积)

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=10 Area Time Limit: 2 Seconds      Mem ...

  8. 【小米校招笔试】给定一些线段,线段有起点和终点,求这些线段的覆盖长度,重复的部分只计算一次

    2016年小米校招笔试第一题(西安站) 1 给定一些线段,线段有起点和终点,求这些线段的覆盖长度,重复的部分只计算一次. 参考解法(Java版): package XiaoMi;/********** ...

  9. 两条线段的夹角 cesium_《原本》命题1.10 一条线段可以被分成两条相等的线段

    命题1.10 一条线段可以被分成两条相等的线段 设:AB为一条直线. 求作:平分为两条相等的线段. 作等边三角形ABC(命题1.1) 命题1.1已知一条线段可作一个等边三角形. 作∠ACB的角平分线C ...

最新文章

  1. 业务场景是什么意思_深度思考:麦乐积分兑换商城系统业务逻辑
  2. eclipse使用技巧_有效使用Eclipse的热门技巧
  3. mysql 实现计数器_MySQL实现计数器的表设计及实现
  4. np.where使用:根据条件生成新的数组
  5. MongoDB使用经验总结
  6. redis cluster 集群拓展
  7. Java基础:MySQL
  8. ios 团购信息客户端demo(二)
  9. 科学计算机中log,科学计算器的科学用法.docx
  10. 【CircuitPython】RaspberryPi Pico RP2040 自定义机械键盘实例
  11. 考研刷题小程序的盈利模式分析
  12. 求解立方根 java
  13. Bose Soundlink Ⅲ 随机断电故障处理
  14. mysql替换字段中的部分字符
  15. A5SHB,A5SHB芯片三极管规格书
  16. Kettle: 合并记录
  17. React的React.StrictMode
  18. 遥信量采集、显示及信息处理功能 遥测及数据处理功能
  19. Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷
  20. Hive表解锁 Locks on the underlying objects cannot be acquired. retry after some time

热门文章

  1. kalilinux链接蓝牙音响_Kali-Linux安驱动、使用Blueman连接蓝牙耳机
  2. (含代码)基于51单片机的红外遥控(独立按键)舵机开关灯控制
  3. pc系统设计演变_设计师的演变
  4. 技术开发项目收获了什么_鸡西拼拼优米是什么模式
  5. Linux系统下rar软件的安装以及如何解压文件
  6. Restful API是什么?初探Restful API,传统接口写法与Restful API接口写法区别
  7. [图文]历届奥斯卡影后(下)
  8. hdu2838(树状数组)
  9. Android 最详细的图片压缩攻略(建议收藏)
  10. python语言创意绘画是什么-Python街机模块的draw系列绘画例子集合