判断两条线段是否相交

主要用到了通过向量积的正负判断两个向量位置关系

向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的顺时针方向;若结果大于0,表示向量b在向量a的逆时针方向;若等于0,表示向量a与向量b平行

主要代码参考自文末链接,但是他并没有给出跨立检验函数的具体内容,因此补充了一下放在下面

using System;
using System.Collections.Generic;
using System.Windows;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace lineTest
{
class Program
{
public struct Point
{
public double X;
public double Y; public Point(double x, double y)
{
X = x;
Y = y;
}
} static void Main(string[] args)
{
Point a = new Point(0, 0);
Point b = new Point(100, 100);
Point c = new Point(100,0);
Point d = new Point(50,49);
var result = IsIntersect(a, b, c, d);
} public static Point? GetIntersection(Point lineAStart, Point lineAEnd, Point lineBStart, Point lineBEnd)
{
double x1 = lineAStart.X, y1 = lineAStart.Y;
double x2 = lineAEnd.X, y2 = lineAEnd.Y; double x3 = lineBStart.X, y3 = lineBStart.Y;
double x4 = lineBEnd.X, y4 = lineBEnd.Y; //equations of the form x=c (two vertical lines)
if (x1 == x2 && x3 == x4 && x1 == x3)
{
return null;
} //equations of the form y=c (two horizontal lines)
if (y1 == y2 && y3 == y4 && y1 == y3)
{
return null;
} //equations of the form x=c (two vertical lines)
if (x1 == x2 && x3 == x4)
{
return null;
} //equations of the form y=c (two horizontal lines)
if (y1 == y2 && y3 == y4)
{
return null;
}
double x, y; if (x1 == x2)
{
double m2 = (y4 - y3) / (x4 - x3);
double c2 = -m2 * x3 + y3; x = x1;
y = c2 + m2 * x1;
}
else if (x3 == x4)
{
double m1 = (y2 - y1) / (x2 - x1);
double c1 = -m1 * x1 + y1; x = x3;
y = c1 + m1 * x3;
}
else
{
//compute slope of line 1 (m1) and c2
double m1 = (y2 - y1) / (x2 - x1);
double c1 = -m1 * x1 + y1; //compute slope of line 2 (m2) and c2
double m2 = (y4 - y3) / (x4 - x3);
double c2 = -m2 * x3 + y3; x = (c1 - c2) / (m2 - m1);
y = c2 + m2 * x;
} if (IsInsideLine(lineAStart, lineAEnd, x, y) &&
IsInsideLine(lineBStart, lineBEnd, x, y))
{
return new Point(x, y);
} //return default null (no intersection)
return null;
}
private static bool IsInsideLine(Point start, Point end, double x, double y)
{
return ((x >= start.X && x <= end.X)
|| (x >= end.Y && x <= start.Y))
&& ((y >= start.Y && y <= end.Y)
|| (y >= end.Y && y <= start.Y));
} public static bool IsIntersect(Point p1, Point p2, Point q1, Point q2)
{
//排斥试验,判断p1p2在q1q2为对角线的矩形区之外
if (Math.Max(p1.X, p2.X) < Math.Min(q1.X, q2.X))
{//P1P2中最大的X比Q1Q2中的最小X还要小,说明P1P2在Q1Q2的最左点的左侧,不可能相交。
return false;
} if (Math.Min(p1.X, p2.X) > Math.Max(q1.X, q2.X))
{//P1P2中最小的X比Q1Q2中的最大X还要大,说明P1P2在Q1Q2的最右点的右侧,不可能相交。
return false;
} if (Math.Max(p1.Y, p2.Y) < Math.Min(q1.Y, q2.Y))
{//P1P2中最大的Y比Q1Q2中的最小Y还要小,说明P1P2在Q1Q2的最低点的下方,不可能相交。
return false;
} if (Math.Min(p1.Y, p2.Y) > Math.Max(q1.Y, q2.Y))
{//P1P2中最小的Y比Q1Q2中的最大Y还要大,说明P1P2在Q1Q2的最高点的上方,不可能相交。
return false;
} //跨立试验
var crossP1P2Q1 = VectorCross(p1, p2, q1);
var crossP1Q2P2 = VectorCross(p1, q2, p2);
var crossQ1Q2P1 = VectorCross(q1, q2, p1);
var crossQ1P2Q2 = VectorCross(q1, p2, q2); bool isIntersect = (crossP1P2Q1 * crossP1Q2P2 >= 0) && (crossQ1Q2P1 * crossQ1P2Q2 >= 0);
return isIntersect;
} private static double VectorCross(Point p1, Point p2, Point p3)
{
Vector vectorP1 = new Vector(p1.X, p1.Y);
Vector vectorP2 = new Vector(p2.X, p2.Y);
Vector vectorP3 = new Vector(p3.X, p3.Y);
Vector vectorP1P2 = Vector.Subtract(vectorP2, vectorP1);
Vector vectorP1P3 = Vector.Subtract(vectorP3, vectorP1);
return Vector.CrossProduct(vectorP1P2, vectorP1P3);
}
}
}

参考

https://blog.csdn.net/weixin_33973609/article/details/93580049

https://www.cnblogs.com/tuyang1129/p/9390376.html

[CSharpTips]判断两条线段是否相交的更多相关文章

  1. Pick-up sticks(判断两条线段是否相交)

    Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 8351 Accepted: 3068 Description Stan has ...

  2. c# 判断两条线段是否相交(判断地图多边形是否相交)

    private void button1_Click(object sender, EventArgs e) { //var result = intersect3(point1, point2, p ...

  3. 计算几何--判断两条线段相交--poj 2653

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8862   Accepted: 3262 De ...

  4. 求两条线段交点zz

    "求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法说一说, 希望对大家有所帮助. 本 ...

  5. 平面内,线与线 两条线找交点 两条线段的位置关系(相交)判定与交点求解 C#

    个人亲自编写.测试,可以正常使用   道理看原文,这里不多说   网上找到的几篇基本都不能用的   C#代码 bool Equal(float f1, float f2) { return (Math ...

  6. 两条线段求交点+叉积求面积 poj 1408

    题目链接:https://vjudge.net/problem/POJ-1408 题目是叫我们求出所有四边形里最大的那个的面积. 思路:因为这里只给了我们正方形四条边上的点,所以我们要先计算横竖线段两 ...

  7. 判断线段和直线相交 POJ 3304

    // 判断线段和直线相交 POJ 3304 // 思路: // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. #include <cstdio ...

  8. 判断直线与线段相交 POJ 3304 Segments

    题意:在二维平面中,给定一些线段,然后判断在某直线上的投影是否有公共点. 转化,既然是投影,那么就是求是否存在一条直线L和所有的线段都相交. 证明: 下面给出具体的分析:先考虑一个特殊的情况,即n=1 ...

  9. JVM-如何判断一段数据是真正的数据,还是对象的引用

    JVM 判断一段数据到底是数据还是引用类型,首先要看JVM选择用什么方式.通常这个选择会影响到GC的实现. 一.保守式 如果JVM选择不记录任何这种类型的数据,那么它就无法区分内存里某个位置上的数据到 ...

随机推荐

  1. 彰显个性│制作一个独一无二的动态 svg 头像

    一.头像预览 看一下博主的动态图像,是不是很炫酷,想不想拥有一个? 这是一个 svg 图片,svg 图片不仅可以通过制图软件制作外,其实也可以通过代码进行开发 因为 svg 本质上是一个下 xml 文 ...

  2. 最简单的离散概率分布,伯努利分布 《考研概率论学习之我见》 -by zobol

    上文讲了离散型随机变量的分布,我们从最简单的离散型分布伯努利分布讲起,伯努利分布很简单,但是在现实生活中使用的很频繁.很多从事体力工作的人,在生活中也是经常自觉地"发现"伯努利分布 ...

  3. colab简易使用

    解压文件(zip文件) !unzip -o /content/drive/MyDrive/test.zip -d /content/ 解压test.zip到指定目录, 其他解压缩命令: linux-常 ...

  4. SimpleMarkDown编辑器离线版以及桌面应用版上线

    之前,我们开发了Web版本SimpleMarkDown编辑器.今天,我们又推出了离线版和桌面应用版. 主要功能: 页面简约: 实时保存: 一键清空内容: 支持微信公众号.知乎.稀土掘金.CSDN等多个 ...

  5. Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...

  6. 获取mybatis注解方式新增数据时非自增插入的主键

    场景:插入数据的时候,获取不到非自增的主键.原因:对象中没有主键的值,插入后主键才有值. 解决方案:使用 @SelectKey @SelectKey中: statement是要运行的SQL语句,即查询 ...

  7. DNS原理&ssh

    作用:实现域名的解析! www.baidu.com => 14.215.177.37 域名: www.baidu.com 实际域名为: www.baidu.com. 域名的解析,是反向的. 最后 ...

  8. Mysql安装配置以及解决重装Mysql时忘记root password问题

    目录 1.Mysql安装以及环境变量配置 重装Mysql时忘记root password问题 1.Mysql安装以及环境变量配置 官网安装:​​​​​​https://www.mysql.com/ 按 ...

  9. C#/VB.NET 将PDF转为Excel

    PDF文档可以避免可防⽌他⼈⽆意中触到键盘修改⽂件内容.但是在避免他人⽆意修改的同时也妨碍了正常的修改.如果你想处理或修改PDF文档中的数据,不妨试试用Excel来实现.Excel拥有强大的数据处理功 ...

  10. 原生实现.NET5.0+ 自定义日志

    一.定义一个静态类 声明一个 ReaderWriterLockSlim 对象 用于并发控制 1 /// <summary> 2 /// IO锁 3 /// </summary> ...