利用矢量计算快速判定一点在直线的哪一侧
2017-08-28 13:10
302 查看
很实用的一片判断点与直线关系的文章,转自:http://www.cnblogs.com/vilyLei/articles/1567852.html
这个例子是用来说明矢量运算可以快速判定一点在直线的哪一侧。
如上图所示,直线是从pA到pB的直线AB。下面的工作是构建一个方法,来判断某点在这条直线AB的左下侧还是右上侧。
如上图所示,pC点就在直线AB的右上侧,而pD点就在直线AB的左下侧。
这里要用矢量运算来解决这个问题,所以需要用到2D空间的矢量类,这个类:Vector_2D.as在此处http://www.cnblogs.com/vilyLei/articles/1567703.html可以找见。
下面用的Vector_2D类都指的是这个矢量类,每个Vector_2D类实例的方法都是这个类中已有的方法。
注:这里的矢量指的是数学或物理上的矢量,不是cs4中的Vector,它也叫向量。当然有很多东西可以在逻辑上表示为矢量,例如rgb颜色。
首先定义四个矢量对象来记录四个位置(pA,pB,pC,pD四个点)
//定义四个点矢量来记录四个点的相应位置
private var _a_V:Vector_2D = new Vector_2D(196,123);
private var _b_V:Vector_2D = new Vector_2D(370,230);
private var _c_V:Vector_2D = new Vector_2D(422,112);
private var _d_V:Vector_2D = new Vector_2D(159,296);
接着定义点pA到点pC的矢量,如上图pA到pC的箭头所示:
private var _ac_V:Vector_2D = null;
定义点pB到点pC的矢量,如上图pB到pC的箭头所示:
private var _bc_V:Vector_2D = null;
定义点pA到点pD的矢量,如上图pA到pD的箭头所示:
private var _ad_V:Vector_2D = null;
定义点pB到点pD的矢量,如上图pB到pD的箭头所示:
private var _bd_V:Vector_2D = null;
接下来计算出_ab_V, _bc_V, _bd_V这三个矢量:
//_c_V减去_a_V 就可以计算出点pA到点pC的矢量
_ac_V = _c_V.minusNew(_a_V);
//_c_V减去_b_V 就可以计算出点pB到点pC的矢量
_bc_V = _c_V.minusNew(_b_V);
//_d_V减去_a_V 就可以计算出点pA到点pD的矢量
_ad_V = _d_V.minusNew(_a_V);
//_d_V减去_b_V 就可以计算出点pB到点pD的矢量
_bd_V = _d_V.minusNew(_b_V);
现在来做一个测试,需要用到矢量叉乘,即Vector_2D类的cross(...)方法。
这里简要介绍一下叉乘。对于2D矢量的叉乘最后得到的一定是一个数字,它可能大于零,可能等于零,也可能小于零
如果两个矢量的方向夹角是180度/0度的时候,它们的叉乘值一定是等于零(当然在计算机中可能是 0.0001),对应的数学公式为A x B = |A|*|B|*sin(angle)
一定要记住叉乘不遵循交换律。
例如矢量A×矢量B=矢量C
设想矢量A沿小于180度的角度转向矢量B
将右手的四指指向矢量A的方向,右手的四指弯曲代表上述旋转方向,则伸直的拇指指向它们的叉乘得到的矢量C
如上图所示,利用Vector_2D类,可以计算出_ac_V 与_bc_V 的叉乘结果
var cr
4000
ossNum:Number = _ac_V.cross(_bc_V);
得到的 crossNum是小于零的。
同理_ad_V 与_bd_V 的叉乘结果是:
crossNum = _ad_V.cross(_bd_V);
crossNum大于零。
继续推测,得到一个方法:
对于任意一个点P,建立矢量tP_V来记录这个点的坐标,算出 点pA到点P的矢量tA_V 和 点pB到点P的矢量tB_V,再计算出这两个矢量的叉乘
crossNum = tA_V.cross(tB_V);(不能写成 tB_V.cross(tA_V) )
if(crossNum < 0){
//说明P点在直线AB的右上侧
}else{
//说明P点在直线AB的左下侧
}
演示代码如下:
这个例子是用来说明矢量运算可以快速判定一点在直线的哪一侧。
如上图所示,直线是从pA到pB的直线AB。下面的工作是构建一个方法,来判断某点在这条直线AB的左下侧还是右上侧。
如上图所示,pC点就在直线AB的右上侧,而pD点就在直线AB的左下侧。
这里要用矢量运算来解决这个问题,所以需要用到2D空间的矢量类,这个类:Vector_2D.as在此处http://www.cnblogs.com/vilyLei/articles/1567703.html可以找见。
下面用的Vector_2D类都指的是这个矢量类,每个Vector_2D类实例的方法都是这个类中已有的方法。
注:这里的矢量指的是数学或物理上的矢量,不是cs4中的Vector,它也叫向量。当然有很多东西可以在逻辑上表示为矢量,例如rgb颜色。
首先定义四个矢量对象来记录四个位置(pA,pB,pC,pD四个点)
//定义四个点矢量来记录四个点的相应位置
private var _a_V:Vector_2D = new Vector_2D(196,123);
private var _b_V:Vector_2D = new Vector_2D(370,230);
private var _c_V:Vector_2D = new Vector_2D(422,112);
private var _d_V:Vector_2D = new Vector_2D(159,296);
接着定义点pA到点pC的矢量,如上图pA到pC的箭头所示:
private var _ac_V:Vector_2D = null;
定义点pB到点pC的矢量,如上图pB到pC的箭头所示:
private var _bc_V:Vector_2D = null;
定义点pA到点pD的矢量,如上图pA到pD的箭头所示:
private var _ad_V:Vector_2D = null;
定义点pB到点pD的矢量,如上图pB到pD的箭头所示:
private var _bd_V:Vector_2D = null;
接下来计算出_ab_V, _bc_V, _bd_V这三个矢量:
//_c_V减去_a_V 就可以计算出点pA到点pC的矢量
_ac_V = _c_V.minusNew(_a_V);
//_c_V减去_b_V 就可以计算出点pB到点pC的矢量
_bc_V = _c_V.minusNew(_b_V);
//_d_V减去_a_V 就可以计算出点pA到点pD的矢量
_ad_V = _d_V.minusNew(_a_V);
//_d_V减去_b_V 就可以计算出点pB到点pD的矢量
_bd_V = _d_V.minusNew(_b_V);
现在来做一个测试,需要用到矢量叉乘,即Vector_2D类的cross(...)方法。
这里简要介绍一下叉乘。对于2D矢量的叉乘最后得到的一定是一个数字,它可能大于零,可能等于零,也可能小于零
如果两个矢量的方向夹角是180度/0度的时候,它们的叉乘值一定是等于零(当然在计算机中可能是 0.0001),对应的数学公式为A x B = |A|*|B|*sin(angle)
一定要记住叉乘不遵循交换律。
例如矢量A×矢量B=矢量C
设想矢量A沿小于180度的角度转向矢量B
将右手的四指指向矢量A的方向,右手的四指弯曲代表上述旋转方向,则伸直的拇指指向它们的叉乘得到的矢量C
如上图所示,利用Vector_2D类,可以计算出_ac_V 与_bc_V 的叉乘结果
var cr
4000
ossNum:Number = _ac_V.cross(_bc_V);
得到的 crossNum是小于零的。
同理_ad_V 与_bd_V 的叉乘结果是:
crossNum = _ad_V.cross(_bd_V);
crossNum大于零。
继续推测,得到一个方法:
对于任意一个点P,建立矢量tP_V来记录这个点的坐标,算出 点pA到点P的矢量tA_V 和 点pB到点P的矢量tB_V,再计算出这两个矢量的叉乘
crossNum = tA_V.cross(tB_V);(不能写成 tB_V.cross(tA_V) )
if(crossNum < 0){
//说明P点在直线AB的右上侧
}else{
//说明P点在直线AB的左下侧
}
演示代码如下:
package { /**//** * Copyright (C) 2009-2010 Vily * * @class name(类名): TestLineSideMain * * @author(创建人): Vily * * @version(版本): v1.1 * * @create date(创建日期): 2009-9-16 * * @purpose(对此类实现的功能的描述):TestLineSideMain文档类 * * @public properties(公开的属性): None. Static constants only. * @public methods(公开的方法): * TestLineSideMain( ) - Constructor. * */ import flash.display.Sprite; import org.vily.primitives.Vector_2D; public class TestLineSideMain extends Sprite{ //定义四个点矢量来记录四个点的相应位置 private var _a_V:Vector_2D = new Vector_2D(196,123); private var _b_V:Vector_2D = new Vector_2D(370,273); private var _c_V:Vector_2D = new Vector_2D(422,112); private var _d_V:Vector_2D = new Vector_2D(159,296); //是个测试用的矢量 private var _ac_V:Vector_2D = null; private var _bc_V:Vector_2D = null; private var _ad_V:Vector_2D = null; private var _bd_V:Vector_2D = null; public function TestLineSideMain(){ init(); } /**//** * 系统程序初始化入口 */ private function init():void{ trace("init"); initObj(); } /**//** * 初始化非显示对象 */ private function initObj():void{ //_c_V减去_a_V _ac_V = _c_V.minusNew(_a_V); //_c_V减去_b_V _bc_V = _c_V.minusNew(_b_V); //_d_V减去_a_V _ad_V = _d_V.minusNew(_a_V); //_d_V减去_b_V _bd_V = _d_V.minusNew(_b_V); var crossNum:Number = _ac_V.cross(_bc_V);//crossNum小于零 crossNum = _ad_V.cross(_bd_V);//crossNum大于零 //判定任意点tP_V在直线的左下侧还是右上侧 var tP_V:Vector_2D = new Vector_2D(Math.random()*400,Math.random()*400); var tA_V:Vector_2D = tP_V.minusNew(_a_V); var tB_V:Vector_2D = tP_V.minusNew(_b_V); crossNum = tA_V.cross(tB_V); if(crossNum < 0){ trace("在右上侧"); }else{ trace("在左下侧"); } } } }
相关文章推荐
- 利用矢量计算快速判定一点在直线的哪一侧
- sharepoint 2010 list利用datatable聚合函数快速计算
- 【人脸检测:Haar】利用积分图像法快速计算Haar特征(二)
- 利用积分图像法快速计算Haar特征
- 如何计算空间一条直线外一点到这条直线的垂足点坐标
- 利用Python进行数据分析(6) NumPy基础: 矢量计算
- 【图像处理】利用积分图像法快速计算Haar特征
- 利用虚拟机快速搭建N个分布式计算节点服务器
- 利用递推快速计算方差和均值
- 利用积分图像法快速计算Haar特征
- 利用积分图像法快速计算Haar特征
- 二、利用积分图像法快速计算Haar特征
- 【Paper】利用积分图像法快速计算Haar特征
- 利用“三角化”计算行列式快速求解程序(验证过很多题目的,绝对准确)
- 【图像处理】利用积分图像法快速计算Haar特征
- Numpy基础 --数组和矢量计算 利用Python进行数据分析读书笔记
- python利用地图两个点的经纬度计算两点间距离
- 利用阿里云提供的镜像快速更换本地的yum源
- C++上机报告 利用公式计算π=4(1-1/3+1/5-1/7+1/9-...)的近似值,直到括号中最后一项的绝对值小于0.000001为止。
- 利用JS代码快速获得知网论文作为参考文献的引用文本