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

139 lines
3.7 KiB
Python

from typing import Dict, List, Tuple
import ezdxf
from ezdxf import colors
from ezdxf.addons import binpacking as bp
from ezdxf.addons.drawing import RenderContext, Frontend, matplotlib
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
import matplotlib.pyplot as plt
# Length (cm), Width (cm), Height (cm), Capacity (kg)
CONTAINERS: List[Tuple[str, float, float, float, float]] = [
("20'", 590, 235, 239, 21670),
("40'", 1203, 240, 239, 25680),
("40'HQ", 1203, 235, 269, 26480),
]
COLORS: List[str] = ["red", "blue", "green", "yellow", "purple"]
def float_input(msg: str) -> float:
read_str: str = input(f"{msg}: ")
read_float: float
try:
read_float = float(read_str)
except:
return float_input(msg)
return read_float
def int_input(msg: str) -> int:
read_str: str = input(f"{msg}: ")
read_int: int
try:
read_int = int(read_str)
except:
return int_input(msg)
return read_int
def yes_no_input(msg: str) -> bool:
read_str: str = input(f"{msg} (j/n): ").strip().lower()
if read_str == "j":
return True
elif read_str == "n":
return False
else:
return yes_no_input(msg)
def build_packer(
items: List[Tuple[Tuple[float, float, float, float], int]]
) -> bp.Packer:
packer: bp.Packer = bp.Packer()
for i, ((length, width, height, weight), count) in enumerate(items):
for ii in range(count):
packer.add_item(f"Item {i}_{ii}", width, height, length, weight)
return packer
def make_doc():
doc = ezdxf.new()
doc.layers.add("FRAME", color=colors.YELLOW)
doc.layers.add("ITEMS")
doc.layers.add("TEXT")
return doc
def main() -> None:
print("Container-Auslastungsrechner")
items: List[Tuple[Tuple[float, float, float, float], int]] = []
more_items: bool = True
while more_items:
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("- Packstückzahl")
items += [((length, width, height, weight), count)]
more_items = yes_no_input("Weitere Packstücke hinzufügen?")
for name, length, width, height, capacity in CONTAINERS:
print(
f"Teste {name:>5} Container ({length / 100:>5.2f}m x {width / 100:>5.2f}m x {height / 100:>5.2f}m mit {capacity / 1000:>5.2f}t)..."
)
packer: bp.Packer = build_packer(items)
packer.add_bin(name, width, height, length, capacity)
packer.pack(bp.PickStrategy.BIGGER_FIRST)
if len(packer.unfitted_items) > 0:
print(f"{name} Container ist zu klein!")
break
bins: List[bp.Bin] = []
bins.extend(packer.bins)
doc = make_doc()
bp.export_dxf(doc.modelspace(), bins, offset=(0, 20, 0))
# doc.saveas("packing.dxf")
print(
f"{name} Container passt: Zu {packer.get_fill_ratio() * 100:.2f}% gefüllt ({packer.get_total_weight():.2f}kg)"
)
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
# Container bounding box
ax.bar3d(0, 0, 0, length, width, height, alpha=0.1, color="gray")
# Package bounding boxes
for it in packer.bins[0].items:
x, y, z = it.position
w, h, l = it.width, it.height, it.depth
ax.bar3d(x, y, z, l, w, h, color="red")
plt.title(
f"{name} Container mit {packer.get_fill_ratio() * 100:.2f}% Auslastung"
)
plt.autoscale()
plt.show()
return
print("Konnte keinen passenden Container ermitteln!")
if __name__ == "__main__":
main()