8 Commits

Author SHA1 Message Date
Bob
45a99ccc56 offset stems example 2020-09-05 22:52:33 -04:00
Bob
d9c9cf776f Merge pull request #60 from rsheldiii/polyRound-everything
Use polyRound for all skin shapes
2020-08-28 20:38:38 -04:00
Bob
3e76968a03 Use polyRound for all skin shapes
slightly faster it seems!
2020-08-28 10:10:30 -04:00
Bob
2b341af540 Merge pull request #58 from rsheldiii/iso-enter-tweak
Iso enter tweak
2020-08-23 23:30:52 -04:00
Bob
5d36c545a7 Use polyround to round ISO enter
exciting times, my friends
2020-08-23 18:26:11 -04:00
Bob
d4321abd40 tweak ISO_enter.scad
backporting some changes I made a while ago on the new key structure branch
2020-08-23 17:42:30 -04:00
Bob
7ee27737c8 Merge pull request #54 from rsheldiii/grid-updates
grid updates
2020-08-23 17:13:48 -04:00
Bob
5de61f8b04 grid updates 2020-07-09 01:02:27 -04:00
20 changed files with 847 additions and 144 deletions

View File

@@ -544,8 +544,8 @@ module hipro_row(row=3, column=0) {
module grid_row(row=3, column = 0) {
$bottom_key_width = 18.16;
$bottom_key_height = 18.16;
$width_difference = 0.2;
$height_difference = 0.2;
$width_difference = 1;
$height_difference = 1;
$top_tilt = 0;
$top_skew = 0;
$dish_type = "old spherical";
@@ -557,8 +557,8 @@ module grid_row(row=3, column = 0) {
$linear_extrude_shape = true;
$dish_overdraw_width = -8;
$dish_overdraw_height = -8;
$dish_overdraw_width = -6.5;
$dish_overdraw_height = -6.5;
$minkowski_radius = 0.5;
//also,
@@ -567,7 +567,7 @@ module grid_row(row=3, column = 0) {
$top_tilt_y = side_tilt(column);
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
$total_depth = 6 + abs((row-3) * 0.5) + extra_height;
$total_depth = 7 + abs((row-3) * 0.5) + extra_height;
if (row == 5 || row == 0) {
/* $top_tilt = -18.55; */
@@ -1950,15 +1950,10 @@ module cherry_stabilizer_stem(depth, slop, throw) {
}
}
thickness = .84;
inner_stem_size = [6,4];
outer_stem_size = inner_stem_size + [thickness, thickness];
module custom_stem(depth, slop, throw){
linear_extrude(height=depth) {
difference() {
square(outer_stem_size + [slop,slop], center = true);
square(inner_stem_size + [slop,slop], center = true);
}
square($alps_stem, center = true);
}
}

View File

@@ -1,3 +1,4 @@
// the point of this file is to be a sort of DSL for constructing keycaps.
// when you create a method chain you are just changing the parameters
// key.scad uses, it doesn't generate anything itself until the end. This
@@ -6,18 +7,35 @@
// special variables, but that's a limitation of SCAD we have to work around
include <./includes.scad>
include <src/libraries/round-anything/polyround.scad>
// example key
/* $stem_throw = 1; */
$stem_type = "custom";
/* $stem_type = "custom"; */
$outset_legends = true;
dcs_row(5) front_legend("j") key();
/* $hull_shape_type = "linear extrude"; */
/* dcs_row(5) iso_enter() front_legend("j") key(); */
$stabilizer_type = "cherry_stabilizer";
$stem_support_type = "disabled";
/* $stem_rotation=90; */
/* $skin_extrude_shape = true; */
dcs_row(1) spacebar() uh(1.5){
/* $top_tilt = -6; */
key();
}
/* $rounded_key = true; */
/* sa_row(1) key(); */
// example row
/* for (x = [0:1:4]) {
translate_u(0,-x) dcs_row(x) key();
} */
// example layout
/* preonic_default("dcs"); */
/* %side_rounded_square([10,10], 0.5); */
/* translate([00,0,0]) polygon(new_side_rounded_square([10,10], 0.5)); */

View File

@@ -1 +1,3 @@
SMALLEST_POSSIBLE = 1/128;
$fs = .1;
$unit = 19.05;

View File

@@ -59,3 +59,7 @@ function surface_function(x,y) = (sin(acos(x/$3d_surface_size)));
function surface_function(x,y) = (sin(acos(x/$3d_surface_size))) * sin(acos(y/$3d_surface_size));
// (statically) random!
/* function surface_function(x,y) = sin(rands(0,90,1,x+y)[0]); */
// adds uniform rounding radius for round-anything polyRound
function add_rounding(p, radius)=[for(i=[0:len(p)-1])[p[i].x,p[i].y, radius]];
// computes millimeter length from unit length
function unit_length(length) = unit * (length - 1) + 18.16;

View File

@@ -1,4 +1,5 @@
// files
include <constants.scad>
include <functions.scad>
include <shapes.scad>
include <stems.scad>
@@ -15,15 +16,10 @@ use <libraries/scad-utils/lists.scad>
use <libraries/scad-utils/shapes.scad>
use <libraries/skin.scad>
/* [Hidden] */
SMALLEST_POSSIBLE = 1/128;
$fs = .1;
$unit = 19.05;
// key shape including dish. used as the ouside and inside shape in hollow_key(). allows for itself to be shrunk in depth and width / height
module shape(thickness_difference, depth_difference=0){
dished(depth_difference, $inverted_dish) {
/* %shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0); */
color($primary_color) shape_hull(thickness_difference, depth_difference, $inverted_dish ? 2 : 0);
}
}
@@ -217,7 +213,7 @@ module front_placement() {
// just to DRY up the code
module _dish() {
color($secondary_color) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish);
translate([$dish_offset_x,0,0]) dish(top_total_key_width() + $dish_overdraw_width, top_total_key_height() + $dish_overdraw_height, $dish_depth, $inverted_dish);
}
module envelope(depth_difference=0) {
@@ -235,9 +231,9 @@ module dished_for_show() {
difference(){
union() {
envelope();
if ($inverted_dish) top_placement(0) _dish();
if ($inverted_dish) top_placement(0) color($secondary_color) _dish();
}
if (!$inverted_dish) top_placement(0) _dish();
if (!$inverted_dish) top_placement(0) color($secondary_color) _dish();
}
}
@@ -251,9 +247,10 @@ module dished(depth_difference = 0, inverted = false) {
difference(){
union() {
envelope(depth_difference);
if (inverted) top_placement(depth_difference) _dish();
if (inverted) top_placement(depth_difference) color($secondary_color) _dish();
}
if (!inverted) top_placement(depth_difference) _dish();
if (!inverted) top_placement(depth_difference) color($secondary_color) _dish();
/* %top_placement(depth_difference) _dish(); */
}
}
}
@@ -405,7 +402,7 @@ module key(inset = false) {
// both stem and support are optional
if ($stem_type != "disable" || ($stabilizers != [] && $stabilizer_type != "disable")) {
dished($keytop_thickness, $inverted_dish) {
translate([0, 0, $stem_inset]) {
translate([0, (unit_length($key_height) - unit_length(1))/2, $stem_inset]) {
if ($stabilizer_type != "disable") stems_for($stabilizers, $stabilizer_type);
if ($stem_type != "disable") stems_for($stem_positions, $stem_type);
@@ -415,7 +412,7 @@ module key(inset = false) {
if ($support_type != "disable"){
inside() {
translate([0, 0, $stem_inset]) {
translate([0, (unit_length($key_height) - unit_length(1))/2, $stem_inset]) {
if ($stabilizer_type != "disable") support_for($stabilizers, $stabilizer_type);
// always render stem support even if there isn't a stem.

View File

@@ -12,7 +12,7 @@ module dsa_row(row=3, column = 0) {
$dish_skew_y = 0;
$height_slices = 10;
$enable_side_sculpting = true;
$corner_radius = 0.25;
$corner_radius = 1;
$top_tilt_y = side_tilt(column);
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;

View File

@@ -1,8 +1,8 @@
module grid_row(row=3, column = 0) {
$bottom_key_width = 18.16;
$bottom_key_height = 18.16;
$width_difference = 0.2;
$height_difference = 0.2;
$width_difference = 1;
$height_difference = 1;
$top_tilt = 0;
$top_skew = 0;
$dish_type = "old spherical";
@@ -14,8 +14,8 @@ module grid_row(row=3, column = 0) {
$linear_extrude_shape = true;
$dish_overdraw_width = -8;
$dish_overdraw_height = -8;
$dish_overdraw_width = -6.5;
$dish_overdraw_height = -6.5;
$minkowski_radius = 0.5;
//also,
@@ -24,7 +24,7 @@ module grid_row(row=3, column = 0) {
$top_tilt_y = side_tilt(column);
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;
$total_depth = 6 + abs((row-3) * 0.5) + extra_height;
$total_depth = 7 + abs((row-3) * 0.5) + extra_height;
if (row == 5 || row == 0) {
/* $top_tilt = -18.55; */

View File

@@ -13,9 +13,7 @@ module hipro_row(row=3, column=0) {
$dish_skew_y = 0;
$top_skew = 0;
$height_slices = 10;
// might wanna change this if you don't minkowski
// do you even minkowski bro
$corner_radius = 0.25;
$corner_radius = 1;
$top_tilt_y = side_tilt(column);
extra_height = $double_sculpted ? extra_side_tilt_height(column) : 0;

View File

@@ -10,9 +10,7 @@ module sa_row(n=3, column=0) {
$dish_skew_y = 0;
$top_skew = 0;
$height_slices = 10;
// might wanna change this if you don't minkowski
// do you even minkowski bro
$corner_radius = 0.25;
$corner_radius = 1;
// this is _incredibly_ intensive
/* $rounded_key = true; */

View File

@@ -44,6 +44,12 @@ module rotated() {
children();
}
module vertically_stabilized(mm=12, vertical=true, type=undef) {
stabilized(mm,vertical,type) {
children();
}
}
module stabilized(mm=12, vertical = false, type=undef) {
if (vertical) {
$stabilizer_type = (type ? type : ($stabilizer_type ? $stabilizer_type : "costar_stabilizer"));

View File

@@ -1,3 +1,5 @@
include <functions.scad>
module spacebar() {
$inverted_dish = true;
$dish_type = "sideways cylindrical";
@@ -43,13 +45,15 @@ module iso_enter() {
$key_length = 1.5;
$key_height = 2;
$top_tilt = 0;
$dish_offset_x = -(unit_length(1.5) - unit_length(1.25))/2;
/* $top_tilt = 0; */
$stem_support_type = "disable";
$key_shape_type = "iso_enter";
/* $linear_extrude_shape = true; */
$linear_extrude_height_adjustment = 19.05 * 0.5;
// this equals (unit_length(1.5) - unit_length(1.25)) / 2
$dish_overdraw_width = 2.38125;
/* $dish_overdraw_width = 2.38125; */
stabilized(vertical=true) {

View File

@@ -0,0 +1,687 @@
// Library: round-anything
// Version: 1.0
// Author: IrevDev
// Contributors: TLC123
// Copyright: 2020
// License: MIT
function addZcoord(points,displacement)=[for(i=[0:len(points)-1])[points[i].x,points[i].y, displacement]];
function translate3Dcoords(points,tran=[0,0,0],mult=[1,1,1])=[for(i=[0:len(points)-1])[
(points[i].x*mult.x)+tran.x,
(points[i].y*mult.y)+tran.y,
(points[i].z*mult.z)+tran.z
]];
function offsetPolygonPoints(points, offset=0)=
// Work sthe same as the offset does, except for the fact that instead of a 2d shape
// It works directly on polygon points
// It returns the same number of points just offset into or, away from the original shape.
// points= a series of x,y points[[x1,y1],[x2,y2],...]
// offset= amount to offset by, negative numbers go inwards into the shape, positive numbers go out
// return= a series of x,y points[[x1,y1],[x2,y2],...]
let(
isCWorCCW=sign(offset)*CWorCCW(points)*-1,
lp=len(points)
)
[for(i=[0:lp-1]) parallelFollow([
points[listWrap(i-1,lp)],
points[i],
points[listWrap(i+1,lp)],
],thick=offset,mode=isCWorCCW)];
function makeCurvedPartOfPolyHedron(radiiPoints,r,fn,minR=0.01)=
// this is a private function that I'm not expecting library users to use directly
// radiiPoints= serise of x, y, r points
// r= radius of curve that will be put on the end of the extrusion
// fn= amount of subdivisions
// minR= if one of the points in radiiPoints is less than r, it's likely to converge and form a sharp edge,
// the min radius on these converged edges can be controled with minR, though because of legacy reasons it can't be 0, but can be a very small number.
// return= array of [polyhedronPoints, Polyhedronfaces, theLength of a singe layer in the curve]
let(
lp=len(radiiPoints),
radii=[for(i=[0:lp-1])radiiPoints[i].z],
isCWorCCWOverall=CWorCCW(radiiPoints),
dir=sign(r),
absR=abs(r),
fractionOffLp=1-1/fn,
allPoints=[for(fraction=[0:1/fn:1])
let(
iterationOffset=dir*sqrt(sq(absR)-sq(fraction*absR))-dir*absR,
theOffsetPoints=offsetPolygonPoints(radiiPoints,iterationOffset),
polyRoundOffsetPoints=[for(i=[0:lp-1])
let(
pointsAboutCurrent=[
theOffsetPoints[listWrap(i-1,lp)],
theOffsetPoints[i],
theOffsetPoints[listWrap(i+1,lp)]
],
isCWorCCWLocal=CWorCCW(pointsAboutCurrent),
isInternalRadius=(isCWorCCWLocal*isCWorCCWOverall)==-1,
// the radius names are only true for positive r,
// when are r is negative increasingRadius is actually decreasing and vice-vs
// increasingRadiusWithPositiveR is just to verbose of a variable name for my liking
increasingRadius=max(radii[i]-iterationOffset, minR),
decreasingRadius=max(radii[i]+iterationOffset, minR)
)
[theOffsetPoints[i].x, theOffsetPoints[i].y, isInternalRadius? increasingRadius: decreasingRadius]
],
pointsForThisLayer=polyRound(polyRoundOffsetPoints,fn)
)
addZcoord(pointsForThisLayer,fraction*absR)
],
polyhedronPoints=flatternArray(allPoints),
allLp=len(allPoints),
layerLength=len(allPoints[0]),
loopToSecondLastLayer=allLp-2,
sideFaces=[for(layerIndex=[0:loopToSecondLastLayer])let(
currentLayeroffset=layerIndex*layerLength,
nextLayeroffset=(layerIndex+1)*layerLength,
layerFaces=[for(subLayerIndex=[0:layerLength-1])
[
currentLayeroffset+subLayerIndex, currentLayeroffset + listWrap(subLayerIndex+1,layerLength), nextLayeroffset+listWrap(subLayerIndex+1,layerLength), nextLayeroffset+subLayerIndex]
]
)layerFaces],
polyhedronFaces=flatternArray(sideFaces)
)
[polyhedronPoints, polyhedronFaces, layerLength];
function flatternRecursion(array, init=[], currentIndex)=
// this is a private function, init and currentIndex are for the function's use
// only for when it's calling itself, which is why there is a simplified version flatternArray that just calls this one
// array= array to flattern by one level of nesting
// init= the array used to cancat with the next call, only for when the function calls itself
// currentIndex= so the function can keep track of how far it's progressed through the array, only for when it's calling itself
// returns= flatterned array, by one level of nesting
let(
shouldKickOffRecursion=currentIndex==undef?1:0,
isLastIndex=currentIndex+1==len(array)?1:0,
flatArray=shouldKickOffRecursion?flatternRecursion(array,[],0):
isLastIndex?concat(init,array[currentIndex]):
flatternRecursion(array,concat(init,array[currentIndex]),currentIndex+1)
)
flatArray;
function flatternArray(array)=
// public version of flatternRecursion, has simplified params to avoid confusion
// array= array to be flatterned
// return= array that been flatterend by one level of nesting
flatternRecursion(array);
function offsetAllFacesBy(array,offset)=[
// polyhedron faces are simply a list of indices to points, if your concat points together than you probably need to offset
// your faces array to points to the right place in the new list
// array= array of point indicies
// offset= number to offset all indecies by
// return= array of point indices (i.e. faces) with offset applied
for(faceIndex=[0:len(array)-1])[
for(pointIndex=[0:len(array[faceIndex])-1])array[faceIndex][pointIndex]+offset
]
];
function extrudePolygonWithRadius(radiiPoints,h=5,r1=1,r2=1,fn=4)=
// this basically calls makeCurvedPartOfPolyHedron twice to get the curved section of the final polyhedron
// and then goes about assmbling them, as the side faces and the top and bottom face caps are missing
// radiiPoints= series of [x,y,r] points,
// h= height of the extrude (total including radius sections)
// r1,r2= define the radius at the top and bottom of the extrud respectively, negative number flange out the extrude
// fn= number of subdivisions
// returns= [polyhedronPoints, polyhedronFaces]
let(
// top is the top curved part of the extrude
top=makeCurvedPartOfPolyHedron(radiiPoints,r1,fn),
topRadiusPoints=translate3Dcoords(top[0],[0,0,h-r1]),
singeLayerLength=top[2],
topRadiusFaces=top[1],
radiusPointsLength=len(topRadiusPoints), // is the same length as bottomRadiusPoints
// bottom is the bottom curved part of the extrude
bottom=makeCurvedPartOfPolyHedron(radiiPoints,r2,fn),
// Z axis needs to be multiplied by -1 to flip it so the radius is going in the right direction [1,1,-1]
bottomRadiusPoints=translate3Dcoords(bottom[0],[0,0,abs(r2)],[1,1,-1]),
// becaues the points will be all concatenated into the same array, and the bottom points come second, than
// the original indices the faces are points towards are wrong and need to have an offset applied to them
bottomRadiusFaces=offsetAllFacesBy(bottom[1],radiusPointsLength),
// all of the side panel of the extrusion, connecting points from the inner layers of each
// of the curved sections
sideFaces=[for(i=[0:singeLayerLength-1])[
i,
listWrap(i+1,singeLayerLength),
radiusPointsLength + listWrap(i+1,singeLayerLength),
radiusPointsLength + i
]],
// both of these caps are simple every point from the last layer of the radius points
topCapFace=[for(i=[0:singeLayerLength-1])radiusPointsLength-singeLayerLength+i],
bottomCapFace=[for(i=[0:singeLayerLength-1])radiusPointsLength*2-singeLayerLength+i],
finalPolyhedronPoints=concat(topRadiusPoints,bottomRadiusPoints),
finalPolyhedronFaces=concat(topRadiusFaces,bottomRadiusFaces, sideFaces, [topCapFace], [bottomCapFace])
)
[
finalPolyhedronPoints,
finalPolyhedronFaces
];
module polyRoundExtrude(radiiPoints,length=5,r1=1,r2=1,fn=10,convexity=10) {
polyhedronPointsNFaces=extrudePolygonWithRadius(radiiPoints,length,r1,r2,fn);
polyhedron(points=polyhedronPointsNFaces[0], faces=polyhedronPointsNFaces[1], convexity=convexity);
}
// testingInternals();
module testingInternals(){
//example of rounding random points, this has no current use but is a good demonstration
random=[for(i=[0:20])[rnd(0,50),rnd(0,50),/*rnd(0,30)*/1000]];
R =polyRound(random,7);
translate([-25,25,0]){
polyline(R);
}
//example of different modes of the CentreN2PointsArc() function 0=shortest arc, 1=longest arc, 2=CW, 3=CCW
p1=[0,5];p2=[10,5];centre=[5,0];
translate([60,0,0]){
color("green"){
polygon(CentreN2PointsArc(p1,p2,centre,0,20));//draws the shortest arc
}
color("cyan"){
polygon(CentreN2PointsArc(p1,p2,centre,1,20));//draws the longest arc
}
}
translate([75,0,0]){
color("purple"){
polygon(CentreN2PointsArc(p1,p2,centre,2,20));//draws the arc CW (which happens to be the short arc)
}
color("red"){
polygon(CentreN2PointsArc(p2,p1,centre,2,20));//draws the arc CW but p1 and p2 swapped order resulting in the long arc being drawn
}
}
radius=6;
radiipoints=[[0,0,0],[10,20,radius],[20,0,0]];
tangentsNcen=round3points(radiipoints);
translate([10,0,0]){
for(i=[0:2]){
color("red")translate(getpoints(radiipoints)[i])circle(1);//plots the 3 input points
color("cyan")translate(tangentsNcen[i])circle(1);//plots the two tangent poins and the circle centre
}
translate([tangentsNcen[2][0],tangentsNcen[2][1],-0.2])circle(r=radius,$fn=25);//draws the cirle
%polygon(getpoints(radiipoints));//draws a polygon
}
}
function polyRound(radiipoints,fn=5,mode=0)=
/*Takes a list of radii points of the format [x,y,radius] and rounds each point
with fn resolution
mode=0 - automatic radius limiting - DEFAULT
mode=1 - Debug, output radius reduction for automatic radius limiting
mode=2 - No radius limiting*/
let(
p=getpoints(radiipoints), //make list of coordinates without radii
Lp=len(p),
//remove the middle point of any three colinear points, otherwise adding a radius to the middle of a straigh line causes problems
radiiPointsWithoutTrippleColinear=[
for(i=[0:len(p)-1]) if(
// keep point if it isn't colinear or if the radius is 0
!isColinear(
p[listWrap(i-1,Lp)],
p[listWrap(i+0,Lp)],
p[listWrap(i+1,Lp)]
)||
p[listWrap(i+0,Lp)].z!=0
) radiipoints[listWrap(i+0,Lp)]
],
newrp2=processRadiiPoints(radiiPointsWithoutTrippleColinear),
plusMinusPointRange=mode==2?1:2,
temp=[
for(i=[0:len(newrp2)-1]) //for each point in the radii array
let(
thepoints=[for(j=[-plusMinusPointRange:plusMinusPointRange])newrp2[listWrap(i+j,len(newrp2))]],//collect 5 radii points
temp2=mode==2?round3points(thepoints,fn):round5points(thepoints,fn,mode)
)
mode==1?temp2:newrp2[i][2]==0?
[[newrp2[i][0],newrp2[i][1]]]: //return the original point if the radius is 0
CentreN2PointsArc(temp2[0],temp2[1],temp2[2],0,fn) //return the arc if everything is normal
]
)
[for (a = temp) for (b = a) b];//flattern and return the array
function round5points(rp,fn,debug=0)=
rp[2][2]==0&&debug==0?[[rp[2][0],rp[2][1]]]://return the middle point if the radius is 0
rp[2][2]==0&&debug==1?0://if debug is enabled and the radius is 0 return 0
let(
p=getpoints(rp), //get list of points
r=[for(i=[1:3]) abs(rp[i][2])],//get the centre 3 radii
//start by determining what the radius should be at point 3
//find angles at points 2 , 3 and 4
a2=cosineRuleAngle(p[0],p[1],p[2]),
a3=cosineRuleAngle(p[1],p[2],p[3]),
a4=cosineRuleAngle(p[2],p[3],p[4]),
//find the distance between points 2&3 and between points 3&4
d23=pointDist(p[1],p[2]),
d34=pointDist(p[2],p[3]),
//find the radius factors
F23=(d23*tan(a2/2)*tan(a3/2))/(r[0]*tan(a3/2)+r[1]*tan(a2/2)),
F34=(d34*tan(a3/2)*tan(a4/2))/(r[1]*tan(a4/2)+r[2]*tan(a3/2)),
newR=min(r[1],F23*r[1],F34*r[1]),//use the smallest radius
//now that the radius has been determined, find tangent points and circle centre
tangD=newR/tan(a3/2),//distance to the tangent point from p3
circD=newR/sin(a3/2),//distance to the circle centre from p3
//find the angle from the p3
an23=getAngle(p[1],p[2]),//angle from point 3 to 2
an34=getAngle(p[3],p[2]),//angle from point 3 to 4
//find tangent points
t23=[p[2][0]-cos(an23)*tangD,p[2][1]-sin(an23)*tangD],//tangent point between points 2&3
t34=[p[2][0]-cos(an34)*tangD,p[2][1]-sin(an34)*tangD],//tangent point between points 3&4
//find circle centre
tmid=getMidpoint(t23,t34),//midpoint between the two tangent points
anCen=getAngle(tmid,p[2]),//angle from point 3 to circle centre
cen=[p[2][0]-cos(anCen)*circD,p[2][1]-sin(anCen)*circD]
)
//circle center by offseting from point 3
//determine the direction of rotation
debug==1?//if debug in disabled return arc (default)
(newR-r[1]):
[t23,t34,cen];
function round3points(rp,fn)=
rp[1][2]==0?[[rp[1][0],rp[1][1]]]://return the middle point if the radius is 0
let(
p=getpoints(rp), //get list of points
r=rp[1][2],//get the centre 3 radii
ang=cosineRuleAngle(p[0],p[1],p[2]),//angle between the lines
//now that the radius has been determined, find tangent points and circle centre
tangD=r/tan(ang/2),//distance to the tangent point from p2
circD=r/sin(ang/2),//distance to the circle centre from p2
//find the angles from the p2 with respect to the postitive x axis
angleFromPoint1ToPoint2=getAngle(p[0],p[1]),
angleFromPoint2ToPoint3=getAngle(p[2],p[1]),
//find tangent points
t12=[p[1][0]-cos(angleFromPoint1ToPoint2)*tangD,p[1][1]-sin(angleFromPoint1ToPoint2)*tangD],//tangent point between points 1&2
t23=[p[1][0]-cos(angleFromPoint2ToPoint3)*tangD,p[1][1]-sin(angleFromPoint2ToPoint3)*tangD],//tangent point between points 2&3
//find circle centre
tmid=getMidpoint(t12,t23),//midpoint between the two tangent points
angCen=getAngle(tmid,p[1]),//angle from point 2 to circle centre
cen=[p[1][0]-cos(angCen)*circD,p[1][1]-sin(angCen)*circD] //circle center by offseting from point 2
)
[t12,t23,cen];
function parallelFollow(rp,thick=4,minR=1,mode=1)=
//rp[1][2]==0?[rp[1][0],rp[1][1],0]://return the middle point if the radius is 0
thick==0?[rp[1][0],rp[1][1],0]://return the middle point if the radius is 0
let(
p=getpoints(rp), //get list of points
r=thick,//get the centre 3 radii
ang=cosineRuleAngle(p[0],p[1],p[2]),//angle between the lines
//now that the radius has been determined, find tangent points and circle centre
tangD=r/tan(ang/2),//distance to the tangent point from p2
sgn=CWorCCW(rp),//rotation of the three points cw or ccw?let(sgn=mode==0?1:-1)
circD=mode*sgn*r/sin(ang/2),//distance to the circle centre from p2
//find the angles from the p2 with respect to the postitive x axis
angleFromPoint1ToPoint2=getAngle(p[0],p[1]),
angleFromPoint2ToPoint3=getAngle(p[2],p[1]),
//find tangent points
t12=[p[1][0]-cos(angleFromPoint1ToPoint2)*tangD,p[1][1]-sin(angleFromPoint1ToPoint2)*tangD],//tangent point between points 1&2
t23=[p[1][0]-cos(angleFromPoint2ToPoint3)*tangD,p[1][1]-sin(angleFromPoint2ToPoint3)*tangD],//tangent point between points 2&3
//find circle centre
tmid=getMidpoint(t12,t23),//midpoint between the two tangent points
angCen=getAngle(tmid,p[1]),//angle from point 2 to circle centre
cen=[p[1][0]-cos(angCen)*circD,p[1][1]-sin(angCen)*circD],//circle center by offseting from point 2
outR=max(minR,rp[1][2]-thick*sgn*mode) //ensures radii are never too small.
)
concat(cen,outR);
function findPoint(ang1,refpoint1,ang2,refpoint2,r=0)=
let(
m1=tan(ang1),
c1=refpoint1.y-m1*refpoint1.x,
m2=tan(ang2),
c2=refpoint2.y-m2*refpoint2.x,
outputX=(c2-c1)/(m1-m2),
outputY=m1*outputX+c1
)
[outputX,outputY,r];
function beamChain(radiiPoints,offset1=0,offset2,mode=0,minR=0,startAngle,endAngle)=
/*This function takes a series of radii points and plots points to run along side at a consistant distance, think of it as offset but for line instead of a polygon
radiiPoints=radii points,
offset1 & offset2= The two offsets that give the beam it's thickness. When using with mode=2 only offset1 is needed as there is no return path for the polygon
minR=min radius, if all of your radii are set properly within the radii points this value can be ignored
startAngle & endAngle= Angle at each end of the beam, different mode determine if this angle is relative to the ending legs of the beam or absolute.
mode=1 - include endpoints startAngle&2 are relative to the angle of the last two points and equal 90deg if not defined
mode=2 - Only the forward path is defined, useful for combining the beam with other radii points, see examples for a use-case.
mode=3 - include endpoints startAngle&2 are absolute from the x axis and are 0 if not defined
negative radiuses only allowed for the first and last radii points
As it stands this function could probably be tidied a lot, but it works, I'll tidy later*/
let(
offset2undef=offset2==undef?1:0,
offset2=offset2undef==1?0:offset2,
CWorCCW1=sign(offset1)*CWorCCW(radiiPoints),
CWorCCW2=sign(offset2)*CWorCCW(radiiPoints),
offset1=abs(offset1),
offset2b=abs(offset2),
Lrp3=len(radiiPoints)-3,
Lrp=len(radiiPoints),
startAngle=mode==0&&startAngle==undef?
getAngle(radiiPoints[0],radiiPoints[1])+90:
mode==2&&startAngle==undef?
0:
mode==0?
getAngle(radiiPoints[0],radiiPoints[1])+startAngle:
startAngle,
endAngle=mode==0&&endAngle==undef?
getAngle(radiiPoints[Lrp-1],radiiPoints[Lrp-2])+90:
mode==2&&endAngle==undef?
0:
mode==0?
getAngle(radiiPoints[Lrp-1],radiiPoints[Lrp-2])+endAngle:
endAngle,
OffLn1=[for(i=[0:Lrp3]) offset1==0?radiiPoints[i+1]:parallelFollow([radiiPoints[i],radiiPoints[i+1],radiiPoints[i+2]],offset1,minR,mode=CWorCCW1)],
OffLn2=[for(i=[0:Lrp3]) offset2==0?radiiPoints[i+1]:parallelFollow([radiiPoints[i],radiiPoints[i+1],radiiPoints[i+2]],offset2b,minR,mode=CWorCCW2)],
Rp1=abs(radiiPoints[0].z),
Rp2=abs(radiiPoints[Lrp-1].z),
endP1a=findPoint(getAngle(radiiPoints[0],radiiPoints[1]), OffLn1[0], startAngle,radiiPoints[0], Rp1),
endP1b=findPoint(getAngle(radiiPoints[Lrp-1],radiiPoints[Lrp-2]), OffLn1[len(OffLn1)-1], endAngle,radiiPoints[Lrp-1], Rp2),
endP2a=findPoint(getAngle(radiiPoints[0],radiiPoints[1]), OffLn2[0], startAngle,radiiPoints[0], Rp1),
endP2b=findPoint(getAngle(radiiPoints[Lrp-1],radiiPoints[Lrp-2]), OffLn2[len(OffLn1)-1], endAngle,radiiPoints[Lrp-1], Rp2),
absEnda=getAngle(endP1a,endP2a),
absEndb=getAngle(endP1b,endP2b),
negRP1a=[cos(absEnda)*radiiPoints[0].z*10+endP1a.x, sin(absEnda)*radiiPoints[0].z*10+endP1a.y, 0.0],
negRP2a=[cos(absEnda)*-radiiPoints[0].z*10+endP2a.x, sin(absEnda)*-radiiPoints[0].z*10+endP2a.y, 0.0],
negRP1b=[cos(absEndb)*radiiPoints[Lrp-1].z*10+endP1b.x, sin(absEndb)*radiiPoints[Lrp-1].z*10+endP1b.y, 0.0],
negRP2b=[cos(absEndb)*-radiiPoints[Lrp-1].z*10+endP2b.x, sin(absEndb)*-radiiPoints[Lrp-1].z*10+endP2b.y, 0.0],
OffLn1b=(mode==0||mode==2)&&radiiPoints[0].z<0&&radiiPoints[Lrp-1].z<0?
concat([negRP1a],[endP1a],OffLn1,[endP1b],[negRP1b])
:(mode==0||mode==2)&&radiiPoints[0].z<0?
concat([negRP1a],[endP1a],OffLn1,[endP1b])
:(mode==0||mode==2)&&radiiPoints[Lrp-1].z<0?
concat([endP1a],OffLn1,[endP1b],[negRP1b])
:mode==0||mode==2?
concat([endP1a],OffLn1,[endP1b])
:
OffLn1,
OffLn2b=(mode==0||mode==2)&&radiiPoints[0].z<0&&radiiPoints[Lrp-1].z<0?
concat([negRP2a],[endP2a],OffLn2,[endP2b],[negRP2b])
:(mode==0||mode==2)&&radiiPoints[0].z<0?
concat([negRP2a],[endP2a],OffLn2,[endP2b])
:(mode==0||mode==2)&&radiiPoints[Lrp-1].z<0?
concat([endP2a],OffLn2,[endP2b],[negRP2b])
:mode==0||mode==2?
concat([endP2a],OffLn2,[endP2b])
:
OffLn2
)//end of let()
offset2undef==1?OffLn1b:concat(OffLn2b,revList(OffLn1b));
function revList(list)=//reverse list
let(Llist=len(list)-1)
[for(i=[0:Llist]) list[Llist-i]];
function CWorCCW(p)=
let(
Lp=len(p),
e=[for(i=[0:Lp-1])
(p[listWrap(i+0,Lp)].x-p[listWrap(i+1,Lp)].x)*(p[listWrap(i+0,Lp)].y+p[listWrap(i+1,Lp)].y)
]
)
sign(sum(e));
function CentreN2PointsArc(p1,p2,cen,mode=0,fn)=
/* This function plots an arc from p1 to p2 with fn increments using the cen as the centre of the arc.
the mode determines how the arc is plotted
mode==0, shortest arc possible
mode==1, longest arc possible
mode==2, plotted clockwise
mode==3, plotted counter clockwise
*/
let(
isCWorCCW=CWorCCW([cen,p1,p2]),//determine the direction of rotation
//determine the arc angle depending on the mode
p1p2Angle=cosineRuleAngle(p2,cen,p1),
arcAngle=
mode==0?p1p2Angle:
mode==1?p1p2Angle-360:
mode==2&&isCWorCCW==-1?p1p2Angle:
mode==2&&isCWorCCW== 1?p1p2Angle-360:
mode==3&&isCWorCCW== 1?p1p2Angle:
mode==3&&isCWorCCW==-1?p1p2Angle-360:
cosineRuleAngle(p2,cen,p1),
r=pointDist(p1,cen),//determine the radius
p1Angle=getAngle(cen,p1) //angle of line 1
)
[for(i=[0:fn])
let(angleIncrement=(arcAngle/fn)*i*isCWorCCW)
[cos(p1Angle+angleIncrement)*r+cen.x,sin(p1Angle+angleIncrement)*r+cen.y]];
function translateRadiiPoints(radiiPoints,tran=[0,0],rot=0)=
[for(i=radiiPoints)
let(
a=getAngle([0,0],[i.x,i.y]),//get the angle of the this point
h=pointDist([0,0],[i.x,i.y]) //get the hypotenuse/radius
)
[h*cos(a+rot)+tran.x,h*sin(a+rot)+tran.y,i.z]//calculate the point's new position
];
module round2d(OR=3,IR=1){
offset(OR,$fn=100){
offset(-IR-OR,$fn=100){
offset(IR,$fn=100){
children();
}
}
}
}
module shell2d(offset1,offset2=0,minOR=0,minIR=0){
difference(){
round2d(minOR,minIR){
offset(max(offset1,offset2)){
children(0);//original 1st child forms the outside of the shell
}
}
round2d(minIR,minOR){
difference(){//round the inside cutout
offset(min(offset1,offset2)){
children(0);//shrink the 1st child to form the inside of the shell
}
if($children>1){
for(i=[1:$children-1]){
children(i);//second child and onwards is used to add material to inside of the shell
}
}
}
}
}
}
module internalSq(size,r,center=0){
tran=center==1?[0,0]:size/2;
translate(tran){
square(size,true);
offs=sin(45)*r;
for(i=[-1,1],j=[-1,1]){
translate([(size.x/2-offs)*i,(size.y/2-offs)*j])circle(r);
}
}
}
module extrudeWithRadius(length,r1=0,r2=0,fn=30){
n1=sign(r1);n2=sign(r2);
r1=abs(r1);r2=abs(r2);
translate([0,0,r1]){
linear_extrude(length-r1-r2){
children();
}
}
for(i=[0:fn-1]){
translate([0,0,i/fn*r1]){
linear_extrude(r1/fn+0.01){
offset(n1*sqrt(sq(r1)-sq(r1-i/fn*r1))-n1*r1){
children();
}
}
}
translate([0,0,length-r2+i/fn*r2]){
linear_extrude(r2/fn+0.01){
offset(n2*sqrt(sq(r2)-sq(i/fn*r2))-n2*r2){
children();
}
}
}
}
}
function mirrorPoints(radiiPoints,rot=0,endAttenuation=[0,0])= //mirrors a list of points about Y, ignoring the first and last points and returning them in reverse order for use with polygon or polyRound
let(
a=translateRadiiPoints(radiiPoints,[0,0],-rot),
temp3=[for(i=[0+endAttenuation[0]:len(a)-1-endAttenuation[1]])
[a[i][0],-a[i][1],a[i][2]]
],
temp=translateRadiiPoints(temp3,[0,0],rot),
temp2=revList(temp3)
)
concat(radiiPoints,temp2);
function processRadiiPoints(rp)=
[for(i=[0:len(rp)-1])
processRadiiPoints2(rp,i)
];
function processRadiiPoints2(list,end=0,idx=0,result=0)=
idx>=end+1?result:
processRadiiPoints2(list,end,idx+1,relationalRadiiPoints(result,list[idx]));
function cosineRuleBside(a,c,C)=c*cos(C)-sqrt(sq(a)+sq(c)+sq(cos(C))-sq(c));
function absArelR(po,pn)=
let(
th2=atan(po[1]/po[0]),
r2=sqrt(sq(po[0])+sq(po[1])),
r3=cosineRuleBside(r2,pn[1],th2-pn[0])
)
[cos(pn[0])*r3,sin(pn[0])*r3,pn[2]];
function relationalRadiiPoints(po,pi)=
let(
p0=pi[0],
p1=pi[1],
p2=pi[2],
pv0=pi[3][0],
pv1=pi[3][1],
pt0=pi[3][2],
pt1=pi[3][3],
pn=
(pv0=="y"&&pv1=="x")||(pv0=="r"&&pv1=="a")||(pv0=="y"&&pv1=="a")||(pv0=="x"&&pv1=="a")||(pv0=="y"&&pv1=="r")||(pv0=="x"&&pv1=="r")?
[p1,p0,p2,concat(pv1,pv0,pt1,pt0)]:
[p0,p1,p2,concat(pv0,pv1,pt0,pt1)],
n0=pn[0],
n1=pn[1],
n2=pn[2],
nv0=pn[3][0],
nv1=pn[3][1],
nt0=pn[3][2],
nt1=pn[3][3],
temp=
pn[0]=="l"?
[po[0],pn[1],pn[2]]
:pn[1]=="l"?
[pn[0],po[1],pn[2]]
:nv0==undef?
[pn[0],pn[1],pn[2]]//abs x, abs y as default when undefined
:nv0=="a"?
nv1=="r"?
nt0=="a"?
nt1=="a"||nt1==undef?
[cos(n0)*n1,sin(n0)*n1,n2]//abs angle, abs radius
:absArelR(po,pn)//abs angle rel radius
:nt1=="r"||nt1==undef?
[po[0]+cos(pn[0])*pn[1],po[1]+sin(pn[0])*pn[1],pn[2]]//rel angle, rel radius
:[pn[0],pn[1],pn[2]]//rel angle, abs radius
:nv1=="x"?
nt0=="a"?
nt1=="a"||nt1==undef?
[pn[1],pn[1]*tan(pn[0]),pn[2]]//abs angle, abs x
:[po[0]+pn[1],(po[0]+pn[1])*tan(pn[0]),pn[2]]//abs angle rel x
:nt1=="r"||nt1==undef?
[po[0]+pn[1],po[1]+pn[1]*tan(pn[0]),pn[2]]//rel angle, rel x
:[pn[1],po[1]+(pn[1]-po[0])*tan(pn[0]),pn[2]]//rel angle, abs x
:nt0=="a"?
nt1=="a"||nt1==undef?
[pn[1]/tan(pn[0]),pn[1],pn[2]]//abs angle, abs y
:[(po[1]+pn[1])/tan(pn[0]),po[1]+pn[1],pn[2]]//abs angle rel y
:nt1=="r"||nt1==undef?
[po[0]+(pn[1]-po[0])/tan(90-pn[0]),po[1]+pn[1],pn[2]]//rel angle, rel y
:[po[0]+(pn[1]-po[1])/tan(pn[0]),pn[1],pn[2]]//rel angle, abs y
:nv0=="r"?
nv1=="x"?
nt0=="a"?
nt1=="a"||nt1==undef?
[pn[1],sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1])),pn[2]]//abs radius, abs x
:[po[0]+pn[1],sign(pn[0])*sqrt(sq(pn[0])-sq(po[0]+pn[1])),pn[2]]//abs radius rel x
:nt1=="r"||nt1==undef?
[po[0]+pn[1],po[1]+sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1])),pn[2]]//rel radius, rel x
:[pn[1],po[1]+sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1]-po[0])),pn[2]]//rel radius, abs x
:nt0=="a"?
nt1=="a"||nt1==undef?
[sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1])),pn[1],pn[2]]//abs radius, abs y
:[sign(pn[0])*sqrt(sq(pn[0])-sq(po[1]+pn[1])),po[1]+pn[1],pn[2]]//abs radius rel y
:nt1=="r"||nt1==undef?
[po[0]+sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1])),po[1]+pn[1],pn[2]]//rel radius, rel y
:[po[0]+sign(pn[0])*sqrt(sq(pn[0])-sq(pn[1]-po[1])),pn[1],pn[2]]//rel radius, abs y
:nt0=="a"?
nt1=="a"||nt1==undef?
[pn[0],pn[1],pn[2]]//abs x, abs y
:[pn[0],po[1]+pn[1],pn[2]]//abs x rel y
:nt1=="r"||nt1==undef?
[po[0]+pn[0],po[1]+pn[1],pn[2]]//rel x, rel y
:[po[0]+pn[0],pn[1],pn[2]]//rel x, abs y
)
temp;
function invtan(run,rise)=
let(a=abs(atan(rise/run)))
rise==0&&run>0?
0:rise>0&&run>0?
a:rise>0&&run==0?
90:rise>0&&run<0?
180-a:rise==0&&run<0?
180:rise<0&&run<0?
a+180:rise<0&&run==0?
270:rise<0&&run>0?
360-a:"error";
function cosineRuleAngle(p1,p2,p3)=
let(
p12=abs(pointDist(p1,p2)),
p13=abs(pointDist(p1,p3)),
p23=abs(pointDist(p2,p3))
)
acos((sq(p23)+sq(p12)-sq(p13))/(2*p23*p12));
function sum(list, idx = 0, result = 0) =
idx >= len(list) ? result : sum(list, idx + 1, result + list[idx]);
function sq(x)=x*x;
function getGradient(p1,p2)=(p2.y-p1.y)/(p2.x-p1.x);
function getAngle(p1,p2)=p1==p2?0:invtan(p2[0]-p1[0],p2[1]-p1[1]);
function getMidpoint(p1,p2)=[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2]; //returns the midpoint of two points
function pointDist(p1,p2)=sqrt(abs(sq(p1[0]-p2[0])+sq(p1[1]-p2[1]))); //returns the distance between two points
function isColinear(p1,p2,p3)=getGradient(p1,p2)==getGradient(p2,p3)?1:0;//return 1 if 3 points are colinear
module polyline(p, width=0.3) {
for(i=[0:max(0,len(p)-1)]){
color([i*1/len(p),1-i*1/len(p),0,0.5])line(p[i],p[listWrap(i+1,len(p) )],width);
}
} // polyline plotter
module line(p1, p2 ,width=0.3) { // single line plotter
hull() {
translate(p1){
circle(width);
}
translate(p2){
circle(width);
}
}
}
function getpoints(p)=[for(i=[0:len(p)-1])[p[i].x,p[i].y]];// gets [x,y]list of[x,y,r]list
function listWrap(x,x_max=1,x_min=0) = (((x - x_min) % (x_max - x_min)) + (x_max - x_min)) % (x_max - x_min) + x_min; // wraps numbers inside boundaries
function rnd(a = 1, b = 0, s = []) =
s == [] ?
(rands(min(a, b), max( a, b), 1)[0]):(rands(min(a, b), max(a, b), 1, s)[0]); // nice rands wrapper

View File

@@ -1,35 +0,0 @@
function sign_x(i,n) =
i < n/4 || i > n*3/4 ? 1 :
i > n/4 && i < n*3/4 ? -1 :
0;
function sign_y(i,n) =
i > 0 && i < n/2 ? 1 :
i > n/2 ? -1 :
0;
function rectangle_profile(size=[1,1],fn=32) = [
for (index = [0:fn-1])
let(a = index/fn*360)
sign_x(index, fn) * [size[0]/2,0]
+ sign_y(index, fn) * [0,size[1]/2]
];
function rounded_rectangle_profile(size=[1,1],r=1,fn=32) = [
let(max_fn = max(fn,8))
for (index = [0:max_fn-1])
let(a = index/max_fn*360)
r * [cos(a), sin(a)]
+ sign_x(index, max_fn) * [size[0]/2-r,0]
+ sign_y(index, max_fn) * [0,size[1]/2-r]
];
function double_rounded_rectangle_profile(size=[1,1], r=1, fn=32) = [
let(max_fn = max(fn,8))
for (index = [0:max_fn-1])
let(a = index/max_fn*360)
r * [cos(a), sin(a)]
+ sign_x(index, max_fn) * [size[0]/2-r,0]
+ sign_y(index, max_fn) * [0,size[1]/2-r]
];

View File

@@ -102,7 +102,11 @@ $dish_depth = 1;
$dish_skew_x = 0;
// How skewed in the y direction (height) the dish is
$dish_skew_y = 0;
// If you need the dish to extend further, you can 'overdraw' the rectangle it will hit
$dish_offset_x = 0;
// If you need the dish to extend further, you can 'overdraw' the rectangle it will hit. this was mostly for iso enter and should be deprecated
$dish_overdraw_width = 0;
// Same as width but for height
$dish_overdraw_height = 0;

View File

@@ -1,6 +1,9 @@
// corollary is rounded_square
// NOT 3D
function unit_length(length) = unit * (length - 1) + 18.16;
include <../functions.scad>
include <../libraries/round-anything/polyround.scad>
width_ratio = unit_length(1.25) / unit_length(1.5);
height_ratio = unit_length(1) / unit_length(2);
module ISO_enter_shape(size, delta, progress){
width = size[0];
@@ -13,43 +16,53 @@ module ISO_enter_shape(size, delta, progress){
// and wants to pass just width and height, we make these ratios to know where
// to put the elbow joint
width_ratio = unit_length(1.25) / unit_length(1.5);
height_ratio = unit_length(1) / unit_length(2);
delta = delta / 2;
pointArray = [
[ 0, 0], // top right
[ 0, -height], // bottom right
[-width * width_ratio, -height], // bottom left
[-width * width_ratio,-height * height_ratio], // inner middle point
[ -width,-height * height_ratio], // outer middle point
[ -width, 0] // top left
[ 0-delta.x, 0-delta.y], // top right
[ 0-delta.x, -height+delta.y], // bottom right
[-width * width_ratio+delta.x, -height+delta.y], // bottom left
[-width * width_ratio + delta.x,-height * height_ratio+delta.y], // inner middle point
[ -width + delta.x,-height * height_ratio + delta.y], // outer middle point
[ -width + delta.x, 0-delta.y] // top left
];
minkowski(){
circle(r=corner_size);
circle(r=$corner_radius);
// gives us rounded inner corner
offset(r=-corner_size*2) {
offset(r=-$corner_radius*2) {
translate([(width * width_ratio)/2, height/2]) polygon(points=pointArray);
}
}
}
function iso_enter_vertices(width, height, width_ratio, height_ratio, wd, hd) = [
[ 0-wd, 0-hd], // top right
[ 0-wd, -height+hd], // bottom right
[-width * width_ratio+wd, -height+hd], // bottom left
[-width * width_ratio+wd,-height * height_ratio+hd], // inner middle point
[ -width+wd,-height * height_ratio+hd], // outer middle point
[ -width+wd, 0-hd] // top left
function iso_enter_vertices(size, delta, progress, thickness_difference) = [
[ 0-delta.x/2 * progress - thickness_difference/2, 0 - delta.y / 2 * progress - thickness_difference/2], // top right
[ 0-delta.x/2 * progress - thickness_difference/2, -size[1] + delta.y / 2 * progress + thickness_difference/2], // bottom right
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/2, -size[1] + delta.y / 2 * progress + thickness_difference/2], // bottom left
[-size[0] * width_ratio + delta.x/2 * progress + thickness_difference/2,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // inner middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/2,-size[1] * height_ratio + delta.y / 2 * progress + thickness_difference/2], // outer middle point
[ -size[0] + delta.x/2 * progress + thickness_difference/2, 0 - delta.y / 2 * progress - thickness_difference/2] // top left
] + [
[(width * width_ratio)/2, height/2 ],
[(width * width_ratio)/2, height/2 ],
[(width * width_ratio)/2, height/2 ],
[(width * width_ratio)/2, height/2 ],
[(width * width_ratio)/2, height/2 ],
[(width * width_ratio)/2, height/2 ]
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ],
[(size[0] * width_ratio)/2, size[1]/2 ]
];
// no rounding on the corners at all
function skin_iso_enter_shape(size, delta, progress, thickness_difference) =
iso_enter_vertices(size.x, size.y, unit_length(1.25) / unit_length(1.5), unit_length(1) / unit_length(2), thickness_difference/2 + delta.x * progress/2, thickness_difference/2 + delta.y * progress/2);
polyRound(
add_rounding(
iso_enter_vertices(
size,
delta,
progress,
thickness_difference
),
$corner_radius
),
$shape_facets
);

View File

@@ -1,4 +1,5 @@
include <../libraries/rounded_rectangle_profile.scad>
include <square.scad>
include <../libraries/round-anything/polyround.scad>
module rounded_square_shape(size, delta, progress, center = true) {
offset(r=$corner_radius, $fa=360/$shape_facets){
@@ -7,6 +8,5 @@ module rounded_square_shape(size, delta, progress, center = true) {
}
// for skin
function skin_rounded_square(size, delta, progress, thickness_difference) =
rounded_rectangle_profile(size - (delta * progress), fn=$shape_facets, r=$corner_radius);
polyRound(add_rounding(rectangle_profile(size - (delta * progress)), $corner_radius), $shape_facets/4);

View File

@@ -1,5 +1,3 @@
include <../libraries/rounded_rectangle_profile.scad>
// rounded square shape with additional sculpting functions to better approximate
// When sculpting sides, how much in should the tops come
@@ -44,8 +42,35 @@ module sculpted_square_shape(size, delta, progress) {
}
}
// fudging the hell out of this, I don't remember what the negative-offset-positive-offset was doing in the module above
// also no 'bowed' square shape for now
function new_side_rounded_square(size, r, cornerRadius=0) =
let(
width = (size.x - r)/2,
height = (size.y - r)/2,
// fudge numbers! the radius conflict resolution in polyround smooths out
// the entire shape based on the ratios between conflicting radii. bumping
// these up makes the whole shape more fluid
widthRadius = r ? width*8 : 0,
heightRadius = r ? height*8 : 0,
bow = r/2,
// close enough :/
facets = 360 / $shape_facets/2,
points = [
[-width,-height,cornerRadius],
[0,-height-bow,widthRadius],
[width,-height,cornerRadius],
[width + bow,0,heightRadius],
[width,height,cornerRadius],
[0,height + bow,widthRadius],
[-width,height,cornerRadius],
[-width-bow,0,heightRadius]
]
) polyRound(points,facets);
function skin_sculpted_square_shape(size, delta, progress, thickness_difference) =
let(
width = size[0],
@@ -67,13 +92,7 @@ function skin_sculpted_square_shape(size, delta, progress, thickness_difference)
width - extra_width_this_slice - thickness_difference,
height - extra_height_this_slice - thickness_difference
]
) double_rounded_rectangle_profile(square_size - [extra_corner_radius_this_slice, extra_corner_radius_this_slice]/4, fn=$shape_facets, r=extra_corner_radius_this_slice/1.5 + $more_side_sculpting_factor * progress);
/* offset(r = extra_corner_radius_this_slice) {
offset(r = -extra_corner_radius_this_slice) {
side_rounded_square(square_size, r = $more_side_sculpting_factor * progress);
}
} */
) new_side_rounded_square(square_size, $more_side_sculpting_factor * progress, extra_corner_radius_this_slice);
module side_rounded_square(size, r) {

View File

@@ -1,6 +1,4 @@
use <../functions.scad>
include <../libraries/rounded_rectangle_profile.scad>
// we do this weird key_shape_type check here because rounded_square uses
// square_shape, and we want flat sides to work for that too.
@@ -23,14 +21,23 @@ module square_shape(size, delta, progress){
// shape makes the sides flat by making the top a trapezoid.
// This obviously doesn't work with rounded sides at all
module flat_sided_square_shape(size, delta, progress) {
polygon(points=[
[(-size.x + (delta.x + extra_keytop_length_for_flat_sides()) * progress)/2, (-size.y + delta.y * progress)/2],
[(size.x - (delta.x + extra_keytop_length_for_flat_sides()) * progress)/2,(-size.y + delta.y * progress)/2],
[(size.x - (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2],
[(-size.x + (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2]
]);
polygon(skin_flat_sided_square_shape(size, delta, progress));
}
function skin_flat_sided_square_shape(size,delta,progress) = [
[(-size.x + (delta.x + extra_keytop_length_for_flat_sides()) * progress)/2, (-size.y + delta.y * progress)/2],
[(size.x - (delta.x + extra_keytop_length_for_flat_sides()) * progress)/2,(-size.y + delta.y * progress)/2],
[(size.x - (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2],
[(-size.x + (delta.x - extra_keytop_length_for_flat_sides()) * progress)/2, (size.y - delta.y * progress)/2]
];
function rectangle_profile(size) = [
[-size.x/2, -size.y/2],
[size.x/2, -size.y/2],
[size.x/2, size.y/2],
[-size.x/2, size.y/2],
];
function skin_square_shape(size, delta, progress, thickness_difference) =
let(
width = size[0],
@@ -43,4 +50,4 @@ function skin_square_shape(size, delta, progress, thickness_difference) =
width - width_difference - thickness_difference,
height - height_difference - thickness_difference
]
) rectangle_profile(square_size, fn=36);
) $key_shape_type == "flat_sided_square" ? skin_flat_sided_square_shape(size, delta, progress) : rectangle_profile(square_size);

View File

@@ -21,8 +21,6 @@ module stem(stem_type, depth, slop, throw){
filled_stem();
} else if (stem_type == "cherry_stabilizer") {
cherry_stabilizer_stem(depth, slop, throw);
} else if (stem_type == "custom") {
custom_stem(depth, slop, throw);
} else if (stem_type == "disable") {
children();
} else {

View File

@@ -1,12 +0,0 @@
thickness = .84;
inner_stem_size = [6,4];
outer_stem_size = inner_stem_size + [thickness, thickness];
module custom_stem(depth, slop, throw){
linear_extrude(height=depth) {
difference() {
square(outer_stem_size + [slop,slop], center = true);
square(inner_stem_size + [slop,slop], center = true);
}
}
}