Eu acho que o formalismo de "álgebra de borda" de Guibas e Stolfi é um pouco desnecessário.
Tudo o que é realmente necessário é lembrar a distinção entre gráficos primários e duplos. Cada face do gráfico primal tem um vértice duplo correspondente f ∗ ; cada aresta e do gráfico primal tem uma aresta dupla correspondente e ∗ ; e cada vértice v do gráfico primitivo tem uma face dupla correspondente v ∗ . As arestas primárias conectam vértices primários e separam faces primárias; arestas duplas conectam vértices duplos e separam faces duplas. O dual do dual de qualquer coisa é a coisa original. Veja a Figura 4 no artigo de Guibas e Stolfi:ff∗ee∗vv∗
Guibas e Stolfi propõem pensar em cada aresta (primal ou dupla) como uma coleção de quatro arestas direcionadas e orientadas ; por simplicidade, chamarei esses dardos . Cada dardo pontos de um endpoint cauda ( → e ) para a outra extremidade da cabeça ( → e ) , e localmente separa duas faces esquerda ( → e ) e direita ( → e ) . A escolha de qual ponto final chamar cauda ( → e ) é o ponto de partida do dardoe⃗ tail(e⃗ )head(e⃗ )left(e⃗ )right(e⃗ )tail(e⃗ )direção e a escolha de qual face chamar à é sua orientação . (Guibas e Stolfi usam "Org" e "Dest" em vez de "cauda" e "cabeça", mas eu prefiro os rótulos mais curtos, porque abreviações desnecessárias são más.)left(e⃗ )
Para qualquer dardo , Guibas e Stolfi associam três dardos relacionados:e⃗
- : o dardo que sai da cauda ( → e ) em seguida no sentido anti-horário após → e .tailNext(e⃗ )tail(e⃗ )e⃗
- : O “mesmo” dardo que → e , mas com a esquerda ( → e ) e a direita ( → e ) trocadas.flip(e⃗ )e⃗ left(e⃗ )right(e⃗ )
- : o dardo duplo obtido dando → e um quarto de volta no sentido anti-horário em torno de seu ponto médio.rotate(e⃗ )e⃗
Essas três funções satisfazem todos os tipos de identidades maravilhosas, como as seguintes:
- right(tailNext(e⃗ ))=left(e⃗ )
- right(flip(e⃗ ))=left(e⃗ )
- right(rotate(e⃗ ))=head(e⃗ )∗
- flip(flip(e⃗ ))=e⃗
- rotate(rotate(rotate(rotate(e⃗ ))))=e⃗
- tailNext(rotate(tailNext(rotate(e⃗ ))))=e⃗
e Flipe.Flip
Além disso, dadas essas três funções, é possível definir várias outras funções úteis, como
- reverse(e⃗ )=rotate(flip(rotate(e⃗ )))
- leftNext(e⃗ )=rotate(tailNext(rotate(rotate(rotate(e⃗ )))))e⃗ left(e⃗ )
Por fim, conhecer essas funções diz tudo sobre a topologia da subdivisão e qualquer subdivisão poligonal de qualquer superfície (orientável ou não) pode ser codificada usando essas três funções.
A estrutura de dados quad-edge é uma representação particularmente conveniente de um gráfico de superfície que fornece acesso a todas essas funções, juntamente com várias outras operações em tempo constante, como inserir, excluir, contratar, expandir, e inverter bordas; dividir ou mesclar vértices ou faces; e adicionar ou excluir alças ou capas cruzadas.
Diverta-se!