Punkt in gedrehtes Rechteck Problem

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Matthias

Betreff: Punkt in gedrehtes Rechteck Problem

BeitragMo, Apr 20, 2009 17:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Hay.

Da ich eine Function brauche die einen Punkt in einem Rechteck findet habe ich gesucht und auch eine Function dafür gefunden.

Doch leider functioniert sich bei einem gedrehten Viereck nicht mehr.
Seltsamm.
Kann mir jemand helfen.

Code: [AUSKLAPPEN]

Graphics 800,600,32,2

AX=100:AY=100
BX=200:BY=50
CX=250:CY=150
DX=150:DY=200

WK=270:L=100

AX=200+Sin(WK+90)*L:AY=200+Cos(WK+90)*L
BX=200+Sin(WK+180)*L:BY=200+Cos(WK+180)*L
CX=200+Sin(WK+270)*L:CY=200+Cos(WK+270)*L
DX=200+Sin(WK+360)*L:DY=200+Cos(WK+360)*L


SetBuffer BackBuffer()
Repeat
   Cls
   PX=MouseX()
   PY=MouseY()
   Oval PX-2,PY-2,4,4
   Color 255,0,0:Line AX,AY,BX,BY
   Color 255,255,255:Line BX,BY,CX,CY
   Line CX,CY,DX,DY
   Line DX,DY,AX,AY
 
   Text 0,100,PointInsideQuad(PX,PY,AX,AY,BX,BY,CX,CY,DX,DY)

Flip
Until KeyDown(1)=1:End


Function PointInsideQuad (x,y,  x1,y1,x2,y2,x3,y3,x4,y4)
 
   
   If ((y - y1) * (x2 - x1)) - ((x - x1) * (y2 - y1)) <= 0 Then Return 0
   If ((y - y2) * (x3 - x2)) - ((x - x2) * (y3 - y2)) <= 0 Then Return 0
   If ((y - y3) * (x4 - x3)) - ((x - x3) * (y4 - y3)) <= 0 Then Return 0
   If ((y - y4) * (x1 - x4)) - ((x - x4) * (y1 - y4)) <= 0 Then Return 0
   Return True
End Function

SpionAtom

BeitragMo, Apr 20, 2009 17:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Theoretisch würde ichs so machen:
Dreh das Rechteck samt Prüf-Punkt auf 0° zurück (Sprich Punkt und Rechteck müssen beide um dieselbe Gradzahl gedreht werden). Dann kannst du die normale Überprüfung starten.

Oder nimm gleich das hier
https://www.blitzforum.de/foru...light=neck
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

Noobody

BeitragMo, Apr 20, 2009 17:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Da die Funktion das Vorzeichen des Punktes gesehen vom Abstand zur Linie untersucht, müssen die Punkte richtigrum angegeben werden. Richtig wäre Code: [AUSKLAPPEN]
AX=100:AY=100
BX=200:BY=50
CX=250:CY=150
DX=150:DY=200

WK=270:L=100

AX=200+Sin(WK-90)*L:AY=200+Cos(WK-90)*L
BX=200+Sin(WK-180)*L:BY=200+Cos(WK-180)*L
CX=200+Sin(WK-270)*L:CY=200+Cos(WK-270)*L
DX=200+Sin(WK-360)*L:DY=200+Cos(WK-360)*L
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragMo, Apr 20, 2009 17:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja. So einfach ist es leider nicht, da die 4Eckpunkte ein 3DQuad symboliesieren sollen.
Das Flach auf dem Boden liegt.

Deshalb wäre es wichtig das die Function PointInsideQuad das selbständig erkennen soll.

Aber irgendwie fehlt mir dazu der Ansatzpunkt.

Noobody

BeitragMo, Apr 20, 2009 18:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Das hier sollte funktionieren: BlitzBasic: [AUSKLAPPEN]
Function PointInRectangle( PX#, PY#, X1#, Y1#, X2#, Y2#, X3#, Y3#, X4#, Y4# )
CenterX# = ( X1# + X2# + X3# + X4# )/4
CenterY# = ( Y1# + Y2# + Y3# + Y4# )/4

If Sgn( SignedDistance( X1#, Y1#, X2#, Y2#, CenterX#, CenterY# ) ) <> Sgn( SignedDistance( X1#, Y1#, X2#, Y2#, PX#, PY# ) ) Then Return False
If Sgn( SignedDistance( X2#, Y2#, X3#, Y3#, CenterX#, CenterY# ) ) <> Sgn( SignedDistance( X2#, Y2#, X3#, Y3#, PX#, PY# ) ) Then Return False
If Sgn( SignedDistance( X3#, Y3#, X4#, Y4#, CenterX#, CenterY# ) ) <> Sgn( SignedDistance( X3#, Y3#, X4#, Y4#, PX#, PY# ) ) Then Return False
If Sgn( SignedDistance( X4#, Y4#, X1#, Y1#, CenterX#, CenterY# ) ) <> Sgn( SignedDistance( X4#, Y4#, X1#, Y1#, PX#, PY# ) ) Then Return False
Return True
End Function

Function SignedDistance#( X1#, Y1#, X2#, Y2#, X3#, Y3# )
NX# = Y1# - Y2#
NY# = X2# - X1#
W# = -( NX#*X1# + NY#*Y1# )

Return ( NX#*X3# + NY#*Y3 + W# )/Sqr( NX#*NX# + NY#*NY# )
End Function
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragMo, Apr 20, 2009 18:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen dank Noobody.

Sad
Aber ist das die einzigste Möglichkeit mit den 8Quadratwurzeln.

Ich muß leider diese Function extrem oft aufrufen.
Da sie für mein Mommentanes Projekt ist.
Es wird ein Formel1 Wagen auf einem Pfad bewegt also von Wegpunkt zu Wegpunkt.
Wenn der Wagen wegen Fliehkraft vom Pfad rutcht dann wird es neu simuliert doch diesemal mit weniger geschwindikkeit. Solange wie der Formel1 wagen nicht mehr von dem Pfad rutcht.

Doch um heraus zu finden ob der Wargen nun vom Pfad gerutcht ist, mus ich wissen ob sich der Wargen noch inerhalb des PfadQuads befindet.

Deshalb solte die Function möglichst schnell sein.



user posted image
 

matze-t

BeitragMo, Apr 20, 2009 18:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Funktion hat auch einen Haken: Der Mittelpunkt eines Vierecks liegt nicht unbedingt im Viereck. Wenn das der Fall ist, liefert die Funktion einen falschen Wert. Wenn es aber nur um gedrehte Rechtecke geht sollts funktionieren.

Noobody

BeitragMo, Apr 20, 2009 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Quadratwurzel kann man in der Tat samt Division streichen. Der Abstand wird dann nicht mehr richtig berechnet, aber für die Überprüfung spielt ja nur das Vorzeichen eine Rolle.

mathe-t hat Folgendes geschrieben:
Die Funktion hat auch einen Haken: Der Mittelpunkt eines Vierecks liegt nicht unbedingt im Viereck.

Das hast du gut erkannt Razz
Aber da er ja an sich nur gedrehte Quads will, habe ich die Funktion gepostet. In anderen Fällen würde sich die von SpionAtom verlinkte Funktion eignen.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Matthias

BeitragMo, Apr 20, 2009 18:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Stimmt es geht auch ohne Quadratwurzel. Das ist dann natürlich richtig super.

Vielen dank Noobody.

Edit: Habs jetzt vernünftig umgebaut.


Code: [AUSKLAPPEN]

Graphics 800,600,32,2
WK=100:L=100
AX=200+Sin(WK+90)*L:AY=200+Cos(WK+90)*L
BX=200+Sin(WK+190)*L:BY=200+Cos(WK+180)*L
CX=200+Sin(WK+270)*L:CY=200+Cos(WK+270)*L
DX=200+Sin(WK+360)*L:DY=200+Cos(WK+360)*L


SetBuffer BackBuffer()
Repeat
   Cls
   PX=MouseX()
   PY=MouseY()
   Oval PX-2,PY-2,4,4
   Color 255,0,0:Line AX,AY,BX,BY
   Color 255,255,255:Line BX,BY,CX,CY
   Line CX,CY,DX,DY
   Line DX,DY,AX,AY
 
   Text 0,100,PointInRectangle(PX,PY,AX,AY,BX,BY,CX,CY,DX,DY)

Flip
Until KeyDown(1)=1:End


Function PointInRectangle( PX#, PY#, X1#, Y1#, X2#, Y2#, X3#, Y3#, X4#, Y4# )
   Local X#,Y#,W#
   CX#=(X1+X2+X3+X4)/4:CY#=(Y1+Y2+Y3+Y4)/4
   
   X=Y1-Y2:Y=X2-X1:W=X*X1+Y*Y1:A=((X*CX+Y*CY-W)>0)
   If A<>((X*PX+Y*PY-W)>0) Then Return

   X=Y2-Y3:Y=X3-X2:W=X*X2+Y*Y2:A=((X*CX+Y*CY-W)>0)
   If A<>((X*PX+Y*PY-W)>0) Then Return

   X=Y3-Y4:Y=X4-X3:W=X*X3+Y*Y3:A=((X*CX+Y*CY-W)>0)
   If A<>((X*PX+Y*PY-W)>0) Then Return
   
   X=Y4-Y1:Y=X1-X4:W=X*X4+Y*Y4:A=((X*CX+Y*CY-W)>0)
   If A<>((X*PX+Y*PY-W)>0) Then Return
   
   Return True
End Function

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group