$fn=64; // --- Parameters --- cable_diameter = 6.0; clip_outer_diameter = 13.0; banner_width = 30.0; banner_length = 50.0; banner_thickness = 2.0; slit_width = 3.5; module medieval_banner() { union() { // Main Banner Base (prints flat on the bed) difference() { translate([-banner_width/2, -banner_length, 0]) cube([banner_width, banner_length + clip_outer_diameter, banner_thickness]); // Swallowtail cut at the bottom translate([0, -banner_length, banner_thickness/2]) rotate([0, 0, 45]) cube([25, 25, banner_thickness + 2], center=true); } // Cable Clip (integrated with the top of the banner) difference() { // Clip body translate([-banner_width/2, clip_outer_diameter/2, clip_outer_diameter/2]) rotate([0, 90, 0]) cylinder(h=banner_width, d=clip_outer_diameter); // Cable hole translate([-banner_width/2 - 1, clip_outer_diameter/2, clip_outer_diameter/2]) rotate([0, 90, 0]) cylinder(h=banner_width + 2, d=cable_diameter); // Tapered slit for cable insertion (faces UP during print, no overhangs) hull() { translate([-banner_width/2 - 1, clip_outer_diameter/2 - slit_width/2, clip_outer_diameter/2]) cube([banner_width + 2, slit_width, 0.1]); translate([-banner_width/2 - 1, clip_outer_diameter/2 - (slit_width+2)/2, clip_outer_diameter + 0.1]) cube([banner_width + 2, slit_width + 2, 0.1]); } } // Decorative Shield and Cross translate([0, -15, banner_thickness]) { shield_base(); translate([0, 0, 1.5]) cross_decoration(); } } } module shield_base() { hull() { // Top wide part of the shield translate([-10, -5, 0]) cube([20, 15, 1.5]); // Bottom point of the shield translate([0, -15, 0]) cylinder(d=3, h=1.5); } } module cross_decoration() { // Vertical bar translate([-2.5, -10, 0]) cube([5, 17, 1.5]); // Horizontal bar translate([-7.5, -2, 0]) cube([15, 5, 1.5]); } medieval_banner();