热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在自定义地图控件中缩放和平移-Zoomingandpanninginacustommapcontrol

Imwonderingifanyonecanhelpmewiththisoratleastprovidepointersintherightdirection.I

I'm wondering if anyone can help me with this or at least provide pointers in the right direction. I can post code if required however, due to the nature of the question, there is a lot of it and hence why I haven't so far.

我想知道是否有人可以帮助我,或至少提供正确方向的指示。如果需要,我可以发布代码,但由于问题的性质,有很多,因此我没有到目前为止。

I have a custom control which represents a "map". On this "map" I can draw specific glyphs at specific latitude and longitude's. I use GPS behind the scenes to obtain a geographic fix location which I then feed into the map as its origin position.

我有一个代表“地图”的自定义控件。在这张“地图”上,我可以在特定的纬度和经度上绘制特定的字形。我在后台使用GPS获取地理定位位置,然后我将其作为原点位置输入地图。

All objects drawn to the map have their lat/long positions converted to easting and northings (using an algorithm similar to the Google Maps/Bing projection) before being converted to screen pixels.

在转换为屏幕像素之前,绘制到地图的所有对象都将其纬度/长度位置转换为东向和北向(使用类似于Google Maps / Bing投影的算法)。

I take the centre of my "map" control client region as the reference screen position. When the "map" is panned, I store the delta mouse movement as an offset which when added to the reference position, gives me the location to start drawing my origin grid (this is also where the GPS position links in).

我将“地图”控制客户区域的中心作为参考屏幕位置。当平移“地图”时,我将增量鼠标移动存储为偏移量,当添加到参考位置时,为我提供开始绘制原点网格的位置(这也是GPS位置链接的位置)。

I hope this is making sense so far...

我希望到目前为止这是有意义的......

Now, all works well so far - I can draw objects at specific latitude and longitudes and they all appear in their correct locations relative to the centre of the origin grid.

现在,到目前为止一切运行良好 - 我可以在特定纬度和经度绘制物体,它们都出现在相对于原始网格中心的正确位置。

The issue which I can't seem to get my head around is how to zoom the map and focus on a specific area - like when using Google Maps/Google Earth, the position underneath the cursor at the point of zooming stays the same. Crudely, I use a zoom system which just increases or decreases the number of metres represented by 100 screen pixels (I'd like a more logarithmic style zoom but that will come later).

我似乎无法理解的问题是如何缩放地图并专注于特定区域 - 就像使用谷歌地图/谷歌地球时,光标下方缩放点的位置保持不变。粗略地说,我使用的是一个变焦系统,它只增加或减少100个屏幕像素所代表的米数(我想要一个更对数的样式变焦,但稍后会出现)。

What happens when I zoom in is that zooming always keeps my grid origin in the same position (this is because I use an offset for panning the map - and the offset isn't affected by zoom) however I have no idea how to think through the more correct zoom system.

当我放大时会发生的变化是缩放始终使我的网格原点保持在相同位置(这是因为我使用偏移来平移地图 - 并且偏移不受缩放影响)但是我不知道如何思考更正确的变焦系统。

I appreciate that this is a lot of text with no code - I can post code but like I said, there is a heck of a lot of it! I'm also sure that I've not explained my scenario very well but I'd appreciate any help at all.

我很欣赏这是很多没有代码的文本 - 我可以发布代码,但就像我说的那样,有很多内容!我也很确定我没有很好地解释我的情景,但我会感激任何帮助。

1 个解决方案

#1


All calculations are preferably done in GPS units, and conversions to device units should be the very last step. With this in mind, the following design should resolve your problem, with the assumption that you can store latitude and longitude in a float type:

所有计算最好以GPS单位进行,转换到设备单元应该是最后一步。考虑到这一点,以下设计应解决您的问题,假设您可以在float类型中存储纬度和经度:

enter image description here

type
  TMapCOntrol= class(TCustomControl)
  protected
    procedure Paint; override;
  public
    Glyph: TBitmap;
    //These are known, in GPS-coördinate units:
    MapRect: TRectF;
    ZoomFactor: Single;
    ZoomOrigin: TPointF;
    GlyphOrigin: TPointF;
  end;

procedure TMapControl.Paint;
var
  ZoomWidth: Single;
  ZoomHeight: Single;
  ZoomRect: TRectF;
  Scale: Single;
  GlyphPoint: TPoint;
begin
  // Calculation in GPS units:
  ZoomWidth := MapRect.Width * ZoomFactor;
  ZoomHeight := ZoomWidth * ClientHeight / ClientWidth;
  ZoomRect.Left := ZoomOrigin.X - ZoomWidth / 2;
  ZoomRect.Top := ZoomOrigin.Y - ZoomHeight / 2;
  // Not required for calculation, but for future convenience:
  ZoomRect.Width := ZoomWidth;
  ZoomRect.Height := ZoomHeight;
  // Calculation in device units:
  Scale := ZoomWidth / ClientWidth;  
  GlyphPoint.X := Round((GlyphOrigin.X - ZoomRect.Left) / Scale);
  GlyphPoint.Y := Round((GlyphOrigin.Y - ZoomRect.Top) / Scale);
  Canvas.Draw(GlyphPoint.X - Glyph.Width div 2,
    GlyphPoint.Y - Glyph.Height div 2, Glyph);
end;

The zoom factor is the percentage of the part of the total map being viewed. The scale factor converts the size of that portion to the size of your control.

缩放系数是正在查看的总地图部分的百分比。比例因子将该部分的大小转换为控件的大小。

Now the above code has some assumptions, most notably that the zoom origin and the zoom factor are known. Also, the origin of the map is considered to be (0, 0), which is not strictly required, but it keeps calculations easy and is practical too. If these are not the case, that I suggest you mimic the above or redesign what should be considered input and what be output. Or you need to explain better, wíth code, which conversions and calculations you are already doing. (You do not need to post all code for that, just strip to the absolute essential.)

现在上面的代码有一些假设,最值得注意的是变焦原点和缩放因子是已知的。此外,地图的原点被认为是(0,0),这不是严格要求的,但它使计算变得容易并且也是实用的。如果不是这种情况,我建议你模仿上述内容或重新设计应该考虑的输入和输出内容。或者你需要更好地解释代码,你正在做的转换和计算。 (你不需要为此发布所有代码,只需剥离绝对必要的。)


推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本文探讨了如何在编程中正确处理包含空数组的 JSON 对象,提供了详细的代码示例和解决方案。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • JavaScript中属性节点的类型及应用
    本文深入探讨了JavaScript中属性节点的不同类型及其在实际开发中的应用,帮助开发者更好地理解和处理HTML元素的属性。通过具体的案例和代码示例,我们将详细解析如何操作这些属性节点。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 在 Swift 编程中,遇到错误提示“一元运算符 '!' 不能应用于 '()' 类型的操作数”,通常是因为尝试对没有返回值的方法或函数应用逻辑非运算符。本文将详细解释该错误的原因,并提供解决方案。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 本文详细介绍了如何在ECharts中使用线性渐变色,通过echarts.graphic.LinearGradient方法实现。文章不仅提供了完整的代码示例,还解释了各个参数的具体含义及其应用场景。 ... [详细]
  • 本文详细介绍了如何在Kendo UI for jQuery的数据管理组件中,将行标题字段呈现为锚点(即可点击链接),帮助开发人员更高效地实现这一功能。通过具体的代码示例和解释,即使是新手也能轻松掌握。 ... [详细]
author-avatar
丹丹2502912601
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有