So I need to find te distance from a touch to a line segment.
function Dist(x1, y1, x2, y2)
m = CurrentTouch.x
n = CurrentTouch.y
A = -1*(y2 - y1)
B = x2-x1
m = (-1*A)/B
C = -1*(y1-(m*x1))
d = math.abs(A*m + B*n + C)/math.sqrt(A^2 + B^2)
return d
end
@Ignatz WHAT! I have been staring at this for an hour! Well, after I fixed the code, the results were better, but still off. I used this code to test it
-- Intersect test
-- Use this function to perform your initial setup
function setup()
parameter.integer("x1", 0, WIDTH, 400)
parameter.integer("y1", 0, HEIGHT, 100)
parameter.integer("x2", 0, WIDTH, 400)
parameter.integer("y2", 0, HEIGHT, 200)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
line(x1, y1, x2, y2)
-- Do your drawing here
text(tostring(Dist(x1, y1, x2, y2)), 100, 100)
end
function Dist(x1, y1, x2, y2)
m = CurrentTouch.x
n = CurrentTouch.y
A = -1*(y2 - y1)
B = x2-x1
slope = (-1*A)/B
C = -1*(y1-(slope*x1))
d = math.abs(A*m + B*n + C)/math.sqrt(A^2 + B^2)
return d
end
@CNCode Try this. Tap the screen for a point from the line.
function setup()
x1=100
y1=100
x2=500
y2=500
M=0
n=0
end
function draw()
background(0)
fill(255)
stroke(255)
strokeWidth(2)
line(x1,y1,x2,y2)
ellipse(M,n,5)
if M>0 and n>0 then
text(Dist(x1,y1,x2,y2),WIDTH/2,HEIGHT-100)
end
end
function Dist(x1, y1, x2, y2)
M = CurrentTouch.x
n = CurrentTouch.y
A = y2-y1
B = x2-x1
m = A/B
C=(y1*-1)-(m*x1*-1)
d = math.abs(-m*M+n+C)/math.sqrt(m*m+1)
return(d)
end
function touched(t)
if t.state==BEGAN then
M=t.x
n=t.y
end
end
The original post says “line segment” but the formula posted, ugly as it is, is for the distance from a point to an infinite line. These are different things. Which do you want?
@CNCode Just in case you can’t make up your mind, this one does both. Drag the white ball around the screen. The colored distance matches the colored line.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
x1=400
y1=200
x2=800
y2=400
M=200
n=300
end
function draw()
background(0)
noStroke()
fill(255)
text("Drag the white circle around the screen",WIDTH/2,HEIGHT-25)
ellipse(M,n,20)
strokeWidth(2)
stroke(255,0,0)
line(x1,y1,x2,y2)
distXX(x1,y1,x2,y2,M,n)
if a<=0 or a>=1 then
fill(0,0,255)
text(d1,WIDTH/2,HEIGHT-75)
end
fill(0,255,0)
text(d2,WIDTH/2,HEIGHT-125)
stroke(0,0,255)
line(M,n,x6,y6)
stroke(0,255,0)
line(M,n,x7,y7)
end
function distXX(x1,y1, x2,y2, x3,y3)
dx=x2-x1
dy=y2-y1
temp=dx*dx+dy*dy
a=((x3-x1)*dx+(y3-y1)*dy)/temp
b=a
bdx=dx
bdy=dy
if a>1 then
a=1
elseif a<0 then
a=0
end
x6=x1+a*dx
y6=y1+a*dy
dx=M-x6
dy=n-y6
d1=math.sqrt(dx*dx+dy*dy)
x7=x1+b*bdx
y7=y1+b*bdy
dx=M-x7
dy=n-y7
d2=math.sqrt(dx*dx+dy*dy)
end
function touched(t)
if t.state==BEGAN or t.state==MOVING then
M=t.x
n=t.y
end
end
-- Returns the distance from the point p to the line segment from a to b
-- p,a,b are all vec2s
function lineDist(p,a,b)
-- Vector along the direction of the line from a to b
local v = b - a
-- Project p onto the vector v and compare with the projections of a and b
if v:dot(p) < v:dot(a) then
-- The projection of p is lower than a, so return the distance from p to a
return p:dist(a)
elseif v:dot(p) > v:dot(b) then
-- The projection of p is beyond b, so return the distance from p to b
return p:dist(b)
end
-- The projection of p is between a and b, so we need to take the dot product with the orthogonal vector to v, so we rotate v and normalise it.
v = v:rotate90():normalize()
-- This is the distance from v to the line segment.
return math.abs(v:dot(p)-v:dot(a))
end
@loopSpace Thanks! Do you know if there is any way to put this in a mathematical formula? (I needed this for something else, but the question came up in class. A formula will also help for translating in to other languages). Do you think this is possible? I did test this code out, and it definitely works.
@dave1707 As to the v:rotate90():normalize() in my code, that’s because if u and v are vectors in the place which are unit vectors and are at 90 degrees to each other, then for any vector p we have:
p = (p.u) u + (p.v) v
Moreover, (p.v) v is the orthogonal projection of p onto the line in the direction v so is the closest point of p to that line. Thus the distance from p to that line is the length of the vector p - (p.v) v. From the above, this is the length of the vector (p.u) u and, as u is of unit length, this is just the absolute value of p.u.
In our case, v points along the line so we need a unit vector at 90 degrees to the line. This is what v:rotate90():normalize() returns.
@CNCode I changed my code above to show just the distance to a line segment. If you want a formula, then use the code in the function distToLineSeg where x1,y1 and x2,y2 are the end points of the line segment and px,py is the values of the point. d1 is the distance from the point to the line segment at tx,ty.
displayMode(FULLSCREEN)
function setup()
x1=300 -- first x,y point of line segment
y1=200
x2=600 -- second x,y point of line segment
y2=500
px=300 -- x,y values of a point
py=300
end
function draw()
background(0)
noStroke()
fill(255)
text("Drag the white circle around the screen",WIDTH/2,HEIGHT-25)
ellipse(px,py,20)
strokeWidth(2)
stroke(255,0,0)
line(x1,y1,x2,y2)
distToLineSeg(x1,y1,x2,y2,px,py)
fill(0,255,0)
text(d1,WIDTH/2,HEIGHT-125) -- display distance from point to line segment
stroke(0,0,255)
line(px,py,tx,ty) -- draw line from point to line segment
end
-- calculate closest point and distance to a line segment
function distToLineSeg(x1,y1,x2,y2,px,py)
local dx=x2-x1
local dy=y2-y1
local temp=dx*dx+dy*dy
local a=((px-x1)*dx+(py-y1)*dy)/temp
if a>1 then
a=1
elseif a<0 then
a=0
end
tx=x1+a*dx -- x value on line segment
ty=y1+a*dy -- y value on line segment
dx=px-tx
dy=py-ty
d1=math.sqrt(dx*dx+dy*dy) -- distance of point to line segment
end
-- get x,y values of new point
function touched(t)
if t.state==BEGAN or t.state==MOVING then
px=t.x
py=t.y
end
end
@piinthesky Since this is just an example, and it’s used in one spot, it probably doesn’t matter that much. If this was in a larger program and called from a lot of different places, then returning the values would probably be better. I haven’t tried comparing the values, I figured they were correct since it’s not a very complicated routine.
@piinthesky I added @LoopSpace routine in my code and the distance values were exact if the point was beyond either end of the line, but the value from his code was way off when the point was between the end points. I was getting values of 0 when the point was still 70 pixels from the line.
@LoopSpace@dave1707 if u could make a app for studying high school math and college math?add formula and theorem demos?its best to solve math problems automatically?like Codea makes games?it will be nice