【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
原创粉丝点击