Modular multiplication on a circle

Here is yet another implementation of the drawing algorithm commonly known as "Modular multiplication on a circle", inspired by this Houdini tutorial and countless images, which were drawn using this very algorithm and are offered for purchasing in microstock agencies.

A word about Houdini implementation: instead of using multiple circles as the basis for generating lines as it is done in the mentioned above tutorial, one can do it in VEX code, as explained on the bottom of the page.

Number of steps Multiplier Line start offset Line end offset Colorize

Modular multiplication on a circle in Side FX Houdini using VEX

In order to generate the lines in Houdini VEX do the folloving:

VEX code of the basic algorithm - lines only

int steps = chi("Steps");
int multiplier = chi("Multiplier");
float scale = ch("Scale");
float angle = ch("Angle")/180*PI;

float step = PI*2/steps;
for (int i = 0; i < steps; ++i)
{
 addpoint(0, set(cos(angle)*scale, sin(angle)*scale, 0.0));
 angle += step;
}

for (int i = 0; i < steps; ++i)
{
 int primid = addprim(0, "polyline");
 addvertex(0, primid, i);
 addvertex(0, primid, i * multiplier % steps);
}

VEX code allowing to adjust length of the lines

int steps = chi("Steps");
int multiplier = chi("Multiplier");
float scale = ch("Scale");
float angle = ch("Angle")/180*PI;
float startoffset = ch("StartOffset");
float endoffset = ch("EndOffset");

int pointlerp(vector positionsarray[]; int p0, p1; float ratio)
{
 vector pos0 = positionsarray[p0];
 vector pos1 = positionsarray[p1];
 return addpoint(0, lerp(pos0, pos1, ratio));
}

float step = PI*2/steps;
vector positions[] = {};
for (int i = 0; i < steps; ++i)
{
 vector pos = set(cos(angle)*scale, sin(angle)*scale, 0.0);
 push(positions, pos);
 addpoint(0, pos);
 angle += step;
}

for (int i = 0; i < steps; ++i)
{
 int primid = addprim(0, "polyline");
 if(startoffset == 0 && endoffset == 0)
 {
  addvertex(0, primid, i);
  addvertex(0, primid, i * multiplier % steps);
 }
 else
 {
  int endpt = i * multiplier % steps;
  int startpt = startoffset == 0 ? i : pointlerp(positions, i, endpt, startoffset);
  if(endoffset != 0)
  endpt = pointlerp(positions, endpt, i, endoffset);
  addvertex(0, primid, startpt);
  addvertex(0, primid, endpt);
 }
}
The article was created on 1/22/2018