/// <summary> /// Extracts all the currently selected datasets (including blue marble). /// </summary> internal void CmdTakeSnapshot() { string szGeoTiff = null; List<ExportEntry> aExportList = new List<ExportEntry>(); // Gather info first foreach (LayerBuilder oBuilder in this.AllLayers) { if (oBuilder.Visible) { RenderableObject oRObj = oBuilder.GetLayer(); if (oRObj != null) { RenderableObject.ExportInfo oExportInfo = new RenderableObject.ExportInfo(); oRObj.InitExportInfo(MainForm.WorldWindowSingleton.DrawArgs, oExportInfo); if (oExportInfo.iPixelsX > 0 && oExportInfo.iPixelsY > 0) aExportList.Add(new ExportEntry(oBuilder, oRObj, oExportInfo)); } } } if (aExportList.Count == 0) { Program.ShowMessageBox( "There are no visible layers to export.", "Create GeoTIFF Snapshot", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1, MessageBoxIcon.Warning); return; } // Reverse the list to do render order right aExportList.Reverse(); if (DownloadsInProgress) { Program.ShowMessageBox( "It is not possible to create a snapshot while Dapple is downloading tiles for visible data layers.\nPlease wait for tile downloading to complete and try again.", "Create GeoTIFF Snapshot", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1, MessageBoxIcon.Warning); return; } WorldWind.Camera.MomentumCamera camera = MainForm.WorldWindowSingleton.DrawArgs.WorldCamera as WorldWind.Camera.MomentumCamera; if (camera.Tilt.Degrees > 5.0) { Program.ShowMessageBox( "It is not possible to create a snapshot of a tilted view.\nPlease reset the tilt using the navigation buttons and try again.", "Create GeoTIFF Snapshot", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1, MessageBoxIcon.Warning); return; } try { ExportView oExportDialog = null; if (MainForm.MontajInterface != null) { try { oExportDialog = new ExportView(Path.Combine(MainForm.UserPath, MainApplication.Settings.ConfigPath), MainForm.MontajInterface.BaseDirectory()); } catch (System.Runtime.Remoting.RemotingException) { oExportDialog = new ExportView(Path.Combine(MainForm.UserPath, MainApplication.Settings.ConfigPath)); } } else { oExportDialog = new ExportView(Path.Combine(MainForm.UserPath, MainApplication.Settings.ConfigPath)); } if (oExportDialog.ShowDialog(this) == DialogResult.OK) { String szFilename = Path.ChangeExtension(oExportDialog.FullFileName, ".tif"); // --- Delete all the files that OM generates, so we don't get invalid projections --- if (System.IO.File.Exists(szFilename)) System.IO.File.Delete(szFilename); if (System.IO.File.Exists(System.IO.Path.ChangeExtension(szFilename, ".ipj"))) System.IO.File.Delete(System.IO.Path.ChangeExtension(szFilename, ".ipj")); if (System.IO.File.Exists(System.IO.Path.ChangeExtension(szFilename, ".gi"))) System.IO.File.Delete(System.IO.Path.ChangeExtension(szFilename, ".gi")); if (System.IO.File.Exists(System.IO.Path.ChangeExtension(szFilename, ".tif.xml"))) System.IO.File.Delete(System.IO.Path.ChangeExtension(szFilename, ".tif.xml")); Cursor = Cursors.WaitCursor; // Stop the camera camera.SetPosition(camera.Latitude.Degrees, camera.Longitude.Degrees, camera.Heading.Degrees, camera.Altitude, camera.Tilt.Degrees); // Determine output parameters GeographicBoundingBox oViewedArea = GeographicBoundingBox.FromQuad(MainForm.WorldWindowSingleton.CurrentAreaOfInterest); int iExportPixelsX, iExportPixelsY; // Minimize the estimated extents to what is available double dMinX = double.MaxValue; double dMaxX = double.MinValue; double dMinY = double.MaxValue; double dMaxY = double.MinValue; foreach (ExportEntry oExportEntry in aExportList) { dMaxY = Math.Max(dMaxY, oExportEntry.Info.dMaxLat); dMinY = Math.Min(dMinY, oExportEntry.Info.dMinLat); dMaxX = Math.Max(dMaxX, oExportEntry.Info.dMaxLon); dMinX = Math.Min(dMinX, oExportEntry.Info.dMinLon); } GeographicBoundingBox oExtractArea = new GeographicBoundingBox(dMaxY, dMinY, dMinX, dMaxX); oViewedArea.East = Math.Min(oViewedArea.East, oExtractArea.East); oViewedArea.North = Math.Min(oViewedArea.North, oExtractArea.North); oViewedArea.West = Math.Max(oViewedArea.West, oExtractArea.West); oViewedArea.South = Math.Max(oViewedArea.South, oExtractArea.South); // Determine the maximum resolution based on the highest res in layers double dPixelsPerDegree = -1; foreach (ExportEntry oExportEntry in aExportList) { double dXRes = (double)oExportEntry.Info.iPixelsX / (oExportEntry.Info.dMaxLon - oExportEntry.Info.dMinLon); double dYRes = (double)oExportEntry.Info.iPixelsY / (oExportEntry.Info.dMaxLat - oExportEntry.Info.dMinLat); dPixelsPerDegree = Math.Max(dPixelsPerDegree, Math.Max(dXRes, dYRes)); } double dMaxPixelsPerDegree = Math.Sqrt((5120 * 2560) / (oViewedArea.Latitude * oViewedArea.Longitude)); if (dPixelsPerDegree > dMaxPixelsPerDegree) dPixelsPerDegree = dMaxPixelsPerDegree; iExportPixelsX = (int)(oViewedArea.Longitude * dPixelsPerDegree); iExportPixelsY = (int)(oViewedArea.Latitude * dPixelsPerDegree); // Make geotiff metadata file to use for georeferencing images szGeoTiff = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); using (StreamWriter sw = new StreamWriter(szGeoTiff, false)) { sw.WriteLine("Geotiff_Information:"); sw.WriteLine("Version: 1"); sw.WriteLine("Key_Revision: 1.0"); sw.WriteLine("Tagged_Information:"); sw.WriteLine("ModelTiepointTag (2,3):"); sw.WriteLine("0 0 0"); sw.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} {1} {2}", oViewedArea.West, oViewedArea.North, 0)); sw.WriteLine("ModelPixelScaleTag (1,3):"); sw.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} {1} {2}", (oViewedArea.East - oViewedArea.West) / (double)iExportPixelsX, (oViewedArea.North - oViewedArea.South) / (double)iExportPixelsY, 0)); sw.WriteLine("End_Of_Tags."); sw.WriteLine("Keyed_Information:"); sw.WriteLine("GTModelTypeGeoKey (Short,1): ModelTypeGeographic"); sw.WriteLine("GTRasterTypeGeoKey (Short,1): RasterPixelIsArea"); sw.WriteLine("GeogAngularUnitsGeoKey (Short,1): Angular_Degree"); sw.WriteLine("GeographicTypeGeoKey (Short,1): GCS_WGS_84"); sw.WriteLine("End_Of_Keys."); sw.WriteLine("End_Of_Geotiff."); } // Export image(s) try { using (Bitmap oExportedImage = new Bitmap(iExportPixelsX, iExportPixelsY)) { using (Graphics oEIGraphics = Graphics.FromImage(oExportedImage)) { oEIGraphics.FillRectangle(Brushes.White, new Rectangle(0, 0, iExportPixelsX, iExportPixelsY)); foreach (ExportEntry oExportEntry in aExportList) { // Clip layer export to viewed area if (oExportEntry.Info.dMinLon < oViewedArea.West) oExportEntry.Info.dMinLon = oViewedArea.West; if (oExportEntry.Info.dMaxLon > oViewedArea.East) oExportEntry.Info.dMaxLon = oViewedArea.East; if (oExportEntry.Info.dMinLat < oViewedArea.South) oExportEntry.Info.dMinLat = oViewedArea.South; if (oExportEntry.Info.dMaxLat > oViewedArea.North) oExportEntry.Info.dMaxLat = oViewedArea.North; // Re-scale pixels oExportEntry.Info.iPixelsX = (int)((oExportEntry.Info.dMaxLon - oExportEntry.Info.dMinLon) * dPixelsPerDegree); oExportEntry.Info.iPixelsY = (int)((oExportEntry.Info.dMaxLat - oExportEntry.Info.dMinLat) * dPixelsPerDegree); // Cancel if the layer doesn't intersect the viewed area if (oExportEntry.Info.iPixelsX < 0 || oExportEntry.Info.iPixelsY < 0) continue; try { using (Bitmap oLayerImage = new Bitmap(oExportEntry.Info.iPixelsX, oExportEntry.Info.iPixelsY)) { int iOffsetX, iOffsetY; int iWidth, iHeight; using (oExportEntry.Info.gr = Graphics.FromImage(oLayerImage)) oExportEntry.RO.ExportProcess(MainForm.WorldWindowSingleton.DrawArgs, oExportEntry.Info); iOffsetX = (int)Math.Round((oExportEntry.Info.dMinLon - oViewedArea.West) * (double)iExportPixelsX / (oViewedArea.East - oViewedArea.West)); iOffsetY = (int)Math.Round((oViewedArea.North - oExportEntry.Info.dMaxLat) * (double)iExportPixelsY / (oViewedArea.North - oViewedArea.South)); iWidth = oExportEntry.Info.iPixelsX; iHeight = oExportEntry.Info.iPixelsY; ImageAttributes imgAtt = new ImageAttributes(); float[][] fMat = { new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f, (float)oExportEntry.Container.Opacity/255.0f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f} }; ColorMatrix clrMatrix = new ColorMatrix(fMat); imgAtt.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); oEIGraphics.DrawImage(oLayerImage, new Rectangle(iOffsetX, iOffsetY, iWidth, iHeight), 0, 0, oExportEntry.Info.iPixelsX, oExportEntry.Info.iPixelsY, GraphicsUnit.Pixel, imgAtt); } } catch (System.ArgumentException) { String szLayers = String.Empty; foreach (LayerBuilder oBuilder in this.AllLayers) { szLayers += "\"" + oBuilder.Title + "\"" + ", "; } throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Error creating layer image for snapshot. Width[{0}] Height[{1}] Bounds[{2}] Layers[{3}]", oExportEntry.Info.iPixelsX, oExportEntry.Info.iPixelsY, oViewedArea.ToString(), szLayers)); } } } SaveGeoImage(oExportedImage, szFilename, szGeoTiff); } } catch (System.ArgumentException) { String szLayers = String.Empty; foreach (LayerBuilder oBuilder in this.AllLayers) { szLayers += "\"" + oBuilder.Title + "\"" + ", "; } throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "Error creating layer image for snapshot. Width[{0}] Height[{1}] Bounds[{2}] Layers[{3}]", iExportPixelsX, iExportPixelsY, oViewedArea.ToString(), szLayers)); } Program.ShowMessageBox( "GeoTIFF snapshot created.", "Create GeoTIFF Snapshot", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1, MessageBoxIcon.Information); } } finally { if (szGeoTiff != null && File.Exists(szGeoTiff)) File.Delete(szGeoTiff); Cursor = Cursors.Default; } }
internal bool exportToGeoTiff(String szFilename) { if (!GeographicBoundingBox.FromQuad(MainForm.WorldWindowSingleton.CurrentAreaOfInterest).Intersects(this.Extents)) return false; String szTempMetaFilename = String.Empty; String szTempImageFile = String.Empty; szFilename = Path.ChangeExtension(szFilename, ".tif"); RenderableObject oRObj = GetLayer(); RenderableObject.ExportInfo oExportInfo = new RenderableObject.ExportInfo(); oRObj.InitExportInfo(MainForm.WorldWindowSingleton.DrawArgs, oExportInfo); if (!(oExportInfo.iPixelsX > 0 && oExportInfo.iPixelsY > 0)) return false; // Stop the camera //camera.SetPosition(camera.Latitude.Degrees, camera.Longitude.Degrees, camera.Heading.Degrees, camera.Altitude, camera.Tilt.Degrees); // Minimize the estimated extents to what is available GeographicBoundingBox oViewedArea = GeographicBoundingBox.FromQuad(MainForm.WorldWindowSingleton.CurrentAreaOfInterest); oViewedArea.East = Math.Min(oViewedArea.East, oExportInfo.dMaxLon); oViewedArea.North = Math.Min(oViewedArea.North, oExportInfo.dMaxLat); oViewedArea.West = Math.Max(oViewedArea.West, oExportInfo.dMinLon); oViewedArea.South = Math.Max(oViewedArea.South, oExportInfo.dMinLat); //Calculate the image dimensions int iImageWidth = (int)(oExportInfo.iPixelsX * (oViewedArea.East - oViewedArea.West) / (oExportInfo.dMaxLon - oExportInfo.dMinLon)); int iImageHeight = (int)(oExportInfo.iPixelsY * (oViewedArea.North - oViewedArea.South) / (oExportInfo.dMaxLat - oExportInfo.dMinLat)); if (iImageWidth < 0 || iImageHeight < 0) return false; try { // Export image using (System.Drawing.Bitmap oExportedImage = new System.Drawing.Bitmap(iImageWidth, iImageHeight)) { using (System.Drawing.Graphics oEIGraphics = System.Drawing.Graphics.FromImage(oExportedImage)) { oExportInfo.dMaxLat = oViewedArea.North; oExportInfo.dMaxLon = oViewedArea.East; oExportInfo.dMinLat = oViewedArea.South; oExportInfo.dMinLon = oViewedArea.West; oExportInfo.gr = oEIGraphics; oExportInfo.iPixelsX = iImageWidth; oExportInfo.iPixelsY = iImageHeight; if (MainForm.Client == Dapple.Extract.Options.Client.ClientType.ArcMAP) { oEIGraphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(254, 254, 254)), new System.Drawing.Rectangle(0, 0, iImageWidth, iImageHeight)); } oRObj.ExportProcess(MainForm.WorldWindowSingleton.DrawArgs, oExportInfo); } szTempMetaFilename = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); using (StreamWriter sw = new StreamWriter(szTempMetaFilename, false)) { sw.WriteLine("Geotiff_Information:"); sw.WriteLine("Version: 1"); sw.WriteLine("Key_Revision: 1.0"); sw.WriteLine("Tagged_Information:"); sw.WriteLine("ModelTiepointTag (2,3):"); sw.WriteLine("0 0 0"); sw.WriteLine(oViewedArea.West.ToString(CultureInfo.InvariantCulture) + " " + oViewedArea.North.ToString(CultureInfo.InvariantCulture) + " 0"); sw.WriteLine("ModelPixelScaleTag (1,3):"); sw.WriteLine(((oViewedArea.East - oViewedArea.West) / (double)iImageWidth).ToString(CultureInfo.InvariantCulture) + " " + ((oViewedArea.North - oViewedArea.South) / (double)iImageHeight).ToString(CultureInfo.InvariantCulture) + " 0"); sw.WriteLine("End_Of_Tags."); sw.WriteLine("Keyed_Information:"); sw.WriteLine("GTModelTypeGeoKey (Short,1): ModelTypeGeographic"); sw.WriteLine("GTRasterTypeGeoKey (Short,1): RasterPixelIsArea"); sw.WriteLine("GeogAngularUnitsGeoKey (Short,1): Angular_Degree"); sw.WriteLine("GeographicTypeGeoKey (Short,1): GCS_WGS_84"); sw.WriteLine("End_Of_Keys."); sw.WriteLine("End_Of_Geotiff."); } szTempImageFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); oExportedImage.Save(szTempImageFile, System.Drawing.Imaging.ImageFormat.Tiff); ProcessStartInfo psi = new ProcessStartInfo(Path.GetDirectoryName(Application.ExecutablePath) + @"\System\geotifcp.exe"); psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.Arguments = "-g \"" + szTempMetaFilename + "\" \"" + szTempImageFile + "\" \"" + szFilename + "\""; using (Process p = Process.Start(psi)) p.WaitForExit(); if (File.Exists(szFilename + ".gi")) File.Delete(szFilename + ".gi"); } } catch (ArgumentException ex) { throw new ArgumentException( String.Format(CultureInfo.InvariantCulture, "An error occurred extracting data layer [{0}]: Viewed Area={1}, Extract area={2}, Extract image size={3}x{4}", this.ToString(), oViewedArea.ToString(), GeographicBoundingBox.FromQuad(MainForm.WorldWindowSingleton.CurrentAreaOfInterest), iImageWidth, iImageHeight), ex); } finally { if (File.Exists(szTempMetaFilename)) File.Delete(szTempMetaFilename); if (File.Exists(szTempImageFile)) File.Delete(szTempImageFile); } return true; }
internal ExportEntry(LayerBuilder container, RenderableObject ro, RenderableObject.ExportInfo expInfo) { Container = container; RO = ro; Info = expInfo; }