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

![]() |
BobBetreff: Größtmögliche quadratische Fläche in belibiger Form finden |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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... | ||
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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... ![]() |
||
![]() |
Bob |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo Leute,
danke für die Resonanz. @rema Hier mal eine Typisches Land ![]() @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 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke für deine Bemühungen klepto.
Leider funzt der Code bei mir nicht. Fehler: "Pixmap coordinates out of bounds" in Method GetRectsFast() |
||
klepto2 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Die Zeile die den Fehler verursacht ist
If y+Height1 > h-1 Then Exit Zeile 43 in Blide |
||
klepto2 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ups, Fehler gefunden: (der Fehler liegt: in der ReadPixel anweisung, also eine Zeile tiefer ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja. Das war's. Danke nochmal für die Bemühungen.
Dein Code ist wesentlich schneller als der den ich mir ausgetüftelt habe. |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group