判断点是否在线段上

代码一

原文地址:http://blog.sina.com.cn/s/blog_4c8bb86b0100k2lc.html

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
 
/// <summary>
    /// 点是否点中了线
    /// </summary>
    class ClickOnLine
    {
        /// <summary>
        /// 点是否在直线上
        /// </summary>
        /// <param name="ptCurr"></param>
        /// <param name="pStart">线的起点</param>
        /// <param name="pEnd"></param>
        /// <param name="allowErr">容许误差</param>
        /// <returns>在线上返回true</returns>
        public static bool IsPtInLine(Point ptCurr, Point pStart, Point pEnd, int allowErr)
        {
            CCADCoord pt = new CCADCoord(ptCurr.X, ptCurr.Y);
            CCADCoord p1 = new CCADCoord(pStart.X, pStart.Y);
            CCADCoord p2 = new CCADCoord(pEnd.X, pEnd.Y);
            int n = PtInPolyLine(pt, p1, p2, allowErr);
            if (n == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 判断给定点 pt 是否在折线上: 1:在折线上;0:不在折线上
        /// </summary>
        /// <param name="pt">待判断的点</param>
        /// <param name="polyline">折线坐标列表</param>
        /// <param name="allowError">容差值(该值应包括线的宽度,如为零则表示精确匹配)</param>
        /// <returns>1:在折线上;0:不在折线上</returns>
        public static int PtInPolyLine(CCADCoord pt, CCADCoord l1, CCADCoord l2, double allowError)
        {
            //如果选择的点与当前点重合
            if (Math.Abs(l2.X - pt.X) <= allowError && Math.Abs(l2.Y - pt.Y) <= allowError)
                return 1;
            if (Math.Min(l1.X, l2.X) <= pt.X && Math.Min(l1.Y, l2.Y) <= pt.Y &&
            Math.Max(l1.X, l2.X) >= pt.X && Math.Max(l1.Y, l2.Y) >= pt.Y)
            {
                //精确匹配判断的话
                if (Math.Abs(allowError - 0.0) <= 0.0001)
                {
                    #region 该方法理论上是100%可行的,但是在实际过程中,用户的点击往往是模糊的,大概的,所以该方法就会出现问题
                    CCADCoord tp1 = new CCADCoord(l2.X - pt.X, l2.Y - pt.Y);  //矢量减法
                    CCADCoord tp2 = new CCADCoord(pt.X - l1.X, pt.Y - l1.Y);  //矢量减法
                    if (Math.Abs(Math.Abs(tp1.X * tp2.Y - tp2.X * tp1.Y) - 0.0) <= 0.00000001)         //矢量叉乘,平行四边形的面积
                        return 1;
                    #endregion
                }
                else
                {
                    if (Math.Abs(l2.X - l1.X) <= allowError && Math.Abs(l2.X - pt.X) <= allowError)
                        return 1;
                    if (Math.Abs(l2.Y - l1.Y) <= allowError && Math.Abs(l2.Y - pt.Y) <= allowError)
                        return 1;
                    if (DistancePointToSegment(pt, l1, l2) <= allowError)
                        return 1;
                    //如果点到线段的距离在容差范围内,则选取成功
                    if (DistancePointToSegment(pt, l1, l2) <= allowError)
                        return 1;
                }
            }

            return 0;
        }
        /// <summary>
        /// 点到线段的距离公式(利用平行四边形的面积算法,非常牛叉)
        /// </summary>
        /// <param name="P">目标点</param>
        /// <param name="A">线段端点A</param>
        /// <param name="B">线段端点B</param>
        /// <returns></returns>
        public static double DistancePointToSegment(CCADCoord P, CCADCoord A, CCADCoord B)
        {
            //计算点到线段(a,b)的距离  
            double l = 0.0;
            double s = 0.0;
            l = DistancePointToPoint(A, B);
            s = ((A.Y - P.Y) * (B.X - A.X) - (A.X - P.X) * (B.Y - A.Y)) / (l * l);
            return (Math.Abs(s * l));
        }
        /// <summary>
        /// 点到点的距离
        /// </summary>
        /// <param name="ptA"></param>
        /// <param name="ptB"></param>
        /// <returns></returns>
        private static double DistancePointToPoint(CCADCoord ptA, CCADCoord ptB)
        {
            return Math.Sqrt(Math.Pow(ptA.X - ptB.X, 2) + Math.Pow(ptA.Y - ptB.Y, 2));
        }
        /// <summary>
        /// 坐标
        /// </summary>
        public struct CCADCoord
        {
            public double X;
            public double Y;
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            public CCADCoord(double x, double y)
            {
                X = x;
                Y = y;
            }
        }
    }
 

代码二:

原文地址:http://www.cnblogs.com/dxp498688071/archive/2011/03/03/1970217.html

/*
判断点是否在线段上:

  设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:( Q - P1 ) × ( P2 - P1 ) = 0 且 Q 在以 P1,P2为对角顶点的矩形内。前者保证Q点在直线P1P2上,后者是保证Q点不在线段P1P2的延长线或反向延长线上,对于这一步骤的判断可以用以下过程实现:

  ON-SEGMENT(pi,pj,pk)

  if min(xi,xj) <= xk <= max(xi,xj) and min(yi,yj) <= yk <= max(yi,yj)

  then return true;

  else return false;

  特别要注意的是,由于需要考虑水平线段和垂直线段两种特殊情况,min(xi,xj)<=xk<=max(xi,xj)和min(yi,yj)<=yk<=max(yi,yj)两个条件必须同时满足才能返回真值。

*/

#include<stdio.h>
 
struct point
{
 double x,y;
};
double direction( point p1,point p2,point p )
{
    return ( p1.x -p.x )*( p2.y-p.y) -  ( p2.x -p.x )*( p1.y-p.y)   ;
}
 
int on_segment( point p1,point p2 ,point p )
{
    double max=p1.x > p2.x ? p1.x : p2.x ;
    double min =p1.x < p2.x ? p1.x : p2.x ;
 double max1=p1.y > p2.y ? p1.y : p2.y ;
    double min1=p1.y < p2.y ? p1.y : p2.y ;
    if( p.x >=min && p.x <=max && 
  p.y >=min1 && p.y <=max1 )
        return 1;
    else
        return 0;
}
 
int main()
{
 point p1,p2,q;
 while( 1 )
 {
  scanf("%lf %lf %lf %lf %lf %lf",&q.x ,&q.y ,&p1.x ,&p1.y ,
   &p2.x ,&p2.y  ) ;
  if( !on_segment( p1,p2,q ) )
  {
   printf("no\n");
   continue;
  }
  if( direction( q,p1,p2 )==0 )
   printf("yes\n");
  else
   printf("no\n");
 }
 return 0;
}

代码三

原文地址:http://blog.csdn.net/lishiming0308/article/details/5537441

// 判断一点是否在指定线段中  

       //线段ab,a(ax,ay),b(bx,by),p(x,y);判断点p是否在线段ab上 
        public static   bool PtInSegment(double x, double y, double ax, double ay, double bx, double by)
        {
            #region
            /*利用斜率是否相同进行判断
            if (((x <= ax && x >= bx) || (x <= bx && x >= ax)) && ((y <= ay && y >= by) || (y <= by && y >= ay)))
            {
                if (ax == bx || ay==by)
                    return true;
                double result = (by - ay) / (bx - ax) - (y - ay) / (x - ax);

                return Math.Abs(result) < 0.1;

            }
            return false;
             * */
            #endregion
            #region
           
            //利用三角形定理判断 两边之和大于第三边
            //线段ap的长度
            double a_p = Math.Sqrt(Math.Pow(Math.Abs(ax - x), 2) + Math.Pow(Math.Abs(ay - y), 2));
            //线段b_p的长度
            double b_p = Math.Sqrt(Math.Pow(Math.Abs(bx - x), 2) + Math.Pow(Math.Abs(by - y), 2));
            //线段ab的长度
            double a_b = Math.Sqrt(Math.Pow(Math.Abs(ax - bx), 2) + Math.Pow(Math.Abs(ay - by), 2));
            //线段a_p和线段b_p的和
            double a_p_b = a_p + b_p;
            if (a_p_b - a_b < 0.5)
            {
                return true;
            }
            else
            {
                return false;
            }
           
            /*
            #endregion
            //利用向量的叉积进行判断,确定不可以进行模糊匹配
            //p(x,y),a(ax,ay),b(bx,by)
            //线段ab的向量表示(bx-ax,by-ay)
            //线段ap的向量表示(x-ax,y-ay)
            //向量ab和向量ap的叉积abp=(bx-ax)*(y-ay)+(by-ay)*(x-ax)
            double abp = (bx - ax) * (y - ay) -(by - ay) * (x - ax);
            double  MaxX = Math.Max(ax, bx);
            double MinX = Math.Min(ax, bx);
            double MaxY = Math.Max(ay, by);
            double MinY = Math.Min(ay, by);
            ax = MinX; bx = MaxX; ay = MinY; by = MaxY;
            if (ax <= x &&x<= bx && ay <= y &&y<= by )
            {
                if(Math .Abs (abp )==0)
                return true;
            }
            return false ;
            */

        }


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值