Por Augusto Gonçalves, Autodesk Developer Network
Este post é uma continuação do post anterior, onde as curvas de bordo foram numeradas. Aqui o objetivo é criar uma tabela com o resumo das curvas, contendo o número, raio, comprimento, norte/este do PC e PT. A figura abaixo apresenta a tabela de resultado.
Neste caso iremos criar uma tabela utilizando APIs do AutoCAD. Isto significa que a tabela será independente do Civil 3D e não irá atualizar como outras tabelas nativas. Ainda não temos APIs para acessar as tabelas nativas do Civil 3D.
Para criar a tabela iremos utilizar o objeto Table, que está dentro do namespace Autodesk.AutoCAD.DatabaseServices. Um namespace do .NET é utilizado para organizar os objetos, e sempre iremos encontrar objetos com características em comum. Neste case, o namespace é o DatabaseServices, que contém os objetos de banco de dados do AutoCAD, ou seja, aqueles que são gravados no desenho.
O nosso código anterior já tinha este e outros namespaces, como EditorInput, que contem a linha de comando e objetos de seleção, ou Geometry, que contém objetos relacionados a operações geométricas. É possível ter namespaces com mesmo nome, como DatabaseServices, mas em diferentes APIs, como Autodesk.AutoCAD e Autodesk.Civil.
Para este exemplo iremos criar uma tabela com 5 colunas. A quantidade de linhas será definida pela quantidade de curvas + 2, para conter o cabeçalho. Para adaptar este código e incluir mais colunas, é necessário alterar esta quantidade e escrever os valores desejados.
O código abaixo contém o código do post anterior em cinza, e o código adicional em cores, fica a sua escolha copiar o código inteiro (e colar substituindo no arquivo CurvasBordo.vb) ou adicionar as novas linhas.
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 acontencer,
‘ então temos um arco e adicionamos a lista,
‘ se não, vamos para a proxima entidade
Dim curva As Arc = TryCast(trans.GetObject(
idEntidade, OpenMode.ForRead), Arc)
‘ se for vazio, então proximo 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
‘ próximo 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
‘ *********************************************
‘ Incluir a tabela de curvas
‘ *********************************************
‘ como este comando é uma continuação, vamos
‘ pedir ao usuário para selecionar o ponto de
‘ inserção da tabela, mas se decidir cancelar
‘ (com ESC), então vamos aceitar o que já foi
‘ feito, mas se for OK, continuamos com a tabela
Dim resSelPontoInsercaoTabela As _
PromptPointResult = _
ed.GetPoint(“Ponto inserção da tabela: “)
If (resSelPontoInsercaoTabela.Status <> _
PromptStatus.OK) Then
trans.Commit()
Exit Sub
End If
‘ criar uma tabela, com 5 colunas e linhas para
‘ as curvas que foram encontradas
Dim tabela As New _
Autodesk.AutoCAD.DatabaseServices.Table
tabela.SetSize(cont + 1, 5)
tabela.TableStyle = db.Tablestyle
tabela.Position = resSelPontoInsercaoTabela.Value
‘ iniciar a tabela com o cabeçalho
Dim linha As Integer = 0
linha = 0 ‘ linha de título
tabela.Cells(linha, 0).TextString = “Curvas de Bordo”
tabela.MergeCells(CellRange.Create(tabela, 0, 0, 0, 4))
linha = 1 ‘ linha de cabeçalho
tabela.Cells(linha, 0).TextString = “Número”
tabela.Cells(linha, 1).TextString = “Raio”
tabela.Cells(linha, 2).TextString = “Comp.”
tabela.Cells(linha, 3).TextString = “PC”
tabela.Cells(linha, 4).TextString = “PT”
linha = 2 ‘ próxima linha
‘ percorrer as curvas encontradas
cont = 1
For Each curva As Arc In curvasBordoFiltrada
‘ coluna 1: número
tabela.Cells(linha, 0).TextString = _
cont.ToString()
‘ coluna 2: raio, com 4 casas decimais
tabela.Cells(linha, 1).TextString = _
String.Format(“{0:0.000}”, curva.Radius)
‘ coluna 3: comprimento
tabela.Cells(linha, 2).TextString = _
String.Format(“{0:0.000}”, curva.Length)
‘ coluna 4: norte e este do primeiro ponto
tabela.Cells(linha, 3).TextString = _
String.Format(“{0:0.0000}, {1:0.0000}”, _
curva.StartPoint.Y, _
curva.StartPoint.X)
‘ coluna 5: norte e este do segundo ponto
tabela.Cells(linha, 4).TextString = _
String.Format(“{0:0.0000}, {1:0.0000}”, _
curva.EndPoint.Y, _
curva.EndPoint.X)
cont += 1 ‘ próximo número de curva
linha += 1 ‘ próxima linha
Next
‘ ajusta o layout da tabela
tabela.GenerateLayout()
‘ insere a tabela no model space
mSpace.AppendEntity(tabela)
trans.AddNewlyCreatedDBObject(tabela, True)
‘ *********************************************
‘ 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
Os passos adicionais são exatamente os mesmos: chamar o Build no Visual Basic 2010 Express e em seguida executar NETLOAD no Civil 3D para carregar a DLL criada. Finalmente o comando NUMERARCURVABORDO.
Este post conclui o exemplo com curvas de bordo. No próximo post iremos abordar outros pontos da API.