Тема: И снова полинии

Здравствуйте. Есть такая задача. Существует замкнутый контур из линейных сегментов полилинии. Допустим, надо отрисовать прямоугольное отверстие внутри этого контура. Если отверстие добавляется не по краю контура, то просто внутри него рисуется новая полилиния, обозначающее отверстие. А как сделать так, чтобы отверстие, которое попадает на край заданного контура в этом месте обрывало бы и сам контур, и контур отверстия, т.е. образовывало бы вырез и создавало бы новый контур? И так далее при добавлении нового отверстия. Заранее благодарю.

Re: И снова полинии

Примерно так

(defun C:OTK ( / blk pt Lpt pline otv L H *error* nab)
  (defun *error* (msg)(princ msg)
(if (and blk (entget blk)) (entdel blk))(princ))
(vl-load-com)
(setvar "cmdecho" 0)(setvar "expert" 5)
(setq pline (car (entsel "\nУкажите полилинию контура: ")))
(setq Lpt t pt (getvar "LASTPOINT"))
(while (and pline Lpt)
 (initget 7 )(setq L (getdist "\nДлина отверствия: "))
 (initget 7 )(setq H (getdist "\nВысота отверствия: "))
 (VL-CMDF "_.Rectang" "0,0" (list L H))
 (VL-CMDF "_.-block" "TMPBLK" "0,0" "_L" "")
 (VL-CMDF "_-INSERT" "TMPBLK" "0,0" "" "" "")
 (setq blk (entlast))
 (princ "\n Вставьте отверствие (ENTER-Хватит): ")
 (setq pt (getvar "LASTPOINT"))
 (vl-cmdf "_.CHANGE" blk "" "" pause "")
 (setq Lpt (getvar "LASTPOINT"))
 (if (equal Lpt pt 0.000001)
 (progn (entdel blk)(setq Lpt nil))
 (progn
  (vl-cmdf "_.Explode" blk)
  (setq otv (entlast))
  (if (not(vl-catch-all-error-p
    (vl-catch-all-apply 'vlax-safearray->list (list (vlax-variant-value
    (vla-intersectwith (vlax-ename->vla-object otv) (vlax-ename->vla-object pline) acextendnone))))))
  (progn ;_ пересекаются
    (vl-cmdf "_.Region" pline "")(setq pline (entlast))
    (vl-cmdf "_.Region" otv "")(setq otv (entlast))
    (vl-cmdf "_subtract" pline "" otv "")
    (setq otv (entlast) nab (ssadd))
    (foreach item (vlax-invoke (vlax-ename->vla-object otv) 'Explode)
      (ssadd (vlax-vla-object->ename item) nab))
    (if (and (getvar "PEDITACCEPT") (= (getvar "PEDITACCEPT") 1))
    (vl-cmdf "_pedit" "_Multiple" nab "" "_Join" 0 "")
    (vl-cmdf "_pedit" "_Multiple" nab "" "_Y" "_Join" 0 ""))
    (setq pline (entlast) nab nil)
    (entdel otv)
    )
) ;_ if
(setq pt (getvar "LASTPOINT"))
)
)
)
(princ)
)

Re: И снова полинии

> VVA
Спасибо, буду пробовать

Re: И снова полинии

> VVA
Все отлично работает. Огромное спасибо!

Re: И снова полинии

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

Re: И снова полинии

Или может есть возможность создания такой функции, которая перед тем как отрисовать линию или полилинию проверяла бы будет ли являться новый примитив (или его участки) "видимымми" или "невидимыми" и соответственно отрисовывала его (или его участки) сплошной или штриховой линией?

Re: И снова полинии

> [Re:]
Михаил
То, что вы делаете, похоже на создание системы 3-мерной графики. Не проще ли использовать уже созданное, например, работать не с полилиниями, а с регионами, телами, поверхностями? В 3D-системах проблемы видимости/невидимости уже давно решены.

Re: И снова полинии

Ну а в принципе можно ли такую задачу решить не прибегая к 3d-системам?

Re: И снова полинии

> Михаил
Можно. Осталось только написать свой аналог 3D-системы. :)

Re: И снова полинии

Попытался начать реализовывать задачу, начало выглядит примерно так: (обработчика ошибок нет пока, поэтому линия должна обязательно пересекать контур)

;;;Отрисовка "невидимых" линий
(defun c:visible (/ _clist points p1 p2 i lines quantity_points len)
  (setq *old_osnap* (getvar "OSMODE"))
  (setvar "OSMODE" 0)
  (setq pline (car (entsel "\nУкажите полилинию контура: ")))
  (setq p1 (getpoint "\nНачальная точка линии"))
  (setq p2 (getpoint "\nКонечная точка линии"))
  (vl-cmdf "_.line" p1 p2 "")
  (setq liine (entlast))
  (setq    points (vlax-safearray->list
         (vlax-variant-value
           (vla-intersectwith
             (vlax-ename->vla-object liine)
             (vlax-ename->vla-object pline)
             acextendnone
           ) ;_ vla-intersectwith
         ) ;_ vlax-variant-value
           ) ;_ vlax-safearray->list
  ) ;_ setq
  (setq len (length points))
  (setq    quantity_points
     (/ len 3)
    i 1
  ) ;_ setq
  (while (<= i quantity_points)
    (repeat 3
      (setq _clist (append _clist (list (car points))))
      (setq points (cdr points))
    ) ;_ repeat
    (set (read (strcat "p_i_" (itoa i))) _clist)
    (setq _clist nil)
    (setq i (1+ i))
  ) ;_ while
  (setq i 1)
  (setq lines 1)
  (vl-cmdf "_erase" liine "" "")
  (while (<= lines (/ quantity_points 2))
    (vl-cmdf "_.line"
         (eval (read (strcat "p_i_" (itoa i))))
         (eval (read (strcat "p_i_" (itoa (1+ i)))))
         ""
    ) ;_ vl-cmdf
    (setq lines (1+ lines))
    (setq i (+ 2 i))
  ) ;_ while
  (setvar "OSMODE" *old_osnap*)
) ;_ defun 

Но в результате не всегда получается то, что требуется. Можете подсказать, в какой последовательности находятся точки пересечения функцией vla-intersectwith? Существует ли в этом какая-нибудь определенная закономерность? Т.е. иногда получается в результате все правильно, а иногда последовательность нахождения точек пересечения меняется.

Re: И снова полинии

Пробуй так

;|****************** In_Figure *****************************
  * Тест — находится ли точка pt внутри контура contur.    *
  * Тема поднималась здесь                                 *
  * https://www.caduser.ru/forum/topic4008.html    *
  * Алгоритм взят из статьи О.Р.Мусина в журнале           *
  * "Программирование" 4, 91г.                             *
  * Выбран алгоритм "Сумма ориентаций пересечений"         *
  **********************************************************
* Аргументы [Тип] :
  pt     — тестируемая точка (X Y Z) [list]
  contur — список координат точек образующих контур
           в виде (pt1 pt2 ...ptn) [list]
* Возвращает
  t   - точка в контуре
  nil -  точка вне контура
* Функции :
 _locat — проверяет находится ли пара точек в квадрантах
* ((1,4)(2,4)(1,3))
 _kk  — вычисляет ориентацию отрезка
***********************************************************|;
(defun In_Figure (pt contur / pt1 pt2 pti ptl ptp ptc eps tmp)
;;;----------------------------------------------------------
  (defun My- (x y)(cond ((< x y) -1)((> x y) 1)(t 0)))
;;;----------------------------------------------------------
  (defun My+ (x y) (or (zerop x) (zerop y) (zerop (+ x y))))
;;;----------------------------------------------------------
  (defun _Locat    (pt1 pt2)
    ;_ Допустимая ли комбинация четвертей ?
    (cond
      ((and (>= (car pt1) 0) (>= (cadr pt1) 0))       ;_ 1
       (or (and (>= (car pt2) 0) (< (cadr pt2) 0)) ;_ 1-4
       (and (< (car pt2) 0) (< (cadr pt2) 0))));_ 1-3
      ((and (< (car pt1) 0) (>= (cadr pt1) 0))     ;_ 2
       (and (>= (car pt2) 0) (< (cadr pt2) 0)))    ;_ 2-4
      ((and (< (car pt1) 0) (< (cadr pt1) 0))      ;_ 3
       (and (>= (car pt2) 0) (>= (cadr pt2) 0)))   ;_ 3-1
      (t                                           ;_ 4
       (or (and (>= (car pt2) 0) (>= (cadr pt2) 0)) ;_ 4-1
       (and (< (car pt2) 0) (>= (cadr pt2) 0))))));_ 4-2
;_------------------------------------------------------------
  (defun _Kk (pt1 pt2)(if(>= (cadr pt1) (cadr pt2)) 1 -1))
;_------------------------------------------------------------
  (setq    tmp nil
    pt1 (mapcar '- (car contur) pt)
    ptp pt1)
;_ создается список отрезков
  (while contur
    (setq ptc     (mapcar '- (car contur) pt)
      contur (cdr contur))
    (if    (_locat ptc ptp)
      (setq tmp (cons (list ptc ptp) tmp)))
    (setq ptp ptc));_while
  (if (_locat pt1 ptp)
    (setq tmp (cons (list pt1 ptp) tmp)))
;_ ищем точки пересечения L+ с контуром
  (setq    pt  '(0 0 0)
    ptl '(1 0 0)
    eps 0)
  (while tmp
    (setq pt1 (caar tmp)
      pt2 (cadar tmp)
      tmp (cdr tmp)
      pti (inters pt1 pt2 pt ptl nil))
    (cond
      ((< (car pti) 0) nil);_ Отрезок пересекает L-
      (t (setq eps (+ (_kk pt1 pt2) eps))))
    );_while
;_ В eps — сформированный признак
  (not (zerop eps))
)
;;======================================================;;
;;  Return list of segms and radii valiues of polyline  ;;
;;  written by Fatty The Old Horse 10/13/05    ;;
;;      (framework)      ;;
;;======================================================;;
;;      helper functions  ;;
;; group list by number
(defun lib:group-by-num (lst num / ls ret)
  (if (= (rem (length lst) num ) 0)
    (progn
      (setq ls nil)
      (repeat (/ (length lst) num)
  (repeat num (setq ls
        (cons (car lst) ls)
        lst (cdr lst)))
  (setq ret (append ret (list (reverse ls)))
        ls nil)))
    )
ret
  )
;;;Отрисовка "невидимых" линий
(defun c:vis (/ _clist points p1 p2 i lines quantity_points len crs pl adoc)
  (VL-LOAD-COM)
  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))
  (setq *old_osnap* (getvar "OSMODE"))
  (setvar "OSMODE" 0)
  (setq pline (car (entsel "\nУкажите полилинию контура: "))
    pl (vlax-ename->vla-object pline))
  (setq crs (lib:group-by-num (vlax-get pl 'Coordinates)(if (= (vla-get-ObjectName pl) "AcDbPolyline") 2 3)))
  (setq p1 (getpoint "\nНачальная точка линии"))
  (setq p2 (getpoint p1 "\nКонечная точка линии"))
  (vl-cmdf "_.line" p1 p2 "")
  (setq liine (entlast))
  (setq points (vlax-variant-value (vla-intersectwith(vlax-ename->vla-object liine)
    (vlax-ename->vla-object pline) acextendnone )))
   (setq points (if (> (vlax-safearray-get-u-bound points 1) 0)(vlax-safearray->list points) nil))
  (if points
    (progn
      (setq points (lib:group-by-num points 3)
        p1 (cdr(assoc 10 (entget liine))))
      (setq lst (append points (list p1 (cdr(assoc 11 (entget liine))))))
      (setq lst (vl-sort lst '(lambda (pt1 pt2)(< (distance pt1 p1)(distance pt2 p1)))))
      (setq p1 (car lst))
      (entdel liine)
      (foreach item (cdr lst)
    (setq liine (vla-addline (vla-ObjectIDToObject adoc (vla-get-OwnerID pl))
      (vlax-3d-point p1)(vlax-3d-point item)))
    (setq p2 (polar p1 (angle p1 item)(* 0.5 (distance p1 item))))
    (if (In_Figure p2 crs)
      (progn ;_Внутри контура полилинии
        (vla-put-Color liine acRed) ;_Меняем цвет
        )
      )
    (setq p1 item)
    )
      )
    )
  (princ)
  )

Отрезки в контуре рисуются красным цветом

Re: И снова полинии

> VVA
Большое спасибо!