nearest

Useful functions to find the nearest.

Nearest point in array of points

-- function to calculate the distance between two points
local function distance(x1, y1, x2, y2)
	return math.sqrt((x2 - x1)^2 + (y2 - y1)^2)
end

-- function to find the nearest point from a list of points
function findNearestPointInPoints (points, point)
-- points is array of pairs: {x1, y1, x2, y2, ...}
	local minDistance = math.huge
	local nearestX, nearestY = nil, nil
	for i = 1, #points, 2 do
		local x, y = points[i], points[i + 1]
		local dist = distance(x, y, point[1], point[2])
		if dist < minDistance then
			minDistance = dist
			nearestX, nearestY = x, y
		end
	end
	return nearestX, nearestY, minDistance
end

Nearest point on line segment

-- function to calculate the distance between two points
local function distance(x1, y1, x2, y2)
	return math.sqrt((x2 - x1)^2 + (y2 - y1)^2)
end

-- function to find the nearest point on a segment to the given point
function findNearestPointOnSegment(segment, point)
-- segment is array of pairs: {x1, y1, x2, y2}
	local x1, y1, x2, y2 = segment[1], segment[2], segment[3], segment[4]
	local px, py = point[1], point[2]

	-- vector from the first point of the segment to the second point
	local dx, dy = x2 - x1, y2 - y1
	-- vector from the first point of the segment to the point
	local dx1, dy1 = px - x1, py - y1
	-- segment length squared
	local segmentLengthSquared = dx * dx + dy * dy

	if segmentLengthSquared == 0 then
		-- degenerate segment (same point), return the start point
		return {x1, y1}, distance(px, py, x1, y1)
	end

	-- projection of the point onto the line (parameter t)
	local t = ((dx1 * dx + dy1 * dy) / segmentLengthSquared)

	-- clamp t to be between 0 and 1 to stay within the segment
	if t < 0 then
		t = 0
	elseif t > 1 then
		t = 1
	end

	-- calculate the nearest point on the segment
	local nearestX = x1 + t * dx
	local nearestY = y1 + t * dy

	-- return the nearest point and its distance from the given point
	return nearestX, nearestY, distance(px, py, nearestX, nearestY)
end

Nearest point on the polyline

A polyline is a broken line made up of a series of connected line segments.

function findNearestPointOnPolyline(polyline, point)
	-- polyline is array of pairs: {x1, y1, x2, y2, ...}
	local minDistance = math.huge
	local nearestX, nearestY = nil, nil

	for i = 1, #polyline - 2, 2 do
		-- get segment
		local segment = {polyline[i], polyline[i + 1], polyline[i + 2], polyline[i + 3]}
		-- find the nearest point on the current segment
-- function findNearestPointOnSegment(segment, point) is above
		local px, py, dist = nearestPointOnSegment(segment, point)

		-- update the minimum distance and nearest point
		if dist < minDistance then
			minDistance = dist
			nearestX, nearestY = px, py
		end
	end

	return nearestX, nearestY, minDistance
end

Nearest point on the circle

function nearestPointOnCircle(px, py, cx, cy, r)
	-- calculate the angle between the point and the center
	local theta = math.atan2(py - cy, px - cx)

	-- calculate the nearest point on the circle using the angle
	local nx = cx + r * math.cos(theta)
	local ny = cy + r * math.sin(theta)

	return nx, ny
end