Guest User

gdal_retile.py translated into C# beta

a guest
Sep 24th, 2012
560
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 54.12 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Windows.Media.Imaging;
  8. using System.Text;
  9. using OSGeo.GDAL;
  10. using OSGeo.OGR;
  11. using OSGeo.OSR;
  12. using Driver = OSGeo.GDAL.Driver;
  13.  
  14. namespace RasterLoader
  15. {
  16.     public class GdalRetile
  17.     {
  18.         private const double MetersPerInch = 0.0254;
  19.         private const double DPI = 96;
  20.  
  21.         private string _format = string.Empty;
  22.         private List<string> _createOptions = new List<string>();
  23.         private DataType _bandType;
  24.         private bool _verbose;
  25.         private string _targetDir = string.Empty;
  26.         private int _tileWidth = -1;
  27.         private int _tileHeight = -1;
  28.         private string _resamplingMethodString = string.Empty;
  29.         private ResampleAlg _resamplingMethod;
  30.         private int _levels = -1;
  31.         private SpatialReference _sourceSRS;
  32.         private bool _pyramidOnly;
  33.         private string _tileIndexName = string.Empty;
  34.         private string _tileIndexFieldName = string.Empty;
  35.         private string _tileIndexDriverTyp = string.Empty;
  36.         private string _csvFileName = string.Empty;
  37.         private string _csvDelimiter = string.Empty;
  38.         private bool _useDirForEachRow;
  39.         private List<string> _names = new List<string>();
  40.         private Driver _driver;
  41.         private Driver _memDriver;
  42.         private int _lastRowIndex;
  43.         private string _extension;
  44.         private bool _8to32bit;
  45.         private double _scaleFactor;
  46.         private double _rasterSize = -1;
  47.         private double _meters = -1;
  48.  
  49.         public GdalRetile(string[] args)
  50.         {
  51.             Gdal.AllRegister();
  52.  
  53.             InitFields();
  54.  
  55.             if (args.Any())
  56.             {
  57.                 string[] argv = Gdal.GeneralCmdLineProcessor(args, 0);
  58.                 if (!argv.Any())
  59.                     throw new Exception("Command line has no parameters.");
  60.  
  61.                 int i = 1;
  62.                 while (i < argv.Count())
  63.                 {
  64.                     string arg = argv.ElementAt(i);
  65.                     string ext;
  66.                     switch (arg)
  67.                     {
  68.                         case "-of":
  69.                             i++;
  70.                             _format = argv.ElementAt(i);
  71.                             break;
  72.                         case "-ot":
  73.                             i++;
  74.                             _bandType = Gdal.GetDataTypeByName(argv.ElementAt(i));
  75.                             Console.WriteLine(_bandType);
  76.                             if (_bandType == DataType.GDT_Unknown)
  77.                             {
  78.                                 throw new Exception("Unknown GDAL data type: " + argv.ElementAt(i));
  79.                             }
  80.                             break;
  81.                         case "-co":
  82.                             i++;
  83.                             _createOptions.Add(argv.ElementAt(i));
  84.                             break;
  85.                         case "-v":
  86.                             _verbose = true;
  87.                             break;
  88.                         case "-targetDir":
  89.                             i++;
  90.                             _targetDir = argv.ElementAt(i);
  91.                             if (!Directory.Exists(_targetDir))
  92.                             {
  93.                                 throw new Exception("TargetDir " + _targetDir + " does not exist.");
  94.                             }
  95.                             break;
  96.                         case "-ps":
  97.                             i++;
  98.                             _tileWidth = int.Parse(argv.ElementAt(i));
  99.                             i++;
  100.                             _tileHeight = int.Parse(argv.ElementAt(i));
  101.                             break;
  102.                         case "-r":
  103.                             i++;
  104.                             _resamplingMethodString = argv.ElementAt(i);
  105.                             switch (_resamplingMethodString)
  106.                             {
  107.                                 case "near":
  108.                                     _resamplingMethod = ResampleAlg.GRA_NearestNeighbour;
  109.                                     break;
  110.                                 case "bilinear":
  111.                                     _resamplingMethod = ResampleAlg.GRA_Bilinear;
  112.                                     break;
  113.                                 case "cubic":
  114.                                     _resamplingMethod = ResampleAlg.GRA_Cubic;
  115.                                     break;
  116.                                 case "cubicspline":
  117.                                     _resamplingMethod = ResampleAlg.GRA_CubicSpline;
  118.                                     break;
  119.                                 case "lanczos":
  120.                                     _resamplingMethod = (ResampleAlg)4;
  121.                                     break;
  122.                                 default:
  123.                                     throw new Exception("Unknown resampling method: " + _resamplingMethodString);
  124.                             }
  125.                             break;
  126.                         case "-levels":
  127.                             i++;
  128.                             _levels = int.Parse(argv.ElementAt(i));
  129.                             if (_levels < 1)
  130.                             {
  131.                                 throw new Exception("Invalid number of _levels: " + _levels);
  132.                             }
  133.                             break;
  134.                         case "-s_srs":
  135.                             i++;
  136.                             string wkt = string.Empty;
  137.                             if (Osr.GetUserInputAsWKT(argv.ElementAt(i), out wkt) != 0)
  138.                             {
  139.                                 throw new Exception("Invalid -s_srs: " + argv.ElementAt(i));
  140.                             }
  141.                             _sourceSRS = new SpatialReference(wkt); // TODO: check this!
  142.                             break;
  143.                         case "-pyramidOnly":
  144.                             _pyramidOnly = true;
  145.                             break;
  146.                         case "-tileIndex":
  147.                             i++;
  148.                             _tileIndexName = argv.ElementAt(i);
  149.                             ext = Path.GetExtension(_tileIndexName);
  150.                             if (ext.Length == 0)
  151.                             {
  152.                                 _tileIndexName += ".shp";
  153.                             }
  154.                             break;
  155.                         case "-tileIndexField":
  156.                             i++;
  157.                             _tileIndexFieldName = argv.ElementAt(i);
  158.                             break;
  159.                         case "-csv":
  160.                             i++;
  161.                             _csvFileName = argv.ElementAt(i);
  162.                             ext = Path.GetExtension(_csvFileName);
  163.                             if (ext.Length == 0)
  164.                             {
  165.                                 _csvFileName += ".csv";
  166.                             }
  167.                             break;
  168.                         case "-csvDelim":
  169.                             i++;
  170.                             _csvDelimiter = argv.ElementAt(i);
  171.                             break;
  172.                         case "-useDirForEachRow":
  173.                             _useDirForEachRow = true;
  174.                             break;
  175.                         case "-8to32bit":
  176.                             _8to32bit = true;
  177.                             break;
  178.                         default:
  179.                             if (arg.StartsWith("-"))
  180.                             {
  181.                                 Usage();
  182.                                 throw new Exception("Unrecognized command option: " + arg);
  183.                             }
  184.                             _names.Add(arg);
  185.                             break;
  186.                     }
  187.                     i++;
  188.                 }
  189.  
  190.                 if (!_names.Any())
  191.                 {
  192.                     Usage();
  193.                     throw new Exception("No input files selected.");
  194.                 }
  195.  
  196.                 if (_tileWidth <= 0 || _tileHeight <= 0)
  197.                 {
  198.                     Usage();
  199.                     throw new Exception("Invalid tile dimension: " + _tileWidth + "x" + _tileHeight + ".");
  200.                 }
  201.  
  202.                 if (string.IsNullOrEmpty(_targetDir) || string.IsNullOrWhiteSpace(_targetDir))
  203.                 {
  204.                     Usage();
  205.                     throw new Exception("Missing directory for tiles [-targetDir].");
  206.                 }
  207.  
  208.                 if (_8to32bit)
  209.                 {
  210.                     foreach (string name in _names)
  211.                     {
  212.                         //TiffConverter.Convert8To32Bit(name);
  213.                     }
  214.                 }
  215.  
  216.                 // create level 0 directory if needed
  217.                 if (_useDirForEachRow && _pyramidOnly == false)
  218.                 {
  219.                     string levelDir = Path.Combine(_targetDir, 0.ToString());
  220.                     if (!Directory.Exists(levelDir))
  221.                         Directory.CreateDirectory(levelDir);
  222.                 }
  223.  
  224.                 // prepare dirs for the pyramid
  225.                 if (_levels > 0)
  226.                 {
  227.                     int startIndex = 1;
  228.                     for (int levelIndex = startIndex; levelIndex < _levels + 1; levelIndex++)
  229.                     {
  230.                         string levelDir = Path.Combine(_targetDir, levelIndex.ToString());
  231.                         if (Directory.Exists(levelDir))
  232.                         {
  233.                             continue;
  234.                         }
  235.                         try
  236.                         {
  237.                             Directory.CreateDirectory(levelDir);
  238.                         }
  239.                         catch
  240.                         {
  241.                             throw new Exception("Cannot create level directory: " + levelDir);
  242.                         }
  243.                         if (_verbose)
  244.                         {
  245.                             Debug.WriteLine("Created level directory: " + levelDir);
  246.                         }
  247.                     }
  248.                 }
  249.  
  250.                 _driver = Gdal.GetDriverByName(_format);
  251.                 if (_driver == null)
  252.                 {
  253.                     UsageFormat();
  254.                     throw new Exception("Format _driver " + _format + " not found, pick a supported _driver.");
  255.                 }
  256.  
  257.                 //_extension = _driver.GetMetadataItem(GdalConst.GDAL_DMD_EXTENSION, GdalConst.GDAL_DMD_LONGNAME); // TODO: check this
  258.                 string[] driverMD = _driver.GetMetadata(null); // null for the default domain
  259.                 _extension = _driver.GetMetadataItem("DMD_EXTENSION", null);
  260.  
  261.                 if (driverMD.Contains("DCAP_CREATE"))
  262.                 {
  263.                     _memDriver = Gdal.GetDriverByName("MEM");
  264.                 }
  265.  
  266.                 DataSource tileIndexDS = GetTileIndexFromFiles(_names, _tileIndexDriverTyp);
  267.                 if (tileIndexDS == null)
  268.                 {
  269.                     throw new Exception("Error building tile index.");
  270.                 }
  271.  
  272.                 MosaicInfo mInfo = new MosaicInfo(_names[0], tileIndexDS);
  273.                 TileInfo ti = new TileInfo(mInfo.XSize, mInfo.YSize, _tileWidth, _tileHeight);
  274.  
  275.                 if (_sourceSRS == null && mInfo.Projection.Length > 0)
  276.                 {
  277.                     // TODO: check this
  278.                     string wkt = string.Empty;
  279.                     Osr.GetUserInputAsWKT(mInfo.Projection, out wkt);
  280.                     _sourceSRS = new SpatialReference(wkt);
  281.  
  282.                     if (_sourceSRS.SetFromUserInput(mInfo.Projection) != 0)
  283.                     {
  284.                         throw new Exception("Invalid projection: " + mInfo.Projection);
  285.                     }
  286.                 }
  287.  
  288.                 if (_verbose)
  289.                 {
  290.                     ti.Report();
  291.                 }
  292.  
  293.                 DataSource dsCreatedTileIndex;
  294.                 if (!_pyramidOnly)
  295.                 {
  296.                     dsCreatedTileIndex = TileImage(mInfo, ti);
  297.                     tileIndexDS.Dispose();
  298.                 }
  299.                 else
  300.                 {
  301.                     dsCreatedTileIndex = tileIndexDS;
  302.                 }
  303.  
  304.                 if (_levels > 0)
  305.                 {
  306.                     BuildPyramid(mInfo, dsCreatedTileIndex, _tileWidth, _tileHeight);
  307.                 }
  308.             }
  309.             else
  310.             {
  311.                 throw new Exception("Command line has no parameters.");
  312.             }
  313.         }
  314.  
  315.         private void InitFields()
  316.         {
  317.             _verbose = false;
  318.             _createOptions = new List<string>();
  319.             _names = new List<string>();
  320.             _tileWidth = 256;
  321.             _tileHeight = 256;
  322.             _format = "GTiff";
  323.             _bandType = DataType.GDT_Unknown;
  324.             _driver = null;
  325.             _extension = null;
  326.             _memDriver = null;
  327.             _tileIndexFieldName = "location";
  328.             _tileIndexName = null;
  329.             _tileIndexDriverTyp = "Memory";
  330.             _csvDelimiter = ";";
  331.             _csvFileName = null;
  332.             _sourceSRS = null;
  333.             _targetDir = null;
  334.             _resamplingMethod = ResampleAlg.GRA_NearestNeighbour;
  335.             _levels = 0;
  336.             _pyramidOnly = false;
  337.             _lastRowIndex = -1;
  338.             _useDirForEachRow = false;
  339.         }
  340.  
  341.         private double GetScale(int meters, int pixels)
  342.         {
  343.             return meters / pixels / MetersPerInch * DPI;
  344.         }
  345.  
  346.         private void BuildPyramid(MosaicInfo mInfo, DataSource createdTileIndexDS, int tileWidth, int tileHeight)
  347.         {
  348.             DataSource inputDS = createdTileIndexDS;
  349.  
  350.             for (int level = 1; level < _levels + 1; level++)
  351.             {
  352.                 _lastRowIndex = -1;
  353.                 MosaicInfo levelMosaicInfo = new MosaicInfo(mInfo.FileName, inputDS);
  354.  
  355.                 if (level == 1)
  356.                 {
  357.                     double scale = GetScale((int) Math.Round(_meters), (int) Math.Round(_rasterSize));
  358.                     double power = Math.Log(scale, 2);
  359.                     if (power - (double) ((int) power) > 0d)
  360.                     {
  361.                         power = Math.Ceiling(power);
  362.                     }
  363.  
  364.                     _scaleFactor = Math.Pow(2, power) / scale;
  365.                 }
  366.                 else
  367.                 {
  368.                     _scaleFactor = 2;
  369.                 }
  370.                 TileInfo levelOutputTileInfo = new TileInfo(levelMosaicInfo.XSize / _scaleFactor, levelMosaicInfo.YSize / _scaleFactor, tileWidth, tileHeight);
  371.                 inputDS = BuildPyramidLevel(levelMosaicInfo, levelOutputTileInfo, level);
  372.             }
  373.         }
  374.  
  375.         private DataSource BuildPyramidLevel(MosaicInfo levelMosaicInfo, TileInfo levelOutputTileInfo, int level)
  376.         {
  377.             List<int> xRange = Enumerable.Range(1, levelOutputTileInfo.CountTilesX + 1).ToList();
  378.             List<int> yRange = Enumerable.Range(1, levelOutputTileInfo.CountTilesY + 1).ToList();
  379.  
  380.             DataSource ogrds = CreateTileIndex("TileResult_" + level, _tileIndexFieldName, _sourceSRS,
  381.                                                _tileIndexDriverTyp);
  382.  
  383.             foreach (int yIndex in yRange)
  384.             {
  385.                 foreach (int xIndex in xRange)
  386.                 {
  387.                     int offsetY = (yIndex - 1) * levelOutputTileInfo.TileHeight;
  388.                     int offsetX = (xIndex - 1) * levelOutputTileInfo.TileWidth;
  389.  
  390.                     int width, height;
  391.                     if (yIndex == levelOutputTileInfo.CountTilesY)
  392.                     {
  393.                         height = levelOutputTileInfo.LastTileHeight;
  394.                     }
  395.                     else
  396.                     {
  397.                         height = levelOutputTileInfo.TileHeight;
  398.                     }
  399.  
  400.                     if (xIndex == levelOutputTileInfo.CountTilesX)
  401.                     {
  402.                         width = levelOutputTileInfo.LastTileWidth;
  403.                     }
  404.                     else
  405.                     {
  406.                         width = levelOutputTileInfo.TileWidth;
  407.                     }
  408.  
  409.                     string tileName = GetTileName(levelMosaicInfo, levelOutputTileInfo, xIndex, yIndex, level);
  410.                     CreatePyramidTile(levelMosaicInfo, offsetX, offsetY, width, height, tileName, ogrds);
  411.                 }
  412.             }
  413.  
  414.             if (!string.IsNullOrEmpty(_tileIndexName))
  415.             {
  416.                 // TODO: check this
  417.                 string shapeName = GetTargetDir(level) + _tileIndexName;
  418.                 CopyTileIndexToDisk(ogrds, shapeName);
  419.             }
  420.  
  421.             if (!string.IsNullOrEmpty(_csvFileName))
  422.             {
  423.                 string csvName = GetTargetDir(level) + _csvFileName;
  424.                 CopyTileIndexToCSV(ogrds, csvName);
  425.             }
  426.  
  427.             return ogrds;
  428.         }
  429.  
  430.         private void CreatePyramidTile(MosaicInfo levelMosaicInfo, int offsetX, int offsetY, int width, int height, string tileName, DataSource ogrds)
  431.         {
  432.             double sx = levelMosaicInfo.ScaleX * _scaleFactor;
  433.             double sy = levelMosaicInfo.ScaleY * _scaleFactor;
  434.  
  435.             AffineTransformDecorator dec =
  436.                 new AffineTransformDecorator(new[]
  437.                                                  {
  438.                                                      levelMosaicInfo.Ulx + offsetX*sx, sx, 0,
  439.                                                      levelMosaicInfo.Uly + offsetY*sy, 0, sy
  440.                                                  });
  441.  
  442.             Dataset sFh = levelMosaicInfo.GetDataSet((int) Math.Round(dec.Ulx),
  443.                                                      (int) Math.Round((dec.Uly + height*dec.ScaleY)),
  444.                                                      (int) Math.Round((dec.Ulx + width*dec.ScaleX)),
  445.                                                      (int) Math.Round(dec.Uly));
  446.  
  447.             if (sFh == null)
  448.             {
  449.                 return;
  450.             }
  451.  
  452.             if (ogrds != null)
  453.             {
  454.                 var points = dec.PointsFor(width, height);
  455.                 AddFeature(ref ogrds, tileName, points);
  456.             }
  457.  
  458.             DataType bt;
  459.             if (_bandType == DataType.GDT_Unknown)
  460.             {
  461.                 bt = levelMosaicInfo.BandType;
  462.             }
  463.             else
  464.             {
  465.                 bt = _bandType;
  466.             }
  467.  
  468.             double[] geotransform = { dec.Ulx, dec.ScaleX, 0, dec.Uly, 0, dec.ScaleY };
  469.             int bands = levelMosaicInfo.Bands;
  470.  
  471.             Dataset tFh;
  472.             if (_memDriver == null)
  473.             {
  474.                 tFh = _driver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
  475.             }
  476.             else
  477.             {
  478.                 tFh = _memDriver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
  479.             }
  480.  
  481.             if (tFh == null)
  482.             {
  483.                 throw new Exception("Creation failed, terminating gdal_tile.");
  484.             }
  485.  
  486.             tFh.SetGeoTransform(geotransform);
  487.             tFh.SetProjection(levelMosaicInfo.Projection);
  488.  
  489.             for (int band = 1; band < bands + 1; band++)
  490.             {
  491.                 Band tBand = tFh.GetRasterBand(band);
  492.                 if (levelMosaicInfo.Ct != null)
  493.                 {
  494.                     tBand.SetRasterColorTable(levelMosaicInfo.Ct);
  495.                 }
  496.                 tBand.SetRasterColorInterpretation(levelMosaicInfo.Ci[band - 1]);
  497.             }
  498.  
  499.             // TODO: check this
  500.             var res = Gdal.ReprojectImage(sFh, tFh, null, null, _resamplingMethod, 0, 0, null, null);
  501.  
  502.             if (res != 0)
  503.             {
  504.                 throw new Exception("Reprojection failed for " + tileName + ", error " + res + ".");
  505.             }
  506.  
  507.             levelMosaicInfo.CloseDataSet(sFh);
  508.  
  509.             if (_memDriver != null)
  510.             {
  511.                 Dataset ttFh = _driver.CreateCopy(tileName, tFh, 0, _createOptions.ToArray(), null, null);
  512.                 ttFh.Dispose();
  513.             }
  514.  
  515.             tFh.Dispose();
  516.         }
  517.  
  518.         private DataSource TileImage(MosaicInfo mInfo, TileInfo ti)
  519.         {
  520.             _lastRowIndex = -1;
  521.             DataSource ogrds = CreateTileIndex("TileResult_0", _tileIndexFieldName, _sourceSRS, _tileIndexDriverTyp);
  522.  
  523.             for (int yIndex = 1; yIndex < ti.CountTilesY + 1; yIndex++)
  524.             {
  525.                 for (int xIndex = 1; xIndex < ti.CountTilesX + 1; xIndex++)
  526.                 {
  527.                     int width, height;
  528.                     int offsetY = (yIndex - 1) * ti.TileHeight;
  529.                     int offsetX = (xIndex - 1) * ti.TileWidth;
  530.                     if (yIndex == ti.CountTilesY)
  531.                     {
  532.                         height = ti.LastTileHeight;
  533.                     }
  534.                     else
  535.                     {
  536.                         height = ti.TileHeight;
  537.                     }
  538.  
  539.                     if (xIndex == ti.CountTilesX)
  540.                     {
  541.                         width = ti.LastTileWidth;
  542.                     }
  543.                     else
  544.                     {
  545.                         width = ti.TileWidth;
  546.                     }
  547.  
  548.                     string tileName = string.Empty;
  549.                     if (_useDirForEachRow)
  550.                     {
  551.                         tileName = GetTileName(mInfo, ti, xIndex, yIndex, 0);
  552.                     }
  553.                     else
  554.                     {
  555.                         tileName = GetTileName(mInfo, ti, xIndex, yIndex);
  556.                     }
  557.  
  558.                     CreateTile(ref mInfo, offsetX, offsetY, width, height, tileName, ref ogrds);
  559.                 }
  560.             }
  561.  
  562.             if (!string.IsNullOrEmpty(_tileIndexName))
  563.             {
  564.                 string shapeName = string.Empty;
  565.                 if (_useDirForEachRow && !_pyramidOnly)
  566.                 {
  567.                     shapeName = GetTargetDir(0) + _tileIndexName;
  568.                 }
  569.                 else
  570.                 {
  571.                     shapeName = GetTargetDir() + _tileIndexName;
  572.                 }
  573.  
  574.                 CopyTileIndexToDisk(ogrds, shapeName);
  575.             }
  576.  
  577.             if (!string.IsNullOrEmpty(_csvFileName))
  578.             {
  579.                 string csvName = string.Empty;
  580.                 if (_useDirForEachRow && !_pyramidOnly)
  581.                 {
  582.                     csvName = GetTargetDir(0) + _csvFileName;
  583.                 }
  584.                 else
  585.                 {
  586.                     csvName = GetTargetDir() + _csvFileName;
  587.                 }
  588.  
  589.                 CopyTileIndexToCSV(ogrds, csvName);
  590.             }
  591.  
  592.             return ogrds;
  593.         }
  594.  
  595.         private void CopyTileIndexToDisk(DataSource ogrds, string fileName)
  596.         {
  597.             DataSource shapeDS = CreateTileIndex(fileName, _tileIndexFieldName, ogrds.GetLayerByIndex(0).GetSpatialRef(),
  598.                                                  "ESRI Shapefile");
  599.             ogrds.GetLayerByIndex(0).ResetReading();
  600.  
  601.             while (true)
  602.             {
  603.                 Feature feature = ogrds.GetLayerByIndex(0).GetNextFeature();
  604.                 if (feature == null)
  605.                 {
  606.                     break;
  607.                 }
  608.  
  609.                 Feature newFeature = feature.Clone();
  610.                 string basename = Path.GetFileName(feature.GetFieldAsString(0));
  611.                 if (_useDirForEachRow)
  612.                 {
  613.                     string fExt = Path.GetExtension(basename);
  614.                     basename = fExt + "/" + basename;
  615.                 }
  616.  
  617.                 newFeature.SetField(0, basename);
  618.                 shapeDS.GetLayerByIndex(0).CreateFeature(newFeature);
  619.             }
  620.  
  621.             CloseTileIndex(shapeDS);
  622.  
  623.             ogrds.Dispose();
  624.         }
  625.  
  626.         private void CopyTileIndexToCSV(DataSource ogrds, string fileName)
  627.         {
  628.             using (File.Open(fileName, FileMode.Create))
  629.             {
  630.             }
  631.  
  632.             ogrds.GetLayerByIndex(0).ResetReading();
  633.  
  634.             while (true)
  635.             {
  636.                 Feature feature = ogrds.GetLayerByIndex(0).GetNextFeature();
  637.                 if (feature == null)
  638.                 {
  639.                     break;
  640.                 }
  641.  
  642.                 string basename = Path.GetFileName(feature.GetFieldAsString(0));
  643.                 if (_useDirForEachRow)
  644.                 {
  645.                     string fExt = Path.GetExtension(basename);
  646.                     basename = fExt + "/" + basename;
  647.                 }
  648.  
  649.                 using (StreamWriter sw = new StreamWriter(fileName, true))
  650.                 {
  651.                     sw.Write(basename);
  652.                     Geometry geom = feature.GetGeometryRef();
  653.                     Envelope coords = new Envelope();
  654.                     geom.GetEnvelope(coords);
  655.  
  656.                     // TODO: check this
  657.                     sw.Write(_csvDelimiter + coords.MinX);
  658.                     sw.Write(_csvDelimiter + coords.MaxX);
  659.                     sw.Write(_csvDelimiter + coords.MinY);
  660.                     sw.Write(_csvDelimiter + coords.MaxY);
  661.                     sw.Write(Environment.NewLine);
  662.                 }
  663.             }
  664.  
  665.             ogrds.Dispose();
  666.         }
  667.  
  668.         private void CloseTileIndex(DataSource ogrDataSource)
  669.         {
  670.             ogrDataSource.Dispose();
  671.         }
  672.  
  673.         private void CreateTile(ref MosaicInfo mInfo, int offsetX, int offsetY, int width, int height, string tileName, ref DataSource ogrds)
  674.         {
  675.             DataType bt;
  676.             if (_bandType == DataType.GDT_Unknown)
  677.             {
  678.                 bt = mInfo.BandType;
  679.             }
  680.             else
  681.             {
  682.                 bt = _bandType;
  683.             }
  684.  
  685.             AffineTransformDecorator dec = new AffineTransformDecorator(new[]
  686.                                                                             {
  687.                                                                                 mInfo.Ulx,
  688.                                                                                 mInfo.ScaleX,
  689.                                                                                 0d,
  690.                                                                                 mInfo.Uly,
  691.                                                                                 0d,
  692.                                                                                 mInfo.ScaleY
  693.                                                                             });
  694.  
  695.             Dataset sFh = mInfo.GetDataSet(
  696.                 (int) Math.Round((dec.Ulx + offsetX*dec.ScaleX)),
  697.                 (int) Math.Round((dec.Uly + offsetY*dec.ScaleY + height*dec.ScaleY)),
  698.                 (int) Math.Round((dec.Ulx + offsetX*dec.ScaleX + width*dec.ScaleX)),
  699.                 (int) Math.Round((dec.Uly + offsetY*dec.ScaleY)));
  700.  
  701.             if (sFh == null)
  702.             {
  703.                 return;
  704.             }
  705.  
  706.             var geotransform = new[]
  707.                                    {
  708.                                        dec.Ulx + offsetX * dec.ScaleX,
  709.                                        dec.ScaleX,
  710.                                        0d,
  711.                                        dec.Uly + offsetY * dec.ScaleY,
  712.                                        0d,
  713.                                        dec.ScaleY
  714.                                    };
  715.  
  716.             if (ogrds != null)
  717.             {
  718.                 AffineTransformDecorator dec2 = new AffineTransformDecorator(geotransform);
  719.                 var points = dec2.PointsFor(width, height);
  720.                 AddFeature(ref ogrds, tileName, points);
  721.             }
  722.  
  723.             int bands = mInfo.Bands;
  724.  
  725.             Dataset tFh;
  726.             if (_memDriver == null)
  727.             {
  728.                 tFh = _driver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
  729.             }
  730.             else
  731.             {
  732.                 tFh = _memDriver.Create(tileName, width, height, bands, bt, _createOptions.ToArray());
  733.             }
  734.  
  735.             if (tFh == null)
  736.             {
  737.                 throw new Exception("Creation failed, terminating gdal_tile.");
  738.             }
  739.  
  740.             tFh.SetGeoTransform(geotransform);
  741.             if (_sourceSRS != null)
  742.             {
  743.                 string wkt = string.Empty;
  744.                 _sourceSRS.ExportToWkt(out wkt);
  745.                 tFh.SetProjection(wkt);
  746.             }
  747.  
  748.             int readX = Math.Min(sFh.RasterXSize, width);
  749.             int readY = Math.Min(sFh.RasterYSize, height);
  750.  
  751.             Band tBand, sBand;
  752.             for (int band = 1; band < bands + 1; band++)
  753.             {
  754.                 sBand = sFh.GetRasterBand(band);
  755.                 tBand = tFh.GetRasterBand(band);
  756.  
  757.                 if (mInfo.Ct != null)
  758.                 {
  759.                     tBand.SetRasterColorTable(mInfo.Ct);
  760.                 }
  761.  
  762.                 // TODO: check this
  763.                 byte[] data = new byte[readX * readY];
  764.                 sBand.ReadRaster(0, 0, readX, readY, data, readX, readY, 0, 0);
  765.                 tBand.WriteRaster(0, 0, readX, readY, data, readX, readY, 0, 0);
  766.             }
  767.  
  768.  
  769.             mInfo.CloseDataSet(sFh);
  770.  
  771.             Dataset ttFh;
  772.             if (_memDriver != null)
  773.             {
  774.                 ttFh = _driver.CreateCopy(tileName, tFh, 0, _createOptions.ToArray(), null, null);
  775.                 ttFh.Dispose();
  776.             }
  777.  
  778.             tFh.Dispose();
  779.             sFh.Dispose();
  780.         }
  781.  
  782.         private string GetTileName(MosaicInfo mInfo, TileInfo ti, int xIndex, int yIndex, int level = -1)
  783.         {
  784.             int max = ti.CountTilesX;
  785.             if (ti.CountTilesY > max)
  786.             {
  787.                 max = ti.CountTilesY;
  788.             }
  789.  
  790.             int countDigits = max.ToString().Length;
  791.             string fileName = Path.GetFileNameWithoutExtension(mInfo.FileName).Replace("@", "");
  792.             string extension = Path.GetExtension(mInfo.FileName).Replace("@", "");
  793.  
  794.             string format = string.Empty;
  795.             if (_useDirForEachRow)
  796.             {
  797.                 //format = Path.Combine(GetTargetDir(level) + yIndex,
  798.                 //                             fileName + "_%0" + countDigits + "i_%0" + countDigits + "i");
  799.                 format = Path.Combine(GetTargetDir(level) + yIndex,
  800.                                              fileName + "_" + yIndex.ToString().PadLeft(countDigits, '0') + "_" + xIndex.ToString().PadLeft(countDigits, '0'));
  801.  
  802.                 // see if there was a switch in the row, if so then create new dir for row
  803.                 if (_lastRowIndex < yIndex)
  804.                 {
  805.                     _lastRowIndex = yIndex;
  806.                     if (!Directory.Exists(GetTargetDir(level) + yIndex))
  807.                     {
  808.                         Directory.CreateDirectory(GetTargetDir(level) + yIndex);
  809.                     }
  810.                 }
  811.             }
  812.             else
  813.             {
  814.                 //format = GetTargetDir(level) + fileName + "_%0" + countDigits + "i_%0" + countDigits + "i";
  815.                 format = GetTargetDir(level) + fileName + "_" + yIndex.ToString().PadLeft(countDigits, '0') + "_" + xIndex.ToString().PadLeft(countDigits, '0');
  816.             }
  817.  
  818.             // check for the extension that should be used
  819.             if (string.IsNullOrEmpty(extension))
  820.             {
  821.                 format += extension;
  822.             }
  823.             else
  824.             {
  825.                 format += "." + _extension;
  826.             }
  827.  
  828.             return format;
  829.         }
  830.  
  831.         private string GetTargetDir(int level = -1)
  832.         {
  833.             string directory = _targetDir;
  834.             if (!directory.EndsWith("\\"))
  835.             {
  836.                 directory = directory + "\\";
  837.             }
  838.             return level == -1 ? directory : (Path.Combine(directory, level.ToString()) + "\\");
  839.         }
  840.  
  841.         private DataSource GetTileIndexFromFiles(IEnumerable<string> inputTiles, string driverType)
  842.         {
  843.             DataSource ogrTileIndexDS = CreateTileIndex("TileIndex", _tileIndexFieldName, null, driverType);
  844.             foreach (string inputTile in inputTiles)
  845.             {
  846.                 Dataset fhInputTile = Gdal.Open(inputTile, Access.GA_ReadOnly);
  847.                 if (fhInputTile == null)
  848.                 {
  849.                     return null;
  850.                 }
  851.  
  852.                 // TODO: check this
  853.                 double[] argout = new double[6];
  854.                 fhInputTile.GetGeoTransform(argout);
  855.                 AffineTransformDecorator dec = new AffineTransformDecorator(argout);
  856.                 List<Point> points = dec.PointsFor(fhInputTile.RasterXSize, fhInputTile.RasterYSize);
  857.  
  858.                 if (_rasterSize == -1 || _meters == -1)
  859.                 {
  860.                     _meters = dec.ScaleX * fhInputTile.RasterXSize;
  861.                     _rasterSize = fhInputTile.RasterXSize;
  862.                 }
  863.  
  864.                 AddFeature(ref ogrTileIndexDS, inputTile, points);
  865.                 fhInputTile.Dispose(); // TODO: check this
  866.             }
  867.  
  868.             if (_verbose)
  869.             {
  870.                 Debug.WriteLine("Finished");
  871.             }
  872.  
  873.             return ogrTileIndexDS;
  874.         }
  875.  
  876.         private void AddFeature(ref DataSource ogrDataSource, string location, List<Point> points)
  877.         {
  878.             Layer ogrLayer = ogrDataSource.GetLayerByIndex(0); // TODO: check this
  879.             Feature ogrFeature = new Feature(ogrLayer.GetLayerDefn());
  880.             if (ogrFeature == null)
  881.             {
  882.                 throw new Exception("Could not vreate the feature.");
  883.             }
  884.  
  885.             ogrFeature.SetField(_tileIndexFieldName, location);
  886.  
  887.             string wkt = string.Format("POLYGON (({0} {1},{2} {3},{4} {5},{6} {7},{8} {9} ))",
  888.                 points.ElementAt(0).X,
  889.                 points.ElementAt(0).Y,
  890.                 points.ElementAt(1).X,
  891.                 points.ElementAt(1).Y,
  892.                 points.ElementAt(2).X,
  893.                 points.ElementAt(2).Y,
  894.                 points.ElementAt(3).X,
  895.                 points.ElementAt(3).Y,
  896.                 points.ElementAt(0).X,
  897.                 points.ElementAt(0).Y);
  898.  
  899.             var ogrGeometry = Ogr.CreateGeometryFromWkt(ref wkt, ogrLayer.GetSpatialRef());
  900.             if (ogrGeometry == null)
  901.             {
  902.                 throw new Exception("Could not create geometry.");
  903.             }
  904.  
  905.             ogrFeature.SetGeometryDirectly(ogrGeometry);
  906.             ogrLayer.CreateFeature(ogrFeature);
  907.             ogrFeature.Dispose(); // TODO: check this
  908.         }
  909.  
  910.         private static DataSource CreateTileIndex(string dsName, string fieldName, SpatialReference srs, string driverName)
  911.         {
  912.             var ogrDriver = Ogr.GetDriverByName(driverName);
  913.             if (ogrDriver == null)
  914.             {
  915.                 throw new Exception("ESRI Shapefile _driver not found.");
  916.             }
  917.  
  918.             DataSource ogrDataSource = ogrDriver.Open(dsName, 1);
  919.             if (ogrDataSource != null)
  920.             {
  921.                 // python:
  922.                 // OGRDataSource.Destroy()
  923.                 ogrDataSource.Dispose(); // TODO: check this
  924.                 ogrDriver.DeleteDataSource(dsName);
  925.             }
  926.  
  927.             ogrDataSource = ogrDriver.CreateDataSource(dsName, new string[] { }); // TODO: check this
  928.             if (ogrDataSource == null)
  929.             {
  930.                 throw new Exception("Could not open datasource " + dsName);
  931.             }
  932.  
  933.             Layer ogrLayer = ogrDataSource.CreateLayer("index", srs, wkbGeometryType.wkbPolygon, new string[] { }); // TODO: check this
  934.             if (ogrLayer == null)
  935.             {
  936.                 throw new Exception("Could not create layer.");
  937.             }
  938.  
  939.             FieldDefn ogrFieldDefn = new FieldDefn(fieldName, FieldType.OFTString);
  940.             if (ogrFieldDefn == null)
  941.             {
  942.                 throw new Exception("Could not create FieldDefn for " + fieldName);
  943.             }
  944.  
  945.             ogrFieldDefn.SetWidth(256);
  946.             if (ogrLayer.CreateField(ogrFieldDefn, 1) != 0) // TODO: check this
  947.             {
  948.                 throw new Exception("Could not create field for " + fieldName);
  949.             }
  950.  
  951.             return ogrDataSource;
  952.         }
  953.  
  954.         private static void Usage()
  955.         {
  956.             Console.WriteLine("Usage: gdal_retile ");
  957.             Console.WriteLine("        [-v] [-co NAME=VALUE]* [-of out_format]");
  958.             Console.WriteLine("        [-ps pixelWidth pixelHeight]");
  959.             Console.WriteLine("        [-ot  {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/");
  960.             Console.WriteLine("               CInt16/CInt32/CFloat32/CFloat64}]");
  961.             Console.WriteLine("        [-tileIndex _tileIndexName [-tileIndexField fieldName]]");
  962.             Console.WriteLine("        [-csv fileName [-csvDelim delimiter]]");
  963.             Console.WriteLine("        [-s_srs srs_def]  [-pyramidOnly] -levels numberoflevels");
  964.             Console.WriteLine("        [-r {near/bilinear/cubic/cubicspline/lanczos}]");
  965.             Console.WriteLine("        [-useDirForEachRow]");
  966.             Console.WriteLine("        [-targetDir tile_directory input_files]");
  967.  
  968.         }
  969.  
  970.         private void UsageFormat()
  971.         {
  972.             Console.WriteLine("Valid formats:");
  973.             int count = Gdal.GetDriverCount();
  974.             for (int i = 0; i < count; i++)
  975.             {
  976.                 _driver = Gdal.GetDriver(i);
  977.                 Console.WriteLine(_driver.ShortName);
  978.             }
  979.         }
  980.  
  981.         // a class providing some usefull methods for affine Transformations
  982.         internal class AffineTransformDecorator
  983.         {
  984.             private double[] _geotransform;
  985.             private double _scaleX, _scaleY, _ulx, _uly;
  986.  
  987.             public double ScaleX
  988.             {
  989.                 get { return _scaleX; }
  990.                 set { _scaleX = value; }
  991.             }
  992.  
  993.             public double ScaleY
  994.             {
  995.                 get { return _scaleY; }
  996.                 set { _scaleY = value; }
  997.             }
  998.  
  999.             public double Ulx
  1000.             {
  1001.                 get { return _ulx; }
  1002.                 set { _ulx = value; }
  1003.             }
  1004.  
  1005.             public double Uly
  1006.             {
  1007.                 get { return _uly; }
  1008.                 set { _uly = value; }
  1009.             }
  1010.  
  1011.             public AffineTransformDecorator(double[] transform)
  1012.             {
  1013.                 _geotransform = transform;
  1014.                 _scaleX = _geotransform[1];
  1015.                 _scaleY = _geotransform[5];
  1016.  
  1017.                 if (_scaleY > 0)
  1018.                     _scaleY *= -1;
  1019.  
  1020.                 _ulx = _geotransform[0];
  1021.                 _uly = _geotransform[3];
  1022.             }
  1023.  
  1024.             public List<Point> PointsFor(int width, int height)
  1025.             {
  1026.                 List<Point> points = new List<Point>();
  1027.                 int w = (int)_scaleX * width;
  1028.                 int h = (int)_scaleY * height;
  1029.  
  1030.                 points.Add(new Point((int) Math.Round(_ulx), (int) Math.Round(_uly)));
  1031.                 points.Add(new Point((int) Math.Round((_ulx + w)), (int) Math.Round(_uly)));
  1032.                 points.Add(new Point((int) Math.Round(_ulx + w), (int) Math.Round(_uly + h)));
  1033.                 points.Add(new Point((int) Math.Round(_ulx), (int) Math.Round(_uly + h)));
  1034.  
  1035.                 return points;
  1036.             }
  1037.         }
  1038.  
  1039.         // a class holding information about a GDAL file or a GDAL fileset
  1040.         internal class MosaicInfo : IDisposable
  1041.         {
  1042.             private Driver _tempDriver;
  1043.             private string _fileName;
  1044.             private DataSetCache _cache;
  1045.             private DataSource _ogrTileIndexDS;
  1046.             private int _bands;
  1047.             private DataType _bandType;
  1048.             private string _projection;
  1049.             private double _scaleX, _scaleY;
  1050.             private ColorTable _ct;
  1051.             private ColorInterp[] _ci;
  1052.             private double _ulx, _uly, _lrx, _lry;
  1053.             private double _xSize, _ySize;
  1054.  
  1055.             public double XSize
  1056.             {
  1057.                 get { return _xSize; }
  1058.                 set { _xSize = value; }
  1059.             }
  1060.  
  1061.             public double YSize
  1062.             {
  1063.                 get { return _ySize; }
  1064.                 set { _ySize = value; }
  1065.             }
  1066.  
  1067.             public double ScaleX
  1068.             {
  1069.                 get { return _scaleX; }
  1070.                 set { _scaleX = value; }
  1071.             }
  1072.  
  1073.             public double ScaleY
  1074.             {
  1075.                 get { return _scaleY; }
  1076.                 set { _scaleY = value; }
  1077.             }
  1078.  
  1079.             public string Projection
  1080.             {
  1081.                 get { return _projection; }
  1082.                 set { _projection = value; }
  1083.             }
  1084.  
  1085.             public string FileName
  1086.             {
  1087.                 get { return _fileName; }
  1088.                 set { _fileName = value; }
  1089.             }
  1090.  
  1091.             public DataType BandType
  1092.             {
  1093.                 get { return _bandType; }
  1094.                 set { _bandType = value; }
  1095.             }
  1096.  
  1097.             public double Ulx
  1098.             {
  1099.                 get { return _ulx; }
  1100.                 set { _ulx = value; }
  1101.             }
  1102.  
  1103.             public double Uly
  1104.             {
  1105.                 get { return _uly; }
  1106.                 set { _uly = value; }
  1107.             }
  1108.  
  1109.             public double Lrx
  1110.             {
  1111.                 get { return _lrx; }
  1112.                 set { _lrx = value; }
  1113.             }
  1114.  
  1115.             public double Lry
  1116.             {
  1117.                 get { return _lry; }
  1118.                 set { _lry = value; }
  1119.             }
  1120.  
  1121.             public int Bands
  1122.             {
  1123.                 get { return _bands; }
  1124.                 set { _bands = value; }
  1125.             }
  1126.  
  1127.             public ColorTable Ct
  1128.             {
  1129.                 get { return _ct; }
  1130.                 set { _ct = value; }
  1131.             }
  1132.  
  1133.             public ColorInterp[] Ci
  1134.             {
  1135.                 get { return _ci; }
  1136.                 set { _ci = value; }
  1137.             }
  1138.  
  1139.             public MosaicInfo(string fileName, DataSource inputDS)
  1140.             {
  1141.                 _tempDriver = Gdal.GetDriverByName("MEM");
  1142.                 _fileName = fileName;
  1143.                 _cache = new DataSetCache();
  1144.                 _ogrTileIndexDS = inputDS;
  1145.  
  1146.                 // TODO: check this
  1147.                 // python: self.ogrTileIndexDS.GetLayer().ResetReading()
  1148.                 _ogrTileIndexDS.GetLayerByIndex(0).ResetReading();
  1149.                 Feature feature = _ogrTileIndexDS.GetLayerByIndex(0).GetNextFeature();
  1150.                 string imgLocation = feature.GetFieldAsString(0);
  1151.  
  1152.                 Dataset fhInputTile = _cache.Get(imgLocation);
  1153.  
  1154.                 _bands = fhInputTile.RasterCount;
  1155.                 _bandType = fhInputTile.GetRasterBand(1).DataType;
  1156.                 _projection = fhInputTile.GetProjection();
  1157.  
  1158.                 double[] argout = new double[6];
  1159.                 fhInputTile.GetGeoTransform(argout);
  1160.                 AffineTransformDecorator dec = new AffineTransformDecorator(argout);
  1161.  
  1162.                 _scaleX = dec.ScaleX;
  1163.                 _scaleY = dec.ScaleY;
  1164.  
  1165.                 ColorTable ct = fhInputTile.GetRasterBand(1).GetRasterColorTable();
  1166.                 if (ct != null)
  1167.                 {
  1168.                     _ct = ct.Clone();
  1169.                 }
  1170.                 else
  1171.                 {
  1172.                     _ct = null;
  1173.                 }
  1174.  
  1175.                 List<ColorInterp> ciList = new List<ColorInterp>();
  1176.                 for (int i = 0; i < _bands; i++)
  1177.                 {
  1178.                     ciList.Add(ColorInterp.GCI_Undefined);
  1179.                 }
  1180.  
  1181.                 if (_ci == null)
  1182.                 {
  1183.                     _ci = new ColorInterp[_bands];
  1184.                 }
  1185.  
  1186.                 for (int iBand = 0; iBand < _bands; iBand++)
  1187.                 {
  1188.                     _ci[iBand] = fhInputTile.GetRasterBand(iBand + 1).GetRasterColorInterpretation();
  1189.                 }
  1190.  
  1191.                 // TODO: check this
  1192.                 // python:
  1193.                 //                extent = self.ogrTileIndexDS.GetLayer().GetExtent()
  1194.                 //                self.ulx = extent[0]
  1195.                 //                self.uly = extent[3]
  1196.                 //                self.lrx = extent[1]
  1197.                 //                self.lry = extent[2]
  1198.                 Envelope extent = new Envelope();
  1199.                 _ogrTileIndexDS.GetLayerByIndex(0).GetExtent(extent, 1);
  1200.  
  1201.                 _ulx = extent.MinX;
  1202.                 _uly = extent.MaxY;
  1203.                 _lrx = extent.MaxX;
  1204.                 _lry = extent.MinY;
  1205.  
  1206.                 _xSize = (int) Math.Round((Math.Round((_lrx - _ulx)/_scaleX)));
  1207.                 _ySize = Math.Abs((int) Math.Round((Math.Round((_uly - _lry)/_scaleY))));
  1208.             }
  1209.  
  1210.             public Dataset GetDataSet(double minX, double minY, double maxX, double maxY)
  1211.             {
  1212.                 _ogrTileIndexDS.GetLayerByIndex(0).ResetReading();
  1213.                 _ogrTileIndexDS.GetLayerByIndex(0).SetSpatialFilterRect(minX, minY, maxX, maxY);
  1214.  
  1215.                 List<Feature> features = new List<Feature>();
  1216.                 Envelope envelope = null;
  1217.  
  1218.                 while (true)
  1219.                 {
  1220.                     Feature feature = _ogrTileIndexDS.GetLayerByIndex(0).GetNextFeature();
  1221.                     if (feature == null)
  1222.                     {
  1223.                         break;
  1224.                     }
  1225.                     features.Add(feature);
  1226.                     if (envelope == null)
  1227.                     {
  1228.                         // TODO: check this
  1229.                         // python:
  1230.                         // envelope=feature.GetGeometryRef().GetEnvelope()
  1231.                         envelope = new Envelope();
  1232.                         feature.GetGeometryRef().GetEnvelope(envelope);
  1233.                     }
  1234.                     else
  1235.                     {
  1236.                         Envelope featureEnv = new Envelope();
  1237.                         feature.GetGeometryRef().GetEnvelope(featureEnv);
  1238.  
  1239.                         envelope.MinX = Math.Min(featureEnv.MinX, envelope.MinX);
  1240.                         envelope.MinY = Math.Min(featureEnv.MinY, envelope.MinY);
  1241.                         envelope.MaxX = Math.Max(featureEnv.MaxX, envelope.MaxX);
  1242.                         envelope.MaxY = Math.Max(featureEnv.MaxY, envelope.MaxY);
  1243.                     }
  1244.                 }
  1245.  
  1246.                 if (envelope == null)
  1247.                 {
  1248.                     return null;
  1249.                 }
  1250.  
  1251.                 // enlarge to query rect if necessairy
  1252.                 envelope.MinX = Math.Min(minX, envelope.MinX);
  1253.                 envelope.MinY = Math.Min(minY, envelope.MinY);
  1254.                 envelope.MaxX = Math.Max(maxX, envelope.MaxX);
  1255.                 envelope.MaxY = Math.Max(maxY, envelope.MaxY);
  1256.  
  1257.                 _ogrTileIndexDS.GetLayerByIndex(0).SetSpatialFilter(null);
  1258.  
  1259.                 // merge tiles
  1260.                 int resultSizeX = (int) Math.Round((Math.Ceiling((double) (maxX - minX)/(double) _scaleX)));
  1261.                 int resultSizeY = (int) Math.Round((Math.Ceiling((double) (minY - maxY)/(double) _scaleY)));
  1262.  
  1263.                 Dataset resultDS = _tempDriver.Create("TEMP", resultSizeX, resultSizeY, _bands, _bandType, new string[] { });
  1264.                 resultDS.SetGeoTransform(new[] { minX, _scaleX, 0, maxY, 0, _scaleY });
  1265.  
  1266.                 foreach (Feature feature in features)
  1267.                 {
  1268.                     string featureName = feature.GetFieldAsString(0);
  1269.                     Dataset sourceDS = _cache.Get(featureName);
  1270.  
  1271.                     double[] argout = new double[6];
  1272.                     sourceDS.GetGeoTransform(argout);
  1273.                     AffineTransformDecorator dec = new AffineTransformDecorator(argout);
  1274.  
  1275.                     // calculate read and write offsets
  1276.                     int readOffsetX = (int) Math.Round((Math.Round((double) (minX - dec.Ulx)/(double) _scaleX)));
  1277.                     int readOffsetY = (int) Math.Round((Math.Round((double) (maxY - dec.Uly)/(double) _scaleY)));
  1278.  
  1279.                     int writeOffsetX = 0;
  1280.                     if (readOffsetX < 0)
  1281.                     {
  1282.                         writeOffsetX = readOffsetX * (-1);
  1283.                         readOffsetX = 0;
  1284.                     }
  1285.                     int writeOffsetY = 0;
  1286.                     if (readOffsetY < 0)
  1287.                     {
  1288.                         writeOffsetY = readOffsetY * (-1);
  1289.                         readOffsetY = 0;
  1290.                     }
  1291.  
  1292.                     // calculate read and write dimensions
  1293.                     int readX = Math.Min(Math.Min(resultSizeX, sourceDS.RasterXSize - readOffsetX), resultSizeX - writeOffsetX);
  1294.                     if (readX <= 0)
  1295.                         continue;
  1296.  
  1297.                     int readY = Math.Min(Math.Min(resultSizeY, sourceDS.RasterYSize - readOffsetY), resultSizeY - writeOffsetY);
  1298.                     if (readY <= 0)
  1299.                         continue;
  1300.  
  1301.                     for (int bandNr = 1; bandNr < _bands + 1; bandNr++)
  1302.                     {
  1303.                         Band sBand = sourceDS.GetRasterBand(bandNr);
  1304.                         Band tBand = resultDS.GetRasterBand(bandNr);
  1305.  
  1306.                         if (_ct != null)
  1307.                         {
  1308.                             tBand.SetRasterColorTable(_ct);
  1309.                         }
  1310.                         tBand.SetRasterColorInterpretation(_ci[bandNr - 1]);
  1311.                         // TODO: check this
  1312.                         //var data = sBand.ReadRaster(readOffsetX, readOffsetY, readX, readY, readX, readY, _bandType);
  1313.                         byte[] buffer = new byte[readX * readY];
  1314.                         sBand.ReadRaster(readOffsetX, readOffsetY, readX, readY, buffer, readX, readY, 0, 0);
  1315.                         tBand.WriteRaster(writeOffsetX, writeOffsetY, readX, readY, buffer, readX, readY, 0, 0);
  1316.                     }
  1317.                 }
  1318.  
  1319.                 return resultDS;
  1320.             }
  1321.  
  1322.             public void CloseDataSet(Dataset memDS)
  1323.             {
  1324.                 memDS.Dispose();
  1325.             }
  1326.  
  1327.             public void Dispose()
  1328.             {
  1329.                 _cache.Dispose();
  1330.                 _ogrTileIndexDS.Dispose();
  1331.             }
  1332.         }
  1333.  
  1334.         internal class DataSetCache : IDisposable
  1335.         {
  1336.             private int _cacheSize;
  1337.             private Queue<string> _queue;
  1338.             private Dictionary<string, Dataset> _dict;
  1339.  
  1340.             public DataSetCache()
  1341.             {
  1342.                 _cacheSize = 8;
  1343.                 _queue = new Queue<string>();
  1344.                 _dict = new Dictionary<string, Dataset>();
  1345.             }
  1346.  
  1347.             public Dataset Get(string name)
  1348.             {
  1349.                 if (_dict.ContainsKey(name))
  1350.                     return _dict[name];
  1351.  
  1352.                 Dataset result = Gdal.Open(name, Access.GA_ReadOnly);
  1353.                 if (result == null)
  1354.                 {
  1355.                     throw new Exception("Error opening: " + name);
  1356.                 }
  1357.  
  1358.                 if (_queue.Count() == _cacheSize)
  1359.                 {
  1360.                     string toRemove = _queue.Dequeue();
  1361.                     _dict.Remove(toRemove);
  1362.                 }
  1363.  
  1364.                 _queue.Enqueue(name);
  1365.                 _dict[name] = result;
  1366.  
  1367.                 return result;
  1368.             }
  1369.  
  1370.             public void Dispose()
  1371.             {
  1372.                 _dict.Clear();
  1373.                 _queue.Clear();
  1374.                 _dict = null;
  1375.                 _queue = null;
  1376.                 GC.Collect();
  1377.             }
  1378.         }
  1379.  
  1380.         // a class holding info how to tile
  1381.         internal class TileInfo
  1382.         {
  1383.             private int _tileWidth, _tileHeight;
  1384.             private int _countTilesX, _countTilesY;
  1385.             private int _lastTileWidth, _lastTileHeight;
  1386.  
  1387.             public int CountTilesX
  1388.             {
  1389.                 get { return _countTilesX; }
  1390.                 set { _countTilesX = value; }
  1391.             }
  1392.  
  1393.             public int CountTilesY
  1394.             {
  1395.                 get { return _countTilesY; }
  1396.                 set { _countTilesY = value; }
  1397.             }
  1398.  
  1399.             public int TileWidth
  1400.             {
  1401.                 get { return _tileWidth; }
  1402.                 set { _tileWidth = value; }
  1403.             }
  1404.  
  1405.             public int TileHeight
  1406.             {
  1407.                 get { return _tileHeight; }
  1408.                 set { _tileHeight = value; }
  1409.             }
  1410.  
  1411.             public int LastTileWidth
  1412.             {
  1413.                 get { return _lastTileWidth; }
  1414.                 set { _lastTileWidth = value; }
  1415.             }
  1416.  
  1417.             public int LastTileHeight
  1418.             {
  1419.                 get { return _lastTileHeight; }
  1420.                 set { _lastTileHeight = value; }
  1421.             }
  1422.  
  1423.             public TileInfo(double xSize, double ySize, int tileWidth, int tileHeight)
  1424.             {
  1425.                 _tileWidth = tileWidth;
  1426.                 _tileHeight = tileHeight;
  1427.                 _countTilesX = (int) Math.Round(xSize/(double) tileWidth);
  1428.                 _countTilesY = (int) Math.Round(ySize/(double) tileHeight);
  1429.                 _lastTileWidth = (int) Math.Round(xSize - (double) _countTilesX*(double) tileWidth);
  1430.                 _lastTileHeight = (int) Math.Round(ySize - (double) _countTilesY*(double) tileHeight);
  1431.  
  1432.                 if (_lastTileWidth > 0)
  1433.                 {
  1434.                     _countTilesX = _countTilesX + 1;
  1435.                 }
  1436.                 else
  1437.                 {
  1438.                     _lastTileWidth = tileWidth;
  1439.                 }
  1440.  
  1441.                 if (_lastTileHeight > 0)
  1442.                 {
  1443.                     _countTilesY = _countTilesY + 1;
  1444.                 }
  1445.                 else
  1446.                 {
  1447.                     _lastTileHeight = tileHeight;
  1448.                 }
  1449.             }
  1450.  
  1451.             public void Report()
  1452.             {
  1453.                 Console.WriteLine("tileWidth       " + _tileWidth);
  1454.                 Console.WriteLine("tileHeight      " + _tileHeight);
  1455.                 Console.WriteLine("countTilesX:    " + _countTilesX);
  1456.                 Console.WriteLine("countTilesY:    " + _countTilesY);
  1457.                 Console.WriteLine("lastTileWidth:  " + _lastTileWidth);
  1458.                 Console.WriteLine("lastTileHeight: " + _lastTileHeight);
  1459.             }
  1460.         }
  1461.     }
  1462. }
Advertisement
Add Comment
Please, Sign In to add comment