private void GenerateTMCFile(AFS2GridSquare afs2GridSquare, string stitchedTilesDirectory, string afsGridSquareDirectory, StitchedImage firstStitchedImageAeroFile) { // Create directories for Geoconvert output if they do not exist. // Better to do this here in case anyone wants to run Geoconvert manually var geoConvertRawDirectory = String.Format("{0}-geoconvert-raw\\", firstStitchedImageAeroFile.ZoomLevel); var geoConvertTTCDirectory = String.Format("{0}-geoconvert-ttc\\", firstStitchedImageAeroFile.ZoomLevel); var geoConvertRawPath = afsGridSquareDirectory + geoConvertRawDirectory; var geoConvertTTCPath = afsGridSquareDirectory + geoConvertTTCDirectory; if (!Directory.Exists(geoConvertRawPath)) { Directory.CreateDirectory(geoConvertRawPath); } if (!Directory.Exists(geoConvertTTCPath)) { Directory.CreateDirectory(geoConvertTTCPath); } var tmcFile = new TMCFile(); tmcFile.AlwaysOverwrite = true; tmcFile.DoHeightmaps = false; tmcFile.FolderDestinationRaw = geoConvertRawPath; tmcFile.FolderDestinationTTC = geoConvertTTCPath; tmcFile.FolderSourceFiles = stitchedTilesDirectory; tmcFile.WriteImagesWithMask = AeroSceneryManager.Instance.Settings.GeoConvertWriteImagesWithMask.Value; tmcFile.WriteRawFiles = AeroSceneryManager.Instance.Settings.GeoConvertWriteRawFiles.Value; tmcFile.WriteTTCFiles = true; // All TMC regions will have the same lat / lon max and min // Create a template Region here to base other regions off TMCRegion tmcRegionTemplate = new TMCRegion(); // Really NW Corner tmcRegionTemplate.LatMin = afs2GridSquare.NorthLatitude; tmcRegionTemplate.LonMin = afs2GridSquare.WestLongitude; // Realy SE Corner tmcRegionTemplate.LatMax = afs2GridSquare.SouthLatitude; tmcRegionTemplate.LonMax = afs2GridSquare.EastLongitude; tmcFile.Regions = this.GenerateTMCFileRegions(tmcRegionTemplate); var tmcFileStr = tmcFile.ToString(); var filenameParts = firstStitchedImageAeroFile.FileName.Split('_'); var tmcFilename = String.Format("{0}_{1}_{2}", filenameParts[0], filenameParts[1], filenameParts[2]); string path = String.Format("{0}{1}.tmc", stitchedTilesDirectory, tmcFilename); File.WriteAllText(path, tmcFileStr); }
private void DoSecondDirectoryRename(List <GridSquare> gridSquares) { var afsGrid = new AFS2Grid(); foreach (GridSquare gridSquare in gridSquares) { if (gridSquare.Fixed == 0) { var afs2GridSquare = AFS2GridSquare.FromGridSquare(gridSquare); var squareCenter = afs2GridSquare.GetCenter(); var newGridSquare = afsGrid.GetGridSquareAtLatLon(squareCenter.Lat, squareCenter.Lng, gridSquare.Level); var gridSquareDirectory = AeroSceneryManager.Instance.Settings.WorkingDirectory + "_" + gridSquare.Name; var renamedGridSquareDirectory = AeroSceneryManager.Instance.Settings.WorkingDirectory + newGridSquare.Name; try { if (Directory.Exists(gridSquareDirectory)) { if (gridSquareDirectory != renamedGridSquareDirectory) { // VB version seems to be more reliable than Directory.Move Microsoft.VisualBasic.FileIO.FileSystem.MoveDirectory(gridSquareDirectory, renamedGridSquareDirectory); Thread.Sleep(500); } } // Only update the database once we've renamed the dir gridSquare.Name = newGridSquare.Name; gridSquare.Fixed = 1; dataRepository.UpdateGridSquare(gridSquare); } catch (Exception ex) { failedCount++; this.HandleDirectoryMoveError(ex, gridSquareDirectory, renamedGridSquareDirectory); } } } }
public static AFS2GridSquare FromGridSquare(GridSquare gridSquare) { var afs2GridSquare = new AFS2GridSquare(); var pointLatLon1 = new PointLatLng(gridSquare.NorthLatitude, gridSquare.WestLongitude); var pointLatLon2 = new PointLatLng(gridSquare.NorthLatitude, gridSquare.EastLongitude); var pointLatLon3 = new PointLatLng(gridSquare.SouthLatitude, gridSquare.EastLongitude); var pointLatLon4 = new PointLatLng(gridSquare.SouthLatitude, gridSquare.WestLongitude); afs2GridSquare.Coordinates.Add(pointLatLon1); afs2GridSquare.Coordinates.Add(pointLatLon2); afs2GridSquare.Coordinates.Add(pointLatLon3); afs2GridSquare.Coordinates.Add(pointLatLon4); afs2GridSquare.Name = gridSquare.Name; afs2GridSquare.Level = gridSquare.Level; return(afs2GridSquare); }
public async Task GenerateAFSFilesAsync(AFS2GridSquare afs2GridSquare, string stitchedTilesDirectory, string afsGridSquareDirectory, IProgress <AFSFileGeneratorProgress> progress) { await Task.Run(() => { var afsFileGeneratorProgress = new AFSFileGeneratorProgress(); StitchedImage firstStitchedImageAeroFile = null; // The number of stiched tiles should always be pretty manageable so we can get a list of filenames if (Directory.Exists(stitchedTilesDirectory)) { string[] stitchedImagesAeroFiles = Directory.GetFiles(stitchedTilesDirectory, "*.aero"); int i = 0; foreach (string aeroFilename in stitchedImagesAeroFiles) { try { StitchedImage stitchedImageAeroFile; using (StreamReader reader = new StreamReader(aeroFilename)) { stitchedImageAeroFile = (StitchedImage)xmlSerializer.Deserialize(reader); reader.Close(); } if (i == 0) { firstStitchedImageAeroFile = stitchedImageAeroFile; } double stepsPerPixelX = Math.Abs((stitchedImageAeroFile.WestLongitude - stitchedImageAeroFile.EastLongitude) / stitchedImageAeroFile.Width); double stepsPerPixelY = -Math.Abs((stitchedImageAeroFile.NorthLatitude - stitchedImageAeroFile.SouthLatitude) / stitchedImageAeroFile.Height); var aidFile = new AIDFile(); aidFile.ImageFile = stitchedImageAeroFile.FileName + "." + stitchedImageAeroFile.ImageExtension; aidFile.FlipVertical = false; aidFile.StepsPerPixelX = stepsPerPixelX; aidFile.StepsPerPixelY = stepsPerPixelY; aidFile.X = stitchedImageAeroFile.WestLongitude; aidFile.Y = stitchedImageAeroFile.NorthLatitude; var aidFileStr = aidFile.ToString(); string path = stitchedTilesDirectory + stitchedImageAeroFile.FileName + ".aid"; log.InfoFormat("Writing AID file {0}", path); File.WriteAllText(path, aidFileStr); } catch (Exception ex) { } i++; } if (firstStitchedImageAeroFile != null) { this.GenerateTMCFile(afs2GridSquare, stitchedTilesDirectory, afsGridSquareDirectory, firstStitchedImageAeroFile); } else { var messageBox = new CustomMessageBox("No stiched images found for this grid square and this image detail (zoom) level.\nRun the 'Download Image Tiles' and 'Stitch Image Tiles' actions first.", "AeroScenery", MessageBoxIcon.Error); messageBox.ShowDialog(); } } }); }
/// <summary> /// Returns the coordinates and unique name of a AFS2 grid square given latitude, longitude and /// the AFS2 grid level. /// /// Thanks go to this thread /// https://www.aerofly.com/community/forum/index.php?thread/12550-image-tile-coordinates/&pageNo=1 /// and users: qwery42, Rodeo, vogel69 /// /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <param name="level"></param> /// <returns></returns> public AFS2GridSquare GetGridSquareAtLatLon(double lat, double lon, int level) { var afs2GridSquare = new AFS2GridSquare(); var worldGridConstant = 2.3311223704144; var lonLatX = (lon * Math.PI) / 180; var lonLatY = (lat * Math.PI) / 180; var x0 = lonLatX / Math.PI; var y0 = lonLatY / Math.PI; var y1 = Math.Tan(worldGridConstant * y0) / worldGridConstant; var x1 = 0.5 + 0.5 * x0; var y2 = 0.5 + 0.5 * y1; var outX = Math.Pow(2, level) * x1; var outY = Math.Pow(2, level) * y2; // -------------- // NW var nwCornerWorldGridX = Math.Floor(outX); var nwCornerWorldGridY = Math.Ceiling(outY); var nwX0 = nwCornerWorldGridX / Math.Pow(2, level); var nwY0 = nwCornerWorldGridY / Math.Pow(2, level); var nwX1 = 2 * (nwX0 - 0.5); var nwY1 = 2 * (nwY0 - 0.5); var nwY2 = Math.Atan(worldGridConstant * nwY1) / worldGridConstant; var nwX2 = nwX1 * Math.PI; var nwY3 = nwY2 * Math.PI; var westLongitude = (nwX2 * 180) / Math.PI; var northLatitude = (nwY3 * 180) / Math.PI; //-------------- // SE var seCornerWorldGridY = Math.Floor(outY); var seCornerWorldGridX = 0; if (Math.Ceiling(outX) == nwCornerWorldGridX) { seCornerWorldGridX = (int)Math.Ceiling(outX + 0.75); } else { seCornerWorldGridX = (int)Math.Ceiling(outX); } var seX0 = seCornerWorldGridX / Math.Pow(2, level); var seY0 = seCornerWorldGridY / Math.Pow(2, level); var seX1 = 2 * (seX0 - 0.5); var seY1 = 2 * (seY0 - 0.5); var seY2 = Math.Atan(worldGridConstant * seY1) / worldGridConstant; var seX2 = seX1 * Math.PI; var seY3 = seY2 * Math.PI; var eastLongitude = (seX2 * 180) / Math.PI; var southLatitude = (seY3 * 180) / Math.PI; // ------------- var pointLatLon1 = new PointLatLng(northLatitude, westLongitude); var pointLatLon2 = new PointLatLng(northLatitude, eastLongitude); var pointLatLon3 = new PointLatLng(southLatitude, eastLongitude); var pointLatLon4 = new PointLatLng(southLatitude, westLongitude); afs2GridSquare.Coordinates.Add(pointLatLon1); afs2GridSquare.Coordinates.Add(pointLatLon2); afs2GridSquare.Coordinates.Add(pointLatLon3); afs2GridSquare.Coordinates.Add(pointLatLon4); // Aerofly names grid squares as follows: // map_level_ hex((65536 / 2 ^ level) * grid square x) _ hex((65536 / 2 ^ level) * grid square y) int xInt = (int)((65536 / Math.Pow(2, level)) * nwCornerWorldGridX); int yInt = (int)((65536 / Math.Pow(2, level)) * nwCornerWorldGridY); var xHex = xInt.ToString("x4"); var yHex = yInt.ToString("x4"); afs2GridSquare.Name = String.Format("map_{0}_{1}_{2}", level.ToString("d2"), xHex, yHex); afs2GridSquare.Level = level; return(afs2GridSquare); }