Mend Trochoid math

h/t Pere for pointing out my mistake!
This commit is contained in:
Bill Kendrick 2024-01-15 22:14:33 -08:00
parent 9ab7b2b3b7
commit ab4cd4fdde
2 changed files with 55 additions and 19 deletions

View file

@ -72,7 +72,7 @@ https://tuxpaint.org/
(https://freesound.org/people/mudflea2/sounds/708182/) (https://freesound.org/people/mudflea2/sounds/708182/)
Creative Commons 0 by mudflea2 Creative Commons 0 by mudflea2
* WIP Epitrochoid and Hypotrochoid magic tools: * Epitrochoid and Hypotrochoid magic tools:
+ Tools to draw centered trochoids; to create art similar to a + Tools to draw centered trochoids; to create art similar to a
Spirograph or Wondergraph. Drag left/right to adjust the Spirograph or Wondergraph. Drag left/right to adjust the
radius of the stator (fixed circle). Drag up/down to adjust radius of the stator (fixed circle). Drag up/down to adjust
@ -83,7 +83,6 @@ https://tuxpaint.org/
epitrochoid and hypotrochoid drawing tools will be made epitrochoid and hypotrochoid drawing tools will be made
available, each with differing pen positions (inside, edge, available, each with differing pen positions (inside, edge,
and outside). and outside).
+ FIXME Angles reversed!?!
+ Code: Bill Kendrick <bill@newbreedsoftware.com> + Code: Bill Kendrick <bill@newbreedsoftware.com>
(with help from Pere Pujal i Carabantes <perepujal@gmail.com>) (with help from Pere Pujal i Carabantes <perepujal@gmail.com>)
+ Sounds: + Sounds:

View file

@ -5,8 +5,9 @@
Spirograph and Wondergraph. Spirograph and Wondergraph.
by Bill Kendrick <bill@newbreedsoftware.com> by Bill Kendrick <bill@newbreedsoftware.com>
with help from Pere Pujal Carabantes
January 6, 2024 - January 7, 2024 January 6, 2024 - January 15, 2024
*/ */
#include <stdio.h> #include <stdio.h>
@ -17,8 +18,8 @@
#include "SDL_image.h" #include "SDL_image.h"
#include "SDL_mixer.h" #include "SDL_mixer.h"
#define deg_cos(x) cos((float) (x) * M_PI / 180.0) #define deg_cos(x) cosf((float) (x) * M_PI / 180.0)
#define deg_sin(x) sin((float) (x) * M_PI / 180.0) #define deg_sin(x) sinf((float) (x) * M_PI / 180.0)
/* All _possible_ tools */ /* All _possible_ tools */
enum enum
@ -347,17 +348,17 @@ void trochoids_work(magic_api * api, int which,
r = (r / 10) * 10; r = (r / 10) * 10;
/* Epitrochoid: rotator is outside the stator;
Hypotrochoid: rotator is inside the stator */
if (which == TOOL_HYPOTROCHOID_SIZES || if (which == TOOL_HYPOTROCHOID_SIZES ||
which == TOOL_HYPOTROCHOID_NOSIZES_1 || which == TOOL_HYPOTROCHOID_NOSIZES_1 ||
which == TOOL_HYPOTROCHOID_NOSIZES_2 || which == TOOL_HYPOTROCHOID_NOSIZES_2 ||
which == TOOL_HYPOTROCHOID_NOSIZES_3) { which == TOOL_HYPOTROCHOID_NOSIZES_3) {
r = -r - 2; /* Hypotrochoid */
r_ratio = (float) (R - r) / (float) r;
} else {
/* Epitrochoid */
r_ratio = (float) (R + r) / (float) r;
} }
r_ratio = (float) (R + r) / (float) r;
/* Size option (or use of alternate tools, if --nomagicsizes) /* Size option (or use of alternate tools, if --nomagicsizes)
determines the distance from the center of the rotator determines the distance from the center of the rotator
that the pen draws */ that the pen draws */
@ -378,16 +379,30 @@ void trochoids_work(magic_api * api, int which,
SDL_BlitSurface(snapshot, update_rect, canvas, update_rect); SDL_BlitSurface(snapshot, update_rect, canvas, update_rect);
/* Draw the lines */ /* Draw the lines */
LCM = calc_lcm(r, R); LCM = calc_lcm(r, R);
for (a = 0; a < 360.0 * (float) (LCM / R); a++) { for (a = 0; a < 360.0 * (float) (LCM / R); a++) {
float a2 = (a + 1); float a2 = (a + 1);
px = trochoids_x + (((R + r) * deg_cos(a)) + (d * deg_cos(r_ratio * a))); if (which == TOOL_HYPOTROCHOID_SIZES ||
py = trochoids_y + (((R + r) * deg_sin(a)) - (d * deg_sin(r_ratio * a))); which == TOOL_HYPOTROCHOID_NOSIZES_1 ||
px2 = trochoids_x + (((R + r) * deg_cos((a2))) + (d * deg_cos(r_ratio * a2))); which == TOOL_HYPOTROCHOID_NOSIZES_2 ||
py2 = trochoids_y + (((R + r) * deg_sin((a2))) - (d * deg_sin(r_ratio * a2))); which == TOOL_HYPOTROCHOID_NOSIZES_3) {
api->line((void *)api, which, canvas, snapshot, px, py, px2, py2, (20 * guides) + 1, trochoids_line_callback); /* Hypotrochoid */
px = trochoids_x + (((R - r) * deg_cos(a)) + (d * deg_cos(r_ratio * a)));
py = trochoids_y + (((R - r) * deg_sin(a)) - (d * deg_sin(r_ratio * a)));
px2 = trochoids_x + (((R - r) * deg_cos((a2))) + (d * deg_cos(r_ratio * a2)));
py2 = trochoids_y + (((R - r) * deg_sin((a2))) - (d * deg_sin(r_ratio * a2)));
} else {
/* Epitrochoid */
px = trochoids_x + (((R + r) * deg_cos(a)) - (d * deg_cos(r_ratio * a)));
py = trochoids_y + (((R + r) * deg_sin(a)) - (d * deg_sin(r_ratio * a)));
px2 = trochoids_x + (((R + r) * deg_cos((a2))) - (d * deg_cos(r_ratio * a2)));
py2 = trochoids_y + (((R + r) * deg_sin((a2))) - (d * deg_sin(r_ratio * a2)));
}
api->line((void *)api, which, canvas, snapshot, px, py, px2, py2, (20 * (guides && (a >= 360.0))) + 1, trochoids_line_callback);
} }
if (guides) { if (guides) {
@ -405,16 +420,38 @@ void trochoids_work(magic_api * api, int which,
api->xorpixel(canvas, px + 1, py + 1); api->xorpixel(canvas, px + 1, py + 1);
/* Rotator (rolling circle) */ /* Rotator (rolling circle) */
px = (int) ((float) trochoids_x + ((R + r) * deg_cos(rotator_anim_a)) + ((float) r * deg_cos(a))); if (which == TOOL_HYPOTROCHOID_SIZES ||
py = (int) ((float) trochoids_y + ((R + r) * deg_sin(rotator_anim_a)) - ((float) r * deg_sin(a))); which == TOOL_HYPOTROCHOID_NOSIZES_1 ||
which == TOOL_HYPOTROCHOID_NOSIZES_2 ||
which == TOOL_HYPOTROCHOID_NOSIZES_3) {
/* Hypotrochoid */
px = (int) ((float) trochoids_x + ((R - r) * deg_cos(rotator_anim_a)) + ((float) -r * deg_cos(a)));
py = (int) ((float) trochoids_y + ((R - r) * deg_sin(rotator_anim_a)) - ((float) -r * deg_sin(a)));
} else {
/* Epitrochoid */
px = (int) ((float) trochoids_x + ((R + r) * deg_cos(rotator_anim_a)) + ((float) r * deg_cos(a)));
py = (int) ((float) trochoids_y + ((R + r) * deg_sin(rotator_anim_a)) - ((float) r * deg_sin(a)));
}
api->xorpixel(canvas, px, py); api->xorpixel(canvas, px, py);
api->xorpixel(canvas, px + 1, py); api->xorpixel(canvas, px + 1, py);
api->xorpixel(canvas, px, py + 1); api->xorpixel(canvas, px, py + 1);
api->xorpixel(canvas, px + 1, py + 1); api->xorpixel(canvas, px + 1, py + 1);
} }
px = (int) ((float) trochoids_x + ((R + r) * deg_cos(rotator_anim_a)) + ((float) d * deg_cos(0)));
py = (int) ((float) trochoids_y + ((R + r) * deg_sin(rotator_anim_a)) - ((float) d * deg_sin(0))); /* Pen */
if (which == TOOL_HYPOTROCHOID_SIZES ||
which == TOOL_HYPOTROCHOID_NOSIZES_1 ||
which == TOOL_HYPOTROCHOID_NOSIZES_2 ||
which == TOOL_HYPOTROCHOID_NOSIZES_3) {
/* Hypotrochoid */
px = trochoids_x + (((R - r) * deg_cos(rotator_anim_a)) + (d * deg_cos(rotator_anim_a)));
py = trochoids_y + (((R - r) * deg_sin(rotator_anim_a)) - (d * deg_sin(rotator_anim_a)));
} else {
/* Epitrochoid */
px = trochoids_x + (((R + r) * deg_cos(rotator_anim_a)) - (d * deg_cos(rotator_anim_a)));
py = trochoids_y + (((R + r) * deg_sin(rotator_anim_a)) - (d * deg_sin(rotator_anim_a)));
}
for (int yy = -2; yy <= 2; yy++) { for (int yy = -2; yy <= 2; yy++) {
for (int xx = -2; xx <= 2; xx++) { for (int xx = -2; xx <= 2; xx++) {
api->putpixel(canvas, px + xx, py + yy, trochoids_color); api->putpixel(canvas, px + xx, py + yy, trochoids_color);