.net - 具有特定区域和缩放功能的可缩放墨卡托 SVG 像素转换器 (VB.NET)
问题描述
我正在尝试使用特定文件制作自己的地图渲染引擎,SVG
以便可以在没有任何第三方资源(例如在线谷歌地图)的情况下使用 VB.NET 加载它。
此地图可以拖动(移动 - 这不会在转换中考虑)、缩放(SVG 的原因),以及从静态文件或XDocument
变量从 SVG 加载。
我的目标是我正在尝试创建一个函数,在该函数中我可以GDI
在System.Drawing
渲染地图的特定点绘制对象。我计划在 a 中渲染地图,每次缩放都会刷新并在特定级别PictureBox
重新渲染地图。SVG
我的最终目标是有一种方法可以渲染这种类型的地图,并且能够在GDI
地图上的特定经度/纬度点绘制对象。
例如,如果我想在 的经度点和 的纬度点绘制circle
半径为 100 英里的,我会将经度和纬度传递给一个函数,以通过考虑缩放级别和其他来获取 中的相对点有关(例如 SVG 地图的边界)的信息,并返回在地图上呈现特定位置的相对点对。我创建了一个图解示例以在下面可视化这一点。
重要的是要考虑缩放 SVG 的方法是特殊的,以使事情变得更容易。例如,当用户请求将 放大到 2 的缩放因子时,地图的大小将被调整为当前大小的 2 倍(如果的大小是35.011665
135.768326
PictureBox
SVG
PictureBox
SVG
PictureBox
10,10
(20,20)
) 并且 SVG 被重绘以适合picturebox
自身。为了像实际地图一样拖动它,将注册点击事件,用户将PictureBox
自己移动实际地图。这可能会占用大量内存,但这个问题超出了这个问题的范围。
我已经尝试解决这个问题。这是我的代码,它不考虑比例因子,但只考虑包含特定区域的地图。另外,它根本不起作用,并且将点定位得太远。
Private Function ConvertGeoToPixel(ByVal latitude As Double, ByVal longitude As Double, ByVal imageWidth As Integer, ByVal imageHeight As Integer, ByVal mapLonLeft As Double, ByVal mapLonRight As Double, ByVal mapLatBottom As Double) As Point
Dim mapLatBottomRad As Double = mapLatBottom * Math.PI / 180
Dim latitudeRad As Double = latitude * Math.PI / 180
Dim mapLonDelta As Double = mapLonRight - mapLonLeft
Dim worldMapWidth As Double = (imageWidth / mapLonDelta * 360) / (2 * Math.PI)
Dim mapOffsetY As Double = worldMapWidth / 2 * Math.Log((1 + Math.Sin(mapLatBottomRad)) / (1 - Math.Sin(mapLatBottomRad)))
Dim x As Double = (longitude - mapLonLeft) * (imageWidth / mapLonDelta)
Dim y As Double = imageHeight - ((worldMapWidth / 2 * Math.Log((1 + Math.Sin(latitudeRad)) / (1 - Math.Sin(latitudeRad)))) - mapOffsetY)
Return New Point() With {
.X = Convert.ToInt32(x),
.Y = Convert.ToInt32(y)
}
End Function
这个功能不起作用。
此代码用于渲染 SVG。它使用库 SVG-NET.:
'LOAD THE SVG
Dim svgDocument = Svg.SvgDocument.Open("C:\users\admin\Pictures\jcss.svg")
svgDocument.ShapeRendering = SvgShapeRendering.Auto
Dim bmp As Bitmap = svgDocument.Draw(650, 700)
PictureBox2.Image = bmp
'Draggable SVG map.
Private Sub PictureBox2_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox2.MouseDown
StartPoint = PictureBox2.PointToScreen(New Point(e.X, e.Y))
IsDragging = True
End Sub
Private Sub PictureBox2_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox2.MouseMove
If IsDragging Then
Dim EndPoint As Point = PictureBox2.PointToScreen(New Point(e.X, e.Y))
PictureBox2.Left += (EndPoint.X - StartPoint.X)
PictureBox2.Top += (EndPoint.Y - StartPoint.Y)
StartPoint = EndPoint
End If
End Sub
'Used for Zooming and Dragging
Dim SF As String = 1
Private IsDragging As Boolean = False
Private StartPoint As Point
Private Sub PictureBox2_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox2.MouseUp
IsDragging = False
End Sub
'ZOOM THE SVG.
If e.Delta > 0 Then
SF = SF + 0.1
Dim svgDocument = Svg.SvgDocument.Open("C:\users\admin\Pictures\jcss.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\jcss.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
我知道地图的width
450 和height
530。我还知道,当根本不缩放时,地图的左经度是123.658963
,它的上纬度是45.523885
,它的右经度是145.820743
,它的下纬度是24.217586
。此信息包含在我下载 SVG 地图的源代码中。
SVG 地图可在此处下载:下载 SVG (G. Drive)
考虑到缩放因子,我是否可以编写任何函数,可以将经度和纬度转换为带有墨卡托投影的地图上的一个点?我已经为此工作了几个月,但我从未成功过。
编辑:
我发现我可以调整MapWidth
andMapHeight
来考虑缩放。如果不考虑缩放,该功能仍然不起作用。
解决方案
推荐阅读
- signal-processing - 为什么等幅信号分量的峰值大小在 FFT 频域表示中不相等?
- spring - 无法解包数据,无效状态 CLOSED - 未使用代理服务器
- amazon-web-services - 在单个 EC2 实例上托管多个 API,并通过具有 HTTPS 的子域访问它们
- python - 在python3.6中调用Matlab函数比直接在Matlab中运行同一个函数慢十倍
- spring-boot - 无法使用 Cloud Config Server 从 GIT 存储库中读取 application.properties
- r - 将数据框列名设置为字符串,即切换字符类型为“编程语言”类型?
- javascript - 在 Quilljs 中保留自定义 ID 属性
- c# - C# COM+ 服务无法接受来自 C# 客户端的事件注册
- r - 在 r studio 中更改图例标签 ggscatter 图
- python - 使用 Python 将 HTML 表格数据从电子邮件提取到 csv 文件,将第一列值提取到行标题