$fn=64; // --- Parameters --- panel_width = 200; panel_thickness = 3; // Tab parameters (slots into the baseplate) tab_width = 180; tab_depth = 8; tab_thickness = 2.6; // Slightly thinner than panel for clearance // --- Modules --- module building_skyline() { union() { // Solid lower wall for stability and figure backdrop cube([panel_width, 40, panel_thickness]); // Building 1 (Far Left) translate([0, 0, 0]) cube([35, 110, panel_thickness]); // Building 2 translate([35, 0, 0]) cube([45, 85, panel_thickness]); // Building 3 (Center Tall - Stepped with Spire) translate([80, 0, 0]) { cube([50, 140, panel_thickness]); translate([10, 140, 0]) cube([30, 15, panel_thickness]); translate([22, 155, 0]) cube([6, 25, panel_thickness]); // Spire } // Building 4 translate([130, 0, 0]) cube([35, 105, panel_thickness]); // Building 5 (Far Right) translate([165, 0, 0]) { cube([35, 125, panel_thickness]); translate([5, 125, 0]) cube([25, 10, panel_thickness]); } } } module window_cutouts() { // Cutouts are made slightly taller than thickness to ensure clean manifold cuts cut_z = -1; cut_h = panel_thickness + 2; // Building 1 Windows for(x = [5 : 10 : 25]) { for(y = [50 : 15 : 100]) { translate([x, y, cut_z]) cube([5, 8, cut_h]); } } // Building 2 Windows (Horizontal Slits) for(y = [50 : 10 : 75]) { translate([40, y, cut_z]) cube([35, 4, cut_h]); } // Building 3 Windows (Dense Grid) for(x = [85 : 8 : 120]) { for(y = [55 : 12 : 130]) { translate([x, y, cut_z]) cube([4, 6, cut_h]); } } // Building 4 Windows (Large Panes) for(y = [50 : 15 : 95]) { translate([140, y, cut_z]) cube([15, 8, cut_h]); } // Building 5 Windows (Vertical staggered) for(x = [170 : 10 : 190]) { for(y = [50 : 10 : 115]) { translate([x, y, cut_z]) cube([5, 5, cut_h]); } } } module mounting_tab() { // Tab extends downwards from Y=0 // Overlap by 0.1mm on Y axis to ensure manifold union translate([(panel_width - tab_width)/2, -tab_depth + 0.1, (panel_thickness - tab_thickness)/2]) cube([tab_width, tab_depth, tab_thickness]); } // --- Main Assembly --- // Centered around the X axis for easy placement translate([-panel_width/2, 0, 0]) { union() { difference() { building_skyline(); window_cutouts(); } mounting_tab(); } }