/// <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))); }
/// <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; }
/// <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); }
/// <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))); }
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(); }
/// <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; }
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)); }
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; }
/// <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)); }
/// <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)); }
/// <inheritdoc /> public Vector3 Project(GeoCoordinate coordinate, double height) { var point = GeoUtils.ToMapCoordinate(_worldZeroPoint, coordinate); return new Vector3(point.x, (float)height, point.y); }
/// <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; }
/// <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); }
/// <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); }