我在c#中使用GMAP.NET。我能够在表单上显示地图,现在我试图通过单击一个certian点来绘制CIRCLE鼠标,保持鼠标左键并将鼠标拖动到特定位置。一旦绘制了圆形,我想从中心点获得半径,我确信GMAP能够做到这一点。我正在使用Opentstreet地图。
我无法在功能上实现这一点,任何玩过GMAP控件的人都会与一些可行的代码分享您的经验。
由于
答案 0 :(得分:9)
我所知道的唯一可以实现这种结果的方法是使用PointLatLng点创建一个列表并将它们绘制为多边形。这是一个例子:
private void CreateCircle(PointF point, double radius, int segments)
{
List<PointLatLng> gpollist = new List<PointLatLng>();
double seg = Math.PI * 2 / segments;
int y = 0;
for (int i = 0; i < segments; i++)
{
double theta = seg * i;
double a = point.X + Math.Cos(theta) * radius;
double b = point.Y + Math.Sin(theta) * radius;
PointLatLng gpoi = new PointLatLng(a,b);
gpollist.Add(gpoi);
}
GMapPolygon gpol = new GMapPolygon(gpollist, "pol");
overlayOne.Polygons.Add(gpol);
}
答案 1 :(得分:5)
如果要使用与绘图类关联的典型GDI功能,可以直接继承GMapMarker类。这允许您绘制简单的形状,如圆形,并创建自定义属性(例如,将以形状的英里数计算半径):
public class GMapPoint : GMap.NET.WindowsForms.GMapMarker
{
private PointLatLng point_;
private float size_;
public PointLatLng Point
{
get
{
return point_;
}
set
{
point_ = value;
}
}
public GMapPoint(PointLatLng p, int size)
: base(p)
{
point_ = p;
size_ = size;
}
public override void OnRender(Graphics g)
{
g.FillRectangle(Brushes.Black, LocalPosition.X, LocalPosition.Y, size_, size_);
//OR
g.DrawEllipse(Pens.Black, LocalPosition.X, LocalPosition.Y, size_, size_);
//OR whatever you need
}
}
在地图上绘制点:
GMapOverlay points_ = new GMapOverlay("pointCollection");
points_.Markers.Add(new GMapPoint(new PointLatLng(35.06, -106.36), 10));
gMapControl1.Overlays.Add(points_);
(因为我对它有一些疑问)因为我们从标记类中固有,所以我们仍然可以利用tooltiptext功能:
GMapPoint pnt = new GMapPoint(new PointLatLng(35.06, -106.36), 10);
pnt.Size = new Size(10,10);
pnt.ToolTipText = "Text Here";
pnt.ToolTipMode = MarkerTooltipMode.Always;
points_.AddMarker(pnt);
答案 2 :(得分:1)
我遇到了同样的问题,在进入时我有Lon,Lat和radius,这是我的解决方案。它就像一个魅力:)
private void CreateCircle(Double lat, Double lon, double radius)
{
PointLatLng point = new PointLatLng(lat, lon);
int segments = 1000;
List<PointLatLng> gpollist = new List<PointLatLng>();
for (int i = 0; i < segments; i++)
gpollist.Add(FindPointAtDistanceFrom(point, i, radius / 1000));
GMapPolygon gpol = new GMapPolygon(gpollist, "pol");
markers.Polygons.Add(gpol);
}
public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Lat);
var startLonRad = DegreesToRadians(startPoint.Lng);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad + Math.Atan2(
Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,
distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
public static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180 / Math.PI;
return radians * radToDegFactor;
}
呼叫
CreateCircle(51.640980, -2.673544, 1143.899431);
答案 3 :(得分:1)
private void CreateCircle(Double lat, Double lon, double radius, int ColorIndex)
{
PointLatLng point = new PointLatLng(lat, lon);
int segments = 1080;
List<PointLatLng> gpollist = new List<PointLatLng>();
for (int i = 0; i < segments; i++)
{
gpollist.Add(FindPointAtDistanceFrom(point, i*(Math.PI/180), radius / 1000));
}
GMapPolygon polygon = new GMapPolygon(gpollist, "Circle");
switch (ColorIndex) {
case 1:
polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Red));
break;
case 2:
polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Orange));
break;
case 3:
polygon.Fill = new SolidBrush(Color.FromArgb(20, Color.Aqua));
break;
default:
MessageBox.Show("No search zone found!");
break;
}
polygon.Stroke = new Pen(Color.Red, 1);
markers.Polygons.Add(polygon);
gMapCtl.Overlays.Add(markers);
}
public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Lat);
var startLonRad = DegreesToRadians(startPoint.Lng);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad + Math.Atan2(Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI/180;
return degrees * degToRadFactor;
}
public static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180/Math.PI;
return radians * radToDegFactor;
}
public static double DistanceTwoPoint(double startLat, double startLong, double endLat, double endLong) {
var startPoint = new GeoCoordinate(startLat, startLong);
var endPoint = new GeoCoordinate(endLat, endLong);
return startPoint.GetDistanceTo(endPoint);
}
答案 4 :(得分:0)
以下是如何在WPF地图上绘制带有黑色边框的红色圆圈:
public class YourMapControl : GMapControl
{
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
Point center(40.730610, -73.935242);
double radius = 0.1;
drawingContext.DrawEllipse(Brushes.Red, Pens.Black, center, radius, radius);
}
}
就问题本身的第二部分而言,您将使用以下内置MapControl函数:
public bool DisableAltForSelection; //if true, selects area just by holding mouse and moving
public bool SelectionUseCircle; //use circle for selection
public event SelectionChange OnSelectionChange; //occurs when mouse selection is changed
public RectLatLng SelectedArea { get; set; } //returns rect with coordinates of the selected area
答案 5 :(得分:0)
GMapOverlay markers = new GMapOverlay("markers");
private void CreateCircle(Double lat, Double lon, double radius, int segments)
{
markers.Polygons.Clear();
PointLatLng point = new PointLatLng(lat, lon);
List<PointLatLng> gpollist = new List<PointLatLng>();
for (int i = 0; i < segments; i++)
gpollist.Add(FindPointAtDistanceFrom(point, i, radius / 1000));
List<PointLatLng> gpollistR = new List<PointLatLng>();
List<PointLatLng> gpollistL = new List<PointLatLng>();
foreach (var gp in gpollist)
{
if (gp.Lng > lon)
{
gpollistR.Add(gp);
}
else
{
gpollistL.Add(gp);
}
}
gpollist.Clear();
List<PointLatLng> gpollistRT = new List<PointLatLng>();
List<PointLatLng> gpollistRB = new List<PointLatLng>();
foreach (var gp in gpollistR)
{
if (gp.Lat > lat)
{
gpollistRT.Add(gp);
}
else
{
gpollistRB.Add(gp);
}
}
gpollistRT.Sort(new LngComparer());
gpollistRB.Sort(new Lng2Comparer());
gpollistR.Clear();
List<PointLatLng> gpollistLT = new List<PointLatLng>();
List<PointLatLng> gpollistLB = new List<PointLatLng>();
foreach (var gp in gpollistL)
{
if (gp.Lat > lat)
{
gpollistLT.Add(gp);
}
else
{
gpollistLB.Add(gp);
}
}
//gpollistLT.Sort(new LngComparer());
gpollistLB.Sort(new Lng2Comparer());
gpollistLT.Sort(new LngComparer());
gpollistL.Clear();
gpollist.AddRange(gpollistRT);
gpollist.AddRange(gpollistRB);
gpollist.AddRange(gpollistLB);
gpollist.AddRange(gpollistLT);
GMapPolygon gpol = new GMapPolygon(gpollist, "pol");
gpol.Stroke = new Pen(Color.Red, 1);
markers.Polygons.Add(gpol);
}
public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Lat);
var startLonRad = DegreesToRadians(startPoint.Lng);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad + Math.Atan2(
Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,
distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
public static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180 / Math.PI;
return radians * radToDegFactor;
}
和这个班
class LngComparer : IComparer<PointLatLng>
{
#region IComparer Members
public int Compare(PointLatLng x, PointLatLng y)
{
if (x == null || y == null)
throw new ArgumentException("At least one argument is null");
if (x.Lng == y.Lng)
{
if (x.Lat > y.Lat)
{
return 1;
}
else if (x.Lat < y.Lat)
{
return -1;
}
else
{
return 0;
}
}
if (x.Lng < y.Lng) return -1;
return 1;
}
#endregion
}
class Lng2Comparer : IComparer<PointLatLng>
{
#region IComparer Members
public int Compare(PointLatLng x, PointLatLng y)
{
if (x == null || y == null)
throw new ArgumentException("At least one argument is null");
if (x.Lng == y.Lng)
{
if (x.Lat > y.Lat)
{
return 1;
}
else if (x.Lat > y.Lat)
{
return -1;
}
else
{
return 0;
}
}
if (x.Lng > y.Lng) return -1;
return 1;
}
#endregion
}
答案 6 :(得分:0)
我的代码绘制弧线,并且也继承自GMapMarker。圆弧以枢轴点C为中心点从A点扫到B点。如果A点和B点重合,则会画一个圆。
public class CustomArc : GMapMarker, ISerializable {
[NonSerialized]
public Pen pen;
private int radius = 20;
private int pen_width = 2;
private float start = 0.0f;
private float sweep = 0.0f;
private GPoint ptA;
private GPoint ptB;
private GPoint ptC;
private List<PointF> points;
private static Logger logger = LogManager.GetCurrentClassLogger();
public CustomArc(GPoint ptA, GPoint ptB, GPoint ptC, PointLatLng geo) : base(geo) {
this.ptA = ptA;
this.ptB = ptB;
this.ptC = ptC;
initialise();
}
private void initialise() {
this.pen = new Pen(Brushes.White, this.pen_width);
this.radius = (int)UIMaths.distance(ptC, ptA);
this.points = new List<PointF>();
if (ptA == ptB) {
this.sweep = 360.0f;
} else {
// Calculate the radius
this.sweep = (float)UIMaths.sweepAngleDeg(ptA, ptB, ptC);
}
this.start = (float)UIMaths.startAngle(ptC, ptB);
Size = new Size(2 * radius, 2 * radius);
Offset = new Point(-Size.Width / 2, -Size.Height / 2);
Console.Out.WriteLine("Radius {0}, Start {1:0.0}, Sweep {2:0.0}", radius, start, sweep);
}
public override void OnRender(Graphics g) {
try {
Rectangle rect = new Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height);
g.DrawArc(pen, rect, start, sweep);
} catch (ArgumentException ex) {
logger.Error(ex.Message);
}
}
public sealed override void Dispose() {
if (pen != null) {
pen.Dispose();
pen = null;
}
base.Dispose();
}
#region ISerializable Members
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
base.GetObjectData(info, context);
}
protected CustomArc(SerializationInfo info, StreamingContext context)
: base(info, context) {
}
#endregion
}
答案 7 :(得分:0)
我的方法是覆盖绘画事件然后定义一个矩形。定义矩形后,您可以绘制圆、弧或饼图。
private void MainMap_Paint(object sender, PaintEventArgs e)
{
drawPie(e.Graphics, 50, 22.321, 45.44498);
}
private void drawPie(Graphics g, int angle, double latitude, double longitude)
{
PointLatLng pn = new PointLatLng(latitude , longitude );
double dist = 295; // 200 km
// define rectangle points
PointLatLng p1 = FindPointAtDistanceFrom(pn, 315 * constants.DEGREES_TO_RADIAN, dist);
PointLatLng p2 = FindPointAtDistanceFrom(pn, 45 * constants.DEGREES_TO_RADIAN, dist);
PointLatLng p3 = FindPointAtDistanceFrom(pn, 135 * constants.DEGREES_TO_RADIAN, dist);
PointLatLng p4 = FindPointAtDistanceFrom(pn, 225 * constants.DEGREES_TO_RADIAN, dist);
GPoint dp1 = MainMap.FromLatLngToLocal(p1);
GPoint dp2 = MainMap.FromLatLngToLocal(p2);
GPoint dp3 = MainMap.FromLatLngToLocal(p3);
GPoint dp4 = MainMap.FromLatLngToLocal(p4);
RectangleF rec = new RectangleF(dp1.X, dp1.Y, dp2.X - dp1.X, dp3.Y - dp1.Y);
SolidBrush ptlbrush = new SolidBrush(Color.Cyan);
Pen ptlpen = new Pen(ptlbrush, 1);
float direction1 = (-90 + angle - 45) % 360;
float startAngle = direction1;
float sweepAngle = 90;
var brush = new SolidBrush(Color.FromArgb(50, 80, 0, 150));
g.DrawPie(ptlpen, rec, startAngle, sweepAngle);
if (angleFilledBox.Checked == true)
g.FillPie(brush, Rectangle.Round(rec), startAngle, sweepAngle);
}