diff --git a/.gitmodules b/.gitmodules index 95b403e..0180858 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "write"] - path = write - url = https://github.com/rohieb/Write.scad -[submodule "thing-logos"] - path = thing-logos - url = https://github.com/rohieb/thing-logos.git +[submodule "write"] + path = write + url = https://github.com/rohieb/Write.scad diff --git a/c3cat-bottle-clip/c3cat-bottle-clip.scad b/c3cat-bottle-clip/c3cat-bottle-clip.scad index 95f6176..19a51e7 100644 --- a/c3cat-bottle-clip/c3cat-bottle-clip.scad +++ b/c3cat-bottle-clip/c3cat-bottle-clip.scad @@ -8,14 +8,17 @@ * * This file was modified again by djerun to use the catars printed * by c3cat: https://www.printables.com/model/35076-cat-ears - * as the logo and optionally allow use the ears from + * as the logo and optionally allow use the easrs from * https://www.thingiverse.com/thing:5029374 * printed at scale 0.2 as glue-ins for additional ears. * - * This file has also being modified and reformatted by Ajabep to: - * - be easier to understand - * - be easier to modify and extend - * - be easier to use and build + * `Ohren_4.stl` and `catears.stl` need to be placed in `../stls/` + * for the symlinks to work otherwise `catears.stl` needs to be placed + * at `./catears.stl` and `Ohren_4.stl` at `./catear.stl`. + * + * Version of the modification: 1.0 + * + * See examples.scad for examples on how to use this module. * * The contents of this file are licenced under CC-BY-SA 3.0 Unported. * See https://creativecommons.org/licenses/by-sa/3.0/deed for the @@ -25,57 +28,14 @@ include use - -// The name that is printed on your name tag. -NAME = "c3cat"; -// The logo that is printed on your name tag. Has to be a DXF file. You can use the thing-logo repository for inspiration. -LOGO_FILE = ""; // empty string is catear model -// The font to be used for the name tag. See Write.scad for details. -FONT = ""; // empty string is for Orbitron font - -// Format of the bottle clip you want to create. -FORMAT = 0; // [0=Club Mate 50cL, 1=Long Neck as 25cL Club Mate or Fritz-kola, 2=Euroform 2, 3=Steinie bottles, 4=Monster can] - -// Style of the ears to add... or not add. This parameter can add a LOT of calculation time. -EARS_STYLE = 0; // [0=No ears, 1=Just arcs, 2=Filled ears with the same thickness, 3=Filled ears with the a thinner thickness inside, 4=Filled ears with the same thickness but shifted] - -/* [Ear Parameters] */ - -// Space between both ears. -SPACE_BETWEEN_EARS = 13; // .1 - -// The X orientation of the ears, to give a more organic look. Angle in degree -EAR_TILT = 15; // .1 - -// The depth of the ear -EAR_DEPTH = 2; // .1 - -// The thickness of the ear arcs -EAR_THICKNESS = 1; // .1 - -// The width of the ear -EAR_SIDE_LEN = 6; - -// How much the ear is bent. 1 = half circle, 0.00001 = almost straight -EAR_BEND_FACTOR = 0.5; // [.01:.01:1] - -// How much the ear is stretched, useful for fox ears or this kind of shapes -EAR_STRETCH_FACTOR = 1.2; - - -/* [Render] */ -// Whether to render the clip, the body. -RENDER_COLOR_CLIP = true; -// Whether to render the text part. -RENDER_COLOR_TEXT = true; -// Whether to render the logo part. -RENDER_COLOR_LOGO = true; -// Whether to render the cat ears part. -RENDER_COLOR_EARS = true; - -// Set the number of facets for circles. $fn = 360; +NAME = "c3cat"; +LOGO_FILE = ""; // empty string is catear model +RENDER_COLOR_ONE = true; +RENDER_COLOR_TWO = true; +RENDER_COLOR_THREE = true; +USE_TINY_EARS = true; /** * Creates one instance of a bottle clip name tag. The default values are @@ -88,710 +48,172 @@ $fn = 360; * rl: the radius on the lower side of the clip * ht: the height of the clip * width: the thickness of the wall. Values near 2.5 usually result in a good - * clippiness for PLA prints. + * clippiness for PLA prints. * name: the name that is printed on your name tag. For the default ru/rt/ht - * values, this string should not exceed 18 characters to fit on the name tag. + * values, this string should not exceed 18 characters to fit on the name tag. * font: the path to a font for Write.scad. */ -scale([0.2, 0.2, 0.2]) { - render_bottle_clip( - name=NAME, - font=FONT, - logo=LOGO_FILE, - format=FORMAT, - ears_style=EARS_STYLE); -} - /** - * Render a bottle clip with a name, logo and ears (depending the `ears_style` argument) for a bottle given as `format`. - * - * Parameters: - * name: The name to write on the clip - * font: The font file to use - * logo: The logo file to print on the clip - * - * format: id of the bottle clip format - * 0: Club Mate 50cL - * 1: Long Neck as 25cL Club Mate or Fritz-kola - * 2: Euroform 2 - * 3: Steinie bottles (with logo and name) - * - * ear_style: id of the ear style we want: - * -1 or less: Should NEVER being used. Unknown behavior. - * 0: No ears, just a bottle clip with a name and a logo. - * 1: Just arcs. - * 2: Filled ears with the same thickness - * 3: Filled ears with the a thinner thickness inside - * 4: Filled ears with the same thickness but shifted - * - * By default, thus function will generate a clip for a 50cL Club-Mate Bottle, with a headband with cat ears as a logo, and with a cat ears of the clip formed by 2 arcs. + * currently openscad fails to render the original `Ohren_4.stl` outside of the preview mode + * according to [the wiki](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/FAQ#Why_is_my_imported_STL_file_appearing_with_F5_but_not_F6?) this is the stls fault + * using meshlab to run `Filters` -> `Cleaning and Repairing` -> `Remove T-Vertices` by `Edge-Flip` with `Ratio` of `1000000` before importing the stl works but but two errors remain. */ -module render_bottle_clip(name="", font="", logo="", format=0, ears_style=1) { - name = name == "" ? "c3cat" : name ; - font = font == "" ? "write/orbitron.dxf" : font ; - - if (format < 0 || format > 4) { - assert(false, str("Unknown format ", format, ".")); +scale([0.2, 0.2, 0.2]) { + difference() { + scale([5, 5, 5]) rotate(45, [0, 0, 1]) bottle_clip(name=NAME); + translate([ 15*5, 0*5, 18*5]) rotate(80, [0, 1, 0]) catear(); + translate([-15*5, 0*5, 18*5]) rotate(-80, [0, 1, 0]) catear(); } - - // Format == 0: Club-Mate 0.5L bottle - // Format == 1: Long Neck bottle (like fritz-kola) 0.25L - // Format == 2: Euroform 2 bottle - // Format == 3: Steinie bottle - // Format == 4: Monster Can - ru = format == 4 ? 26 : 13; - rl = format == 4 ? 32 : format == 1 ? 15 : format == 2 ? 22.5 : 17.5 ; - ht = format == 4 ? 10 : format == 3 ? 13 : 26 ; - width = 2.5; - - - scale([5, 5, 5]) { - difference() { - bottle_clip( - name=NAME, - font=FONT, - logo=LOGO_FILE, - ru=ru, - rl=rl, - ht=ht, - width=width, - format=format); - - // Render ears if requested - if (ears_style > 0) { - ears( - ht=ht, - ru=ru, - rl=rl, - clip_width=width, - space_between_ears=SPACE_BETWEEN_EARS, - ear_tilt=EAR_TILT, - ear_depth=EAR_DEPTH, - ear_thickness=EAR_THICKNESS, - ear_side_len=EAR_SIDE_LEN, - ear_bend_factor=EAR_BEND_FACTOR, - ear_stretch_factor=EAR_STRETCH_FACTOR, - ears_style=ears_style - ); - } - } - - // Render ears if requested - if (ears_style > 0 && RENDER_COLOR_EARS) { - ears( - ht=ht, - ru=ru, - rl=rl, - clip_width=width, - space_between_ears=SPACE_BETWEEN_EARS, - ear_tilt=EAR_TILT, - ear_depth=EAR_DEPTH, - ear_thickness=EAR_THICKNESS, - ear_side_len=EAR_SIDE_LEN, - ear_bend_factor=EAR_BEND_FACTOR, - ear_stretch_factor=EAR_STRETCH_FACTOR, - ears_style=ears_style - ); - } + if (RENDER_COLOR_TWO) { + color("orange") + translate([ 15*5, 0*5, 18*5]) + rotate(80, [0, 1, 0]) + catear(); + } + if (RENDER_COLOR_THREE) { + color("yellow") + translate([-15*5, 0*5, 18*5]) + rotate(-80, [0, 1, 0]) + catear(); } } -module name(name, font, rl, ht, ru, format) { +module name(name, font, rl, ht, ru) { writecylinder( text=name, - where=[0, 0, 0], + where=[0,0,0], radius=rl+0.5, - height=format == 4 ? ht : ht/13*7, - h=format == 4 ? ht/13*7 : ht/13*4, + height=ht/13*7, + h=ht/13*4, t=max(rl,ru), font=font); } -module logo(logo, rl, ht, ru, width, format) { - echo(logo=logo); +module logo(logo, rl, ht, ru, width) { + echo("logo: ", logo); if(logo == "") { - // No logo file specified? Let's print a catear headband instead! ear_size=ht; - echo(ht=ht); - echo(ru=ru); - echo(rl=rl); - echo(width=width); - translate([0, -max(ru,rl), format == 4 ? ht/2 : ht*3/4+.5]) - rotate([90, 0, 0]) - scale([format == 4 ? ht/50 : ht/100, format == 4 ? ht/50 : ht/100, 1]) - translate([0, format == 4 ? 0 : -ht/2, 0]) - rotate(-90, [0, 0, 1]) - catear_headband( - size=ear_size, - height=max(ru, rl), - thickness=width, - stretch_len=0, - tip_len=0, - details=false, - with_rake=false - ); + echo("ht: ", ht); + echo("ru: ", ru); + echo("rl: ", rl); + echo("width: ", width); + translate([0,-max(ru,rl),ht*3/4+.5]) + rotate([90,0,0]) + scale([1,1,1]) + scale([ht/100,ht/100,1]) + translate([0, -ht/2,0]) + rotate(-90, [0, 0, 1]) + catear_headband( + size=ear_size, + height=max(ru,rl), + thickness=width, + stretch_len=0, + tip_len=0, + details=false, + with_rake=false + ); } else { - translate([0, 0, ht*3/4-0.1]) - rotate([90, 0, 0]) - scale([0.8, 0.8, 1]) - scale([ht/100, ht/100, 1]) - translate([-18, -22, 0.5]) - linear_extrude(height=max(ru, rl)*2) - import(logo); + // The logo has been split in 3 parts. // well was... TODO +/* + rotate([0,0,-48]) translate([0,0,ht*3/4-0.1]) + rotate([90,0,0]) + scale([0.9,0.9,1]) + scale([ht/100,ht/100,1]) + translate([-25,-29,0.5]) + linear_extrude(height=max(ru,rl)*2) + import("logo_1.dxf"); +*/ + translate([0,0,ht*3/4-0.1]) + rotate([90,0,0]) + scale([0.8,0.8,1]) + scale([ht/100,ht/100,1]) + translate([-18,-22,0.5]) + linear_extrude(height=max(ru,rl)*2) + import(logo); +/* + rotate([0,0,44]) translate([0,0,ht*3/4-0.1]) + rotate([90,0,0]) + scale([0.7,0.7,1]) + scale([ht/100,ht/100,1]) + translate([-25,-26,0.5]) + linear_extrude(height=max(ru,rl)*2) + import("logo_3.dxf"); +*/ } } -/** - * Creates a Bootle Clip with logo and/or text, depending what is asked using the RENDER_COLOR_* variables. - * - * Parameters: - * - * Size: - * ht: the height of the bottle clip - * ru: the radius on the upper side of the clip - * rl: the radius on the lower side of the clip - * width: the thickness of the bottle clip - * - * name: The name to write on the clip - * font: The font file to use - * logo: The logo file to print on the clip - * - * By default, will create a Club-Mate 0.5L bottle clip. - * - * An empty logo file will create a headband with cat ears as a logo. - */ -module bottle_clip(ru=13, rl=17.5, ht=26, width=2.5, name="c3cat", font="write/orbitron.dxf", logo="", format=0) { - e = 100; // should be big enough, used for the outer boundary of the text/logo - - // main cylinder - if (RENDER_COLOR_CLIP) { - color("#006168") difference() { - cylinder(r1=rl+width, r2=ru+width, h=ht); - difference() { - union() { - if (name != "" || format != 4) { - name(name=name, font=font, rl=rl, ht=ht, ru=ru, format=format); - } - if (name == "" || format != 4) { - logo(logo=logo, rl=rl, ht=ht, ru=ru, width=width, format=format); +module bottle_clip(ru=13, rl=17.5, ht=26, width=2.5, name="c3cat", font="write/orbitron.dxf", logo="") { + e=100; // should be big enough, used for the outer boundary of the text/logo + rotate([0,0,-45]) { + // main cylinder + if (RENDER_COLOR_ONE) { + color("black") difference() { + cylinder(r1=rl+width, r2=ru+width, h=ht); + difference() { + union() { + name(name=name, font=font, rl=rl, ht=ht, ru=ru); + logo(logo=logo, rl=rl, ht=ht, ru=ru, width=width); } + cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); } - cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); + translate([0,0,-1]) + cylinder(r1=rl, r2=ru, h=ht+2); + // finally, substract a cube as a gap so we can clip it to the bottle + rotate([0, 0, 45]) + translate([0,0,-1]) + cube([50,50,50]); } - - clear_anti_aliasing = 0.01; // The margin to avoid empty surfaces in the preview. - translate([0, 0, -clear_anti_aliasing/2]) - cylinder(r1=rl, r2=ru, h=ht+clear_anti_aliasing); - // finally, subtract a cube as a gap so we can clip it to the bottle - rotate([0, 0, 45]) - translate([0, 0, -1]) - cube([rl+ru, rl+ru, 2*ht]); } - } - // text - if (RENDER_COLOR_TEXT && (name != "" || format != 4)) { - color("orange") difference() { - name(name=name, font=font, rl=rl, ht=ht, ru=ru, format=format); - cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); - outer_cutoff(rl, e, ru, ht, width); + // text + if (RENDER_COLOR_TWO) { + color("orange") difference() { + name(name=name, font=font, rl=rl, ht=ht, ru=ru); + cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); + outer_cutoff(rl, e, ru, ht, width); + } } - } - // logo - if (RENDER_COLOR_LOGO && (name == "" || format != 4)) { - color("yellow") difference() { - logo(logo=logo, rl=rl, ht=ht, ru=ru, width=2*width, format=format); - cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); - outer_cutoff(rl, e, ru, ht, width); + // logo + if (RENDER_COLOR_THREE) { + color("yellow") difference() { + logo(logo=logo, rl=rl, ht=ht, ru=ru, width=2*width); + cylinder(r1=rl+width/2, r2=ru+width/2, h=ht); + outer_cutoff(rl, e, ru, ht, width); + } } } } module outer_cutoff(rl, e, ru, ht, width) { - // outer cylinder which is subtracted, so the text and the logo end + // outer cylinder which is substracted, so the text and the logo end // somewhere on the outside ;-) difference () { cylinder(r1=rl+e, r2=ru+e, h=ht); - translate([0, 0, -1]) + translate([0,0,-1]) // Note: bottom edges of characters are hard to print when character // depth is > 0.7 cylinder(r1=rl+width+0.7, r2=ru+width+0.7, h=ht+2); } } -/** - * Will create a pair of ears to the bottle clip. By default, they are cat ears. - * - * Parameters: - * - * Positioning: - * ht: the height of the bottle clip, used to scale the ears - * ru: the radius on the upper side of the clip, used to position the ears - * rl: the radius on the lower side of the clip, used to position the ears - * clip_width: the thickness of the bottle clip - * - * Ears: - * space_between_ears: Space between both ears. - * ear_tilt: The X orientation of the ears, to give a more organic look. Angle in degree - * - * ear_depth: the depth of the ear - * ear_thickness: the thickness of the ear arcs - * ear_side_len: the width of the ear - * ear_bend_factor: how much the ear is bent. 1 = half circle, 0.00001 = almost straight - * ear_stretch_factor: how much the ear is stretched, useful for fox ears or this kind of shapes - * - * ear_chamfer: size of the chamfer to apply to the edges - * ear_chamfer_shape: The shape of the chamfer: "cone", "curve", "curve-in", "pyramid", maybe some others - * ear_details: whether to chamfer also the partial arcs - * - * ear_style: id of the ear style we want: - * 0 or less: Should NEVER being used. Unknown behavior. - * 1: Just arcs. - * 2: Filled ears with the same thickness - * 3: Filled ears with the a thinner thickness inside - * 4: Filled ears with the same thickness but shifted - */ -module ears(ht, ru, rl, clip_width, space_between_ears = 15, ear_tilt = 15, ear_depth=2, ear_thickness=.6, ear_side_len=6, ear_bend_factor=0.5, ear_stretch_factor=1.2, ear_chamfer=1, ear_chamfer_shape="curve", ear_details=true, ears_style=1) { - - // This is the radius on which the ears has to be to be centered on the clip. - radius = ru+(clip_width/2); - - - // Math time! - - // The ears are not that bad without this calculation, but I want to improve the base and the join between ears and the clip. - // Actually, by tilting the ear, a side of the end will go deeper withing the clip, but the other side may be separated from the clip. - // So we need to translate the ears more deeper within the clip to avoid any separation - // - // So! Trigonometry! - // - // Viewed from the right of the ear, an ear is like that: - // - // A - // |\ - // | \ - // h | \ s - // | \ - // +----\ D - // C l \ - // \ - // \ - // \ - // B - // - // A is the side of the ear which is going upper - // B is the side of the ear which is going deeper - // C is the clip level - // D is the midpoint between A and B - // s is the depth of the ear (from A to B!) - // h is the heigh we are searching for. We will lower the ear of this size. - // l is the half of length of the fingerprint of the ear in the clip. - // ADC is the tilt angle - // ACD is a 90 degree angle - // - // So, to find the h length, we can use s and the angle ADC. - // - // CAH => We don't have the adjacent length. So, we can't use this formula - // SOH => sin(ADC) = h / (s/2) - // TOA => We don't have the adjacent length. So, we can't use this formula - // - // sin(ADC) = h / (s/2) - // sin(ADC) * (s/2) = h - // - // BUT! Since we will raise the Clip level C to the end of the ear A, the print of the ear within the clip will be shifted of `l`! - // So, let's calculate it! - // - // - // CAH => cos(ADC) = l / (s/2) - // SOH => Is not targeting what we want. - // TOA => The opposed side is less precise than the hypotenuse, so, we will not use this formula - // - // cos(ADC) = l / (s/2) - // cos(ADC) * (s/2) = l - - tilt_compensation = sin(ear_tilt) * (ear_depth/2); - tilt_shift = cos(ear_tilt) * (ear_depth/2); - - // Pythagoras! - // Viewed from the top, an ear is like that: - // - // A s - // +----- E - // | / - // x | / r - // | / - // |/ - // c - // - // c is the center of the circle forming the top surface of the clip - // E is the perfect position of the ear - // r is the radius, calculated previously - // s is the half of the space between ears - // x is the position of the ears on the Y axis. It's what we want to calculate - // A is the projection of the ears on the Y axis - // A is a 90 degrees angle - // - // x**2 + s**2 = r**2 - // x**2 = r**2 - s**2 - // x = sqrt( r**2 - s**2 ) - s = space_between_ears / 2; - pos_ears_yaxis = sqrt(pow(radius, 2) - pow(s, 2)); - - // Trigonometry! - // Now, lets, rotate the ears to be at tangent to the clip - // - // From the top, an ear is like this: - // - // A s - // +------- E - // | / - // | / - // x | / r - // | / - // | / - // | / - // |/ - // C - // - // E is the position of the ears - // C is the center of the clip - // A is the projection of the ears on the Y axis - // r is the radius - // s is the half of the space between the ears. - // x is the same from the last figure. - // A is a 90 degrees angle - // - // The angle of the ear is the same as the angle ACE. - // So, we need to calculate this angle - // - // Since, we already know every lengths s, r and x, we can choose the formula we want! - // IDK which one is faster, but that could be a nice optimization. - // - // CAH => cos(ACE) = x/r - // SOH => sin(ACE) = s/r - // TOA => tan(ACE) = x/s - // - // Let's choose the sine, since it's linked to the our best raw non-rounded values. It will give us values with the best accuracy. - ears_angle = asin(s/radius); - - // Like that, it's good enough. And it could be committed like that. Actually, my first model (never published it) was like that. - // BUT we can do better and smarter! (and we will probably need to refine it) - - // If we stop our math here, we centered the middle of the ear on the clip. But the end of the ears are NOT centered. - // - // So, we will use (again) Pythagoras! - // We want to position the ear (on its center) to put the end of the ear in the radius. - // - // Form the top, an ear looks like that: - // e - // /| - // / | - // / | - // r / | h - // / | - // / | - // / | - // C /-------+ E - // p - // - // C is the center of the clip - // e is the end of the ear - // E is the middle of the ear. - // r is the Radius - // h is the half of the width of the ear - // E is a 90 degrees angles - // p is wanted length to position correctly the center of the ear. - // - // h**2 + p**2 = r**2 - // p**2 = r**2 - h**2 - // p = sqrt(r**2 - h**2) - - center_radius = sqrt( pow(radius, 2) - pow((ear_side_len+(tilt_shift))/2, 2) ); - - // So, we need to update the projection of the ears on the Y axis, based on center_radius, instead of radius. - pos_ears_yaxis_end_ear = sqrt(pow(center_radius, 2) - pow(s, 2)); - - translate([0, -pos_ears_yaxis_end_ear, ht-tilt_compensation-(ear_thickness/2)]) - rotate(90, [0, 0, 1]) - rotate(90, [0, 1, 0]) - union() { - scale([1, 1 ,1]) - translate([0, space_between_ears/2, 0]) - rotate(ears_angle, [1, 0, 0]) - rotate(-ear_tilt, [0, 1, 0]) - ear_with_style( - style=ears_style, - depth=ear_depth, - thickness=ear_thickness, - side_len=ear_side_len, - bend_factor=ear_bend_factor, - stretch_factor=ear_stretch_factor, - chamfer=ear_chamfer, - chamfer_shape=ear_chamfer_shape, - details=ear_details - ); - scale([1, -1, 1]) - translate([0, space_between_ears/2, 0]) - rotate(ears_angle, [1, 0, 0]) - rotate(-ear_tilt, [0, 1, 0]) - ear_with_style( - style=ears_style, - depth=ear_depth, - thickness=ear_thickness, - side_len=ear_side_len, - bend_factor=ear_bend_factor, - stretch_factor=ear_stretch_factor, - chamfer=ear_chamfer, - chamfer_shape=ear_chamfer_shape, - details=ear_details - ); - } -} - -/** - * Module that creates an ear given a style id. - * - * Parameters: - * - * style: id of the ear style we want: - * 0 or less: Should NEVER being used. Unknown behavior. - * 1: Just arcs. - * 2: Filled ears with the same thickness - * 3: Filled ears with the a thinner thickness inside - * 4: Filled ears with the same thickness but shifted - * - * depth: the depth of the ear - * thickness: the thickness of the ear arcs - * side_len: the width of the ear - * bend_factor: how much the ear is bent. 1 = half circle, 0.00001 = almost straight - * stretch_factor: how much the ear is stretched, useful for fox ears or this kind of shapes - * - * chamfer: size of the chamfer to apply to the edges - * chamfer_shape: The shape of the chamfer: "cone", "curve", "curve-in", "pyramid", maybe some others - * details: whether to chamfer also the partial arcs - * - * By default, this module creates a cat ear countour. - */ -module ear_with_style(style = 1, depth, thickness, side_len=30, bend_factor=0.5, stretch_factor=1.2, chamfer=1, chamfer_shape="curve", details=true) { - if (style == 1 || style == 2 || style == 3 || style == 4) { - // Style 1: Just arcs - // Style 2: Filled ears with the same thickness - // Style 3: Filled ears with the a thinner thickness inside - // Style 4: Filled ears with the same thickness but shifted - - ear( - depth=depth, - thickness=thickness, - side_len=side_len, - bend_factor=bend_factor, - stretch_factor=stretch_factor, - chamfer=chamfer, - chamfer_shape=chamfer_shape, - details=details - ); - } - - - if (style == 2 || style == 3 || style == 4) { - // Style 2: Filled ears with the same thickness - // Style 3: Filled ears with the a thinner thickness inside - // Style 4: Filled ears with the same thickness but shifted - - thickness_steps = thickness*0.5; - depth_steps = (depth-thickness)/((side_len / thickness_steps)); - - for (round_side_len = [side_len-thickness_steps:-thickness_steps:0]) { - // round_side_len = side_len - (thickness_steps * x) - // (thickness_steps * x) + round_side_len = side_len - // (thickness_steps * x) = side_len - round_side_len - // x = (side_len - round_side_len) / thickness_steps - x = (side_len - round_side_len) / thickness_steps; - round_shift = depth_steps * x; - current_depth = depth - (style == 3 ? round_shift : 0); - translation = style == 2 ? 0 : round_shift / 2; - - translate([0, 0, translation]) - color("green") - ear( - depth=current_depth, - thickness=thickness, - side_len=round_side_len, - bend_factor=bend_factor, - stretch_factor=stretch_factor, - chamfer=chamfer, - chamfer_shape=chamfer_shape, - details=true - ); +module catear() { + if (USE_TINY_EARS) { + rotate(-90, [0, 0, 1]) union() { + scale([1, 1 ,1]) translate([0, -85]) import("catear.stl"); + scale([1, -1, 1]) translate([0, -85]) import("catear.stl"); } } } /** - * Module that creates an ear shape. - * - * Parameters: - * - * depth: the depth of the ear - * thickness: the thickness of the ear arcs - * side_len: the width of the ear - * bend_factor: how much the ear is bent. 1 = half circle, 0.00001 = almost straight - * stretch_factor: how much the ear is stretched, useful for fox ears or this kind of shapes - * - * chamfer: size of the chamfer to apply to the edges - * chamfer_shape: The shape of the chamfer: "cone", "curve", "curve-in", "pyramid", maybe some others - * details: whether to chamfer also the partial arcs - * - * By default, this module creates a cat ear. - * - * I don't remember the original author of this module. I refactored it and improved it a bit. Documentation is from me. - */ -module ear(depth, thickness, side_len=30, bend_factor=0.5, stretch_factor=1.2, chamfer=1, chamfer_shape="curve", details=true) { - depth = depth == undef ? 20 : depth ; - thickness = thickness == undef ? 3 : thickness ; - - // $A and $B are the end of the ear - // $C is the higher end point. - $A=[0, side_len/2]; - $B=[0,-side_len/2]; - // From the front, an ear looks like: - // - // $C - // /|\ - // / | \ - // / | \ - // /---+---\ - // $B c $A - // - // c is the origin of the ear. - // $Bc$C and $Ac$C are 90deg angles. - // - // The length [$B $A] is `side_len` - // Thus, [$B c] == [c $A] == side_len/2 - // - // Since SOH, sin(angle) = Opposed / Hypotenuse - // sin(angle) = Opposed / Hypotenuse - // sin(angle) * Hypotenuse = Opposed - // Hypotenuse = Opposed / sin(angle) - // - // Thus, the `(side_len/2/sin(120))` implies that "The opposed side of the 120 angle is `(side_len/2)` length" and is the formula to know the size of the hypotenuse. - // Moreover, a 120deg angle in a right rectangle does not exists: the sum of all the angles of a triangle needs to be 180deg. I think the author tried, instead, to use the 60 as an angle, since the sinus is the same. - // - // The correct formula should be `((side_len/2)*tan(60))`: since $C$B$A should a 60deg angle to have an equilateral `$A$B$C` triangle, the product of the tangent ("TOA") of this angle and the adjacent segment [$B c] will give us the size of length of the opposed segment [$C c]. - // - // MOREOVER, the product of the magic number `1.5` with the divisor `sin(120)`... is actually the result of the `tan(60)`! - // - // The original formula was: - // $C=[-(side_len/2/sin(120))*1.5*stretch_factor, 0]; - $C=[-((side_len/2)*tan(60))*stretch_factor, 0]; - - // $a, $b and $c are the distance between the different points of the triangle. - $c=sqrt(pow($A.x-$B.x, 2)+pow($A.y-$B.y, 2)); - $b=sqrt(pow($A.x-$C.x, 2)+pow($A.y-$C.y, 2)); - $a=sqrt(pow($C.x-$B.x, 2)+pow($C.y-$B.y, 2)); - - // $hc is the height of $C. - $hc=-$C.x; - - // $alpha should be the angle of the $B$A$C. This should is 60deg if `stretch_factor` is `1`, but this angle change with this factor. - $alpha=asin($hc/$b); - $beta=$alpha; - // $gamma is the $A$C$B angle. - $gamma=180-$alpha-$beta; - $delta=180*bend_factor; - $bend_radius=$a/(2*cos(90-$delta/2)); - $bend_offset=$bend_radius*sin(90-$delta/2); - - translate([0, -$c/2, 0]) - rotate($beta, [0, 0, 1]) - translate([0, $a/2, 0]) - translate([$bend_offset, 0, 0]) - color("#00ffff") - chamfer(size=(details)?chamfer:0, child_h=depth, child_bot=-depth/2, shape=chamfer_shape) - partial_ring( - part=$delta/360, - radius=$bend_radius, - thickness=thickness, - height=depth - ); - translate([0, $c/2, 0]) - rotate(-$alpha, [0, 0, 1]) - translate([0, -$b/2, 0]) - translate([$bend_offset, 0, 0]) - color("#ff00ff") - chamfer(size=(details)?chamfer:0, child_h=depth, child_bot=-depth/2, shape=chamfer_shape) - partial_ring( - part=$delta/360, - radius=$bend_radius, - thickness=thickness, - height=depth - ); - translate($A) color("#aaaaaa") - chamfer(size=chamfer, child_h=depth, child_bot=-depth/2, shape=chamfer_shape) - cylinder(h=depth, d=thickness, center=true); - translate($B) color("#bbbbbb") - chamfer(size=chamfer, child_h=depth, child_bot=-depth/2, shape=chamfer_shape) - cylinder(h=depth, d=thickness, center=true); - translate($C) color("#cccccc") - chamfer(size=chamfer, child_h=depth, child_bot=-depth/2, shape=chamfer_shape) - cylinder(h=depth, d=thickness, center=true); + * Creates one instance of a bottle clip name tag suitable for 0.33l longneck + * bottles (like fritz cola, etc.). All parameters are passed to the module + * bottle_clip(), see there for their documentation. + */ +module bottle_clip_longneck(name="c3cat", width=2.5, font="write/orbitron.dxf") { + bottle_clip(name=name, ru=13, rl=15, ht=26, width=width, font=font, logo=""); } /** - * This module is not mine. - */ -module partial_ring(part, radius, thickness, height) { - rotate(180-180*part, [0, 0, 1]) - rotate_extrude(angle=360*part) - translate([radius, 0]) - square([thickness, height], center=true); -} - -/** - * This module is not mine. - */ -module chamfer(size=2, child_h=5, child_bot=0, shape="curve") { - chamfer_size=size; - - module chamfer_shape() { - if (shape == "cone") { - $fn=16; - cylinder(chamfer_size/2,chamfer_size/2,0); - } else if (shape == "curve") { - $fn=4; - for( y = [0:1/$fn:1]) { - cylinder(chamfer_size/2*(1-y),chamfer_size/2/cos(180/$fn)*y,0); - } - } else if (shape == "curve-in") { - $fn=16; - intersection() { - sphere(chamfer_size/2/cos(180/$fn)); - translate([0,0,chamfer_size/2]) - cube(chamfer_size, center=true); - } - } else if (shape == "pyramid") { - $fn=4; - cylinder(chamfer_size/2/cos(180/$fn),chamfer_size/2,0); - } - } - - module lower_chamfer() { - minkowski() - { - linear_extrude(0.0001) difference() { - square([1000,1000],center=true); - projection()children(0); - } - chamfer_shape(); - } - } - - module upper_chamfer() { - scale([1,1,-1])lower_chamfer()children(); - } - - render()difference() { - children(); - translate([0,0,child_bot])lower_chamfer()children(); - translate([0,0,child_bot+child_h])upper_chamfer()children(); - } -} + * The Steinie-Tag has been removed since it does not support logos. +**/ diff --git a/generate_bottle_tag.sh b/generate_bottle_tag.sh index 3c726dc..8ea378d 100755 --- a/generate_bottle_tag.sh +++ b/generate_bottle_tag.sh @@ -6,37 +6,28 @@ set -u VERSION=2.2 LOGO_FILE='""' +TINY_EARS=false FN=90 -EARS_STYLE=1 NAME="\"$1\"" -# usage: render NAME PART [BOTTLE_FORMAT] +# usage: render NAME PART render() { case "$2" in body) - CLIP=true - TEXT=false - LOGO=false - EARS=false + ONE=true + TWO=false + THREE=false ;; name) - CLIP=false - TEXT=true - LOGO=false - EARS=false + ONE=false + TWO=true + THREE=false ;; logo) - CLIP=false - TEXT=false - LOGO=true - EARS=false - ;; - ears) - CLIP=false - TEXT=false - LOGO=false - EARS=true + ONE=false + TWO=false + THREE=true ;; *) echo 'fatal: invalid part' >&2 @@ -44,34 +35,23 @@ render() { ;; esac - if [ $# -lt 3 ]; then - BOTTLE_FORMAT="0" - else - BOTTLE_FORMAT="$3" - fi - echo rendering "$1" "$2" openscad \ -D "\$fn=${FN}" \ - -D "EARS_STYLE=${EARS_STYLE}" \ + -D "USE_TINY_EARS=${TINY_EARS}" \ -D "LOGO_FILE=${LOGO_FILE}" \ -D "NAME=${NAME}" \ - -D "RENDER_COLOR_CLIP=${CLIP}" \ - -D "RENDER_COLOR_TEXT=${TEXT}" \ - -D "RENDER_COLOR_LOGO=${LOGO}" \ - -D "RENDER_COLOR_EARS=${EARS}" \ - -o "stls/c3cat-bottle-clip-v${VERSION}_BOTTLE${BOTTLE_FORMAT}_${NAME}_${PART}.stl" \ + -D "RENDER_COLOR_ONE=${ONE}" \ + -D "RENDER_COLOR_TWO=${TWO}" \ + -D "RENDER_COLOR_THREE=${THREE}" \ + -o "stls/c3cat-bottle-clip-v${VERSION}_${NAME}_${PART}.stl" \ c3cat-bottle-clip/c3cat-bottle-clip.scad } cd "$(dirname $0)" -for BOTTLE_FORMAT in 0 1 2 +for PART in body logo name do - echo "Generating bottle format ${BOTTLE_FORMAT}" - for PART in body logo name ears - do - render "$NAME" "$PART" "$BOTTLE_FORMAT" - sleep 1 - done + render "$NAME" "$PART" + sleep 1 done diff --git a/thing-logos b/thing-logos deleted file mode 160000 index 2ac5bec..0000000 --- a/thing-logos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2ac5bec02e5015918dff95b6c12ba890ef1ea95a