I've been a fan of Froggerprogger's 3d Vector Procedures for quite some time now. In some point I needed also plain 2d lines and so here is my implementation.
One could easily create Turtle-style graphics with these.
This 2d line "class" includes also an example is for testing whether a mouse pointer is inside the quadrangle area or not. It has worked well so far, but I'm more concerned about the speed.
Code: Select all
EnableExplicit
; Tiny 2d Line "class" for PureBasic users (25.11.2010)
;
; And a mousepick - example
;
; by Kapslok
#Deg2Rad = 0.01745329
#Rad2Deg = 57.2957795
Structure Line2D
x.f
y.f
x2.f
y2.f
EndStructure
Procedure.l DefineLine(*line.Line2D, x.f, y.f, x2.f, y2.f)
*line\x = x
*line\y = y
*line\x2 = x2
*line\y2 = y2
ProcedureReturn *line
EndProcedure
Procedure.f GetLineLength(*line.Line2D)
ProcedureReturn Sqr(Pow(*line\x-*line\x2,2)+Pow(*line\y-*line\y2,2))
EndProcedure
Procedure.f GetLineAngle(*line.Line2D)
Static x1.f, y1.f, temp.f
x1 = *line\x2 - *line\x
y1 = *line\y2 - *line\y
If y1=0
If x1<0 : ProcedureReturn 180 : Else : ProcedureReturn 0 : EndIf
EndIf
If x1=0
If y1<0 : ProcedureReturn 90 : Else : ProcedureReturn 270 : EndIf
EndIf
temp = ATan(y1 / x1) * #Rad2Deg
If y1 <= 0
If temp <= 0
temp * -1
Else
temp = 180 - temp
EndIf
Else
If temp < 0
temp = 180 - temp
Else
temp = 360 - temp
EndIf
EndIf
ProcedureReturn temp
EndProcedure
Procedure.l RotateLine(*line.Line2D,angle.f)
Static dx.f,dy.f
dx.f=*line\x2 - *line\x
dy.f=*line\y2 - *line\y
angle * #Deg2Rad
*line\x2 = Cos(angle) * dx - Sin(angle)*dy + *line\x
*line\y2 = Sin(angle) * dx + Cos(angle)*dy + *line\y
ProcedureReturn *line
EndProcedure
;
; Here is the actual code, which utilizes the previous
; "class"
Procedure TestMousePick(Xmouse,Ymouse,x1,y1,x2,y2,x3,y3,x4,y4)
Static rot.f, llen.f
Static MyLin.Line2D
Static PickLin.Line2D
; Is the pointer on the window?
If Xmouse<0 : ProcedureReturn 0 : EndIf
; Another quick way out?
If Xmouse<x1 And Xmouse<x2 And Xmouse<x3 And Xmouse<x4
ProcedureReturn 0
EndIf
If Xmouse>x1 And Xmouse>x2 And Xmouse>x3 And Xmouse>x4
ProcedureReturn 0
EndIf
If Ymouse>y1 And Ymouse>y2 And Ymouse>y3 And Ymouse>y4
ProcedureReturn 0
EndIf
If Ymouse<y1 And Ymouse<y2 And Ymouse<y3 And Ymouse<y4
ProcedureReturn 0
EndIf
; Some coordinates match... let's do more exact inspection
; One rotation for each side of the quadrangle
DefineLine(@MyLin,x1,y1,x2,y2)
DefineLine(@PickLin,x1,y1,Xmouse,Ymouse)
rot=GetLineAngle(@MyLin)
RotateLine(@PickLin,rot)
llen=GetLineLength(@MyLin)
If PickLin\y2<y1
ProcedureReturn 0
EndIf
DefineLine(@MyLin,x2,y2,x3,y3)
DefineLine(@PickLin,x2,y2,Xmouse,Ymouse)
rot=GetLineAngle(@MyLin)
RotateLine(@PickLin,rot)
llen=GetLineLength(@MyLin)
If PickLin\y2<y2
ProcedureReturn 0
EndIf
DefineLine(@MyLin,x3,y3,x4,y4)
DefineLine(@PickLin,x3,y3,Xmouse,Ymouse)
rot=GetLineAngle(@MyLin)
RotateLine(@PickLin,rot)
llen=GetLineLength(@MyLin)
If PickLin\y2<y3
ProcedureReturn 0
EndIf
DefineLine(@MyLin,x4,y4,x1,y1)
DefineLine(@PickLin,x4,y4,Xmouse,Ymouse)
rot=GetLineAngle(@MyLin)
RotateLine(@PickLin,rot)
llen=GetLineLength(@MyLin)
If PickLin\y2<y4
ProcedureReturn 0
EndIf
ProcedureReturn 1
EndProcedure
OpenWindow(0,0,0,800,600,"Point Inside Quadrangle",#PB_Window_ScreenCentered | #PB_Window_SystemMenu )
Define x1=550,y1=130,x2=700,y2=400,x3=220,y3=300,x4=250,y4=250
Define ev
Repeat
ev = WindowEvent()
Delay(20)
If StartDrawing(WindowOutput(0))
If TestMousePick(WindowMouseX(0),WindowMouseY(0),x1,y1,x2,y2,x3,y3,x4,y4)
FrontColor(RGB(200,20,20))
Else
FrontColor(RGB(20,200,20))
EndIf
LineXY(x1,y1,x2,y2)
LineXY(x3,y3,x2,y2)
LineXY(x3,y3,x4,y4)
LineXY(x1,y1,x4,y4)
StopDrawing()
EndIf
Until ev = #PB_Event_CloseWindow
One morning I started wondering whether there is any faster solution for this?
Greetings for all,
Kapslok

