Algoritmo de geração automática de telhado 3D de polígono arbitrário

Algoritmo de geração automática de telhado 3D variável arbitrário


        Estou no CSDN cat há um ano e posso encontrar muitos recursos aqui, especialmente o Android. Mas eu nunca escrevi um blog. Sou grato por encontrar respostas para minhas perguntas em alguns ótimos blogs. Então, a partir de hoje, vou seguir o exemplo de todos e escrever algumas coisas que fiz. Parece mais valioso para discussões técnicas. Se não estiver claro, críticas e discussões são bem-vindas.

       O primeiro é escrever sobre um algoritmo tridimensional de telhado feito em outubro deste ano. Este algoritmo é a base para o projeto de pré-pesquisa de GIS 3D construindo edifícios automaticamente com base em dados de mapas. Eu encontrei muitos problemas na época e, recentemente, tive que escrever alguns documentos de algoritmo e publicá-los para discutir e aprender uns com os outros. Este algoritmo envolve a compilação e o uso da biblioteca de geometria CGAL. ​​Espero dar uma dica para amigos que compilam esta biblioteca pela primeira vez. Além disso, embora este algoritmo seja baseado em CGAL, ainda não estou familiarizado com o uso da biblioteca CGAL. CGAL é uma biblioteca muito poderosa, um recurso indispensável de alta qualidade para figuras geométricas. O seguinte descreve o processo de implementação do algoritmo de geração automática para telhados de polígonos 3D arbitrários.


1. Requisitos da tarefa:

1. O telhado inclinado é gerado automaticamente de acordo com os vértices da sequência de polígonos fornecida e o tipo de parâmetro de entrada.

2. Furos são permitidos na deformação múltipla de entrada e o número de furos é arbitrário.

3. Exporte o telhado poligonal gerado no formato de modelo OSG.

4. O algoritmo requer estabilidade, alta eficiência e pode aceitar qualquer teste.

2. Projeto de algoritmo

1. Idéias de design

De acordo com as necessidades da tarefa, o algoritmo de esqueleto de polígono arbitrário Straight_skeleton_2 na biblioteca de código aberto CGAL é selecionado como a função de geração de esqueleto subjacente. Gerando o caminho mais curto da aresta de esqueleto obtida, a relação topológica de multi-deformação da superfície do telhado deve ser atingida. Definindo o ângulo da inclinação do telhado, o valor da altura do ponto do esqueleto é obtido. Renderize as coordenadas do ponto de esqueleto geradas e a relação topológica para a cena OSG para gerar um modelo de formato OSG.

2. Etapas do processo

   (1) Compilar a biblioteca de código aberto CGAL.

   (2) Obtenha a relação topológica do polígono com a linha do esqueleto a partir do algoritmo Esqueleto_Reto_2.

   (3) O algoritmo do caminho mais curto é usado para percorrer e verificar as arestas do esqueleto para gerar polígonos do telhado.

   (4) Defina a altura do ponto do esqueleto de acordo com a distância entre o ponto do esqueleto e a linha do esqueleto adjacente.

   (5) Corte o telhado de acordo com a altura do telhado definida para gerar o plano do telhado correspondente.

   (6) Insira o relacionamento da topologia do telhado gerado na cena OSG e renderize o formato do modelo OSG.

Terceiro, o processo de implementação do algoritmo

1. Compilação de biblioteca de código aberto CGAL

  CGAL é uma biblioteca de algoritmos geométricos de código aberto relativamente clássica, o algoritmo é clássico, estável e eficiente. É difícil de compilar e precisa ser configurado de acordo com as etapas correspondentes para ter sucesso. Existem três dificuldades principais: 1 preciso confiar na biblioteca BOOST, ambiente QT, LibQGLviewer. 2. É difícil configurar o ambiente correspondente e o problema de configuração faz com que a compilação falhe diretamente. Devido ao problema de versão causado pelo processo de compilação da biblioteca BOOST, o nome do arquivo da biblioteca correspondente precisa ser modificado, caso contrário, a compilação falhará. (Resumindo, é problemático, mas sempre pode ser compilado! Sério + cuidado + perseverança = CGAL compilado com sucesso, vamos!) Existem muitos exemplos na Internet, mas situações diferentes sempre aparecem em ambientes diferentes. Aqui está minha própria compilação processo…….

(1) Preparação

Sistema operacional nativo: Win7 + VS2010

【Boost_1_56_0】

【CGAL-4.2】

【Cmake-2.8.0-win32-x86】

【Qt-opensource-windows-x86-vs2010-4.8.6】

【LibQGLViewer】

       Se você quiser fazer coisas boas, primeiro deve aprimorar suas ferramentas. Embora alguns internautas digam que você precisa de algumas funções sem instalar certos módulos, para aqueles que não têm experiência de compilação de bibliotecas de código aberto, eles devem ser honestos e totalmente preparados para o acima. As coisas acima são as melhores. Não perca a mesma coisa. Caso contrário, você saberá ... Eu uso esta versão, e o teste foi bem sucedido, mas não é a única solução. Você pode se referir a outros internautas. Encontre Duma para o link de download da versão.

Nota: Alguns internautas disseram que a biblioteca BOOST é melhor para usar a versão de instalação online, mas parece que a página da web é inválida, basta usar boost_1_56_0. Há também CGAL. ​​Ele precisa estar conectado à Internet durante a instalação. Às vezes, a velocidade da rede é lenta e alguns arquivos falham no download. Minha solução é copiar o endereço para o navegador e baixá-lo e, em seguida, colocá-lo na pasta correspondente, que será especificamente mencionada a seguir.

(2) O primeiro lote de instalação e configuração

Difícil e fácil, comece com caquis macios. Instale QT, libQGLViewe, Cmake por sua vez, descompacte BOOST para uma pasta, aqui minha pasta é D: \ Instruct.

Para evitar o erro de configuração da variável de caminho, minha configuração de variável de ambiente de instalação de caminho é fornecida abaixo, isso é muito importante! Se você não sabe como definir as variáveis ​​de ambiente, vá para o canto e pense um pouco sobre isso.

CAMINHO : D: \ CGAL-4.2; D: \ CGAL-4.2 \ auxiliary \ gmp \ lib;

D: \ Instruct \ cmake \ cmake-2.8.10-win32-x86 \ bin;

C: \ Qt \ 4.8.6 \ bin; C: \ Qt \ bin;

D: \ Instruct \ boost_1_56_0 \ boost_1_56_0;

      C: \ CGAL \ lib;

 

BOOST_INCLUD : D: \ Instruct \ boost_1_56_0 \ boost_1_56_0

BOOST_LIBRAR : D: \ Instruct \ boost_1_56_0 \ boost_1_56_0 \ stage \ lib

BOOST_ROOT : D: \ Instruct \ boost_1_56_0 \ boost_1_56_0

(3) Auto-compilação da biblioteca BOOST

Este caminho D: \ Instruct \ boost_1_56_0 \ boost_1_56_0 \ stage \ lib não existe antes da compilação. Você precisa primeiro executar bootstrap.bat para gerar e, em seguida, executar o bjam.exe gerado; não vou falar sobre isso em detalhes, consulte os procedimentos de outros usuários. Esta parte precisa esperar 20 minutos.

(4) Instale CGAL e defina o caminho da variável de ambiente.

   A conexão com a Internet é necessária durante a instalação. Se a velocidade da Internet for lenta e o download do arquivo falhar, use o navegador para fazer o download conforme solicitado. Em seguida, coloque-o no diretório da pasta correspondente.

(5) Iniciar Cmake

                                    aax01

Figura 1 Configuração de caminho Cmake

Defina o caminho correspondente de acordo com a Figura 1 acima. Em seguida, clique em configurar e você será solicitado a selecionar o compilador. Eu usei o VS2010. O processo de seleção de 2010 leva cerca de dois minutos. Se não houver nada de errado, clique em gerar e haverá um CGAL.sln sob o caminho de saída selecionado. O problema está chegando. Em muitos casos, várias exceções serão solicitadas. O motivo é que o caminho está definido incorretamente. A compilação correta exibirá as três linhas a seguir. Se o caminho estiver correto e houver erros, modifique o nome do arquivo de acordo com o prompt de erro do problema e verifique o seguinte Se a configuração nas três informações está correta.

D: /CGAL-4.2/auxiliary/gmp/lib/libgmp-10.lib

MPFR inclui: D: /CGAL-4.2/auxiliary/gmp/include

Bibliotecas MPFR: D: /CGAL-4.2/auxiliary/gmp/lib/libmpfr-4.lib

(6) Abra CGAL.sln e execute-o nos modos Debug e Release. Ele mostra sucesso 5 e falha 0. CGAL-vc100-mt.lib, CGAL-vc100-mt-gd.lib e outros libs serão gerados na pasta lib sob o caminho de saída.

Isso é considerado compilado.

Se você compilar com sucesso uma vez, terá muita sorte para o TMD. Se for compilado em um dia, significa que você é inteligente, se for dois dias, significa que você é capaz, e se for compilado em três dias, significa que você tem perseverança! Tenho muita perseverança, ha ha! As lágrimas estavam quase saindo quando o configure foi bem sucedido!

2. Obtenha a relação topológica da aresta do esqueleto através do algoritmo de geração do esqueleto Straight_skeleton_2

referência:

http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Straight_skeleton_2/Chapter_main.html

Conforme mostrado na Figura 2,

Os círculos pretos representam os vértices de entrada, os círculos azuis representam os pontos do esqueleto gerados e as linhas vermelhas são as arestas do esqueleto.

 ss01

Figura 2

A função de saída do esqueleto (código a seguir) fornecida pelo exemplo Straight_skeleton_2 pode gerar os pontos do esqueleto e arestas do esqueleto gerados.

modelo < classe K>

void print_straight_skeleton (CGAL :: Straight_skeleton_2 <K> const & ss) (1)

{

  typedef CGAL :: Straight_skeleton_2 <K> Ss;

 

  typedef typename Ss :: Vertex_const_handle Vertex_const_handle;

  typedef typename Ss :: Halfedge_const_handle Halfedge_const_handle;

  typedef typename Ss :: Halfedge_const_iteratorHalfedge_const_iterator;

 

  Halfedge_const_handle null_halfedge; // Alça de controle de meia borda

  Vertex_const_handle null_vertex; // identificador de controle de vértice

 

  std :: cout << "Straightskeleton with" << ss.size_of_vertices () // 顶 点数

            << "vértices," << ss.size_of_halfedges () // Número de meias arestas

            << "meias bordas e" << ss.size_of_faces () // 骨架 面 数

            << "faces" << std :: endl;

           

  para (Halfedge_const_iterator i = ss.halfedges_begin (); i! = ss.halfedges_end (); ++ i)

  {

    print_point (i-> oposto () -> vértice () -> ponto ()); // Exibe as coordenadas do ponto inicial da aresta do esqueleto

    std :: cout << "->" ;

    print_point (i-> vertex () -> point ()); // Mostra as coordenadas do ponto final da aresta do esqueleto

std :: cout << "" << (i-> is_bisector ()? "bisector" : "contour" ) << std :: endl;

// "bissetriz": "contorno" borda original: borda de contorno gerada

  }

}

No exemplo, apenas a saída de informações do lado do esqueleto é fornecida, e não há saída da superfície do esqueleto. Estou tentando encontrar a função de controle da superfície do esqueleto.

typedef typename Ss :: Face_const_handle Face_const_handle;

typedef typename Ss :: Face_const_iterator Face_const_iterator;

Mas não há um prompt inteligente do método de saída da superfície do esqueleto. Depois de pesquisar por um longo tempo, encontrei algumas funções sobre a face, mas não tive sucesso na operação e, então, desisti da ideia de obter diretamente a relação topológica da superfície do esqueleto, porque o algoritmo de caminho mais curto pode ser usado para encontrar cada aresta original de acordo com a relação entre a aresta original e a aresta do esqueleto. A superfície do esqueleto correspondente.

3. O algoritmo de caminho mais curto obtém o polígono do telhado

Conforme mostrado na Figura 3, os vértices 1 a 8 são os vértices do polígono original e 9 a 13 são os pontos do esqueleto gerados.A relação de conexão é mostrada na figura e pode ser obtida pela função (1) em Esqueleto_Reto_2. Usando o algoritmo de caminho mais curto, defina o peso do lado do link original para infinito (lado preto: 1000000) e defina o peso do lado do esqueleto gerado para 1 (lado vermelho) e, em seguida, calcule o lado original 1-> 2,2-> 3 por sua vez , ..., o caminho mais curto de 8-> 1. A superfície do esqueleto correspondente a cada borda original pode ser obtida.

A referência de algoritmo de caminho mais curto: DijkstraShortestPathAlg.

 sss01

imagem 3

4. Cálculo do valor de elevação do ponto de esqueleto

As coordenadas do ponto do esqueleto calculadas por Straight_skeleton_2 são coordenadas planas. Para obter um telhado tridimensional, basta atribuir um valor de altura ao ponto do esqueleto gerado. Mas este valor de altura é uma configuração subjetiva, talvez você queira que a altura de cada ponto seja diferente, o que pode ser mais realista. Portanto, aqui está um método para calcular automaticamente a altura do ponto do telhado, definindo o ângulo de inclinação do telhado. Conforme mostrado na Figura 3, em um pentágono (1-11-12-13-2) em uma superfície de esqueleto, ele pode ser obtido multiplicando a distância do vértice 11, 12, 13 à borda (1-2) pela tangente do ângulo do telhado Seu valor de altura. Claro, isso é apenas um regulamento, assumindo que os valores de altura dos pontos originais são iguais. Você também pode definir outras regras.

5 Defina a altura do plano do telhado para obter a seção do telhado

ss01

Figura 4 (a)

Conforme mostrado na Figura 4 (a), é o telhado totalmente inclinado gerado, mas às vezes nossos telhados não são todas superfícies inclinadas, mas os beirais inclinados, com telhados planos, como um bisel. Portanto, de acordo com o algoritmo acima, obtemos a altura do ponto do telhado (ou seja, o ponto do esqueleto) e, em seguida, usamos um plano com uma certa altura para ser tangente ao telhado para obter uma seção tangente. Claro, às vezes há várias seções de corte, o que exige que configuremos um determinado método para encontrá-las.Como mostrado na Figura 4 (b), a parte vermelha é a seção de corte.

sss01

Figura 4 (b)

6 Renderizar no formato de modelo OSG

A relação topológica da superfície do telhado pode ser obtida nas primeiras etapas e, em seguida, no processo de leitura no processo de renderização OSG. Claro, OPENGL é suficiente. Contanto que a topologia do modelo seja renderizada por qual mecanismo, depende de suas próprias preferências. Se você quiser que o modelo final do telhado esteja no formato OSG, é claro que você deve compilar a biblioteca OSG.Para este processo, consulte os blogs de outros internautas.

Salve como um modelo OSG com esta função: osgDB :: writeNodeFile (* (root.get ()), "RzXpdRoof.osg" ); Uma linha de código, você pode salvar a cena do desenho como um modelo OSG.

Quarto, a implementação do código principal do algoritmo

(1) Algoritmo de geração de esqueleto Straight_skeleton_2 para obter a relação topológica das arestas de esqueleto

Consulte o código de amostra no exemplo em CGAL: http://doc.cgal.org/latest/Straight_skeleton_2/index.html

Na função (1), você pode adicionar o seguinte código para visualizar o número do vértice:

std :: cout <<i-> oposto () -> vértice () -> id () << "" << i-> vértice () -> id ();

(2) Geração de telhado e busca de seção de corte

Para obter detalhes, consulte a função no código-fonte print.h: ROOFgetxpd_straight_skeleton (CGAL :: Straight_skeleton_2 <K> const & ss, PLOYGON merofploy, float Angle, float maxhight)

 

(3) Para renderização OSG, consulte o arquivo main.cpp no ​​projeto C: \ Users \ zyp \ Desktop \ 1111111111

(4) Por fim, o projeto de integração é a seção MFC para teste, consulte o projeto C: \ Users \ zyp \ Desktop \ SSZRidegLine para obter detalhes

Cinco, análise de teste de algoritmo

Demorou quase três semanas para implementar todo este conjunto de procedimentos.Agora o pensamento está claro e me sinto muito simples, mas foi muito difícil atravessar o rio sentindo as pedras. Dificuldades: 1. Compilação CGAL; 2. Descubra a relação topológica das bordas do esqueleto; 3. Encontre a face do esqueleto (usei o algoritmo do caminho mais curto para obtê-lo. Ainda não sei como operar a face do esqueleto, por favor, esclareça-me se você está familiarizado com CGAL); 4. Encontre a seção de corte.

Especialmente quando encontrei a seção cruzada, o algoritmo que iniciei era complicado e havia bugs. A depuração neste local ficou parada por quase uma ou duas semanas. Foi muito doloroso. 80% das vezes eu obtive o resultado correto, o outro era o triângulo errado. A princípio suspeitei que meu modo de renderização estava incorreto.Depois de muitos testes, percebi que o algoritmo para encontrar a seção de corte não estava apertado. Depois de perceber onde estava o problema, foi feito em um dia.

 ss01

Figura 5 Polígono arbitrário sem orifícios

sss01

Figura 6 Situação com buracos

A estrutura ROOF é definida no projeto SSZRidegLine para armazenar a topologia do modelo gerado.

O formato de leitura de entrada do polígono é definido no projeto C: \ Users \ zyp \ Desktop \ SSZRidegLine \ cinploys.txt (o polígono mais externo do polígono é classificado no sentido horário e o buraco no sentido anti-horário)

PloygonNum: 6 10 3 12 5 7 3

6: Significa que há seis polígonos no total //

Ploygonouter: representa o polígono externo //

ploygonhole: // indica um buraco no polígono

10 3 12 5 7 3 respectivamente indicam o número de vértices de 6 polígonos.

ploygonouter:

134.000 97.0000.000 /// Coordenadas (x, y)

273.000 68.0000.000

561.000 62.0000.000

530.000 298.0000.000

455.000 381.0000.000

363.000 130.0000.000

279.000 260.0000.000

148.000 206.0000.000

127.000 320.0000.000

91.000 117.0000.000

ploygonhole:

227.000 116.0000.000

197.000 149.0000.000

264.000 187.0000.000

ploygonhole:

481.000 119.0000.000

445.000 151.0000.000

453.000 193.0000.000

487.000 192.0000.000

510.000 183.0000.000

515.000 151.0000.000

517.000 114.0000.000

505.000 91.0000.000

449.000 81.0000.000

391.000 104.0000.000

406.000 124.0000.000

440.000 118.0000.000

ploygonhole:

464.000 253.0000.000

455.000 273.0000.000

469.000 293.0000.000

486.000 289.0000.000

501.000 264.0000.000

ploygonhole:

153.000 185.0000.000

204.000 209.0000.000

220.000 195.0000.000

137.000 148.0000.000

150.000 126.0000.000

118.000 121.0000.000

115.000 153.0000.000

ploygonhole:

336.000 99.0000.000

295.000 117.0000.000

317.000 133.0000.000

 

Formato de arquivo do modelo de saída

C: \ Users \ zyp \ Desktop \ SSZRidegLine \ Debug \ faceoutxpd.txt

RoofObject: 1 3 11 14

///

1: Significa que o telhado está achatado, e o número de vezes desta posição é 0, o que significa que o telhado é estritamente inclinado

3: indica que o telhado é gerado por três polígonos (ou seja, existem dois orifícios)

11: indica que o polígono mais externo tem 11 vértices

14: indica que existem 14 faces do telhado

///

PosId: 35 4 3 4

0 907.000 140.000 0,000 // número de série 0; coordenadas (x, y, z)

1 916.000 459.000 0,000

2 116.000 420.000 0,000

3 228.000 100.000 0,000

4 382.000 197.000 0,000

5 332.000 259.000 0,000

6 507.000 332.000 0,000

7 814.000 257.000 0,000

8 709.000 287.000 0,000

9 705.000 390.000 0,000

10 811.000 390.000 0,000

11 675,253 418,615 28,592

12 624,759 414,220 30,522

13 842.971 422.701 32.675

14 380,184 143,822 34,769

15 861.972 194.873 46.521

16 862.564 404.457 51.835

17 855.390 190.053 52.959

18 230,129 284,846 63,023

19 640.432 380.605 64.833

20 285,195 185,860 82,282

21 618,737 216,125 92,871

22 250,119 329,674 96,673

23 589,450 242,684 121,084

24 882.637 163.628 25.000

25 890.228 432.694 25.000

26 150.684 396.641 25.000

27 245.378 126.087 25.000

28 380.694 158.763 25.000

29 291.590 269.253 25.000

30 603.455 399.345 25.000

31 839.780 223.614 25.000

32 684,702 267,921 25.000

33 678.990 415.020 25.000

34 835.462 415.020 25.000

Face: 4 // A face do telhado tem 4 vértices

3 27 24 0 A relação de conexão da superfície do telhado; registre o número do vértice

Rosto: 4

0 24 25 1

Rosto: 4

1 25 26 2

Rosto: 4

2 26 27 3

Rosto: 4

6 30 28 4

Rosto: 4

4 28 29 5

Rosto: 4

5 29 30 6

Rosto: 4

10 34 31 7

Rosto: 4

7 31 32 8

Rosto: 4

8 32 33 9

Rosto: 4

9 33 34 10

Rosto: 4

27 24 25 26 27

Rosto: 3

30 28 29 30

Rosto: 4

34 31 32 33 34

A introdução do algoritmo acabou!

Se você estiver interessado, deixe um comentário e forneça o código!

 

Acho que você gosta

Origin blog.csdn.net/sun19890716/article/details/42679161
Recomendado
Clasificación