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

时间:2015-05-05 20:48:25

标签: delphi zoom coordinates latitude-longitude

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

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

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

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

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;

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

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