Projeto de Geometria Computacional - ano 2000



Integrantes
N. USP
e-mail
Bitwise
Cláudio Seidi Takamiya
2869604
cst@linux.ime.usp.br
Estressado
Fábio Pará D' Incecco
3021187
incecco@linux.ime.usp.br
CyberCop
Wu Chen Lung
2231931
wlung@linux.ime.usp.br

Nesta página você poderá acompanhar como foi o desenvolvimento do projeto que escolhemos:

Problema do Par mais Próximo no R²
Arquivos Fontes
Executável (linkado estaticamente)

Observações:

Como este projeto foi feito em C, há alguns requisitos básicos para o funcionamento:

- GLUT/Mesa

- GTK e GDK

- Biblioteca GTK GLArea Arquivo para instalação



É possível entrar com os pontos do conjunto no formato arquivo texto, ou através de cliques do mouse.
O formato do arquivo texto deve ser:

3 --------------------> Número de pontos do conjunto
5.36 -5----------------> Coordenadas (x,y) dos pontos, um por linha
0 -1.2
1 2.04

Maiores informações podem ser encontradas no menu Ajuda do programa executável.

Relatório do desenvolvimento:


O objetivo desse relatório é descrever as tomadas de decisões que tivemos 
que fazer durante o desenvolvimento do projeto de Geometria Computacional, 
intitulado Problema do Par mais Próximo, realizado no ano de 2000. 
(Data de criação [início] do projeto: 23/05/2000)

23/05/2000:
        Ao pensarmos melhor no problema e na interface que teria que ser feita
com o usuário, decidimos alterar a biblioteca que usaríamos. Ao invés de se
utilizar a Mesa/GLUT, precisaremos usar a GTK, pois esta contém intrinsicamente
funções usadas para controle de janelas, botões e caixas de diálogo.
        Quanto ao problema de desenho, vimos que todas as funções que 
usaríamos no Mesa, possuem equivalentes no GTK, não alterando muito o que 
tinhamos planejado. Pelo que vimos, há uma biblioteca chamada GDK, que pode
ser usada em conjunto com o GTK, usada para desenhos.

20/06/2000:
        Retomamos o projeto, ainda pensando nas estruturas que teremos que 
        utilizar para desenvolvermos o Problema do Par mais Próximo.
         Precisaremos ter:
         Estrutura para guardar os n pontos do R² : 
         Lista duplamente ligada: P ={0,...,n-1}

         (D1,p1,p2) = ParProximo(P):  
         Se #elementos <= 3, use força bruta e devolva (Dmin,pmin1,pmin2).
         Caso contrário: /* Divisão, conquista e combinação */
              2 PRÉ-PROCESSAMENTOS:
              - Ordenação dos pontos segundo as x-coordenadas (em caso de 
              empate, use como decisão a coordenada y). [O(n.logn)] 
              Coloque o resultado em um vetor X.
              - Ordenação dos pontos segundo as y-coordenadas (em caso de 
              empate, use como decisão a coordenada x). [O(n.logn)]
              Coloque o resultado em um vetor Y.
              
              ALGORITMO de Divisão e Conquista [O(n)]
              Dividir:
              * Pegue o elemento do meio em X e considere-o como mediana do
                conjunto, chame-o de med.
              * Tome Pl o conjunto {0,...,med} de pontos.       
              * Tome Pr o conjunto {med+1,...,n-1} de pontos.   
                      
              Conquistar: Resolver recursivamente para os dois conjuntos.
              * (Dl,pl1,pl2) = ParProximo(Pl).        
              * (Dr,pr1,pr2) = ParProximo(Pr).        
              * onde: Dr = dist(pr1, pr2);
              *       Dl = dist(pl1, pl2);

              Combinar: 
              * D = min(Dl, Dr);
              * Calcula-se todos os pontos de Pl a uma dist. <= D da reta 
              vertical dada pela mediana em X (reta: x = med). => Conj. Pl'
              * Calcula-se todos os pontos de Pr a uma dist. <= D da reta 
              vertical dada pela mediana em X (reta: x = med). => Conj. Pr'.
              *  Para cada ponto p em Pl' faça:
                      Encontre os pontos em Pr' a uma dist. máxima D de p:
                      Para isso, projete p em y:
                       Percorra Pr' e tome apenas os pontos q cujo cálculo:
                        |q.y - p.y| <= D. O número máximo de q será 6.
                       Calcule a distância entre p e cada q.
                 No final encontraremos um par (p3,q3) que deverá ser o
                 que tem menor distância nessa faixa entre Pl' e Pr'.
              * Para determinar o par mais próximo, teremos que determinar
              quem é o mínimo entre Dl = dist(pl1, pl2), 
                                    Dr = dist(pr1, pr2),
                                    Dm = dist(p3, q3).
                                    Chame-os de Dmin, pmin1, pmin2
              RETORNE: (Dmin, pmin1,pmin2).     
27/06/2000:
        Início da implementação propriamente dita:
        Começamos a desenvolver as estruturas para guardar os pontos e também
        o algoritmo de ordenação dos pontos segundo suas x-coordenadas.
        Escolhemos o Quicksort como algoritmo de ordenação, seguindo uma 
        implementação dada no livro do Sedgewick (Algorithms in C), que se o
        vetor a ser ordenado for menor que uma certa constante M, não se chama
        o Quicksort recursivamente. No final, é feita uma ordenação 
        InsertionSort que rearruma os termos que não foram ordenados. Mesmo com
        essa passagem do vetor por um Insertionsort, o custo da ordenação ainda
        é O(n.log n).
        O algoritmo ainda não está perfeito, caso haja pontos com mesma 
        coordenada x. Ou seja, ainda não colocamos o desempate pela y-coordenada.

28/06/2000:
        O algoritmo para ordenar em relação à x-coordenada foi arrumado. 
        Ou seja, agora também está funcionando quando há empate na coordenada x
        dos pontos analisados.
        Também foi pensado uma forma rápida de reaproveitar o código e poder 
        usá-lo para ordenação em relação à y-coordenada sem muitas alterações.

29/06/2000:
        Foi implementado o algoritmo para ordenação através das y-coordenadas 
        dos pontos. A idéia foi tentar reaproveitar ao máximo o código que já 
        tinhamos feito para ordenar em relação à x-coordenada.
        Partindo desse princípio, foram necessários apenas alguns ajustes 
        nas funções que eram responsáveis pela comparação das coordenadas 
        de dois pontos, que eram passados como parâmetros.
        Sendo assim, à parte do projeto que corresponde ao pré-processamento,
        que é a ordenação dos pontos em termos das x-coordenadas e  
        y-coordenadas, já está feito. Resta apenas testar para quantidades
        realmente grande de números (mais de 30 pontos, por exemplo).

04/07/2000:
        Retomamos o projeto. Nosso objetivo hoje é começar a implementar a 
        parte interna do programa, ou seja, a parte responsável pela 
        determinação do par de pontos mais próximo.
        Estávamos com dúvida quanto ao real uso de 2 vetores ordenados (um em
        relação à X e outro em relação em Y), mas pensamos um pouco mais e 
        estamos quase certos que um só será necessário.
        Também pensamos quanto à função distância que será definida pelo 
        usuário. Definimos que:
                 - Precisa haver um arquivo cabeçalho, com nome: distancia.h
        que é o protótipo da função que incluiremos no programa principal.
                 - O cabeçalho da função deve ser:

                   double Distancia(double, double, double, double);
        onde cada double recebido como parâmetro é na verdade uma coordenada
        do ponto ao qual queremos calcular a distância. Por exemplo, a 
        chamada:
                 Distancia(-5.6, 4.2 8.0, 0.33)

        Calcula a distância entre os pontos do R²: (-5.6, 4.2) e (8.0, 0.33). 

                 - O arquivo que contém a implementação da função deve se
        chamar: distancia.c
        
        Implementamos mais algumas estruturas que usaremos para guardar os
        pontos mais próximos e sua distância, um vetor de Pontos, que é a 
        coleção onde armazenaremos os pontos do problema. Além disso, 
        escrevemos operações básicas que mexam com essas estruturas.

05/07/2000:
        Detalharemos uma estrutura que será muito usada:
        Estrutura ParProximo:
         valor double para a distância.
         vetor com 2 Pontos, que são os mais próximos.
         
        Na parte da manhã, a função para calcular a distância mínima, Parproximo,
        foi codificada seguindo o pseudo-código que foi escrito nesse relatório no
        dia 20/06. O código só foi compilado e corrigido no início da tarde.

        A função Parproximo, que é a parte principal do programa entre os pontos 
        do conjunto está completada e, pelos testes realizados, parece estar
        funcionando corretamente, devolvendo a estrutura que corresponde ao
        verdadeiro par de pontos que minimiza a distância.

        Falta realizar mais testes, no sentido de comprovar a validade do programa
        desenvolvido.
        
        Próximos passos: Interface gráfica, que ainda estamos em dúvida se 
        utilizaremos GLUT/Mesa3D ou GTK (com GDK) ou ainda os dois juntos.

06/07 - 03/08:
        A Rede Linux ficou por duas semanas inoperante, o que nos forçou a 
        trabalharmos na rede IME e também em casa.
        Tivemos que estudar o GTK e o GDK para fazermos a interface, o que 
        já nos consumiu um bom tempo.
        Gastamos cerca de uma semana e meia ajustando o código à interface.  
        No dia 03/08 o projeto já estava concluído e apresentamos ao professor.      


Última atualização : Mon Aug 14 10:27:10 2000