一般的切图都是基于GIS平台,这种方式编程简单,但效率不高。通过MITab在内存中切图,可极大的提高效率。实现切图的步骤:
1、空间对象的读取。
2、空间对象的分块。
3、空间对象在GDI中的映射。
4、空间对象在GDI中的绘制。
我们重温下使用MITab读取MapInfo的TAB文件代码:
'/************************************************************************/ '/* ReadFile */ '/************************************************************************/ Sub ReadFile(ByVal pszFilename As String) Dim dataset As Long = mitab_c_open(pszFilename) If (dataset = 0) Then sTmp = Space$(255) i1 = mitab_c_getlasterrormsg_vb(sTmp, 255) MsgBox ("mitab_c_open: " & pszFilename & " failed." & vbCrLf & Left$(sTmp, i1)) Exit Sub End If feature_id As Long = mitab_c_next_feature_id(dataset, -1) Do While feature_id <> -1 '/* -------------------------------------------------------------------- */ '/* Read next feature object */ '/* -------------------------------------------------------------------- */ feature = mitab_c_read_feature(dataset, feature_id) If (feature = 0) Then sTmp = Space$(255) i1 = mitab_c_getlasterrormsg_vb(sTmp, 255) MsgBox ("Failed to read feature " & Str$(feature_id) & vbCrLf & Left$(sTmp, i1)) Exit Sub End If feature_type = mitab_c_get_type(feature) num_parts = mitab_c_get_parts(feature) '/* -------------------------------------------------------------------- */ '/* ... and coordinates. */ '/* In real applications, we would probably want to handle each */ '/* object type differently but we won't do it here. */ '/* -------------------------------------------------------------------- */ For partno = 0 To num_parts - 1 num_points = mitab_c_get_vertex_count(feature, partno) For pointno = 0 To num_points - 1 dX = mitab_c_get_vertex_x(feature, partno, pointno) dY = mitab_c_get_vertex_y(feature, partno, pointno) Next Next mitab_c_destroy_feature (feature) feature_id = mitab_c_next_feature_id(dataset, feature_id) Loop mitab_c_close (dataset) End Sub
地图的分块可以参考谷歌地图的金字塔模型的地图瓦片技术。
映射根据地图所在块的大小和图像尺寸进行换算,如:(X坐标 - 空间对象所在块左上角X坐标) / 块大小 * 图像大小, (空间对象所在块左上角Y坐标 - Y坐标) / 块大小 * 图像大小)。其中空间坐标系的Y坐标向上为正,而图像坐标系的Y坐标向下为正。
绘制代码:
'区域 Sub DrawPolygon(ByVal feature As Long, ByVal partno As Long, ByVal block As Rectangle, ByVal g As Graphics) Dim num_points As Long = mitab_c_get_vertex_count(feature, partno) Dim ps(0 To num_points - 1) As Drawing.PointF For pointno As Long = 0 To num_points - 1 dX = mitab_c_get_vertex_x(feature, partno, pointno) dY = mitab_c_get_vertex_y(feature, partno, pointno) ps(i) = New PointF((dX - block.Left) / block.Width * 256, (block.Top - dY) / block.Height * 256) Next Dim fc As Color = Color.FromArgb(mitab_c_get_brush_fgcolor(feature)) fc = Color.FromArgb(fc.R, fc.G, fc.B) Dim bc As Color = Color.FromArgb(mitab_c_get_brush_bgcolor(feature)) bc = Color.FromArgb(bc.R, bc.G, bc.B) g.FillPolygon(New Drawing.SolidBrush(fc), ps) Dim c As Color = Color.FromArgb(mitab_c_get_pen_color(feature)) c = Color.FromArgb(c.R, c.G, c.B) g.DrawPolygon(New Drawing.Pen(c, mitab_c_get_pen_width(feature)), ps) End Sub
'线 Sub DrawLine(ByVal feature As Long, ByVal partno As Long, ByVal block As Rectangle, ByVal g As Graphics) Dim num_points As Long = mitab_c_get_vertex_count(feature, partno) Dim ps(0 To num_points - 1) As Drawing.PointF For pointno As Long = 0 To num_points - 1 dX = mitab_c_get_vertex_x(feature, partno, pointno) dY = mitab_c_get_vertex_y(feature, partno, pointno) ps(i) = New PointF((dX - block.Left) / block.Width * 256, (block.Top - dY) / block.Height * 256) Next Dim c As Color = Color.FromArgb(mitab_c_get_pen_color(feature)) c = Color.FromArgb(c.R, c.G, c.B) g.DrawLines(New Drawing.Pen(c, mitab_c_get_pen_width(feature)), ps) End Sub