Page 2 of 2

Re: [Help] Math: Shortest distance from point to line (EDITE

Posted: Fri Jul 12, 2013 5:29 pm
by micha
Ref wrote:Saw the typo and after correction seems to work for me.
Question:
Easy to find closest-point-on-line but pretty mess to get closest-point-on-line-segment.
Do you have a 'neat' way of doing this?
This is the 'neatest' I can come up with:

Code: Select all

function ClosestPointOnLineSegment(px,py,x1,y1,x2,y2)
  local dx,dy = x2-x1,y2-y1
  local length = math.sqrt(dx*dx+dy*dy)
  dx,dy = dx/length,dy/length
  local posOnLine = math.min(length, math.max(0,dx*(px-x1) + dy*(py-y1)))
  return x1+posOnLine*dx,x2+posOnLine*dy
end
The only difference to a closest-point-on-line-calculation is the clamping of the posOnLine. This is a coordinate along the line segment. If the point has to be on the line segment, then this coordinates has to be between zero and length.

Re: [Help] Math: Shortest distance from point to line (EDITE

Posted: Fri Jul 12, 2013 5:48 pm
by XHH
Sorry that didn't work. But I did figure out how to do it! Should I post the solution?

Re: [Help] Math: Shortest distance from point to line (EDITE

Posted: Fri Jul 12, 2013 5:53 pm
by davisdude
If you want to. The whole point of the forums is to help people out. It would help somebody with the same problem as you.

Re: [Help] Math: Shortest distance from point to line (EDITE

Posted: Fri Jul 12, 2013 6:19 pm
by Ref
Mr. Typo again! :)
try changing:

Code: Select all

return x1+posOnLine*dx,x2+posOnLine*dy
to

Code: Select all

return x1+posOnLine*dx,y1+posOnLine*dy
Haven't tried to test it too much yet.

Re: [Help] Math: Shortest distance from point to line (EDITE

Posted: Mon Jul 15, 2013 12:35 am
by XHH
Here's my code. You just need to use distLine(LINE,POINT). I was hesitant to post this because I used it in Python. It can be easily changed back to Lua using keywords like function and local.

Code: Select all

#Compute the distance from LINE(x1,y1,x2,y2) to POINT(x,y)

def distLine(line,point):
        A,B = [line[0],line[1]],[line[2],line[3]]
        C = point
        if self.distance(A,B) != 0:
            dist = cross(A,B,C)/self.distance(A,B)
        else:
            dist = self.cross(A,B,C/1)
        dot1 = dot(A,B,C)
        if dot1 > 0:return distance(B,C)
        dot2 = dot(B,A,C)
        if dot2 > 0:return distance(A,C)
        return abs(dist)

def dot(A,B,C):
        AB,BC=[0,0],[0,0]

        AB[0] = B[0]-A[0]
        AB[1] = B[1]-A[1]
        BC[0] = C[0]-B[0]
        BC[1] = C[1]-B[1]
        dot = AB[0] * BC[0] + AB[1] * BC[1]
        return dot

    #Compute the cross product AB x AC
def cross(A,B,C):
        AB,AC = [0,0],[0,0]

        AB[0] = B[0]-A[0]
        AB[1] = B[1]-A[1]
        AC[0] = C[0]-A[0]
        AC[1] = C[1]-A[1]
        cross = AB[0] * AC[1] - AB[1] * AC[0]
        return cross

    #Compute the distance from A to B
def distance(A,B):
        d1 = A[0] - B[0]
        d2 = A[1] - B[1]
        return math.sqrt(d1*d1+d2*d2)

Re: [SOLVED] Math: Shortest distance from point to line (EDI

Posted: Mon Jul 15, 2013 2:28 am
by Ref
I think Micha's code is pretty neat.

Re: [SOLVED] Math: Shortest distance from point to line (EDI

Posted: Mon Jul 15, 2013 5:58 am
by micha
Thanks Ref. I definitely go for neatness, whenever possible :)

Re: [SOLVED] Math: Shortest distance from point to line (EDITED)

Posted: Fri Sep 17, 2021 11:16 pm
by darkfrei
I've googled it a lot of times, my solution:

Code: Select all

local function distPointToLine(px,py,x1,y1,x2,y2) -- point, start and end of the segment
	local dx,dy = x2-x1,y2-y1
	local length = math.sqrt(dx*dx+dy*dy)
	dx,dy = dx/length,dy/length
	local p = dx*(px-x1)+dy*(py-y1)
	if p < 0 then
		dx,dy = px-x1,py-y1
		return math.sqrt(dx*dx+dy*dy), x1, y1 -- distance, nearest point
	elseif p > length then
		dx,dy = px-x2,py-y2
		return math.sqrt(dx*dx+dy*dy), x2, y2 -- distance, nearest point
	end
	return math.abs(dy*(px-x1)-dx*(py-y1)), x1+dx*p, y1+dy*p -- distance, nearest point
end
So you can get (and highlight) the nearest segment of a polyline:

Code: Select all

function nearestSegmentInLine (x, y, line)
	local x1, y1, x2, y2, min_dist
	local nx, ny, px, py
	local ax,ay = line[1], line[2]
	for j = 3, #line-1, 2 do
		local bx,by = line[j], line[j+1]
		local dist, px,py = distPointToLine(x,y,ax,ay,bx,by)
		if not min_dist or dist < min_dist then
			min_dist = dist
			x1, y1, x2, y2 = ax,ay,bx,by
			nx,ny = px,py
		end
		ax, ay = bx, by
	end
	return x1, y1, x2, y2, nx, ny -- segment, nearest point
end

Re: [SOLVED] Math: Shortest distance from point to line (EDITED)

Posted: Sat Sep 18, 2021 11:25 am
by darkfrei
So, if the drawn line has different colors along the it's length, we can set to every point in window the color of the nearest sector of this line:

The gradient function:

Code: Select all

function get_red_blue_gradient_color (t) -- t is between 0 as red to 1 as blue
	local r = 2-4*t
	local g = t < 1/2 and 4*t or 4-4*t
	local b = -2 + 4*t
	r = math.min(math.max(0, r), 1)
	g = math.min(math.max(0, g), 1)
	b = math.min(math.max(0, b), 1)
	return {r^0.5,g^0.5,b^0.5,1}
end