在二维坐标下介绍一些定义:

点:A(x1,y1),B(x2,y2)
向量:向量AB=( x2 - x1 , y2 - y1 )= ( x , y );
向量的模 |AB| = sqrt ( x*x+y*y );


向量的点积:

向量叉积 结果为 x1*x2 + y1*y2。
点积的结果是一个数值。
点积的集合意义:
我们以向量 a 向向量 b 做垂线,则 | a | * cos(a,b)为 a 在向量 b 上的投影,即点积是一个向量在另一个向量上的投影乘以另一个向量。且满足交换律
应用:
可以根据集合意义求两向量的夹角,cos(a,b) =( 向量a * 向量b ) / (| a | * | b |) = x1*x2 + y1*y2 / (| a | * | b |)

向量的叉积:

向量叉积 结果为 x1*y2-x2*y1
叉积的结果也是一个向量,是垂直于向量a,b所形成的平面,如果看成三维坐标的话是在 z 轴上,上面结果是它的模。

方向判定:

右手定则,(右手半握,大拇指垂直向上,四指右向量a握向b,大拇指的方向就是叉积的方向)

叉积的集合意义:

1:其结果是a和b为相邻边形成平行四边形的面积。
2:结果有正有负,有sin(a,b)可知和其夹角有关,夹角大于180°为负值。
3:叉积不满足交换律

应用:

1:通过结果的正负判断两矢量之间的顺逆时针关系
若 a x b > 0表示a在b的顺时针方向上
若 a x b < 0表示a在b的逆时针方向上
若 a x b == 0表示a在b共线,但不确定方向是否相同

2:判断折线拐向,可转化为判断第三点在前两的形成直线的顺逆时针方向,然后判断拐向。
3:判断一个点在一条直线的那一侧,同样上面的方法。
4:判断点是否在线段上,可利用叉乘首先判断是否共线,然后在判断是否在其上。
5:判断两条直线是否想交(跨立实验)
根据判断点在直线那一侧我们可以判断一个线段的上的两点分别在另一个线段的两侧,当然这是不够的,因为我们画图发现这样只能够让直线想交,而不是线段,所以我们还要对另一条线段也进行相同的判断就ok。

判断两线段是否相交:

  我们分两步确定两条线段是否相交:

(1)快速排斥试验

设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。

(2)跨立试验

如果两线段相交,则两线段必然相互跨立对方。
若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,
即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。
上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。
当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,
但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:
( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。
同理判断Q1Q2跨立P1P2的依据是:
( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。


POJ3304

题意:

给出一些线段,求是否存在一条直线,使得这些线段在该直线的投影有共同交点。

题解:

求这样一条直线是否存在,因为这些线段在这条直线的投影有共同交点,即这条直线的垂线和所有线段都有交点,问题即转换成了是否存在一条直线和所有线段相交。
直线可以分别枚举每条线段的两个端点,然后在判断和每个线段是否相交即可。

代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std ;
#define MAX 110
const double eps = 1e-8;
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) ;}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 ;}
};
struct Line
{Point s , e ;Line(){}Line(Point _s , Point _e){s = _s ; e = _e ;}
};
double xmult(Point p0,Point p1,Point p2) //叉积p0p1 X p0p2
{return (p1-p0)^(p2-p0);
}
bool Seg_inter_line(Line l1,Line l2) //判断直线l1和线段l2是否相交
{return sgn(xmult(l2.s,l1.s,l1.e))*sgn(xmult(l2.e,l1.s,l1.e)) <= 0;
}
double dist(Point a,Point b)
{return sqrt( (b - a)*(b - a) );
}
Line line[MAX] ;
bool check(Line l1 , int n)
{if(sgn(dist(l1.s,l1.e)) == 0) return false ;for(int i = 0;i < n;i++)if(Seg_inter_line(l1,line[i]) == false)return false ;return true ;
}
int main()
{int T , n;scanf("%d" , &T) ;while(T --){scanf("%d" , &n) ;double x1,x2,y1,y2 ;for(int i = 0 ; i < n ; i ++){scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);line[i] = Line(Point(x1,y1),Point(x2,y2));}bool flag = false ;for(int i = 0 ; i < n ; i ++){for(int j = 0 ; j < n ; j ++){if(check(Line(line[i].s,line[j].s),n) || check(Line(line[i].s,line[j].e),n)|| check(Line(line[i].e,line[j].s),n) || check(Line(line[i].e,line[j].e),n) ){flag = true;break;}}}if(flag) printf("Yes!\n") ;else printf("No!\n") ;}return 0 ;
}

跨立实验判断线段是否相交-POJ3304相关推荐

  1. 【代码超详解】ZOJ 2551 / POJ 2653 Pick-up Sticks(快速排斥实验 + 跨立实验判断线段是否相交 · 模板)

    一.传送门 http://poj.org/problem?id=2653 https://zoj.pintia.cn/problem-sets/91827364500/problems/9182736 ...

  2. 快速排斥、跨立实验判断线段是否相交

    写在前面 在其他博客中看到这方面的知识,很多都是重复,并且说的总是云里雾里的,所以这里我就自己总结一下这种问题如何求解,判断两个线段是否相交在前面我们提到了会用到叉积的一点知识,那么这里就来详细说一下 ...

  3. 计算几何 快速排斥和跨立实验 判断两线段相交

    线段P1P2, Q1Q2,判断其是否相交,通过快速排斥和跨立实验则说明相交 首先要知道:向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的逆时针方向:若结果大于0,表示向量b在向量a的 ...

  4. 快速排斥实验amp;跨立实验 判断两直线是否相交

    两条线段有且仅有一个公共点,且这个点不是任何一条线段的端点时,称这两条线段是严格相交的. 也就是说线段不严格相交时可以将端点作为交点,但本文不讨论不严格相交,只讨论严格相交的情况(即使它们在算法实现上 ...

  5. 暑假集训#2 div1 J 四点直角 J - Space Invader 四点共面+跨立实验

    题意:给你四个点,判断能否先依次通过A,B两点,然后再在某个地方只进行一次直角转弯再一次经过C,D两点: #include <iostream> #include <cstdio&g ...

  6. 判断两线段是否相交——快速排斥与跨立实验

    如何判断两条线段是否相交呢?如果是我们去解决这个问题,用眼睛很容易就看出来了,但是如果用计算机来解决这个问题,该怎么办呢?下面介绍两个方法,这两个方法结合起来就能完美解决这个问题了. 一.快速排斥 对 ...

  7. 【计算几何】判断线段相交(跨立实验)

    题意:有n条线段(编号为1n),按1n的顺序放在二维坐标系上(就是先放1号,再放2号--),要求输出最上面的那些线段的编号.(就是没有其他线段压在它上面的那些线段) 注意:有交点即为被压. 1.叉积 ...

  8. [GIS算法] 判断两线段是否相交的四种方案(快速排斥+跨立实验、参数方程求解、凸多边形、点在线的哪一侧)-附C语言实现

    文章目录 算法一:快速排斥+跨立试验 代码 算法二:参数方程求解 代码 算法三:凸多边形 算法四:点在线的哪一侧 算法一:快速排斥+跨立试验 重点掌握 [原理]利用矢量的叉乘 [图解] 代码 #def ...

  9. 判断两个线段相交问题(快速排斥实验跨立实验)

    代码实现: import numpy as np import cv2class Check_line():def __init__(self):passdef step_one(self, p1, ...

最新文章

  1. kubernetes入门(04)kubernetes的核心概念(1)
  2. luogu P1843 奶牛晒衣服 | 二分法
  3. 人工智能:第六章 专家系统
  4. boost::lambda::bind用法的测试程序
  5. HTTP调试工具:Fiddler 介绍二
  6. JavaScript 音频处理库 pico.js
  7. 深度学习基础(四)优化函数(梯度下降函数)
  8. 个人材料(上报公司)
  9. C++ 工厂模式(设计模式)
  10. Unix——fprintf与stderr、stdout的使用
  11. CentOS 7.2安装zabbix 3.0 LTS
  12. 论文笔记_S2D.43_2018-CVPR_单张RGB-D图像的深度补全
  13. java 分布式同步锁_java编程进阶之路:回归锁的本质,探索分布式锁之源头
  14. C++设计模式 - 适配器模式(Adapter)
  15. conda 转载自 生信技能树
  16. 利用css3伪元素实现加号、减号、对号小图标效果
  17. Obsidian media extended以及bilibili插件链接总是打开外部网页以及退回编辑视图会弹出另外一个相同文件
  18. symlink(): Protocol error
  19. 薅羊毛的神器,悄悄介绍给你,低调使用!
  20. 风口的猪?中国智能家居恐因没有专利集体阵亡

热门文章

  1. 计算机太阳,计算机可以学习在大量太阳图像中查找太阳耀斑和其他事件
  2. ai杀手级_游戏花了太长时间才能利用stadias杀手级功能
  3. mysql count 不走索引_sql中不走索引情况
  4. 蛋花花分析人工智能靠什么走向大众
  5. GNSS四大卫星导航系统导航电文构成
  6. 应用商店调研-百度手机助手
  7. 爬虫-网站地址及反爬机制
  8. SAP事务码开关控制,TCODE
  9. 基于JAVA研究生实验室综合管理系统计算机毕业设计源码+系统+lw文档+部署(2)
  10. TikTok产品分析竞品分析