
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



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 resizing 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



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);
}



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.



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 reproject 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 reproject 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!

