--- /dev/null
+/*
+ * Draw a support to tie Tetramag spheres to a bike wheel.
+ *
+ * Copyright (C) 2018 Antonio Ospite <ao2@ao2.it>
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Using a formula from:
+ * https://math.stackexchange.com/questions/12166/numbers-of-circles-around-a-circle
+ */
+
+function calc_inner_radius(sphere_radius, number_of_spheres) = (
+ let(ratio = sin(180 / number_of_spheres) / (1 - sin(180 / number_of_spheres)))
+ sphere_radius / ratio
+);
+
+module draw_spheres(sphere_radius, number_of_spheres) {
+ if (sphere_radius <= 0) {
+ echo("Radius of outer spheres cannot be zero");
+ }
+
+ if (number_of_spheres < 3) {
+ echo("Number of outer spheres cannot be smaller than 3");
+ }
+
+ inner_radius = calc_inner_radius(sphere_radius, number_of_spheres);
+
+ for (i = [0:number_of_spheres]) {
+ theta = i * 360 / number_of_spheres;
+
+ /*
+ cx = sin(theta) * (inner_radius + sphere_radius);
+ cy = cos(theta) * (inner_radius + sphere_radius);
+ translate([cx, cy, 0]) {
+ sphere(sphere_radius, $fn=2);
+ }
+ */
+
+ /* A better version which also rotates the objects radially. */
+ rotate ([0, 0, theta]) {
+ translate([0, inner_radius + sphere_radius, 0]) {
+ sphere(sphere_radius, $fn=40);
+ }
+ }
+ }
+}
+
+module draw_cylinder(sphere_radius, number_of_spheres) {
+ radius = calc_inner_radius(sphere_radius, number_of_spheres) + sphere_radius / 2;
+ cylinder(sphere_radius * 2, r = radius, center=true, $fn=100);
+}
+
+module draw_mounting_holes(hole_radius) {
+ /* 9 is the number of the bike spokes to attach the holder to. */
+ mounting_holes = 9;
+ cube_size = 2;
+ cube_spacing = 2;
+
+ for (i = [0:mounting_holes]) {
+ theta = i * 360 / mounting_holes;
+ rotate ([0, 0, theta]) {
+ translate([-cube_spacing, hole_radius + cube_size, 0]) {
+ cube([cube_size, cube_size, cube_size * 10], true);
+ }translate([cube_spacing, hole_radius + cube_size, 0]) {
+ cube([cube_size, cube_size, cube_size * 10], true);
+ }
+ }
+ }
+
+}
+
+module draw_holes(height, hole_radius) {
+ cylinder(height, r = hole_radius, center=true, $fn=100);
+ mounting_holes = 9;
+ cube_size = 2;
+ cube_spacing = 2;
+
+ draw_mounting_holes(hole_radius);
+}
+
+/* The actual parameters */
+sphere_radius = 2.5;
+number_of_spheres = 38;
+hole_radius = 47 / 2; // 47mm is the hole diameter
+
+difference() {
+ draw_cylinder(sphere_radius, number_of_spheres);
+ draw_spheres(sphere_radius, number_of_spheres);
+ draw_holes(sphere_radius * 3, hole_radius);
+}