/*
 Magnet Push-Pin with Custom Graphic
 Copyright 2025 Tyler Tork
 
 This model is a pushpin-style magnet you can customize with a top graphic (SVG file) or shape (STL file). The parameters let you specify the sizes of the magnet you are using and the dimensions you want to custom artwork to appear, among other things.
 
 The default parameter values are intended to work with a stack of two 5mm magnets you can get from Amazon.com: https://amzn.to/3PvZZDm (affiliate link). But you can use any cylindrical magnet.
 
  A complete guide for configuring this model can be found at https://freelittleartgalleries.art/2025/01/3d-print-pushpin-magnets/

 Licensed under Creative Commons - Attribution - Non-Commercial - Share Alike
    https://creativecommons.org/licenses/by-nc-sa/4.0/
 */
 
inner_dimensions = [100,127,35]; // 0.1
wall_thickness = 1.7;
glass_dimensions = [76.2, 101.6, 1.59];
glass_overlap = 2; // [0.5:0.25:3]
corner_radius = 7; // 0.5
lid_overlap = 6.5;
holder_type = 0; // [0:clips,1:pole,2:hook,3:card holder]

/* [Pole settings] */
Pole_height = 26;
Pole_diameter = 10;
Pole_gap = 6;

/* [Hook settings] */
Hook_diameter = 4;
Hook_height = 10;

/* [Card holder settings] */
Card_dimensions = [ 100, 127 ]; // 0.25

/* [Text] */
text1 = "IN CASE OF"; // 15
text2 = "EMERGENCY"; // 15
text_size = 10; // 0.5
text_font = "Liberation Sans:style=Bold";
text_emboss = 0.3;
/* [Advanced] */
tolerance = 0.15;
assembled = false;
debug = true;
section = false;

include <BOSL2/std.scad>

/* [Hidden] */
$fa=2; $fs=.2;
EPS=.001;
TOL = tolerance;
TOL2 = TOL*2;
tkWall = wall_thickness;
tk2Wall = tkWall*2;
dInt = inner_dimensions;
dOut = dInt + [tk2Wall,tk2Wall,tkWall];
rOuter = corner_radius;
rInner = max(0,rOuter-tkWall);
dGlass = glass_dimensions;

module cardHolder() {
EPS=.3;
	pts = [[-1,-EPS], [0,-EPS], [0,1], [2,3], [1, 3], [-1, 1]];
	ptsWall = [
		[-EPS,1-EPS],
		[2, 3],
		[1.5,2.8],//@@
		[1,3],
		[-EPS, 2-EPS]
	];
	
	leng = Card_dimensions/2;
	offs = leng+[.5,.5];
	big = offs*2 - [dInt.x, dInt.y];
	echo(big);
	up(tkWall) {
		translate([0,-offs.y,0])
		xrot(90)
		yrot(90)
		linear_extrude(height=leng.x, center=true)
		polygon(big.y >= 0 ? ptsWall : pts);
		
		translate([-offs.x,0,0])
		xrot(90)
		linear_extrude(height=leng.y, center=true)
		polygon(big.x >= 0 ? ptsWall : pts);
		
		translate([offs.x,0,0])
		zrot(180)
		xrot(90)
		linear_extrude(height=leng.y, center=true)
		polygon(big.x >= 0 ? ptsWall : pts);
	}
}

module pole() {
	ht = Pole_gap;
	di = Pole_diameter;
	r=Pole_diameter/2;
	raise = ht+r+tkWall;
	hull() {
		up(raise) xrot(90) zrot(45) {
			cube([di,2,2], center=true);
			cube([2,di,2], center=true);
		}
//		cylinder(2, r=r, center=true);
		cube([r*2, 2, 1], anchor=BOTTOM);
	}
	up(raise) xrot(-90) zrot(45) {
		cube([di,2,Pole_height], anchor=BOTTOM);
		cube([2,di,Pole_height], anchor=BOTTOM);
	}
	pts = [[0,0], [ht+di,0], [ht+di,-1], [0,-r]];
	yrot(-90)
//	rotate([90,90,0])
	linear_extrude(1.5,center=true)
	polygon(pts);
//	up(raise) xrot(-90) cylinder(Pole_height, r=r);
	
}

module hook() {
	ht = Hook_height;
	di = Hook_diameter;
	raise = ht + tkWall;
	cylinder(h=raise+EPS, d=di);
	hull() {
		up(raise) cylinder(h=2, d=di);
		translate([0, di, raise]) cylinder(h=1, d=di);
	}
}

module xhook() {
	ht = 7;
	di = 3;
	raise = ht + tkWall;
	cylinder(h=raise, d=di);

	up(raise) 
	rotate([90, 0, -90])
	left(di*2)
	rotate_extrude(angle=60)
	right(di*2)
	circle(d=di);
//	fwd(di/2) xrot(-45) back(di/2) cylinder(h=di*1.5, d=di);
}

module clip() {
	hw = tkWall/2;
	pts = [ [-hw,-EPS], [hw, -EPS],
			[hw, 1+tkWall*sin(20)],
			[-hw+tkWall*sin(40), 1+tkWall*cos(40)],
			[-hw, 1] ];

	up(tkWall) {
		back(5)
		xrot(90)
		linear_extrude(10)
		polygon(pts);

		translate([-tkWall/2,0,1])
		yrot(40)
		difference() {
			cylinder(tkWall, r=5);
			translate([EPS, -5.5, -1])
			cube([6, 11, tkWall+2]);
		}
	}
}

module ptex(tex, size, depth) {
	intersection() {
		roof()
		text(tex, size=size, halign="center");
		limit = size*len(tex)*5;
		cube([limit, limit, depth], anchor=BOTTOM);
	}
}

module box() {
	render()
	color("red") {
		difference() {
			cuboid(size=dOut, rounding=rOuter, edges="Z", anchor=BOTTOM);
			up(tkWall) cuboid(size=inner_dimensions+[0,0,EPS], rounding=rInner, edges="Z", anchor=BOTTOM);
		}

		translate([dInt.x/2-EPS, 0, dOut.z-5])
		rotate([90,0,-90])
		ptex("Tork Inner Prizes", size=4, .7);
		translate([EPS-dInt.x/2, 0, dOut.z-5])
		rotate([90,0,90])
		ptex("tylertork.com/ag", size=4, .7);
		
		if (holder_type == 1) {
			translate([0,3-dGlass.y/2,0])
			pole();
		} else if (holder_type == 2) {
			back(dGlass.y/2) hook();
		} else if (holder_type == 3) {
			cardHolder();
		} else {
			for(a = [0,180]) {
				zrot(a)
				for(d=[1,-1])
					translate([-dInt.x/3,d*dInt.y/6, 0])
					clip();
			}
		}
	}
}

module lid() {
	offsInner = TOL2;
	offsOuter = tk2Wall+TOL2;
	dLid = [dOut.x+offsOuter, dOut.y+offsOuter, tkWall+lid_overlap];
	color("red") {
		render()
		difference() {
			cuboid(
				size=dLid,
				rounding=rOuter+offsOuter/2,
				edges="Z", anchor=BOTTOM);
			
			down(EPS)
			cuboid(
				size=[dOut.x+offsInner, dOut.y+offsInner, EPS+lid_overlap],
				rounding=rOuter+offsInner,
				edges="Z", anchor=BOTTOM);
				
			cube([dGlass.x-2*glass_overlap, dGlass.y-2*glass_overlap, tkWall+lid_overlap+1], anchor=BOTTOM);
		}
		dFrame = dGlass+[TOL+2, TOL+2, TOL];

		up(lid_overlap-dFrame.z)
		linear_extrude(dFrame.z+EPS)
		difference() {
			square(dFrame, center=true);
			square(dFrame+[1,-21], center=true);
			square(dFrame+[-21,1], center=true);
			square(dFrame-[2,2], center=true);
		}
	}
	

//	up(lid_overlap+EPS)
//	difference() {
//		cube(dFrame, anchor=TOP);
//		up(.5) cube(dFrame+[-2,-2,1], anchor=TOP);
//	}
	offsText = dLid.y/2 - (dLid.y-dGlass.y+2)/4 -1.5;
	color("white")
	up(dLid.z)
	linear_extrude(text_emboss) {
		translate([0,offsText, 0])
		text(text1, size=text_size, font=text_font, halign="center", valign="center");
		translate([0,-offsText, 0])
		text(text2, size=text_size, font=text_font, halign="center", valign="center");
	}
}

module glass_holder() {
	difference() {
//		cuboid(
	}
}

module main() {
	union() {
		box();
		if (assembled && $preview) {
			up(.01+dOut.z-lid_overlap) lid();
		} else {
			right(dOut.x+tkWall+10) lid();
		}
	}
}

if (debug) {
	cardHolder();
} else if (section) {
	render()
	difference() {
		main();
		cube(dOut+[5,5,5]);
	}
} else {
	main();
}