Author Topic: Object ID and Entity  (Read 19599 times)

0 Members and 1 Guest are viewing this topic.

Helsinki_Dave

  • Guest
Object ID and Entity
« on: April 29, 2011, 09:06:19 AM »
Hi, I'm working with ACA and vb.net, could anyone clarify the Object Browser info given below.

Public Shared Function GetClassification(ByVal entity As Autodesk.Aec.DatabaseServices.Entity, ByVal classificationDefinitionId As Autodesk.AutoCAD.DatabaseServices.ObjectId) As Autodesk.AutoCAD.DatabaseServices.ObjectId
     Member of: Autodesk.Aec.DatabaseServices.ClassificationDefinition

Summary:
Get an entity's classification for a specific classification definition.

Parameters:
entity: The entity.
classificationDefinitionId: The classification definition.

Return Values:
Returns an entity's classification for a specific classification definition.

Exceptions:
Autodesk.AutoCAD.Runtime.Exception: Autodesk.AutoCAD.Runtime.Exception.



I think that what this is saying here is that I need to isolate an entity (which the classifcation is attached to - which is my case is a AecDbSpace. Then I need to  add to this isolate the Object ID for the classfication that I'm want to read.

What I'm not sure about is if I have the AecDbSpace ObjectID, how do I turn this into an entity or are they in effect, the same kind of thing. Currently my code is not reading any classfications in the count property (spobj.Classifications.Count) when I just use a straight objectID - where there should be four classfications available on these AecDbSpace objects.

The mere fact that Intellisense gave me the option of writing spobj.Classifications suggests to me that MSExpress considers spobj to be an Entity - so maybe I have got this right - which then would mean that I'm using the wrong Entity to create a collection of classifications from.
Thanks in advance!

Code: [Select]
#Region "Namespaces"

Imports System

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

Imports Autodesk.Aec.DatabaseServices
Imports Autodesk.Aec.PropertyData.DatabaseServices

Imports DBTransactionManager = Autodesk.AutoCAD.DatabaseServices.TransactionManager
Imports AcadDb = Autodesk.AutoCAD.DatabaseServices
Imports AecDb = Autodesk.Aec.DatabaseServices
Imports AecPropDb = Autodesk.Aec.PropertyData.DatabaseServices

Imports ObjectId = Autodesk.AutoCAD.DatabaseServices.ObjectId
Imports ObjectIdCollection = Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection

Imports AecDbSrvcs = Autodesk.Aec.DatabaseServices
Imports ArchDbSrvcs = Autodesk.Aec.Arch.DatabaseServices

#End Region

Public Class Renumber_Blocks

#Region "Command_Renumber"
    ' <summary>
    ' Command implementation for SetPropertyDataByName.
    ' </summary>
    <Autodesk.AutoCAD.Runtime.CommandMethod("AecPropertySampleMgd", "koe", Autodesk.AutoCAD.Runtime.CommandFlags.Modal)> _
    Public Sub Command_SetPropertyDataByName()
        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim psetname As String = "Block_properties"
        Dim pname As String = "Block_ID"
        Dim NewValue As Integer = 0

        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim tm As AcadDb.TransactionManager = db.TransactionManager

        Dim dbobj As AcadDb.DBObject

        Dim trans As Transaction = tm.StartTransaction()

        Dim bt As BlockTable = tm.GetObject(db.BlockTableId, OpenMode.ForRead, False)
        Dim btr As BlockTableRecord = tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead, False)

        Dim id As ObjectId
        For Each id In btr
            If id.ObjectClass.Name = "AecDbSpace" Then

                dbobj = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim spobj As ArchDbSrvcs.Space = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim c_classf As ClassificationCollection = spobj.Classifications


                'Dim Clasf_Entity As Autodesk.Aec.DatabaseServices.Entity = CType(tm.GetObject(dbobj, OpenMode.ForRead, True), Autodesk.Aec.DatabaseServices.Entity)

                'Dim target_clasf As Autodesk.Aec.DatabaseServices.ClassificationDefinition = ClassificationDefinition.GetClassification(Clasf_Entity)

                'GetClassification(ByVal entity As Autodesk.Aec.DatabaseServices.Entity, ByVal classificationDefinitionId As Autodesk.AutoCAD.DatabaseServices.ObjectId) As Autodesk.AutoCAD.DatabaseServices.ObjectId

                If c_classf.Count <> 0 Then

                    Dim classf_category As String = c_classf(0).ToString

                End If

                Dim spceStyle As ArchDbSrvcs.SpaceStyle = tm.GetObject(spobj.StyleId, OpenMode.ForRead, False, False)

                If spceStyle.Name = "Block" Then


                    'Dim values As System.Collections.ArrayList = GetValueFromPropertySetByName(psetname, pname, dbobj)
                    'Dim value_unit As AecPropDb.PropertyValueUnitPair
                    'For Each value_unit In values
                    '    Dim currentValue As Object = value_unit.Value
                    '    If Not currentValue Is Nothing Then
                    '        If (currentValue.GetType() Is GetType(Double)) Then
                    Dim trans2 As Transaction = tm.StartTransaction()

                    dbobj.UpgradeOpen()

                    Dim WasChanged As Boolean = SetValueFromPropertySetByName(psetname, pname, dbobj, NewValue)
                    If WasChanged Then
                        ed.WriteMessage(vbCrLf + "Succesfully changed value for objectId = " + id.ToString())
                        ed.WriteMessage(vbCrLf + " New Value = " + NewValue.ToString())
                        NewValue = NewValue + 1
                    Else
                        ed.WriteMessage(vbCrLf + "Failed to change value for objectId = " + id.ToString())
                    End If
                    trans2.Commit()
                    trans2.Dispose()
                    '    End If
                    'End If
                End If
            End If
        Next
        'Next
        trans.Commit()
        trans.Dispose()
    End Sub
#End Region

#Region "GetValueFromPropertySetByName"
    ' <summary>
    ' Returns the value (PropertyValueUnitPair) of a property by name on a given object.
    ' </summary>
    ' <param name="pname">The property name to find on the object.</param>
    ' <param name="dbobj">The object to find the property on. </param>
    ' <returns> An array of the values </returns>
    Public Function GetValueFromPropertySetByName(ByVal psetname As String, ByVal pname As String, ByVal dbobj As AcadDb.DBObject) As ArrayList


        Dim setIds As ObjectIdCollection = AecPropDb.PropertyDataServices.GetPropertySets(dbobj) 'this is almost like a count in that it is counting the number of psets attached to dbobj

        Dim values As System.Collections.ArrayList = New System.Collections.ArrayList() 'this sets up the collector that is returned by the function

        If setIds.Count = 0 Then
            Return values
        End If

        'at this point, where setIds.count <> 0, then we know that we have property set attached

        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim tm As AcadDb.TransactionManager = db.TransactionManager
        Dim psId As ObjectId
        Dim local_psetName As String


        'this is searching every property set looking for a single category - no need!! It may only cycle through 3 psets
        For Each psId In setIds

            'opens the propertyset found at psid in setid (where setid is the collection of psets on the dbobj) - so this is cycle one
            Dim pset As AecPropDb.PropertySet = tm.GetObject(psId, OpenMode.ForRead, False, False) 'As AecPropDb.PropertySet

            local_psetName = pset.PropertyIdToName(0)

            Try
                local_psetName = psetname 'this needs to true or else it goes to the catch
                Dim psetdef_id As Integer

                Try
                    'clever this - there is no cycling since pset is a collection and you can hunt down a name directly
                    'here it hunts down the pname
                    psetdef_id = pset.PropertyNameToId(pname)

                    'values is an arraylist since it holds any text or integer date - otherwise the function would have trouble returning a value
                    values.Add(pset.GetValueAndUnitAt(psetdef_id))

                Catch e As Autodesk.AutoCAD.Runtime.Exception
                    ' most likely eKeyNotfound.

                End Try


            Catch e As Autodesk.AutoCAD.Runtime.Exception
                ' most likely eKeyNotfound.


            End Try


        Next

        Return values

    End Function
#End Region
#Region "SetValueFromPropertySetByName"
    ' <summary>
    ' Sets the values (PropertyValueUnitPair) of a property by name on a given object.
    ' </summary>
    ' <param name="pname">The property name to find on the object.</param>
    ' <param name="dbobj">The object to set the property on. </param>
    ' <param name="value">The value to set. </param>
    ' <returns> true if succesful, or false otherwise. </returns>
    Public Function SetValueFromPropertySetByName(ByVal psetname As String, ByVal pname As String, ByVal dbobj As AcadDb.DBObject, ByVal NewValue As Object) As Boolean

        Dim findany As Boolean = False
        Dim setIds As ObjectIdCollection = AecPropDb.PropertyDataServices.GetPropertySets(dbobj)

        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim tm As AcadDb.TransactionManager = db.TransactionManager
        Dim trans As Transaction = tm.StartTransaction()
        Dim psId As ObjectId

        For Each psId In setIds 'setids is all property sets
            Dim pset As AecPropDb.PropertySet = tm.GetObject(psId, OpenMode.ForWrite, False, False) ' As AecPropDb.PropertySet

            If pset.PropertySetDefinitionName = psetname Then

                Dim pid As Integer 'have to create this object to place the PropertyNameToId somewhere

                pid = pset.PropertyNameToId(pname) 'propertynametoid gives the id for the psetdef
                If (pset.IsWriteEnabled) Then
                    pset.SetAt(pid, NewValue) 'note the SetAt...this is vital where all factors are in place ie <pset> <pid> and <NewValue>
                End If

                findany = True
                'esential findany changes the value of the function

            End If
        Next

        trans.Commit()
        trans.Dispose()

        Return findany
    End Function

#End Region
End Class
« Last Edit: April 29, 2011, 09:18:51 AM by Helsinki_Dave »

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Object ID and Entity
« Reply #1 on: April 29, 2011, 01:30:58 PM »
        . . .
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim tm As AcadDb.TransactionManager = db.TransactionManager

        Dim dbobj As AcadDb.DBObject

        Dim trans As Transaction = tm.StartTransaction()

        Dim bt As BlockTable = tm.GetObject(db.BlockTableId, OpenMode.ForRead, False)
        Dim btr As BlockTableRecord = tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead, False)

        Dim id As ObjectId
        For Each id In btr
            If id.ObjectClass.Name = "AecDbSpace" Then

                dbobj = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim spobj As ArchDbSrvcs.Space = tm.GetObject(id, OpenMode.ForRead, False, False)
                . . .

I'm not a VB.NET guy so take this for what it's worth.

One thing I see is that you are using TransactionManger (tm) to get your object.
You should be using the running Transaction (trans) instead.
It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object ID and Entity
« Reply #2 on: April 30, 2011, 02:33:51 AM »
Not quit sure what you are asking but a Space 'is a' Autodesk.Aec.DatabaseServices.Entity.
It derives(Inheritance) from a Entity.

Have you ever wondered how GetObject returns a DBObject but is used for so many objects?



Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object ID and Entity
« Reply #3 on: April 30, 2011, 07:51:31 AM »
Not sure what you after but here is a way to list all the space classifications

Code: [Select]

        <CommandMethod("Classifications")> _
        Public Sub Classifications()

            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim classDefDictionary As New DictionaryClassificationDefinition(db)

                Dim objectIds As Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection = classDefDictionary.Records

                For Each objId As ObjectId In objectIds

                    Dim classDef As ClassificationDefinition = trx.GetObject(objId, OpenMode.ForRead)

                    If classDef.AppliesToFilter.Contains("AecDbSpace") Then
                        ed.WriteMessage(vbCrLf & classDef.Name)
                        GetClassifications(classDef.ClassificationTree)
                    End If

                Next

                trx.Commit()

            End Using

        End Sub

        Public Sub GetClassifications(ByRef classTree As ClassificationTree)

            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Using trx As Transaction = db.TransactionManager.StartTransaction()



                If classTree Is Nothing Then
                    Exit Sub
                End If


                If Not classTree.Id.IsNull Then
                    Dim clasfction As Classification = trx.GetObject(classTree.Id, OpenMode.ForRead)

                    ed.WriteMessage("---" & vbCrLf & clasfction.Name)
                End If



                If classTree.Children.Count > 0 Then

                    For Each cTree As ClassificationTree In classTree.Children
                        GetClassifications(cTree)
                    Next

                End If

                trx.Commit()

            End Using


        End Sub



fixo

  • Guest
Re: Object ID and Entity
« Reply #4 on: May 01, 2011, 08:40:20 AM »
Sorry guys,

Hi Jeff,
sorry for off-topic
Can you test on your machine:
use StartOpenCloseTransaction instead of StarTransaction
and remove for this object 'using' and 'commit'
(for my own interest)

Oleg

 
edit kdub: change textColor
« Last Edit: May 01, 2011, 10:20:09 AM by kdub_bne »

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #5 on: May 02, 2011, 06:41:25 AM »
Thanks a million for the reply Jeff. (ja hauska nähdä Fixo!)

You've clearly found your way around the ACA API! I didn't manage to find any examples about Classfications in AU or the like, so its great to see one in action. It works fine!

My main gist is to find the classfication of a AecDbSpace object. The name of the classfication is Category. If the Category is "Block", then I move on to further code. This can't be done in VBA as Classifications were not exposed, and as you can see in the attached file, we got around this by pulling the classification value into a Property Set definition then reading it from there. This creates other problems further down the chain.

I had hoped it would be as easy as something like this:
Code: [Select]
               Dim spobj As ArchDbSrvcs.Space = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim c_classf As ClassificationCollection = spobj.Classifications

onto which I could use something like GetClassification function and then read it. But the above code returns a big fat zero in the count property..even though there are a number of classfications.
« Last Edit: May 16, 2011, 05:20:40 AM by Helsinki_Dave »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object ID and Entity
« Reply #6 on: May 02, 2011, 11:15:30 PM »
Sorry guys,

Hi Jeff,
sorry for off-topic
Can you test on your machine:
use StartOpenCloseTransaction instead of StarTransaction
and remove for this object 'using' and 'commit'
(for my own interest)

Oleg

 
edit kdub: change textColor
The transaction should be passed in instead creating 157 transaction, but will test and see what happens

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object ID and Entity
« Reply #7 on: May 02, 2011, 11:35:13 PM »
Thanks a million for the reply Jeff. (ja hauska nähdä Fixo!)

You've clearly found your way around the ACA API! I didn't manage to find any examples about Classfications in AU or the like, so its great to see one in action. It works fine!

My main gist is to find the classfication of a AecDbSpace object. The name of the classfication is Category. If the Category is "Block", then I move on to further code. This can't be done in VBA as Classifications were not exposed, and as you can see in the attached file, we got around this by pulling the classification value into a Property Set definition then reading it from there. This creates other problems further down the chain.

I had hoped it would be as easy as something like this:
Code: [Select]
               Dim spobj As ArchDbSrvcs.Space = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim c_classf As ClassificationCollection = spobj.Classifications

onto which I could use something like GetClassification function and then read it. But the above code returns a big fat zero in the count property..even though there are a number of classfications.
I had a little help

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #8 on: May 03, 2011, 06:47:51 AM »
I had a little help

..aha, a Beetles fan.

I'll post back here when I've found a solution to the reading Classifications on a single entity. Thanks again for your help.

fixo

  • Guest
Re: Object ID and Entity
« Reply #9 on: May 03, 2011, 11:09:51 AM »
Sorry guys,

Hi Jeff,
sorry for off-topic
Can you test on your machine:
use StartOpenCloseTransaction instead of StarTransaction
and remove for this object 'using' and 'commit'
(for my own interest)

Oleg

 
edit kdub: change textColor
The transaction should be passed in instead creating 157 transaction, but will test and see what happens
Thanks Jeff,
that make a sense

Oleg

kaefer

  • Guest
Re: Object ID and Entity
« Reply #10 on: May 03, 2011, 06:12:08 PM »
My main gist is to find the classfication of a AecDbSpace object. The name of the classfication is Category. If the Category is "Block", then I move on to further code. This can't be done in VBA as Classifications were not exposed, and as you can see in the attached file, we got around this by pulling the classification value into a Property Set definition then reading it from there.

Disregarding my very limited experience in ACA automation, this looks fine to me.

Quote
This creates other problems further down the chain.

How? To use the classification as a tag in an annotation object would require that very procedure too.

Quote
I had hoped it would be as easy as something like this:
Code: [Select]
               Dim spobj As ArchDbSrvcs.Space = tm.GetObject(id, OpenMode.ForRead, False, False)

                Dim c_classf As ClassificationCollection = spobj.Classifications

It is, but only for values explicitly supplied; not for defaults by style.

If I get the thrust of your code and your sample drawing correctly, there are 7 spaces that meet your criteria, and, incidentally, one of them has a space style named "Block". You want them renumbered. My approach ain't pretty and is probably written in a sinister language, but here goes:
Code: [Select]
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.Runtime
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.Aec.DatabaseServices
open Autodesk.Aec.Arch.DatabaseServices
open Autodesk.Aec.PropertyData.DatabaseServices

[<CommandMethod "koe">]
let koeCmd() =
    let doc = Application.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor
    use tr = db.TransactionManager.StartTransaction()

    let blkPSetName = "Block_properties"
    let blkPName = "Block_ID"
    let catPSetName = "Object_category"
    let catPName = "Category"
   
    let pSetDefs = new DictionaryPropertySetDefinitions(db)
    let tryGetAt pSetName =
        if pSetDefs.Has(pSetName, tr) then pSetDefs.GetAt pSetName
        else ObjectId.Null
    let blkPSetDefId = tryGetAt blkPSetName
    let catPSetDefId = tryGetAt catPSetName
   
    if blkPSetDefId.IsNull || catPSetDefId.IsNull then
        ed.WriteMessage(
            "\nEither PropertySetDefinition {0} or PropertySetDefinition {1} missing from drawing. ",
            blkPSetName, catPSetName )
    else
        let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) :?> BlockTable
        let btr = tr.GetObject(bt.[BlockTableRecord.ModelSpace], OpenMode.ForRead, false) :?> BlockTableRecord
        let mutable newValue = 0

        for oid in btr do
            if oid.ObjectClass.Name = "AecDbSpace" then
                let spc = tr.GetObject(oid, OpenMode.ForRead, false, false) :?> Space
                let tryGetPSetId pSetDefId =
                    try PropertyDataServices. GetPropertySet(spc, pSetDefId) with _ -> ObjectId.Null
                let blkPSetId = tryGetPSetId blkPSetDefId
                let catPSetId = tryGetPSetId catPSetDefId
                if blkPSetId.IsNull || catPSetId.IsNull then   
                    ed.WriteMessage(
                        "\n{0} has no Property Set {1} or {2}. ",
                        spc.Name, blkPSetName, catPSetName )
                else 
                    let blkPSet = tr.GetObject(blkPSetId, OpenMode.ForWrite, false, false) :?> PropertySet 
                    let catPSet = tr.GetObject(catPSetId, OpenMode.ForRead, false, false) :?> PropertySet
                    let blkPId = blkPSet.PropertyNameToId blkPName
                    let catPId = catPSet.PropertyNameToId catPName
                    let cat = catPSet.GetAt catPId :?> string
                    if cat <> "Block" then
                        ed.WriteMessage("\n{0} has Category {1}. ", spc.Name, cat)
                    else
                        blkPSet.SetAt(blkPId, newValue)
                        ed.WriteMessage(
                            "\nSuccesfully changed value for {0}, new value = {1} ",
                            spc.Name, newValue )
                        newValue <- newValue + 1
    tr.Commit()

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #11 on: May 09, 2011, 08:41:17 AM »
Thanks for the posting kaefer , brilliant actually. I'll plug this is and see if any lights come on.

Draftek

  • Guest
Re: Object ID and Entity
« Reply #12 on: May 10, 2011, 06:12:34 AM »
My only comment would be - if your going to process that much stuff, you might consider not using a transaction at all. Performance might become an issue.

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #13 on: May 12, 2011, 08:42:31 AM »
Quote
How? To use the classification as a tag in an annotation object would require that very procedure too.

Just thought I should get back to a few of these questions, just in case you thought I'ld gone to sleep.

ACA has this problem when inserting AecDbSpaces via a customised toolbar - in that it automatically attaches every single property set that it can find that is relevant to 'Spaces. This means that you then need a bit of VBA that determines the type of object it is (ie, building, city block, surface etc) as well as checking that every 'Space has the right PropertySet attached (ie if during editing somebody accidentily removed a property set attached ByObject)

That last point is the problem, to check if you have the right PropertySet attached, you need to know what kind of object it is, and to know what kind of object it is, you need to know the Classification ("Category") - BUT, VBA can't read classifications, nor can it read PropertySets that are attached ByStyle. So there's not an immediate automatic answer. You can't just read the stylename since as you build up the options of Classifications (inside site area or not, use of building etc) the stylename becomes irrelevant.

We get around this by first attaching a kind of 'what am i' property set, then using that to direct what the correct PropertySet should be. To blocks go Block _Properties propertyset and to Buildings go Building_Propoerties property set.

I noticed that Kaefers code is in F#.  I'll give it a crack to bring it back to VB but it's looking ugly.

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #14 on: May 13, 2011, 06:01:23 AM »
Not sure what you after but here is a way to list all the space classifications

I can see that I'm all at sea with this...my question wasn't clear. Apologies for this - I'm not looking to waste anyones time.

Is there a way to find the value of a single classficiation on a single entity (in the file above, an Enity could be a Building or a Cityblock. It appears that I can use the Function that I list below..but I'm struggling. I'll try to use Jeff's kindly donated code to grab a classificationDefinitionId as it appears in the db. Maybe that will work. Thanks in advance for your thoughts.

Quote
Public Shared Function GetClassification(ByVal entity As Autodesk.Aec.DatabaseServices.Entity, ByVal classificationDefinitionId As Autodesk.AutoCAD.DatabaseServices.ObjectId) As Autodesk.AutoCAD.DatabaseServices.ObjectId
     Member of: Autodesk.Aec.DatabaseServices.ClassificationDefinition
Summary:
Get an entity's classification for a specific classification definition.

Parameters:
entity: The entity.
classificationDefinitionId: The classification definition.

Return Values:
Returns an entity's classification for a specific classification definition.

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #15 on: May 13, 2011, 09:52:24 AM »
Well, I went back to some code that Jeff put out some place; I thought it might clarify the problem in my head and with you guys.
I believe that what is below will get a single Classification on a single Entity (thanks Jeff) but what I can't understand is how to pull a value off this. I can get as far as finding the ObjectID of exactly one classification on exactly one entity. Very cool.

But now it is not clear to me how to find the assigned value of the Classification. This value is assigned within ACA by the user. As you know, there is no such thing as ObjectID.Value

To be concise - how can I can determine what Category each AecDbSpace has. I can get each AecDbSpace's 'Category', but I can't see where I can read what the actual Category is (eg Building, Block etc)

Code: [Select]
'many thanks to Jeff H
Imports System
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput

Imports ObjectId = Autodesk.AutoCAD.DatabaseServices.ObjectId


Imports AecDbSrvcs = Autodesk.Aec.DatabaseServices
Imports ArchDbSrvcs = Autodesk.Aec.Arch.DatabaseServices

Imports Autodesk.Aec.PropertyData.DatabaseServices
Imports Autodesk.Aec.DatabaseServices


<Assembly: CommandClass(GetType(MEPExamplesVB.MyCommands))>
Namespace MEPExamplesVB
    Public Class MyCommands
        <CommandMethod("GetSpaceDataVB")> _
        Public Sub GetSpaceDataVB()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim mdlSpace As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)

                For Each objId As ObjectId In mdlSpace

                    If objId.ObjectClass.Name = "AecDbSpace" Then

                        Dim spce As ArchDbSrvcs.Space = trx.GetObject(objId, OpenMode.ForRead)

                        Dim Ret_TClass As ObjectId = GetClassifID("Category")

                        Dim RetrClassID As ObjectId = Autodesk.Aec.DatabaseServices.ClassificationDefinition.GetClassification(spce, Ret_TClass)

                        'I dont what to do from here. I need to find the value of this Classficiation.

                        Dim spceStyle As ArchDbSrvcs.SpaceStyle = trx.GetObject(spce.StyleId, OpenMode.ForRead)

                        'ed.WriteMessage(String.Format("{0}This Space Name: {1} Area: {2} and is on Stlye?: {3}", _
                        'vbCrLf, spce.Name, spce.Area, spceStyle.Name))

                        Dim spc_ownerID As ObjectId = spce.OwnerId

                        If spc_ownerID.ObjectClass.Name = "AecDbSpace" Then

                            Dim plg As AecDbSrvcs.Polygon = trx.GetObject(spc_ownerID, OpenMode.ForRead)

                        End If
                    End If

                Next
            End Using
        End Sub


#Region "GetClassficationId"
    'we need to
    'takes the AecDbSpace object <id>
    'takes the ClassficiationName <TargClasName>
    'returns the objectid for the targeted classification
    Public Function GetClassifID(ByVal TargClasName As String) As ObjectId

        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim TargetClassID As ObjectId
            Dim ed As Editor = doc.Editor

        Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim classDefDictionary As New DictionaryClassificationDefinition(db)

            Dim objectIds As Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection = classDefDictionary.Records

            For Each objId As ObjectId In objectIds

                Dim classDef As ClassificationDefinition = trx.GetObject(objId, OpenMode.ForRead)

                If classDef.AppliesToFilter.Contains("AecDbSpace") Then
                        'ed.WriteMessage(vbCrLf & classDef.Name)
                    If classDef.Name = TargClasName Then
                        TargetClassID = classDef.ObjectId
                        'GetClassifications(classDef.ClassificationTree)
                    End If
                End If
            Next
            trx.Commit()
        End Using
        Return TargetClassID
    End Function
#End Region
    End Class
End Namespace

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object ID and Entity
« Reply #16 on: May 13, 2011, 07:57:21 PM »
This is probably not the best way I was just looking at it with AECMgd and the function you were trying to use.

Since the classifications are set with style it seems there will be a easy way to grab it using the style.


Here is what this does it searches the DictionaryClassificationDefinition for "Category" and once found assigns the ObjectID to a variable that will be used as ClassificationDefinition ID.

Then it iterates through model space and if it is a space object it gets the classification using GetClassification() with the space object and ClassificationDefinition ObjectId as its arguments

Code: [Select]
        <CommandMethod("GetClassificationWithDefinition")> _
        Public Sub GetClassificationWithDefinition()

            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim classficationDefId As ObjectId

            Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim classDefDictionary As New DictionaryClassificationDefinition(db)

                Dim objectIds As Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection = classDefDictionary.Records

                For Each objId As ObjectId In objectIds

                    Dim classDef As ClassificationDefinition = trx.GetObject(objId, OpenMode.ForRead)

                    If classDef.Name = "Category" Then
                        classficationDefId = classDef.ObjectId
                        Exit For
                    End If

                Next


                Dim mdlSpace As BlockTableRecord = SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(OpenMode.ForRead)

                For Each objId As ObjectId In mdlSpace

                    If objId.ObjectClass.Name = "AecDbSpace" Then
                        Dim spce As ArchDbSrvcs.Space = trx.GetObject(objId, OpenMode.ForRead)

                        Dim cls As Classification = trx.GetObject(ClassificationDefinition.GetClassification(spce, classficationDefId), OpenMode.ForRead)

                        ed.WriteMessage(String.Format("{0}This Classification is: {1} ", vbCrLf, cls.Name))

                    End If

                Next



                trx.Commit()

            End Using
        End Sub



Output from your drawing

Quote

This Classification is: Block
This Classification is: Block
This Classification is: Block
This Classification is: Block
This Classification is: Block
This Classification is: Block
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Building
This Classification is: Block
This Classification is: Block
« Last Edit: May 14, 2011, 09:26:48 PM by Jeff H »

Helsinki_Dave

  • Guest
Re: Object ID and Entity
« Reply #17 on: May 16, 2011, 05:17:40 AM »
Gents,

It works.
 
with many thanks to mohnston, kaefer and special thanks to Jeff H