This project is read-only.

Draw Circle on a Map.Drawing layer

Nov 7, 2013 at 10:53 AM
Hi,
I need for my project to mark with circles specific areas on a Map and I am wondering if there is there is a way to draw a circle on a drawing layer and add it on the map the same way as points, lines polygons etc.

I know that I can draw it using Graphics handle of the DotSpatial.Controls.Map control but I want to avoid that.

I would apreciate any help. Thanks in advance.

Dimitrios
Nov 7, 2013 at 1:01 PM
Edited Nov 7, 2013 at 1:24 PM
there was this old post on that

https://dotspatial.codeplex.com/discussions/249408

I didn't try to do what you ask but maybe it is a good starting point

otherwise you may also take advantage of the tutorial no. 4 of dotspatial, where they basically show you how to draw points, lines and polygons. I would implement something similar to the line drawing where you basically tell the code the center and the radius of the circle and draw a polyline made of a large number of small segments that resemble a circle.

Oscar
Nov 7, 2013 at 8:20 PM
Oscar,
     thanks for your reply. I had already reviewed the old post and it's not what I want. In the old post you create a circle but it behaves like a symbol on map and not as a shape like a line or a polygon. I mean when you zoom in/out the circle size remains the same you can overcome that of course by re-sizing it every time you change zoom but is a CPU expensive practice. On the other hand for lines, polygons etc you add them in a drawing layer and you get it for free.
Dimitrios
Nov 8, 2013 at 9:17 PM
I actually found out that the best way to do it is to calculate the circle circumference coordinates (for a given circle center and radius) and then feed them to MapPolygonLayer.

The circle points can be calculated by a step of a circle segment angle. The smaller the angle the smoother the circle. I think for most cases 60 segments will do.
I used the following two functions:
 protected void RecalculatePoints() {
            List<Coordinate> circlePoints = new List<Coordinate>();
            double arcSegment = 360.0/m_segments;

            for (int i = 0; i < m_segments; i++) {
                PointD c = CirclePoint(arcSegment*i);
                circlePoints.Add(new Coordinate(c.X, c.Y));
            }

            LinearRing lr = new LinearRing(circlePoints);
            Polygon obj = new Polygon(lr);
            IFeature f = ShapeFeatureSet.AddFeature(obj);
            ...
            ...
            ...

        }

        private PointD CirclePoint(double segAngle) {  
             // a little tip the m_radius should be in Radians
            double x = m_radius * Math.Cos(segAngle* Math.PI / 180.0) + Center.X;
            double y = m_radius * Math.Sin(segAngle* Math.PI / 180.0) + Center.Y;

            return new PointD(x, y);
        }
Jul 2, 2015 at 4:09 PM
Hi dfiliago,
i found your code and it seems me more interesting.

Where I must insert it?
Which function must call your function RecalculatePoints?

Thanks.
Sep 26, 2016 at 1:19 PM
Hi,

Can anybody tel me how to draw a smooth curve without using graphics on a map in Dotspatial, so that I can add this curve to the existing line string.

Thank you..!
Sep 26, 2016 at 7:32 PM
Edited Sep 26, 2016 at 7:35 PM
Hi,
I worked on a project back in 2013 and there was no way to insert a circle on a map using a dotSpatial embedded function back then. The way I did it was to calculate the circumference points of a circle given a center, a radius and a number of segments. The number of segments defines the number of points to be calculated that will be inserted in a Polygon to create the circle. The larger the number of segments the more smoother the circle. For my project a segment number of 60 point was more than enough.

I hereby give two classes the ShapePolygon and the deriving ShapeCircle, to give you an idea:
 public class ShapePolygon :Shape,IShape{
        protected double m_lineWidth = 1.0;

        public double LineStroke {
            get {
                return m_lineWidth;
            }
            set {
                m_lineWidth = value;
                (ShapeSymbolizer as PolygonSymbolizer).SetOutline(m_outlineColor, m_lineWidth);
            }
        }

        public ShapePolygon(Map map,IList<Coordinate> vertices, Color? fillColor = null, Color? outlineColor =null, string name = "new polygon", double lineStroke = 1.0)
            : base(map, name) {
                m_shapeType = TYPE.POLYGON;
                Vertices = vertices;
                OutlineColor = outlineColor.HasValue ? outlineColor.Value : m_outlineColor;

                if (fillColor.HasValue) {
                    FillColor = fillColor.Value;
                }

                
                Add(ShapeMapLayer);

                DataColumn distCol = new DataColumn("Name");
                distCol.DataType = typeof(string);
                ShapeFeatureSet.DataTable.Columns.Add(distCol);
                ReDraw();
                m_shapeLabelLayer = createLabelLayer(ShapeFeatureSet, "Name");
                Add(m_shapeLabelLayer);
                if (vertices != null) {
                    m_map.MapFrame.DrawingLayers.AddRange(this);
                }
        }


        public IFeatureSymbolizer ShapeSymbolizer {
                get {
                    if (m_shapeSymbolizer == null) {
                        m_shapeSymbolizer = new PolygonSymbolizer( FillColor, OutlineColor);
                    }
                    return m_shapeSymbolizer;
                }
                set {
                    m_shapeSymbolizer = value;
                    //Rfreshh tbd
            }
        }


        public IMapLayer ShapeMapLayer {
                get {
                    if (m_shapeLayer == null) {
                        m_shapeLayer = new MapPolygonLayer(ShapeFeatureSet);
                        m_shapeLayer.Projection = ShapeFeatureSet.Projection;
                        m_shapeLayer.LegendText = "Point";
                        (m_shapeLayer as MapPolygonLayer).Symbolizer = ShapeSymbolizer as IPolygonSymbolizer;
                    }
                    return m_shapeLayer;
                }

                set {
                    m_shapeLayer = value;
            }
        }


        public virtual FeatureSet ShapeFeatureSet {
                get {
                    if (m_shapeFeatureSet == null) {
                        m_shapeFeatureSet = new FeatureSet(FeatureType.Polygon);
                        m_shapeFeatureSet.Projection = m_map.Projection;
                    }
                    return m_shapeFeatureSet;
                }

                set {
                    m_shapeFeatureSet = value;
                }
        }

        public  IMapLayer GetMapLayer() { return ShapeMapLayer; }

        

        public Shape.TYPE Type {
            get {
                return ShapeType;
            }
            set { }
        }

        public override Color OutlineColor {
            get {
                return m_outlineColor;
            }
            set {
                m_outlineColor = value;
                (ShapeSymbolizer as PolygonSymbolizer).SetOutline(m_outlineColor, m_lineWidth);
            }
        }

        public override Color FillColor {
            get {
                return m_fillColor;
            }
            set {
                m_fillColor = value;
                if(m_fillColor!=Color.Transparent){
                    m_fillColor = m_fillColor.ToTransparent(0.3f);
                }

                (ShapeSymbolizer as PolygonSymbolizer).SetFillColor(m_fillColor);
            }
        }


        public virtual void ReDraw() {
            ShapeFeatureSet.Features.Clear();
            List<Coordinate> temp = new List<Coordinate>();

            //if projection is webmercator re-project vertices appropriately since they come always in WGS1984
            if (m_map.Projection.Equals(KnownCoordinateSystems.Projected.World.WebMercator)) {
                foreach (Coordinate c in Vertices) {
                    temp.Add(MapManipulator.ConvertToWebMercator(c));
                }
            }
            else {
                temp = Vertices as List<Coordinate>;
            }
           

            LinearRing lr = new LinearRing(temp);
            Polygon obj = new Polygon(lr);
            IFeature f = ShapeFeatureSet.AddFeature(obj);
            DataRow dr = f.DataRow;
            dr.BeginEdit();
            dr["Name"] = Name;
            dr.EndEdit();

            ShapeFeatureSet.LockDispose();
            ShapeFeatureSet.InvalidateVertices();
            ShapeFeatureSet.UnlockDispose();
        }
    }
public class ShapeCircle :ShapePolygon,IShape{
        protected double m_radius = 10.0;

        public double Radius {
            get { 
                return Unit.RadToDeg(m_radius); 
            }
            set {
                m_radius = Unit.DegToRad(value);             
            }
        }

        protected double m_radiusToMapProj;
        protected int m_segments = 60;

        public int Segments {
            get {
                return m_segments;
            }
            set {
                m_segments = value;
            }
        }

        public Coordinate Center {get;set;}


        public ShapeCircle(Map map, Coordinate center, double radius, Color? fillColor = null, Color? outlineColor = null, string name = "new circle", double lineStroke = 0.0)
            : base(map,null,fillColor,outlineColor, name) {
                m_shapeType = TYPE.CIRCLE;
                Center = center;
                Radius = radius;
                ReDraw();
                m_map.MapFrame.DrawingLayers.AddRange(this);
        }


        public override void ReDraw() {
            if (Center != null) {
                ShapeFeatureSet.Features.Clear();
                List<Coordinate> circlePoints = new List<Coordinate>();
                double arcSegment = 360.0 / m_segments;

                Coordinate center = new Coordinate(Center);
                Coordinate radius = new Coordinate(m_radius, 0);
                //if projection is webmercator re-project vertices appropriately since they come always in WGS1984
                if (Projection.Equals(KnownCoordinateSystems.Projected.World.WebMercator)) {
                    center = MapManipulator.ConvertToWebMercator(Center);
                    radius = MapManipulator.ConvertToWebMercator(radius);
                }

//I create the circle segment points
                for (int i = 0; i < m_segments; i++) {
                    PointD c = PointOnCircle(arcSegment * i, center, radius.X);
                    circlePoints.Add(new Coordinate(c.X, c.Y));
                }

//I put the circle points into a Polygon

                LinearRing lr = new LinearRing(circlePoints);
                Polygon obj = new Polygon(lr);

                IFeature f = ShapeFeatureSet.AddFeature(obj);
                DataRow dr = f.DataRow;
                dr.BeginEdit();
                dr["Name"] = Name;
                dr.EndEdit();

                ShapeFeatureSet.LockDispose();
                ShapeFeatureSet.InvalidateVertices();
                ShapeFeatureSet.UnlockDispose();
            }

        }

//Each point of the circle is calculated via this function I am passing the center, radius, 
//and the arc in degrees of the point for instance for 60 segments the arc in degrees 
//should be 360/60 = 6 degrees so the values I am passing in this function will be 6,12,18, ....,354
//the function will return the x,y value of the circle point each time._ 
        private PointD PointOnCircle(double angleInDegrees, Coordinate center, double radius) {
            // Convert from degrees to radians via multiplication by PI/180                          
            double x = radius * Math.Cos(angleInDegrees * Math.PI / 180.0) + center.X;
            double y = radius * Math.Sin(angleInDegrees * Math.PI / 180.0) + center.Y;

            return new PointD(x, y);
        }
    }
When I want to draw a circle I do something like:
 Shape.ShapeCircle circle = new ShapeCircle(m_map, center, radius, null, lineColor, circleNameStr);
 m_shapes.Add(circle);
I hope that these will be helpful!