/// <summary>
        /// If no file exists, this writes the header and no-data values.  If a file exists, it will assume
        /// that data already has been filled in the file and will attempt to insert the data values
        /// as a window into the file.  If you want to create a copy of the file and values, just use
        /// System.IO.File.Copy, it almost certainly would be much more optimized.
        /// </summary>
        /// <param name="filename">The string filename to write values to.</param>
        public void Write(string filename)
        {
            FileStream fs;
            BinaryWriter bw;
            ProgressMeter pm = new ProgressMeter(ProgressHandler, "Writing values to " + filename, NumRows);
            long expectedByteCount = NumRows*NumColumns*ByteSize;
            if (expectedByteCount < 1000000) pm.StepPercent = 5;
            if (expectedByteCount < 5000000) pm.StepPercent = 10;
            if (expectedByteCount < 100000) pm.StepPercent = 50;


            if (File.Exists(filename))
            {
                FileInfo fi = new FileInfo(filename);
                // if the following test fails, then the target raster doesn't fit the bill for pasting into, so clear it and write a new one.
                if (fi.Length == HeaderSize + ByteSize*NumColumnsInFile*NumRowsInFile)
                {
                    WriteHeader(filename);
                    // assume that we already have a file set up for us, and just write the window of values into the appropriate place.
                    fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None,
                                        ByteSize*NumColumns);
                    fs.Seek(HeaderSize, SeekOrigin.Begin);
                    fs.Seek(ByteSize*StartRow, SeekOrigin.Current);
                    bw = new BinaryWriter(fs); // encoding doesn't matter because we don't have characters

                    for (int row = 0; row < NumRows; row++)
                    {
                        fs.Seek(StartColumn*ByteSize, SeekOrigin.Current);
                        for (int col = 0; col < NumColumns; col++)
                        {
                            // this is the only line that is type dependant, but I don't want to type check on every value
                            bw.Write(Data[row][col]);
                        }
                        fs.Flush(); // Since I am buffering, make sure that I write the buffered data before seeking
                        fs.Seek((NumColumnsInFile - EndColumn - 1)*ByteSize, SeekOrigin.Current);
                        pm.CurrentValue = row;
                    }

                    pm.Reset();
                    bw.Close();
                    return;
                }
            }

            if (File.Exists(filename)) File.Delete(filename);
            WriteHeader(filename);
            // Open as append and it will automatically skip the header for us.
            fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None, ByteSize*NumColumnsInFile);
            bw = new BinaryWriter(fs);
            // the row and column counters here are relative to the whole file, not just the window that is currently in memory.
            pm.EndValue = NumRowsInFile;


            for (int row = 0; row < NumRowsInFile; row++)
            {
                for (int col = 0; col < NumColumnsInFile; col++)
                {
                    if (row < StartRow || row > EndRow || col < StartColumn || col > EndColumn)
                        bw.Write(DoubleNoDataValue);
                    else
                        bw.Write(Data[row - StartRow][col - StartColumn]);
                }
                pm.CurrentValue = row;
            }

            fs.Flush(); // flush anything that hasn't gotten written yet.
            pm.Reset();
            bw.Close();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private IImageData OpenFile(string filename)
        {
            
            
            GdalImage result = new GdalImage(filename);
            if(result.Width > 8000 || result.Height > 8000)
            {

                // Firstly, if there are pyramids inside of the GDAL file itself, we can just work with this directly,
                // without creating our own pyramid image.




                // For now, we can't get fast, low-res versions without some kind of pyramiding happening.
                // since that can take a while for huge images, I'd rather do this once, and create a kind of
                // standardized file-based pyramid system.  Maybe in future pyramid tiffs could be used instead?
                string pyrFile = Path.ChangeExtension(filename, ".mwi");
                if(File.Exists(pyrFile))
                {
                    if(File.Exists(Path.ChangeExtension(pyrFile, ".mwh")))
                    {
                        return new PyramidImage(filename); 
                    }
                    File.Delete(pyrFile);
                }
                
                GdalImageSource gs = new GdalImageSource(filename);
                PyramidImage py = new PyramidImage(pyrFile, gs.Bounds);
                int width = gs.Bounds.NumColumns;
                int blockHeight = 64000000 / width;
                if (blockHeight > gs.Bounds.NumRows) blockHeight = gs.Bounds.NumRows;
                int numBlocks = (int)Math.Ceiling(gs.Bounds.NumRows/(double)blockHeight);
                ProgressMeter pm = new ProgressMeter(ProgressHandler, "Copying Data To Pyramids", numBlocks* 2);
                ProgressHandler.Progress("pyramid", 0, "Copying Data To Pyramids: 0% Complete");
                Application.DoEvents();
                for(int j = 0; j < numBlocks; j++)
                {
                    int h = blockHeight;
                    if(j==numBlocks-1)
                    {
                        h = gs.Bounds.NumRows - j*blockHeight;
                    }
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    byte[] vals = gs.ReadWindow(j*blockHeight, 0, h, width, 0);
                    Debug.WriteLine("Reading Value time: " + sw.ElapsedMilliseconds);
                    pm.CurrentValue = j * 2 + 1;
                    sw.Reset();
                    sw.Start();
                    py.WriteWindow(vals, j * blockHeight, 0, h, width, 0);
                    sw.Stop();
                    Debug.WriteLine("Writing Pyramid time: " + sw.ElapsedMilliseconds);
                    pm.CurrentValue = (j+1) * 2;
                }                
                gs.Dispose();
                pm.Reset();
                py.CreatePyramids(ProgressHandler);
                py.WriteHeader(pyrFile);
                return py;
            }
            result.Open(filename);
            return result;
        }
        /// <summary>
        /// This assumes that the base image has been written to the file.  This will now attempt to calculate
        /// the down-sampled images.
        /// </summary>
        /// <param name="progressHandler"></param>
        public void CreatePyramids(IProgressHandler progressHandler)
        {
            int w = _header.ImageHeaders[0].NumColumns;
            int h = _header.ImageHeaders[0].NumRows;
            int blockHeight = 32000000/w;
            if (blockHeight > h) blockHeight = h;
            int numBlocks = (int)Math.Ceiling(h/(double)blockHeight);
            ProgressMeter pm = new ProgressMeter(progressHandler, "Generating Pyramids", _header.ImageHeaders.Length * numBlocks);
            for(int block = 0; block < numBlocks; block++)
            {
                GC.Collect();
                // Normally block height except for the lowest block which is usually smaller
                int bh = blockHeight;
                if(block == numBlocks -1) bh = h - block*blockHeight;
                
                // Read a block of bytes into a bitmap
                byte[] vals = ReadWindow(block * blockHeight, 0, bh, w, 0);
                
                Bitmap bmp = new Bitmap(w, bh);
                BitmapData bd = bmp.LockBits(new Rectangle(0, 0, w, bh), ImageLockMode.WriteOnly,
                                              PixelFormat.Format32bppArgb);
                Marshal.Copy(vals, 0, bd.Scan0, vals.Length);
                bmp.UnlockBits(bd);
                
                // cycle through the scales, and write the resulting smaller bitmap in an appropriate spot
                int sw = w; // scale width
                int sh = bh; // scale height
                int sbh = blockHeight;
                for (int scale = 1; scale < _header.ImageHeaders.Length - 1; scale++)
                {
                    sw = sw / 2;
                    sh = sh / 2;
                    sbh = sbh / 2;
                    if(sh == 0 || sw == 0)
                    {
                        break;
                    }
                    Bitmap subSet = new Bitmap(sw, sh);
                    Graphics g = Graphics.FromImage(subSet);
                    g.DrawImage(bmp, 0, 0, sw, sh);
                    bmp.Dispose(); // since we keep getting smaller, don't bother keeping the big image in memory any more.
                    bmp = subSet;  // keep the most recent image alive for making even smaller subsets.
                    g.Dispose();
                    BitmapData bdata = bmp.LockBits(new Rectangle(0, 0, sw, sh), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    byte[] res = new byte[sw * sh * 4];
                    Marshal.Copy(bdata.Scan0, res, 0, res.Length);
                    bmp.UnlockBits(bdata);
                    WriteWindow(res, sbh * block, 0, sh, sw, scale);
                    pm.CurrentValue = block*_header.ImageHeaders.Length + scale;
                }
                bmp.Dispose();

            }
            pm.Reset();

            
    

        }
        // X Y Poly Lines: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 3        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little


        // X Y M Poly Lines: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 23       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little
       
       
        
        // X Y Z M Poly Lines: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big       
        // Byte 8       Shape Type 13       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

       


        private void FillPolygons(string filename, IProgressHandler progressHandler)
        {
           
            // Check to ensure the filename is not null
            if (filename == null)
            {
                throw new NullReferenceException(MessageStrings.ArgumentNull_S.Replace("%S", filename));
            }

            if (File.Exists(filename) == false)
            {
                throw new FileNotFoundException(MessageStrings.FileNotFound_S.Replace("%S", filename));
            }

            // Get the basic header information.  
            ShapefileHeader header = new ShapefileHeader(filename);
            Extent = new Extent(new[]{header.Xmin, header.Ymin, header.Xmax, header.Ymax});

            // Check to ensure that the filename is the correct shape type
            if (header.ShapeType != ShapeTypes.Polygon &&
                 header.ShapeType != ShapeTypes.PolygonM &&
                 header.ShapeType != ShapeTypes.PolygonZ)
            {
                throw new ArgumentException(MessageStrings.FileNotLines_S.Replace("%S", filename));

            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(filename);


            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            IO.BufferedBinaryReader bbReader = new IO.BufferedBinaryReader(filename, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;
            
            int [] partOffsets = new int[numShapes];
            byte[] bigEndians = new byte[numShapes * 8];
            byte[] allBounds = new byte[numShapes * 32];

            ByteBlock allParts = new ByteBlock(BLOCKSIZE); // probably all will be in one block, but use a byteBlock just in case.
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool isM = (header.ShapeType == ShapeTypes.PolyLineM || header.ShapeType == ShapeTypes.PolyLineZ);
            bool isZ = (header.ShapeType == ShapeTypes.PolyLineZ);
            ByteBlock allZ = null;
            ByteBlock allM = null;
            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }

            int pointOffset = 0;
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                                                                    // Position     Value               Type        Number      Byte Order
                ShapeRange shape = new ShapeRange(FeatureTypes.Polygon); //-------------------------------------------------------------------- 
                shape.RecordNumber = bbReader.ReadInt32(false);     // Byte 0       Record Number       Integer     1           Big
                shape.ContentLength = bbReader.ReadInt32(false);    // Byte 4       Content Length      Integer     1           Big
                shape.ShapeType = (ShapeTypes)bbReader.ReadInt32(); // Byte 8       Shape Type          Integer     1           Little
                shape.StartIndex = pointOffset;
                if (shape.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                bbReader.Read(allBounds, shp*32, 32);
                //double xMin = bbReader.ReadDouble();                // Byte 12      Xmin                Double      1           Little
               // double yMin = bbReader.ReadDouble();                // Byte 20      Ymin                Double      1           Little
                //double xMax = bbReader.ReadDouble();                // Byte 28      Xmax                Double      1           Little
                //double yMax = bbReader.ReadDouble();                // Byte 36      Ymax                Double      1           Little
                shape.NumParts = bbReader.ReadInt32();              // Byte 44      NumParts            Integer     1           Little
                //feature.NumPoints = bbReader.ReadInt32();             // Byte 48      NumPoints           Integer     1           Little
                shape.NumPoints = bbReader.ReadInt32();                                             
                
                // Create an envelope from the extents box in the file.
                //feature.Envelope = new Envelope(xMin, xMax, yMin, yMax);

                partOffsets[shp] = allParts.IntOffset();
                allParts.Read(shape.NumParts * 4, bbReader);
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;



                if (header.ShapeType == ShapeTypes.PolygonM)
                {
                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        
                        if(allM != null)allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }

                if (header.ShapeType == ShapeTypes.PolygonZ)
                {
                    bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    double zMin = bbReader.ReadDouble();
                    double zMax = bbReader.ReadDouble();
                   
                    
                    // For Z shapefiles, the Z part is not optional.  
                    if (allZ != null) allZ.Read(shape.NumPoints * 8, bbReader);
                   
                    // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        double mMin = bbReader.ReadDouble();
                        double mMax = bbReader.ReadDouble();
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                    
                }
                ShapeIndices.Add(shape);
            }

            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM) M = allM.ToDoubleArray();
            if (isZ) Z = allZ.ToDoubleArray();
            List<ShapeRange> shapes = ShapeIndices;
            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            int[] parts = allParts.ToIntArray();
            ProgressMeter = new ProgressMeter(ProgressHandler, "Testing Parts and Holes", numShapes);
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                for (int part = 0; part < shape.NumParts; part++)
                {
                    int offset = partOffsets[shp];
                    int endIndex = shape.NumPoints + shape.StartIndex;
                    int startIndex = parts[offset + part] + shape.StartIndex;
                    if (part < shape.NumParts - 1) endIndex = parts[offset + part + 1] + shape.StartIndex;
                    int count = endIndex - startIndex;
                    PartRange partR = new PartRange(vert, shape.StartIndex, parts[offset + part], FeatureTypes.Polygon);
                    partR.NumVertices = count;
                    shape.Parts.Add(partR);
                }
                ProgressMeter.CurrentValue = shp;
            }
            ProgressMeter.Reset();
            GC.Collect();
        }
示例#5
0
        // ----------------------------------- FROM AND TO IN RAM ONLY ---------------------------------
        /// <summary>
        /// This creates an IN MEMORY ONLY window from the in-memory window of this raster.  If, however, the requested range
        /// is outside of what is contained in the in-memory portions of this raster, an appropriate cast
        /// is required to ensure that you have the correct File handling, like a BinaryRaster etc.
        /// </summary>
        /// <param name="startRow">The 0 based integer index of the top row to get from this raster.  If this raster is itself a window, 0 represents the startRow from the file.</param>
        /// <param name="endRow">The integer index of the bottom row to get from this raster.  The largest allowed value is NumRows - 1.</param>
        /// <param name="startColumn">The 0 based integer index of the leftmost column to get from this raster.  If this raster is a window, 0 represents the startColumn from the file.</param>
        /// <param name="endColumn">The 0 based integer index of the rightmost column to get from this raster.  The largest allowed value is NumColumns - 1</param>
        /// <param name="inRam">Boolean.  If this is true and the window is small enough, a copy of the values will be loaded To memory.</param>
        /// <returns>An implementation of IRaster</returns>
        public IRaster GetWindow(int startRow, int endRow, int startColumn, int endColumn, bool inRam)
        {
            if (IsInRam == false)
            {
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }
            if (startRow < StartRow || endRow > EndRow || StartColumn < startColumn || EndColumn > endColumn)
            {
                // the requested extents are outside of the extents that have been windowed into ram.  File Handling is required.
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }

            int numCols = endColumn - startColumn + 1;
            int numRows = endRow - startRow + 1;
            ShortRaster result = new ShortRaster(numRows, numCols);
            result.Filename = Filename;
            result.Projection = Projection;
            result.DataType = typeof(short);
            result.NumRows = numRows;
            result.NumColumns = numCols;
            result.NumRowsInFile = NumRowsInFile;
            result.NumColumnsInFile = NumColumnsInFile;
            result.NoDataValue = NoDataValue;
            result.StartColumn = startColumn;
            result.StartRow = startRow;
            result.EndColumn = endColumn;
            result.EndRow = EndRow;
            result.FileType = FileType;

            // Reposition the new "raster" so that it matches the specified window, not the whole raster
            // X = [0] + [1] * column + [2] * row;
            // Y = [3] + [4] * column + [5] * row;
            result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, new double[6]);
            result.Bounds.AffineCoefficients[0] = Bounds.AffineCoefficients[0] + Bounds.AffineCoefficients[1] * startColumn + Bounds.AffineCoefficients[2] * startRow;
            result.Bounds.AffineCoefficients[1] = Bounds.AffineCoefficients[1];
            result.Bounds.AffineCoefficients[2] = Bounds.AffineCoefficients[2];
            result.Bounds.AffineCoefficients[3] = Bounds.AffineCoefficients[3] + Bounds.AffineCoefficients[4] * startColumn + Bounds.AffineCoefficients[5] * startRow;
            result.Bounds.AffineCoefficients[4] = Bounds.AffineCoefficients[4];
            result.Bounds.AffineCoefficients[5] = Bounds.AffineCoefficients[5];



            // Now we can copy any values currently in memory.


            ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CopyingValues, endRow);
            pm.StartValue = startRow;
            // copy values directly using both data structures
            for (int row = 0; row < numRows; row++)
            {
                for (int col = 0; col < numCols; col++)
                {
                    result.Data[row][col] = Data[startRow + row][startColumn + col];
                }
                pm.CurrentValue = row;
            }
            pm.Reset();

            result.Value = new ShortValueGrid(result);
            return result;
        }
        /// <summary>
        /// This populates the Table with data from the file.
        /// </summary>
        /// <param name="numRows">In the event that the dbf file is not found, this indicates how many blank rows should exist in the attribute Table.</param>
        public void Fill(int numRows)
        {
            if (!_loaded) Load();
            _dataRowWatch = new Stopwatch();

            _dataTable.Rows.Clear(); // if we have already loaded data, clear the data.

            if (File.Exists(_filename) == false)
            {
                _numRecords = numRows;
                _dataTable.BeginLoadData();
                _dataTable.Columns.Add("FID", typeof (int));
                for (int row = 0; row < numRows; row++)
                {
                    DataRow dr = _dataTable.NewRow();
                    dr["FID"] = row;
                    _dataTable.Rows.Add(dr);
                }
                _dataTable.EndLoadData();
                return;
            }
            Stopwatch sw = new Stopwatch();
            sw.Start();
            ProgressMeter = new ProgressMeter(ProgressHandler, "Reading from DBF Table...", _numRecords);
            if (_numRecords < 10000000) ProgressMeter.StepPercent = 5;
            if (_numRecords < 5000000) ProgressMeter.StepPercent = 10;
            if (_numRecords < 100000) ProgressMeter.StepPercent = 50;
            if (_numRecords < 10000) ProgressMeter.StepPercent = 100;
            _dataTable.BeginLoadData();
            // Reading the Table elements as well as the shapes in a single progress loop.
            for (int row = 0; row < _numRecords; row++)
            {
                // --------- DATABASE --------- CurrentFeature = ReadTableRow(myReader);
                try
                {
                    _dataTable.Rows.Add(ReadTableRowFromChars(row));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    _dataTable.Rows.Add(_dataTable.NewRow());
                }

                // If a progress message needs to be updated, this will handle that.
                ProgressMeter.CurrentValue = row;
            }
            ProgressMeter.Reset();
            _dataTable.EndLoadData();
            sw.Stop();

            Debug.WriteLine("Load Time:" + sw.ElapsedMilliseconds + " Milliseconds");
            Debug.WriteLine("Conversion:" + _dataRowWatch.ElapsedMilliseconds + " Milliseconds");
            _attributesPopulated = true;
            OnAttributesFilled();
        }
        /// <summary>
        /// Reads all the information from the specified file.  This also sends status messages through progressHandler.
        /// </summary>
        public void Open(IProgressHandler progressHandler)
        {
            
            IFeature currentFeature;
            string dbfFile = Path.ChangeExtension(Filename, ".dbf");
            FileStream myStream = new FileStream(dbfFile, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader myReader = new BinaryReader(myStream);
            ReadTableHeader(myReader); // based on the header, set up the fields information etc.

            ProgressMeter pm = new ProgressMeter(progressHandler, "Opening " + Path.GetFileName(Filename), _numRecords);
             
           
            
            ShapeReader myShapeReader = new ShapeReader(Filename);
            IEnumerator en = myShapeReader.GetEnumerator();
            en.MoveNext();
            // Reading the Table elements as well as the shapes in a single progress loop.
            for (int row = 0; row < _numRecords; row++)
            {
                // --------- DATABASE --------- CurrentFeature = ReadTableRow(myReader);
                // rem this line if the DATABASE is turned back on
                currentFeature = new Feature();

                currentFeature.BasicGeometry = (IBasicGeometry)en.Current;
                en.MoveNext();
                Features.Add(currentFeature);

             
                // --------- DATABASE ---------  _Table.Rows.Add(CurrentFeature.DataRow);

                // If a progress message needs to be updated, this will handle that.
                
                pm.CurrentValue = row;
                

            }
            Envelope = null; // invalidate the envelope so that it will be re-calculated from all the points
            
            pm.Reset(); // Shows the basic "Ready." message indicating that we are done with this step.
            

        }
示例#8
0
        // ------------------------------------------FROM AND TO IN RAM ONLY -----------------
        /// <summary>
        /// This creates a completely new raster from the windowed domain on the original raster.  This new raster
        /// will not have a source file, and values like NumRowsInFile will correspond to the in memory version.
        /// All the values will be copied to the new source file.  InRam must be true at this level.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="startRow">The 0 based integer index of the top row to copy from this raster.  If this raster is itself a window, 0 represents the startRow from the file.</param>
        /// <param name="endRow">The integer index of the bottom row to copy from this raster.  The largest allowed value is NumRows - 1.</param>
        /// <param name="startColumn">The 0 based integer index of the leftmost column to copy from this raster.  If this raster is a window, 0 represents the startColumn from the file.</param>
        /// <param name="endColumn">The 0 based integer index of the rightmost column to copy from this raster.  The largest allowed value is NumColumns - 1</param>
        /// <param name="copyValues">If this is true, the valeus are saved to the file.  If this is false and the data can be loaded into Ram, no file handling is done.  Otherwise, a file of NoData values is created.</param>
        /// <param name="inRam">Boolean.  If this is true and the window is small enough, a copy of the values will be loaded into memory.</param>
        /// <returns>An implementation of IRaster</returns>
        public IRaster CopyWindow(string filename, int startRow, int endRow, int startColumn, int endColumn, bool copyValues, bool inRam)
        {
            if (inRam == false || (endColumn - startColumn + 1) * (endRow - startRow + 1) > 64000000)
            {
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }
            if (IsInRam == false)
            {
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }
            int numCols = endColumn - startColumn + 1;
            int numRows = endRow - startRow + 1;



            ShortRaster result = new ShortRaster(numRows, numCols);

            result.Projection = Projection;

            // The affine coefficients defining the world file are the same except that they are translated over.  Only the position of the
            // upper left corner changes.  Everything else is the same as the previous raster.

            // X = [0] + [1] * column + [2] * row;
            // Y = [3] + [4] * column + [5] * row;
            result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, new double[6]);
            result.Bounds.AffineCoefficients[0] = Bounds.AffineCoefficients[0] + Bounds.AffineCoefficients[1] * startColumn + Bounds.AffineCoefficients[2] * startRow;
            result.Bounds.AffineCoefficients[1] = Bounds.AffineCoefficients[1];
            result.Bounds.AffineCoefficients[2] = Bounds.AffineCoefficients[2];
            result.Bounds.AffineCoefficients[3] = Bounds.AffineCoefficients[3] + Bounds.AffineCoefficients[4] * startColumn + Bounds.AffineCoefficients[5] * startRow;
            result.Bounds.AffineCoefficients[4] = Bounds.AffineCoefficients[4];
            result.Bounds.AffineCoefficients[5] = Bounds.AffineCoefficients[5];


            ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CopyingValues, numRows);
            // copy values directly using both data structures
            for (int row = 0; row < numRows; row++)
            {
                for (int col = 0; col < numCols; col++)
                {
                    result.Data[row][col] = Data[startRow + row][startColumn + col];
                }
                pm.CurrentValue = row;
            }
            pm.Reset();


            result.Value = new ShortValueGrid(result);
            return result;

        }
示例#9
0
        /// <summary>
        /// Gets the count of members that match the expression
        /// </summary>
        /// <param name="expressions">The string expression to test</param>
        /// <param name="progressHandler">THe progress handler that can also cancel the counting</param>
        /// <param name="maxSampleSize">The integer maximum sample size from which to draw counts.  If this is negative, it will not be used.</param>
        /// <returns>The integer count of the memebrs that match the expression.</returns>
        public override int[] GetCounts(string[] expressions, ICancelProgressHandler progressHandler, int maxSampleSize)
        {
            if (InternalDataSet != null) return InternalDataSet.GetCounts(expressions, progressHandler, maxSampleSize);
            if (AttributesPopulated) return base.GetCounts(expressions, progressHandler, maxSampleSize);


            int[] counts = new int[expressions.Length];
            
            // The most common case would be no filter expression, in which case the count is simply the number of shapes.
            bool requiresRun = false;
            for(int iex = 0; iex < expressions.Length;iex++)
            {
                if (!string.IsNullOrEmpty(expressions[iex]))
                {
                    requiresRun = true;
                }
                else
                {
                    counts[iex] = NumRows();
                }
            }
            if (!requiresRun) return counts;

            AttributePager ap = new AttributePager(this, 5000);
            ProgressMeter pm = new ProgressMeter(progressHandler, "Calculating Counts", ap.NumPages());
           
            // Don't bother to use a sampling approach if the number of rows is on the same order of magnitude as the number of samples.
            if(maxSampleSize > 0 && maxSampleSize < NumRows()/2)
            {
                DataTable sample = new DataTable();
                sample.Columns.AddRange(GetColumns());
                Dictionary<int, int> usedRows = new Dictionary<int, int>();
                int samplesPerPage = maxSampleSize/ap.NumPages();
                Random rnd = new Random(DateTime.Now.Millisecond);
                for (int page = 0; page < ap.NumPages(); page++)
                {
                    for (int i = 0; i < samplesPerPage; i++ )
                    {
                        int row;
                        do
                        {
                            row = rnd.Next(ap.StartIndex, ap.StartIndex + ap.PageSize);
                        } while (usedRows.ContainsKey(row));
                        usedRows.Add(row, row);
                        sample.Rows.Add(ap.Row(row).ItemArray);
                    }
                    ap.MoveNext();
                       
                    pm.CurrentValue = page;
                    if (progressHandler.Cancel) break;
                    System.Windows.Forms.Application.DoEvents();
                }
                for (int i = 0; i < expressions.Length; i++)
                {
                    try
                    {
                        DataRow[] dr = sample.Select(expressions[i]);
                        if (dr != null) counts[i] += dr.Length;
                    }
                    catch (Exception)
                    {

                    }
                    
                    
                }
                pm.Reset();
                return counts;
            }
            for (int page = 0; page < ap.NumPages(); page++)
            {
                for (int i = 0; i < expressions.Length; i++)
                {
                    DataRow[] dr = ap[page].Select(expressions[i]);
                    if(dr != null)counts[i] += dr.Length;
                }
                pm.CurrentValue = page;
                if (progressHandler.Cancel) break;
                System.Windows.Forms.Application.DoEvents();
            }
            pm.Reset();
            return counts;
        }
        private void ReadRGB()
        {

            if (_dataset.RasterCount < 3)
            {
                throw new GdalException("RGB Format was indicated but there are only " + _dataset.RasterCount + " bands!");
            }
            _green = _dataset.GetRasterBand(2);
            _blue = _dataset.GetRasterBand(3);

            int tw = TileCollection.TileWidth;
            int th = TileCollection.TileHeight;
            int ntt = TileCollection.NumTilesTall();
            int ntw = TileCollection.NumTilesWide();
            ProgressMeter pm = new ProgressMeter(_prog, "Reading Tiles ", ntt*ntw);
            for (int row = 0; row < ntt; row++)
            {
                for (int col = 0; col < ntw; col++)
                {

                    int width = TileCollection.GetTileWidth(col);
                    int height = TileCollection.GetTileHeight(row);
                    MWImageData id = new MWImageData(width, height);

                    
                    Bitmap image = new Bitmap(width, height, PixelFormat.Format32bppArgb);

                    byte[] red = new byte[width*height];
                    byte[] g = new byte[width*height];
                    byte[] b = new byte[width*height];

                    _red.ReadRaster(col * tw, row * th, width, height, red, width, height, 0, 0);
                    _green.ReadRaster(col * tw, row * th, width, height, g, width, height, 0, 0);
                    _blue.ReadRaster(col * tw, row * th, width, height, b, width, height, 0, 0);

                    BitmapData bData = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
                                                       PixelFormat.Format32bppArgb);
                    Stride = bData.Stride;
                    image.UnlockBits(bData);
                    byte[] vals = new byte[width*height*4];
                    int stride = Stride;
                    const int bpp = 4;
                    for (int r = 0; r < height; r++)
                    {
                        for (int c = 0; c < width; c++)
                        {
                            vals[r*stride + c*bpp] = b[r*width + c];
                            vals[r*stride + c*bpp + 1] = g[r*width + c];
                            vals[r*stride + c*bpp + 2] = red[r*width + c];
                            vals[r*stride + c*bpp + 3] = 255;
                        }
                    }
                    id.Values = vals;
                    id.WriteBytes();
                    TileCollection.Tiles[row, col] = id;
                    pm.CurrentValue = row*ntw + col;
                }
            }
            pm.Reset();
            SetTileBounds(Bounds.AffineCoefficients);
        }
示例#11
0
        /// <summary>
        /// Creates a bitmap using only the colorscheme, even if a hillshade was specified
        /// </summary>
        /// <param name="bitmap">The bitmap to edit.  Ensure that this has been created and saved at least once</param>
        /// <param name="progressHandler">An IProgressHandler</param>
        /// <param name="rasterSymbolizer">The raster symbolizer to use</param>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public virtual void PaintColorSchemeToBitmap(IRasterSymbolizer rasterSymbolizer, Bitmap bitmap,
                                                     IProgressHandler progressHandler)
        {
            Debug.WriteLine("IntRaster - PaintColorSchemeToBitamp");
            BitmapData bmpData;
            if (Data == null) return;

            if (rasterSymbolizer == null)
                throw new NullLogException("rasterSymbolizer");

            if (rasterSymbolizer.Scheme == null || rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, NumColumns, NumRows);
            try
            {
                bmpData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            }
            catch (ArgumentException ex)
            {
                if (ex.ParamName == "format")
                    throw new BitmapFormatException();
                LogManager.DefaultLogManager.Exception(ex);
                throw;
            }
            int numBytes = bmpData.Stride*bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);


            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.PaintingColorScheme, NumRows);
            if (NumRows*NumColumns < 100000) pm.StepPercent = 50;
            if (NumRows*NumColumns < 500000) pm.StepPercent = 10;
            if (NumRows*NumColumns < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumColumns; col++)
                {
                    // use the colorbreaks to calculate the colors
                    pixelColor = rasterSymbolizer.GetColor(Data[row][col]);

                    // control transparency here
                    int alpha = Convert.ToInt32(rasterSymbolizer.Opacity*255);
                    if (alpha > 255) alpha = 255;
                    if (alpha < 0) alpha = 0;
                    byte a = (byte) alpha;


                    byte r = pixelColor.R;
                    byte g = pixelColor.G;
                    byte b = pixelColor.B;

                    int offset = row*bmpData.Stride + col*4;
                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                    rgbData[offset + 3] = a;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();
            // Copy the values back into the bitmap
            Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
示例#12
0
        /// <summary>
        /// Creates a bitmap based on the specified RasterSymbolizer
        /// </summary>
        /// <returns></returns>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public virtual void DrawToBitmap(IRasterSymbolizer rasterSymbolizer, Bitmap bitmap,
                                         IProgressHandler progressHandler)
        {
            Debug.WriteLine("IntRaster Calculated Bitmap");
            BitmapData bmpData;
            if (Data == null) return;

            if (rasterSymbolizer == null)
                throw new NullLogException("rasterSymbolizer");

            if (rasterSymbolizer.Scheme == null || rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, NumColumns, NumRows);
            try
            {
                bmpData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            }
            catch (ArgumentException ex)
            {
                if (ex.ParamName == "format")
                    throw new BitmapFormatException();
                LogManager.DefaultLogManager.Exception(ex);
                throw;
            }
            int numBytes = bmpData.Stride*bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            bool useHillShade = false;
            float[][] hillshade = rasterSymbolizer.HillShade;
            if (rasterSymbolizer.ShadedRelief.IsUsed)
            {
                hillshade = rasterSymbolizer.HillShade;
                useHillShade = true;
            }
            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.CreatingTexture, NumRows);
            if (NumRows*NumColumns < 100000) pm.StepPercent = 50;
            if (NumRows*NumColumns < 500000) pm.StepPercent = 10;
            if (NumRows*NumColumns < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumColumns; col++)
                {
                    // use the colorbreaks to calculate the colors
                    pixelColor = rasterSymbolizer.GetColor(Data[row][col]);

                    // control transparency here
                    int alpha = Convert.ToInt32(rasterSymbolizer.Opacity*255);
                    if (alpha > 255) alpha = 255;
                    if (alpha < 0) alpha = 0;
                    byte a = (byte) alpha;


                    byte r, g, b;
                    if (useHillShade && hillshade != null)
                    {
                        if (hillshade[row][col] == -1)
                        {
                            pixelColor = rasterSymbolizer.NoDataColor;
                            r = pixelColor.R;
                            g = pixelColor.G;
                            b = pixelColor.B;
                        }
                        else
                        {
                            int red = Convert.ToInt32(pixelColor.R*hillshade[row][col]);
                            int green = Convert.ToInt32(pixelColor.G*hillshade[row][col]);
                            int blue = Convert.ToInt32(pixelColor.B*hillshade[row][col]);
                            if (red > 255) red = 255;
                            if (green > 255) green = 255;
                            if (blue > 255) blue = 255;
                            if (red < 0) red = 0;
                            if (green < 0) green = 0;
                            if (blue < 0) blue = 0;
                            b = (byte) blue;
                            r = (byte) red;
                            g = (byte) green;
                        }
                    }
                    else
                    {
                        r = pixelColor.R;
                        g = pixelColor.G;
                        b = pixelColor.B;
                    }

                    int offset = row*bmpData.Stride + col*4;
                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                    rgbData[offset + 3] = a;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();

            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother sm = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = sm.Smooth();
            }
            // Copy the values back into the bitmap
            Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);

            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
        /// <summary>
        /// Saves the file to a new location
        /// </summary>
        /// <param name="filename">The filename to save</param>
        /// <param name="overwrite">Boolean that specifies whether or not to overwrite the existing file</param>
        public override void SaveAs(string filename, bool overwrite)
        {
            if(IndexMode)
            {
                SaveAsIndexed(filename, overwrite);
                return;
            }
            if (File.Exists(filename) && filename != Filename && overwrite == false)
            {
                if (MessageBox.Show("The file already exists.  Do you wish to overwrite it?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No) return;
                File.Delete(filename);
            }
            string dir = Path.GetDirectoryName(filename);
            if (!Directory.Exists(dir))
            {
                if (MessageBox.Show("Directory " + dir + " does not exist.  Do you want to create it?", "Create Directory?", MessageBoxButtons.YesNo) != DialogResult.OK)
                    return;
                Directory.CreateDirectory(dir);
            }
            InvalidateEnvelope();
            Header.Xmin = Envelope.Minimum.X;
            Header.Xmax = Envelope.Maximum.X;
            Header.Ymin = Envelope.Minimum.Y;
            Header.Ymax = Envelope.Maximum.Y;
            if (CoordinateType == CoordinateTypes.Regular)
            {
                Header.ShapeType = ShapeTypes.MultiPoint;
            }
            if (CoordinateType == CoordinateTypes.M)
            {
                Header.ShapeType = ShapeTypes.MultiPointM;
            }
            if (CoordinateType == CoordinateTypes.Z)
            {
                Header.ShapeType = ShapeTypes.MultiPointZ;
            }
            
            if (Header.ShapeType == ShapeTypes.MultiPoint || Header.ShapeType == ShapeTypes.MultiPointM)
            {
                // test to see if the coordinates have added z or m values in the first coordinate
                Coordinate c = Features[0].BasicGeometry.Coordinates[0];
                if (!double.IsNaN(c.Z))
                {
                    Header.ShapeType = ShapeTypes.MultiPointZ;
                }
            }
            if (Header.ShapeType == ShapeTypes.MultiPointZ)
            {
                Header.Zmin = Envelope.Minimum.Z;
                Header.Zmax = Envelope.Maximum.Z;
            }
            if (Header.ShapeType == ShapeTypes.MultiPointM || Header.ShapeType == ShapeTypes.MultiPointZ)
            {
                Header.Mmin = Envelope.Minimum.M;
                Header.Mmax = Envelope.Maximum.M;
            }
            

            
            Header.ShxLength = 50 + 4 * Features.Count;
            Header.SaveAs(filename);

            IO.BufferedBinaryWriter bbWriter = new IO.BufferedBinaryWriter(filename);
            IO.BufferedBinaryWriter indexWriter = new IO.BufferedBinaryWriter(Header.ShxFilename);
            int fid = 0;
            int offset = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words
            int contentLength = 0;
            ProgressMeter = new ProgressMeter(ProgressHandler, "Saving (Not Indexed)...", Features.Count);
            foreach (IFeature f in Features)
            {
                offset += contentLength; // adding the previous content length from each loop calculates the word offset
                List<Coordinate> points = new List<Coordinate>();
                contentLength = 20;
                for (int iPart = 0; iPart < f.NumGeometries; iPart++)
                {
                    IList<Coordinate> coords = f.BasicGeometry.GetBasicGeometryN(iPart).Coordinates;
                    foreach (Coordinate coord in coords)
                    {
                        points.Add(coord);
                    }
                }

                if (Header.ShapeType == ShapeTypes.MultiPoint)
                {

                    contentLength += points.Count * 8;
                }
                if (Header.ShapeType == ShapeTypes.MultiPointM)
                {
                    contentLength += 8; // mmin, mmax
                    contentLength += points.Count * 12;
                }
                if (Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    contentLength += 16; // mmin, mmax, zmin, zmax
                    contentLength += points.Count * 16;
                }

                //                                              Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                indexWriter.Write(offset, false);            // Byte 0       Offset       Integer     1           Big                 
                indexWriter.Write(contentLength, false);     // Byte 4       Content Length       Integer     1           Big

                //                                              X Y Poly Lines
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                bbWriter.Write(fid+1, false);                // Byte 0       Record Number       Integer     1           Big
                bbWriter.Write(contentLength, false);        // Byte 4       Content Length      Integer     1           Big
                bbWriter.Write((int)Header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
                if (Header.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                bbWriter.Write(f.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
                bbWriter.Write(f.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little

                bbWriter.Write(points.Count);                // Byte 44      NumPoints           Integer     1           Little
             

                foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                {
                    bbWriter.Write(coord.X);
                    bbWriter.Write(coord.Y);
                    //if (Header.ShapeType == ShapeTypes.MultiPointZ)
                    //{
                    //    bbWriter.Write(coord.Z);
                    //}
                }

                if (Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    bbWriter.Write(f.Envelope.Minimum.Z);
                    bbWriter.Write(f.Envelope.Maximum.Z);
                    foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                    {
                        bbWriter.Write(coord.Z);
                    }
                }
                if (Header.ShapeType == ShapeTypes.MultiPointM || Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    if(f.Envelope == null)
                    {
                        bbWriter.Write(0.0);
                        bbWriter.Write(0.0);
                    }
                    else
                    {
                        bbWriter.Write(f.Envelope.Minimum.M);
                        bbWriter.Write(f.Envelope.Maximum.M);
                    }
                    foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                    {
                        bbWriter.Write(coord.M);
                    }
                }

                ProgressMeter.CurrentValue = fid;
                fid++;
                offset += 4;
            }
            ProgressMeter.Reset();
            bbWriter.Close();
            indexWriter.Close();

            offset += contentLength;
            WriteFileLength(Filename, offset);
            UpdateAttributes();
            SaveProjection();
        }
        /// <summary>
        /// Creates a bitmap based on the specified RasterSymbolizer
        /// </summary>
        /// <param name="bitmap"> the bitmap to paint to</param>
        /// <param name="progressHandler">The progress handler</param>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public void PaintShadingToBitmap(Bitmap bitmap, IProgressHandler progressHandler)
        {
            System.Drawing.Imaging.BitmapData bmpData;
           
            if (_hillshade == null)
            {
                return;
            }

            

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            try
            {
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            catch (ArgumentException ex)
            {
                if (ex.ParamName == "format")
                {
                    throw new BitmapFormatException();
                }
                Components.LogManager.DefaultLogManager.Exception(ex);
                throw;
            }
            int numBytes = bmpData.Stride * bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);


            float[][] hillshade = _hillshade;

            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.PaintingHillshade, bitmap.Height);
            if (bitmap.Width * bitmap.Height < 100000) pm.StepPercent = 50;
            if (bitmap.Width * bitmap.Height < 500000) pm.StepPercent = 10;
            if (bitmap.Width * bitmap.Height < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < bitmap.Height; row++)
            {
                for (int col = 0; col < bitmap.Width; col++)
                {
                    int offset = row * bmpData.Stride + col * 4;
                    byte b = rgbData[offset];
                    byte g = rgbData[offset + 1];
                    byte r = rgbData[offset + 2];

                    //  rgbData[offset + 3] = a; don't worry about alpha


                    int red = Convert.ToInt32(r * hillshade[row][col]);
                    int green = Convert.ToInt32(g * hillshade[row][col]);
                    int blue = Convert.ToInt32(b * hillshade[row][col]);
                    if (red > 255) red = 255;
                    if (green > 255) green = 255;
                    if (blue > 255) blue = 255;
                    if (red < 0) red = 0;
                    if (green < 0) green = 0;
                    if (blue < 0) blue = 0;
                    b = (byte)blue;
                    r = (byte)red;
                    g = (byte)green;

                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();
            // Copy the values back into the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            
            return;
        }
示例#15
0
        /// <summary>
        /// Create Hillshade of values ranging from 0 to 1, or -1 for no-data regions.  
        /// This should be a little faster since we are accessing the Data field directly instead of working 
        /// through a value parameter.
        /// </summary>
        /// <param name="raster">The raster to create the hillshade from.</param>
        /// <param name="shadedRelief">An implementation of IShadedRelief describing how the hillshade should be created.</param>
        /// <param name="progressHandler">An implementation of IProgressHandler for progress messages</param>
        public static float[][] CreateHillShade(this IRaster raster, IShadedRelief shadedRelief, IProgressHandler progressHandler)
        {
           
            int numCols = raster.NumColumns;
            int numRows = raster.NumRows;
            double noData = raster.NoDataValue;
            float extrusion = shadedRelief.Extrusion;
            float elevationFactor = shadedRelief.ElevationFactor;
            float lightIntensity = shadedRelief.LightIntensity;
            float ambientIntensity = shadedRelief.AmbientIntensity;
            FloatVector3 lightDirection = shadedRelief.GetLightDirection();
           


            float[] aff = new float[6]; // affine coefficients converted to float format
            for (int i = 0; i < 6; i++)
            {
                aff[i] = Convert.ToSingle(raster.Bounds.AffineCoefficients[i]);
            }
            float[][] hillshade = new float[numRows][];

            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.CreatingShadedRelief, numRows);
            for (int row = 0; row < numRows; row++)
            {
                hillshade[row] = new float[numCols];

                for (int col = 0; col < numCols; col++)
                {
                    // 3D position vectors of three points to create a triangle.
                    FloatVector3 v1 = new FloatVector3(0f, 0f, 0f);
                    FloatVector3 v2 = new FloatVector3(0f, 0f, 0f);
                    FloatVector3 v3 = new FloatVector3(0f, 0f, 0f);

                    double val = raster.Value[row, col];
                    // Cannot compute polygon ... make the best guess
                    if (col >= numCols - 1 || row <= 0)
                    {
                        if (col >= numCols - 1 && row <= 0)
                        {
                            v1.Z = (float)val;
                            v2.Z = (float)val;
                            v3.Z = (float)val;
                        }
                        else if (col >= numCols - 1)
                        {
                            v1.Z = (float)raster.Value[row, col - 1];        // 3 - 2
                            v2.Z = (float)raster.Value[row - 1, col];        // | /
                            v3.Z = (float)raster.Value[row - 1, col - 1];    // 1   *
                        }
                        else if (row <= 0)
                        {
                            v1.Z = (float)raster.Value[row + 1, col];         //  3* 2
                            v2.Z = (float)raster.Value[row, col + 1];         //  | /
                            v3.Z = (float)val;                         //  1
                        }
                    }
                    else
                    {
                        v1.Z = (float)val;                              //  3 - 2
                        v2.Z = (float)raster.Value[row - 1, col + 1];          //  | /
                        v3.Z = (float)raster.Value[row - 1, col];              //  1*
                    }

                    // Test for no-data values and don't calculate hillshade in that case
                    if (v1.Z == noData || v2.Z == noData || v3.Z == noData)
                    {
                        hillshade[row][col] = -1; // should never be negative otherwise.
                        continue;
                    }
                    // Apply the Conversion Factor to put elevation into the same range as lat/lon
                    v1.Z = v1.Z * elevationFactor * extrusion;
                    v2.Z = v2.Z * elevationFactor * extrusion;
                    v3.Z = v3.Z * elevationFactor * extrusion;

                    // Complete the vectors using the latitude/longitude coordinates
                    v1.X = aff[0] + aff[1] * col + aff[2] * row;
                    v1.Y = aff[3] + aff[4] * col + aff[5] * row;

                    v2.X = aff[0] + aff[1] * (col + 1) + aff[2] * (row + 1);
                    v2.Y = aff[3] + aff[4] * (col + 1) + aff[5] * (row + 1);

                    v3.X = aff[0] + aff[1] * col + aff[2] * (row + 1);
                    v3.Y = aff[3] + aff[4] * col + aff[5] * (row + 1);

                    // We need two direction vectors in order to obtain a cross product
                    FloatVector3 dir2 = FloatVector3.Subtract(v2, v1); // points from 1 to 2
                    FloatVector3 dir3 = FloatVector3.Subtract(v3, v1); // points from 1 to 3


                    FloatVector3 cross = FloatVector3.CrossProduct(dir3, dir2); // right hand rule - cross direction should point into page... reflecting more if light direction is in the same direction

                    // Normalizing this vector ensures that this vector is a pure direction and won't affect the intensity
                    cross.Normalize();

                    // Hillshade now has an "intensity" modifier that should be applied to the R, G and B values of the color found at each pixel.
                    hillshade[row][col] = FloatVector3.Dot(cross, lightDirection) * lightIntensity + ambientIntensity;

                }
                pm.CurrentValue = row;
            }
            pm.Reset();
            // Setting this indicates that a hillshade has been created more recently than characteristics have been changed.
            shadedRelief.HasChanged = false;
            return hillshade;
        }
示例#16
0
        private void CreateUniqueCategories(string fieldName, IAttributeSource source, ICancelProgressHandler progressHandler)
        {
            Breaks = GetUniqueValues(fieldName, source, progressHandler);
            
            string fieldExpression = "[" + fieldName.ToUpper() + "]";
            ClearCategories();

            bool isStringField = CheckFieldType(fieldName, source);
            
 
            ProgressMeter pm = new ProgressMeter(progressHandler, "Building Feature Categories", Breaks.Count);
            
            List<double> sizeRamp = GetSizeSet(Breaks.Count);
            List<Color> colorRamp = GetColorSet(Breaks.Count);
            for (int colorIndex = 0; colorIndex < Breaks.Count; colorIndex++)
            {
                Break brk = Breaks[colorIndex];
                //get the color for the category
                Color randomColor = colorRamp[colorIndex];
                double size = sizeRamp[colorIndex];
                IFeatureCategory cat = CreateNewCategory(randomColor, size) as IFeatureCategory;
                if (cat != null)
                {
                    //cat.SelectionSymbolizer = _selectionSymbolizer.Copy();
                    cat.LegendText = brk.Name;
                    if (isStringField)
                        cat.FilterExpression = fieldExpression + "= '" + brk.Name.Replace("'", "''") + "'";
                    else
                        cat.FilterExpression = fieldExpression + "=" + brk.Name;

                    AddCategory(cat);
                }

                colorIndex++;
                pm.CurrentValue = colorIndex;
            }
            pm.Reset();
            
            
        }
示例#17
0
        /// <summary>
        /// Creates a bitmap from this raster using the specified rasterSymbolizer
        /// </summary>
        /// <param name="raster">The raster to draw to a bitmap</param>
        /// <param name="rasterSymbolizer">The raster symbolizer to use for assigning colors</param>
        /// <param name="bitmap">This must be an Format32bbpArgb bitmap that has already been saved to a file so that it exists.</param>
        /// <param name="progressHandler">The progress handler to use.</param>
        /// <returns>A System.Drawing.Bitmap if the operation was successful or null.</returns>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public static void DrawToBitmap(this IRaster raster, IRasterSymbolizer rasterSymbolizer, Bitmap bitmap, IProgressHandler progressHandler)
        {
         
            System.Drawing.Imaging.BitmapData bmpData;
            
            if (rasterSymbolizer == null)
            {
                throw new NullLogException("rasterSymbolizer");
            }

            if (rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            Rectangle rect = new Rectangle(0, 0, raster.NumColumns, raster.NumRows);
            try
            {
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            catch(Exception ex)
            {
                string originalError = ex.ToString();
                // if they have not saved the bitmap yet, it can cause an exception
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                ms.Position = 0;
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                // any further exceptions should simply throw exceptions to allow easy debugging
            }

            int numBytes = bmpData.Stride * bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            bool useHillShade = false;
            float[][] hillshade = rasterSymbolizer.HillShade;
            if (rasterSymbolizer.ShadedRelief.IsUsed)
            {
                hillshade = rasterSymbolizer.HillShade;
                useHillShade = true;
            }
            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, "Recreating Bitmap", raster.NumRows);

            try
            {
                for (int row = 0; row < raster.NumRows; row++)
                {
                    for (int col = 0; col < raster.NumColumns; col++)
                    {
                        // use the colorbreaks to calculate the colors
                        pixelColor = rasterSymbolizer.GetColor(raster.Value[row, col]);

                        // control transparency here
                        float alpha = rasterSymbolizer.Opacity * 255f;
                        if (alpha > 255f) alpha = 255f;
                        if (alpha < 0f) alpha = 0f;
                        byte a = Convert.ToByte(alpha);
                        byte g;
                        byte r;
                        byte b;
                        if (useHillShade && hillshade != null)
                        {
                            if (hillshade[row][col] == -1 || float.IsNaN(hillshade[row][col]))
                            {
                                pixelColor = rasterSymbolizer.NoDataColor;
                                r = pixelColor.R;
                                g = pixelColor.G;
                                b = pixelColor.B;
                            }
                            else
                            {
                                float red = pixelColor.R * hillshade[row][col];
                                float green = pixelColor.G * hillshade[row][col];
                                float blue = pixelColor.B * hillshade[row][col];
                                if (red > 255f) red = 255f;
                                if (green > 255f) green = 255f;
                                if (blue > 255f) blue = 255f;
                                if (red < 0f) red = 0f;
                                if (green < 0f) green = 0f;
                                if (blue < 0f) blue = 0f;
                                b = Convert.ToByte(blue);
                                r = Convert.ToByte(red);
                                g = Convert.ToByte(green);

                            }
                        }
                        else
                        {
                            r = pixelColor.R;
                            g = pixelColor.G;
                            b = pixelColor.B;
                        }

                        int offset = row * bmpData.Stride + col * 4;
                        rgbData[offset] = b;
                        rgbData[offset + 1] = g;
                        rgbData[offset + 2] = r;
                        rgbData[offset + 3] = a;
                    }
                    pm.CurrentValue = row;
                }
            }
            catch
            {
                System.Diagnostics.Debug.WriteLine(" Unable to write data to raster.");
            }
            pm.Reset();
            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother mySmoother = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = mySmoother.Smooth();
            }


            // Copy the values back into the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
示例#18
0
        // ------------------------------------ IN RAM ONLY ------------------------------------------------------------
        /// <summary>
        /// Gets the statistics all the values, but only if this raster is InRam and fully windowed.  Statistics from a file based
        /// raster will require casting to the appropriate file type.
        /// </summary>
        public override void GetStatistics()
        {
            if (IsInRam == false || this.IsFullyWindowed() == false)
            {
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }
            ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CalculatingStatistics, NumRows);

            short min = short.MaxValue;
            short max = short.MinValue;

            double total = 0;
            double sqrTotal = 0;
            int count = 0;

            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumColumns; col++)
                {
                    short val = Data[row][col];

                    if (val.CompareTo(_shortNoDataValue) != 0)
                    {
                        if (val.CompareTo(max) > 0) max = val;
                        if (val.CompareTo(min) < 0) min = val;
                        double dblVal = val;
                        total += dblVal;
                        sqrTotal += dblVal * dblVal;
                        count++;
                    }
                }
                pm.CurrentValue = row;
            }
            Minimum = min;
            Maximum = max;
            NumValueCells = count;
            StdDeviation = (short)Math.Sqrt((sqrTotal / NumValueCells) - (total / NumValueCells) * (total / NumValueCells));
            pm.Reset();
        }
示例#19
0
        /// <summary>
        /// Creates a bitmap using only the colorscheme, even if a hillshade was specified
        /// </summary>
        /// <param name="raster">The Raster containing values that need to be drawn to the bitmap as a color scheme.</param>
        /// <param name="bitmap">The bitmap to edit.  Ensure that this has been created and saved at least once</param>
        /// <param name="progressHandler">An IProgressHandler</param>
        /// <param name="rasterSymbolizer">The raster symbolizer to use</param>
        /// <exception cref="MapWindow.Main.NullLogException">rasterSymbolizer cannot be null</exception>
        public static void PaintColorSchemeToBitmap(this IRaster raster, IRasterSymbolizer rasterSymbolizer, Bitmap bitmap, IProgressHandler progressHandler)
        {
         
            System.Drawing.Imaging.BitmapData bmpData;
            int numRows = raster.NumRows;
            int numColumns = raster.NumColumns;
            if (rasterSymbolizer == null)
            {
                throw new NullLogException("rasterSymbolizer");
            }

            if (rasterSymbolizer.Scheme.Categories == null || rasterSymbolizer.Scheme.Categories.Count == 0) return;

            // Create a new Bitmap and use LockBits combined with Marshal.Copy to get an array of bytes to work with.

            Rectangle rect = new Rectangle(0, 0, numColumns, numRows);
            try
            {
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            catch
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                ms.Position = 0;
                bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            int numBytes = bmpData.Stride * bmpData.Height;
            byte[] rgbData = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbData, 0, numBytes);

            Color pixelColor;
            ProgressMeter pm = new ProgressMeter(progressHandler, MessageStrings.PaintingColorScheme, raster.NumRows);
            if (numRows * numColumns < 100000) pm.StepPercent = 50;
            if (numRows * numColumns < 500000) pm.StepPercent = 10;
            if (numRows * numColumns < 1000000) pm.StepPercent = 5;
            for (int row = 0; row < numRows; row++)
            {
                for (int col = 0; col < numColumns; col++)
                {
                    // use the colorbreaks to calculate the colors
                    pixelColor = rasterSymbolizer.GetColor(raster.Value[row, col]);

                    // control transparency here
                    int alpha = Convert.ToInt32(rasterSymbolizer.Opacity * 255);
                    if (alpha > 255) alpha = 255;
                    if (alpha < 0) alpha = 0;
                    byte a = (byte)alpha;


                    byte r = pixelColor.R;
                    byte g = pixelColor.G;
                    byte b = pixelColor.B;

                    int offset = row * bmpData.Stride + col * 4;
                    rgbData[offset] = b;
                    rgbData[offset + 1] = g;
                    rgbData[offset + 2] = r;
                    rgbData[offset + 3] = a;
                }
                pm.CurrentValue = row;
            }
            pm.Reset();
            if (rasterSymbolizer.IsSmoothed)
            {
                Smoother mySmoother = new Smoother(bmpData, rgbData, progressHandler);
                rgbData = mySmoother.Smooth();
            }


            // Copy the values back into the bitmap
            System.Runtime.InteropServices.Marshal.Copy(rgbData, 0, bmpData.Scan0, numBytes);
            bitmap.UnlockBits(bmpData);
            rasterSymbolizer.ColorSchemeHasUpdated = true;
            return;
        }
        /// <summary>
        /// Creates a new raster with the specified cell size.  If the cell size
        /// is zero, this will default to the shorter of the width or height
        /// divided by 256.  If the cell size produces a raster that is greater
        /// than 8,000 pixels in either dimension, it will be re-sized to
        /// create an 8,000 length or width raster.
        /// </summary>
        /// <param name="fs">The featureset to convert to a raster</param>
        /// <param name="cellSize">The double extent of the cell.</param>
        /// <param name="fieldName">The integer field index of the file.</param>
        /// <param name="destFilename">The filename of the raster to create</param>
        /// <param name="driverCode">The optional GDAL driver code to use if using GDAL 
        /// for a format that is not discernable from the file extension.  An empty string
        ///  is usually perfectly acceptable here.</param>
        /// <param name="options">For GDAL rasters, they can be created with optional parameters
        ///  passed in as a string array.  In most cases an empty string is perfectly acceptable.</param>
        /// <param name="progressHandler">An interface for handling the progress messages.</param>
        /// <returns>Generates a raster from the vectors.</returns>
        public static IRaster ToRaster(IFeatureSet fs, ref double cellSize, string fieldName, string destFilename, string driverCode, string[] options, IProgressHandler progressHandler)
        {
            IEnvelope env = fs.Envelope;
            if(cellSize == 0)
            {
                if(fs.Envelope.Width < fs.Envelope.Height)
                {
                    cellSize = env.Width/256;
                }
                else
                {
                    cellSize = env.Height/256;
                }
            }
            int w = (int)Math.Ceiling(env.Width/cellSize);
            if (w > 8000)
            {
                w = 8000;
                cellSize = env.Width/8000;
            }
            int h = (int) Math.Ceiling(env.Height/cellSize);
            if (h > 8000)
            {
                cellSize = env.Height/8000;
                h = 8000;
            }
            Bitmap bmp = new Bitmap(w, h);
            Graphics g = Graphics.FromImage(bmp);
            g.Clear(Color.Transparent);
            g.SmoothingMode = SmoothingMode.None;
            g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
            g.InterpolationMode = InterpolationMode.NearestNeighbor;
            Hashtable colorTable;
            MapArgs args = new MapArgs(new Rectangle(0, 0, w, h), env, g);

            switch (fs.FeatureType)
            {
                case FeatureTypes.Polygon:
                    {
                        MapPolygonLayer mpl = new MapPolygonLayer(fs);
                        PolygonScheme ps = new PolygonScheme();
                        colorTable = ps.GenerateUniqueColors(fs, fieldName);
                        mpl.Symbology = ps;
                        mpl.DrawRegions(args, new List<IEnvelope> {env});
                    }
                    break;
                case FeatureTypes.Line:
                    {
                        MapLineLayer mpl = new MapLineLayer(fs);
                        LineScheme ps = new LineScheme();
                        colorTable = ps.GenerateUniqueColors(fs, fieldName);
                        mpl.Symbology = ps;
                        mpl.DrawRegions(args, new List<IEnvelope> { env });
                    }
                    break;
                default:
                    {
                        MapPointLayer mpl = new MapPointLayer(fs);
                        PointScheme ps = new PointScheme();
                        colorTable = ps.GenerateUniqueColors(fs, fieldName);
                        mpl.Symbology = ps;
                        mpl.DrawRegions(args, new List<IEnvelope> { env });
                    }
                    break;
            }
            Type tp = fieldName == "FID" ? typeof(int) : fs.DataTable.Columns[fieldName].DataType;
           
            if (tp == typeof(string)) tp = typeof (double); // We will try to convert to double if it is a string
            Raster output = new Raster();
            MWImageData image = new MWImageData(bmp, env);
            ProgressMeter pm = new ProgressMeter(progressHandler, "Converting To Raster Cells", h);
            
            output.CreateNew(destFilename, driverCode, w, h, 1, tp, options);
            output.Bounds = new RasterBounds(h, w, env);
            List<RcIndex> locations = new List<RcIndex>();
            List<string> failureList = new List<string>();
            for (int row = 0; row < h; row++)
            {
                for (int col = 0; col < w; col++)
                {
                    Color c = image.GetColor(row, col);
                    if (c.A == 0)
                    {
                        output.Value[row, col] = output.NoDataValue;
                    }
                    else
                    {
                        if (colorTable.ContainsKey(c) == false)
                        {
                            if (c.A < 125)
                            {
                                output.Value[row, col] = output.NoDataValue;
                                continue;
                            }
                            // Use a color matching distance to pick the closest member
                            object val = GetCellValue(w, h, row, col, image, c, colorTable, locations);

                            output.Value[row, col] = GetDouble(val, failureList);
                        }
                        else
                        {
                            
                            output.Value[row, col] = GetDouble(colorTable[c], failureList);
                        }

                    }


                }
                pm.CurrentValue = row;
            }
            const int maxIterations = 5;
            int iteration = 0;
            while(locations.Count > 0)
            {
                List<RcIndex> newLocations = new List<RcIndex>();
                foreach (RcIndex location in locations)
                {
                    object val = GetCellValue(w, h, location.Row, location.Column, image, image.GetColor(location.Row, location.Column), colorTable, newLocations);
                    output.Value[location.Row, location.Column] = GetDouble(val, failureList);
                }
                locations = newLocations;
                iteration++;
                if(iteration > maxIterations) break;
            }

            pm.Reset();
            return output;
        }
        /// <summary>
        /// This creates a completely new raster from the windowed domain on the original raster.  This new raster
        /// will have a separate source file, and values like NumRowsInFile will correspond to the newly created file.
        /// All the values will be copied to the new source file.  If inRam = true and the new raster is small enough,
        /// the raster values will be loaded into memory.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="startRow">The 0 based integer index of the top row to copy from this raster.  If this raster is itself a window, 0 represents the startRow from the file.</param>
        /// <param name="endRow">The integer index of the bottom row to copy from this raster.  The largest allowed value is NumRows - 1.</param>
        /// <param name="startColumn">The 0 based integer index of the leftmost column to copy from this raster.  If this raster is a window, 0 represents the startColumn from the file.</param>
        /// <param name="endColumn">The 0 based integer index of the rightmost column to copy from this raster.  The largest allowed value is NumColumns - 1</param>
        /// <param name="copyValues">If this is true, the valeus are saved to the file.  If this is false and the data can be loaded into Ram, no file handling is done.  Otherwise, a file of NoData values is created.</param>
        /// <param name="inRam">Boolean.  If this is true and the window is small enough, a copy of the values will be loaded into memory.</param>
        /// <returns>An implementation of IRaster</returns>
        public new IRaster CopyWindow(string filename, int startRow, int endRow, int startColumn, int endColumn,
                                  bool copyValues, bool inRam)
        {
            int numCols = endColumn - startColumn + 1;
            int numRows = endRow - startRow + 1;


            BinaryDoubleRaster result = new BinaryDoubleRaster(filename, numCols, numRows, inRam);

            result.Projection = Projection;

            // The affine coefficients defining the world file are the same except that they are translated over.  Only the position of the
            // upper left corner changes.  Everything else is the same as the previous raster.

            // X = [0] + [1] * column + [2] * row;
            // Y = [3] + [4] * column + [5] * row;
            result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, new double[6]);
            result.Bounds.AffineCoefficients[0] = Bounds.AffineCoefficients[0] +
                                                  Bounds.AffineCoefficients[1]*startColumn +
                                                  Bounds.AffineCoefficients[2]*startRow;
            result.Bounds.AffineCoefficients[1] = Bounds.AffineCoefficients[1];
            result.Bounds.AffineCoefficients[2] = Bounds.AffineCoefficients[2];
            result.Bounds.AffineCoefficients[3] = Bounds.AffineCoefficients[3] +
                                                  Bounds.AffineCoefficients[4]*startColumn +
                                                  Bounds.AffineCoefficients[5]*startRow;
            result.Bounds.AffineCoefficients[4] = Bounds.AffineCoefficients[4];
            result.Bounds.AffineCoefficients[5] = Bounds.AffineCoefficients[5];

            if (IsInRam)
            {
                ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CopyingValues, numRows);
                // copy values directly using both data structures
                for (int row = 0; row < numRows; row++)
                {
                    for (int col = 0; col < numCols; col++)
                    {
                        result.Data[row][col] = Data[startRow + row][startColumn + col];
                    }
                    pm.CurrentValue = row;
                }
                pm.Reset();

                if (result.IsInRam == false)
                {
                    // Force the result raster to write itself to a file and then purge its memory.
                    result.Write(filename);
                    result.Data = null;
                }
            }
            else
            {
                if (result.IsInRam)
                {
                    // the source is not in memory, so we just read the values from the file as if opening it directly from the file.
                    result.OpenWindow(Filename, startRow, endRow, startColumn, endColumn, true);
                }
                else
                {
                    // Both sources are file based so we basically copy rows of bytes from one to the other.
                    FileStream source = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                    result.WriteHeader(filename);
                    FileStream dest = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None);
                    source.Seek(HeaderSize, SeekOrigin.Begin);
                    BinaryReader bReader = new BinaryReader(source);
                    BinaryWriter bWriter = new BinaryWriter(dest);
                    ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CopyingValues, numRows);
                    // copy values directly using both data structures
                    source.Seek(NumColumnsInFile*startRow*ByteSize, SeekOrigin.Current);
                    for (int row = 0; row < numRows; row++)
                    {
                        source.Seek(numCols*ByteSize, SeekOrigin.Current);
                        byte[] rowData = bReader.ReadBytes(ByteSize*numCols);
                        bWriter.Write(rowData);
                        source.Seek(NumColumnsInFile - endColumn + 1, SeekOrigin.Current);
                        bWriter.Flush();
                        pm.CurrentValue = row;
                    }
                    pm.Reset();
                }
            }
            return result;
        }
示例#22
0
        /// <summary>
        /// This assumes that the base image has been written to the file.  This will now attempt to calculate
        /// the down-sampled images.
        /// </summary>
        /// <param name="progressHandler"></param>
        public void CreatePyramids2(IProgressHandler progressHandler)
        {
           
            double count = _header.ImageHeaders[0].NumRows;
            ProgressMeter pm = new ProgressMeter(progressHandler, "Generating Pyramids", count);
            int prog = 0;
            for(int scale = 0; scale < _header.ImageHeaders.Length-1; scale++)
            {
                PyramidImageHeader ph = _header.ImageHeaders[scale];
                int rows = ph.NumRows;
                int cols = ph.NumColumns;
                // Horizontal Blur Pass
                byte[] r1 = ReadWindow(0, 0, 1, cols, scale);
                byte[] r2 = ReadWindow(1, 0, 1, cols, scale);

                byte[] vals = Blur(null, r1, r2);
                vals = DownSample(vals);
                WriteWindow(vals, 0, 0, 1, cols/2, scale + 1);
                prog++;
                pm.CurrentValue = prog;

                byte[] r3 = ReadWindow(2, 0, 1, cols, scale);
                vals = Blur(r1, r2, r3);
                vals = DownSample(vals);
                WriteWindow(vals, 1, 0, 1, cols / 2, scale + 1);
                prog++;
                pm.CurrentValue = prog;
                for(int row = 3; row < rows -1; row++)
                {
                    
                    r1 = r2;
                    r2 = r3;
                    r3 = ReadWindow(row, 0, 1, cols, scale);
                    prog++;
                    pm.CurrentValue = prog;
                    if (row % 2 == 1) continue;
                    vals = Blur(r1, r2, r3);
                    vals = DownSample(vals);
                    WriteWindow(vals, row/2-1, 0, 1, cols/2, scale + 1);
                    
                    
                }
                if ((rows - 1)%2 == 0)
                {
                    vals = Blur(r2, r3, r2);
                    vals = DownSample(vals);
                    WriteWindow(vals, rows / 2 - 1, 0, 1, cols / 2, scale + 1);
                }
                
                prog++;
                pm.CurrentValue = prog;
            }
            pm.Reset();
            
        }
        /// <summary>
        /// This creates a window from this raster.  The window will still save to the same
        /// source file, but only has access to a small window of data, so it can be loaded like a buffer.
        /// The georeferenced extents will be for the new window, not the original raster.  startRow and endRow
        /// will exist in the new raster, however, so that it knows how to copy values back to the original raster.
        /// </summary>
        /// <param name="startRow">The 0 based integer index of the top row to get from this raster.  If this raster is itself a window, 0 represents the startRow from the file.</param>
        /// <param name="endRow">The integer index of the bottom row to get from this raster.  The largest allowed value is NumRows - 1.</param>
        /// <param name="startColumn">The 0 based integer index of the leftmost column to get from this raster.  If this raster is a window, 0 represents the startColumn from the file.</param>
        /// <param name="endColumn">The 0 based integer index of the rightmost column to get from this raster.  The largest allowed value is NumColumns - 1</param>
        /// <param name="inRam">Boolean.  If this is true and the window is small enough, a copy of the values will be loaded into memory.</param>
        /// <returns>An implementation of IRaster</returns>
        public new IRaster GetWindow(int startRow, int endRow, int startColumn, int endColumn, bool inRam)
        {
            int numCols = endColumn - startColumn + 1;
            int numRows = endRow - startRow + 1;
            BinaryDoubleRaster result = new BinaryDoubleRaster();
            result.Filename = Filename;
            result.Projection = Projection;
            result.NumRows = endRow - startRow + 1;
            result.NumColumns = endColumn - startColumn + 1;
            result.NumRowsInFile = NumRowsInFile;
            result.NumColumnsInFile = NumColumnsInFile;
            result.NoDataValue = NoDataValue;
            result.StartColumn = startColumn + StartColumn;
            result.StartRow = startRow + StartRow;
            result.EndColumn = endColumn + StartColumn;
            result.EndRow = EndRow + StartRow;

            // Reposition the "raster" so that it matches the window, not the whole raster
            // X = [0] + [1] * column + [2] * row;
            // Y = [3] + [4] * column + [5] * row;
            result.Bounds = new RasterBounds(result.NumRows, result.NumColumns, new double[6]);
            result.Bounds.AffineCoefficients[0] = Bounds.AffineCoefficients[0] +
                                                  Bounds.AffineCoefficients[1]*startColumn +
                                                  Bounds.AffineCoefficients[2]*startRow;
            result.Bounds.AffineCoefficients[1] = Bounds.AffineCoefficients[1];
            result.Bounds.AffineCoefficients[2] = Bounds.AffineCoefficients[2];
            result.Bounds.AffineCoefficients[3] = Bounds.AffineCoefficients[3] +
                                                  Bounds.AffineCoefficients[4]*startColumn +
                                                  Bounds.AffineCoefficients[5]*startRow;
            result.Bounds.AffineCoefficients[4] = Bounds.AffineCoefficients[4];
            result.Bounds.AffineCoefficients[5] = Bounds.AffineCoefficients[5];


            // Now we can copy any values currently in memory.
            if (IsInRam)
            {
                //result.ReadHeader(Filename);
                result.Data = new double[numRows][];
                ProgressMeter pm = new ProgressMeter(ProgressHandler, MessageStrings.CopyingValues, endRow);
                pm.StartValue = startRow;
                // copy values directly using both data structures
                for (int row = 0; row < numRows; row++)
                {
                    result.Data[row] = new double[numCols];
                    for (int col = 0; col < numCols; col++)
                    {
                        result.Data[row][col] = Data[startRow + row][startColumn + col];
                    }
                    pm.CurrentValue = row;
                }
                pm.Reset();
            }
            else
                result.OpenWindow(Filename, startRow, endRow, startColumn, endColumn, inRam);
            result.Value = new DoubleValueGrid(result);
            return result;
        }
示例#24
0
        /// <summary>
        /// This tests each feature of the input  
        /// </summary>
        /// <param name="self">This featureSet</param>
        /// <param name="other">The featureSet to perform intersection with</param>
        /// <param name="joinType">The attribute join type</param>
        /// <param name="progHandler">A progress handler for status messages</param>
        /// <returns>An IFeatureSet with the intersecting features, broken down based on the join Type</returns>
        public static IFeatureSet Intersection(this IFeatureSet self, IFeatureSet other, FieldJoinType joinType, IProgressHandler progHandler)
        {
          
            IFeatureSet result = null;
            ProgressMeter pm = new ProgressMeter(progHandler, "Calculating Intersection", self.Features.Count);
            if (joinType == FieldJoinType.All)
            {
                result = CombinedFields(self, other);
                // Intersection is symetric, so only consider I X J where J <= I
                int i=0;
                foreach(IFeature selfFeature in self.Features)
                {
                    List<IFeature> potentialOthers = other.Select(selfFeature.Envelope);
                    foreach (IFeature otherFeature in potentialOthers)
                    {
                        selfFeature.Intersection(otherFeature, result, joinType);
                        
                    }
                    pm.CurrentValue = i;
                    i++;
                }
                pm.Reset();
            }
            if (joinType == FieldJoinType.LocalOnly)
            {
                result = new FeatureSet();
                result.CopyTableSchema(self);
                result.FeatureType = self.FeatureType;
                IFeature union;
                pm = new ProgressMeter(progHandler, "Calculating Union", other.Features.Count);
                if(other.Features != null && other.Features.Count > 0)
                {
                    union = other.Features[0];
                    for(int i = 1; i < other.Features.Count; i++)
                    {
                        union = union.Union(other.Features[i]);
                        pm.CurrentValue = i;
                    }
                    pm.Reset();
                    pm = new ProgressMeter(progHandler, "Calculating Intersections", self.NumRows());
                    Extent otherEnvelope = new Extent(union.Envelope);
                    for (int shp = 0; shp < self.ShapeIndices.Count; shp++)
                    {
                        if (!self.ShapeIndices[shp].Extent.Intersects(otherEnvelope)) continue;
                        IFeature selfFeature = self.GetFeature(shp);
                        selfFeature.Intersection(union, result, joinType);
                        pm.CurrentValue = shp;
                    }
                    pm.Reset();
                }

                
            }
            if (joinType == FieldJoinType.ForeignOnly)
            {
                result = new FeatureSet();
                result.CopyTableSchema(other);
                IFeature union;
                if (self.Features != null && self.Features.Count > 0)
                {
                    pm = new ProgressMeter(progHandler, "Calculating Union", self.Features.Count);
                    union = self.Features[0];
                    for (int i = 1; i < self.Features.Count; i++)
                    {
                        union = union.Union(self.Features[i]);
                        pm.CurrentValue = i;
                    }
                    pm.Reset();
                    if (other.Features != null)
                    {
                        pm = new ProgressMeter(progHandler, "Calculating Intersection", other.Features.Count);
                        int j = 0;
                        foreach (IFeature otherFeature in other.Features)
                        {
                            IFeature test = otherFeature.Intersection(union, result, joinType);
                            if (test.BasicGeometry != null)
                            {
                                result.Features.Add(test);
                            }
                            pm.CurrentValue = j;
                            j++;
                        }
                    }
                    pm.Reset();
                }
                
                
            }
            return result;

        }
示例#25
0
        /// <summary>
        /// This will resample the cells.
        /// If the cell size is zero, this will default to the shorter of the width or height
        /// divided by 256.
        /// </summary>
        /// <param name="input1">Input Raster.</param>
        /// <param name="cellHeight">New Cell Height or Null.</param>
        /// <param name="cellWidth">New Cell Width or Null.</param>
        /// <param name="destFilename">Output Raster Name.</param>
        /// <param name="progressHandler">An interface for handling the progress messages.</param>
        /// <returns>Resampled raster.</returns>
        public static IRaster ReSample(IRaster input1,double cellHeight, double cellWidth, string destFilename, IProgressHandler progressHandler)
        {
            if (input1 == null)
                return null;

            IEnvelope envelope = input1.Bounds.Envelope;

            if (cellHeight == 0)
            {
                cellHeight = envelope.Height / 256;
            }
            if(cellWidth==0)
            {
                cellWidth = envelope.Width / 256;
            }
                
            //Calculate new number of columns and rows
            int noOfCol = Convert.ToInt32(Math.Abs(envelope.Width / cellWidth));
            int noOfRow = Convert.ToInt32(Math.Abs(envelope.Height / cellHeight));


            IRaster output = Raster.Create(destFilename, "", noOfCol, noOfRow, 1, input1.DataType, new[] { "" });
            RasterBounds bound = new RasterBounds(noOfRow, noOfCol, envelope);
            output.Bounds = bound;

            output.NoDataValue = input1.NoDataValue;

            RcIndex index1;
            int max = (output.Bounds.NumRows);
            ProgressMeter pm = new ProgressMeter(progressHandler, "ReSize Cells", max);
            //Loop throug every cell for new value

            for (int i = 0; i < max; i++)
            {
                for (int j = 0; j < output.Bounds.NumColumns; j++)
                {
                    //Projet the cell position to Map
                    Coordinate cellCenter = output.CellToProj(i, j);
                    index1 = input1.ProjToCell(cellCenter);

                    double val;
                    if (index1.Row <= input1.EndRow && index1.Column <= input1.EndColumn && index1.Row > -1 && index1.Column > -1)
                    {
                        if (input1.Value[index1.Row, index1.Column] == input1.NoDataValue)
                            val = output.NoDataValue;
                        else
                            val = input1.Value[index1.Row, index1.Column];
                    }
                    else
                        val = output.NoDataValue;

                    output.Value[i, j] = val;
                }
                pm.CurrentPercent = i;
            }

            output.Save();
            pm.Reset();
            return output;
        }