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