Por Augusto Gonçalves, Autodesk Developer Network
Neste post irei mostrar como numerar as curvas de bordo de um alinhamento utilizando VB.NET. É necessário ter completado o exemplo do post anterior.
O objetivo geral é, em um dado alinhamento, por exemplo em verde na figura abaixo, localizar as curvas de bordo e escrever um texto indicativo numerado, por exemplo, “Curva = 1”.
Para numerar as curvas, é necessário descobrir a ordem. Sempre que trabalhamos com programação, temos que elaborar uma regra inequívoca para determinar a quais curvas serão consideradas e a ordem.
Então algumas regras deve ser adotadas: deve existir um Alinhamento do Civil 3D como referência, as curvas de bordo devem ser do tipo Arco do AutoCAD, e estes arcos devem estar até uma distância máxima do alinhamento. Estas regras definem quais arcos serão considerados.
Para determinar a ordem iremos determinar qual a estaca mais próxima do centro do arco que representa a curva de bordo (ver figura abaixo). Esta ordem deve ser definida no sentido de crescimento das estacas. Desta maneira, independente do lado, a numeração dos arcos será definida pela estaca onde o centro do arco está projetado.
Dica: embora possam parecer óbvias, as regras que serão implementadas em programação devem ser o mais especificas possíveis. Regras fracas levam a rotinas que podem falhar (produzir resultados inesperados).
Preparando para o código!
Partindo do projeto do post anterior, inicie o Visual Basic 2010 Express, abra o projeto ProjetoCivil3DBR. Na janela de Solution Explorer, clique com o botão direto no projeto e escolha Add, em seguida a opção Class. No formulário que se abrirá, digite o nome da classe, neste exemplo CurvasBordo.
Na prática não é necessário criar uma classe para cada novo comando, mas iremos adotar esta abordagem para facilitar a organização. A nova classe será criada em um novo arquivo .vb do projeto.
API de busca e ordenação
Na prática vamos sempre assumir que uma lista de qualquer coisa estará fora da ordem desejada. Para este exemplo, temos que selecionar todos os arcos, filtrar pelos que estão até uma determinada distância máxima do alinhamento, e ordená-los pela estaca.
A API do Civil 3D não incluir métodos para filtros muito específicos ou ordenação, mas por se tratar de uma API .NET, podemos utilizar recursos nativos da plataforma VB.NET. E isto vale para (praticamente) todos as maravilhas do .NET! Espetacular!
Para filtro e ordenação, dentre outros, temos uma API do .NET chamada LINQ (Language-Integrated Query), que existe desde a versão 3.5 e é extremamente útil. Vale a pena estudar um pouco.
Nota: Civil 3D 2012, 2013 e 2014 usam .NET 4.0.
Hora do código!
Como no exemplo anterior, todas a linhas de código que começam com ‘ (aspas simples) são comentários e ficam verde no Visual Basic 2010 Express. Utilizamos comentários para explicar o que um conjunto de linhas de código irá executar. Não é necessário, ou prático, comentar todas a linhas de código, apenas o que for necessário.
O código abaixo começa de maneira similar ao código do post anterior, com CommandMethod. Esta marcação (atributo em .NET) define o nome do comando no AutoCAD Civil 3D. Ou seja, sempre que digitarmos NUMERARCURVABORDO na linha de comando, iremos executar a rotina deste comando.
Este comando requer que o usuário selecione um alinhamento e digite uma distância. Temos que garantir que isso ocorra, caso contrário o comando não pode prosseguir. Observe o Exit Sub quando o resultado da seleção não é OK (o código <> significa diferente).
Em seguida selecionamos todos os arcos do model space. Estes arcos serão filtrados pela distancia máxima e ordenados pelo estaca, resultando na coleção curvasBordoFiltrada. Esta coleção será utilizada para a criação dos textos indicativos (similares ao label).
Agora copie o código abaixo, cole no arquivo CurvaBordo.vb aberto no Visual Basic 2010 Express. O resultado deve ser como na imagem abaixo. Retire eventuais linhas em branco.
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.Civil.DatabaseServices
Public Class CurvasBordo
<CommandMethod(“numerarCurvaBordo”)> _
Public Sub CmdNumerarCurvaBordo()
‘ acessar o editor do AutoCAD
‘ através deste objeto podemos selecionar
‘ entidade na tela
Dim ed As Editor = Application.DocumentManager.
MdiActiveDocument.Editor
‘ selecionar o alinhamento
‘ o método AddAllowedClass garante que apenas alinhamentos
‘ poderão ser selecionados pelo usuário
Dim opSelAlinhamento As New PromptEntityOptions(
“Selecione o alinhamento: “)
opSelAlinhamento.SetRejectMessage(“Apenas alinhamento”)
opSelAlinhamento.AddAllowedClass(GetType(Alignment), True)
Dim resSelAlinhamento As PromptEntityResult =
ed.GetEntity(opSelAlinhamento)
If (resSelAlinhamento.Status <> PromptStatus.OK) Then Exit Sub
Dim idAlinhamento As ObjectId = resSelAlinhamento.ObjectId
‘ distancia máxima para centro do circulo
Dim opSelDistancia As New PromptDistanceOptions(
“Distancia máxima das curvas (centro): “)
opSelDistancia.AllowZero = False
Dim resSelDistancia As PromptDoubleResult =
ed.GetDistance(opSelDistancia)
If (resSelDistancia.Status <> PromptStatus.OK) Then Exit Sub
Dim distanciaMax As Double = resSelDistancia.Value
Dim db As Database = Application.DocumentManager.
MdiActiveDocument.Database
Using trans As Transaction =
db.TransactionManager.StartTransaction
‘ abrir o alinhamento
Dim alinhamento As Alignment = trans.GetObject(
idAlinhamento, OpenMode.ForRead)
‘ abrir o model space
Dim mSpace As BlockTableRecord = trans.GetObject(
alinhamento.OwnerId, OpenMode.ForWrite)
‘ criar uma lista de arcos
Dim curvasBordo As New DBObjectCollection
‘ percorrer o model space buscando por curvas de bordo
For Each idEntidade As ObjectId In mSpace
‘ abrir cada entidade do model space e tentar
‘ converter para Arc, se a conversão acontecer,
‘ então temos um arco e adicionamos a lista,
‘ se não, vamos para a próxima entidade
Dim curva As Arc = TryCast(trans.GetObject(
idEntidade, OpenMode.ForRead), Arc)
‘ se for vazio, então próximo item da lista
If (curva Is Nothing) Then Continue For
curvasBordo.Add(curva)
Next
‘ usando LINQ para filtrar e ordenar os arcos
‘ obteremos o ponto no alinhamento mais próximo do centro
‘ do arco em seguida iremos ordenar estes pontos, desta
‘ maneira os arcos estarão ordenados pelo ponto mais
‘ proximo no alinhamento
Dim curvasBordoFiltrada =
From arco As Arc In curvasBordo
Where arco.Center.DistanceTo(
alinhamento.GetClosestPointTo(
arco.Center, False)) < distanciaMax
Order By alinhamento.GetDistAtPoint(
alinhamento.GetClosestPointTo(arco.Center, False))
‘ numerador que será usado no texto
Dim cont As Integer = 1
‘ escrever os textos nas curvas utilizando DBText
‘ os textos serão independentes do alinhamento
For Each curva As Arc In curvasBordoFiltrada
‘ linha de referência entre os pontos inicial e
‘ final do arco. Esta linha não será desenhada no
‘ Civil3D, apenas utilizada para encontrar o midpoint,
‘ onde será inserido o texto
Dim linhaRef As New LineSegment3d(
curva.StartPoint, curva.EndPoint)
Dim labelCurva As New DBText
labelCurva.SetDatabaseDefaults()
‘ especificar o texto
labelCurva.TextString = String.Format(
“Curva = {0}”, cont)
‘ alinha pelo centro
labelCurva.HorizontalMode =
TextHorizontalMode.TextCenter
‘ alinhar pelo MidPoint
labelCurva.AlignmentPoint = linhaRef.MidPoint
‘ rotacionar alinhado com os pontos do arco
labelCurva.Rotation = linhaRef.
Direction.GetAngleTo(Vector3d.XAxis)
‘ adicionar ao model space
mSpace.AppendEntity(labelCurva)
trans.AddNewlyCreatedDBObject(labelCurva, True)
‘ incrementar o numerador
cont += 1
Next
‘ este ‘commit’ confirma que as alterações estão
‘ ok e podem ser enviadas para a base de dados do C3D
trans.Commit()
End Using
End Sub
End Class
Agora com o código inserido no Visual Basic 2010 Express, vá ao menu Debug, escolha a opção Build ProjetoCivil3DBR, da mesma forma que foi feito para o exemplo do primeiro post.
Finalmente abra o Civil 3D, execute o comando NETLOAD, escolha a DLL na pasta Release. Assim como no exemplo do primeiro post, a DLL deve estar na pasta:
…\ProjetoCivil3DBR\ProjetoCivil3DBR\bin\Release\ProjetoCivil3DBR.dll
O novo comando está pronto, execute NUMERARCURVABORDO, selecione o alinhamento, especifique a distancia máxima e pronto. O textos serão desenhados no projeto do Civil 3D.
No próximo post iremos incrementar este comando para desenhar uma tabela de curvas, com raio, comprimento, PC e PT.
Sugestões e comentários são bem vindos!