/// <summary> /// <param name="locations">A 2D map of locations on the surface of earth. </param> /// </summary> public void FillElevationData(ref LatLonAlt[,] locations) { CultureInfo ci = new CultureInfo("en-US"); List<string> loc = new List<string>(); for (int J = 0; J < locations.GetLength(0); J++) { for (int I = 0; I < locations.GetLength(1); I++) { loc.Add(String.Format(ci, "{0:0.0000},{1:0.0000}", locations[I, J].Latitude, locations[I, J].Longitude)); } } var url = String.Format("http://maps.googleapis.com/maps/api/elevation/xml?sensor=false&locations={0}", loc.Aggregate((i, j) => i + "|" + j)); Console.WriteLine("Fetching elevation data from maps.googleapis.com..."); XmlDocument elevationData = new XmlDocument(); elevationData.Load(url); XmlNodeList xmlNodeList = elevationData.SelectNodes("/ElevationResponse/result/elevation"); var di = 0; // A local counter int x = 0; // the I-index of the matrix int y = 0; // the J-index of the matrix. foreach (XmlNode xmlNode in xmlNodeList) { // Update locations directly as we're spinning through all XML nodes. locations[x, y].Altitude = double.Parse(xmlNode.InnerText, ci.NumberFormat); di++; x = di % locations.GetLength(0); if (x == 0) y++; } }
static void Main(string[] args) { try { // Set the Culture Info for the entire main thread. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); // Using the "Command Line Parser Library" from CodePlex // The MIT License (MIT) // Copyright (c) 2005 - 2012 Giacomo Stelluti Scala var options = new Options(); ICommandLineParser parser = new CommandLineParser(); /// Example /// elevation --dms-latitude 61:53:37.20 --dms-longitude 9:51:43.92 --num-cells-I 10 --num-cells-J 10 --distance-ew 2000.0 --distance-ns 2000.0 --output rondane.stl if (parser.ParseArguments(args, options)) { // consume Options type properties var lat = options.dmsLatitude; var lon = options.dmsLongitude; var ni = options.NI; var nj = options.NJ; var distSN = options.distNS; var distEW = options.distEW; // Generate a surface, i.e. a map of LatLonAlt types surrounding the initial // central location given by the user. var surface = new Surface(new LatLonAlt(lat, lon), distSN, distEW); var locations = new LatLonAlt[ni, nj]; surface.GenerateSurface(ref locations); // Fetch elevation data from Google var service = new GoogleElevationService(); service.FillElevationData(ref locations); // Generate a matrix of vertices using cartesian coordinates with // the point of interest in the center (0,0) var vertices = GenerateVerticesMatrix(ref locations, ni, nj, distEW, distSN); // Write the map to an STL output file var fileName = options.Output; //var vertices = Vertex.ToVertex(ref locations); var stl = new Stereolithography(vertices); // vertices); stl.Write(fileName); Console.WriteLine(String.Format("Output written to {0}", fileName)); } } catch (Exception e) { Console.WriteLine("{0} Exception Error", e); } }
/// <summary> /// Calculates the end-point from a given source at a given range (meters) and bearing (degrees). /// This methods uses simple geometry equations to calculate the end-point. /// </summary> /// <param name="source">Point of origin</param> /// <param name="range">Range in meters</param> /// <param name="bearing">Bearing in degrees</param> /// <returns>End-point from the source given the desired range and bearing.</returns> /// public static LatLonAlt CalculateDerivedPosition(LatLonAlt source, double distance, double bearing) { double latA = source.Latitude * DegreesToRadians; double lonA = source.Longitude * DegreesToRadians; double angularDistance = distance / EarthRadius; double trueCourse = bearing * DegreesToRadians; double lat = Math.Asin(Math.Sin(latA) * Math.Cos(angularDistance) + Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse)); double dlon = Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA), Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat)); double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2.0)) - Math.PI; return(new LatLonAlt(lat * RadiansToDegrees, lon * RadiansToDegrees, source.Altitude)); }
/// <summary> /// Calculates the end-point from a given source at a given range (meters) and bearing (degrees). /// This methods uses simple geometry equations to calculate the end-point. /// </summary> /// <param name="source">Point of origin</param> /// <param name="range">Range in meters</param> /// <param name="bearing">Bearing in degrees</param> /// <returns>End-point from the source given the desired range and bearing.</returns> /// public static LatLonAlt CalculateDerivedPosition(LatLonAlt source, double distance, double bearing) { double latA = source.Latitude * DegreesToRadians; double lonA = source.Longitude * DegreesToRadians; double angularDistance = distance / EarthRadius; double trueCourse = bearing * DegreesToRadians; double lat = Math.Asin(Math.Sin(latA) * Math.Cos(angularDistance) + Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse)); double dlon = Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA), Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat)); double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2.0)) - Math.PI; return new LatLonAlt(lat * RadiansToDegrees, lon * RadiansToDegrees, source.Altitude); }
/// <summary> /// Generates a cartesian mesh by inserting relative X and Y coordinates based on the given distance /// and Z (elevation) based on a locations map. /// </summary> /// <param name="locations">Location data containing elevation information</param> /// <param name="ni">Number of horizontal (X) grid cells</param> /// <param name="nj">Number of vertical (Y) grid cells</param> /// <param name="distEW">Total horizontal distance</param> /// <param name="distSN">Total vertical distance</param> /// <returns></returns> private static Vertex[,] GenerateVerticesMatrix(ref LatLonAlt[,] locations, int ni, int nj, double distEW, double distSN) { var x0 = -distEW / 2F; var y0 = -distSN / 2F; var y = y0; double dx = distEW / (double)ni; double dy = distSN / (double)nj; var vertices = new Vertex[ni, nj]; for (var j = 0; j < nj; j++) { var x = x0; for (var i = 0; i < ni; i++) { vertices[i, j] = new Vertex(x, y, locations[i, j].Altitude); x += dx; } y += dy; } return vertices; }
public static Vertex[,] ToVertex(ref LatLonAlt[,] pos) { var vertex = new Vertex[pos.GetLength(0), pos.GetLength(1)]; for (var j = 0; j < pos.GetLength(1); j++) { for (var i = 0; i < pos.GetLength(1); i++) { vertex[i, j] = ToVertex(pos[i, j]); } } return vertex; }
public static Vertex ToVertex(LatLonAlt pos) { var vertex = new Vertex(pos.Latitude, pos.Longitude, pos.Altitude); return vertex; }
public static Vertex ToVertex(LatLonAlt pos) { var vertex = new Vertex(pos.Latitude, pos.Longitude, pos.Altitude); return(vertex); }
/// <summary> /// Constructor /// </summary> /// <param name="center">The center of the map</param> /// <param name="distanceNS">Length of the map from South to North (in meters)</param> /// <param name="distanceEW">Length of the map from East to West (in meters)</param> /// <param name="ni">Number of grid cells in I - direction (EW)</param> /// <param name="nj">Number of grid cells in J - direction (NS)</param> /// <author>Thomas F. Hagelien</author> public Surface(LatLonAlt center, double distanceNS, double distanceEW) { Center = center; DistanceNS = distanceNS; DistanceEW = distanceEW; }
/// <summary> /// Constructor using default settings (10x10 grid, 100m bearing) /// </summary> /// <param name="center">The center of the map</param> public Surface(LatLonAlt center) { Center = center; DistanceEW = 100.0; DistanceNS = 100.0; }
public void GenerateSurface(ref LatLonAlt [,] locations) { var west = Geometry.CalculateDerivedPosition(Center, DistanceNS / 2.0, 180.0); var southWest = Geometry.CalculateDerivedPosition(west, DistanceEW / 2.0, 240.0); var ni = locations.GetLength(0); var nj = locations.GetLength(1); double dNS = DistanceNS / (double)ni; double dEW = DistanceEW / (double)nj; // Fill in the geographics from southWest up to northEast. var position = southWest; for (int J = 0; J < nj; ++J) { position = Geometry.CalculateDerivedPosition(position, dEW * (double)J, 90.0); locations[0, J] = position; for (int I = 1; I < ni; I++) { locations[I, J] = Geometry.CalculateDerivedPosition(position, dNS * (double)I, 0.0); } } }