LineSegmentIntersector::Intersections中ratio含义及LineSegmentIntersector相交点说明

osgintersection例子 先说一下osgSim库,它提供虚拟仿真效果的节点工具,用于特殊效果。 这个例子中涉及到了osgSim::LineOfSight,我们就来看看这个类是干什么,从字面上可知,它 是视线、瞄准线。 DatabaseCacheReadCallback这个类继承ReadCallback,在相交的测试中,场景可能有PagedLOD ,而计算相交过程中,PagedLOD不是精度最高的节点(如地球),这样 阅读详情

osg用osgUtil库中的LineSegmentIntersector、IntersectionVisitor类来求线段和三维模型的交点。如下代码:

#include <osgViewer/Viewer>
#include <osgUtil/IntersectionVisitor>
#include <osgUtil/LineSegmentIntersector>
#include<iostream>

//创建盒子
osg::ref_ptr<osg::Geode> createBox()
{
    osg::ref_ptr<osg::Geode> geode1 = new osg::Geode;
    auto box1 = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 10.0, 8.0, 6.0));
    geode1->addDrawable(box1);

   // geode1->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 0.1, 0.1, 20)));
    return geode1;
}

int main(int argc, char *argv[])
{

    osg::ref_ptr<osgViewer::Viewer> viewer1 = new osgViewer::Viewer;
    osg::ref_ptr<osg::Group> group1 = new osg::Group;

    osg::ref_ptr<osgUtil::LineSegmentIntersector> lineSegmentIntesector = new osgUtil::LineSegmentIntersector(osg::Vec3(0, 0,15), osg::Vec3(0, 0, -15));
    osg::ref_ptr<osgUtil::IntersectionVisitor> intersectionVisitor1 = new osgUtil::IntersectionVisitor(lineSegmentIntesector);

    group1->addChild(createBox());
    group1->accept(*intersectionVisitor1.get());

    osgUtil::LineSegmentIntersector::Intersections intersections;

    //输出交点
    intersections = lineSegmentIntesector->getIntersections();
    osgUtil::LineSegmentIntersector::Intersections::iterator iter;
    for (iter = intersections.begin(); iter != intersections.end(); ++iter)
    {
        std::cout << "ratio:" << "   " << iter->ratio << "    x:" << iter->getWorldIntersectPoint().x() << "    y:" << iter->getWorldIntersectPoint().y() << "    z:" << iter->getWorldIntersectPoint().z() << std::endl;
    }

    viewer1->setSceneData(group1.get());
    viewer1->setUpViewInWindow(200, 200, 800, 600, 0);

    return viewer1->run();
}

上述代码构建了一条线段,线段起始坐标如下:

Vec3(0, 0,15)

 终点坐标如下:

osg::Vec3(0, 0, -15)

同时构建了一个长方体,长方体中心位于原点,长、宽、高、分别为:5、4、3。

效果如下(注意:为了便于观察,我使这个长方体绕X轴逆时针转动了一定角度):

                                                                图1

 上述代码的第23、24行构造了一个求交器和求交访问器对象。通过求交器和求交访问器对象相互协同合作,再通过调用第27行代码accept函数,就能求出线段和长方体的交点,结果如下:

图2 

  其中ratio含义如下:                     

        线段起点到交点之间的长度 / 线段总长度

           即:线段起点和交点之间的长度占线段总长度的比例。上例子,线段起点z坐标为15,线段在Z轴的总长度为15 -(-15) = 30,由图2知道,第1个交点的长方体z坐标为3,则第1个ratio为: 

                   ( 15 - 3 ) / 30 = 0.4

       同样地,可以算出最后一个交点的ratio为:                    

                   [ 15 - (-3 )] / 30 = 0.6

当把第27行线段的起始点、终止点坐标换成如下代码:

osg::ref_ptr<osgUtil::LineSegmentIntersector> lineSegmentIntesector = new osgUtil::LineSegmentIntersector(osg::Vec3(1, 5, 2), osg::Vec3(15, 0, -2));

则结果如下:

图3 

 则根据上面提到的计算ratio方法,线段起点z坐标为2,线段在Z轴的总长度为2 -(-2) = 4,由图3知道,第1个交点的长方体z坐标为1.2,则第1个ratio为: 

                       (2 - 1.2) / 4.0 =  0.2

同理,第2个ratio为:

                           ( 2 - 0.857143 ) / 4 = 0.285714

在平时的开发中,可以根据ratio知道交点占据整个线段z轴的比例。

      在图2中,可以看到第1、2个交点是同一个点;第3、4个交点也是同一个点,为何出现两个相同的交点?下面分析如下:

       通过断点跟进到底层源码发现:虽然长方体6个面是四边形,但OPenGl是通过绘制两个三角形来实现一个四边形的。即长方体上顶面、下底面的四边形绘制如下:

 图4

通过在for循环中循环2次绘制两个三角形从而形成四边形(四边形由两个三角形拼接而成,在底层硬件实现上,大部分多边形的绘制是分割为三角形进行绘制的,这样效率要高些)。第1次循环绘制v0v1v2(或v0v2v3)三角形,此时检测到线段和该三角形交于A点;第2次循环绘制v0v2v3(或v0v1v2)三角形,此时又检测到线段和该三角形交于A点,这就是上面交点被输出两次的原因。

       如果把上面代码的第13行改为如下:


    auto box1 = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 0.1, 0.1, 20))

即把长方体宽、高尽量小,则结果如下(注意:为了便于观察,我使这个长方体绕X轴逆时针转动了一定角度):

 图5

可以看到,长方体上顶面和直线的交点只有一个,下底面和直线的交点符合前文提到的三角形描述,输出2个相同的交点值,长方体上顶面和下底面都平行于水平面,应该说上顶面和下底面没啥区别,都应该输出2个相同的交点值才行,跟踪到LineSegmentIntersector.cpp文件的intersect函数:

void intersect(const osg::Vec3& v0, const osg::Vec3& v1, const osg::Vec3& v2)
    {


          ....... // 其它代码略
              if ((u + v) > det)
            {
                return;       // 上顶面本来应该输出2个相同交点,但有一个三角形检测,从这里返回了
            }

           ....... // 其它代码略
   }

上顶面本来应该输出2个相同交点,但上顶面有一个三角形检测时,从return返回了,导致交点没插入交点容器,里面的算法不是很懂,希望懂的人留言交流,感谢了!。

           通过测试发现,只要长方体长、宽、高小于1时,都会存在这个问题。

更多关于这个类的知识,请参考如下博文:

4-osg 拓展线段求交器(Expand LineSegmentIntersector拾取:点,线,面) 4-osg 拓展线段求交器(拾取:点,线,面) 实现功能 拓展:LineSegmentIntersector, 实现点,线,面的求交 ray: 根据near and far plane 求出frustum所截取的线段; kdTree, octree(oct tree 在LOD时再补): 加速搜索 intersection: select point, line, face and object hight light the selection object 实现思路 ray ray: 单击window 阅读详情

相关推荐

osg节点拾取 & 点击切换高亮

osg节点拾取 & 点击切换高亮。可以实现对模型的拾取以及点击切换高亮模式。

IntersectionObserver(交叉观察器)

文章目录1.IntersectionObserver1.1 observe 方法1.2 unobserve 方法1.3 disconnect 方法1.4 takeRecords 方法1.5 callback 参数2. IntersectionObserverEntry 对象3. 图片懒加载4. 元素吸顶、吸底5. 加载更多 1.IntersectionObserver IntersectionObserver可以用来自动监听元素是否进入了设备的可视区域之内,而不需要频繁的计算来做这个判断。由于可见(visi

fmk1023的博客 1万+

一文读懂:CAN总线Bus-Off的触发条件与自动恢复机制

本文详细解析CAN总线Bus-Off状态的触发条件与自动恢复机制。根据ISO 11898-1标准,当发送错误计数器(TEC)超过255时节点进入Bus-Off状态,并通过检测128次总线空闲条件实现自动恢复。文章结合实战案例,探讨硬件故障、软件配置及电磁干扰等常见触发场景,并提供快慢恢复策略与调试方法,帮助工程师快速定位并解决CAN网络故障。

rgv234567的博客 361

osgUtil::LineSegmentIntersector类源码分析(一)

osgUtil::Intersector有几个子类,如下:每个子类表示不同的求交器。所谓求交器就是判定和物体相交的类,通过这些类可以很方便的得出交点、实现拾取功能等。LineSegmentIntersector类是osgUtil::Intersector其中的一个子类,其表示直线求交器,即通过直线和三维场景中的某个物体相交,该类一般和osgUtil::IntersectionVisitor即求交访问器类一起使用,从而得出交点、实现拾取功能等。。

danshiming的博客 1255

LTspice 导入 PSpice 模型实战指南 --(解决语法兼容性与模型优化问题)

本文提供了将PSpice模型成功导入LTspice的详细实战指南。针对两者间的语法兼容性问题,文章以TI UCC23513为例,逐步讲解模型获取、符号创建、常见语法错误修改及仿真验证方法,并分享了模型优化与个人库管理技巧,帮助用户高效解决模型导入与仿真难题。

weixin_28278377的博客 823

对Palantir的本体论的理解

本体论Ontology是Palantir的整个技术架构的核心与基石,它远不止是一个数据模型,而是一个旨在对企业决策本身进行建模的“数字世界的操作系统”。

liuyukuan的专栏 1151

OSG LineSegmentIntersector进行碰撞检测

view plaincopy to clipboardprint? #include    #include    #include    #include    #include    #include    #include    #include    #include    int main()   {       osg::ref_ptr c

痞子龙3D编程 7293

ABAP BOM展开避坑指南:CS_BOM_EXPL_MAT_V2函数参数配置详解

本文深入解析了SAP ABAP开发中用于物料清单展开的核心函数CS_BOM_EXPL_MAT_V2。针对其复杂的参数配置,如CAPID、STLAN、DATUV和MEHRS,提供了详细的避坑指南和最佳实践,帮助开发者避免数据错误与性能陷阱,实现高效、准确的BOM多层展开。

pea55的博客 855

微信小程序开发笔记4—— IntersectionObserver 用法详解

看微信文档时看到这个很有趣的api,但是官方的文档和例子关于这个api的介绍都是很让人失望的,所以花了点时间了解了以下这个方法,做个记录,供参考。 简介 首先,我的理解是,这是一个观察器(废话),它用来监测目标对象与某个参照物的相交情况。什么是相交情况?通俗的说,就是两个区域有重叠(公共区域)了,类似与数学中的交集,不过这个是平面上的。 我们用官方给的一个简单的例子进行讲解:https://dev...

袁杰Jerry 2万+

雷达原理习题答案【西电】

  目前教材用的是陈老师新版的,但是,我发现课后题有一部分是之前某本书里的。答案如下【建议参看原题→查阅答案】 【原题点这里!!点这里!!】 目录跳转功能目前好像只支持网页版 文章目录% 第一章、第二章% 第三章% 第四章% 第五章% 第六章% 第七章% 第八章 % 第一章、第二章 % 第三章 % 第四章 % 第五章 % 第六章 % 第七章 % 第八章 ...

薛定谔的壳的博客 1万+

比NTP还牛逼的时间同步协议:1588v2,亚微秒级!

1588v2,又称为Precision Time Protocol Version 2,即精密时间协议的第二版本,或称为PTPv2,是一种精密时间同步协议标准,旨在实现网络中设备之间的高精度时间同步。该协议由IEEE标准组织发布,并在网络测量和控制系统中得到广泛应用。1588v2的主要目的是在计算机网络中提供高度准确的时间同步。它可用于确保不同设备之间的时钟同步,从而协调它们的操作。这对于需要协同工作的系统、无线通信基站等具有关键性的应用非常重要。

网络技术联盟站 4281

LineSegmentIntersector::Intersection结构体各成员含义

osgUtil::Intersector有几个子类,如下:每个子类表示不同的求交器。所谓求交器就是判定和物体相交的类,通过这些类可以很方便的得出交点、实现拾取功能等。LineSegmentIntersector类是osgUtil::Intersector其中的一个子类,其表示线段求交器,即通过线段和三维场景中的某个物体相交,该类一般和osgUtil::IntersectionVisitor即求交访问器类一起使用,从而得出交点、实现拾取功能等。

danshiming的博客 1333

计算图像哈希SHA-512

上述需要将lena.jpg放在当前目录下。

计算机视觉之光 961

场景交互与场景漫游-交运算与对象选取(8-1)

osg 场景解耦阿虎与场景漫游 ​​​​​​​显示位置及拾取示例

liangfei868的博客 1969

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

OSG:幼儿园篇 第六章 碰撞检测类

一.简介 osgUtil::LineSegmentIntersector 类继承自 osgUtil::Intersector 类,用于检测指定线段和场景图形之间相交情况,该类提供了一种定义 二.osgUtil::Intersector(相交类) 三.osgUtil::LineSegmentIntersector(线段相交类) 1.类定义 typed...

weixin_30716141的博客 565

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

OSG求交器(一)面求交器PlaneIntersector

OSG求交器之平面求交器

Frank的专栏 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

使用IntersectionObserver更高效的监视某个页面元素是否进入了可见窗口

比如说,你想跟踪 DOM 树里的一个元素,当它进入可见窗口时得到通知。 也许想实现即时延迟加载图片功能,或者你需要知道用户是否真的在看一个广告 banner。 你可以通过绑定scroll事件或者用一个周期性的定时器,然后再回调函数中调用元素的getBoundingClientRect()获取元素位置实现这个功能。 但是,这种实现方式性能极差,因为每次调用getBoundingClient...

weixin_34283445的博客 657

OSG入门_场景图形与OpenSceneGraph概述01

osgUtil库集合了许多用于场景图形处理和几何修改的工具; osgDB使用插件管理的架构,支持大量常见的2D图形和3D模型文件格式; osgViewer库定义了一些视口类,因而可以将OSG集成到许多视窗设计工具中。

部落阁 1820

【前端】图片懒加载的原理和三种实现方式

图片懒加载的原理和实现方法

qq_44947815的博客 2万+

OSG画折线程序函数总结

osgUtil::LineSegmentIntersector::Intersections Intersection数组 osgUtil::LineSegmentIntersector::Intersection computeIntersections(x,y,intersections) intersections得到所有相交的点 push_back()加进数组 pop_back()弹出数组

pipixiaodan的专栏 697

osgUtil::LineSegmentIntersector类源码分析(二)

osgUtil::Intersector有几个子类,如下:每个子类表示不同的求交器。所谓求交器就是判定和物体相交的类,通过这些类可以很方便的得出交点、实现拾取功能等。LineSegmentIntersector类是osgUtil::Intersector其中的一个子类,其表示线段求交器,即通过线段和三维场景中的某个物体相交,该类一般和osgUtil::IntersectionVisitor即求交访问器类一起使用,从而得出交点、实现拾取功能等。

danshiming的博客 1318

OpenSceneGraph实现的NeHe OpenGL教程 - 第四十四课

简介 这节课NeHe教我们怎么在场景中实现3D光晕的效果,光晕会在摄像机镜头对准太阳的时候就会出现,实现的原理是在光源与摄像机视点之间绘制一系列贴好纹理的四边形,并且让这些四边形正对着视点(Billboard) 实现 在OSG中的实现与OpenGL中有一些不同,在OpenGL中很容易得到屏幕上某一点的深度值从而判断遮挡,在OSG中需要在获取到OpenGL RC的时候才

ALLENJIAO的专栏 966

osg解析系列-[osgUtil::IntersectionVisitor]-场景求交示例 线段/射线/面/多面体 求交

【代码】M23.11.W5[osgUtil::IntersectionVisitor]-场景求交示例 线段/射线/面/多面体 求交。

qq_42531872的博客 668

osg线段和模型求交点

osg::Vec3p_start(-100,0,0); osg::Vec3p_end(100,0,0); osgUtil::LineSegmentIntersector::Intersections_intersections; osg::ref_ptr<osgUtil::LineSegmentIntersector>_line...

weixin_30617797的博客 1017

OSG鼠标选择求交

OSG鼠标选择求交 ////求交方法一:(用WINDOW坐标值,在相机下求交) //osg::ref_ptr picker = newosgUtil::LineSegmentIntersector( // osgUtil::Intersector::WINDOW,ea.getX(), ea.getY()); //osgUtil::IntersectionVisitoriv( picker.

u010698150的专栏 1848
上一篇: 左/右手坐标系绕不同轴顺时针旋转动不同的理解与总结
下一篇: osg操控器之动画路径操控器osgGA::AnimationPathManipulator分析
荆楚闲人
博客等级 码龄20年 3万+粉丝 473原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值