Exemple #1
0
        /// <summary>
        /// Calculates the bearing to.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <returns></returns>
        public double CalculateBearingTo(GeoPoint point)
        {
            double lat1 = Latitude * Math.PI / 180, lat2 = point.Latitude * Math.PI / 180;
            double dLon = (point.Longitude - Longitude) * Math.PI / 180;

            double y = Math.Sin(dLon) * Math.Cos(lat2);
            double x = Math.Cos(lat1) * Math.Sin(lat2) -
                    Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLon);

            var brng = Math.Atan2(y, x);

            return (brng * 180 / Math.PI + 360) % 360;
        }
Exemple #2
0
        private static double CalcLineLength(GeoPoint p1, GeoPoint p2)
        {
            var deltaX = Math.Abs(p1.Latitude - p2.Latitude);
            var deltaY = Math.Abs(p1.Longitude - p2.Longitude);

            return Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
        }
Exemple #3
0
        public void Run(String[] args)
        {
            Console.Write("Enter Address: ");
            string addressPart = Console.ReadLine();

            Console.Write("Enter City: ");
            var cityName = Console.ReadLine();

            Console.Write("Enter State: ");
            var stateTerm = Console.ReadLine();

            Console.WriteLine("Searching...");

            GeoPoint foundPoint = null;

            var number = 0;

            if (addressPart != null)
            {
                var firstSpaceIndex = addressPart.IndexOf(' ');
                if (firstSpaceIndex != -1 && firstSpaceIndex + 1 < addressPart.Length)
                {
                    number = (int)Convert.ChangeType(addressPart.Substring(0, firstSpaceIndex), typeof(int));
                    addressPart = addressPart.Substring(firstSpaceIndex + 1);
                }
            }

            if( number == 0 ) throw new InvalidOperationException("Please specify a valid address");

            using (var ds = new TigerLineDataService())
            {
                var placeMatch = ds.GetPlaceByCityAndState(cityName, stateTerm);

                // was there an exact match?
                if (placeMatch == null)
                {
                    // if not, have to use levenshtein distance to find the closest match
                    var stateDistanceList = new List<dynamic>();

                    // now calculate the best levenshtein distance for city
                    foreach (var place in ds.GetPlacesByState(stateTerm))
                    {
                        var distance = Levenshtein.Compute(place.PlaceName, cityName);

                        dynamic distanceHolder = new ExpandoObject();
                        distanceHolder.Distance = distance;
                        distanceHolder.Record = place;

                        stateDistanceList.Add(distanceHolder);
                    }

                    var distanceQuery = from dno in stateDistanceList
                                        orderby dno.Distance
                                        select dno.Record as Place;

                    var sortedList = distanceQuery.ToList();

                    placeMatch = sortedList.FirstOrDefault();
                }

                if (placeMatch != null)
                {
                    var result = ds.GetStreetSummaryByAddress(number, placeMatch.RecordId, addressPart);

                    //// we found something
                    //var result =
                    //    context.USP_CRUD_STREET_NAMES_FIND_BY_ADDRESS(number, foundPlace.Id, addressPart).FirstOrDefault
                    //        ();
                    if (result != null)
                    {
                        // get address range
                        //var firstAddress = (int) Convert.ChangeType(result.First ?? "0", typeof (int));
                        //var lastAddress = (int) Convert.ChangeType(result.Last ?? "0", typeof (int));
                        var firstAddress = result.First;
                        var lastAddress = result.Last;

                        //var addressRange = Math.Abs(firstAddress - lastAddress);

                        var segments = ds.GetStreetSegmentsByTigerLineIdOrdered(result.TigerLineId);

                        // find all segmenst for this TLID, ordered by sequence
                        //var segmentQuery = from segment in context.StreetSegments
                        //                   where segment.TLID == result.TLID
                        //                   orderby segment.Sequence
                        //                   select segment;

                        //var segments = segmentQuery.ToList();

                        // calcuate segment lenghts
                        var segmentLengths = new List<double>();
                        var numSegments = segments.Count - 1;
                        for (var i = 0; i < numSegments; i++)
                        {
                            var point1 = new GeoPoint(segments[i].Latitude, segments[i].Longitude);
                            var point2 = new GeoPoint(segments[i + 1].Latitude, segments[i + 1].Longitude);
                            segmentLengths.Add(CalcLineLength(point1, point2));
                        }

                        var totalLength = segmentLengths.Sum();
                        if (Math.Abs(totalLength - 0) < Double.Epsilon)
                        {
                            // distances are too small, return start of street
                            return;
                        }

                        var addressPosition = Math.Abs(number - lastAddress);
                        var addressCount = Math.Abs(firstAddress - lastAddress);

                        // get distance as a ratio of address to addresscount taken in terms of totalLength
                        var distanceAlongLine = (addressPosition/(double) addressCount)*totalLength;

                        // 1. Calculate total distance of segments by calculating the deltas between points
                        // 2. Estimate travel distance based on ratio between total distance and difference number and first address
                        // 3. Find segment that contains our address by adding travel distances up until we meet or exceed the travel distance calcuated in 2
                        // 4. Once segment is found, estimate bottom address of segment based on travel distance
                        // 5. Estimate remaining distance between segment and travel distance
                        // 6. Add that distance to the point at the beggining segment, convert back to lat/long and you have address

                        // Figure out which segment our address is in, and where it is
                        double travelDistance = 0;
                        for (var i = 0; i < numSegments; i++)
                        {
                            var bottomAddress = (int) (firstAddress + (travelDistance/totalLength*addressCount));

                            travelDistance += segmentLengths[i];
                            if (travelDistance < distanceAlongLine) continue;

                            // We've found our segment, do the final computations
                            var topAddress = (int) (firstAddress + (travelDistance/totalLength*addressCount));

                            // Determine how far along this segment our address is
                            var addressesForThisSegment = Math.Abs(topAddress - bottomAddress);
                            var addressLocationScale = Math.Abs(number - (double) bottomAddress)/addressesForThisSegment;

                            var point1 = new GeoPoint(segments[i].Latitude, segments[i].Longitude);
                            var point2 = new GeoPoint(segments[i + 1].Latitude, segments[i + 1].Longitude);

                            var sqlPoint =
                                point1.CalculateDestinationPoint(
                                    point1.CalculateDistanceTo(point2)*addressLocationScale,
                                    point1.CalculateBearingTo(point2));
                            foundPoint = new GeoPoint(sqlPoint.Latitude, sqlPoint.Longitude);
                            break;
                        }
                    }
                }
            }

            if (foundPoint != null)
            {
                Console.WriteLine("Found point: {0}, {1}", foundPoint.Latitude, foundPoint.Longitude);
            }
            else
            {
                Console.WriteLine("Not found.");
            }

            Console.ReadKey();
        }
Exemple #4
0
        /// <summary>
        /// Calculates the intersection.
        /// </summary>
        /// <param name="p1">The p1.</param>
        /// <param name="brng1">The BRNG1.</param>
        /// <param name="p2">The p2.</param>
        /// <param name="brng2">The BRNG2.</param>
        /// <returns></returns>
        public GeoPoint CalculateIntersection(GeoPoint p1, double brng1, GeoPoint p2, double brng2)
        {
            double lat1 = p1.Latitude.ToRad(), lon1 = p1.Longitude.ToRad();
            double lat2 = p2.Latitude.ToRad(), lon2 = p2.Longitude.ToRad();
            double brng13 = brng1.ToRad(), brng23 = brng2.ToRad();
            double dLat = lat2-lat1, dLon = lon2-lon1;

            double dist12 = 2*Math.Asin( Math.Sqrt( Math.Sin(dLat/2)*Math.Sin(dLat/2) +
              Math.Cos(lat1)*Math.Cos(lat2)*Math.Sin(dLon/2)*Math.Sin(dLon/2) ) );
            if (dist12 == 0) return null;

            // initial/final bearings between points
            double brngA = Math.Acos( ( Math.Sin(lat2) - Math.Sin(lat1)*Math.Cos(dist12) ) /
              ( Math.Sin(dist12)*Math.Cos(lat1) ) );

            if (double.IsNaN(brngA)) brngA = 0; // protected against rounding

            double brngB = Math.Acos( ( Math.Sin(lat1) - Math.Sin(lat2)*Math.Cos(dist12) ) /
              ( Math.Sin(dist12)*Math.Cos(lat2) ) );

            double brng12;
            double brng21;

            if (Math.Sin(lon2-lon1) > 0) {
              brng12 = brngA;
              brng21 = 2*Math.PI - brngB;
            } else {
              brng12 = 2*Math.PI - brngA;
              brng21 = brngB;
            }

            double alpha1 = (brng13 - brng12 + Math.PI) % (2*Math.PI) - Math.PI;  // angle 2-1-3
            double alpha2 = (brng21 - brng23 + Math.PI) % (2*Math.PI) - Math.PI;  // angle 1-2-3

            if (Math.Sin(alpha1)==0 && Math.Sin(alpha2)==0) return null;  // infinite intersections
            if (Math.Sin(alpha1)*Math.Sin(alpha2) < 0) return null;       // ambiguous intersection

            double alpha3 = Math.Acos( -Math.Cos(alpha1)*Math.Cos(alpha2) +
                                 Math.Sin(alpha1)*Math.Sin(alpha2)*Math.Cos(dist12) );
            double dist13 = Math.Atan2(Math.Sin(dist12) * Math.Sin(alpha1) * Math.Sin(alpha2),
                                 Math.Cos(alpha2) + Math.Cos(alpha1) * Math.Cos(alpha3));
            double lat3 = Math.Asin( Math.Sin(lat1)*Math.Cos(dist13) +
                              Math.Cos(lat1)*Math.Sin(dist13)*Math.Cos(brng13) );
            double dLon13 = Math.Atan2( Math.Sin(brng13)*Math.Sin(dist13)*Math.Cos(lat1),
                                 Math.Cos(dist13)-Math.Sin(lat1)*Math.Sin(lat3) );
            double lon3 = lon1+dLon13;
            lon3 = (lon3+Math.PI) % (2*Math.PI) - Math.PI;  // normalise to -180..180º

            return new GeoPoint(lat3.ToDeg(), lon3.ToDeg());
        }
Exemple #5
0
        /// <summary>
        /// Calculates the distance to.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <returns></returns>
        public double CalculateDistanceTo(GeoPoint point)
        {
            double R = radius;
            double lat1 = Latitude * Math.PI / 180, lon1 = Longitude * Math.PI / 180;
            double lat2 = point.Latitude * Math.PI / 180, lon2 = point.Longitude * Math.PI / 180;
            double dLat = lat2 - lat1;
            double dLon = lon2 - lon1;

            double a = Math.Sin(dLat/2) * Math.Sin(dLat/2) +
                Math.Cos(lat1) * Math.Cos(lat2) *
                Math.Sin(dLon/2) * Math.Sin(dLon/2);

            double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
            double d = R * c;

            return d;
        }