Größtmögliche quadratische Fläche in belibiger Form finden

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Bob

Betreff: Größtmögliche quadratische Fläche in belibiger Form finden

BeitragMi, Apr 04, 2007 11:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute,

ich brüte grade über folgendem Problem.
Für einen Startegie Spiel (risiko ähnlich) werden per Zufall Images erzeuge die wie typisch Länder auf einer Politischen Karte aussehen.
Man stelle sich z.B. Deutschland als Bild vor, komplett mit einer Farbe ausgefüllt.
Alle anderen Teile des Images sind Transparent.
Um nun über dieses images z.B. Piktogramme von Einheiten zu legen, die in dem land stationietrt sind, suche ich eine Function die mir den größtmöglichen quadratischen Bereich in dem Image bzw Array aufspürt.
Das Zentrum des Images zu verwenden hat leider keinen Zweck. Man stelle sich nur Italien vor. Da wäre das Zentrum des Bildes wahrscheinlich im Mittelmeer.

Mein erster Ansatz bestand darin die breiteste Zeile und die höchste Spalte zu ermitteln und den Schnittpunkt zu verwenden.
Leider kann dieser Punkt ebenfalls im Transparenten Bereich liegen.

Irgendwelche Vorschläge.
Realtim nicht erforderlich.

ChaosCoder

BeitragMi, Apr 04, 2007 12:08
Antworten mit Zitat
Benutzer-Profile anzeigen
hmmmmm, also da müssteste vllt doch alle pixel durch gucken und immer gaaaaanz viele quadrate ausprobieren, is ne sau arbeit fürn pc, dauert deswegen auch n bissl, aber schreibarbeit dürfte das nich viel sein.

Müssten denn nur die 4 Eckpunkte im Image liegen oder auch die Punkte dazwischen? Ist aber im Nachhinein egal...

Machst einfach 2 For Next schleifen, dann noch eine die bis zum nächstliegenden Rand des Bildes geht (rechts oder unten) merkst dir die entstandenen Punkte, gehst mit ner for schleife einmal komplett über alle Pixel der Linien des Quadrates, liest dort die farbe des Bildes aus und checkst auf transparenz, merkst dir dann in ein paar variablen, anfangspunkt (x,y) und weite (a), machst weiter, wenn jetzt ein neu errechnetes a größer is dann merkst du dir das und am ende solltest du dir x,y und a ausgeben lassen, fertig
Man kann natürlich um die Performance zu steigern, gleich checken ob das Quadrat überhaupt größer sein kann (wegen der Randbegrenzung)...
Was anderes fällt mir nicht ein und glaube, dass es was anderes auch nicht geben wird.

MfG
Chaos|Dragon
Projekte: Geolaria | aNemy
Webseite: chaosspace.de

skey-z

BeitragMi, Apr 04, 2007 14:12
Antworten mit Zitat
Benutzer-Profile anzeigen
ich denke mal die Bilder hast du vorher in einem malprogramm erzeugt und nicht erst zur Laufzeit von BB.

schreib dir doch ne kleine Textdatei, mit Informationen zum jeweiligen land, wo du per Hand Positionen einträgst, wo später Einheiten angezeigt werden sollen, das wäre wohl am einfachsten.
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz
BAC#57: 2. Platz
Twitter

TheShadow

Moderator

BeitragMi, Apr 04, 2007 17:19
Antworten mit Zitat
Benutzer-Profile anzeigen
meine idee wäre jetzt den punkt zu bestimmen wo die meisten pixel liegen... das mürde ich so machen:

wenn an xy-koord ein "land-punkt" ist, dann addiere die x koord zu x2 und y zu y2 - und erhöhe den count-wert

dann alle punkte durchlaufen und das ergebnis durch anzahl der punkte teilen...


for y=0 to ymax
for x=0 to xmax

if point(x,y)=1 then
x2=x2+x
y2=y2+y
count=count+1
endif

next
next

print x2/count
print y2/count



probier mal...
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

rema

BeitragMi, Apr 04, 2007 18:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe mal sowas geproggt um Schriften die als Image vorlagen oder auch Images selber in 3D zu wandeln. Muss aber mal den Code suchen...

TheShadow

Moderator

BeitragMi, Apr 04, 2007 22:26
Antworten mit Zitat
Benutzer-Profile anzeigen
ansonsten kann man noch - jeden punkt im bild abrasen - und den punkt als mitte des rechtecks nehmen - dann jedem punkt die max größe des rechtecks ermitteln... ist dann zeitaufwendiger
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

rema

BeitragDo, Apr 05, 2007 5:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmmm... Habe den Quelltext nicht gefunden. War ja auch zu Blitz3D Zeiten...

Wenn du hier eine Beispielgraphics publizierst, so könnten ich dir was zuscheiden.

//Edit//

Dieses Beispiel macht es sehr einfach.

1. Welche Farben sind vorhanden
2. von Links nach rechts scannen
3. von oben nach unten scannen

Dann solltest du für jede Farbe bzw Land dein Rechteck haben. Der Rest sollte von der Hand gehn...

user posted image

Bob

BeitragDo, Apr 05, 2007 8:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute,

danke für die Resonanz.

@rema

Hier mal eine Typisches Land

user posted image

@The Shadow

Werde deinen Vorschlag mal testen


@Skey-z
Doch. Die Länder Images werden zur Laufzeit von B-Max selber generiert.
Inklusive Liste zu jedem Land, welches Länder benachbaert sind und eines Outline Images um die Grenzen besser anzuzeigen.


@ChAoS|DrAgOn
Dein Vorschlag entspricht ziemlich genau dem was ich mir auch schon überlegt hatte und ich scheue da sehr recheintensiv.


Wenn es euch interessiert könnt Ihr den Quellcode finden unter.
http://www.iomagic.de/bb/landgenerator.bmx

Nach dem Start braucht Ihr je nach Rechnerspeed etwa 2 - 5 Minuten bis die Welt komplett berechnet ist.
Legt in dem Ordner in dem der Quellcode ligt einen Unterordner "Lander" an. Dort hinein werden alle Images abgelegt sowie eine Definitionsdatei für die eigentliche Spielengine (ist aber nicht enthalten)
Schaltet den Debugger ein bzw. Console bei Blide um den Vortgang der generierung zu beobachten.
Nach der Generierung könnt iher mit der Maus über das Spielfeld srollen in dem Ihr die Maus an die Fensterränder führt.
Bringt etwas gedult mit.
 

klepto2

BeitragDo, Apr 05, 2007 22:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, ich habe hier mal schnell 2 Möglichkeiten zusammen gebastelt und mit deinem MapCreator getestet.

Code: [AUSKLAPPEN]

Type TRect
   Field X:Int
   Field Y:Int
   Field Width:Int
   Field Height:Int
   
   Method GetArea:Int()
      Return Width * Height
   End Method
End Type

Type TRectImage
   
   Field Image:TPixmap
   Field BiggestRectFast:TRect
   Field AccuRect:TRect
   
   Function Create:TRectImage(url:String)
      Local RI:TRectImage = New TRectImage
      RI.Image = LoadPixmap(url)
      Return RI
   End Function
   
   Method GetRectsFast()
      Local W:Int = PixmapWidth(Image)
      Local H:Int = PixmapHeight(Image)
      
      For Local X:Int = 0 To W-1
         For Local Y:Int = 0 To H-1
            Local Pixel:Int = ReadPixel(Image , X , Y)
            If Pixel <> $00 Then
               'GetWidth
               Local Width:Int = 0
               Repeat
                  Width:+ 1
                  If X+Width > W-1 Then Exit
               Until ReadPixel(Image,X+Width,Y) = $00
      
               'GetHeight1
               Local Height1:Int = 0
               Repeat
                  Height1:+ 1
                  If Y+Height1 > H-1 Then Exit
               Until ReadPixel(Image , X + Width , Y + Height1) = $00
               
               'GetHeight1
               Local Height2:Int = 0
               Repeat
                  Height2:+ 1
                  If Y+Height2 > H-1 Then Exit
               Until ReadPixel(Image , X , Y + Height2) = $00

               If Height1 <= Height2 Then
                  Local R:TRect = New TRect
                  R.X = X
                  R.Y = Y
                  R.Width = Width-1
                  R.height = height1 - 1
                  
                  R = ResizeRect(R)
                  
                  If BiggestRectFast <> Null Then
                     If R.GetArea() > BiggestRectFast.GetArea() Then BiggestRectFast = R
                  Else
                     BiggestRectFast = R
                  EndIf
                  
               EndIf
            EndIf
         Next
      Next
      
   End Method
      
   Method GetRectsAcc()
      Local W:Int = PixmapWidth(Image)
      Local H:Int = PixmapHeight(Image)

      For Local X1:Int = 0 To W-1
         For Local Y1:Int = 0 To H-1
            Local Pixel:Int = ReadPixel(Image , X1 , Y1)
            If CheckPoint(X1,Y1) = True Then
               Local Width:Int = 0
               Local Height:Int = 0
               
               Repeat
                  Width:+ 1
                  Height:+ 1
                  
                  If X1+Width < 0 Or x1+Width > W-1 Then Exit                  
                  If Y1+Height < 0 Or Y1+Height > H-1 Then Exit
                  
               Until CheckRect(X1,Y1,Width,Height) = False 
                  
                  
               Local R:TREct = New TRect
               R.X = x1
               R.Y = y1   
               R.Width = Width-1
               R.Height = Height-1
               
               R = ResizeRect(R)
               
               If AccuRect <> Null Then
                  If R.GetArea() > AccuRect.GetArea() Then
                     AccuRect = R
                  EndIf
               Else
                  AccuRect = R
               EndIf
            EndIf
         Next
      Next
   End Method
   
   Method CheckRect:Byte(X:Int , Y:Int , W:Int , H:Int)
      If CheckPoint(X , Y) = False Then Return False
      If CheckPoint(X + W , Y) = False Then Return False
      If CheckPoint(X , Y + H) = False Then Return False
      If CheckPoint(X + W , Y + H) = False Then Return False
      Return True
   End Method
   
   Method CheckPoint:Byte(X:Int , Y:Int)
      If ReadPixel(Image , X , Y) = $00 Then Return False
      Return True
   End Method   
   
   Method ResizeRect:TRect(R:TRect)
      Local BR:TREct = New TRect
      Local X:Int = R.X
      Local Y:Int = R.Y
      Local W:Int = R.Width
      Local H:Int = R.Height
      
      'Resizing Upper Line
      'Most time consuming part comment this out if you want faster results
      'but with less accurancy and lower squares
      While CheckLine(X , Y , X + W , Y) = True
         Y:- 1
         H:+ 1
         If Y < 0 Then Exit
      Wend
      Y:+1
      H:-1
      'Resizing Lower Line
      While CheckLine(X , Y + H , X + W , Y + H) = False
         H:- 1
      Wend
      'Resizing Right Line
      While CheckLine(X + W , Y , X + W , Y + H) = False
         W:- 1
      Wend
      
      BR.X = X
      BR.Y = Y
      BR.Width = W
      BR.Height = H
      
      Return BR
   End Method
   
   Method CheckLine(X1:Int , Y1:Int , X2:Int , Y2:Int)
      For Local X:Int = X1 To X2
         For Local Y:Int = Y1 To Y2
            If CheckPoint(X , Y) = False Then Return False
         Next
      Next
      Return True
   End Method



End Type

Local IS:TRectImage[51]

For Local I:Int = 1 To 51
IS[I-1] = TRectImage.Create("Lander\land"+I+".png")
Local T:Int = MilliSecs()
IS[I-1].GetRectsFast()
Print "Less Accurate: " + (MilliSecs()-T)+"ms"
T = MilliSecs()
IS[I-1].GetRectsAcc()
Print "Accurate : " + (MilliSecs()-T)+"ms"
Next


Graphics 800 , 600 , 0 , 60

Local Mode:Int = 1
Local Index:Int = 0
Local Time:Int = MilliSecs()

While Not KeyHit(Key_Escape)
   Cls
   DrawPixmap(IS[Index].Image , 0 , 0)
   SetBlend Alphablend
   SetAlpha 0.5
   SetColor 255 , 0 , 0
   If Mode = 0 Then
      DrawRect(IS[Index].BiggestRectFast.X , IS[Index].BiggestRectFast.Y , IS[Index].BiggestRectFast.Width , IS[Index].BiggestRectFast.Height)
   EndIf
   If Mode = 1 Then
      DrawRect(IS[Index].AccuRect.X , IS[Index].AccuRect.Y , IS[Index].AccuRect.Width , IS[Index].AccuRect.Height)
   EndIf
   SetAlpha 1.0
   SetColor 255 , 255 , 255
   
   If KeyHit(KEY_SPACE) Then Mode = 1 - Mode
   
   If MilliSecs() - Time > 150 Then
      Time = MilliSecs()
      If KeyDown(KEY_RIGHT) Then Index:+ 1
      If KeyDown(Key_LEFT) Then Index:- 1
   EndIf
   
   If Index < 0 Then Index = 50
   If Index > 50 Then Index = 0
   
   DrawText "Land : " + Index , 400 , 20
   Select Mode
      Case 0
      DrawText "Mode : Less Accurate" , 400 , 40
      Case 1
      DrawText "Mode : Accurate" , 400 , 40
   End Select
      
   Flip
Wend



einfach in dein mapcreator verzeichniss speichern und ausführen lassen.
Der langsamste Part ist die ResizeRect Methode, aber dort habe ich auch einen kleinen Kommentar zu geschrieben.

Hoffe damit kannst du was anfangen.
Matrix Screensaver
Console Modul für BlitzMax
KLPacker Modul für BlitzMax

HomePage : http://www.brsoftware.de.vu

Bob

BeitragFr, Apr 06, 2007 9:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für deine Bemühungen klepto.
Leider funzt der Code bei mir nicht.
Fehler:
"Pixmap coordinates out of bounds" in Method GetRectsFast()
 

klepto2

BeitragFr, Apr 06, 2007 12:34
Antworten mit Zitat
Benutzer-Profile anzeigen
hmm, merkwürdig. Bei mir funktioniert es einwandfrei. Ich hatte es bei mir sogar direkt in deinen Code eingebaut um die Rechtecke direkt zu testen.
Kannst du mal genauer beschreiben in welcher Zeile der Fehler auftritt und vielleicht überprüfen ob die Anzahl der Länder korrekt ist.

Code: [AUSKLAPPEN]

Local IS:TRectImage[51]

For Local I:Int = 1 To 51


das war nur auf die gerade bei mir kreierten Maps angepasst. Kann sein das du das bei dir ändern musst.
Matrix Screensaver
Console Modul für BlitzMax
KLPacker Modul für BlitzMax

HomePage : http://www.brsoftware.de.vu

Bob

BeitragFr, Apr 06, 2007 15:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Zeile die den Fehler verursacht ist
If y+Height1 > h-1 Then Exit

Zeile 43 in Blide
 

klepto2

BeitragFr, Apr 06, 2007 20:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ups, Fehler gefunden: (der Fehler liegt: in der ReadPixel anweisung, also eine Zeile tiefer Wink kleiner bug von BMax)

bei dem X+ Width einfach X+Width-1 draus machen. Dann läufts, aber teste es lieber im Release Modus sonst wartest du wirklich ewig auf ergebnisse.

Debug:
ca. 4sek pro Land

Release:
ca. 0.5 sek pro Land

wenn du willst kann ich dir auch die Version schicken, die ich in deinen 'Viewer' eingebaut habe.
Matrix Screensaver
Console Modul für BlitzMax
KLPacker Modul für BlitzMax

HomePage : http://www.brsoftware.de.vu

Bob

BeitragSo, Apr 08, 2007 9:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja. Das war's. Danke nochmal für die Bemühungen.
Dein Code ist wesentlich schneller als der den ich mir ausgetüftelt habe.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group