地图比例尺是地图当中不可缺少的元素。在地理信息系统软件的设计与开发过程中,如何绘制地图比例尺是一个需要认真解决的问题。在解决过程中有如下几个问题需要提出:
1、采用什么工具?
2、不同类型的地图比例尺如何分别绘制?
3、如何控制地图比例尺的绘制精度?
前面两个问题好解决。在VC中采用GDI即可完成各种图形的绘制,而通过研究不同类型的比例尺的特点,咱们完全可以通过GDI函数完成这些比例尺图形的绘制。
咱们来详细探讨如何控制地图比例尺的绘制精度。所谓控制地图比例尺的绘制精度,就是说屏幕上显示的长度和实际代表的空间距离的比例应该和显示出来的数字相符合,不然,咱们所绘制的比例尺就失去了意义。要做到这一点,我们有必要先了解一下坐标映射。
我们现在要接触两种坐标,一种是设备坐标,另一种则是逻辑坐标。设备坐标是针对计算机输出设备而言的,比如显示器上的坐标,打印机上的坐标,在一般的情况之下进行绘图操作都是以像素作为绘图单位。逻辑坐标可以理解为咱们地图上的实际坐标,其单位可能是米或者分米等。
这种情况要求我们有一个设备坐标到逻辑坐标的对应关系,这就是坐标映射。WINDOWS提供了几种映射方式,可以实现对应的逻辑坐标系。例如,MM_TEXT方式下,设备坐标系的坐标原点位于屏幕的左上角,X轴和Y轴的正方向分别指向我们面对屏幕的右方和下方,它的绘图单位是像素;MM_LOMETRIC方式下,绘图单位是0.1毫米,坐标原点位于屏幕的左上角,X轴和Y轴正方向分别指向面对屏幕的右方和上方。我们在地图比例尺的绘制过程中会选择MM_LOMETRIC方式,道理很简单,它和我们实际使用的地图坐标系很相似,它们的坐标单位只是数量级的差别,转换是很方便的。
注:关于这方面的内容,大家可以参考一下刘先生发表的一篇文章《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是如何实现的。首先咱们用SetMapMode来完成映射模式的转换。由于咱们要绘制的比例尺在X方向是充满整个绘制范围的,因此绘制范围在屏幕上的显示大小(ds)与实际代表的空间距离(DS)之比便是比例尺大小1/m_fScale,即: 1/m_fScale = ds / DS;
为了计算ds,我们首先把以像素为单位表达的屏幕坐标转换为以0.1mm为单位表达的屏幕坐标,方法是通过DPtoLP函数: 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);
现在求取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);