Author Topic: C3D Survey Figures - sample code?  (Read 8883 times)

0 Members and 1 Guest are viewing this topic.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #15 on: July 26, 2014, 02:19:06 PM »
I had some time this morning to test my theory and, yes, it does work. Sorry about the c# code, but it's what I know best.

Code - C#: [Select]
  1.         [CommandMethod("SurveyTest")]
  2.         public void surveytest()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptEntityOptions entOpts = new PromptEntityOptions("Select survey figure: ");
  8.             entOpts.SetRejectMessage("..Not a Survey Figure, try again!");
  9.             entOpts.AddAllowedClass(typeof(CivDb.SurveyFigure), true);
  10.             PromptEntityResult entRes = ed.GetEntity(entOpts);
  11.             if (entRes.Status != PromptStatus.OK)
  12.                 return;
  13.             using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
  14.             {
  15.                 AcadEntity acadent = (AcadEntity)entRes.ObjectId.GetObject(OpenMode.ForRead).AcadObject;
  16.                 AeccSurveyApplication survapp = new AeccSurveyApplication();
  17.                 survapp.Init((AcadApplication)Application.AcadApplication);
  18.                 AeccSurveyDatabase Surveydb = (AeccSurveyDatabase)survapp.ActiveDocument.Database;
  19.                 AeccSurveyProjects surveyProjs = Surveydb.Projects;
  20.                 AeccSurveyProject surveyProj = surveyProjs.FindItem("test");
  21.                 surveyProj.Open();
  22.                 if (surveyProj == null)
  23.                     return;
  24.                 AeccSurveyFigures figs = surveyProj.Figures;
  25.                 int id = 0;
  26.                 foreach (AeccSurveyFigure fig in figs)
  27.                 {
  28.                     if (fig.IsInDrawing((AcadDatabase)db.AcadDatabase) && (fig.GetObjectId((AcadDatabase)db.AcadDatabase) == acadent.ObjectID))
  29.                     {
  30.                         id=fig.ID;
  31.                         break;
  32.                     }
  33.                 }
  34.                 if (id != 0)
  35.                     figs.Remove(id);
  36.                 tr.Commit();
  37.             }
  38.         }
  39.  
Note that this removes the figure from the Database, but not from the drawing.

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #16 on: July 28, 2014, 08:23:07 AM »
Thanks Jeff!  That worked perfectly and it did delete the object from the drawing as well.  Here it is in VB.NET just as a reference for those of us who use VB.NET:

Code: [Select]
<CommandMethod("DF")> _
        Public Sub DeleteSurveyFigure()
            Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
            Dim oAcadApp As Autodesk.AutoCAD.Interop.AcadApplication = Nothing
            Dim oAeccSurveyApp As Autodesk.AECC.Interop.UiSurvey.AeccSurveyApplication = Nothing
            Dim oAeccSurveyDoc As Autodesk.AECC.Interop.UiSurvey.AeccSurveyDocument = Nothing
            Dim oAeccSurveyDB As Autodesk.AECC.Interop.Survey.AeccSurveyDatabase = Nothing
            Dim opt1 As New PromptEntityOptions(vbCrLf & "Select survey figure to delete: ")
            opt1.SetRejectMessage(vbCrLf & "error!")
            opt1.AppendKeywordsToMessage = False
            opt1.AddAllowedClass(GetType(SurveyFigure), True)

            Dim entRes As PromptEntityResult = ed.GetEntity(opt1)

            If (entRes.Status = PromptStatus.OK) Then 'single item picked
                Using tr As Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()
                    Dim acadent As AcadEntity = DirectCast(entRes.ObjectId.GetObject(OpenMode.ForRead).AcadObject, AcadEntity)
                    Dim survapp As New AeccSurveyApplication()
                    survapp.Init(DirectCast(Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication, AutoCAD.Interop.AcadApplication))
                    Dim Surveydb As AeccSurveyDatabase = DirectCast(survapp.ActiveDocument.Database, AeccSurveyDatabase)
                    Dim surveyProj As AeccSurveyProject = Surveydb.CurrentProject
                    surveyProj.Open()
                    If surveyProj Is Nothing Then
                        Return
                    End If
                    Dim figs As AeccSurveyFigures = surveyProj.Figures
                    Dim id As Integer = 0
                    For Each fig As AeccSurveyFigure In figs
                        If fig.IsInDrawing(DirectCast(db.AcadDatabase, AcadDatabase)) AndAlso (fig.GetObjectId(DirectCast(db.AcadDatabase, AcadDatabase)) = acadent.ObjectID) Then
                            id = fig.ID
                            Exit For
                        End If
                    Next
                    If id <> 0 Then
                        figs.Remove(id)
                    End If
                    tr.Commit()
                End Using
            End If
        End Sub

I really appreciate the help.  One quick question for you.  Do you happen to know if there is a method to "refresh" the list of figure lines in the survey tab?  I figured out how to toggle the .isbreakline property but the change only shows up in the figure list if I manually click on figures and select refresh.  Thanks again for all you help, you are an asset to this community!  :-)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #17 on: July 28, 2014, 09:35:00 AM »
You're welcome, happy to help! I have not found a way to force a Refresh of the Toolspace. Depending of what I'm doing, it seems like sometimes it refreshes on it's own, other times I need to manually do so.

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #18 on: July 29, 2014, 10:01:28 AM »
Yeah, your right.  It seems like it's hit or miss on whether or not it updates.  Hopefully they will add a refresh method or something like that down the road.  Have a good one, Jeff!

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #19 on: August 18, 2014, 02:20:36 PM »
One last question for you guys:

I notice that they surveyfigure has a .GetObjectID method to it that is returned as a long.

How can I utilize this to get the actual Autocad entity from the database.  Or is there a better way to get the Autocad object??
In short, I'm trying to get the AcadObject so I can add it as a break line on a surface.

The following code didn't work:
Code: [Select]
Dim BreaklineID as long
BreaklineID = fig.GetObjectId(DirectCast(db.AcadDatabase, AcadDatabase))
Dim hn As Handle = New Handle(BreaklineID)
Dim oid As ObjectId = db.GetObjectId(False, hn, 0)
Dim ent As AcadObject = DirectCast(tr.GetObject(oid, OpenMode.ForRead, False), AcadObject)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #20 on: August 18, 2014, 02:31:44 PM »
I think this is what you want:
Code - vb.net: [Select]
  1. Dim BreaklineID as long
  2. BreaklineID = fig.GetObjectId(DirectCast(db.AcadDatabase, AcadDatabase))
  3. Dim ent As AcadObject = DirectCast(tr.GetObject(oid, OpenMode.ForRead, False).AcadObject, AcadObject)
  4.  

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #21 on: August 18, 2014, 04:40:30 PM »
Thanks Jeff...  No joy...  still not working.  I keep hitting a "eUnknownHandle" exception.  I think I'm approaching this the right way but don't have the code implemented properly.  I should be able to get the handle of the objectID returned from the survey figure.

Well...  It seems that the handle doesn't exist for whatever reason.  Kean Walmsley says " If the handle entered doesn't exist, then GetObjectId() will throw an exception" which makes sense.  But it doesn't make sense that it wouldn't have a handle.
« Last Edit: August 18, 2014, 05:50:47 PM by surveyor_randy »

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #22 on: August 18, 2014, 05:57:27 PM »
The SurveyDatabase Figure may not be in the current drawing, at which point it will not have a Handle. As I showed in my earlier code, verify that it does, in fact, reside in the current drawing prior to attempting to get the ObjectId.

If fig.IsInDrawing(DirectCast(db.AcadDatabase, AcadDatabase))

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #23 on: August 19, 2014, 08:18:52 AM »
Code: [Select]
For Each fig As AeccSurveyFigure In figs
                    If fig.IsInDrawing(DirectCast(db.AcadDatabase, AcadDatabase)) AndAlso (fig.IsBreakline = True) Then

                        BreaklineID = fig.GetObjectId(DirectCast(db.AcadDatabase, AcadDatabase))
                        ed.WriteMessage(BreaklineID.ToString & vbCrLf)
                        Dim hn As Autodesk.AutoCAD.DatabaseServices.Handle = New Handle(BreaklineID)

                        Try
                            Dim oid As ObjectId = db.GetObjectId(False, hn, 0)
                        Catch ex As Autodesk.AutoCAD.Runtime.Exception
                            ed.WriteMessage("Exception" & vbCrLf)
                        End Try

                        Dim ent As AcadObject = DirectCast(tr.GetObject(oid, OpenMode.ForRead, False).AcadObject, AcadObject)
                    End If
                Next

I'm checking to see if the figures are in the drawing in the loop.  The line that is throwing the exception is "Dim oid As ObjectId = db.GetObjectId(False, hn, 0)".  It throws an exception on every survey figure.  Maybe I'm approaching this wrong.  Thank you for your help Jeff.  You are certainly an asset to the community!

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #24 on: August 19, 2014, 10:33:45 AM »
The Long returned by fig.GetObjectID is the COM ObjectID, not the .NET ObjectId. You are passing the ObjectID when the New Handle(id) is expecting the ObjectId. I think this should work:

Code - vb.net: [Select]
  1.                 Dim acaddb As AcadDatabase = DirectCast(db.AcadDatabase, AcadDatabase)
  2.                 For Each fig As AeccSurveyFigure In figs
  3.                     If fig.IsInDrawing(acaddb) AndAlso (fig.IsBreakline = True) Then
  4.                         Dim BreaklineID As Long
  5.                         BreaklineID = fig.GetObjectId(acaddb)
  6.                         Dim ent As AcadObject = DirectCast(acaddb.ObjectIdToObject(BreaklineID), AcadObject)
  7.                     End If
  8.                 Next
  9.  

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #25 on: August 19, 2014, 12:53:26 PM »
Thanks Jeff!  That worked!

It's pretty frustrating when you are getting started programming AutoCAD customizations.  I always seem to run into trouble by not knowing when I'm mixing COM and .NET objects together.  I hope someday I can fully understand how this works.  Is there a difference between the Aecc database and the autocad database?  I'm guessing the Aecc database would contain all of the civil objects.  You should consider writing a book on customizing Civil 3D.  I'd certainly buy it!  :-)

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: C3D Survey Figures - sample code?
« Reply #26 on: August 19, 2014, 01:11:06 PM »
  I always seem to run into trouble by not knowing when I'm mixing COM and .NET objects together.
Part of this confusion is compounded, I'm sure, by the use of VB.NET. Let me explain why....VB.NET doesn't care how you type things, as long as they are spelled correctly. For instance: OBjecTId, OBJECTID, objectid, ObjectID, ObjectId are all valid incarnations that would point to the same object. So you have no idea that the COM AcadDatabase ObjectID and the .NET Managed Acad.Database ObjectId are two different things. Whereas, in C#, you must type them exactly as they are defined in the API. So ObjectID (COM) and ObjectId (.NET) ARE 2 different objects, this is how I keep things sane when combining COM and managed code (which I try to keep to a minimum).

When working with C3D objects, ALL COM objects start with Aecc. When working with Acad object, ALL COM objects start with Acad. Their .NET counterparts do not: AeccSurveyFigure vs SurveyFigure; AcadDatabase vs Database; AeccAlignment vs Alignment; AcadEntity vs Entity

surveyor_randy

  • Guest
Re: C3D Survey Figures - sample code?
« Reply #27 on: August 21, 2014, 10:00:37 AM »
Thanks for that nice explanation Jeff.  I had no idea that there were differences in ObjectId (.NET) vs ObjectID (.COM).  I also never knew that all civil objects that start with "Aecc" are referencing COM objects and any AutoCAD objects that start with "Acad" are also COM objects.  Knowing this will help me out tremendously.  I know a little C#.  Maybe it's time that I just abandon VB.NET altogether.  It seems that it would make programming for C3D much easier.  The languages are similar in many ways.  It's just getting the syntax down.  Thanks again for all of your help!  :-D

GTVic

  • Mosquito
  • Posts: 1
Re: C3D Survey Figures - sample code?
« Reply #28 on: May 06, 2016, 04:50:38 PM »
Hope it is okay to resurrect this. I usually try for late binding to support as many versions of possible with a single DLL where COM is required. But I cannot get fig.GetObjectId(oAeccSurveyDB) to work in this case where the fig.IsInDrawing(oAeccSurveyDB) call works fine. The exception is Type mismatch. (Exception from HRESULT: 0x8002802A (TYPE_E_WRONGTYPEKIND))

Code below shows TEST1 which works and TEST2 which does not. The only difference is the the variable definition "As Object".

Code: [Select]
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.Civil.DatabaseServices
Imports Autodesk.AECC.Interop.Survey
Imports System
Public Class Main

    Implements Autodesk.AutoCAD.Runtime.IExtensionApplication

    Public Sub Initialize() Implements IExtensionApplication.Initialize
        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor()
        ed.WriteMessage("Initializing - " & My.Application.Info.AssemblyName)
    End Sub

    Public Sub Terminate() Implements IExtensionApplication.Terminate
    End Sub

    <CommandMethod("TEST1")> Public Sub Test1()

        Dim oAcadApp As Autodesk.AutoCAD.Interop.AcadApplication = Nothing
        Dim oAeccSurveyApp As Autodesk.AECC.Interop.UiSurvey.AeccSurveyApplication = Nothing
        Dim oAeccSurveyDoc As Autodesk.AECC.Interop.UiSurvey.AeccSurveyDocument = Nothing
        Dim oAeccSurveyDB As Autodesk.AECC.Interop.Survey.AeccSurveyDatabase = Nothing

        oAcadApp = GetObject(, "AutoCAD.Application")
        oAeccSurveyApp = oAcadApp.GetInterfaceObject("AeccXUiSurvey.AeccSurveyApplication.10.4")
        oAeccSurveyDoc = oAeccSurveyApp.ActiveDocument 'AeccSurveyCOMDoc
        oAeccSurveyDB = oAeccSurveyApp.ActiveDocument.Database

        Using trans As Autodesk.AutoCAD.DatabaseServices.Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()

            Dim oCurrentProject As AeccSurveyProject = oAeccSurveyDB.CurrentProject

            For Each fig As AeccSurveyFigure In oCurrentProject.Figures
                If fig.IsInDrawing(oAeccSurveyDB) Then
                    Dim comID As Long = fig.GetObjectId(oAeccSurveyDB)
                    Dim netID As Object = oAeccSurveyDB.ObjectIdToObject(comID)
                    Dim figID As Integer = fig.ID
                End If
            Next

        End Using

    End Sub

    <CommandMethod("TEST2")> Public Sub Test2()

        Dim oAcadApp As Object = Nothing
        Dim oAeccSurveyApp As Object = Nothing
        Dim oAeccSurveyDoc As Object = Nothing
        Dim oAeccSurveyDB As Object = Nothing

        oAcadApp = GetObject(, "AutoCAD.Application")
        oAeccSurveyApp = oAcadApp.GetInterfaceObject("AeccXUiSurvey.AeccSurveyApplication.10.4")
        oAeccSurveyDoc = oAeccSurveyApp.ActiveDocument 'AeccSurveyCOMDoc
        oAeccSurveyDB = oAeccSurveyApp.ActiveDocument.Database

        Using trans As Autodesk.AutoCAD.DatabaseServices.Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()

            Dim oCurrentProject As Object = oAeccSurveyDB.CurrentProject

            For Each fig As Object In oCurrentProject.Figures
                If fig.IsInDrawing(oAeccSurveyDB) Then
                    Dim comID As Long = fig.GetObjectId(oAeccSurveyDB)
                    Dim netID As Object = oAeccSurveyDB.ObjectIdToObject(comID)
                    Dim figID As Integer = fig.ID
                End If
            Next

        End Using

    End Sub

End Class

Code: [Select]
System.Runtime.InteropServices.COMException (0x8002802A): Type mismatch. (Exception from HRESULT: 0x8002802A (TYPE_E_WRONGTYPEKIND))
   at Microsoft.VisualBasic.CompilerServices.LateBinding.InternalLateCall(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack, Boolean IgnoreReturn)
   at Main.Test2() in F:\Visual Studio\Projects\Main.vb:line 73
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()