Basic Univers
; Comtois 05/02/05
; Détection d'un point dans un triangle

;-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, "", #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
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

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
  ; 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
  ; 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(AX1)= Signe(P1) And Signe(AX2)= Signe(P2) And Signe(AX3)= Signe(P3)
    Resultat =#True
  EndIf
  ProcedureReturn Resultat
EndProcedure

Procedure AffPoints(*T.Triangle, *P.point, mem)
  StartDrawing(ScreenOutput())
    ;/Affiche le triangle
    Circle(*T\X1, *T\Y1, 4, RGB(255, 0, 0))
    Circle(*T\X2, *T\Y2, 4, RGB(255, 0, 0))
    Circle(*T\X3, *T\Y3, 4, RGB(255, 0, 0))
    LineXY(*T\X1, *T\Y1, *T\X2, *T\Y2, RGB(255, 0, 0))
    LineXY(*T\X2, *T\Y2, *T\X3, *T\Y3, RGB(255, 0, 0))
    LineXY(*T\X1, *T\Y1, *T\X3, *T\Y3, RGB(255, 0, 0))
    ;/Affiche le point
    If mem
      DrawingMode(4)
      Circle(*P\x, *P\y, 6, RGB(255, 255, 255))
    Else
      DrawingMode(0)
      Circle(*P\x, *P\y, 4, RGB(255, 255, 255))
    EndIf
    ;/Affiche une croix pour mieux suivre le déplacement du point
    LineXY(*P\x, 0, *P\x, ScreenHeight - 1, RGB(255, 255, 255))
    LineXY(0, *P\y, ScreenWidth - 1, *P\y, RGB(255, 255, 255))
    If CollisionTriangle(*T, *P)
      FrontColor(RGB(255, 255, 0))
      BackColor(RGB(255, 0, 0))
      texte$ = "  IN "
    Else
      FrontColor(RGB(155, 155, 155))
      BackColor(RGB(0, 255, 0))
      texte$ = " OUT "
    EndIf
    DrawText(0, 0, texte$)
  StopDrawing()
EndProcedure
Procedure TestPoint(X1, Y1, X2, Y2, d)
  If X1>X2 - d And X1 And Y1>Y2 - d And Y1
    ProcedureReturn #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)