ObjectARX -> .NET функции map_dwgtrimobj

Автор Тема: ObjectARX -> .NET функции map_dwgtrimobj  (Прочитано 8632 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Имеется непреодалимое желание использовать функцию map_dwgtrimobj (Map 3D API), которая доступна только на C++. Если будет создана библиотека на С++, реализующая эту функцию, и ее потом подключить к проекту .NET, большие потери времени будут? Предполагается использовать эту функцию много раз в цикле.
« Последнее редактирование: 10-03-2017, 23:54:23 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET
« Ответ #1 : 09-03-2017, 22:14:44 »
Потери будут только при передаче параметров и возврате результатов (если она что-то возвращает).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: ObjectARX -> .NET
« Ответ #2 : 09-03-2017, 22:17:23 »
Т.е. это будет практически то же самое, что и "родные" функции .NET?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET
« Ответ #3 : 09-03-2017, 22:19:57 »
Ну точно оценить я не берусь, но помню что существенные потери были при передача очень больших список (десятки и сотни тысяч элементов). Всё что меньше было несущественно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET
« Ответ #4 : 09-03-2017, 22:40:00 »
Я посмотрел описание этой функции:
Код - C++ [Выбрать]
  1. /*
  2.  *  Trims linear objects which cross boundary edge(s)
  3.  *
  4.  *  Parameters:
  5.  *  ssclip      - selection set of objects to clip;
  6.  *  boundary    - boundary entity name of list of points.
  7.  *  inorout     - 1 = cut inside boundary
  8.  *                0 = cut outside boundary
  9.  *  skiptopo    - 1 = Skip objects referenced by a topology
  10.  *                0 = Clip objects referenced by a topology
  11.  *  keepod      - 1 = Retains all object data on any clipped object
  12.  *                0 = Drops object data on any clipped object
  13.  *  bitflag     - 0 = Delete any non edge objects within or on clip boundary
  14.  *                1 = Ignore any non edge objects within or on clip boundary
  15.  *                2 = Reference the insertion point of any non edge objects
  16.  *                    within or on clip boundary
  17.  *  ssreturn    - selection set of trimmed objects or Nil in case of error
  18.  *
  19.  *  Returns RTNORM or RTERROR
  20.  */
  21.     int map_dwgTrimObj (ads_name ssclip,
  22.                         ads_name boundary,
  23.                         short inorout,
  24.                         short skiptopo,
  25.                         short keepod,
  26.                         short bitflag,
  27.                         ads_name ssreturn);
Теоретически её можно вызвать через P/Invoke. Не знаю почему http://adndevblog.typepad.com/infrastructure/2014/03/using-maptrim-in-net-application.html пишут, что нужно делать через командные методы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Алексей Терно 10-03-2017, 08:35:28

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET
« Ответ #5 : 10-03-2017, 01:59:37 »
Всё оказалось еще проще и еще интересней. Параллельно с map_dwgTrimObj в ObjectARX для Map 3D есть еще и одноимённая функция, экспортируемая из arx в lisp, которою можно легко использовать из .NET напрямую при помощи Application.Invoke. Так как количество данных здесь минимальное и все потери времени на самой работе функции map_dwgTrimObj, то мы воспользуемся именно lisp-функцией. Код будет выглядеть так:

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5.  
  6. [assembly: CommandClass(typeof(Rivilis.Commands))]
  7.  
  8. namespace Rivilis
  9. {
  10.   public class Commands
  11.   {
  12.     [CommandMethod("MapTrimmer")]
  13.     public void MyCommand()
  14.     {
  15.       Document doc = Application.DocumentManager.MdiActiveDocument;
  16.       if (doc == null) return;
  17.       Editor ed = doc.Editor;
  18.       PromptSelectionOptions prSel = new PromptSelectionOptions();
  19.       prSel.MessageForAdding = "Выберите обрезаемые объекты";
  20.       PromptSelectionResult rsSel = ed.GetSelection(prSel);
  21.       if (rsSel.Status != PromptStatus.OK || rsSel.Value.Count == 0)
  22.         return;
  23.       PromptEntityResult rsEnt = ed.GetEntity("Выберите контур обрезки");
  24.       if (rsEnt.Status != PromptStatus.OK)
  25.         return;
  26.       SelectionSet ss = Map_DwgTrimobj(rsSel.Value, rsEnt.ObjectId, 1, 1, 1, 0);
  27.       if (ss != null)
  28.       {
  29.         ed.WriteMessage("\nВ наборе {0} объектов.", ss.Count);
  30.         ss.Dispose();
  31.       }
  32.       else
  33.       {
  34.         ed.WriteMessage("\nОшибка обрезки!!!");
  35.       }
  36.     }
  37.     static public SelectionSet Map_DwgTrimobj(
  38.       SelectionSet ss,
  39.       ObjectId boundary,
  40.       int inorout,  // 1 - оставлять внутреннюю часть, 0 - оставлять наружную
  41.       int skiptopo, // 1 - пропускать объекты с ссылками на топологию, 0 - обрезать
  42.       int keepod,   // 1 - сохранять объектные данные обрезаемых объектов, 0 - удалять объектные данные
  43.       int bitflag   // 0 - удалять все объекты, которые не имеют ребер, находящиеся внутри или на границе
  44.                     // 1 - игнорировать все объекты не имеющие ребер, находящиеся внутри или на границе
  45.                     // 2 - в зависимости от того есть ли точка вставки у объектов не имеющих ребер
  46.       )
  47.     {
  48.       SelectionSet ssout = null;
  49.       // Готовим данные для Application.Invoke
  50.       ResultBuffer resbuf = new ResultBuffer();
  51.       resbuf.Add(new TypedValue((int)LispDataType.Text, "map_dwgtrimobj"));
  52.       resbuf.Add(new TypedValue((int)LispDataType.SelectionSet, ss));
  53.       resbuf.Add(new TypedValue((int)LispDataType.ObjectId, boundary));
  54.       resbuf.Add(new TypedValue((int)LispDataType.Int16, inorout));
  55.       resbuf.Add(new TypedValue((int)LispDataType.Int16, skiptopo));
  56.       resbuf.Add(new TypedValue((int)LispDataType.Int16, keepod));
  57.       resbuf.Add(new TypedValue((int)LispDataType.Int16, bitflag));
  58.       ResultBuffer result = null;
  59.       try
  60.       {
  61.         result = Application.Invoke(resbuf);
  62.       }
  63.       catch { }
  64.       // Освобождаем буфер
  65.       resbuf.Dispose();
  66.       if (result != null)
  67.       {
  68.         TypedValue[] tpArr = result.AsArray();
  69.         if (tpArr[0].TypeCode == (int) LispDataType.SelectionSet)
  70.           ssout = tpArr[0].Value as SelectionSet;
  71.         result.Dispose();
  72.       }
  73.       return ssout;
  74.     }
  75.   }
  76. }

Ну и результат работы проверим в Civil 3d 2016:

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: ObjectARX -> .NET
« Ответ #6 : 10-03-2017, 08:35:23 »
Александр, это то, что надо!!! Спасибо огромное!  :)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET
« Ответ #7 : 10-03-2017, 13:07:30 »
Александр, это то, что надо!!! Спасибо огромное!  :)
Я и не сомневался :) Интересно почему за столько лет никто не предложил такое простое решение? Думаю оформить это всё в виде статьи на сайт.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #8 : 18-05-2017, 22:13:01 »
Начал изощряться с этой функцией и пошли странные результаты.
Исходные данные:
набор выбранных обрезаемых объектов - SelectionSet ss
коллекция границ - List<ObjectId> ids (первая границы внешняя, остальные внутренние).
Вот исходные объекты - сетка и границы:


Надо получить вот такое:


Имеется вот такой код:
Код - C# [Выбрать]
  1. for (int i = 0; i < ids.Count; i++)
  2. {
  3.     if (i == 0)
  4.     {
  5.         //первый - внешний контур
  6.         ss = TrimObjects(ss, ids[i], 1, 1, 1, 0);
  7.     }
  8.     else
  9.     {
  10.         //остальные - внутренние
  11.         ss = TrimObjects(ss, ids[i], 0, 1, 1, 0);
  12.     }
  13. }

И в результате получаю вот такую картину:


Начал разбираться в  последовательных операциях и вот, что получил:
после первой обрезки:


после второй:


после третьей:



После второй обрезки остаются объекты только те, которые пересекают контур. Причем, если выбирать эти контуры по отдельности, то команда отрабатывает на ура.
Это ошибка функции map_dwgtrimobj?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #9 : 19-05-2017, 01:00:06 »
Думаю, что после первой обрезки объекты в ss становятся недействительными. Во всяком случае часть из них, которая обрезалась. Подумай над этим.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #10 : 19-05-2017, 01:09:18 »
Думаю, что после первой обрезки объекты в ss становятся недействительными. Во всяком случае часть из них, которая обрезалась. Подумай над этим.

Исходя из самой функции, это не так, поскольку она возвращает новый набор объектов, уже обрезанных.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #11 : 19-05-2017, 01:15:25 »
Ну поэкспериментируй еще с параметрами.
Если ничего не получится, то останется списать на баг. Тем более, что функция недокументированная и похоже никем не востребованная.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #12 : 19-05-2017, 01:18:57 »
Я уже пробовал различные комбинации параметров - мою проблему не решили.
Если эта функция никем не востребована, то и исправлять баг никто не будет, а значит, что и рапортовать нет смысла :(
Подумаю, как это можно обойти. Как придумаю, отпишусть здесь.

Оффлайн German

  • ADN Club
  • **
  • Сообщений: 84
  • Карма: 13
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #13 : 19-05-2017, 10:22:31 »
Причем, если выбирать эти контуры по отдельности, то команда отрабатывает на ура.
Если вместо первой обрезки сразу запустить только одну вторую, что на выходе?
Если корректная дырка, значит и функция корректна.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: ObjectARX -> .NET функции map_dwgtrimobj
« Ответ #14 : 19-05-2017, 10:28:49 »
Исходя из самой функции, это не так, поскольку она возвращает новый набор объектов, уже обрезанных.
Но тебе же нужны не только обрезанные, но и те, которые не обрезались для дальнейших обрезок.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение