Skip to content

Instantly share code, notes, and snippets.

@yuigoto
Last active April 19, 2019 23:15
Show Gist options
  • Save yuigoto/4f836af7c159905f20d44e40ec375f86 to your computer and use it in GitHub Desktop.
Save yuigoto/4f836af7c159905f20d44e40ec375f86 to your computer and use it in GitHub Desktop.
[Processing : Pi com Montecarlo] Minha versão para Processing (3.x) do algoritmo para estimar o valor de PI, do vídeo do canal Yarquen.
/**
* ESTIMANDO PI COM MONTECARLO
* ============================================================
*
* Baseado no vídeo e no sketch P5.js feitos pelo Guilherme Rey
* (Yarquen) em https://www.youtube.com/watch?v=VQvw3u-zSZg.
*
* Assista! É importante para entender bem o que acontece aqui!
*
* Apesar do P5.js ser uma versão do processing, pelo fato de
* ser em JavaScript, algumas coisas funcionam um pouco diferente.
*
* Este é o meu take de como estimar o valor de PI, de acordo com
* o vídeo. Tem algumas peculiaridades do Processing que tentei
* explicar, mas podem estar meio mal escritas, portanto: RTFM! :P
*
* @author Fabio Y. Goto <lab@yuiti.com.br>
*/
// GLOBAIS
// ============================================================
/**
* Raio da circunferência.
*/
int r = 500;
/**
* Total de pontos dentro da circunferência.
*/
int n_in = 0;
/**
* Máximo de pontos a serem criados.
*/
int n_max = 50000;
/**
* Framerate do sketch, diminua isso e a quantidade de pontos se
* tiver problemas de performance.
*/
int fps = 60;
/**
* Array para armazenar pontos.
*/
Point[] points;
// CLASSES
// ============================================================
/**
* Um objeto de ponto.
*
* Possui apenas três atributos: x, y e is_in, que indica se
* o ponto está dentro, ou não, da circunferência.
*/
class Point {
float x;
float y;
boolean is_in;
/**
* Construtor da classe.
*
* @var {float} x
* @var {float} y
*/
Point(float x, float y) {
this.x = x;
this.y = y;
}
}
// FUNÇÕES AUXILIARES
// ============================================================
/**
* Adiciona um ponto ao array.
*/
void addPoint() {
Point coord = getRandomPoint();
boolean is_in = isPointIn(coord);
n_in += (is_in) ? 1 : 0;
coord.is_in = is_in;
// Para adicionar itens ao array no Procesing, você precisa
// usar append e, ainda, indicar o tipo de dado.
points = (Point[]) append(points, coord);
}
/**
* Desenha a elipse utilizada no vídeo.
*/
void drawEllipse() {
fill(#009900);
noStroke();
ellipse(0, 0, r * 2, r * 2);
}
/**
* Retorna um novo ponto, com uma posição (pseudo-)aleatória.
*
* @return {Point}
*/
Point getRandomPoint() {
float _x = random(0, r);
float _y = random(0, r);
return new Point(_x, _y);
}
/**
* Verifica se um ponto está dentro, ou fora, da circunferência.
*
* @var {Point} pt
* @return {boolean}
*/
boolean isPointIn(Point pt) {
float square_x = pow(pt.x, 2);
float square_y = pow(pt.y, 2);
// Hipotenusa é menor ou igual ao raio?
return (sqrt(square_x + square_y) <= r);
}
// EXECUÇÃO
// ============================================================
/**
* Setup do Processing.
*/
void setup() {
/**
* Definimos o tamanho do canvas aqui, usando o P2D como
* renderer, embora seu uso seja opcional, visto que é
* o renderer padrão.
*/
size(500, 500, P2D);
// Define framerate
frameRate(fps);
// Cria o array (importante fazer isso aqui!)
// O "0" é pra criar um array vazio, PRECISA ser declarado!
points = new Point[0];
}
/**
* Update + Desenha.
*/
void draw() {
// Define fundo + desenha elipse
background(0);
drawEllipse();
// Vamos adicionar pontos ao array, enquanto possível
if (points.length < n_max) {
for (int a = 0; a < 100; a++) {
addPoint();
}
}
// Adicionou o ponto? Ótimo, vamos desenhar e tirar estimativa!
strokeWeight(3);
// Vamos apenas desenhar e testar se length > 0
for (int i = 0; i < points.length; i++) {
if (points[i].is_in) {
// Tá dentro?
stroke(255, 255, 0);
} else {
// Ou tá fora?
stroke(255, 0, 0);
}
point(points[i].x, points[i].y);
}
/**
* Note que, antes de dividir o valor pelo comprimento do array,
* multiplicamos o comprimento por "1.0".
*
* O motivo? É simples, se você simplesmente dividir (4 * n_in)
* pelo valor do comprimento do array, ele "arredonda" o resultado
* final para baixo (fica 3.0), visto que points.length é um int.
*
* Coisa do Processing. :P
*/
float pi_value = (4 * n_in) / (points.length * 1.0);
println(pi_value);
// Desenhando o texto na tela com COMIC SANS, pois TODOS GOSTAM
PFont font = createFont("Comic Sans MS", 40, true);
textFont(font, 40);
fill(0);
int text_x = 30;
int text_y = 60;
// Desenhando uma borda para o texto, já que strokeWidth não funciona.
// Deve haver meios melhores que este. :P
for (int yy = -2; yy <= 2; yy++) {
for (int xx = -2; xx <= 2; xx++) {
text("PI: " + pi_value, text_x + xx, text_y + yy);
}
}
fill(0, 255, 255);
text("PI: " + pi_value, text_x, text_y);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment