1. This picture is a modification of the algorithm of the Rotor Router that presents a nice shape.The modification is an additional step in the rotor router “up/down/left/right” where:
When the rotor has been moved, the agent goes to the next location. If in this next location the direction is in the same direction as the agent at source, then rotate it. Then continue the loop..
The number of iterations of the algorithm is 3 Millions with the sample on the right and 55K on the left.
What is interesting with this extension is that most of the internal features of the rotor router are moved to the bottom part.
The obtained shape seems to be inscribed in a spiral. (unclear which one)
2. This picture uses the rotor router algorithm (up,down,left,right) with the following extension:
In the rotor router agent iteration loop is added this extension:
- If the agent value at initial position equals "up" and if the current agent location equals "down", then set the rotor of this position to "up".
- If the agent value at initial position equals "down" and if the current agent location equals "down", then set the rotor of this position to "up".
What is nice with this extension is that:
-the circle aspect is maintained. (unclear if it is actually a circle)
-most of the internal Moiré features of the original rotor router algorithm are removed.
3.b
there is a better way to remove the Moiré effect.
simply in the rotor router algorithm, when arriving to an empty position, instead of setting it to "UP" set it to the current agent value at center position.
As a result, this algorithm might show an improved quasirandom effect.
It may also give a hint about the internal Moiré effect that is present because of the setting of an empty cell to UP.
Second picture is 3M iterations.
There is also an alternate way to remove the moiré not presented in this page where if the number of hop made by the agent is odd then set the empty cell to 1 else set the empty cell to 0.
3.c
Sophisticating this approach where an empty cell is fno more filled to "UP" in the "up,down,left,right" rotor router algorithm, it is possible to erase only portions of the Moiré.
In this example, when arriving to an empty position, the agent is set to the agent value used at the center at the beginning of the iteration only if the currentAgentValue is the same as in the adjacent pixel up.
if (grid[agentCurrentPositionx][agentCurrentPositiony] == 0)
{ if(grid[agentCurrentPositionx][agentCurrentPositiony-1] == agentCurrentValue){grid[agentCurrentPositionx]
[agentCurrentPositiony] = agentCurrentValue;}else{grid[agentCurrentPositionx][agentCurrentPositiony] =1;}
What is interesting doing so is that by chaning the matching adjacent or combining mulitple matchs, it is possible to scramble specific parts of the Moiré.
This picture presents the UDLR rotor router with the extension of case3c but with an initialization of the grid with a square with UP value prior to launching the algorithm.
You may notice that the shape is similar to the one you may see on the moon Jellyfish (Aurelia Aurita).
https://en.wikipedia.org/wiki/Aurelia_aurita#/media/File:Aurelia_aurita_2.jpg
This picture presents the UDLR rotor router with the extension of case3c but with an initialization of the grid with a circle with UP value prior to launching the algorithm.
These pictures presents the also the UDLR rotor router algorithm launched on a grid in which is initialized with embedded circles of UP and DOWN values.
It is interresting to observe that the rotor router algorithm UDLR show the pattern of a magnetic quadrupole while with the background initialisation described here we get something Like a dipole magnet.
3. This picture uses the rotor router algorithm (up,down,left,right) with the following extension:
In the rotor router agent iteration loop is added this extension:
- If the agent value at initial position equals "right" and if the current agent location equals "left", then set the rotor of this position to right.
What we observe this extension is that:
-the circle is not maintained.
-most of the internal Moiré features of the original rotor router algorithm are still there
C code:
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 4 && agentCurrentValue==2)
{
grid[agentCurrentPositionx][agentCurrentPositiony]=2;
}
4. this picture is yet another modification in the rotor router algorithm.
the grid represents the current agent location and the agentvalue at origin is
is used to make an additional rotation in some pixels if the here after rule is true:
if(grid[agentCurrentPositionx+agentCurrentValue-2][agentCurrentPositiony
+agentCurrentValue-2]== agentCurrentValue)
{
grid[agentCurrentPositionx+agentCurrentValue-2][agentCurrentPositiony+agentCurrentValue-
2]=agentCurrentValue+1;
if(grid[agentCurrentPositionx+agentCurrentValue-2][agentCurrentPositiony
+agentCurrentValue-2]==5)
{
grid[agentCurrentPositionx+agentCurrentValue-2][agentCurrentPositiony
+agentCurrentValue-2]=1;
}
}
The point here is that almost no features are maintained and the shape has symetries.
5. this picture is still the rotor router algorithm with a modification of another kind.
Here in the agent iteration loop, when the current agent position equals "right"
move it to left and reset the rotor in the previous position to "down".
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 4)
{
agentCurrentPositionx++;
// then reset previous position
grid[agentCurrentPositionx-1][agentCurrentPositiony]=3;
}
What is of interest here is that we get an elipse. there is also not much features of the original rotor router remaining. there are 300K iterations in this picture.
Full C Code for the 3.b case:
// extract from https://sites.google.com/site/projectsced/
long grid[10001][10001];
int main (int argc , char *argv[])
{
printf("\nrotor router program from CED builds an image");
printf("\nrule is the rotor router UDLR but with additional rule to make funny form ");
// Main algorithm run as a memory map
char *cmd;
cmd=malloc(1024);
// build the svg file from the memory map
// initialize the 2D array
printf("DEBUG: create 2D array");
/* 2D array declaration*/
long maxx = 10000;
long maxy = 10000;
long centerx = 5000;
long centery = 5000;
long agentCurrentPositionx = 0;
long agentCurrentPositiony = 0;
long agentCurrentValue = 4;
long numberOfAlgoIterations = 100000;
/*Counter variables for the loop*/
long i, j, k;
long endAgentIteration=1;
long firstcenterpass=0;
int test=0;
int itcounter=0;
int itflag=0;
printf("DEBUG: grid created");
//init to 0 the array
for(i=0; i<=maxx; i++)
{
for(j=0; j<=maxy; j++)
{
grid[i][j]=0;
//printf("DEBUG: %i",grid[i][j]);
}
}
printf("DEBUG: grid initialized");
//main loop:
for(k=0; k<=numberOfAlgoIterations; k++)
{
//agent position init:
agentCurrentPositionx=centerx;
agentCurrentPositiony=centery;
// init starting value for agent
if(agentCurrentValue < 4)
{
agentCurrentValue++;
}
else
{
agentCurrentValue=1;
}
//agent iteration loop
endAgentIteration=0;
firstcenterpass=0;
itcounter=0;
itflag=0;
while (endAgentIteration == 0)
{
//this part to faster detect probable endlessloops
itflag=0;
itcounter++;
if(itcounter>2000000 && itflag==0)
{
printf("\nDEBUG: loop 2M at %i",k);
itflag=1;
}
//we arrive to a new position
if (grid[agentCurrentPositionx][agentCurrentPositiony] == 0)
{
//empty position found
grid[agentCurrentPositionx][agentCurrentPositiony] = agentCurrentValue;
// in original rotor router this is set to UP while I set here to the agentCurrentValue
// this is an important modification that removes the moiré
endAgentIteration=1;
agentCurrentPositionx=centerx;
agentCurrentPositiony=centery;
}
if (endAgentIteration==0)
{
if(endAgentIteration==0)
{
//the agent is positive and the position is positive, lets continue the move
//then move to this direction
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 1)
{
agentCurrentPositiony--;
// then rotate the rotor of the previous position
if(grid[agentCurrentPositionx][agentCurrentPositiony+1] < 4)
{
grid[agentCurrentPositionx][agentCurrentPositiony+1]=grid[agentCurrentPositionx][agentCurrentPositiony+1]+1;
}
else
{
grid[agentCurrentPositionx][agentCurrentPositiony+1]= 1;
}
}
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 4)
{
agentCurrentPositionx++;
// then rotate the rotor of the previous position
if(grid[agentCurrentPositionx-1][agentCurrentPositiony] < 4)
{
grid[agentCurrentPositionx-1][agentCurrentPositiony]=grid[agentCurrentPositionx-1][agentCurrentPositiony]+1;
}
else
{
grid[agentCurrentPositionx-1][agentCurrentPositiony]= 1;
}
}
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 2)
{
agentCurrentPositiony++;
// then rotate the rotor of the previous position
if(grid[agentCurrentPositionx][agentCurrentPositiony-1] < 4)
{
grid[agentCurrentPositionx][agentCurrentPositiony-1]=grid[agentCurrentPositionx][agentCurrentPositiony-1]+1;
}
else
{
grid[agentCurrentPositionx][agentCurrentPositiony-1]= 1;
}
}
if(grid[agentCurrentPositionx][agentCurrentPositiony]== 3)
{
agentCurrentPositionx--;
// then rotate the rotor of the previous position
if(grid[agentCurrentPositionx+1][agentCurrentPositiony] < 4)
{
grid[agentCurrentPositionx+1][agentCurrentPositiony]=grid[agentCurrentPositionx+1][agentCurrentPositiony]+1;
// grid[agentCurrentPositionx+1][agentCurrentPositiony]=0;
}
else
{
grid[agentCurrentPositionx+1][agentCurrentPositiony]=0;
}
}
}
}
}
All images presented in this website are courtesy of Cedric Vandenweghe at https://sites.google.com/site/projectsced/home
Please feel free to leave me a comment at rotorrouterprojectsced (at) gmail.com.