Number of sides
Number of join per side
Join coverage [mm]
Join compression
Material thickness [mm]
kerf [mm]
Key = Piece width [mm]
Join type
2D or 3D
Repeat pieces x (repeat_x × repeat_y)
Space between pieces [mm]

Live changing code :

/*
// FILE    : Kit carboard/wood pieces parametric regular polygons with different joins
// VERSION : 0.1 (draft)
// LICENSE : M.I.T. (https://opensource.org/licenses/mit-license.php)
// AUTHOR  : Nicolas H.-P. De Coster (Vigon)
// TARGET  : OpenSCAD
*/

///////////////////////////
// D E F I N I T I O N S //
///////////////////////////

nSides = 6;
nJointsPerSides = 1;
join_cover = 15;
compress_fact = 1.5;
material_thick = 3;
kerf = 0.1;
key = 40;
/*
Join type must be :
    0 : simple join, no chamfer;
    1 : simple join, with chamfer;
    2 : join with jaw - blocking;
    3 : join with jaw - non-blocking;
*/
join_type = 3;
/*
isFlat let you choose if you want:
    - true : 2D version (for SVG export and laser cutting, for example)
    - false : 3D version keeps the 3D format of the drawing
*/
isFlat=true;


repeat_x = 3;
repeat_y = 2;
interPiece = 2;



/////////////////////////////
// P R E - C A L C U L U S //
/////////////////////////////

angle=360/nSides;

mid_key = (key+kerf)/2;
radius=mid_key/cos(angle/2);
diameter=2*radius;
side=2*mid_key*tan(angle/2);
mid_side=side/2;
join_distance=side/(nJointsPerSides+1);


/////////////
// C O D E //
/////////////

if(isFlat){
    projection(cut=true)setOfPieces(repeat_x,repeat_y);
}
else{
    setOfPieces(repeat_x,repeat_y);
}

////////////////
// Set of Pieces
////////////////
// Is the will align several pieces and repeat in x and y

module setOfPieces(repeat_x, repeat_y){
    for(x=[0:repeat_x-1]){
        x_distance = nSides%2 ? mid_key+radius+interPiece+kerf : key+interPiece+kerf;
        y_distance = nSides%2 ? diameter+interPiece+kerf : key+interPiece+kerf;
            for(y=[0:repeat_y-1]){
                x_offset = y%2 && (nSides%4)!=0 ? 1/2:0;
                translate([x_distance*(x+x_offset), y_distance*y,0])Piece();
            }
    }
}



////////////////
// Piece
////////////////
// Is the diffenrence of a basic Polygon and the joinss

module Piece(){
    difference(){
        rotate([0,0,angle/2])
            Polygon(nSides, radius, material_thick);
        for(i=[0:nSides-1]){
            for(j=[1:nJointsPerSides]){
                rotate([0,0,angle*i])translate([mid_key,-mid_side+join_distance*j,0])
                Join();
            }
        }
    }
}


//////////
// Join
//////////
//Different joins (others can easily be added)

module Join(){
    if(join_type<2){
        half_deep=join_cover/2;
        translate([-half_deep/2,0,material_thick/2]){
            translate([kerf/4,0,0])
            cube([half_deep-(kerf/2),material_thick-kerf, material_thick], center=true);
        if(join_type==1){
            translate([half_deep/2,0,0])rotate([0,0,45])
                cube([material_thick-kerf, material_thick-kerf, material_thick], center=true);}
        }
    }
    else if(join_type==2 || join_type==3){
        thick_kerf=material_thick-kerf;
        translate([-join_cover/2,0,material_thick/2]){
            translate([-3*join_cover/8,0,0])cube([join_cover/4-kerf,thick_kerf, material_thick], center=true);
            translate([join_cover/8,0,0])cube([join_cover/4-kerf,thick_kerf, material_thick], center=true);
            translate([3*join_cover/8,0,0])cube([join_cover/2,material_thick/compress_fact-kerf, material_thick], center=true);
            if(join_type==3){
                translate([join_cover/4-kerf/2,0,0])rotate([0,0,45])cube([thick_kerf/sqrt(2),thick_kerf/sqrt(2),material_thick], center=true);}
            translate([join_cover/2,0,0])rotate([0,0,45])cube([thick_kerf,thick_kerf,material_thick], center=true);
        }
    }
}

////////////
// Polygon
////////////
//Base Module : regular polygon

module Polygon(nSides, radius, height){
    cylinder(r=radius, h=height, $fn=nSides);
}