Optical illusion parallel lines

Asked

Viewed 59 times

2

I have the following exercise that asks me to draw an optical illusion like the following:Ilusão óptica parede do café

But I’m not finding a simple way to make the code so that it does this progression where it goes one square forward and then a few backwards. Now I’m missing the "detours":

import javafx.application.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.scene.shape.*;
import javafx.embed.swing.*;
import javafx.application.*;
import javafx.scene.text.*;
import java.util.*;
import javafx.scene.paint.Color;


public class Ilusão2  {  
    private Pane pane;
    private void start(Stage primaryStage) 
  {
    primaryStage.setOnCloseRequest(
        e -> Platform.runLater( () -> {Platform.exit(); System.exit(0);} ) 
  ); 

    // https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Pane.html
    this.pane = new Pane();
    this.pane.setPrefSize(750, 600);
    primaryStage.setScene(new Scene(this.pane, Color.BLACK));
    primaryStage.show();

    this.squares(10);
    this.lines(1);
} // END start

/**
 * Add shape to pane 
 */
public void addShape(Shape shape)
{
     Platform.runLater(() -> this.pane.getChildren().add(shape));
}

/** execute this method to start the program
 * executing the code in method start(Stage primaryStage) 
 */
public static void start()
{
    Ilusão2 drawingApp = new Ilusão2();
    drawingApp.launch();
}

public void launch()
{
    // Initialises JavaFX:
    new JFXPanel();
    // Makes sure JavaFX doesn't exit when first window is closed:
    Platform.setImplicitExit(false);
    // Runs initialisation on the JavaFX thread:
    Platform.runLater(() -> start(new Stage()));
}

public Ilusão2() 
{
    super();
}

private void squares(int squares)
{
    int width = 50;
    int heigth = width;
    for(int j = 100;j<=450;j+=50)
    {
    for(int i =50;i<=700;i+=100)
    {
     Rectangle square = new Rectangle(i,j,width,heigth);
     square.setStrokeWidth(3);
     square.setStroke(Color.GREY);
     square.setFill(Color.WHITE);
     pane.getChildren().add(square);
    }

    // for (int i = 50;i<=1000;i+=100)
    // {
     // for(int k = 0;k<=600;k+=50)
     // {
         // Rectangle squaresLow = new Rectangle(i,k,width,heigth);
         // squaresLow.setStrokeWidth(1);
         // squaresLow.setStroke(Color.GREY);
         // squaresLow.setFill(Color.WHITE);
         // pane.getChildren().add(squaresLow);
        // }
    // }
}
}

private void lines(int lines)
{
 int xInit= 0;
 int xFin=750;
 for(int y = 100;y<=500;y+=50)
 {
 Line line = new Line (xInit,y,xFin,y);
 line.setStrokeWidth(3);
 line.setStroke(Color.GREY);
 pane.getChildren().add(line);
}

}
} // END class World

This code makes:

Tentativa de ilusão

  • By the figure, what you need is to create a sequence where the line below is a little ahead of the first, and the third is a little behind the second. And repeat these 3 examples.

1 answer

4


I added a bit of code that basically checks which rectangle line is being created in the current loop iteration and sets the appropriate increment in the x-position (each row has its own increment in the x-position, which can be 0, 20, or 40). It is this increment that is creating the "deviations" that you spoke of.

See the result:

Resultado obtido pelo código abaixo (ilusão de ótica similar ao desejado)

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class Ilusao2 {
    private Pane pane;

    private void start(Stage primaryStage) {
        primaryStage.setOnCloseRequest(e -> Platform.runLater(() -> {
            Platform.exit();
            System.exit(0);
        }));

        // https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Pane.html
        this.pane = new Pane();
        this.pane.setPrefSize(710, 600);
        primaryStage.setScene(new Scene(this.pane, Color.BLACK));
        primaryStage.show();

        this.squares(10);
        this.lines(1);
    } // END start

    /**
     * Add shape to pane
     */
    public void addShape(Shape shape) {
        Platform.runLater(() -> this.pane.getChildren().add(shape));
    }

    /**
     * execute this method to start the program executing the code in method
     * start(Stage primaryStage)
     */
    public static void start() {
        Ilusao2 drawingApp = new Ilusao2();
        drawingApp.launch();
    }

    public void launch() {
        // Initialises JavaFX:
        new JFXPanel();
        // Makes sure JavaFX doesn't exit when first window is closed:
        Platform.setImplicitExit(false);
        // Runs initialisation on the JavaFX thread:
        Platform.runLater(() -> start(new Stage()));
    }

    public Ilusao2() {
        super();
    }

    private void squares(int squares) {
        int width = 50;
        int heigth = width;
        int linhaAtual = 0;
        for (int j = 100; j <= 450; j += 50) {
            for (int i = 10; i <= 700; i += 100) {
                int xIncremento = definirIncrementoEmX(linhaAtual);
                Rectangle square = new Rectangle(i + xIncremento, j, width, heigth);
                square.setStrokeWidth(3);
                square.setStroke(Color.GREY);
                square.setFill(Color.WHITE);
                pane.getChildren().add(square);
            }
            linhaAtual++;
        }
    }

    private int definirIncrementoEmX(int linhaAtual) {
        int xIncremento;
        if (linhaAtual == 0) {
            xIncremento = 0;
        } else if (linhaAtual == 1) {
            xIncremento = 20;
        } else if (linhaAtual == 2) {
            xIncremento = 40;
        } else if (linhaAtual == 3) {
            xIncremento = 20;
        } else if (linhaAtual == 4) {
            xIncremento = 0;
        } else if (linhaAtual == 5) {
            xIncremento = 20;
        } else if (linhaAtual == 6) {
            xIncremento = 40;
        } else if (linhaAtual == 7) {
            xIncremento = 20;
        } else if (linhaAtual == 8) {
            xIncremento = 0;
        } else {
            throw new RuntimeException("Há mais Linhas que o esperado!");
        }
        return xIncremento;
    }

    private void lines(int lines) {
        int xInit = 0;
        int xFin = 750;
        for (int y = 100; y <= 500; y += 50) {
            Line line = new Line(xInit, y, xFin, y);
            line.setStrokeWidth(3);
            line.setStroke(Color.GREY);
            pane.getChildren().add(line);
        }

    }

    public static void main(String[] args) {
        start();
    }
} // END class World

The implementation of the method "definirIncrementoEmX(...)" is simple to understand but is limited; you can replace these ifs/elses (which nay are a flexible implementation, as they only work with a limited number of possible lines) for a better implementation, which is able to return the appropriate increment for any number of lines (currently only works until linhaAtual be 8, which is sufficient for the given example).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.