最近用GDIPlus做符號庫,發現很多問題,nightware已經在一篇文章《GDI+的雷區 》中指出過http://blog.csdn.net/Nightmare/archive/2005/04/22/359092.aspx。
nightware說得很對,但我覺得還有一點必須提出來,GDIPlus使用float型,精度不夠,在縮放比達到float的最小數值極限,問題就出來了,而在GIS程式中這個還是很容易碰到的。
另外,提供了int型座標的所有繪製方法應該都只是調用了float型座標的方法,因為GDIPlus的繪製座標都是全局座標,int型此時只有做一個全部都用int型座標的簡單程式時才用得上,實際應用中,這種程式通常只是玩具。所以提供int型座標是意義不大的。
另外GDIPlus中還有很多的bug,比如下面一個例子,可能還是精度的問題,包括取樣精度。scale小於168000f時,矩形、橢圓和直線都可以繪製出來、到168000f時,直線繪製不出來了,到169000f時,橢圓也出不來了。
float scale = 168000f;
float width = 100f / scale;
PointF pt = new PointF(100f, 100f);
RectangleF rect = new RectangleF(pt.X, pt.Y, width, width);
e.Graphics.TranslateTransform(pt.X, pt.Y);
e.Graphics.ScaleTransform(scale, scale);
e.Graphics.TranslateTransform(-pt.X, -pt.Y);
e.Graphics.FillRectangle(new SolidBrush(Color.Red), rect);
e.Graphics.FillEllipse(new SolidBrush(Color.Green), rect);
e.Graphics.DrawLine(new Pen(Color.Blue, 0), pt, new PointF(pt.X + width, pt.Y + width));
提一下GDIPlus的繪製效率。我測試了5000個多邊形,大約15M點資料。在VC下用GDI繪製大約450ms,C#用GDIPlus大約1450ms,VC下用OpenGL繪製只要幾十毫秒。記得以前看過有人做過測試,但我找不到那篇文章了。
要解決精度的問題,除非不用GDI+的座標轉換,整個繪製過程中保持全局座標系和裝置座標系統一,然後自己記錄實際座標與裝置座標的縮放和位移,然後在繪製時將實際座標轉換為裝置座標。以前用GDI就是這麼乾的,因為VC做這種計算很快,release下上面的15M資料只用20-30ms。但在C#中這個計算要200-300ms,太耗時間。
總結下來,GDIPlus真的比較垃圾,不過做對精度和繪製效率要求不高的圖形程式,用GDIPlus可以很容易做出很花的效果。