Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <summary>
        /// Determines if a Coordinate is within a ring.
        ///
        /// Algorithm based on: http://msdn.microsoft.com/en-us/library/cc451895.aspx
        /// </summary>
        /// <param name="cc">LocationCollection that makes up a ring</param>
        /// <param name="coord">Coordinate to search with</param>
        /// <returns>A boolean indicating if a coordinate is contained inside the LocationCollection.</returns>
        private bool CoordinateInRing(CoordinateCollection cc, Coordinate coord)
        {
            //TODO: Make spatially accurate
            int  j      = cc.Count - 1;
            bool inPoly = false;

            for (int i = 0; i < cc.Count; i++)
            {
                if (cc[i].Longitude < coord.Longitude && cc[j].Longitude >= coord.Longitude || cc[j].Longitude < coord.Longitude && cc[i].Longitude >= coord.Longitude)
                {
                    if (cc[i].Latitude + (coord.Longitude - cc[i].Longitude) / (cc[j].Longitude - cc[i].Longitude) * (cc[j].Latitude - cc[i].Latitude) < coord.Latitude)
                    {
                        inPoly = !inPoly;
                    }
                }

                j = i;
            }

            return(inPoly);
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
 public Polygon(CoordinateCollection extriorRing)
 {
     this.ExteriorRing  = extriorRing;
     this.InteriorRings = new List <CoordinateCollection>();
 }