예제 #1
0
        /// <summary> Creates bounding box as rectangle. </summary>
        /// <param name="center">Center point.</param>
        /// <param name="width">Width in meters.</param>
        /// <param name="height">Heigh in meters.</param>
        public static BoundingBox Create(GeoCoordinate center, double width, double height)
        {
            // Bounding box surrounding the point at given coordinates,
            // assuming local approximation of Earth surface as a sphere
            // of radius given by WGS84
            var lat = MathUtils.Deg2Rad(center.Latitude);
            var lon = MathUtils.Deg2Rad(center.Longitude);

            // Radius of Earth at given latitude
            var radius = GeoUtils.WGS84EarthRadius(lat);
            // Radius of the parallel at given latitude
            var pradius = radius*Math.Cos(lat);

            var dWidth = width/(2*radius);
            var dHeight = height/(2*pradius);

            var latMin = lat - dWidth;
            var latMax = lat + dWidth;
            var lonMin = lon - dHeight;
            var lonMax = lon + dHeight;

            return new BoundingBox(
                new GeoCoordinate(MathUtils.Rad2Deg(latMin), MathUtils.Rad2Deg(lonMin)),
                new GeoCoordinate(MathUtils.Rad2Deg(latMax), MathUtils.Rad2Deg(lonMax)));
        }
예제 #2
0
        /// <summary> Adapts element data received from utymap. </summary>
        public void AdaptElement(long id, string[] tags, int tagCount, double[] vertices, int vertexCount, 
            string[] styles, int styleCount)
        {
            var geometry = new GeoCoordinate[vertexCount / 2];
            for (int i = 0; i < vertexCount / 2; i += 2)
                geometry[i / 2] = new GeoCoordinate(vertices[i + 1], vertices[i]);

            Element element = new Element(id, geometry, ReadDict(tags), ReadDict(styles));
            _observer.OnNext(new Union<Element, Mesh>(element));
        }
        /// <inheritdoc />
        public float GetElevation(GeoCoordinate coordinate)
        {
            int latDec = (int) coordinate.Latitude;
            int lonDec = (int) coordinate.Longitude;

            float secondsLat = (float) (coordinate.Latitude - latDec)*3600;
            float secondsLon = (float) (coordinate.Longitude - lonDec)*3600;

            LoadTile(latDec, lonDec);

            // load tile
            //X coresponds to x/y values,
            //everything easter/norhter (< S) is rounded to X.
            //
            //  y   ^
            //  3   |       |   S
            //      +-------+-------
            //  0   |   X   |
            //      +-------+-------->
            // (sec)    0        3   x  (lon)

            //both values are [0; totalPx - 1] (totalPx reserved for interpolating)
            int y = (int) (secondsLat/_secondsPerPx);
            int x = (int) (secondsLon/_secondsPerPx);

            //get norther and easter points
            var height2 = ReadPx(y, x);
            var height0 = ReadPx(y + 1, x);
            var height3 = ReadPx(y, x + 1);
            var height1 = ReadPx(y + 1, x + 1);

            //ratio where X lays
            float dy = (secondsLat%_secondsPerPx)/_secondsPerPx;
            float dx = (secondsLon%_secondsPerPx)/_secondsPerPx;

            // Bilinear interpolation
            // h0------------h1
            // |
            // |--dx-- .
            // |       |
            // |      dy
            // |       |
            // h2------------h3

            return height0*dy*(1 - dx) +
                   height1*dy*(dx) +
                   height2*(1 - dy)*(1 - dx) +
                   height3*(1 - dy)*dx;
        }
예제 #4
0
        /// <inheritdoc />
        public Vector3 Project(GeoCoordinate coordinate, double height)
        {
            // the x-axis goes through long,lat (0,0), so longitude 0 meets the equator;
            // the y-axis goes through (0,90);
            // and the z-axis goes through the pol
            // x = R * cos(lat) * cos(lon)
            // y = R * cos(lat) * sin(lon)
            // z = R * sin(lat)

            double radius = _radius + height;
            double latRad = (Math.PI / 180) * coordinate.Latitude;
            double lonRad = (Math.PI / 180) * coordinate.Longitude;
            float x = (float)(radius * Math.Cos(latRad) * Math.Cos(lonRad));
            float y = (float)(radius * Math.Cos(latRad) * Math.Sin(lonRad));
            float z = (float)(radius * Math.Sin(latRad));

            return new Vector3(x, z, y);
        }
예제 #5
0
 /// <summary> Download SRTM data for given coordinate. </summary>
 /// <param name="coordinate">Coordinate.</param>
 /// <returns>Stream.</returns>
 public IObservable<byte[]> Download(GeoCoordinate coordinate)
 {
     var prefix = GetFileNamePrefix(coordinate);
     // TODO do not read file every time
     foreach (var line in _fileSystemService.ReadText(_schemaPath).Split('\n'))
     {
         if (line.StartsWith(prefix))
         {
             var parameters = line.Split(' ');
             // NOTE some of files miss extension point between name and .hgt.zip
             var url = String.Format("{0}/{1}/{2}", _server, ContinentMap[int.Parse(parameters[1])],
                 parameters[1].EndsWith("zip") ? "" : parameters[0] + ".hgt.zip");
             _trace.Warn(TraceCategory, String.Format("Downloading SRTM data from {0}", url));
             return ObservableWWW.GetAndGetBytes(url);
         }
     }
     return Observable.Throw<byte[]>(new ArgumentException(
         String.Format("Cannot find {0} on {1}", prefix, _schemaPath)));
 }
예제 #6
0
        public static CompositionRoot GetCompositionRoot(GeoCoordinate worldZeroPoint,
            Action<IContainer, IConfigSection> action)
        {
            // create default container which should not be exposed outside
            // to avoid Service Locator pattern.
            IContainer container = new Container();

            // create default application configuration
            var config = ConfigBuilder.GetDefault()
                .SetStringIndex("Index/")
                .SetSpatialIndex("Index/")
                .Build();

            // initialize services
            return new CompositionRoot(container, config)
                .RegisterAction((c, _) => c.Register(Component.For<ITrace>().Use<ConsoleTrace>()))
                .RegisterAction((c, _) => c.Register(Component.For<IPathResolver>().Use<TestPathResolver>()))
                .RegisterAction((c, _) => c.Register(Component.For<Stylesheet>().Use<Stylesheet>(DefaultMapCss)))
                .RegisterAction((c, _) => c.Register(Component.For<IProjection>().Use<CartesianProjection>(worldZeroPoint)))
                .RegisterAction(action)
                .Setup();
        }
예제 #7
0
        /// <summary>
        ///     Gets start geocoordinate using desired method: direct latitude/longitude or
        ///     via reverse geocoding request for given place name.
        /// </summary>
        private GeoCoordinate GetWorldZeroPoint()
        {
            var coordinate = new GeoCoordinate(StartLatitude, StartLongitude);
            if (!String.IsNullOrEmpty(PlaceName))
            {
                // NOTE this will freeze UI thread as we're making web request and should wait for its result
                // TODO improve it
                var place = AppManager.GetService<IGeocoder>().Search(PlaceName)
                    .Wait();

                if (place != null)
                {
                    StartLatitude = place.Coordinate.Latitude;
                    StartLongitude = place.Coordinate.Longitude;
                    // NOTE this prevents name resolution to be done more than once
                    PlaceName = null;
                    return place.Coordinate;
                }

                AppManager.GetService<ITrace>()
                    .Warn("init", "Cannot resolve '{0}', will use default latitude/longitude", PlaceName);
            }
            return coordinate;
        }
예제 #8
0
 private string GetFileNamePrefix(GeoCoordinate coordinate)
 {
     return String.Format("{0}{1:00}{2}{3:000}",
         coordinate.Latitude > 0 ? 'N' : 'S', Math.Abs((int)coordinate.Latitude),
         coordinate.Longitude > 0 ? 'E' : 'W', Math.Abs((int)coordinate.Longitude));
 }
예제 #9
0
 public static CompositionRoot GetCompositionRoot(GeoCoordinate worldZeroPoint)
 {
     return GetCompositionRoot(worldZeroPoint, (container, section) => { });
 }
        private void CheckBoundingBox(BoundingBox bbox, Action<GeoCoordinate> action)
        {
            var minLat = (int) bbox.MinPoint.Latitude;
            var minLon = (int) bbox.MinPoint.Longitude;

            var maxLat = (int) bbox.MaxPoint.Latitude;
            var maxLon = (int) bbox.MaxPoint.Longitude;

            var latDiff = maxLat - minLat;
            var lonDiff = maxLon - minLon;
            var minPoint = bbox.MinPoint;
            for (int j = 0; j <= latDiff; j++)
                for (int i = 0; i <= lonDiff; i++)
                {
                    var coordinate = new GeoCoordinate(minPoint.Latitude + j, minPoint.Longitude + i);
                    if (!HasElevation(coordinate))
                        action(coordinate);
                }
        }
 /// <inheritdoc />
 public void SetNullPoint(GeoCoordinate coordinate)
 {
     _relativeNullPoint = coordinate;
 }
예제 #12
0
        /// <summary> Extends current bounding box by given coordinate. </summary>
        public void Extend(GeoCoordinate coordinate)
        {
            MinPoint = new GeoCoordinate(
                Math.Min(MinPoint.Latitude, coordinate.Latitude),
                Math.Min(MinPoint.Longitude, coordinate.Longitude));

            MaxPoint = new GeoCoordinate(
                Math.Max(MaxPoint.Latitude, coordinate.Latitude),
                Math.Max(MaxPoint.Longitude, coordinate.Longitude));
        }
예제 #13
0
 /// <summary> Creates bounding box from given min and max points. </summary>
 /// <param name="minPoint">Point with minimal latitude and longitude</param>
 /// <param name="maxPoint">Point with maximum latitude and longitude</param>
 public BoundingBox(GeoCoordinate minPoint, GeoCoordinate maxPoint)
 {
     MinPoint = minPoint;
     MaxPoint = maxPoint;
 }
        private Rect GetTileRect(GeoCoordinate coordinate)
        {
            var quadKey = GeoUtils.CreateQuadKey(coordinate, LevelOfDetails);
            var boundingBox = GeoUtils.QuadKeyToBoundingBox(quadKey);
            var minPoint = GeoUtils.ToMapCoordinate(_worldZeroPoint, boundingBox.MinPoint);
            var maxPoint = GeoUtils.ToMapCoordinate(_worldZeroPoint, boundingBox.MaxPoint);

            return new Rect(minPoint.x, maxPoint.y, maxPoint.x - minPoint.x, maxPoint.y - minPoint.y);
        }
        private IObservable<Unit> Download(GeoCoordinate coordinate)
        {
            _trace.Info(TraceCategory, "downloading data for {0}", coordinate.ToString());
            return _downloader.Download(coordinate).SelectMany(bytes =>
                {
                    _trace.Info(TraceCategory, "downloaded {0} bytes", bytes.Length.ToString());
                    _hgtData = CompressionUtils.Unzip(bytes).Single().Value;
                    InitData((int) coordinate.Latitude, (int) coordinate.Longitude);
                    // store data to disk
                    var path = GetFilePath(_srtmLat, _srtmLon);
                    _trace.Info(TraceCategory, "storing as {0}", path);
                    using (var stream = _fileSystemService.WriteStream(path))
                        stream.Write(_hgtData, 0, _hgtData.Length);

                    return Observable.Return<Unit>(Unit.Default);
                });
        }
 private bool HasElevation(GeoCoordinate coordinate)
 {
     var latitude = (int) coordinate.Latitude;
     var longitude = (int) coordinate.Longitude;
     return (_srtmLat == (latitude) && _srtmLon == (longitude)) ||
            _fileSystemService.Exists(GetFilePath(latitude, longitude));
 }
예제 #17
0
 /// <inheritdoc />
 public Vector3 Project(GeoCoordinate coordinate, double height)
 {
     var point = GeoUtils.ToMapCoordinate(_worldZeroPoint, coordinate);
     return new Vector3(point.x, (float)height, point.y);
 }
예제 #18
0
 /// <summary> Creates instance of <see cref="CartesianProjection"/>. </summary>
 /// <param name="worldZeroPoint"> GeoCoordinate for (0, 0) point. </param>
 public CartesianProjection(GeoCoordinate worldZeroPoint)
 {
     _worldZeroPoint = worldZeroPoint;
 }
 /// <inheritdoc />
 public float GetElevation(GeoCoordinate coordinate)
 {
     return 0;
 }
예제 #20
0
 /// <summary> Creates bounding box as square. </summary>
 /// <param name="center">Center.</param>
 /// <param name="sideInMeters">Length of the bounding box.</param>
 public static BoundingBox Create(GeoCoordinate center, float sideInMeters)
 {
     return Create(center, sideInMeters, sideInMeters);
 }
예제 #21
0
 /// <summary> Checks whether given coordinate inside bounding box. </summary>
 public bool Contains(GeoCoordinate coordinate)
 {
     return coordinate.Latitude > MinPoint.Latitude && coordinate.Longitude > MinPoint.Longitude &&
            coordinate.Latitude < MaxPoint.Latitude && coordinate.Longitude < MaxPoint.Longitude;
 }
 private GeoCoordinate MovePosition(GeoCoordinate currentPosition, Vector2 direction, float distance)
 {
     var point = GeoUtils.ToMapCoordinate(_worldZeroPoint, currentPosition);
     var newPoint = point + direction*distance;
     return GeoUtils.ToGeoCoordinate(_worldZeroPoint, newPoint);
 }