so i have a vector2
how would i detect if that vector2 is inside an area
You can check the x,y of the point and see if its within a given area.
E.g the top left would be
X < 0 and y > 0
And you can even do areas by checking between two points for the x and y like so
X > -10 and x < 0 – will see if x is between 0 and -10
You would individually check the X
and Y
values of the Vector2 you are experimenting on.
Let’s say you want it to be in a square. The square has 4 points, which are (1, 4), (2, 1), (4, 2), and (3, 6). With that in mind, we know a few things. The X value has to be between 1 and 4. The Y value has to be between 1 and 6. BOTH of those things need to be true, and then we have figured out whether the point is within the square or not.
However, that only works for regular, straight quadrilaterals. The following will deal with imaginary rays that goes along an axis. If the number of times the ray intersects the polygon is even (including 0 times), it means the point is not inside of the polygon. The opposite is true if the number turns out odd.
Here is a visual representation, then of course the code:
local square = {
Vector2.new(1,4),
Vector2.new(2,1),
Vector2.new(4,2),
Vector2.new(3,6)
}
local function isInVicinity(point, vicinity)
local result = false
for i,v in pairs(vicinity) do
local nxt = i+1
if nxt>#vicinity then nxt=1 end
if ((v.Y>point.Y)~=(vicinity[nxt].Y>point.Y) and point.X<(vicinity[nxt].X-v.X)*(point.Y-v.Y)/(vicinity[nxt].Y-v.Y)+v.X) then
result = not result
end
end
return result
end
local point1 = Vector2.new(3,5)
local point2 = Vector2.new(0,-1)
print(isInVicinity(point1, square)) -- true
print(isInVicinity(point2, square)) -- false
You can add however many more points that you want, and any type of shape, and this will still work.
To check if a point lies in the area of a shape formed by a set of arbitrary points. You can use winding numbers. This method is really fast and easy to implement. I found this method over at twitter shared by @.sleitnick (Which also linked to Freya Holmer’s original tweet).
The idea is to add the signed angles between the point and the points of the shape i.e. the angle subtended by a side of the shape on the point. If this sum adds up to 360, then the point lies inside the confined area. Surprisingly, this works for all kinds of shapes, even with ones that have holes in them.
Here’s a simple implementation for Vector2s. (Haven’t tested this, lemme know if there are any mistakes/corrections)
-- shape is a table of vector2s of the boundary of the area (in order).
local function IsInsideShape(point: Vector2, shape)
local angleSum = 0
for i, a in ipairs(shape) do
local b = shape[i + 1] or shape[1]
local vector1 = a - point
local vector2 = b - point
local dot = vect1:Dot(vect2)
dot /= vect1.Magnitude * vect2.Magnitude
local subtendedAngle = math.deg(math.acos(dot))
local signedAngle = subtendedAngle * math.sign(subtendedAngle)
angleSum += subtendedAngle
end
return math.round(angleSum) == 360
end
-- false
IsInsideShape(Vector2.new(0, 0), {
Vector2.new(1, 1),
Vector2.new(2, 2),
Vector2.new(2, 1)
})
-- true
IsInsideShape(Vector2.new(0, 0), {
Vector2.new(1, 1),
Vector2.new(1, -1),
Vector2.new(-1, -1),
Vector2.new(-1, 1)
})
You can also use another method which deals with casting rays. If you cast an axis-aligned ray from the point towards the axis-aligned direction, and if it intersects the boundary of the shape an odd number of times then it is inside the point else not. This will be harder and slower to implement though.
Moreover, you can also use methods as told by others above for simpler structures of shapes.
The method I provided above this used that idea. Cool how there are many ways to solve one seemingly simple problem.
Edited my solution a bit, you can recheck. My older solution worked only if the point was Vector2.new(0, 0) i.e. the origin. It works for any point now!