public void Flood(Vector2Int32 pt) { int bitmapWidth = _wvm.CurrentWorld.TilesWide; int bitmapHeight = _wvm.CurrentWorld.TilesHigh; int x = pt.X; int y = pt.Y; _wvm.CheckTiles = new bool[bitmapWidth * bitmapHeight]; var originTile = (Tile)_wvm.CurrentWorld.Tiles[x, y].Clone(); LinearFloodFill(ref x, ref y, ref originTile); while (_ranges.Count > 0) { //**Get Next Range Off the Queue FloodFillRange range = _ranges.Dequeue(); //**Check Above and Below Each Pixel in the Floodfill Range int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc,y+1); int upPxIdx = (bitmapWidth * (range.Y - 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc, y - 1); int upY = range.Y - 1; //so we can pass the y coord by ref int downY = range.Y + 1; for (int i = range.StartX; i <= range.EndX; i++) { //*Start Fill Upwards //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance if (range.Y > 0 && (!_wvm.CheckTiles[upPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, upY]) && _wvm.Selection.IsValid(i, upY)) { LinearFloodFill(ref i, ref upY, ref originTile); } //*Start Fill Downwards //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance if (range.Y < (bitmapHeight - 1) && (!_wvm.CheckTiles[downPxIdx]) && CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[i, downY]) && _wvm.Selection.IsValid(i, downY)) { LinearFloodFill(ref i, ref downY, ref originTile); } downPxIdx++; upPxIdx++; } if (upY < _minY) { _minY = upY; } if (downY > _maxY) { _maxY = downY; } } }
/// <summary>Removes and returns the <see cref="FloodFillRange"/> at the beginning of the queue.</summary> public FloodFillRange Dequeue() { var range = new FloodFillRange(); if (size > 0) { range = array[head]; array[head] = new FloodFillRange(); head++; //advance head position size--; //update size to exclude dequeued item } return(range); }
public FloodFillRange Dequeue() { FloodFillRange range = new FloodFillRange(); if (size > 0) { range = array[head]; array[head] = new FloodFillRange(); head++; size--; } return(range); }
private static void PerformLinearFill( Layer layer, Queue <FloodFillRange> floodFillQueue, Coordinates coords, int width, SKColor colorToReplace, ref Int32Rect dirtyRect, bool[] visited, List <Coordinates> output) { // Find the Left Edge of the Color Area int fillXLeft = coords.X; while (true) { // Indicate that this pixel has been checked int pixelIndex = (coords.Y * width) + fillXLeft; visited[pixelIndex] = true; // Move one pixel to the left fillXLeft--; // Exit the loop if we're at edge of the bitmap or the color area if (fillXLeft < 0 || visited[pixelIndex - 1] || layer.GetPixelWithOffset(fillXLeft, coords.Y) != colorToReplace) { break; } } int lastCheckedPixelLeft = fillXLeft + 1; // Find the Right Edge of the Color Area int fillXRight = coords.X; while (true) { int pixelIndex = (coords.Y * width) + fillXRight; visited[pixelIndex] = true; fillXRight++; if (fillXRight >= width || visited[pixelIndex + 1] || layer.GetPixelWithOffset(fillXRight, coords.Y) != colorToReplace) { break; } } int lastCheckedPixelRight = fillXRight - 1; int relativeY = coords.Y; LineTool.CalculateBresenhamLine(new Coordinates(lastCheckedPixelLeft, relativeY), new Coordinates(lastCheckedPixelRight, relativeY), output); dirtyRect = dirtyRect.Expand(new Int32Rect(lastCheckedPixelLeft, coords.Y, lastCheckedPixelRight - lastCheckedPixelLeft + 1, 1)); FloodFillRange range = new FloodFillRange(lastCheckedPixelLeft, lastCheckedPixelRight, coords.Y); floodFillQueue.Enqueue(range); }
public override void FloodFill(CvPoint pt) { PrepareForFloodFill(); unsafe { scan0 = (byte *)bitmap.DataByte; int x = pt.X; int y = pt.Y; int loc = CoordsToIndex(ref x, ref y); byte *colorPtr = ((byte *)(scan0 + loc)); startColor = new byte[] { colorPtr[0], colorPtr[1], colorPtr[2] }; LinearFloodFill4(ref x, ref y); bool[] pixelsChecked = this.pixelsChecked; while (ranges.Count > 0) { FloodFillRange range = ranges.Dequeue(); //START THE LOOP UPWARDS AND DOWNWARDS int upY = range.Y - 1; //so we can pass the y coord by ref int downY = range.Y + 1; byte *upPtr = (byte *)(scan0 + CoordsToIndex(ref range.StartX, ref upY)); byte *downPtr = (byte *)(scan0 + CoordsToIndex(ref range.StartX, ref downY)); int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX; //CoordsToPixelIndex(range.StartX,range.Y+1); int upPxIdx = (bitmapWidth * (range.Y - 1)) + range.StartX; //CoordsToPixelIndex(range.StartX, range.Y - 1); for (int i = range.StartX; i <= range.EndX; i++) { //START LOOP UPWARDS //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance if (range.Y > 0 && CheckPixel(ref upPtr) && (!(pixelsChecked[upPxIdx]))) { LinearFloodFill4(ref i, ref upY); } //START LOOP DOWNWARDS if (range.Y < (bitmapHeight - 1) && CheckPixel(ref downPtr) && (!(pixelsChecked[downPxIdx]))) { LinearFloodFill4(ref i, ref downY); } upPtr += bitmapPixelFormatSize; downPtr += bitmapPixelFormatSize; downPxIdx++; upPxIdx++; } } } }
private static void LinearFloodFill(ref Vector2Int32 start, ref Vector2Int32 minBound, ref Vector2Int32 maxBound, Func <Vector2Int32, bool> validation, ref FloodFillRangeQueue ranges, ref HashSet <Vector2Int32> points) { //FIND LEFT EDGE OF COLOR AREA int lFillLoc = start.X; //the location to check/fill on the left int x = start.X; int y = start.Y; points.Add(start); while (true) { points.Add(new Vector2Int32(lFillLoc, y)); // Preform validation for next point lFillLoc--; var curPoint = new Vector2Int32(lFillLoc, y); if (lFillLoc <= minBound.X || !validation(curPoint) || points.Contains(curPoint)) { break; //exit loop if we're at edge of bitmap or match area } } lFillLoc++; //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left while (true) { points.Add(new Vector2Int32(rFillLoc, y)); rFillLoc++; var curPoint = new Vector2Int32(rFillLoc, y); if (rFillLoc >= maxBound.X || !validation(curPoint) || points.Contains(curPoint)) { break; //exit loop if we're at edge of bitmap or color area } } rFillLoc--; var r = new FloodFillRange(lFillLoc, rFillLoc, y); ranges.Enqueue(ref r); }
public static void Flood(Vector2Int32 start, Vector2Int32 minBound, Vector2Int32 maxBound, Func <Vector2Int32, bool> validation) { var ranges = new FloodFillRangeQueue(); var points = new HashSet <Vector2Int32>(); LinearFloodFill(ref start, ref minBound, ref maxBound, validation, ref ranges, ref points); while (ranges.Count > 0) { //**Get Next Range Off the Queue FloodFillRange range = ranges.Dequeue(); //**Check Above and Below Each Pixel in the Floodfill Range int upY = range.Y - 1;//so we can pass the y coord by ref int downY = range.Y + 1; var curPoint = new Vector2Int32(); for (int i = range.StartX; i <= range.EndX; i++) { //*Start Fill Upwards //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance curPoint = new Vector2Int32(i, upY); if (range.Y > 0 && (!points.Contains(curPoint) && validation(curPoint))) { LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points); } //*Start Fill Downwards //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance curPoint = new Vector2Int32(i, downY); if (range.Y < (maxBound.Y - 1) && (!points.Contains(curPoint) && validation(curPoint))) { LinearFloodFill(ref curPoint, ref minBound, ref maxBound, validation, ref ranges, ref points); } } } }
private void LinearFill(ref int x, ref int y) { // Find left edge int lFillLoc = x; while (true) { TileCoord tid = new TileCoord(lFillLoc, y); if (SourceType == TileSourceType.Brush && ActiveBrush != null) { ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y); } else { _fillCommand.QueueReplacement(tid, _sourceStack); _fillLayer[tid] = _sourceStack; } lFillLoc--; tid = new TileCoord(lFillLoc, y); if (lFillLoc < 0 || /*_sourceStack.Equals(_fillLayer[tid]) ||*/ !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid]))) break; } lFillLoc++; // Find right edge int rFillLoc = x; while (true) { TileCoord tid = new TileCoord(rFillLoc, y); /*if (!_sourceStack.Equals(_fillLayer[tid])) {*/ if (SourceType == TileSourceType.Brush && ActiveBrush != null) { ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y); } else { _fillCommand.QueueReplacement(tid, _sourceStack); _fillLayer[tid] = _sourceStack; } //} rFillLoc++; tid = new TileCoord(rFillLoc, y); if (rFillLoc >= _fillLayer.TilesWide || /*_sourceStack.Equals(_fillLayer[tid]) ||*/ !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid]))) break; } rFillLoc--; FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y); _ranges.Enqueue(ref r); }
public void Enqueue(ref FloodFillRange r) { if (size + head == array.Length) { FloodFillRange[] newArray = new FloodFillRange[2 * array.Length]; Array.Copy(array, head, newArray, 0, size); array = newArray; head = 0; } array[head + (size++)] = r; }
public FloodFillRange Dequeue() { FloodFillRange range = new FloodFillRange(); if (size > 0) { range = array[head]; array[head] = new FloodFillRange(); head++; size--; } return range; }
/// <summary>Removes and returns the <see cref="FloodFillRange"/> at the beginning of the queue.</summary> public FloodFillRange Dequeue() { var range = new FloodFillRange(); if (size > 0) { range = array[head]; array[head] = new FloodFillRange(); head++;//advance head position size--;//update size to exclude dequeued item } return range; }
private static void LinearFloodFill(ref Vector2Int32 start, ref Vector2Int32 minBound, ref Vector2Int32 maxBound, Func<Vector2Int32, bool> validation, ref FloodFillRangeQueue ranges, ref HashSet<Vector2Int32> points) { //FIND LEFT EDGE OF COLOR AREA int lFillLoc = start.X; //the location to check/fill on the left int x = start.X; int y = start.Y; points.Add(start); while (true) { points.Add(new Vector2Int32(lFillLoc, y)); // Preform validation for next point lFillLoc--; var curPoint = new Vector2Int32(lFillLoc, y); if (lFillLoc <= minBound.X || !validation(curPoint) || points.Contains(curPoint)) break; //exit loop if we're at edge of bitmap or match area } lFillLoc++; //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left while (true) { points.Add(new Vector2Int32(rFillLoc, y)); rFillLoc++; var curPoint = new Vector2Int32(rFillLoc, y); if (rFillLoc >= maxBound.X || !validation(curPoint) || points.Contains(curPoint)) break; //exit loop if we're at edge of bitmap or color area } rFillLoc--; var r = new FloodFillRange(lFillLoc, rFillLoc, y); ranges.Enqueue(ref r); }
private void LinearFill(ref int x, ref int y) { // Find left edge int lFillLoc = x; while (true) { TileCoord tid = new TileCoord(lFillLoc, y); if (SourceType == TileSourceType.Brush && ActiveBrush != null) { ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y); } else { _fillCommand.QueueReplacement(tid, _sourceStack); _fillLayer[tid] = _sourceStack; } lFillLoc--; tid = new TileCoord(lFillLoc, y); if (lFillLoc < 0 || /*_sourceStack.Equals(_fillLayer[tid]) ||*/ !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid]))) { break; } } lFillLoc++; // Find right edge int rFillLoc = x; while (true) { TileCoord tid = new TileCoord(rFillLoc, y); /*if (!_sourceStack.Equals(_fillLayer[tid])) {*/ if (SourceType == TileSourceType.Brush && ActiveBrush != null) { ActiveBrush.ApplyBrush(_fillLayer, tid.X, tid.Y); } else { _fillCommand.QueueReplacement(tid, _sourceStack); _fillLayer[tid] = _sourceStack; } //} rFillLoc++; tid = new TileCoord(rFillLoc, y); if (rFillLoc >= _fillLayer.TilesWide || /*_sourceStack.Equals(_fillLayer[tid]) ||*/ !(_matchStack == null ? _matchStack == _fillLayer[tid] : _matchStack.Equals(_fillLayer[tid]))) { break; } } rFillLoc--; FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y); _ranges.Enqueue(ref r); }
private void LinearFloodFill(ref int x, ref int y, ref Tile originTile) { int bitmapWidth = _wvm.CurrentWorld.TilesWide; int bitmapHeight = _wvm.CurrentWorld.TilesHigh; //FIND LEFT EDGE OF COLOR AREA int lFillLoc = x; //the location to check/fill on the left int tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(lFillLoc, y); _wvm.SetPixel(lFillLoc, y); _wvm.UpdateRenderPixel(lFillLoc, y); _wvm.CheckTiles[tileIndex] = true; } lFillLoc--; tileIndex--; if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y)) { break; //exit loop if we're at edge of bitmap or color area } } /* Heathtech */ BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1); lFillLoc++; if (lFillLoc < _minX) { _minX = lFillLoc; } //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(rFillLoc, y); _wvm.SetPixel(rFillLoc, y); _wvm.UpdateRenderPixel(rFillLoc, y); _wvm.CheckTiles[tileIndex] = true; BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1); } rFillLoc++; tileIndex++; if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y)) { break; //exit loop if we're at edge of bitmap or color area } } /* Heathtech */ BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1); rFillLoc--; if (rFillLoc > _maxX) { _maxX = rFillLoc; } var r = new FloodFillRange(lFillLoc, rFillLoc, y); _ranges.Enqueue(ref r); }
private void LinearFloodFill(ref int x, ref int y, ref Tile originTile) { int bitmapWidth = _wvm.CurrentWorld.TilesWide; int bitmapHeight = _wvm.CurrentWorld.TilesHigh; //FIND LEFT EDGE OF COLOR AREA int lFillLoc = x; //the location to check/fill on the left int tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(lFillLoc, y); _wvm.SetPixel(lFillLoc, y); _wvm.UpdateRenderPixel(lFillLoc, y); _wvm.CheckTiles[tileIndex] = true; } lFillLoc--; tileIndex--; if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y)) break; //exit loop if we're at edge of bitmap or color area } /* Heathtech */ BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1); lFillLoc++; if (lFillLoc < _minX) _minX = lFillLoc; //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(rFillLoc, y); _wvm.SetPixel(rFillLoc, y); _wvm.UpdateRenderPixel(rFillLoc, y); _wvm.CheckTiles[tileIndex] = true; BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1); } rFillLoc++; tileIndex++; if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y)) break; //exit loop if we're at edge of bitmap or color area } /* Heathtech */ BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1); rFillLoc--; if (rFillLoc > _maxX) _maxX = rFillLoc; var r = new FloodFillRange(lFillLoc, rFillLoc, y); _ranges.Enqueue(ref r); }
private void LinearFloodFill(ref int x, ref int y, ref TilePicker tp, ref Tile originTile) { int bitmapWidth = _world.Header.MaxTiles.X; int bitmapHeight = _world.Header.MaxTiles.Y; //FIND LEFT EDGE OF COLOR AREA int lFillLoc = x; //the location to check/fill on the left int tileIndex = (bitmapWidth * y) + x; while (true) { if (HistMan.SaveHistory) HistMan.AddTileToBuffer(lFillLoc, y, ref _world.Tiles[x, y]); _world.SetTileXY(ref lFillLoc, ref y, ref tp, ref _selection); tilesChecked[tileIndex] = true; lFillLoc--; tileIndex--; if (lFillLoc <= 0 || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[lFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(lFillLoc, y))) break; //exit loop if we're at edge of bitmap or color area } lFillLoc++; if (lFillLoc < minX) minX = lFillLoc; //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left tileIndex = (bitmapWidth * y) + x; while (true) { if (HistMan.SaveHistory) HistMan.AddTileToBuffer(rFillLoc, y, ref _world.Tiles[x, y]); _world.SetTileXY(ref rFillLoc, ref y, ref tp, ref _selection); tilesChecked[tileIndex] = true; rFillLoc++; tileIndex++; if (rFillLoc >= bitmapWidth || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[rFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(rFillLoc, y))) break; //exit loop if we're at edge of bitmap or color area } rFillLoc--; if (rFillLoc > maxX) maxX = rFillLoc; FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y); ranges.Enqueue(ref r); }