как работает vla-IntersectWith ?
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > как работает vla-IntersectWith ?

как работает vla-IntersectWith ?

Ответ
Поиск в этой теме
Непрочитано 17.02.2012, 13:21 #1
как работает vla-IntersectWith ?
loginovskiy
 
Регистрация: 31.10.2011
Сообщений: 31

Доброго времени суток, коллеги.
Не могу уяснить, почему vla-IntersectWith с одним типом полилинии работает, а с другим нет.
Поясню. Есть проектная ось, представленная LWPOLYLINE, необходимо найти точки пересечения с
другими полилиниями тоже LWPOLYLINE. При этом все хорошо, если эти полилинии сплошные. Но как только
им изменить тип на штрихпунктирную, так в результате получаю nil.
Та же линия, на том же месте - только изменен тип.
И еще, если узловая точка пересекаемой плинии (вершина) лежит достаточно близко
от пересекающей (0.05 ед), так получаю две пересекаемых (т.е. 2 точки пересечения очень близких но две!)
Кто сталкивался с подобным. HELP!!!
Просмотров: 8681
 
Непрочитано 17.02.2012, 14:04
#2
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,701
Отправить сообщение для Do$ с помощью Skype™


А можно пример в dwg и лисп-код?
Do$ вне форума  
 
Автор темы   Непрочитано 17.02.2012, 14:44 За код прошу не критиковать, он в старом стиле.
#3
loginovskiy


 
Регистрация: 31.10.2011
Сообщений: 31


Фрагмент
Код:
[Выделить все]
(DEFUN SEL_PLIN ( / i j);;ВЫБОР ПЕРЕСЕЧЕК
  (setq nab (ssget "_F" sp_k '((0 . "LWPOLYLINE") (-4 . "<NOT") (62 . 42) (-4 . "NOT>")) ))
  (IF (/= nab nil) (PROGN
    (ssdel entyti_tr nab);;удалить саму трассу, она попадает в набор при выборе пересечек -они ведь выбираются только по Xdata
    (setq i 0);;линии должны быть все LWPOLYLINE
    (setq sp_peres_dist (list))
    (REPEAT (sslength nab);; по каждой линии
       (setq nam_l (ssname nab i))
       (setq obj_l (vlax-ename->vla-object nam_l))
       (setq nam_layer (vlax-get-property obj_l 'Layer))
       ;(setq col_l (vlax-get-property obj_l 'Color))
       ;(IF (AND (/= nam_layer layer_gor) (/= col_gor col_l)) (progn        
          (PERES obj_l);;определить точки пересечения (их может быть не одна)
          (setq j 0)
          (repeat (/ (length sp_peres) 3) ;;по количеству пересечений трассы данной полилинией (например горизонталь может не один раз попадаться)
            (setq t_per (list (nth j sp_peres) (nth (1+ j) sp_peres) 0.0));;непосредственно точка пересечения
	    (setq dist (vlax-curve-getDistAtPoint vla_tr t_per));;дистанцию
            (setq sp_peres_dist (cons (list nam_layer dist) sp_peres_dist));;список <имя слоя . дистанция>
            (setq j (+ j 3));;т.о. в sp будут все пересечения, даже если линия пересекается не одинажды
          );_repeat
        ;;));_IF	  
       (setq i (1+ i))
    );_REPEAT
  ));;_IF (/= nab

(print sp_peres_dist)

(EXIT)

);;_DEFUN
;;==========================================================================================================
(DEFUN PERES ( vla_obj );;определение точек пересечения полилиний РАБОТАЕТ ТОЛЬКО КОГДА ПОЛИЛИНИИ ДЕЙСТВИТЕЛЬНО ПЕРЕСЕКАЮТСЯ !!!
  ;;(setq kopiya (vla-Copy vla_obj));;по-этому нужно сделать копию объекта (полилинии) 
  (setq elev (vlax-put-property obj_l 'Elevation 0));;и установить свойство в 0 (все это справедливо только для LWPOLYLINE)
  (setq t_peres (vla-IntersectWith vla_tr obj_l acExtendNone));;vla-объект пересечений
  (setq sp_peres (vlax-safearray->list (vlax-variant-value t_peres)));;список координат пересечений (оно же может быть не одно!)
  ;;(vla-delete kopiya);;удалить копию
)
Вложения
Тип файла: dwg
DWG 2004
330.dwg (761.0 Кб, 1928 просмотров)
loginovskiy вне форума  
 
Непрочитано 17.02.2012, 15:02
#4
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


У тебя разные значения свойства Elevation
у разных полилиний, проверь сам в 3dView
поэтому не найдешь все точки пересечений
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 17.02.2012, 15:36
#5
loginovskiy


 
Регистрация: 31.10.2011
Сообщений: 31


Не согласен.Та линия которой выбираю - сиреневая с Elevation = 0 и ту которую выбираю (штрих пунктирная) то же 0.0.
Но стоит заменить тип на сплошную - как точка пересечения находится. Проверь.
loginovskiy вне форума  
 
Непрочитано 17.02.2012, 16:14
#6
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Цитата:
Сообщение от loginovskiy Посмотреть сообщение
Не согласен.Та линия которой выбираю - сиреневая с Elevation = 0 и ту которую выбираю (штрих пунктирная) то же 0.0.
Но стоит заменить тип на сплошную - как точка пересечения находится. Проверь.
Сделай копии таких пунктирных полилиний с типом линии continuous
собирай точки и удали эти копии в конце программы,
я других надежных способов не вижу
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 22.02.2012, 12:36
#7
loginovskiy


 
Регистрация: 31.10.2011
Сообщений: 31


А может быть лучше искать inters по всем сегментам 2-х пересекающихся полилиний?
По крайней мере надежнее. Я надеялся узнать мнение классиков, но что то они молчат.
Тема "мелковата", может быть?
loginovskiy вне форума  
 
Непрочитано 22.02.2012, 14:59
#8
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,446


Я, конечно, не классик, но выскажусь.
1. В файле полно прокси-объектов.
2. При имеющемся виде в AutoCAD 2009 я сколько ни искал, не нашел сиреневой полилинии.
3. Штрих-пунктирных линий там 2 штуки.

Оставь в файле только те полилинии, на которых "косяк", можно будет пообщаться.

P.S. (inters) позволяет найти пересечения только прямых кусков. Если устроит - то пожалуйста. Но скорость работы будет отвратительная.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 22.02.2012, 18:15
#9
loginovskiy


 
Регистрация: 31.10.2011
Сообщений: 31


Прошу прощения за паузу. Вот облегчил файл и записал для Acad2004.
Magenta - трасса, а пересечение - шрихпунктирная.
Вложения
Тип файла: dwg
DWG 2004
330.dwg (751.6 Кб, 1910 просмотров)
loginovskiy вне форума  
 
Непрочитано 22.02.2012, 22:57
#10
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,446


Элементарная проверка
Код:
[Выделить все]
(setq int (vla-IntersectWith (vlax-ename->vla-object (car (entsel "\nFirst : "))) (vlax-ename->vla-object (car (entsel "\nSecond : "))) acExtendNone))
(entmakex (list (cons 0 "POINT") (cons 10 (vlax-safearray->list (vlax-variant-value int))) (cons 62 1)))
строит точку именно там, где и надо (в данном конкретном случае).

Если не отслеживать состояние слоев, то как вариант:
Код:
[Выделить все]
 (defun get-inter-points (/                           trass  elev                     selset
                         res                         _kpblc-conv-list-to-3dpoints
                         _kpblc-conv-ent-to-ename    _kpblc-conv-ent-to-vla      _kpblc-conv-selset-to-ename
                         _kpblc-conv-vla-to-list
                         )
                        ;|
*    Получение точек пересечения полилиний
|;

  (defun _kpblc-conv-list-to-3dpoints (lst / res)
                                      ;|
*    Функция конвертации списка чисел в список 3-мерных точек.
*    Параметры вызова:
*	lst	список чисел
*    Примеры вызова:
(_kpblc-conv-list-to-3dpoints '(1 2 3 4 5 6)) ;-> ((1 2 3) (4 5 6))
(_kpblc-conv-list-to-3dpoints '(1 2 3 4 5))   ;-> ((1 2 3) (4 5 0.))
|;
    (cond
      ((not lst)
       nil
       )
      (t
       (setq res (cons (list (car lst)
                             (if (cadr lst)
                               (cadr lst)
                               0.
                               ) ;_ end of if
                             (if (caddr lst)
                               (caddr lst)
                               0.
                               ) ;_ end of if
                             ) ;_ end of list
                       (_kpblc-conv-list-to-3dpoints (cdddr lst))
                       ) ;_ end of cons
             ) ;_ end of setq
       )
      ) ;_ end of cond
    res
    ) ;_ end of defun

  (defun _kpblc-conv-ent-to-ename (ent_value /)
                                  ;|
*    Функция преобразования полученного значения в ename
*    Параметры вызова:
*	ent_value	значение, которое надо преобразовать в примитив. Может
*			быть именем примитива, vla-указателем или просто
*			списком.
*			Если не принадлежит ни одному из указанных типов,
*			возвращается nil
*    Примеры вызова:
(_kpblc-conv-ent-to-ename (entlast))
(_kpblc-conv-ent-to-ename (vlax-ename->vla-object (entlast)))
|;
    ;; "_kpblc-conv-ent-to-ename")
    (cond
      ((= (type ent_value) 'vla-object)
       (vlax-vla-object->ename ent_value)
       )
      ((= (type ent_value) 'ename) ent_value)
      ((= (type ent_value) 'str) (handent ent_value))
      ((= (type ent_value) 'list) (cdr (assoc -1 ent_value)))
      (t nil)
      ) ;_ end of cond
    ) ;_ end of defun
  (defun _kpblc-conv-ent-to-vla (ent_value / res)
                                ;|
*    Функция преобразования полученного значения в vla-указатель.
*    Параметры вызова:
*	ent_value	значение, которое надо преобразовать в указатель. Может
*			быть именем примитива, vla-указателем или просто
*			списком.
*			Если не принадлежит ни одному из указанных типов,
*			возвращается nil
*    Примеры вызова:
(_kpblc-conv-ent-to-vla (entlast))
(_kpblc-conv-ent-to-vla (vlax-ename->vla-object (entlast)))
|;
    (cond
      ((= (type ent_value) 'vla-object) ent_value)
      ((= (type ent_value) 'ename) (vlax-ename->vla-object ent_value))
      ((setq res (_kpblc-conv-ent-to-ename ent_value))
       (vlax-ename->vla-object res)
       )
      ) ;_ end of cond
    ) ;_ end of defun

  (defun _kpblc-conv-selset-to-ename (selset / tab item)
                                     ;|
*    Преобразование набора, полученного через ssget, в список ename-представлени
* примитивов.
*    Параметры вызова:
	selset	набор примитивов
*    Примеры вызова:
(_kpblc-conv-selset-to-ename (ssget))
|;
    (cond
      ((not selset) nil)
      ((= (type selset) 'pickset)
       (repeat (setq tab  nil
                     item (sslength selset)
                     ) ;_ end setq
         (setq tab (cons (ssname selset (setq item (1- item))) tab))
         ) ;_ end repeat
       )
      ((= (type selset) 'vla-object)
       (_kpblc-conv-vla-to-list selset)
       )
      ((listp selset) selset)
      ) ;_ end of cond
    ) ;_ end of defun

  (defun _kpblc-conv-vla-to-list (value / res)
                                 ;|
*    Преобразовывает vlax-variant или vlax-safearray в список.
|;
    (cond
      ((listp value)
       (mapcar (function _kpblc-conv-vla-to-list) value)
       )
      ((= (type value) 'variant)
       (_kpblc-conv-vla-to-list (vlax-variant-value value))
       )
      ((= (type value) 'safearray)
       (if (>= (vlax-safearray-get-u-bound value 1) 0)
         (_kpblc-conv-vla-to-list (vlax-safearray->list value))
         ) ;_ end of if
       )
      ((and (member (type value) (list 'ename 'str 'vla-object))
            (= (type (_kpblc-conv-ent-to-vla value)) 'vla-object)
            (vlax-property-available-p (_kpblc-conv-ent-to-vla value) 'count)
            ) ;_ end of and
       (vlax-for sub (_kpblc-conv-ent-to-vla value)
         (setq res (cons sub res))
         ) ;_ end of vlax-for
       )
      (t value)
      ) ;_ end of cond
    ) ;_ end of defun

  (if (and (= (type (setq trass (vl-catch-all-apply
                                  (function
                                    (lambda ()
                                      (car (entsel "\nУкажите трассу <Отмена> : "))
                                      ) ;_ end of lambda
                                    ) ;_ end of function
                                  ) ;_ end of vl-catch-all-apply
                          ) ;_ end of setq
                    ) ;_ end of type
              'ename
              ) ;_ end of =
           (wcmatch (cdr (assoc 0 (entget trass))) "*POLYLINE")
           (= (type (setq selset (vl-catch-all-apply
                                   (function
                                     (lambda ()
                                       (ssget '((0 . "LWPOLYLINE")))
                                       ) ;_ end of lambda
                                     ) ;_ end of function
                                   ) ;_ end of vl-catch-all-apply
                          ) ;_ end of setq
                    ) ;_ end of type
              'pickset
              ) ;_ end of =
           ) ;_ end of and
    (progn
      (setq trass (_kpblc-conv-ent-to-vla trass)
            elev (vla-get-elevation trass))
      (vla-put-elevation trass 0.)
            (setq  res   (apply (function append)
                         (mapcar
                           (function
                             (lambda (x / int _elev _res)
                               (setq _elev (vla-get-elevation x))
                               (vla-put-elevation x 0.)
                               (if (setq int (_kpblc-conv-list-to-3dpoints
                                               (_kpblc-conv-vla-to-list
                                                 (vla-intersectwith trass (setq x (vlax-ename->vla-object x)) acextendnone)
                                                 ) ;_ end of _kpblc-conv-vla-to-list
                                               ) ;_ end of _kpblc-conv-list-to-3dpoints
                                         ) ;_ end of setq
                                 (setq _res (mapcar
                                   (function
                                     (lambda (a)
                                       (list (cons "layer" (vla-get-layer x))
                                             (cons "dist" (vlax-curve-getdistatpoint trass a))
                                             (cons "pt" a)
                                             ) ;_ end of list
                                       ) ;_ end of lambda
                                     ) ;_ end of function
                                   int
                                   ))
                                 ) ;_ end of if
                               (vla-put-elevation x _elev)
                               _res
                               ) ;_ end of lambda
                             ) ;_ end of function
                           (_kpblc-conv-selset-to-ename selset)
                           ) ;_ end of mapcar
                         ) ;_ end of apply
            ) ;_ end of setq
      (vla-put-elevation trass elev)
      ) ;_ end of progn
    ) ;_ end of if
  res
  ) ;_ end of defun
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 26.02.2012, 14:04
#11
Composter

Отопление и вентиляция
 
Регистрация: 31.10.2008
Москва
Сообщений: 445


а еще пересечения объектов можно находить вот таким способом
Код:
[Выделить все]
  (ssnamex (ssget "_F" (list (getpoint) (getpoint)))) 
, если пересечения с конкретным объектом
Код:
[Выделить все]
  (vl-remove-if-not '(lambda(x)(equal(cadr x) ent_name_polyline ))(ssnamex (ssget "_F" (list (getpoint)(getpoint))))) 
Composter вне форума  
 
Непрочитано 26.02.2012, 14:26
#12
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,446


Цитата:
Сообщение от Composter Посмотреть сообщение
можно находить вот таким способом
При условии (как минимум), что обе точки находятся в видимой части экрана (мне так кажется).
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 29.02.2012, 12:35
#13
loginovskiy


 
Регистрация: 31.10.2011
Сообщений: 31


Спасибо всем, я кое что почерпнул, в частности понравился подход Кулика.
Но, очевидно в спешке, я не совсем правильно изложил проблему.
Дело в том, что эти самые пересечки нужно не указанием получать, а через ssget (ssget "_CP" sp_k или ssget "_F" sp_k) где sp_k - список координат
трассы (секущей). И вот тут то и возникают проблемы с выбором.
А потом уже вторая проблема с двойной точкой пересечения.
Первую проблему решил так. Выбираю все полилинии на чертеже (ssget "_X" '((0 . "*POLYLINE"))),
Создаю список по набору <имя примитива . тип линии>, изменяю их все на Continuous, выбираю их секущей плинией, определяю точки пересечения
через intersectWith и наконец возвращаю им тип. Все это только потому, что не хотят выбираться штрихпунктирные динии.
Причем замечено (может и бред), если секущая проходит по штриху - выбирается, если между штрихами - не выбирается.
loginovskiy вне форума  
 
Непрочитано 29.02.2012, 13:20
#14
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,446


Сколько ни гонял, все едино: вычисление пересечения не зависит от типа линии. Да и не должно вообще-то.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 01.03.2013, 12:46
#15
kakt00z

инженер-проектировщик КИПиА
 
Регистрация: 30.08.2008
Минск
Сообщений: 159


вопрос на тему
линия пресекает блок (замкнутый овал из 4-х примитивов). код ниже находит 4 точки пересечения.
собственно вопрос на тему - откуда 4 точки? , вопрос не на тему - почему координата Z не нуль, хотя все элементы вроде бы в Z=0 ?
инстинктивно подозреваю что это связано, но где и как? (ACAD 2008 +SP1)
Код:
[Выделить все]
 (defun structlist (pts k / i stl line)
  (= 'INT (type (/ (length pts) k)))
  (setq i 1)
  (foreach item pts
    (if (= i 4)
      (progn
	(setq stl (append stl (list line)))
	(setq line (list item))
	(setq i 1)
	)
      (setq line (append line (list item)))
      )
    (setq i (1+ i))
    )
  (append stl (list line))
  )

  (defun cdr* (lst) (reverse (cdr (reverse lst))))

;;;;--------------------------------------------------------
  (setq obj (vlax-ename->vla-object (car (entsel))))    ;;;; тыкаем в блок
  (vla-GetBoundingBox obj 'p1 'p2)
  (setq p1 (cdr* (vlax-safearray->list p1)))
  (setq p2 (cdr* (vlax-safearray->list p2)))
  
  (vl-cmdf "_.zoom" "_W" p1 p2)
  (setq ssg (ssget "_C" p1 p2 '((0 . "LINE"))))
  (setq ssg (ssname ssg 0))

  (setq pts (vlax-safearray->list (vlax-variant-value (vla-IntersectWith obj ssg 0))))
  (setq pts (structlist pts 3))
Вложения
Тип файла: dwg
DWG 2004
22222.dwg (65.3 Кб, 1785 просмотров)
kakt00z вне форума  
 
Непрочитано 04.03.2013, 14:45
#16
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,701
Отправить сообщение для Do$ с помощью Skype™


Было дело, тоже искал точки пересечения с блоком. Как я установил опытным путем, помимо пересечения с примитивами, еще добавляются точки пересечения с габаритным контейнером блока.
Тема: http://forum.dwg.ru/showthread.php?p=460622#post460622
Do$ вне форума  
 
Непрочитано 04.03.2013, 19:48
#17
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,996


Еще похожая тема Почему некорректно работает vla-intersectwith?. Там есть пример lib:GetBlockInters . Взято отсюда (см. VxGetBlockInters)
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Непрочитано 06.06.2023, 09:23
#18
Sege


 
Регистрация: 05.07.2007
Санкт-Петебург
Сообщений: 110


Коллеги, разбираюсь с IntersectWith
Тоже заметил, что IntersectWith добавляет точки переечения с габаритным контейнером блока
блок_IntersectWith.dwg
Есть блок, в отключаемом слое которого стоит объект (в моем случае это блок пожарного извещателя с радиусом действия в виде круга)
vla-IntersectWith дает координаты пересечения с учетом окружности, даже если этот слой выключен в текущем отображении (т.е. получается что габаритный контейнер блока учитывает все примитивы)
Есть ли вариант получить точки пересечения блока с полилинией только видимой части блока?
Sege вне форума  
 
Непрочитано 06.06.2023, 12:29
1 | #19
kp+

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


Красивого решения на lisp не знаю, может на arx можно, но это для профи.
Сам решал подобную задачу колхозно - делал копию блока извещателя, фиксировал entlast, потом explode, и дальше определял точки пересечения "обломков" с нужными линиями.

Последний раз редактировалось kp+, 06.06.2023 в 13:04.
kp+ вне форума  
 
Непрочитано 06.06.2023, 14:13
#20
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,499


для упрощения можно ввести отдельный скрытый непечатаемый слой типа SysClearlimitDevices и блоки обвести один раз по контуру в редакторе.
Сергей812 вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > как работает vla-IntersectWith ?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не работает инструмент "ОБРЕЗАТЬ" для полилинии. VictorHunter Вертикальные решения на базе AutoCAD 10 10.03.2021 13:46
Почему перестала работать кнопка delete? Skat AutoCAD 43 05.11.2012 17:49
Лира 9.4 не работает. maxim903 Лира / Лира-САПР 12 14.03.2009 12:42
Макрос c _Attedit не работает в 2009 Vova AutoCAD 4 12.10.2008 16:49
2009 Publish на принтер установленный в page setup не работает. Red Nova AutoCAD 18 01.09.2008 16:57