# Optical illusion: are these lines parallel or not?

**URL:** <https://discourse.processing.org/t/optical-illusion-are-these-lines-parallel-or-not/17385>\
**Category:** Gallery\
**Created:** [January 27, 2020, 9:00pm UTC](https://discourse.processing.org/t/optical-illusion-are-these-lines-parallel-or-not/17385 "2020-01-27T21:00:24Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![trikaphundo](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/trikaphundo/32/7913_2.png) [@trikaphundo](https://discourse.processing.org/u/trikaphundo)\
**Post date:** [January 27, 2020, 9:00pm UTC](https://discourse.processing.org/t/optical-illusion-are-these-lines-parallel-or-not/17385/1 "2020-01-27T21:00:24Z")

</div>

Hello, I joined recently the forum.

I’ve decided to share some of my sketches which, I believe, some may find interesting.

From time to time, I like wandering the Internet to look for ideas on maths and arts. I came across [this optical illusion](https://szimmetria-airtemmizs.tumblr.com/post/170377417893/illusion-the-horizontal-lines-between-the) in a Tumblr blog and I decided to make a sketch out of it. This is a gif with the result; you can find the code below to run the animation endlessly.

![illusio_optica](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/a/a64d92c8f144afd7177e1eb6d8fe3ecea4599a2b.gif)

> **main sketch**
>
> ```auto
> /*
> Intent to reproduce the following optical illusion: 
> https://szimmetria-airtemmizs.tumblr.com/post/170377417893/illusion-the-horizontal-lines-between-the
>  
> The animation loops forever with a period set
> via the variable 'duration_secs'.
>  
> The image can be divided into rows of squares,
> some of which move, while other don't.
>  
> The visual part (render, colours, etc.) is managed
> by the class 'Row'; on the other hand, the dynamic
> of the mobile rows are carried out by the class 'DynSyst'.
> */
> Row[] rows;
> int q_rows;
> int q_squares; // squares per row
> float edge; // edge of the squares
> float duration_secs; // duration of the animation, in secs
> DynSyst sd;
> 
> void setup() {
> size(640, 480);
> //fullScreen();
> frameRate(34);
> 
> //background(80);
> rectMode(CENTER); // important
> stroke(120);
> strokeWeight(2);
> 
> duration_secs = 6; // 6 seconds
> edge = 80;
> q_rows = int(height / edge) + 1;
> q_squares = int(width / edge) + 5;
> 
> float cx_ini = -2 * edge; // abscissa of all rows' position
> 
> sd = new DynSyst(cx_ini, 3.f * edge / 4, duration_secs);
> rows = new Row[q_rows];
> for (int i = 0; i < rows.length; i++) {
> rows[i] = new Row(cx_ini, i * edge, edge, q_squares);
> rows[i].is_mobile = i % 2 == 0 ? false : true;
> rows[i].draw();
> }
> }
> 
> void draw() {
> sd.iterate();
> for (int i = 0; i < rows.length; i++) {
> rows[i].update(sd.x);
> rows[i].draw();
> }
> }
> 
> ```

> **class for the motion bits**
>
> ```auto
> /*
> Class representing a (discrete) simple harmonic motion (SHM).
> A simple harmonic motion is a sort of periodic motion,
> which is described by a sinusoidal function.
>  
> This class will be using this one:
> x(t) = A * sin(w * t + a)
>  
> Where:
> -A is the amplitude of the motion.
> -w is the angular velocity, calculated as w = 2 * PI / T.
> -T is the motion's period, in seconds.
> -a is the initial phase, which we'll take as 0.
>  
> By <em>discrete</em>, it is meant that the time variable
> changes in a discrete manner, instead of continuously.
> In each iteration the time variable's value is incremented
> by a fixed value.
>  
> This fixed value is related to the sketch's frameRate
> and guarantees that, if the dynamical system's 'iterate()'
> method is called once per frame, the animation has period T.
> */
> class DynSyst {
> final float DELTA_T = 1.f / frameRate; // time increment per iteration
> private float cx; // center or equilibrium point of the SHM
> float x; // position at time t
> float amplitude;
> float period;
> float ang_vel;
> float t;
> 
> DynSyst(float cx, float amplitude, float period_secs) {
> this.cx = x = cx;
> this.amplitude = amplitude;
> period = period_secs;
> ang_vel = 2 * PI / period;
> t = 0.f;
> }
> 
> /*Increments dynamical system's time variable
> and returns the position at this new time.*/
> float iterate() {
> t += DELTA_T;
> if (t >= period) {
> t = 0.f;
> }
> x = cx + amplitude * sin(ang_vel * t);
> 
> return x;
> }
> }
> 
> ```

> **class for the visual bits**
>
> ```auto
> /*
> Class representing a row of squares with alternating colours.
> The row's position is the center of its first (left-most) square.
> */
> class Row {
> private float cx_ini; // row's initial abscissa
> float cx, cy; // row's current position
> float edge;
> int q_squares; // quantity of squares
> color c1 = #ffffff, c2 = #000000; // colours to alternate between
> boolean is_mobile;
> 
> /**/
> Row(float cx, float cy, float edge, int q_squares) {
> this.cx = cx_ini = cx;
> this.cy = cy;
> this.edge = edge <= 0.f ? 0.f : edge;
> this.q_squares = q_squares <= 0 ? 0 : q_squares;
> is_mobile = false;
> }
> 
> void update(float cx) {
> if (is_mobile) {
> this.cx = cx;
> }
> }
> 
> /*Draws this row alternating the colour of the squares.
> Assumes rectMode(CENTER) has been set.*/
> void draw() {
> color c;
> 
> c = c1;
> for (int i = 0; i < q_squares; i++) {
> draw_square(cx + i * edge, cy, edge, c);
> c = c == c1 ? c2 : c1;
> }
> }
> 
> /*Draws a square given its center, edge and colour.
> Assumes rectMode(CENTER) has been set.*/
> private void draw_square(float cx, float cy, float edge, color c) {
> fill(c);
> rect(cx, cy, edge, edge);
> }
> }
> 
> ```

* * *

Feel free to make any comments, suggestions or even post back your tinkers.
