Geometria, limites e Game of Thrones

Karl Marx Alexander
investigacoesholisticas
5 min readApr 15, 2019

Há algum tempo eu estava desenvolvendo uma versão do Os Elementos de Euclides para web como desculpa para treinar minhas habilidades com Javascript/CSS. Apesar do projeto estar juntando poeira no GitHub, um dia ele ainda será retomado, e esse dia seria hoje.

Seria porque ao voltar ao projeto, além de notar que minhas habilidades há um ano eram bem piores que as atuais, eu percebi que não faria mais sentido um projeto nos moldes que em que foi pensado inicialmente. No meu trabalho atual na Espresso Labs, eu tenho muita vivência com HTML/CSS e Javascript principalmente, sendo que a maior parte do meu trabalho envolve criar servidores em NodeJS.

Compilando geometrias

A versão atual do projeto contém classes que representam construções geométricas e que desenha (de forma bem ruim) animações em um canvas. A ideia inicial era que fosse possível realizar provas/desenhos geométricos utilizando um método parecido com o que se faz ao desenhar estas formas no papel. A intenção final era que um código do tipo:

const baseLine = new Line(0, 10); // Inicio e fim do segmentoconst firstCircle = new Circ(0, 10); // Centro e raio
const secondCircle = new Circ(10, 10);
const triLeftSide = new Line(firsCircle, cross(firstCircle, secondCircle));const triRightSide = new Line(secondCricle, cross(firstCircle, secondCircle));

Que produziria a animação da construção de um triângulo equilátero, passo a passo.

Obviamente quando estamos desenhando formas aleatórias não necessariamente pensa-se em todos estes passos, porém como a intenção principal era a animação da construção de provas com base nas minhas classes principais, pode-se dizer que esta sequência de passos é de fato uma simulação de “desenho”.

A função cross ainda não havia sido implementada pois é um problema detectar se um ponto está em duas linhas diferentes (um dos requisitos é suporte a linhas infinitas). Porém somente com estas funções eu não consigo validar algumas coisas relacionadas a geometria, como por exemplo o fato de que a construção anterior é um triângulo equilátero.

Estendendo um projeto não feito

Pensando nisso, e com algumas ideias de Prolog na cabeça, eu resolvi definir uma nova implementação que fosse capaz de validar certas construções com base em outras (o que também é feito no livro), e garantir que se existe uma definição de triângulo equilátero, seja possível testar a construção anterior.

A primeira questão é que no momento eu não tenho uma ideia muito boa de como farei isso, sendo que até o momento a melhor implementação que pensei segue os seguintes passos:

1) Plano: É até engraçado o fato de eu iniciar uma implementação dessa lógica em uma definição, e não em um axioma, como eu mesmo esperava, porém antes de definir um ponto, que não tem dimensão, é necessário que eu saiba onde ele pode se encaixar, o plano.

Seguindo um modelo bastante óbvio, a implementação do plano será definido como uma matriz, o que pode acarretar em alguns problemas quando se tem um plano que pretende-se infinito tanto nos inteiros quanto nos racionais, mas isso vai ser discutido mais a frente. (Ainda não existe uma definição para irracionais que podem ser construídos geometricamente, como PI)

2) Tipos básicos: O primeiro tipo básico, que consiste na representação de um ponto no plano, é o tipo ponto. Sua única propriedade é onde o mesmo se encontra localizado no plano.

Caso exista uma definição de localização com numero racional, o plano passa a ter um novo multiplicador de índices que reescreve seus componentes de acordo com o numerador.

Por exemplo, em um plano inicial de 10x10, é definido um ponto na localização 1/2, Dobrando a matriz do plano nas duas direções (area 4x maior), é possível definir que a localização 1/2 tem índice (0,1), e a localização 1 tem indice (0,2), logo para todo índice do novo plano, basta que seus índices sejam multiplicados pelo racional inicial.

É importante notar que o novo plano tem suporte para qualquer localização {k + 1/2}, assim como qualquer plano com indices {1/(m * 2)} suporta as localizações pares para racionais maiores de denominador par, de fato isso vale para todo nova localização em que o denominador não é primo, e para os que são, um novo plano que suporta esta reconstrução pode ser dado por {1/(p * m)}, em que p é primo e m é o denominador atual.

A notação de ponto será (x, y), sua localização no plano.

const newPoint = new Point(x, y);

O próximo tipo básico são linhas, que consistem em um conjunto infinito de pontos, que pode ou não ter extremidades. É importante lembrar que uma linha não é necessariamente uma reta, embora uma reta seja o tipo mais simples possível de linha. Para este tipo de construção, eu defini três possíveis declarações:

const newLine = new Line(i, c, [(x1,y1),(x2,y2),..(xn,yn)]);

Em que i define se a mesma é infinita e seu padrão se repete, c define se a interligação dos pontos deve ser curva e um vetor com seus pontos de interesse. Ou:

const newLine = new Line(i, c, (x,y), k);

Em que k é uma função baseada executada a partir do ponto de interesse inicial.

Um círculo é um tipo especial de linha, e terá como declaração a seguinte forma:

const newCircle = new Circle(r, c);

Sendo r seu raio e c o seu centro

3) Operações básicas: Partindo disto, existem algumas operações que precisam ser implementadas para que as provas se tornem possíveis. A primeira delas é determinar se um ponto pertence a uma linha, a segunda é se o mesmo está contido dada uma certa região delimitada por um ângulo ou círculo.

Na primeira operação, dadas as formas de se declarar uma linha, é bem simples determinar se um ponto pertence a mesma.

No caso da primeira declaração, basta que se itere sobre o array de pontos checando se o ponto dado pode ser escrito como {(xk / m), (yk / n)} com m e n multiplos de xk, yk. Já no segundo caso basta que se teste o ponto na função.

Já a operação sobre ângulos e círculos, existem algumas complicações em relação as regiões de teste, e ainda não pensei em um algoritmo bom o suficiente para planos muito grandes, assim como uma boa definição de ângulo.

Com base nestas construções, é possível definir testes para formas mais complexas, seguindo o exemplo do triângulo equilátero, alguns testes podem ser:

baseLine e triLeftSide formam um angulo?
baseLine e triRightSide formam um angulo?
triLeftSide e triRightSide formam um angulo?

Pela propriedade de transição, isto é um triângulo.

baseLine e triLeftSide tem o mesmo tamanho?
baseLine e triRightSide tem o mesmo tamanho?

Então este triângulo é equilátero.

Estas construções podem então ser utilizadas para novas provas, como por exemplo um losango que é formado por dois triângulos equilátero.

E Game of Thrones?

Quando eu comecei a escrever isso faltava algumas horas para a estreia de Game of Thrones, e eu sabia que provavelmente não iria dar tempo de terminar, então me desculpe a parada brusca, mas o inverno está chegando!

--

--

Karl Marx Alexander
investigacoesholisticas

The less smarter and Brazilian Feynman, Software engineer at Gaivota