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.