I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Peripheral drift illusion

Peripheral drift illusion
You are encouraged to solve this task according to the task description, using any language you may know.

Generate and display a Peripheral Drift Illusion

The image appears to be moving even though it is perfectly static.

Provide a link to show the output, either by running the code online or a screenshot uploaded to a suitable image host.

References

## Action!

`PROC DrawTile(INT x BYTE y,flip,c1,c2)  BYTE i   Color=1  FOR i=y+2 TO y+11  DO    Plot(x+1,i) DrawTo(x+5,i)  OD  Color=c1  IF flip THEN    Plot(x,y+12) DrawTo(x,y) DrawTo(x+6,y)  ELSE    Plot(x,y) DrawTo(x+6,y) DrawTo(x+6,y+12)  FI  Plot(x+1,y+1) DrawTo(x+5,y+1)  Color=c2  IF flip THEN    Plot(x,y+13) DrawTo(x+6,y+13) DrawTo(x+6,y+1)  ELSE    Plot(x,y+1) DrawTo(x,y+13) DrawTo(x+6,y+13)  FI  Plot(x+1,y+12) DrawTo(x+5,y+12)RETURN PROC Draw()  INT x,y,n  BYTE flip,c1,c2   FOR y=0 TO 8  DO    FOR x=0 TO 15    DO      n=(x-y)&15      IF (n RSH 2)&1 THEN        flip=1      ELSE        flip=0      FI      IF (n RSH 3)&1 THEN        c1=3 c2=2      ELSE        c1=2 c2=3      FI      DrawTile(x*10,y*20+6,flip,c1,c2)    OD  ODRETURN PROC Main()  BYTE CH=\$02FC ;Internal hardware value for last key pressed  BYTE PALNTSC=\$D014 ;To check if PAL or NTSC system is used   Graphics(15+16)  IF PALNTSC=15 THEN    SetColor(4,14,10) ;yellow for NTSC    SetColor(0,8,4)   ;blue for NTSC  ELSE    SetColor(4,13,10) ;yellow for PAL    SetColor(0,7,4)   ;blue for PAL  FI  SetColor(1,0,0)  SetColor(2,0,14)  Draw()   DO UNTIL CH#\$FF OD  CH=\$FFRETURN`
Output:

## Julia

Line color tables taken from the Wren example. See the output on imgur.

`using Gtk, Colors, Cairo function CodepenApp()    # left-top, top-right, right-bottom, bottom-left    LT, TR, RB, BL = 1, 2, 3, 4    edges = [        [LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],        [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],        [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],        [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT],        [RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT],        [RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR],        [BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR],        [BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB],        [LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],        [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],        [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],        [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT]]    W, B = colorant"white", colorant"darkgray"    colors = [        [W, B, B, W],        [W, W, B, B],        [B, W, W, B],        [B, B, W, W]]    win = GtkWindow("Peripheral drift illusion", 230, 230) |> (can = GtkCanvas())    @guarded draw(can) do widget        ctx = Gtk.getgc(can)        function line(x1, y1, x2, y2, colr)            set_source(ctx, colr)            move_to(ctx, x1, y1)            line_to(ctx, x2, y2)            stroke(ctx)        end        set_source(ctx, colorant"yellow")        rectangle(ctx, 0, 0, 250, 250)        fill(ctx)        set_line_width(ctx, 2)        for x in 1:12            px = 18 + x * 14            for y in 1:12                py = 18 + y * 14                set_source(ctx, colorant"skyblue")                rectangle(ctx, px, py, 10, 10)                fill(ctx)                carray = colors[edges[y][x]]                line(px, py, px + 9, py, carray[1])                line(px + 9, py, px + 9, py + 9, carray[2])                line(px + 9, py + 9, px, py + 9, carray[3])                line(px, py + 9, px, py, carray[4])            end        end    end    showall(win)    draw(can)    condition = Condition()    endit(w) = notify(condition)    signal_connect(endit, win, :destroy)    showall(win)    wait(condition)end CodepenApp() `

## Nim

Translation of: Julia
Library: gintro

A translation using Gtk via the `gintro` bindings for Nim, so the code is quite different. We chose also different sizes for the window and the grid, and colors closer to those of the codepen demo.

See window screenshot here.

`import gintro/[glib, gobject, gtk, gio, cairo] const  Width = 600  Height = 460 type  Color = array[3, float]  Edge {.pure.} = enum LT, TR, RB, BL const   Edges = [[LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],           [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],           [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],           [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT],           [RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT],           [RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR],           [BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR],           [BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB],           [LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],           [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],           [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],           [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT]]   Black: Color = [0.0, 0.0, 0.0]  Blue: Color = [0.2, 0.3, 1.0]  White: Color = [1.0, 1.0, 1.0]  Yellow: Color = [0.8, 0.8, 0.0]   Colors: array[Edge, array[4, Color]] = [[White, Black, Black, White],                                          [White, White, Black, Black],                                          [Black, White, White, Black],                                          [Black, Black, White, White]] #--------------------------------------------------------------------------------------------------- proc draw(area: DrawingArea; context: Context) =  ## Draw the pattern in the area.   func line(x1, y1, x2, y2: float; color: Color) =    context.setSource(color)    context.moveTo(x1, y1)    context.lineTo(x2, y2)    context.stroke   context.setSource(Yellow)  context.rectangle(0, 0, Width, Height)  context.fill()   for x in 0..11:    let px = float(86 + x * 36)    for y in 0..11:      let py = float(16 + y * 36)      context.setSource(Blue)      context.rectangle(px, py, 24, 24)      context.fill()      let carray = Colors[Edges[y][x]]      context.setLineWidth(2)      line(px, py, px + 23, py, carray[0])      line(px + 23, py, px + 23, py + 23, carray[1])      line(px + 23, py + 23, px, py + 23, carray[2])      line(px, py + 23, px, py, carray[3]) #--------------------------------------------------------------------------------------------------- proc onDraw(area: DrawingArea; context: Context; data: pointer): bool =  ## Callback to draw/redraw the drawing area contents.   area.draw(context)  result = true #--------------------------------------------------------------------------------------------------- proc activate(app: Application) =  ## Activate the application.   let window = app.newApplicationWindow()  window.setSizeRequest(Width, Height)  window.setTitle("Peripheral drift illusion")   # Create the drawing area.  let area = newDrawingArea()  window.add(area)   # Connect the "draw" event to the callback to draw the pattern.  discard area.connect("draw", ondraw, pointer(nil))   window.showAll() #——————————————————————————————————————————————————————————————————————————————————————————————————— let app = newApplication(Application, "Rosetta.Illusion")discard app.connect("activate", activate)discard app.run()`

## Perl

`use strict;use warnings; my \$svg = <<'EOD';<svg xmlns="http://www.w3.org/2000/svg"     xmlns:svg="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink" width="1200" height="825">     <rect width="100%" height="100%" fill="#d3d004" />     <defs>        <g id="block">            <polygon points="-25,-25,-25,25,25,25" fill="white" />            <polygon points="25,25,25,-25,-25,-25" fill="black" />            <rect x="-20" y="-20" width="40" height="40" fill="#3250ff" />        </g>     </defs>EOD for my \$X (1..15) {   for my \$Y (1..10) {    my \$r = int((\$X + \$Y) / 2) % 4 * 90;    my \$x = \$X * 75;    my \$y = \$Y * 75;    my \$a = \$r > 0 ? "rotate(\$r,\$x,\$y) " : '';    \$svg .= qq{<use xlink:href="#block" transform="\$a translate(\$x,\$y)" />\n}  }}\$svg .= '</svg>'; open my \$fh, '>', 'peripheral-drift.svg';print \$fh \$svg;close \$fh;`

## Phix

Library: Phix/online

You can run this online here.

```--
-- demo\rosetta\Peripheral_Drift_Illusion.exw
-- ==========================================
--
-- converted from https://codepen.io/josetxu/pen/rNmXjrq
--
with javascript_semantics
include pGUI.e
Ihandle dlg, canvas
cdCanvas cdcanvas

constant title = "Peripheral Drift Illusion",
CD_LIGHT_OLIVE = #d3d004,
CD_PALE_BLUE = #3250ff,
dxy = {{45,45},{0,45},{0,0},{45,0},{45,45},{0,45}}

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
cdCanvasActivate(cdcanvas)
cdCanvasSetBackground(cdcanvas, CD_LIGHT_OLIVE)
cdCanvasClear(cdcanvas)
integer c = 0,
cy = floor(height/2)*2-81
while cy>100 do
integer d = c,
cx = 81
while cx<width-100 do
cdCanvasSetForeground(cdcanvas, CD_WHITE)
cdCanvasBox(cdcanvas, cx, cx+45, cy, cy-45)
cdCanvasSetForeground(cdcanvas, CD_BLACK)
cdCanvasBegin(cdcanvas, CD_FILL)
for i=4 to 6 do
integer {dy,dx} = dxy[i-d]
cdCanvasVertex(cdcanvas, cx+dx, cy-dy)
end for
cdCanvasEnd(cdcanvas)
cdCanvasSetForeground(cdcanvas, CD_PALE_BLUE)
cdCanvasBox(cdcanvas, cx+4, cx+41, cy-4, cy-41)
d = remainder(d+(odd(cx)==odd(cy)),4)
cx += 63
end while
c = remainder(c+4-even(cy),4)
cy -= 63
end while
cdCanvasFlush(cdcanvas)
return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
IupGLMakeCurrent(canvas)
if platform()=JS then
cdcanvas = cdCreateCanvas(CD_IUP, canvas)
else
cdcanvas = cdCreateCanvas(CD_GL, "10x10 %g", {res})
end if
cdCanvasSetBackground(cdcanvas, CD_PARCHMENT)
return IUP_DEFAULT
end function

function canvas_resize_cb(Ihandle /*canvas*/)
integer {cw, ch} = IupGetIntInt(canvas, "DRAWSIZE")
atom res = IupGetDouble(NULL, "SCREENDPI")/25.4
cdCanvasSetAttribute(cdcanvas, "SIZE", "%dx%d %g", {cw, ch, res})
return IUP_DEFAULT
end function

procedure main()
IupOpen()
canvas = IupGLCanvas("RASTERSIZE=780x600") -- (sensible restore size)
sequence cb = {"MAP_CB", Icallback("map_cb"),
"ACTION", Icallback("redraw_cb"),
"RESIZE_CB", Icallback("canvas_resize_cb")}
IupSetCallbacks(canvas, cb)
dlg = IupDialog(canvas,`TITLE="%s",PLACEMENT=MAXIMIZED`,{title})
IupShow(dlg)
if platform()!=JS then
IupMainLoop()
IupClose()
end if
end procedure
main()
```

## Raku

`use SVG; my @blocks = (1..15 X 1..10).map: -> (\$X, \$Y) {    my \$x = \$X * 75;    my \$y = \$Y * 75;    my \$a = (my \$r = (\$X + \$Y) div 2 % 4 * 90) > 0 ?? "rotate(\$r,\$x,\$y) " !! '';    :use['xlink:href'=>'#block', 'transform'=>"{\$a}translate(\$x,\$y)"]} 'peripheral-drift-raku.svg'.IO.spurt: SVG.serialize(    svg => [        :1200width, :825height,        :rect[:width<100%>, :height<100%>, :fill<#d3d004>],        :defs[            :g[                :id<block>,                :polygon[:points<-25,-25,-25,25,25,25>, :fill<white>],                :polygon[:points<25,25,25,-25,-25,-25>, :fill<black>],                :rect[:x<-20>, :y<-20>, :width<40>, :height<40>, :fill<#3250ff>]            ]        ],        |@blocks,    ])`

## Wren

Library: DOME

This reproduces the codepen image and does indeed appear to move although it's static. See the output on imgur

`import "dome" for Windowimport "graphics" for Canvas, Color // signifies the white edges on the blue squaresvar LT = 0var TR = 1var RB = 2var BL = 3 var Edges = [    [LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],    [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],    [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],    [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT],    [RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT],    [RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR, TR],    [BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB, TR],    [BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB, RB],    [LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL, RB],    [LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL, BL],    [TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT, BL],    [TR, TR, LT, LT, BL, BL, RB, RB, TR, TR, LT, LT]] var Light_olive = Color.hex("#d3d004")var Pale_blue   = Color.hex("#3250ff") var W = Color.whitevar B = Color.black var Colors = [    [W, B, B, W],    [W, W, B, B],    [B, W, W, B],    [B, B, W, W]] class PeripheralDrift {    construct new() {        Window.resize(1000, 1000)        Canvas.resize(1000, 1000)        Window.title = "Peripheral drift illusion"    }     init() {        Canvas.cls(Light_olive)        for (x in 0..11) {            var px = 90 + x * 70            for (y in 0..11) {                var py = 90 + y * 70                Canvas.rectfill(px, py, 50, 50, Pale_blue)                drawEdge(px, py, Edges[y][x])            }        }    }     drawEdge(px, py, edge) {        var c = Colors[edge]        Canvas.line(px, py, px + 46, py, c[0], 4)        Canvas.line(px + 46, py, px + 46, py + 46, c[1], 4)        Canvas.line(px, py + 46, px + 46, py + 46, c[2], 4)        Canvas.line(px, py + 46, px, py, c[3], 4)    }     update() {}     draw(alpha) {}} var Game = PeripheralDrift.new()`