Ejemplo n.º 1
0
 /// <summary>
 /// Creates a new instance of Smoother
 /// </summary>
 public Smoother(BitmapData inBmpData, byte[] inRgbData, IProgressHandler progHandler)
 {
     _bmpData = inBmpData;
     _rgbData = inRgbData;
     _result = new byte[inRgbData.Length];
     pm = new ProgressMeter(progHandler, "Smoothing Image", inBmpData.Height);
 }
Ejemplo n.º 2
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;
        }
Ejemplo n.º 3
0
 private void Configure()
 {
     _indexMode = false; // this is false unless we are loading it from a specific shapefile case.
     _featureLookup = new Dictionary<DataRow, IFeature>();
     _progressHandler = Components.DataManager.DefaultDataManager.ProgressHandler;
     _progressMeter = new ProgressMeter(_progressHandler);
     _features = new FeatureList(this);
     _features.FeatureAdded += FeaturesFeatureAdded;
     _features.FeatureRemoved += FeaturesFeatureRemoved;
     _dataTable = new DataTable();
 }
Ejemplo n.º 4
0
        /// <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();
        }
Ejemplo n.º 5
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 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();

            
    

        }
Ejemplo n.º 6
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;
        }
Ejemplo n.º 7
0
        /// <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>
        /// Obtains only the statistics for the small window specified by startRow, endRow etc.
        /// </summary>
        public new void GetWindowStatistics()
        {
            if (IsInRam)
            {
                // don't bother to do file calculations if the whole raster is in memory
                base.GetWindowStatistics();
                return;
            }

            // The window was not in memory, so go ahead and get statistics for the window from the file.

            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read, NumColumns*ByteSize);
            BinaryReader br = new BinaryReader(fs);
            fs.Seek(HeaderSize, SeekOrigin.Begin);
            ProgressMeter pm = new ProgressMeter(ProgressHandler,
                                                 "Calculating Statistics for the entire raster " + Filename, NumRows);


            double total = 0;
            double sqrTotal = 0;
            int count = 0;
            int byteSize = ByteSize; // cache this for faster calcs
            double min = double.MaxValue;
            double max = double.MinValue;
            fs.Seek(StartRow*ByteSize*NumColumnsInFile, SeekOrigin.Current); // To top edge of the Window


            for (int row = 0; row < NumRows; row++)
            {
                fs.Seek(StartColumn*byteSize, SeekOrigin.Current); // to the left edge of the window
                for (int col = 0; col < NumColumns; col++)
                {
                    double val = br.ReadDouble();

                    if (val != DoubleNoDataValue)
                    {
                        if (val > max) max = val;
                        if (val < min) min = val;
                        double dblVal = val;
                        total += dblVal;
                        sqrTotal += dblVal*dblVal;
                        count++;
                    }
                }
                fs.Seek(NumColumnsInFile - EndRow - 1, SeekOrigin.Current); // skip to the end of this row.
                pm.CurrentValue = row;
            }
            Minimum = min;
            Maximum = max;
            NumValueCells = count;
            StdDeviation = (float) Math.Sqrt((sqrTotal/NumValueCells) - (total/NumValueCells)*(total/NumValueCells));
            br.Close();
        }
        /// <summary>
        /// Copies the contents from the specified sourceRaster into this sourceRaster.  If both rasters are InRam, this does not affect the files.
        /// </summary>
        /// <param name="sourceRaster">The raster of values to paste into this raster.  If the CellWidth and CellHeight values do not match between the files,
        /// an exception will be thrown.  If the sourceRaster overlaps with the edge of this raster, only the intersecting region will be
        /// pasted.</param>
        /// <param name="startRow">Specifies the row in this raster where the top row of the sourceRaster will be pasted </param>
        /// <param name="startColumn">Specifies the column in this raster where the left column of the sourceRaster will be pasted.</param>
        public void PasteRaster(IRaster sourceRaster, int startRow, int startColumn)
        {
            const int byteSize = 8;

            if (sourceRaster.DataType != typeof (double))
            {
                throw new ArgumentException(
                    MessageStrings.ArgumentOfWrongType_S1_S2.Replace("%S1", "sourceRaster").Replace("%S2",
                                                                                                    "BinaryDoubleRaster"));
            }
            DoubleRaster sourceRasterT = (DoubleRaster) sourceRaster;
            if (startRow + sourceRaster.NumRows <= 0) return; // sourceRaster is above this raster
            if (startColumn + sourceRaster.NumColumns <= 0) return; // sourceRaster is left of this raster
            if (startRow > NumRows) return; // sourceRaster is below this raster
            if (startColumn > NumColumns) return; // sourceRaster is to the right of this raster
            if (sourceRaster.CellWidth != CellWidth || sourceRaster.CellHeight != CellHeight)
                throw new ArgumentException(MessageStrings.RastersNeedSameCellSize);

            // These are specified in coordinates that match the source raster
            int sourceStartColumn = 0;
            int sourceStartRow = 0;
            int destStartColumn = startColumn;
            int destStartRow = startRow;

            int numPasteColumns = sourceRaster.NumColumns;
            int numPasteRows = sourceRaster.NumRows;


            // adjust range to cover only the overlapping sections
            if (startColumn < 0)
            {
                sourceStartColumn = -startColumn;
                destStartColumn = 0;
            }
            if (startRow < 0)
            {
                sourceStartRow = -startRow;
                destStartRow = 0;
            }

            if (numPasteRows + destStartRow > NumRows) numPasteRows = (NumRows - destStartRow);
            if (numPasteColumns + destStartColumn > NumColumns) numPasteColumns = (NumColumns - destStartRow);


            if (IsInRam) // ---------------------- RAM BASED ------------------------------------------------------
            {
                if (sourceRaster.IsInRam)
                {
                    // both members are inram, so directly copy values.
                    for (int row = 0; row < numPasteRows; row++)
                    {
                        for (int col = 0; col < numPasteColumns; col++)
                        {
                            // since we are copying direct, we don't have to do a type check on T 
                            Data[destStartRow + row][destStartColumn + col] =
                                sourceRasterT.Data[sourceStartRow + row][sourceStartColumn + col];
                        }
                    }
                }
                else
                {
                    FileStream fs = new FileStream(sourceRaster.Filename, FileMode.Open, FileAccess.Write,
                                                   FileShare.None, (numPasteColumns)*byteSize);
                    ProgressMeter pm = new ProgressMeter(ProgressHandler,
                                                         MessageStrings.ReadingValuesFrom_S.Replace("%S",
                                                                                                    sourceRaster.
                                                                                                        Filename),
                                                         numPasteRows);
                    fs.Seek(HeaderSize, SeekOrigin.Begin);

                    // Position the binary reader at the top of the "sourceRaster"
                    fs.Seek(sourceStartRow*sourceRaster.NumColumnsInFile*byteSize, SeekOrigin.Current);
                    BinaryReader br = new BinaryReader(fs);


                    for (int row = 0; row < numPasteRows; row++)
                    {
                        // Position the binary reader at the beginning of the sourceRaster
                        fs.Seek(byteSize*sourceStartColumn, SeekOrigin.Current);

                        for (int col = 0; col < numPasteColumns; col++)
                        {
                            Data[destStartRow + row][destStartColumn + col] = br.ReadDouble();
                        }
                        pm.CurrentValue = row;
                        fs.Seek(byteSize*(NumColumnsInFile - sourceStartColumn - numPasteColumns), SeekOrigin.Current);
                    }


                    br.Close();
                }
                // The statistics will have changed with the newly pasted data involved
                GetStatistics();
            }
            else // ----------------------------------------- FILE BASED ---------------------------------
            {
                FileStream writefs = new FileStream(Filename, FileMode.Open, FileAccess.Write, FileShare.None,
                                                    NumColumns*byteSize);
                BinaryWriter bWriter = new BinaryWriter(writefs);

                ProgressMeter pm = new ProgressMeter(ProgressHandler,
                                                     MessageStrings.WritingValues_S.Replace("%S", Filename),
                                                     numPasteRows);


                writefs.Seek(HeaderSize, SeekOrigin.Begin);
                writefs.Seek(destStartRow*NumColumnsInFile*byteSize, SeekOrigin.Current);
                    // advance to top of paste window area

                if (sourceRaster.IsInRam)
                {
                    // we can just write values


                    for (int row = 0; row < numPasteColumns; row++)
                    {
                        // Position the binary reader at the beginning of the sourceRaster
                        writefs.Seek(byteSize*destStartColumn, SeekOrigin.Current);

                        for (int col = 0; col < numPasteColumns; col++)
                        {
                            double val = sourceRasterT.Data[sourceStartRow + row][sourceStartColumn + col];
                            bWriter.Write(val);
                        }
                        pm.CurrentValue = row;
                        writefs.Seek(byteSize*(NumColumnsInFile - destStartColumn - numPasteColumns), SeekOrigin.Current);
                    }
                }
                else
                {
                    // Since everything is handled from a file, we don't have to type check.  Just copy the bytes.

                    FileStream readfs = new FileStream(sourceRaster.Filename, FileMode.Open, FileAccess.Read,
                                                       FileShare.Read, numPasteColumns*byteSize);
                    BinaryReader bReader = new BinaryReader(readfs);
                    readfs.Seek(HeaderSize, SeekOrigin.Begin);
                    readfs.Seek(sourceStartRow*sourceRaster.NumColumnsInFile*byteSize, SeekOrigin.Current);
                        // advances to top of paste window area

                    for (int row = 0; row < numPasteRows; row++)
                    {
                        readfs.Seek(sourceStartColumn*byteSize, SeekOrigin.Current);
                        writefs.Seek(destStartColumn*byteSize, SeekOrigin.Current);
                        byte[] rowData = bReader.ReadBytes(numPasteColumns*byteSize);
                        bWriter.Write(rowData);
                        readfs.Seek(sourceRaster.NumColumnsInFile - sourceStartColumn - numPasteColumns,
                                    SeekOrigin.Current);
                        writefs.Seek(NumColumnsInFile - destStartColumn - numPasteColumns, SeekOrigin.Current);
                    }
                    bReader.Close();
                }
                bWriter.Close();
            }
        }
        /// <summary>
        /// Gets the statistics for the entire file, not just the window portion specified for this raster.
        /// </summary>
        public override void GetStatistics()
        {
            if (IsInRam && this.IsFullyWindowed())
            {
                // The in-memory version of this is a little faster, so use it, but only if we can.
                base.GetStatistics();
                return;
            }
            // If we get here, we either need to check the file because no data is in memory or because
            // the window that is in memory does not have all the values.

            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            fs.Seek(HeaderSize, SeekOrigin.Begin);
            ProgressMeter pm = new ProgressMeter(ProgressHandler,
                                                 "Calculating Statistics for the entire raster " + Filename,
                                                 NumRowsInFile);
            double min = double.MaxValue;
            double max = double.MinValue;

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

            for (int row = 0; row < NumRowsInFile; row++)
            {
                for (int col = 0; col < NumColumnsInFile; col++)
                {
                    double val = br.ReadDouble();

                    if (val != DoubleNoDataValue)
                    {
                        if (val > max) max = val;
                        if (val < min) min = val;

                        total += val;
                        sqrTotal += val*val;
                        count++;
                    }
                }
                pm.CurrentValue = row;
            }
            Minimum = min;
            Maximum = max;
            NumValueCells = count;
            StdDeviation = (float) Math.Sqrt((sqrTotal/NumValueCells) - (total/NumValueCells)*(total/NumValueCells));
            br.Close();
        }
        /// <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;
        }
        /// <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;
        }
Ejemplo n.º 13
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;
        }
Ejemplo n.º 14
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;
        }
Ejemplo n.º 15
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;

        }
        /// <summary>
        /// Reads the the contents for the "window" specified by the start and end values
        /// for the rows and columns.
        /// </summary>
        public void Read()
        {
            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read, NumColumns*ByteSize);
            ProgressMeter pm = new ProgressMeter(ProgressHandler,
                                                 MessageStrings.ReadingValuesFrom_S.Replace("%S", Filename), NumRows);
            fs.Seek(HeaderSize, SeekOrigin.Begin);

            // Position the binary reader at the top of the "window"
            fs.Seek(StartRow*NumColumnsInFile*ByteSize, SeekOrigin.Current);
            BinaryReader br = new BinaryReader(fs);

            double total = 0;
            double sqrTotal = 0;
            Data = new double[NumRows][];


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

            for (int row = 0; row < NumRows; row++)
            {
                Data[row] = new double[NumColumns];


                // Position the binary reader at the beginning of the window
                fs.Seek(4*StartColumn, SeekOrigin.Current);

                for (int col = 0; col < NumColumns; col++)
                {
                    double val = br.ReadDouble();

                    Data[row][col] = val;

                    if (val != DoubleNoDataValue)
                    {
                        if (val > max) max = val;
                        if (val < min) min = val;
                        total += val;
                        sqrTotal += val*val;
                        NumValueCells++;
                    }
                }
                pm.CurrentValue = row;
                fs.Seek(ByteSize*(NumColumnsInFile - EndColumn - 1), SeekOrigin.Current);
            }
            Maximum = max;
            Minimum = min;

            StdDeviation = Math.Sqrt((sqrTotal/NumValueCells) - (total/NumValueCells)*(total/NumValueCells));

            br.Close();
        }
Ejemplo n.º 17
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();
        }
        /// <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();
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Obtains only the statistics for the small window specified by startRow, endRow etc.
        /// this only works if the window is also InRam.
        /// </summary>
        public void GetWindowStatistics()
        {
            if (IsInRam == false)
            {
                throw new ArgumentException(MessageStrings.RasterRequiresCast);
            }


            ProgressMeter pm = new ProgressMeter(ProgressHandler, "Calculating Statistics.", NumRows);


            double total = 0;
            double sqrTotal = 0;
            int count = 0;
            short min = short.MaxValue;
            short max = short.MinValue;

            for (int row = 0; row < NumRows; row++)
            {
                for (int col = 0; col < NumColumns; col++)
                {
                    short val = Data[row][col];
                    if (val != _shortNoDataValue)
                    {
                        if (val > max) max = val;
                        if (val < min) 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));
            Value.Updated = false; 
        }
Ejemplo n.º 20
0
        /// <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;
        }
Ejemplo n.º 21
0
 private void Configure()
 {
     _fileType = 0x03;
     _progressHandler = DataManager.DefaultDataManager.ProgressHandler;
     _progressMeter = new ProgressMeter(_progressHandler);
     _dataTable = new DataTable();
     _columns = new List<Field>();
     _attributesPopulated = true; // only turn this false during an "open" method
 }
Ejemplo n.º 22
0
        /// <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;
        }
Ejemplo n.º 23
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();
            
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Gets the values from a file based data source rather than an in memory object.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="progressHandler"></param>
        public void GetValues(IAttributeSource source, ICancelProgressHandler progressHandler)
        {
            int pageSize = 100000;
           
            Values = new List<double>();
            string normField = EditorSettings.NormField;
            string fieldName = EditorSettings.FieldName;
            if (source.NumRows() < EditorSettings.MaxSampleCount)
            {
                int numPages = (int)Math.Ceiling((double)source.NumRows() / pageSize);
                for (int ipage = 0; ipage < numPages; ipage++)
                {
                    int numRows = (ipage == numPages - 1) ? source.NumRows()%pageSize : pageSize;
                    DataTable table = source.GetAttributes(ipage*pageSize, numRows);
                    if (!string.IsNullOrEmpty(EditorSettings.ExcludeExpression))
                    {
                        DataRow[] rows = table.Select("NOT (" + EditorSettings.ExcludeExpression + ")");
                        foreach (DataRow row in rows)
                        {
                            
                            double val;
                            if (!double.TryParse(row[fieldName].ToString(), out val)) continue;
                            if (double.IsNaN(val)) continue;

                            if (normField != null)
                            {
                                double norm;
                                if (!double.TryParse(row[normField].ToString(), out norm) || double.IsNaN(val))
                                    continue;
                                Values.Add(val/norm);
                                continue;
                            }
                            Values.Add(val);
                        }
                    }
                    else
                    {
                        foreach (DataRow row in table.Rows)
                        {

                            double val;
                            if (!double.TryParse(row[fieldName].ToString(), out val)) continue;
                            if (double.IsNaN(val)) continue;

                            if (normField != null)
                            {
                                double norm;
                                if (!double.TryParse(row[normField].ToString(), out norm) || double.IsNaN(val))
                                    continue;
                                Values.Add(val / norm);
                                continue;
                            }
                            Values.Add(val);
                        }
                    }
                }
            }
            else
            {
                Dictionary<int, double> randomValues = new Dictionary<int, double>();
                pageSize = 10000;
                int count = EditorSettings.MaxSampleCount;
                

                int max = source.NumRows();
                Random rnd = new Random();
                AttributePager ap = new AttributePager(source, pageSize);
                int countPerPage = count/ap.NumPages();
                ProgressMeter pm = new ProgressMeter(progressHandler, "Sampling " + count + " random values", count);
                for (int iPage = 0; iPage < ap.NumPages(); iPage++)
                {
                    for (int i = 0; i < countPerPage; i++)
                    {
                        double val;
                        double norm = 1;
                        int index;
                        bool failed = false;
                        do
                        {
                            index = rnd.Next(ap.StartIndex, ap.StartIndex + pageSize);
                            DataRow dr = ap.Row(index);
                            if (!double.TryParse(dr[fieldName].ToString(), out val)) failed = true;
                            if (normField == null) continue;
                            if (!double.TryParse(dr[normField].ToString(), out norm))
                                failed = true;
                        } while (randomValues.ContainsKey(index) || double.IsNaN(val) || failed);
                        if (normField != null)
                        {
                            Values.Add(val / norm);
                        }
                        else
                        {
                            Values.Add(val);
                        }
                        randomValues.Add(index, val);
                        pm.CurrentValue = i + iPage*countPerPage;
                    }
                    Application.DoEvents();
                    if(progressHandler != null && progressHandler.Cancel)
                    {
                        break;
                    }
                }
                    
            }
            Values.Sort();
            Statistics.Calculate(Values);
            return;
        }
Ejemplo n.º 25
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;

        }
Ejemplo n.º 26
0
        /// <summary>
        /// Gets a list of all unique values of the attribute field.
        /// </summary>
        private List<Break> GetUniqueValues(string fieldName, IAttributeSource source, ICancelProgressHandler progressHandler)
        {
            ArrayList lst;
            bool _hugeCountOk = false;
            if(_cachedUniqueValues.ContainsKey(fieldName))
            {
                lst = _cachedUniqueValues[fieldName];
            }
            else
            {
                lst = new ArrayList();
                AttributePager ap = new AttributePager(source, 5000);
                ProgressMeter pm = new ProgressMeter(progressHandler, "Discovering Unique Values", source.NumRows());
                for (int row = 0; row < source.NumRows(); row++)
                {
                    object val = ap.Row(row)[fieldName] ?? "[NULL]";
                    if (val.ToString() == "") val = "[NULL]";
                    if (lst.Contains(val)) continue;
                    lst.Add(val);
                    if (lst.Count > 1000 && !_hugeCountOk)
                    {
                        if (MessageBox.Show(
                            "There are more than 1000 unique values, which can result in very slow performance.  Do you wish to try to create unique categories from all the values anyway?",
                            "Extreme Number of Categories", MessageBoxButtons.YesNo) == DialogResult.No)
                        {
                            break;
                        }
                        _hugeCountOk = true;
                    }
                    pm.CurrentValue = row;
                    if (progressHandler.Cancel) break;
                }
                lst.Sort();
                if (lst.Count < EditorSettings.MaxSampleCount)
                {
                    _cachedUniqueValues[fieldName] = lst;
                }
            }
           
            List<Break> result = new List<Break>();

            if (lst != null)
            {
                foreach (object item in lst)
                {
                    result.Add(new Break(item.ToString()));
                }
            }
            return result;
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Creates a new FeatureSet using a given list of IFeatures.
 /// This will copy the existing features, rather than removing
 /// them from their parent feature set.
 /// </summary>
 /// <param name="inFeatures">The list of IFeatures</param>
 public FeatureSet(IList<IFeature> inFeatures)
 {
     _progressHandler = Components.DataManager.DefaultDataManager.ProgressHandler;
     _progressMeter = new ProgressMeter(_progressHandler);
     _dataTable = new DataTable();
     _dataTable.RowDeleted += DataTableRowDeleted;
     
     if (inFeatures.Count > 0)
     {
         FeatureType = inFeatures[0].FeatureType;
     }
     _features = new FeatureList(this);
     if (inFeatures.Count > 0)
     {
         if (inFeatures[0].ParentFeatureSet != null)
         {
             CopyTableSchema(inFeatures[0].ParentFeatureSet);
         }
         else
         {
             if (inFeatures[0].DataRow != null)
             {
                 CopyTableSchema(inFeatures[0].DataRow.Table);
             }
         }
         _features.SuspendEvents(); 
         foreach (IFeature f in inFeatures)
         {
             IFeature myFeature = f.Copy();
             _features.Add(myFeature);
         }
         _features.ResumeEvents();
     }
 }
Ejemplo n.º 28
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();
            
            
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Copies all the features from the specified featureset.  
 /// </summary>
 /// <param name="source">The source IFeatureSet to copy features from.</param>
 /// <param name="copyAttributes">Boolean, true if the attributes should be copied as well.  If this is true,
 /// and the attributes are not loaded, a FillAttributes call will be made.</param>
 public void CopyFeatures(IFeatureSet source, bool copyAttributes)
 {
     ProgressMeter = new ProgressMeter(ProgressHandler, "Copying Features", ShapeIndices.Count);
     Vertex = source.Vertex.Copy();
     _shapeIndices = new List<ShapeRange>();
     foreach (ShapeRange range in source.ShapeIndices)
     {
         _shapeIndices.Add(range.Copy());
     }
     foreach (DataColumn dc in source.GetColumns())
     {
         if (dc != null)
         {
             DataColumn outCol = new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping);
             Field fld = new Field(outCol);
             DataTable.Columns.Add(fld);
         }
     }
     if(source.AttributesPopulated)
     {
         // Handle data table content directly
         if(!IndexMode)
         {
             // If not in index mode, just handle this using features
             Features.SuspendEvents();
             foreach (IFeature f in source.Features)
             {
                 IFeature copy = AddFeature(f.BasicGeometry);
                 if (copyAttributes)
                 {
                     for (int col = 0; col < source.DataTable.Columns.Count; col++)
                     {
                         copy.DataRow[col] = f.DataRow[col];
                     }
                 }
             }
             Features.ResumeEvents();
         }
         else
         {
             // We need to copy the attributes, but just copy a datarow
             DataTable = source.DataTable.Copy();
         }
     }
     else
     {
          AttributesPopulated = false;
         // Handle data table content directly
         if (!IndexMode)
         {
             // If not in index mode, just handle this using features
             Features.SuspendEvents();
             foreach (IFeature f in source.Features)
             {
                 AddFeature(f.BasicGeometry);
             }
             Features.ResumeEvents();
         }
         if(copyAttributes)
         {
            
             // We need to copy the attributes, but use the page system
             int maxRow = NumRows();
             const int pageSize = 10000;
             int numPages = (int)Math.Ceiling(maxRow/(double)pageSize);
             for(int i = 0; i < numPages; i++)
             {
                 int numRows = pageSize;
                 if (i == numPages - 1) numRows = numPages - (pageSize*i);
                 DataTable dt = source.GetAttributes(i * pageSize, numRows);
                 SetAttributes(i*pageSize, dt);
             }
             
         }
     }
     
     
 }
        /// <summary>
        /// Creates a new instance of BufferedBinaryReader, and specifies where to send progress messages.
        /// </summary>
        /// <param name="filename">The string path of a file to open using this BufferedBinaryReader.</param>
        /// <param name="progressHandler">Any implementation of IProgressHandler for receiving progress messages.</param>
        public BufferedBinaryReader(string filename, IProgressHandler progressHandler)
        {
            //Modified 9/22/09 by L. C. Wilson to open as read-only so it is possible to open read-only files
            //Not sure if elsewhere write access is required
            _filename = filename;
            _fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); 
            _binaryReader = new BinaryReader(_fileStream);
 
            FileInfo fi = new FileInfo(filename);
            
            _fileLength = fi.Length;
            _fileOffset = 0;

            _readOffset = -1; // There is no buffer loaded.

            _bufferSize = 0;
            _bufferOffset = -1; // -1 means no buffer is loaded.
            
            _isFinishedBuffering = false;
            _isFinishedReading = false;
            _progressMeter = new ProgressMeter(progressHandler, "Reading from " + Path.GetFileName(filename), _fileLength);

            if (_fileLength < 10000000) _progressMeter.StepPercent = 5;
            if (_fileLength < 5000000) _progressMeter.StepPercent = 10;
            if (_fileLength < 100000) _progressMeter.StepPercent = 50;
            if (_fileLength < 10000) _progressMeter.StepPercent = 100;
            //long testMax = _fileLength / _progressMeter.StepPercent;
            //if (testMax < (long)9600000) _maxBufferSize = Convert.ToInt32(testMax); // otherwise keep it at 96000000
        }