我现在用GDI+实现了地图的显示,平移,缩放等功能,但是当地图的数据量过大时地图的显示,平移和缩放会变得非常慢,几乎让人难于接受。我担心我在实现上面的功能时有些思路不正确。现将我的实现方法和我的疑问写在下面,欢迎高手莅临指正。实现方法:
1.读取地图数据,将点和线以及他们的属性信息解析出来,存储在点和线的对象中。
2.遍历对象中的每一个点和线,计算它们的坐标,然后显示出来。
3.平移时,我的做法是坐标系不变,重新计算各个点的坐标,将它们显示出来,在mousemove事件中用 了this.panel1.Invalidate()语句来刷新地图。
4.实现缩放时,改变比例尺Scale,然后调用this.panel1.Invalidate()来刷新地图我的疑问:
1.GDI+中有没有画点的函数?我使用g.FillEllips()方法来实现的。
2.平移和缩放时,我的实现方法是坐标系不变,重新计算各点的坐标,然后显示,不知道各位高手是用什么方法实现平移的?
3.我还实现了拖动的功能,可以拖动点和线,但是我每次都使用了this.panel1.Invalidate()来刷新地图,这样会使显示速度变慢,但我不知道如何得到需要刷新的区域,如果只对需要刷新的区域重绘,速度定然快了许多。
4.在显示点和线时,每个点和线都是用g.FillEllips()和g.drawline()来实现的,这样是不是会降低显示速度?该如何改进呢?
5.缩放时,我没有使用g.ScaleTransform()方法,而是使用了一个全局变量Scale,然后计算坐标来实现的。因为使用了g.ScaleTransform()后,点的大小会随着比例尺的大小而改变,这不是我想要的。我以前没有做过图形编程,看的资料也少,我的实现方法都是自己想出来的,有些地方肯定走了很大的弯路,在此恳请各位前辈高人不吝赐教。

解决方案 »

  1.   

    使用 Bitmap.SetPixel 方法来画点
      

  2.   

    Bitmap.SetPixel这个方法也是相当慢的,不推荐,呵呵
      

  3.   

    贴出你的代码来,我帮你一起看看,同时请参考:
    http://begincsdn.cnblogs.com/archive/2005/07/14/193005.html
      

  4.   

    在OnPaint()中做一下坐标变换,将y轴改为正向向上,原点改在panel控件的中间点。
    //变换坐标系
    e.Graphics.Transform=new Matrix(1,0,0,-1,0,0);
    e.Graphics.TranslateTransform(this.ClientSize.Width/2,this.ClientSize.Height/2,MatrixOrder.Append);由于绘图有很多代码,现在只给出绘制node的代码。//绘制Node
    private void DrawNode(Graphics g,Data roadData)
    {
    Node mynode;
    Point pnt=new Point(); if(roadData==null ) 
    return;
    if(roadData.node==null)
    return; for(int i=0;i<roadData.node.Length;i++)
    {
    mynode=roadData.node[i];
    if(mynode.isDelete)
    continue;

    pnt=convertPnt(mynode.x,mynode.y); if(this.displayItem.roadNode)
    {
    g.FillEllipse(Brushes.Black,(float)pnt.X-1.5f,(float)pnt.Y-1.5f,3,3);
    }
    if(mynode.Light_flag==1)
    {
    if(this.displayItem.roadLight)//红绿灯(用红色圆点表示)
    {
    g.FillEllipse(Brushes.Red,pnt.X-3,pnt.Y-3,6,6);
    }
    }

    string str=mynode.kind.Substring(2);
    if(str=="10")//收费站(用填充的红色三角形表示)
    {
    this.DrawToll(g,pnt);
    }
    }
    }
      

  5.   

    如果对效率要求很高又不太可能在硬件上提供优势的话直接操作Win32API(我没记错的话主要在System32目录下的GDI32.dll和User32.dll这2个文件里)来在底层画吧.
      

  6.   

    对效率也不是要求太高,只要不是慢的难以接受就可以了,GDI+作为一种新技术,应该可以胜任的。要不然不就没用了么。
      

  7.   

    兄弟加上双缓冲应该可以把效率提高一些。我个人对你的平移方式的一点意见,
    我也做过图形处理的程序,也用的是GDI+,我下面说得不对请不要见怪:
    平移应该尽可能的利用现有的图像,尽可能不要重新绘制图形,这是总的原则
    首先获得要平移的区域(Rectangle或其他)的图像,存储在内存中
    改变这个Rectangle的起点坐标,其他不变,然后把内存中的图形放到新坐标显示就好了总之尽量利用现有的图形来操作,避免频繁的创建新图形。
      

  8.   

    To  storm97(风暴不再):
        非常感谢你提出的建议,可是我不知道具体怎么操作,不知道你能不能贴出部分代码?
      

  9.   

    构造函数添加以下内容:
    this.SetStyle(ControlStyles.UserPaint,true);
    this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
    this.SetStyle(ControlStyles.DoubleBuffer,true);得到整幅图的一个剪切区域有现成的方法,你查一下。
      

  10.   

    MARK,只用MAPINFO做过GIS的东西。
      

  11.   

    gdipkf1986(纯粹理性) 说的对,我确实没有整幅图,全是用点和线直接在屏幕上画出来的。你说的得到整幅图是不是先在bmp图像上绘制整个地图,然后显示出来?如果你有代码,贴出来看看,我不知道具体是怎么实现的。