private static bool ValidateRequestedLocation(GeoLocation geolocation, List <RegionPolygonsCache> subregions)
        {
            List <Point> points = new List <Point>();

            if (geolocation.Point != null)
            {
                points.Add(geolocation.Point.Center);
            }
            else if (geolocation.Region != null)
            {
                points.AddRange(geolocation.Region.Exterior);
            }

            bool isValidLocation = true;

            foreach (Point wsdLocation in points)
            {
                double latitude  = wsdLocation.Latitude.ToDouble();
                double longitude = wsdLocation.Longitude.ToDouble();

                isValidLocation = GeoCalculations.IsPointInRegionPolygons(subregions, latitude, longitude);

                if (!isValidLocation)
                {
                    break;
                }
            }

            return(isValidLocation);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Determines whether a point is in a RegionPolygons.
        /// </summary>
        /// <param name="subregion">Type of RegionPolygonsCache.</param>
        /// <param name="latitude">The latitude.</param>
        /// <param name="longitude">The longitude.</param>
        /// <returns>The boolean value indicating point lies inside the polygon or not</returns>
        public static List <Location> Contains(this RegionPolygonsCache subregion, double latitude, double longitude)
        {
            if (subregion == null)
            {
                return(null);
            }

            // If the point doesn't exist in region bounding box then return false.
            if (!subregion.BoundingBox.Contains(latitude, longitude))
            {
                return(null);
            }

            List <LocationRect> locationRectangles = subregion.LocationRectangles;

            // Start with smaller location rectangles, so that we have less polygon points to deal with when finding a point inside the polygon.
            for (int i = locationRectangles.Count - 1; i >= 0; i--)
            {
                if (locationRectangles[i].Contains(latitude, longitude))
                {
                    List <Location> polygon = subregion.PolygonCollection[i];

                    if (GeoCalculations.IsPointInPolygon(polygon, latitude, longitude))
                    {
                        return(polygon);
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Zoom out of the map.
 /// </summary>
 /// <param name="ScreenX">The x-coordinate of the zoom center on the map.</param>
 /// <param name="ScreenY">The y-coordinate of the zoom center on the map.</param>
 public void ZoomOut(Double ScreenX, Double ScreenY)
 {
     if (this.ZoomLevel > MinZoomLevel)
     {
         ZoomTo(GeoCalculations.Mouse2GeoCoordinate(ScreenX - this.ScreenOffset.X,
                                                    ScreenY - this.ScreenOffset.Y,
                                                    this.ZoomLevel),
                this.ZoomLevel - 1);
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// The mouse was moved.
        /// </summary>
        /// <param name="Sender">The sender of the event.</param>
        /// <param name="MouseButtonEventArgs">The mouse button event arguments.</param>
        public void ProcessMouseRightButtonDown(Object Sender, MouseButtonEventArgs MouseButtonEventArgs)
        {
            var MousePosition = MouseButtonEventArgs.GetPosition(this);

            var GeoPos = GeoCalculations.Mouse2GeoCoordinate(MousePosition.X - this.ScreenOffset.X,
                                                             MousePosition.Y - this.ScreenOffset.Y,
                                                             ZoomLevel);

            Clipboard.SetData(DataFormats.Text, (Object)(GeoPos.Latitude.Value.ToString().Replace(",", ".") + ", " + GeoPos.Longitude.Value.ToString().Replace(",", ".")));
        }
        /// <summary>
        /// Calculates the elevation.
        /// </summary>
        /// <param name="paramEasting">The parameter easting.</param>
        /// <param name="paramNorthing">The parameter northing.</param>
        /// <returns>returns the clutter dataset value.</returns>
        public double CalculateElevation(double paramEasting, double paramNorthing)
        {
            string logMethodName = string.Format("ClutterDatasetReader.CalculateElevation- Easting -> {0}, Northing -> {1}", paramEasting, paramNorthing);

            // Begin Log transaction
            this.Logger.Log(TraceEventType.Information, LoggingMessageId.ElevationMessage, "Enter " + logMethodName);

            int easting  = (int)paramEasting;
            int northing = (int)paramNorthing;

            string fileInitial = GeoCalculations.GetNationalGridTileName(easting, northing);

            string eastingSuffix  = ((easting / 10000) % 10).ToString();
            string northingSuffix = ((northing / 10000) % 10).ToString();
            string format         = ".asc";

            string fileName = string.Concat(fileInitial, eastingSuffix, northingSuffix, format);

            double elevation = 0.0;

            try
            {
                byte[]   fileData       = this.ElevationDataCache.ReadCachedData(fileName) as byte[];
                string   terrainRawData = Encoding.ASCII.GetString(fileData);
                string[] terrainData    = terrainRawData.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

                terrainData = terrainData.Skip(5).ToArray();

                int terrainEastingCellIndex = ((int)easting % 10000) / 50;

                // calculate from end of file
                int terrainNorthingCellIndex = 199 - (((int)northing % 10000) / 50);

                string row = terrainData[terrainNorthingCellIndex];

                var rowEastings = row.Split(new[] { " " }, StringSplitOptions.None);

                elevation = Convert.ToDouble(rowEastings[terrainEastingCellIndex]);

                if (elevation == -0.8)
                {
                    elevation = 0;
                }
            }
            catch (Exception ex)
            {
                this.Logger.Log(TraceEventType.Error, LoggingMessageId.ElevationGlobUnsupportedTileId, ex.ToString());

                return(0);
            }

            return(elevation);
        }
        /// <summary>
        /// Validates the Add Incumbents request.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        public override bool ValidateAddIncumbentRequestTBAS(Parameters parameters, out List <string> errorMessages)
        {
            var valResult = base.ValidateAddIncumbentRequestTBAS(parameters, out errorMessages);

            if (valResult)
            {
                if (!this.TvSpectrum(parameters, out errorMessages))
                {
                    return(false);
                }

                if (!this.TempBasLocation(parameters, out errorMessages))
                {
                    return(false);
                }

                if (!this.TransmitLocation(parameters, out errorMessages))
                {
                    return(false);
                }

                if (!this.EventTBAS(parameters, out errorMessages))
                {
                    return(false);
                }

                if (parameters.TvSpectrum.CallSign == null)
                {
                    errorMessages.Add(Constants.ErrorMessageCallSignRequired);
                    return(false);
                }

                var serviceCacheRequestParameter = new ServiceCacheRequestParameters()
                {
                    VsdService = "DT"
                };
                var callSigns = DatabaseCache.ServiceCacheHelper.SearchCacheObjects(ServiceCacheObjectType.TvEngData, SearchCacheRequestType.ByVsdService, serviceCacheRequestParameter) as IEnumerable <CacheObjectTvEngdata>;

                if (callSigns.FirstOrDefault(obj => obj.CallSign == parameters.TvSpectrum.CallSign) == null)
                {
                    errorMessages.Add(Constants.ErrorMessageCallSignNotExist);
                    return(false);
                }

                if (GeoCalculations.GetDistance(parameters.TransmitLocation, parameters.TempBasLocation).InMeter() < 100)
                {
                    errorMessages.Add(Constants.ErrorMessageDistanceLessThan100);
                    return(false);
                }
            }

            return(valResult);
        }
        /// <summary>
        /// Calculates the radial contour.
        /// </summary>
        /// <param name="startLocation">The start location.</param>
        /// <param name="distance">The distance.</param>
        /// <returns>returns List{Location}.</returns>
        private static List <Location> CalculateRadialContour(Location startLocation, Distance distance)
        {
            // rotating azimuth at 1 degree intervals
            List <Location> deltaLocations = new List <Location>();

            for (int azimuth = 0; azimuth <= 360; azimuth++)
            {
                var deltaCoord = GeoCalculations.GetLocationTowardsBearing(startLocation, distance, azimuth);
                deltaLocations.Add(deltaCoord);
            }

            return(deltaLocations);
        }
Ejemplo n.º 8
0
        public IEnumerable <GeoPoint> GetLocalCoords(GeoPoint geo)
        {
            var bounding = GeoCalculations.GetBoundingBoxMiles(new GeoCalculations.MapPoint {
                Latitude = geo.Lat, Longitude = geo.Long
            }, geo.Distance);

            using (var cn = new MySqlConnection(_connectionString))
            {//TODO: need to bound query with oblong coords to limit DB index lookup
                cn.Open();
                const string sql = "SELECT *,3956 * 2 * ASIN(SQRT(POWER(SIN((@Lat - `Lat`) * PI() / 180 / 2), 2) + COS(@Lat * PI() / 180) * COS(`Lat` *PI() / 180) * POWER(SIN((@Long - `Long`) * PI() / 180 / 2), 2) )) AS distance FROM `geopoints` WHERE `Long` BETWEEN @Long1 AND @long2 AND `Lat` BETWEEN @Lat1 AND @Lat2 HAVING distance < @Distance; ";
                return(cn.Query <GeoPoint>(sql, new { @Distance = geo.Distance, @Lat = geo.Lat, @Long = geo.Long, @Long1 = bounding.MinPoint.Longitude, @Long2 = bounding.MaxPoint.Longitude, @Lat1 = bounding.MinPoint.Latitude, @Lat2 = bounding.MaxPoint.Latitude }));
            }
        }
        /// <summary>
        /// Ares the quadrilateral vertices valid.
        /// </summary>
        /// <param name="quadrilateralArea">The quadrilateral area.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool AreQuadrilateralVerticesValid(QuadrilateralArea quadrilateralArea)
        {
            List <Location> locations = new List <Location>();

            locations.AddRange(new[] { quadrilateralArea.NEPoint.ToLocation(), quadrilateralArea.NWPoint.ToLocation(), quadrilateralArea.SEPoint.ToLocation(), quadrilateralArea.SWPoint.ToLocation(), quadrilateralArea.NEPoint.ToLocation() });
            for (int locationIndex = 0; locationIndex < locations.Count - 1; locationIndex++)
            {
                var distance = GeoCalculations.GetDistance(locations[locationIndex], locations[locationIndex + 1]);
                if (distance.InKm() > 3)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Checks the if any of the incumbents contains desired location.
        /// </summary>
        /// <param name="station">The incumbent.</param>
        /// <param name="point">The target incumbent.</param>
        /// <param name="offContourDistance">The desired external contour distance.</param>
        /// <returns>returns Incumbent.</returns>
        public static bool IsInOrAroundContour(this Incumbent station, Location point, Distance offContourDistance)
        {
            if (string.IsNullOrEmpty(station.Contour))
            {
                return(false);
            }

            var             contour       = JsonSerialization.DeserializeString <Contour>(station.Contour);
            List <Location> polygonPoints = contour.ContourPoints;

            if (GeoCalculations.IsPointInPolygon(polygonPoints, point))
            {
                return(true);
            }

            // point is not in contour
            // need to check for safe Distance from contour
            var bearingToTarget = GeoCalculations.CalculateBearing(station.Location, point);

            double distance = 0.0;
            bool   lessThanOffContourDistance = false;
            int    index;

            for (int i = (int)bearingToTarget - 90; i < (int)bearingToTarget + 90; i++)
            {
                index = i;
                if (index >= 360)
                {
                    index = i - 360;
                }
                else if (index < 0)
                {
                    index = 360 + i;
                }

                distance = GeoCalculations.GetDistance(point, polygonPoints[index]).Value / 1000.0;
                if (distance <= offContourDistance.InKm())
                {
                    lessThanOffContourDistance = true;
                    break;
                }
            }

            return(lessThanOffContourDistance);
        }
Ejemplo n.º 11
0
    void Start()
    {
#if UNITY_EDITOR
        loadWithoutGPS = true; // Test if this caues bugs on android
#endif
        googleMap       = GetComponent <GoogleMap>();
        geoCalculations = GetComponent <GeoCalculations>();

        currentLocation         = new GoogleMapLocation();
        currentLocation.address = "";

        if (loadWithoutGPS)
        {
            Debug.LogError("Not using GPS");
        }
        else
        {
            StartCoroutine(StartLocation());
        }
    }
Ejemplo n.º 12
0
        public static bool IsPointInRegulatoryBodyBoundary(double latitude, double longitude, out string regionCode)
        {
            bool isInBoundary = false;

            regionCode = null;

            Dictionary <string, List <RegionPolygonsCache> > regionPolygons = (Dictionary <string, List <RegionPolygonsCache> >)DatabaseCache.ServiceCacheHelper.GetServiceCacheObjects(ServiceCacheObjectType.RegionPolygons, null);

            foreach (var regionPolygon in regionPolygons)
            {
                isInBoundary = GeoCalculations.IsPointInRegionPolygons(regionPolygon.Value, latitude, longitude);

                if (isInBoundary)
                {
                    regionCode = regionPolygon.Key;
                    break;
                }
            }

            return(isInBoundary);
        }
Ejemplo n.º 13
0
        public virtual async Task <IActionResult> List(PropertyListModel model, string viewName = "_List_Property")
        {
            var propertySettings = Engine.Settings.Property;

            if (!propertySettings.Enabled || !propertySettings.ShowList)
            {
                return(NotFound());
            }

            model.PublishStatus = ContentStatus.Published;
            model = await _property.GetPropertiesAsync(model);

            model.Locations = await _property.GetLocationsAsync(model);

            model.CentrePoint = GeoCalculations.GetCentralGeoCoordinate(model.Locations.Select(p => new GeoCoordinate(p.Latitude, p.Longitude)));
            PropertySettings settings = Engine.Settings.Property;

            model.AvailableTypes = settings.GetListingTypes();
            model.PlanningTypes  = settings.GetPlanningTypes();

            return(View(viewName, model));
        }
        // TODO: Investigate should we need to validate device location on UX side or should it be done in back-end ?
        public IEnumerable <ValidationResult> Validate(ValidationContext validationContext)
        {
            double latitude  = double.Parse(this.Latitude);
            double longitude = double.Parse(this.Longitude);

            bool isValidLocation = false;

            Region region     = CommonUtility.GetRegionByName(this.Country);
            string regionCode = region.Regulatory.RegionCode;

            Dictionary <string, List <RegionPolygonsCache> > regionPolygons = (Dictionary <string, List <RegionPolygonsCache> >)DatabaseCache.ServiceCacheHelper.GetServiceCacheObjects(ServiceCacheObjectType.RegionPolygons, null);

            if (region != null && regionPolygons.ContainsKey(regionCode))
            {
                isValidLocation = GeoCalculations.IsPointInRegionPolygons(regionPolygons[regionCode], latitude, longitude);
            }

            if (!isValidLocation)
            {
                yield return(new ValidationResult(string.Format("{0},{1} is outside the boundaries of supported CountryRegions", latitude, longitude), new List <string> {
                    "City"
                }));
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// The mouse was moved above all canvas.
        /// </summary>
        /// <param name="Sender">The sender of the event.</param>
        /// <param name="MouseEventArgs">The mouse event arguments.</param>
        public void ProcessMouseMove(Object Sender, MouseEventArgs MouseEventArgs)
        {
            Int64 MapSizeAtZoomLevel;
            var   MousePosition = MouseEventArgs.GetPosition(this);

            if (LastMousePositionDuringMovement.X != MousePosition.X ||
                LastMousePositionDuringMovement.Y != MousePosition.Y)
            {
                #region The left mouse button is pressed => drag the map!

                if (MouseEventArgs.LeftButton == MouseButtonState.Pressed)
                {
                    if (Sender == BackgroundLayer &&
                        LastMouseClickPosition.X != 0 &&
                        LastMouseClickPosition.Y != 0)
                    {
                        MapSizeAtZoomLevel = (Int64)(Math.Pow(2, ZoomLevel) * 256);

                        this.ScreenOffset_AtMovementStart = new Point(this.ScreenOffset_AtMovementStart.X % MapSizeAtZoomLevel,
                                                                      this.ScreenOffset_AtMovementStart.Y % MapSizeAtZoomLevel);

                        this.ScreenOffset = new Point((Math.Round(ScreenOffset_AtMovementStart.X + MousePosition.X - LastMouseClickPosition.X) % MapSizeAtZoomLevel),
                                                      (Math.Round(ScreenOffset_AtMovementStart.Y + MousePosition.Y - LastMouseClickPosition.Y) % MapSizeAtZoomLevel));

                        AvoidEndlessVerticalScrolling();

                        MapCenter = GeoCalculations.Mouse2GeoCoordinate(MousePosition.X - this.ScreenOffset.X,
                                                                        MousePosition.Y - this.ScreenOffset.Y,
                                                                        this.ZoomLevel);

                        MapLayers.Values.ForEach(MapLayer => MapLayer.Move(MousePosition.X - LastMousePositionDuringMovement.X,
                                                                           MousePosition.Y - LastMousePositionDuringMovement.Y));

                        MapLayers.Values.ForEach(MapLayer => MapLayer.Redraw());

                        #region Send MapViewChanged events

                        MapMovements++;

                        if (MapViewChanged != null)
                        {
                            MapViewChanged(this, ScreenOffset, this.MapMovements);
                        }

                        #endregion
                    }
                }

                else
                {
                    LastMouseClickPosition.X = 0;
                    LastMouseClickPosition.Y = 0;
                }

                #endregion

                #region Send current mouse position as geo position

                if (GeoPositionChanged != null)
                {
                    GeoPositionChanged(this, GeoCalculations.Mouse2GeoCoordinate(MousePosition.X - this.ScreenOffset.X,
                                                                                 MousePosition.Y - this.ScreenOffset.Y,
                                                                                 ZoomLevel));
                }

                #endregion

                LastMousePositionDuringMovement = MousePosition;
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// To the latitude longitude.
        /// </summary>
        /// <param name="eastings">The easting.</param>
        /// <param name="northings">The northing.</param>
        /// <returns>returns Location.</returns>
        public static Location ToLatitudeLongitude(int eastings, int northings)
        {
            ////if (!IsInitialized)
            ////{
            ////    Initialize();
            ////}

            double easting         = eastings;
            double northing        = northings;
            var    shifts          = CalculateShifts(easting, northing);
            var    initialEasting  = easting - shifts.se;
            var    initialNorthing = northing - shifts.sn;
            var    continousShift  = CalculateShifts(initialEasting, initialNorthing);
            var    secondEasting   = easting - continousShift.se;
            var    secondNorthing  = northing - continousShift.sn;
            var    diff1           = Math.Abs(initialEasting - secondEasting);
            var    diff2           = Math.Abs(initialNorthing - secondNorthing);

            while (diff1 > .0001 || diff2 > .0001)
            {
                initialEasting  = secondEasting;
                initialNorthing = secondNorthing;
                continousShift  = CalculateShifts(initialEasting, initialNorthing);
                secondEasting   = easting - continousShift.se;
                secondNorthing  = northing - continousShift.sn;
                diff1           = Math.Abs(secondEasting - initialEasting);
                diff2           = Math.Abs(secondNorthing - initialNorthing);
            }

            easting  = secondEasting;
            northing = secondNorthing;

            ////airy 180
            ////const double a = 6377563.39600; // Airy 1830 major & minor semi-axes
            ////const double b = 6356256.909; // Airy 1830 major & minor semi-axes
            ////const double f0 = 0.9996012717; // NatGrid scale factor on central meridian
            ////double e2 = (Math.Pow(a, 2) - Math.Pow(b, 2)) / Math.Pow(a, 2); // eccentricity squared

            //// grs 180
            double a = 6378137, b = 6356752.314; // GRS 180
            double f0 = 0.9996012717;            // NatGrid scale factor on central meridian
            double e2 = 6.69437999e-3;           // eccentricity squared

            double lat0    = GeoCalculations.ToRad(49.0);
            double lon0    = GeoCalculations.ToRad(-2.0); // NatGrid true origin
            double n0      = -100000.0;                   // northing & eastings of true origin, metres
            double e0      = 400000.0;                    // northing & eastings of true origin, metres
            double n       = (a - b) / (a + b);
            double nsquare = n * n;
            double ncube   = n * n * n;

            Func <double, double> calculateMeridonalArc = (lat01) =>
            {
                double ma = (1 + n + ((5.0 / 4.0) * nsquare) + ((5.0 / 4.0) * ncube)) * (lat01 - lat0);
                double mb = ((3.0 * n) + (3.0 * nsquare) + ((21.0 / 8.0) * ncube)) * Math.Sin(lat01 - lat0) * Math.Cos(lat01 + lat0);
                double mc = (((15.0 / 8.0) * nsquare) + ((15.0 / 8.0) * ncube)) * Math.Sin(2 * (lat01 - lat0)) * Math.Cos(2 * (lat01 + lat0));
                double md = (35.0 / 24.0) * ncube * Math.Sin(3.0 * (lat01 - lat0)) * Math.Cos(3.0 * (lat01 + lat0));
                double m  = b * f0 * (ma - mb + mc - md); // meridional arc

                return(m);
            };

            double initialLat = ((northing - n0) / (a * f0)) + lat0;
            double m1         = calculateMeridonalArc(initialLat);
            double projection = Math.Abs(northing - n0 - m1);

            while (projection >= 0.001)
            {
                initialLat = ((northing - n0 - m1) / (a * f0)) + initialLat;
                m1         = calculateMeridonalArc(initialLat);
                projection = Math.Abs(northing - n0 - m1);
            }

            double cosLat = Math.Cos(initialLat), sinLat = Math.Sin(initialLat);
            double nu = (a * f0) / Math.Sqrt(1.0 - (e2 * Math.Pow(sinLat, 2.0)));            // transverse radius of curvature
            double ro = (a * f0 * (1.0 - e2)) / Math.Pow(1.0 - (e2 * sinLat * sinLat), 1.5); // meridional radius of curvature
            double η2 = (nu / ro) - 1.0;
            double tanLat = Math.Tan(initialLat), tan2lat = Math.Pow(tanLat, 2), tan4lat = Math.Pow(tanLat, 4), tan6lat = Math.Pow(tanLat, 6);
            double seclat = 1.0 / cosLat;
            double nu3 = Math.Pow(nu, 3), nu5 = Math.Pow(nu, 5), nu7 = Math.Pow(nu, 7);

            double vii  = tanLat / (2.0 * ro * nu);
            double viii = (tanLat / (24.0 * ro * nu3)) * (5.0 + (3.0 * tan2lat) + η2 - (9.0 * tan2lat * η2));
            double ix   = (tanLat / (720.0 * ro * nu5)) * (61.0 + (90.0 * tan2lat) + (45.0 * tan4lat));
            double x    = seclat / nu;
            double xi   = (seclat / (6.0 * nu3)) * ((nu / ro) + (2.0 * tan2lat));
            double xii  = (seclat / (120.0 * nu5)) * (5.0 + (28.0 * tan2lat) + (24.0 * tan4lat));
            double xiia = (seclat / (504.0 * nu7)) * (61.0 + (662.0 * tan2lat) + (1320.0 * tan4lat) + (720.0 * tan6lat));

            double lat1 = initialLat - (vii * Math.Pow(easting - e0, 2)) + (viii * Math.Pow(easting - e0, 4)) - (ix * Math.Pow(easting - e0, 6));
            double lon1 = lon0 + (x * (easting - e0)) - (xi * Math.Pow(easting - e0, 3)) + (xii * Math.Pow(easting - e0, 5)) - (xiia * Math.Pow(easting - e0, 7));

            double latitude  = GeoCalculations.Rad2Deg(lat1);
            double longitude = GeoCalculations.Rad2Deg(lon1);

            return(new Location(latitude, longitude));
        }
Ejemplo n.º 17
0
 /// <summary>
 /// To the RADIAN.
 /// </summary>
 /// <param name="objValue">The object value.</param>
 /// <returns>returns System.Double.</returns>
 public static double ToRad(this double objValue)
 {
     return(GeoCalculations.ToRad(objValue));
 }
Ejemplo n.º 18
0
 /// <summary>
 /// To the EASTING NORTHINGS.
 /// </summary>
 /// <param name="location">The location.</param>
 /// <returns>returns KeyValuePair{System.DoubleSystem.Double}.</returns>
 public static OSGLocation ToEastingNorthing(this Location location)
 {
     return(GeoCalculations.GetEastingNorthing(location));
 }
Ejemplo n.º 19
0
 /// <summary>Calculates the bearing.</summary>
 /// <param name="source">The source.</param>
 /// <param name="destination">The destination.</param>
 /// <returns>returns bearing.</returns>
 public static double CalculateBearing(Location source, Location destination)
 {
     return(GeoCalculations.CalculateBearing(source, destination));
 }
Ejemplo n.º 20
0
 /// <summary>Gets the location towards bearing.</summary>
 /// <param name="source">The source.</param>
 /// <param name="distance">The distance.</param>
 /// <param name="bearing">The bearing.</param>
 /// <returns>returns Location.</returns>
 public static Location GetLocationTowardsBearing(this Location source, Distance distance, double bearing)
 {
     return(GeoCalculations.GetLocationTowardsBearing(source, distance, bearing));
 }
Ejemplo n.º 21
0
 /// <summary>To the square area.</summary>
 /// <param name="objLocation">The object location.</param>
 /// <param name="squareSize">Size of the square.</param>
 /// <returns>returns SquareArea.</returns>
 public static SquareArea ToSquareArea(this Location objLocation, Distance squareSize)
 {
     return(GeoCalculations.BuildSquare(objLocation, squareSize));
 }
Ejemplo n.º 22
0
        /// <summary>
        /// To the easting northing.
        /// </summary>
        /// <param name="latitude">The latitude.</param>
        /// <param name="longitude">The longitude.</param>
        /// <returns>returns OSGLocation.</returns>
        public static Tuple <double, double> ToEastingNorthing(double latitude, double longitude)
        {
            if (!isInitialized)
            {
                Initialize();
            }

            latitude  = GeoCalculations.ToRad(latitude);
            longitude = GeoCalculations.ToRad(longitude);

            double cosLat = Math.Cos(latitude), sinLat = Math.Sin(latitude);

            ////airy 180
            ////double a = 6377563.39600, b = 6356256.909; // Airy 1830 major & minor semi-axes
            ////double f0 = 0.9996012717; // NatGrid scale factor on central meridian

            //////// grs 180
            double a = 6378137, b = 6356752.314; // GRS 180
            double f0 = 0.9996012717;            // NatGrid scale factor on central meridian
            double e2 = 6.69437999e-3;           // eccentricity squared
            double no = -100000;                 // northing & eastings of true origin, metres
            double e0 = 400000;                  // northing & eastings of true origin, metres

            double lat0 = GeoCalculations.ToRad(49.0);
            double lon0 = GeoCalculations.ToRad(-2.0); // NatGrid true origin

            double n  = (a - b) / (a + b);
            double nu = (a * f0) / Math.Sqrt(1.0 - (e2 * Math.Pow(sinLat, 2)));          // transverse radius of curvature
            double ro = (a * f0 * (1 - e2)) / Math.Pow(1 - (e2 * sinLat * sinLat), 1.5); // meridional radius of curvature

            double η2      = (nu / ro) - 1;
            double nsquare = n * n;
            double ncube   = n * n * n;

            double ma = (1 + n + ((5.0 / 4.0) * nsquare) + ((5.0 / 4.0) * ncube)) * (latitude - lat0);
            double mb = ((3.0 * n) + (3.0 * nsquare) + ((21.0 / 8.0) * ncube)) * Math.Sin(latitude - lat0) * Math.Cos(latitude + lat0);
            double mc = (((15.0 / 8.0) * nsquare) + ((15.0 / 8.0) * ncube)) * Math.Sin(2 * (latitude - lat0)) * Math.Cos(2 * (latitude + lat0));
            double md = (35.0 / 24.0) * ncube * Math.Sin(3.0 * (latitude - lat0)) * Math.Cos(3.0 * (latitude + lat0));
            double m  = b * f0 * (ma - mb + mc - md); // meridional arc

            double cos3lat = cosLat * cosLat * cosLat;
            double cos5lat = cos3lat * cosLat * cosLat;
            double tan2lat = Math.Tan(latitude) * Math.Tan(latitude);
            double tan4lat = tan2lat * tan2lat;

            double i    = m + no;
            double ii   = (nu / 2.0) * sinLat * cosLat;
            double iii  = (nu / 24.0) * sinLat * cos3lat * (5 - tan2lat + (9 * η2));
            double iiia = (nu / 720.0) * sinLat * cos5lat * (61 - (58 * tan2lat) + tan4lat);
            double iv   = nu * cosLat;
            double v    = (nu / 6.0) * cos3lat * ((nu / ro) - tan2lat);
            double vi   = (nu / 120.0) * cos5lat * (5 - (18 * tan2lat) + tan4lat + (14 * η2) - (58 * tan2lat * η2));

            double lon1 = longitude - lon0;
            double lon2 = lon1 * lon1, lon3 = lon2 * lon1, lon4 = lon3 * lon1, lon5 = lon4 * lon1, lon6 = lon5 * lon1;

            double northings = i + (ii * lon2) + (iii * lon4) + (iiia * lon6);
            double eastings  = e0 + (iv * lon1) + (v * lon3) + (vi * lon5);

            ////var eastIndex = (int)eastings / 1000;
            ////var northIndex = (int)northings / 1000;
            ////var x0 = eastIndex * 1000;
            ////var y0 = northIndex * 1000;
            ////var shiftloc_se0sn0sg0 = eastIndex + (northIndex * 701) + 1;
            ////var shiftloc_se1sn1sg1 = (eastIndex + 1) + (northIndex * 701) + 1;
            ////var shiftloc_se2sn2sg2 = (eastIndex + 1) + ((northIndex + 1) * 701) + 1;
            ////var shiftloc_se3sn3sg3 = (eastIndex) + ((northIndex + 1) * 701) + 1;

            ////double[] shift_se0sn0sg0 = OSGFileGrid[shiftloc_se0sn0sg0 - 1];
            ////double[] shift_se1sn1sg1 = OSGFileGrid[shiftloc_se1sn1sg1 - 1];
            ////double[] shift_se2sn2sg2 = OSGFileGrid[shiftloc_se2sn2sg2 - 1];
            ////double[] shift_se3sn3sg3 = OSGFileGrid[shiftloc_se3sn3sg3 - 1];

            ////double dx = eastings - x0;
            ////double dy = northings - y0;
            ////double t = dx / 1000;
            ////double u = dy / 1000;

            ////double se = ((1 - t) * (1 - u) * shift_se0sn0sg0[3]) + (t * (1 - u) * shift_se1sn1sg1[3]) + (t * u * shift_se2sn2sg2[3]) + ((1 - t) * u * shift_se3sn3sg3[3]);
            ////double sn = ((1 - t) * (1 - u) * shift_se0sn0sg0[4]) + (t * (1 - u) * shift_se1sn1sg1[4]) + (t * u * shift_se2sn2sg2[4]) + ((1 - t) * u * shift_se3sn3sg3[4]);
            ////////double sg = ((1 - t) * (1 - u) * shift_se0sn0sg0[5]) + (t * (1 - u) * shift_se1sn1sg1[5]) + (t * u * shift_se2sn2sg2[5]) + ((1 - t) * u * shift_se3sn3sg3[5]);
            var shifts = CalculateShifts(eastings, northings);

            double trueEasting  = eastings + shifts.se;
            double trueNorthing = northings + shifts.sn;

            return(new Tuple <double, double>(trueEasting, trueNorthing));
        }
Ejemplo n.º 23
0
        public async Task <PropertyListModel> GetPropertiesAsync(PropertyListModel model)
        {
            IQueryable <PropertyListing> properties = _db.Properties
                                                      .Include(p => p.Agent)
                                                      .Include(p => p.Metadata);

            if (model.LoadImages)
            {
                properties = properties
                             .Include(p => p.Media)
                             .Include(p => p.FloorPlans);
            }

            if (model.PublishStatus.HasValue)
            {
                properties = properties.Where(p => p.Status == model.PublishStatus);
            }

            if (model.Type != null)
            {
                model.Type.RemoveAll(t => !t.IsSet());
                if (model.Type.Count > 0)
                {
                    properties = properties.Where(n => model.Type.Any(t => n.ListingType == t));
                }
            }

            if (model.Status != null)
            {
                model.Status.RemoveAll(t => !t.IsSet());
                if (model.Status.Count > 0)
                {
                    properties = properties.Where(n => model.Status.Any(t => n.LeaseStatus == t));
                }
            }

            if (model.Agent.IsSet())
            {
                properties = properties.Where(n => n.Agent.UserName == model.Agent);
            }

            if (model.Location.IsSet())
            {
                properties = properties.Where(n => n.Address2 == model.Location);
            }

            if (model.PlanningType.IsSet())
            {
                properties = properties.Where(n => n.Planning == model.PlanningType);
            }

            if (model.MinBedrooms.HasValue)
            {
                properties = properties.Where(n => n.Bedrooms >= model.MinBedrooms.Value);
            }

            if (model.MaxBedrooms.HasValue)
            {
                properties = properties.Where(n => n.Bedrooms <= model.MaxBedrooms.Value);
            }

            if (model.Bedrooms.HasValue)
            {
                properties = properties.Where(n => n.Bedrooms == model.Bedrooms.Value);
            }

            if (model.MinRent.HasValue)
            {
                properties = properties.Where(n => n.Rent >= model.MinRent.Value);
            }

            if (model.MaxRent.HasValue)
            {
                properties = properties.Where(n => n.Rent <= model.MaxRent.Value);
            }

            if (model.MinPremium.HasValue)
            {
                properties = properties.Where(n => n.Premium >= model.MinPremium.Value);
            }

            if (model.MaxPremium.HasValue)
            {
                properties = properties.Where(n => n.Premium <= model.MaxPremium.Value);
            }

            if (model.MinPrice.HasValue)
            {
                properties = properties.Where(n => n.AskingPrice >= model.MinPrice.Value);
            }

            if (model.MaxPrice.HasValue)
            {
                properties = properties.Where(n => n.AskingPrice <= model.MaxPrice.Value);
            }

            if (model.Search.IsSet())
            {
                properties = properties.Where(n =>
                                              n.Title.Contains(model.Search) ||
                                              n.Address1.Contains(model.Search) ||
                                              n.Address2.Contains(model.Search) ||
                                              n.City.Contains(model.Search) ||
                                              n.County.Contains(model.Search) ||
                                              n.Postcode.Contains(model.Search) ||
                                              n.ShortDescription.Contains(model.Search) ||
                                              n.Lease.Contains(model.Search) ||
                                              n.Location.Contains(model.Search) ||
                                              n.Planning.Contains(model.Search) ||
                                              n.Reference.Contains(model.Search)
                                              );
            }

            if (model.Order.IsSet())
            {
                switch (model.Order)
                {
                case "name":
                case "title":
                    properties = properties.OrderBy(n => n.Title);
                    break;

                case "date":
                    properties = properties.OrderBy(n => n.PublishDate);
                    break;

                case "views":
                    properties = properties.OrderBy(n => n.Views);
                    break;

                case "name+desc":
                case "title+desc":
                    properties = properties.OrderByDescending(n => n.Title);
                    break;

                case "date+desc":
                    properties = properties.OrderByDescending(n => n.PublishDate);
                    break;

                case "views+desc":
                    properties = properties.OrderByDescending(n => n.Views);
                    break;

                case "rent":
                    properties = properties.OrderBy(n => n.Rent);
                    break;

                case "planning":
                    properties = properties.OrderBy(n => n.Planning);
                    break;

                case "type":
                    properties = properties.OrderBy(n => n.ListingType);
                    break;

                case "premium":
                    properties = properties.OrderBy(n => n.Premium);
                    break;

                case "rent+desc":
                    properties = properties.OrderByDescending(n => n.Rent);
                    break;

                case "planning+desc":
                    properties = properties.OrderByDescending(n => n.Planning);
                    break;

                case "type+desc":
                    properties = properties.OrderByDescending(n => n.ListingType);
                    break;

                case "premium+desc":
                    properties = properties.OrderByDescending(n => n.Premium);
                    break;

                default:
                    properties = properties.OrderByDescending(n => n.PublishDate).ThenBy(n => n.Id);
                    break;
                }
            }

            model.AvailableTypes = await _db.Properties.Select(p => p.ListingType).Distinct().ToListAsync();

            model.AvailableStatuses = await _db.Properties.Select(p => p.LeaseStatus).Distinct().ToListAsync();

            model.AvailablePlanningTypes = await _db.Properties.Select(p => p.Planning).Distinct().ToListAsync();

            model.PlanningTypes = Engine.Settings.Property.GetPlanningTypes();

            await model.ReloadAsync(properties);

            if (model.List != null)
            {
                model.Locations   = model.List.Select(p => new MapMarker(p, p.Title, p.QuickInfo, p.Id.ToString(), p.Url, p.FeaturedImage.Url)).ToList();
                model.CentrePoint = GeoCalculations.GetCentralGeoCoordinate(model.Locations.Select(p => new GeoCoordinate(p.Latitude, p.Longitude)));
            }
            return(model);
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Zoom into the map onto the given coordinates and zoom level.
        /// </summary>
        /// <param name="Latitude">The latitude of the zoom center on the map.</param>
        /// <param name="Longitude">The longitude of the zoom center on the map.</param>
        /// <param name="ZoomLevel">The desired zoom level.</param>
        public void ZoomTo(Latitude Latitude, Longitude Longitude, UInt32 ZoomLevel)
        {
            #region Initial checks

            if (Latitude.Value > 90 || Latitude.Value < -90)
            {
                throw new ArgumentException("Invalid Latitude!");
            }

            if (Longitude.Value > 90 || Longitude.Value < -90)
            {
                throw new ArgumentException("Invalid Longitude!");
            }

            if (ZoomLevel < MinZoomLevel || ZoomLevel > MaxZoomLevel)
            {
                throw new ArgumentException("Invalid zoom level!");
            }

            #endregion

            var OldZoomLevel = this.ZoomLevel;
            this.ZoomLevel = ZoomLevel;
            var NewOffset = GeoCalculations.GeoCoordinate2ScreenXY(Latitude, Longitude, ZoomLevel);

            var MapSizeAtZoomLevel = (Int64)(Math.Pow(2, ZoomLevel) * 256);

            this.ScreenOffset = new Point((-((Int64)NewOffset.X) + ForegroundLayer.ActualWidth / 2) % MapSizeAtZoomLevel,
                                          (-((Int64)NewOffset.Y) + ForegroundLayer.ActualHeight / 2) % MapSizeAtZoomLevel);

            AvoidEndlessVerticalScrolling();

            MapLayers.Values.ForEach(MapLayer => MapLayer.Redraw());

            #region Send MapViewChanged events

            MapMovements++;

            if (MapViewChanged != null)
            {
                MapViewChanged(this, this.ScreenOffset, this.MapMovements);
            }

            #endregion

            #region Send ZoomLevelChanged event

            if (this.ZoomLevel != OldZoomLevel && ZoomLevelChanged != null)
            {
                ZoomLevelChanged(this, OldZoomLevel, this.ZoomLevel);
            }

            #endregion

            #region Activate/Deactivate zoom buttons

            if (this.ZoomLevel == MinZoomLevel)
            {
                ZoomOutButton.IsEnabled = false;
            }

            if (this.ZoomLevel > MinZoomLevel)
            {
                ZoomOutButton.IsEnabled = true;
            }

            if (this.ZoomLevel < MaxZoomLevel)
            {
                ZoomInButton.IsEnabled = true;
            }

            if (this.ZoomLevel == MaxZoomLevel)
            {
                ZoomInButton.IsEnabled = false;
            }

            #endregion
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Run the tutorial.
        /// </summary>
        public void Run()
        {
            foreach (var Filename in new DirectoryInfo(Directory.GetCurrentDirectory()).
                     EnumerateFiles("PolyfileReader/*.poly", SearchOption.TopDirectoryOnly))
            {
                var a = Polyfiles.Polyfile2ShapeInfo(new StreamReader("PolyfileReader/" + Filename).GetLines().Skip(1), 2, 23);

                var lat_start = a.Latitude_Start;
                var lng_start = a.Longitude_Start;
                var lat_end   = a.Longitude_Start;
                var lng_end   = a.Longitude_End;
                var zoom5     = a.PathAtZoomLevel[5];
            }



            //var _PolyMetaPipe = new PolyReaderMetaPipe(SearchPattern: "PolyfileReader/*.poly",
            //                                           SearchOption:  SearchOption.TopDirectoryOnly);

            //_PolyMetaPipe.SetSource(Directory.GetCurrentDirectory());

            //_PolyMetaPipe.ForEach(s => Console.WriteLine(s));

            foreach (var Filename in new DirectoryInfo(Directory.GetCurrentDirectory()).
                     EnumerateFiles("PolyfileReader/*.poly",
                                    SearchOption.TopDirectoryOnly))
            {
                Console.WriteLine("Processing... " + Filename);

                var Shapes = new Dictionary <UInt32, Tuple <List <GeoCoordinate>, Dictionary <UInt32, Tuple <List <Tuple <UInt64, UInt64> >, StringBuilder> > > >();

                UInt32        Integer       = 1;
                UInt32        ShapeNumber   = 1;
                GeoCoordinate GeoCoordinate = null;

                var min_lat = Double.MaxValue;
                var min_lng = Double.MaxValue;
                var max_lat = Double.MinValue;
                var max_lng = Double.MinValue;

                foreach (var line in new StreamReader("PolyfileReader/" + Filename).GetLines().Skip(1))
                {
                    if (UInt32.TryParse(line, out Integer))
                    {
                        ShapeNumber = Integer;
                        Shapes.Add(ShapeNumber, new Tuple <List <GeoCoordinate>, Dictionary <UInt32, Tuple <List <Tuple <UInt64, UInt64> >, StringBuilder> > >(
                                       new List <GeoCoordinate>(),
                                       new Dictionary <UInt32, Tuple <List <Tuple <UInt64, UInt64> >, StringBuilder> >()));
                    }

                    else if (line == "END")
                    {
                        continue;
                    }

                    else if (GeoCoordinate.TryParseString(line, out GeoCoordinate))
                    {
                        // Polyfiles store lng lat!!!
                        Shapes[ShapeNumber].Item1.Add(new GeoCoordinate(GeoCoordinate.Longitude, GeoCoordinate.Latitude));

                        if (min_lat > GeoCoordinate.Longitude)
                        {
                            min_lat = GeoCoordinate.Longitude;
                        }

                        if (min_lng > GeoCoordinate.Latitude)
                        {
                            min_lng = GeoCoordinate.Latitude;
                        }

                        if (max_lat < GeoCoordinate.Longitude)
                        {
                            max_lat = GeoCoordinate.Longitude;
                        }

                        if (max_lng < GeoCoordinate.Latitude)
                        {
                            max_lng = GeoCoordinate.Latitude;
                        }
                    }
                }


                var Output1 = new StreamWriter("PolyfileReader/" + Filename.Name.Replace(".poly", ".data"));
                var Array   = new StringBuilder();

                var Output2  = new StreamWriter("PolyfileReader/" + Filename.Name.Replace(".poly", ".geo"));
                var Language = new StringBuilder();

                Shapes.ForEach((shape) =>
                {
                    Array.AppendLine(shape.Key.ToString());
                    shape.Value.Item1.ForEach(c =>
                    {
                        Array.AppendLine("\t\t\t{ " + c.Latitude.ToString("00.000000").Replace(",", ".") + ", " + c.Longitude.ToString("00.000000").Replace(",", ".") + " },");
                    });
                });

                Output1.WriteLine(Array.ToString());
                Output1.Flush();
                Output1.Close();


                var diff_lat = Math.Abs(min_lat - max_lat);
                var diff_lng = Math.Abs(min_lng - max_lng);

                var min_resolution = 2U;
                var max_resolution = 23U;

                Output2.WriteLine("From:       " + max_lat.ToString("00.000000").Replace(",", ".") + ", " + min_lng.ToString("00.000000").Replace(",", "."));
                Output2.WriteLine("To:         " + min_lat.ToString("00.000000").Replace(",", ".") + ", " + max_lng.ToString("00.000000").Replace(",", "."));
                Output2.WriteLine("Diff:       " + diff_lat.ToString("00.000000").Replace(",", ".") + ", " + diff_lng.ToString("00.000000").Replace(",", "."));
                Output2.WriteLine("Resolution: " + min_resolution + " -> " + max_resolution);

                Shapes.ForEach((shape) =>
                {
                    for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
                    {
                        shape.Value.Item2.Add(resolution, new Tuple <List <Tuple <UInt64, UInt64> >, StringBuilder>(new List <Tuple <UInt64, UInt64> >(), new StringBuilder()));

                        shape.Value.Item1.ForEach(coor =>
                        {
                            var XY = GeoCalculations.WorldCoordinates_2_Screen(coor, resolution);

                            //if (XY.Item1 < min_x) min_x = XY.Item1;
                            //if (XY.Item2 < min_y) min_y = XY.Item2;

                            shape.Value.Item2[resolution].Item1.Add(XY);
                        });

                        //var Char = "M ";

                        //shape.Value.Item2[resolution].Item1.ForEach(XY =>
                        //{
                        //    shape.Value.Item2[resolution].Item2.Append(Char + (XY.Item1 - min_x) + " " + (XY.Item2 - min_y) + " ");
                        //    if (Char == "L ") Char = "";
                        //    if (Char == "M ") Char = "L ";
                        //});

                        //shape.Value.Item2[resolution].Item2.Append(" Z ");
                    }
                });

                var min_x = 0UL;
                var min_y = 0UL;

                for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
                {
                    min_x = UInt64.MaxValue;
                    min_y = UInt64.MaxValue;

                    Shapes.ForEach((shape) =>
                    {
                        shape.Value.Item2[resolution].Item1.ForEach(XY =>
                        {
                            if (XY.Item1 < min_x)
                            {
                                min_x = XY.Item1;
                            }
                            if (XY.Item2 < min_y)
                            {
                                min_y = XY.Item2;
                            }
                        });
                    });

                    Shapes.ForEach((shape) =>
                    {
                        var Char = "M ";

                        shape.Value.Item2[resolution].Item1.ForEach(XY =>
                        {
                            shape.Value.Item2[resolution].Item2.Append(Char + (XY.Item1 - min_x) + " " + (XY.Item2 - min_y) + " ");
                            if (Char == "L ")
                            {
                                Char = "";
                            }
                            if (Char == "M ")
                            {
                                Char = "L ";
                            }
                        });

                        shape.Value.Item2[resolution].Item2.Append("Z ");
                    });
                }


                var ShapeLanguage = String.Empty;

                for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
                {
                    ShapeLanguage = "\"";
                    Shapes.ForEach((shape) => ShapeLanguage += shape.Value.Item2[resolution].Item2.ToString().Trim() + " ");
                    Output2.WriteLine(ShapeLanguage.TrimEnd() + "\",");
                }


                //var Points = (from coor
                //              in Coordinates.Skip(1)
                //              select GeoCalculations.WorldCoordinates_2_Screen(coor, 7)).ToList();

                //var min_x = (from p in Points select p.Item1).Min();
                //var min_y = (from p in Points select p.Item2).Min();


                //var FirstPoint = new Tuple<uint, uint>((Points.First().Item1 - min_x), (Points.First().Item2 - min_y));
                //Language.Append("M " + FirstPoint.Item1 + " " + FirstPoint.Item2 + " L ");
                //Points.Skip(1).ForEach(p => { Language.Append((p.Item1 - min_x) + " " + (p.Item2 - min_y) + " "); });
                //Language.AppendLine("z");

                //Output2.WriteLine(Language.ToString());
                Output2.Flush();
                Output2.Close();
            }
        }
        /// <summary>
        /// Calculate contours from given incumbent and parent incumbent locations
        /// </summary>
        /// <param name="sourceContour">portal contours</param>
        /// <returns>contours data</returns>
        private static string GetContourPoints(PortalContour sourceContour)
        {
            lock (portalContourLock)
            {
                Location stationLocation            = new Location(sourceContour.Latitude, sourceContour.Longitude);
                Distance sameChannelKeyHoleDistance = new Distance(80, DistanceUnit.KM); // 80 km (outer keyhole)
                Distance sameChannelDistance        = new Distance(8, DistanceUnit.KM);  // 8 km (inner keyhole)
                Location parentLocation             = new Location(sourceContour.ParentLatitude, sourceContour.ParentLongitude);

                var stationToParentTxBearing = GeoCalculations.CalculateBearing(stationLocation, parentLocation);

                // keyhole calculations
                var keyHoleArcStarting = stationToParentTxBearing - 30;
                var keyHoleArcEnding   = stationToParentTxBearing + 30;

                if (keyHoleArcStarting > 360)
                {
                    keyHoleArcStarting = keyHoleArcStarting - 360;
                }

                if (keyHoleArcEnding > 360)
                {
                    keyHoleArcEnding = keyHoleArcEnding - 360;
                }

                if (keyHoleArcStarting < 0)
                {
                    keyHoleArcStarting = keyHoleArcStarting + 360;
                }

                if (keyHoleArcEnding < 0)
                {
                    keyHoleArcEnding = keyHoleArcEnding + 360;
                }

                List <Location> contourPoints = CalculateRadialContour(stationLocation, sameChannelDistance);
                List <Location> keyHolePoints = CalculateRadialContour(stationLocation, sameChannelKeyHoleDistance);

                if (keyHoleArcStarting < keyHoleArcEnding)
                {
                    for (int i = (int)keyHoleArcStarting; i < (int)keyHoleArcEnding; i++)
                    {
                        contourPoints[i] = keyHolePoints[i];
                    }
                }
                else
                {
                    for (int i = (int)keyHoleArcStarting; i <= 360; i++)
                    {
                        contourPoints[i] = keyHolePoints[i];
                    }
                    for (int i = (int)0; i <= (int)keyHoleArcEnding; i++)
                    {
                        contourPoints[i] = keyHolePoints[i];
                    }
                }

                StringBuilder contourBuilder = new StringBuilder();
                foreach (Location point in contourPoints)
                {
                    contourBuilder.Append(point.Latitude);
                    contourBuilder.Append(" ");
                    contourBuilder.Append(point.Longitude);
                    contourBuilder.Append(" ");
                }

                return(contourBuilder.ToString().Trim());
            }
        }