ich habe wieder einmal ein Geometrieproblem.
Ein Spielfeld ist durch senkrechte und waagrechte Linien und diagonale Linien (nur in eine Richtung) in ein Raster aufgeteilt. Auf dem Spielfeld befinden sich diverse Objekte, Ort und Länge (Breite ist im Moment egal) und Orientierung sind bekannt. Die Orientierung kann beliebig sein.
Ich muss nun feststellen, ob diese Objekte die Gitterlinien schneiden. Bei den waagrechten und senkrechten Linien ist das kein Problem, aber wie mache ich das bei den Diagonalen?
Zur Veranschaulichung stark vergößert Folgendes, wobei die hier zufällig verteilten Objekte, die senkrechte oder waagerechte Linien schneiden, rot übermalt sind. Der Rasterabstand der Senkrechen/Waagerechten beträgt hier 64 Pixel:
Code: Alles auswählen
; Hier werden die Objekte gezeichnet und es wird geprüft, ob sie senkrechte oder waagrechte Linien schneiden
Procedure makeobjects(canvGad,imageWidth,imageHeight)
StartDrawing(CanvasOutput(canvGad))
; Die Objekte sind hier maßstabsgetreu 12.8 Pixel lang, wird natürlich beim Zeichnen gerundet
For x = 1 To 200
x1 = Random(imageWidth,12.8) ; x-Position des Anfangs; die 12.8 stellen den Abstand vom Rand sicher
y1 = Random(imageHeight,12.8); y-Position des Anfangs
degree.f = Random(360,0)
x2 = x1 + Sin(Radian(degree)) * 12.8 ; x-Position des Endes ; na ja, kann über den Rand hinausgehen, egal
y2 = y1 + Cos(Radian(degree)) * 12.8 ; y-Position des Endes
LineXY(x1,y1,x2,y2,RGB(0,0,250)) ; Alle Objekte erstmal blau
;Die Objekte schneiden waagrechte oder senkrechte Linien, wenn sich
;Anfangs- und Endpunkte der Objekte in verschiedenen Gitterfeldern befinden.
;Dazu einfach die AnfangXY-Position und die EndeXY-Position durch den Linienabstand von 64 Punkten teilen.
;Wenn das Ergebnis für StartXY-Position und EndXY-Position unterschiedlich ist,
;liegen Anfang- und Endpositionen in unterschiedlichen Feldern
If x1/64 <> x2/64 Or y1/64 <> y2/64 ; Objekte, die waagrechte oder senkrechte Linien schneiden,
LineXY(x1,y1,x2,y2,RGB(255,0,0)) ; werden rot übermalt
EndIf
; Wie funktioniert der Test auf das Schneiden bei den diagonalen Linien?
Next
StopDrawing()
EndProcedure
Procedure makeLines(canvGad,imageWidth,imageHeight)
StartDrawing(CanvasOutput(canvgad))
;Grid senkrecht und waagrecht
For x = 0 To imagewidth Step 64
For y = 0 To imageheight Step 64
LineXY(x,y + 64 ,imagewidth,y + 64,RGB(150,150,150)) ; Waagrechte Linien
LineXY(x + 64, 0, x + 64, imageheight,RGB(0,0,0)) ;Senkrechte Linien
Next
Next
; Diagonalen
For x = 0 To imagewidth - 64 Step 64
For y = 0 To imageWidth Step 64;
LineXY(x,y,x + 64,y - 64,RGB(0,0,0))
Next
Next
; Folgendes ist unwichtig, diente mir nur der Visualisierung
; Die roten Rasterlinien ergeben schräg liegende, versetzte ungleichseitige Sechecke.
; Sieht man aber nur, wenn man es weiß
;Die Struktur bezieht sich nur auf den unwichten Teil und ist unwichtig ;-)
Structure lines
x1.i
y1.i
deg1.f
x2.i
y2.i
deg2.f
x3.i
y3.i
deg3.f
x4.i
y4.i
deg4.f
x5.i
y5.i
deg5.f
x6.i
y6.i
deg6.f
degree.f
made.b
EndStructure
NewList lines.lines()
a = 0
b = imageheight
For b = imageHeight + 64 To 0 Step - 192; von oben nach unten abnehmend, da hier y = 0 links unten
For a =- 64 To imagewidth Step 192
; waagrechte Linie unten
x1 = a
y1 = b
x2 = a + 64
y2 = b
; senkrechte Linie links
x3 = x1
y3 = y1 - 64
;schräge Linie links
x4 = x3 + 64
y4 = y3 - 64
;waagrechte Linie oben
x5 = x4 + 64
y5 = y4
;schräge Linie rechts
x6 = x2 + 64
y6 = y2 - 64
;waagrechte linie oben/Wird bei Versatz erfasst
;1.reguläre 6ecke
AddElement(lines())
With lines()
\x1 = x1
\y1 = y1
\deg1.f = 90
\x2 = x2
\y2 = y2
\deg2.f = 90
\x3 = x3
\y3 = y3
\deg3.f = 360
\x4 = x4
\y4 = y4
\deg4.f = 45
\x5 = x5
\y5 = y5
\deg5.f = 90
\x6 = x6
\y6 = y6
\deg6.f = 225
EndWith
Next
Next
;2.versetzte 6ecke
For b = imageHeight To 0 Step - 192 ; - 64
For a = 64 To imagewidth - 64 Step 192 ; 0
;waagrechte Linie unten
x1 = a
y1 = b
x2 = a + 64
y2 = b
;senkrechte Linie links
x3 = x1
y3 = y1 - 64
;schräge Linie links
x4 = x3 + 64
y4 = y3 - 64
;waagrechte Linie oben
x5 = x4 + 64
y5 = y4
;schräge Linie rechts
x6 = x2 + 64
y6 = y2 - 64
;waagrechte linie oben
AddElement(lines())
With lines()
\x1 = x1
\y1 = y1
\x2 = x2
\y2 = y2
\x3 = x3
\y3 = y3
\x4 = x4
\y4 = y4
\x5 = x5
\y5 = y5
\x6 = x6
\y6 = y6
EndWith
Next
Next
ForEach lines()
LineXY(lines()\x1,lines()\y1,lines()\x2,lines()\y2,RGB(200,0,0))
LineXY(lines()\x1,lines()\y1,lines()\x3,lines()\y3,RGB(200,0,0))
LineXY(lines()\x3,lines()\y3,lines()\x4,lines()\y4,RGB(200,0,0))
LineXY(lines()\x4,lines()\y4,lines()\x5,lines()\y5,RGB(200,0,0))
LineXY(lines()\x2,lines()\y2,lines()\x6,lines()\y6,RGB(200,0,0))
LineXY(lines()\x5,lines()\y5,lines()\x6,lines()\y6,RGB(200,0,0))
Next
; unwichtig Ende
StopDrawing()
EndProcedure
Procedure closeprog(window)
If IsWindow(window)
CloseWindow(window)
EndIf
End
EndProcedure
windowWidth = 1024
windowHeight = 1024
window = OpenWindow(#PB_Any,#PB_Ignore,#PB_Ignore,windowWidth,windowHeight,"Demo",#PB_Window_SystemMenu )
imageWidth = 1024
imageHeight = 1024
canvGad = CanvasGadget(#PB_Any,0,0,imageWidth,imageHeight,#PB_Canvas_Keyboard)
makeLines(canvGad,imageWidth,imageHeight)
makeobjects(canvGad,imageWidth,imageHeight)
Repeat
event = WindowEvent()
Select event
Case #PB_Event_CloseWindow
close = 1
While WindowEvent() : Wend
EndSelect
Until close = 1
Ich kippe das Koordinatensystem so, dass die Diagonalen senkrecht oder waagerecht stehen. Dann muss ich aber auch alle Objekte und einiges mehr umrechnen, sehr unschön.
Oder: Wenn die Diagonalen geschnitten werden, bilden die Anfangskoordinaten (oder Endkoordinaten) der Elemente mit den Diagonalen ein Dreieck. Ich berechne die senkrechte Distanz dieser Koordinaten auf die Diagonale und aus dem Orientierungswinkel der Objekte dann, ob der Abstand so klein ist, dass das Objekt die Diagonale schneiden kann. Nachteil ist hier, dass ich jedes Objekt gegen jede Linie laufen lassen muss, und das mit Geometriefunktionen. Dauert sicherlich ewig.
Gibt es für die Diagonalen eine vergleichbar schlanke Lösung wie für die Senkrechten/Waagrechten?
Grüße,
S. Error