Estrutura de Dados II 2013.1 Trabalho Parte 1 Universidade Federal de Juiz de Fora Prof. Jairo Francisco de Souza Indexação de dados geográficos 1. Introdução e objetivo do trabalho Aplicações que manipulam dados espaciais necessitam implementar estruturas de dados especiais para esse tipo de uso. É o caso de sistemas gerenciadores de dados geográficos, jogos e simuladores. Neste trabalho, iremos implementar operações de inserção e busca em uma K-d Tree de 2 dimensões para indexação de arquivos com dados geográficos. O objetivo desse trabalho é simular o comportamento de busca em POIs (points of interest), os quais são utilizados em aparelhos GPS para marcar pontos como locais turísticos, semáforos, pontos de gasolina, etc. 2. Descrição do trabalho Utilizaremos uma árvore de busca de dados em duas dimensões para armazenar pontos no espaço. Para tal, usaremos uma base de pontos com locais do Brasil. Essa base pode ser acessada em http://download.geonames.org/export/dump/BR.zip. Os registros estão dispostos no arquivo por linha, sendo que cada campo está dividido por tabulação. Ou seja, entre cada campo existe um caractere TAB delimitando-o. O final da linha indica fim do registro. Para entender o significado de cada campo, o arquivo README.txt, presente no zip, explica: The main 'geoname' table has the following fields : --------------------------------------------------geonameid : integer id of record in geonames database name : name of geographical point (utf8) varchar(200) asciiname : name of geographical point in plain ascii characters, varchar(200) alternatenames : alternatenames, comma separated varchar(5000) latitude : latitude in decimal degrees (wgs84) longitude : longitude in decimal degrees (wgs84) feature class : see http://www.geonames.org/export/codes.html, char(1) feature code : see http://www.geonames.org/export/codes.html, varchar(10) country code : ISO-3166 2-letter country code, 2 characters cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters admin1 code : fipscode (subject to change to iso code), see exceptions below, see file admin1Codes.txt for display names of this code; varchar(20) admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80) admin3 code : code for third level administrative division, varchar(20) admin4 code : code for fourth level administrative division, varchar(20) population : bigint (8 byte int) elevation : in meters, integer gtopo30 : average elevation of 30'x30' (ca 900mx900m) area in meters, integer timezone : the timezone id (see file timeZone.txt) modification date : date of last modification in yyyy-MM-dd format Cada registro no arquivo indica um ponto, sendo que esse ponto pode representar diferentes tipos de locação (cidade, rio, ilha, museu, etc). Para identificar cada tipo de locação, é necessário entender os campos feature class e feature code. A explicação sobre esses campos está em http://www.geonames.org/export/codes.html. 3. Funcionalidades a serem implementadas 1. O sistema deve ler todos os registros do arquivo de pontos e inseri-los em 2. 3. uma Kd-Tree. A árvore terá como nó uma estrutura com os campos latitude, longitude, featureClass, featureCode, geonameid e posicaoArq . O sistema deverá plotar todos os pontos da árvore na tela. O usuário poderá inserir uma coordenada e o sistema disponibilizará na tela o nome da localização correspondente a esse ponto. Caso o ponto informado não exista na árvore, deve informar então o nome dos pontos mais próximos (3 no máximo). Para encontrar os pontos, o sistema deverá pesquisar o nó correspondente na árvore, recuperar a posição no arquivo em que se encontra as informações da cidade e acessar essa posição no arquivo. Para tal, guarde a posição do arquivo no campo posicaoArq do nó. Cuidado: não faça busca sequencial no arquivo toda vez que for ler o arquivo! Use os métodos ftell/fseek (ou fgetpos/fsetpos) para isso. ATENÇÃO: Para plotar os pontos na tela, deve-se percorrer a árvore. O arquivo texto só pode ser lido para fazer a tarefa 1 e para completar a tarefa 3! 4. Entrega O grupo deverá ser formado por 4 alunos e as responsabilidades de cada aluno deve ser documentada e registrada. Deve ser entregue um relatório contendo a descrição das atividades realizadas por cada membro do grupo. Ainda, deve ser entregue a implementação dos algoritmos (código documentado informando o que faz e quais os autores de cada função); O grupo deve agendar um horário com o professor para entrega pessoal do trabalho e apresentação oral no DCC. O sistema deverá ser instalado na máquina do professor (sistema operacional Ubuntu 13.04 com CodeBlocks). Atenção para a data de entrega dos trabalhos: caso você deixe para o último dia, não espere que o professor estará disponível para te atender (outro grupo já pode ter reservado o horário!). Se não tiver espaço vago para a sua apresentação, será considerado entrega com atraso. 6. Pontuação Os membros da equipe serão avaliados pelo produto final do trabalho e pelos resultados individuais alcançados. Assim, numa mesma equipe, um membro pode ficar com nota 90 e outro com nota 50, por exemplo. Dentre os pontos que serão avaliados, estão: • Execução do programa (caso o programa não funcione, a nota será zero) • Corretude do programa (se todas as funções geram resultados esperados) • Boa solução de programação para resolução do problema proposto. • Código documentado e boa prática de programação (o mínimo necessário de variáveis globais, variáveis e funções com nomes de fácil compreensão, soluções elegantes de programação, código bem modularizado, etc) • Pontualidade (quanto mais atrasada for a entrega do trabalho, mais pontos o trabalho perde) • Relatório bem redigido Apêndice I: como criar gráficos (em C e em Java) Para criar gráficos em C, baixe a biblioteca chamada Allegro. É necessário compilar a biblioteca para o seu sistema operacional. As instruções de instalação estão no site da biblioteca (pesquise no google). Para usuários do Ubuntu, pode-se baixar a biblioteca já compilada no repositório da Canonical (digite liballegro4.2-dev na Central de Programas do Ubuntu). Para usuários Windows, boa-sorte... :-) Para compilar o seu projeto, será necessário setar a biblioteca liballeg-4.2.2.so no CodeBlocks. Para tal, vá em Project → Build options → Linker settings → Add e adicione o caminho completo da biblioteca. No Ubuntu, a biblioteca estará em /usr/lib/liballeg-4.2.2.so . Exemplo de código para criação gráfica de pontos em C usando o Allegro: #include <stdio.h> #include <stdlib.h> #include <allegro.h> if (allegro_init() != 0) return 1; install_keyboard(); /* configura o modo gráfico para resolução de 1366x768 */ if (set_gfx_mode(GFX_AUTODETECT, 1366, 768, 0, 0) != 0) { if (set_gfx_mode(GFX_SAFE, 800, 600, 0, 0) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set any graphic mode\n%s\n", allegro_error); return 1; } } set_palette(desktop_palette); clear_to_color(screen, makecol(255, 255, 255)); acquire_screen(); /** Cria um pixel na coordenada (150,150). O último parâmetro é a cor. Deve ter um grupo de constantes para facilitar o uso. Procure na documentação **/ putpixel(screen, 150, 150, 1); /** cria um texto na tela *// textout_centre_ex(screen, font, makecol(0,0,0), -1); “Hello World”, SCREEN_W/2, SCREEN_H/2, release_screen(); readkey(); exit(0); return 0; } Exemplo de código para inserção de pontos em Java usando o AWT: // Teste.class import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import javax.swing.JComponent; public class Teste extends JComponent { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); // Serve para transladar o centro do gráfico. Pode ser muito útil para posicionar bem as coordenadas das cidades... A linha abaixo, contudo, não tem efeito pois estamos transladando o centro em 0 pixels. g2.translate(0, 0); Rectangle2D rect = new Rectangle2D.Double(); g2.setColor(Color.BLUE); // Cria um retângulo na posição (150,150) com tamanho 1 de altura e largura. } } // Frame.class rect = new Rectangle2D.Double(150, 150, 1, 1); g2.fill(rect); g2.dispose(); import import import import import java.awt.Color; java.awt.EventQueue; java.awt.Graphics; java.awt.Graphics2D; javax.swing.JFrame; public class Frame extends JFrame { Teste teste = new Teste(); public Frame() { setTitle("Teste mapa"); setSize(800,640); setLocationRelativeTo(null); setDefaultCloseOperation(EXIT_ON_CLOSE); } @Override public void paint(Graphics g) { //Criamos um contexto gráfico com a área de pintura restrita //ao interior da janela. Graphics2D clip = (Graphics2D) g.create(getInsets().left, getInsets().top, getWidth() - getInsets().right, getHeight() - getInsets().bottom); //Pintamos o fundo do frame de preto clip.setColor(Color.WHITE); clip.fill(clip.getClipBounds()); teste.paint(clip); clip.dispose(); } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new Frame().setVisible(true); } }); }