Desenvolvimento

2 mar, 2016

Como renderizar superfícies 3D em PHP usando gráficos de contorno 2D

Publicidade

Algumas aplicações requerem a visualização de superfície de 3 dimensões em uma imagem de 2 dimensões.

Gráficos de contorno nos permitem renderizar uma representação de superfície de 3 dimensões que representa desenhos irregulares, como um mapa geográfico.

php-1Superfícies de 3 dimensões

Um exemplo que pode ser renderizado como um gráfico de contorno é aquele que representa a altura do terreno em mapas geográficos. Outro exemplo é a representação da temperatura em mapas meteorológicos.

Esse tipo de gráfico ou diagrama é especialmente útil para a agricultura (previsões do tempo), turismo, energia renovável etc.

Considere isto: para cada valor que você precisa representar nesses mapas, você precisa de 3 valores – valor X representa a distância no eixo x, valor Y representa a distância no valor y, e o valor Z representa um valor de magnitude que veríamos no eixo z se o diagrama fosse em 3 dimensões, mas é preciso representar de alguma forma em 2 dimensões.

O pacote gráfico de contorno PHP (PHP Contour Plot Package) resolve o problema ao plotar linhas que possuem um valor Z constante. Essas linhas são chamadas contornos quando representadas em um diagrama de 2 dimensões. Isto é, dado um valor de Z, as linhas são desenhadas para ligar as coordenadas (x, y) onde o mesmo valor de Z ocorre.

A solução mais simples de mapa de renderização é usar o algoritmo Marching Square. Esse pacote usa a Triangulação Delaunay para mapear um mapa. Especificamente, ele usa a Triangulação Incremental Delaunay, que é muito rápida e também muito fácil de implementar.

A Triangulação Delaunay é mais precisa do que um mapa quadriculado, mas também mais difícil de entender. Um algoritmo mais avançado é Kriging.

Quando a Triangulação Delaunay é calculada (isso é demorado, porque ela utiliza matemática muito difícil), o valor de Z é mapeado ao longo de cada borda da triangulação. Por exemplo, ela utiliza o valor médio de z (aproximadamente max(z)+min(z))/2) e interpola as fatias/valores de z do valor de z da triangulação.

Shapefile e Corners

Outro problema é que um mapa geográfico não é um casco convexo, mas existem cantos do mapa que apontam em direção ao interior, ou seja, o centro do mapa. Em particular, Isso não parece bom quando esse canto cruza com a triangulação e cria vários polígonos.

Um shapefile é geralmente um arquivo de texto com as coordenadas de todos os pontos que têm o mesmo valor de Z.

Para corrigir essa questão, esse pacote cria um bitmap virtual do shapefile e usa um hit-test rápido de pixel por pixel se há um canto que cruza com uma triangulação. Outras soluções não combinam perfeitamente com as bordas do shapefile ou são muito lentas para computar.

Se o pixel da triangulação intercepta ou sobrepõe o shapefile, então ele é simplesmente excluído. O algoritmo é muito rápido porque é necessário apenas para testar a cor do mapa de bits virtual. Ele pode usar as funções do PHP imagecolorat() e imagesetpixel().

A forma geográfica é frequentemente muito irregular devido a cantos côncavos e formas isoladas (ilhas). Portanto, o algoritmo também calcula uma caixa de limite mínimo a partir do shapefile para minimizar o hit-test.

Esquema de cores e tons de cinza

Os gráficos de contorno do PHP utilizam 2 cores e tons de cinza entre as 2 cores para representar a diferença no valor z em relação ao valor da média de z. Especificamente, permite definir uma constante (STEPS) para realizar a interpolação linear para transformar as cores e ter uma visualização mais suave.

Tons de cinza

Na imagem gerada, uma cor é representada pelo vermelho, verde e azul (RGB). As outras cores e especialmente os tons de uma cor usam os tons de cinza de uma cor. O nível de tons de cinza é outro parâmetro no valor de cor RGB.

Interpolação

Para criar uma interpolação linear dos valores, esse pacote encontra o maior valor de z, e calcula a diferença (delta z) do maior valor de z e o valor médio de z, e o mapeia para uma gama de valores compreendidos entre 0 e 255. Esses são os valores mínimo e máximo para a representação de cores RGB. Em seguida, o valor RGB resultante é utilizado no diagrama gráfico.

Exemplo básico do pacote gráfico de contorno PHP

O pacote gráfico de contorno PHP requer o PHP 5.3 ou posterior.

require_once( "contour.php" );

define("ALPHA", 12.5);
define("STEPS", 6);

// your code here

$plot = new Contourplot();
$res = $plot->main( $D, $x_size, $y_size, $A, $mean, ALPHA);
$pic = new Image( $plot );
$pic->draw( $im );

// your code here

ImageGIF($im);
ImageDestroy($im);

Um tutorial mais aprofundado

A geração da criação do gráfico de contorno é dividida em 2 partes: o algoritmo e a apresentação gráfica.

O pacote gráfico de contorno PHP espera que sejam definidas duas constantes com os nomes ALPHA e STEPS.

A constante ALPHA

O valor ALPHA é um número positivo de 0 a infinito. Ele é usado para ocultar ou excluir bordas mais longas do que a média da distância euclidiana (alpha shape).

Um valor de 1 significa que, se as bordas são maiores ou iguais, então a média é excluída. Um valor acima de 1 significa que bordas maiores ou iguais à média multiplicada pelo valor ALPHA serão excluídos. Um valor abaixo de 1 significa que bordas maiores ou iguais, então a média multiplicada por ALPHA será excluída.

Por exemplo, você pode definir ALPHA em 12,5:

define("ALPHA" ,12.5);

A constante STEPS

O valor STEPS permite definir como a superfície de 3 dimensões é representada na imagem de 2 dimensões. O valor é um número positivo e quanto maior o valor, melhor a distinção entre a média do valor de z e o mínimo e o máximo valor de z.

Por exemplo, se você definir set STEPS em 6:

define("STEPS", 6);

Quando você tiver definido as constantes, inclua o arquivo contour.php no seu script, por exemplo, usando:

require_once("contour.php");

Criação e computação

Para criar um gráfico de contorno, crie um novo objeto da classe Contourplot:

$plot=new Contourplot();

Em seguida, chame a função principal do objeto. A função principal leva 6 argumentos:

  • $D é a superfície de 3 dimensões
  • $x_size é a largura da imagem
  • $y_size é a altura da imagem
  • $A é o shapefile geográfico
  • $mean é a média do valor z
  • ALPHA é uma constante Alphashape
$res = $plot->main( $D, $x_size, $y_size, $A, $mean, ALPHA);

A função principal retorna o número de triângulos. A classe também cria dados internos de entrada como os índices dos triângulos (em object->indices), os triângulos (em object->delaunay) e o fecho convexo (em object->hull).

Renderizando o gráfico

A segunda parte do trabalho da classe é implementar o algoritmo para desenhar o diagrama do gráfico de contorno.

Crie um novo objeto de imagem da classe gráfico e alimente-o com um recurso do imagemagick. Use a função draw() para renderizar a imagem e dar a saída para mostrar no navegador.

$pic = new Image($plot);
$pic->draw($im);
ImageGIF($im);
ImageDestroy($im);

Conclusão

Gráficos de contorno pode ser úteis para muitas aplicações que precisam gerar visualizações de como certas medidas físicas, como altitude ou temperatura, variam dentro de uma determinada região geográfica.

Apesar que requer alguns algoritmos relativamente complexos, o pacote PHP Contour deixa mais fácil a geração desde tipo de diagramas em suas aplicações PHP.

Se você gostou deste artigo, ou tem uma pergunta sobre este tema, deixe um comentário aqui.

***

Dan Thanh faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://www.phpclasses.org/blog/package/9195/post/1-How-to-Render-3D-Surfaces-in-PHP-using-2D-Contour-Plots.html