Получение сегментов границ штриховки и заливки

Автор Антон Чумаков, 19.07.21, 22:12:37

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

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

Антон Чумаков

Здравствуйте!
Имеется Компас-фрагмент, содержащий всякую геометрию, в т.ч. штриховки и заливки. Моя задача состоит в посегментном воспроизведении границы этих объектов. Вопрос: как получить интерфейс сегмента границы какой-нибудь штриховки/заливки?
На данный момент я додумался только до такого: длинным обходным путём (см. ниже тестовый код) получаю у штриховки интерфейс IContourSegment, у которого (согласно справке по SDK) можно получить доп. интерфейсы IContourLineSegment и IContourArc. Но! Эти интерфейсы можно получить только тогда, когда нужный сегмент является отрезком и дугой соответственно. В случае, когда сегмент является Безье-сплайном или дугой эллипса, выскакивает ошибка.
Есть ли возможность получить интерфейс сегмента произвольного типа?

Полный тестовый код:
import pythoncom
from win32com.client import Dispatch, gencache
import KompasAPI7 as KAPI7

def GetQueryInterface(iBaseObject, NamesToIIDMapCB, sNamesToIIDMap):
    """ Обёртка-костыль для UnknownInterface """
    return NamesToIIDMapCB(iBaseObject._oleobj_.QueryInterface(KAPI7.NamesToIIDMap[sNamesToIIDMap], pythoncom.IID_IDispatch))

kapi7module = gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)
application = kapi7module.IApplication(Dispatch("Kompas.Application.7")._oleobj_.QueryInterface(kapi7module.IApplication.CLSID, pythoncom.IID_IDispatch))
#Documents = application.Documents

kompas_document = application.ActiveDocument
iDocument2D = kapi7module.IKompasDocument2D(kompas_document)
iViewsAndLayersMgr = iDocument2D.ViewsAndLayersManager
iViews = iViewsAndLayersMgr.Views
iView = iViews.ActiveView

iDrawingContainer = GetQueryInterface(iView, KAPI7.IDrawingContainer, 'IDrawingContainer')
iHatches = iDrawingContainer.Hatches
iHatch = iHatches.Hatch(0)    # получение 0-й штриховки из коллекции

iBoundariesObject = GetQueryInterface(iHatch, KAPI7.IBoundariesObject, 'IBoundariesObject')
iDrawingContours = iBoundariesObject.Boundaries  # выдрать копию границы (тип объекта - 'tuple')
iContour = GetQueryInterface(iDrawingContours[0], KAPI7.IContour, 'IContour')  # получить 0-й элемент копии границы

iSeg = iContour.Segment(0)  # интерфейс сегмента №0 (тип - IContourSegment)
iCSeg = GetQueryInterface(iSeg, KAPI7.IContourLineSegment, 'IContourLineSegment') # работает для сегмента-отрезка, в других случаях - ошибка
print (iCSeg.SegmentType)

Вират Лакх

Зачем вам "обёртка-костыль"? Вот же у вас здесь iDocument2D = kapi7module.IKompasDocument2D(kompas_document) выполняется QueryInterface простым способом, а в остальных местах вы городите эти сложности и начинаете путаться в типах. Вы, когда получили интерфейс, посмотрите через print, что он там выдал. Если выдал не то, что написано в SDK (как, например, iContour.Segment(i) выдает IKompasAPIObject вместо IContourSegment, то нужно добить его до нужного типа опять же с помощью QueryInterface). В итоге ваш код можно переписать так:
from win32com.client import Dispatch, gencache
API7 = gencache.EnsureModule('{69AC2981-37C0-4379-84FD-5DD2F3C0A520}', 0, 1, 0)
iApplication = Dispatch('Kompas.Application.7')
iKompasDocument = iApplication.ActiveDocument
iKompasDocument2D = API7.IKompasDocument2D(iKompasDocument)
iViewsAndLayersManager = iKompasDocument2D.ViewsAndLayersManager
iViews = iViewsAndLayersManager.Views
iView = iViews.ActiveView
iDrawingContainer = API7.IDrawingContainer(iView)
iHatches = iDrawingContainer.Hatches
iHatch = iHatches.Hatch(0)
iBoundariesObject = API7.IBoundariesObject(iHatch)
iDrawingContour = iBoundariesObject.Boundaries[0]
iContour = API7.IContour(iDrawingContour)
for i in range(iContour.Count):
iContourSegment = API7.IContourSegment(iContour.Segment(i))
segment_type = iContourSegment.SegmentType
if segment_type == 1:
iContourLineSegment = API7.IContourLineSegment(iContourSegment)
print(iContourLineSegment.Length)
elif segment_type == 3:
iContourArc = API7.IContourArc(iContourSegment)
print(iContourArc.Radius)
else:
print('segment_type:', segment_type)

print(iContour.TmpObjects)
Тут в конце есть iContour.TmpObjects. Может вам просто им воспользоваться и не перебирать циклом геометрию? А дальше массивы копировать в буфер и вставлять из буфера в другой документ или как вы хотите... Только при работе через штриховку полученная геометрия может и не быть на самом деле вокруг этой штриховки. На то оно и TmpObjects.

Антон Чумаков

Во, стало получаться! Благодарю за помощь! Кстати, интересно выходит: если сегмент границы является Безье-сплайном, то он разбивается по узлам (впрочем, в моей задаче это не страшно).
Касательно обёртки-костыля, я к ней пришёл методом проб и ошибок и не уделял должного внимания: работает - и ладно. Оказалось, плохо работает. Но теперь, благодаря Вашей подсказке, причешу код.