Распознавание дерева построения модели

Автор IronMaxxx, 01.01.06, 11:50:42

« предыдущая - следующая »

0 Пользователей и 1 гость просматривают эту тему.

IronMaxxx

Здравствуйте!
Такая вот задача... Нужно прочитать и распознать дерево построения модели (детали или сборки). Распознать имеется в виду определить тип трехмерного объекта (o3d_surface, o3d_sketch, o3d_axis2Planes и т.д.) и подсчитать количество объектов каждого вида (для сборки еще и количество деталей и подсборок). С этим проблемы нет : использую ksPart::EntityCollection для детали и ksDocument3D::PartCollection для сборки (во входных параметрах задаю необходимый тип объекта и получаю их количество через ::GetCount).
Но как быть, если мне нужно отобразить дерево построения в порядке его формирования, т.е. создать его схему? Для этого при распознании детали в методе ksPart::EntityCollection задаю тип o3d_unknown, чтобы перебрать все обьекты. Все работает... Но потом, когда с помощью метода ksDocument3D::GetObjectType пытаюсь определить тип объекта всегда получаю возвращаемое значение 105, что соответсвует o3d_entity  ::) . Подскажите, как выкрутиться...

Gek

Чисто теоретически, попробуй ksEntity::IsIt - проверка объекта на соответствие указанному типу. Конечно, гемор все возможные типы перебирать  >:(

IronMaxxx

Всем отбой! Я как всегда разобрался сам (это уже не впервый раз - мучаюсь день-два  :o, но стоит только сесть и написать за помощью на форум - через час расчехляюсь сам  :-)))). Я нашел способ попроще, при котором не нужно перебирать все типы для каждого объекта, но все равно, Gek, спасибо за ответ!

IgorRUtver

Столкнулся с проблемой, требуется "пробежаться по дереву " сборки, и определить ко-во деталей, в том числе и в подсборках. Проверяю является ли элемент деталью если нет то открыть сборку и тд. Все хорошо, но вот с массивами не работает.
var
   newKompasAPI : IApplication;
   disp : IDispatch;
   pDocuments : iDocuments;
    pDocument : IKompasDocument;
     Doc3D : IKompasDocument3D;
      pPart7 : IPart7;
       pParts7 : IParts7;
       countPart : integer;
begin
disp := IDispatch( CreateKompasApplication );
  newKompasAPI := disp As IApplication;
   pDocuments := newKompasAPI.Documents;
     pDocument := newKompasAPI.ActiveDocument;
     Doc3D:=pDocument as IKompasDocument3D;
      pPart7:=Doc3D.TopPart;
       pParts7 := pPart7.Parts;
       countPart:= pParts7.Count;
end;

Количество элементов (countPart) выдаёт 1
Помогите решить проблему, как можно учесть массивы?

IgorRUtver

Возможно это другая тема, но может лучше через функцию создания отчета сборки?, с дальнейшим сохранением в excel таблицу, хотя работа с деревом по мне так, более красивое решение.

Sabahs

10.12.13, 20:40:25 #5 Последнее редактирование: 10.12.13, 20:53:52 от Sabahs
Данное свойство проверяли?
IPart7.InstanceCount - Количество вставок компонента.
или
Получаете IFeaturePatterns - указатель на интерфейс коллекции операций копирования и разбираете его на запчасти.
P.S. Если код приведённый выше, это всё, то он для детей. Функция должна, как минимум быть рекурсивной.

IgorRUtver

Конечно, это фрагмент, и рекурсивный вызов тоже есть, я показал только интерфейс который использую. Спасибо, буду тыкать

chelkar

Свойство Parts не учитывает компоненты из под массивов.
Есть другое свойство - PartsEx. Для прохода по всем компонентам сборки лучше использовать его.

IgorRUtver

Судя по описанию, это то, что нужно. Только не знаю как использовать интерфейс.
"2. Коллекция объектов возвращается в виде массива SAFEARRAY объектов LPDISPATCH ( VT_ARRAY | VT_DISPATCH). Если возвращается один объект, то тип VARIANT-а будет VT_DISPATCH, если возвращается несколько объектов, то тип VARIANT-а будет VT_ARRAY | VT_DISPATCH."

Делаю
var
   newKompasAPI : IApplication;
   disp : IDispatch;
   pDocuments : iDocuments;
    pDocument : IKompasDocument;
     Doc3D : IKompasDocument3D;
      pPart7 : IPart7;
       pPartsEx : variant;
begin
disp := IDispatch( CreateKompasApplication );
  newKompasAPI := disp As IApplication;
   pDocuments := newKompasAPI.Documents;
     pDocument := newKompasAPI.ActiveDocument;
     Doc3D := pDocument as IKompasDocument3D;
      pPart7:=Doc3D.TopPart;
       pPartsEx := pPart7.PartsEx[ksAllParts];
       
end;

А вот, что дальше делать ума не приложу, что за массив SAFEARRAY и как им пользоваться?

Sabahs


IgorRUtver

If (VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH) then
чтобы распознать VT_ARRAY и VT_DISPATCH надо какойто файл подключить? Че ничего не нашел в .pas файлах в папке Include

Sabahs


IgorRUtver

Вроде нечто получилось, но сам пока толком не понял. что у меня получилось.
Это сборка на которой пробую


  var
   i1 : integer;
   //API7
   FileNameAss : string;
   newKompasAPI : IApplication;
   disp : IDispatch;
   pDocuments : iDocuments;
    pDocument : IKompasDocument;
     Doc3D : IKompasDocument3D;
      pPart7 : IPart7;
       pParts7 : IParts7;
       pPartsEx : variant;
   pModelObject : IModelObject;

begin
disp := IDispatch( CreateKompasApplication );
  newKompasAPI := disp As IApplication;
   pDocuments := newKompasAPI.Documents;
     pDocument := newKompasAPI.ActiveDocument;
     Doc3D := pDocument as IKompasDocument3D;
      pPart7:=Doc3D.TopPart;
       pPartsEx := pPart7.PartsEx[ksAllParts];
        If VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH) then  pModelObject := IDispatch(pPartsEx[0]) as IModelObject;
        i1 := VarArrayHighBound(pPartsEx,1);
         Showmessage(IntToStr(i1));
         pPart7 := pModelObject.Part;
           pParts7 := pPart7.Parts;
            Showmessage(IntToStr(pParts7.Count));
         pPart7 := pParts7.Part[0];
           Showmessage(pPart7.FileName);
end;

VarArrayHighBound(pPartsEx,1); возвращает 3, не пойму, что лежит в массиве, поидее должно быть 2 - одна деталь и один массив
с другой стороны я указал pPartsEx := pPart7.PartsEx[ksAllParts]; я думал. что получу "Все компоненты (включая копии из операций копирования)" Что собственно я тут делаю?

pParts7.Count считает только элементы дерева, без массива.

IDispatch(pPartsEx[0]) и неочень понятна вот эта строка, количество элементов равно 3, но менял араметр pPartsEx от 0 до 2 результат выполнения кода всегда один и тотже.

Хочу добавить. что до этого момента я думал, что IDispatch это интерфейс компаса, а прочитав разочаровался, пока только начал изучать, и прошу простить если гдето неверно свормулировал мысль :~



Sabahs

В массиве лежит 4 тела, т.к. массив начинается с нуля.
Что конкретно лежит, можно узнать посмотрев свойство pModelObject.ModelObjectType - тип модельного объекта.

IgorRUtver

Действительно. Я невнимательно прочитал описание функции VarArrayHighBound, я думал. что возвращается количество элементов. Спасибо, в массиве действительно 4 детали.

Если не затруднит, объясните, что происходит в этой строке
If VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH) then  pModelObject := IDispatch(pPartsEx[0]) as IModelObject;
поидее  pModelObjec должен указывать на 1ю деталь

Если написать
If VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH) then  pModelObject := IDispatch(pPartsEx[0]) as IModelObject;
pPart7 := pModelObject.Part;
Showmessage(pPart7.FileName);
Получаю имя сборки, и опять же результат один и тотже независимо от параметра pPartsEx[0]

Sabahs

Здесь идёт проверка, что pPartsEx является массивом интерфейсов, далее получаете указатель на первый интерфейс, с приведением его к базовому интерфейсу для всех модельных объектов - IModelObject.
Чтобы не гадать на кофейной гуще, посмотрите свойство pModelObject.ModelObjectType, я думаю там первый экземпляр массива.

IgorRUtver

Все допер! :o: Спасибо большое! Я не так получал pPart7
Теперь все понятно

If VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH) then  pModelObject := IDispatch(pPartsEx[0]) as IModelObject;
pPart7 := pModelObject as iPart7;
Все нормально. получил интерфейс первой детали.
pPartsEx[0] содержит все детали и сборки, с учетом операций копирования, теперь не надо разбирать каждый массив. ура!)