/** * Método responsável por desenhar as retas ligando cada movimento do caminho passado como parâmetro. */ private void DesenharCaminho(Caminho caminhoParaDesenhar) { if (caminhoParaDesenhar != null) { Graphics g = pbMapa.CreateGraphics(); Pen pen = new Pen(Color.Blue, 3); int xProporcional = 4096 / pbMapa.Width + 1; int yProporcional = 2048 / pbMapa.Height + 1; Caminho caminhoClone = (Caminho)caminhoParaDesenhar.Clone(); int coordenadaXOrigem = 0, coordenadaXDestino = 0, coordenadaYOrigem = 0, coordenadaYDestino = 0; while (!caminhoClone.Movimentos.EstaVazia) { foreach (Cidade c in gps.ListaCidades) { if (caminhoClone.Movimentos.Primeiro.Info.IdCidadeOrigem == c.Id) { coordenadaXOrigem = c.CoordenadaX; coordenadaYOrigem = c.CoordenadaY; } if (caminhoClone.Movimentos.Primeiro.Info.IdCidadeDestino == c.Id) { coordenadaXDestino = c.CoordenadaX; coordenadaYDestino = c.CoordenadaY; } } g.DrawLine(pen, new Point(coordenadaXOrigem / xProporcional, coordenadaYOrigem / yProporcional), new Point(coordenadaXDestino / xProporcional, coordenadaYDestino / yProporcional)); caminhoClone.RemoverMovimento(); } } }
/** * Método com a função de exibir os resultados para o usuário. * Percorre a lista de caminhos encontrados e de melhor caminho, exibindo cada passo em uma coluna do dataGridView. * Caso nenhuma coluna seja exibida, nenhum caminho foi encontrado e o usuário é alertado. */ private void ExibirCaminhos(List <Caminho> listaCaminhos, Caminho melhorCaminho) { dgvCaminhos.ColumnCount = 0; dgvCaminhos.RowCount = listaCaminhos.Count; int caminhosExibidos = 0; int qtdMovimentos; foreach (Caminho caminho in listaCaminhos) { qtdMovimentos = caminho.Tamanho; if (qtdMovimentos > dgvCaminhos.ColumnCount) { dgvCaminhos.ColumnCount = qtdMovimentos; // quantidade de colunas do dataGridView se iguala ao tamanho de passos do maior caminho for (int i = 0; i < qtdMovimentos; i++) { dgvCaminhos.Columns[i].HeaderText = "Cidade"; } } // exibe cada movimento do caminho em questão for (int i = qtdMovimentos - 1; !caminho.Movimentos.EstaVazia; i--) { Movimento mov = (Movimento)caminho.RemoverMovimento(); dgvCaminhos.Rows[caminhosExibidos].Cells[i].Value = mov.ToString(); } caminhosExibidos++; } if (melhorCaminho.Tamanho > 0) // se a lista de melhorCaminho não estiver vazia { qtdMovimentos = melhorCaminho.Tamanho; dgvMelhorCaminho.ColumnCount = qtdMovimentos; dgvMelhorCaminho.RowCount = 1; for (int i = qtdMovimentos - 1; !melhorCaminho.Movimentos.EstaVazia; i--) // exibe cada movimento do melhor caminho { Movimento mov = melhorCaminho.RemoverMovimento(); dgvMelhorCaminho.Rows[0].Cells[i].Value = mov.ToString(); } lbTotalMenorPercurso.Text = melhorCaminho.PesoTotal.ToString(); } else // se nenhum caminho foi encontrado, o usuário é alertado e os dataGridViews limpados { LimparPictureBox(); dgvMelhorCaminho.RowCount = 0; lbTotalMenorPercurso.Text = ""; MessageBox.Show("Não foi encontrado nenhum caminho."); } }
/** * Método que retorna o melhor caminho entre duas cidades. * É passado como parâmetro a lista "caminhos", que representa todos os caminhos possíveis entre determinadas cidades. * Dessa forma, são declarados uma Pilha de retorno e uma matriz, que representará a matriz de adjacência. * Cada caminho da lista passada como parâmetro é percorrido e tem seu critério (distância, tempo ou custo) total calculado. * Por fim, a pilhaDeMovimentos de retorno recebe o caminho com o menor critério total e é retornado. */ public Caminho BuscarMelhorCaminho(List <Caminho> caminhos) { Caminho ret = new Caminho(); int menorPeso = 0; // critério -> distância, tempo ou custo (o que for escolhido pelo usuário) foreach (Caminho caminho in caminhos) { Caminho caminhoClone = (Caminho)caminho.Clone(); // caminhoClone para não desempilhar o caminho que deve ser retornado. int pesoTotal = 0; while (!caminhoClone.Movimentos.EstaVazia) { int idCidadeOrigem = caminhoClone.Movimentos.OTopo().IdCidadeOrigem; int idCidadeDestino = caminhoClone.Movimentos.OTopo().IdCidadeDestino; switch (this.Criterio) { case CriterioMelhorCaminho.Distancia: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Distancia; break; case CriterioMelhorCaminho.Tempo: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Tempo; break; case CriterioMelhorCaminho.Custo: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Custo; break; } caminhoClone.RemoverMovimento(); } if (pesoTotal < menorPeso || menorPeso == 0) // se a distância total do caminho em questão for menor que todas as outras até o momento { ret = (Caminho)caminho.Clone(); menorPeso = pesoTotal; ret.PesoTotal = menorPeso; } } return(ret); }