VB.NET Get Relative Point/Coordinates in Mercator Zoomed Map

blinkor12 101 Reputation points
2021-05-01T02:20:40.283+00:00

I'm attempting to make a map renderer inside a PictureBox with VB.NET. I'm trying to convert a map (with Mercator) projection when given a Longitude and Latitude value and a zoomed factor would convert it to a pixel point location.

I've found several examples of converting a Mercator projection-based map's longitude and latitude but they either are using a world map (I'm using a specific area of that map) or don't account or use a different type of Scale Factor.

My map rendering application takes a SVG and loads it with the SVG-NET library as a bitmap into a PictureBox with a variable that contains a Zoom Factor.

I'm trying to write a function that when given the zoom factor, longitude, and latitude will output the relative location of that point inside a PictureBox.

This is the code I use to render the SVG into the PictureBox.

Dim SF As String = 1 'Zoom/Scale Factor
'Use Scrollbar to Zoom PictureBox2 which contains the loaded bitmap

 Private Sub PictureBox2_MouseWheel(sender As Object, e As MouseEventArgs) Handles PictureBox2.MouseWheel
        If e.Delta > 0 Then
            SF = SF + 0.1
            Dim svgDocument = Svg.SvgDocument.Open("C:\users\admin\Pictures\doc.svg")
            svgDocument.ShapeRendering = SvgShapeRendering.Auto

            PictureBox2.Size = New Size(CInt(650 * SF), CInt(700 * SF))

            Dim bmp As Bitmap = svgDocument.Draw(PictureBox2.Size.Width, PictureBox2.Size.Height)
            PictureBox2.Image = bmp
        Else
            SF = SF - 0.1
            Dim svgDocument = Svg.SvgDocument.Open("C:\users\admin\Pictures\doc.svg")
            svgDocument.ShapeRendering = SvgShapeRendering.Auto

            PictureBox2.Size = New Size(CInt(650 * SF), CInt(700 * SF))

            Dim bmp As Bitmap = svgDocument.Draw(PictureBox2.Size.Width, PictureBox2.Size.Height)
            PictureBox2.Image = bmp
        End If
    End Sub

I know that the SVG's default width is 450 and the height is 530. I also know that the left longitude is "123.658963" and the top latitude is "45.523885" and the right longitude is "145.820743" and the bottom latitude is "24.217586".

How can I write a function for this?

The SVG can be downloaded from here: Google Drive Link

Developer technologies | VB
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Xingyu Zhao-MSFT 5,381 Reputation points
    2021-05-04T01:24:06.66+00:00

    Hi @blinkor12 ,
    Do you consider scaling the picture in the following ways.
    93256-gif.gif
    If so, you need to create a custom PictureBox(code from here).

    Public Class CustomPictureBox  
        Inherits System.Windows.Forms.UserControl  
      
        Private PicBox As System.Windows.Forms.PictureBox  
        Private OuterPanel As Panel  
        Private components As Container = Nothing  
        Private m_sPicName As String = ""  
        Private ZOOMFACTOR As Double = 1.25  
        Private MINMAX As Integer = 5  
      
        Private Sub InitializeComponent()  
            Me.PicBox = New System.Windows.Forms.PictureBox()  
            Me.OuterPanel = New System.Windows.Forms.Panel()  
            Me.OuterPanel.SuspendLayout()  
            Me.SuspendLayout()  
            Me.PicBox.Location = New System.Drawing.Point(0, 0)  
            Me.PicBox.Name = "PicBox"  
            Me.PicBox.Size = New System.Drawing.Size(150, 140)  
            Me.PicBox.TabIndex = 3  
            Me.PicBox.TabStop = False  
            Me.OuterPanel.AutoScroll = True  
            Me.OuterPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle  
            Me.OuterPanel.Controls.Add(Me.PicBox)  
            Me.OuterPanel.Dock = System.Windows.Forms.DockStyle.Fill  
            Me.OuterPanel.Location = New System.Drawing.Point(0, 0)  
            Me.OuterPanel.Name = "OuterPanel"  
            Me.OuterPanel.Size = New System.Drawing.Size(210, 190)  
            Me.OuterPanel.TabIndex = 4  
            Me.Controls.Add(Me.OuterPanel)  
            Me.Name = "CustomPictureBox"  
            Me.Size = New System.Drawing.Size(210, 190)  
            Me.OuterPanel.ResumeLayout(False)  
            Me.ResumeLayout(False)  
        End Sub  
      
        Public Sub New()  
            InitializeComponent()  
            InitCtrl()  
        End Sub  
      
        Private _pictureImage As Image  
      
        Public Property PictureImage As Image  
            Get  
                Return _pictureImage  
            End Get  
            Set(ByVal value As Image)  
      
                If value IsNot Nothing Then  
      
                    Try  
                        PicBox.Image = value  
                        _pictureImage = value  
                    Catch ex As OutOfMemoryException  
                        RedCross()  
                    End Try  
                Else  
                    RedCross()  
                End If  
            End Set  
        End Property  
      
        <Browsable(False)>  
        Public Property Picture As String  
            Get  
                Return m_sPicName  
            End Get  
            Set(ByVal value As String)  
      
                If value IsNot Nothing Then  
      
                    If System.IO.File.Exists(value) Then  
      
                        Try  
                            PicBox.Image = Image.FromFile(value)  
                            m_sPicName = value  
                        Catch ex As OutOfMemoryException  
                            RedCross()  
                        End Try  
                    Else  
                        RedCross()  
                    End If  
                End If  
            End Set  
        End Property  
      
        <Browsable(False)>  
        Public Property Border As BorderStyle  
            Get  
                Return OuterPanel.BorderStyle  
            End Get  
            Set(ByVal value As BorderStyle)  
                OuterPanel.BorderStyle = value  
            End Set  
        End Property  
      
        Private Sub InitCtrl()  
            PicBox.SizeMode = PictureBoxSizeMode.StretchImage  
            PicBox.Location = New Point(0, 0)  
            OuterPanel.Dock = DockStyle.Fill  
            OuterPanel.Cursor = System.Windows.Forms.Cursors.NoMove2D  
            OuterPanel.AutoScroll = True  
            AddHandler OuterPanel.MouseEnter, AddressOf PicBox_MouseEnter  
            AddHandler PicBox.MouseEnter, AddressOf PicBox_MouseEnter  
            AddHandler OuterPanel.MouseWheel, AddressOf PicBox_MouseWheel  
        End Sub  
      
        Private Sub RedCross()  
            Dim bmp As Bitmap = New Bitmap(OuterPanel.Width, OuterPanel.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555)  
            Dim gr As Graphics  
            gr = Graphics.FromImage(bmp)  
            Dim pencil As Pen = New Pen(Color.Red, 5)  
            PicBox.Image = bmp  
            gr.Dispose()  
        End Sub  
      
        Private Sub ZoomIn()  
            If (PicBox.Width < (MINMAX * OuterPanel.Width)) AndAlso (PicBox.Height < (MINMAX * OuterPanel.Height)) Then  
                PicBox.Width = Convert.ToInt32(PicBox.Width * ZOOMFACTOR)  
                PicBox.Height = Convert.ToInt32(PicBox.Height * ZOOMFACTOR)  
                PicBox.SizeMode = PictureBoxSizeMode.StretchImage  
            End If  
        End Sub  
      
        Private Sub ZoomOut()  
            If (PicBox.Width > (OuterPanel.Width / MINMAX)) AndAlso (PicBox.Height > (OuterPanel.Height / MINMAX)) Then  
                PicBox.SizeMode = PictureBoxSizeMode.StretchImage  
                PicBox.Width = Convert.ToInt32(PicBox.Width / ZOOMFACTOR)  
                PicBox.Height = Convert.ToInt32(PicBox.Height / ZOOMFACTOR)  
            End If  
        End Sub  
      
        Private Sub PicBox_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs)  
            If e.Delta < 0 Then  
                ZoomIn()  
            Else  
                ZoomOut()  
            End If  
        End Sub  
      
        Private Sub PicBox_MouseEnter(ByVal sender As Object, ByVal e As EventArgs)  
            If PicBox.Focused = False Then  
                PicBox.Focus()  
            End If  
        End Sub  
      
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)  
            If disposing Then  
                If components IsNot Nothing Then components.Dispose()  
            End If  
      
            MyBase.Dispose(disposing)  
        End Sub  
    End Class  
    

    Then use this:

            Dim svgDocument = Svg.SvgDocument.Open("...svg")  
            svgDocument.ShapeRendering = SvgShapeRendering.Auto  
            Dim bmp As Bitmap = svgDocument.Draw(PictureBox1.Width, PictureBox1.Height)  
            CustomPictureBox1.PictureImage = bmp  
    

    Best Regards,
    Xingyu Zhao
    *
    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.