Reputation: 2028
I have been able to draw an ellipse on my map using latitude and longitude values around a given center point. Although I see a shape on the map, I get an ellipse instead of a circle and I don't think it matches the distance specified. I intend to use this to display objects within that circle (this will be done later on once I can get the circle displaying properly, which is the reason why i need a circle not an ellipse as it should be perfectly round).
I am using a Bing Maps API. I wish to draw the circle in a given miles (distance) from the center which has been passed in through the parameter, the other variable in the parameter called miles is just holding a double value of 1D. I think the problem is to do with the way my maths is being calculated. Has anyone got a clue on how I can refine this code to calculate my miles better.
private void drawPoly(SearchLocation center, Double miles)
{
//amount of vertex
double vertexCount = 100D;
//used by the api to carried out searches
List<SearchLocation> vertices = new List<SearchLocation>();
double v = 0;
double radians = Math.PI / 180D;
double radiansPerDegree = Math.PI / 180D;
double degreePerVertex = 360D / vertexCount;
double radiansPerVertex = degreePerVertex * radiansPerDegree;
var centerOfMap = center;
const double degLatMiles = 68.68637156368D;
double degLonMiles = Math.Cos(center.Latitude.Value) * (68.68637156368D);
double milesLat = (miles * degLatMiles) / 3600;
double milesLon = (miles * degLonMiles) / 3600;
for (v = 0; v < vertexCount; v++)
{
radians = v * radiansPerVertex;
//adds the miles from the center point and draws a circle
double centrLat = center.Latitude.Value + (milesLat * Math.Sin(radians));
double centrLon = center.Longitude.Value + (milesLon * Math.Cos(radians));
vertices.Add(new SearchLocation() { Latitude = centrLat, Longitude = centrLon });
}
Upvotes: 1
Views: 4131
Reputation: 355
To prevent elipses on sertain latitudes I use the following code:
// Function to draw circle on map:
private void DrawCircle(BasicGeoposition CenterPosition, int Radius)
{
Color FillColor = Colors.Purple;
Color StrokeColor = Colors.Red;
FillColor.A = 80;
StrokeColor.A = 80;
Circle = new MapPolygon
{
StrokeThickness = 2,
FillColor = FillColor,
StrokeColor = StrokeColor,
Path = new Geopath(Functions.CalculateCircle(CenterPosition, Radius))
};
mpBingMaps.MapElements.Add(Circle);
}
// Constants and helper functions:
const double earthRadius = 6371000D;
const double Circumference = 2D * Math.PI * earthRadius;
public static List<BasicGeoposition> CalculateCircle(BasicGeoposition Position, double Radius)
{
List<BasicGeoposition> GeoPositions = new List<BasicGeoposition>();
for (int i = 0; i <= 360; i++)
{
double Bearing = ToRad(i);
double CircumferenceLatitudeCorrected = 2D * Math.PI * Math.Cos(ToRad(Position.Latitude)) * earthRadius;
double lat1 = Circumference / 360D * Position.Latitude;
double lon1 = CircumferenceLatitudeCorrected / 360D * Position.Longitude;
double lat2 = lat1 + Math.Sin(Bearing) * Radius;
double lon2 = lon1 + Math.Cos(Bearing) * Radius;
BasicGeoposition NewBasicPosition = new BasicGeoposition();
NewBasicPosition.Latitude = lat2 / (Circumference / 360D);
NewBasicPosition.Longitude = lon2 / (CircumferenceLatitudeCorrected / 360D);
GeoPositions.Add(NewBasicPosition);
}
return GeoPositions;
}
private static double ToRad(double degrees)
{
return degrees * (Math.PI / 180D);
}
This code is usefull for small radius of less than a few miles.
Upvotes: 1
Reputation: 3006
Ok, I've misundestood your question. This should work :
/// <summary>
/// Calculates the end-point from a given source at a given range (meters) and bearing (degrees).
/// This methods uses simple geometry equations to calculate the end-point.
/// </summary>
/// <param name="source">Point of origin</param>
/// <param name="range">Range in meters</param>
/// <param name="bearing">Bearing in degrees</param>
/// <returns>End-point from the source given the desired range and bearing.</returns>
public static PointLatLng CalculateDerivedPosition(PointLatLng source, double range, double bearing)
{
double latA = source.Lat * DEGREES_TO_RADIANS;
double lonA = source.Lng * DEGREES_TO_RADIANS;
double angularDistance = range / EARTH_RADIUS_M;
double trueCourse = bearing * DEGREES_TO_RADIANS;
double lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
double dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
return new PointLatLng(
lat / DEGREES_TO_RADIANS,
lon / DEGREES_TO_RADIANS);
}
Juste take your center as source :
for (int i = 0; i < 360; i++)
{
vertices.Add(CalculateDerivedPosition(center, circleRadius, i));
}
Upvotes: 1