- Home /
Fit in squares in a dedicated space
A random number between 2 and 100, What I want to do is; create a number of squares(doesn't have to be, any shape is ok) that will fit accordingly inside the dedicated space for them(let's say half of the screen, etc). if the number is 2, create two squares that are half the space size big. if the number is 10, create 10 squares 1/10 space size big. maximum squares per rows and columns are 10... Example:
How can I achieve something like this, any tutorial or idea?
Answer by Bunny83 · Aug 24, 2020 at 09:49 AM
If the rectangles should be congruent, it gets tricky since this becomes a pure mathematical issue. It completely depends on the number you roll and how many prime factors this number has. For example any prime number X would mean you can only have a single row and X columns since you can not divide a prime number into any smaller whole numbers. For example the number 15 has the factors 3 * 5
, so you can simply split the area into equal rectangles and arrange them in a 3 by 5 grid.
If the number is 42 the factors are 2 * 3 * 7
. It's up to you how you split those factors into two numbers. However in this case we would probably use 6 and 7. However a number like 43 which is a prime number can not be divided at all. So your only choice with this number is to have one row with 43 columns, or one column with 43 rows. This holds true for all prime numbers in your range, specifically 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97. Keep in mind that you can also end up with a number that consists a combination of a quite large prime factor and a very small one. For example 94. It's prime factors are 2 * 47
However if you just want the rectangles to just have "equal size" / "equal area" it's possible to arrange any number of rectangles in a certain rectangular area, though the rectangles would not be congruent. So the rectangles would have different width and heights but their product would always give the same value. So a single rectangle that is 2.3 * 4.2
has an area of 9.66. Likewise a rectangle that has dimensions 1.6 * 6.0375
also has an area of 9.66. The process is a bit more complicated. Of course you would start calculating the area of a single rectangles by dividing your whole area through the number of rectangles you want. Next would be a similar process to above, but in the case of prime numbers or very small factors we have to split the number "additively". There are also many ways it could be split up. For example the prime number 41 can be split into the sum 12+12+12+5. So we could simply divide our space into 4 columns with the ratio 12:12:12:5. In each "12" area we can create 2*6
rectangles, so 2 columns and 6 rows in the first 3 areas and just a single column with 5 rows. So in the end we have a 6x6 area on the left and a single additional column with 5 rectangles.
Assume we have an area that is 800x600. Dividing 800 by 41 gives us 19.51219 (where 0.51219 are recurring). So our first 3 big columns would be 12 times that much which is 234.14634. Since we split each of the first 3 columns into 2 a single rectangle in those first columns would have a width of 117.07317. The last column with just 5 rectangles would have a width of 97.56097. A similar process is done for the height. We divide space into 6 rows in the first two columns but into 5 rows in the last column so 600 / 6 == 100 and 600 / 5 == 120. So we end up with a 6x6 grid of congruent rectangles which have a dimensions 117.07317 x 100 and an additional column with 5 congruent rectangles with dimensions 97.56097 x 120. So each rectangle has an area of about 11707.31707 and we will fill the whole space tightly.
In the end it can get really complicated however your exact rules / requirements are important because depending on your requirements, not all cases are possible.
What I was thing was; max 10 squares in columns & rows. so if the number is 11 first row will be filled with 10 squares. and then there will be a second row with just 1 square. space will be halved since there need to be 2 rows. like in the image(number 20) so we can count the rows with just a simple divide 10. each square will be the same size. so how do I calculate the size? I think that's the main problem.
Well, if the size of the rectangles doesn't matter at all you can of course arrange them however you want. But you clearly have some constraints you just haven't really thought about. If you just want to fill rows one after the other up to 10 it's quite trivial.
First you divide your number by 10 and round the value down. This is the number of rows you need. Next you simply take the modulo of your number by 10 to get the number of rects in the last row. So all you have to do now is fill as many rows you have with 10 rects except for the last one which is filled with the remaining rects.
public static List<Rect> SubdivideRect(Rect aSource, int aCount)
{
var rects = new List<Rect>(aCount);
int rows = aCount / 10;
int remain = aCount % 10;
float height = aSource.height / rows;
float width = aSource.width / 10;
rows--;
for(int i = 0; i < rows; i++)
{
for(int n = 0; n < 10; n++)
rects.Add(new Rect(n*width, i*height, width, height));
}
width = aSource.width / remain;
for(int i = 0; i < remain; i++)
rects.Add(new Rect(i*width, rows*height, width, height));
return rects;
}
This should do what you said. Of course the rectangles don't really follow any size restrictions. So as you said if you have 11, you will fill the first half with 10 rects and the second half with a single rect.
Answer by benj11scool · Aug 23, 2020 at 11:28 PM
You can find the scaling of the each cube with this piece of code:
public Vector2 RectScale(int HeightInSquares, int WidthInSquares, float ScreenSpaceHeight, float ScreenSpaceWidth){
//We divide the screen space by the number of cubes to get how much each fill up
float Height = (float)ScreenSpaceHeight/HeightInSquares;
float WidthOfEachCube = (float)ScreenSpaceWidth/WidthInSquares;
return new Vector2(Width, Height);
}
Next you can use a for loop to generate your squares like this:
Vector2 UnitScale = RectScale(HeightInSquares, WidthInSquares, ScreenSpaceHeight, ScreenSpaceWidth);
for(x = 1; x > HeightInSquares * WidthInSquares, x++){
int y = x/10
Vector2 Pos = new Vector2(x * UnitScale.x, y * UnitScale.y)
//Create your square here using the vector2 position above and UnitScale Vector2
}