4.3 Uso e Actualiza¸c˜ao da Informa¸c˜ao
4.3.4 Exemplo
Observemos o pol´ıgono da Figura 4.18 (a). Temos Gs(p) = {v
1, v14}. Para determinar a
parti¸c˜ao induzida pelas sec¸c˜oes vis´ıveis da pe¸ca p, introduzimos em p, para cada v ∈ Gs(p),
os respectivos cortes partindo a pe¸ca. `A medida que os cortes s˜ao adicionados ´e necess´ario actualizar a visibilidade. Isto ´e, a forma como cada uma das novas pe¸cas ´e vis´ıvel de cada v´ertice em Gs(p), se totalmente vis´ıvel ou se n˜ao vis´ıvel.
p v3 v4 v1 v2 v5 v6 v7 v8 v9 v1 0 v 11 v1 2 v1 3 v1 4 v1 5 v1 6 v1 7 (a) (b) (c) v1 8
Figura 4.18: (a) A pe¸ca p ´e parcialmente vis´ıvel dos v´ertices v1 e v14. (b) Resultado da
introdu¸c˜ao do corte que define a sec¸c˜ao vis´ıvel de v1 e actualiza¸c˜ao da visibilidade. (c)
Adi¸c˜ao dos cortes originados pela sec¸c˜ao vis´ıvel de v14 e actualiza¸c˜ao da visibilidade. Uma
face do arranjo n˜ao fica vis´ıvel de nenhum v´ertice.
Na Figura 4.18 (b) ´e adicionado `a pe¸ca o corte provocado pelo v´ertice v1, resultando duas
novas pe¸cas. A pe¸ca vis´ıvel de v1 ´e a que est´a `a esquerda do corte introduzido. Na
Figura 4.18 (c) s˜ao inseridos os cortes relativos ao v´ertice v14. Da pe¸ca n˜ao vis´ıvel de v1
resultam duas novas pe¸cas e da pe¸ca vis´ıvel resultam trˆes novas pe¸cas. O v´ertice v4 vˆe a
regi˜ao delimitada pelos cortes.
A conclus˜ao que se retira ´e que a pe¸ca p ´e n˜ao vis´ıvel por sec¸c˜oes. Isto porque uma das pe¸cas de Zp ´e invis´ıvel para todos os v´ertices em Gs(p). Nesta situa¸c˜ao, a parti¸c˜ao da
74 Determinac¸˜ao da Visibilidade Consideremos agora o exemplo da Figura 4.19. Neste caso, temos Gs(p) = {v
1, v6, v16}. v3 v4 v2 v5 v7 v8 v9 v1 0 v11 v1 2 v1 3 v1 4 v1 5 v1 7 v1 8 v1 9 v2 0 p v1 v6 v1 6
Figura 4.19: A pe¸ca p ´e parcialmente vis´ıvel dos v´ertices v1, v6 e v14.
Constru´ımos a parti¸c˜ao Zp como a Figura 4.20 ilustra.
(a) (b) (c)
Figura 4.20: Actualiza¸c˜ao do arranjo e da visibilidade por (a) introdu¸c˜ao do corte provocado pelo v´ertice v1; (b) adi¸c˜ao do corte originado pelo v´ertice v6; (c) inser¸c˜ao do corte relativo
ao v´ertice v16.
Conclu´ımos que todas as pe¸cas resultantes s˜ao vis´ıveis dalgum v´ertice v em Gs(p), logo a
Cap´ıtulo 5
Implementa¸c˜ao
Para avaliar o m´etodo proposto implement´amos uma aplica¸c˜ao com uma interface gr´afica utilizando a linguagem Java e o ambiente de desenvolvimento Netbeans 4.11. Para a resolu-
¸c˜ao dos sucessivos sub-problemas de cobertura m´ınima, analisados no Cap´ıtulo 2, utiliz´amos os resolutores da biblioteca Choco (vers˜ao 1.2.03) que ´e uma biblioteca Java para resolu¸c˜ao de problemas de satisfa¸c˜ao de restri¸c˜oes em dom´ınios finitos baseada no paradigma de Pro- grama¸c˜ao por Restri¸c˜oes [Rossi et al. 2007]. O sistema Choco2 ´e actualmente um projecto
em c´odigo aberto (open source, em Inglˆes) [F. Laburthe & Le Project OCRE 2000]. Essencialmente, em programa¸c˜ao por restri¸c˜oes s˜ao declaradas restri¸c˜oes e um resolutor ´e usado para as resolver. As restri¸c˜oes s˜ao rela¸c˜oes e um problema de satisfa¸c˜ao de restri¸c˜oes (tamb´em abreviadamente designado por CSP, Constraint Satisfaction Problem, em Inglˆes) estabelece as rela¸c˜oes entre as vari´aveis de decis˜ao. Mais formalmente, um problema de satisfa¸c˜ao de restri¸c˜oes consiste num conjunto de vari´aveis, cada uma com um dom´ınio de valores, e num conjunto de restri¸c˜oes em subconjuntos dessas vari´aveis.
5.1
Estrutura de Classes da Implementa¸c˜ao
Na Figura 5.1 est´a desenhado o diagrama correspondente `as classes que definem as estru- turas de dados. Al´em destas classes/estruturas criadas por n´os, foram ainda utilizadas as classes Hashtable, BitSet e Arrays existentes na API do Java.
1http://www.netbeans.org/ 2http://choco.sourceforge.net
76 Implementac¸˜ao
Figura 5.1: Diagrama das classes que constituem as estruturas de dados.
Classes para estruturas de dados Em seguida ser˜ao descritas, duma forma geral, as principais classes para as estruturas de dados utilizadas na implementa¸c˜ao.
A classe Structure (Figura 5.2) ´e utilizada para representar o pol´ıgono/parti¸c˜ao. Um
Figura 5.2: Atributos das classes Structure, LoL e Vertex.
objecto desta classe ´e definido `a custa de objectos da classe Vertex e da classe LoL. A classe LoL (Figura 5.2) permite representar listas simples de objectos com uma etiqueta (ou chave) associada. Cada objecto desta classe ´e composto por um objecto Object, um outro Rational e um do tipo LoL para guardar a referˆencia do elemento seguinte da lista.
Implementac¸˜ao 77 No caso dum objecto Structure, esta estrutura auxiliar cont´em a lista dos buracos. Um objecto da classe Vertex (Figura 5.2) representa um elemento duma lista duplamente ligada de GridNode. Outros atributos relevantes s˜ao objectos do tipo BitSet para representar os conjuntos Gt(v) e Gs(v) e um objecto do tipo HasseNode para possibilitar uma mais r´apida
actualiza¸c˜ao do diagrama de Hasse que representa a rela¸c˜ao ¤-dominˆancia entre classes de v´ertices.
GridNode (Figura 5.3) cont´em, al´em das coordenadas do ponto da parti¸c˜ao, uma referˆencia para uma das meias arestas de que ´e origem. Para isso, GridNode tem associado um objecto
Figura 5.3: Atributos das classes GridNode, HalfEdge e Face.
do tipo HalfEdge. Um objecto da classe HalfEdge (Figura 5.3) representa um elemento duma lista duplamente ligada de meias arestas. Cada objecto desta classe ´e definido pelo GridNode que ´e a sua origem, pela HalfEdge g´emea e pela Face incidente, isto ´e, a pe¸ca que delimita. A classe Face (Figura 5.3) permite representar pe¸cas. Cada objecto da classe Face ´e definido por uma das HalfEdge que a delimita, por objectos BitSet para representar Gt(p) e Gs(p) e uma lista LoL para guardar os cortes, agrupados pelo v´ertice
que os origina (etiqueta correspondente `a posi¸c˜ao do foco). A classe Face cont´em ainda m´etodos que permitem decompor uma pe¸ca e verificar se a pe¸ca ´e ou n˜ao vis´ıvel por sec¸c˜oes. Um objecto do tipo Cut (Figura 5.4) identifica uma sec¸c˜ao vis´ıvel dum guarda e ´e definido por um array de objectos da classe RationalPoint2D e por um Vertex, para identificar o guarda que originou o(s) corte(s).
78 Implementac¸˜ao A classe RationalPoint2D representa um ponto cujas coordenadas s˜ao n´umeros racionais, isto ´e, do tipo Rational. Como pode existir mais do que uma sec¸c˜ao vis´ıvel associada a um mesmo v´ertice numa pe¸ca, os objectos do tipo Cut s˜ao guardados em objectos do tipo MPElement. Cada objecto da classe MPElement (Figura 5.4) representa um elemento duma lista de Object duplamente ligada. Deste modo, a lista de cortes em Face ´e uma lista de cortes associados a um mesmo v´ertice.
Algumas das classes da estrutura de dados foram criadas como estruturas auxiliares. ´
E este o caso da classe Segment (Figura 5.5) que ´e definida por dois objectos do tipo HalfEdge (primeira e ´ultima meia aresta do p-segmento) e ainda um objecto do tipo Segment que nos permite aceder ao p-segmento seguinte. Portanto, um objecto da classe
Figura 5.5: Classes Segment, EdgeVisibility e VisibilityWindow e seus atributos. Segment representa um elemento duma lista de p-segmentos. As classes EdgeVisibility e VisibilityWindow auxiliam na determina¸c˜ao da visibilidade. A classe EdgeVisibility (Figura 5.5) ´e uma subclasse da classe Segment. Al´em dos atributos desta classe tem dois objectos RationalPoint2D que indicam os pontos de in´ıcio e fim do segmento vis´ıvel. Estes pontos est˜ao sobre os p-segmentos in´ıcio e fim herdados da classe Segment. Um objecto da classe VisibilityWindow (Figura 5.5) ´e definido por dois objectos do tipo RationalPoint2D e um outro do tipo VisibilityWindow que nos permite aceder `a janela de visibilidade seguinte, caso exista. Durante a an´alise duma pe¸ca, para saber a forma como a pe¸ca ´e vis´ıvel dum guarda g, v˜ao sendo determinados os segmentos da sua fron- teira que s˜ao vis´ıveis de g. Estes segmentos vis´ıveis s˜ao guardados em objectos do tipo EdgeVisibility. Ap´os a an´alise da pe¸ca, determinamos os pontos iniciais e finais de cada segmento vis´ıvel e criamos objectos VisibilityWindow que ser˜ao associados `a respectiva pe¸ca vizinha (n˜ao analisada) da pe¸ca acabada de analisar. Cada um destes pontos ficar´a guardado num dos objectos do tipo RationalPoint2D. Assim, em cada objecto do tipo Face poder´a existir uma lista de janelas de visibilidade que ´e re-iniciada para cada guarda g. Apesar de os elementos da classe VisibilityWindow constituirem uma estrutura auxiliar e tempor´aria, esta estrutura est´a associada `a classe Face para evitar a inser¸c˜ao e pesquisa de janelas de visibilidade numa lista com as pe¸cas da parti¸c˜ao.
Implementac¸˜ao 79 Cada objecto da classe HasseNode (Figura 5.6) ´e constitu´ıdo por trˆes objectos do tipo MPElement que representam a lista de pais, filhos e de objectos (v´ertices ou pe¸cas) daquele n´o do diagrama. Al´em destes atributos, tem ainda um objecto do tipo BitSet para Gt(v)
Figura 5.6: Classes HasseNode e VertexHN e respectivos atributos.
ou Gt(p) conforme se trate dum n´o dum diagrama para v´ertices/guardas ou para pe¸cas. No
caso dos v´ertices, os n´os tˆem guardados objectos da classe VertexHN (Figura 5.6). Cada objecto desta classe ´e definido por um objecto Vertex e por uma etiqueta que identifica a posi¸c˜ao considerada para o foco.
Classes para algoritmos Na Figura 5.7 est´a desenhado o correspondente diagrama das classes que implementam os algoritmos necess´arios ao longo de todo o processo de determina¸c˜ao do n´umero m´ınimo de guardas necess´arios para vigiar um dado pol´ıgono assim como a sua localiza¸c˜ao.
Figura 5.7: Classes que implementam as diferentes fases do m´etodo.
A classe associada `a interface gr´afica ´e uma subclasse da classe JFrame que permite a interac¸c˜ao com o utilizador. ´E nesta classe que ser˜ao chamados os m´etodos correspondentes `as diferentes fases do algoritmo de resolu¸c˜ao de MVG. De notar que a execu¸c˜ao destes m´etodos n˜ao est´a dependente da existˆencia duma classe deste tipo. Isto ´e, para executar os m´etodos basta ter uma classe com um m´etodo main(). A classe come¸ca por fazer a
80 Implementac¸˜ao leitura do ficheiro com o pol´ıgono e criar o objecto do tipo Structure. Os procedimentos necess´arios a esta tarefa encontram-se na classe WriteReadData (Figura 5.7). Esta classe ´e tamb´em respons´avel por guardar (em ficheiros) a informa¸c˜ao final sobre cada um dos pol´ıgonos (Figura 5.8).
Figura 5.8: Informa¸c˜ao recolhida na resolu¸c˜ao de MVG para um pol´ıgono.
Para executar a parti¸c˜ao do pol´ıgono recorremos aos m´etodos implementados na classe Sweep (Figura 5.7). Primeiro, ´e necess´ario proceder `a constru¸c˜ao da lista de eventos. Vimos no Cap´ıtulo 3 que os eventos s˜ao determinados por p-segmentos. Para representar um
p-segmento usamos a classe Segment. A classe Sweep tem as classes Horizontal e Vertical
(Figura 5.7) como suas subclasses. Estas classes implementam m´etodos espec´ıficos para os varrimentos horizontal e vertical, respectivamente.
A classe Visibility (Figura 5.7) cont´em os m´etodos que permitem caracterizar a visi- bilidade. Estes m´etodos determinam os conjuntos Gt(p), Gs(p), Gt(v) e Gs(v) para cada
v ∈ VP e cada p ∈ Π. Durante a determina¸c˜ao destes conjuntos, fica associada a cada pe¸ca
p ∈ Π, a informa¸c˜ao sobre os cortes que cada v´ertice de Gs(p) origina na pe¸ca. Ainda na
caracteriza¸c˜ao da visibilidade, para cada v´ertice, s˜ao determinados os segmentos vis´ıveis da fronteira das pe¸cas. No final de termos todos os segmentos vis´ıveis da fronteira duma pe¸ca, determinamos as suas janelas de visibilidade (para as pe¸cas que lhe s˜ao vizinhas e ainda n˜ao foram analisadas). Isto ´e, determinamos os pontos inicial e final de cada segmento vis´ıvel. A janela de visibilidade ´e representada pela classe classe VisibilityWindow. Cada objecto desta classe ´e definido por dois pontos (um para o in´ıcio e outro para o fim da janela de visibilidade) e um objecto do tipo VisibilityWindow. Como cada pe¸ca poder´a ter mais do que uma janela de visibilidade, cada objecto VisibilityWindow representa um elemento da lista de janelas de visibilidade associada a uma pe¸ca. Os cones de visibilidade s˜ao constru´ıdos tamb´em com base nas janelas de visibilidade.
Implementac¸˜ao 81 As classes Dominance (Figura 5.7) e HasseNode contˆem os m´etodos necess´arios para cons- truir e actualizar os diagramas de Hasse que representam as rela¸c˜oes de ¤-dominˆancia para classes de v´ertices/guardas e classes de pe¸cas. A classe Dominance implementa ainda o algoritmo boxDominanciaConjunta. DomFace e DomVertex (Figura 5.7) s˜ao subclasses de Dominance e tˆem m´etodos espec´ıficos para a ¤-dominˆancia entre classes de pe¸cas e entre classes de v´ertices/guardas, respectivamente.
A classe MinVertexGuard (Figura 5.7) implementa os m´etodos que definem e resolvem os sub-problemas de cobertura m´ınima e controla tamb´em as condi¸c˜oes de paragem que definem a descoberta do n´umero de guardas ´optimo. A classe General (Figura 5.7) cont´em um conjunto de fun¸c˜oes comuns a diversas classes.