SharpMap深度分析:地圖渲染、座標和比例尺

來源:互聯網
上載者:User
文章目錄
  • 不同的地圖單位和投影下的地圖渲染操作

上篇對SharpMap的分析文章裡,一個重點就是地圖的渲染流程和機制,這裡就不專門介紹這個問題了,只是就座標的一些細節問題分析一下。

地圖都有一個單位(Unit)、比例尺(Zoom)的概念,還有投影的問題。對於Unit,一般使用Km、m或者經緯度來表示。一幅地圖,在其所有資料的Unit和投影都一致的情況下,在繪製這些對象到地圖時,就要根據比例尺進行座標轉換;同時,在進行地圖的縮放、移動、拾取等操作的時候,滑鼠的座標是案頭的座標系統,也要轉換到地圖座標系統(一般稱為World Coordinates System,簡稱WCS)。

首先來看比例(Zoom)在Map類裡的定義:

private double _Zoom;

public double Zoom
{
    get { return _Zoom; }
    set {
        if (value < _MinimumZoom)
            _Zoom = _MinimumZoom;
        else if (value > _MaximumZoom)
            _Zoom = _MaximumZoom;
        else
            _Zoom = value;
        if (MapViewOnChange != null)
            MapViewOnChange();
    }
}

這個Zoom表示使用地圖Unit表示的地圖寬度。例如地圖單位是Km,那麼如果目前地圖的寬度是500Km,Zoom就是500。這個和Mapinfo中Zoom的概念是一致的。

那麼在渲染的時候,就要對所有對象進行座標轉換,轉換為要渲染的圖片的座標系統,然後調用GDI+進行渲染。

對於對象的渲染,定義在Layer的名稱空間裡,在VectorLayer類的Render方法裡,根據Geometry對象的層次依次遍曆各個對象,然後調用Rendering名稱空間的VectorRenderer的各個方法來渲染不同的點、線、面等對象。

在渲染具體對象時,我們看到這些方法都調用了一個TransformToImage的方法,而這個方法定義在不同的Geometry名稱空間的不同類裡,目的是由空間對象經過座標變換後返回一個.net的繪圖對象。

我們把這個流程整理如下:

Map對象GetMap方法→GetMap方法遍曆其Layer,調用Layer的Render方法→各個Layer開始渲染自己,對於柵格和WMS層,返回範圍內的圖片即可,主要是VectorLayer的渲染→VectorLayer調用自己DataSource Provider的GetFeaturesInView方法,返回範圍內的對象到一個列表→依次遍曆列表的各個對象,調用Rendering名稱空間的VectorRenderer的各個方法來渲染不同的點、線、面等對象→渲染這些對象前,調用幾何對象的TransformToImage方法,返回一個.net的繪圖對象→GDI+根據Style渲染

在最後一步,各個對象調用的TransformToImage方法其實是逐次轉換這個對象的各個點。而點的座標轉換定義在Utilities.Transform下,有2個方法:

public static System.Drawing.PointF WorldtoMap(SharpMap.Geometries.Point p, SharpMap.Map map)

public static SharpMap.Geometries.Point MapToWorld(System.Drawing.PointF p, SharpMap.Map map)
分別轉換WCS座標到Image座標和轉換Image座標到WCS座標。

這是轉碼:

System.Drawing.PointF result = new System.Drawing.Point();
double Height = (map.Zoom * map.Size.Height) / map.Size.Width;
double left = map.Center.X - map.Zoom/2;
double top = map.Center.Y + Height/2;
double pxSize = map.Zoom / map.Size.Width;
result.X = (float)Math.Round(((p.X - left) / pxSize), 0);
result.Y = (float)Math.Round(((top - p.Y) / pxSize), 0);
return result;

left和top表示當前地圖的左上方座標,Height是高度,需要通過Zoom和Height來換算一下,也許寫作map.Zoom * (map.Size.Height / map.Size.Width)更好理解一點。pxSize相當於在最終的圖片上的一個單位相當於WCS的多少單位,這樣,(p.X - left) / pxSize就是橫座標,縱座標由於圖片y軸相反,因此是(top - p.Y) / pxSize。有過Dos或者Windows圖形編程經驗的人對於這樣的代碼應該是非常熟悉。

這段代碼的計算left、height、top、pxSize這些參數的語句其實應該在Map每次更改Zoom時計算比較好,因為這個函數會被調用非常多次(每個點都要轉換座標),不過這些都是最佳化的話了,可以放在系統穩定以後。

不同的地圖單位和投影下的地圖渲染操作

SharpMap目前還沒有Unit的問題,在Map和Layer裡也沒有定義Unit,投影在新版0.90的beta裡有部分代碼。象ArcGIS和Mapinfo都支援動態投影,也就是對Map定義一個Unit和投影,對不同的Layer定義一個投影和Unit,他可以自動的轉換這些Layer的Unit到地圖,然後疊加顯示。

這樣的話,在顯示(渲染)時,就需要對所有對象都要進行投影和尺度變換。雖然似乎在開啟資料的時候進行轉換,但是由於對於空間資料庫,一次開啟所有資料已經越來越不可能,而且對資料作分析的時候,如果資料開啟時轉換了資料的Unit,那麼分析結果也會出現問題。因此,這類實現應該是在地圖渲染時進行投影和變換。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.