天天看點

ArcEngine中實作Symbol的預覽

版權聲明:歡迎評論和轉載,轉載請注明來源。 https://blog.csdn.net/zy332719794/article/details/9951573

  我們在程式開發的時候經常用到Symbol,有時還需要預覽他們的樣式。這時,我們需要擷取其預覽圖檔,然後放到PictureBox等容器中。是以重點是怎樣擷取他們的預覽圖檔。

  這裡提供了兩種方法。

第一種方法

使用 IStyleGalleryClass 接口

  IStyleGalleryClass擁有一個Preview方法,該方法可以将Symbol的預覽寫入到圖像中,同時提供一個範圍參數。

  下面提供一段參考代碼:

public static Image GetImageFromSymbol(ISymbol pSymbol, int width, int height)
        {
            IStyleGalleryClass styleGalleryClass = null;
            if (pSymbol is IMarkerSymbol)
            {
                styleGalleryClass = new MarkerSymbolStyleGalleryClass();
            }
            else if (pSymbol is ILineSymbol)
            {
                styleGalleryClass = new LineSymbolStyleGalleryClass();
            }
            else if (pSymbol is IFillSymbol)
            {
                styleGalleryClass = new FillSymbolStyleGalleryClassClass();
            }

            if (styleGalleryClass != null)
            {
                return GetImage(styleGalleryClass, pSymbol, width, height);
            }
            
            return null;
        }

        private static Image GetImage(IStyleGalleryClass styleGalleryClass, 
            ISymbol symbol, int width, int height)
        {
            Image img = new Bitmap(width, height);
            Graphics gc = Graphics.FromImage(img);
            IntPtr hdc = gc.GetHdc();

            var rect = new tagRECT();
            rect.left = 0;
            rect.top = 0;
            rect.right = width;
            rect.bottom = height;
            styleGalleryClass.Preview(symbol, hdc.ToInt32(), ref rect);
            gc.ReleaseHdc(hdc);
            gc.Dispose();
            return img;
        }
                   

  這種方法對于大多數的預覽圖檔都能擷取,而且速度也非常快。

  當我們的需求更複雜時,比如當我想得到一條折線的預覽,這種方法就不能滿足我的要求了。要達到目的,我們可以采用下面一種方法。

第二種方法

使用 ISymbol 接口

  ISymbol擁有一個Draw方法。通過ISymbol的SetupDC方法,設定轉換屬性ITransformation後,調用Draw方法,可以得到預覽圖檔。

/// <summary>
        /// 擷取Symbol的bitmap預覽圖檔。
        /// 具有自定義的範圍或路徑樣式。
        /// </summary>
        /// <returns></returns>
        private static Bitmap PreviewItem(ISymbol symbol, int width, int height)
        {
            var bitmap = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bitmap);
            double dpi = graphics.DpiY;

            IEnvelope envelope = new EnvelopeClass();
            envelope.PutCoords(0, 0, bitmap.Width, bitmap.Height);
            IGeometry geometry = GetSymbolGeometry(symbol, envelope);
            
            var myRect = new tagRECT();
            myRect.bottom = bitmap.Height;
            myRect.left = 0;
            myRect.right = bitmap.Width;
            myRect.top = 0;

            IDisplayTransformation displayTransformation = new DisplayTransformationClass();
            displayTransformation.VisibleBounds = envelope;
            displayTransformation.Bounds = envelope;
            displayTransformation.set_DeviceFrame(ref myRect);
            displayTransformation.Resolution = dpi;

            IntPtr hdc = graphics.GetHdc();
            symbol.SetupDC(hdc.ToInt32(), displayTransformation);
            symbol.Draw(geometry);
            symbol.ResetDC();

            graphics.ReleaseHdc(hdc);
            graphics.Dispose();

            return bitmap;
        }

        private static IGeometry GetSymbolGeometry(ISymbol symbol, IEnvelope envelop)
        {
            IGeometry geometry = null;

            if (symbol is IMarkerSymbol)
            {
                var area = (IArea) envelop;
                geometry = area.Centroid;
            }
            else if (symbol is ILineSymbol)
            {
                IPolyline polyline = new PolylineClass();
                var pointCollection = (IPointCollection) polyline;
                
                IPoint point = new PointClass();
                object before = Type.Missing;
                object after = Type.Missing;

                // 自定義一條具有三段的折線
                point.PutCoords(envelop.XMin, envelop.YMax);
                pointCollection.AddPoint(point, ref before, ref after);
                point.PutCoords((envelop.XMax - envelop.XMin)/3, envelop.YMin);
                pointCollection.AddPoint(point, ref before, ref after);
                point.PutCoords((envelop.XMax - envelop.XMin) * 2 / 3, envelop.YMax);
                pointCollection.AddPoint(point, ref before, ref after);
                point.PutCoords((envelop.XMax - envelop.XMin), envelop.YMin);
                pointCollection.AddPoint(point, ref before, ref after);

                geometry = polyline;
            }
            else if (symbol is IFillSymbol)
            {
                geometry = envelop;
            }
            else if (symbol is ITextSymbol)
            {
                var area = (IArea) envelop;
                geometry = area.Centroid;
            }

            return geometry;
        }           

  代碼中 GetSymbolGeometry 方法是設定繪制的位置、範圍、或路徑。這種方式比較靈活。

  第二種方法相較于第一種方法在效率上沒有那麼高,但第二種方法可用于擷取少量有必要特殊樣式預覽的圖檔的情況。是以在産生大量預設樣式的預覽圖檔是盡量采用第一種方法,需要特定的樣式輸出時使用第二種方法。

  歡迎轉載,轉載請注明來源:

http://blog.csdn.net/zy332719794/article/details/9951573