osg坐标系转换

 

osg中将局部坐标系下的点坐标换算成全局坐标系下点的坐标

标签: matrixlist
  2940人阅读  评论(1)  收藏  举报
  分类:
 
 

今天下午我遇到了这个问题,原来都准备去写 nodevisitor 了,后来发现 Transform.cpp 中已定义了 TransformVisitor 可直接实现 tranform 的连乘,然后查看 Transform 的成员函数,发现这个 TransformVisitor 是通过 Transform 的成员函数 computeLocalToWorld(...) ,传入相关参数后,直接就可计算出变换矩阵,visitor都不用考虑了。^_^

正在高兴时我,想了想,这样还是得确定这个对象是 Transform 类型的才可以,于是我看了看 osg::Node 的类说明,想找到 parentList ,这时我发现了 osg::Node 竟然有成员函数 getWorldMatrices() , 返回 MatrixList 。 当前 node 至场景根结点可能有很多条路径(每个路径都会显示一次这个结点),这个 list 便保存了每个路径合成的最终 matrix 。简直太方便了!^-^


现在总结下,共有两个方法,可获得结点的变换矩阵集合:

1. osg::Transform::computeLocalToWorld(...)

2. osg::Node::getWorldMatrices() 


当然,针对这个问题,第二个方法更方便。


一. 空间变换节点

 

空间变换中最重要的是坐标系和矩阵运算了。OSG坐标系中使用右手系,Z轴垂直向上,X轴水平向右,Y轴垂直屏幕向里,与OpenGL和DirectX都不同。
相关缩放、旋转和平移主要由osg::Matrix, osg::Vec3, osg::Quat几个类来完成。
局部坐标系向世界坐标系转换规则是:设在局部坐标系下顶点 V 转换成世界坐标系坐标 V':
    V' = V * 
Mn* Mn-1*……* M3* M2* M1* M0

其中M0到Mn一次为各个矩阵变换。从世界坐标系坐标下顶点 V' 转换成局部坐标系 V:
     = V' * M0-1 
M1-1 * M2-1 * M3-1 *……* Mn-1-1 * Mn-1

 

 

 

对于空间变换而言,无论是OpenGL,DirectX还是OSG,一般都会遵守SRT(Scale/Rotate/Translate)的运算顺序来完成符合矩阵的构建:
其公式为:

 

    M =Ms Mr Mt


<think>根据用户需求,用户希望了解在osgEarth中如何进行坐标转换。结合提供的引用内容,我将整理一个清晰的回答,包括世界坐标、经纬度坐标、投影坐标之间的转换方法,并给出相关代码示例。 回答结构: 1. 介绍osgEarth坐标系统的基本概念 2. 详细说明各种坐标转换方法(世界坐标转经纬度、经纬度转世界坐标、不同投影坐标系之间的转换) 3. 提供代码示例 4. 注意事项(如高程模式) 最后生成相关问题</think>### osgEarth 坐标转换详解 在 osgEarth 中,坐标转换主要涉及三种类型:**世界坐标(XYZ)**、**经纬度高程(Lon/Lat/Alt)** 和 **投影坐标(如UTM)**。以下是核心方法及代码示例: --- #### **1. 世界坐标 ↔ 经纬度高程(WGS84)** **原理**:通过椭球模型(`osg::EllipsoidModel`)进行转换,需注意角度/弧度转换。 **代码实现**: ```cpp #include <osg/CoordinateSystemNode> // 世界坐标转经纬度高程 (XYZ → Lon/Lat/Alt) osg::Vec3d WorldToLonLatAlt(const osg::Vec3d& world) { osg::EllipsoidModel em; double lat, lon, alt; em.convertXYZToLatLongHeight(world.x(), world.y(), world.z(), lat, lon, alt); return osg::Vec3d(osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat), alt); } // 经纬度高程转世界坐标 (Lon/Lat/Alt → XYZ) osg::Vec3d LonLatAltToWorld(const osg::Vec3d& lonLatAlt) { osg::EllipsoidModel em; double x, y, z; em.convertLatLongHeightToXYZ( osg::DegreesToRadians(lonLatAlt.y()), // Lat osg::DegreesToRadians(lonLatAlt.x()), // Lon lonLatAlt.z(), // Alt x, y, z ); return osg::Vec3d(x, y, z); } ``` --- #### **2. 不同投影坐标系转换(如WGS84 ↔ UTM)** **原理**:使用 `SpatialReference` 定义坐标系,通过 `GeoPoint::transform()` 转换。 **代码示例**: ```cpp #include <osgEarth/SpatialReference> // WGS84经纬度 → UTM投影坐标 const SpatialReference* wgs84 = SpatialReference::get("wgs84"); const SpatialReference* utm15 = SpatialReference::get("+proj=utm +zone=15 +ellps=GRS80 +units=m"); // UTM 15N GeoPoint wgsPoint(wgs84, -93.0, 34.0); // 经度-93°, 纬度34° GeoPoint utmPoint = wgsPoint.transform(utm15); // 转换到UTM15N投影坐标 // 带高程的转换(ALTMODE_ABSOLUTE表示绝对高程) GeoPoint pointWithAlt(wgs84, -93.0, 34.0, 100.0, ALTMODE_ABSOLUTE); GeoPoint utmWithAlt = pointWithAlt.transform(utm15); ``` --- #### **3. 世界坐标 ↔ 屏幕坐标** **原理**:结合相机视图矩阵、投影矩阵和视口矩阵计算。 **代码示例**: ```cpp osg::Vec3d WorldToScreen(const osg::Vec3d& world, osg::Camera* camera) { osg::Matrix VPW = camera->getViewMatrix() * camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix(); return world * VPW; // 返回屏幕坐标 (x, y, depth) } ``` --- #### **关键注意事项**: 1. **高程模式**: - `ALTMODE_ABSOLUTE`:高程基于椭球体(如WGS84椭球)。 - `ALTMODE_RELATIVE`:高程基于当地地形表面(需加载地形数据)。 2. **性能优化**: - 频繁转换时复用 `SpatialReference` 和 `EllipsoidModel` 对象,避免重复创建。 3. **依赖项**: - 投影转换需链接 PROJ 库(osgEarth 默认集成)[^1][^4]。 --- ### 相关问题 1. 如何在不同高程模式(绝对/相对)间正确转换坐标? 2. osgEarth 中如何自定义非标准投影坐标系(如地方坐标系)? 3. 坐标转换时出现偏移可能是什么原因?如何调试? 4. 在实时渲染中优化大规模坐标转换性能的方法有哪些? [^1]: GIS / osgearth :坐标系统。即时投影可根据不同坐标系统显示其数据集。 [^2]: osgEarth世界坐标转屏幕坐标的实现依赖相机矩阵。 [^3]: 世界坐标与经纬度高程转换需通过椭球模型计算。 [^4]: 投影坐标系转换需明确定义源和目标SRS,并注意高程模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值