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

Osg行星轨道鼠标获取事件 要求: 星球轨道默认隐藏,鼠标点击某星球,显示该星球轨道; 点击空白处隐藏所有轨道; 点击其他星球隐藏当前轨道,显示新选中星球轨道。 实际效果: 核心代码: //对象选取事件处理器 void CPickHander::pick(osg::ref_ptr<osgViewer::View> view, float x, float y) { osg::ref_ptr<osg::Node> rpNode = new osg::Node(); osg::ref_ptr<osg 阅读详情

目录

1.概述

2.代码环境说明

3.intersects函数分析

3.1.代码分析

4. 附录


1.概述

      osgUtil::Intersector有几个子类,如下:

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

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

2.代码环境说明

环境说明如下:

  • OpenSceneGraph-3.6.2。
  • Windows 10。
  • Microsoft Visual Studio Community 2022 (64 位) - Current版本 17.5.5。

说明:本博文是基于OpenSceneGraph的3.6.2版本来讲解的,读者版本可能和本人的版本不同,

            故本人的源码或功能可能在细节上和读者的有所不同。

3.intersects函数分析

intersects函数有好几个,本节讲解的intersects函数源码如下:

bool LineSegmentIntersector::intersects(const osg::BoundingSphere& bs)
{
    // if bs not valid then return true based on the assumption that an invalid sphere is yet to be defined.
    if (!bs.valid()) return true;

    osg::Vec3d sm = _start - bs._center;
    double c = sm.length2()-bs._radius*bs._radius;
    if (c<0.0) return true;

    osg::Vec3d se = _end-_start;
    double a = se.length2();
    double b = (sm*se)*2.0;
    double d = b*b-4.0*a*c;

    if (d<0.0) return false;

    d = sqrt(d);

    double div = 1.0/(2.0*a);

    double r1 = (-b-d)*div;
    double r2 = (-b+d)*div;

    if (r1<=0.0 && r2<=0.0) return false;

    if (r1>=1.0 && r2>=1.0) return false;

    if (_intersectionLimit == LIMIT_NEAREST && !getIntersections().empty())
    {
        double ratio = (sm.length() - bs._radius) / sqrt(a);
        if (ratio >= getIntersections().begin()->ratio) return false;
    }

    // passed all the rejection tests so line must intersect bounding sphere, return true.
    return true;
}

代码段1 

为了分析该函数,就得写一个例子,让该例子的调用能进入到这个函数,从而实现断点调试,这样分析才高效、明白。 下面是摘自1节提到的博文中的例子,代码如下:

#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();
}

代码段2  

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

osg::Vec3(0, 0,15)

终点坐标如下:

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

同时构建了一个长方体,长方体中心位于原点,长、宽、高、分别为:5、4、3。效果如下(注意:为了便于观察,我使这个长方体绕X轴逆时针转动了一定角度):

上述代码的第23、24行构造了一个求交器和求交访问器对象。通过求交器和求交访问器对象相互协同,再通过调用第27行代码accept函数,就能求出线段和长方体的交点。在代码段1设置断点,当启动该例子时,就能进入到intersects函数并停下来。代码段1的功能是检测线段是否和三维场景中某个物体的最小外接球有交点。

3.1.代码分析

    代码段1中的第4行:如果包围这个长方体的最小外接球是无效的(外接球半径<0),则直接返回true。因为如果最小外接球都无效,则本函数后面的逻辑处理都没意义。

    代码段1中的第6~8行:算出长方体最小外接球球心指向线段起点的向量sm,并计算sm的长度即sm的模是否比外接球半径小,如果是,则证明线段的起点在外接球球内,则返回true,即该线段必定和外接球相交(注:要把外接球看为实心球体)。

    代码段1中的第10~26行:这几行代码是线段起点在球外面时,判断线段是否和球相交。这段代码就是求直线和球的交点,有三种可能,要么相切有一个交点,要么相交有两个交点,否则的话没有交点,这也符合空间直线与球面相交的直观认识,。 关于直线和球的交点算法,请参考:

空间直线与球面的相交算法

上述博文是求直线和球交点,但在计算机中是无法直接表示无限长的直线的,在计算机中,一般用有范围的线段来表示直线,如下代码:

if (r1<=0.0 && r2<=0.0) return false;

r1、r2虽然是表示直线和球的交点,但r1、r2点在线段的起始点前面,不是指定范围的线段内的点,故不是线段和球的交点。如下S表示线段的起点;E表示线段的终点,则r1、r2点在S点前面:

如下代码: 

if (r1>=1.0 && r2>=1.0) return false;

r1、r2点在线段的终点后面,不是指定范围的线段内的点。如下:

如下图:

第30行表示的含义是:DS / SE的比值;根据几何知识我们知道DS是S点到球(圆)的最近距离。getIntersections().begin()->ratio表示从线段起点和球相交的第一个交点的长度占据整个线段长度的比例即SA / SE。那么代码段1中的第28~32行含义为:如果设定要找的交点为离球最近,如果线段起点和第一个交点的长度(SA )比线段起点到球的最近距离(DS)还小,则这样的交点是不存在的,因为DS是离球面最小的。存在的问题:本人觉得此处的等号不能要,即第31行要改为:

 if (ratio > getIntersections().begin()->ratio) return false;

因为如下两种情况都是可以找到符合和球最近距离的交点的:

此种情况是线段SE和球相切,起点S就是第一个和球的交点。

 

此种情况是线段SE和球相交,但起点S就是第一个和球的交点。 

4. 附录

关于该类的更多知识,可参考:

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节点拾取 & 点击切换高亮。可以实现对模型的拾取以及点击切换高亮模式。

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

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

danshiming的博客 1074

卷积神经网络-猫狗识别(附源码)

利用python实现一个卷积神经网络,训练猫狗数据集,实现对猫狗图片的预测识别

m0_63223213的博客 2万+

OSG LineSegmentIntersector进行碰撞检测

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

痞子龙3D编程 7293

Power Automate实战:用SharePoint REST API批量处理列表数据(附JSON解析技巧)

本文深入探讨了如何利用Power Automate调用SharePoint REST API实现列表数据的批量自动化处理。文章详细解析了API的协同工作原理、高效的数据获取与筛选技巧,并重点分享了JSON数据解析的核心难点与实战解决方案,旨在帮助企业用户构建稳定可靠的数据处理流程,提升运营效率。

coffee的博客 769

基于知识图谱的旅游推荐系统

这一系统整合了当今先进的数据技术:采集携程等大型平台的景点数据,通过爬虫技术源源不断地获取最新的旅游信息。此外,我们采用Neo4j图数据库来存储和处理这些数据,结合自然语言处理技术,为你提供精准的旅游建议。:通过直观的知识图谱展示,了解各个景点之间微妙的联系,无论是文化背景还是地理方位,你都能从中发现新的旅行灵感。准备毕业设计的同学,关注我们,这是一个集成了多种前沿技术的项目,为你的学术成果锦上添花。:不再浪费时间,系统根据你的偏好和历史评分,利用协同过滤技术推荐适合的旅游目的地。

qalangtao的博客-qalangtao.com 774

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

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

danshiming的博客 1318

C++笔试题整理

目录 1. 笔试题1 1.1 链表反转 1.2 String 2. 笔试题2 2.1 求下面函数的返回值(微软) 2.2 什么是“引用”?申明和使用“引用”要注意哪些问题? 2.3 将“引用”作为函数参数有哪些特点? 2.4 在什么时候需要使用“常引用”?  2.5 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则? 2.6 “引用”与多态的关系? 2.7 “引用”与指针的区别是什么? 2.8 什么时候需要“引用”? 2.9 结构与联合有和区别? 2.10 下面关于.

星月相随的专栏 2483

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

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

danshiming的博客 1333

Magisk如何针对性隐藏Root避免被检测

Magisk隐藏特征码有两种途径,一种是通过插件,一种是定制源码。插件的方式相对简单,但是使用范围也有限,好处是成本低好上手。定制源码难度大,成本高,好处是稳定,后续也好更新维护。

zhonglunshun的专栏 1万+

精通 Android NDK/JNI:从入门到精通实战与面试精粹

在Android开发中,

郑伟强dev的专栏 144

LineSegmentIntersectorUtils::IntersectFunctor::intersect源码分析

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

danshiming的博客 1177

【QT开发】web开发,内嵌网页展示和交互工具QWebEngineView类详解及实战应用

QWebEngineView 类为 Qt 应用提供了强大的网页展示和交互能力。通过合理运用其方法、属性和事件,能够创建出功能丰富、用户体验良好的网页浏览界面。在开发过程中,要注意处理常见问题,以确保网页的正常展示和交互效果。

科技改变人类,技术成就未来 2004

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

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

weixin_30716141的博客 565

OpenHarmony 显示Display驱动全栈解析:DisplayLayer + Gralloc + Gfx 三位一体,打造高性能图形底座

OpenHarmony Display显示驱动模块是系统图形渲染和显示功能的基础组件,负责管理显示设备、图层渲染、内存分配等核心功能。该模块采用HDI(Hardware Driver Interface)设计架构,为上层图形服务提供统一的显示能力接口,实现了显示设备的初始化、图层管理、内存分配与映射、硬件加速等关键功能。DisplayLayer:负责显示图层的管理, 包括图层创建、显示属性设置、图层填充及刷新等操作;

m0_67505153的博客 315

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

OSG鼠标选择求交

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

u010698150的专栏 1848

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

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

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

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

liangfei868的博客 1969

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

OSG笔记:对线求交失败

使用以下两个求交器,对一根直线进行求交,但始终得不出结果。 直线求交器 osgUtil::LineSegmentIntersector 多面体求交器 osgUtil::PolytopeIntersector

憧憬,思考,奋斗,飞翔 1225

OSG画折线程序函数总结

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

pipixiaodan的专栏 697

OSG交运算、选取和碰撞

osg学习

qq_42491346的博客 2068

OpenSceneGraph源码分析:osgUtil模块

osgUtil(OSG Utilities)模块提供了用于场景遍历(更新、绘制)、裁剪、数据统计等公用工具。 The osgUtil library provides general purpose utility classes such as update, cull and draw traverses, scene graph operators such a scene graph optimisation, tri stripping, and tessellation. 网络资料

国产CAx(CAD/CAE/CAM)软件研发 1158

osg线碰撞检测

简介利用osgUtil::LineSegmentIntersector做的线碰撞检测,原理是把小球当前位置和新位置练成线与盒子做碰撞检测,如果有交点,则不准小球移动,记录于此备忘代码#include "../Common/Common.h" #include <osg/ShapeDrawable> #include <osg/Shape> #include <osgGA/GUIEventAdapte

dancing_night的专栏 2052

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求交器(一)面求交器PlaneIntersector

OSG求交器之平面求交器

Frank的专栏 1万+
上一篇: 观察矩阵(View Matrix)、投影矩阵(Projection Matrix)、视口矩阵(Window Matrix)及VPM矩阵及它们之间的关系
下一篇: 将QComboBox下拉项中的文本居中、居右
荆楚闲人
博客等级 码龄20年 3万+粉丝 473原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值