首页 > 其他分享 >判断点在形状里,点在线段上

判断点在形状里,点在线段上

时间:2024-05-24 18:56:02浏览次数:27  
标签:p2 判断 多边形 pointTmp 线段 形状 p1 inOrNot

/************************************************************************
函数名 :		OnSegment
功能描述:	判断点q是否在p1和p2的线段上(调试用)
输入参数:	p1  线段端点1;   p2  线段端点2;  q 要判断的点;
输出参数:	无
返回值 :		ture 点在线段上;   false 点不在线段上
************************************************************************/
bool ObstacleDetector::OnSegment(pcl::PointXYZINormal p1, pcl::PointXYZINormal p2, pcl::PointXYZINormal q)
{
	// 在X_Z坐标系下,求向量q->p1,用点sta1表示
	pcl::PointXYZINormal sta1;
	sta1.x = p1.x - q.x;
	sta1.z = p1.z - q.z;

	// 求向量q->p2,用点sta2表示
	pcl::PointXYZINormal sta2;
	sta2.x = p2.x - q.x;
	sta2.z = p2.z - q.z;

	// 求向量sta1与sta2的叉积。意义:>0 sta1在sta2的顺时针方向;  <0 sta1在sta2的逆时针方向; =0 sta1和sta2共线(同向或反向)
	float crossPro = sta1.x * sta2.z - sta2.x * sta1.z;

	// 求向量sta1与sta2的点积。意义:如果叉积为0,那么点积≤0,代表q点在在线段p1,p2上。
	float dotPro = sta1.x * sta1.x + sta1.z * sta2.z;

    return (0 == Fcmp(crossPro)) && (0 >= Fcmp(dotPro));
}

  

/************************************************************************
函数名 :		Fcmp
功能描述:	三态函数,判断 x 在eps精度下的大小关系
输入参数:	x 要判断的float值
输出参数:	无
返回值 :		0 x和0相等;   -1 x小于0;   1 x大于0
************************************************************************/
int ObstacleDetector::Fcmp(float x)
{
    if(fabs(x) < 1e-6)
	{
		return 0;
	}
    else
    {
    	return x < 0 ? -1 : 1;
    }
}

  

/************************************************************************
函数名 :        InOctagon
功能描述:    判断点是否在多边形内(xz二维平面判断,使用射线法)
输入参数:    pointTmp 要判断的点;sectionV 多边形的顶点;inYMin 切片的y值;
            inXMin 切片顶点的x轴最小值
            inXMax 切片顶点的x轴最大值
            inZMin 切片顶点的z轴最小值
            inZMax 切片顶点的z轴最大值
输出参数:    无
返回值 :        ture 点在多边形内;   false 点不在多边形内
************************************************************************/
bool ObstacleDetector::InOctagon(pcl::PointXYZINormal& pointTmp, std::vector<pcl::PointXYZINormal>& sectionV, float inYMin, float inXMin, float inXMax, float inZMin, float inZMax)
{
    bool inOrNot = false;    // 是否在切片之内
    // 判断点是否在切片之后,考虑切片厚度
    inYMin += CLOUD_SLICE_STEP;
    // 用原y轴信息比较筛选掉y轴不符合的点,再筛选掉x轴、z轴极值外的点
    if(inYMin < pointTmp.normal_y && inXMin < pointTmp.x && inXMax > pointTmp.x && inZMin < pointTmp.z && inZMax > pointTmp.z)
    {
        // 投影后的八边形已变不规则八边形,适用射线法判断是否在图形内
        pcl::PointXYZINormal p1, p2; //多边形一条边的两个顶点
        int maxIndexShape = sectionV.size() - 1;
        for(int i=0, j = maxIndexShape; i <= maxIndexShape; j = i++)
        {
            p1 = sectionV[i];
            p2 = sectionV[j];
#if 0
            if(OnSegment(p1, p2, pointTmp))
            {
                inOrNot = true; //点在多边形一条边上
                break;
            }
            else
            {
                //前一个判断pointTmp.z在 p1和p2之间
                //后一个判断被测点 在 射线与边交点 的左边
                if( (0 < Fcmp(p1.z - pointTmp.z) != 0 < Fcmp(p2.z - pointTmp.z)) &&
                    0 > Fcmp(pointTmp.x - (pointTmp.z - p1.z) * (p1.x - p2.x) / (p1.z - p2.z) - p1.x))
                {
                    inOrNot = !inOrNot;    // 该点在线段左侧次数为奇数,则在多边性内部;如果为偶数,则在外部。(通过该点水平向右作射线,通过射线和多边形边界的交点数奇偶判断是否在多边形内部)
                }
                else
                {
                    // 射线不与多边形相交。nothing
                }
            }
#endif
            if((0 < Fcmp(p1.z - pointTmp.z)) != (0 < Fcmp(p2.z - pointTmp.z)))
            {
                // 如果pointTmp.z在 p1和p2之间 ,继续判断
                // 计算pointTmp.x在线段p1->p2哪边:edgeV > 0, 在线段右边;   =0 在线段上;   <0 在线段左侧。
                int edgeV = Fcmp(pointTmp.x - (pointTmp.z - p1.z) * (p1.x - p2.x) / (p1.z - p2.z) - p1.x);
                if(0 < edgeV)
                {
                    // 通过该点水平向右作射线,肯定不和线段p1->p2相交。nothing
                }
                else if(0 > edgeV)
                {
                    inOrNot = !inOrNot;    // 该点在线段左侧次数为奇数,则在多边性内部;如果为偶数,则在外部。(通过该点水平向右作射线,通过射线和多边形边界的交点数奇偶判断是否在多边形内部)
                }
                else
                {
                    // =0 , 在线段上
                    inOrNot = true;
                    break;
                }
            }
            else
            {
                // 如果pointTmp.z不在 p1和p2之间。通过该点水平向右作射线,肯定不和线段p1->p2相交。nothing
            }

        }
    }
    else
    {
        // 点在切片前面,不考虑该点。nothing
    }

    return inOrNot;
}

 

标签:p2,判断,多边形,pointTmp,线段,形状,p1,inOrNot
From: https://www.cnblogs.com/gaara-zhang/p/18211553

相关文章

  • [USACO06DEC] Wormholes G(spfa判断环)
    [USACO06DEC]WormholesG题目背景英文题面见此链接题目描述John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有m......
  • 线段(线性dp)
     题目链接:https://www.luogu.com.cn/problem/P3842思路:f[i][0]表示走完第i行且停在第i行的左端点最少用的步数f[i][1]同理,停在右端点的最少步数。那么转移就很简单了,走完当前行且停到左端点,那么一定是从右端点过来的,那么从上一行左端点转移的话就是f[i][0]=abs(上一行左端......
  • 判断日期是否在7天之内
    判断日期是否在7天之内Datedate=newDate();//获取当前时间Dates00=(Date)pageData.get("addTime");//获取需要比较的目标时间Calendarcalendar=Calendar.getInstanc......
  • 线段树模板
    一、模板#definelc(p)p<<1//左孩子#definerc(p)p<<1|1//右孩子constintMAX=5e5+5;//数列元素最大个数lln,m,w[MAX];//n--数列元素个数;m--操作数;w[i]--第i个元素的值struct{intl,r;llsum,tag;}t......
  • 线段树扩展
    首先是动态树,以数列操作为例点击查看代码#include<bits/stdc++.h>#definelsontr[id].l#definersontr[id].rusingnamespacestd;constintN=1e6+20;inta[N];structnode{ intl,r,sum;}tr[N<<2];intn,m;intnum;intrt;voidupdate(int&id,intl,intr,i......
  • 判断两个数的最大公约数
    ​常见点击查看代码#include<bits/stdc++.h>usingnamespacestd;intgcd(inta,intb){returnb?gcd(b,a%b):a;}intmain(){inta,b,c;while(1){cout<<"输入两个数字求最大公约数"<<endl;cin>>a>>b;......
  • hdu4027(线段树区间操作)
    Problem-4027(hdu.edu.cn)许多邪恶的战舰在战斗前排成一排。我们的指挥官决定使用我们的秘密武器来消灭战列舰。每艘战列舰都可以标记为耐力值。对于我们秘密武器的每一次攻击,它都可能降低连续部分战列舰的续航能力,使它们的续航力达到其原始续航力值的平方根。在我们的秘密武......
  • Linux 中 如何判断每一行的数据都是相同的
     001、Linux中如何判断每一行的数据都是相同的 [root@PC1test2]#lsa.txt[root@PC1test2]#cata.txt##测试数据aabbccaabbccaabbccaakkccaabbccaabbcc[root@PC1test2......
  • 判断使用的是 x11 还是 wayland
    date:2024-05-20之前的判断方式是运行命令echo"$XDG_SESSION_TYPE"来查看环境变量的值,如果返回的是wayland则说明用的wayland,如果返回的是x11说明用的x11。但是,如果返回的是tty则不能说明是哪个。例如通过ssh连接到使用x11的远程主机,会返回tty。ps如何判断......
  • oracle的非空判断
    oracle的非空判断参考:oracle的非空字符串判断-CSDN博客在oracle中,空字符串当null处理,所以想找到空字符串,就可以用isnull来获取获取非空字段,就直接用isnotnull来获取用“=''”或者“!=''”来作为条件的话,就会找不到结果......