Flood filling algorithm doesn't work as expected - it creates gaps between pixels










0















Well, I can't be so expressive in the title, so I will try to explain it here.



Basically my flood filling algorithm is doing this:



...



The different colors means the following:



  • Blue pixels are the points from the polygon

  • Red pixels are what Flood Fill has already filled

  • Magenta is the combination of both colors

  • Yellow pixels should never appear (that means that the algorithm that iterates the shape has already been iterated)

  • Everything else is the source texture

This is my current method:



 /// <summary>
/// Floods the fill.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target.</param>
/// <param name="replacement">The replacement.</param>
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement)
where T : IEquatable<T>

int i;

source.FloodFill(x, y, width, height, target, replacement, out i);


/// <summary>
/// Floods the array following Flood Fill algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target to replace.</param>
/// <param name="replacement">The replacement.</param>
/// <param name="i">The i.</param>
// This was generic
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement, out int i)
where T : IEquatable<T>

i = 0;
HashSet<int> queue = new HashSet<int>();

queue.Add(P(x, y, width, height));

while (queue.Count > 0)

int _i = queue.First(),
_x = _i % width,
_y = _i / width;

queue.Remove(_i);

if (source[_i].Equals(target))
source[_i] = replacement;

for (int offsetX = -1; offsetX < 2; offsetX++)
for (int offsetY = -1; offsetY < 2; offsetY++)


if (i > 100000)
break;




I can't show the other code, but I can try to explain it.



Basically, we have this texture (https://themindheist.files.wordpress.com/2015/03/gta_usa_map3.png) (It's too big to be here).



  • We iterate it pixel by pixel.

  • If we found any allowed pixel (Grass, Rock, Ice, Snow or whatever) then...

  • We start looking for the shape of the current biome

  • Then before continuing iterating we call Flood Fill algorithm.

  • With this call we ensure that we will never pass over any pixel that form part of any of the map's polygons.

But as you can see, I have problems.



Watching at my implementation I suppose that when enqueued pixels looks for neighbors they are trapped and they don't return any neighbor pixel.



Or maybe, this is the way my flood fill algorithm executes (under special conditions I don't know).



What could you suggest/recommend me to do?



Note: The texture was get when I manually exited the method. So, my fill algorithm is filling the texture by "layers" that's why there are so many yellow pixels.










share|improve this question
























  • You are missing marking pixels as visited. At the moment you can visit a node multiple times

    – juvian
    Nov 14 '18 at 20:12











  • I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

    – z3nth10n
    Nov 14 '18 at 20:18






  • 1





    You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

    – juvian
    Nov 14 '18 at 20:22











  • So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

    – z3nth10n
    Nov 14 '18 at 20:40











  • I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

    – z3nth10n
    Nov 14 '18 at 20:41















0















Well, I can't be so expressive in the title, so I will try to explain it here.



Basically my flood filling algorithm is doing this:



...



The different colors means the following:



  • Blue pixels are the points from the polygon

  • Red pixels are what Flood Fill has already filled

  • Magenta is the combination of both colors

  • Yellow pixels should never appear (that means that the algorithm that iterates the shape has already been iterated)

  • Everything else is the source texture

This is my current method:



 /// <summary>
/// Floods the fill.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target.</param>
/// <param name="replacement">The replacement.</param>
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement)
where T : IEquatable<T>

int i;

source.FloodFill(x, y, width, height, target, replacement, out i);


/// <summary>
/// Floods the array following Flood Fill algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target to replace.</param>
/// <param name="replacement">The replacement.</param>
/// <param name="i">The i.</param>
// This was generic
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement, out int i)
where T : IEquatable<T>

i = 0;
HashSet<int> queue = new HashSet<int>();

queue.Add(P(x, y, width, height));

while (queue.Count > 0)

int _i = queue.First(),
_x = _i % width,
_y = _i / width;

queue.Remove(_i);

if (source[_i].Equals(target))
source[_i] = replacement;

for (int offsetX = -1; offsetX < 2; offsetX++)
for (int offsetY = -1; offsetY < 2; offsetY++)


if (i > 100000)
break;




I can't show the other code, but I can try to explain it.



Basically, we have this texture (https://themindheist.files.wordpress.com/2015/03/gta_usa_map3.png) (It's too big to be here).



  • We iterate it pixel by pixel.

  • If we found any allowed pixel (Grass, Rock, Ice, Snow or whatever) then...

  • We start looking for the shape of the current biome

  • Then before continuing iterating we call Flood Fill algorithm.

  • With this call we ensure that we will never pass over any pixel that form part of any of the map's polygons.

But as you can see, I have problems.



Watching at my implementation I suppose that when enqueued pixels looks for neighbors they are trapped and they don't return any neighbor pixel.



Or maybe, this is the way my flood fill algorithm executes (under special conditions I don't know).



What could you suggest/recommend me to do?



Note: The texture was get when I manually exited the method. So, my fill algorithm is filling the texture by "layers" that's why there are so many yellow pixels.










share|improve this question
























  • You are missing marking pixels as visited. At the moment you can visit a node multiple times

    – juvian
    Nov 14 '18 at 20:12











  • I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

    – z3nth10n
    Nov 14 '18 at 20:18






  • 1





    You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

    – juvian
    Nov 14 '18 at 20:22











  • So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

    – z3nth10n
    Nov 14 '18 at 20:40











  • I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

    – z3nth10n
    Nov 14 '18 at 20:41













0












0








0








Well, I can't be so expressive in the title, so I will try to explain it here.



Basically my flood filling algorithm is doing this:



...



The different colors means the following:



  • Blue pixels are the points from the polygon

  • Red pixels are what Flood Fill has already filled

  • Magenta is the combination of both colors

  • Yellow pixels should never appear (that means that the algorithm that iterates the shape has already been iterated)

  • Everything else is the source texture

This is my current method:



 /// <summary>
/// Floods the fill.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target.</param>
/// <param name="replacement">The replacement.</param>
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement)
where T : IEquatable<T>

int i;

source.FloodFill(x, y, width, height, target, replacement, out i);


/// <summary>
/// Floods the array following Flood Fill algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target to replace.</param>
/// <param name="replacement">The replacement.</param>
/// <param name="i">The i.</param>
// This was generic
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement, out int i)
where T : IEquatable<T>

i = 0;
HashSet<int> queue = new HashSet<int>();

queue.Add(P(x, y, width, height));

while (queue.Count > 0)

int _i = queue.First(),
_x = _i % width,
_y = _i / width;

queue.Remove(_i);

if (source[_i].Equals(target))
source[_i] = replacement;

for (int offsetX = -1; offsetX < 2; offsetX++)
for (int offsetY = -1; offsetY < 2; offsetY++)


if (i > 100000)
break;




I can't show the other code, but I can try to explain it.



Basically, we have this texture (https://themindheist.files.wordpress.com/2015/03/gta_usa_map3.png) (It's too big to be here).



  • We iterate it pixel by pixel.

  • If we found any allowed pixel (Grass, Rock, Ice, Snow or whatever) then...

  • We start looking for the shape of the current biome

  • Then before continuing iterating we call Flood Fill algorithm.

  • With this call we ensure that we will never pass over any pixel that form part of any of the map's polygons.

But as you can see, I have problems.



Watching at my implementation I suppose that when enqueued pixels looks for neighbors they are trapped and they don't return any neighbor pixel.



Or maybe, this is the way my flood fill algorithm executes (under special conditions I don't know).



What could you suggest/recommend me to do?



Note: The texture was get when I manually exited the method. So, my fill algorithm is filling the texture by "layers" that's why there are so many yellow pixels.










share|improve this question
















Well, I can't be so expressive in the title, so I will try to explain it here.



Basically my flood filling algorithm is doing this:



...



The different colors means the following:



  • Blue pixels are the points from the polygon

  • Red pixels are what Flood Fill has already filled

  • Magenta is the combination of both colors

  • Yellow pixels should never appear (that means that the algorithm that iterates the shape has already been iterated)

  • Everything else is the source texture

This is my current method:



 /// <summary>
/// Floods the fill.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target.</param>
/// <param name="replacement">The replacement.</param>
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement)
where T : IEquatable<T>

int i;

source.FloodFill(x, y, width, height, target, replacement, out i);


/// <summary>
/// Floods the array following Flood Fill algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="target">The target to replace.</param>
/// <param name="replacement">The replacement.</param>
/// <param name="i">The i.</param>
// This was generic
public static void FloodFill<T>(this T source, int x, int y, int width, int height, T target, T replacement, out int i)
where T : IEquatable<T>

i = 0;
HashSet<int> queue = new HashSet<int>();

queue.Add(P(x, y, width, height));

while (queue.Count > 0)

int _i = queue.First(),
_x = _i % width,
_y = _i / width;

queue.Remove(_i);

if (source[_i].Equals(target))
source[_i] = replacement;

for (int offsetX = -1; offsetX < 2; offsetX++)
for (int offsetY = -1; offsetY < 2; offsetY++)


if (i > 100000)
break;




I can't show the other code, but I can try to explain it.



Basically, we have this texture (https://themindheist.files.wordpress.com/2015/03/gta_usa_map3.png) (It's too big to be here).



  • We iterate it pixel by pixel.

  • If we found any allowed pixel (Grass, Rock, Ice, Snow or whatever) then...

  • We start looking for the shape of the current biome

  • Then before continuing iterating we call Flood Fill algorithm.

  • With this call we ensure that we will never pass over any pixel that form part of any of the map's polygons.

But as you can see, I have problems.



Watching at my implementation I suppose that when enqueued pixels looks for neighbors they are trapped and they don't return any neighbor pixel.



Or maybe, this is the way my flood fill algorithm executes (under special conditions I don't know).



What could you suggest/recommend me to do?



Note: The texture was get when I manually exited the method. So, my fill algorithm is filling the texture by "layers" that's why there are so many yellow pixels.







c# algorithm unity3d optimization flood-fill






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 19:59







z3nth10n

















asked Nov 14 '18 at 19:14









z3nth10nz3nth10n

95721124




95721124












  • You are missing marking pixels as visited. At the moment you can visit a node multiple times

    – juvian
    Nov 14 '18 at 20:12











  • I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

    – z3nth10n
    Nov 14 '18 at 20:18






  • 1





    You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

    – juvian
    Nov 14 '18 at 20:22











  • So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

    – z3nth10n
    Nov 14 '18 at 20:40











  • I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

    – z3nth10n
    Nov 14 '18 at 20:41

















  • You are missing marking pixels as visited. At the moment you can visit a node multiple times

    – juvian
    Nov 14 '18 at 20:12











  • I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

    – z3nth10n
    Nov 14 '18 at 20:18






  • 1





    You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

    – juvian
    Nov 14 '18 at 20:22











  • So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

    – z3nth10n
    Nov 14 '18 at 20:40











  • I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

    – z3nth10n
    Nov 14 '18 at 20:41
















You are missing marking pixels as visited. At the moment you can visit a node multiple times

– juvian
Nov 14 '18 at 20:12





You are missing marking pixels as visited. At the moment you can visit a node multiple times

– juvian
Nov 14 '18 at 20:12













I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

– z3nth10n
Nov 14 '18 at 20:18





I mark pixels as visited outside of the Flood Fill algorithm, and I suppose I do the same when I check !queue.Contains(targetIndex). In this case, what do you mean?

– z3nth10n
Nov 14 '18 at 20:18




1




1





You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

– juvian
Nov 14 '18 at 20:22





You start with source. On the first step you remove it from the queue add its neighbour's to the queue. Now you remove first neighbor added from the queue and you will add source again to the queue because it is not in it anymore

– juvian
Nov 14 '18 at 20:22













So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

– z3nth10n
Nov 14 '18 at 20:40





So, it's better to do this queue.Remove(_i) at the end or what do you suggest me?

– z3nth10n
Nov 14 '18 at 20:40













I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

– z3nth10n
Nov 14 '18 at 20:41





I created another forked fiddle: dotnetfiddle.net/jIhRSU and I see no differences, so I will check this. Also, I'm testing if I really need to check for Interloecked.

– z3nth10n
Nov 14 '18 at 20:41












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307270%2fflood-filling-algorithm-doesnt-work-as-expected-it-creates-gaps-between-pixel%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307270%2fflood-filling-algorithm-doesnt-work-as-expected-it-creates-gaps-between-pixel%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3