private static NeighborhoodType[] GetNeighborhoodTypes() { var types = new NeighborhoodType[256]; for (uint mask = 0; mask < 256; ++mask) { var TL = (mask & 1) != 0; var TC = (mask & 2) != 0; var TR = (mask & 4) != 0; var CL = (mask & 8) != 0; var CR = (mask & 16) != 0; var BL = (mask & 32) != 0; var BC = (mask & 64) != 0; var BR = (mask & 128) != 0; var count = MathEx.CountBits(mask); var diagonal = !TC && !CL && TL || !CL && !BC && BL || !BC && !CR && BR || !CR && !TC && TR; var horizontal = !TC && !BC && (TR || CR || BR) && (TL || CL || BL); var vertical = !CL && !CR && (TL || TC || TR) && (BL || BC || BR); var end = count == 1; if (end) { types[mask] = NeighborhoodType.Ending; } else if (!diagonal && !horizontal && !vertical) { types[mask] = NeighborhoodType.Removable; } } return(types); }
static NeighborhoodType[] NeighborhoodTypes() { var types = new NeighborhoodType[256]; for (uint mask = 0; mask < 256; ++mask) { bool TL = (mask & 1) != 0; bool TC = (mask & 2) != 0; bool TR = (mask & 4) != 0; bool CL = (mask & 8) != 0; bool CR = (mask & 16) != 0; bool BL = (mask & 32) != 0; bool BC = (mask & 64) != 0; bool BR = (mask & 128) != 0; uint count = Integers.PopulationCount(mask); bool diagonal = !TC && !CL && TL || !CL && !BC && BL || !BC && !CR && BR || !CR && !TC && TR; bool horizontal = !TC && !BC && (TR || CR || BR) && (TL || CL || BL); bool vertical = !CL && !CR && (TL || TC || TR) && (BL || BC || BR); bool end = (count == 1); if (end) { types[mask] = NeighborhoodType.Ending; } else if (!diagonal && !horizontal && !vertical) { types[mask] = NeighborhoodType.Removable; } } return(types); }
static NeighborhoodType[] GetNeighborhoodTypes() { var types = new NeighborhoodType[256]; for (uint mask = 0; mask < 256; ++mask) { bool TL = (mask & 1) != 0; bool TC = (mask & 2) != 0; bool TR = (mask & 4) != 0; bool CL = (mask & 8) != 0; bool CR = (mask & 16) != 0; bool BL = (mask & 32) != 0; bool BC = (mask & 64) != 0; bool BR = (mask & 128) != 0; int count = MathEx.CountBits(mask); bool diagonal = !TC && !CL && TL || !CL && !BC && BL || !BC && !CR && BR || !CR && !TC && TR; bool horizontal = !TC && !BC && (TR || CR || BR) && (TL || CL || BL); bool vertical = !CL && !CR && (TL || TC || TR) && (BL || BC || BR); bool end = (count == 1); if (end) types[mask] = NeighborhoodType.Ending; else if (!diagonal && !horizontal && !vertical) types[mask] = NeighborhoodType.Removable; } return types; }
/// <summary> /// Is called by SimPe (through the Wrapper) when the Panel is going to be displayed, so /// you should updatet the Data displayed by the Panel with the Attributes stored in the /// passed Wrapper. /// </summary> /// <param name="wrapper">The Attributes of this Wrapper have to be displayed</param> public void UpdateGUI(IFileWrapper wrapper) { Idno wrp = (Idno)wrapper; form.wrapper = null; form.Tag = true; try { form.cbtype.SelectedIndex = 0; for (int i = 0; i < form.cbtype.Items.Count; i++) { NeighborhoodType lt = (NeighborhoodType)form.cbtype.Items[i]; if (lt == wrp.Type) { form.cbtype.SelectedIndex = i; break; } } form.tbtype.Text = "0x" + Helper.HexString((byte)wrp.Type); form.tbversion.Text = "0x" + Helper.HexString((uint)wrp.Version); form.lbVer.Text = wrp.Version.ToString().Replace("_", " "); form.tbid.Text = wrp.Uid.ToString(); form.tbname.Text = wrp.OwnerName; form.tbsubname.Text = wrp.SubName; form.wrapper = wrp; } finally { form.Tag = null; } }
/// <summary> /// Once the Parameter have been configured the Execute command can be called, it returns true if succesful /// </summary> public override bool Execute(ICancelProgressHandler cancelProgressHandler) { IFeatureSet input = _inputParam[0].Value as IFeatureSet; if (input == null) { return(false); } input.FillAttributes(); ListParam lp = _inputParam[1] as ListParam; if (lp == null) { return(false); } string zField = lp.ValueList[lp.Value]; double cellSize = (double)_inputParam[2].Value; double power = (double)_inputParam[3].Value; NeighborhoodType neighborType = _inputParam[4].Value as string == TextStrings.FixedDistance ? NeighborhoodType.FixedDistance : NeighborhoodType.FixedCount; int pointCount = (int)_inputParam[5].Value; double distance = (double)_inputParam[6].Value; IRaster output = _outputParam[0].Value as IRaster; return(Execute( input, zField, cellSize, power, neighborType, pointCount, distance, output, cancelProgressHandler)); }
private static string LoadLabel(SimPe.Packages.File pk, out NeighborhoodType type) { string name = SimPe.Localization.GetString("Unknown"); type = NeighborhoodType.Unknown; try { SimPe.Interfaces.Files.IPackedFileDescriptor pfd = pk.FindFile(0x43545353, 0, 0xffffffff, 1); if (pfd != null) { SimPe.PackedFiles.Wrapper.Str str = new SimPe.PackedFiles.Wrapper.Str(); str.ProcessData(pfd, pk); name = str.LanguageItems(new SimPe.PackedFiles.Wrapper.StrLanguage((byte)Data.MetaData.Languages.English))[0].Title; } pfd = pk.FindFile(0xAC8A7A2E, 0, 0xffffffff, 1); if (pfd != null) { SimPe.Plugin.Idno idno = new Idno(); idno.ProcessData(pfd, pk); type = idno.Type; } //pk.Reader.Close(); } finally { //pk.Reader.Close(); } return(name); }
/// <summary> /// Constructor /// </summary> public Idno() : base() { if (SimPe.PathProvider.Global.EPInstalled >= 1) { this.version = (uint)NeighborhoodVersion.Sims2_University; } else { this.version = (uint)NeighborhoodVersion.Sims2; } this.type = NeighborhoodType.Normal; over = new byte[0]; uid = 0; name = "Nxxx"; subname = ""; }
private void SelectType(object sender, System.EventArgs e) { if (cbtype.SelectedIndex < 0) { return; } NeighborhoodType nt = (NeighborhoodType)cbtype.Items[cbtype.SelectedIndex]; if (nt != NeighborhoodType.Unknown) { this.tbtype.Text = "0x" + Helper.HexString((uint)nt); } tbsubname.Enabled = (nt == NeighborhoodType.University); if (this.Tag != null) { return; } wrapper.Type = nt; wrapper.Changed = true; }
/// <summary> /// Unserializes a BinaryStream into the Attributes of this Instance /// </summary> /// <param name="reader">The Stream that contains the FileData</param> protected override void Unserialize(System.IO.BinaryReader reader) { version = reader.ReadUInt32(); int ct = reader.ReadInt32(); name = Helper.ToString(reader.ReadBytes(ct)); uid = reader.ReadUInt32(); if (version >= (int)NeighborhoodVersion.Sims2_University) { type = (NeighborhoodType)reader.ReadUInt32(); if ((int)type >= (int)NeighborhoodType.University) { ct = reader.ReadInt32(); subname = Helper.ToString(reader.ReadBytes(ct)); } } else { type = NeighborhoodType.Normal; } over = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); }
/// <summary> /// Executes the Area tool with programatic input /// Ping delete static for external testing /// </summary> /// <param name="input">The input raster</param> /// <param name="output">The output polygon feature set</param> /// <param name="zField">The field name containing the values to interpolate</param> /// <param name="cellSize">The double geographic size of the raster cells to create</param> /// <param name="power">The double power representing the inverse</param> /// <param name="neighborType">Fixed distance of fixed number of neighbors</param> /// <param name="pointCount">The number of neighbors to include if the neighborhood type /// is Fixed</param> /// <param name="distance">Points further from the raster cell than this distance are not included /// in the calculation if the neighborhood type is Fixed Distance.</param> /// <param name="output">The output raster where values are stored. The filename is used, but the number /// of rows and columns will be computed from the cellSize and input featureset</param> /// <param name="cancelProgressHandler">A progress handler for receiving progress messages</param> /// <returns>A boolean, true if the IDW process worked correctly</returns> public bool Execute(IFeatureSet input, string zField, double cellSize, double power, NeighborhoodType neighborType, int pointCount, double distance, IRaster output, ICancelProgressHandler cancelProgressHandler) { //Validates the input and output data if (input == null || output == null) return false; //If the cellSize is 0 we calculate a cellsize based on the input extents if (cellSize == 0) cellSize = input.Envelope.Width / 255; //Defines the dimesions and position of the raster int numColumns = Convert.ToInt32(Math.Round(input.Envelope.Width / cellSize)); int numRows = Convert.ToInt32(Math.Round(input.Envelope.Height / cellSize)); output = Raster.Create(output.Filename, "",numColumns, numRows, 1, typeof(double), new[] {""} ); output.CellHeight = cellSize; output.CellWidth = cellSize; output.Xllcenter = input.Envelope.Minimum.X + (cellSize/2); output.Yllcenter = input.Envelope.Minimum.Y + (cellSize/2); //Used to calculate progress int lastUpdate=0; //Populates the KD tree MapWindow.Analysis.Topology.KDTree.KDTree kd = new MapWindow.Analysis.Topology.KDTree.KDTree(2); List<int> randomList = new List<int>(); for (int i = 0; i < input.Features.Count; i++) { randomList.Add(i); } Random rnd = new Random(); List<int> completed = new List<int>(); while (randomList.Count > 0) { int index = rnd.Next(0,randomList.Count -1); Coordinate coord = input.Features[randomList[index]].Coordinates[0]; while (kd.Search(coord.ToArray()) != null) coord.X = coord.X * 1.000000000000001D; kd.Insert(coord.ToArray(), input.Features[randomList[index]]); completed.Add(randomList[index]); randomList.RemoveAt(index); } System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); //Makes sure we don't try to search for more points then exist if (kd.Count < pointCount) pointCount = kd.Count; if (neighborType == NeighborhoodType.FixedCount) { //we add all the old features to output for (int x = 0; x < numColumns; x++) { for (int y = 0; y < numRows; y++) { //Gets the pointCount number of cells closest to the current cell Coordinate cellCenter = output.CellToProj(y, x); Double[] pixelCoord = new double[2]; pixelCoord[0] = output.CellToProj(y, x).X; pixelCoord[1] = output.CellToProj(y, x).Y; sw.Start(); object[] result = kd.Nearest(pixelCoord, pointCount); sw.Stop(); //Sets up the IDW numerator and denominator double top = 0; double bottom = 0; foreach (object feat in result) { IFeature featurePt = feat as Feature; if (featurePt == null) continue; double distanceToCell = cellCenter.Distance(featurePt.Coordinates[0]); if (distanceToCell <= distance || distance == 0) { //If we can't convert the value to a double throw it out try { Convert.ToDouble(featurePt.DataRow[zField]); } catch { continue; } if (power == 2) { top += (1 / (distanceToCell * distanceToCell)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += (1 / (distanceToCell* distanceToCell)); } else { top += (1 / Math.Pow(distanceToCell, power)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += (1 / Math.Pow(distanceToCell, power)); } } } output.Value[y, x] = top / bottom; } //Checks if we need to update the status bar if (Convert.ToInt32(Convert.ToDouble(x*numRows ) / Convert.ToDouble(numColumns * numRows) * 100) > lastUpdate) { lastUpdate = Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100); cancelProgressHandler.Progress("", lastUpdate, "Cell: " + (x * numRows) + " of " + (numColumns * numRows)); if (cancelProgressHandler.Cancel) return false; } } System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds); } output.Save(); return true; }
public static uint ClassifyTile(Grid <float> inputBuffer, uint[,] outputBuffer, float maxHeightDiffBetweenPixels, uint currentClassIndexSpanningTiles, uint minClusterSize, float noDataVal, NeighborhoodType neighborhoodType) { int width = inputBuffer.SizeX; int height = inputBuffer.SizeY; UInt32 currentClassIndex = 2; Dictionary <uint, SortedList <uint, bool> > substitutions = new Dictionary <uint, SortedList <uint, bool> >(); Dictionary <uint, uint> classPixelCounts = new Dictionary <uint, uint>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { UInt32 newClassVal = 0; float thisVal = inputBuffer.Data[x, y]; // skip nodata values if (thisVal != noDataVal) { System.Drawing.Point[] coords = new System.Drawing.Point[4]; int neighborIndex = 0; if (y > 0) { coords[neighborIndex++] = new System.Drawing.Point(x, y - 1); } if (x > 0) { coords[neighborIndex++] = new System.Drawing.Point(x - 1, y); } if (neighborhoodType == NeighborhoodType.EightNeighbors) { if (y > 0 && x > 0) { coords[neighborIndex++] = new System.Drawing.Point(x - 1, y - 1); } if (y > 0 && x < width - 1) { coords[neighborIndex++] = new System.Drawing.Point(x + 1, y - 1); } } for (int i = 0; i < neighborIndex; i++) { int neighborX = coords[i].X; int neighborY = coords[i].Y; float neighborVal = inputBuffer.Data[neighborX, neighborY]; if (neighborVal != noDataVal) { uint neighborClass = outputBuffer[neighborX, neighborY]; if (System.Math.Abs(thisVal - neighborVal) <= maxHeightDiffBetweenPixels) { if (newClassVal == 0) { newClassVal = neighborClass; } else { newClassVal = DetermineNewClassSubstitution(substitutions, newClassVal, neighborClass); } } } } if (newClassVal == 0) { newClassVal = currentClassIndex; currentClassIndex++; } } outputBuffer[x, y] = newClassVal; } } // perform substitutions uint maxPixelCount = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { uint newClass = FindSubstitutePixelClass(substitutions, classPixelCounts, ref maxPixelCount, currentClass); outputBuffer[x, y] = newClass; } } } // filter small clusters (trees and edges) if (minClusterSize > 0) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { uint count = classPixelCounts[currentClass]; uint value = 0; value = currentClass; if (count < minClusterSize) { value = 0; } outputBuffer[x, y] = value; } } } } // Update class indices to reduce max index values and remove duplicates across tiles. // This is feasible because small clusters have been filtered out (set to zero). Dictionary <uint, uint> classMappingUpdate = new Dictionary <uint, uint>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { if (!classMappingUpdate.ContainsKey(currentClass)) { ++currentClassIndexSpanningTiles; classMappingUpdate.Add(currentClass, currentClassIndexSpanningTiles); } outputBuffer[x, y] = classMappingUpdate[currentClass]; } } } return(currentClassIndexSpanningTiles); }
/// <summary> /// Executes the Area tool with programatic input /// Ping delete static for external testing. /// </summary> /// <param name="input">The input raster.</param> /// <param name="zField">The field name containing the values to interpolate.</param> /// <param name="cellSize">The double geographic size of the raster cells to create.</param> /// <param name="power">The double power representing the inverse.</param> /// <param name="neighborType">Fixed distance of fixed number of neighbors.</param> /// <param name="pointCount">The number of neighbors to include if the neighborhood type /// is Fixed.</param> /// <param name="distance">Points further from the raster cell than this distance are not included /// in the calculation if the neighborhood type is Fixed Distance.</param> /// <param name="output">The output raster where values are stored. The fileName is used, but the number /// of rows and columns will be computed from the cellSize and input featureset.</param> /// <param name="cancelProgressHandler">A progress handler for receiving progress messages.</param> /// <returns>A boolean, true if the IDW process worked correctly.</returns> public bool Execute(IFeatureSet input, string zField, double cellSize, double power, NeighborhoodType neighborType, int pointCount, double distance, IRaster output, ICancelProgressHandler cancelProgressHandler) { // Validates the input and output data if (input == null || output == null) { return(false); } // If the cellSize is 0 we calculate a cell size based on the input extents if (cellSize == 0) { cellSize = input.Extent.Width / 255; } // Defines the dimensions and position of the raster int numColumns = Convert.ToInt32(Math.Round(input.Extent.Width / cellSize)); int numRows = Convert.ToInt32(Math.Round(input.Extent.Height / cellSize)); output = Raster.CreateRaster(output.Filename, string.Empty, numColumns, numRows, 1, typeof(double), new[] { string.Empty }); output.CellHeight = cellSize; output.CellWidth = cellSize; output.Xllcenter = input.Extent.MinX + (cellSize / 2); output.Yllcenter = input.Extent.MinY + (cellSize / 2); // Used to calculate progress int lastUpdate = 0; // Populates the KD tree var kd = new KdTreeEx <IFeature>(); List <int> randomList = new(); for (int i = 0; i < input.Features.Count; i++) { randomList.Add(i); } Random rnd = new(); List <int> completed = new(); while (randomList.Count > 0) { int index = rnd.Next(0, randomList.Count - 1); Coordinate coord = input.Features[randomList[index]].Geometry.Coordinates[0]; while (kd.Search(coord) != null) { coord.X *= 1.000000000000001D; } kd.Insert(coord, input.Features[randomList[index]]); completed.Add(randomList[index]); randomList.RemoveAt(index); } if (neighborType == NeighborhoodType.FixedCount) { // we add all the old features to output for (int x = 0; x < numColumns; x++) { for (int y = 0; y < numRows; y++) { // Gets the pointCount number of cells closest to the current cell Coordinate cellCenter = output.CellToProj(y, x); var coord = output.CellToProj(y, x); var result = kd.NearestNeighbor(coord); var featurePt = result?.Data; if (featurePt != null) { // Sets up the IDW numerator and denominator double top = 0; double bottom = 0; double distanceToCell = cellCenter.Distance(featurePt.Geometry.Coordinates[0]); if (distanceToCell <= distance || distance == 0) { // If we can't convert the value to a double throw it out try { Convert.ToDouble(featurePt.DataRow[zField]); } catch { continue; } if (power == 2) { top += (1 / (distanceToCell * distanceToCell)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += 1 / (distanceToCell * distanceToCell); } else { top += (1 / Math.Pow(distanceToCell, power)) * Convert.ToDouble(featurePt.DataRow[zField]); bottom += 1 / Math.Pow(distanceToCell, power); } } output.Value[y, x] = top / bottom; } } // Checks if we need to update the status bar if (Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100) > lastUpdate) { lastUpdate = Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100); cancelProgressHandler.Progress(lastUpdate, "Cell: " + (x * numRows) + " of " + (numColumns * numRows)); if (cancelProgressHandler.Cancel) { return(false); } } } } output.Save(); return(true); }
/// <summary> /// Executes the Area tool with programatic input /// Ping delete static for external testing /// </summary> /// <param name="input">The input raster</param> /// <param name="zField">The field name containing the values to interpolate</param> /// <param name="cellSize">The double geographic size of the raster cells to create</param> /// <param name="power">The double power representing the inverse</param> /// <param name="neighborType">Fixed distance of fixed number of neighbors</param> /// <param name="pointCount">The number of neighbors to include if the neighborhood type /// is Fixed</param> /// <param name="distance">Points further from the raster cell than this distance are not included /// in the calculation if the neighborhood type is Fixed Distance.</param> /// <param name="output">The output raster where values are stored. The fileName is used, but the number /// of rows and columns will be computed from the cellSize and input featureset</param> /// <param name="cancelProgressHandler">A progress handler for receiving progress messages</param> /// <returns>A boolean, true if the IDW process worked correctly</returns> public bool Execute(IFeatureSet input, string zField, double cellSize, double power, NeighborhoodType neighborType, int pointCount, double distance, IRaster output, ICancelProgressHandler cancelProgressHandler) { // Validates the input and output data if (input == null || output == null) { return(false); } // If the cellSize is 0 we calculate a cell size based on the input extents if (cellSize == 0) { cellSize = input.Extent.Width / 255; } // Defines the dimensions and position of the raster int numColumns = Convert.ToInt32(Math.Round(input.Extent.Width / cellSize)); int numRows = Convert.ToInt32(Math.Round(input.Extent.Height / cellSize)); output = Raster.CreateRaster(output.Filename, string.Empty, numColumns, numRows, 1, typeof(double), new[] { string.Empty }); output.CellHeight = cellSize; output.CellWidth = cellSize; output.Xllcenter = input.Extent.MinX + (cellSize / 2); output.Yllcenter = input.Extent.MinY + (cellSize / 2); // Used to calculate progress //int lastUpdate = 0; //TODO jany_ correct code to work with new KdTree //// Populates the KD tree //KdTree kd = new KdTree(2); //List<int> randomList = new List<int>(); //for (int i = 0; i < input.Features.Count; i++) //{ // randomList.Add(i); //} //Random rnd = new Random(); //List<int> completed = new List<int>(); //while (randomList.Count > 0) //{ // int index = rnd.Next(0, randomList.Count - 1); // Coordinate coord = input.Features[randomList[index]].Geometry.Coordinates[0]; // while (kd.Search(coord.ToArray()) != null) // { // coord.X = coord.X * 1.000000000000001D; // } // kd.Insert(coord.ToArray(), input.Features[randomList[index]]); // completed.Add(randomList[index]); // randomList.RemoveAt(index); //} //// Makes sure we don't try to search for more points then exist //if (kd.Count < pointCount) //{ // pointCount = kd.Count; //} //if (neighborType == NeighborhoodType.FixedCount) //{ // // we add all the old features to output // for (int x = 0; x < numColumns; x++) // { // for (int y = 0; y < numRows; y++) // { // // Gets the pointCount number of cells closest to the current cell // Coordinate cellCenter = output.CellToProj(y, x); // Double[] pixelCoord = new double[2]; // pixelCoord[0] = output.CellToProj(y, x).X; // pixelCoord[1] = output.CellToProj(y, x).Y; // object[] result = kd.Nearest(pixelCoord, pointCount); // // Sets up the IDW numerator and denominator // double top = 0; // double bottom = 0; // foreach (object feat in result) // { // IFeature featurePt = feat as Feature; // if (featurePt == null) // { // continue; // } // double distanceToCell = cellCenter.Distance(featurePt.Geometry.Coordinates[0]); // if (distanceToCell <= distance || distance == 0) // { // // If we can't convert the value to a double throw it out // try // { // Convert.ToDouble(featurePt.DataRow[zField]); // } // catch // { // continue; // } // if (power == 2) // { // top += (1 / (distanceToCell * distanceToCell)) // * Convert.ToDouble(featurePt.DataRow[zField]); // bottom += 1 / (distanceToCell * distanceToCell); // } // else // { // top += (1 / Math.Pow(distanceToCell, power)) // * Convert.ToDouble(featurePt.DataRow[zField]); // bottom += 1 / Math.Pow(distanceToCell, power); // } // } // } // output.Value[y, x] = top / bottom; // } // // Checks if we need to update the status bar // if (Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100) > lastUpdate) // { // lastUpdate = Convert.ToInt32(Convert.ToDouble(x * numRows) / Convert.ToDouble(numColumns * numRows) * 100); // cancelProgressHandler.Progress( // string.Empty, lastUpdate, "Cell: " + (x * numRows) + " of " + (numColumns * numRows)); // if (cancelProgressHandler.Cancel) // { // return false; // } // } // } //} output.Save(); return(true); }
public List <Cell> GetNeighborhood(int row, int col, NeighborhoodType type) { // There int MyMod(int x, int mod) => (x >= 0) ? (x % mod) : (x + mod); List <Cell> neighborhood = new List <Cell>(); switch (type) { case NeighborhoodType.L5: { neighborhood.Add(GetAt(row, col)); neighborhood.Add(GetAt(row, MyMod(col - 1, ColCount))); // Left neighborhood.Add(GetAt(MyMod(row - 1, RowCount), col)); // Top neighborhood.Add(GetAt(row, MyMod(col + 1, ColCount))); // Right neighborhood.Add(GetAt(MyMod(row + 1, RowCount), col)); // Bottom Debug.Assert(neighborhood.Count == 5); } break; case NeighborhoodType.L9: { neighborhood.Add(GetAt(row, col)); neighborhood.Add(GetAt(row, MyMod(col - 1, ColCount))); // Left neighborhood.Add(GetAt(row, MyMod(col - 2, ColCount))); // Left 2 neighborhood.Add(GetAt(MyMod(row - 1, RowCount), col)); // Top neighborhood.Add(GetAt(MyMod(row - 2, RowCount), col)); // Top 2 neighborhood.Add(GetAt(row, MyMod(col + 1, ColCount))); // Right neighborhood.Add(GetAt(row, MyMod(col + 2, ColCount))); // Right 2 neighborhood.Add(GetAt(MyMod(row + 1, RowCount), col)); // Bottom neighborhood.Add(GetAt(MyMod(row + 2, RowCount), col)); // Bottom 2 Debug.Assert(neighborhood.Count == 9); } break; case NeighborhoodType.C9: { for (int nRow = row - 1; nRow <= row + 1; nRow++) { for (int nCol = col - 1; nCol <= col + 1; nCol++) { neighborhood.Add(GetAt(MyMod(nRow, RowCount), MyMod(nCol, ColCount))); } } Debug.Assert(neighborhood.Count == 9); } break; case NeighborhoodType.C13: { for (int nRow = row - 1; nRow <= row + 1; nRow++) { for (int nCol = col - 1; nCol <= col + 1; nCol++) { neighborhood.Add(GetAt(MyMod(nRow, RowCount), MyMod(nCol, ColCount))); } } neighborhood.Add(GetAt(row, MyMod(col - 2, ColCount))); // Left 2 neighborhood.Add(GetAt(MyMod(row - 2, RowCount), col)); // Top 2 neighborhood.Add(GetAt(row, MyMod(col + 2, ColCount))); // Right 2 neighborhood.Add(GetAt(MyMod(row + 2, RowCount), col)); // Bottom 2 Debug.Assert(neighborhood.Count == 13); } break; default: throw new Exception("INVALID TYPE."); } return(neighborhood); }
public static uint ClassifyTile(Grid<float> inputBuffer, uint[,] outputBuffer, float maxHeightDiffBetweenPixels, uint currentClassIndexSpanningTiles, uint minClusterSize, float noDataVal, NeighborhoodType neighborhoodType) { int width = inputBuffer.SizeX; int height = inputBuffer.SizeY; UInt32 currentClassIndex = 2; Dictionary<uint, SortedList<uint, bool>> substitutions = new Dictionary<uint, SortedList<uint, bool>>(); Dictionary<uint, uint> classPixelCounts = new Dictionary<uint, uint>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { UInt32 newClassVal = 0; float thisVal = inputBuffer.Data[x, y]; // skip nodata values if (thisVal != noDataVal) { System.Drawing.Point[] coords = new System.Drawing.Point[4]; int neighborIndex = 0; if (y > 0) coords[neighborIndex++] = new System.Drawing.Point(x, y - 1); if (x > 0) coords[neighborIndex++] = new System.Drawing.Point(x - 1, y); if (neighborhoodType == NeighborhoodType.EightNeighbors) { if (y > 0 && x > 0) coords[neighborIndex++] = new System.Drawing.Point(x - 1, y - 1); if (y > 0 && x < width - 1) coords[neighborIndex++] = new System.Drawing.Point(x + 1, y - 1); } for (int i = 0; i < neighborIndex; i++) { int neighborX = coords[i].X; int neighborY = coords[i].Y; float neighborVal = inputBuffer.Data[neighborX, neighborY]; if (neighborVal != noDataVal) { uint neighborClass = outputBuffer[neighborX, neighborY]; if (System.Math.Abs(thisVal - neighborVal) <= maxHeightDiffBetweenPixels) { if (newClassVal == 0) newClassVal = neighborClass; else newClassVal = DetermineNewClassSubstitution(substitutions, newClassVal, neighborClass); } } } if (newClassVal == 0) { newClassVal = currentClassIndex; currentClassIndex++; } } outputBuffer[x, y] = newClassVal; } } // perform substitutions uint maxPixelCount = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { uint newClass = FindSubstitutePixelClass(substitutions, classPixelCounts, ref maxPixelCount, currentClass); outputBuffer[x, y] = newClass; } } } // filter small clusters (trees and edges) if (minClusterSize > 0) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { uint count = classPixelCounts[currentClass]; uint value = 0; value = currentClass; if (count < minClusterSize) value = 0; outputBuffer[x, y] = value; } } } } // Update class indices to reduce max index values and remove duplicates across tiles. // This is feasible because small clusters have been filtered out (set to zero). Dictionary<uint, uint> classMappingUpdate = new Dictionary<uint, uint>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint currentClass = outputBuffer[x, y]; if (currentClass > 0) { if (!classMappingUpdate.ContainsKey(currentClass)) { ++currentClassIndexSpanningTiles; classMappingUpdate.Add(currentClass, currentClassIndexSpanningTiles); } outputBuffer[x, y] = classMappingUpdate[currentClass]; } } } return currentClassIndexSpanningTiles; }
public NgbhType(string file, string name, NeighborhoodType type) { this.name = name; this.type = type; this.file = file; }