主要内容:

  • 判断两线段是否相交
  • 计算两线段的交叉点
  • 点与直线的位置关系
  • 判断两线段重合并计算其重合部分
  • 判断合并两条线段

说明全都在注释里了,有的方法可能不是最佳,欢迎大家提出建议~~

public class Line : MonoBehaviour
{Vector2 impossiblePoint = -1000 * Vector2.one;// ----------//判断两线段交叉并计算交叉点,线段AB,线段CDpublic Vector2 LineCross(Vector2 A, Vector2 B, Vector2 C, Vector2 D){//可能情况说明://01 完全交叉,线段AB的端点分别在线段CD的两侧,且线段CD的端点也分别在线段AB的两侧//  pointPosA * pointPosB < 0 && pointPosC * pointPosD < 0//  pointPosA * pointPosB < 0   点AB在线段CD两侧, > 0,点AB在线段同侧, == 0,点AB至少有一个点在线段上//02 线段一个端点在另一条线段上,且另一个端点不在//  pointPosA == 0 && pointPosB != 0 || pointPosA != 0 && pointPosB == 0//  pointPosC == 0 && pointPosD != 0 || pointPosC != 0 && pointPosD == 0//计算各端点与线段的关系float pointPosA, pointPosB, pointPosC, pointPosD;pointPosA = PointPosionOfLine(A, C, D);pointPosB = PointPosionOfLine(B, C, D);pointPosC = PointPosionOfLine(C, A, B);pointPosD = PointPosionOfLine(D, A, B);//01if (pointPosA * pointPosB < 0 && pointPosC * pointPosD < 0){return GetCrosPoint(A, B, C, D);}//02if (IsZero(pointPosA) && !IsZero(pointPosB))return A;else if (!IsZero(pointPosA) && IsZero(pointPosB))return B;if (IsZero(pointPosC) && !IsZero(pointPosD))return C;else if (!IsZero(pointPosC) && IsZero(pointPosD))return D;//03 若不符合以上条件,则不交叉return impossiblePoint;}//点与直线的位置,目标点M,直线ABfloat PointPosionOfLine(Vector2 M, Vector2 A, Vector2 B){// 返回值 > 0 在右侧, = 0 在线上, < 0 在左侧return (B.y - M.y) * (A.x - M.x) - (A.y - M.y) * (B.x - M.x);//公式计算过程//直线公式:a * X + b * Y + c = 0//将线段端点代入公式// a * A.x + b * A.y + c = 0// a * B.x + b * B.y + c = 0//两式分别相加、相减// (A.x + B.x) * a + (A.y + B.y) * b + 2c = 0// (A.x - B.x) * a + (A.y - B.y) * b = 0//化简得// b = (B.x - A.x) / (A.y - B.y) * a// c = -a * (A.y * B.x - A.x * B.y) / (A.y - B.y)//原直线公式用a表示为// a * X + (B.x - A.x) / (A.y - B.y) * a * Y - a * (A.y * B.x - A.x * B.y) / (A.y - B.y) = 0//公式两边同时除a,直线公式用点A/B表示为// X + (B.x - A.x) / (A.y - B.y) * Y - (A.y * B.x - A.x * B.y) / (A.y - B.y) = 0//再次化简// (A.y - B.y) * X + (B.x - A.x) * Y - (A.y * B.x - A.x * B.y) = 0//公式左侧==0,点在直线上,公式左侧>0,点在直线右侧,工作左侧<0,点在直线左侧//将目标点M代入公式// (A.y - B.y) * M.x + (B.x - A.x) * M.y - (A.y * B.x - A.x * B.y)// A.y * M.x - B.y * M.x + B.x * M.y - A.x * M.y - A.y * B.x + A.x * B.y//整理为// (B.y - M.y) * (A.x - M.x) - (A.y - M.y) * (B.x - M.x)}//计算两线段交点,线段AB,线段CDVector2 GetCrosPoint(Vector2 A, Vector2 B, Vector2 C, Vector2 D){//直线方程:// Y = aX + bfloat x = 0, y = 0;float a1 = (B.y - A.y) / (B.x - A.x);float a2 = (D.y - C.y) / (D.x - C.x);if (IsZero((A.x - B.x) - (C.x - D.x))){//两线段都没有斜率,或者两斜率相等,此时两线段平行return impossiblePoint;}else if (IsZero(A.x - B.x)){//线段AB竖直方向,交点为M//方法一:解方程式//两线段方程:(方程式由公式Y = aX + b代入两点参数得)// X = A.x// Y = a2 * X + (C.y - C.x * a2)//解方程式即可//方法二:三角形关系(不推荐)//计算过程如下://交点M在线段AB上,其x坐标与线段任一点x坐标相同//交点M在线段CD上,CM与CD在同一条直线上,两线段斜率相等// (M.y - C.y) / (M.x - C.x) = a2// M.y = a2 * (M.x - C.x) + C.y// M.x = A.x// M.y = a2 * (A.x - C.x) + C.y//最终均可得x = A.x;y = a2 * (A.x - C.x) + C.y;return new Vector2(x, y);}else if (IsZero(C.x - D.x)){//线段CD竖直方向,计算过程同上x = C.x;y = a1 * (C.x - A.x) + A.y;return new Vector2(x, y);}else{//线段都有斜率,且不相等//解方程式,(方程式由公式Y = aX + b代入两点参数得)// Y = a1 * X + (A.y - A.x * a1)// Y = a2 * X + (C.y - C.x * a2)x = (a1 * A.x - a2 * C.x - A.y + C.y) / (a1 - a2);y = a1 * x - a1 * A.x + A.y;return new Vector2(x, y);}}// ----------//判断两线段重合并计算其重合部分(重合部分为线段,返回重合线段两个端点,不考虑只有一个重合点的情况)//线段AB,线段CDpublic Vector2[] LineCoincide(Vector2 A, Vector2 B, Vector2 C, Vector2 D){//可能情况说明://01 包含关系,一条线段包含在另一条线段内,比如:线段AB的端点A和端点B都在线段CD上//  onLineA && onLineB//  onLineC && onLineD//02 交错关系,各包含一个端点,比如:线段AB的端点A在线段CD上,线段CD的端点C在线段AB上//  onLineA && onLineC && A != C//  onLineA && onLineD && A != D//  onLineB && onLineC && B != C//  onLineB && onLineD && B != D//为使计算过程开起来更加直观,这里不对公式进行过多化简//计算各个端点与线段的关系(点是否在线段上)bool onLineA, onLineB, onLineC, onLineD;onLineA = IsPointOnLine(A, C, D);onLineB = IsPointOnLine(B, C, D);onLineC = IsPointOnLine(C, A, B);onLineD = IsPointOnLine(D, A, B);//如果只需要返回bool结果,不需要获取重合点,使用以下代码/*//直接判断bool值并返回bool coincide01 = (onLineA && onLineB) || (onLineC && onLineD);bool coincide02 = (onLineA && onLineC && (A != C))|| (onLineA && onLineD && (A != D))|| (onLineB && onLineC && (B != C))|| (onLineB && onLineD && (B != D));return (coincide01 || coincide02);*/// -- -- -- -- --//如果需要返回重合点,使用以下代码//coincide01if (onLineA && onLineB)return new Vector2[] { A, B };else if (onLineC && onLineD)return new Vector2[] { C, D };//coincide02if (onLineA && onLineC && (A != C))return new Vector2[] { A, C };else if (onLineA && onLineD && (A != D))return new Vector2[] { A, D };else if (onLineB && onLineC && (B != C))return new Vector2[] { B, C };else if (onLineB && onLineD && (B != D))return new Vector2[] { B, D };//若不符合以上条件,则不重合return null;}// 判断点是否在线段上,目标点M,线段ABbool IsPointOnLine(Vector2 M, Vector2 A, Vector2 B){//可以直接利用PointPosionOfLine(M, A, B)方法计算//if (IsZero(PointPosionOfLine(M, A, B)))//    return true;//else//return false;//这里提供另一种计算方式,略显麻烦//与端点重合if (M == A || M == B)return true;//在同一竖直方向,线段竖直,点在该线段所在的直线上if (IsZero(A.x - B.x) && IsZero(A.x - M.x)){//已判定点在直线上,若点在两端点中间,即点在线段上//if ((M.y < B.y && M.y > A.y) || (M.y < A.y && M.y > B.y)),化简为:if ((A.y - M.y) * (M.y - B.y) > 0.0f){return true;}return false;}//在同一水平方向else if (IsZero(A.y - B.y) && IsZero(A.y - M.y)){if ((A.x - M.x) * (M.x - B.x) > 0.0f){return true;}return false;}//线段倾斜,此时线段所在直线存在斜率else{//点在直线上,MA与MB斜率相等,且有共同点M,此时MA与MB重合,即点M在直线AB上//(A.y - M.y) / (A.x - M.x) == (M.y - B.y) / (M.x - B.x))if (IsZero((A.y - M.y) / (A.x - M.x) - (M.y - B.y) / (M.x - B.x))){//已判定点在直线上,若点在两端点中间,即点在线段上if (((A.y - M.y) * (M.y - B.y) > 0) && ((A.x - M.x) * (M.x - B.x) > 0)){return true;}}return false;}}// ----------//合并两条线段,线段AB,线段CDpublic Vector2[] LineCombine(Vector2 A, Vector2 B, Vector2 C, Vector2 D){//与LineCoincide(Vector2 A, Vector2 B, Vector2 C, Vector2 D)相似//可能情况说明://01 有一个公共端点,两线段反向,夹角180度//  A == C && AB/CD共线//  A == D && AB/CD共线//  B == C && AB/CD共线//  B == D && AB/CD共线//02 交错关系,各包含一个端点,比如:线段AB的端点A在线段CD上,线段CD的端点C在线段AB上//  A != C && onLineA && onLineC//  A != D && onLineA && onLineD //  B != C && onLineB && onLineC //  B != D && onLineB && onLineD//03 包含关系,一条线段包含在另一条线段内,比如:线段AB的端点A和端点B都在线段CD上//  onLineA && onLineB//  onLineC && onLineD//以上01和02两种情况可以合并如下//一般情况下,点A在线段CD上,C在AB上,此时AB/CD已经共线,但A/C是同一点的时候特殊考虑,需要验证夹角180度//  onLineA && onLineC && AB/CD共线//  onLineA && onLineD && AB/CD共线//  onLineB && onLineC && AB/CD共线//  onLineB && onLineD && AB/CD共线//再将以上三种情况合并//只有两线段共线,才有可能合并//计算各个端点与线段的关系(点是否在线段上)bool onLineA, onLineB, onLineC, onLineD;onLineA = IsPointOnLine(A, C, D);onLineB = IsPointOnLine(B, C, D);onLineC = IsPointOnLine(C, A, B);onLineD = IsPointOnLine(D, A, B);//01,02,03if (IsLineDirection(A, B, C, D)){if (onLineA && onLineC)return new Vector2[] { B, D };else if (onLineA && onLineD)return new Vector2[] { B, C };else if (onLineB && onLineC)return new Vector2[] { A, D };else if (onLineB && onLineD)return new Vector2[] { A, C };else if (onLineA && onLineB)return new Vector2[] { C, D};else if (onLineC && onLineD)return new Vector2[] { A, B };}//若不符合以上条件,则不可合并return null;}//是否线段共线,线段AB,CDbool IsLineDirection(Vector2 A, Vector2 B, Vector2 C, Vector2 D){// dotValue == 1 0度// dotValue == 0 90度// dotValue == -1 180度float dotValue = Vector2.Dot((A - B).normalized, (C - D).normalized);if (IsZero(dotValue - 1) || IsZero(dotValue + 1))return true;elsereturn false;}// ----------//判断float == 0bool IsZero(float floatValue){if (floatValue > -0.00001f & floatValue < 0.00001f)return true;elsereturn false;}
}

线段(向量)的计算(判断线段重叠、相交,合并线段,点与线的关系)相关推荐

  1. 向量法计算空间点到线段的距离(python)

    中学数学告诉我们,计算点到线段的距离有两种. 我们假设点是P,线段是AB.P和AB都由三维的笛卡尔坐标表示.现计算P到AB的距离. 第一种是,过点P向线段AB上画垂线,判断垂足有没有落在线段上.如果落 ...

  2. (计算几何)判断一个点是否在线段上

    累加器传送门: http://blog.csdn.net/NOIAu/article/details/71775000 这个问题需要用到向量的叉积性质,下面先从百度截一些语句来介绍一下 用向量的叉积来 ...

  3. Java生成两个圆判断是否重叠,用java随机画出两个圆,判断它们是不是相交

    用java随机画出两个圆,判断它们是否相交 import java.awt.*; import java.util.Random; import javax.swing.*; import javax ...

  4. 算法优化---向量数组计算替代元素级别判断

    算法优化---向量数组计算替代判断 目录 前言 元素级别迭代与series,ndarray的迭代 测试 series, ndarray之间的数学计算,替代元素遍历判断. 根据数量级大小,选择适合的算法 ...

  5. 判断两条直线(线段)的交点问题

    要判断两条直线是否有交点首先要求出两直线的斜率,如果相等级两直线平行的话就肯定没有了,反之就一定有了,就可以联立两条直线的方程(我们假定直线的方程都是可以表示出来的),求出两直线的交点然后结果就有了, ...

  6. java 平面向量_【JS图形学基础】平面向量的计算和运用实例

    平面向量的计算和运用实例 相关概念 有向线段:具有方向的线段叫做有向线段,以A为起点,B为终点的有向线段记作 或AB: 向量的模:有向线段AB的长度叫做向量的模,记作|AB|: 零向量:长度等于0的向 ...

  7. 如何判断两条线段相交(python实现)

    向量叉乘(行列式计算):向量a(x1,y1),向量b(x2,y2): 首先我们要明白一个定理:向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的顺时针方向:若结果大于0,表示向量b在向 ...

  8. 【JS图形学基础】平面向量的计算和运用实例

    平面向量的计算和运用实例 相关概念 有向线段:具有方向的线段叫做有向线段,以A为起点,B为终点的有向线段记作 或AB: 向量的模:有向线段AB的长度叫做向量的模,记作|AB|: 零向量:长度等于0的向 ...

  9. Kinect体感机器人(三)—— 空间向量法计算关节角度

    Kinect体感机器人(三)-- 空间向量法计算关节角度 By 马冬亮(凝霜  Loki) 一个人的战争(http://blog.csdn.net/MDL13412) 终于写到体感机器人的核心代码了, ...

最新文章

  1. JMeter脚本获取变量名、检验字符串值
  2. Dynamics 365新功能:可编辑的网格(行内编辑)
  3. qt中QTreeWidget控件的使用
  4. 利用MFC按钮使能(或禁用)属性使按钮变正常色(或灰色)
  5. libqrencode 3.4.3 发布,二维码的C解析库
  6. eNSP仿真模拟与实际环境的几个不符点
  7. 元数据:数据治理的基石
  8. exchange2003系列总结:-5邮件加密与签名的工作流程
  9. python selenium无头浏览器
  10. timesat数据如何读取_CMPR软件安装教程和如何转换XRD格式
  11. 程序猿如何使用清单,高效完成工作
  12. 自我介绍html模板王,一分钟自我介绍模板范文15篇
  13. FFMpeg的码率控制 - CBR or VBR
  14. java跑酷游戏_HTML5游戏实战(1):50行代码实现正面跑酷游戏
  15. word论文排版和写作04:用MathType和word公式编辑器插入数学公式
  16. YOLOv3在Intel Realsense上的Python实现(未实现)
  17. 参加腾讯云TVP的Coding吐槽大会感想
  18. 腾讯产品总监曹菲:如何克服职业焦虑
  19. AutoCAD Civil 3D贴图
  20. RPG Maker MV 图块冲突解决、素材管理

热门文章

  1. 关于集合removeAll方法的性能测试
  2. 非药物治疗鼻炎方法大全(转)
  3. vue从入门到放弃(五)
  4. Excel小技巧!格式刷的5个高级用法,你不一定知道哦
  5. 阿里微服务架构的分布式事务GTS
  6. Stable Diffusion 无损放大图像和缩小图像
  7. greenplum客户端工具_首发全新Greenplum数据库图形化客户端
  8. 【毕业设计】13-基于单片机的锂电池管理系统(原理图+源码+仿真工程+论文)
  9. C++筑器 引用生死唯一
  10. 国外精选视频课:编译原理入门1