地圖比例尺是地圖當中不可缺少的元素。在地理信息系統(tǒng)軟件的設計與開發(fā)過程中,如何繪制地圖比例尺是一個需要認真解決的問題。在解決過程中有如下幾個問題需要提出:
  1、采用什么工具?
  2、不同類型的地圖比例尺如何分別繪制?
 。、如何控制地圖比例尺的繪制精度?

  前面兩個問題好解決。在VC中采用GDI即可完成各種圖形的繪制,而通過研究不同類型的比例尺的特點,咱們完全可以通過GDI函數(shù)完成這些比例尺圖形的繪制。
  咱們來詳細探討如何控制地圖比例尺的繪制精度。所謂控制地圖比例尺的繪制精度,就是說屏幕上顯示的長度和實際代表的空間距離的比例應該和顯示出來的數(shù)字相符合,不然,咱們所繪制的比例尺就失去了意義。要做到這一點,我們有必要先了解一下坐標映射。
  我們現(xiàn)在要接觸兩種坐標,一種是設備坐標,另一種則是邏輯坐標。設備坐標是針對計算機輸出設備而言的,比如顯示器上的坐標,打印機上的坐標,在一般的情況之下進行繪圖操作都是以像素作為繪圖單位。邏輯坐標可以理解為咱們地圖上的實際坐標,其單位可能是米或者分米等。
  這種情況要求我們有一個設備坐標到邏輯坐標的對應關系,這就是坐標映射。WINDOWS提供了幾種映射方式,可以實現(xiàn)對應的邏輯坐標系。例如,MM_TEXT方式下,設備坐標系的坐標原點位于屏幕的左上角,X軸和Y軸的正方向分別指向我們面對屏幕的右方和下方,它的繪圖單位是像素;MM_LOMETRIC方式下,繪圖單位是0.1毫米,坐標原點位于屏幕的左上角,X軸和Y軸正方向分別指向面對屏幕的右方和上方。我們在地圖比例尺的繪制過程中會選擇MM_LOMETRIC方式,道理很簡單,它和我們實際使用的地圖坐標系很相似,它們的坐標單位只是數(shù)量級的差別,轉換是很方便的。
  注:關于這方面的內容,大家可以參考一下劉先生發(fā)表的一篇文章《VC6.0映射模式轉換及如何消除坐標誤差》,但這篇文章結尾所提供的方案不可取,大家可以改進改進!
  為了方便比例尺的繪制,咱們首先定義Scale類。另外還定義一個枚舉類型,用于列舉比例尺的類型。

enum FGScaleType
{
  ST_SINGLELINE,
  ST_SINGLELINE2,
  ST_SINGLELINE3,
  ST_FILLRECT,
  ST_FILLRECT2,
  ST_STEPPEDLINE,
  ST_LINERECT
};

class CFGScaleDraw
{
  ......

  FGScaleType m_ScaleType;
  float m_fScale;
  int m_nMinX, m_nMaxX, m_nMinY, m_nMaxY;

public:
  void SetScaleType(int type);
  void SetScale(float scale);
  void SetRect(CRect rect);
  void SetRect(int minx, int miny, int maxx, int maxy);
  void DrawScale(CDC* pdc);
};
  其中,m_fScale是比例尺分母,例如1:10000的比例尺,m_fScale = 10000;m_nMinX, m_nMaxX, m_nMinY, m_nMaxY控制地圖比例尺繪制的范圍;DrawScale用于比例尺輸出。
  咱們重點來看看DrawScale是如何實現(xiàn)的。首先咱們用SetMapMode來完成映射模式的轉換。由于咱們要繪制的比例尺在X方向是充滿整個繪制范圍的,因此繪制范圍在屏幕上的顯示大小(ds)與實際代表的空間距離(DS)之比便是比例尺大小1/m_fScale,即:   1/m_fScale = ds / DS;
  為了計算ds,我們首先把以像素為單位表達的屏幕坐標轉換為以0.1mm為單位表達的屏幕坐標,方法是通過DPtoLP函數(shù):   CPoint p[2];
  p[0].x = m_nMinX;
  p[0].y = m_nMinY;
  p[1].x = m_nMaxX;
  p[1].y = m_nMaxY;
  pdc->DPtoLP(p, 2);
  現(xiàn)在求取ds = p[1].x - p[0].x。再求取DS = ds * m_fScale * 0.00001。(假設地圖單位為米)
  這個DS是需要顯示出來,它是屏幕上所顯示的線段所代表的空間距離。

  關于地圖比例尺繪制的核心問題已經解決,剩下的就由你來完成了:)

CFGScaleDraw的使用:   CFGScaleDraw m_ScaleDraw;
  m_ScaleDraw.SetScale(10000);
  m_ScaleDraw.SetRect(100, 100, 400, 120);
  m_ScaleDraw.SetScaleType(ST_SINGLELINE);
  m_ScaleDraw.DrawScale(pDC);