• Добро пожаловать на Форум пользователей ПО АСКОН. Пожалуйста, авторизуйтесь.
 

Уважаемые пользователи,

Хотим проинформировать вас о режиме работы регистрации на нашем сайте.

Зарегистрироваться возможно в рабочие дни, с 8:00 до 20:00 (мск).

Если у вас возникнут вопросы или потребуется дополнительная информация, не стесняйтесь обращаться к нашей службе поддержки. Вы можете связаться с нами по указанным контактным данным на нашем сайте.

Благодарим вас за понимание и сотрудничество. Мы ценим ваше терпение и стремимся предоставить вам лучший опыт использования нашего сервиса.

С уважением,
Команда Ascon

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

Автор 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 таблицу, хотя работа с деревом по мне так, более красивое решение.

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

IgorRUtver

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

chelkar

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

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 и как им пользоваться?


IgorRUtver

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


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 это интерфейс компаса, а прочитав разочаровался, пока только начал изучать, и прошу простить если гдето неверно свормулировал мысль :~



В массиве лежит 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]

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

IgorRUtver

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

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

Дмитрий Геннадьевич

Тоже долго разбирался, когда приспичило получить состав верхнего уровня сборки, а оказалось все просто.
Готовый код, вдруг кому сгодится, работает)))
Профессионалы - поправьте пож-ста, если где-то "подводный камень" или моя неверная трактовка в комментариях.

var
  newKompasAPI : IApplication;
  Document : IKompasDocument;
  Doc3D : IKompasDocument3D;         
  TopPart7, pPart7 : IPart7;                   
  pParts7 : IParts7;                 
  pPartsEx : variant;               
  pModelObject : IModelObject;

begin
Document := newKompasAPI.ActiveDocument;    //подключаемся к интерфейсу активного документа
if (Document.DocumentType=5)    //раскрытие состава верхнего уровня изделия, если оно - сборка
      then
        begin
          Doc3D := Document as IKompasDocument3D;   
          TopPart7:=Doc3D.TopPart;                       //подключаемся к интерфейсу верхней модели в документе
          pPartsEx := TopPart7.PartsEx[ksUniqueParts];   //получаем массив интерфейсов компонентов, входящих в верхнюю модель ( только первые экземпляры)
          If VarType(pPartsEx)=(VT_ARRAY or VT_DISPATCH)      //проверяем, что pPartsEx действительно является массивом интерфейсов
           then
            begin
              imax := VarArrayHighBound(pPartsEx,1);     //получаем верхнюю границу размерности 1 массива pPartsEx
              Showmessage('Количество объектов '+IntToStr(imax+1));  //+1 потому что счет от нуля
              for It := 0 to imax do         //проходим все компоненты
                begin
                  pModelObject := IDispatch(pPartsEx[It]) as IModelObject;    //получаем указатель на  интерфейс It-го компонента
                  pPart7:=pModelObject as iPart7;                // получаем интерфейс It-го компонента
                  Showmessage(pPart7.Marking+'  '+pPart7.name +'   '+inttostr(TopPart7.InstanceCount[pPart7])); //выводим обозначение, имя, количество
                end;
            end;
        end;
end;