【SuperMap .Net 组件】地图与场景同步(二) 视图范围同步
来源:互联网 发布:遗传算法讲解 编辑:程序博客网 时间:2024/06/05 17:14
二维地图与三维场景的同步主要就是视图的同步。原理很简单,Scene去同步Map的过程就是获得Map的视图范围,然后让Scene显示这个范围,Map去同步Scene的过程就是获得Scene的视图范围,然后让Map显示这个范围。实际也是这个过程,但是Scene的视图范围不是那么好获得的,需要按照高度和视角去计算。另外,根据场景的类型不同(平面还是球面),计算过程也稍有不同。详细代码如下
找个地方先把事件和用于捕捉的函数绑定:
AddHandler m_MapControl.Map.Drawn, AddressOf MapDrawnHandler AddHandler m_SceneControl.Scene.Timer.Tick, AddressOf SceneTimerTickHandler
Scene同步Map:
Private Sub MapDrawnHandler(ByVal sender As Object, ByVal e As MapDrawnEventArgs) '投影坐标转为地理坐标(如果本来就是地理坐标则不发生变化) Dim centerPoint As Point2D = New Point2D(m_MapControl.Map.Center.X, m_MapControl.Map.Center.Y) Dim left As Double = m_MapControl.Map.ViewBounds.Left Dim right As Double = m_MapControl.Map.ViewBounds.Right Dim top As Double = m_MapControl.Map.ViewBounds.Top Dim bottom As Double = m_MapControl.Map.ViewBounds.Bottom Dim lbPoint As Point2D = New Point2D(left, bottom) Dim rtPoint As Point2D = New Point2D(right, top) Dim points As Point2Ds = New Point2Ds(New Point2D() {centerPoint, lbPoint, rtPoint}) Dim prjCoordSys As PrjCoordSys = m_Workspace.Datasources.Item(DataSourceName).PrjCoordSys Dim b As Boolean = CoordSysTranslator.Inverse(points, prjCoordSys) Dim geoCenterPoint As Point2D = points.ToArray()(0) Dim geoLBPoint As Point2D = points.ToArray()(1) Dim geoRTPoint As Point2D = points.ToArray()(2) Dim viewBouns As Rectangle2D = New Rectangle2D(geoLBPoint, geoRTPoint) Dim camera As Camera = New Camera(geoCenterPoint.X, geoCenterPoint.Y, CalculateAltitudeFromBounds(viewBouns)) ''通过Map视图范围计算Scene高度 camera.Heading = m_MapControl.Map.Angle m_SceneControl.Scene.Camera = camera m_SceneControl.Refresh() m_SceneControl.Scene.Refresh() End Sub
这里要稍微说明一下,大部分是用的示例代码,但由于我的项目里有时候是平面场景有时候是球面场景,就得做一下判断。bounds经过转换已经是大地坐标了,宽、长都是经纬度(角度),可以看到计算过程中都是角度制转换为弧度制。但如果场景是平面的,bounds里面的长宽就是投影坐标了,这时候就需要根据地球半径算一下它在场景中的俯角了。
Private Function CalculateAltitudeFromBounds(ByVal bounds As Rectangle2D) As Double Dim altitude As Double = EarthRadius Dim width As Double If m_SceneControl.Scene.Type = SceneType.NonEarthFlat Then width = (bounds.Width / 3.1415926 / EarthRadius) * 180 Else width = bounds.Width End If If width >= 120 Then Dim mapWidth As Double = width altitude = EarthRadius * mapWidth / 60 - EarthRadius ElseIf width <> 0 Then Dim angle1 As Double = width / 2 / 180 * Math.PI Dim height As Double = Math.Sin(angle1) * EarthRadius Dim a As Double = height / Math.Tan(angle1) Dim b As Double = height / Math.Tan(Math.PI / 6) altitude = a + b - EarthRadius End If Return altitude End Function
Map同步Scene:
'其他的卫语句就不说了,这里对比一下镜头的经纬度,以防场景不停的刷啊刷啊 Dim camera As Camera = m_SceneControl.Scene.Camera If camera.Longitude = oldLog AndAlso camera.Latitude = oldLat Then Return End If Dim point As Point2D = New Point2D(camera.Longitude, camera.Latitude) Dim size As Size2D = CalculateSizeFromAltitude(camera.Altitude) ''通过镜头高度计算地图视图范围 Dim geobounds As Rectangle2D = New Rectangle2D(point, size) oldLat = camera.Latitude oldLog = camera.Longitude '地理坐标转投影坐标 Dim geoLBPoint As Point2D = New Point2D(geobounds.Left, geobounds.Bottom) Dim geoRTPoint As Point2D = New Point2D(geobounds.Right, geobounds.Top) Dim points As Point2Ds = New Point2Ds(New Point2D() {geoLBPoint, geoRTPoint, point}) Dim prjCoordSys As PrjCoordSys = m_Workspace.Datasources.Item(DataSourceName).PrjCoordSys CoordSysTranslator.Forward(points, prjCoordSys) Dim LBPoint As Point2D = points.ToArray()(0) Dim RTPoint As Point2D = points.ToArray()(1) Dim CenterPoint As Point2D = points.ToArray()(2) Dim bounds As Rectangle2D = New Rectangle2D(LBPoint, RTPoint) If bounds <> m_MapControl.Map.Bounds OrElse m_MapControl.Map.Angle <> camera.Heading Then m_MapControl.Map.ViewBounds = bounds m_MapControl.Map.Angle = camera.Heading m_MapControl.Map.Refresh() End If m_SceneControl.Scene.Refresh() m_SceneControl.Refresh() End Sub
道理同上,需要判断一下
Private Function CalculateSizeFromAltitude(ByVal altitude As Double) As Size2D Dim size As Size2D = New Size2D(0, 0) If altitude >= EarthRadius Then Dim ratio As Double = (altitude + EarthRadius) / 2 Dim longitudeWidth As Double = 120 * ratio / EarthRadius Dim latitudeWidth As Double = 120 * ratio / EarthRadius size = New Size2D(longitudeWidth, latitudeWidth) Else Dim tan30 As Double = Math.Tan(Math.PI / 6) Dim a As Double = (Math.Pow(tan30, 2) + 1) * Math.Pow(EarthRadius, 2) Dim b As Double = -2 * (EarthRadius + altitude) * EarthRadius * Math.Pow(tan30, 2) Dim c As Double = Math.Pow(tan30, 2) * Math.Pow((EarthRadius + altitude), 2) - Math.Pow(EarthRadius, 2.0) Dim cosd As Double = (-b + Math.Sqrt(Math.Pow(b, 2) - 4 * a * c)) / 2 / a Dim d As Double = Math.Acos(cosd) Dim widthd As Double = 2 * d * EarthRadius Dim width As Double = (widthd / 3.1415926 / EarthRadius) * 180 If m_SceneControl.Scene.Type = SceneType.NonEarthFlat Then size = New Size2D(widthd, widthd) ElseIf m_SceneControl.Scene.Type = SceneType.Globe Then size = New Size2D(width, width) Else size = New Size2D(widthd, widthd) End If End If Return size End Function
0 0
- 【SuperMap .Net 组件】地图与场景同步(二) 视图范围同步
- 【SuperMap .Net 组件】地图与场景同步(一)同步的十字丝
- 【SuperMap .Net 组件】新建平面场景与球面场景
- KRpano (大)小地图添加热点,同步切换场景
- 【SuperMap .Net 组件】场景中添加DEM三维地形
- 游戏 场景同步 实现(状态同步)
- SuperMap IObjects C++组件学习笔记(二) - Qt接管下IObjectsC++组件的自定义地图绘制
- .NET简谈组件程序设计之(上下文与同步域)
- 同步与异步(二)
- java线程(二):线程同步与同步锁
- 【SuperMap .Net 组件】投影坐标与大地坐标转换
- java与.NET同步的MD5加密算法(二)
- 互斥与同步(二)
- 同步规范------生产者与消费者(二)
- JAVA——多线程编程之同步:同步代码块与同步函数(二)
- 同步定位与地图构建SLAM过程
- CGrid 设置视图与滚动条同步
- 多线程同步(二)
- SSH框架总结(框架分析+环境搭建+实例源码下载)
- 递归与分治算法
- LRU最近最久未使用算法
- 互联网协议入门(一)
- linux 权限掩码 umask
- 【SuperMap .Net 组件】地图与场景同步(二) 视图范围同步
- Java之JNI参数传递
- GRE作文备考——行动理论
- 反病毒工具-Wireshark
- 使用jquery为dropdownchecklist动态设置值
- Android应用程序的默认最大内存值
- Uva - 1103 - Ancient Messages
- linux daemon进程为什么要fork 2次?
- Myeclipse 10使用hibernate生成注解(annotation)实体类