Архитектору и проектировщику|Тепло- и звукоизоляция URSA.RU
| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Быстро получить Набор объектов попадающих в Сферу

Быстро получить Набор объектов попадающих в Сферу

Ответ
Поиск в этой теме
Непрочитано 05.08.2009, 20:27 #1
Быстро получить Набор объектов попадающих в Сферу
[N.S]
 
инженер-дефектоскопист
 
Санкт-Петербург
Регистрация: 08.12.2006
Сообщений: 58

Если нарисовать большое количество 3DSold-ов и часть из них заключить в сферу, то выполняя команду "Interfere" (ACAD2006, англ.) за какие-то доли секунды можно получить количество попадающих в эту сферу объектов. Однако, набор элементов, попадающих в сферу, таким образом получить не удается.
Господа, подскажите пожалуйста:
1) Есть ли возможность вытащить такой набор при выполнении команды?
2) Какой есть сопоставимо быстрый способ получить набор объектов, попадающих в сферу из заданной точки и с заданным радиусом?
Спасибо
Просмотров: 3320
 
Непрочитано 05.08.2009, 22:50
#2
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,843


Незнаю насчет быстрый, но первое что приходт в голову, проверить набор внутри окружности по любой из осей на предмет vla-boolean c созданной сферой.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 06.08.2009, 09:21
#3
Евгений А.

Армспорт
 
Регистрация: 18.07.2006
Ейск
Сообщений: 355


Есть для тел функция vla-CheckInterference.
Евгений А. вне форума  
 
Автор темы   Непрочитано 06.08.2009, 16:57
#4
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Дима_: Можно пояснить поподробней?
Евгений А.: vla-CheckInterference не подойдет. Она работает только с двумя объектами и может возвращать объект-пересечение двух тел. Можно последовательно проверять каждое тело чертежа (из нескольких тысяч) на пересечение со сферой , но это, думаю, займет много времени.
[N.S] вне форума  
 
Непрочитано 06.08.2009, 17:37
#5
Puroshev


 
Регистрация: 22.10.2008
Сообщений: 73
Отправить сообщение для Puroshev с помощью Skype™


Интересная задача, но если можно опиши всю проблему целиком.
Puroshev вне форума  
 
Непрочитано 06.08.2009, 17:54
#6
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,440
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от [N.S] Посмотреть сообщение
Дима_: Можно пояснить поподробней?
Евгений А.: vla-CheckInterference не подойдет. Она работает только с двумя объектами и может возвращать объект-пересечение двух тел. Можно последовательно проверять каждое тело чертежа (из нескольких тысяч) на пересечение со сферой , но это, думаю, займет много времени.
В любом случае, автокад не может получить набор для сферы. Здесь придется проходить по объектам и проверять расстояние. Примерный алгоритм:
1. Получаем набор всех объектов, попадающих в куб со стороной, равной диаметру сферы.
2. проходим по всем объектам и проверяем возможность их пересечений.

Как вариант, можно пытаться ускорить этот алгоритм.
Если объекты не слишком сложные или объекты предсказуемой конфигурации, я бы предложил написать свою функцию получения расстояний от объекта до точки.
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 06.08.2009, 18:14
#7
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Елпанов Евгений: Про куб то я не подумал! Спасибо. Ведь можно наверно отсечь ненужные элементы кубом, а потом со сферой разбираться..)
Вообщето мне нужно отобрать попадающие в сферу элементы типа линий (0 . "*LINE"), и блоков (0 . "INSERT"). Через интерференцию тел - это извращенный способ, который мне первый в голову пришел.)
Так. Какой-бы теперь такой хитрый фильтр для ssget придумать, чтобы сразу выбрать примитивы попадающие в куб?

Собственно говоря задача про попадание в сферу полилиний всего чертежа уже мной решена:

Вот кривенькая ф-ция координат полилайна
Код:
[Выделить все]
;|
Получить координаты полилайна 
Параметры:
	ent	| ENAME	| имя примитива, координаты которого нужно получить
Возвращает:
	res	| LIST	| список координат в WCS вида ((x1 y1 z1) (x2 y2 z2) ...)
|;
(defun polyline-ends
       		(ent / 	obj acad_doc utility e n lst ptlst trpt res
		 ;|local func|; _group-by-num _pline-get-verts)

  
;|
Сгруппировать элементы lst по num элементов
Пример:
	(_group-by-num '(1 2 3 4) 2)
	((1 2) (3 4))
|;
  	(defun _group-by-num (lst num / ls ret)
		(if
	  		(= (rem (length lst) num ) 0)
 			(repeat
				(/ (length lst) num)
  				(repeat
					num
					(setq 	ls	(cons (car lst) ls)
						lst 	(cdr lst)
					)
				) ; _end repeat
  				(setq 	ret
					(append	ret
						(list (reverse ls))
					)
					ls 	nil
				) ; _end setq
			) ; _end repeat
		) ; _end if
  		ret
	) ; _end defun _group-by-num
;|
Получить список 2D или 3D точек в зависимости от типа полилинии
|;
	(defun _pline-get-verts (pline_obj / verts)
		(setq 	verts 	(vlax-get pline_obj 'Coordinates)
	     		verts
      			(cond
		  	  (	(wcmatch	
			 	 	(vlax-get pline_obj 'Objectname)
					"AcDb2dPolyline,AcDb3dPolyline"
				)
         			(_group-by-num verts 3)
		  	  )
        	 	  (	(eq
			  		(vlax-get pline_obj 'Objectname)
					"AcDbPolyline"
				)
         			(_group-by-num verts 2)
		  	  )
		  	  (1 nil)
			) ; _end cond
		) ; _end setq
	) ; _end defun _pline-get-verts

  	(setq
	  	elist	(entget ent)
		obj	(vlax-ename->vla-object ent)
		acad_doc 	(vla-get-ActiveDocument (vlax-get-acad-object))
		utility		(vla-get-Utility	acad_doc)
		
		e	(vlax-get obj 'Elevation ) ;|расстояние от цента по нормали|;
		n	(vlax-get obj 'Normal)	;|вектор нормали|;
		lst	(_pline-get-verts obj)	;|первоначальный список точек|;
		ptlst	nil	
	) ; _end setq
  	(if	;|Если 2-х мерн. координаты - добавляем третью = Elevation|;
	  	(= 2 (length (car lst)))
	  	(progn
		  (foreach pt lst
		    	(setq 	ptlst
				(append	ptlst
					(list (append	pt (list e)))
				)
			) ; _end setq
		  ) ; _end foreach
		)
	) ; _end if
  	(foreach pt	;|Переводим каждую координату из OCS в WCS|;
		 ptlst
 		(setq	trpt 
			(vlax-variant-value
				(vla-TranslateCoordinates
			      		utility
					(vlax-3d-point pt)
					acOCS
					acWorld
					0
					(vlax-3d-point n)
				) ; _end vla-TranslateCoordinates
			) ; _end vlax-variant-value
			res
			(append	res
				(list (list 
					(vlax-safearray-get-element trpt 0)
					(vlax-safearray-get-element trpt 1)
					(vlax-safearray-get-element trpt 2)
				)) ; _end list list
			)
		) ; _end setq
	) ; _end foreach
  	res
) ; _end defun 
;|

(polyline-ends (car (entsel)))

|;
Вот преобразование набора в ((имя-примитива список точек) ...):
Код:
[Выделить все]
;|
Преобразовать набор в список
((<ename> <1/nil маркер блока> <pt1> [<pt2> ...]) ... )
|;
(defun ss-to-coordlist (ss / i lst ent)
 (setq i 0)
 (repeat (sslength ss)
  (setq lst
        (append lst
                (list
                 (append
                  (list (setq ent (ssname ss i)))
                  ;|Если блок - берем точку вставки|;
                  (if (= "INSERT" (cdr (assoc 0 (entget ent))))
                   (list
                    'fake	;|маркер блока|;
                    (vlax-get
                     (vlax-ename->vla-object ent)
                     'InsertionPoint
                     )
                    ) ; _end list
                   ;|Если полилайн - берем координаты концов|;
                   (append
                    (list nil)
                    (polyline-ends ent)
                    ) ; _end append
                   ) ; _end if
                  ) ; _end append
                 ) ; _end list
                ) ; _end append lst
        i	(1+ i)
        ) ; _end setq
  ) ; end repeat
 lst
 ) ; _end defun
;|
(ss-to-coordlist (ssget))
|;
Сам алгоритм проверки попадания в сферу и тест времени выполнения:

Код:
[Выделить все]
(defun in-sphere
       (r cpt B / in onborder out in-p _radius-vector)
  (defun _radius-vector (pt / x y z)
    (setq x (- (car pt) (car cpt))
	  y (- (cadr pt) (cadr cpt))
	  z (- (caddr pt) (caddr cpt))
	  )
    (sqrt (+ (* x x) (* y y) (* z z)))
    ) ; _end defun
  (foreach e B
    (setq in-p nil)
    (foreach pt (cddr e)
      (setq in-p
	     (append in-p
		     (list
		       (if (<= (_radius-vector pt) r) 1 nil)
		       ) ; _end list
		     ) ; _end append
	    ) ; _end setq
      ) ; _end foreach
    (if (apply 'and in-p)
      (setq in (append in (list e)))
      (if (apply 'or in-p)
	(setq onborder (append onborder (list e)))
	(setq out (append out (list e)))
	)
      )
    ) ; _end foreach
  (list in onborder out)
  ) ; _end defun

;; Тест времени
(defun ts (l pt / ss time)
 (setq time (getvar "CDATE"))
 (setq ss (ssget "_X" '((0 . "LWPOLYLINE"))))
 (setq lst (ss-to-coordlist ss))
 (in-sphere l pt lst)
 (* (- (getvar "CDATE") time) 1e6)
 ) ; _end defun

;|
(setq pt (getpoint))
(ts 10000 pt)
|;
У меня работает на вложенном файле 1.5 сек. - что конечно много. Сама in-sphere работает 0.3 сек., а тормозят кривые преобразования координат.. Надо ускорять!
Вложения
Тип файла: dwg
DWG 2004
test3.dwg (945.0 Кб, 532 просмотров)

Последний раз редактировалось [N.S], 06.08.2009 в 18:55. Причина: дополнение
[N.S] вне форума  
 
Непрочитано 06.08.2009, 18:33
#8
kp+

идущий по граблям
 
Регистрация: 26.05.2005
Днепройт
Сообщений: 3,989


Цитата:
"Что тут хитрить?.." (М. Ю. Лермонтов)
Найти с помощью GETBOUNDINGBOX ограничивающие "кубы" сферы и всех остальных объектов в модели, сравнить результаты. По-моему, этот метод работает достаточно быстро.
Теми, чей "куб" хоть частично попадает в "куб" сферы, заняться вплотную (с помощью довольно тормозных методов CheckInterference и Intersectwith)
kp+ вне форума  
 
Непрочитано 07.08.2009, 09:04
#9
Евгений А.

Армспорт
 
Регистрация: 18.07.2006
Ейск
Сообщений: 355


Цитата:
Сообщение от [N.S] Посмотреть сообщение
Евгений А.: vla-CheckInterference не подойдет. Она работает только с двумя объектами и может возвращать объект-пересечение двух тел. ...
она ещё может и не возвращать объект пересечения, а только флаг пересечения, так на порядок быстрее (читай справку по команде).
Евгений А. вне форума  
 
Непрочитано 08.08.2009, 17:56
#10
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Метод IntersectWith. Все графические элементы кроме Pviewport и PoligonMesh.
В книге Полещука Н.Н. "AutoLisp и Visual Lisp в среде AutoCAD" Есть функция ent-int (стр. 878). С ее помощью все и делается.
Строите хоть сферу (3D солид), хоть куб, хоть звезду и находите пересечение с этим телом этой функцией.
А PoligonMesh можно и по частям проверять.
Supermax вне форума  
 
Непрочитано 09.08.2009, 11:04
#11
Евгений А.

Армспорт
 
Регистрация: 18.07.2006
Ейск
Сообщений: 355


Цитата:
С ее помощью все и делается.
Ан нет!
Метод IntersectWith для тел хоть и приписан, но на самом деле не реализован (может в 2010 версии только, но вряд ли), так что не так всё просто с телами.
Евгений А. вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Быстро получить Набор объектов попадающих в Сферу

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подскажите, существуют ли практические руководства по Lisp? vn LISP 261 26.11.2015 13:27
Набор объектов DEM Программирование 21 26.03.2014 19:11
FILTER / фильтр BM60 Справочник команд 0 08.07.2008 15:35
Как получить таблицу свойств объектов такую же как в OrCad passat AutoCAD 1 08.12.2004 01:12