Autodesk Inventor API. Первые шаги/Ссылочные ключи (Reference keys) и атрибуты (Attributes)

Краткое введение: что это такое и зачем.


Ссылочные ключи править

Ссылочные ключи (Reference keys) являются средством получения особых ссылок на объекты Инвентора. Такие ссылки отличаются тем, что сохраняются между этапами редактирования модели и даже между сеансами работы Инвентора. Например, приведенный ниже программный фрагмент получает ссылку на тело и затем ссылку на грань этого тела.

Dim oBody As SurfaceBody
Set oBody = ThisApplication.ActiveDocument.ComponetDefinition.SurfaceBodies.Item(1)
    
Dim oFace As Face
Set oFace = oBody.Faces.Item(1)


Это наиболее распространенный вариант ссылок на объекты, однако они являются временными. Если каким-либо образом сохранить такие ссылки, затем закрыть и снова открыть документ, выяснится, что сохраненные ссылки более не актуальны. Если ссылка указывает на объект типа B-Rep (SurfaceBody, FaceShell, Face, EdgeLoop, Edge, EdgeUse или Vertex), и вы сделали нечто, что вызвало пересчет модели, скажем, изменили значение параметра, ссылка перестанет быть актуальной и, следовательно, сколько-нибудь полезной. Для объектов типа B-Rep такие ссылки имеют смысл только, пока модель пребывает в неизменном статичном состоянии. Ссылки на прочие (не B-Rep) объекты остаются действительными и после пересчета модели, однако теряют актуальность c закрытием документа. API предоставляет два метода, которые позволят получить более долгоживущие ссылки на любой объект внутри Инвентора. Это ссылочные ключи (reference key) и атрибуты (attribute).


Ссылочные ключи (Reference Keys) править

Ссылочный ключ (Reference key) —это уникальный и неизменный идентификатор объекта. Reference key это не сама ссылка, но он используется для создания ссылки на тот объект, для которого reference key был сгенерирован. Он неизменный, поскольку продолжает работать в процессе пересчета модели, а также после закрытия и повторного открытия документа.

Другой особенностью ссылочных ключей является то, что сам Инвентор их не поддерживает. Это означает, что Инвентор не сохраняет эту информацию в своих файлах. Если вы используете ссылочные ключи, задача их сохранения между сеансами работы Инвентора ложится на вас. Использовать ссылочные ключи в пределах одной сессии Инвентора довольно просто, для этого достаточно сохранить ключ в переменной и использовать его по мере необходимости.

Чтобы воспользоваться ссылочными ключами в последующих сеансах Инвентора, вы вероятно сохраните их во внешнем файле и, таким образом, сможете использовать ключи в любой момент в будущем. Управление ссылочными ключами является исключительно вашей заботой. Инвентор лишь предоставляет их в ваше распоряжение, а для заданного ключа возвращает соответствующий ему объект.

Поскольку сам Инвентор не управляет ключами, возникает любопытный побочный эффект — вы можете использовать ссылочные ключи без изменения документа, в котором ключи были получены. Это означает, что вам не требуется сохранять документ, в котором они были сгенерированы, более того, сам документ может быть защищенным от изменений (read-only). По этой причине ссылочные ключи используются в Apprentice.

Техника использования ссылочных ключей для объектов типа B-Rep отличается рядом особенностей. Мы начнем с более простых не B-Rep объектов, а уже потом перейдем к B-Rep. При необходимости поддерживать одновременно B-Rep и не B-Rep объекты, вы можете для всех объектов применять единообразную технику, характерную для B-Rep, как более универсальную.

Ссылочные ключи для не B-Rep объектов править

В принципе, идея ссылочных ключей довольно проста, если представлять их как идентификаторы объектов. Ссылочные ключи не B-Rep объектов еще и довольно просты в применении. Вы получаете ссылочный ключ объекта, каким-либо образом сохраняете его и позднее используете в любой момент, чтобы получить нормальную «живую» ссылку на объект. Объект ReferenceKeyManager (менеджер ссылочных ключей) в документе с нужными вам объектами, обеспечивает ряд методов и свойств для работы со ссылочными ключами. В этом процессе есть только одна особенность. Ссылочный ключ это не одно значение, а байтовый массив. Вспомним, байт — целое число в интервале от 0 до 255. Ниже приведен фрагмент кода, который иллюстрирует получение ссылочных ключей, запись ключа в файл, чтение его из файла, и, наконец, восстановление связи ключа с исходным объектом. Процедура SaveNonBRepKey может быть выполнена для любого документа детали, содержащего хотя бы два эскиза. GetNonBRepKey можно применить для того же самого документа (даже после его закрытия и повторного открытия), чтобы восстановить ключи из файла и использовать их для установления связи с эскизами.

Public Sub SaveNonBRepKey()

    Dim oDoc As PartDocument
    Set oDoc = ThisApplication.ActiveDocument
    
    ' Получение ссылочных ключей (reference keys) для двух эскизов
    Dim oSketch As Sketch
    Set oSketch = oDoc.ComponentDefinition.Sketches.Item(1)
    Dim abtRefKey1() As Byte
    Call oSketch.GetReferenceKey(abtRefKey1)

    Set oSketch = oDoc.ComponentDefinition.Sketches.Item(2)
    Dim abtRefKey2() As Byte
    Call oSketch.GetReferenceKey(abtRefKey2)

    ' Открываем файл в режиме binary access.
    Dim iFile As Integer
    iFile = FreeFile
    Open "C:\Temp\RefKey.dat" For Binary As #iFile

    ' Запись ссылочных ключей в файл (вместе с длиной массива).
    Dim iSize As Long
    iSize = UBound(abtRefKey1) - LBound(abtRefKey1)
    Put #iFile, , iSize
    Put #iFile, , abtRefKey1
    iSize = UBound(abtRefKey2) - LBound(abtRefKey2)
    Put #iFile, , iSize
    Put #iFile, , abtRefKey2
    
    ' Закрываем файл.
    Close #iFile
End Sub

Public Sub GetNonBRepKey()
    ' Открываем файл.
    Dim iFile As Integer
    iFile = FreeFile
    Open "C:\Temp\RefKey.dat" For Binary As #iFile
    
    ' Читаем из файла два ссылочных ключа.
    Dim iRefKeyLen As Long
    Get #iFile, , iRefKeyLen
    Dim abtRefKey1() As Byte
    ReDim abtRefKey1(iRefKeyLen) As Byte
    Get #iFile, , abtRefKey1

    Get #iFile, , iRefKeyLen
    Dim abtRefKey2() As Byte
    ReDim abtRefKey2(iRefKeyLen) As Byte
    Get #iFile, , abtRefKey2

    ' Закрываем файл.
    Close #iFile
    
    ' Получаем ссылку на менеджер ссылочных ключей (reference key manager)
    ' активного документа.
    Dim oRefKeyManager As ReferenceKeyManager
    Set oRefKeyManager = ThisApplication.ActiveDocument.ReferenceKeyManager
    
    ' Восстановление связи с исходными объектами
    On Error Resume Next
    Dim oSketch1 As Sketch
    Set oSketch1 = oRefKeyManager.BindKeyToObject(abtRefKey1)
    If Err Then
        MsgBox "Failed to bind back to the first sketch."
        Err.Clear
    End If

    Dim oSketch2 As Sketch
    Set oSketch2 = oRefKeyManager.BindKeyToObject(abtRefKey2)
    If Err Then
        MsgBox "Failed to bind back to the second sketch."
        Err.Clear
    End If
    On Error Goto 0
    
    ' Используем свойство Name эскиза для проверки работоспособности ссылок.
    MsgBox oSketch1.Name
    MsgBox oSketch2.Name
End Sub


Обратите внимание, попытка восстановить из ключа ссылку вполне может закончиться неудачей. Например, если объект, на который ссылается ключ, уже более не существует. Если в нашем примере вы удалите один из эскизов, вызов метода BindKeyToObject для этого отсутствующего эскиза приведет к ошибке.


Ссылочные ключи для B-Rep объектов править

Использование reference keys в случае объектов B-Rep несколько сложнее. Для объекта B Rep ключ это не просто набор байтов, однозначно идентифицирующих объект, но последовательность байтов, используемая для поиска объекта в таблице. Поскольку объекты B-Rep очень динамичны, определение ссылок на конкретный объект внутри B-Rep оказывается сложным процессом. Полный идентификатор B-Rep в действительности есть описание самого объекта и связанных с ним объектов в составе B-Rep, которое и позволяет Инвентору находить их снова. По этой причине идентификаторы B-Rep могут быть довольно большими. Для минимизации размера ссылочных ключей и с учетом того, что часть этой описательной информации дублируется в других B-Rep объектах, применяются специальные таблицы. На них и ссылаются ссылочные ключи объектов B-Rep. В API эта таблица получила название reference key context — контекст ссылочных ключей.

Если понять назначение таблицы контекста, то работать с объектами B-Rep станет не намного сложнее, чем с прочими объектами. Как уже отмечалось, вы всегда можете выбрать ссылочный контекст (reference context), независимо от того, работаете ли вы с объектами B-Rep или нет, обеспечивая внутренние связи в своей программе. Если у вас не B-Rep объект, таблица контекста будет просто проигнорирована. Следующий программный фрагмент иллюстрирует приемы работы со ссылочными ключами для объектов B-Rep.

Public Sub SaveBRepKey()
    Dim oDoc As PartDocument
    Set oDoc = ThisApplication.ActiveDocument
    
    ' Получение ссылки на выделенную грань
    Dim oFace As Face
    On Error Resume Next
    Set oFace = oDoc.SelectSet.Item(1)
    If Err Then
        MsgBox "A face must be selected."
        Exit Sub
    End If
    On Error GoTo 0
    
    ' Ссылка на ReferenceKeyManager активного документа
    Dim oRefKeyManager As ReferenceKeyManager
    Set oRefKeyManager = oDoc.ReferenceKeyManager
    
    ' Создание контекста ключа.
    Dim iKeyContext As Long
    iKeyContext = oRefKeyManager.CreateKeyContext
    
    ' Создание ключа для грани.
    Dim abtRefKey() As Byte
    Call oFace.GetReferenceKey(abtRefKey, iKeyContext)
    
    ' Открываем файлOpen a file for binary access.
    Dim iFile As Integer
    iFile = FreeFile
    Open "C:\Temp\RefKey.dat" For Binary As #iFile
    
    ' Преобразование контекста ключа (key context) в байтовый массив.
    Dim abtKeyContext() As Byte
    Call oRefKeyManager.SaveContextToArray(iKeyContext, abtKeyContext)
    
    ' Запись контекста ключа в файл вместе с длиной массива.
    Dim iSize As Long
    iSize = UBound(abtKeyContext) - LBound(abtKeyContext)
    Put #iFile, , iSize
    Put #iFile, , abtKeyContext
    
    ' Запись ссылочного ключа в файл вместе с длиной массива.
    iSize = UBound(abtRefKey) - LBound(abtRefKey)
    Put #iFile, , iSize
    Put #iFile, , abtRefKey
    
    ' Закрываем файл.
    Close #iFile
End Sub

Public Sub GetBRepKey()
    ' Открываем файл.
    Dim iFile As Integer
    iFile = FreeFile
    Open "C:\Temp\RefKey.dat" For Binary As #iFile
    
    ' Считываем из файла данные контекста ключа.
    Dim iLen As Long
    Get #iFile, , iLen
    Dim abtKeyContext() As Byte
    ReDim abtKeyContext(iLen) As Byte
    Get #iFile, , abtKeyContext
    
    ' Читаем из файла ключ.
    Get #iFile, , iLen
    Dim abtRefKey() As Byte
    ReDim abtRefKey(iLen) As Byte
    Get #iFile, , abtRefKey
    
    ' Закрываем файл.
    Close #iFile
    
    ' Получаем ссылку на менеджер ссылочных ключей активного документа.
    Dim oRefKeyManager As ReferenceKeyManager
    Set oRefKeyManager = ThisApplication.ActiveDocument.ReferenceKeyManager
    
    ' Восстанавливаем контекст ключа (key context).
    Dim iKeyContext As Long
    iKeyContext = oRefKeyManager.LoadContextFromArray(abtKeyContext)
    
    ' Устанавливаем связь с гранью. 
    ' Вернется объект Face (грань), если будет найдена одна грань.
    ' Если граней будет несколько, то вернется коллекция.
    ' Если ни одной грани не найдется, будет сгенерирована ошибка.
    Dim oResult As Object
    On Error Resume Next
    Set oResult = oRefKeyManager.BindKeyToObject(abtRefKey, iKeyContext)
    If Err Then
        MsgBox "The face doesn't exist."
    Else

        ' Выделяем полученную грань (грани).
        Dim oHS As HighlightSet
        Set oHS = ThisApplication.ActiveDocument.HighlightSets.Add
        If TypeOf oResult Is Face Then
            oHS.AddItem oResult
            MsgBox "A single face still exists."
        Else
            Dim i As Integer
            For i = 1 To oResult.Count
                oHS.AddItem oResult.Item(i)
            Next
            MsgBox oResult.Count & " faces now exist for the original face."
        End If
        
        oHS.Clear
    End If
End Sub


Этот пример иллюстрирует две концепции, уникальные для ссылочных ключей B Rep объектов. Первая заключается в использовании контекста ключа (key context). Вы создаете контекст ключа и передаете его идентификатор методам GetReferenceKey и BindKeyToObject. При сохранении данных ключа в файл используется метод SaveContextToArray менеджера контекста, чтобы преобразовать контекст ключа в массив байтов. После считывания из файла информации о контексте ключа вы можете вызвать метод LoadContextFromArray менеджера контекста, чтобы воссоздать контекст ключа из массива байтов.

Атрибуты (Attributes) править

Атрибуты (attributes) довольно сильно отличаются от ссылочных ключей, но они успешно применяются для решения сходных задач. Вы можете использовать атрибуты для обеспечения доступа к помеченному объекту в любой момент его жизни. Если эта задача является основной, то через атрибуты ее решить проще, чем с помощью ссылочных ключей. Главная причина легкости их применения заключается в том, что вам не нужно беспокоиться о поддержке данных атрибутов, как это обстоит со ссылочными ключами, за вас это сделает Инвентор. Однако для этого вы должны иметь доступ к файлу на запись, т.к. Инвентору необходимо сохранить в файлах данные атрибутов. В большинстве случаев, если вам требуется лишь запомнить конкретный объект для продолжения работы с ним в следующей сессии, атрибутам следует отдать предпочтение.


Кроме организации ссылок на объекты в последующих сеансах работы Инвентора, атрибуты оказываются полезными и для решения других задач. Функционал атрибутов позволяет «прикрепить» дополнительную информацию практически к любому объекту Инвентора. Позднее эта информация может не только извлекаться из объектов, но и использоваться для организации запросов на поиск конкретных объектов.

 

На рисунке показана относящаяся к атрибутам часть объектной модели. Здесь Entity — любой объект, поддерживающий атрибуты. Свидетельством этой поддержки является наличие у объекта Entity свойства AttributeSets (указатель на коллекцию ассоциированных с объектом наборов атрибутов).

Любой объект может быть связан со многими объектами AttributeSet (набор атрибутов). Наборы атрибутов AttributeSet обязаны иметь уникальные в пределах объекта имена. Множественность наборов атрибутов AttributeSet у любого Entity позволяет всякому приложению формировать собственные и независимые от других приложений наборы атрибутов. Каждый набор AttributeSet может включать любое количество атрибутов — объектов Attribute. Каждый атрибут Attribute имеет имя и значение. Имя атрибута обязано быть уникальным в пределах его набора AttributeSet. Допустимые в атрибутах типы данных: Double, Integer, String и массив байтов (array of Bytes).

 

После добавления к объекту набора атрибутов AttributeSet и самих атрибутов Attribute, они становятся доступными через сам объект. Однако более общий подход заключается формировании запросов на выборку объектов на базе ассоциированной с ними атрибутной информации. Эту задачу решает менеджер атрибутов AttributeManager, ссылку на который предоставляет объект Document. Менеджер атрибутов AttributeManager может выполнять разнообразные задания на выборку объектов Entity, наборов AttributeSet или самих объектов Attribute.

Давайте посмотрим, как можно применить атрибуты для решения задачи из предыдущего примера со ссылочными ключами. Ниже приведен фрагмент, эквивалентный обеим предыдущим процедурам сохранения ключей SaveKey. С точки зрения атрибутов нет различий между B-Rep и не B-Rep объектами.

Public Sub AddAttribute()
    Dim oDoc As PartDocument
    Set oDoc = ThisApplication.ActiveDocument
    
    ' Get a reference to the selected face.
    ' получение ссылки на выделенную грань.
    Dim oFace As Face
    On Error Resume Next
    Set oFace = oDoc.SelectSet.Item(1)
    If Err Then
        MsgBox "Грань должна быть выделена."
        Exit Sub
    End If
    On Error GoTo 0
    
    ' Создание набора атрибутов с именем "AttributeSample"
    Dim oAttSet As AttributeSet
    Set oAttSet = oFace.AttributeSets.Add("AttributeSample")
    
    ' Создание атрибута с именем "Face" и текстовым значением "Some data"
    Dim oAtt As Inventor.Attribute
    Set oAtt = oAttSet.Add("Face", kStringType, "Some data")
End Sub


Как и в примере с ключами, процедура сначала определяет ссылку на выделенную пользователем грань oFace, а затем она создает для oFace набор атрибутов и в нем атрибут. Для простой идентификации объекта, как в этом примере, в принципе, достаточно создать лишь пустой набор без каких-либо атрибутов. Собственно, атрибутная информация полезна в случае, когда вы хотите связать с объектом какие-либо дополнительные данные.

Пример ниже использует ранее созданный атрибут для поиска ассоциированной с ним грани. Обратите внимание, насколько код выглядит проще и короче, чем в примере со ссылочными ключами.

Public Sub QueryAttribute()
    ' Получение ссылки на менеджер атрибутов активного документа
    Dim oAttribManager As AttributeManager
    Set oAttribManager = ThisApplication.ActiveDocument.AttributeManager
    
    ' Запрос на выборку объектов с конкретной атрибутной информацией.
    Dim oObjects As ObjectCollection
    Set oObjects = oAttribManager.FindObjects("AttributeSample", "Face", "Some data")
    
    ' Выделить найденные грани, если таковые будут.
    If oObjects.Count > 0 Then
        Dim oHS As HighlightSet
        Set oHS = ThisApplication.ActiveDocument.HighlightSets.Add
        Dim i As Integer
        For i = 1 To oObjects.Count
            oHS.AddItem oObjects.Item(i)
        Next
        
        MsgBox "Found objects are highlighted."
        
        oHS.Clear
    End If
End Sub


Данный пример вызывает метод FindObjects менеджера атрибутов AttributeManager, чтобы получить коллекцию всех объектов, у которых имеется набор атрибутов AttributeSet с именем «AttributeSample» и в нем атрибут с именем «Face» и текстовым значением «Some data». Все три аргумента — необязательные (optional), и в данном конкретном примере указание любого из них будет достаточным, чтобы получить требуемую грань. К примеру, поставленную задачу успешно выполнит следующая инструкция:

    Set oObjects = oAttribManager.FindObjects("AttributeSample")

Поиск на основе всех трех параметров делает возможным выполнение сложных запросов в документе с множеством разнообразных атрибутов.


Литература править

[1] Brian Ekins. Inside the Autodesk Inventor® API. Лекция MA42-4, Autodesk University 2003.