OSG选取点云坐标不准的解决办法
一、默认的相机和所有模型求交的方式
1.1 传统的模型与屏幕点求交的方法如下:
osgViewer::View* viewer = dynamic_cast<osgViewer::View*>(&aa);
if ( viewer )
{
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector =
new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
osgUtil::IntersectionVisitor iv( intersector.get() );
viewer->getCamera()->accept( iv ); if ( intersector->containsIntersections() )
{
osgUtil::LineSegmentIntersector::Intersection result = *(intersector->getIntersections().begin());
doUserOperations( result );
}
}
从上面可以知道通过点击屏幕上一点其实就是构造一根线,然后将这条线和场景中的模型进行碰撞检测,会生成一个结果集,通过遍历结果集就可以处理相交的点,默认结果集中第一个点就是最近的相交点
但是在osg和点云结合的程序中,通过线和点云求交是几乎没有交点的,所以我们需要重写与点云模型的求交器,下面的PointIntersector求交器就是派生自osgUtil::LineSegmentIntersector,然后重写求交逻辑的点云模型求交器,主要参考的就是OpenSceneGraph Cookbook,下面就是点云模型和屏幕点求交的用法:
1.2、OSG中与点云模型选点的方法:
osg::ref_ptr<PointIntersector> intersector = new PointIntersector(osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
osgUtil::IntersectionVisitor iv(intersector.get());
viewer->getCamera()->accept(iv); if (intersector->containsIntersections())
{
//osg::Vec3d worldpoint = CRealInteractionUtil::getNeartestPoint(intersector, osg::Vec2f(ea.getX(), ea.getY()), transformMatrix*vpw);
PointIntersector::Intersection result = *intersector->getIntersections().begin();
//....
9 }
以上通过osg里面重写的求交器可以与场景中的点云模型进行求交,然后求得相交点的坐标,求交的原理大概就是PointIntersector求交器首先构造一个管状空间,此空间参数可以设置,默认半径是两米,所以求交的结果集是屏幕点生成线,然后通过线扩充成圆柱,根据此圆柱和点云模型求得结果集,结果集会包括屏幕点附近的点,此时如何知道结果集中哪个点时认为认为的选中点呢?默认结果集中第一个结果就是最近的相交点
二、指定的模型节点和相机求交的方式
通过以上方式也可以求得和点云求交选中点的坐标,但如果是单独与osg中的点云节点求交,此时就不能通过屏幕点构造求交器了,原因如下:
camera中的点都是基于屏幕的二维坐标,用屏幕点构造求交器也是二维坐标,所以两者可以进行求交得出碰撞点
特定节点中的点可能是基于世界坐标系的三维点,所以求交器也得是世界坐标系的三维点来构造的,如果用屏幕点构造求交器去求交就会导致没结果,因为坐标系没有统一起来
所以需要先构造三维场景中的一个开始点和一个结束点构造求交器,如下:
osgViewer::View* viewer = dynamic_cast<osgViewer::View*>(&aa);
if (!viewer)
{
return false;
}
osg::Matrixd Matrix_V = viewer->getCamera()->getViewMatrix();//观察矩阵-将对象由世界坐标变换为像机坐标
osg::Matrixd Matrix_P = viewer->getCamera()->getProjectionMatrix();//投影矩阵-投影到屏幕
osg::Matrixd Matrix_W = viewer->getCamera()->getViewport()->computeWindowMatrix();//视口矩阵-将投影坐标变换到二维视口
osg::Matrixd vwp = Matrix_V*Matrix_P*Matrix_W; //求得 世界到屏幕的矩阵
osg::Matrixd inverseVPW = osg::Matrixd::inverse(vwp);
osg::Vec3d world_sta = osg::Vec3d(ea.getX(), ea.getY(), )*inverseVPW;//屏幕坐标转成世界坐标
osg::Vec3d world_end = osg::Vec3d(ea.getX(), ea.getY(), )*inverseVPW;
osg::ref_ptr<PointIntersector> intersector = new PointIntersector(world_sta, world_end);
osgUtil::IntersectionVisitor iv(intersector.get());
m_pDataManagerSingleton->getVectorNode()->accept(iv);
if (!intersector->containsIntersections())
{
return false;
}
osg::Vec3d worldpoint = CRealInteractionUtil::getNeartestPoint(intersector, osg::Vec2f(ea.getX(), ea.getY()), vwp);
PointIntersector::Intersection result = *(intersector->getIntersections().begin());
osg::Vec3d CRealInteractionUtil::getNeartestPoint(PointIntersector* intersector, osg::Vec2f& curScreenXY, osg::Matrixd& vpw)
{
vector<osg::Vec3d> points;
for (osgUtil::LineSegmentIntersector::Intersections::iterator iter = intersector->getIntersections().begin(); iter != intersector->getIntersections().end(); iter++)
{
points.push_back(iter->getWorldIntersectPoint());
}
float distance = ;
osg::Vec3d curNeartestPoint;
for (int i = ; i < points.size(); i++)
{
osg::Vec3d tempPoint = points[i] * vpw;
osg::Vec2f tempScreenXY = osg::Vec2f(tempPoint[], tempPoint[]);
float lenth = (tempScreenXY - curScreenXY).length2();
if (lenth < distance)
{
distance = lenth;
curNeartestPoint = points[i];
}
}
return curNeartestPoint;
}
以上代码就是通过三维中的一个开始点和一个结束点构造一个柱状空间与点云模型求交,此时会求出很多个相交的点结果,如果我们默认也认为结果集的第一个就是正确的点,那就错了,开始我也是如此使用的,但是始终觉得会选偏,就是选不准,返回的第一个点总是在屏幕点附近,而不是正中心的那个点,即使我把半径设为很小,还是会偏,因为求交的结果集是在一个圆柱里面的,都是杂乱无章的,我们是无法判断哪个是正确的那个点的,此时我们可以将结果集的三维点先投影到屏幕中,通过与屏幕点的点再次求一个最近点,此时这个点的三维坐标就是正确的点云求交点了
OSG选取点云坐标不准的解决办法的更多相关文章
- PHP下的浮点运算不准的解决办法
首先看一段代码: 首先看一段代码: <?php $a = 0.1; $b = 0.7; var_dump(($a + $b) == 0.8); 打印出来的值居然为 boolean false P ...
- pod导入融云路径报错解决办法
build Settings中搜索sear Search Patchs下点开Library Search Paths 将$(inherited)"$(SRCROOT)/Pods"分 ...
- 利用jink调试程序,时间不准的解决办法
前几天,做工程,遇到了利用jlink的SWD的模式调试程序,定时器延时不准的问题,上网搜了好多,终于找到了问题所在,感谢万能的网友.时间不对是因为Keil的设置问题. 以下是转自网友: 一.先说说仿真 ...
- WInforn中设置ZedGraph的焦点显示坐标格式化以及显示三个坐标数的解决办法
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...
- 阿里云服务器被挖矿minerd入侵的解决办法
上周末,更新易云盘的时候,发现阿里云服务器CPU很高,执行 top 一看,有个进程minerd尽然占用了90%多的CPU, 赶紧百度一下,查到几篇文章都有人遇到同样问题 Hu_Wen遇到的和我最相似, ...
- 阿里云vps上mysql挂掉的解决办法
阿里云vps上mysql挂掉的解决办法 4条回复 用阿里云的vps用作blog服务器,系统很稳定,已经100多天一直运行正常,大概从上个月开始发现blog的mysql会有时挂掉,会收到短信通知.之前没 ...
- 【地图API】为何您的坐标不准?如何纠偏?
原文:[地图API]为何您的坐标不准?如何纠偏? 摘要:各种坐标体系之间如何转换?到底有哪些坐标体系?什么是火星坐标?为什么我的坐标,在地图上显示会有偏移?本文详细解答以上问题.最后给出坐标拾取工具. ...
- 在阿里云服务器上安装完成并启动Tomcat后,通过http不能访问--解决办法
在阿里云服务器上安装完成并启动Tomcat后,通过http不能访问的原因是阿里云平台为了安全设置了安全组策略,必须我们授权的端口,其他计算机才能通过http访问 解决办法:(这里以阿里轻量应用服务器为 ...
- 阿里云安装mysql后查看不到初始密码的解决办法
在阿里云安装mysql后用grep 'A temporary password' /var/log/mysqld.log命令查看MySQL初始密码,毛线都没有看到,然后直接到/var/log/mysq ...
随机推荐
- AWS CSAA -- 02 AWS - 10000 Feet Overview
004 The History Of AWS So Far 005 AWS - 10000 Foot Overview 006 AWS - 10000 Foot Overview 007 AWS - ...
- 2017年秋季个人阅读计划 ---《掌握需求过程》第二版 pdf
这学期我们学习是软件需求分析,为了扩展视野,我们老师要求精读一本书,我根据老师推荐的书籍中找到了一本,名字叫做<掌握需求过程>,我大概浏览了一下这本书,这本书论述了软件开发中的重要课题—如 ...
- 从本机构建Linux应用程序VHD映像
下图描述了总体的虚拟机映像的VHD生成,上传以及发布到 Azure 镜像市场的全过程: 具体步骤如下: 在本地计算机(Windows平台)上安装Hyper-V,并安装您所需要的虚拟机操作系统 在此操作 ...
- mac 手动卸载软件位置
系统偏爱设置 /Users/xxxxx/Library/Preferences/ xxxx 支持文件 /Users/xxxxx/Library/Application Support/xxx文件夹 数 ...
- 使用UISearchDisplayController
使用UISearchDisplayController 虽然UISearchDisplayController名字中带有controller,可他不是一个UIView相关的controller,因为, ...
- 拟牛顿 DFP matlab
function sevnn x=[1,0]'; [x,val]=dfp('fun','gfun',x) end function f=fun(x) f=100*(x(1)^2-x(2))^2+(x( ...
- Echarts使用小结
还是先来简单的了解一下Echart是什么吧? ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前 ...
- MySQL-5.6版本GTID的主从复制
mysql GTID Replication 一.GTID的概述: 1.全局事物标识:global transaction identifieds. 2.GTID事物是全局唯一性的,且一个事务对应一个 ...
- AOP:选择正确的时机进行编织
在本文中,我们将采用三种重要的实现的例子,来实践本文提出的概念.这三种 AOP 实现是 AspectJ,Spring 和 JBoss.通过比较他们在 Weave 时机方面的不同,来获得对于如何选择 W ...
- java.sql.SQLException: Incorrect string value: '\xE5\xB0‘
mysql插入中文字符报java.sql.SQLException: Incorrect string value: '\xE5\xB0‘ #原因:由于默认情况下,mysql的字符集是latin1(I ...