Code cleaning + add ears to the bottle clip! #22
1 changed files with 362 additions and 19 deletions
Add the ear generation in this file.
commit
8d0fae7652
|
|
@ -12,13 +12,6 @@
|
|||
* https://www.thingiverse.com/thing:5029374
|
||||
* printed at scale 0.2 as glue-ins for additional ears.
|
||||
*
|
||||
* `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
|
||||
|
|
@ -73,11 +66,6 @@ $fn = 360;
|
|||
* font: the path to a font for Write.scad.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
scale([0.2, 0.2, 0.2]) {
|
||||
render_bottle_clip(
|
||||
name=NAME,
|
||||
|
|
@ -248,11 +236,366 @@ module outer_cutoff(rl, e, ru, ht, width) {
|
|||
}
|
||||
}
|
||||
|
||||
module ear() {
|
||||
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");
|
||||
/**
|
||||
* 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 length of one side of the ear base triangle
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
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) {
|
||||
|
||||
// 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 hypothenus, 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(
|
||||
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(
|
||||
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 shape.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* depth: the depth of the ear
|
||||
* thickness: the thickness of the ear arcs
|
||||
* side_len: the length of one side of the ear base triangle
|
||||
* 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 an 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 ;
|
||||
|
||||
echo("Generating ONE single 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
|
||||
);
|
||||
|
||||
$A=[0, side_len/2];
|
||||
$B=[0,-side_len/2];
|
||||
$C=[-(side_len/2/sin(120))*1.5*stretch_factor, 0];
|
||||
$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=-$C.x;
|
||||
$alpha=asin($hc/$b);
|
||||
$beta=$alpha;
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue