Point Rendering? not only Bitmap as symbol....

Topics: General Topics, SharpMap v0.9 / v1.x
Sep 17, 2010 at 2:21 PM

Hi!

Should be very very nice to be able to render custom vectorial symbol on Point Feature. 

 

This should involve the  VectorRenderer "DrawPoint" method ...   it should take not just a "Bitmap" as parameter but should be nice it it can took a sort of "delegate" to a method that render directly vectors on the "Graphic" object....

 

Wath do you thing about?

 

Alberto

Sep 17, 2010 at 2:29 PM

...in the end...   this property of Vector Style should be collapsed into a sort of Interface like ISymbol   

And into ISymbol should be nice to be able to switch from a raster symbol (bitmap like now) or into a Vectorial Symbol 

        /// <summary>
        /// Symbol used for rendering points
        /// </summary>
        public Bitmap Symbol
        {
            get { return _Symbol; }
            set { _Symbol = value; }
        }

        /// <summary>
        /// Scale of the symbol (defaults to 1)
        /// </summary>
        /// <remarks>
        /// Setting the symbolscale to '2.0' doubles the size of the symbol, where a scale of 0.5 makes the scale half the size of the original image
        /// </remarks>
        public float SymbolScale
        {
            get { return _SymbolScale; }
            set { _SymbolScale = value; }
        }

        /// <summary>
        /// Gets or sets the offset in pixels of the symbol.
        /// </summary>
        /// <remarks>
        /// The symbol offset is scaled with the <see cref="SymbolScale"/> property and refers to the offset af <see cref="SymbolScale"/>=1.0.
        /// </remarks>
        public PointF SymbolOffset
        {
            get { return _SymbolOffset; }
            set { _SymbolOffset = value; }
        }

        /// <summary>
        /// Gets or sets the rotation of the symbol in degrees (clockwise is positive)
        /// </summary>
        public float SymbolRotation
        {
            get { return _SymbolRotation; }
            set { _SymbolRotation = value; }
        }

ISymbol could have a method like "RenderSymbo( Graphics g , rotation, offsett ecc ecc ecc) and even the other information provided to VectorRender. Draw Point...  

Nicee no???

I'm going to doing this...   then if someone need it ...   we can try to submit as feature change...
Coordinator
Sep 17, 2010 at 3:03 PM

Albert,

you can safely change Bitmap to Image in the given source. That way, you have the posibility of passing metafile symbols.

Perhaps that already serves your needs.

Hth FObermaier

Sep 17, 2010 at 3:21 PM
Edited Sep 17, 2010 at 3:26 PM

mhmmm...

 

i mean something like this:
namespace SharpMap.Rendering
{
    /// <summary>
    /// Interface for Symbol Renderer
    /// </summary>
    public interface ISymbolRenderer
    {
        /// <summary>
        /// Render the Symbol into the Map provided using the position P the Scale, Offset and Rotation
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="point">Point to render</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        void RenderSymbol(Graphics g, SharpMap.Geometries.Point point, float symbolscale, PointF offset,
                                     float rotation, Map map);
    }
}


 

 

then... this is the "new" property inside VectorStyle instead of Symbol....

 

 

        /// <summary>
        /// Symbol Renderer
        /// </summary>
        public ISymbolRenderer SymbolRenderer
        {
            get { return _SymbolRenderer; }
            set { _SymbolRenderer = value; }
        }

 

 

Then...  i builded a default renderer for the Bitmap....

 

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SharpMap.Rendering
{
    /// <summary>
    /// Bitmap Symbol Renderer is an helper bitmap symbol renderer class.
    /// </summary>
    public class BitMapSymbolRenderer : ISymbolRenderer
    {
        #region Members
        
        protected Bitmap _Symbol;

        #endregion

        #region Constructors

        /// <summary>
        /// BitMapSymbolRenderer Constructor
        /// </summary>
        public BitMapSymbolRenderer()
        { }

        /// <summary>
        /// BitMapSymbolRenderer Constructor
        /// </summary>
        /// <param name="symbol"></param>
        public BitMapSymbolRenderer(Bitmap symbol)
        {
            _Symbol = symbol;
        }
 
        #endregion
        
        #region Properties
        
        /// <summary>
        /// Bitmap Symbol to be rendered
        /// </summary>
        public Bitmap Symbol
        {
            get { return _Symbol; }
            set { _Symbol = value; }
        } 

        #endregion

        #region ISymbolRenderer Members

        /// <summary>
        /// Render the Bitmap
        /// </summary>
        /// <param name="g"></param>
        /// <param name="point"></param>
        /// <param name="symbolscale"></param>
        /// <param name="offset"></param>
        /// <param name="rotation"></param>
        /// <param name="map"></param>
        public void RenderSymbol(System.Drawing.Graphics g, SharpMap.Geometries.Point point,
            float symbolscale, System.Drawing.PointF offset, float rotation, Map map)
        {

            PointF pp = Transform.WorldtoMap(point, map);

            Matrix startingTransform = g.Transform;

            if (rotation != 0 && !Single.IsNaN(rotation))
            {
                PointF rotationCenter = PointF.Add(pp, new SizeF(_Symbol.Width / 2, _Symbol.Height / 2));
                Matrix transform = new Matrix();
                transform.RotateAt(rotation, rotationCenter);

                g.Transform = transform;

                if (symbolscale == 1f)
                    g.DrawImageUnscaled(_Symbol, (int)(pp.X - _Symbol.Width / 2 + offset.X),
                                        (int)(pp.Y - _Symbol.Height / 2 + offset.Y));
                else
                {
                    float width = _Symbol.Width * symbolscale;
                    float height = _Symbol.Height * symbolscale;
                    g.DrawImage(_Symbol, (int)pp.X - width / 2 + offset.X * symbolscale,
                                (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
                }

                g.Transform = startingTransform;
            }
            else
            {
                if (symbolscale == 1f)
                    g.DrawImageUnscaled(_Symbol, (int)(pp.X - _Symbol.Width / 2 + offset.X),
                                        (int)(pp.Y - _Symbol.Height / 2 + offset.Y));
                else
                {
                    float width = _Symbol.Width * symbolscale;
                    float height = _Symbol.Height * symbolscale;
                    g.DrawImage(_Symbol, (int)pp.X - width / 2 + offset.X * symbolscale,
                                (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
                }
            }
        }


        #endregion
    }
}


and the "default class" that read the default embedded bitmap

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Reflection;

namespace SharpMap.Rendering
{
    /// <summary>
    /// Default Symbol Renderer
    /// </summary>
    public class DefaultSymbolRenderer : BitMapSymbolRenderer, ISymbolRenderer
    {
        #region Fields
        
        private static readonly Bitmap defaultsymbol =
            (Bitmap)
                Image.FromStream(
                    Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Styles.DefaultSymbol.png"));


        #endregion

        #region Constructor
        
        /// <summary>
        /// DefaultSymbolRenderer Constructor
        /// </summary>
        public DefaultSymbolRenderer()
            : base(defaultsymbol)
        {

        } 

        #endregion
    }
}


 

Then the Vector Renderer was modified in this way:

 

 

        /// <summary>
        /// Renders a point to the map.
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="point">Point to render</param>
        /// <param name="symbol">Symbol to place over point</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public static void DrawPoint(Graphics g, Point point, ISymbolRenderer symbolRenderer, float symbolscale, PointF offset,
                                     float rotation, Map map)
        {
            if (point == null)
                return;
            
            if (symbolRenderer == null) //We have no point style - Use a default symbol
                symbolRenderer = new DefaultSymbolRenderer();

            //OK Render the Symbol using the renderer
            symbolRenderer.RenderSymbol(g, point, symbolscale, offset, rotation, map);
        }

        /// <summary>
        /// Renders a <see cref="SharpMap.Geometries.MultiPoint"/> to the map.
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="points">MultiPoint to render</param>
        /// <param name="symbol">Symbol to place over point</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public static void DrawMultiPoint(Graphics g, MultiPoint points, ISymbolRenderer symbolRenderer, float symbolscale, PointF offset,
                                          float rotation, Map map)
        {
            for (int i = 0; i < points.Points.Count; i++)
                DrawPoint(g, points.Points[i], symbolRenderer, symbolscale, offset, rotation, map);
        }

 

and of course even the code that call the Vector Renderer...  now provide the "ISymbolRenderer" instead of Bitmap...   ant that's all

 

Now you can implement your own ISymbolRenderer and you can directly play with Graphics object!   in this way you can make calls like "DrawRectangle" ... etc etc etc...  or   you can always draw a bitmap with the Bitmap Renderer  for free.... 

 

what do you think???

Sep 17, 2010 at 3:29 PM
Edited Sep 17, 2010 at 3:44 PM

Then... with this trick....

 

        #region Overloaded implicit conversion Operator

        public static implicit operator
            BitMapSymbolRenderer(Bitmap bitmapSymbol)
        {
            return new BitMapSymbolRenderer { Symbol = bitmapSymbol };
        }

        public static implicit operator
            Bitmap(BitMapSymbolRenderer bitmapRenderer)
        {
            if (bitmapRenderer == null)
                return null;
            else return bitmapRenderer.Symbol;
        } 

        #endregion

 

And some other modify in the very end no change in the API usage... @ all...   now i'm trying.. to implement this ZERO API Modify ...    if it runs...  should be nice to integrate into SVN repository?? 

 

 

Sep 17, 2010 at 4:05 PM

Definitely IT WORKS,

 

this is the job: a base class for the SymbolRenderer,  this class implements  implicits converter from and to Bitmap object!   how?  because i've implemented aderived class called  BitmapSymbolRenderer

using System;
using System.Collections.Generic;
using System.Text;
using SharpMap.Geometries;
using System.Drawing;


namespace SharpMap.Rendering
{
    /// <summary>
    /// Interface for Symbol Renderer
    /// </summary>
    public abstract class SymbolRenderer
    {
        /// <summary>
        /// Render the Symbol into the Map provided using the position P the Scale, Offset and Rotation
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="point">Point to render</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public abstract void RenderSymbol(Graphics g, SharpMap.Geometries.Point point, float symbolscale, PointF offset,
                                     float rotation, Map map);

        #region Overloaded implicit conversion Operator

        /// <summary>
        /// Implicit Cast from Bitmap
        /// </summary>
        /// <param name="bitmapSymbol"></param>
        /// <returns></returns>
        public static implicit operator
            SymbolRenderer(Bitmap bitmapSymbol)
        {
            return new BitmapSymbolRenderer { Symbol = bitmapSymbol };
        }

        /// <summary>
        /// Implicit Cast To Bitmap
        /// </summary>
        /// <param name="bitmapRenderer"></param>
        /// <returns></returns>
        public static implicit operator
            Bitmap(SymbolRenderer bitmapRenderer)
        {
            if (bitmapRenderer == null)
                return null;
            else
            {
                if (bitmapRenderer is BitmapSymbolRenderer)
                    return (bitmapRenderer as BitmapSymbolRenderer).Symbol;
            }

            return null;
        }

        #endregion
    }
}



This is the BitmapRender that take the code from the VectorRender class DrawPoint... 


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SharpMap.Rendering
{
    /// <summary>
    /// Bitmap Symbol Renderer is an helper bitmap symbol renderer class.
    /// </summary>
    public class BitmapSymbolRenderer : SymbolRenderer
    {
        #region Members
        
        protected Bitmap _Symbol;

        #endregion

        #region Constructors

        /// <summary>
        /// BitMapSymbolRenderer Constructor
        /// </summary>
        public BitmapSymbolRenderer()
        { }

        /// <summary>
        /// BitMapSymbolRenderer Constructor
        /// </summary>
        /// <param name="symbol"></param>
        public BitmapSymbolRenderer(Bitmap symbol)
        {
            _Symbol = symbol;
        }
 
        #endregion
        
        #region Properties
        
        /// <summary>
        /// Bitmap Symbol to be rendered
        /// </summary>
        public Bitmap Symbol
        {
            get { return _Symbol; }
            set { _Symbol = value; }
        } 

        #endregion

        #region ISymbolRenderer Members

        /// <summary>
        /// Render the Bitmap
        /// </summary>
        /// <param name="g"></param>
        /// <param name="point"></param>
        /// <param name="symbolscale"></param>
        /// <param name="offset"></param>
        /// <param name="rotation"></param>
        /// <param name="map"></param>
        public override void RenderSymbol(System.Drawing.Graphics g, SharpMap.Geometries.Point point,
            float symbolscale, System.Drawing.PointF offset, float rotation, Map map)
        {

            PointF pp = SharpMap.Utilities.Transform.WorldtoMap(point, map);

            Matrix startingTransform = g.Transform;

            if (rotation != 0 && !Single.IsNaN(rotation))
            {
                PointF rotationCenter = PointF.Add(pp, new SizeF(_Symbol.Width / 2, _Symbol.Height / 2));
                Matrix transform = new Matrix();
                transform.RotateAt(rotation, rotationCenter);

                g.Transform = transform;

                if (symbolscale == 1f)
                    g.DrawImageUnscaled(_Symbol, (int)(pp.X - _Symbol.Width / 2 + offset.X),
                                        (int)(pp.Y - _Symbol.Height / 2 + offset.Y));
                else
                {
                    float width = _Symbol.Width * symbolscale;
                    float height = _Symbol.Height * symbolscale;
                    g.DrawImage(_Symbol, (int)pp.X - width / 2 + offset.X * symbolscale,
                                (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
                }

                g.Transform = startingTransform;
            }
            else
            {
                if (symbolscale == 1f)
                    g.DrawImageUnscaled(_Symbol, (int)(pp.X - _Symbol.Width / 2 + offset.X),
                                        (int)(pp.Y - _Symbol.Height / 2 + offset.Y));
                else
                {
                    float width = _Symbol.Width * symbolscale;
                    float height = _Symbol.Height * symbolscale;
                    g.DrawImage(_Symbol, (int)pp.X - width / 2 + offset.X * symbolscale,
                                (int)pp.Y - height / 2 + offset.Y * symbolscale, width, height);
                }
            }
        }

        #endregion

        #region Overloaded implicit conversion Operator

        /// <summary>
        /// Implicit Cast from Bitmap
        /// </summary>
        /// <param name="bitmapSymbol"></param>
        /// <returns></returns>
        public static implicit operator
            BitmapSymbolRenderer(Bitmap bitmapSymbol)
        {
            return new BitmapSymbolRenderer { Symbol = bitmapSymbol };
        }

        /// <summary>
        /// Implicit Cast To Bitmap
        /// </summary>
        /// <param name="bitmapRenderer"></param>
        /// <returns></returns>
        public static implicit operator
            Bitmap(BitmapSymbolRenderer bitmapRenderer)
        {
            if (bitmapRenderer == null)
                return null;
            else return bitmapRenderer.Symbol;
        }

        #endregion
    }
}



then i've modified the VectorStyle Class...  now the Symbols has no more Bitmap type but....  SymbolRender..   but you can still assign Bitmap!!!  because the implicit operator!!!!  NICE!!


 

using System.Drawing;
using SharpMap.Rendering;

namespace SharpMap.Styles
{
    /// <summary>
    /// Defines a style used for rendering vector data
    /// </summary>
    public class VectorStyle : Style
    {
        #region Privates

        private Brush _FillStyle;
        private Pen _LineStyle;
        private bool _Outline;
        private Pen _OutlineStyle;
       
        #endregion

        /// <summary>
        /// Initializes a new VectorStyle and sets the default values
        /// </summary>
        /// <remarks>
        /// Default style values when initialized:<br/>
        /// *LineStyle: 1px solid black<br/>
        /// *FillStyle: Solid black<br/>
        /// *Outline: No Outline
        /// *Symbol: null-reference
        /// </remarks>
        public VectorStyle()
        {
            Outline = new Pen(Color.Black, 1);
            Line = new Pen(Color.Black, 1);
            Fill = Brushes.Black;
            EnableOutline = false;

            _Symbol = new DefaultSymbolRenderer();
            SymbolScale = 1f;
        }

        #region Properties

        private SymbolRenderer _Symbol;
        private PointF _SymbolOffset;
        private float _SymbolRotation;
        private float _SymbolScale;

        /// <summary>
        /// Linestyle for line geometries
        /// </summary>
        public Pen Line
        {
            get { return _LineStyle; }
            set { _LineStyle = value; }
        }

        /// <summary>
        /// Outline style for line and polygon geometries
        /// </summary>
        public Pen Outline
        {
            get { return _OutlineStyle; }
            set { _OutlineStyle = value; }
        }

        /// <summary>
        /// Specified whether the objects are rendered with or without outlining
        /// </summary>
        public bool EnableOutline
        {
            get { return _Outline; }
            set { _Outline = value; }
        }

        /// <summary>
        /// Fillstyle for Polygon geometries
        /// </summary>
        public Brush Fill
        {
            get { return _FillStyle; }
            set { _FillStyle = value; }
        }
            
        /// <summary>
        /// Symbol used for rendering points
        /// </summary>
        public SymbolRenderer Symbol
        {
            get { return _Symbol; }
            set { _Symbol = value; }
        }

        /// <summary>
        /// Scale of the symbol (defaults to 1)
        /// </summary>
        /// <remarks>
        /// Setting the symbolscale to '2.0' doubles the size of the symbol, where a scale of 0.5 makes the scale half the size of the original image
        /// </remarks>
        public float SymbolScale
        {
            get { return _SymbolScale; }
            set { _SymbolScale = value; }
        }

        /// <summary>
        /// Gets or sets the offset in pixels of the symbol.
        /// </summary>
        /// <remarks>
        /// The symbol offset is scaled with the <see cref="SymbolScale"/> property and refers to the offset af <see cref="SymbolScale"/>=1.0.
        /// </remarks>
        public PointF SymbolOffset
        {
            get { return _SymbolOffset; }
            set { _SymbolOffset = value; }
        }

        /// <summary>
        /// Gets or sets the rotation of the symbol in degrees (clockwise is positive)
        /// </summary>
        public float SymbolRotation
        {
            get { return _SymbolRotation; }
            set { _SymbolRotation = value; }
        }      

        #endregion
    }
}

 

of course the default bitmap...   is it still here!

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Reflection;

namespace SharpMap.Rendering
{
    /// <summary>
    /// Default Symbol Renderer
    /// </summary>
    public class DefaultSymbolRenderer : BitmapSymbolRenderer
    {
        #region Fields
        
        private static readonly Bitmap defaultsymbol =
            (Bitmap)
                Image.FromStream(
                    Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Styles.DefaultSymbol.png"));


        #endregion

        #region Constructor
        
        /// <summary>
        /// DefaultSymbolRenderer Constructor
        /// </summary>
        public DefaultSymbolRenderer()
            : base(defaultsymbol)
        {

        } 

        #endregion
    }
}

 

then the VectorRender

 

   /// <summary>
        /// Renders a point to the map.
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="point">Point to render</param>
        /// <param name="symbolRenderer">Symbol to place over point</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public static void DrawPoint(Graphics g, Point point, SymbolRenderer symbolRenderer, float symbolscale, PointF offset,
                                     float rotation, Map map)
        {
            if (point == null)
                return;
            
            if (symbolRenderer == null) //We have no point style - Use a default symbol
                symbolRenderer = new DefaultSymbolRenderer();

            //OK Render the Symbol using the renderer
            symbolRenderer.RenderSymbol(g, point, symbolscale, offset, rotation, map);
        }

        /// <summary>
        /// Renders a <see cref="SharpMap.Geometries.MultiPoint"/> to the map.
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="points">MultiPoint to render</param>
        /// <param name="symbolRenderer">Symbol to place over point</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public static void DrawMultiPoint(Graphics g, MultiPoint points, SymbolRenderer symbolRenderer, float symbolscale, PointF offset,
                                          float rotation, Map map)
        {
            for (int i = 0; i < points.Points.Count; i++)
                DrawPoint(g, points.Points[i], symbolRenderer, symbolscale, offset, rotation, map);
        }

 

ant that's all folks!!!   now i can render bitmap  or i can manipulate directly Graphics object from my custom  Symbol Renderer

Sep 17, 2010 at 4:37 PM

and... with very few modify you can still use the "delegate" approach...

like:


using System;
using System.Collections.Generic;
using System.Text;
using SharpMap.Geometries;
using System.Drawing;


namespace SharpMap.Rendering
{
    /// <summary>
    /// Interface for Symbol Renderer
    /// </summary>
    public abstract class SymbolRenderer : ISymbolRenderer
    {
        #region Members

        private RenderSymbolMethod _renderSymbolDelegate;

        private static DefaultSymbolRenderer _defaultSymbolRenderer;

        #endregion

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        public SymbolRenderer()
        {

        }

        /// <summary>
        /// Constructor 
        /// </summary>
        /// <param name="renderSymbolDelegate"></param>
        public SymbolRenderer(RenderSymbolMethod renderSymbolDelegate)
        {
            _renderSymbolDelegate = renderSymbolDelegate;
        } 

        #endregion

        #region Delegate 
        
        /// <summary>
        /// Render the Symbol into the Map provided using the position P the Scale, Offset and Rotation
        /// </summary>
        /// <param name="g">Graphics reference</param>
        /// <param name="point">Point to render</param>
        /// <param name="symbolscale">The amount that the symbol should be scaled. A scale of '1' equals to no scaling</param>
        /// <param name="offset">Symbol offset af scale=1</param>
        /// <param name="rotation">Symbol rotation in degrees</param>
        /// <param name="map">Map reference</param>
        public delegate void RenderSymbolMethod(Graphics g, SharpMap.Geometries.Point point, float symbolscale, PointF offset,
                                     float rotation, Map map); 

        #endregion

        #region Properties
        
        public RenderSymbolMethod RenderSymbolDelegate
        {
            get { return _renderSymbolDelegate; }
            set { _renderSymbolDelegate = value; }
        } 

        #endregion


        #region Overloaded implicit conversion Operator

        /// <summary>
        /// Implicit Cast from Bitmap
        /// </summary>
        /// <param name="bitmapSymbol"></param>
        /// <returns></returns>
        public static implicit operator
            SymbolRenderer(Bitmap bitmapSymbol)
        {
            return new BitmapSymbolRenderer { Symbol = bitmapSymbol };
        }

        /// <summary>
        /// Implicit Cast To Bitmap
        /// </summary>
        /// <param name="bitmapRenderer"></param>
        /// <returns></returns>
        public static implicit operator
            Bitmap(SymbolRenderer bitmapRenderer)
        {
            if (bitmapRenderer == null)
                return null;
            else
            {
                if (bitmapRenderer is BitmapSymbolRenderer)
                    return (bitmapRenderer as BitmapSymbolRenderer).Symbol;
            }

            return null;
        }

        #endregion

        #region ISymbolRenderer Members

        public void RenderSymbol(Graphics g, SharpMap.Geometries.Point point, float symbolscale, PointF offset, float rotation, Map map)
        {
            if (_renderSymbolDelegate != null)
            {
                _renderSymbolDelegate(g, point, symbolscale, offset, rotation, map);
            }
            else
            {
                if (_defaultSymbolRenderer == null)
                { 
                    _defaultSymbolRenderer = new DefaultSymbolRenderer();
                }

                _defaultSymbolRenderer.RenderSymbol(g, point, symbolscale, offset, rotation, map);
            }
        }

        #endregion
    }
}

 

 

 

 

and in the application code... that want so render a circle.. for the symbol...

  vectorStyle.Symbol.RenderSymbolDelegate = this.RenderSymbol; 

       public void RenderSymbol(Graphics g, SharpMap.Geometries.Point point, float symbolscale, PointF offset, float rotation, SharpMap.Map map)
        {
            PointF pp = SharpMap.Utilities.Transform.WorldtoMap(point, map);

            g.DrawEllipse(new Pen(Color.Red), pp.X, pp.Y, 3, 3);
        }