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

ADN Club => AutoCAD .NET API => Тема начата: maratovich от 02-02-2020, 20:54:00

Название: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 02-02-2020, 20:54:00
Используется позднее связывание (другое не интересует). Чистый СОМ без библиотек.
Для создания AddRegion и CopyObjects требуется массив SAFEARRAY.
Перерыл всё, нигде нет информации как создать SAFEARRAY на vb.net

regionObj = ThisDrawing.ModelSpace.AddRegion(curves)

здесь curves нужно как SAFEARRAY, другое не прнимает.

Неужто никто не столкнулся ? Как его собрать ?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 02-02-2020, 23:35:49
VB.NET? SAFEARRAY? Однако! Знаешь почему никто не сталкивался? Потому что это никому не нужно.
Теоретически это должен быть обычный System.Array с атрибутом [MarshalAs(UnmanagedType.Safe)]
Впрочем, насколько я знаю, большинство COM-объектов в AutoCAD "неполноценные" и поэтому такие вещи не помогут.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 03-02-2020, 03:11:54
Можешь попробовать такую функцию для преобразования обычного Array в SafeArray(VT_ARRAY|VT_DISPATCH)
Код - vb.net [Выбрать]
  1. Public Function MarshalVariantIDispatchArray(ByVal ObjIn As Object) _
  2.                As <System.Runtime.InteropServices.MarshalAsAttribute( _
  3.                    System.Runtime.InteropServices.UnmanagedType.SafeArray, _
  4.                    SafeArraySubType:=System.Runtime.InteropServices.VarEnum.VT_DISPATCH)> Object
  5.   Return ObjIn
  6. End Function
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 03-02-2020, 07:15:41
Можешь попробовать такую функцию для преобразования обычного Array в SafeArray(VT_ARRAY|VT_DISPATCH)
Спасибо, вечером проверю, может сработает.

Впрочем, насколько я знаю, большинство COM-объектов в AutoCAD "неполноценные" и поэтому такие вещи не помогут.

На VB6 всё работает без проблем, а в .net повылазило...
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 03-02-2020, 07:52:03
https://docs.microsoft.com/ru-ru/dotnet/framework/interop/default-marshaling-for-arrays
https://docs.microsoft.com/ru-ru/dotnet/api/system.runtime.interopservices.unmanagedtype?view=netframework-4.8
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 03-02-2020, 07:59:41
trir
И вам спасибо.
P.S. я не против почитать много умных слов, но рабочий пример был бы полезнее.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 03-02-2020, 10:28:35
Можешь попробовать такую функцию для преобразования обычного Array в SafeArray(VT_ARRAY|VT_DISPATCH)

Не работает. Может я чего то не понимаю, но не хочет.

Код - vb.net [Выбрать]
  1. Public Class Form1
  2.    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  3.       Dim Acad As Object = GetObject(, "AutoCAD.Application")
  4.       Dim ThisDrawing As Object = Acad.ActiveDocument
  5.       Dim NameDoc As String = ThisDrawing.Name
  6.       '-----------------------------------------------------------------+
  7.       Dim curves(0 To 1) As Object
  8.       Dim centerPoint(0 To 2) As Double
  9.       Dim radius As Double
  10.       Dim startAngle As Double
  11.       Dim endAngle As Double
  12.       '-----------------------------------------------------------------+
  13.       centerPoint(0) = 5.0# : centerPoint(1) = 3.0# : centerPoint(2) = 0.0#
  14.       radius = 2.0#
  15.       startAngle = 0
  16.       endAngle = 3.141592
  17.       curves(0) = ThisDrawing.ModelSpace.AddArc(centerPoint, radius, startAngle, endAngle)
  18.       curves(1) = ThisDrawing.ModelSpace.AddLine(curves(0).startPoint, curves(0).endPoint)
  19.       ' Create the region
  20.       Dim regionObj As Object
  21.       '-----------------------------------------------------------------+
  22.       regionObj = ThisDrawing.ModelSpace.AddRegion(MarshalVariantIDispatchArray(curves))
  23.       '-----------------------------------------------------------------+
  24.    End Sub
  25.    Public Function MarshalVariantIDispatchArray(ByVal ObjIn As Object) _
  26.                As <System.Runtime.InteropServices.MarshalAsAttribute( _
  27.                    System.Runtime.InteropServices.UnmanagedType.SafeArray, _
  28.                    SafeArraySubType:=System.Runtime.InteropServices.VarEnum.VT_DISPATCH)> Object
  29.       Return ObjIn
  30.    End Function
  31. End Class




(https://i.postimg.cc/yDZvZHCW/11.png) (https://postimg.cc/yDZvZHCW)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 03-02-2020, 11:40:15
Не работает. Может я чего то не понимаю, но не хочет.
Увы. Похоже что неполноценность COM-объектов AutoCAD не позволяет так делать.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 03-02-2020, 11:55:13
Увы. Похоже что неполноценность COM-объектов AutoCAD не позволяет так делать.
Скорее это неполноценность .net , потому что на VB6 работает без проблем.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 03-02-2020, 11:56:40
А зачем вообще использовать COM?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 03-02-2020, 11:56:49
Скорее это неполноценность .net
Тоже возможно. .NET более жестко относится к типам данным.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 03-02-2020, 12:08:20
А зачем вообще использовать COM?
Чтобы не привязываться к версии.
Работает в любом CAD независимо от года и разрядности. Одна сборка для всего.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 03-02-2020, 12:18:24
Цитировать
Чтобы не привязываться к версии.
Работает в любом CAD независимо от года и разрядности. Одна сборка для всего.
мой опыт говорит, что оно так не работает - например нет нужных методов...
NET тянет примерно три версии
можно ещё python попробовать (https://adn-cis.org/forum/index.php?topic=7864.0)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 03-02-2020, 12:24:06
maratovich,
Как я понял и в ADN DevHelp не знают как это реализовать в .NET: https://forums.autodesk.com/t5/net/invalid-object-array-exception-while-calling-copyobjects/td-p/4405461
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 03-02-2020, 12:27:53
кажется на python'е тоже с этим проблема, я лет 10 назад в Delphi с этим плюхался...
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 03-02-2020, 12:30:11
кажется на python'е тоже с этим проблема, я лет 10 назад в Delphi с этим плюхался...
Вроде работает: https://adn-cis.org/forum/index.php?topic=7864.msg42066#msg42066
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 10:11:13
Как только не ковырял - не выходит каменная чаша.
Странно всё это.
Грустно...
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 10:12:57
Как только не ковырял - не выходит каменная чаша.
Странно всё это.
Грустно...
Если бы выходило, то за последние 15 лет кто-нибудь это отметил.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 04-02-2020, 11:09:31
Чтобы не привязываться к версии.
Работает в любом CAD независимо от года и разрядности. Одна сборка для всего.
Так себе аргумент, если честно. В Visual Studio штатным функционалом можно легко настроить так, чтобы под все версии одним нажатием собирались библиотеки. Можно дополнительно ещё чуток настроить события после сборки - и все собранные библиотеки будут автоматически помещаться на своё место в структуре Bundle. Если, конечно, не используются версии AutoCAD ниже 2012...
К тому же, AutoCAD API очень мало меняется с версии 2013. Поэтому, есть большой шанс, что то что написано под 2013 будет работать и в 2020 без перекомпиляции. Но безопаснее, конечно, делать отдельные сборки.
Вы уже пишете на VB.NET - так сделайте ещё один шаг вперёд и избавьтесь от COM-зависимости! И код писать легче станет и возможностей откроется вагон и маленькая тележка!
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 11:21:12
Вы уже пишете на VB.NET - так сделайте ещё один шаг вперёд и избавьтесь от COM-зависимости!
Нет уж, писать отдельные проги под 7 CAD систем, учитывая их годы и разрядность - мозг заклинит.
Ели-ели сил хватает переварить существующие проекты.
У меня тут идея - создать маленькую dll на VB6 и засунуть в неё функцию для региона. Если это сработает, то будет одно неудобство - надо регистрировать dll.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 04-02-2020, 11:42:36
У меня тут идея - создать маленькую dll на VB6 и засунуть в неё функцию для региона. Если это сработает, то будет одно неудобство - надо регистрировать dll.
На лиспе напишите  ;)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 11:50:18
У меня тут идея - создать маленькую dll на VB6 и засунуть в неё функцию для региона. Если это сработает, то будет одно неудобство - надо регистрировать dll.
На лиспе напишите  ;)
Кстати, неплохая идея и не понадобится иметь еще один dll-файл. lisp можно и на лету создавать. :-)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 11:55:57
На лиспе напишите  ;)
В некоторых CAD не все функции лиспа работают, а алгоритм сложный, массив элементов проходит предварительную обработку, на это нужно переписать всю прогу, а это не реально.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 12:02:39
maratovich,
Я на всякий случай отправил запрос в ADN DevHelp, но особо на результат не надеюсь.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 12:04:12
Спасибо.  :)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 04-02-2020, 12:10:55
Цитировать
Нет уж, писать отдельные проги под 7 CAD систем, учитывая их годы и разрядность - мозг заклинит.
проще сразу делать dxf/dwg без всяких CAD систем
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 12:25:26
проще сразу делать dxf/dwg без всяких CAD систем
Не... там цель другая..
Off-Topic: показать
вот, не сочтите за рекламу, для полного понимания сути (http://www.kdmsoft.ru (http://www.kdmsoft.ru))
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 04-02-2020, 13:22:04
В некоторых CAD не все функции лиспа работают, а алгоритм сложный, массив элементов проходит предварительную обработку, на это нужно переписать всю прогу, а это не реально.
Не обязательно всю программу на лисп переводить, достаточно только часть для создания региона. И придумать как передать данные в лисп из расчетной части, наверняка уже есть решения.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 04-02-2020, 13:30:28
Как я понял, там кросс-платформенные приложения. AutoCAD + клоны. Я так подозреваю, что с лиспом могут быть проблемы, особенно с его vla- и vlax- функциями.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 04-02-2020, 13:37:34
Как я понял, там кросс-платформенные приложения. AutoCAD + клоны. Я так подозреваю, что с лиспом могут быть проблемы, особенно с его vla- и vlax- функциями.
Они могут возникнуть и с СОМ. Возможно для построения Region не потребуется прибегать к vla- и vlax- функциям. Они кстати случаем не через СОМ?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 04-02-2020, 13:49:16
Возможно для построения Region не потребуется прибегать к vla- и vlax- функциям.
Альтернатива - только через командные методы. Но для серьёзного приложения это тот ещё костыль. Тут есть примеры: https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/create-a-closed-polyline-and-convert-it-to-region/td-p/4505893
Они кстати случаем не через СОМ?
vla- и vlax-? Да, это функции для работы с COM с помощью VisualLISP.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 04-02-2020, 14:06:22
Альтернатива - только через командные методы.
Возможно можно по другому. (в "программистком" стиле)
https://autolisp.ru/2009/09/22/programming-style/
Наверняка эксперты по VisualLISP смогут подсказать.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 14:14:55
Lisp в ветке по NET - к этому меня еще не готовили :)
Через entmakex создать регион, по-моему, не получится. Значительно проще создавать его через COM (то бишь vla-функции). Можно "пошутить" - создать новый документ, в нем создать все необходимые примитивы, регионы, выполнить все булевые операции, а результат перенести в текущий документ. Документ, естественно, уничтожить.
Но мне что-то кажется, что СОМ тут не нужен от слова совсем. NET значительно более мощный и гибкий инструмент.
Сугубо ИМХО, как обычно ;)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 14:17:12
Как я понял проблема не в массиве, а в объекте.
Массив создаётся правильно, но в .net  Object не принимает свойства
Dim curves(0 To 1) As Object
т.е внутри этого массива не верные свойства объектов.
В VB6 Object и Variant это разные вещи, а тут всё слили в один Object, и скорее всего .net воспринимает объект автокада не как объект а как строку.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 14:19:27
а результат перенести в текущий документ.
Для этого нужна CopyObjects , а оно аналогично идёт через массив объектов - о чем здесь и говорится, и тоже не работает.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 14:20:06
Всю ветку просмотрел по диагонали, может, кого и дублирую.
Используется позднее связывание (другое не интересует). Чистый СОМ без библиотек.
Для создания AddRegion и CopyObjects требуется массив SAFEARRAY.
Перерыл всё, нигде нет информации как создать SAFEARRAY на vb.net
Специально открыл справку:
https://knowledge.autodesk.com/ru/search-result/caas/CloudHelp/cloudhelp/2018/RUS/AutoCAD-ActiveX-Reference/files/GUID-74C8765E-EB4A-4773-ADD4-6C0F318FE6BE-htm.html
http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-D9E0A89C-2D81-4141-8B88-B9AC6EAABD62
Примеры на VBA есть, вряд ли будет большой проблемой перевести их на VB.NET.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 14:22:53
Алексей Кулик,
Леша. Ты всё пропустил. :-) Пока этого сделать никто не смог. И вопрос упирается в позднее связывание (VBA в AutoCAD использует раннее связывание).
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 04-02-2020, 14:25:40
В VB6 Object и Variant это разные вещи, а тут всё слили в один Object
Если долго гуглить, может что и найдется.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/f4bbec03-bd70-427c-8e8b-a2852e4c2b48/quotvariant-quot-data-type-alternative-in-vbnet?forum=vbgeneral
https://ru.vingrad.com/Perekhod-ot-Variant-(VB)-k-object-(NET)-id50ba779b6ccc19eb0101c19d

и скорее всего .net воспринимает объект автокада не как объект а как строку.
это врятли.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 14:29:11
Привалов Дмитрий,
Это нормально работает с обычными типами (int, string, double и т.д., которые известны в .NET), но не работает с пользовательскими типами, реализованными через IDispatch. Как видишь пробы выше уже были сделаны.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 14:40:51
Перевести с VBA на VB? Ну, не буду спорить :)
Сейчас попробовал через консольное приложение с поздним связыванием достучаться хотя бы до пространства модели текущего документа - не получилось. М-да, не умею я на нормальных языках писать программы...
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 14:59:26
Сейчас попробовал через консольное приложение с поздним связыванием достучаться хотя бы до пространства модели текущего документа - не получилось.
Тут же есть код: https://adn-cis.org/forum/index.php?topic=9710.msg42379#msg42379
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 15:53:21
У меня вываливало ошибку на строке получения указателя на пространство модели.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 15:55:25
У меня вываливало ошибку на строке получения указателя на пространство модели.
И AutoCAD был запущен?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 15:57:02
Конечно! И документ в нем тоже был открыт. Правда, там ни до чего мне добраться не удалось - ни до пространства модели, ни до коллекции блоков / стилей / слоев.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 15:58:02
Очень странно.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 04-02-2020, 15:58:34
Правда, там ни до чего мне добраться не удалось - ни до пространства модели, ни до коллекции блоков / стилей / слоев.
Так и должно быть. Это позднее связывание.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 04-02-2020, 15:59:35
Правда, там ни до чего мне добраться не удалось - ни до пространства модели, ни до коллекции блоков / стилей / слоев.
Так и должно быть. Это позднее связывание.
Но ошибку вываливать на этом не должно.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 04-02-2020, 15:59:47
Сейчас попробовал через консольное приложение с поздним связыванием достучаться хотя бы до пространства модели текущего документа - не получилось.
У меня валялся где-то код, можно найти и допилить
Получится что-то типа:
https://adn-cis.org/forum/index.php?topic=9657.0
Если нужно конечно?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 16:51:03
Наверняка какие-то настройки не выставил. Я уже даже не удивляюсь этому :)
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 04-02-2020, 16:52:22
Привалов Дмитрий, я просто пытался из VB через позднее связывание достучаться до текущего документа и его элементов.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 05-02-2020, 08:25:55
Как ранее писал идею - создать dll и подключать.
Но факир был пьян и фокус не удался.
Dll  на VB6 получается х32 и на  vb.net х64 не подключается, разрядность не стыкуется.
 :'(
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: trir от 05-02-2020, 10:28:32
Цитировать
Dll  на VB6 получается х32 и на  vb.net х64 не подключается, разрядность не стыкуется.
это не смертельно - в AutoDESK в своё время это побороли, но это ОЧЕНЬ большой геморрой
https://docs.microsoft.com/ru-ru/windows/win32/com/using-the-system-supplied-surrogate?redirectedfrom=MSDN
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 05-02-2020, 10:59:20
Как ранее писал идею - создать dll и подключать.
Но факир был пьян и фокус не удался.
Dll  на VB6 получается х32 и на  vb.net х64 не подключается, разрядность не стыкуется.
 
Скорее всего остается смешать entmakex для создания контура
вызвать командный метод "_region"
И затем попробовать выбрать созданный контур.
Наверное такое возможно?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 05-02-2020, 11:31:40
Как ранее писал идею - создать dll и подключать.
Но факир был пьян и фокус не удался.
Dll  на VB6 получается х32 и на  vb.net х64 не подключается, разрядность не стыкуется.
 
Скорее всего остается смешать entmakex для создания контура
вызвать командный метод "_region"
И затем попробовать выбрать созданный контур.
Наверное такое возможно?

Безусловно.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 05-02-2020, 11:54:39
Проверил. Через подключение лиспа получается создать область:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun create-region (handles-list)
  2.  
  3.   (setq mspace (vlax-get-property
  4.                  (vla-get-activedocument (vlax-get-acad-object))
  5.                  'modelspace
  6.                )
  7.   )
  8.  
  9.   (vlax-invoke
  10.     mspace
  11.     'addregion
  12.     (mapcar (function
  13.               (lambda (handle) (vlax-ename->vla-object (handent handle)))
  14.             )
  15.             handles-list
  16.     )
  17.   )
  18.  
  19.   (setvar "users1" (vlax-get-property (vlax-ename->vla-object (entlast)) 'handle))
  20.   (princ)
  21. )
Код - C# [Выбрать]
  1. using System;
  2. using System.Runtime.InteropServices;
  3.  
  4. namespace AcadLateCOM
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {            
  10.             dynamic acad = Marshal.GetActiveObject("AutoCAD.Application");
  11.             dynamic thisDrawing = acad.ActiveDocument;
  12.  
  13.             double[] centerPoint = new[] { 5.0, 3.0, 0.0 };
  14.             double
  15.                 radius = 2.0,
  16.                 startAngle = 0.0,
  17.                 endAngle = Math.PI;
  18.  
  19.             dynamic
  20.                 arc = thisDrawing.ModelSpace.AddArc
  21.                     (centerPoint, radius, startAngle, endAngle),
  22.                 line = thisDrawing.ModelSpace.AddLine
  23.                     (arc.StartPoint, arc.EndPoint);            
  24.  
  25.             thisDrawing.SendCommand($"(create-region '(\"{arc.Handle}\" \"{line.Handle}\")) ");
  26.  
  27.             string regionHandle = thisDrawing.GetVariable("users1");            
  28.         }
  29.     }
  30. }
Код примитивен, т.к. написан только для проверки идеи.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 05-02-2020, 12:00:27
Через подключение лиспа получается создать область:
Согласен, об этом и не спорим.
Но когда объектов 100500 штук.  ...
Да хотелось использовать стандартное.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Привалов Дмитрий от 05-02-2020, 12:16:27
Согласен, об этом и не спорим.
Но когда объектов 100500 штук.  ...
Да хотелось использовать стандартное.
Может объектов 100-500 штук? А то 100500 чет слишком большое число, тут CAD другую систему надо искать, для отображения REGION.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 05-02-2020, 12:40:57
Но когда объектов 100500 штук.  ...
Да хотелось использовать стандартное.
Вряд ли лисп будет работать медленнее, чем код из подключаемой через COM сторонней DLL. Единственное что добавляется - преобразования handle-объект и обратно. Тоже не думаю, что это сильно повлияет на скорость работы.
Насчёт стандартного - я не нашёл ничего для того, чтобы напрямую в .NET создать массив объектов, который бы принял метод создания области. Вроде даже есть специальный метод CreateTypedArray (http://help.autodesk.com/view/ACD/2015/ENU/?guid=GUID-A40B9E8B-47D0-4D7A-BDAF-8B28B26B3328), но он не может создавать массив из объектов AutoCAD.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 05-02-2020, 12:43:28
Единственное что добавляется - преобразования handle-объект и обратно.
Это на уровне открытия объекта (Transaction.GetObject(...)) в AutoCAD .NET API.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 06-02-2020, 20:44:59
Можешь попробовать такую функцию для преобразования обычного Array в SafeArray(VT_ARRAY|VT_DISPATCH)
Код - vb.net [Выбрать]

    Public Function MarshalVariantIDispatchArray(ByVal ObjIn As Object) _
                   As <System.Runtime.InteropServices.MarshalAsAttribute( _
                       System.Runtime.InteropServices.UnmanagedType.SafeArray, _
                       SafeArraySubType:=System.Runtime.InteropServices.VarEnum.VT_DISPATCH)> Object
      Return ObjIn
    End Function


Александр, здесь я не силён,  если это возможно - добавьте чтобы было = VT_ARRAY|VT_DISPATCH|VT_BYREF

вот тут http://rsdn.org/forum/com/591449.all (http://rsdn.org/forum/com/591449.all) есть рабочее решение и говорят что без VT_BYREF будет ошибка
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 06-02-2020, 21:13:28
Александр, здесь я не силён,  если это возможно - добавьте чтобы было = VT_ARRAY|VT_DISPATCH|VT_BYREF

вот тут http://rsdn.org/forum/com/591449.all есть рабочее решение и говорят что без VT_BYREF будет ошибка
Это работает в C++, но не работает в .NET
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 07-02-2020, 01:05:33
Это работает в C++, но не работает в .NET
Да. Ситуация не изменилась.
Проверочный код:
Код - C# [Выбрать]
  1. using System;
  2. using System.Runtime.InteropServices;
  3.  
  4. namespace AcadLateCOM
  5. {
  6.     class Program
  7.     {
  8.         [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_DISPATCH | VarEnum.VT_BYREF)]
  9.         static object GetCurves(object curves) => curves;
  10.  
  11.         static void Main(string[] args)
  12.         {            
  13.             dynamic acad = Marshal.GetActiveObject("AutoCAD.Application.23.1");
  14.             dynamic thisDrawing = acad.ActiveDocument;
  15.  
  16.             double[] centerPoint = new[] { 5.0, 3.0, 0.0 };
  17.             double
  18.                 radius = 2.0,
  19.                 startAngle = 0.0,
  20.                 endAngle = Math.PI;
  21.  
  22.             dynamic
  23.                 arc = thisDrawing.ModelSpace.AddArc
  24.                     (centerPoint, radius, startAngle, endAngle),
  25.                 line = thisDrawing.ModelSpace.AddLine
  26.                     (arc.StartPoint, arc.EndPoint);
  27.  
  28.             thisDrawing.ModelSpace.AddRegion(GetCurves(new[] { arc, line }));
  29.         }
  30.     }
  31. }
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in System.Dynamic.dll
Additional information: Неверный массив объектов

P.S. Интересно, что на работе код работал со строкой "AutoCAD.Application", а дома пришлось добавить "23.1". Иначе отказывался запускаться...
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 07-02-2020, 07:23:51
P.S. Интересно, что на работе код работал со строкой "AutoCAD.Application", а дома пришлось добавить "23.1". Иначе отказывался запускаться...

Это потому что у Вас 2020 Автокад, он сырой до ужаса. Сам не регистрируется в реестре. Нужно перепроверять ветку: HKEY_CLASSES_ROOT\AutoCAD.Application
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 07-02-2020, 12:57:40
Попробовал посмотреть что внутри метода AddRegion. Увидел такое объявление:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.Interop.Common.IAcadModelSpace
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4.  
  5. [MethodImpl(MethodImplOptions.InternalCall)]
  6. [DispId(1566)]
  7. [return: MarshalAs(UnmanagedType.Struct)]
  8. new object AddRegion([In] [MarshalAs(UnmanagedType.Struct)] object ObjectList);
  9.  
Я правильно понимаю, что весь наш предварительный маршаллинг коту под хвост, т.к. присутствует маршаллинг параметра на входе в метод?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 07-02-2020, 13:26:22
Я правильно понимаю, что весь наш предварительный маршаллинг коту под хвост, т.к. присутствует маршаллинг параметра на входе в метод?
Не думаю. Если бы это было так, то и при раннем связывании код бы не работал.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Дмитрий Загорулькин от 07-02-2020, 14:51:56
Логично!
Если использовать COM изнутри, то у меня получилось пропихнуть только строго типизированный массив типа AcadEntity[]:
Код - C# [Выбрать]
  1. [CommandMethod("CreateRegionCOMTest")]
  2. public void CreateRegion()
  3. {
  4.     AcadApplication acadApp = Application.AcadApplication as AcadApplication;
  5.     AcadDocument adoc = acadApp.ActiveDocument;
  6.     AcadModelSpace mSpace = adoc.ModelSpace;          
  7.  
  8.     double[] centerPoint = new[] { 5.0, 3.0, 0.0 };
  9.     double
  10.         radius = 2.0,
  11.         startAngle = 0.0,
  12.         endAngle = Math.PI;
  13.  
  14.     AcadArc arc = mSpace.AddArc(centerPoint, radius, startAngle, endAngle);
  15.     AcadLine line = mSpace.AddLine(arc.StartPoint, arc.EndPoint);
  16.  
  17.     AcadEntity[] entities = new AcadEntity[]
  18.     {
  19.         arc as AcadEntity,
  20.         line as AcadEntity
  21.     };            
  22.  
  23.     try
  24.     {
  25.         mSpace.AddRegion(entities);
  26.     }
  27.     catch (System.Exception ex)
  28.     {
  29.         Application.ShowAlertDialog(ex.Message);
  30.     }
  31. }
  32.  
Массивы object[] и dynamic[] тоже вызывали исключения.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Алексей Кулик от 07-02-2020, 15:23:49
А это случайно не раннее связывание?
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 07-02-2020, 15:24:42
А это случайно не раннее связывание?
Именно. Но об этом Дмитрий Загорулькин и пишет.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 17-02-2020, 21:30:46
maratovich,
Увы, но и сотрудники ADN DevHelp не смогли "победить .NET", хотя испробовали массу вариантов. Создать правильный тип не удалось. Так что остаются только предложенные в данной теме варианты.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: maratovich от 17-02-2020, 22:06:05
Увы, но и сотрудники ADN DevHelp не смогли "победить .NET
Спасибо за информацию. Жаль.
Пришлось скрестить .NET  и Lisp кусками, получилась гадость ещё та, но хотя бы так работает.
Название: Re: Как создать SAFEARRAY для создания AddRegion
Отправлено: Александр Ривилис от 17-02-2020, 22:14:08
Пришлось скрестить .NET  и Lisp кусками, получилась гадость ещё та, но хотя бы так работает.
Именно это и предложили ребята из ADN DevHelp в качестве workaround. Некрасиво, но работает вне зависимости от версии AutoCAD.