Jump to content

Check if something is within four given points


Recommended Posts

Hello!

I am trying to do a boundary system based on coordinates, so no col shapes or anything. Unfortunately I'm not that good at math, but I tried doing it based on found results on the internet.

My problem is that this whole script is not working how it should, check it for yourself, it has debug outputs and visible markers for corners and the center.

  • Why does the width and height return a much bigger number than the calculatedX and calculatedY?
  • Why does the calculatedX and calculatedY return always the same?
  • Why does the width and height change values as I move around?

I would be really grateful if somebody could help me, this is for a community project, so others would be too!

Here's my current full code:

Global:

customBoundaries = {
  	-- this boundary is between the big brown building(s) and the skatepark on the road in LS
	["test"] = {
		point1 = {x = 1842.2908935547, y = -1412.469360351},
		point2 = {x = 1856.8596191406, y = -1412.555664062},
		point3 = {x = 1851.5925292969, y = -1436.5225830078},
		point4 = {x = 1842.0438232422, y = -1424.5217285156},
	},
}

Client:

local debugEnabled = true

function sum(n)
   return ((n+1) * n) / 2
end

function isElementWithinBoundary(element, boundary)
	if element and isElement(element) then
		local elementX, elementY, elementZ = getElementPosition(element)
		boundary = tostring(boundary)
		if boundary and type(boundary) == "string" then
			if customBoundaries and customBoundaries[boundary] then
				local corner1 = {customBoundaries[boundary].point1.x, customBoundaries[boundary].point1.y}
				local corner2 = {customBoundaries[boundary].point2.x, customBoundaries[boundary].point2.y}
				local corner3 = {customBoundaries[boundary].point3.x, customBoundaries[boundary].point3.y}
				local corner4 = {customBoundaries[boundary].point4.x, customBoundaries[boundary].point4.y}
				
				local centerX, centerY = (corner1[1] + corner2[1] + corner3[1] + corner4[1])/4, (corner1[2] + corner2[2] + corner3[2] + corner4[2])/4
				local originX, originY = elementX - corner1[1], elementY - corner1[2]
				
				local width = math.sqrt((corner2[1] - originX)^2 + (corner2[2] - originY)^2)
				local height = math.sqrt((corner4[1] - originX)^2 + (corner4[2] - originY)^2)
				
				local calculatedX = originX * (corner2[1] - originX)/width + originY * (corner2[2] - originY)/height
				local calculatedY = originX * (corner4[1] - originX)/width + originY * (corner4[2] - originY)/height
				
				outputChatBox("X: " .. math.floor(calculatedX) .. " | width: " .. math.floor(width))
				outputChatBox("Y: " .. math.floor(calculatedY) .. " | height: " .. math.floor(height))
				
				if (0 <= calculatedX and calculatedX <= width) and (0 <= calculatedY and calculatedY <= height) then
					outputChatBox("XD")
				end
				
				if debugEnabled then
					for points, coordinates in pairs(customBoundaries[boundary]) do
						
						local cornerMarker = createMarker(coordinates.x, coordinates.y, getGroundPosition(coordinates.x, coordinates.y, elementZ), "cylinder", 2, 140, 245, 20, 150)
						
						
						local centerMarker = createMarker(centerX, centerY, getGroundPosition(centerX, centerY, elementZ)+2, "arrow", 1, 245, 140, 20, 150)
					end
				end
			end
		end
	end
end

isElementWithinBoundary(localPlayer, "test")

Here's the calculation I was trying to copy and make it work based on: https://math.stackexchange.com/a/190257

I hope you understand my problem, thank you for your reply in advance!

Link to comment
customBoundaries = {
  	-- this boundary is between the big brown building(s) and the skatepark on the road in LS
	["test"] = {
		{x = 1842.2908935547, y = -1412.469360351},
		{x = 1856.8596191406, y = -1412.555664062},
		{x = 1851.5925292969, y = -1436.5225830078},
		{x = 1842.0438232422, y = -1424.5217285156},
	},
}

local colorOfBounds = tocolor(255, 0, 0)

bindKey("e", "down",
	function ()
		if isElementWithinBoundary(localPlayer, "test") then
			colorOfBounds = tocolor(0, 255, 0)
		else
			colorOfBounds = tocolor(255, 0, 0)
		end
	end
)

addEventHandler("onClientRender", getRootElement(),
	function ()
		local localX, localY, localZ = getElementPosition(localPlayer)
		local boundary = "test"

		for i = 1, #customBoundaries[boundary] do
			local currentPoint = customBoundaries[boundary][i]
			local nextPoint = customBoundaries[boundary][i + 1]

			if currentPoint then
				if i == #customBoundaries[boundary] then
					nextPoint = customBoundaries[boundary][1]
					dxDrawLine3D(currentPoint.x, currentPoint.y, localZ, nextPoint.x, nextPoint.y, localZ, colorOfBounds, 3)
				end

				dxDrawLine3D(currentPoint.x, currentPoint.y, localZ, nextPoint.x, nextPoint.y, localZ, colorOfBounds, 3)
			end
		end
	end
)

function isElementWithinBoundary(element, boundary)
	if isElement(element) and boundary and customBoundaries[boundary] and #customBoundaries[boundary] >= 3 then
		local pointX, pointY, pointZ = getElementPosition(element)
		local intersections = 0

		for i = 1, #customBoundaries[boundary] do
			local currentPoint = customBoundaries[boundary][i]

			if currentPoint then
				local nextPoint = customBoundaries[boundary][i + 1]
				local previousPoint = customBoundaries[boundary][i - 1]

				if i == 1 then
					previousPoint = customBoundaries[boundary][1]
				elseif i == #customBoundaries[boundary] then
					nextPoint = customBoundaries[boundary][1]
				end

				if areIntersecting(pointX, pointY, previousPoint.x, previousPoint.y, currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y) then
					intersections = intersections + 1
				end
			end
		end

		if intersections > 0 then
			return true
		end
	end

	return false
end

function sign(x1, y1, x2, y2, x3, y3)
	return (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3)
end

function areIntersecting(pointX, pointY, x1, y1, x2, y2, x3, y3)
	local b1 = sign(pointX, pointY, x1, y1, x2, y2) < 0
	local b2 = sign(pointX, pointY, x2, y2, x3, y3) < 0
	local b3 = sign(pointX, pointY, x3, y3, x1, y1) < 0

	return b1 == b2 and b2 == b3
end

 

Tested. Works with 3 or more points.

Yes, you can check the element within the the polygon.

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...