Stellen Sie sich einen Würfel basierten Welt (wie Minecraft, Trove oder Cube World) , wo alles gleich großer Würfel aus und alle Würfel sind von der gleichen Art .
Das Ziel ist es, die Welt mit der geringsten Anzahl rechteckiger Kästchen darzustellen (indem Würfel zusammengeführt werden, aber die konvexe Form beibehalten wird (auch bekannt als rechteckige Kastenform)). Mein Algorithmus ist erfolgreich, aber seine Leistung ist zu langsam für den beabsichtigten Zweck. Gibt es schnellere Algorithmen?
Der Pseudo-C # -Code für meinen Algorithmus lautet im Grunde:
struct Coordinate { int x,y,z; }; //<-- integer based grid
HashSet<Coordinate> world; // <-- contains all the cubes
//width, height, and length represent how many cubes it spans
struct RectangularBox { Coordinate coord; int width,height,length; }
void Begin()
{
List<RectangularBox> fewestBoxes = new List<RectangularBox>();
while(world.Count > 0)
{
RectangularBox currentLargest = ExtractLargest();
fewestBoxes.Add(currentLargest);
world.RemoveRange(currentLargest.ContainedCubes());
}
//done; `fewestBoxes` contains the fewest rectangular boxes needed.
}
private RectangularBox ExtractLargest()
{
RectangularBox largestBox = new RectangularBox();
foreach (Coordinate origin in world)
{
RectangularBox box = FindMaximumSpan(origin);
if (box.CalculateVolume() >= largestBox.CalculateVolume())
largestBox = box;
}
return largestBox;
}
private RectangularBox FindMaximumSpan(Coordinate origin)
{
int maxX, maxY,maxZ;
while (world.Contains(origin.Offset(maxX, 0, 0))) maxX++;
while (world.Contains(origin.Offset(0, maxY, 0))) maxY++;
while (world.Contains(origin.Offset(0, 0, maxZ))) maxZ++;
RectangularBox largestBox;
for (int extentX = 0; extentX <= maxX; extentX++)
for (int extentY = 0; extentY <= maxY; extentY++)
for (int extentZ = 0; extentZ <= maxZ; extentZ++)
{
int lengthX = extentX + 1;
int lengthY = extentY + 1;
int lengthZ = extentZ + 1;
if (BoxIsFilledWithCubes(origin, lengthX, lengthY, lengthZ))
{
int totalVolume = lengthX * lengthY * lengthZ;
if (totalVolume >= largestBox.ComputeVolume())
largestBox = new RectangularBox(origin, lengthX, lengthY, lengthZ);
}
else
break;
}
return largestBox;
}
private bool BoxIsFilledWithCubes(Coordinate coord,
int lengthX, int lengthY, int lengthZ)
{
for (int gX = 0; gX < lengthX; gX++)
for (int gY = 0; gY < lengthY; gY++)
for (int gZ = 0; gZ < lengthZ; gZ++)
if (!world.Contains(coord.Offset(gX, gY, gZ)))
return false;
return true;
}
Im Wesentlichen wird für jeden Block auf der Welt zunächst ermittelt, wie viele zusammenhängende Blöcke sich in jeder der drei positiven Dimensionen befinden (+ X, + Y, + Z). Und dann füllt es das Volumen irgendwie mit Flut und prüft, welche Füllung die größte ist, bei der keine Blöcke fehlen.
Update: Da ich anscheinend angedeutet habe, dass dies für die Rendering-Engine eines Spiels ist, möchte ich nur klarstellen, dass dies nicht für die Rendering-Engine eines Spiels gilt. Es ist für einen Dateikonverter. keine GUI.