Hi,
I’m trying to subdivide my canvas into multiple random areas and then being able to access each area’s width and height to draw patterns inside.
Is there a classic algorithm to do this?
Would you recommend and not too convoluted approach I could study?
Thanks
Hi @goldorak,
One solution is to store your random areas an an object with the required properties:
{
x: 20,
y: 45,
width: 500,
height: 254,
}
where x
and y
are the top left coordinates of the area and width
and height
store the size of that area.
If your canvas has a total size of 500x500
, then you need to create random sub areas that fits in that area. Then if you want the areas not to be smaller than a certain value you need to take that into account.
The steps would be:
- Create an empty array of areas
- Do a loop
n
number of times - Each time choose a random location of the top left corner (inside the canvas)
- Choose it’s size randomly so that it lies in the main canvas
- Add that object to the array
Then in another part of your program you can access those areas by looking at the elements in that array and draw things based on that!
Hi @goldorak,
One approach could be the following:
- Randomly split your canvas/part in 2 in both the x and y direction. You end up with 4 parts.
- For each new parts, decide weither or not you want to split it even more.
- If you decide to split it even more, repeat step 1 and 2.
The issue with this is that, the result will fill quite “squary” as you can see here:
From there, maybe it could be a good idea to merge some parts:
And why not going through the subdivising step one more time as well as the merging step to try making it even less “squary”?
the first answer gives a good data structure
the issue here is that the sub-canvases are not clearly defined.
- Are they allowed to overlap? The 2nd answer gives a good answer to that.
- Is it allowed that the sub-canvases are distributed in a way that parts of the canvas are left empty (are not covered by a sub-canvas)?
My idea
My idea is similar to answer 2.
When you
- define 3 random points A and B and C and
- A.x < B.x < C.x and
- C.x=width
you have 6 non-overlapping sub-canvases
Use the data structure of answer 1.
Example
ArrayList <SubCanvas> subCanvases = new ArrayList();
void setup() {
size(800, 500);
PVector a=new PVector(), b=new PVector(), c=new PVector();
a.set(random(width/2), random(height-100));
b.set(random(a.x+20, width-100), random(height-100));
c.set(width, random(height-100));
SubCanvas sC = new SubCanvas();
sC.sCx=0;
sC.sCy=0;
sC.sCwidth=a.x;
sC.sCheight=a.y;
subCanvases.add(sC);
// #2 is below #1
sC = new SubCanvas();
sC.sCx=0;
sC.sCy=a.y;
sC.sCwidth=a.x;
sC.sCheight=height-a.y;
subCanvases.add(sC);
// #3
sC = new SubCanvas();
sC.sCx = a.x;
sC.sCy = 0;
sC.sCwidth = b.x-a.x;
sC.sCheight = b.y;
subCanvases.add(sC);
}
void draw() {
background(255, 0, 0);
for ( SubCanvas sc : subCanvases) {
sc.display();
}
}
// ===============================================================
class SubCanvas {
float sCx,
sCy,
sCwidth,
sCheight;
color sCcol = color(random(255));
void display() {
fill(sCcol);
stroke(255);
rect(sCx,
sCy,
sCwidth,
sCheight);
}
//
}
//
I would create a class subCanvas that stores x and y (upper left corner = origin of that subCanvas) as well as w and h (width and height of that subcanvas).
Instead of a simple array of subCanvases I´d create a second class canvasList storing an array of subCanvases and having a method to create a new one. In this method all functionality to check size of new subCanvas and overlap would be situated.
This would allow for having/not having overlapping supCanvases, allowing/restricting subCanvases to/from reaching outside the P5 canvas… on the fly
Factoring these things in those 2 classes reduces convolution while retaining all the flexibility you want.
The other answers you got here can be seen (and realized) as special cases, maybe with special createSubCanvas methods.
Then add a show()-method to the subCanvas class. For testing just paint a rect (this.x, this.y, this.w, this.h). If you want that border later is your design decision.
Find a way to associate the things you want to display on a certain subCanvas to that subCanvas.
then translate(subCanvas.x subCanvas.y) them and find a way to constrict them from reaching over your subCanvas (that may be a little tricky)
Another possible approach (maybe a little over the top) for putting things on your subCanvas:
look into createImage().
A subCanvas could be an image of width w and height h that is shown at position x,y
Then you can draw your stuff using loadPixels/updatePixels