Posted: Sat Jun 14, 2008 8:05 pm
If you say so.veganisafreak wrote:LOL, "nice math", that's a new concept to me... you must be a geek!srod wrote:Yes some nice math there and some familiar old formulas.
http://www.purebasic.com
https://www.purebasic.fr/english/
If you say so.veganisafreak wrote:LOL, "nice math", that's a new concept to me... you must be a geek!srod wrote:Yes some nice math there and some familiar old formulas.
A 2D point p(p1,p2) is contained in a 2D line defined by segment a(a1,a2)-b(b1,b2) if:zxtunes.com wrote:No more ideas?![]()
I cannot finish game without it.
Code: Select all
(p1-a1)*(b1-a1)+(p2-a2)*(b2-a2)=Sqr(((p1-a1)^2+(p2-a2)^2)*((b1-a1)^2+(b2-a2)^2))Code: Select all
(p1-a1)*(b1-a1)+(p2-a2)*(b2-a2)+ ... +(pn-an)*(bn-an)=Sqr(((p1-a1)^2+(p2-a2)^2+ ... +(pn-an)^2)*((b1-a1)^2+(b2-a2)^2+ ... +(bn-an)^2))And this not work too.Psychophanta wrote:A 2D point p(p1,p2) is contained in a 2D line defined by segment a(a1,a2)-b(b1,b2) if:zxtunes.com wrote:No more ideas?![]()
I cannot finish game without it.Code: Select all
(p1-a1)*(b1-a1)+(p2-a2)*(b2-a2)=Sqr(((p1-a1)^2+(p2-a2)^2)*((b1-a1)^2+(b2-a2)^2))
Code: Select all
InitSprite():InitKeyboard():InitMouse()
Procedure LineIntersection(p1,p2,a1,b1,a2,b2)
a.f = (p1 - a1) * (b1 - a1) + (p2 - a2) * (b2 - a2)
b.f = Sqr( (Pow((p1 - a1),2) + Pow((p2 - a2),2)) * (Pow((b1 - a1),2) + Pow((b2 - a2),2)) )
If a = b: ProcedureReturn 1: EndIf
EndProcedure
OpenWindow(0, 0, 0, 300, 300, "Line to point collison", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 300, 300, 0, 0, 0)
Gosub random_line
Repeat
FlipBuffers()
ExamineKeyboard()
ExamineMouse()
event = WindowEvent()
px=MouseX()
py=MouseY()
If MouseButton(#PB_MouseButton_Left): Gosub random_line: EndIf
c = LineIntersection(px, py, x1, y1, x2, y2)
ClearScreen(c*255)
StartDrawing(ScreenOutput())
DrawText(0,0, Str(px)+","+Str(py))
LineXY(x1, y1, x2, y2, RGB(0, 255, 0))
Plot(px,py,RGB(255,255,255))
StopDrawing()
Until KeyboardPushed(#PB_Key_Escape)
random_line:
x1 = Random(300)
y1 = Random(300)
x2 = Random(300)
y2 = Random(300)
ReturnCode: Select all
;http://www.swissdelphicenter.ch/torry/printcode.php?id=2080
;If you need to deal with speed
;http://texel3d.free.fr/opengl/collisions.htm
#Epsilon = 0.5
InitSprite():InitKeyboard()
Procedure.f Distance(x1, y1, x2, y2)
ProcedureReturn Sqr((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
EndProcedure
Procedure.f PntToSegmentDistance(Px, Py, x1, y1, x2, y2)
Define.f Ratio, Dx, Dy, Result
If x1 = x2 And y1 = y2
Result = Distance(Px, Py, x1, y1)
Else
Dx = x2 - x1
Dy = y2 - y1
Ratio = ((Px - x1) * Dx + (Py - y1) * Dy) / (Dx * Dx + Dy * Dy)
If Ratio < 0
Result = Distance(Px, Py, x1, y1)
ElseIf Ratio > 1
Result = Distance(Px, Py, x2, y2)
Else
Result = Distance(Px, Py, (1 - Ratio) * x1 + Ratio * x2, (1 - Ratio) * y1 + Ratio * y2)
EndIf
EndIf
ProcedureReturn Result
; If Result > -#Epsilon And Result < #Epsilon
; ProcedureReturn 1
; Else
; ProcedureReturn 0
; EndIf
EndProcedure
OpenWindow(0, 0, 0, 300, 300, "Line to point collison", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 300, 300, 0, 0, 0)
Gosub random_line
Repeat
FlipBuffers()
ExamineKeyboard()
event = WindowEvent()
px=WindowMouseX(0)
py=WindowMouseY(0)
If event = #WM_LBUTTONDOWN : Gosub random_line: EndIf
c.f = PntToSegmentDistance(px, py, x1, y1, x2, y2)
If c > -#Epsilon And c < #Epsilon
ClearScreen($0000FF)
Else
ClearScreen($00FF00)
EndIf
StartDrawing(ScreenOutput())
DrawText(0,0, StrF(c,2))
LineXY(x1, y1, x2, y2, RGB(0, 0, 255))
;Plot(px,py,RGB(255,255,255))
StopDrawing()
Until KeyboardPushed(#PB_Key_Escape)
random_line:
x1 = Random(300)
y1 = Random(300)
x2 = Random(300)
y2 = Random(300)
ReturnCode: Select all
lNumberOfLoops.l = 1000000
RandomSeed(33333)
Timer1 = GetTickCount_()
For i = 0 To lNumberOfLoops
PntToSegmentDistance(Random(5000),Random(5000),Random(5000),Random(5000),Random(5000),Random(5000))
;procedure call repeated 10 times inside the loop to demonstrate the procedure's speed and not the loop's speed
Next
Timer1 = GetTickCount_() - Timer1Code: Select all
;Author: Demivec (Jared) 6/19/2008
;PureBasic v4.20
;Description: check if a point is on a rasterized line segment. The point's coordiates are determined
;to be on the line segment if it's coordinates coincide with a point that would be used to draw the line segment
;using Bresenham's line algorithm.
;
Procedure.l isPointOnSegment(Px.l, Py.l, x1.l, y1.l, x2.l, y2.l)
Protected dx.l,dy.l,xInc.l,yInc.l
;calculate cordinate delta's for line segment
dx = x2 - x1
If dx < 0
If Px > x1 Or Px < x2 ;check if x coordinante of point is in the span of points that contain line segment
ProcedureReturn #False
EndIf
dx = - dx ;make delta positive (for comparison later)
xInc = -1 ;set the line's slope direction
Else
If Px > x2 Or Px < x1
ProcedureReturn #False
EndIf
xInc = 1
EndIf
dy = y2 - y1
If dy < 0
If Py > y1 Or Py < y2
ProcedureReturn #False
EndIf
dy = - dy
yInc = -1
Else
If Py > y2 Or Py < y1
ProcedureReturn #False
EndIf
yInc = 1
EndIf
;check if remaining coordinate matches the calculated one for the line segment
If (dx > dy)
If Py = y1 + Int(((Px - x1) * dy / dx) + 0.5 * xInc) * xInc * yInc
ProcedureReturn #True
EndIf
Else
If dy > 0
If Px = x1 + Int(((Py - y1) * dx / dy) + 0.5 * yInc) * xInc * yInc
ProcedureReturn #True
EndIf
Else ;special case to avoid division by zero for vertical segments and singular line segments (i.e. points)
If Px = x1
ProcedureReturn #True
EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedureThe first way that I thought of was to look at the distance from the line, unfortunately that ran into a problem (for me) with floating point inaccuracies.zxtunes.com wrote:thanks Demivec!
I am surprised.![]()
In fact the first that has occurred to me it your way, but it has seemed to me stupid, I even did not reflect that it can be faster mathematical method. :roll: