Say, for example, you got several Rectangles in a table like this,
And you want to get a point with equal probability like this;
How would I write a function that would get a point with equal probability across all rectangles?
No rotations.
Say, for example, you got several Rectangles in a table like this,
And you want to get a point with equal probability like this;
How would I write a function that would get a point with equal probability across all rectangles?
No rotations.
The quick way (not in terms of efficiency, but in terms of implementing what you want) would probably be:
This would perform really badly if, for example, the rectangles are very far apart. Just keep that in mind! If after enough iterations you still don’t find a point, you can select a random rectangle and generate a random point inside that rectangle as a fallback. If you want to be more sophisticated, you can weigh the rectangles based on their area.
I had a solution in mind.
What you could do is, since your rectangles seem to be grid aligned, use a range on X and Y to generate your points (random between each of the four corners, or basically a random within the rectangle).
What you should do is, for every point generated, use a test of that point’s position to see if it’s inside of another rectangle.
You should then, if the amount of rectangles that contain that point is >1, do another random chance which is 1/n
where n
is the amount of rectangles. Here it is visualized for you:
For checking collision you should keep it simple: For every rectangle, make the following check:
function PointCollidesIn(a, b, point)
-- a is the top left corner of the rectangle as a Vector2
-- b is the lower right corner of the rectangle as a Vector2
-- point is your point as a Vector2
if (point.X >= a.X and point.X <= b.X) and (point.Y >= a.Y and point.Y <= b.Y) then
-- The parenthesis are not necessary, it's just something that helps organize the operands.
return true
end
return false
end
local pointCollisions = 0
for _, rectanglePart in pairs(someArrayOfRectangles) do
-- Assume you've already formatted the args to conform to the requirements of PointCollidesIn
-- Also assume you've created a "point" variable that is a point within one of your rectangles. How you select which rectangle the point is generated in is on you to decide.
if PointCollidesIn(a, b, point) then
pointCollisions = pointCollisions + 1
end
end
if math.random() < 1/pointCollisions then
-- Place the point
else
-- Scrap the point
end
Something along these lines should (ideally) make you the right result. I’m not very good with working with complex shapes like this so there may be a better, much faster way. I’m afraid I’m unable to present such a solution, however.
How would you then merge it altogether?