Неактуальность API

Автор omgtustudent, 08.04.23, 10:40:30

« назад - далее »

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

omgtustudent

Доброго времени суток, я занимаюсь реализацией булевых операций, но создать работающий макрос не могу. При этом написанный код, касающийся булевой операции, на мой взгляд, выглядит таким, каким он и должен быть. Однако строка вызова в Компасе булевой операции возвращает False:
solid_one = part_one.BodyCollection().GetByIndex(0)
solid_two = part_two.BodyCollection().GetByIndex(0)
partBool = Kompas6API5.ksPart(doc3d.GetPart(LDefin3D.pNew_Part))
entBool = partBool.NewEntity(LDefin3D.o3d_aggregate)
definition = entBool.GetDefinition()
collection = definition.BodyCollection()
collection.Add(solid_one)
collection.Add(solid_two)
definition.BooleanType = 2 # вычитание
entBool.Create() # ничего не происходит, функция возвращает False
entBool.Update()
print(solid_one.IsSolid(), solid_two.IsSolid()) # True True
print(collection.GetCount()) # 2
print(entBool.Create()) # False
print(entBool.Update()) # False
print(entBool.IsCreated()) # False
doc3d.RebuildDocument() # результата нет
В макросе реализовано создание нового окна трехмерного моделирования, импорт двух m3d моделей, их совмещение и (вроде бы) применение булевой операции:
# -*- coding: utf-8 -*-

import pythoncom
from win32com.client import Dispatch, gencache, VARIANT
import Kompas6API5, LDefin3D, LDefin2D

kompas6_constants = gencache.EnsureModule("{75C9F5D0-B5B8-4526-8681-9903C567D2ED}", 0, 1, 0).constants
kompas6_constants_3d = gencache.EnsureModule("{2CAF168C-7961-4B90-9DA2-701419BEEFE3}", 0, 1, 0).constants
kompas6_api5_module = gencache.EnsureModule("{0422828C-F174-495E-AC5D-D31014DBBE87}", 0, 1, 0)
kompas_object = kompas6_api5_module.KompasObject(Dispatch("Kompas.Application.5")._oleobj_.QueryInterface(kompas6_api5_module.KompasObject.CLSID, pythoncom.IID_IDispatch))
kompas_api7_module = gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)
kompas_api_object = kompas_api7_module.IKompasAPIObject(Dispatch("Kompas.Application.7")._oleobj_.QueryInterface(kompas_api7_module.IKompasAPIObject.CLSID, pythoncom.IID_IDispatch))

application = kompas_api_object.Application
documents = application.Documents

kompas_document = documents.Add(kompas6_constants.ksDocumentPart, True)
kompas_document.Active = True

kompas_document_3d = kompas_api7_module.IKompasDocument3D(kompas_document)
part7 = kompas_document_3d.TopPart
parts7 = part7.Parts

doc3d = kompas_object.ActiveDocument3D()

part_one = parts7.AddFromFile("F:\\2.m3d", True)
placement_one = part_one.Placement
placement_one.SetOrigin(0, 0, 0);
part_one.CreateSpcObjects = False
part_one.IsLocal = False
part_one.IsLayoutGeometry = False
part_one.IsBillet = True
part_one.InheritExclude = False
part_one.StaffVisible = True
part_one.UseDummy = False
part_one.UpdatePlacement(True)
part_one.Fixed = True
part_one.LeftHandedCS = False
part_one.Name = '1'
part_one.Update()

part_two = parts7.AddFromFile("F:\\1.m3d", True)
placement_two = part_two.Placement

placement_two.SetOrigin(0, 0, -50);
part_two.CreateSpcObjects = False
part_two.IsLocal = False
part_two.Name = '2'
part_two.IsLayoutGeometry = False
part_two.IsBillet = True
part_two.InheritExclude = False
part_two.StaffVisible = True
part_two.UseDummy = False
part_two.UpdatePlacement(True)
part_two.Fixed = False
part_two.LeftHandedCS = False
part_two.Update()

placement_two.SetOrigin(0, 0, -50)
part_two.UpdatePlacement(True)
part_two.Update()

partBool = Kompas6API5.ksPart(doc3d.GetPart(LDefin3D.pNew_Part))
entBool = partBool.NewEntity(LDefin3D.o3d_aggregate)

definition = entBool.GetDefinition()
collection = definition.BodyCollection()

solid_one = doc3d.GetPart(0).BodyCollection().GetByIndex(0)
solid_two = doc3d.GetPart(0).BodyCollection().GetByIndex(0)

collection.Add(solid_one)
collection.Add(solid_two)

definition.BooleanType = 2

entBool.Create()
entBool.Update()

doc3d.RebuildDocument()
Я перепробовал, кажется, все возможные варианты внесения изменений в макрос, а также написал почти аналогичный код ни c#, чтобы лучше разобраться с типами в API и доказать себе, что проблема не в python. Но результат выполнения кода прежний – детали импортируются, но булева операция не работает:
static void Main(string[] arguments)
  {
      IApplication app = (IApplication)Marshal2.GetActiveObject("KOMPAS.Application.7");
      KompasObject kompas = (KompasObject)Marshal2.GetActiveObject("KOMPAS.Application.5");
      IKompasDocument doc = app.Documents.Add(DocumentTypeEnum.ksDocumentPart);
      Document3D document3D = (Document3D)kompas.ActiveDocument3D();
      IKompasDocument3D doc3d = (IKompasDocument3D)doc;
      IParts7 parts = doc3d.TopPart.Parts;

      IPart7 part_one = parts.AddFromFile("C:\\2.m3d");
      IPlacement3D placement_one = part_one.Placement;
      placement_one.SetOrigin(0, 0, 0);
      part_one.CreateSpcObjects = false;
      part_one.IsLocal = false;
      part_one.IsLayoutGeometry = false;
      part_one.IsBillet = true;
      part_one.InheritExclude = false;
      part_one.StaffVisible = true;
      part_one.UseDummy = true;
      part_one.UpdatePlacement(true);
      part_one.Fixed = true;
      part_one.LeftHandedCS = false;
      part_one.Name = "1";

      part_one.Update();

      IPart7 part_two = parts.AddFromFile("C:\\1.m3d");
      IPlacement3D placement_two = part_two.Placement;
      placement_two.SetOrigin(0, 0, 0);
      part_two.CreateSpcObjects = false;
      part_two.IsLocal = false;
      part_two.IsLayoutGeometry = false;
      part_two.IsBillet = true;
      part_two.InheritExclude = false;
      part_two.StaffVisible = true;
      part_two.UseDummy = true;
      part_two.UpdatePlacement(true);
      part_two.Fixed = false;
      part_two.LeftHandedCS = false;
      part_two.Name = "2";

      part_two.Update();

      placement_two.SetOrigin(0, 0, -50);
      part_two.UpdatePlacement(true);
      part_two.Update();

      ksPart partBool = (ksPart)document3D.GetPart((int)Part_Type.pNew_Part);
      ksEntity entBool = (ksEntity)partBool.NewEntity((short)Obj3dType.o3d_aggregate);

      Body7 b1 = part_one.GetBodyById(0);
      Body7 b2 = part_two.GetBodyById(0);

      ksAggregateDefinition definition = (ksAggregateDefinition)entBool.GetDefinition();
      definition.BooleanType = 2;
      ksBodyCollection collection = (ksBodyCollection)definition.BodyCollection();

      collection.Add(b2);
      collection.Add(b1);

      entBool.Create();
      entBool.Update();
}
Моя основная теория заключается в неактуальности API. Булевой операции действительно требовалось два параметра в старых версиях компаса, сейчас же двух параметров недостаточно, но апи никак не изменилось. Программно для булевой опереации можно задать только BooleanType и BodyCollection, других параметров нет. И это полностью соответствует тому, что можно было увидеть в графическом интерфейсе Компаса ранних версий. Однако последняя версия содержит уже пять параметров.

И я предполагаю, что именно невозможность программно задать их приводит к тому, что функция возвращает False. Релиз API был точно давно. Мне кажется, оно осталось практически таким, каким было лет десять назад, при этом сам кад менялся. Конечно, мне совсем не ясно, что программно апи из себя представляет, как обновляется и как связано с ядром. Но после всех страданий с булевыми операциями реализация чего-то подобного мне теперь не кажется безусловно выполнимой задачей, несмотря даже на наличие описаний в документации. Кроме того, уроки по API посвящены чему угодно, только не операциям твердотельного моделирования, как будто это не только не попадает в главную область применения апи, но и как будто бы является нетривиальной задачей. При этом я знаю, что моя задача успешно решалась восемь лет назад, что все прекрасно работало на соответствующей версии компаса, не знаю точно на какой. Сегодня же я сделать ничего не могу. И отсутствие возможности задать определенные параметры для булевой операции заставило меня родить такие вот пессимистичные предположения об API.

Здесь также никуда не исчезает вероятность того, что проблема исключительно в моем макросе, так как в версиях, где Компасу достаточно двух параметров, результат такой же. Речь о 20-ой версии, которая все равно сильно изменилась по сравнению с теми версиями, на которых подобный макрос успешно запускался.

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

Что думаете на счет этого всего? Можете ли вы подтвердить либо опровергнуть мои предположения? Занимались ли вы реализацией подобных операций? Какие версии Компаса вы использовали? Видите ли ошибки в коде? Или можете ли предположить, что может быть настоящей причиной того, что мой макрос не работает? Спасибо.

П.С. Прикрепить скриншот не смог: сайт не может обработать запрос. Параметры булевой операции раньше (до версии 20 включительно): результат операции, список объектов. Сейчас: результат операции, базовый объект, сохранить копию базового объекта, модифицирующие объекты, сохранить копию модифицирующих объектов. Очень даже может быть, что такие различия в основном косметические и реализованы как дополнительный функционал поверх имевшегося, никак не затрагивая прежний код.

Михаил88

#1
Все работает проверил на К18.1. У вас в коде ошибки.

# -*- coding: utf-8 -*-
import pythoncom
from win32com.client import Dispatch, gencache
import LDefin3D

#  Подключим описание интерфейсов API5
kompas6_api5_module = gencache.EnsureModule("{0422828C-F174-495E-AC5D-D31014DBBE87}", 0, 1, 0)
kompas_object = kompas6_api5_module.KompasObject(
    Dispatch("Kompas.Application.5")._oleobj_.QueryInterface(kompas6_api5_module.KompasObject.CLSID,
                                                            pythoncom.IID_IDispatch))

doc3d = kompas_object.ActiveDocument3D()
print(doc3d)

part_collection = doc3d.PartCollection(True)
print(part_collection)
solid_one = part_collection.GetByIndex(0).BodyCollection().GetByIndex(0)
solid_two = part_collection.GetByIndex(1).BodyCollection().GetByIndex(0)
print(solid_one, solid_two)

ks_part = doc3d.GetPart(-1)
print(ks_part.name)
entBool = ks_part.NewEntity(LDefin3D.o3d_aggregate)
print(entBool)
definition = entBool.GetDefinition()
print(definition)

collection = definition.BodyCollection()
print(collection.GetCount())

collection.Add(solid_one)
collection.Add(solid_two)
collection.refresh()
print(collection.GetCount())

definition.BooleanType = 2  # вычитание

print(entBool.Create())
ДО
Screenshot_1.bmp
ПОСЛЕ
Screenshot_2.bmp
ПРИНТЫ
Screenshot_3.bmp

Такой результат вы хотели получить?
+ Благодарностей: 1

omgtustudent

Прекрасно, спасибо. Буду думать, проблем с совместимостью нет, хотя различия в работе на разных версиях всего, что связано с компас-макро, похоже, есть все равно. Но мои проблемы только из-за кривых рук

Vi2

Цитата: omgtustudent от 08.04.23, 10:40:30Булевой операции действительно требовалось два параметра в старых версиях компаса, сейчас же двух параметров недостаточно, но апи никак не изменилось. Программно для булевой опереации можно задать только BooleanType и BodyCollection, других параметров нет. И это полностью соответствует тому, что можно было увидеть в графическом интерфейсе Компаса ранних версий. Однако последняя версия содержит уже пять параметров.
И чему тут удивляться, если интерфейсы разные: ksAggregateDefinition содержит 2 старых метода, IBoolean содержит 5 новых. Разработчики как-то внутри согласовали эти объекты, наверное, новый интерфейс позволяет немного изменить поведение операции по сравнению со старым интерфейсом. Не больше. Но ты можешь использовать оба в равной степени.

По поводу невыполнения операции. Возможно, операция и не может быть выполнена, т.к. не каждая булева операция может быть выполнена из-за ошибок в моделях.