Получение объектов, проходящих через точку (vla-SelectAtPont)

Автор Тема: Получение объектов, проходящих через точку (vla-SelectAtPont)  (Прочитано 13189 раз)

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

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

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
Обнаружил странности в работе vla-SelectAtPoint. Задача такая: найти все объекты с заданными свойствами (а именно линии, полилинии и вхождения блоков, имеющие расширенные данные), проходящие через указанную точку.
Сначала я думал, что получится вот такая конструкция:

Вот, что получилось:
Код - Auto/Visual Lisp [Выбрать]
  1. (if (= (type (setq pt (vl-catch-all-apply (function (lambda () (trans (getpoint "\nУкажите точку: ") 1 0)))))) 'list)
  2.     (progn
  3.       ;Создание набора (если есть, то создаём заново):
  4.       (setq ssets (vla-get-selectionsets actdoc))
  5.       (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-item (list ssets "Set")))
  6.         (setq newSet (vla-add ssets "Set"))
  7.         (progn
  8.           (vla-delete (vla-item ssets "Set"))
  9.           (setq newSet (vla-add ssets "Set"))
  10.         );progn
  11.       );if
  12.       ;Помещение в набор всех линий и вхождений блоков с расширенными данными:
  13.       (setq filter_code (vlax-make-safearray vlax-vbinteger '(0 . 9)))
  14.       (setq filter_value (vlax-make-safearray vlax-vbvariant '(0 . 9)))
  15.       (vlax-safearray-fill filter_code '(-4 -4 0 -3 -4 -4 0 -3 -4 -4)); DXF-группы для фильтра
  16.       (vlax-safearray-fill filter_value '("<OR" "<AND" "*LINE" "'(\"MyApp\")" "AND>" "<AND" "INSERT" "'(\"MyApp\")" "AND>" "OR>"))
  17.       (vla-SelectAtPoint newSet (vlax-3d-point pt) filter_code filter_value)
  18.     ); progn
  19.     (princ)
  20.   )
Однако с -3 постоянно возникает ошибка (наверное, неправильно задаю список в строке).
Если убрать расширенные данные в фильтре, то всё равно возникает ошибка параметров метода (при этом vla-Select ошибку не выдаёт).
Более того, если всё полностью упростить и оставить в фильтре только INSERT, то (vla-get-count newSet) выдаст один элемент при указании точки на блоке:
Код - Auto/Visual Lisp [Выбрать]
  1. (if (= (type (setq pt (vl-catch-all-apply (function (lambda () (trans (getpoint "\nУкажите точку: ") 1 0)))))) 'list)
  2.     (progn
  3.       ;Создание набора (если есть, то создаём заново):
  4.       (setq ssets (vla-get-selectionsets actdoc))
  5.       (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-item (list ssets "Set")))
  6.         (setq newSet (vla-add ssets "Set"))
  7.         (progn
  8.           (vla-delete (vla-item ssets "Set"))
  9.           (setq newSet (vla-add ssets "Set"))
  10.         );progn
  11.       );if
  12.       ;Помещение в набор всех линий и вхождений блоков с расширенными данными:
  13.       (setq filter_code (vlax-make-safearray vlax-vbinteger '(0 . 0)))
  14.       (setq filter_value (vlax-make-safearray vlax-vbvariant '(0 . 0)))
  15.       (vlax-safearray-fill filter_code '(0)); DXF-группы для фильтра
  16.       (vlax-safearray-fill filter_value '("INSERT"))
  17.       (vla-SelectAtPoint newSet (vlax-3d-point pt) filter_code filter_value)
  18.  
  19.       (vla-get-count newSet)
  20.     ); progn
  21.     (princ)
  22.   )

Но стоит только начертить отрезок от этой точки, как тот же самый код в итоге покажет 0 элементов в наборе!

Если кто-то сталкивался с этими особенностями и проблемами, прошу просветить  :)

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Я пожалуй дам хороший совет: "Забудь про SelectAtPoint". Если нужно выбрать все примитивы проходящие через точку - воспользуйся выбором по секущей рамке, задав её размеры порядка значения системной переменной APERTURE (или PICKBOX), пересчитанную в единицы чертежа.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
Я пожалуй дам хороший совет: "Забудь про SelectAtPoint"
Спасибо, запомню. Какие ещё функции-методы пометить красным крестиком? Кажется, Vla-IntersectWith иногда клинит?
задав её размеры порядка значения системной переменной APERTURE (или PICKBOX), пересчитанную в единицы чертежа
Это не очень понял. APERTURE 10, PICKBOX 3, единицы миллиметры. Отступить от точки указания в две противоположные стороны по 3 единицы?

Отмечено как Решение Macondo 01-11-2015, 02:25:35

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Это не очень понял. APERTURE 10, PICKBOX 3, единицы миллиметры. Отступить от точки указания в две противоположные стороны по 3 единицы?
Нет. Обе эти системных переменных в пикселях, а не в единицах чертежа. Так что нужно учесть масштабный коэффициент:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun PIX2UNITS (pix) (* pix (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE")))))
  2. (setq BOX (PIX2UNITS (getvar "PICKBOX"))) ;; Размер PICKBOX в единицах чертежа
Ну а дальше:
Код - Auto/Visual Lisp [Выбрать]
  1. (setq ss (ssget "_C" (mapcar '- p (list BOX BOX 0.0)) (mapcar '+ p (list BOX BOX 0.0)) ...)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати, что касается фильтра по расширенным данным, то:
Код - Auto/Visual Lisp [Выбрать]
  1. (ssget ... '((-3 ("MYAPP"))))
и никаких лишних скобок и апострофов, да еще и в строке.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
и никаких лишних скобок и апострофов, да еще и в строке
Это да, но только в случае ssget. Я рассчитывал на применение vla: они, вроде, более быстродействующие.

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Я рассчитывал на применение vla: они, вроде, более быстродействующие.
Очень сомневаюсь, что в данном случе будет какой-то выигрыш по времени, т.к. и та и другая функция используют одну и туже функцию из ObjectARX.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати, если фильтровать через vla-SelectXXX, то нужно для расширенных данных использовать группу 1001 (а не -3):
http://adndevblog.typepad.com/autocad/2012/05/making-a-filtered-selection-set-using-visual-lisp-activex-functions.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
SSGET хорошо выполняет свою задачу, но только в пределах видимой части экрана. Допустим, пользователь ведёт длинный отрезок из точки А в точку B. Указав точку А, пользователь передвигает видимую область чертежа туда, где нужно поставить точку B, в результате чего в этот момент точка А не видна.
Как в этот момент узнать, какие объекты проходят через точку А? Я вижу вариант зумирования туда и обратно
Код - Auto/Visual Lisp [Выбрать]
  1. (vla-ZoomExtents (vlax-get-acad-object))
  2. ssget
  3. (vla-ZoomPrevious (vlax-get-acad-object))
Проблема в том, что если это массовые операции в цикле, то экран будет постоянно моргать от зума. Что тут можно сделать иначе?

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Что тут можно сделать иначе?
Ничего. Только не пользоваться ssget или терпеть "моргание"
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
Очень жаль. В .NET тоже нет подобных методов, не зависящих от видимой области экрана?

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

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Очень жаль. В .NET тоже нет подобных методов, не зависящих от видимой области экрана?
Аналог (ssget)? Только такой же аналог. Но тут на форуме обсуждалось использование R-tree для быстрого поиска.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение