点的空间查询纠错

点的空间查询纠错

​ 作者在两个星期前提出了以下问题,并做了解答,可是千算万算还是出错了,细究每一行代码才知道是之前的解决问题出错了。

​ 问题回顾:点的空间查询

​ 在做空间的点分类时,需要查询:(三维空间中)某一范围内到某条边两个端点p1、p2的距离小于这条边长l的所有点。因为边有方向,所以范围规定为:从p1的垂直平面和p2的垂直平面之间。

详情:p1(x0,y0,z0)、p2(x1,y1,z1)边长l,范围是如图所示阴影。
在这里插入图片描述
图1 求解范围:橙色

出错原因:
查找:√l 范围内的点 不只是绿色,还包括多余的点(深绿色),如图所示
在这里插入图片描述
图2 错误未考虑范围深绿色(已经考虑了嫩绿色)

作者思路:

因为我们只想要 橙色部分的点, 先扩大筛选范围根号l,是为了 先考虑蓝色区域 再根据到中心点距离小于半径 剩下的公共区域。

在这里插入图片描述
图3 多考虑根号l 是为了蓝色部分

可是,多出了上图的嫩绿色深绿色 怎么办?

点的空间查询中已经解决了,嫩绿色,对于深绿色,作者的解法如下。
在这里插入图片描述

图4 钝角示意图

由图上可知,深绿色区域内,一定会形成钝角三角形,只要判断三个点围成的三角形是否是钝角三角形即可排除绿色区域。

由上我们就求出了,橙色区域的所有点。

该方法的C++实现为:

#include<Eigen/Dense>
#define M_PI 3.1415926
typedef Eigen::Vector3d Point;

//求角度
double getDegAngle(Point p1, Point p2, Point p3) {
	Eigen::Vector3d v1 = p2 - p1;
	Eigen::Vector3d v2 = p3 - p1;
	//one method, radian_angle belong to 0~pi
	//double radian_angle = atan2(v1.cross(v2).transpose() * (v1.cross(v2) / v1.cross(v2).norm()), v1.transpose() * v2);
	//another method, radian_angle belong to 0~pi
	double radian_angle = atan2(v1.cross(v2).norm(), v1.transpose() * v2);
	if (v1.cross(v2).z() < 0) {
		radian_angle = 2 * M_PI - radian_angle;
	}
	return radian_angle * 180 / M_PI;
}

//待求点p
Point_3 p;
std::vector<Point_3>ps;
//已知直线为line 两个端点为:line[0]、line[1]
std::list<Point_3> line;
//这条边的长度
float line_len = std::sqrt(std::abs(line[0].x() - line[1].x())*std::abs(line[0].x() - line[1].x()) + std::abs(line[0].y() - line[1].y())*std::abs(line[0].y() - line[1].y()) + std::abs(line[0].z() - line[1].z())*std::abs(line[0].z() - line[1].z()));
//计算p到点line[0]的距离
float r0= std::sqrt(std::abs(p.x() - line[0].x())*std::abs(p.x() - line[0].x()) + std::abs(p.y() - line[0].y())*std::abs(p.y() - line[0].y()) + std::abs(p.z() - line[0].z())*std::abs(p.z() - line[0].z()));
//计算p到点line[1]的距离
float r1 = std::sqrt(std::abs(p.x() - line[1].x())*std::abs(p.x() - line[1].x()) + std::abs(p.y() - line[1].y())*std::abs(p.y() - line[1].y()) + std::abs(p.z() - line[1].z())*std::abs(p.z() - line[1].z()));
		if (r0 <= line_len*1.41421) {
			//在球心为line[0]半径为√line_len半球内
			if ( r1<= line_len*1.41421) {
				//在球心为line[1]半径为√line_len半球内
				if (r0<line_len|| r1<line_len) {
					//在line[0]所在的l半球内或在line[1]所在的l半球内

          						//在line[0]所在的l半球内或在line[1]所在的l半球内
						//因为区域内的点 围成的三角形应该是锐角,所以判断,R1和R2小于等于len
						float angle1=getDegAngle(Point(line[1].x(), line[1].y(), line[1].z()), Point(line[0].x(), line[0].y(), line[0].z()), Point(p.x(), p.y(), p.z()));
						float angle2 = getDegAngle( Point(line[0].x(), line[0].y(), line[0].z()), Point(line[1].x(), line[1].y(), line[1].z()), Point(p.x(), p.y(), p.z()));
						if((angle1<=90||(angle1 >= 270&& angle1 <= 360))&& (angle2 <= 90 || (angle2 >= 270 && angle2 <= 360)))
						{
              std::cout<<p<<"is in area"<<std::endl;
              ps.push_back(p);
						}
				}
				
			}
		}

该方法的优缺点:

优:只需要计算三个重要的数:line_len、r0、r1,剩下的就是比较

缺点:没有进行空间检索筛选,如果空间中涉及的点很多很多,需要从第一个点开始 到最后一个点查找,那么计算量会非常大,目前还没有直接从坐标入手考虑是否在范围内的方法。

注:萌新投稿,轻喷。有疑问,请私聊

下的就是比较

缺点:没有进行空间检索筛选,如果空间中涉及的点很多很多,需要从第一个点开始 到最后一个点查找,那么计算量会非常大,目前还没有直接从坐标入手考虑是否在范围内的方法。

注:萌新投稿,轻喷。有疑问,请私聊

更正完毕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值