Найти объект под заданной точкой

Автор Тема: Найти объект под заданной точкой  (Прочитано 13802 раз)

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

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

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Задача такая: Надо разобраться на какой объект указывает MLeader. Т.е. что собственно видно во вьюпорте в той точке, куда пользователь тыкнул стрелку выноски. Напрашивается решение «в лоб»: создать луч по оси Z текущего вида в этой известной точке и перебрать ВСЕ объекты чертежа на IntersectWith с этим лучом. Но чертеж будет большим; много блоков, которые надо рекурсивно взрывать… Это катастрофа для производительности. И у меня возникла мысль, что ведь автокад мгновенно выдает объект, когда пользователь кликает по экрану и даже динамически подсвечивает все, что попадается под указателем. Нет ли какого-то эффективного API для аналогичного выбора объекта по точке? Может GetDBObjectIds с каким-то хитрым фильтром?
Заранее благодарен за любые подсказки.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Найти объект под заданной точкой
« Ответ #1 : 20-10-2015, 23:39:35 »
То есть, нужно определить объект модели по точке, заданной в листе на отображении этого объекта в видовом экране?

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #2 : 20-10-2015, 23:48:25 »
Да, можно и так сформулировать. Но MLeader может находится и в пространстве модели. Так что просто задана точка, могу найти настройки текущего вида (не важно модель или вьюпорт), надо как-то найти первый видимый объект "под" этой точкой.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #3 : 21-10-2015, 00:10:05 »
avc
Приветствую на форуме.
1) Для того, чтобы выполнялся "быстрый поиск" точка должна быть в видимой области на экране.
2) Для выбора объектов можно воспользоваться Editor.SelectCrossingWindow и задать точки с небольшим смещением влево-вниз и вправо-вверх от заданной точки.
3) Возможно тебе поможет этот код: http://www.theswamp.org/index.php?topic=22963.msg345716#msg345716
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: Найти объект под заданной точкой
« Ответ #4 : 21-10-2015, 09:14:16 »
перебрать ВСЕ объекты чертежа на IntersectWith с этим лучом. Но чертеж будет большим; много блоков, которые надо рекурсивно взрывать… Это катастрофа для производительности.
Чтоб это не было катастрофой - читайте соседнею тему - http://adn-cis.org/forum/index.php?topic=2826.0, ключевое слово Rtree.

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #5 : 21-10-2015, 11:12:36 »
Даже не ожидал столь оперативной помощи :)
Александр Ривилис, спасибо! Editor.SelectCrossingWindow - это похоже на то, что я искал. Буду пробовать. Если не получится - попробую пошаманить с external вызовами.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #6 : 21-10-2015, 11:15:50 »
Даже не ожидал столь оперативной помощи :)
Здесь всегда так. Не удивляйся.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #7 : 22-10-2015, 10:32:04 »
Я попробовал метод №3, но получил EntryPointNotFoundException с сообщением "Unable to find an entry point named 'acedNEntSelPEx' in DLL 'acad.exe'"
Недокументированная функция уже удалена из автокада? Или проблемы с версией/разрядностью? Я пробую на Acad 2016 x64

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #8 : 22-10-2015, 10:39:08 »
Я попробовал метод №3, но получил EntryPointNotFoundException с сообщением "Unable to find an entry point named 'acedNEntSelPEx' in DLL 'acad.exe'"
Недокументированная функция уже удалена из автокада? Или проблемы с версией/разрядностью? Я пробую на Acad 2016 x64
Нет. Но есть пару нюансов, связанных с версией и разрядностью AutoCAD:
1) Вместо "acad.exe" должно быть "accore.dll" во всех версиях AutoCAD начиная с 2013
2)
EntryPoint="?acedNEntSelPEx@@YAHPB_WQAJQANHQAY03NPAPAUresbuf@@IPAH@Z" для AutoCAD x86
EntryPoint="?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z" для AutoCAD x64
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #9 : 22-10-2015, 10:42:28 »
А не подскажите, можно как-то в C# подлинковывать разные dll во время исполнения в зависимости от текущей версии Автокада?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #10 : 22-10-2015, 11:07:27 »
А не подскажите, можно как-то в C# подлинковывать разные dll во время исполнения в зависимости от текущей версии Автокада?
О каких dll идёт речь? Если о тех, которые вызываются через P/Invoke, как в случае с acedNEntSelPEx, то нужно просто описать несколько прототипов и вызвать тот, который соответствует разрядности и версии AutoCAD:
1) Если Application.Version.Major > 18 - то версия 2013 или выше
2) Если IntPtr.Size == 4, то x86. В противном случае x64.

P.S.: Это не линковка, а динамическая загрузка и вызов функции. Аналогично LoadLibrary + GetProcAddress в C++

P.S.S.: В качестве примера: http://adn-cis.org/forum/index.php?topic=819.msg3301#msg3301
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 02-11-2015, 00:27:52

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #11 : 27-10-2015, 16:19:41 »
Наконец-то я нашел время, отписаться о результатах. Все получилось. Считаю своим долгом опубликовать код. Надеюсь,  кому-нибудь пригодится.
Итак, внятная обертка для функции acedNEntSelPEx получилась такой:
(К сожалению, не знаю назначение некоторых параметров)
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.Runtime;
  8. using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  9.  
  10. namespace AVC
  11. {
  12.   /// <summary>
  13.   /// Обертка для недокументированной функции acedNEntSelPEx
  14.   /// </summary>
  15.   public static class ObjUnderPoint
  16.   {
  17.     static int ver = Application.Version.Major;
  18.  
  19.     /// <summary>
  20.     /// Поиск видимого объекта чертежа под заданной точкой
  21.     /// Точку можно передать или запросить у пользователя
  22.     /// Возвращает только 1 объект (верхний в порядке DrawOrder)
  23.     /// Работает только с  MdiActiveDocument и только на текущем Layout
  24.     /// </summary>
  25.     /// <param name="Prompt">Запрос выбора точки</param>
  26.     /// <param name="Picked">Точка для поиска в UCS (передаваемая методу или возвращаемая от пользователя)</param>
  27.     /// <param name="UsePickedPoint">Использовать переданную точку и ничего не запрашивать у пользователя</param>
  28.     /// <param name="Transform">Какая-то матрица. Может пересчет текущей системы координат в систему координат выбранного объекта?</param>
  29.     /// <param name="TransSpace">Видеть сквозь viewport</param>
  30.     /// <param name="GSMarker">Код SubEntity (Часть солида) Например 5-грань,6-вершина,26-ребро... 0-неделимый объект</param>
  31.     /// <returns>Список найденных объектов. Сначала видимый объект, потом блоки в который он включен, потом viewport (если включен TransSpace) </returns>
  32.     public static List<ObjectId> Find(string Prompt, out Point3d Picked, bool UsePickedPoint, out Matrix3d Transform, bool TransSpace, out int GSMarker)
  33.     {
  34.       List<ObjectId> ret = new List<ObjectId>();
  35.       long[] adsname = { 0, 0 };
  36.       IntPtr resbuf = IntPtr.Zero;
  37.       int result = 0;
  38.       uint transSpaceFlag = (uint)(TransSpace ? 1 : 0);
  39.       int pickflag = UsePickedPoint ? 1 : 0;
  40.  
  41.       if (ver < 19) // AutoCAD 2012 и старее
  42.       {
  43.         if (IntPtr.Size == 4)
  44.           result = acedNEntSelPEx2012x32("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
  45.         else
  46.           result = acedNEntSelPEx2012x64("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
  47.       }
  48.       else // AutoCAD 2013 и новее
  49.       {
  50.         if (IntPtr.Size == 4)
  51.           result = acedNEntSelPEx2013x32("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
  52.         else
  53.           result = acedNEntSelPEx2013x64("", adsname, out Picked, pickflag, out Transform, out resbuf, transSpaceFlag, out GSMarker);
  54.       }
  55.  
  56.       if (result == 5100) // 5100 == OK
  57.       {
  58.         ObjectId id = new ObjectId();
  59.         switch (ver)
  60.         {
  61.           case 17: acdbGetObjectId17(ref id, adsname); break;
  62.           case 18: acdbGetObjectId18(ref id, adsname); break;
  63.           case 19: acdbGetObjectId19(ref id, adsname); break;
  64.           case 20: acdbGetObjectId20(ref id, adsname); break;
  65.           default: throw new NotImplementedException("Комманда не совместима с данной версией автокада");
  66.         }
  67.         if (!id.IsNull) ret.Add(id);
  68.  
  69.         if (resbuf != IntPtr.Zero) // значит попался вьюпорт или блок
  70.         {
  71.           ResultBuffer buffer = (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), resbuf, true);
  72.           foreach (TypedValue v in buffer) // первым в списке будет самый глубоко вложенный блок, последним - вьюпорт
  73.             ret.Add((ObjectId)v.Value);
  74.           buffer.Dispose();
  75.         }
  76.  
  77.  
  78.       }
  79.  
  80.       return ret;
  81.     }
  82.  
  83.     /// <summary>
  84.     /// Поиск видимого объекта чертежа под заданной точкой. Видит "сквозь" вьюпорты
  85.     /// Возвращает только 1 объект (верхний в порядке DrawOrder)
  86.     /// Работает только с MdiActiveDocument и только на текущем листе (Layout). Система координат листа должна быть мировой.
  87.     /// </summary>
  88.     /// <param name="Picked">Точка поиска в UCS</param>
  89.     /// <returns>Список найденных объектов. Сначала видимый объект, потом блоки в который он включен, потом viewport (если включен TransSpace)</returns>
  90.     public static List<ObjectId> Find(Point3d Picked)
  91.     {
  92.       Matrix3d xform;
  93.       int gsmarker = 0;
  94.       // set uTransSpaceFlag to 0, if the current layout is in model space
  95.       bool transSpace = ((Convert.ToInt16(AcadApp.GetSystemVariable("CVPORT")) == 1));  // Paper space
  96.  
  97.       return Find("", out Picked, true, out xform, transSpace, out gsmarker);
  98.     }
  99.  
  100.     #region acdbGetObjectId
  101.  
  102.     [DllImport("acdb17.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
  103.     private static extern int acdbGetObjectId17(ref ObjectId objId, long[] name);
  104.  
  105.     [DllImport("acdb18.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
  106.     private static extern int acdbGetObjectId18(ref ObjectId objId, long[] name);
  107.  
  108.     [DllImport("acdb19.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
  109.     private static extern int acdbGetObjectId19(ref ObjectId objId, long[] name);
  110.  
  111.     [DllImport("acdb20.dll", EntryPoint = "acdbGetObjectId", CallingConvention = CallingConvention.Cdecl)]
  112.     private static extern int acdbGetObjectId20(ref ObjectId objId, long[] name);
  113.  
  114.     #endregion
  115.  
  116.     #region acedNEntSelPEx
  117.  
  118.     [DllImport("acad.exe", EntryPoint = "?acedNEntSelPEx@@YAHPB_WQAJQANHQAY03NPAPAUresbuf@@IPAH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
  119.     private static extern int acedNEntSelPEx2012x32(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
  120.  
  121.     [DllImport("acad.exe", EntryPoint = "?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
  122.     private static extern int acedNEntSelPEx2012x64(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
  123.  
  124.     [DllImport("accore.dll", EntryPoint = "?acedNEntSelPEx@@YAHPB_WQAJQANHQAY03NPAPAUresbuf@@IPAH@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
  125.     private static extern int acedNEntSelPEx2013x32(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
  126.  
  127.     [DllImport("accore.dll", EntryPoint = "?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
  128.     private static extern int acedNEntSelPEx2013x64(string prompt, long[] adsname, out Point3d picked, int pickflag, out Matrix3d transform, out IntPtr resbuf, uint transSpaceFlag, out int gsMarker);
  129.  
  130.     #endregion
  131.  
  132.   }
  133. }
  134.  
  135.  
« Последнее редактирование: 02-11-2015, 12:39:02 от avc »

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #12 : 27-10-2015, 16:20:23 »
Тестовая команда может быть такой:
Код - C# [Выбрать]
  1. [CommandMethod("doit")]
  2. public static void acedNEntSelPExTest()
  3. {
  4.   Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  5.   if (doc == null) return;
  6.   Editor ed = doc.Editor;
  7.   PromptPointResult ppr = ed.GetPoint("Кликните по объекту");
  8.   if (ppr.Status != PromptStatus.OK) return;
  9.   List<ObjectId> ids = ObjUnderPoint.Find(ppr.Value);
  10.   foreach (ObjectId id in ids) ed.WriteMessage("\n" + id.ObjectClass.Name + " #" + id.Handle.ToString());
  11. }

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #13 : 27-10-2015, 16:21:38 »
Для моей задачи оказалось не удобным, что функция возвращает только один «верхний» объект. А в точке вставки выноски – это всегда сама выноска. Пришлось забивать костыль - отключать видимость выноски и вызывать Editor.Regen(), который притормаживает и приводит к морганию экрана.
И еще вылезла проблемка: если найдется изощренный пользователь, который переключит систему координат листа, то объекты во вьюпорте уже не найдутся, как не трансформируй точку. Пришлось назло пользователю возвращать мировую систему координат.

Код - C# [Выбрать]
  1. using (Transaction tr = doc.TransactionManager.StartTransaction())
  2. {
  3.   MLeader ml = tr.GetObject(mLeaderId, OpenMode.ForWrite) as MLeader;
  4.   if (ml.ContentType != ContentType.MTextContent || ml.MText.Contents != "") return;
  5.   Point3d point = ml.GetFirstVertex(0);
  6.   if ((Convert.ToInt16(AcadApp.GetSystemVariable("CVPORT")) != 1))  // Model space
  7.   {
  8.     Matrix3d ucs = ed.CurrentUserCoordinateSystem;
  9.     point = point.TransformBy(ucs.Inverse()); // Пересчет WCS -> UCS
  10.   }
  11.   else // Если пользователя угораздит перенести систему координат на бумаге, то объекты во вьюпорте найти не получится
  12.   {
  13.     ed.CurrentUserCoordinateSystem = Matrix3d.Identity; // вернем WCS для листа
  14.   }
  15.   ml.Visible = false;
  16.   ed.Regen();
  17.  
  18.   List<ObjectId> ids;
  19.   try
  20.   {
  21.     ids = ObjUnderPoint.Find(point);
  22.   }
  23.   finally { ml.Visible = true; }
  24.   if (ids.Count == 0) return;
  25.   using (DBObject obj = tr.GetObject(ids[0], OpenMode.ForRead))
  26.   {
  27.     // Записываем информацию об объекте obj в ml.MText.Contents
  28.     ..
  29.        
  30.   }
  31.   tr.Commit();
  32. }

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #14 : 27-10-2015, 17:15:40 »
Для моей задачи оказалось не удобным, что функция возвращает только один «верхний» объект. А в точке вставки выноски – это всегда сама выноска.
Может проще было бы выноску куда-то сдвинуть на время выбора точки?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #15 : 27-10-2015, 17:21:48 »
Сдвинуть или отключить - не важно. Заковырка не в этом, а в том, что надо как-то обновить изображение перед вызовом поиска объекта.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #16 : 27-10-2015, 17:31:04 »
Сдвинуть или отключить - не важно. Заковырка не в этом, а в том, что надо как-то обновить изображение перед вызовом поиска объекта.
Если разделишь транзакцию на две, то не придётся выполнять регенерацию, которая может быть достаточно длительной операцией. По поводу отключить или передвинуть - согласен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #17 : 27-10-2015, 17:45:18 »
А подскажете код EntryPoint этой функции (acedNEntSelPEx) для Acad 2012x64 ?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #18 : 27-10-2015, 17:47:22 »
А подскажете код EntryPoint этой функции (acedNEntSelPEx) для Acad 2012x64 ?
"?acedNEntSelPEx@@YAHPEB_WQEA_JQEANHQEAY03NPEAPEAUresbuf@@IPEA_J@Z"
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #19 : 02-11-2015, 15:57:57 »
Замечу еще одну особенность применения функции acedNEntSelPEx. Она возвращает вовсе не тот объект, который находится точно под заданной точкой. Она выбирает первый попавшийся (в порядке DrawOrder) объект, среди всех объектов попавших в квадрат перекрестья курсора (PickBox). Даже если сработала привязка к точке на одном объекте, на выходе функции будет другой объект. А пользователь скорее всего не заметит, что выбран не тот объект, т.к. они расположены очень близко (pickbox обычно всего 3 пиксела на экране). "Виртуальный" пикбокс учитывается даже в случае, если точка передается в функцию извне.
Исправить этот баг не сложно. Я просто ставлю системную переменную PICKBOX на 0 (AcadApp.SetSystemVariable("PICKBOX", 0)) на время вызова функции, и возвращаю ее обратно по завершении. В try-finally, конечно.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #20 : 02-11-2015, 16:03:43 »
Она возвращает вовсе не тот объект, который находится точно под заданной точкой. Она выбирает первый попавшийся (в порядке DrawOrder) объект, среди всех объектов попавших в квадрат перекрестья курсора (PickBox).
Точно также работают и acedEntsel (Editor.GetEntity), acedNentsel(p) (Editor.GetNestedEntity). Это стандарт AutoCAD с незапамятных времён...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн aipx

  • ADN OPEN
  • Сообщений: 2
  • Карма: 0
Re: Найти объект под заданной точкой
« Ответ #21 : 24-04-2016, 17:22:04 »
Я начинающий в написании плагинов, не судите строго если вопрос будет сформулирован не верно:
У меня есть модель на которой размещены блоки с указателями их названий мультивыноской, мне нужно создать  SortedDictionary<TKey, TValue> Блок-Название.

С помощью метода указанного в данном посте, я нахожу координаты Point3d мультивыносок, которые я получаю командой -  Mleader.FirstVertex(0) ( я так понимаю координаты мне передаются с  ModelSpace ). При этом хотелось бы получить объекты под всеми мультивыносками модели, что бы это не зависило от того насколько я отмасштабировал модель, а оно ищет только в том участке который виден на экране.  Подскажите хотя бы в каком направлении копать? Я предпологаю, что это связано с видовыми экранами и системами координат, но описать не могу  :(

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #22 : 24-04-2016, 17:36:17 »
aipx
Приветствую на форуме!
Обозначенный алгоритм работает только с примитивами в видимой области экрана. Так что если тебя это не устраивает нужно думать о другом алгоритме.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Найти объект под заданной точкой
« Ответ #23 : 24-04-2016, 17:38:58 »
Например, отбираешь все свои блоки в модели и все свои мультивыноски в модели. Ну а дальше находишь соответствие их друг другу (опираясь на точки вставки блоков и начало мультивыноски)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн aipx

  • ADN OPEN
  • Сообщений: 2
  • Карма: 0
Re: Найти объект под заданной точкой
« Ответ #24 : 24-04-2016, 17:48:08 »
Александр Ривилис, Очень благодарен за помощь! Вы мне сэкономили кучу времени, на протяжении которого я бы ковырялся еще в этом коде. Буду думать в другом направлении!

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Re: Найти объект под заданной точкой
« Ответ #25 : 25-05-2016, 23:22:00 »
Буду думать в другом направлении!
Необязательно!
Я наконец нашел время решить эту проблему с поиском объектов за экраном и все оказалось проще простого. Перед поиском объектов надо:
1. Для выносок в пространстве бумаги надо выйти из вьюпорта:
Код - C# [Выбрать]
  1.             if (mleader.BlockName != "*Model_Space") { db.TileMode = false;  ed.SwitchToPaperSpace(); }
2. Вывести все объекты на экран
Код - C# [Выбрать]
  1.             ZoomExtents();  ed.UpdateScreen();
ZoomExtents приходится вызывать через маленький танец с бубном
Код - C# [Выбрать]
  1.     public static void ZoomExtents()
  2.     {
  3.       object acadObject = Application.AcadApplication;
  4.       acadObject.GetType().InvokeMember("ZoomExtents", BindingFlags.InvokeMethod, null, acadObject, null);
  5.     }
Все это безусловно костыли. Настройки вида мы пользователю по портим. По хорошему надо писать свой метод поиска объектов в заданной точке, точнее на пересечении осью Z текущего вида. А связывать объекты через XData или как-то еще "не геометрически" - по моему гораздо более  тернистый путь. Придется отлавливать любые модификации этих объектов. И как гарантировать, что эти модификации не произошли на компьютере, где нет нашего плагина?