Soviet PO-2 concrete (Lachman pattern)
by Mach3 ·
An OpenSCAD implementation of the iconic Soviet PO-2 concrete wall, featuring the distinctive Lachman pattern. It can be used as a lampshade or decorative light enclosure.
Interactive Preview & Customizer
3D preview with browser-based OpenSCAD rendering on parameter changes.
Maximum outer diameter of the hexagon (vertex-to-vertex) in mm
Height of the box in mm
Nominal wall thickness at the frame in mm
Add a solid floor at the bottom of the box
Number of columns of waffle pyramids per face (5 matches ref-pattern-3.png)
Number of rows of waffle pyramids per face (4 matches ref-pattern-3.png)
Minimum width of the border frame around each panel in mm
Width of the grooves between waffle cells in mm (0.0 for sharp V-grooves)
Depth/height of the waffle pyramids in mm
Proportional length of the horizontal flat top ridge (0.0 to 1.0)
Vertical shift of the top ridge relative to cell height (0.167 gives 33% / 66% split)
Height of the stacking ridge in mm
Width of the stacking ridge in mm
Chamfer size on the stacking ridge for easy alignment in mm
Clearance between top lip and bottom groove in mm
Screenshots
Prompt
Create a hollow hexagonal “box” with no top or bottom, featuring the design of a Soviet PO-2 concrete fence, also known as the “Lachman pattern.”
Adapt the model for 3D printing. Its maximum cross-sectional dimension should be 250 mm, with the height scaled proportionally. Add interlocking grooves at the top and bottom so multiple sections can be stacked into a tower.
Use the ref-* images as references for the exterior wall texture.
OpenSCAD Code
/*
* Hexagonal Box with Soviet PO-2 Fence Design (Version 11)
* Corrected waffle pattern geometry using robust hull() primitives with shifted top ridge
* Zero flat spacing between cells (extrapolated base sizes)
* Blocks are exactly square, spanning the full window width (no ugly side paddings)
* Concrete gray color styling
* Perfect 120-degree bevel joints on the outer frame to eliminate V-notches
* 45-degree chamfered inner frame edges to eliminate support-requiring overhangs
* Adaptable for 3D printing (supports-free stacking joints)
*/
/* [Hexagonal Box Dimensions] */
// Maximum outer diameter of the hexagon (vertex-to-vertex) in mm
D_max = 250; // [100:5:300]
// Height of the box in mm
H = 105; // [30:5:200]
// Nominal wall thickness at the frame in mm
wall_thickness = 6.0; // [4.0:0.5:10.0]
// Add a solid floor at the bottom of the box
has_bottom = false;
/* [PO-2 Waffle Grid Pattern] */
// Number of columns of waffle pyramids per face (5 matches ref-pattern-3.png)
panel_cols = 5; // [4:1:16]
// Number of rows of waffle pyramids per face (4 matches ref-pattern-3.png)
panel_rows = 4; // [2:1:8]
// Minimum width of the border frame around each panel in mm
border_w = 6.0; // [3.0:0.5:12.0]
// Width of the grooves between waffle cells in mm (0.0 for sharp V-grooves)
groove_w = 0.0; // [0.0:0.1:3.0]
// Depth/height of the waffle pyramids in mm
pyramid_height = 2.0; // [1.0:0.1:5.0]
// Proportional length of the horizontal flat top ridge (0.0 to 1.0)
pyramid_top_ratio = 0.5; // [0.1:0.05:0.9]
// Vertical shift of the top ridge relative to cell height (0.167 gives 33% / 66% split)
pyramid_shift = 0.167; // [-0.3:0.01:0.3]
/* [Stacking Joint Parameters] */
// Height of the stacking ridge in mm
j_height = 3.0; // [2.0:0.1:5.0]
// Width of the stacking ridge in mm
j_width = 2.4; // [1.0:0.1:5.0]
// Chamfer size on the stacking ridge for easy alignment in mm
j_chamfer = 0.6; // [0.2:0.1:1.5]
// Clearance between top lip and bottom groove in mm
clearance = 0.2; // [0.05:0.05:0.5]
/* [Hidden] */
frame_height = 1.5;
// Derived geometry calculations
R_outer = D_max / 2;
R_face = R_outer * cos(30);
W = R_outer;
module po2_waffle_cell(cell_w, cell_h, pyr_h, top_w) {
base_depth = 0.5; // Overlap depth into the base wall to prevent coplanar rendering artifacts
z_shift = cell_h * pyramid_shift;
// Extrapolate base size so that the cell size is exactly cell_w x cell_h at X = 0
w_base = cell_w + base_depth * (cell_w - top_w) / pyr_h;
h_base = cell_h * (1 + base_depth / pyr_h);
hull() {
// Base plate (at X = -base_depth)
translate([-base_depth, -w_base/2, -h_base/2])
cube([0.01, w_base, h_base]);
// Top line segment (at X = pyr_h, shifted in Z)
translate([pyr_h, -top_w/2, z_shift - 0.005])
cube([0.01, top_w, 0.01]);
}
}
module top_lip() {
translate([0, 0, H])
rotate([90, 0, 0])
linear_extrude(height = W + 20, center = true) {
polygon([
[-wall_thickness/2 - j_width/2, 0],
[-wall_thickness/2 - j_width/2 + j_chamfer, j_height],
[-wall_thickness/2 + j_width/2 - j_chamfer, j_height],
[-wall_thickness/2 + j_width/2, 0]
]);
}
}
module bottom_groove() {
h_recess = j_height + clearance + 0.1;
w_recess = j_width + 2 * clearance;
entry_chamfer = j_chamfer;
rotate([90, 0, 0])
linear_extrude(height = W + 20, center = true) {
polygon([
[-wall_thickness/2 - w_recess/2 - entry_chamfer, -0.1],
[-wall_thickness/2 - w_recess/2, entry_chamfer],
[-wall_thickness/2 - w_recess/2, h_recess],
[-wall_thickness/2 + w_recess/2, h_recess],
[-wall_thickness/2 + w_recess/2, entry_chamfer],
[-wall_thickness/2 + w_recess/2 + entry_chamfer, -0.1]
]);
}
}
module single_face() {
// cell_size is determined solely by the width of the window, so they span it exactly
W_win = W - 2 * border_w;
cell_size = W_win / panel_cols;
cell_w = cell_size;
cell_h = cell_size;
grid_w = W_win;
grid_h = panel_rows * cell_size;
difference() {
union() {
// Base wall
translate([-wall_thickness, -W/2, 0])
cube([wall_thickness, W, H]);
// Raised border frame (extra width added so bevel cut resolves perfectly at corners)
difference() {
translate([0, -W/2 - 5, 0])
cube([frame_height, W + 10, H]);
// 45-degree chamfered window cutout matching the grid size
hull() {
// Back sheet (X = -2)
w_back = grid_w - 2 * frame_height - 4;
h_back = grid_h - 2 * frame_height - 4;
translate([-2, -w_back/2, H/2 - h_back/2])
cube([0.01, w_back, h_back]);
// Front sheet (X = frame_height + 2)
w_front = grid_w + 4;
h_front = grid_h + 4;
translate([frame_height + 2, -w_front/2, H/2 - h_front/2])
cube([0.01, w_front, h_front]);
}
}
// Waffle grid
pyr_base_w = cell_w - groove_w;
pyr_base_h = cell_h - groove_w;
for (c = [0 : panel_cols - 1]) {
for (r = [0 : panel_rows - 1]) {
y_pos = -grid_w/2 + (c + 0.5) * cell_w;
z_pos = H/2 - grid_h/2 + (r + 0.5) * cell_h;
translate([0, y_pos, z_pos])
po2_waffle_cell(pyr_base_w, pyr_base_h, pyramid_height, pyr_base_w * pyramid_top_ratio);
}
}
// Top lip (male joint)
top_lip();
}
// Subtract bottom groove (female joint)
bottom_groove();
}
}
module bevel_hull(h, wall_t, R_out, relief_h) {
linear_extrude(height = h) {
polygon([
[-wall_t, -W/2 + wall_t * tan(30)],
[relief_h, -W/2 - relief_h * tan(30)],
[relief_h, W/2 + relief_h * tan(30)],
[-wall_t, W/2 - wall_t * tan(30)]
]);
}
}
module beveled_face() {
intersection() {
single_face();
bevel_hull(H + j_height + 1, wall_thickness, W, pyramid_height + 2);
}
}
// Assemble the hexagonal box in concrete gray color
color("LightGrey") {
union() {
for (i = [0 : 5]) {
rotate([0, 0, i * 60])
translate([R_face, 0, 0])
beveled_face();
}
// Optional bottom floor
if (has_bottom) {
r_in = R_face - wall_thickness;
R_inner = r_in / cos(30);
translate([0, 0, j_height + clearance])
rotate([0, 0, 30])
cylinder(r = R_inner, h = 2.0, $fn = 6);
}
}
}