zoukankan      html  css  js  c++  java
  • 点是否在三角形内的判断

    1.利用三角形ABC面积,1/2*|A||B|Sin(a); 任意一点P,分别向三角形(A,B,C)三个顶点连线,形成三个三角形(PAB,PBC,PAC)。如果S(ABC)==S(PAB)+S(PBC)+S(PAC),则点在三角形内,反之,在三角形外

    2.判断点是否在三条边的同一层

    先说一下叉乘:

    设矢量P   =   (x1,y1)   ,Q   =   (x2,y2)
    则矢量叉积定义为:     P   ×   Q   =   x1*y2   –   x2*y1       得到的是一个标量
    显然有性质   P   ×   Q   =   –   (   Q   ×   P   )       P   ×   (   –   Q   )   =   –   (   P   ×   Q   )
    如不加说明,下面所有的点都看作矢量,点的乘法看作矢量叉积;
    叉乘的重要性质:
     若   P   ×   Q     >   0   ,     则P   在Q的顺时针方向
    &#61548; 若   P   ×   Q     <   0   ,     则P   在Q的逆时针方向
    &#61548; 若   P   ×   Q     =   0   ,     则P   与Q共线,但可能同向也可能反向

    我提出的算法中有一步要判断顺时针逆时针的方向,其实很简单。假设有两端连续的险段,其公共端点是P0,其他的两个端点是P1和P1,计算向量 <P0,P1> 和 <P0,P2> 的叉乘,如果若结果为正,则 <P0,P1> 在 <P0,P2> 的顺时针方向;若为0则 <P0,P1> <P0,P2> 共线(可能同向和反向);若为负则 <P0,P1> 在 <P0,P2> 的在逆时针方向。因此可以根据这个判断p0p1和p1p2在p1处是左转还是右转,只要求(p2-p0)*(p1-p0),若 <0则左转,> 0则右转,=0则共线。


    下面的简单的函数可以计算叉乘。


    #define   infinity   1e20
    #define   EP   1e-10

    struct   TPoint   {
            float   x,y;
    };

    struct   TLineSeg   {
            TPoint   a,b;
    };


    /********************************************************   *                                                                                                            
      *     返回(P1-P0)*(P2-P0)的叉积。                                                  
      *     若结果为正,则 <P0,P1> 在 <P0,P2> 的顺时针方向;                
      *     若为0则 <P0,P1> <P0,P2> 共线;                                                
      *     若为负则 <P0,P1> 在 <P0,P2> 的在逆时针方向;                          
      *     可以根据这个函数确定两条线段在交点处的转向,                  
      *     比如确定p0p1和p1p2在p1处是左转还是右转,只要求            
      *     (p2-p0)*(p1-p0),若 <0则左转,> 0则右转,=0则共线        
      *                                                                                                      
    \********************************************************/

    float   multiply(TPoint   p1,   TPoint   p2,   TPoint   p0)
    {
            return   (   (   p1.x   -   p0.x   )   *   (   p2.y   -   p0.y   )   -   (   p2.x   -   p0.x   )   *   (   p1.y   -   p0.y   )   );        
    }

    叉乘还有很多用途,举例如下:

    1。判断点在线段上
    设点为Q,线段为P1P2   ,判断点Q在该线段上的依据是:
    (   Q   –   P1   )   ×   (   P2   –   P1   )   =   0     且   Q   在以   P1,P2为对角顶点的矩形内

    //   判断点p是否在线段l上
    int   online(TLineSeg   l,TPoint   p)
    {
            return(   (multiply(l.b,p,l.a)==0)&&(   ((p.x-l.a.x)*(p.x-l.b.x) <0   )||(   (p.y-l.a.y)*(p.y-l.b.y) <0   ))   );
    }


    2。判断两线段是否相交
    我们分两步确定两条线段是否相交:
    1.快速排斥试验
    设以线段   P1P2   为对角线的矩形为R,   设以线段   Q1Q2   为对角线的矩形为T,如果R和T不相交,显然两线段不会相交;
    2.跨立试验
    如果两线段相交,则两线段必然相互跨立对方,如图1所示(可惜这里无法显示图:(     )。在图1中,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
    至此已经完全解决判断线段是否相交的问题。


    //确定两条线段是否相交
    int   intersect(TLineSeg   u,TLineSeg   v)
    {
            return(   (max(u.a.x,u.b.x)> =min(v.a.x,v.b.x))&&
                            (max(v.a.x,v.b.x)> =min(u.a.x,u.b.x))&&
                            (max(u.a.y,u.b.y)> =min(v.a.y,v.b.y))&&
                            (max(v.a.y,v.b.y)> =min(u.a.y,u.b.y))&&
                            (multiply(v.a,u.b,u.a)*multiply(u.b,v.b,u.a)> =0)&&
                            (multiply(u.a,v.b,v.a)*multiply(v.b,u.b,v.a)> =0));
    }

  • 相关阅读:
    Leetcode Python笔记
    Jenkins 自动化构建基于svn的vue项目 ,以及uniapp的H5项目
    Jenkins 持续化部署
    java中的各种锁详细介绍
    Maven私有仓库搭建 Nexu3
    Spring Cloud构建微服务架构(一)服务注册与发现
    SpringCloud学习笔记(开篇)
    介绍一款 redis 可视化工具
    java 在线网络考试系统源码 springboot mybaits vue.js 前后分离跨域
    java OA办公系统源码 Springboot Activiti工作流 vue.js 前后分离 集成代码生成器
  • 原文地址:https://www.cnblogs.com/waterdragon/p/2661180.html
Copyright © 2011-2022 走看看