Сообщество программистов Autodesk в СНГ

ADN Club => VBA => Тема начата: Khasan Mamaev от 17-06-2017, 13:17:27

Название: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 17-06-2017, 13:17:27
Рад приветствовать вас коллеги! Python это язык программирования высокого уровня, который ввиду простоты своего синтаксиса приобрел на сегодняшний день огромную армию пользователей и помогает решать широкий круг задач из различных сфер нашей жизни. Проектирование также не осталось в стороне. В этой теме я хочу делиться с читателями своим опытом использования Python для Autocad. Попытки использовать Питон для Автокад конечно же предпринимались и раньше, нашим соотечественником Романом Харитоновым даже была написана библиотека pyautocad(https://pypi.python.org/pypi/pyautocad), но я покажу более простой способ подключения к Автокад. Начну пожалуй со своего первого урока из цикла "Python for Engineers", который посвящен подключению к Автокад:



А это сам код:
Код - Python [Выбрать]
  1. from math import cos, sin, pi
  2. import System
  3. from System import Array
  4. app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
  5. AcDoc = app.ActiveDocument
  6. mSp = AcDoc.ModelSpace
  7.  
  8. a = 100
  9. fi = range(0,360,10)
  10. r = 4
  11.  
  12. for i in fi:
  13.         x = (a/360.0)*i*cos(i*pi/180.0)
  14.         y = (a/360.0)*i*sin(i*pi/180.0)
  15.         pt = Array[float]([x,y,0])
  16.         mSp.AddCircle(pt,r*(1+i/360.0))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 17-06-2017, 18:18:16
Тему закрепил, чтобы её легче было найти. Рекомендую побольше кода выкладывать здесь на форуме, так как с youtube'овского ролика переписывать его не слишком удобно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 17-06-2017, 18:22:00
Тему закрепил, чтобы её легче было найти. Рекомендую побольше кода выкладывать здесь на форуме, так как с youtube'овского ролика переписывать его не слишком удобно.

Спасибо! Это собственно весь код, который был показан в ролике) могу еще добавить макрос кнопки
Код - Auto/Visual Lisp [Выбрать]
  1. (startapp "C:/Program Files (x86)/IronPython 2.7/ipyw.exe" "g:/Lessons/!PythonForIngeneers/Py4Eng01PythonAutocad/Py4Eng_PythonAutocad.py")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 17-06-2017, 18:24:31
Спасибо! Это собственно весь код, который был показан в ролике
Это было моё пожелание на будущее. Надеюсь, что это будет не единственный урок. :)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 17-06-2017, 18:26:15
Спасибо! Это собственно весь код, который был показан в ролике
Это было моё пожелание на будущее. Надеюсь, что это будет не единственный урок. :)
Будем стараться
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 18-06-2017, 19:42:33
Ну вот, не прошло и года, и новый ролик, вставка выносок Autocad с автоматической нумерацией:



Код - Python [Выбрать]
  1. ### Autocad MLeaders Insertion
  2. ### ©2017, Khasan Mamaev
  3. ### www.dynamobim.ru
  4.  
  5. import System
  6.  
  7. marsh = System.Runtime.InteropServices.Marshal
  8. app = marsh.GetActiveObject("Autocad.Application")
  9. aDoc = app.ActiveDocument
  10. mSp = aDoc.ModelSpace
  11.  
  12. def ptA(p,x1,y1):
  13.         return System.Array[float]([p[0],p[1],p[2],p[0]+x1,p[1]+y1,p[2]])
  14.  
  15. x1 = 500
  16. y1 = 500
  17. p0 = System.Array[float]([0,0,0])
  18.  
  19. pref = aDoc.Utility.GetString(False, "Enter prefix: ")
  20. j = aDoc.Utility.GetInteger("Enter start num: ")
  21.  
  22. while True:
  23.         pt = aDoc.Utility.GetPoint(p0,'GetPoint: ')
  24.         points = ptA(pt,x1,y1)
  25.         lead = mSp.AddMLeader(points, 0)
  26.         lead.TextString = pref + str(j)
  27.         j += 1
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 03-07-2017, 22:49:30
Записал ролик с инструкцией как подключать IronPython к Notepad++

Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 05-11-2017, 16:03:23
Доступ к AutoCAD можно получить не только из IronPython, дальнейшее развитие которого, мягко говоря, находится под вопросом, но и из стандартной реализации Python, используя модуль pywin32 https://sourceforge.net/projects/pywin32 (https://sourceforge.net/projects/pywin32):

Код - Python [Выбрать]
  1. import win32com.client
  2. app = win32com.client.Dispatch("AutoCAD.Application")
  3.  
Дальше - всё по COM модели
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 05-11-2017, 16:32:35
Такой способ подключения из Питон к Автокад для меня не секрет, но возникают трудности при создании дотнетовских массивтв необходимых для СОМ. Ну и разговоры о скорой кончине АйронПайтон имеют давнюю историю, однако АйронПайтон не прекращают прикручивать к различным серьёзным программных  комплексам.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 06-11-2017, 16:04:18
Массивы достаточно просто создаются, наример один из самых распространенных случаев - преобразование в массив чисел с плавающей точкой (variant array of doubles) для координат:

Код - Python [Выбрать]
  1. import win32com.client
  2. from pythoncom import VT_R8, VT_ARRAY
  3. pythoncoord = [x, y, z]
  4. acadcoord = win32com.client.VARIANT(VT_ARRAY | VT_R8, pythoncoord)
IronPython, к сожалению, продолжают прикручивать к различным серьёзным программных комплексам, потому что другой нормально работающей реализации Python для .NET на данный момент просто не существует. Есть несколько проектов, типа pythonnet, но без танцев с бубном они с тем же автокадом не работают. IronPython вряд ли в обозримом будущем перейдёт на поддержку Python 3x, постепенно поддержка ветки 2х будет свёрнута в первую очередь со стороны разработчиков различных модулей (а множество доступных модулей практически на все случаи жизни - одно из самых весомых преимуществ Python для инженера, когда разработка программ - возможность повысить производительность и облегчить себе жизнь). Автодеск, например, с IronPython в Revit, наступает ровно на те же грабли, что и с LISP в автокаде. Кому сейчас реально нужен лисп вне автокада? Никому. Но заменить его чем-то невозможно - у пользователей просто горы кода на лиспе накопилось за все годы.
Для инженера же Python - один из лучших языков за счёт относительной простоты и наличия огромного количества модулей.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-11-2017, 17:02:15
dlobyntsev
У меня в подписи написано как следует форматировать код на форуме. Прошу ознакомится и принять к сведению.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 07-11-2017, 11:03:47
Массивы достаточно просто создаются, наример один из самых распространенных случаев - преобразование в массив чисел с плавающей точкой (variant array of doubles) для координат:

Код - Python [Выбрать]
import win32com.client
from pythoncom import VT_R8, VT_ARRAY
pythoncoord = [x, y, z]
acadcoord = win32com.client.VARIANT(VT_ARRAY | VT_R8, pythoncoord)
IronPython, к сожалению, продолжают прикручивать к различным серьёзным программных комплексам, потому что другой нормально работающей реализации Python для .NET на данный момент просто не существует. Есть несколько проектов, типа pythonnet, но без танцев с бубном они с тем же автокадом не работают. IronPython вряд ли в обозримом будущем перейдёт на поддержку Python 3x, постепенно поддержка ветки 2х будет свёрнута в первую очередь со стороны разработчиков различных модулей (а множество доступных модулей практически на все случаи жизни - одно из самых весомых преимуществ Python для инженера, когда разработка программ - возможность повысить производительность и облегчить себе жизнь). Автодеск, например, с IronPython в Revit, наступает ровно на те же грабли, что и с LISP в автокаде. Кому сейчас реально нужен лисп вне автокада? Никому. Но заменить его чем-то невозможно - у пользователей просто горы кода на лиспе накопилось за все годы.
Для инженера же Python - один из лучших языков за счёт относительной простоты и наличия огромного количества модулей.

Про богатство библиотек Питон я в курсе, поскольку пользуюсь для своей работы Jupyter Notebook. Если АйронПайтон будет убит, то это будет крайне прискорбно, но думаю 3-4 года у нас еще есть, а за это время можно сделать кучу всего, дальше посмотрим. Про создание подобных массивов не знал, спасибо за информацию. Буду чаще использовать работу с СОМ из чистого Питона, очень уж хочется использовать модули numpy, scipy и т п. Кстати, недавно закостылил синтез Питон и АйронПитон, осуществил работу с Автокад из Юпитер ноутбука, в ближайшее время покажу на своем канале.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 13-11-2017, 12:14:55
dlobyntsev,

Можно ли в чистом Питоне осуществить этот код:

Код - Python [Выбрать]
  1. import System
  2. from System import Array
  3. import clr
  4. clr.AddReferenceToFileAndPath('C:/Program Files/Autodesk/AutoCAD 2016/Autodesk.AutoCAD.Interop.Common')
  5. from Autodesk.AutoCAD.Interop.Common import AcadEntity, AcBooleanType
  6.  
  7. app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")
  8. aDoc = app.ActiveDocument
  9. sset = aDoc.PickfirstSelectionSet
  10. msp = aDoc.ModelSpace
  11.  
  12. elems = list(iter(sset))
  13. def ptA(X,Y,Z):
  14.         return Array[float]([X, Y, Z])
  15.  
  16. def faceToPline(face):
  17.         return msp.AddPolyline(face.Coordinates)
  18.  
  19. def plineToRegion(pl):
  20.         entArr = Array.CreateInstance(AcadEntity,1)
  21.         entArr.SetValue(pl,0)
  22.         return msp.AddRegion(entArr)   
  23.  
  24. def centArea(x):
  25.         return [x.Centroid[0], x.Centroid[1], x.Area]
  26.  
  27. inter = elems[0].Boolean(AcBooleanType.acIntersection, elems[1])
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 13-11-2017, 16:26:50
Можно, код с комментариями ниже:
Код - Python [Выбрать]
  1. import win32com.client
  2. from pythoncom import VT_R8, VT_ARRAY, VT_DISPATCH
  3.  
  4. app = win32com.client.Dispatch("AutoCAD.Application")
  5. aDoc = app.ActiveDocument
  6. msp = aDoc.ModelSpace
  7.  
  8. #немного модифицировал функцию ptA(), теперь она преобразует в variant array of doubles
  9. # все аргументы, в т.ч. и представленные в виде списка или кортежа
  10. def convert_coordinates(*args):
  11.     """
  12.    Функция преобразования координат в формат AutoCAD
  13.    :param args: координаты для преобразования, допустима передача списка или кортежа
  14.    :return: Координаты в формате AutoCAD
  15.    """
  16.     if isinstance(args[0], (list, tuple)):
  17.         coords = [item for item in args[0]]
  18.     else:
  19.         coords = args
  20.     return win32com.client.VARIANT(VT_ARRAY | VT_R8, coords)
  21.  
  22. def faceToPline(face):
  23.     #из кода постом выше непонятно, в каком виде передаётся .Coordinates
  24.     #будет работать при условии, что face.Coordinates - это последовательность, список или кортеж
  25.     #не менее чем из шести чисел. Количество аргументов кратно 3 - ограничения .AddPolyline()
  26.     #возможно, необходимы дополнительные преобразования
  27.     return msp.AddPolyline(convert_coordinates(face.Coordinates))
  28.  
  29. def plineToRegion(pl):
  30.     msp.AddRegion(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [pl]))
  31.  
  32. #из кода постом выше непонятно, как работает функция
  33. def centArea(x):
  34.     return [x.Centroid[0], x.Centroid[1], x.Area]
  35.  
  36. #будет работать при условии, что в списке elems содержаться объекты AutoCAD
  37. #возможно, потребуется преобразование win32com.client.VARIANT(VT_DISPATCH, obj)
  38. #для elems[0] и elems[1]
  39. inter = elems[0].Boolean(2, elems[1])
Вообще, основная проблема работы с AutoCAD через COM - преобразование типов данных, но всё вроде решаемо.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 22-11-2017, 16:49:58
Добрый день!
Пишу скрипт на Python  для черчения в Автокаде.
Столкнулся с проблемой - не могу разобраться с COM моделью AutoCAD, а если конкретнее, не могу настроить создаваемый  мной стиль таблиц. 
Код вроде как работает, стиль создается (хотя и не перезаписывает существующий) :

Код - Python [Выбрать]
  1. import win32com.client
  2.  
  3. app = win32com.client.Dispatch("AutoCAD.Application")
  4. aDoc = app.ActiveDocument
  5. mSp = aDoc.ModelSpace
  6.  
  7. dicts = aDoc.Database.dictionaries
  8.  
  9. ts = dicts.Item("acad_tablestyle")
  10. ts.AddObject("NewStyle", "AcDbTableStyle")

Далее, допустим, мне нужно назначить высоту текста по умолчанию для ячеек с типом  "заголовок" или "данные" этого нового табличного стиля NewStyle.  В справке  по модели COM Автокада читаю:

Цитировать
object.SetTextHeight(rowTypes, TextHeight)

ObjectTable, TableStyle
The object this method applies to.
rowTypesLong; the row types to change.
TextHeight
Double; the text height to use for the specified row types.

Не могу разобраться, что это за rowTypes, и как это реализовать через Пайтон (либо IronPython, либо CPython + win32com)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-11-2017, 17:50:12
Electric,
Приветствую на форуме!
1. Прочитай у меня в подписи как следует форматировать код на форуме и придерживайся этого правила.
2. Ты нашёл неудачную документацию. Удачная здесь: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-35CC52D6-03C1-48EE-90A3-97DFBBAC33C3-htm.html
В частности там сказано, что rowTypes - это одно из значений перечисления (числовые значения я подставил сам):

Код - C++ [Выбрать]
  1. enum AcRowType
  2.     {
  3.         acUnknownRow    = 0,
  4.         acDataRow       = 1,
  5.         acTitleRow      = 2,
  6.         acHeaderRow     = 4
  7.     }   AcRowType;
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 22-11-2017, 19:05:34
Electric,
Приветствую на форуме!

Спасибо за ссылку, помогло!
Но остается проблема, я не могу понять, как реализовать на Пайтоне эту команду  из документации VBA:

Код - Visual Basic [Выбрать]
  1. customObj.SetTextHeight AcRowType.acDataRow + AcRowType.acTitleRow, 1.3

К примеру. у меня все работает, когда передаю "1" или "2" по отдельности , назначая моему табличному стилю newTabStyle высоту 2,5:

Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight("2", 2.5)

 но как передать эти два значения сразу? При попытке передать их в виде списка или кортежа выдает ошибку, когда я передаю "1"+"2" - функция игнорирует  один из них.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-11-2017, 19:18:34
К примеру. у меня все работает, когда передаю "1" или "2" по отдельности , назначая моему табличному стилю newTabStyle высоту 2,5:

Код - Python [Выбрать]

    newTabStyle.SetTextHeight("2", 2.5)


 но как передать эти два значения сразу? При попытке передать их в виде списка или кортежа выдает ошибку, когда я передаю "1"+"2" - функция игнорирует  один из них.
Зачем их передавать сразу?
Вот так тебя не устроит:
Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight(1, 2.5)
  2. newTabStyle.SetTextHeight(2, 2.5)

???

Хотя так тоже должно работать:
Код - Python [Выбрать]
  1. newTabStyle.SetTextHeight(3, 2.5)

Не понял зачем ты пытаешься преобразовать число в строку. Этот метод принимает целые числа, а не строки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-11-2017, 05:45:31
Вот так тебя не устроит:

Да, спасибо. В тот раз мне это помогло, разобрался с той проблемой.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-11-2017, 18:03:00
Возник следующий вопрос.
Пользователю нужно выделить какой-то объект в Автокаде, при этом в командной строке  должен отображаться текст вроде "Выделите прямоугольник"

Этот код работает:

Код - Python [Выбрать]
  1. example, _ = aDoc.Utility.GetEntity()

Но этот выдает уже ошибку:

Код - Python [Выбрать]
  1. example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')

Цитировать
example, _ = aDoc.Utility.GetEntity('Укажите объект: ')
  File "<COMObject <unknown>>", line 3, in GetEntity
  File "C:\ProgramData\Anaconda3\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
    result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
TypeError: The Python instance can not be converted to a COM object

Кроме того, допустим, пользователю нужно выделить не один, а сразу несколько объектов в Автокаде, через какую команду это реализуется? Если смотрю  в справке (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-DE118C17-4567-48CF-8EFA-CABB52A27275-htm.html) по AcadUtility, то там из методов  в основном только выделение единичного объекта или получение чисел, строк, углов и т.п.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 27-11-2017, 18:09:55
Можно получить предварительно выбранные объекты вот так sset = AcDoc.PickfirstSelectionSet
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-11-2017, 18:16:19
Кроме того, допустим, пользователю нужно выделить не один, а сразу несколько объектов в Автокаде, через какую команду это реализуется?
SelectionSet.SelectOnScreen: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-C4B442A3-D6A9-48FA-8C86-03D49A3B2ED7-htm.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-11-2017, 18:45:03
Но этот выдает уже ошибку:

Код - Python [Выбрать]

    example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')
Я не специалист по Python, но может быть так:
Код - Python [Выбрать]
  1. returnObj = aDoc.Utility.GetEntity("Укажите прямоугольник: ")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-11-2017, 19:16:58
Но этот выдает уже ошибку:

Код - Python [Выбрать]

    example, _ = aDoc.Utility.GetEntity('Укажите прямоугольник: ')
Я не специалист по Python, но может быть так:
Код - Python [Выбрать]
  1. returnObj = aDoc.Utility.GetEntity("Укажите прямоугольник: ")

Ну я так понимаю, aDoc.Utility.GetEntity  возвращает и Объект и  координату точки сразу.  Вместе  они с точки зрения Python  являются кортежем tuple, я просто выбирал объект как первую часть кортежа. Без этого выражения у меня ошибка.

Цитировать
AttributeError: 'tuple' object has no attribute 'Layer'
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-11-2017, 19:24:16
Так. Я был не прав:
Код - Visual Basic [Выбрать]
  1. object.GetEntity Object, PickedPoint [, Prompt]
Т.е. первые два параметра - это объект и точка и только третий - это подсказка типа "Укажите прямоугольник: "
https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-69164FAA-F3C7-47A4-962C-5F4B2D5BC583-htm.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 30-11-2017, 10:46:46
Для того, чтобы метод GetEntity корректно работал с подсказкой при обращении к COM Autocad через pywin32, необходимо вызвать его следующим образом:
Код - Python [Выбрать]
  1. result = aDoc.Utility.GetEntity(None, None, "Укажите прямоугольник: ")
  2. picked_object = result[0]
  3. picked_point = result[1]
Выглядит неочевидно, видимо из-за особенностей реализации вызовов в pywin32, но работает. Причем если вместо None подставить переменные, в них ничего не запишется.
Метод возвращает кортеж из объекта и координаты точки. Координаты точки также представляют собой трёхэлементный кортеж: (picked_object, (X, Y, Z))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 30-11-2017, 19:25:36
Спасибо. Разобрался.

Еще вопрос.
В автокаде во многих стандартных командах в командной строке есть возможность выбора опций.
К примеру, когда запускаем стандартное черчение прямоугольника, возникают опции  "Фаска", "Уровень", "Сопряжение", "Толщина", "Ширина", которые можно щелкнуть или набрать их ключевую букву с клавиатуры.

Возможно ли через COM  сделать подобного рода опции для своих текстовых команд?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 30-11-2017, 22:48:36
В лиспе это делается через пару initget и getkword. В .NET, насколько я помню - PromptOptions. Как это делать через COM: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2018/ENU/AutoCAD-ActiveX/files/GUID-2F1938FE-DE63-456B-9C29-612DA4539EB0-htm.html + https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-5D322A2D-3BC9-44F4-AFFD-C5770A357858-htm.html (ИМХО)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 01-12-2017, 11:47:44
Опции для команд через COM, конечно, доступны. При использовании методов Utility.GetInteger, Utility.GetReal, GetString и т.п. достаточно сформировать строку запроса особым образом. Для автокада наличие в запросе текста вида [Опция1/<оПция2>/опЦия3] означает, что в запросе имеются три опции, причем вторая - опция по-умолчанию. Но, как всегда, дьявол кроется в деталях. И имя его в данном случае - обработка ошибок. Например, ввод опции при использовании Utility.GetReal вызывает ошибку, т.к. автокад ожидает ввода числа, а нажатие опции - это ввод строки. Необходимо этот случай предусмотреть и обработать. Делается это следующим образом:
Код - Python [Выбрать]
  1. from pythoncom import com_error
  2. #Инициируем ввод
  3. doc.Utility.InitializeUserInput(128)
  4. #Запрашиваем ввод числа с плавающей точкой
  5. try:
  6.     inputresult = doc.Utility.GetReal("\nВведите число [Опция1/оПция2]"
  7. except com_error as error:
  8.     #Получаем код COM ошибки
  9.     errnumber = error.excepinfo[-1]
  10.     if errnumber == -2145320928: #Была введена строка вместо числа
  11.         #Запрашиваем введённую строку
  12.         inputresult = doc.Utility.GetInput()
  13.         #Проверяем, соответствует ли введенная строка выбору опций
  14.         if inputresult.upper() == "О" or  inputresult.upper() == "ОПЦИЯ1":
  15.             #Код, выполняемый при выборе "Опция1"
  16.             pass
  17.         elif inputresult.upper() == "П" or  inputresult.upper() == "ОПЦИЯ2":
  18.              #Код, выполняемый при выборе "Опция2"
  19.             pass
  20.         else:
  21.             #Код, выполняемый при вводе любых других символов, кроме относящихся к опциям
  22.             #при наличии опции по умолчанию необходимо сопоставить ей ввод пустой строки ""
  23.             pass
  24.     elif errnumber == -2147352567: #Была нажата кнопка Ecs, обработка приведена для примера
  25.         #Код, выполняемый при нажатии Esc
  26.         pass
  27.     else:
  28.         #Код, выполняемый при любых других ошибках
  29.         pass
Я для себя просто написал функции на основе GetString, и преобразую потом введённое в int, float и т.д. уже средствами pyton, при этом внутри функций предусмотрел автоматический конструктор строки запроса для ввода опций, опций по-умолчанию и т.п., чтобы каждый раз не прописывать, с чем сравнивать введенную строку, чтобы понять, была ли выбрана опция.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 01-12-2017, 13:11:54
Опции для команд через COM, конечно, доступны. При использовании методов Utility.GetInteger, Utility.GetReal, GetString и т.п. достаточно сформировать строку запроса особым образом. Для автокада наличие в запросе текста вида [Опция1/<оПция2>/опЦия3] означает, что в запросе имеются три опции, причем вторая - опция по-умолчанию.
Кто сказал? В лиспе, по крайней мере, это не так. И, насколько я помню, в .NET тоже не так.
Вообще-то вот из официальной справки по VBA:
Код - Text [Выбрать]
  1. Sub Example_InitializeUserInput()
  2.     ' This example prompts for user input of a point. By using the
  3.     ' InitializeUserInput method to define a keyword list, the example can also
  4.     ' return keywords entered by the user.
  5.    
  6.     AppActivate ThisDrawing.Application.Caption
  7.    
  8.     On Error Resume Next
  9.    
  10.     ' Define the valid keywords
  11.     Dim keywordList As String
  12.     keywordList = "Line Circle"
  13.    
  14.     ' Call InitializeUserInput to set up the keywords
  15.     ThisDrawing.Utility.InitializeUserInput 128, keywordList
  16.    
  17.     ' Get the user input
  18.     Dim returnPnt As Variant
  19.     returnPnt = ThisDrawing.Utility.GetPoint(, vbLf & "Enter a point [Line/Circle]: ")
  20.     If Err Then
  21.          If StrComp(Err.Description, "User input is a keyword", 1) = 0 Then
  22.          ' One of the keywords was entered
  23.              Dim inputString As String
  24.              Err.Clear
  25.              inputString = ThisDrawing.Utility.GetInput
  26.              MsgBox "You entered the keyword: " & inputString
  27.          Else
  28.              MsgBox "Error selecting the point: " & Err.Description
  29.              Err.Clear
  30.          End If
  31.     Else
  32.         ' Display point coordinates
  33.         MsgBox "The WCS of the point is: " & returnPnt(0) & ", " & returnPnt(1) & ", " & returnPnt(2), , "GetInput Example"
  34.     End If
  35.    
  36. End Sub
Обрати внимание на InitializeUserInput и его обработку.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 01-12-2017, 13:39:29
Тут ещё накладывается не всегда понятное взаимодействие Python с COM через pywin32.
Когда я с вводом разбирался, особой разницы между
Код - Python [Выбрать]
  1. doc.Utility.InitializeUserInput(128, "Line Circle")
и
Код - Python [Выбрать]
  1. doc.Utility.InitializeUserInput(128)
для последующей обработки не заметил, хотя, может, и упустил что-то.
Моя фраза
Цитировать
достаточно сформировать строку запроса особым образом
относится только к тому,что запрос в командной строке будет выглядеть как запрос с опциями, далее я как раз и показываю, что необходимо предусмотреть в коде, чтобы опции запроса не только выглядели, как опции, но и работали соответствующим образом.
Код из официальной справки VBA действует абсолютно по той же схеме, обрабатывая ошибки при вводе значений опций:
Код - Visual Basic [Выбрать]
  1. If Err Then
  2.          If StrComp(Err.Description, "User input is a keyword", 1) = 0 Then
просто я вместо текста ошибки "User input is a keyword" отслеживаю её по коду -2145320928
Код - Python [Выбрать]
  1. errnumber = error.excepinfo[-1]
  2.     if errnumber == -2145320928:
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 01-12-2017, 14:08:43
Я в питоне дуб-дубом, немного только соображаю на предмет COM-взаимодействия :)
Насколько я понимаю, если не ввести ключевые слова, пользователь получает возможность вводить любую абракадабру.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 01-12-2017, 14:22:28
Пользователь в любом случае имеет возможность ввести любую абракадабру, просто если ввод инициализирован как
Код - Python [Выбрать]
  1. doc.Utility.InitializeUserInput(128, "Line Circle")
то при обработке ошибки "User input is a keyword" метод doc.Utility.GetInput() вернет "Circle" при вводе C, c, Circle или CIRCLE, "Line" при вводе L, l, Line или LINE. В остальных случаях - то, что ввёл пользователь.
А если ввод инициализирован как
Код - Python [Выбрать]
  1. doc.Utility.InitializeUserInput(128)
метод doc.Utility.GetInput() будет всегда возвращать то, что ввёл пользователь.
Вся разница только в обработке пользовательского ввода, но она не принципиальна, т.к. обработку, аналогичную той, что выполняет autocad, можно без проблем выполнить и в своём коде.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 08-12-2017, 12:13:17
Заметил сегодня такую ошибку. Вызываю выделение мышью объектов:

Код - Python [Выбрать]
  1. aDoc.Utility.Prompt("Укажите область на экране")
  2. selection = aDoc.SelectionSets.Add("test")
  3. selection.SelectOnScreen()

Если я выделяю область мышью - все работает. Но если я хочу выделить все объекты и по привычке нажимаю сочетание CNTRL+A - команда выделения в автокаде тут же прерывается. Далее по коду в Python при обращении к selection выдает ошибку, как если selection пуст:

Цитировать
File "C:\Program Files\Python\lib\site-packages\win32com\client\dynamic.py", line 252, in __getitem__
    raise TypeError("This object does not support enumeration")

Возможно ли как-то обработать это исключение в Python  и разрешить выделение сразу всех объектов?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-12-2017, 19:23:42
Но если я хочу выделить все объекты и по привычке нажимаю сочетание CNTRL+A - команда выделения в автокаде тут же прерывается.
Всё правильно. Так и должно быть. У AutoCAD свои правила и их следует соблюдать. Вместо CTRL+A нужно жать _A и пробел/ввод (в английской версии можно просто A (латиница), а в русской В (кириллица)). CTRL+A при стандартных настройках запускает прерывание команды и команду _ai_selall.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 10-12-2017, 15:18:30
Вместо CTRL+A нужно жать _A и пробел/ввод (в английской версии можно просто A (латиница), а в русской В (кириллица)).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-12-2017, 15:51:37
Небольшое уточнение:

    Autocad 2018 Eng - A или a не работают, нужно ввести al или all в любом регистре.
    Autocad 2018 Rus - соответственно не работает _A и _a, необходимы _al или _all в любом регистре, при этом кириллические в, все в любом регистре работают.
Мой промах. A, _A не срабатывают, так как воспринимаются как _ADD, а не как _ALL. В русской локализации же эквивалент _ALL - это Все, а эквивалент _ADD - Добавить, т.е. достаточно одной буквы для того, чтобы понять какая опция выбора введена.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 20-12-2017, 05:51:07
Еще такой вопрос по выделению объектов рамкой.
Не могу разобраться с параметрами выделения в object.SelectOnScreen [FilterType][, FilterData]

К примеру, если я хочу выделить не все объекты, а только отрезки и прямоугольники сразу. Любые варианты вроде этого:

Код - Python [Выбрать]
  1. selection.SelectOnScreen(0, "AcDbPolyline")

выдают ошибку:

Цитировать
File "<COMObject Add>", line 3, in SelectOnScreen
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD', 'Недопустимый аргумент FilterType в SelectOnScreen', 'C:\\Program Files\\AutoCAD\\HELP\\OLE_ERR.CHM', -2145320939, -2147024809), None)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 20-12-2017, 07:55:19
Настоятельно советую изучать справку по VBA - там многое описано:
Код - Visual Basic [Выбрать]
  1. Sub Example_Select()
  2.     ' This example adds members to a selection set, first by crossing and
  3.    ' then by filtering for circles.
  4.    
  5.     ' Create the selection set
  6.    Dim ssetObj As AcadSelectionSet
  7.     Set ssetObj = ThisDrawing.SelectionSets.Add("SSET")
  8.    
  9.     ' Add all object to the selection set that lie within a crossing of (28,17,0) and
  10.    ' (-3.3, -3.6,0)
  11.    Dim mode As Integer
  12.     Dim corner1(0 To 2) As Double
  13.     Dim corner2(0 To 2) As Double
  14.    
  15.     mode = acSelectionSetCrossing
  16.     corner1(0) = 28: corner1(1) = 17: corner1(2) = 0
  17.     corner2(0) = -3.3: corner2(1) = -3.6: corner2(2) = 0
  18.     ssetObj.Select mode, corner1, corner2
  19.    
  20.     ' Add all the Circles to the selection set that lie within the crossing of (28,17,0) and
  21.    ' (-3.3, -3.6,0) by filtering from the current drawing
  22.    Dim gpCode(0) As Integer
  23.     Dim dataValue(0) As Variant
  24.     gpCode(0) = 0
  25.     dataValue(0) = "Circle"
  26.    
  27.     Dim groupCode As Variant, dataCode As Variant
  28.     groupCode = gpCode
  29.     dataCode = dataValue
  30.    
  31.     ssetObj.Select mode, corner1, corner2, groupCode, dataCode
  32.    
  33. End Sub
Тебе нужен последний пример.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 20-12-2017, 17:54:12
Настоятельно советую изучать справку по VBA - там многое описано:

Тебе нужен последний пример.

Насколько я понимаю из VBA, эти gpCode и ataValue(0) - это массивы, в нулевое  значение  которых записываются DXF group code  и значение фильтра соответственно. Когда я пытаюсь то же самое проделать в Python, это не приводит ни к какому  результату, ошибка  та же.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 20-12-2017, 18:04:43
Это не массивы, а Variant'ы, в которые всунуты типовые массивы. Для FilterType - это short (не знаю точно как он обозначатся в Python, но это System.Int16 в .NET), для FilterData это Variant (в данном случае строка "LWPOLYLINE", а не "AcDbPolyline").
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 30-05-2018, 18:17:05
Добрый день!
Требуется начертить график в  определенной пустой области пространства модели автокада, которую я хочу выделить прямоугольником. Хочу сделать диалоговое меню, чтобы выделить эту область.
В данный момент я реализовал это через указание нижней  левой и верхней правой точек с помощью Utility.GetPoint(), для получения крайних координат рамки. Но как-то это не эстетичный метод, возможно ли реализовать это через выделение области прямоугольной рамкой? Стандартное выделение SelectByPolygon, как я понимаю, возвращает только набор объектов, но не координаты.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 30-05-2018, 19:39:17
В данный момент я реализовал это через указание нижней  левой и верхней правой точек с помощью Utility.GetPoint(), для получения крайних координат рамки. Но как-то это не эстетичный метод, возможно ли реализовать это через выделение области прямоугольной рамкой?
Можно. Посмотри в сторону Utility.GetCorner(). Первую точку через Utility.GetPoint(), вторую через Utility.GetCorner().
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 08-06-2018, 16:00:54
Здравстуйте, пытаюсь получить данные из ячейки таблицы используя модуль pywin32.

Код - Python [Выбрать]
  1. tab.GetCellValue(1,1)

Получаю следующую ошибку.

Код - Python [Выбрать]
  1. pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147467263), None)

Смотрю в документацию по функции: Function GetCellValue(row As Long, col As Long)
Т.е. я предполагаю что возможно надо python-овский тип данных int перевести в Long
Как это можно сделать?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-06-2018, 17:01:23
Я не уверен, что проблема в этом, но вроде бы для преобразования в long в Python есть функция long().
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 09-06-2018, 11:54:40
Как я понял long был только в Python 2.
Ещё немного поэкспериментировал:

Код - Python [Выбрать]
  1. >>> tab.GetCellValue([1,1])
  2. TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
  3.  
  4. >>> tab.GetCellValue(1,1,1)
  5. TypeError: GetCellValue() takes from 1 to 3 positional arguments but 4 were given
  6.  
  7. >>> tab.GetCellValue('1','1')
  8. pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147467263), None)
  9.  
  10. >>> win32api.FormatMessage(-2147467263)
  11. 'Не поддерживается\r\n'

Всё таки похоже на ошибку с типами данными как мне кажется.
Вот пример где явно тип данных не верный:

Код - Python [Выбрать]
  1. >>> tab.Move((0,0,0),(1,0,0))
  2. pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147024809), None)
  3.  
  4. >>> win32api.FormatMessage(-2147024809)
  5. 'Параметр задан неверно.\r\n'

Правда код ошибок разный :/
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 09-06-2018, 11:56:37
А если попробовать tab.GetCellValue(1, 1) ?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 09-06-2018, 12:03:10
Пробовал уже Ответ #43 (http://adn-cis.org/forum/index.php?topic=7864.msg32533#msg32533)

Код - Python [Выбрать]
  1. >>> tab.GetCellValue(1, 1)
  2. pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147467263), None)

Попробовал ещё раз, на всякий случай.))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 09-06-2018, 12:09:25
А
Код - Python [Выбрать]
  1. tab.GetCellValue(0, 0)
?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 09-06-2018, 12:12:43
Код - Python [Выбрать]
  1. >>> tab.Rows
  2. 5
  3. >>> tab.Columns
  4. 3
  5. >>> tab.GetCellValue(0, 0)
  6. pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147467263), None)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 11-06-2018, 10:46:42
Можно Ваш Excel файлик?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 11-06-2018, 12:40:16
Попробуйте так, еще можно воспользоваться библиотекой xlrd

Код - Python [Выбрать]
  1. import win32com.client
  2.  
  3. app = win32com.client.Dispatch("Excel.Application")
  4.  
  5. wb = app.Workbooks[0]
  6.  
  7. sh = wb.ActiveSheet
  8.  
  9. val = sh.Cells(1,1).value
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 11-06-2018, 14:53:03
Повтор сообщения.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 11-06-2018, 14:54:17
Пробовал уже Ответ #43

Код - Python [Выбрать]

    >>> tab.GetCellValue(1, 1)
    pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147467263), None)


Попробовал ещё раз, на всякий случай.))

Речь точно идет об автокаде? Если  да, то предложенный вариант obj.GetCellValue(1, 1)  у меня работает.  Ты  точно находишься в нужном пространстве модели/листа, таблица выполнена как  'AcDbTable'  и имеет достаточный диапазон столбцов/строк, в котором находится запрашиваемая ячейка?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Khasan Mamaev от 11-06-2018, 15:08:21
так это таблица Автокада была?)) прошу прощения
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 12-06-2018, 17:23:43
Речь точно идет об автокаде? Если  да, то предложенный вариант obj.GetCellValue(1, 1)  у меня работает.

Спасибо, что проверили у себя.
Я действительно пытаюсь это реализовать не в AutoCAD-е, а в ZWCAD-е, он претендует на подобие первого но имеет много неприятных особенностей (отличий) и это по видимому ещё одно.
Попробую попытать тех. поддержку. ))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 12-06-2018, 17:28:04
Я действительно пытаюсь это реализовать не в AutoCAD-е, а в ZWCAD-е
У нас на форуме категорически не обсуждаются "приложения - подобия"!!!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 12-06-2018, 18:34:25
Хорошо, можете удалить тогда всё.  :-X
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 12-06-2018, 19:13:11
Хорошо, можете удалить тогда всё.  :-X
Я оставлю всю эту дискуссию. Она очень поучительна.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 24-06-2018, 18:46:56
Здравствуйте, коллеги!
Я только начинаю осваивать программирование на Python для AutoCAD.
Помогите, пожалуйста, со следующим вопросом.
Пытаюсь успользовать метод AutoCAD.Application.ActiveDocument.Utility.GetEntity().
Ни как не могу пользоваться им в IronPython.
Получилось только при использовании чистого питона с pywin32.
Правда, если пользователь ничего не выбирает, то всеравно получается ошибка.

Код - Python [Выбрать]
  1. >>> import win32com.client
  2. >>> app = win32com.client.Dispatch("AutoCAD.Application")
  3. >>> a = app.ActiveDocument.Utility.GetEntity(None, None, "Select object.")
  4.  
  5. Traceback (most recent call last):
  6.   File "<pyshell#4>", line 1, in <module>
  7.     a = app.ActiveDocument.Utility.GetEntity(None, None, "Select object.")
  8.   File "<COMObject <unknown>>", line 3, in GetEntity
  9.   File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
  10.     result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
  11. com_error: (-2147352567, '\xce\xf8\xe8\xe1\xea\xe0.', (0, None, None, None, 0, -2147352567), None)

Хотелось бы программировать на IronPython, поскольку им я пользуюсь для Revit.

В документации сказано, что GetEntity принимает три параметра: объект (как я понимаю, класса AcadObject, массив и строку.)

Как сформировать объект для передачи в метод???
При попытке создать объект "руками" появляется сообщение, что это не возможно т.к. класс AcadObject абстрактный класс. Что это такое я пока не понимаю. Может быть есть метод, который формирует такой объект?

Заранее благодарю за ответы,
Георгий
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-06-2018, 19:59:02
Пытаюсь успользовать метод AutoCAD.Application.ActiveDocument.Utility.GetEntity().
Ни как не могу пользоваться им в IronPython.
Обязательно с ним? А почему не подходит Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.GetEntity() ?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 24-06-2018, 23:20:12
Я подключаюсь к Autocad следующим образом.
Код - Python [Выбрать]
  1. app = System.Runtime.InteropServices.Marshal.GetActiveObject("Autocad.Application")

Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.GetEntity() у меня не видно. Речь идет о другом способе взаимодействия с AutoCAD?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-06-2018, 23:21:36
Я подключаюсь к Autocad следующим образом.
Подключаешься изнутри AutoCAD или снаружи? Если снаружи, то предложенный мной способ недоступен.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 25-06-2018, 00:07:37
Да, я подключаюсь снаружи.

А изнутри, это надо скомилировать код и netload делать?
Есть референс по классам, доступным изнутри?

Еще может быть кто-то питоновую консоль сделал, которая изнутри подключается?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-06-2018, 00:11:52
А изнутри, это надо скомилировать код и netload делать?
Нет. Компилировать ничего не нужно. Точнее создаётся C#-сборка, которая позволяет загрузить и выполнить python'овский-код.
Посмотри эти две темы:
http://through-the-interface.typepad.com/through_the_interface/2009/03/using-ironpython-with-autocad.html
http://through-the-interface.typepad.com/through_the_interface/2009/12/command-line-scripting-of-ironpython-code-in-autocad.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-06-2018, 00:37:35
Есть референс по классам, доступным изнутри?
Это всё в документации ObjectARX SDK, а в онлайне здесь: https://help.autodesk.com/view/OARX/2019/ENU/?guid=OREFNET-What_s_New
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 25-06-2018, 00:43:32
Спасибо! Буду изучать. :)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-06-2018, 00:54:25
Я приложил файлы к уроку на AU 2009 про использование IronPython с AutoCAD. Могут быть полезны.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 05-07-2018, 10:11:00
Всем доброго времени суток,
Такой вопрос: как можно вывести, что-нибудь в командную строку, типа: код отработан без ошибок, результат такой-то?
На этот раз речь конечно же идёт о ZWAutoCAD.))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 05-07-2018, 11:19:13
На этот раз речь конечно же идёт о ZWAutoCAD.))
Если это шутка, то неудачная.
Такой вопрос: как можно вывести, что-нибудь в командную строку, типа: код отработан без ошибок, результат такой-то?
Код - Python [Выбрать]
  1. Utility.Prompt("код отработан без ошибок, результат такой-то")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Randum от 05-07-2018, 12:55:15
Спасибо Александр, помогло.
На первых порах тяжело идёт, час гуглишь, пишешь строчку кода, ещё час гуглишь, пишешь другую строчку кода и т.д.))
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 08-07-2018, 12:43:17
Добрый день!
У меня такой вопрос.
Можно ли компилировать скрипт на ironpython в библиотеку
и подгружать ее для выполнения к c# с помощью каких-либо средств импорта?
(далее плагин на c# с подключенной библиотекой запускать в autocad.)

Примерно так работают макросы в Revit, на сколько я понимаю.

Хотелось бы получить несколько сборок, которые бы работали на других машинах без установленного питона.

Прошу прощения, если чего-то не понимаю.


В документации к ironpython сказано:
Accessing Python code from other .NET code
Statically-typed languages like C# and VB.Net can be compiled into an assembly that can then be used by other .NET code. However, IronPython code is executed dynamically using ipy.exe. If you want to run Python code from other .NET code, there are a number of ways of doing it.

Меня интересует:
Compiling Python code into an assembly
The pyc sample can be used to compile IronPython code into an assembly. The sample builds on top of clr-CompileModules. The assembly can then be loaded and executed using Python-ImportModule. However, note that the MSIL in the assembly is not CLS-compliant and cannot be directly accessed from other .NET languages.
Но более подробной документации найти не могу. Что это за "Python-ImportModule" и как он работает?

Благодарю за ответы.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2018, 14:40:48
Самое главное в этом тексте вот это:
However, note that the MSIL in the assembly is not CLS-compliant and cannot be directly accessed from other .NET languages.
Т.е. эту сборку в AutoCAD загрузить будет нельзя. Так что в компиляции теряется весь смысл.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 08-07-2018, 14:46:17
Идея в том, чтобы загрузить в автокад сборку на c#, которая загрузит другую сборку на ironpython специальным образом.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2018, 14:51:15
Идея в том, чтобы загрузить в автокад сборку на c#, которая загрузит другую сборку на ironpython.
Мне непонятно зачем это всё нужно. Есть традиционные способы работы с AutoCAD API. Если уж смогли сделать сборку на C#, то зачем Python нужен?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 08-07-2018, 15:02:40
Вопрос в том, можно ли загружать из c# не скрипты на питоне с помощью скриптинджин а скомпилированные dll на питоне. Просто интересно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2018, 15:09:03
Вопрос в том, можно ли загружать из c# не скрипты на питоне с помощью скриптинджин а скомпилированные dll на питоне. Просто интересно.
Я вижу как можно создать exe-файл на IronPython: https://habr.com/post/149621/
Но это совсем не то, что нужно для получения нормальной .NET сборки, которую можно было загрузить в AutoCAD.
Я нигде не нашел информации о том, что можно из (Iron)Python скомпилировать нормальную .NET сборку, т.е. компиляторов как для C#/VB.NET судя по всему не существует. И соответственно это тупиковая ветка. Python хорош именно как скриптовый язык.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 08-07-2018, 15:21:31
Понятно.
Однако в Revit при создание макроса на ironpython запускается интегрированный SharpDevelop IDE, которая компилирует макрос в dll(он это умеет делать.) И макрос работает как библиотека классов dll.
Интересно, как это работает.
В случае с автокадом нельзя напрямую это делать т.к. питон не поддерживает атрибуты.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2018, 15:24:12
Однако в Revit при создание макроса на ironpython запускается интегрированный SharpDevelop IDE, которая компилирует макрос в dll(он это умеет делать.)
Попробуй на SharpDevelop IDE скомпилировать макрос для AutoCAD и посмотри что получится.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2018, 15:35:59
В случае с автокадом нельзя напрямую это делать т.к. питон не поддерживает атрибуты.
Атрибуты методов и классов? Т.е. стандартными методами нельзя определить команду. Тогда можно нестандартными:
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.Internal.Utils.AddCommand("GroupName", "MyGlobalCommand", "MyLocalCommand", CommandFlags.UsePickSet | CommandFlags.Redraw, MyCommandHandler);
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 09-07-2018, 11:09:19
Попробовал собрать dll сборку на питоне в sharpdevelop. Все откомпилировалось и загрузилось в автокад. Но ничего не происходит.
Метод Initialize() не работает.

Вот код.

Код - Python [Выбрать]
  1. import clr
  2. clr.AddReferenceToFileAndPath("C:\\ObjectARX 2015\\inc\\AcCoreMgd.dll")
  3. clr.AddReferenceToFileAndPath("C:\\ObjectARX 2015\\inc\\AcDbMgd.dll")
  4. clr.AddReferenceToFileAndPath("C:\\ObjectARX 2015\\inc\\AcMgd.dll")
  5.  
  6. clr.AddReference("System.Windows.Forms")
  7.  
  8. import System.Windows.Forms
  9. import Autodesk.AutoCAD.Runtime
  10.  
  11. from System.Windows.Forms import *
  12. from Autodesk.AutoCAD.Runtime import *
  13.  
  14. class Commands(IExtensionApplication):
  15.     def Initialize():
  16.         MessageBox.Show("Hello!")
  17.    
  18.     def Terminate():
  19.         MessageBox.Show("Goodbye!")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 09-07-2018, 12:15:36
Выложи сборку, которую ты получил. Посмотрю на неё.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Archigeo от 09-07-2018, 12:22:30
Выкладываю сборку
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 09-07-2018, 12:30:32
Выкладываю сборку
Понятно. Ничего не получится. Результат компиляции такой, что не совпадает ни имя класса, ни имя метода, который AutoCAD должен при загрузке этой сборки найти...
(https://farm2.staticflickr.com/1767/43294796831_e1702d7028_o.png)

Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 13-08-2018, 19:57:38
Вопрос: как можно запустить комманду Акада, например "_regenall", из пайтона?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-08-2018, 20:02:50
Вопрос: как можно запустить комманду Акада, например "_regenall", из пайтона?
Если черед COM, то AcadDocument.SendCommand("_regenall ") (обрати внимание на пробел после имени команды).
А если через .NET, то Document.SendStringToExecute("_regenall ")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 15-08-2018, 16:21:17
Если черед COM, то AcadDocument.SendCommand("_regenall ") (обрати внимание на пробел после имени команды).
А если через .NET, то Document.SendStringToExecute("_regenall ")

Спасибо. Использую через pythoncom.
А если допустим я запустил команду "_purge ", появляется меню автокада с возможностью выбора кнопок "Удалить"  "Удалить все"  "Закрыть"  "Справка". Есть ли программная возможность командами выбрать например кнопку "Удалить все", и в  новом открывшемся меню "Удалить все элементы"? Или это невозможно через COM.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 15-08-2018, 21:28:08
Вместо "_purge" попробуй "_-purge". Дальше смотри в командной строке.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 16-08-2018, 08:42:16
Многие команды в AutoCAD имеют вариант работы через ком.строку - достаточно перед именем поставить "-".
Кстати, если хочешь, чтобы командные методы работали в любой локализации AutoCAD, посмотри http://autolisp.ru/2010/03/04/localization/
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 22-08-2018, 16:58:51
Еще вопрос.
В меню "Поле" (ctrl+F)  Автокада при создании и редактировании формул есть возможность указать мышью ссылку на ячейку, даже ячейку другой таблицы, при этом возвращается адрес столба и строки указанной ячейки. Что за метод используется при этом? Ведь при обычном выделении возвращается только выделенная таблица целиком, а не ее ячейка.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 22-08-2018, 17:08:28
Попробуй использовать HitTest (кажется, так называется)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-08-2018, 17:12:34
Что за метод используется при этом?
В COM для этой цели есть только один метод: HitTest.
Описание метода здесь: http://help.autodesk.com/view/OARX/2018/ENU/?guid=GUID-8812BEE2-BD9F-488D-BAA1-A38060FA4D86
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 23-08-2018, 18:37:34
Честно говоря, даже не могу сообразить, как реализовать такой hittest средствами Python, возникает проблема с аргументами функции.

Возможно ли вызвать этот hittest текстовой командой в меню Автокада? по типу _purge или _regenall.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-08-2018, 18:39:51
Возможно ли вызвать этот hittest текстовой командой в меню Автокада? по типу _purge или _regenall.
Нет.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 26-08-2018, 17:20:44
Нет.

Ok, тогда у меня вопрос скорее по документации к HitTest (http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-8812BEE2-BD9F-488D-BAA1-A38060FA4D86).
Я правильно понимаю, что нужно каким-то способом инициализировать переменные wpt, wviewVec, resultRowIndex, resultColumnIndex, передать их в качестве  аргументов функции object.HitTest(), и если нажатие  было произведено по таблице, функция возвращает True, а  двум последним переменным назаначаются индексы строки и столбца?

Я попробовал с помощью этого кода:

Код - Python [Выбрать]
  1. resultRowIndex = 0
  2. resultColumnIndex = 0
  3.  
  4. py_coord = [0,0,0]
  5. wpt = win32com.client.VARIANT(VT_ARRAY | VT_I4, py_coord)
  6.  
  7. py_vector = [0, 0, 0]
  8. wviewVec = win32com.client.VARIANT(VT_ARRAY | VT_I4, py_vector)
  9.  
  10. if obj.HitTest(wpt, wviewVec, resultRowIndex, resultColumnIndex):
  11.     print(resultRowIndex, resultColumnIndex)

возвращает ошибку:

Цитировать
if obj.HitTest(wpt, wviewVec, resultRowIndex, resultColumnIndex):
  File "<COMObject <unknown>>", line 3, in HitTest
  File "C:\ProgramData\Anaconda64\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
    result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147024809), None)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 26-08-2018, 17:27:41
А как в Python передаются out-параметры?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 26-08-2018, 17:40:25
А как в Python передаются out-параметры?

Ок, я  подкорректировал код, я так понимаю, при работе через Python все выходные параметры HitTest выдаются в виде кортежа (неизменяемого списка):

Цитировать
resultRowIndex = 1
resultColumnIndex = 1

py_coord = [0,0,0]
wpt = win32com.client.VARIANT(VT_ARRAY | VT_R8, py_coord)

py_vector = [0, 0, 0]
wviewVec = win32com.client.VARIANT(VT_ARRAY | VT_R8, py_vector)

print(obj.HitTest(wpt, wviewVec))

Теперь результат вывода на экран:

Цитировать
(False, -1, -1)

Не могу понять, какие нужно подобрать wpt, wviewVec, чтобы функция возвращала True.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 27-08-2018, 08:02:09
На dwg.ru были примеры использования HitTest (правда, на лиспе).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-08-2018, 08:27:30
На dwg.ru были примеры использования HitTest (правда, на лиспе).

Как ни странно, после прочтения примеров LIPS на том сайте, этот вариант у меня сработал  :D

Код - Python [Выбрать]
  1. py_vector = [0.0, 0.0, 1.0]
  2. wviewVec = win32com.client.VARIANT(VT_ARRAY | VT_R8, py_vector)
  3. result = obj.HitTest(cc(aDoc.Utility.GetPoint()), wviewVec)
  4. print(result)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 03-09-2018, 19:43:52
Вопрос: как можно изменить стиль строк с "Данные" на "Заголовок" или "Название" (чтобы  эти строки повторялись при разбиении таблицы).

Т.е. у меня получилось изменить стиль  ячейки (2,2)  через MyTab.SetCellStyle(2, 2, '_Header'). Но тогда стиль ячейки меняется на "Заголовок", а стиль строки по-прежнему "Данные".

Я нашел метод object.GetRowType(row), который возвращает стиль заданной строки. Но с его помощью не получается изменить  значение стиля строки.  Если  ли обратный метод типа  SetRowType?   Ни во встроенной справке, ни через поиск в гугле, ни на dwg.ru форуме  не могу найти.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 03-09-2018, 19:57:07
Т.е. у меня получилось изменить стиль  ячейки (2,2)  через MyTab.SetCellStyle(2, 2, '_Header'). Но тогда стиль ячейки меняется на "Заголовок", а стиль строки по-прежнему "Данные".
Читаем внимательно документацию для метода Table.SetCellStyle:
Цитировать
Notes
To specify cell pass a valid row and column indices; to specify row pass a valid row index and pass -1 as column index; to specify column pass a valid column index and pass -1 as row index.
Перевод нужен или так понятно?
 
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 04-09-2018, 17:14:27
Перевод нужен или так понятно?

Нет, перевод не нужен, с английским на этом уровне проблем нет. Проблема решена.
 
Но в онлайн справке, что я находил через гугл в разделе SetCellStyle Method (ActiveX) (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-ActiveX/files/GUID-2E9EE0DD-31AB-41BC-8ABF-B3ECB549E657-htm.html)   этого пункта notes  нет (или я его в  упор не замечаю?), в моей встроенной chm справке его нет тем более.


Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-09-2018, 17:32:24
Но в онлайн справке, что я находил через гугл в разделе SetCellStyle Method (ActiveX)   этого пункта notes  нет (или я его в  упор не замечаю?), в моей встроенной chm справке его нет тем более.
Посмотри здесь: http://help.autodesk.com/view/OARX/2018/ENU/?guid=OREFNET-Autodesk_AutoCAD_DatabaseServices_TableContent_SetCellStyle_int_int_string
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Aleksey от 11-09-2018, 10:24:49
Подскажите пожалуйста! Как выбрать вхождение блока по имени и считать значение его атрибута (например блок "РАМКА", атрибут PAGE). Пробывал через Blocks.Item, но это не то :o
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 11-09-2018, 10:50:31
У блока может быть несколько вхождений, и при этом не только в пространство модели / листа. Если нужно выбрать вообще все, то лучше будет пройтись по таблице блоков и внутри каждого блока выполнять поиск соответствующих элементов. Если же надо по какому-то пространству, то см.в сторону фильтров в SelectionSet
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 30-01-2019, 16:06:15
У меня тоже вопрос по блокам.
Допустим, я в своем скрипте по очереди выделяю текстовые  объекты и аттрибуты  с помощью GetEntity.
Но среди объектов на чертеже у меня попадается блок вроде этого с текстовыми аттрибутами внутри:

(https://i.postimg.cc/4Hg45ds7/image.jpg) (https://postimg.cc/4Hg45ds7)

если я просто щелкну по его текстовому аттрибуту, GetEntity вернет мне только точку и сам блок в целом. Можно ли как-то таким щелчком сразу получить доступ к текстовому аттрибуту  блока (например, цифре "1") без расчленения самого блока?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 30-01-2019, 16:23:00
Можно ли как-то таким щелчком сразу получить доступ к текстовому аттрибуту  блока (например, цифре "1") без расчленения самого блока?
Можно. Используй GetSubEntity.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 30-01-2019, 16:24:04
Можно, почему нет? Если действительно ткнули на атрибут - см. GetSubEntity. Если нужен доступ к атрибуту со строго определенным тэгом - то получать атрибуты вхождения блока (GetAttributes и GetConstantAttributes) и фильтровать по тэгу.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMA от 19-02-2019, 13:21:21
Подскажите, при данном варианте работы макроса Питона с Автокадом (как в 1-ом ролике: запуск внешнего файла) время срабатывания макроса примерно секунд 5. Это нормально? Или мне настройки покрутить стоит? Такое время ожидания не сильно комфортно при работе...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 21-02-2019, 07:09:14
Задавал тут вопрос, но как то все само собой решилось. Не хотел питон рисовать в пустом документе, зато без проблем нарисовал в одном из рабочих чертежей. Как удалить сообщение не нашел.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 21-02-2019, 12:02:04
Задавал тут вопрос, но как то все само собой решилось. Не хотел питон рисовать в пустом документе, зато без проблем нарисовал в одном из рабочих чертежей. Как удалить сообщение не нашел.
1. Приветствую на форуме!
2. У нас на форуме не удаляют сообщения. Представьте себе, что задан вопрос и кто-то знает и пишет ответ на этот вопрос, а вопроса уже нет...
3. Рад, что вопрос решился, но думаю неплохо было бы исследовать почему не получалось в пустом документе.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 21-02-2019, 12:12:06
По 3 му пункту, согласен, было бы неплохо исследовать этот вопрос. По началу грешил на то что питон 32бит, а автокад64. Потом думал что может версия автокада не та. Потом попробовал с библиотекой pyautocad провести манипуляции, эффект тот же. Причем Эта библиотека возвращала название документа(Чертеж 1). Меня еще больше удивило когда она возвратила название документа при закрытом автокаде, тот же чертеж 1.
Сейчас для того что бы написать этот ответ, провел еще несколько экспериментов, и что библиотека pyautocad, что доступ напрямую через API, нормально отрисовывают элементы.
Даже и не знаю в чем была проблема.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 21-02-2019, 12:14:38
По 3 му пункту, согласен
А по первому и второму? ;)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 21-02-2019, 12:22:30
ОК.
Просто воспринимал этот форум как информационный ресурс, а не как площадку для общения. Поэтому пытался быть краток)) Но если вы не возражаете, то
1. Конечно же здравствуйте, и спасибо за форум и эту тему. В общем то начальное видео в этой теме меня побудило к изучению питона
2. То же согласен. На иных форумах такое наблюдал. Но так же видел и такое, что разрешено удалять и редактировать последнее сообщение, если после него не было сообщений.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 26-02-2019, 19:14:07
По 3 му пункту, согласен, было бы неплохо исследовать этот вопрос. По началу грешил на то что питон 32бит, а автокад64. Потом думал что может версия автокада не та. Потом попробовал с библиотекой pyautocad провести манипуляции, эффект тот же. Причем Эта библиотека возвращала название документа(Чертеж 1). Меня еще больше удивило когда она возвратила название документа при закрытом автокаде, тот же чертеж 1.

У меня наблюдался наверно похожий глюк с win32com библиотекой, когда она выдавала, что автокад или ворд запущены (хотя соответствующие программы были закрыты), при этом в списке процессов в системе действительно висели невидимые процессы с  именами AutoCAD Application или Word. Так и не понял, чем это вызвано.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-02-2019, 20:44:24
По 3 му пункту, согласен, было бы неплохо исследовать этот вопрос. По началу грешил на то что питон 32бит, а автокад64. Потом думал что может версия автокада не та. Потом попробовал с библиотекой pyautocad провести манипуляции, эффект тот же. Причем Эта библиотека возвращала название документа(Чертеж 1). Меня еще больше удивило когда она возвратила название документа при закрытом автокаде, тот же чертеж 1.

У меня наблюдался наверно похожий глюк с win32com библиотекой, когда она выдавала, что автокад или ворд запущены (хотя соответствующие программы были закрыты), при этом в списке процессов в системе действительно висели невидимые процессы с  именами AutoCAD Application или Word. Так и не понял, чем это вызвано.
Ну тут всё просто. Приложение не закрылось корректно. При этом они уже не в состоянии отвечать на COM-запросы.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 04-04-2019, 13:54:18
Коллеги, прошу помощи.
Пишу на питоне код, с помощью которого, хочу собрать значения атрибутов блоков. По аналогии с VBA пытаюсь сделать это с помощью метода GetAttributes, но в ответ получаю ошибку:

Код - Python [Выбрать]
  1. atrr,_ = blk.GetAttributes()
  2.  
  3. ---------------------------------------------------------------------------
  4. KeyError                                  Traceback (most recent call last)
  5. <ipython-input-14-b127d596e8c4> in <module>
  6. ----> 1 atrr,_ = blk.GetAttributes()
  7.  
  8. D:\Programs\lib\site-packages\comtypes\automation.py in __ctypes_from_outparam__(self)
  9.     504     def __ctypes_from_outparam__(self):
  10.     505         # XXX Manual resource management, because of the VARIANT bug:
  11. --> 506         result = self.value
  12.     507         self.value = None
  13.     508         return result
  14.  
  15. D:\Programs\lib\site-packages\comtypes\automation.py in _get_value(self, dynamic)
  16.     455             return value
  17.     456         elif self.vt & VT_ARRAY:
  18. --> 457             typ = _vartype_to_ctype[self.vt & ~VT_ARRAY]
  19.     458             return cast(self._.pparray, _midlSAFEARRAY(typ)).unpack()
  20.     459         else:
  21.  
  22. KeyError: 9
  23.  
  24.  

Кто нибудь может подсказать, как справиться с ошибкой, либо как по-другому собрать значения атрибутов блоков
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2019, 13:58:24
DMuzer,
Посмотри этот код: https://gist.github.com/thengineer/7157510
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 04-04-2019, 14:02:32
DMuzer,
Посмотри этот код: https://gist.github.com/thengineer/7157510

Спасибо!
Это работает.
А не в курсе, с чем связана ошибка? Это Автокад не стыкуется с питоном, или я что то неправльно делаю?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2019, 14:05:05
А не в курсе, с чем связана ошибка? Это Автокад не стыкуется с питоном, или я что то неправльно делаю?
Я же не вижу всего кода, не знаю что такое blk, не знаю есть ли у этой вставки блока атрибуты... Так что затрудняюсь сказать. Но если код, по ссылке которую я дал, работает нормально, то скорее всего это проблема твоего кода.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 04-04-2019, 14:14:17
Привожу весь код.
В  другие операции с объектом выполняются без проблем. Хочется разобраться, т.к. хотелось бы работать через comtypes, потому что я работаю в Jupyter notebook. А при использовании этой библиотекой в интерактивном режиме доступны методы и свойства объектов, это сильно упрощается работу и не нужно каждый раз в справку смотреть.

Код - Python [Выбрать]
  1. import array
  2. import comtypes.client
  3. import comtypes
  4.  
  5. app = comtypes.client.GetActiveObject('AutoCAD.Application')
  6. thisdrawing = app.ActiveDocument
  7.  
  8. blk,_ = thisdrawing.Utility.GetEntity()
  9. print(type(blk))
  10. blk.GetAttributes()
  11.  

Код - Python [Выбрать]
  1. <class 'comtypes.POINTER(IAcadBlockReference)'>
  2.  
  3. ---------------------------------------------------------------------------
  4. KeyError                                  Traceback (most recent call last)
  5. <ipython-input-37-8c74b912e4fb> in <module>
  6.       8 blk,_ = thisdrawing.Utility.GetEntity()
  7.       9 print(type(blk))
  8. ---> 10 blk.GetAttributes()
  9.  
  10. D:\Programs\lib\site-packages\comtypes\automation.py in __ctypes_from_outparam__(self)
  11.     504     def __ctypes_from_outparam__(self):
  12.     505         # XXX Manual resource management, because of the VARIANT bug:
  13. --> 506         result = self.value
  14.     507         self.value = None
  15.     508         return result
  16.  
  17. D:\Programs\lib\site-packages\comtypes\automation.py in _get_value(self, dynamic)
  18.     455             return value
  19.     456         elif self.vt & VT_ARRAY:
  20. --> 457             typ = _vartype_to_ctype[self.vt & ~VT_ARRAY]
  21.     458             return cast(self._.pparray, _midlSAFEARRAY(typ)).unpack()
  22.     459         else:
  23.  
  24. KeyError: 9
  25.  
  26.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2019, 14:22:38
А что даёт:
Код - Python [Выбрать]
  1. HasAttributes = blk.HasAttributes
?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 04-04-2019, 14:28:04
Возвращает True, атрибуты у этого блока есть.
Может это связано что это динамический блок.



привожу код и вывод:
Код - Python [Выбрать]
  1. import array
  2. import comtypes.client
  3. import comtypes
  4.  
  5. app = comtypes.client.GetActiveObject('AutoCAD.Application')
  6. thisdrawing = app.ActiveDocument
  7.  
  8. # blk,_ = thisdrawing.Utility.GetEntity()
  9. blk = thisdrawing.HandleToObject('332A')
  10. print(blk.Handle)
  11. print(f'Наличие атрибутов у блока: {blk.HasAttributes}')
  12. blk.GetAttributes()
  13.  

332A
Наличие атрибутов у блока: True

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-45-72048c5e4e02> in <module>
     10 print(blk.Handle)
     11 print(f'Наличие атрибутов у блока: {blk.HasAttributes}')
---> 12 blk.GetAttributes()

D:\Programs\lib\site-packages\comtypes\automation.py in __ctypes_from_outparam__(self)
    504     def __ctypes_from_outparam__(self):
    505         # XXX Manual resource management, because of the VARIANT bug:
--> 506         result = self.value
    507         self.value = None
    508         return result

D:\Programs\lib\site-packages\comtypes\automation.py in _get_value(self, dynamic)
    455             return value
    456         elif self.vt & VT_ARRAY:
--> 457             typ = _vartype_to_ctype[self.vt & ~VT_ARRAY]
    458             return cast(self._.pparray, _midlSAFEARRAY(typ)).unpack()
    459         else:

KeyError: 9


Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2019, 14:31:58
Может это связано что это динамический блок.
Нет. Это уж точно тут не причем. Если этот же код с этим же блоком у тебя сработает в VBA, то тогда это проблема Python'а.
Особенно интересно вот это:
Цитировать
# XXX Manual resource management, because of the VARIANT bug:
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 04-04-2019, 14:37:27
А может быть это связано с недоработками в библиотеке comtypes?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2019, 14:38:53
А может быть это связано с недоработками в библиотеке comtypes?
Вполне возможно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 24-04-2019, 06:45:30
А кто может подсказать как из питона 3.7 работать с цветами.
В букваре есть такой пример:
 
Код - vb.net [Выбрать]
  1.     Dim color As AcadAcCmColor
  2.         Set color = AcadApplication.GetInterfaceObject("AutoCAD.AcCmColor.16")
  3.     Call color.SetRGB(80, 100, 244)
  4.     layerObj.TrueColor = color

С вижуал бейсиком совсем не знаком, но на сколько понимаю переменная color должна стать каким то специальным автокадовским типом. У меня же не получается запустить подобную конструкцию.

Код - Python [Выбрать]
  1. app = win32com.client.Dispatch("AutoCAD.Application")
  2. color = app.GetInterfaceObject("AutoCAD.AcCmColor.16")

Пробовал и попроще:

Код - Python [Выбрать]
  1. lay.TrueColor = 'Зеленый'
  2. lay.TrueColor = 'Green'
  3. lay.TrueColor=(80,100,244)
  4.  
  5. color = convert_coordinates(80,100,244)
  6. lay.TrueColor=color

И то же ничего не получается. Если кто знает как с цветами работать, подскажите пожалуйста
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 24-04-2019, 15:10:13
Разобрался.
Для 15го автокада нужно указывать "AutoCAD.AcCmColor.20". В остальном все работает по букварю
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 05-05-2019, 21:47:19
Подскажите, как в Python использовать функции с необязательными параметрами? Например, Utiliy.GetPoint(Point, Prompt) имеет два параметра, и мне хотелось-бы не указывать Point, но использовать Prompt. Вариант Utility.GetPoint(None, "Сообщение") вызывает ошибку.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 05-05-2019, 22:18:51
Вариант Utility.GetPoint(None, "Сообщение") вызывает ошибку.
А так: Utility.GetPoint("Сообщение") ?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 05-05-2019, 23:29:35
Пробовал, тоже не работает. Работает только совсем без аргументов.

Выдает такое вот сообщение об ошибке

return self.aDoc.Utility.GetPoint(Msg)
  File "<COMObject <unknown>>", line 3, in GetPoint
  File "C:\Program Files (x86)\Python37-32\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
    result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD', 'Недопустимый аргумент Point в GetPoint', 'C:\\Program Files\\Autodesk\\AutoCAD 2019\\HELP\\OLE_ERR.CHM', -2145320939, -2147024809), None)

Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 05-05-2019, 23:35:33
Ну тогда что-нибудь типа Utility.GetPoint(pythoncom.Empty,"Сообщение") или Utility.GetPoint(pythoncom.Missing,"Сообщение")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 06-05-2019, 15:04:36
Спасибо. С pythoncom.Empty все отлично работает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-05-2019, 15:44:14
Спасибо. С pythoncom.Empty все отлично работает.
Отлично. Не имея возможности проверить я интуитивно догадался, что именно может помочь. Так как использование Python для AutoCAD мягко говоря не очень распространено и не поддерживается Autodesk, то поиск решений таких казалось бы простых задач очень усложнён.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 07-05-2019, 11:16:05
Примерно месяц занимаюсь изучением Python и его применением в AutoCad. Все выглядит не так сложно, даже для непрофессионального программиста. Для меня приемущества Python над LISP перевешивают неудобства связи AutoCad со сторонним приложением. Также я никогда не писал ничего с помощью ObjectARX, но есть несколько идей. Я правильно понимаю, что смогу написать модуль на С++ с использованием ObjectARX и потом им пользоваться в программе на Python?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 07-05-2019, 11:19:33
Я правильно понимаю, что смогу написать модуль на С++ с использованием ObjectARX и потом им пользоваться в программе на Python?
Я не понимаю к чему такие сложности. Для того, чтобы писать для AutoCAD непрофессиональному программисту оптимально использовать AutoCAD .NET API (C# или VB.NET) . Он позволяет делать большинство из того, что можно сделать при помощи ObjectARX и обладает огромным количеством примеров (большинство из них на C#).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 07-05-2019, 20:51:04
Дело в том, что я особо не разбирался с C#, т.к. я не программист, а проектировщик, мне показалось, что в любом случае не буду использовать все его приемущества, а со всеми недостатками придется иметь дело. Python меня привлек простотой изучения, наличием всевозможных плюшек, облегчающих процесс написания программ - динамическая типизация, динамические массивы, множество готовых функций для работы со строками и списками и тд. Также иногда делюсь своими наработками с коллегами и при использовании AutoLisp или Python не надо задумываться над совместимостью с разными версиями AutoCad. Пробовал также VBA, но не пошло.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 07-05-2019, 22:55:35
SilverWork,
Еще раз.
1) Python не поддерживается Autodesk для AutoCAD.
2) Примеров использования Python с AutoCAD очень мало. Во всяком слуачае по сравнению с VisualLisp/VBA/C#/C++
3) Непрограммисту (да и программисту) разбираться с тонкостями использования COM через Python в AutoCAD очень проблематично.
Так что всё на свой страх и риск.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 08-05-2019, 11:25:10
Ну мы находимся в теме  Python & ActiveX/COM Autocad, следовательно она для тех, кто хочет разобраться в этих тонкостях. Да, конечно, есть свои плюсы и минусы. Все зависит от конкретной задачи. В моем случае не требуется много взаимодействовать с Autocad. Приложение собирает какие-то данные из чертежа (атрибуты блоков, значения из таблиц, длины линий и тд), потом внутри себя из обрабатывает и выдает результат обратно в Autocad в нужном мне виде (расчеты, таблицы, рисует каки-либо примитивы). И основная часть работы - это и есть обработка данных и в этом у Python есть преимущества, остается только написать интерфейс взаимодействия с Autocad, что вызывает трудности, но не смертельно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 10-05-2019, 21:37:35
Столкнулся с проблемой, что очень медленно осуществляется взаимодействие программы с Autocad. Например, получение атрибутов сотни блоков занимает секунд 10-15, рисование объектов также заметно медленнее, чем через AutoLisp. Есть способы исправить это или это особенности работы через COM?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-05-2019, 22:22:29
Есть способы исправить это или это особенности работы через COM?
COM между процессами приводит к таким задержкам. Особенно если эти процессы разной разрядности (32/64).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 17-05-2019, 16:46:23
Есть способы исправить это или это особенности работы через COM?
Для ускорения нужно максимально пользоваться средствами самого када, например select с фильтрами вместо select + перебор, и т.п. Но работа через COM будет всегда несколько медленной, хотя для большинства инженерных задач и достаточной.
Передача через COM каду данных и параметров с преобразованием к нужному типу - отдельная головная боль, но это больше камень в огород com библиотек питона.
Организовать запуск команды на питоне из када - тоже квест. Решаемый, но я нашёл путь только через жуткие костыли.
Питон удобно использовать, если нужно вывести результаты расчётов или построений в кад и получить dwg. Плотно работать с кадом можно, но не совсем удобно.
К сожалению, на данный момент с точки зрения Autodesk в их продуктах нет места не .net языкам и питону в частности. В автокад - только через COM, который непонятно сколько ещё проживёт. В ревите реализована только поддержка .net  вариации питона версии 2, и переход на третью ветку даже в перспективе не виден.
Если нужно плотно программировать под продукты Autodesk, лучше выбрать C#. Порог входа чуть выше, но потенциальных проблем намного меньше.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: SilverWork от 17-05-2019, 17:22:26
Тут будет небольшой оффтоп. Я поразбирался с C# и вроде все выглядит не сложно, но один момент меня смущает - это отладка кода. С лиспом и питоном все ясно: запустил, увидел косяки, исправил, повторил... и так хоть 100 раз. В случае с C#, как я понимаю, придется после каждой попытки перезагружать AutoCad, т.к. нет возможности выгрузить dll. Пытался поискать на форумах, также здесь была тема о выгрузке, но, как я понял, способ не простой и не всегда работает. Хочется сразу писать на том, что будет работать хорош и быстро, но вот процесс отладки кода меня, скажем прямо, пугает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 17-05-2019, 17:38:59
Off-Topic: показать
Такая же беда... Ну что, написал лиспик для автозагрузки библиотеки - и вперед, с песнями ;)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 17-05-2019, 20:58:48
Хочется сразу писать на том, что будет работать хорош и быстро, но вот процесс отладки кода меня, скажем прямо, пугает.
Не пугайся. Все так делают. Нужно писать максимально чистый код сразу - это сократит количество запусков AutoCAD для отладки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 19-05-2019, 22:51:20
Это если есть понимание, что и как работает. А вот если его нет или оно вызывает сомнения...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 08-06-2019, 11:56:38
Добрый день!
Подскажите, как обработать события автокада из python.
Есть ли подходящие примеры?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-06-2019, 16:22:16
Есть ли подходящие примеры?
Примеров нет. Во всяком случае мне они не известны. Так что пробуй делать по аналогии с Word/Excel:
https://win32com.goermezer.de/microsoft/ms-office/events-in-microsoft-word-and-excel.html
Подписка на события происходит через win32com.client.DispatchWithEvents
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 08-06-2019, 17:10:13
Спасибо, попробую!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 11-07-2019, 13:23:40
Допустим, у меня активирован режим объектной привязки, а конкретно "конточка", "центр", "узел", для удобства выделения объектов на чертеже я программно деактивирую на время привязку с помощью:

Код - Python [Выбрать]
  1. aDoc.ObjectSnapMode = False

Но когда потом я программно пытаюсь восстановить привязку, установив этому свойству значение True, режим привязки не активируется, все поставленные галочки типа  "конточка", "центр", "узел" пропадают. Есть ли способ получить доступ к настройкам привязки и активировать их программно? Либо как вариант, эмулировать нажатие F3 с клавиатуры. Не могу найти этот момент в документации.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 11-07-2019, 13:27:26
Есть ли способ получить доступ к настройкам привязки и активировать их программно?
Это системная переменная OSMODE: https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/AutoCAD-Core/files/GUID-DD9B3216-A533-4D47-95D8-7585F738FD75-htm.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 11-07-2019, 14:07:37
Попробуй получить системную переменную osmode, и работать с ней.
Не увидел предыдущего ответа...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 11-07-2019, 18:22:23
Спасибо!
Сочетание GetVariable и SetVariable с этой системной переменной - то, что мне было нужно.

Код - Python [Выбрать]
  1. OSMODE = aDoc.GetVariable('OSMODE')
  2.  
  3. aDoc.SetVariable('OSMODE', OSMODE)
  4.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 22-08-2019, 14:18:39
Добрый день!
Прошу подсказать. Например, мне нужно изменить порядок отрисовки объектов а чертеже. Я попробовал следующий код:
Код - Python [Выбрать]
  1.  
  2. acad = Dispatch('autocad.application.23')
  3. doc = acad.ActiveDocument
  4.  
  5. ent, _ = doc.Utility.GetEntity()
  6.  
  7. order_dict = doc.ModelSpace.GetExtensionDictionary()
  8. st = order_dict.GetObject("ACAD_SORTENTS")
  9.  
  10. arr = VARIANT(VT_ARRAY | VT_VARIANT, [ent])
  11.  
  12. st.MoveToTop(arr)



Но в результате получаю такое сообщение:


com_error                                 Traceback (most recent call last)
<ipython-input-365-c2e46e7e77cf> in <module>
      9 arr = VARIANT(VT_ARRAY | VT_VARIANT, [ent])
     10
---> 11 st.MoveToTop(arr)

d:\Prorams\Anaconda\lib\site-packages\win32com\client\dynamic.py in MoveToTop(self, Objects)

com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD.Application', 'Неверный массив объектов', 'D:\\Program Files\\Autodesk\\AutoCAD 2020\\HELP\\OLE_ERR.CHM', -2145320837, -2145320837), None)


Мне понятно, что проблема здесь в упаковке параметров функции. Но вот уже все известные мне варианты перепробовал, результат тот же самый.
Может быть найдется у кого работающий кусок кода, чтобы понять как правильно передать параметры?
Пробовал и объекты в вариант упаковывать и получить через SelectionSets. В общем не получается.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-08-2019, 15:16:22
Могу лишь предположить, что вместо:
Код - Python [Выбрать]
  1. arr = VARIANT(VT_ARRAY | VT_VARIANT, [ent])
должно быть:
Код - Python [Выбрать]
  1. arr = VARIANT(VT_ARRAY | VT_DISPATCH, [ent])
Но больше ничем не помогу.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 22-08-2019, 15:45:01
Да, именно так, все работает! Спасибо огромное!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 26-08-2019, 12:08:07
Добрый день!
Нужен совет.

при использовании кода

Код - Python [Выбрать]
  1.    
  2.     ss = doc.SelectionSets.Add("DM_take")
  3.  
  4.     ss.Select(
  5.         acad_mod.constants.acSelectionSetAll,
  6.         None, None        
  7.     )
  8.  
  9.     for e in ss :
  10.         ….  
  11.  

при переборе объектов в SelectionSet получаем e как IAcadEntity instance, при этом получается, что специфичные для объекта методы недоступны, например InsertionPoint если это блок.
Мне приходися делать примерно так:
Код - Python [Выбрать]
  1. e = doc.HandleToObject(e.Handle)

И тогда в e я получаю нужный объект. Но мне кажется что это не самый оптимальный способ, потому что опять же приходится обращаться к ActiveX, как бы лишний запрос.
Может быть кто знает как решать эту задачу поэлегантнее?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-08-2019, 12:10:34
DMuzer,
Прочитай у меня в подписи как следует форматировать код на форуме. Я уже несколько раз исправлял форматирование твоего кода.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 26-08-2019, 12:23:06
Хорошо, я разобрался как это делать, исправлюсь.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-08-2019, 12:25:47
На VBA этот вопрос решается так:
Код - Visual Basic [Выбрать]
  1. Dim obj As AcadEntity
  2. Dim poly As Polyline
  3. Dim polyLength As Double
  4.  
  5. For Each obj In ssetObj
  6.      If TypeOf obj Is AcadPolyline Then
  7.         Set poly = obj
  8.         MsgBox "Длина полилинии " & poly.Length
  9.      End If
  10. Next
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 10-09-2019, 13:53:02
Доброго дня!
Есть ли у кого опыт подключения к AutoCad из Python для обработки событий? Может быть есть какие-нибудь работающие примеры. Мои попытки самостоятельно это сделать пока были неудачные.
Было бы здорово посмотреть примеры обработку событий, например двойного щелчка по объекту, удаления, создания и т.п.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-09-2019, 16:19:24
DMuzer,
По второму кругу? https://adn-cis.org/forum/index.php?topic=7864.msg38829#msg38829
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 10-09-2019, 17:12:50
Ну да, так по аналогии с Word не заработало. Так не смог добиться какого-то работоспособного варианта.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Aleksey от 13-09-2019, 12:42:07
Здравствуйте! Подскажите пожалуйста по методу Select!
Хочу выбрать все вхождения блока, но не получается задать правильно аргументы FilterType и FilterData!
Код - Python [Выбрать]
  1. import array
  2. from win32com.client import Dispatch, CastTo, VARIANT
  3. from pythoncom import  VT_DISPATCH, VT_ARRAY, VT_UI2,VT_VARIANT,VT_BSTR
  4.  
  5.  
  6.  
  7. acad=Dispatch("Autocad.Application")
  8. doc=acad.ActiveDocument
  9. ms=doc.ModelSpace
  10.  
  11. try:
  12.     for i in doc.SelectionSets:
  13.         i.Delete()
  14. except: pass
  15.        
  16.  
  17. myss=doc.SelectionSets.Add("myss")
  18.  
  19. dxfcode,data=0,"Insert"
  20.  
  21. FilterType=VARIANT(VT_ARRAY|VT_UI2,dxfcode)
  22.  
  23. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,data)
  24.  
  25. SELECT_ALL=5
  26.  
  27. myss.Select(SELECT_ALL,None,None,FilterType,FilterData)


Traceback (most recent call last):
  File "D:\Мои документы\Работа\python exp\AutoCAD\BlocksInBlockCount\block_count2.py", line 27, in <module>
    myss.Select(SELECT_ALL,None,None,FilterType,FilterData)
  File "C:\Program Files\Python34\lib\site-packages\win32com\gen_py\852B2D4E-B1F4-4BD6-8672-9993177C1A40x0x1x0\IAcadSelectionSet.py", line 73, in Select
    , Point1, Point2, FilterType, FilterData)
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.

Научите, что я делаю не так!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-09-2019, 12:53:37
Aleksey,
Прочитай у меня в подписи о правильном форматировании кода на форуме и соблюдай это правило!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-09-2019, 13:27:27
Здравствуйте! Подскажите пожалуйста по методу Select!
Хочу выбрать все вхождения блока, но не получается задать правильно аргументы FilterType и FilterData!
Код - Python [Выбрать]
  1. import array
  2. from win32com.client import Dispatch, CastTo, VARIANT
  3. from pythoncom import  VT_DISPATCH, VT_ARRAY, VT_UI2,VT_VARIANT,VT_BSTR
  4.  
  5.  
  6.  
  7. acad=Dispatch("Autocad.Application")
  8. doc=acad.ActiveDocument
  9. ms=doc.ModelSpace
  10.  
  11. try:
  12.     for i in doc.SelectionSets:
  13.         i.Delete()
  14. except: pass
  15.        
  16.  
  17. myss=doc.SelectionSets.Add("myss")
  18.  
  19. dxfcode,data=0,"Insert"
  20.  
  21. FilterType=VARIANT(VT_ARRAY|VT_UI2,dxfcode)
  22.  
  23. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,data)
  24.  
  25. SELECT_ALL=5
  26.  
  27. myss.Select(SELECT_ALL,None,None,FilterType,FilterData)


Traceback (most recent call last):
  File "D:\Мои документы\Работа\python exp\AutoCAD\BlocksInBlockCount\block_count2.py", line 27, in <module>
    myss.Select(SELECT_ALL,None,None,FilterType,FilterData)
  File "C:\Program Files\Python34\lib\site-packages\win32com\gen_py\852B2D4E-B1F4-4BD6-8672-9993177C1A40x0x1x0\IAcadSelectionSet.py", line 73, in Select
    , Point1, Point2, FilterType, FilterData)
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.

Научите, что я делаю не так!

В функцию VARIANT нужно передавать список, а ты передаешь обычные значения. Поставь их либо в круглые либо в квадратные скобки

Код - Python [Выбрать]
  1. FilterType=VARIANT(VT_ARRAY|VT_UI2,[dxfcode])
  2.  
  3. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,[data])
  4.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-09-2019, 13:27:37
Aleksey,
Подозреваю, что вместо None следует использовать pythoncom.Empty
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Aleksey от 13-09-2019, 13:48:24
Код - Python [Выбрать]
  1. FilterType=VARIANT(VT_ARRAY|VT_UI2,[dxfcode])
  2.  
  3. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,[data])
  4.  
  5. SELECT_ALL=5
  6.  
  7. myss.Select(SELECT_ALL,pythoncom.Empty,pythoncom.Empty,FilterType,FilterData)

Traceback (most recent call last):
  File "D:\Мои документы\Работа\python exp\AutoCAD\BlocksInBlockCount\block_count2.py", line 32, in <module>
    myss.Select(SELECT_ALL,pythoncom.Empty,pythoncom.Empty,FilterType,FilterData)
  File "C:\Program Files\Python34\lib\site-packages\win32com\gen_py\852B2D4E-B1F4-4BD6-8672-9993177C1A40x0x1x0\IAcadSelectionSet.py", line 73, in Select
    , Point1, Point2, FilterType, FilterData)
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD', 'Недопустимый аргумент FilterType в Select', 'C:\\Program Files\\Autodesk\\AutoCAD 2014\\HELP\\OLE_ERR.CHM', -2145320939, -2147024809), None)

Не получается :-[

Меня этот метод интересует в том смысле, что мне кажется так будет быстрее выбирать элементы, чем через перебор всех элементов документа. Дает ли он выигрыш в скорости или может не стоит мучиться:)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-09-2019, 14:00:10
А если:
Код - Python [Выбрать]
  1. FilterType=VARIANT(VT_ARRAY|VT_I2,[0])
  2. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,['INSERT'])
?
Вообще же вроде не VT_UI2, а VT_I2
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-09-2019, 14:04:30
Не нужно pythoncom.Empty, нужно None оставить,
Код - Python [Выбрать]
  1. myss.Select(SELECT_ALL,None,None,FilterType,FilterData)
  2.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-09-2019, 14:26:26
Не нужно pythoncom.Empty, нужно None оставить,
Код - Python [Выбрать]
  1. myss.Select(SELECT_ALL,None,None,FilterType,FilterData)
  2.  
Здесь None не прокатило: https://adn-cis.org/forum/index.php?topic=7864.msg38367#msg38367
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-09-2019, 14:30:57
У меня работает, по 100 раз в день убеждаюсь в этом,
возможно, дело как раз в том, что нужно заменить VT_UI2 на VT_I2.
Опять же может быть дело в версии AutoCad. у меня 2018, и в 2020 тоже будет работать.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-09-2019, 14:33:44
возможно, дело как раз в том, что нужно заменить VT_UI2 на VT_I2.
Наиболее вероятно, т.к. сообщает об ошибке именно в параметре FilterType
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Aleksey от 13-09-2019, 15:24:29
Спасибо большое! Заработало! :)
Код - Python [Выбрать]
  1. FilterType=VARIANT(VT_ARRAY|VT_I2,[dxfcode])
  2.  
  3. FilterData=VARIANT(VT_ARRAY|VT_VARIANT,[data])
  4.  
  5. SELECT_ALL=5
  6.  
  7. myss.Select(SELECT_ALL,None,None,FilterType,FilterData)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 28-10-2019, 11:40:51
Всем здравствуйте.
Подскажите можно как то из питона передать набор в автокад?
То есть выделить один или несколько объектов в открытом документе автокада из питона.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 28-10-2019, 12:17:43
То есть выделить один или несколько объектов в открытом документе автокада из питона.
Имеется в виду выбрать и подсветить, как выбранное? Средствами только COM/ActiveX это сделать нельзя. И соответственно питоном тоже. В VBA это делалось через запуск lisp-функции (sssetfirst).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 28-10-2019, 12:31:24
Понял. А из питона же то же можно некую лисп функцию запустить? Только вот я не уверен что она переварит питоновский массив...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 28-10-2019, 12:33:35
А из питона же то же можно некую лисп функцию запустить?
Запустить можно. Document.SendCommand. Сложность будет только с передачей параметров.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 28-10-2019, 12:35:07
Я понял. Спасибо
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 28-10-2019, 18:53:59
Подскажите пожалуйста! Как выбрать вхождение блока по имени и считать значение его атрибута (например блок "РАМКА", атрибут PAGE). Пробывал через Blocks.Item, но это не то :o

Возник схожий вопрос по динамическим атрибутам блока.
Допустим я выбрал мышкой  динамический блок и среди его динамических свойств  есть параметр "Ширина"

AllowedValues: (210.0, 297.0, 420.0, 594.0, 630.0, 841.0, 891.0, 1051.0, 1189.0, 1261.0, 1471.0, 1486.0, 1682.0, 1783.0, 1892.0, 2080.0, 2102.0, 2378.0, 2523.0)
Description: Ширина внешней рамки
PropertyName: Ширина
ReadOnly: False
Show: False
UnitsType: 2
Value  : 594.0

Как-то можно получить к нему доступ напрямую по имени без перебора всех свойств блока? Пока я получаю  их таким способом, но выглядит это не очень рационально:

Код - Python [Выбрать]
  1. width = [attr.value for attr in obj.GetDynamicBlockProperties() if attr.PropertyName=='Ширина'][0]

P.S. без использования GetBoundingBox()
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 28-10-2019, 21:13:30
Как-то можно получить к нему доступ напрямую по имени без перебора всех свойств блока?
Никак. Такой возможности в API нет. Впрочем это и логично - теоретически может быть несколько свойств с одним именем.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 29-10-2019, 05:29:30
Я надеюсь что я не сильно злоупотребляю вниманием сообщества, у меня еще один вопрос.
Есть ли возможность изменить видимость атрибута в блоке? И есть ли у кого то для этого уже готовый рецепт?
Судя по доке, параметр "Invisible" - изменяемый, нельзя ли его как то изменить тем же способом что и просматриваю?
Код - Python [Выбрать]
  1. object.GetAttributes()[y1].Invisible

Еще нашел метод вот такой:
Код - Python [Выбрать]
  1. object.SetVariable(Invisible, False)
То же не получается изменить параметр

И еще один метод, но я вообще не могу его применить, потому и прошу пример на питоне
Код - Python [Выбрать]
  1. object.AddAttribute(1, acAttributeModeInvisible, Prompt, InsertionPoint, Tag, Value)

Был настроен на питон, но сталкиваюсь со сложностью с реализацией каждой небольшой идеи. Может выбрать какой то более простой и документированный способ автоматизации автокада? Для Вижуал-бейсика хоть примеры есть, но не уверен что это оптимальный подход. В общем прошу проконсультировать.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 29-10-2019, 06:58:16
Я надеюсь что я не сильно злоупотребляю вниманием сообщества, у меня еще один вопрос.
Есть ли возможность изменить видимость атрибута в блоке? И есть ли у кого то для этого уже готовый рецепт?
Судя по доке, параметр "Invisible" - изменяемый, нельзя ли его как то изменить тем же способом что и просматриваю?

Не могу прямо сейчас проверить, но если параметр изменяемый, то разве нельзя ему просто присвоить логическое значение напрямую, без всяких сеттеров?

Код - Python [Выбрать]
  1. object.GetAttributes()[y1].Invisible = False
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Alexll от 29-10-2019, 07:05:53
Вот - вот. Я и думал что как то так можно )
Спасибо, так получилось:
Код - Python [Выбрать]
  1. object.GetAttributes()[y1].Invisible = False
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 29-10-2019, 09:19:10
Был настроен на питон, но сталкиваюсь со сложностью с реализацией каждой небольшой идеи. Может выбрать какой то более простой и документированный способ автоматизации автокада? Для Вижуал-бейсика хоть примеры есть, но не уверен что это оптимальный подход. В общем прошу проконсультировать.
Рекомендую заняться изучением C#. И писать плагины, которые грузятся внутрь AutoCAD, т.к. AutoCAD .NET API значительно мощнее, чем AutoCAD COM/ActiveX
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 29-10-2019, 18:16:49
Рекомендую заняться изучением C#. И писать плагины, которые грузятся внутрь AutoCAD, т.к. AutoCAD .NET API значительно мощнее, чем AutoCAD COM/ActiveX

Тоже задумываюсь над изучением Си шарпа  для этих целей. Интересно, будет ли на практике какой-то прирост в скорости по сравнению с работой с COM в AutoCAD?
И как я понимаю, программа, написанная  на C# будет сильно зависеть от версии Автокада, в отличие от COM, разницу в работе которой в автокаде я не замечал с 2010 по 2020 версии.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 29-10-2019, 18:23:39
Интересно, будет ли на практике какой-то прирост в скорости по сравнению с работой с COM в AutoCAD?
Да. Причем если сравнивать COM/ActiveX из внешнего приложения и .NET из плагина, загружаемого в сам AutoCAD, то прирост скорости может быть и на порядок.
И как я понимаю, программа, написанная  на C# будет сильно зависеть от версии Автокада, в отличие от COM, разницу в работе которой в автокаде я не замечал с 2010 по 2020 версии.
По хорошему нужно под каждую версию AutoCAD делать свою dll, но если не использовать некоторые особенности (точнее не нарваться на них случайно), то с 2013 и по 2020 должна работать одна dll. Ну и могут быть особенности с версией .NET Framework, так как каждая из версий AutoCAD требует свою (а точнее "не меньшую чем" версию .NET Framework: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2020/ENU/AutoCAD-Customization/files/GUID-A6C680F2-DE2E-418A-A182-E4884073338A-htm.html).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 06-11-2019, 19:18:14
Есть идея написать на Пайтоне аналог скрипта AL (https://forum.dwg.ru/showthread.php?t=124456&page=5) для создания листов с видовыми экранами из рамок/блоков в пространстве модели. Предложенный там скрипт не вполне корректно работает с используемым мной динамическим блоком для рамки, а переделывать LISP пока желания не возникает  :D

Так вот, своим Python скриптом, получаю координату базовой точки рамки-блока (правый нижний угол)  x, y в пространстве модели, ширину width, высоту height, поворот orientation. Далее удаляю существующие листы кроме пространства модели и пустого листа по умолчанию "Лист1".

Затем создаю лист c именем pagename и пытаюсь создать видовой  экран в нем (за основу взял этот код (https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-9DCF17E7-717B-4766-AFFE-D3C9ED506BB8-htm.html)):

Код - Python [Выбрать]
  1. newPage = aDoc.Layouts.Add(pagename)
  2.  
  3. aDoc.ActiveLayout = newPage
  4.  
  5. # Установить активным пространство листа
  6. aDoc.ActiveSpace = 0 #acPaperSpace
  7.                                
  8. center = win32com.client.VARIANT(VT_ARRAY | VT_R8, (x-width/2, y+height/2, 0))
  9.  
  10. # Видовой экран
  11. newVport = aDoc.PaperSpace.AddPViewport(center, width, height)  
  12.  
  13. # направление взгляда на viewport
  14.  newVport.Direction = win32com.client.VARIANT(VT_ARRAY | VT_R8, (1,1,1))
  15.  
  16. # Отобразить viewport
  17. newVport.Display(True)
  18.  
  19. # Переключение в пространство модели
  20. aDoc.MSpace = True  
  21.  
  22. # Установить viewport текущим
  23. aDoc.ActivePViewport = newVport
  24.  
  25. # попытка сделать ZoomExtents
  26. win32com.client.Dispatch("AutoCAD.Application").ZoomExtents()
  27.  
  28. # Деактивация пространства модели
  29. aDoc.MSpace = False
  30.  


В результате все вылетает на строчке "aDoc.ActivePViewport = newVport"
Цитировать
0, 'AutoCAD', 'Нет активного видового экрана в пространстве модели. Переключение в пространство листа'

По факту получается пустой лист минимального размера, и где-то полноразмерная рамка видового экрана далеко сбоку (примерно как на расстоянии  от начала координат).
Понимаю, в моем коде может быть много ошибок, укажите хотя бы на несколько из них.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 06-11-2019, 19:31:29
Насколько я помню, средствами ActiveX создавать ВЭ нельзя.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-11-2019, 22:09:00
Насколько я помню, средствами ActiveX создавать ВЭ нельзя.
Вообще-то AddPViewport это делает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-11-2019, 22:18:09
Electric,
Посмотри в каком состоянии у тебя системная переменная LAYOUTCREATEVIEWPORT: https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2016/ENU/AutoCAD-Core/files/GUID-799745E4-9804-41A7-BC48-E67CF2615111-htm.html
Если не 1, то установи её в 1.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 07-11-2019, 11:12:47
сть идея написать на Пайтоне аналог скрипта AL для создания листов с видовыми экранами из рамок/блоков в пространстве модели. Предложенный там скрипт не вполне корректно работает с используемым мной динамическим блоком для рамки, а переделывать LISP пока желания не возникает  Так вот, своим Python скриптом, получаю координату базовой точки рамки-блока (правый нижний угол)  x, y в пространстве модели, ширину width, высоту height, поворот orientation. Далее удаляю существующие листы кроме пространства модели и пустого листа по умолчанию "Лист1". Затем создаю лист c именем pagename и пытаюсь создать видовой  экран в нем (за основу взял этот код):

Думаю проблема в настройках листа,
вот этого не нужно:
aDoc.ActivePViewport = newVport

и нужно настроить параметры листа: единицы измерения и т.п.
Я приведу свою функцию для формирования листа, там присутствуют ссылки на другие функции но в целом понять как работает можно. Функцией каждый день по многу раз пользуюсь поэтому код рабочий.
Обычно у меня на чертеже много прямоугольников из которых потом формируются листы. В XData прямоугольников записан масштаб, исходя из этого подбирается подходящий формат бумаги
Код - Python [Выбрать]
  1.  
  2. def CreateLayout(doc, h, i, scale = 100) :
  3.     """
  4.    Создает новый лист и выводит на него область полилинии
  5.    Подбирает размер, исходя из масштаба
  6.    i - число, из которого создается имя листа. Имена листов всегда будут числовые
  7.  
  8.    """
  9.     import time
  10.     pl = doc.HandleToObject(h)
  11.     bb = pl.GetBoundingBox()
  12.  
  13.     dt, dx = pl.GetXData('DM_Page')
  14.  
  15.     try :
  16.         page_scale = dx[2]
  17.     except :
  18.         page_scale = scale  
  19.    
  20.     size = (bb[1][0] - bb[0][0], bb[1][1]-bb[0][1])
  21.     mn = GetMediaName(size, scale = page_scale)
  22.    
  23.     try :
  24.         lo = doc.Layouts.Add(f'{i:05}')
  25.     except Exception as ex:        
  26.         lo = doc.Layouts(f'{i:05}')
  27.        
  28.        
  29.     lo.ConfigName = "DWG To PDF.pc3"
  30.     lo.RefreshPlotDeviceInfo()
  31.     lo.CanonicalMediaName = mn
  32.     lo.RefreshPlotDeviceInfo()
  33.     lo.PaperUnits = acad_mod.constants.acMillimeters
  34.     lo.PlotType = acad_mod.constants.acLayout
  35.    
  36.     lo.PlotRotation = acad_mod.constants.ac0degrees
  37.        
  38.     doc.Regen(0)
  39.    
  40.     doc.ActiveLayout = lo
  41.     doc.MSpace = False
  42.    
  43.     for e in lo.Block :
  44.         e.Delete()
  45.        
  46.     #     Создаем вид
  47.  
  48.     psize = lo.GetPaperSize()
  49.     margins = lo.GetPaperMargins()
  50.     pvsize = (psize[0] - margins[0][0] - margins[1][0], psize[1] - margins[0][1] - margins[1][1])    
  51.    
  52.     center = (pvsize[0] / 2 , pvsize[1] / 2, 0)    
  53.  
  54.     pv = doc.PaperSpace.AddPViewport(vtr(center), pvsize[0], pvsize[1])
  55.     pv.Layer = 'defpoints'
  56.     pv.Display(True)
  57.    
  58.     doc.MSpace = True
  59.     doc.Application.ZoomWindow(vtr(bb[0]), vtr(bb[1]))
  60.     doc.MSpace = False
  61.     doc.Application.ZoomExtents()
  62.     doc.Regen(0)
  63.     doc.ActiveLayout = doc.Layouts("Model")
  64.     doc.ActiveLayout = lo
  65.     doc.Application.ZoomExtents()
  66.     doc.SendCommand("_PSLTSCALE 0 ")
  67.     doc.SendCommand("ВСЕРЕГЕН ")
  68.  



Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 07-11-2019, 11:19:53
Абсолютно не знаю Python, но почему бы не попробовать использовать вместо
Код - Python [Выбрать]
  1.     doc.SendCommand("_PSLTSCALE 0 ")
  2.     doc.SendCommand("ВСЕРЕГЕН ")
нечто типа
Код - Python [Выбрать]
  1. doc.SetVariable("PSLTSCALE", 0)
  2. doc.Regen 1
P.S. acActiveViewport = 0
acAllViewports = 1
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 07-11-2019, 11:31:15
Абсолютно не знаю Python, но почему бы не попробовать использовать вместоКод - Python [Выбрать]    doc.SendCommand("_PSLTSCALE 0 ")    doc.SendCommand("ВСЕРЕГЕН ")нечто типаКод - Python [Выбрать]doc.SetVariable("PSLTSCALE", 0)doc.Regen 1P.S. acActiveViewport = 0acAllViewports = 1

Думаю, так было бы лучше, команду отправлял потому не было времени разбираться в тонкостях переменных, было понимание что такая команда работает правильно поэтому сделал так, с тех пор не трогал)))
 только так работать не будет

Код - Python [Выбрать]
  1. doc.Regen 1

нужно

Код - Python [Выбрать]
  1. doc.Regen(1)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 07-11-2019, 11:48:25
Ну, я в Python ни бум-бум :)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 07-11-2019, 18:57:50
Я приведу свою функцию для формирования листа, там присутствуют ссылки на другие функции но в целом понять как работает можно.

Благодарю! Пока подгоняю эту функцию под свой код, застрял на этом моменте:

Цитировать
Код - Python [Выбрать]
  1.     doc.Application.ZoomWindow(vtr(bb[0]), vtr(bb[1]))  
  2.  


Я так понимаю, vtr в этом фрагменте - это аналог convert_coordinates из начала темы (https://adn-cis.org/forum/index.php?topic=7864.msg28996#msg28996)?

Код - Python [Выбрать]
  1. def convert_coordinates(*args):
  2.     """
  3.    Функция преобразования координат в формат AutoCAD
  4.    :param args: координаты для преобразования, допустима передача списка или кортежа
  5.    :return: Координаты в формате AutoCAD
  6.    """
  7.     if isinstance(args[0], (list, tuple)):
  8.         coords = [item for item in args[0]]
  9.     else:
  10.         coords = args
  11.     return win32com.client.VARIANT(VT_ARRAY | VT_R8, coords)

Если применить её, получаю в вышеупомянутой строке:

Цитировать
Ошибка здесь float() argument must be a string or a number, not 'VARIANT'
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 08-11-2019, 09:41:44
Кроме того, у меня на разных современных компах, в различающихся версиях AutoCAD, python-скрипты, например связанные с созданием и обновлением листов, непредсказуемо вылетают во время этих операций с ошибкой:

Цитировать
-2147418111, 'Вызов был отклонен'

Спасает только введение пауз в наиболее проблемные места в коде после длительных действий:

Код - Python [Выбрать]
  1. time.sleep(2)

Это такой глюк только у меня или это в принципе нормально для взаимодействия с AutoCAD  через COM? Если я смотрю существующий аналогичный код на LISP, никаких временных пауз там не вводится.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-11-2019, 09:54:47
Это такой глюк только у меня или это в принципе нормально для взаимодействия с AutoCAD  через COM?
Нормально через COM из внешнего приложения.
Если я смотрю существующий аналогичный код на LISP, никаких временных пауз там не вводится.
Lisp работает внутри AutoCAD.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 08-11-2019, 19:20:33
Я так понимаю, vtr в этом фрагменте - это аналог convert_coordinates из начала темы?

vtr у  меня функция получения массива VARIANT double. я этот код выделил в функцию, поскольку очень часто требуется такое преобразование

Код - Python [Выбрать]
  1.  
  2. def vtr (x) :
  3.     """
  4.        Возвращает variant массив double
  5.        x - массив двоичных чисел
  6.    """
  7.     return VARIANT(VT_ARRAY | VT_R8, x)
  8.  
  9.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 13-11-2019, 18:18:58
Исправил все ошибки в своем скрипте для рамок, благодаря  коду выше. Дома работает идеально, но на чуть более слабом компе вылетает со случайными ошибками на разных участках кода при обращении к Автокаду. Похоже, что работа через COM подходит только для простейших операций.

Возможно ли через COM очистить командную строку и остановить выполняемую в  данный момент операцию в Автокаде? При тестировании скриптов постоянна ситуация, что командная строка занята незавершенной командой от предыдущей запуска с ошибкой, и пространство модели таким образом недоступно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-11-2019, 18:23:38
Возможно ли через COM очистить командную строку и остановить выполняемую в  данный момент операцию в Автокаде?
Попробуй через SendCommand("\003\003"). Это единственный, но негарантированный способ.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 15-11-2019, 18:50:13
Возможно ли через COM очистить командную строку и остановить выполняемую в  данный момент операцию в Автокаде?
Попробуй через SendCommand("\003\003"). Это единственный, но негарантированный способ.

Действительно, этот способ очень негарантированн, у меня он либо не работает, либо  выдает ошибку. Если бы я писал через C#  - у меня было бы больше возможностей для этого?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 15-11-2019, 19:03:37
Действительно, этот способ очень негарантированн, у меня он либо не работает, либо  выдает ошибку.
Это аналог двойного нажатия ESC в AutoCAD - так что сообщение об ошибке должно быть и должна прерываться активная команда.
Если бы я писал через C#  - у меня было бы больше возможностей для этого?
Если через COM/ActiveX - возможностей столько же. Если использовать AutoCAD .NET API, то необходимости прерывать команду быть не должно.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 03-12-2019, 11:13:03
Вот такой вопрос, хочу разобраться, связан с формированием листов.
Я программно генерирую листы, лист создается, настраивается и т.п. и затем я распечатываю в pdf
(используется dwg to pdf принтер). Если распечатать сразу, то все ок, если документ закрывается и потом снова открывается, то может появиться такая фигня, что все листы пустые.
Причем так бывает не всегда, иногда листы остаются. Я не могу понять закономерность, может кто знает почему такая ерунда может быть? Ну или по крайней мере
подскажет направление в каком нужно копать.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 03-12-2019, 11:51:08
Возможно поможет эта статья: https://adn-cis.org/pechat-granicz-okna-pri-pomoshhi-vba.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 07-12-2019, 13:22:56
Нормально через COM из внешнего приложения.
Lisp работает внутри AutoCAD.

А если подключаться к AutoCAD не через COM, а через .NET, но не на C#, а например на Python с помощью библиотеки pythonnet - это даст какие-то преимущества? Т.е. с точки зрения Автокад это будет отличасть от написания .NET  на C#?
Просмотрел видеоуроки по C#, вроде синтаксис  понимаю и базовые вещи. Но как только увидел на этом форуме  урок по написанию простейшей программы на C# к AutoCAD -  понимаю, что ничего не понимаю  :D
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 07-12-2019, 15:02:28
А если подключаться к AutoCAD не через COM, а через .NET, но не на C#, а например на Python с помощью библиотеки pythonnet - это даст какие-то преимущества?
Я не пишу на Python, не знаю возможностей PythonNet. Поэтому затрудняюсь ответить на этот вопрос. В любом случае это неподдерживаемый со стороны Autodesk интерфейс.
Но как только увидел на этом форуме  урок по написанию простейшей программы на C# к AutoCAD -  понимаю, что ничего не понимаю 
Да ладно. Ничего сложного в нём нет - нужно просто разобраться в этом первом примере, а дальше будет проще...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: dlobyntsev от 13-12-2019, 13:14:32
А если подключаться к AutoCAD не через COM, а через .NET, но не на C#, а например на Python с помощью библиотеки pythonnet
Не получится подключится. В Autocad что-то делать извне можно только через COM. Написать с помощью pythonnet .NET код для AutoCAD можно, только никак не скомпилировать его в dll, чтобы запустить из AutoCAD.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 13:57:42
Возможно поможет эта статья: https://adn-cis.org/pechat-granicz-okna-pri-pomoshhi-vba.html
Может быть что то в этом есть,  возможно где то несостыковка именно с координатами. В примере показана печать из пространства модели как я понимаю, и преобразование
применяется когда используется метод печати окна. Я же применяю метод печати листа. После того как настройка выполняется, все нормально, можно печатать. После того как закрываеш чертеж и снова его открываешь, приходится все листы сносить и заново делать. А это бывает довольно много времени для этого требуется.
В общем вот мой код, по возможности посоветуйте где имеет смысл воспользоваться преобразованием координат. Я бы прислал и файл, но не вижу как прицепить чертеж. попробую вставить ссылку на файл на облаке

https://1drv.ms/u/s!Aj6-EzSXLgqnhMYM6Tv1iEobI8uxQg?e=ggJbFg

Код - Python [Выбрать]
  1. def CreateLayout(doc, h, i, scale = 100) :
  2.     """
  3.    Создает новый лист и выводит на него область полилинии
  4.    Подбирает размер, исходя из масштаба
  5.    i - число, из которого создается имя листа. Имена листов всегда будут числовые
  6.  
  7.    """
  8.     import time
  9.     pl = doc.HandleToObject(h)
  10.     bb = pl.GetBoundingBox()
  11.  
  12.     dt, dx = pl.GetXData('DM_Page')
  13.  
  14.     try :
  15.         page_scale = dx[2]
  16.     except :
  17.         page_scale = scale  
  18.    
  19.     size = (bb[1][0] - bb[0][0], bb[1][1]-bb[0][1])
  20.     mn = GetMediaName(size, scale = page_scale)
  21.    
  22.     try :
  23.         lo = doc.Layouts.Add(f'{i:05}')
  24.     except Exception as ex:        
  25.         lo = doc.Layouts(f'{i:05}')
  26.        
  27.        
  28.     lo.ConfigName = "DWG To PDF.pc3"
  29.     lo.RefreshPlotDeviceInfo()
  30.     lo.CanonicalMediaName = mn
  31.     lo.RefreshPlotDeviceInfo()
  32.     lo.PaperUnits = acad_mod.constants.acMillimeters
  33.     lo.PlotType = acad_mod.constants.acLayout
  34.    
  35.     lo.PlotRotation = acad_mod.constants.ac0degrees
  36.        
  37.     doc.Regen(0)
  38.    
  39.     doc.ActiveLayout = lo
  40.     doc.MSpace = False
  41.    
  42.     for e in lo.Block :
  43.         e.Delete()
  44.        
  45.     #     Создаем вид
  46.  
  47.     psize = lo.GetPaperSize()
  48.     margins = lo.GetPaperMargins()
  49.     pvsize = (psize[0] - margins[0][0] - margins[1][0], psize[1] - margins[0][1] - margins[1][1])    
  50.    
  51.     center = (pvsize[0] / 2 , pvsize[1] / 2, 0)    
  52.  
  53.     pv = doc.PaperSpace.AddPViewport(vtr(center), pvsize[0], pvsize[1])
  54.     pv.Layer = 'defpoints'
  55.     pv.Display(True)
  56.    
  57.     doc.MSpace = True
  58.     doc.Application.ZoomWindow(vtr(bb[0]), vtr(bb[1]))
  59.     doc.MSpace = False
  60.     doc.Application.ZoomExtents()
  61.     doc.Regen(0)    
  62.  
  63.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-12-2019, 14:49:36
После того как закрываеш чертеж и снова его открываешь, приходится все листы сносить и заново делать.
Зачем?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 15:10:59
Проблема в том, что настройки листа сбиваются, если посмотреть приложенный файл, то, думаю, будет понятно. А выглядит это так: сформировал все листы,
распечатал, закрыл чертеж, после того, как заново чертеж отрываю, в большинстве листов как бы нет самого листа, можно несколько раз щелкнуть колесико, тогда границы листа появляются, но отображают совсем не то, что нужно. В общем работает все не так как нужно и распечатать лист не получается, поэтому сношу все и создаю все заново. Пока так. Хотелось бы справиться с этой проблемой, поскольку это ерунда какая-то. Так не должно быть.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-12-2019, 16:12:42
DMuzer,
Если я правильно понял, у тебя получается нормальным только последний лист.
И похоже из-за этого:
Код - Python [Выбрать]
  1. for e in lo.Block :
  2.         e.Delete()
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 16:26:55
Возможно, я попробую убрать этот блок. Но все-таки поясню его смысл.
При создании нового листа, на нем может быть вьюпорт, который автоматически создается(в настройках можно отключать), но мне кажется этот кусочек кода работает.
lo - это вновь созданный лист, lo.Block - это объекты на листе, на новом листе, только вьюпорт, его я и удаляю, мне он не нужен, я сделаю новый.

В общем, мне кажется, что этот код не должен удалять объекты на других листах, только на листе, с которым я работаю. При этом, я удаляю объекты до того, как создать все свои.
Кроме того, после создания листов - там же все в порядке, я же их могу всега видеть и распечатать, ведь печатаю я после того, как создаю все листы. Проблема возникает когда я закрываю чертеж. А после того как заново открываю - картина такая как в файле который для примера привел.
Так что, на первый взгляд, этот код не должен вызывать этих проблем, но я попробую, может проблема тут глубже. А у Вас может другие предположения есть?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-12-2019, 16:34:59
Кроме того, после создания листов - там все в порядке, я же их могу всега видеть и распечатать, ведь печатаю я после того, как создаю все листы.
Тогда я ничего не понял. После того как ты создаёшь все эти листы у тебя получается нормальный чертеж, каждый из листов которого нормально печатается? И после сохранения и повторного открытия чертежа информация с листов пропадает??? Но это может только означить, что твой код портит чертеж. Я запустил _AUDIT и что я вижу:

Command: _AUDIT
Fix any errors detected? [Yes/No] <N>: _y
Auditing Header
Auditing Tables
Auditing Entities Pass 1
Pass 1 800     objects auditedAcDbBlockReference(437)
                     XData String Length 312 > 255      Truncate to 255
Pass 1 15300   objects auditedAcDbSortentsTable(4B4E)
      Error for Entry (4B51,4B53) eDuplicateKey         fixed
Pass 1 15400   objects auditedAcDbSortentsTable(4B9A)
      Error for Entry (4BA9,4BAB) eDuplicateKey         fixed
Pass 1 16600   objects audited
Invalid viewport-configuration name "*Multiple" found.
  Changed to "AUDIT_I_191213153339-0".
AcDbViewportTableRecord: "AUDIT_I_191213153339-0"
        Tilemode Viewport Corners Not filling up whole screen Set to 0,0..1,1
Invalid viewport-configuration name "*Multiple" found.
  Changed to "AUDIT_I_191213153339-1".
AcDbViewportTableRecord: "AUDIT_I_191213153339-1"
        Tilemode Viewport Corners Not filling up whole screen Set to 0,0..1,1
Pass 1 26600   objects audited
Auditing Entities Pass 2
Pass 2 16700   objects auditedAcDb2dVertex(250DF)         layer != owner's            set to owner's
AcDb2dVertex(250E0)         layer != owner's            set to owner's
AcDb2dVertex(250E1)         layer != owner's            set to owner's
AcDb2dVertex(250E2)         layer != owner's            set to owner's
AcDb2dVertex(250E3)         layer != owner's            set to owner's
Pass 2 26600   objects audited
Auditing Blocks
 349     Blocks audited
Auditing AcDsRecords
Regenerating model.
Total errors found 12 fixed 12
Erased 0 objects

Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 16:42:34
И после сохранения и повторного открытия чертежа информация с листов пропадает???
Именно так.

Я понимаю, что что-то не так делаю.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 16:45:58
Я тоже сделал аудит, меня заинтересовала вот какая строка:

           Paperspace vport layer Not "0"               "0"
AcDbViewport(2B4DB)               не восстановлен.

что это может значить? Я должен при создании vport только на слой 0 помещать? Может в этом дело?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 16:48:34
И еще такая строчка:

Обнаружено недопустимое имя конфигурации видовых экранов "*Multiple".
AcDbViewportTableRecord: "*Multiple"

Что это должно значить?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 13-12-2019, 16:52:49
И еще такая строчка:

Обнаружено недопустимое имя конфигурации видовых экранов "*Multiple".
AcDbViewportTableRecord: "*Multiple"

Что это должно значить?
Для начала удали все листы, выполни _AUDIT с исправлением всех ошибок. Затем сохрани чертеж, снова запусти _AUDIT и убедись, что ошибок нет. Дальше можешь запускать свою программу и посмотри что после неё скажет _AUDIT.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 13-12-2019, 17:16:32
Похоже, что дело как раз в этом.
Вроде как после исправления ошибок и сохранения, далее все правильно идет.
Посмотрим, как все будет дальше.
Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 16:52:15
Доброго дня!
Подскажите, как решить задачу: я через ActiveX вставляю выноски функцией AddMLeader.
Иногда нужно чтобы выноска присоединялась к тексту слева, то все ок, но никак не могу добиться, чтобы при вставке выноска присоединялась справа. Вроде все что в голову приходило перепробовал. Выноска автоматически перескакивает как нужно если ее вручную подвигатть, но это вроде не совсем то что нужно. Можно это через ActiveX решить?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 14-01-2020, 17:04:43
По-моему, надо смотреть в сторону выравнивания аннотации (если там текст).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 14-01-2020, 17:07:23
Подскажите, как решить задачу: я через ActiveX вставляю выноски функцией AddMLeader.
Покажи код, которым ты это делаешь.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 17:09:16
Что с выравниванием не получается...
пробовал
TextAttachmentDirection, TextJustify что то не то...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 17:11:14
Код - Python [Выбрать]
  1.         ml = doc.ModelSpace.AddMLeader(vtr(pts), 0)
  2.        
  3.        
  4.         ml[0].Layer = '_fsa-anno-notes'
  5.         ml[0].TextBackgroundFill=True
  6.         ml[0].TextJustify = 9
  7.         ml[0].TextString = ts
  8.         ml[0].ArrowHeadType = 19
  9.         ml[0].Update()
  10.  
  11.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 14-01-2020, 17:12:45
DMuzer,
Какие координаты точек ты передаёшь (т.е. что в массиве pts)?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 17:13:47
Код - Python [Выбрать]
  1.         ent, p = doc.Utility.GetEntity()
  2.         print(ent, p)
  3.         pl = polyline(ent.Coordinates, doc)
  4.         npoint = pl.get_nearest_point(point2d(p, doc))
  5.         nline = pl.get_nearest_line(point2d(p, doc))
  6.         print(pl, npoint)
  7.        
  8.         ts = re.search(r"dn\d+", ent.Layer).group(0).upper()
  9.        
  10.         a1, b1, c1 = nline[0].nparams
  11.        
  12.         if (a1 != 0) != (b1 != 0) :        
  13.             pts = [npoint[0], npoint[1],0, npoint[0]-1000, npoint[1]-200, 0,]
  14.         else :
  15.              pts = [npoint[0], npoint[1],0, npoint[0]+200, npoint[1]-200, 0,]
  16.        
  17.         ml = doc.ModelSpace.AddMLeader(vtr(pts), 0)
  18.        
  19.        
  20.         ml[0].Layer = '_fsa-anno-notes'
  21.         ml[0].TextBackgroundFill=True
  22.         ml[0].TextJustify = 9
  23.         ml[0].TextString = ts
  24.         ml[0].ArrowHeadType = 19
  25.         ml[0].Update()
  26.  
  27.  
  28.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 17:21:56
Пара пояснений к коду:
Выноска - чтобы автоматически проставить диаметры на трубы, которые отрисованы полилиниями на разных слоях.
polyline и point2d - мои классы, для реализации выч. геометрии.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 14-01-2020, 17:52:10
Ответ здесь: https://adn-cis.org/forum/index.php?topic=2709.0
Нужно использовать метод SetDoglegDirection
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 14-01-2020, 18:08:31
Заработало с DogLegDirection, Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 22-01-2020, 13:32:00
Добрый день!
Подскажите, какими функциями надо воспользоваться, чтобы сделать копию существующего блока в чертеже? Именно определения  блока, а не блока в чертеже.
Попробовал несколько вариантов не получается. Например я пробовал так:

Код - Python [Выбрать]
  1. ent = doc.Utility.GetEntity()[0]
  2. lst = [doc.Blocks(ent.Name)]
  3. lst = VARIANT(VT_DISPATCH|VT_ARRAY, lst)
  4. res = doc.CopyObjects(lst)
  5.  

Пробовал добавлять и ModelSpace и Document в качестве нового собственника, пока не получилось...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-01-2020, 13:34:59
Пробовал добавлять и ModelSpace и Document в качестве нового собственника, пока не получилось...
Попробуй в качестве нового собственника doc.Blocks
Впрочем подозреваю, что так не сработает. Нужно сначала создать блок с новым именем ( doc.Blocks.Add (...) ) и потом в него при помощи CopyObjects скопировать все объекты первого блока (т.е. новым собственником будет новый блок).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 22-01-2020, 14:37:11
Видимо так и придется. Как думаете, если мне нужно скопировать определение блока в другой чертеж, тоже не получится? У меня получалось скопировать вхождение блока из одного чертежа в другой, и соответственно определение тоже копировалось, на крайний случай пойдет, но все таки на мой взгляд грубовато чтобы скопировать определение блока.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-01-2020, 14:39:41
Как думаете, если мне нужно скопировать определение блока в другой чертеж, тоже не получится?
Попробуй. В пределах одного чертежа скорее всего не получится из-за совпадения имён блоков. В другом чертеже если одноимённого блока нет, то возможно скопируется. 
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 22-01-2020, 14:41:54
Вот так у меня получилось сделать копию блока:

Код - Python [Выбрать]
  1. ent = doc.Utility.GetEntity()[0]
  2. o_blk = doc.Blocks(ent.Name)
  3.  
  4. i = 0
  5. while True :
  6.     try :
  7.         b_name = f"{o_blk.Name}_{i:02d}"
  8.         n_blk = doc.Blocks.Add(vtr([0,0,0]),b_name)
  9.         break
  10.     except :
  11.         i += 1
  12.         raise
  13.        
  14. lst = [e for e in o_blk]
  15. v_lst = VARIANT(VT_DISPATCH|VT_ARRAY, lst)
  16.  
  17. res = doc.CopyObjects(v_lst, n_blk)
  18. print(n_blk)
  19.  
  20. res
  21.  

Эта функция возвращает кортеж из двух массивов, в котором возвращаются скопированные объекты. Я правильно понимаю, что это возвращаются и исходные объекты и новые? То есть в этом случае их как то можно связать, или после копирования передать какие то данные?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 22-01-2020, 14:57:55
Я правильно понимаю, что это возвращаются и исходные объекты и новые?
Нет. Эта функция возвращает:
Цитировать
RetVal = object.CopyObjects(Objects [, Owner] [, IDPairs])
RetVal - Variant (array of objects)
An array of newly created duplicate objects. Only primary objects are returned in this array.

Т.е. только новые, да и то не все, а только главные.
А вот в IDPairs:
Цитировать
IDPairs - Variant (array of IDPair objects); input-output; optional
Information on what happened during the copy and translation process.
Input: an empty variant.
Output: an array of IDPair objects.
Т.е. здесь пара: старый-новый объекты.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 23-01-2020, 01:17:23
Ну собственно справку я видел, как раз и вопрос возник, что не совсем понятно, что возвращает функция. Например, скопировала 3 объекта, а возвращает два массива по 3 объекта.
Что касается основных объектов - то я думаю имеется ввиду что если копируется блок, то будет возвращена ссылка именно на блок, а его составляющие возвращены не будут.
Надо будет поэксперементировать, понять, что же все таки она возвращает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 23-01-2020, 01:20:08
 Еще вопрос, у меня есть динамический блок, функция GetBoundingBox возвращает границы объекта включая все невидимые примитивы этого блока, включая и те, которые входят в другие варианты отображения блока.
Существует ли способ определить именно видимые границы блока? то есть только для активной видимости динамического блока?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-01-2020, 01:41:48
Все примитивы, невидимые в текущей видимости вставки блока в составе своего анонимного блока имеют признак Visible установленную в False. Это наводка для получения правильного GetBoundingBox - такие примитивы следует пропустить. Т.е. необходимо вычислить GetBoundingBox для всех видимых примитивов в блоке, а затем этот "ящик" преобразовать по матрице преобразования блока (которую нужно вычислить и готового алгоритма для COM/ActiveX я не нашел). Альтернативный вариант - вызов метода Explode с вычислением GetBoundingBox и последующим удалением полученных примитивов.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 23-01-2020, 10:44:58
То есть получается, что без костылей никак?
Скажите а в .net такие функции присутствуют?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-01-2020, 11:05:19
Скажите а в .net такие функции присутствуют?
В .NET у BlockReference есть свойство BlockTransform, которое возвращает матрицу преобразования из координат блока в координаты МСК (WCS).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-01-2020, 11:09:23
Вот как решается эта задача в .NET: https://adn-cis.org/forum/index.php?topic=2933.msg12071#msg12071
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 23-01-2020, 14:34:05
Ну даже и с помощью .NET не все так просто...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-01-2020, 17:54:25
В .NET в последних версиях AutoCAD есть метод BlockReference.GeometryExtentsBestFit - я не проверял, но вполне возможно, что он учитывает и установленную видимость в динамическом блоке.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-01-2020, 12:45:21
Возможно ли в AutoCAD с помощью COM или .Net определить, что объект на чертеже (например,  отрезок или блок, как на рисунке ниже) находится внутри прямоугольной рамки-полилинии без применения математических расчетов с координатами и границами boundingbox?
Я нашел IntersectWith метод, но если применить его к блоку и синей полилинии ниже - метод просто возвращает пустой список пересечений, т.к. объекты формально не пересекаются. То же самое, если рамка выполнена блоком.

(https://i.postimg.cc/VdSqcPnX/test.jpg) (https://postimg.cc/VdSqcPnX)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-01-2020, 12:50:49
Код - Visual Basic [Выбрать]
  1. SelectionSet.Select acSelectionSetWindow p1 p2
Точки p1 и p2 должны быть видимы на экране.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-01-2020, 12:56:39
Да нет, не выделить объекты на чертеже, а определить, что уже нарисованный блок находится внутри уже нарисованной полилинии. Я так понимаю, такого метода нет, но хочу убедиться наверняка.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-01-2020, 13:05:25
Electric,
Ты таким образом не выделяешь, а находишь все объекты внутри окна (т.е. твоего прямоугольника). Если объект внутри окна, то он попадёт в набор, если нет - нет. Другого способа нет.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 27-01-2020, 16:08:05
Понял. Спасибо за наводку!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 25-02-2020, 21:12:42
Добрый день!
Сталкиваюсь с такой проблемой, например, если программа довольно продолжительное время работает, существует проблема, что
если пользователь ткнет в чертеж или нажмет на клавишу, то при обращении к AutoCad выпадет исключение.
Можно ли как то заблокировать работу автокад на время работы скрипта?
Можно, конечно ловить исключения, но тогда придется ловить каждое обращение к автокаду, что сильно усложняет программу...
Может есть какой нибудь стандартный способ уйти от этого?
Ну и если есть такой, то сразу возникнет обратная задача, прервать работу скрипта и разблокировать автокад...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-02-2020, 21:44:04
Можно ли как то заблокировать работу автокад на время работы скрипта?
Заблокировать через COM/ActiveX нельзя. Можно сделать его невидимым: Application.Visible = False
Ну или контролировать его состояние через Application.GetAcadState().IsQuiescent  - если True, то можно выполнять очередное действие.
Но исключения нужно ловить в любом случае.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 25-02-2020, 23:37:26
То есть получается, в любом случае нужно разбивать код на участки, отлавливать исключения и если исключение возникает, код повторять заново? Ну либо вообще все сбрасывать.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-02-2020, 23:46:30
То есть получается, в любом случае нужно разбивать код на участки, отлавливать исключения и если исключение возникает, код повторять заново? Ну либо вообще все сбрасывать.
Именно так. Вот пример, как это делается в C++: https://adn-cis.org/kak-ispolzuya-visual-c-zapustit-autocad-i-zastavit-ego-vyipolnyat-nekotoryie-dejstviya.html
Для Python в принципе аналогично.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 26-02-2020, 04:11:48
Добрый день!
Сталкиваюсь с такой проблемой, например, если программа довольно продолжительное время работает, существует проблема, что
если пользователь ткнет в чертеж или нажмет на клавишу, то при обращении к AutoCad выпадет исключение.
Можно ли как то заблокировать работу автокад на время работы скрипта?
Можно, конечно ловить исключения, но тогда придется ловить каждое обращение к автокаду, что сильно усложняет программу...
Может есть какой нибудь стандартный способ уйти от этого?
Ну и если есть такой, то сразу возникнет обратная задача, прервать работу скрипта и разблокировать автокад...

Я как-то для подобных целей использовал такой танец с бубном. Вставляю функцию в наиболее проблемные участки кода, когда нужно дождаться AutoCAD, а он занят черчением или может не ответить на запрос, пытаюсь получить доступ к пространству модели, иначе жду в цикле:

Код - Python [Выбрать]
  1. def dynamicPause():
  2.     wait_time = 0.1
  3.     while wait_time<10:
  4.         try:
  5.             app = win32com.client.Dispatch("AutoCAD.Application")
  6.             aDoc = app.ActiveDocument
  7.             mSp = aDoc.ModelSpace
  8.             break
  9.         except:
  10.             sleep(wait_time)
  11.             wait_time *= 2
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 26-02-2020, 12:07:14
Спасибо за ответы!

В принципе я так и так я и предполагал... просто надеялся, что может быть в автокаде есть что то для упрощения этой задачи...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 26-02-2020, 12:08:23
А это неплохое решение, возьму на вооружение... спасибо!

Я как-то для подобных целей использовал такой танец с бубном. Вставляю функцию в наиболее проблемные участки кода, когда нужно дождаться AutoCAD, а он занят черчением или может не ответить на запрос, пытаюсь получить доступ к пространству модели, иначе жду в цикле:

Код - Python [Выбрать]
def dynamicPause():
    wait_time = 0.1
    while wait_time<10:
        try:
            app = win32com.client.Dispatch("AutoCAD.Application")
            aDoc = app.ActiveDocument
            mSp = aDoc.ModelSpace
            break
        except:
            sleep(wait_time)
            wait_time *= 2
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 28-02-2020, 22:44:09
Всем добра!
Подскажите, как вставить блок в Autocad при помощи метода InsertBlock?
В VBA работала строка:

Код - Visual Basic [Выбрать]
  1. insertionPnt(0) = 377.7541: insertionPnt(1) = 304.5495: insertionPnt(2) = 0
  2. Set blockRefObj = acadDoc.ModelSpace.InsertBlock(insertionPnt, "сектор-план", 1#, 1#, 1#, a1r)

Как данную строку перевести в питон?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 28-02-2020, 22:56:03
DFG2020,
Приветствую на форуме!
Обрати внимание на правило форматирования кода у нас на форуме (у меня в подписи) и соблюдай его.
Что касается вопроса, то как-то так наверное:
Код - Python [Выбрать]
  1. import array
  2. import comtypes.client
  3. app = comtypes.client.GetActiveObject("AutoCAD.Application")
  4. ms = app.ActiveDocument
  5. files = r"сектор-план"
  6. insertionPnt = array.array('d', [377.7541,304.5495,0])
  7. ms.ModelSpace.InsertBlock(insertionPnt, files, 1, 1, 1, 0)
P.S.: На Python я не пишу. Этот код - результат двухминутного поиска в интернет.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 28-02-2020, 23:31:28
Что касается вопроса, то как-то так наверное:
Получаю ошибку:
    import comtypes.client
ModuleNotFoundError: No module named 'comtypes'
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 28-02-2020, 23:36:08
А если использовать
import win32com.client
т.е. так:
Код - Python [Выбрать]
  1. import win32com.client
  2. import array
  3.  
  4. app = win32com.client.Dispatch("AutoCAD.Application")
  5. acadDoc = app.ActiveDocument
  6.  
  7. files = r"сектор-план"
  8. insertionPnt = array.array('d', [377.7541,304.5495,0])
  9. acadDoc.ModelSpace.InsertBlock(insertionPnt, files, 1, 1, 1, 0)

получаю ошибку:
    acadDoc.ModelSpace.InsertBlock(insertionPnt, files, 1, 1, 1, 0)
  File "<COMObject <unknown>>", line 5, in InsertBlock
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147024809), None)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 28-02-2020, 23:51:06
А если использовать
import win32com.client
т.е. так:
Код - Python [Выбрать]
import win32com.client
import array
 
app = win32com.client.Dispatch("AutoCAD.Application")
acadDoc = app.ActiveDocument
 
files = r"сектор-план"
insertionPnt = array.array('d', [377.7541,304.5495,0])
acadDoc.ModelSpace.InsertBlock(insertionPnt, files, 1, 1, 1, 0)

получаю ошибку:
    acadDoc.ModelSpace.InsertBlock(insertionPnt, files, 1, 1, 1, 0)
  File "<COMObject <unknown>>", line 5, in InsertBlock
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, None, None, None, 0, -2147024809), None)

Нашел решение, правда сам не до конца понял, как оно работает, но оно работает!))

Код - Python [Выбрать]
  1. import win32com.client
  2. import pythoncom
  3.  
  4. def POINT(x,y,z):
  5.     return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x,y,z))
  6.  
  7. acad = win32com.client.Dispatch("AutoCAD.Application")
  8. doc = acad.ActiveDocument
  9. ms = doc.ModelSpace
  10. files = "сектор-план"
  11. doc.Utility.Prompt("hello World\n")
  12. pt1= POINT(0.0,0.0,0.0)
  13. ms.InsertBlock(pt1, files, 1.0,1.0,1.0, 0)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 29-02-2020, 00:33:41
правда сам не до конца понял, как оно работает, но оно работает!
Функция POINT на основе переданных трёх чисел (x, y, z) формирует VARIANT, соответствующий массиву (VT_ARRAY) из чисел типа double (плавающие с двойной точностью VT_R8). Ну а дальше всё аналогично тому примеру, который я давал.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 02-03-2020, 21:30:30
Спасибо, Александр!

Не смог найти кнопку Решение, подскажите, где она.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 02-03-2020, 21:37:24
DFG2020,
Кнопка <<Решение>> есть только у того, кто создал тему и у Администраторов/Модераторов. Так что у вас в распоряжении только кнопочки [+].
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 04-03-2020, 08:25:00
Существует ли способ программно определить не пользовательскую, а фактическую ширину MText? Т.е. размеры выделенной области с текстом, а не саму ширину рамки-рулетки на рисунке:
(https://i.postimg.cc/LnMPtVDB/image.png) (https://postimg.cc/LnMPtVDB)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Владимир Шу от 04-03-2020, 09:00:11
В VBA, такое не сделали, а вот в .NET вроде бы есть:
MText.ActualHeight
MText.ActualWidth
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 23-03-2020, 22:34:02
Всем здоровья!)

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

Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 23-03-2020, 22:39:57
Всем здоровья!)

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

Спасибо!

Посмотри метод CopyObjects для копирования объектов из одного блока в другой (есть пример в этой теме). Ну а ненужное потом удалишь.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 24-03-2020, 00:01:47
Посмотри метод CopyObjects для копирования объектов из одного блока в другой (есть пример в этой теме).
У блока нет метода CopyObjects, в примере этот метод применяется к документу и , как я понял, создается копия блока в документе, но мне нужно "перезаписать" содержимое уже существующего блока.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-03-2020, 00:35:02
Посмотри метод CopyObjects для копирования объектов из одного блока в другой (есть пример в этой теме).
У блока нет метода CopyObjects, в примере этот метод применяется к документу и , как я понял, создается копия блока в документе, но мне нужно "перезаписать" содержимое уже существующего блока.
Ну значит ты не понял как работает этот метод. Ему нужно указать какой объект будет владельцем новых копий объектов. Вот этим владельцем и должен стать второй блок. Ну а из первого ничего удалять не нужно, так как ты собираешься удалить сам этот блок. В этом случае ты должен будешь сначала удалить все вставки (BlockReference) первого блока, а затем удалить сам блок (из таблицы Blocks)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 24-03-2020, 23:48:14
Ну значит ты не понял как работает этот метод. Ему нужно указать какой объект будет владельцем новых копий объектов. Вот этим владельцем и должен стать второй блок. Ну а из первого ничего удалять не нужно, так как ты собираешься удалить сам этот блок. В этом случае ты должен будешь сначала удалить все вставки (BlockReference) первого блока, а затем удалить сам блок (из таблицы Blocks)

пробую назначить владельца - блок 1, но не выходит, не тот тип данных для владельца, пробовал и первый блок перевести в массив, но тоже не тот тип данных. В примере выше есть строка: b_name = f"{o_blk.Name}_{i:02d}", это на JSON. Как это интерпретировать для питона?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 24-03-2020, 23:50:12
Пример, как я пробовал. Подскажите, как что можно исправить.

Код - Python [Выбрать]
  1. import win32com.client
  2. import pythoncom
  3.  
  4. app = win32com.client.Dispatch("AutoCAD.Application")
  5. acadDoc = app.ActiveDocument
  6. mSp = acadDoc.ModelSpace
  7.  
  8. block_1 = acadDoc.Blocks.Item("блок 1")
  9. block_2 = acadDoc.Blocks.Item("блок 2")
  10.  
  11. lst_1 = [e for e in block_1]
  12. lst_2 = [e for e in block_2]
  13.  
  14. def BLOCK(list):
  15.     return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (list))
  16.  
  17. v_lst_1 = BLOCK(lst_1)
  18. v_lst_2 = BLOCK(lst_2)
  19.  
  20. acadDoc.CopyObjects(v_lst_2, v_lst_1)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-03-2020, 23:52:09
В примере выше есть строка: b_name = f"{o_blk.Name}_{i:02d}", это на JSON. Как это интерпретировать для питона?
Это к теме не имеет отношения - это лишь для формата имени блока.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-03-2020, 23:56:19
1. Почему pythoncom.VT_R8 ???
2. Должно быть как-то так  (если копировать объекты блока 1 в блок 2):
Код - Python [Выбрать]
  1. acadDoc.CopyObjects(v_lst_1, block_2)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 25-03-2020, 00:00:21
2. Должно быть как-то так  (если копировать объекты блока 1 в блок 2):
Пробовал и так. Выдает:
TypeError: float() argument must be a string or a number, not 'CDispatch'
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 25-03-2020, 00:02:50
1. Почему pythoncom.VT_R8
Честно и сам не очень понимаю этот момент. Брал из другого примера для преобразования данных в массив.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-03-2020, 00:13:41
1. Почему pythoncom.VT_R8
Честно и сам не очень понимаю этот момент. Брал из другого примера для преобразования данных в массив.
Не нужно бездумно копипастить. Объекты AutoCAD - это не плавающие числа. Поэтому вместо pythoncom.VT_R8 должно быть (скорее всего) pythoncom.VT_DISPATCH.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-03-2020, 00:26:51
И вообще в этом примере есть всё, что нужно: https://adn-cis.org/forum/index.php?topic=7864.msg42066#msg42066
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 25-03-2020, 00:29:17
это на JSON
Это он случайно выбрал не тот тип форматирования - вместо Python указал JSON.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 26-03-2020, 23:29:49
Не нужно бездумно копипастить. Объекты AutoCAD - это не плавающие числа. Поэтому вместо pythoncom.VT_R8 должно быть (скорее всего) pythoncom.VT_DISPATCH.
Благодарю за этот комментарий! Основная часть пройдена: в блок 1 вставились все элементы блока 2! Теперь нужно удалить (или это нужно было сделать сначала), все первоначальные элементы из блока 1. Как это можно сделать?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 26-03-2020, 23:57:03
ИМХО лучше будет удалить все вхождения "Блок1", а потом уже удалить его описание.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 27-03-2020, 00:02:21
ИМХО лучше будет удалить все вхождения "Блок1", а потом уже удалить его описание.
А это не приведет к удалению блока 1 из тех мест, где он находится в файле? Задача стоит в том, что бы элементы блока 1 заменились на элементы блока 2, при этом все местоположения блока 1 в модели должны сохраниться.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-03-2020, 00:14:10
Задача стоит в том, что бы элементы блока 1 заменились на элементы блока 2, при этом все местоположения блока 1 в модели должны сохраниться.
Так может достаточно у вставок блока поменять свойство Name с "Блок 1" на "Блок 2" ???
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 27-03-2020, 00:19:19
Так может достаточно у вставок блока поменять свойство Name с "Блок 1" на "Блок 2"
Идея правильная, но как это сделать через питон?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-03-2020, 12:31:15
Так может достаточно у вставок блока поменять свойство Name с "Блок 1" на "Блок 2"
Идея правильная, но как это сделать через питон?
Выбрать все вставки блока с именем "Блок 1" и изменить им свойство Name на "Блок 2". На питоне не пишу, поэтому код не предоставлю.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 01-04-2020, 12:41:35
Пробую так:
Код - Python [Выбрать]
  1. block_1 = acadDoc.Blocks.Item("блок 1")
  2. block_1.Name = 'блок 2'

Выдает ошибку. Имя можно менять только на новое, например "блок 3", тогда ошибку не выдает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 01-04-2020, 12:45:57
Пробую так:
Код - Python [Выбрать]
  1. block_1 = acadDoc.Blocks.Item("блок 1")
  2. block_1.Name = 'блок 2'

Выдает ошибку. Имя можно менять только на новое, например "блок 3", тогда ошибку не выдает.
Имя нужно присваивать не Block (описание блока), а BlockReference (вставка блока), о чем я выше и писал.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 01-04-2020, 13:44:27
Имя нужно присваивать не Block (описание блока), а BlockReference (вставка блока), о чем я выше и писал.
Ох, никак не могу понять, как применить BlockReference в питоне...
Может есть ссылка на подобные примеры?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 01-04-2020, 13:58:30
Ох, никак не могу понять, как применить BlockReference в питоне...
На питоне вообще практически нет примеров для работы с AutoCAD.
Алгоритм такой. Тебе нужно найти все BlokReference в чертеже. Для этого ты можешь воспользоваться SelectionSet.Select и указать в качестве фильтра "INSERT" (это и есть BlockReference). Дальше проходишься по всем элементам полученного набора и проверяешь свойство Name - если "Блок 1", то меняешь на "Блок 2".
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 01-04-2020, 14:14:56
Начни отсюда и еще несколько следующих сообщений: https://adn-cis.org/forum/index.php?topic=7864.msg40087#msg40087
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 01-04-2020, 17:40:09
Ура! Все заработало, но без SelectionSets, и очень долго, когда в файле много объектов.
Код - Python [Выбрать]
  1. import win32com.client
  2. import pythoncom
  3.  
  4. acad = win32com.client.Dispatch("AutoCAD.Application")
  5. doc = acad.ActiveDocument
  6.  
  7. for entity in acad.ActiveDocument.ModelSpace:
  8.     name = entity.EntityName
  9.     if name == 'AcDbBlockReference':
  10.         NameAttributes = entity.Name
  11.         if NameAttributes == 'блок 1':
  12.             entity.Name = 'блок 2'

Как можно сделать значительно быстрее? Использование SelectionSets поможет убыстрить процес?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 01-04-2020, 17:43:43
Как можно сделать значительно быстрее? Использование SelectionSets поможет убыстрить процес?
Не думаю, что что-то может этот код ускорить. Разве что отказ от Python, который выполняется в отдельном процессе от AutoCAD, что приводит к замедлению.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 01-04-2020, 17:58:37
Не думаю, что что-то может этот код ускорить.
Может быть как-то можно сделать перебор не всех элементов в Модели, а только вставок блока?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 01-04-2020, 19:34:56
Не думаю, что что-то может этот код ускорить.
Может быть как-то можно сделать перебор не всех элементов в Модели, а только вставок блока?
А это как раз можно, но только через SelectionSet
Название: Re: Python & ActiveX/COM Autocad
Отправлено: mvv_010 от 02-04-2020, 22:53:15
Код - Python [Выбрать]
  1. from comtypes.client import CreateObject, GetActiveObject
  2. from array import array
  3.  
  4. try:
  5.     acad = GetActiveObject("AutoCAD.Application", dynamic=True)
  6. except:
  7.     acad = CreateObject("AutoCAD.Application", dynamic=True)
  8.  
  9. try:
  10.     select = acad.ActiveDocument.SelectionSets.Add("SSET_Blocks")
  11. except:
  12.     select = acad.ActiveDocument.SelectionSets.Item("SSET_Blocks")
  13.     select.Clear()
  14.  
  15. # all_block = [block.Name for block in acad.ActiveDocument.Blocks]
  16. # Имена всех блоков в чертеже включая ModelSpace и PaperSpace
  17.  
  18. Name_Block = ""# Имя вашего блока
  19. FilterType = array("h", [0, 2])# Коды в документации к DXF
  20. FilterDate = ["INSERT", Name_Block]
  21. SelectAll = 5# Режим выбора
  22. point = array("d", [0, 0, 0])
  23.  
  24. select.Select(SelectAll, point, point, FilterType, FilterDate)
  25. print("Select blocks:", select.Count)
  26. for obj in select:# Перебор выбранных элементов
  27.     pass
  28.  
  29. acad = None
  30.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 02-04-2020, 23:03:58
mvv_010,
Код 100 не нужен. И вообще фильтрация по этому коду не работает в большинстве случаев.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 04-04-2020, 01:19:41
Подскажите, как можно поменять прорисовку текста, а точнее вынести на передний план?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 04-04-2020, 15:01:10
Подскажите, как можно поменять прорисовку текста, а точнее вынести на передний план?
Посмотри в документации метод MoveToTop. Там и пример есть на VBA: https://knowledge.autodesk.com/ru/search-result/caas/CloudHelp/cloudhelp/2016/RUS/AutoCAD-ActiveX/files/GUID-0FA80CF9-427C-40F1-A400-BFD4AE81EE99-htm.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 10-04-2020, 15:16:01
Доброго дня!
Подскажите, куда копать,
У меня в чертеже два блока, разбиваю оба функцией

Код - Python [Выбрать]
  1. blk.Explode()

При этом оба блока разбиваются, но при выполнении этой функции с одним из блоков, функция возвращает список элементов получившихся при рабивании,
а для другого блока возвращается пустой список. Причем фактически в чертеже оба блока разбиваются. Есть ли идеи с чем это может быть связано? (Может быть связано с масштабами?)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-04-2020, 15:19:44
DMuzer,
Нужно смотреть на блоки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 10-04-2020, 15:20:18
Да, странное дело, у того блока, который не возвращал массива элементов установлен масштаб 110, меняю на 100, функция начинает возвращать элементы.
Почему?
Выяснилась такая штука, ошибочно  масштаб по Z отличался от масштабав по Х и Y. В этой ситуации функция не возвращает списка объектов.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-04-2020, 15:26:35
Да, странное дело, у того блока, который не возвращал массива элементов установлен масштаб 110, меняю на 100, функция начинает возвращать элементы.
Почему?
О каком масштабе идёт речь? Есть масштабы по X,Y,Z, а есть масштаб аннотаций. Если масштабы по X,Y,Z отличаются, то Explode очень часто не срабатывает, ну и соответственно ничего не возвращает.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 10-04-2020, 15:38:38
Цитата: DMuzer от 10-04-2020, 15:20:18
Да, странное дело, у того блока, который не возвращал массива элементов установлен масштаб 110, меняю на 100, функция начинает возвращать элементы.
Почему?
О каком масштабе идёт речь? Есть масштабы по X,Y,Z, а есть масштаб аннотаций. Если масштабы по X,Y,Z отличаются, то Explode очень часто не срабатывает, ну и соответственно ничего не возвращает.

Ну видимо это как раз тот случай. Устанавливаю одинаковые масштабы, все начинает работать.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 10-04-2020, 15:41:59
Ну видимо это как раз тот случай. Устанавливаю одинаковые масштабы, все начинает работать.
Интересно, а что внутри этого блока? И какая версия AutoCAD?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 10-04-2020, 17:35:22
И что с EXPLMODE ( https://knowledge.autodesk.com/ru/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2018/RUS/AutoCAD-Core/files/GUID-113BD30D-2F46-4E23-9B49-034AB50064A7-htm.html )?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 14-04-2020, 23:33:28
Всем добра!

Подскажите, как к координатам в виде VARIANT задать смещение на заданную величину? Т.е. у меня есть точка в формате VARIANT, как задать ее смещение, т.е. изменить одну или несколько ее  параметров x или y?
Все это в питоне.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 15-04-2020, 10:21:58
Всем добра!

Подскажите, как к координатам в виде VARIANT задать смещение на заданную величину? Т.е. у меня есть точка в формате VARIANT, как задать ее смещение, т.е. изменить одну или несколько ее  параметров x или y?
Все это в питоне.
Преобразовать в массив double, изменить соответствующие элементы массива и обратно преобразовать в VARIANT.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: mvv_010 от 15-04-2020, 19:02:05
DFG2020,
Код - Python [Выбрать]
  1. def POINT(list):
  2.     return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (list))
  3.  
  4. # Как поменять VARIANT
  5. bl = (POINT([1,2,3]))# win32com.client.VARIANT(8197, [1, 2, 3])
  6. bl.value[0] += 10
  7. bl.value[1] += 10
  8. bl.value[2] += 10
  9. print(bl) # win32com.client.VARIANT(8197, [11, 12, 13])
  10.  
  11. # Правка координат для точки
  12. point_1 = acad.ActiveDocument.ModelSpace.AddPoint(POINT([1,2,3]))
  13. print(point_1.Coordinates) # (1.0, 2.0, 3.0)
  14. # Так как возвращается кортеж, переводим его в список и меняем.
  15. listCoordinates = list(point_1.Coordinates)
  16. listCoordinates[0] += 10
  17. listCoordinates[1] += 20
  18. listCoordinates[2] += 30
  19. point_1.Coordinates = POINT(listCoordinates)
  20. # Или так
  21. point_1.Coordinates = POINT([point_1.Coordinates[0] + 10,
  22.                      point_1.Coordinates[1] + 20,
  23.                      point_1.Coordinates[2] + 30])
  24.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 26-04-2020, 15:33:15
Всем терпения!

Подскажите пожалуйста, как использовать Lineweight в питоне, как применить толщину acLnWt030?
В примере для VBA строка выглядит просто: Obj.Lineweight = acLnWt211
Но в питоне выдает ошибку. Как преобразовать acLnWt211 для использования в питоне?

Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-04-2020, 16:55:47
Как преобразовать acLnWt211 для использования в питоне?
Подставь просто целое число 211:
Код - C++ [Выбрать]
  1. enum AcLineWeight
  2.     {
  3.         acLnWt000       = 0,
  4.         acLnWt005       = 5,
  5.         acLnWt009       = 9,
  6.         acLnWt013       = 13,
  7.         acLnWt015       = 15,
  8.         acLnWt018       = 18,
  9.         acLnWt020       = 20,
  10.         acLnWt025       = 25,
  11.         acLnWt030       = 30,
  12.         acLnWt035       = 35,
  13.         acLnWt040       = 40,
  14.         acLnWt050       = 50,
  15.         acLnWt053       = 53,
  16.         acLnWt060       = 60,
  17.         acLnWt070       = 70,
  18.         acLnWt080       = 80,
  19.         acLnWt090       = 90,
  20.         acLnWt100       = 100,
  21.         acLnWt106       = 106,
  22.         acLnWt120       = 120,
  23.         acLnWt140       = 140,
  24.         acLnWt158       = 158,
  25.         acLnWt200       = 200,
  26.         acLnWt211       = 211,
  27.         acLnWtByLayer   = -1,
  28.         acLnWtByBlock   = -2,
  29.         acLnWtByLwDefault       = -3
  30.     }   AcLineWeight;
  31.  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 26-04-2020, 21:01:01
Подскажите, как задать начальную и конечную ширину ломаной линии object.SetWidth SegmentIndex, StartWidth, EndWidth? Линия состоит из одного элемента.
При воспроизводстве данного метода в питоне возникает ошибка, возможно тип данных SegmentIndex не соответствует питону. SegmentIndex - тип данных Integer.
Если задавать как object.SetWidth 0, 5, 5 - ошибка "SyntaxError: invalid syntax" на первом значенни "0"
Если задавать как object.SetWidth , 5, 0 - ошибки нет, но ничего не меняется.


Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-04-2020, 21:13:47
Первый аргумент должен быть целым (int), а второй и третий - плавающим (double)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 26-04-2020, 23:44:00
Первый аргумент должен быть целым (int)
А 0 - это не целое (int)?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 26-04-2020, 23:46:55
А 0 - это не целое (int)?
В Python - не знаю. Может long, может short. Впрочем можешь попробовать short. Но главное второй и третий аргументы должны быть double.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 26-04-2020, 23:50:16
В Python - не знаю. Может long, может short. Впрочем можешь попробовать short. Но главное второй и третий аргументы должны быть double.
Первый аргумент ставлю 0, но питон ругается именно на него:
    arrow_B.SetWidth 0, 5, 5
                               ^
SyntaxError: invalid syntax
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-04-2020, 00:08:32
В Python - не знаю. Может long, может short. Впрочем можешь попробовать short. Но главное второй и третий аргументы должны быть double.
Первый аргумент ставлю 0, но питон ругается именно на него:
    arrow_B.SetWidth 0, 5, 5
                               ^
SyntaxError: invalid syntax
Так это же ошибка синтаксиса, а не типа данных. Может быть как-то так:
Код - Python [Выбрать]
  1.  arrow_B.SetWidth (0, 5.0, 5.0)
???
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 27-04-2020, 00:18:46
Так это же ошибка синтаксиса, а не типа данных.
Ох, да , не отметил, что в питоне нужно добавлять скобки!

Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 30-04-2020, 16:28:05
Возможно я задавал этот вопрос раньше, точно не помню. В AutoCAD последних версий есть полезная возможность импортировать геометрию PDF документов, как раз появилась необходимость автоматизировать этот процесс. Существует ли какая-нибудь возможность через COM работать с этой новой функцией распознавания геометрии? Или COM слишком стар для этого?

Единственное, что я нашел, это возможность через текстовую строку отправить  команду AcadDocument.SendCommand("_-ПДФИМПОРТ "), но далее возникают проблемы с  аргументами. На запрос "Выберите подложку PDF или <Файл>" я могу отправить Ф и AutoCAD тут  же открывает графическое окно выбора файла. Если ли способ передать путь к этому файлу в виде текстовой строки вроде "F:\\target.pdf" в обход графического меню?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 30-04-2020, 17:32:08
Существует ли какая-нибудь возможность через COM работать с этой новой функцией распознавания геометрии?
Нет.
Единственное, что я нашел, это возможность через текстовую строку отправить  команду AcadDocument.SendCommand("_-ПДФИМПОРТ ")
Нужно послать такое lisp-выражение в качестве строки:
Код - Auto/Visual Lisp [Выбрать]
  1. (command "_-pdfimport" "_f" "C:/test.pdf" "1" "0,0" "1" "0")
Не забудь:
1) двойные кавычки следует сдублировать;
2) после закрывающейся круглой скобки нужен еще один пробел;
3) "C:/test.pdf" - полный путь к pdf-файлу и обратные слеши заменяем на прямые;
4) первая "1" в команде - номер страницы из pdf-файла;
5) "0,0" - точка вставки страницы;
6) вторая "1" - масштабный коэффициент;
7) "0" - угол поворота.
Наверное это будет как-то так:

Код - Python [Выбрать]
  1. AcadDocument.SendCommand('(command "_-pdfimport" "_f" "C:/test.pdf" "1" "0,0" "1" "0") ')
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 30-04-2020, 18:33:42
AcadDocument.SendCommand('(command "_-pdfimport" "_f" "C:/test.pdf" "1" "0,0" "1" "0") ')

Спасибо, это то, что нужно!
А если бы, чисто теоретически, мне потребовалось бы применить больше настроек ("Данные PDF для импорта", "Слои", "Параметры импорта"), то эти настройки так же следовало бы вписывать в эту текстовую команду? Есть ли документация на подобные lisp команды?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 30-04-2020, 18:46:49
А если бы, чисто теоретически, мне потребовалось бы применить больше настроек ("Данные PDF для импорта", "Слои", "Параметры импорта"), то эти настройки так же следовало бы вписывать в эту текстовую команду?
Думаю, что это через системные переменные:
(https://live.staticflickr.com/65535/49837778716_db0c54ce48_o.png)

Есть ли документация на подобные lisp команды?
На какие команды?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 01-05-2020, 10:39:29
Есть ли документация на подобные lisp команды?
На какие команды?

Все, я разобрался. Вопрос снят. Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 06-05-2020, 22:31:49
Всем добра!

Подскажите, как воспользоваться командой ВСТСПЕЦ через COM? Т.е. у меня есть скопированный диапазон ячеек в excel, как его вставить питоном в автокад, используя команду ВСТСПЕЦ/Объекты AutoCad?                  
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-05-2020, 22:38:57
Эту команду нельзя запустить в режиме командной строки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 06-05-2020, 22:42:03
Эту команду нельзя запустить в режиме командной строки.
Можно каким-то другим способом вставить таблицу эксел как объект автокад питоном?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-05-2020, 22:58:16
Если на Python можно прочитать excel-файл, то на основе его можно создать таблицу в AutoCAD. Подозреваю, что если это даже и возможно, то очень не просто.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 07-05-2020, 04:31:44
Если на Python можно прочитать excel-файл, то на основе его можно создать таблицу в AutoCAD. Подозреваю, что если это даже и возможно, то очень не просто.

Я так кстати и делал недавно. Питоновская библиотека openpyxl +  создание таблицы по полученным данным через COM.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 08-05-2020, 18:03:23
Я так кстати и делал недавно.
Electric, прошу выслать данные наработки, если сохранились.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 08-05-2020, 20:57:51
Electric, прошу выслать данные наработки, если сохранились.

Минимальный пример без повтора объединения ячеек, считывания по диапазону и т.д.

Код - Python [Выбрать]
  1. from openpyxl import load_workbook
  2. import win32com.client
  3.  
  4. def readFromExcelFile(filename, page_name):
  5.     ''' Функция чтения Excel файла
  6.    filename - полный путь к файлу xlsx
  7.    page_name - название листа в документе    
  8.    '''
  9.     wb = load_workbook(filename, data_only=True)
  10.     sheet = wb[page_name]
  11.  
  12.     # Номер максимальной строки и столбца с данными на листе
  13.     row_count = sheet.max_row
  14.     column_count = sheet.max_column
  15.  
  16.     # Считывание текстовых данных по ячейкам, нумерация начинается c 1
  17.     data = [[sheet.cell(row=row_num, column=col_num).value for col_num in range(1, column_count+1)] for row_num in range(1, row_count+1)]
  18.     return data
  19.  
  20.  
  21. def writeAcadTable(data):
  22.     ''' Функция записи таблицы в Autocad '''
  23.  
  24.     app = win32com.client.Dispatch("AutoCAD.Application")    
  25.     aDoc = app.ActiveDocument
  26.     mSp = aDoc.ModelSpace
  27.  
  28.     # Число строк и столбцов в таблице
  29.     row_count = len(data)    
  30.     column_count = len(data[0])
  31.  
  32.     insertion_point = aDoc.Utility.GetPoint(convert_coordinates(0, 0, 0), 'Укажите точку вставки в пространстве  модели: ')
  33.     table = mSp.AddTable(convert_coordinates(insertion_point), row_count, column_count, 10, 30)
  34.     table.UnmergeCells(0, 0, 0, column_count-1)
  35.  
  36.     # Заполнение таблицы AutoCAD текстовыми данными
  37.     for i in range(row_count):        
  38.         for j in range(column_count):            
  39.             if data[i][j]:                
  40.                 table.SetText(i, j, data[i][j])
  41.  
  42. if __name__=='__main__':
  43.     data = readFromExcelFile('C:\\test.xlsx', 'Лист1')
  44.     writeAcadTable(data)
  45.  
  46.  

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

Код - Python [Выбрать]
  1. sheet = wb.worksheets[0]

В функции записи writeAcadTable  функция "convert_coordinates" - взята из начала темы (https://adn-cis.org/forum/index.php?topic=7864.msg28996#msg28996).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 12-05-2020, 22:24:26
Electric, спасибо!!!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 24-05-2020, 17:59:15
Заметил странное поведение при попытке установить выравнивание ячеек таблицы.
Есть таблица AutoCAD  5 строк, 4 столбца, выравнивание во всех ячейках  по умолчанию стоит "середина по центру".
Если я хочу назначить выравнивание "4" (середина влево) для строки с индексом "2" я пишу  "-1" в  качестве  индекса столбца:

Код - Python [Выбрать]
  1. table.SetCellAlignment(2, -1, 4)

и тогда по всей строке 2 выравнивание становится серединой влево.
Но если я пытаюсь применить подобный трюк с колонкой, а именно назначить всем ячейкам в  колонке с индексом 2 такое  выравнивание:

Код - Python [Выбрать]
  1. table.SetCellAlignment(-1, 2, 4)

у меня ничего не происходит. Что я делаю не так?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 24-05-2020, 19:35:56
у меня ничего не происходит. Что я делаю не так?
В принципе всё так. Проверил в AutoCAD 2021 - действительно целиком колонке выравнивание задать нельзя. Возможно причина как-то связана с разными типами данных в разных колонках (Title, Header, Data). Так что задавать выравнивание придётся в цикле всем ячейкам колонки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 27-06-2020, 13:01:11
Коллеги, подскажите вот что,
построение чертежа занимает много времени. Можно ли как то на время приостановить отрисовку и после завешения построения обновить чертеж чтобы хоть как то ускорить процесс, по типу как это можно сделать с таблицей установив RegenerateTableSuppressed в False?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 27-06-2020, 13:58:42
Средствами COM/ActiveX приостановить отрисовку нельзя. Можно скрыть окно AutoCAD, а потом его сделать видимым. Но это вряд ли как-то ускорит построение чертежа. Кстати, обновление чертежа - это регенерация. И процесс регенерации может быть достаточно длительным.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 06-07-2020, 08:31:08
Есть другой вариант: создать анонимный блок, все сделать внутри него, потом блок вставить, разбить и уничтожить вхождение блока.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 08-07-2020, 18:49:11
Всем добра!

Такая задача: после конвертации из pdf на чертеже присутствует множество прямоугольных треугольников примерно одинаковой площади. Как их можно удалить одним махом, написав прогу в pythone? Треугольники состоят из полилинии. Можно как-то их всех найти по площади?

Спасибо!
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 08-07-2020, 19:43:13
Всем добра!

Такая задача: после конвертации из pdf на чертеже присутствует множество прямоугольных треугольников примерно одинаковой площади. Как их можно удалить одним махом, написав прогу в pythone? Треугольники состоят из полилинии. Можно как-то их всех найти по площади?

Спасибо!

Требуется просто удалить их, к примеру, через поиск?
Или нужно объединить их и заменить нормальными фигурами. Как если все прямые перевелись в виде состыкованных по гипотенузе прямоугольных треугольников.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 08-07-2020, 21:57:30
Требуется просто удалить их, к примеру, через поиск?
Да, просто удалить.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 08-07-2020, 22:04:18
Можно как-то их всех найти по площади?
Нет. Да и вообще если бы это было можно, то способ был бы какой-то ненадежный. Нужно отобрать все полилинии (возможно на каком-то определенном слое), а затем уже обработать полученный набор:
1. Проверить, что у полилинии 3 вершины
2. Проверить, что они образуют прямоугольный треугольник
3. Проверить (возможно), что площадь в каких-то пределах
4. Проверить если есть еще какие-то критерии
Если все условия удовлетворяют, то удалить.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DFG2020 от 08-07-2020, 22:17:26
Если все условия удовлетворяют, то удалить.
Спасибо за ответ. Видимо проще вручную удалить.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 06-09-2020, 18:35:51
Мой скрипт считывает GetBoundingBox() нетекстовых объектов внутри блока, чтобы получить потом минимальную и максимальные точки всех нетекстовых объектов.  Координаты считываются сначала внутри блока, затем с учетом точки вставки, угла поворота и общего зеркалирования перевожу их в общие для чертежа.
Я заметил, что если объект отзеркален с помощью параметра "Отразить" внутри блока (не командой "отразить зеркально" с главной панели), его координаты GetBoundingBox() возвращаются точно такими же.  Я ошибаюсь или это так и должно быть?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 06-09-2020, 20:35:18
Может, стоит обращаться к описанию не динамического блока, а к описанию именно этого анонимного? Т.е. вместо EffectiveName использовать простой Name?
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 06-09-2020, 20:41:23
Координаты считываются сначала внутри блока, затем с учетом точки вставки, угла поворота и общего зеркалирования перевожу их в общие для чертежа.
Вот тут и вопрос. Внутри какого блока? Алексей Кулик правильно написал. Если работать с анонимным блоком, соответствующим текущему состоянию динамического блока, то никакие динамические параметры учитывать уже не нужно - они уже в этом анонимном блоке учтены. Плюс еще учтена и видимость примитивов внутри блока (см. у них свойство Visible).
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 07-09-2020, 05:19:21
Похоже, я плаваю в терминологии, я не знаком с понятием анонимного блока  :-\
У меня просто динамический блок.

У меня есть блок "Клемма_терминала", которую я создал. В ней атрибут "оттразить", который зеркалит ее по горизонтали. Обычно обращение к подобным блокам по EffectiveName проблем не вызывало, значение текстовых аттрибутов, координаты примитивов и прочее - считывалось без проблем.  Но вот считывание GetBoundingBox()  у  отраженного прямоугольника возвращает те же координаты, что и в исходном состоянии.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Алексей Кулик от 07-09-2020, 07:40:32
У вхождения динамического блока (файл не качал, некогда) есть его т.н. "эффективное имя" - которое отображается в панели свойств. А есть обычное имя - которое на самом деле не видно.
Если obj - указатель на вхождение блока, то посмотри, что вернет obj.Name и obj.EffectiveName. И проходить тебе надо именно по doc.Blocks(obj.Name)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 07-09-2020, 08:36:51
Спасибо! Наконец разобрался. Через obj.Name все работает,  не использовал его раньше.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: vxv от 09-09-2020, 09:43:44
Доброго времени суток, Всем кто читает это. Пишу внешнюю программу на Python 3.7 32-bit на виндовс 7. Сам новичок в этом деле и многое не понятно. Хочется систематизировать информацию, которой очень мало на данную тему в интернете. Для начала пытался создать все примитивы через библиотеку ezdxf. Все получилось, но результат меня не устроил. Все что было нарисовано, было сделано без открытия активной модели автокад и сохранено в файл *.dxf. Приходилось открывать этот файл и копировать с базовой точкой от туда в активный документ автокад, что само по себе рушило всю магию работы. Пытался как то это копировать в буфер без открытия, тоже ни чего не получилось. И в следствии решил изучить COM Autocad. На данном этапе остановился на штриховке, ее создании. На моменте задания внешних и внутренних границ все что я бы не делал терпит неудачу. Нашел следующий код на IronPython:

Код - Python [Выбрать]
  1. # Load the Python Standard and DesignScript Libraries
  2. import sys, clr, System
  3. clr.AddReference('ProtoGeometry')
  4. from Autodesk.DesignScript.Geometry import *
  5. from math import tan, radians
  6. from System import Array
  7. # Create Hatch
  8. outerLoop=Array.CreateInstance(AcadEntity,1)
  9. outerLoop[0] = allPoly[0]
  10. innerLoop=Array.CreateInstance(AcadEntity,1)
  11. innerLoop[0] = allPoly[1]
  12. hatchObj = SPACE.AddHatch(0, "ANSI31", True)
  13. hatchObj.AppendOuterLoop(outerLoop)
  14. hatchObj.AppendInnerLoop(innerLoop)
  15. hatchObj.Evaluate()
  16. hatchObj.PatternScale = 1
  17. CAD.Application.Update()
  18. # Assign your output to the OUT variable.
  19. OUT = allPoly, innerLoop

Похожий вопрос был от пользователя  Khasan Mamaev « Ответ #12 : 13-11-2017, 12:14:55 »:
Код - Python [Выбрать]
  1. def plineToRegion(pl):
  2.         entArr = Array.CreateInstance(AcadEntity,1)
  3.         entArr.SetValue(pl,0)
  4.         return msp.AddRegion(entArr)  

Решение было от dlobyntsev « Ответ #13 : 13-11-2017, 16:26:50 »:

Код - Python [Выбрать]
  1. def plineToRegion(pl):
  2.     msp.AddRegion(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [pl]))

Но не пойму как это запустить.
Помогите создать штриховку с указанием внешних и внутренних границ пожалуйста???
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 11-09-2020, 19:00:50
Если нужно создать именно region, т.е. область, то это так  на COM:

Код - Python [Выбрать]
  1. import win32com.client
  2. from pythoncom import VT_ARRAY, VT_R8, VT_DISPATCH
  3.  
  4. def cc(*args):
  5.     '''
  6.    Функция преобразования координат в формат AutoCAD
  7.    :param args: координаты для преобразования, допустима передача списка или кортежа
  8.    :return: Координаты в формате AutoCAD
  9.    '''
  10.     if isinstance(args[0], (list, tuple)):
  11.         coords = [item for item in args[0]]
  12.     else:
  13.         coords = args
  14.     return win32com.client.VARIANT(VT_ARRAY | VT_R8, coords)
  15.  
  16. if __name__=='__main__':
  17.  
  18.     # Доступ к пространству модели
  19.     app = win32com.client.Dispatch("AutoCAD.Application")
  20.     aDoc = app.ActiveDocument
  21.     mSp = aDoc.ModelSpace
  22.  
  23.     # Добавим  два круга, к примеру. Первый аргумент - координата центра, второй - радиус
  24.     circle1 = mSp.AddCircle(cc(0,0,0), 10)
  25.     circle2 = mSp.AddCircle(cc(50,50,0), 20)
  26.  
  27.     # преобразуем  круги в "области"
  28.     region1 = mSp.AddRegion(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle1, circle2]))


Но это область, это не штриховка. Только сейчас  поймал себя на мысли, что никогда не использовал этот объект в своей  работе, видимо, электрикам он не пригождается.
Если надо создать штриховку, то должно быть как-то так:

Код - Python [Выбрать]
  1. hatch1 = mSp.AddHatch(PatternType = 1,
  2.                          PatternName = "ANSI31",
  3.                         Associativity = True,
  4.                         HatchObjectType = 1)
  5.  
  6. hatch1.AppendOuterLoop(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle1, circle2]))

Но лично у меня при попытке назначить такую штриховку вылетает ошибка:

Цитировать
hatch1 = mSp.AddHatch(PatternType = 1,
  File "C:\Users\2E78~1\AppData\Local\Temp\gen_py\3.8\E2077CF2-3573-4E66-B1DC-01118675056Dx0x1x0\IAcadModelSpace.py", line 254, in AddHatch
    ret = self._oleobj_.InvokeTypes(1579, LCID, 1, (9, 0), ((3, 1), (8, 1), (11, 1), (12, 17)),PatternType
pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD.Application', 'Пока не реализовано', 'C:\\Program Files\\Autodesk\\AutoCAD 2020\\HELP\\OLE_ERR.CHM', -2145386495, -2145386495), None)

Пока нереализовано...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 11-09-2020, 19:33:57
Но лично у меня при попытке назначить такую штриховку вылетает ошибка:

Цитировать

    hatch1 = mSp.AddHatch(PatternType = 1,
      File "C:\Users\2E78~1\AppData\Local\Temp\gen_py\3.8\E2077CF2-3573-4E66-B1DC-01118675056Dx0x1x0\IAcadModelSpace.py", line 254, in AddHatch
        ret = self._oleobj_.InvokeTypes(1579, LCID, 1, (9, 0), ((3, 1), (8, 1), (11, 1), (12, 17)),PatternType
    pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD.Application', 'Пока не реализовано', 'C:\\Program Files\\Autodesk\\AutoCAD 2020\\HELP\\OLE_ERR.CHM', -2145386495, -2145386495), None)


Пока нереализовано...
Так и должно быть. Каждый из контуров - это один замкнутый контур. А у тебя две окружности. Т.е. одна должна быть внутренним контуром, а вторая наружным.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 11-09-2020, 19:38:42
Где-то наверное так:
Код - Python [Выбрать]
  1. circle1 = mSp.AddCircle(cc(0,0,0), 100)
  2. circle2 = mSp.AddCircle(cc(20,20,0), 30)
  3. hatch1 = mSp.AddHatch(PatternType = 0,
  4.      PatternName = "ANSI31",
  5.      Associativity = True,
  6.      HatchObjectType = 0)
  7. hatch1.AppendOuterLoop(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle1]))
  8. hatch1.AppendInnerLoop(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle2]))
  9. hatch1.Evaluate()

Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 11-09-2020, 20:53:59
Но лично у меня при попытке назначить такую штриховку вылетает ошибка:

Цитировать

    hatch1 = mSp.AddHatch(PatternType = 1,
      File "C:\Users\2E78~1\AppData\Local\Temp\gen_py\3.8\E2077CF2-3573-4E66-B1DC-01118675056Dx0x1x0\IAcadModelSpace.py", line 254, in AddHatch
        ret = self._oleobj_.InvokeTypes(1579, LCID, 1, (9, 0), ((3, 1), (8, 1), (11, 1), (12, 17)),PatternType
    pywintypes.com_error: (-2147352567, 'Ошибка.', (0, 'AutoCAD.Application', 'Пока не реализовано', 'C:\\Program Files\\Autodesk\\AutoCAD 2020\\HELP\\OLE_ERR.CHM', -2145386495, -2145386495), None)


Пока нереализовано...
Это из-за PatternType = 1. Должно быть PatternType = 0.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: vxv от 12-09-2020, 06:41:37
circle1 = mSp.AddCircle(cc(0,0,0), 100)
circle2 = mSp.AddCircle(cc(20,20,0), 30)
hatch1 = mSp.AddHatch(PatternType = 0,
     PatternName = "ANSI31",
     Associativity = True,
     HatchObjectType = 0)
hatch1.AppendOuterLoop(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle1]))
hatch1.AppendInnerLoop(win32com.client.VARIANT(VT_ARRAY | VT_DISPATCH, [circle2]))
hatch1.Evaluate()

Кстате работает и без строчки:
Код - Python [Выбрать]
  1. hatch1.Evaluate()

Большое спасибо за помощь. я был очень близко к разгадке, ходил кругами. и уже даже отчаялся. Вы меня спасли!!!!!!!!
Хочу выслать ссылку с репозиторем. В нем очень грамотно прописаны все другие моменты по Автокаду для тех кто как я только начинает в этой области творить:
https://github.com/JohnYang1210/PycomCAD
 :) :) :) :) :) :) :)
Название: Re: Python & ActiveX/COM Autocad
Отправлено: vxv от 12-09-2020, 09:56:15
Комплект чертежей состоит из нескольких листов. Мы их обрамляем рамками, у которых есть свой штамп и другое. Эти листы мы располагаем в пространстве модели друг за другом. И на каждом из них может присутствовать какой-то элемент в определенном месте относительно глобальных координат. Можно конечно каждый раз переносить начало координат в нужную нам точку пространства, но думаю есть проектировщики, для кого это критично и недопустипо, да и выглядеть это будет не совсем удобно.
Внимание, а теперь вопрос к знатокам: "Как перед выполнением скрипта отправить запрос в Autocad об указании точки вставки результатов действий скрипта???" Другими словами - указать начало координат для скрипта не (0,0,0), а место куда укажем мышкой. Либо координаты того или иного элемента, который мы выделим мышкой. Думаю такая тема будет много кому полезна. Заранее спасибо и хорошего настроения всем...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 12-09-2020, 12:10:27
Комплект чертежей состоит из нескольких листов. Мы их обрамляем рамками, у которых есть свой штамп и другое. Эти листы мы располагаем в пространстве модели друг за другом. И на каждом из них может присутствовать какой-то элемент в определенном месте относительно глобальных координат. Можно конечно каждый раз переносить начало координат в нужную нам точку пространства, но думаю есть проектировщики, для кого это критично и недопустипо, да и выглядеть это будет не совсем удобно.

Нужно найти и прочитать этот элемент по сдвигу относительно края рамки? номер страницы к примеру.

Цитата: vxv
Внимание, а теперь вопрос к знатокам: "Как перед выполнением скрипта отправить запрос в Autocad об указании точки вставки результатов действий скрипта???" Другими словами - указать начало координат для скрипта не (0,0,0), а место куда укажем мышкой. Либо координаты того или иного элемента, который мы выделим мышкой. Думаю такая тема будет много кому полезна. Заранее спасибо и хорошего настроения всем...

В начале темы где-то было:

Код - Python [Выбрать]
  1. point = aDoc.Utility.GetPoint(cc(0, 0, 0), "Укажите точку вставки:")
Название: Re: Python & ActiveX/COM Autocad
Отправлено: vxv от 12-09-2020, 16:24:01
Electric, щас доберусь до компа попробую эту строчку. Просто пока не забыл хочу поздравить всех с днём програмиста. Ееееехххххууууу ;D ;D ;D ;D
Название: Re: Python & ActiveX/COM Autocad
Отправлено: vxv от 12-09-2020, 16:53:50
Electric, эта строчка то что нужно, работает на ура. Спасибо большое.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 12-10-2020, 06:52:36
Огромная просьба, кто знает, подскажите.

Написано большое количество скриптов на питоне для AutoCad. Внезапно Автокад начал глючить вот в каком плане: при обращении к COM функциям они очень часто стали заканчиваться с ошибкой "Вызов был отклонен". Раньше такое в основном случалось, если во время работы скрипта введешь команду или ткнешь мышкой в чертеж, ну и очень редко, по другим причинам типа автосохранения или еще чего то, но это еще чего то было настолько редким, что в принципе можно было не обращать внимания. Сейчас же такое происходит через раз. Скрипты становятся неработоспособными, потому что вызовов много и если на каком то из них прерывается, то весь скрипт надо перезапускать,  или еще хуже, убирать то что наделал незаконченный скрипт.
В общем проблема серьезная. Понимаю, что можно перед каждым вызовом функции делать проверки, но это не выход: во первых такая ерунда может произойти даже при обращении к свойствам объекта, а каждую такую строчку проверять - как бы уже бредом попахивает.
В общем есть ли у кого мысли что могло произойти с автокадом? Как это можно попробовать исправить? Простую переустановку я сделал, не помогло...
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 12-10-2020, 10:44:02
Понимаю, что можно перед каждым вызовом функции делать проверки, но это не выход: во первых такая ерунда может произойти даже при обращении к свойствам объекта, а каждую такую строчку проверять - как бы уже бредом попахивает.
Это единственный выход при использовании COM. Причем между обращениями к AutoCAD следует делать задержку как минимум в 500 миллисекунд.
Так это выглядит на C++: https://adn-cis.org/kak-ispolzuya-visual-c-zapustit-autocad-i-zastavit-ego-vyipolnyat-nekotoryie-dejstviya.html
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 12-10-2020, 12:23:04
Скажем там, несколько дней назад такой проблемы не было точно... Все работало нормально.
Во вторых - проблема то возникает не только при вызове функции, но даже при обращении к свойствам объектов... Ведь каждый раз делать проверки даже при обращении к свойствам - очень сомнительно что это вообще имеет смысл... Скрипты вроде придумали чтобы упрощать жизнь и исключить работу которую можно поручить компьютеру. В таком случае код превращается в проверки проверок перед проверками перед тем как проверить удачно ли прошло обращение к функции или к объекту.

Опять же, раньше то работало и меня все устраивало.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 12-10-2020, 12:29:57
Опять же, раньше то работало и меня все устраивало.
Если раньше всё работало и AutoCAD не обновлял, то вероятно обновилась Windows. Но вообще-то просто тебе раньше везло. Такая проблема известна как минимум 10 лет. И именно поэтому я не рекомендую использовать COM/ActiveX, а писать приложения, которые грузятся внутрь AutoCAD.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 12-10-2020, 12:33:28
Если только все обращения к свойствам объектов обернуть в:

Код - Python [Выбрать]
  1. while True:
  2.     try:
  3.         #операции считывания свойств у объектов AutoCAD
  4.     except:
  5.         pass
  6.     else:
  7.         break.

Но с графическими построениями такое не прокатит.
Похоже, что кроме изучения C# от такого не избавиться.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Александр Ривилис от 12-10-2020, 12:35:40
Если только все обращения к свойствам объектов обернуть в:
Не хватает задержки перед очередным обращением в случае except.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: Electric от 12-10-2020, 12:40:17
Ну да, тогда импортировать time и  задавать выдержку с помощью time.sleep(0.5). И цикл делать не вечный.
У меня тоже скрипты с COM работают как повезет, приходится обрабатывать такие ошибки.
Название: Re: Python & ActiveX/COM Autocad
Отправлено: DMuzer от 12-10-2020, 15:20:16
Ну что же, спасибо за ответы... Видимо, я везучий)))
Жаль что такая засада с COM вылезает.
Как то я привык python как почти замену командной строки автокада использовать. Учитывая наличие массы библиотек, расчетов
можно делать вещи, которые изнутри автокада недоступны именно потому, что перед загрузкой внутрь автокада приложение нужно написать, отладить, откомпилировать...
А через COM - практически появилась мысль - сразу попробовал, потестировал, извлек инфо из чертежа, обработал, расчитал и обратно построил... На C# это думаю, недоступно просто потому что усилий и времени потребуется в сотни раз больше.