# 2d 'linepick' intersects 2d outline example

ðŸ‘‰ BlitzCoder will be building a new platform and other plans to preserve and continue the Blitz legacy.

To be able to achieve this goal, we need your support by becoming a Patreon Paid Member ðŸ‘ˆ

Tweet 2d blitzbasic code-archives algorithms maths

edit 20221130 : here is a better bcode with a 2d 'linepick' more similar to the 3d linepick (of blitz3d), and with the possibility to move (position) the shapes everywhere easily and have their outlines automatically recalculated...

``````;2d 'linepick' intersects 2d outline example (arbitrary shape) by RemiD (20221130)
;also calculates the intersection 2d point and the outline 2d normals
;sometimes a 2d 'linepick' can go through a 2d outline because it goes between the extremities of 2 lines of the outline,
;a simple fix would be to cast several 2d 'linepick' with a slight offset to be sure to hit the outline...

Global gwidth% = 640 : Global gheight% = 480
Graphics(gwidth,gheight,32,2)

SeedRnd(MilliSecs())

;assume that we have made a 2d shape in a drawing app

;since we have made the 2d shape, we know the 2d lines of the 2d outline
Global ShapesCount%
Dim Shape_CX%(16) : Dim Shape_CY%(16) ; center of shape
Dim Shape_LinesCount%(16)
Dim Shape_Line_Sx#(16,10) : Dim Shape_Line_Sy#(16,10) : Dim Shape_Line_Ex#(16,10) : Dim Shape_Line_Ey#(16,10) ;start point end point of each line
Dim Shape_R%(16) : Dim Shape_G%(16)  : Dim Shape_B%(16) ;color of outline
For n% = 1 To 16 Step +1
ShapesCount = ShapesCount + 1 : SI% = ShapesCount
Shape_CX(SI) = Rand(0+50, 640-1-50) : Shape_CY(SI) = Rand(0+50, 480-1-50)
Shape_LinesCount%(SI) = 10
LI% = 1 : Shape_Line_Sx(SI,LI) = 50-50 : Shape_Line_Sy(SI,LI) = 12-50 : Shape_Line_Ex(SI,LI) = 61-50 : Shape_Line_Ey(SI,LI) = 36-50
LI% = 2 : Shape_Line_Sx(SI,LI) = 62-50 : Shape_Line_Sy(SI,LI) = 36-50 : Shape_Line_Ex(SI,LI) = 87-50 : Shape_Line_Ey(SI,LI) = 26-50
LI% = 3 : Shape_Line_Sx(SI,LI) = 87-50 : Shape_Line_Sy(SI,LI) = 27-50 : Shape_Line_Ex(SI,LI) = 72-50 : Shape_Line_Ey(SI,LI) = 55-50
LI% = 4 : Shape_Line_Sx(SI,LI) = 72-50 : Shape_Line_Sy(SI,LI) = 56-50 : Shape_Line_Ex(SI,LI) = 83-50 : Shape_Line_Ey(SI,LI) = 82-50
LI% = 5 : Shape_Line_Sx(SI,LI) = 82-50 : Shape_Line_Sy(SI,LI) = 82-50 : Shape_Line_Ex(SI,LI) = 58-50 : Shape_Line_Ey(SI,LI) = 67-50
LI% = 6 : Shape_Line_Sx(SI,LI) = 57-50 : Shape_Line_Sy(SI,LI) = 67-50 : Shape_Line_Ex(SI,LI) = 29-50 : Shape_Line_Ey(SI,LI) = 87-50
LI% = 7 : Shape_Line_Sx(SI,LI) = 28-50 : Shape_Line_Sy(SI,LI) = 87-50 : Shape_Line_Ex(SI,LI) = 36-50 : Shape_Line_Ey(SI,LI) = 61-50
LI% = 8 : Shape_Line_Sx(SI,LI) = 36-50 : Shape_Line_Sy(SI,LI) = 60-50 : Shape_Line_Ex(SI,LI) = 11-50 : Shape_Line_Ey(SI,LI) = 36-50
LI% = 9 : Shape_Line_Sx(SI,LI) = 11-50 : Shape_Line_Sy(SI,LI) = 35-50 : Shape_Line_Ex(SI,LI) = 36-50 : Shape_Line_Ey(SI,LI) = 39-50
LI% = 10 : Shape_Line_Sx(SI,LI) = 37-50 : Shape_Line_Sy(SI,LI) = 38-50 : Shape_Line_Ex(SI,LI) = 49-50 : Shape_Line_Ey(SI,LI) = 12-50
Shape_R(SI) = Rand(025,250) : Shape_G(SI) = Rand(025,250) : Shape_B(SI) = Rand(025,250)
Next

;2d line (of a turning moving entity)
Global Sx# : Global Sy# : Global Ex# : Global Ey#
Global Nx# : Global Ny#

;intersection 2d point ( for function LineIntersectsLine() )
Global Intersectx# : Global Intersecty#

;2d normals ( for function LineNormals() )
Global Normal1x# : Global Normal1y#
Global Normal2x# : Global Normal2y#

Global TempsCount%
Dim Temp_Sx#(100) : Dim Temp_Sy#(100) : Dim Temp_Ex#(100) : Dim Temp_Ey#(100)
Dim Temp_Ix#(100) : Dim Temp_Iy#(100)
Dim Temp_Dist#(100)
Dim Temp_N1x#(100) : Dim Temp_N1y#(100)
Dim Temp_N2x#(100) : Dim Temp_N2y#(100)

Global TI%
Global WhichNormal%

Goto ChooseLineProperties

Repeat

If( KeyHit(56)=1 )
;define others positions for shapes
For SI% = 1 To ShapesCount
Shape_CX(SI) = Rand(0+50, 640-1-50) : Shape_CY(SI) = Rand(0+50, 480-1-50)
Next
EndIf

If( MouseHit(1)=1 Or KeyHit(57)=1 )

.ChooseLineProperties
;define another 2d line (of a turning moving entity)
Sx = MouseX() :  Sy = MouseY()
Vx# = Rnd(-1,+1) : Vy# = Rnd(-1,+1)
VLength# =  Sqr( ( Vx * Vx ) + ( Vy * Vy ) )
Nx = Vx / VLength : Ny = Vy / VLength
Ex = Sx+Nx*100 : Ey = Sy+Ny*100

TempsCount = 0
For SI% = 1 To ShapesCount
;color shape in grey (for debug)
Shape_R(SI) = 125 : Shape_G(SI) = 125 : Shape_B(SI) = 125
;check distance between start of 2d linepick and center of shape
D# = Distance2D( Sx, Sy, Shape_Cx(SI), Shape_Cy(SI) )
;if shape near enough start of linepick
If( D < 50+100 )
;color shape in white (for debug)
Shape_R(SI) = 250 : Shape_G(SI) = 250 : Shape_B(SI) = 250

;check If the 2d linepick intersects with some lines of the 2d outline of the shape
For LI% = 1 To Shape_LinesCount(SI) Step +1
R% = LineIntersectsLine( Sx, Sy, Ex, Ey, Shape_CX(SI)+Shape_Line_SX(SI,LI), Shape_CY(SI)+Shape_Line_SY(SI,LI), Shape_CX(SI)+Shape_Line_EX(SI,LI), Shape_CY(SI)+Shape_Line_EY(SI,LI) )
If( R = True )
TempsCount = TempsCount  + 1 : TI% = TempsCount
Temp_Sx(TI) =  Shape_CX(SI)+Shape_Line_SX(SI,LI) : Temp_Sy(TI) = Shape_CY(SI)+Shape_Line_SY(SI,LI) : Temp_Ex(TI) = Shape_CX(SI)+Shape_Line_EX(SI,LI) : Temp_Ey(TI) = Shape_CY(SI)+Shape_Line_EY(SI,LI)
Temp_Ix(TI) = Intersectx : Temp_Iy(TI) = Intersecty
EndIf
Next
;if yes
If (TempsCount > 0 )
;choose the nearest intersection point, and the nearest intersected line
CurrDist# = 100000
STI% = -1
For TI% = 1 To TempsCount Step +1
Temp_Dist(TI) = Distance2D( Sx, Sy, Temp_Ix(TI), Temp_Iy(TI) )
If( Temp_Dist(TI) < CurrDist )
STI = TI
CurrDist = Temp_Dist(TI)
EndIf
Next
TI% = STI
;calculate the 2 2d normals of the nearest intersected line
LineNormals( Temp_Sx(TI), Temp_Sy(TI), Temp_Ex(TI), Temp_Ey(TI) )
Temp_N1x(TI) = Normal1x : Temp_N1y(TI) = Normal1y
Temp_N2x(TI) = Normal2x : Temp_N2y(TI) = Normal2y
;choose the 2d normal pointing outwards (project a point along the normal and choose the nearest point / normal from the start point)
D1# = Distance2D( Sx, Sy, Temp_Ix(TI)+Temp_N1x(TI)*10, Temp_Iy(TI)+Temp_N1y(TI)*10 )
D2# = Distance2D( Sx, Sy, Temp_Ix(TI)+Temp_N2x(TI)*10, Temp_Iy(TI)+Temp_N2y(TI)*10 )
If( D1 < D2 )
;choose normal1
WhichNormal = 1
Else If( D2 < D1 )
;choose normal2
WhichNormal = 2
EndIf
EndIf
EndIf
Next

EndIf

SetBuffer(BackBuffer())
ClsColor(000,000,000) : Cls()

;draw the 2d lines of the 2d outline
For SI% = 1 To ShapesCount Step +1
Color( Shape_R(SI), Shape_G(SI), Shape_B(SI) )
For LI% = 1 To Shape_LinesCount(SI) Step +1
Line( Shape_CX(SI)+Shape_Line_SX(SI,LI), Shape_CY(SI)+Shape_Line_SY(SI,LI), Shape_CX(SI)+Shape_Line_EX(SI,LI), Shape_CY(SI)+Shape_Line_EY(SI,LI) )
Next
Next

;draw the 2d line (of a turning moving entity)
Color(125,125,250) : Line( Sx, Sy, Ex, Ey )

;draw the start point of the 2d line (of a turning moving entity)
Color(125,125,250) : Rect( Sx-2, Sy-2, 4, 4, True )

;if the line intersect
If( TempsCount > 0 )
;draw the intersection 2d point
Color(250,000,250) : Rect( Temp_Ix(TI)-2, Temp_Iy(TI)-2, 4, 4, True )
;draw the 2d normal of the nearest intersected line
If( WhichNormal = 1 )
Color(250,000,250) : Line( Temp_Ix(TI), Temp_Iy(TI), Temp_Ix(TI)+Temp_N1x(TI)*10, Temp_Iy(TI)+Temp_N1y(TI)*10 )
Else If( WhichNormal =  2 )
Color(250,000,250) : Line( Temp_Ix(TI), Temp_Iy(TI), Temp_Ix(TI)+Temp_N2x(TI)*10, Temp_Iy(TI)+Temp_N2y(TI)*10 )
EndIf
EndIf

Flip()

Until( KeyHit(1)=1 )

End()

Function Distance2D#(AX#,AZ#,BX#,BZ#)

Distance2D# = Sqr( ( ( BX - AX ) * ( BX - AX ) ) + ( ( BZ - AZ ) * ( BZ - AZ ) ) )
Return Distance2D

End Function

;2d line intersects 2d line math formula by NoseKills (20141023)
Function LineIntersectsLine( p0_x#, p0_y#, p1_x#, p1_y#, p2_x#, p2_y#, p3_x#, p3_y# )

s1_x# = p1_x - p0_x
s1_y# = p1_y - p0_y
s2_x# = p3_x - p2_x
s2_y# = p3_y - p2_y

s# = ( -s1_y * ( p0_x - p2_x ) + s1_x * ( p0_y - p2_y ) ) / ( -s2_x * s1_y + s1_x * s2_y )
t# = ( s2_x * ( p0_y - p2_y ) - s2_y * ( p0_x - p2_x ) ) / ( -s2_x * s1_y + s1_x * s2_y )

If( s >= 0 And s <= 1 And t >= 0 And t <= 1 )
;intersection detected
intersectx = p0_x + (  t * s1_x ) : intersecty = p0_y + ( t * s1_y )
Return True
Else
;no intersection
intersectx = 0 : intersecty = 0
Return False
EndIf

End Function

;2d normals of a 2d line math formula by Stevie G (20221127)
Function LineNormals( pA_x#, pA_y#, pB_x#, pB_y# )

;vectorAB
vAB_x# = pB_x - pA_x : vAB_y# = pB_y - pA_y
;normalizedvectorAB
vAB_length# = Sqr( ( vAB_x * vAB_x ) + ( vAB_y * vAB_y ) )
nAB_x# = vAB_x / vAB_length : nAB_y# = vAB_y / vAB_length

;one side perpendiculat normalized  vector
Normal1x# = -nAB_y : Normal1y# = +nAB_x
;other side perpendicular normalized  vector
Normal2x# = +nAB_y : Normal2y# = -nAB_x

End Function``````