热门标签 | 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),这不是严格要求的,但它使计算变得容易并且也是实用的。如果不是这种情况,我建议你模仿上述内容或重新设计应该考虑的输入和输出内容。或者你需要更好地解释代码,你正在做的转换和计算。 (你不需要为此发布所有代码,只需剥离绝对必要的。)


推荐阅读
  • 本文探讨了如何利用 Application 对象在 PHP 应用程序中共享数据,特别是在多用户环境中保持数据的一致性和安全性。文章还介绍了 Application 对象的基本结构、方法和事件,并提供了实际应用示例。 ... [详细]
  • 本文提供了详细的指导,帮助开发者了解如何使用PHP插件进行网站内容的翻译,特别是针对WordPress插件和主题的汉化及多语言支持。 ... [详细]
  • C#爬虫Fiddler插件开发自动生成代码
    哈喽^_^一般我们在编写网页爬虫的时候经常会使用到Fiddler这个工具来分析http包,而且通常并不是分析一个包就够了的,所以为了把更多的时间放在分析http包上,自动化生成 ... [详细]
  • django项目中使用手机号登录
    本文使用聚合数据的短信接口,需要先获取到申请接口的appkey和模板id项目目录下创建ubtils文件夹,定义返回随机验证码和调取短信接口的函数function.py文件se ... [详细]
  • 在现代移动应用开发中,尤其是iOS应用,处理来自服务器的JSON数据是一项基本技能。无论是使用Swift还是PHP,有效地解析和利用JSON数据对于提升用户体验至关重要。本文将探讨如何在Swift中优雅地处理JSON,以及PHP中处理JSON的一些技巧。 ... [详细]
  • KNN算法在海伦约会预测中的应用
    本文介绍如何使用KNN算法进行海伦约会的预测。我们将从数据导入、数据预处理、数据可视化到最终的模型训练和测试进行全面解析。 ... [详细]
  • JobScheduler5.0源码分析
    0.JobScheduler执行代码mJobScheduler(JobScheduler)getSystemService(Context.JOB_SCHEDULER_SERVICE); ... [详细]
  • 获取年月日,之前的日期不能选择日历cCalendar.getInstance();获取系统的工具类【可以获取时间】DatePickerDialogdate ... [详细]
  • 本文讨论了在使用表单上传文件时遇到的值为空问题,并提供了几种有效的解决方案。 ... [详细]
  • 实现 WinForms DataGridView 的多级表头功能
    本文介绍了如何在 WinForms 的 DataGridView 控件中实现多级表头,以满足复杂数据展示的需求。通过自定义绘制技术,我们可以在 DataGridView 中实现类似 Web 表格的多级表头效果。 ... [详细]
  • Lua基本语法lua与C#的交互(相当简单详细的例子)
    lua脚本与C#的交互本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验——高分辨率用户请根据需求调整网页缩放比例)1LuaAndC#——L ... [详细]
  • 这个报错出现在userDao里面,sessionfactory没有注入。解决办法:spring整合Hibernate使用test测试时要把spring.xml和spring-hib ... [详细]
  • 使用EF Core在.Net Core控制台应用中操作SQLite数据库
    本文介绍如何利用Visual Studio 2019和Windows 10环境,通过Entity Framework Core(EF Core)实现对SQLite数据库的读写操作。项目源代码可从百度网盘下载。 ... [详细]
  • 本文将指导你如何通过自定义配置,使 Windows Terminal 中的 PowerShell 7 更加高效且美观。我们将移除默认的广告和提示符,设置快捷键,并添加实用的别名和功能。 ... [详细]
  • Qt应用开发:创建基本窗口
    本文介绍如何使用Qt框架创建基础窗口的两种方法。第一种方法直接在main函数中创建并显示窗口;第二种方法通过定义一个继承自QWidget的类来实现更复杂的功能。 ... [详细]
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社区 版权所有