// Headlamp bracket to mount lamp to nylon strap v3
// mostly tested with 21mm light and 20mm strap
// requires tweaking of plateScale when changing strap width
// TODO:
//     autoscale plate geometry with strapwidth, light cant
//
//  PRINT: +1 base, +1 perimeter, 50% infill, random seam, slot overhangs barely work
// downward light angle
lCant = 25;
// clipin angle
clipRot = -30;
// clip length:
clipLength = 29;
// light diameter, testing at 0.1 over measured
lDiam = 21.1;
// clip tightness, use 0.8 (tight) to 0.99 (no retention)
clippiness = 0.88;
// plate thick
plateThick = 9;
// plate scale - how many times cliplength, affected by strap and cant
// 2.7 seems right for 25mm strap, 1.9 for 20mm strap
plateScale = 1.45;
// strap width, rec 0.5mm under
strapWide = 19.5;
// strap thickness try 2mm
strapThick = 1.9;
// head curve, puts slight curve in head side
hcRad = 175;
hcDepth = 5.5;
minkRad = 2;
$fn = 20;
// mechanical interface facets should be high when printing
interfaceFacets = 35;
// lop off several things, each gets comment
difference(){
minkowski(){
      // begin plate:
      rotate([0, -90, 0]){
          linear_extrude(plateThick - minkRad - plateThick / 2, scale = 1.15){
              // this polygon adjusts to cant angle and clip length
              polygon([ [0, 0],
              [clipLength * cos(lCant), -1 * clipLength * sin(lCant)],
              [plateScale * clipLength - 3, strapWide + 4],
              [plateScale * clipLength - 3, strapWide + 8],
              [0, strapWide + 7] ]);
            }
        }
// this does the fillets
sphere(r = minkRad);
}
// cut off below xy plane
translate([0, 0, -22]){
    cube([99, 99, 44], center = true);
  }
// cut off back of plate channel for strap
translate([-44 - minkRad, strapWide / 2 + 8, 0]){
    cube([88, strapWide, 222], center = true);
  }
// add top slot
translate([-2, strapWide / 2 + 8, (plateScale + 1) / 1.825 * clipLength * cos(lCant)]){
    rotate([0, 45, 0]){
        cube([16, strapWide, strapThick], center = true);
      }
  }
// add bottom slot
translate([-2, strapWide / 2 + 8, strapWide / 4]){
    rotate([0, -45, 0]){
        cube([16, strapWide, strapThick], center = true);
      }
  }
// head curve
translate([-1 * hcRad - plateThick + hcDepth, 0, (strapWide / 2 + (plateScale + 1) / 1.95 * clipLength * cos(lCant)) / 2 ]){
    rotate([90, 0, 0]){
        cylinder(r = hcRad, 99, center = true, $fn = 300);
      }
  }
} // plane diff
// add little lower bump
difference(){
  minkowski(){
      translate([ (1.2 * lDiam / 2 - 2.5), -8, 0]){
        // rotate for cant
        rotate([lCant, 0, 0]){
          // rotate clip entry
          rotate([0, 0, clipRot]){
            color("Green"){
              difference(){
                  // outer clip diameter account mink
                  cylinder(d = 1.2 * lDiam, 2 * clipLength, center = true);
                 
                  // minus light diam account mink
                  cylinder(d = lDiam + minkRad, 99, center = true, $fn = interfaceFacets);
                  // minus clip entry account mink, the cube y dimension coefficient is clip clippiness, try 0.8-0.95
                  translate([44, 0, 0]){
                      cube([88, clippiness * (lDiam + minkRad), 99], center = true);
                    }
                } // end diff
              }
            } // rot clip
          } // rot cant
        } // trans in xy
      sphere(r = minkRad);
    }
    // cut off below xy plane again?
    translate([0, 0, -22]){
        cube([99, 99, 44], center = true);
      }
 }