/// <summary> /// Calculates a list of coordinates that are an equal distance away from a central point to create a regular polygon. /// </summary> /// <param name="center">Center of the polygon.</param> /// <param name="radius">Radius of the polygon.</param> /// <param name="distanceUnits">Distance units of radius.</param> /// <param name="numberOfPoints">Number of points the polygon should have.</param> /// <param name="offset">The offset to rotate the polygon. When 0 the first coordinate will align with North.</param> /// <returns>A list of coordinates that form a regular polygon</returns> public static CoordinateCollection GenerateRegularPolygon(Coordinate center, double radius, DistanceUnits units, int numberOfPoints, double offset) { var points = new CoordinateCollection(); double centralAngle = 360 / numberOfPoints; for (var i = 0; i <= numberOfPoints; i++) { points.Add(CalculateDestinationCoordinate(center, (i * centralAngle + offset) % 360, radius, units)); } return(points); }
/// <summary> /// Vertex reduction is the brute-force algorithm for simplifying a list of coordinates. /// It does this by ensuring that no two coordinates are closer than a specified distance /// in the unit of measurment. If working with coordinates in degrees then the distance /// would be in degrees. /// </summary> /// <param name="coordinates">A list of coordinates to reduce</param> /// <param name="tolerance">A distance in the unit of the coordinate parameters in which no two coordinates should be closer than.</param> /// <returns>A list of coordinates where no two cordinates are closer than the tolerance distance.</returns> public static CoordinateCollection VertexReduction(CoordinateCollection coordinates, double tolerance) { //Verify that there are at least 2 or more coordinates in the LocationCollection if (coordinates == null || coordinates.Count < 3) { return(coordinates); } var newCoordinates = new CoordinateCollection(); //Store the initial cooridnate newCoordinates.Add(coordinates[0]); var baseCoord = coordinates[0]; for (int i = 1; i < coordinates.Count - 1; i++) { //check to see if the distance between the base coordinate and the coordinate in question is outside the tolerance distance. if (Math.Sqrt(Math.Pow(coordinates[i].Latitude - baseCoord.Latitude, 2) + Math.Pow(coordinates[i].Longitude - baseCoord.Longitude, 2)) > tolerance) { //store the coordinate and make it the new base coordinate for comparison. newCoordinates.Add(coordinates[i]); baseCoord = coordinates[i]; } } //store the last cooridnate newCoordinates.Add(coordinates[coordinates.Count - 1]); //ensure there are enough points to create a SQLGeometry object if (newCoordinates.Count > 4) { //return the new coordinate collection return(newCoordinates); } //return the original coordinates return(coordinates); }
/// <summary> /// Takes a list of coordinates and fills in the space between them with accurately /// positioned pints to form a Geodesic path. /// /// Source: http://alastaira.wordpress.com/?s=geodesic /// </summary> /// <param name="coordinates">List of coordinates to work with.</param> /// <param name="nodeSize">Number of nodes to insert between each coordinate</param> /// <returns>A set of coordinates that for geodesic paths.</returns> public static CoordinateCollection CalculateGeodesic(CoordinateCollection coordinates, int nodeSize) { if (nodeSize <= 0) { nodeSize = 32; } var locs = new CoordinateCollection(); for (var i = 0; i < coordinates.Count - 1; i++) { // Convert coordinates from degrees to Radians var lat1 = ToRadians(coordinates[i].Latitude); var lon1 = ToRadians(coordinates[i].Longitude); var lat2 = ToRadians(coordinates[i + 1].Latitude); var lon2 = ToRadians(coordinates[i + 1].Longitude); // Calculate the total extent of the route var d = 2 * Math.Asin(Math.Sqrt(Math.Pow((Math.Sin((lat1 - lat2) / 2)), 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Pow((Math.Sin((lon1 - lon2) / 2)), 2))); // Calculate positions at fixed intervals along the route for (var k = 0; k <= nodeSize; k++) { var f = (k / (double)nodeSize); var A = Math.Sin((1 - f) * d) / Math.Sin(d); var B = Math.Sin(f * d) / Math.Sin(d); // Obtain 3D Cartesian coordinates of each point var x = A * Math.Cos(lat1) * Math.Cos(lon1) + B * Math.Cos(lat2) * Math.Cos(lon2); var y = A * Math.Cos(lat1) * Math.Sin(lon1) + B * Math.Cos(lat2) * Math.Sin(lon2); var z = A * Math.Sin(lat1) + B * Math.Sin(lat2); // Convert these to latitude/longitude var lat = Math.Atan2(z, Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2))); var lon = Math.Atan2(y, x); // Add this to the array locs.Add(new Coordinate(ToDegrees(lat), ToDegrees(lon))); } } return(locs); }