1
Files
container-packing/containers.py
2024-11-21 11:44:08 +01:00

169 lines
5.2 KiB
Python

import matplotlib.pyplot as plt
class Container:
def __init__(self, length, width, height, capacity):
self.length = length # Länge in m
self.width = width # Breite in m
self.height = height # Höhe in m
self.capacity = capacity # Gewichtskapazität in t
self.items = []
self.fitting = []
def volume(self):
return self.length * self.width * self.height
def used_volume(self):
if len(self.items) == 0:
raise Exception("Container empty, can't calculate used volume!")
return sum(item[0].volume() * item[1] for item in self.items)
def utilization_volume(self):
return self.used_volume() / self.volume() * 100
def used_weight(self):
if len(self.items) == 0:
raise Exception("Container empty, can't calculate load weight!")
return sum(item[0].weight * item[1] for item in self.items)
def utilization_weight(self):
return self.used_weight() / self.capacity * 100
def try_fit(self, items) -> bool:
self.items = items
if self.used_weight() > self.capacity:
print("Load too heavy!")
return False
if self.used_volume() > self.volume():
print("Load too large!")
return False
fitting = []
# Packstücke, Packordnung: Y, Z, X (Breite -> Höhe -> Länge)
x_offset = 0
y_offset = 0
z_offset = 0
for i, item_ in enumerate(items):
item, count = item_
for _ in range(count):
fitting += [
(
x_offset,
y_offset,
z_offset,
item.length,
item.width,
item.height,
COLORS[i],
)
]
if y_offset + item.width < self.width:
# Selbe "Zeile"
y_offset += item.width
elif z_offset + item.height < self.height:
y_offset = 0
# Neue "Ebene" (Höhe)
z_offset += item.height
elif x_offset + item.length < self.length:
y_offset = 0
z_offset = 0
# Neue "Scheibe" (Länge)
x_offset += item.length
else:
return False
if x_offset + item.length < self.length:
x_offset += item.length
else:
return False
y_offset = 0
z_offset = 0
self.fitting = fitting
return True
def visualize(self):
if len(self.fitting) == 0:
raise Exception("Container not fitted, can't visualize!")
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
# Container
ax.bar3d(0, 0, 0, self.length, self.width, self.height, alpha=0.1, color="gray")
# TODO: Don't add individual packages, combine them into blocks (perf)
# Packages
for x, y, z, l, w, h, color in self.fitting:
ax.bar3d(x, y, z, l, w, h, color=color)
ax.set_xlim([0, self.length])
ax.set_ylim([0, self.width])
ax.set_zlim([0, self.height])
ax.set_xlabel("Länge (cm)")
ax.set_ylabel("Breite (cm)")
ax.set_zlabel("Höhe (cm)")
plt.title(f"Container-Auslastung: {self.utilization_volume():.2f}%")
plt.autoscale()
plt.show()
class Item:
def __init__(self, length, width, height, weight):
self.length = length # Länge in cm
self.width = width # Breite in cm
self.height = height # Höhe in cm
self.weight = weight # Gewicht in kg
def volume(self):
return self.length * self.width * self.height
# Length (cm), Width (cm), Height (cm), Capacity (kg)
CONTAINERS = {
"20'": Container(590, 235, 239, 21670),
"40'": Container(1203, 240, 239, 25680),
"40'HQ": Container(1203, 235, 269, 26480),
}
COLORS = ["red", "blue", "green", "yellow", "purple"]
def main():
print("Container-Auslastungsrechner")
items = []
while True:
print("\nNeues Packstück hinzufügen:")
length = float(input("Länge (cm): "))
width = float(input("Breite (cm): "))
height = float(input("Höhe (cm): "))
weight = float(input("Gewicht (kg): "))
count = int(input("Anzahl der Packstücke: "))
item = Item(length, width, height, weight)
items += [(item, count)]
more_items = input("Weitere Packstücke hinzufügen? (ja/nein): ").strip().lower()
if more_items != "ja":
break
for name, container in CONTAINERS.items():
if container.try_fit(items):
print(
f"\nBenötigter Container: {name}, Gesamtauslastung (Volumen): {container.utilization_volume():.2f}%, Ladungsgewicht: {container.used_weight()}kg, Gesamtauslastung (Gewicht): {container.utilization_weight():.2f}%"
)
container.visualize()
return
print("Couldn't find fitting container!")
if __name__ == "__main__":
main()