Quirks and nuances when using p5's pixel fill function

I am currently utilizing the p5.js library to work on a program that is designed to automatically fill closed spaces. However, I am encountering an issue where the program sometimes fills half-closed loops for reasons unknown to me. If anyone could provide assistance in pinpointing the problem, I would greatly appreciate it.

Here is an example illustrating the issue: https://i.sstatic.net/alfgW.png

To observe the problem, you need to zoom in significantly; otherwise, it breaks (on a side note, any guidance on scaling up the pixels would also be valuable).

let pixelVals;
let checkedPixels;
let filledPixels;
let iter = 0;
let drawFilled;

function setup() {
  pixelVals = array(height, width, 4);

  createCanvas(25, 25);
  pixelDensity(1);

  // Additional code for setting initial values
}

// Further functions and definitions...

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>

Apologies for the messy JavaScript code as I am still new to this language :)

// Additional code snippet

function setFilledFalse() {
  // Code implementation...
}

function array(length) {
  // Array function definition...
}

Thank you in advance,

Zac

Answer №1

My solution involved modifying the checkSurroundings function:

function checkArea(x, y) {
  pixelValues[x][y][1] = 255;
  filledPixels[x][y] = true;
  checkedPixels[x][y] = true;

  if(x == width - 1 || x == 0 || y == height - 1 || y == 0) {
    drawFilledArea = false;
  }
  if(x + 1 < width) {
    if(pixelValues[x + 1][y][0] != 255) {
      if(!checkedPixels[x + 1][y]) {
        checkArea(x + 1, y)
      }
    }
  }
  if(x - 1 >= 0) {
    if(pixelValues[x - 1][y][0] != 255) {
      if(!checkedPixels[x - 1][y]) {
        checkArea(x - 1, y)
      }
    }
  }
  if(y + 1 < height) {
    if(pixelValues[x][y + 1][0] != 255) {
      if(!checkedPixels[x][y + 1]) {
        checkArea(x, y + 1)
      }
    }
  }
  if(y - 1 >= 0) {
    if(pixelValues[x][y - 1][0] != 255) {
      if(!checkedPixels[x][y - 1]) {
        checkArea(x, y - 1)
      }
    }
  }
}

let pixelValues;
let checkedPixels;
let filledPixels;
let iteration = 0;
let drawFilledArea;

function setup() {
  pixelValues = array(height, width, 4);

  createCanvas(25, 25);
  pixelDensity(1);

  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      pixelValues[i][j][0] = 0;
      pixelValues[i][j][1] = 0;
      pixelValues[i][j][2] = 0;
      pixelValues[i][j][3] = 255;
    }
  }
}

function draw() {
  loadPixels();

  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      pixelValues[i][j][1] = 0;
    }
  }

  if(mouseIsPressed) {
    if(mouseX < width && mouseX >= 0 && mouseY < height && mouseY >= 0) {
      pixelValues[mouseX][mouseY][0] = 255;
    }
  }

  checkEnclosedArea();

  updatePixels();
}

function checkEnclosedArea() {
  checkedPixels = array(height, width);
  filledPixels = array(height, width);

  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      checkedPixels[i][j] = false;
      filledPixels[i][j] = false;
    }
  }

  for(var i = 0; i < height; i++) {
    for(var j = 0; j < width; j++) {
      if(!checkedPixels[i][j] && pixelValues[i][j][0] != 255) {
        drawFilledArea = true;
        checkArea(i, j);
        if(drawFilledArea) {
          fillArea();
        } else {
          clearFilledArea();
        }
      }
    }
  }

  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      for(var k = 0; k < 4; k++) {
        pixels[(i + j * width) * 4 + k] = pixelValues[i][j][k];
      }
    }
  }
}

function checkArea(x, y) {
  pixelValues[x][y][1] = 255;
  filledPixels[x][y] = true;
  checkedPixels[x][y] = true;

  if(x == width - 1 || x == 0 || y == height - 1 || y == 0) {
    drawFilledArea = false;
  }
  if(x + 1 < width) {
    if(pixelValues[x + 1][y][0] != 255) {
      if(!checkedPixels[x + 1][y]) {
        checkArea(x + 1, y)
      }
    }
  }
  if(x - 1 >= 0) {
    if(pixelValues[x - 1][y][0] != 255) {
      if(!checkedPixels[x - 1][y]) {
        checkArea(x - 1, y)
      }
    }
  }
  if(y + 1 < height) {
    if(pixelValues[x][y + 1][0] != 255) {
      if(!checkedPixels[x][y + 1]) {
        checkArea(x, y + 1)
      }
    }
  }
  if(y - 1 >= 0) {
    if(pixelValues[x][y - 1][0] != 255) {
      if(!checkedPixels[x][y - 1]) {
        checkArea(x, y - 1)
      }
    }
  }
}

function fillArea() {
  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      if(filledPixels[i][j]) {
        pixelValues[i][j][2] = 255;
      }
    }
  }
}

function clearFilledArea() {
  for(var i = 0; i < width; i++) {
    for(var j = 0; j < height; j++) {
      filledPixels[i][j] = false;
    }
  }
}

function array(size) {
  var arr = new Array(size || 0), i = size;

  if (arguments.length > 1) {
    var args = Array.prototype.slice.call(arguments, 1);
    while(i--) arr[size-1 - i] = array.apply(this, args);
  }
  return arr
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adjusting the size and location of the current browser window using jQuery

Is there a way to modify the height, width, and position of the browser window using jQuery's document.ready() function? ...

The jQuery prop("disabled") function is not operating as expected

Although I've seen this question answered multiple times, none of the suggested solutions seem to be working for my specific example. Hopefully, a fresh set of eyes can help me figure out what's going wrong. Even after adding alerts to confirm t ...

Incorporate a division based on the selection made from a jQuery dropdown menu

Is there a way to dynamically display a div to the right of a drop-down menu based on the user's selection using DOM manipulation? For reference, you can view an example of my current progress here: http://jsbin.com/#/afojid/1/edit The initial drop ...

Update the ngModel value once input validation has been successfully validated

My input is defined as shown below <input id="xInputControl" name="xInputControl" type="text" xInput class="form-control" [(ngModel)]="x" #validated="ng ...

Only retrieve links that don't have the specified class by using regular expressions

I am trying to extract all links from an HTML document using REGEX, except for those with a specific class name. For example: <a href="someSite" class="className">qwe</a> <a href="someSite">qwe</a> My goal is to only capture the ...

Traverse an array containing nested objects using Javascript

I am facing difficulty printing out objects stored in an array. When I console log, this is the result: console.log(product.categories) https://i.stack.imgur.com/YVprQ.png How can I iterate through these nested objects to display them individually like t ...

When refreshing the page, the authentication token set in the Vuex store using axios in Nuxt.js/Vue.js gets reset

Here is the code snippet I am using to manage login, logout, user retrieval, and token setting for all axios requests as an auth header. While this code works perfectly during client-side rendering - such as logging in, storing the token in cookies, etc. ...

Using Vue.js to sift through and refine data

I have retrieved data from an API and am displaying it here using VueJS. The user information is stored inside the users[] array, with two types of plans: basic_plan and standard_plan. Currently, all users are being shown. Now I want to apply filters simi ...

I am attempting to achieve a smooth transition effect by fading in and out the CSS background color using JQuery and AJAX

Can anyone help me with my issue related to using Ajax to fadeIn a background color in beforeSend and fadeOut in success? I seem to have made some mistakes but can't figure out what went wrong. var data={ ...

Is There a Workaround for XMLHttpRequest Cannot Load When Using jQuery .load() with Relative Path?

My current project is stored locally, with a specific directory structure that I've simplified for clarity. What I'm aiming to do is include an external HTML file as the contents of a <header> element in my index.html file without manually ...

Building a multi-page application with ExtJs MVC

I'm new to MVC, especially when it comes to extJs. I want to implement the MVC approach in my project. I came across a tutorial at , which provided an example with only one page. In this example, they used app.js to load extjs views. My question is, w ...

Steps for extracting a portion of the current page's URL

Can someone help me extract a specific part of the current URL using JavaScript? The URL looks something like this: I need to isolate the number "3153038" from the URL and store it in a JavaScript variable. Thank you! ...

Day Change Triggers React [Native] View Update

I've been working on a React Native component that needs to update itself when the day changes, regardless of user interaction. Is there another method besides using setInterval for this task? If I use setTimeout in my viewDidLoad function with the n ...

Creating a Validation Form using either PHP or JavaScript

I need to create a form with the following columns: fullname, email, mobile, and address. If the visitor fills out the mobile field, they should only be allowed to enter numbers. And if the visitor fills out the email field, they should only be allowed to ...

Encountering problems when trying to open .dialog using JQuery

Hello everyone! I have an interface where, after a user logs in, their information is checked. If the user has not read the Terms of Service (TOS), then a dialog box should open. However, I am facing an issue as the dialog box never opens. Here is the cod ...

Import ES6 code by wrapping it in parentheses

Currently delving into React Native and I'm intrigued by the parentheses used in the first line of import. import React, { Component } from 'react'; import { AppRegistry, Text } from 'react-native'; class HelloWorldApp extends Co ...

Is there a way for me to automatically generate and send a random collection each time a GET request is made on my Node.js

I have been developing a typing application that utilizes an API to fetch random quotes from . I successfully created an API using MongoDB, Node.js, and Express which functions well. However, I encountered an issue when trying to send a random collection ...

"Error: The chai testing method appears to be improperly defined and is not

I am trying to set up a Mocha and Chai test. Here is my class, myClass.js: export default class Myclass { constructor() {} sayhello() { return 'hello'; }; } Along with a test file, test.myclass.js: I am attempting to a ...

Expanding the Element prototype with TypeScript

Is there a corresponding TypeScript code to achieve the same functionality as the provided JavaScript snippet below? I am looking to extend the prototype of the HTML DOM element, but I'm struggling to write TypeScript code that accomplishes this with ...

Is it advisable for postcss plugins to list postcss as a peer dependency?

I'm trying to incorporate the PostCSS Sass Color Function into my project. Unfortunately, I encountered this error: PostCSS plugin error: Your current version of PostCSS is 6.0.22, while postcss-sass-color-functions requires 5.2.18. This discrepa ...