RoseEngine

Documentation for RoseEngine.

I first learned abot rose engines from the ClixkSpring YouTube channel. Other information and inspiration came from the channels of Uri Tuckman and DM Tiffany Timepieces.

A rose engine is similar to a lathe but has cams on the spindle which can control the position of the cross slide and thus the radius of the cutter from the axis of the spindle.

This can be modeled by a function that maps a parametric angle - the rotation of the spindle - to the radius of the cutter from the spindle's axis. This function is implemented by the Rotor struct.

Because each of the cams on a rose engine has an integer number of lobes, the rose engine also has a way to offset the cam from the axis of rotation by an initial phase angle. A rose engine also has a way to add an initial phase angle to the axis of rotation. We model this using PhasedRotor.

Wave Functions

Rotor expects a wave functioon. These are the available wave functions

Writing an SVG File

A real rose engine is a continuous, analog machine. On a digital computer we can only use discreet steps. To generate our pattern we use a sequence of discreet steps at which we compute the position of the cutter. This step size is specified by a step_angle parameter. The graphic is generated starting with a step_angle of 0 and incrementing it by step_angle until the cutter returns to its starting position. This is performed by svg_path_for_rotor.

My CNC router (Shaper Origin) is driven by an SVG file. Here's how I can write one from this package:

using RoseEngine
rotor = Rotor(3, 1//2, 1//8, sine_wave)
render_rotors(joinpath(@__DIR__, "svg-example-1.svg"),
              map([ 0, 1//32, 2//32, 3//32 ]) do phase
                  PhasedRotor(rotor, phase)
              end,
              1//256)
false

Here's the resulting file:

using RoseEngine
rotor = Rotor(3, 1, 13//29, sine_wave)
render_rotors(joinpath(@__DIR__, "svg-example-2.svg"),
              rotor,
              1//256)
false
using RoseEngine
rotor = Rotor(3, 1, 43//5, triangle_wave)
render_rotors(joinpath(@__DIR__, "svg-example-3.svg"),
              rotor,
              1//256)
false

Index

Other Definitions

RoseEngine.PhasedRotorType
PhasedRotor(::Rotor, initial_phase_angle)

PhasedRotor encapsulates a Rotor to provide an initial phase angle offset when drawing the rotor.

source
RoseEngine.RotorType
Rotor(radius, amplitude, waves_per_rotation)

Rotor is a function that for a given angle, returns a radius from the center of the Rotor's spindle. In this package, angles are in units of fractions of a full circle, arther than in degrees or radians.

radius is the radius at zero amplitude.

amplitude is the extent above and below radius of the range of the "cutter". The range of the Rotor funnction will be from radius - amplitude to radius + amplitude.

wave_function is a function describing one cycle of the wave. Its domain goes from 0 to 1 and its range goes from -1 to 1. See [triangle_wave(@ref) as an example.

waves_per_rotation is the number of full oscillations of wave_function per one turn of the Rotor.

source
RoseEngine.full_cycle_countMethod
full_cycle_count(::AbstractRotor)::Int

Returns the number of cycles that the Rotor should rotate such that its wave_function returns to its starting point (same angle and radius). This is an integer number of full rotations of the rootor.

source
RoseEngine.input_rangeMethod
input_range(::AbstractRotor, step_angle::Rational)

Returns a Julia AbstractRange that will fully generate the design of the Rotor when the rotor function is applied to the values of that range.

source
RoseEngine.svg_path_for_rotorMethod
svg_path_for_rotor(rotor::Rotor, step_angle::Rational)

Returns an SVG path expression suitable for the value of the d attribute of an SVG path to draw the design specified by the Rotor. Also returns the minimum and maximum x and y coordinates of the path.

source