diff --git a/.gitignore b/.gitignore index 5509140..3075608 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.DS_Store +benchmark \ No newline at end of file diff --git a/README.md b/README.md index f1f5483..9c98525 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,9 @@ PLA is not recommended but this doesn't mean you can't get an acceptable results ### Dependencies -* [OpenSCAD](https://www.openscad.org/downloads.html) + [cli](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment) ([Mac](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment#MacOS_notes)) ([Windows](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment#Windows_notes)) * Bash +* [OpenSCAD](https://www.openscad.org/downloads.html) + [cli](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment) ([Mac](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment#MacOS_notes)) ([Windows](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment#Windows_notes)) +* [ADMesh](https://github.com/admesh/admesh) ### Build Scripts diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh new file mode 100644 index 0000000..47d9f43 --- /dev/null +++ b/scripts/benchmark.sh @@ -0,0 +1,54 @@ +echo "Benchmarking GNAL spiral generation" + +VERSION=`bash ./scripts/version.sh` +CPU=`bash ./scripts/cpu.sh` +DATE=`date -u +%s` #timestamp in seconds +NOTES="./notes/benchmark.csv" + +ROTATIONS=( 1 2 5 10 20 ) +DIAMETERS=( 47 225 300 ) +COMPLETE=( 40 60 ) + +echo "version,cpu,date,source,diameter,rotations,$fn,size,time" > $NOTES + +for SPIRAL in ./spiral/*.scad +do + FILENAME=`basename ${SPIRAL}` + echo "Rendering ${SPIRAL}..." + for ROT in "${ROTATIONS[@]}" + do + : + for D in "${DIAMETERS[@]}" + do + : + echo "Rendering ${SPIRAL} for ${ROT} rotations @ ${D}mm" + TMP=`mktemp` + start=`date +%s` + openscad -o "${TMP}.stl" -D N=${ROT} -D D=${D} -D FN=100 "${SPIRAL}" + end=`date +%s` + runtime=$((end-start)) + size=`wc -c < "${TMP}.stl"` + size=`echo $size | xargs` + + line="${VERSION},${CPU},${DATE},${FILENAME},${D},${ROT},100,$size,$runtime" + echo $line + echo $line >> $NOTES + + rm "${TMP}.stl" + done + done + + for C in "${COMPLETE[@]}" + do + : + echo "Rendering complete ${SPIRAL} with ${C} rotations" + TMP=`mktemp` + start=`date +%s` + echo -o "${TMP}.stl" -D N=${C} -D D=47 "${SPIRAL}" + end=`date +%s` + runtime=$((end-start)) + echo "${TMP}.stl" + + #rm "${TMP}.stl" + done +done \ No newline at end of file diff --git a/spiral/spiral_1.scad b/spiral/spiral_1.scad new file mode 100644 index 0000000..391db8b --- /dev/null +++ b/spiral/spiral_1.scad @@ -0,0 +1,67 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + + +H = 2.1; + +/** + * Render all spiral facets for as many rotations as supplied + */ +module spiral (START_D = 50, SPIRALS = 39) { + //STOP_D = 100; + + SPACING = 0.86;//1.34; + + TOP_T = 0.86; //thickness + BOTTOM_T = 1.4; + + START_R = START_D / 2; + union () { + for (i = [0 : $fn]) { + rotate ([0, 0, i * (360 / $fn)]) { + for (x = [0: (SPIRALS - 1)]) { + spiral_facet(i, x, START_R, SPACING, BOTTOM_T, TOP_T, H); + } + } + } + } +} + +/** + * Generates a single face of the spiral, in this case a trapazoidal + * shape. Issues are (1) performance (maybe use of hull()) and (2) all + * facet lenths are the same, despite the diameter. This means that + * there are excessive numbers of facets for the smaller spirals to + * compensate for the number of facets needed for the outer spiral. + */ + +module spiral_facet (i, x, START_R, SPACING, BOTTOM_T, TOP_T, H) { + STEP_SIZE = ((SPACING + BOTTOM_T) / $fn); + + STEP_OFFSET = i * STEP_SIZE; + SPIRAL_START_OFFSET = (x * (SPACING + BOTTOM_T)); + + ACTUAL_R = START_R + SPIRAL_START_OFFSET + STEP_OFFSET; + + L = 2 * (ACTUAL_R * tan((360 / $fn) / 2)); + + ANGLE = -atan( STEP_SIZE / (L / 2) ) / 2; + + OFFSET = START_R - (BOTTOM_T / 2) + SPIRAL_START_OFFSET + STEP_OFFSET; + + translate ([OFFSET, 0, - H / 2]) { + rotate ([0, 0, ANGLE]) { + //replace hull for quick render? + //test spiral lib + hull () { + translate([0, 0, H]) + cube([TOP_T, L, 0.1], center=true); + cube([BOTTOM_T, L, 0.1], center=true); + } + } + } +} + +spiral(D, N); diff --git a/spiral/spiral_2.scad b/spiral/spiral_2.scad new file mode 100644 index 0000000..f6e0488 --- /dev/null +++ b/spiral/spiral_2.scad @@ -0,0 +1,47 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + +module spiral_facet (i, SPIRAL, START_R = 48, SPACING = 2, FACET_SIZE = 1, FN = 360) { + BOTTOM_T = 1.2; + TOP_T = .3; + H = 2.1; + + STEP_SIZE = SPACING / FN; + STEP_OFFSET = (SPIRAL * SPACING) + (i * STEP_SIZE); + + ROT = i* (360 / FN); + ANGLE = 0; + + OFFSET = START_R + STEP_OFFSET; + + rotate([0, 0, ROT]) translate ([OFFSET, 0, - H / 2]) { + rotate ([0, 0, ANGLE]) { + hull () { + translate([(BOTTOM_T - TOP_T) / 2, 0, H]) + cube([TOP_T, FACET_SIZE, 0.1], center=true); + cube([BOTTOM_T, FACET_SIZE, 0.1], center=true); + } + //cube([BOTTOM_T, FACET_SIZE, H], center = true); + } + } +} + +//https://www.youtube.com/watch?v=lsSeRxpoIaY +//https://www.mathportal.org/calculators/plane-geometry-calculators/right-triangle-calculator.php +module spiral (SPIRALS = 40, START_D = 48) { + SPACING = 2.075; + FACET_SIZE = 1; + for (SPIRAL = [0 : SPIRALS - 1]) { + //C = PI * R^2 + C = PI * pow(( (START_D / 2) + (SPIRAL * SPACING) ) / 2, 2); + FN = ceil( (C / FACET_SIZE) * .37 ); + + for (i = [0 : FN - 1]) { + spiral_facet(i, SPIRAL, START_D / 2, SPACING, FACET_SIZE, FN); + } + } +} + +spiral(N, D); \ No newline at end of file diff --git a/spiral/spiral_3.scad b/spiral/spiral_3.scad new file mode 100644 index 0000000..2ae899d --- /dev/null +++ b/spiral/spiral_3.scad @@ -0,0 +1,29 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + +include <../libraries/path_extrude.scad>; + +module spiral (count = 40, start_d = 48, spacing = 2.075) { + + //$fn = 80; + + bottom = 1.2; + top = .3; + top_offset = (bottom - top); + h = 2.2; + + angle_i = 360 / $fn; + increment = spacing / $fn; + + facetProfile = [[0, 0], [top_offset, -h], [bottom, -h], [bottom, 0]]; + + + spiralPath = [ for(t = [0 : $fn * count]) + [((start_d / 2) + (t * increment)) * cos(t * angle_i), ((start_d / 2) + (t * increment)) * sin(t * angle_i), 0] ]; + + path_extrude(exShape=facetProfile, exPath=spiralPath); +} + +spiral(N, D); \ No newline at end of file diff --git a/spiral/spiral_4.scad b/spiral/spiral_4.scad new file mode 100644 index 0000000..99efd48 --- /dev/null +++ b/spiral/spiral_4.scad @@ -0,0 +1,35 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + +include <../libraries/path_extrude.scad>; + +//Distinction from v3: use of for loop and union to join rotations + +module spiral (count = 40, start_d = 48, spacing = 2.075) { + facet_size = 30; + bottom = 1.2; + top = .4; + top_offset = (bottom - top); + h = 2.2; + + od = start_d + (spacing * 2 * count); + echo("SPIRAL LENGTH", PI * count * (od + start_d + 1) / 2); + echo("OUTER D", od); + + facetProfile = [[0, 0], [top_offset, -h], [bottom, -h], [bottom, 0]]; + union () { + for (s = [0 : count - 1]) { + d = start_d + (s * spacing * 2); + c = PI * pow(d / 2, 2); + $fn = ceil( c / facet_size ); + angle_i = 360 / $fn; + increment = spacing / $fn; + spiralPath = [ for(t = [0 : $fn + 1]) [((d / 2) + (t * increment)) * cos(t * angle_i), ((d / 2) + (t * increment)) * sin(t * angle_i), 0] ]; + path_extrude(exShape=facetProfile, exPath=spiralPath); + } + } +} + +spiral(N, D); \ No newline at end of file diff --git a/spiral/spiral_5.scad b/spiral/spiral_5.scad new file mode 100644 index 0000000..18fb11e --- /dev/null +++ b/spiral/spiral_5.scad @@ -0,0 +1,24 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + +include <../libraries/path_extrude.scad>; + +//Distinction from v4 compressed spiralPath generation into single line + +module spiral (count = 40, start_d = 48, spacing = 2.095) { + facet_size = 10; + bottom = 1.2; + top = .3; + top_offset = (bottom - top); + h = 2.2; + + facetProfile = [[0, 0], [top_offset, -h], [bottom, -h], [bottom, 0]]; + + spiralPath = [ for (s = [0 : count - 1]) for(t = [0 : ceil( (PI * pow((start_d + (s * spacing * 2)) / 2, 2)) / facet_size ) - 1]) [(((start_d + (s * spacing * 2)) / 2) + (t * (spacing / ceil( (PI * pow((start_d + (s * spacing * 2)) / 2, 2)) / facet_size )))) * cos(t * (360 / ceil( (PI * pow((start_d + (s * spacing * 2)) / 2, 2)) / facet_size ))), (((start_d + (s * spacing * 2)) / 2) + (t * (spacing / ceil( (PI * pow((start_d + (s * spacing * 2)) / 2, 2)) / facet_size )))) * sin(t * (360 / ceil( (PI * pow((start_d + (s * spacing * 2)) / 2, 2)) / facet_size ))), 0] ]; + + path_extrude(exShape=facetProfile, exPath=spiralPath); +} + +spiral(N, D); \ No newline at end of file diff --git a/spiral/spiral_6.scad b/spiral/spiral_6.scad new file mode 100644 index 0000000..b62ff02 --- /dev/null +++ b/spiral/spiral_6.scad @@ -0,0 +1,81 @@ +D=300; // start diameter +N=1; // number of spirals +FN=100; +$fn=FN; + +R = (D + (N * 2.095)) / 2; + +module ShapeToExtrude () +{ + bottom = 1.2; + top = .3; + top_offset = (bottom - top); + h = 2.2; + // Build in +x space. The outside edge of this shape must follow the extrusion path, or there will be open seams.. + polygon ( points= [ + [0, 0], + [top_offset, h], + [bottom, h], + [bottom, 0] + ]); +} + +module InwardSpiral (StepSize, Steps, StartRadius, Pitch, ShapeX) { + for (i=[0 : Steps - 1]) { + // This could be made more computationally efficient + // by collapsing intermediate values and by doing only + // essential calculations inside the loop, but for now + // let's just leave it easy to read. + + ThisTheta = StepSize * i; + NextTheta = StepSize * (i + 1); + ThisRadius = StartRadius - i * (Pitch * (StepSize / 360)); + + // Spiral step approximated by arc of radius ThisRadius, + // passing through the start and end points calculated here. + + NextRadius = StartRadius - (i + 1) * (Pitch * (StepSize / 360)); + ThisX = ThisRadius * sin(ThisTheta); + ThisY = ThisRadius * cos(ThisTheta); + NextX = NextRadius * sin(NextTheta); + NextY = NextRadius * cos(NextTheta); + DeltaX = NextX - ThisX; + DeltaY = NextY - ThisY; + SlopeToNext = DeltaY / DeltaX; + BisecSlope = -1 / SlopeToNext; + ThisXYToBisector = sqrt(DeltaX * DeltaX + DeltaY * DeltaY) / 2; + BisectX = ThisX + (DeltaX / 2); + BisectY = ThisY + (DeltaY / 2); + BisectToCentre = sqrt(pow(ThisRadius, 2) - pow(ThisXYToBisector, 2)); + AbsXComponent = sqrt(pow(BisectToCentre, 2) / ( 1 + pow(BisecSlope, 2))); + XComponent = NextY < ThisY ? AbsXComponent: -AbsXComponent; + YComponent = XComponent * BisecSlope; + CentreX = BisectX - XComponent; + CentreY = BisectY - YComponent; + ExtrudeAngle = -2 * acos(BisectToCentre / ThisRadius); + ArcOrientation = NextY < ThisY ? atan(BisecSlope) - (ExtrudeAngle / 2) : -180 + atan(BisecSlope) -(ExtrudeAngle / 2); + translate([CentreX, CentreY, 0]) { + rotate ([0, 0, ArcOrientation]) { + rotate_extrude (angle=ExtrudeAngle, $fn=300) translate ([ThisRadius - ShapeX, 0, 0])ShapeToExtrude(); + } + } + } +} + + +module spiral () { + SPIRALROTATION=N * 360; + SPIRALSTEPS=180; + INITIALRADIUS= 300 / 2 ; + PITCH=2.095; + XMAXSHAPE=2; + + InwardSpiral ( + SPIRALROTATION/SPIRALSTEPS, + SPIRALSTEPS, + INITIALRADIUS, + PITCH, + XMAXSHAPE); +} + +spiral(); \ No newline at end of file