Imports ThinkGeo.MapSuite.Core Imports ThinkGeo.MapSuite.WpfDesktopEdition Imports MapDemo.MapSuiteCustomObjects Class MainWindow Const UseTileCache As Boolean = True Private Sub WpfMap1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles WpfMap1.Loaded 'Init WpfMap ZoomLevels, Extent and Background Call InitializeWpfMap() 'Adds the WorldMap Overlay Call CreateWorldMapOverlay() ''Adds Graticule, Scale Adornment and Satlink Logo 'Call CreateAdornmentOverlay() ''Add the general PopupOverlay, and setup special InteractiveOverlay to catch MouseWheel events 'Call CreateGeneralPopupOverlay() ''Add the Custom TrackInteractiveOverlay (Ruler, Polygons, etc) 'Call CreateCustomTrackInteractiveOverlay() ''Adds the GPS Overlay and init the Vessel GPS service 'Call CreateGPSOverlay() ''Add a GeneralPurpose SimpleMarkerOverlay (FindArrow, etc) 'Call CreateSimpleMarkerOverlay() KmlLayerOther.CurrentExtent = WpfMap1.CurrentExtent KmlLayerZEE.CurrentExtent = WpfMap1.CurrentExtent 'We now need to call the Refresh() method of the Map control so that the Map can redraw based on the data that has been provided. WpfMap1.Refresh() AddHandler WpfMap1.CurrentExtentChanged, AddressOf extentChanged_Handler End Sub Private Sub InitializeWpfMap() 'Set the BaseShape library to Microsoft.SqlServer.Types BaseShape.GeometryLibrary = GeometryLibrary.Unmanaged 'Set the Map Unit. The reason for setting it to DecimalDegrees is that is what the shapefile’s unit of measure is inherently in. WpfMap1.MapUnit = GeographyUnit.DecimalDegree 'Disables PanZoomBar and Logo WpfMap1.MapTools.PanZoomBar.IsEnabled = False WpfMap1.MapTools.Logo.IsEnabled = False 'Sets the maximun ZoomOut and extent WpfMap1.MaximumScale = 73000000 WpfMap1.RestrictExtent = New RectangleShape(-3600, 89, 3600, -89) 'Set a proper extent for the Map. WpfMap1.CurrentExtent = New RectangleShape(-120, 89, 132, -68) 'Sets the map background Dim MapBackground As New GeoSolidBrush(GeoColor.GeographicColors.DeepOcean) WpfMap1.Background = New SolidColorBrush(System.Windows.Media.Color.FromRgb(MapBackground.Color.RedComponent, MapBackground.Color.GreenComponent, MapBackground.Color.BlueComponent)) WpfMap1.BackgroundOverlay.BackgroundBrush = MapBackground End Sub Private Sub extentChanged_Handler(ByVal sender As Object, ByVal e As CurrentExtentChangedWpfMapEventArgs) If KmlLayerOther IsNot Nothing Or KmlLayerOther IsNot Nothing Then KmlLayerZEE.CurrentExtent = e.CurrentExtent KmlLayerOther.CurrentExtent = e.CurrentExtent End If End Sub Dim KmlLayerZEE As KmlFeatureLayer Dim KmlLayerOther As KmlFeatureLayer Private Sub CreateWorldMapOverlay() 'Create the WorldMap LayerOverlay to holds the background chart Dim WorldMapOverlay As LayerOverlay = New LayerOverlay() 'WorldMapOverlay.Name = "WorldMapOverlay" 'WorldMapOverlay.WrappingMode = WrappingMode.WrapDateline 'WorldMapOverlay.TransitionEffect = TransitionEffect.None WorldMapOverlay.TileType = TileType.SingleTile 'TileType.MultipleTile 'WorldMapOverlay.TileBuffer = 2 'TileCache If UseTileCache Then Try Dim bitmapTileCache As New FileBitmapTileCache() bitmapTileCache.CacheDirectory = System.Windows.Forms.Application.StartupPath & "\Data\TilesCache" bitmapTileCache.CacheId = "WorldMapOverlay" bitmapTileCache.TileAccessMode = TileAccessMode.ReadAddDelete bitmapTileCache.ImageFormat = TileImageFormat.Png WorldMapOverlay.TileCache = bitmapTileCache 'Call LOG("WorldMapOverlay TilesCache loaded", 0, "MapView") Catch ex As Exception 'Call LOG("WorldMapOverlay TilesCache load error: " & ex.Message, 2, "MapView") End Try End If 'Delete it if created before If System.IO.Directory.Exists(System.Windows.Forms.Application.StartupPath & "\Data\TilesCache") Then Try System.IO.Directory.Delete(System.Windows.Forms.Application.StartupPath & "\Data\TilesCache", True) Catch ex As Exception End Try End If 'Add a background Layer Dim MapBackground As New GeoSolidBrush(GeoColor.GeographicColors.DeepOcean) Dim BackgroundLayer As New BackgroundLayer(MapBackground) BackgroundLayer.Name = "BackgroundLayer" WorldMapOverlay.Layers.Add("BackgroundLayer", BackgroundLayer) Dim kmlLayerOverlay As New LayerOverlay 'Adds the ZEE zones Try If System.IO.File.Exists(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\ZEE.kml") Then KmlLayerZEE = New KmlFeatureLayer(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\ZEE.kml") KmlLayerZEE.Name = "ZEELayer" KmlLayerZEE.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = New AreaStyle(New GeoPen(GeoColor.SimpleColors.Black), New GeoSolidBrush(GeoColor.FromArgb(30, GeoColor.SimpleColors.Yellow.RedComponent, GeoColor.SimpleColors.Yellow.GreenComponent, GeoColor.SimpleColors.Yellow.BlueComponent))) KmlLayerZEE.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = New LineStyle(New GeoPen(GeoColor.SimpleColors.Blue, 2)) KmlLayerZEE.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 kmlLayerOverlay.Layers.Add("ZEELayer", KmlLayerZEE) 'Call LOG("WorldMapOverlay 'ZEE.kml' loaded", 0, "MapView") End If Catch ex As Exception 'Call LOG("WorldMapOverlay 'ZEE.kml' KML load error: " & ex.Message, 2, "MapView") End Try 'Adds any other KML zone file Try For Each tmpFileName As String In System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\", "*.kml") Try If tmpFileName <> System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\ZEE.kml" And tmpFileName.ToUpper.EndsWith("KML") Then KmlLayerOther = New KmlFeatureLayer(tmpFileName) KmlLayerOther.Name = System.IO.Path.GetFileName(tmpFileName) KmlLayerOther.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = New AreaStyle(New GeoPen(GeoColor.SimpleColors.Black), New GeoSolidBrush(GeoColor.FromArgb(30, GeoColor.SimpleColors.Red.RedComponent, GeoColor.SimpleColors.Red.GreenComponent, GeoColor.SimpleColors.Red.BlueComponent))) KmlLayerOther.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = New LineStyle(New GeoPen(GeoColor.SimpleColors.Red, 2)) KmlLayerOther.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 kmlLayerOverlay.Layers.Add(System.IO.Path.GetFileName(tmpFileName), KmlLayerOther) 'Call LOG("WorldMapOverlay '" & System.IO.Path.GetFileName(tmpFileName) & "' KML loaded", 0, "MapView") End If Catch ex As Exception 'Call LOG("WorldMapOverlay '" & System.IO.Path.GetFileName(tmpFileName) & "' KML load error: " & ex.Message, 2, "MapView") End Try Next Catch End Try 'Adds the Bathymetry ShapeFiles Try For Each tmpFileName As String In System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath & "\Data\Bathymetry\", "GebcoOneBathy*.shp") Try Dim GebcoOneBathymetricLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(tmpFileName, ShapeFileReadWriteMode.ReadOnly) GebcoOneBathymetricLayer.Name = System.IO.Path.GetFileNameWithoutExtension(tmpFileName) GebcoOneBathymetricLayer.ZoomLevelSet.ZoomLevel08.DefaultLineStyle = New LineStyle(New GeoPen(GeoColor.SimpleColors.Silver, 1)) GebcoOneBathymetricLayer.ZoomLevelSet.ZoomLevel08.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 WorldMapOverlay.Layers.Add(System.IO.Path.GetFileNameWithoutExtension(tmpFileName), GebcoOneBathymetricLayer) 'Call LOG("WorldMapOverlay '" & System.IO.Path.GetFileName(tmpFileName) & "' Bathymetry loaded", 0, "MapView") Catch ex As Exception 'Call LOG("WorldMapOverlay '" & System.IO.Path.GetFileName(tmpFileName) & "' Bathymetry load error: " & ex.Message, 2, "MapView") End Try Next Catch End Try 'Adds the WorldMap from a ShapeFile Try If System.IO.File.Exists(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\Countries.shp") Then Dim WorldCountriesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\Countries.shp", ShapeFileReadWriteMode.ReadOnly) WorldCountriesLayer.Name = "WorldCountriesLayer" WorldCountriesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.County1 If System.IO.File.Exists(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\WorldCoastline.shp") Then 'Exist a detailed coastline WorldCountriesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level09 Else 'Does not exist detailed coastline (default until 28/08/2012) WorldCountriesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 End If WorldMapOverlay.Layers.Add("WorldCountriesLayer", WorldCountriesLayer) 'Call LOG("WorldMapOverlay Countries.shp Countries loaded", 0, "MapView") 'Add coastline if exist If System.IO.File.Exists(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\WorldCoastline.shp") Then Dim WorldCoastlineLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\WorldCoastline.shp", ShapeFileReadWriteMode.ReadOnly) WorldCoastlineLayer.Name = "WorldCoastlineLayer" WorldCoastlineLayer.ZoomLevelSet.ZoomLevel10.DefaultAreaStyle = AreaStyles.County1 WorldCoastlineLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 WorldMapOverlay.Layers.Add("WorldCoastlineLayer", WorldCoastlineLayer) 'Call LOG("WorldMapOverlay WorldCoastline.shp loaded", 0, "MapView") End If 'Layer for displaying the country labels using ClassBreakStyle to have the label size proportinal to the country size. Dim WorldCountriesLabelsLayer As New ShapeFileFeatureLayer(System.Windows.Forms.Application.StartupPath & "\Data\WorldMap\Countries.shp", ShapeFileReadWriteMode.ReadOnly) WorldCountriesLabelsLayer.Name = "WorldCountriesLabelsLayer" 'For Zoom Levels 04 to 05, displays the country labels for countries above 100,000 sqkm in area with three classes. Dim classBreakStyle2 As New ClassBreakStyle("SQKM") Dim textStyle2a As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 9, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle2b As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 11, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle2c As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 14, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 3, 0, 0) classBreakStyle2.ClassBreaks.Add(New ClassBreak(100000, textStyle2a)) classBreakStyle2.ClassBreaks.Add(New ClassBreak(500000, textStyle2b)) classBreakStyle2.ClassBreaks.Add(New ClassBreak(3000000, textStyle2c)) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel04.CustomStyles.Add(classBreakStyle2) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel04.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05 'For Zoom Levels 06 to 07, displays the country labels for countries above 20,000 sqkm in area with four classes. Dim classBreakStyle3 As New ClassBreakStyle("SQKM") Dim textStyle3a As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 9, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle3b As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 12, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle3c As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 14, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle3d As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 18, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 3, 0, 0) classBreakStyle3.ClassBreaks.Add(New ClassBreak(20000, textStyle3a)) classBreakStyle3.ClassBreaks.Add(New ClassBreak(100000, textStyle3b)) classBreakStyle3.ClassBreaks.Add(New ClassBreak(500000, textStyle3c)) classBreakStyle3.ClassBreaks.Add(New ClassBreak(3000000, textStyle3d)) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel06.CustomStyles.Add(classBreakStyle3) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level07 'For Zoom Levels 08 to 15, displays the country labels for all countries with five classes. Dim classBreakStyle4 As New ClassBreakStyle("SQKM") Dim textStyle4a As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 9, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle4b As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 12, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle4c As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 14, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle4d As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 18, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2, 0, 0) Dim textStyle4e As TextStyle = TextStyles.CreateSimpleTextStyle("CNTRY_NAME", "Arial", 22, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 3, 0, 0) classBreakStyle4.ClassBreaks.Add(New ClassBreak(0, textStyle4a)) classBreakStyle4.ClassBreaks.Add(New ClassBreak(20000, textStyle4b)) classBreakStyle4.ClassBreaks.Add(New ClassBreak(100000, textStyle4c)) classBreakStyle4.ClassBreaks.Add(New ClassBreak(500000, textStyle4d)) classBreakStyle4.ClassBreaks.Add(New ClassBreak(3000000, textStyle4e)) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel08.CustomStyles.Add(classBreakStyle4) WorldCountriesLabelsLayer.ZoomLevelSet.ZoomLevel08.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15 WorldMapOverlay.Layers.Add("WorldCountriesLabelsLayer", WorldCountriesLabelsLayer) 'Call LOG("WorldMapOverlay Countries.shp Labels loaded", 0, "MapView") Else 'Call LOG("WorldMapOverlay Countries.shp not found", 1, "MapView") End If Catch ex As Exception 'Call LOG("WorldMapOverlay Countries.shp load error: " & ex.Message, 2, "MapView") End Try 'And finally add the layerOverlay to the map. WpfMap1.Overlays.Add("kmlLayerOverlay", kmlLayerOverlay) WpfMap1.Overlays.Add("WorldOverlay", WorldMapOverlay) End Sub Private Sub CreateAdornmentOverlay() 'Adds the graticule Dim GraticuleAdornmentLayer As CustomGraticuleAdornmentLayer = New CustomGraticuleAdornmentLayer() 'No topmost graticule GraticuleAdornmentLayer.Name = "GraticuleAdornmentLayer" 'WpfMap1.AdornmentOverlay.Layers.Add("graticule", graticuleAdornmentLayer) 'Topmost graticule Dim AdornmentOverlay As New AdornmentOverlay AdornmentOverlay.Name = "AdornmentOverlay" AdornmentOverlay.Layers.Add(GraticuleAdornmentLayer) WpfMap1.Overlays.Add(AdornmentOverlay) 'Adds the custom Scale Adornment Dim CustomUnitScaleBarAdornmentLayer As CustomUnitScaleBarAdornmentLayer = New CustomUnitScaleBarAdornmentLayer() CustomUnitScaleBarAdornmentLayer.Name = "CustomUnitScaleBarAdornmentLayer" CustomUnitScaleBarAdornmentLayer.UnitText = "nm" CustomUnitScaleBarAdornmentLayer.MeterToUnit = 1852 CustomUnitScaleBarAdornmentLayer.XOffsetInPixel = 20 CustomUnitScaleBarAdornmentLayer.YOffsetInPixel = -5 WpfMap1.AdornmentOverlay.Layers.Add("ScaleBarAdornmentLayer", CustomUnitScaleBarAdornmentLayer) 'Adds our GraphicLogAdornmentLayer with Satlink's Logo (From the resources) Dim GraphicLogoAdornmentLayer As GraphicLogoAdornmentLayer = New GraphicLogoAdornmentLayer() GraphicLogoAdornmentLayer.Name = "GraphicLogoAdornmentLayer" 'Gets the logo from the resources Dim MS As New System.IO.MemoryStream Dim TC As New TiffBitmapEncoder TC.Frames.Add(BitmapFrame.Create(New Uri("pack://application:,,,/MapView;component/Resources/SatlinkLogoAlpha.png"))) TC.Save(MS) MS.Position = 0 Dim Logo As New System.Drawing.Bitmap(MS) MS.Close() 'Use it GraphicLogoAdornmentLayer.LogoImage = Logo GraphicLogoAdornmentLayer.YOffsetInPixel = -5 WpfMap1.AdornmentOverlay.Layers.Add(GraphicLogoAdornmentLayer) End Sub Private Sub CreateGeneralPopupOverlay() Dim TracksPopupOverlay As New PopupOverlay() TracksPopupOverlay.Name = "TracksPopupOverlay" WpfMap1.Overlays.Add("TracksPopupOverlay", TracksPopupOverlay) End Sub Private Sub CreateCustomTrackInteractiveOverlay() 'Creates the CustomTrackInteractiveOverlay WpfMap1.TrackOverlay = New CustomTrackInteractiveOverlay() 'Restore the previous stored objects (MeasureLines, Polygons, Circles) Try If System.IO.File.Exists(System.Windows.Forms.Application.StartupPath & "\Data\Marks.dat") Then Dim F As New System.IO.FileStream(System.Windows.Forms.Application.StartupPath & "\Data\Marks.dat", IO.FileMode.Open, IO.FileAccess.Read) Dim B(F.Length - 1) As Byte F.Read(B, 0, B.Length) F.Close() 'Restore the serialized state of the old CustomTrackInteractiveOverlay, but only takes the internal features, so styles are 'not restores and hence can be modified later on Dim tmpTrackOverlay As New CustomTrackInteractiveOverlay tmpTrackOverlay.LoadState(B) 'Adds the internal features to TrackOverlay.TrackShapeLayer For Each tmpFeature In tmpTrackOverlay.InternalFeatures Try If tmpFeature.IsValid Then 'Additional check for filter empty polygons Dim Valid As Boolean = True If tmpFeature.GetWellKnownType = WellKnownType.Polygon Or tmpFeature.GetWellKnownType = WellKnownType.Multipolygon Then Dim BB As RectangleShape = tmpFeature.GetBoundingBox If BB.GetPerimeter(GeographyUnit.DecimalDegree, DistanceUnit.NauticalMile) < 1 Then Valid = False End If If Valid Then WpfMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(tmpFeature.Id, tmpFeature) End If Catch ex As Exception End Try Next 'Call LOG(WpfMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count & " marks loaded", 0, "MapView") End If Catch ex As Exception 'Call LOG("TrackInteractiveOverlay restore exception: " & ex.Message, 2, "MapView") End Try '----- EditOverlay configuration ----- 'Copy the TrackOverlay DefaultStyles to the EditOverlay WpfMap1.EditOverlay.EditShapesLayer.WrappingExtent = New RectangleShape(-180, 90, 180, -90) WpfMap1.EditOverlay.EditShapesLayer.WrappingMode = WrappingMode.WrapDateline WpfMap1.EditOverlay.EditShapesLayer.ZoomLevelSet.ZoomLevel05.DefaultLineStyle = WpfMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet.ZoomLevel05.DefaultLineStyle.CloneDeep 'Define a white Inner pen for EditOverlay LineStlye so selected lines looks selected WpfMap1.EditOverlay.EditShapesLayer.ZoomLevelSet.ZoomLevel05.DefaultLineStyle.InnerPen = New GeoPen(New GeoColor(150, GeoColor.StandardColors.White), WpfMap1.EditOverlay.EditShapesLayer.ZoomLevelSet.ZoomLevel05.DefaultLineStyle.CenterPen.Width + 4) WpfMap1.EditOverlay.EditShapesLayer.ZoomLevelSet.ZoomLevel05.DefaultAreaStyle = WpfMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet.ZoomLevel05.DefaultAreaStyle.CloneDeep WpfMap1.EditOverlay.EditShapesLayer.ZoomLevelSet.ZoomLevel05.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20 'Define default EditOverlay behavior WpfMap1.EditOverlay.CanAddVertex = False WpfMap1.EditOverlay.CanDrag = False WpfMap1.EditOverlay.CanRemoveVertex = True WpfMap1.EditOverlay.CanReshape = True WpfMap1.EditOverlay.CanResize = False WpfMap1.EditOverlay.CanRotate = False End Sub Private Sub CreateGPSOverlay() 'Create the SimpleMarkerOverlay to hold the Vessel Marker Dim GPSMarkerOverlay As New SimpleMarkerOverlay() GPSMarkerOverlay.Name = "GPSMarkerOverlay" Dim VesselMarker As New VesselMarker(0, 0) VesselMarker.Visibility = Visibility.Hidden 'Not visible until initialized 'Rotates at the center DirectCast(VesselMarker.RenderTransform, RotateTransform).CenterX = 48 / 2 '48 is the size of the image DirectCast(VesselMarker.RenderTransform, RotateTransform).CenterY = 48 / 2 GPSMarkerOverlay.Markers.Add("VesselMarker", VesselMarker) 'And finally add the SimpleMarkerOverlay to the map WpfMap1.Overlays.Add("GPSMarkerOverlay", GPSMarkerOverlay) 'Start the GPSRefresh service TimerGPSRefresh.Start() End Sub #Region "GPS" Dim WithEvents TimerGPSRefresh As New Timers.Timer(1000) Private Sub TimerGPSRefresh_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles TimerGPSRefresh.Elapsed If TimerGPSRefresh.Enabled = False Then Exit Sub Try TimerGPSRefresh.Stop() Call RefreshGPSPosition() Finally TimerGPSRefresh.Start() End Try End Sub Private Delegate Sub RefreshGPSPositionDelegate() Private Sub RefreshGPSPosition() '========= Syncronization of call from other thread =============== If Me.Dispatcher.CheckAccess() Then Dim GPSMarkerOverlay As SimpleMarkerOverlay = DirectCast(WpfMap1.Overlays("GPSMarkerOverlay"), SimpleMarkerOverlay) 'Gets the GPS Overlay Dim VesselMarker As Marker = DirectCast(GPSMarkerOverlay.Markers("VesselMarker"), VesselMarker) Try 'Updates the position and heading 'Position Dim DummyLong As Double = (Date.UtcNow.Millisecond Mod 7) Dim DummyLat As Double = (Date.UtcNow.Millisecond Mod 3) VesselMarker.Position = New Point(GetVirtualizedLongitude(DummyLong), DummyLat) 'Heading Dim DummyCOG As Double = (Date.UtcNow.Second * 6) DirectCast(VesselMarker.RenderTransform, RotateTransform).Angle = DummyCOG 'Visibility (If GPS is enabled and location updated within the last 60 seconds 'VesselMarker.Visibility = IIf(CoreServices.GPS.Enabled And , Visibility.Visible, Visibility.Collapsed) VesselMarker.Visibility = Visibility.Visible ' IIf(CoreServices.GPS.Enabled And (CoreServices.GPS.LastSentenceReceived > Date.MinValue), Visibility.Visible, Visibility.Collapsed) VesselMarker.Opacity = 1.0 'IIf(Date.UtcNow < CoreServices.GPS.LastSentenceReceived.AddSeconds(60), 1.0, 0.7) 'Is in center at vessel mode? If False Then Dim GPSPos As New PointShape(DummyLong, DummyLat) 'Go to central projection WpfMap1.CenterAt(GPSPos) End If Catch VesselMarker.Visibility = Visibility.Collapsed End Try Else Me.Dispatcher.Invoke(New RefreshGPSPositionDelegate(AddressOf RefreshGPSPosition)) End If End Sub Private Function GetVirtualizedLongitude(ByVal RealLongitude As Double) As Double 'Gets the "virtualized" longitude as the nearest to the projection at the center of the current extent Dim CenterLong As Double = WpfMap1.CurrentExtent.GetCenterPoint.X Dim VirtualizedLong As Double = RealLongitude If CenterLong < VirtualizedLong Then Do While Math.Abs(Math.Abs(CenterLong) - Math.Abs(VirtualizedLong)) > Math.Abs(Math.Abs(CenterLong) - Math.Abs(VirtualizedLong - 360)) VirtualizedLong -= 360 Loop Else Do While Math.Abs(Math.Abs(CenterLong) - Math.Abs(VirtualizedLong)) > Math.Abs(Math.Abs(CenterLong) - Math.Abs(VirtualizedLong + 360)) VirtualizedLong += 360 Loop End If Return VirtualizedLong End Function #End Region Private Sub CreateSimpleMarkerOverlay() 'Create the SimpleMarkerOverlay to hold general purpose Markers (FindArrow, etc) Dim GeneralPurposeSimpleMarkerOverlay As New SimpleMarkerOverlay() GeneralPurposeSimpleMarkerOverlay.Name = "SimpleMarkerOverlay" 'And finally add the SimpleMarkerOverlay to the map WpfMap1.Overlays.Add("SimpleMarkerOverlay", GeneralPurposeSimpleMarkerOverlay) End Sub End Class