from build123d import Vector, Wire, Face, Compound, extrude, export_step, export_stl
import ezdxf
import os

os.makedirs("/work/out", exist_ok=True)

# Dimensions in millimeters. Thickness and slot width are illustrative,
# untested assumptions, not a claim of fit or structural stability.
height = 2200.0
thickness = 17.4
slot_width = 18.0
half_slot = slot_width / 2
slot_end = 1100.0

# Decorative tier proportions are chosen for a recognizable tree silhouette.
# Each panel's outline fits within 1000 x 2200 mm. The short central stem
# and flat-topped tip leave material on either side of their open slots.
right_edge = [
    (450, 0), (500, 180),
    (335, 480), (425, 480),
    (260, 770), (360, 770),
    (200, 1050), (305, 1050),
    (155, 1320), (245, 1320),
    (105, 1580), (190, 1580),
    (65, 1830), (130, 1830),
    (36, height),
]
left_edge = [(-x, z) for x, z in reversed(right_edge)]

# Panel A's slot is accessible from the top; panel B's from the bottom.
# Each is one continuous, closed perimeter with the slot cut into its edge.
panel_a_outline = right_edge + [
    (half_slot, height), (half_slot, slot_end),
    (-half_slot, slot_end), (-half_slot, height),
] + left_edge
panel_b_outline = right_edge + left_edge + [
    (-half_slot, 0), (-half_slot, slot_end),
    (half_slot, slot_end), (half_slot, 0),
]

# Assemble the two separate solids at 90 degrees, centered on the same axis.
# Their complementary open slots provide the vertical assembly access path.
a_wire = Wire.make_polygon(
    [Vector(x, -thickness / 2, z) for x, z in panel_a_outline],
    close=True,
)
b_wire = Wire.make_polygon(
    [Vector(-thickness / 2, y, z) for y, z in panel_b_outline],
    close=True,
)
panel_a = extrude(Face(a_wire), amount=thickness, dir=(0, 1, 0))
panel_b = extrude(Face(b_wire), amount=thickness, dir=(1, 0, 0))
assembly = Compound(children=[panel_a, panel_b])

export_step(assembly, '/work/out/model.step')
export_stl(assembly, '/work/out/model.stl')

# Flat, separate outlines for manual CAM review. Each contour occupies its
# own 1000 x 2200 mm envelope; their DXF placements are not a sheet nesting.
doc = ezdxf.new('R2010')
doc.header['$INSUNITS'] = 4  # millimeters
doc.layers.new('CUT')
space = doc.modelspace()
for outline, center_x in ((panel_a_outline, 500), (panel_b_outline, 1600)):
    space.add_lwpolyline(
        [(x + center_x, z) for x, z in outline],
        close=True,
        dxfattribs={'layer': 'CUT'},
    )
doc.saveas('/work/out/cutting.dxf')
