Ad

Sunday, March 14, 2010

Flatten Feature Line

In Civil 3D there are several ways to flatten a feature line to 0 elevation. You may find that none of them are very convenient. It may be nice to have the ability to right click a feature line and flatten it. To do it now you have to go into the elevation editor or use the regular AutoCAD FLATTEN command. One can use the API to add a command to the right click menu to flatten a feature line from there. To do it modify the cui and add the command to the right click menu of a feature line. There is a way to programmatically add it, but I didn’t do it here.
The code to do it in vb.net is below:
   1:  Option Explicit On
   2:  
   3:  Imports System.Runtime.InteropServices.Marshal
   4:  Imports Autodesk.AutoCAD.Runtime
   5:  Imports Autodesk.AutoCAD.ApplicationServices
   6:  Imports Autodesk.AutoCAD.DatabaseServices
   7:  Imports Autodesk.AutoCAD.EditorInput
   8:  Imports Autodesk.AutoCAD.Geometry
   9:  Imports Autodesk.Civil.DatabaseServices.Styles
  10:  Imports Autodesk.Civil.ApplicationServices
  11:  Imports Autodesk.Civil.Land.DatabaseServices
  12:  Imports AeccLandLib = Autodesk.AECC.Interop.Land
  13:  Imports AeccLandUi = Autodesk.AECC.Interop.UiLand
  14:  Imports AcadCom = Autodesk.AutoCAD.Interop
  15:  Imports System.Security
  16:  Imports C3DRemindersPack.Utilities
  17:   
  18:  <Assembly: CommandClass(GetType(FlattenFeatureLine))> 
  19:   
  20:  Public Class FlattenFeatureLine
  21:   
  22:      Public Shared g_sName As String
  23:   
  24:      <CommandMethod("C3DRFlattenFeatureLine", CommandFlags.UsePickSet Or CommandFlags.Redraw Or CommandFlags.Modal)> _
  25:      Public Sub cmdFlattenFeatureLine()
  26:   
  27:          Try
  28:              'Get Civil 3D application, document and database
  29:              GetCivilObject()
  30:   
  31:              Dim oDoc As Document = Application.DocumentManager.MdiActiveDocument
  32:              Dim ed As Editor = oDoc.Editor
  33:   
  34:              Try
  35:                  Dim selectionRes As PromptSelectionResult = ed.SelectImplied()
  36:                  If selectionRes.Status = PromptStatus.Error Then
  37:                      ' Ask the user to select points.
  38:                      Dim selectionOpts As New PromptSelectionOptions()
  39:                      selectionOpts.MessageForAdding = vbLf & "Select feature line to flatten: "
  40:                      selectionRes = ed.GetSelection(selectionOpts)
  41:                  Else
  42:                      ' If there was a pickfirst set, clear it.
  43:                      ed.SetImpliedSelection(New ObjectId(-1) {})
  44:                  End If
  45:   
  46:                  ' If the user hasn't cancelled.
  47:                  If selectionRes.Status = PromptStatus.OK Then
  48:                      ' Take the objects one by one.
  49:                      Dim tr As Transaction = oDoc.TransactionManager.StartTransaction()
  50:                      Try
  51:   
  52:                          Dim objIds As ObjectId() = selectionRes.Value.GetObjectIds()
  53:                          For Each objId As ObjectId In objIds
  54:                              Dim ent As Entity = DirectCast(tr.GetObject(objId, OpenMode.ForRead), Entity)
  55:                              ' Check to see if the entity is a point.
  56:                              If TypeOf ent Is FeatureLine Then
  57:                                  Dim oFeatLine As AeccLandLib.AeccLandFeatureLine
  58:   
  59:                                  Dim entid As ObjectId = ent.ObjectId
  60:                                  Dim obj As Object = g_oCivil3DDoc.ObjectIdToObject(entid.OldIdPtr)
  61:                                  oFeatLine = obj
  62:                                  oFeatLine.ShowToolTip() = False
  63:                                  Dim dPoints() As Double
  64:                                  dPoints = oFeatLine.GetPoints()
  65:   
  66:                                  Dim i As Integer
  67:   
  68:                                  For i = 2 To UBound(dPoints)
  69:                                      dPoints(i) = 0
  70:                                      i = i + 2
  71:                                  Next
  72:   
  73:                                  oFeatLine.SetPointsElevation(dPoints)
  74:   
  75:                              End If
  76:                          Next
  77:                          tr.Commit()
  78:                      Catch ex As Autodesk.AutoCAD.Runtime.Exception
  79:                          ed.WriteMessage(ex.Message)
  80:                          tr.Abort()
  81:   
  82:                      End Try
  83:                  End If
  84:              Catch ex As Autodesk.AutoCAD.Runtime.Exception
  85:                  ed.WriteMessage(ex.Message)
  86:              End Try
  87:   
  88:   
  89:   
  90:          Catch ex As Exception
  91:   
  92:          Finally
  93:   
  94:   
  95:          End Try
  96:   
  97:   
  98:      End Sub
  99:   
 100:  End Class

I may have some unneeded items in it, but it should get the job done. Hopefully in a future version the Civil 3D developers will provide the command currently located on the Elevation Editor. I didn’t test it, but the code should take several selected feature lines and flatten all of them. You should be able to take the code from the Civil 3D Reminders Pack and add this class to it and compile the code and use netload to load the dll.

Friday, March 12, 2010

Will it Clear?

Occasionally I’ve been tasked with seeing if a car, truck or aircraft engine cart will make it over a vertical curve without scraping on the pavement. In the past I’ve used a template over a paper set of plans. Today I had some time to see if I could automate the task to not have to create a paper template. I think I came up with a pretty good way of doing it.
The quick method I’m utilizing is drawing a polyline along the profile in a profile view. I’ve hard coded the values I need, but also added the code to prompt the user for the information.
   1:  Sub PerformProfileDemonstration()
   2:      
   3:      ' Always get the objects again since MDI is supported.
   4:      If (GetBaseCivilObjects() = False) Then
   5:          MsgBox "Error accessing top civil objects."
   6:          Exit Sub
   7:      End If
   8:      
   9:      Dim oAcadObj As AcadObject
  10:      Dim vPt As Variant
  11:      
  12:      ThisDrawing.Utility.GetEntity oAcadObj, vPt, "Pick Profile: "
  13:      
  14:      Dim dAxelHt As Double
  15:      dAxelHt = 1.5 ' ThisDrawing.Utility.GetReal("Enter Axel Height: ")
  16:      
  17:      Dim dLength As Double
  18:      dLength = 35 ' ThisDrawing.Utility.GetReal("Enter Length between Axels: ")
  19:      
  20:      If (TypeOf oAcadObj Is AeccProfile) Then
  21:          
  22:          Dim oProfile As AeccProfile
  23:          Set oProfile = oAcadObj
  24:          
  25:          ThisDrawing.Utility.GetEntity oAcadObj, vPt, "Pick Profile View: "
  26:          Dim oProfileView As AeccProfileView
  27:          If (TypeOf oAcadObj Is AeccProfileView) Then
  28:              Set oProfileView = oAcadObj
  29:          Else
  30:              Exit Sub
  31:          End If
  32:          
  33:          Dim dStartSta As Double
  34:          Dim dStaInt As Double
  35:          Dim dEndSta As Double
  36:          
  37:          dStartSta = 250 ' ThisDrawing.Utility.GetReal("Enter starting Station: ")
  38:          dEndSta = 400 'ThisDrawing.Utility.GetReal("Enter Ending Station: ")
  39:          dStaInt = 2 ' ThisDrawing.Utility.GetReal("Enter Station interval: ")
  40:          
  41:          Dim oPoly As AcadLWPolyline
  42:          Dim dPoints(0 To 7) As Double
  43:          Dim dStartElev As Double
  44:          Dim dEndElev As Double
  45:          Do Until dStartSta > dEndSta
  46:              
  47:              dStartElev = oProfile.ElevationAt(dStartSta)
  48:              dEndElev = oProfile.ElevationAt(dStartSta + dLength)
  49:              
  50:              ' Get the points on the profile view, it will account for vertical exageration.
  51:              oProfileView.FindXYAtStationAndElevation dStartSta, dStartElev, dPoints(0), dPoints(1)
  52:              oProfileView.FindXYAtStationAndElevation dStartSta, dStartElev + dAxelHt, dPoints(2), dPoints(3)
  53:              oProfileView.FindXYAtStationAndElevation dStartSta + dLength, dEndElev + dAxelHt, dPoints(4), dPoints(5)
  54:              oProfileView.FindXYAtStationAndElevation dStartSta + dLength, dEndElev, dPoints(6), dPoints(7)
  55:              
  56:              ThisDrawing.ModelSpace.AddLightWeightPolyline dPoints
  57:                  
  58:              dStartSta = dStartSta + dStaInt
  59:          Loop
  60:          
  61:      End If
  62:   
  63:  End Sub

The output looks something like this:
image
As you can see my vertical curve is too steep for the vehicle. You’ll also notice that I haven’t written the code for the tires to be perpendicular to the profile. In order to get realistic values I probably should revise the code to account for this. Since I don’t have that much time available to day I might leave that for another post or maybe you can come up with a way to do it. The hard part isn’t getting the first tire to be perpendicular, but finding out where the other other tire should sit and be perpendicular to the surface. Fortunately the difference isn’t that much so this method should give a close enough answer. In the picture above the difference was 0.097’.

Monday, March 08, 2010

Copying Profile from Surface

Once upon a time in a land far, far, away (in Civil 3D 2008) you could easily copy profiles from surface by clicking on the Copy Profile button on the Profile Layout Tools bar. But the nefarious developers, well not really, of the New Hampshire decided to make things hard on the loyal users of Civil 3D 2010 by graying out the Copy Profile button.

image

“What are we to do?”, the users asked puzzling, "Is this a bug or feature?”

Off from the fair land of the Central Coast of California a shout out came “Fear not for there is another way!”

“For we can create a profile from surface, making sure to set the surface to be static or change an existing profile created from surface to be Static.”

image

Now the profile may be copied. The profile may even be set to dynamic after creation (though you loose the ability to copy the profile) and set back to static to copy the profile again. You may have close out of the Profile Layout Tools and then open it up again to get the copy button to be un-grayed out.

Copying the profile helps create a visual method to design by, by copying the profile it can be moved up or down  to show a minimum or maximum depth from a surface.

Friday, March 05, 2010

Set Elevation Points on a Feature Line (API)

Sometimes the Civil 3D API can be a bit confusing. Sometimes the API does a similar task in one place and a totally different way in another place. Setting elevation point(s) on a feature line is one such case. It can be a bit confusing on trying to figure out what exactly is required. Below is some sample code that shows how to set elevation points, assuming you already have a feature line created.

        Dim dPointPL(8) As Double
dPointPL(0) = 2010: dPointPL(1) = 2010
dPointPL(3) = 2579: dPointPL(4) = 2579
dPointPL(6) = 3010: dPointPL(7) = 2510

' SetPointElevation Method sets the elevation by input point.
Dim dPointElev(2) As Double
dPointElev(0) = 2010: dPointElev(1) = 2010: dPointElev(2) = 43
oFeatureLine2.SetPointElevation dPointElev

' SetPointsElevation Method sets the elevation by input points.
Dim vPointsPL As Variant
vPointsPL = dPointPL
vPointsPL(2) = 67
vPointsPL(5) = 79
vPointsPL(8) = 109
oFeatureLine2.SetPointsElevation vPointsPL



If I remember correctly you need to make sure the point is on the feature line before setting the point elevation.

Tuesday, March 02, 2010

Field Code Escape

I’m brushing up on my survey coding methods. To add a comment to the codes use a / (forward slash) to indicate a comment. The comments can be embedded into coding by adding another / (forward slash) at the end of the comment.

For instance the field book code below:

EP1 B/parking space line/LN CPN211

is read into Civil 3D as:

EP1 B LN CPN211

since Civil 3D ignores the comment.

LinkWithin

Blog Widget by LinkWithin

Ad