3 method.
Code: Select all
;Comtois 05/02/05
;Détection d'un point dans un triangle
;Update 07/07/07 - PB 4.10
;-Initialisation
Global ScreenHeight.l,ScreenWidth.l
Declare Erreur(Message$)
If ExamineDesktops()
ScreenWidth = DesktopWidth(0)
ScreenHeight = DesktopHeight(0)
Else
Erreur("Euh ?")
EndIf
If InitSprite() = 0 Or InitMouse() = 0 Or InitKeyboard()=0
Erreur("Impossible d'initialiser DirectX 7 Ou plus")
ElseIf OpenWindow(0,0,0,ScreenWidth,ScreenHeight,"Collision", #PB_Window_BorderLess) = 0
Erreur("Impossible de créer la fenêtre")
EndIf
;{/ouvre un écran
If OpenWindowedScreen( WindowID(0), 0, 0, ScreenWidth , ScreenHeight, 0, 0, 0 ) = 0
Erreur("Impossible d'ouvrir l'écran ")
EndIf
Structure Triangle
X1.l
Y1.l
X2.l
Y2.l
X3.l
Y3.l
EndStructure
Structure Pointf
x.f
y.f
EndStructure
Structure FloatLong
StructureUnion
f.f
l.l
EndStructureUnion
EndStructure
Procedure Erreur(Message$)
MessageRequester( "Erreur" , Message$ , 0 )
End
EndProcedure
Procedure Signe(a.l)
If a>0
ProcedureReturn 1
ElseIf a=0
ProcedureReturn 0
Else
ProcedureReturn -1
EndIf
EndProcedure
Macro NORME(V)
(Sqr(V\x * V\x + V\y * V\y))
EndMacro
Macro SOUSTRACTION_VECTEUR(V, V1, V2)
V\x = V1\x - V2\x
V\y = V1\y - V2\y
EndMacro
Macro PRODUIT_SCALAIRE(V1, V2)
(V1\x * V2\x + V1\y * V2\y)
EndMacro
Procedure Normalise(*N.Pointf)
Define.f NormeVecteur
NormeVecteur = NORME(*N)
If NormeVecteur <> 0.0
*N\x / NormeVecteur
*N\y / NormeVecteur
EndIf
EndProcedure
Procedure CollisionTriangle(*T.Triangle,*P.point)
;Test la collision du point avec le triangle
;pour en savoir plus http://tanopah.jo.free.fr/seconde/region.html
;Plan 1
xu1=*T\X2-*T\X1:yu1=*T\Y2-*T\Y1
c1=*T\Y1*xu1-*T\X1*yu1
P1=*T\X3*yu1-*T\Y3*xu1+c1
AX1=*P\x*yu1-*P\y*xu1+c1
If Signe(AX1)<>Signe(P1)
ProcedureReturn #False
EndIf
;Plan 2
xu2=*T\X3-*T\X2:yu2=*T\Y3-*T\Y2
c2=*T\Y2*xu2-*T\X2*yu2
P2=*T\X1*yu2-*T\Y1*xu2+c2
AX2=*P\x*yu2-*P\y*xu2+c2
If Signe(AX2)<>Signe(P2)
ProcedureReturn #False
EndIf
;Plan 3
xu3=*T\X1-*T\X3:yu3=*T\Y1-*T\Y3
c3=*T\Y3*xu3-*T\X3*yu3
P3=*T\X2*yu3-*T\Y2*xu3+c3
AX3=*P\x*yu3-*P\y*xu3+c3
If Signe(AX3)<>Signe(P3)
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure CollisionTriangle1(*T.Triangle,*P.point)
Define.Pointf PA, PB, PC, Somme
PA\x=*T\x1-*P\x
PA\y=*T\y1-*P\y
Normalise(@PA)
PB\x=*T\x2-*P\x
PB\y=*T\y2-*P\y
Normalise(@PB)
PC\x=*T\x3-*P\x
PC\y=*T\y3-*P\y
Normalise(@PC)
Somme\x=PA\x+PB\x+PC\x
Somme\y=PA\y+PB\y+PC\y
;on calcule la taille du vecteur Somme
If NORME(Somme) > 1
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure CollisionTriangle2(*T.Triangle,*P.point)
;Thanks To Keidy from Mr-Gamemaker who posted this particular version
;of the function in a little competition
Define.Pointf e10, e20, vp
Define.f a, b, c, d, e
Define.FloatLong x, y, z
e10\x = *T\x2 -*T\x1
e10\y = *T\y2 -*T\y1
e20\x = *T\x3 -*T\x1
e20\y = *T\y3 -*T\y1
a = PRODUIT_SCALAIRE(e10, e10)
b = PRODUIT_SCALAIRE(e10, e20)
c = PRODUIT_SCALAIRE(e20, e20)
vp\x = *P\x -*T\x1
vp\y = *P\y -*T\y1
d = PRODUIT_SCALAIRE(vp, e10)
e = PRODUIT_SCALAIRE(vp, e20)
x\f = (d * c) - (e * b)
y\f = (e * a) - (d * b)
z\f = x\f + y\f - (a * c) + (b * b)
ProcedureReturn ((z\l & ~(x\l | y\l)) & $80000000)
EndProcedure
Procedure AffPoints(*T.Triangle,*P.point,mem)
StartDrawing(ScreenOutput())
;/Affiche le triangle
Circle(*T\X1,*T\Y1,4, #Red)
Circle(*T\X2,*T\Y2,4, #Red)
Circle(*T\X3,*T\Y3,4, #Red)
LineXY(*T\X1,*T\Y1,*T\X2,*T\Y2, #Red)
LineXY(*T\X2,*T\Y2,*T\X3,*T\Y3, #Red)
LineXY(*T\X1,*T\Y1,*T\X3,*T\Y3, #Red)
If CollisionTriangle(*T,*P) ;<<<<<<<<<<<<<<<<<<<<< CHANGE HERE <<<<<<<<<<<<<<<
FillArea(*P\x,*P\y,#Red,#Blue)
EndIf
;/Affiche une croix pour mieux suivre le déplacement du point
LineXY(*P\x,0,*P\x,ScreenHeight-1,#White)
LineXY(0,*P\y,ScreenWidth-1,*P\y,#White)
;/Affiche le point
If mem
DrawingMode(4)
Circle(*P\x,*P\y,6, #White)
Else
DrawingMode(0)
Circle(*P\x,*P\y,4, #White)
EndIf
DrawText(0,0,texte$)
StopDrawing()
EndProcedure
Procedure TestPoint(X1,Y1,X2,Y2,d)
If X1>X2-d And X1<X2+d And Y1>Y2-d And Y1<Y2+d
Resultat=#True
EndIf
ProcedureReturn Resultat
EndProcedure
Triangle.Triangle
Point.point
;Triangle modifiable à la souris
Triangle\X1=50
Triangle\Y1=50
Triangle\X2=200
Triangle\Y2=400
Triangle\X3=730
Triangle\Y3=150
;Point à tester
Point\x=340
Point\y=100
DiametreSelection=6
Repeat
While WindowEvent():Wend
ClearScreen(0)
ExamineKeyboard()
ExamineMouse()
;Le triangle est modifiable à la souris en cliquant sur un point
If MouseButton(1)
If MemPoint=1
Triangle\X1=MouseX()
Triangle\Y1=MouseY()
ElseIf MemPoint=2
Triangle\X2=MouseX()
Triangle\Y2=MouseY()
ElseIf MemPoint=3
Triangle\X3=MouseX()
Triangle\Y3=MouseY()
EndIf
Else
MemPoint=0
EndIf
If TestPoint(MouseX(),MouseY(),Triangle\X1,Triangle\Y1,DiametreSelection)
MemPoint=1
ElseIf TestPoint(MouseX(),MouseY(),Triangle\X2,Triangle\Y2,DiametreSelection)
MemPoint=2
ElseIf TestPoint(MouseX(),MouseY(),Triangle\X3,Triangle\Y3,DiametreSelection)
MemPoint=3
EndIf
;Place le point à tester sous la souris
Point\x=MouseX()
Point\y=MouseY()
;Affiche le tout
AffPoints(@Triangle,@Point,MemPoint)
FlipBuffers()
Delay(1)
Until KeyboardPushed(#PB_Key_Escape)