Тема: Использование command в LISP коде для offset на определенный слой

Здраствуйте.
Есть проблема.
Хочу сделать offset от линий на определенный слой.
До offset надо сделать пару начальных действий, после - все сделанный примитивы перекинуть на определенный слой.
Вот код:

(defun c:otl ()
  (print "Pick layer to offset to:")
  (setq lay (ssget)
    lay (assoc 8 (entget (ssname lay 0)));pick layer
    lastelem (entlast);mark last element
  )
  (command "_OFFSET")
)
(defun c:lto()
  (setq lastelem (entnext lastelem))
  (while (/= nil lastelem) ; all added after lastelem
    (setq ed (entget lastelem);modify to layer lay
      ed (subst  lay
             (assoc 8 ed)        ; Changes the layer group in ed.
             ed                 ; to layer MYLAYER.
             )
      )
    (entmod ed)
    (setq lastelem (entnext lastelem))
  )
) 

Как видите две процедуры, а очень охота одну.

Re: Использование command в LISP коде для offset на определенный слой

Примерно что-то вроде этого:

(vl-load-com)
(setq величина_OFFSET 5)
(setq ss (ssget))
(if ss (progn
  (setq i 0)
  (repeat (sslength ss)
    (setq obj
         (car
            (vlax-safearray->list
              (vlax-variant-value
                (vla-offset (vlax-ename->vla-object (ssname ss i)) величина_OFFSET)
              )
            )
         )
    )
    (vla-Put-Layer obj "МОЙ_СЛОЙ")
    (setq i (1+ i))
  )
))

Re: Использование command в LISP коде для offset на определенный слой

Подскажите по поводу  "vla-offset"  у меня часто появляется непонятный глюк: часть полилиний делает офсет наружу, а часть внутрь...
в своих кодах приходится использовать vl-cmdf...
может поделитесь сокровенным знанием с неофитом?
Заранее СПАСИБО!

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Проблемы с vla-offset возникают от того, что какой-то "чебурашка" сделал так, что для отрезков "оно" ведёт себя по одним правилам ('+' влево от направления отрисовки примитива, '-' вправо), для полилиний, дуг и подобного по другим (наоборот), а для окружностей по третьим ('+' вовне, '-' вовнутрь). Мало того, в R15 и R16 поведение этой функции не идентично (приведено описание для R16). Ну и кому этого мало - "крокодил", который писал хэлп описал всё совсем отдельно от всего реально происходящего. Одно слово - чудовища.

Re: Использование command в LISP коде для offset на определенный слой

> Шапокляк
И все-таки имея несколько замкнутых полилиний
при овсете с "+" некоторые делают "vla-offset"  только во внутрь...
Чем эти полилинии отличаются от других, я не понимаю... но, что-бы после офсета не сравнивать площади, приходится использовать  vl-cmdf... хотя догадываюсь - кто-то давно нашел выход или знает в каких случаях появляется глюк...

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Рисуем замкнутую полилинию "по часовой" и такую-же "против", сравниваем, и всё понимаем...

Re: Использование command в LISP коде для offset на определенный слой

а без Vla можно как-нибудь обойтись?

Re: Использование command в LISP коде для offset на определенный слой

> Шапокляк
СПАСИБО!!! сам за пару месяцев, недодумался, вставил  vl-cmdf и злился, что слишком медленно ;(   (разница в 3-5 раз!).
Подскажите , как попроще узнать в какую сторону нарисованна полилиния, проблемма в том, что нужно програмно обрабатывать тысячи vla полилиний с сотней-двумя узловыми точками...

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
С учётом того, что полилиния может иметь самопересечения, только анализом координат узловых точек.

Re: Использование command в LISP коде для offset на определенный слой

> Шапокляк
Самопересечений гарантированно нет!

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Сравниваем координаты 1 и 2 полилинии.
Если {x1>x2 & y1>y2 or x1<x2 & y1<y2} меняем знак величины офсета на противоположный. Правда для чистоты не мешало бы еще проверять знак Z нормали.

Re: Использование command в LISP коде для offset на определенный слой

> BigBrother
Полилиния может идти замысловатой змейкой...
Т.е. чтобы не обрабатывать больше сотни узловых точек, берем координаты 3х ближайших точек к вершинам габаритного контейнера, и смотрим расстояния от начала до точек (вдоль полилинии)...
СПАСИБО ЗА СОВЕТ! Сейчас попробую настрочить код.

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Направление однозначно определяется по первым 2-м точкам. А как она потом куда "загнется", дело десятое...
(setq x1 (vlax-safearray-get-element (vlax-variant-value(vla-get-Coordinates vlaobj)) 0)
x2 (...(...(... ...)1) и т.д.

Re: Использование command в LISP коде для offset на определенный слой

Пардон, на месте x2 - y1 конечно же... :(

Re: Использование command в LISP коде для offset на определенный слой

> BigBrother
Что-то я совсем запутался... получается 2 варианта:
1. Общее направление замкнутой полилинии по часовой или против...
2. Начальный вектор в (+) или в (-)...
;~(((

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Упс... Проверка моего предположения на 10 кошка... , нет п.линиях вроде бы показывала его правильность, но стоило оформить это дело в функцию и :(
Как решение частного случая с закрытыми непересекающимися полилиниями можно предложить проверку св-ва "area" у только что созданной п.линии и если оно меньше\больше чем у оригинала (зависит от знака величины офсета) стирать ее и отрисовывать с другим знаком офсета.

Re: Использование command в LISP коде для offset на определенный слой

Вот быстренько накидала (на вскидку, могут быть принципиальные ошибки):

(defun is-lwpoly-clock (lwpoly / dxf coords ang)
  (setq    coords (mapcar (function cdr)
               (vl-remove-if-not
             (function
               (lambda (a)
                 (= (car a) 10)
               ) ;_ end of lambda
             ) ;_ end of function
             (setq dxf (entget lwpoly))
               ) ;_ end of vl-remove-if-not
           ) ;_ end of mapcar
  ) ;_ end of setq
  (setq    ang (mapcar (function angle) (cons (last coords) coords) coords)
    ang (mapcar (function -) ang (cons (last ang) ang))
  ) ;_ end of setq
  (< (length (vl-remove-if (function minusp) ang))
     (length (vl-remove-if-not (function minusp) ang))
  ) ;_ end of <
) ;_ end of defun

Аргумент - примитив.
Возврат - T/nil

Re: Использование command в LISP коде для offset на определенный слой

Пожалуй, лучше так:

(defun is-lwpoly-clock (lwpoly / dxf coords ang)
  (setq    coords (mapcar (function cdr)
               (vl-remove-if-not
             (function
               (lambda (a)
                 (= (car a) 10)
               ) ;_ end of lambda
             ) ;_ end of function
             (setq dxf (entget lwpoly))
               ) ;_ end of vl-remove-if-not
           ) ;_ end of mapcar
  ) ;_ end of setq
  (setq    ang (mapcar (function angle) (cons (last coords) coords) coords)
    ang (mapcar (function
              (lambda (b)
            (if (> (abs b) pi)
              (- (rem b pi))
              b
            ) ;_ end of if
              ) ;_ end of lambda
            ) ;_ end of function
            (mapcar (function -) ang (cons (last ang) ang))
        ) ;_ end of mapcar
  ) ;_ end of setq
  (< (length (vl-remove-if (function minusp) ang))
     (length (vl-remove-if-not (function minusp) ang))
  ) ;_ end of <
) ;_ end of defun

Re: Использование command в LISP коде для offset на определенный слой

а так:

(defun is-lwpoly-clock (lwpoly / dxf coords ang)
  (setq    coords (mapcar (function cdr)
               (vl-remove-if-not
             (function
               (lambda (a)
                 (= (car a) 10)
               ) ;_ end of lambda
             ) ;_ end of function
             (setq dxf (entget lwpoly))
               ) ;_ end of vl-remove-if-not
           ) ;_ end of mapcar
  ) ;_ end of setq
  (setq    ang (mapcar (function angle) (cons (last coords) coords) coords)
    ang (mapcar (function
              (lambda (b)
            (if (> (abs b) pi)
              (- (rem b pi))
              b
            ) ;_ end of if
              ) ;_ end of lambda
            ) ;_ end of function
            (mapcar (function -) ang (cons (last ang) ang))
        ) ;_ end of mapcar
  ) ;_ end of setq
  (minusp (apply (function +) ang))
) ;_ end of defun

ещё вернее

Re: Использование command в LISP коде для offset на определенный слой

ОГРОМНОЕ ВСЕМ СПАСИБО!!! Скорость работы последнего варианта - более чем!!!

Re: Использование command в LISP коде для offset на определенный слой

> Евгений
Там ещё кое-какой мусор оставался от промежуточных вариантов, в вычищенном виде:

(defun is-lwpoly-clock (lwpoly / coords ang)
  (setq coords (mapcar (function cdr)
                       (vl-remove-if-not
                         (function
                           (lambda (a)
                             (= (car a) 10)
                           ) ;_ end of lambda
                         ) ;_ end of function
                         (entget lwpoly)
                       ) ;_ end of vl-remove-if-not
               ) ;_ end of mapcar
        ang    (mapcar (function angle) (cons (last coords) coords) coords)
  ) ;_ end of setq
  (minusp (apply (function +)
                 (mapcar (function
                           (lambda (b)
                             (if (> (abs b) pi)
                               (- (rem b pi))
                               b
                             ) ;_ end of if
                           ) ;_ end of lambda
                         ) ;_ end of function
                         (mapcar (function -) ang (cons (last ang) ang))
                 ) ;_ end of mapcar
          ) ;_ end of apply
  ) ;_ end of minusp
) ;_ end of defun

Re: Использование command в LISP коде для offset на определенный слой

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

(defun is-lwpoly-clock (lwpl / pnts angl)
  (setq pnts (mapcar (function cdr)
                     (vl-remove-if-not
                       (function
                         (lambda (a)
                           (= (car a) 10)
                         ) ;_ end of lambda
                       ) ;_ end of function
                       (entget lwpl)
                     ) ;_ end of vl-remove-if-not
             ) ;_ end of mapcar
        angl (mapcar (function angle) (cons (last pnts) pnts) pnts)
  ) ;_ end of setq
  (minusp (apply (function +)
                 (mapcar (function
                           (lambda (b)
                             (cond ((< (abs b) pi) b)
                                   ((minusp b) (+ (* 2 pi) b))
                                   (t (+ (* -2 pi) b))
                             ) ;_ end of cond
                           ) ;_ end of lambda
                         ) ;_ end of function
                         (mapcar (function -) angl (cons (last angl) angl))
                 ) ;_ end of mapcar
          ) ;_ end of apply
  ) ;_ end of minusp
) ;_ end of defun

Re: Использование command в LISP коде для offset на определенный слой

Еще раз огромное спасибо!!!
Вставил ваш код в свою прогу - просто супер!
Очень понравилась работа со списками...
А я до сих пор car nth или максимум vl-sort  ;((