判断点是否在线段上

二个向量的数积有二种表达形式
1、设向量a=(x1,y1),向量b=(x2,y2)
向量a•向量b =|向量a|*|向量b|*cos
|向量a|=√(x1^2+y1^2)
|向量b|=√(x2^2+y2^2)
为二向量的夹角
2,坐标形式:向量a•向量b= x1x2+y1y2

向量积为正向量夹角小于90度,为负夹角大于90度,为0向量垂直

 

pInLineSegment.cpp

#include <math.h>
#include <float.h>

#include <iostream>
using namespace std;

typedef struct {
  double x;
  double y;
} POINT;

double pInVectorLR(POINT begin,POINT end,POINT p){
    POINT p1 = begin,p2 = end,p3=p;
    //S(P1,P2,P3)=|y1 y2 y3|= (x1-x3)*(y2-y3)-(y1-y3)*(x2-x3) 
    /*
    令矢量的起点为A,终点为B,判断的点为C, 
    如果S(A,B,C)为正数,则C在矢量AB的左侧; 
    如果S(A,B,C)为负数,则C在矢量AB的右侧; 
    如果S(A,B,C)为0,则C在直线AB上。
     */
    double s = (begin.x-p3.x)*(p2.y-p3.y) - (p1.y-p3.y)*(p2.x-p3.x);
    return s;
}
bool pInLineSegment(POINT pt,POINT begin,POINT end){
  //首先判断点是否在直线上
  double dv = pInVectorLR(begin,end,pt);
  if (fabs(dv) > FLT_EPSILON){
    return false;
  }

  ///两个向量积大于0说明向量同方向,点在直线上。小于0,方向相反,不在直线上。等于0 与开始或者结束点重合
  POINT v1={pt.x-begin.x,pt.y-begin.y};
  POINT v2={end.x-pt.x,end.y-pt.y};
  double result=0;
  result = v1.x*v2.x+v1.y*v2.y;
  if (result>=0){
    return true;
  }
  return false;
}

int main(void){
  POINT pa={0,0},pb={5,5},p1={2,2},p2={5,5},p3={10,10};

  cout<<"p1 "<<pInLineSegment(p1,pa,pb)<<endl;
  cout<<"p2 "<<pInLineSegment(p2,pa,pb)<<endl;
  cout<<"p3 "<<pInLineSegment(p3,pa,pb)<<endl;
}

 

发表评论

邮箱地址不会被公开。 必填项已用*标注