Was sind gute Algorithmen, um Grenzen / Staatsgebiete auf 2D-Sternenkarten zu generieren?

9

Ich versuche eine ziemlich große zweidimensionale Sternenkarte zu erstellen, die verschiedene Fraktionen / Zustände zeigt, die jeweils ein oder mehrere Sternensysteme besitzen. Ich möchte automatisch Grenzen / Gebiete für die Fraktionen erstellen.

Die Idee ist, im Wesentlichen von so etwas auszugehen (die Punkte repräsentieren Sternensysteme auf einer 2D-Ebene, Farben sind Fraktionszugehörigkeiten)

Sternensysteme und ihre Fraktionszugehörigkeit

dazu

Sternensysteme mit Fraktionsgebieten

Das Generieren solcher Karten scheint eine ziemlich häufige Anforderung zu sein, daher lautet meine eigentliche Frage: Gibt es Standardalgorithmen zum Generieren von Zustandsbereichen wie gezeigt? Wenn ja, können Sie mich darauf hinweisen? Wenn nicht, können Sie sich einen guten Algorithmus vorstellen (Grundidee oder Pseudocode sind in Ordnung)?

Die Leistung des Algorithmus ist für mich kein Hauptanliegen, daher hätte ich lieber eine "schönere" Karte als eine schneller zu generierende. Diese ähnliche Frage bietet einen Ansatz, der wahrscheinlich auf mein Problem anwendbar ist, obwohl eine gewisse "Verschönerung" erforderlich ist: Wie erstelle eine Karte aus einem Diagramm

Lassen Sie mich erklären, was ich meine, wenn ich hübscher sage: Am Ende der verknüpften Frage präsentiert die Fragestellerin ihr Endergebnis, nachdem sie die akzeptierte Antwort implementiert hat. Mein erstes Problem hier: Die Bereiche für die Knoten Nr. 6, Nr. 9 und Nr. 12 sind sehr klein und merkwürdig geformt. Anstelle der scharfen Kanten würde ich auch einen glatteren, geschwungenen Look bevorzugen.

Meine eigenen Ideen, einschließlich der jeweiligen Nachteile / Fragen, die ich mit ihnen sehe:

  • Generieren Sie für jede Fraktion ein "konvexes Rumpf" -Polygon und erweitern Sie es dann etwas nach außen. Probleme: Keine konkaven Funktionen. Wie gehen Sie mit Überschneidungen um?
  • Generieren Sie ein Voronoi-Diagramm für die Punkte und verwenden Sie dann die Voronoi-Polygonkanten zwischen benachbarten Systemen verschiedener Fraktionen als Grenzen. Problem: Große Polygone an den Kartenrändern - wie identifiziere und behebe ich diese?
  • Generieren Sie für jeden Punkt ein Polygon mit fester Größe und vereinen Sie alle Polygone für eine einzelne Fraktion (was zu einem großen, möglicherweise komplexen "Fraktionspolygon" führt). Dann tun Sie etwas, um überlappende Bereiche zwischen zwei Fraktionen in Einklang zu bringen. Probleme: Wie würde ich das genau machen? Nicht gerade ein trivialer Prozess. Was ist, wenn sich mehr als zwei Fraktionen überschneiden?

Deine Hilfe wird wertgeschätzt.


Nachtrag: Nachdem ich über die ersten beiden Antworten und ihre jeweiligen Lösungsansätze nachgedacht habe, habe ich festgestellt, dass meine obigen Anforderungen unvollständig sind.

Ich muss hinzufügen, dass die Karte dünn besiedelte Gebiete haben kann, was bedeutet, dass es einen isolierten Stern oder eine Gruppe von Sternen geben kann. Ich möchte jeden dieser Cluster mit einem eigenen zusammenhängenden farbigen Bereich anzeigen. Etwas wie das:

Sternensysteme mit Fraktionsgebieten, verschiedenen Clustern

Mir ist klar, dass dies möglicherweise einen ersten Schritt erfordert, der Cluster identifiziert und dann den eigentlichen Algorithmus für jeden der Cluster ausführt.

Grüse
quelle
(Brainstorming) Möglicherweise können Sie den Rest des Raums mit blauem Rauschen (z. B. Poisson-Scheibe) füllen und dann voronoi ausführen, um eine Farbzuweisung zu erhalten. Den hinzugefügten Punkten würde der weiße Hintergrundbereich zugewiesen.
Amitp
@amitp Hey Amit, es ist mir eine Ehre, dass Sie hier einen Kommentar abgeben! Ich habe beim Lesen Ihrer Artikel zu Red Blob Games eine enorme Menge an Inspiration und praktischem Wissen erhalten. Mehr zum Thema: Die Idee, zusätzliche Punkte zu erzeugen, ist sinnvoll. Gibt es einen bestimmten Grund, warum Sie speziell blaues Rauschen erwähnen ?
Grüse
... Ich denke, weil es natürlicher aussieht als andere Geräuscharomen.
Grüse

Antworten:

16

Ich denke, die Voronoi-Idee ist gut. Jeder Stern wird zu einem Startpunkt für Voronoi, und dann zeigen die Voronoi-Regionen die Gebiete, die jeder Fraktion gehören. Es gibt jedoch einige Änderungen, die dafür sorgen, dass es besser funktioniert:

  1. Wie Sie bereits erwähnt haben, gibt es leere Bereiche, die keiner Fraktion zugeordnet werden sollten. Voronoi wird große Polygone erstellen, die sich bis in Bereiche erstrecken, in die die Fraktion nicht gelangen sollte. Um dies zu beheben, verwenden Sie einen Algorithmus für blaues Rauschen wie eine Poisson-Scheibe, um den nicht besetzten Raum mit Sternen zu füllen, die niemandem gehören. Blaues Rauschen ist zufällig, aber gleichmäßig verteilt (es kann auch nützlich sein, um Ihre Sternpositionen zu generieren).
  2. Voronoi produziert blockige Regionen. Ersetzen Sie Voronois Umkreiszentrumsberechnung durch eine Schwerpunktberechnung, um rundere Zellen zu erzeugen. Ich habe ein wenig darüber geschrieben hier mit einigen Vergleichsbildern.
  3. Voronoi erzeugt Polygone, aber Sie möchten runde Bereiche. An jeder Ecke befinden sich drei Polygone. Wenn alle drei dieselbe Fraktion sind, können Sie sie in Ruhe lassen. Wenn zwei dieselbe Fraktion sind, führen Sie eine quadratische Bezierkurve ein, die die Grenze zur anderen Fraktion verschiebt. Wenn alle drei Fraktionen unterschiedlich sind, können Sie entweder die Ecke in Ruhe lassen oder drei Bezierkurven einführen, um alle Grenzen voneinander zu entfernen. Ich bin mir nicht sicher, was besser aussieht.

Hier ist die Ausgabe:

Blobby Karte

Ich habe auch eine Seite geschrieben, auf der Sie die Regionen malen können, um zu sehen, wie sie aussehen würden.

amitp
quelle
Das passt perfekt zu meinem Anwendungsfall, vielen Dank! Ich muss sagen, es ist ebenso beeindruckend und deprimierend, dass Sie so schnell ein interaktives Beispiel zusammenstellen konnten, während ich wahrscheinlich mindestens ein paar Tage brauchen werde, um das zu reproduzieren, was Sie hier vorgestellt haben :) Ich freue mich auf diesen Tutorial-Artikel.
Grüse
4

Eine von vielen Methoden ist eine Einflusskarte . Sie können nach bestimmten Code-Implementierungen suchen, aber der grundlegende Algorithmus ist ziemlich einfach.

Weisen Sie jedem Fraktionsobjekt (z. B. Sternensystem) einen positiven (heißen) Wert zu. Weisen Sie allen Objekten anderer Fraktionen einen negativen (kalten) Wert zu. Die Größe von heiß oder kalt sollte davon abhängen, wie viel Einfluss das Objekt Ihrer Meinung nach auf seine Umgebung und seine Nachbarn ausübt. Diese Werte müssen nicht proportional sein, wenn Sie letztendlich ein "dmz" zwischen Fraktionen beibehalten möchten.

Verwenden Sie diese Details, um ein temporäres Raster (z. B. ein Array) zu erstellen, das sich den Pixeln Ihrer Karte annähert. Sie können ein solches Raster mit der gewünschten Auflösung erstellen, einschließlich 1: 1.

Verwenden Sie als Nächstes die Wärme- / Feldübertragungsgleichung, um die Stärken der Fraktionsobjekte (Wärme) zu iterieren und gegen die Stärken der Objekte der Gegner (Kälte) für jede Nachbarzelle im Gitter zu verteilen.

Spüle und wiederhole für jede Fraktion auf deiner Karte, indem du für jede Fraktion separate Fraktionsgitter erstellst.

Interpolieren Sie schließlich die Fraktionsgitter zusammen, um für jede Fraktion eine Einflusskontur zu erstellen. Übertragen Sie dieses Raster dann mit der Auflösung, die Sie für das Raster verwendet haben (Hinzufügen fraktionsspezifischer Farben usw.), zurück auf Ihre Pixelkarte.

Die Kunst in diesem Prozess besteht darin, zu bestimmen, wie viel Einfluss jedes Objekt haben sollte und welche Spielelemente Sie verwenden, um diesen Wert zu quantifizieren.

Abgesehen davon können die Produkte dieser Methode für alle möglichen anderen Zwecke verwendet werden, z. B. für Ihre Entscheidungsfindung.


Zusätzliche Referenz: Diskussionsthread zu den Ursprüngen der Einflussabbildung .

J'Eight
quelle
Dieser Ansatz sollte offensichtlich sein, ist mir aber nie in den Sinn gekommen. Vielen Dank, dass Sie mich darauf aufmerksam gemacht haben! Ein Gedanke: Meine Karten können in bestimmten Gebieten spärlich sein, während andere Gebiete dicht nebeneinander mit Sternen unterschiedlicher Zugehörigkeit gefüllt sind. Gibt es eine Möglichkeit, unterschiedliche Rasterzellengrößen für die verschiedenen Bereiche zu verwenden? Denken nach dem Vorbild eines Quadtree oder ähnlichem.
Grüse
2

Sie sollten sich Voronoi-Diagramme ansehen. Hier ist die Definition auf Wikipedia:

In der Mathematik ist ein Voronoi-Diagramm eine Aufteilung einer Ebene in Regionen basierend auf der Entfernung zu Punkten in einer bestimmten Teilmenge der Ebene.

Die Basispunkte werden normalerweise zufällig generiert und oft als Knoten bezeichnet. In Ihrem Fall könnte jeder Knoten Ihre Sterne sein. Auf diese Weise kann die mit den Sternen verknüpfte Fraktion mit der den Stern umgebenden Voronoi-Zelle verknüpft werden. Wenn jede Zelle berechnet wurde, verbinden Sie diejenigen mit derselben Fraktion miteinander und sollten einen hübschen Rand um Ihre Sterne haben.

Die FastNoise-Bibliothek unterstützt Voronoi-Diagramme. Vielleicht sollten Sie sie sich ansehen.

Glättung der Regionen

Bewahren Sie Ihre Sterne in einem «sicheren Array» auf und verwenden Sie eine Kopie davon, in der Sie durch Interpolation der nächsten Nachbarn tatsächlich weitere Punkte hinzufügen und aus diesen Punkten das Diagramm erstellen. Es sollte Ihnen glattere Regionen geben.

Andere Ideen Der Fortune-Algorithmus basiert auf einer geraden Linie, die die kartesische Ebene fegt. Eine interessante Idee wäre, stattdessen einen Kreis zu verwenden, um die Ebene vom Zentrum Ihrer Galaxie / Ihres Raums zu fegen. Vielleicht könnte dies auch zu einigen interessanten Formen führen.

Geometriemanipulation

Ihre letzte Idee, kleinere Polygone zu größeren zu kombinieren und dann die Kanten zu fixieren, erfordert erweiterte Spline-Algorithmen, um die Formen zu ändern. Ich bin mir nicht sicher, ob das effizient oder gut aussehend wäre. Ich bin mir ziemlich sicher, dass das Voronoi-Diagramm mit zusätzlicher Tessellation der richtige Weg ist, da es das Kantenproblem selbst behebt und sogar einige zusätzliche Daten wie den Abstand von den Rändern (die zur Bestimmung der Zonen von verwendet werden könnten) selbst anbieten kann Konflikt zwischen den verschiedenen Fraktionen, die Wahrscheinlichkeit, auf verschiedene Schiffstypen zu stoßen usw.)

BadgerBadger
quelle
Beachten Sie, dass OP bereits auf eine Antwort mit Voronoi-Diagrammen verwiesen hat, sodass sie sich der Technik bewusst sind, jedoch nach spezifischen Änderungen gefragt haben, um das Erscheinungsbild der Rahmen zu ändern. Können Sie Ihre Antwort erweitern, um diese spezifischen Anfragen zu beantworten?
DMGregory
Sorry, falsch gelesen den Beitrag
BadgerBadger
Vielen Dank, dass Sie Ihre Antwort geändert haben! Die Glättungsidee ist interessant. Ich habe zwei Probleme mit dem Voronoi-Ansatz: Erstens: Wie erkenne und beschränke ich die "äußeren" Punkte, damit sich die Ränder nicht bis zu den Rändern des Bildschirms erstrecken (siehe das zweite Bild meiner Frage). Zweitens: In dünn besiedelten Gebieten liefert Voronoi keine großartigen Ergebnisse, da die Polygone riesig werden. Vielleicht gibt es eine offensichtliche Lösung für diejenigen, die ich nicht sehe?
Grüse
Wäre das eine Option, um selbst Punkte hinzuzufügen, um den Bereich einzurahmen? Wenn Sie dann beim Rendern des Diagramms eine Linie erreichen, die den tatsächlichen Bildrand erreicht, zeichnen Sie sie einfach nicht, da sie nicht Teil des Spielbereichs ist. Das zweite Problem sollte mit der Glättung behoben werden können. Sie können weitere Punkte hinzufügen, wenn diese weiter voneinander entfernt sind, sodass Sie eine konsistente «Rastergröße» beibehalten.
BadgerBadger
@BadgerBadger yep, ich experimentiere gerade mit dem Hinzufügen von Punkten
Grüse