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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Готовые программы > LISP. Отрисовка произвольной трассы из отрезков и дуг.

LISP. Отрисовка произвольной трассы из отрезков и дуг.

Ответ
Поиск в этой теме
Непрочитано 16.02.2009, 08:40 #1
LISP. Отрисовка произвольной трассы из отрезков и дуг.
Profan
 
Москва
Регистрация: 25.12.2005
Сообщений: 13,627

Программа может заменить стандартную команду "_Line" ("Отрезок")
Код:
[Выделить все]
 
;********** SETI.LSP ***********************************
; Программа отрисовки сети из сопряженных отрезков.
; Автор Громов В.В. 2009 г.
; Макрос для загрузки:
; ^C^C(if (not C:СЕТИ) (load "seti")) СЕТИ
;
(defun C:СЕТИ ( / echo rd pt1 pt2 pt3 ent1 ent2)
(setq echo (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(if (null rds) (setq rds "0"))
(princ (strcat "\n Радиус сопряжения <" rds ">: "))
(setq rd (getint))
(if (= rd nil) (setq rd (atoi rds)) (setq rds (itoa rd)))
(vl-cmdf "_FILLET" "_r" rd)
(initget 7)
(setq pt1 (getpoint "\n Начальная точка: "))
(initget 7)
(setq pt2 (getpoint pt1 "\n Вторая точка: "))
(vl-cmdf "_LINE" pt1 pt2 "")
(setq ent1 (entlast))
(setq pt3 (getpoint pt2 "\n Следующая точка <Enter-Конец>: "))
(if pt3
(progn
(vl-cmdf "_LINE" pt2 pt3 "")
(setq ent2 (entlast))
(vl-cmdf "_fillet" ent1 ent2)
(while pt3
   (setq pt2 pt3)
   (setq ent1 ent2)
   (setq pt3 (getpoint pt2 "\n Следующая точка <Enter-Конец> "))
   (if pt3
       (progn
       (vl-cmdf "_LINE" pt2 pt3 "")
       (setq ent2 (entlast))
       (vl-cmdf "_fillet" ent1 ent2)
       )
       (princ "\n Конец.")
   )
)
)
)
(setvar "CMDECHO" echo)
(princ)
)
(princ "\n Ввести в командной строке СЕТИ")
Вариант с преобразованием отрезков и дуг в полилинию.

Код:
[Выделить все]
 
;********** SETI_PL.LSP *****************************************
; Программа отрисовки сети из сопряженных отрезков 
; с последующим объединением в полилинию.
; Автор Громов Владимир 2009 г.
; Макрос для загрузки:
; ^C^C(if (not C:СЕТИ_ПЛ) (load "seti_pl")) СЕТИ_ПЛ
;
(defun C:СЕТИ_ПЛ ( / echo rd pt1 pt2 pt3 ent1 ent2 ss dlina)
(setq echo (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(setq ss (ssadd))
(if (null rds) (setq rds "0"))
(princ (strcat "\n Радиус сопряжения <" rds ">: "))
(setq rd (getint))
(if (= rd nil) (setq rd (atoi rds)) (setq rds (itoa rd)))
(vl-cmdf "_FILLET" "_r" rd)
(initget 7)
(setq pt1 (getpoint "\n Начальная точка: "))
(initget 7)
(setq pt2 (getpoint pt1 "\n Вторая точка: "))
(vl-cmdf "_LINE" pt1 pt2 "")
(setq ent1 (entlast))
(ssadd ent1 ss)
(setq pt3 (getpoint pt2 "\n Следующая точка <Enter-Конец>: "))
(if pt3
(progn
(vl-cmdf "_LINE" pt2 pt3 "")
(setq ent2 (entlast))
(ssadd ent2 ss)
(vl-cmdf "_fillet" ent1 ent2)
(ssadd (entlast) ss)
(while pt3
   (setq pt2 pt3)
   (setq ent1 ent2)
   (setq pt3 (getpoint pt2 "\n Следующая точка <Enter-Конец> "))
   (if pt3
       (progn
       (vl-cmdf "_LINE" pt2 pt3 "")
       (setq ent2 (entlast))
       (ssadd ent2 ss)
       (vl-cmdf "_fillet" ent1 ent2)
       (ssadd (entlast) ss)
       )
       (princ "\n Конец.")
   )
)
)
)
(vl-cmdf "_PEDIT" "_m" ss "" "_yes" "_join" "" "")
(vl-load-com)
(setq dlina (vlax-get-property (vlax-ename->vla-object (entlast)) 'length))
(princ "\n Длина трассы = ") (princ dlina)
(setvar "CMDECHO" echo)
(princ)
)
(princ "\n Ввести в командной строке СЕТИ_ПЛ")

Последний раз редактировалось Profan, 17.02.2009 в 06:16.
Просмотров: 16497
 
Непрочитано 17.02.2009, 00:02
#2
Кулик Алексей aka kpblc
Moderator

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


Критику примешь?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 17.02.2009, 06:23
#3
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Критику примешь?
Критику приму. Только отмечу, что программа написана по просьбе специалистов-слаботочников и в таком виде вполне их устраивает. Привязки специально не отключены, пользователи могут отключать и включать их вручную в процессе отрисовки. Модуль обработки ошибок сознательно не делал, возможные ошибки здесь мало чем отличаются от возможных ошибок при выполнении команды "_Line". Возможно, в программах появятся некоторые усовершенствования, связанные с с печатью на экране длин сегментов. Интересно, что неправильное задание радиуса сопряжения не приводит к аварийному завершению программы.
Profan вне форума  
 
Непрочитано 17.02.2009, 11:09
#4
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,381


Привязки должны работать в момент ввода данных, но обязательно должны отключаться каждый раз в момент рисования. А потом восстанавливаться. Типа
Код:
[Выделить все]
(setq old_osnap (getvar "OSMODE"))
(setvar "OSMODE" 0)
(vl-cmdf "_LINE" pt1 pt2 "")
(setvar "OSMODE" old_osnap)
Тогда и пользователь может любыми привязками пользоваться и программа будет работать правильно.
ShaggyDoc вне форума  
 
Непрочитано 17.02.2009, 11:59
#5
Krieger

инженер (КМ)
 
Регистрация: 30.10.2004
Красноярск
Сообщений: 3,825


Тогда уж так:
(vl-cmdf "_LINE" "_none" pt1 "_none" pt2 "")
Тогда восстанавливать не надо привязки и esc не помешает.
__________________
Делай хорошо, плохо само получится.
Krieger вне форума  
 
Непрочитано 17.02.2009, 12:05
#6
Makswell

Инженер-строитель
 
Регистрация: 15.08.2007
Киров
Сообщений: 2,204


Цитата:
Сообщение от Profan Посмотреть сообщение
Модуль обработки ошибок сознательно не делал, возможные ошибки здесь мало чем отличаются от возможных ошибок при выполнении команды "_Line".
Как сказать. При отмене команды _Line переменная CMDECHO не сбрасывается в 0. ИМХО это важно.
Makswell вне форума  
 
Автор темы   Непрочитано 17.02.2009, 12:29
#7
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


Именно эти замечания я и ожидал увидеть. Можно оставить CMDECHO равной 1. Если количество командных строк не более 3, то фактически все промежуточные сообщения проскакивают незаметно. С OSMODE вообще связываться не хочу. Не думаем же мы об этой переменной, когда рисуем отрезки, просто устанавливаем заранее нужные нам объектные привязки. Да и F3 работает ведь. Честно скажу - совсем неохота расчитывать на дремучих пользователей.
Profan вне форума  
 
Непрочитано 17.02.2009, 15:44
#8
Дима_

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


Ну если уж на то пошло - почему-бы просто не заменить
Код:
[Выделить все]
(vl-cmdf "_LINE" pt2 pt3 "")
на
Код:
[Выделить все]
(entmakex (list (cons 0 "line") (cons 10 pt2) (cons 11 pt3)))
P.S. А еще красивее вместо
Код:
[Выделить все]
(vl-cmdf "_LINE" pt2 pt3 "")
(setq ent2 (entlast))
Код:
[Выделить все]
(setq ent2 (entmakex (list (cons 0 "line") (cons 10 pt2) (cons 11 pt3))))
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 17.02.2009, 15:53
#9
Makswell

Инженер-строитель
 
Регистрация: 15.08.2007
Киров
Сообщений: 2,204


ну и
Код:
[Выделить все]
(vl-cmdf "_FILLET" "_r" rd)
ИМХО лучше заменить на
Код:
[Выделить все]
(setvar "FILLETRAD" rd)
Добавлено:
а лучше, конечно так:
Код:
[Выделить все]
(setq old_FILLETRAD (getvar "FILLETRAD"))
....
....
(setvar "FILLETRAD" rd)
....
....
(setvar "FILLETRAD" old_FILLETRAD)
Makswell вне форума  
 
Автор темы   Непрочитано 17.02.2009, 16:23
#10
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


Дима_, объясни - в чем для пользователя проявится преимущество твоего варианта кода?
Makswell, а в твоей замене что-то не вижу смысла...
Profan вне форума  
 
Непрочитано 17.02.2009, 16:38
#11
Makswell

Инженер-строитель
 
Регистрация: 15.08.2007
Киров
Сообщений: 2,204


Цитата:
Сообщение от Profan Посмотреть сообщение
Makswell, а в твоей замене что-то не вижу смысла...
Так быстрее и без эха в ком. строке.
А насчет добавленного позже кода, я (и не только) считаю, что после окончания работы программы сама система Автокада должна оставаться в таком же виде, что и непосредственно перед запуском лиспа. Вот запустит потом юзер просто _FILLET, а там уже какой-то непонятный радиус появился. А может у юзера вообще привычка делать _FILLET с радиусом 0? Короче, вспомни увлекательные приключения некоторых пользователей на тему FILEDIA.
Makswell вне форума  
 
Непрочитано 17.02.2009, 16:41
#12
Дима_

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


То Profan 100% избавления от гемороя с привязками.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 17.02.2009, 18:29
#13
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


Да какой, блин, геморрой с привязками? Пользователь рисовал подобную трассу отрезками с нужными ему привязками или с отключенными привязками и никакого геморроя у него не образовалось. Точно так же, и с теми же привязками или без оных он будет тащить свою трассу с помощью программы. Суть-то программы в том, что теперь пользователю не надо прощелкивать трассу, отрисованную последовательными отрезками, командой "_FILLET" ("СОПРЯЖЕНИЕ"). Вот это главное.
Makswell, FILEDIA скрыта от пользователя, а при выполнении команды "_FILLET" на экран выводится текущее значение радиуса сопряжения, причем, независимо от значения переменной CMDECHO.

И вообще, знаете, чем слаботочник обосновал необходимость такой программы? Думаете, он кабель или короб гнет по радиусу, скажем, 150 мм? Да нет, это не трубопровод. Просто ему нужно, чтобы его трассы на чертеже имели закругления в углах. В отличие от стен, которые закруглений в углах не имеют. Вот такая подоплёка.

Еще добавлю. На форуме caduser.ru один пользователь предложил дополнить программу возможностью по ходу построения отменять сегменты. Что-то я сомневаюсь в необходимости этого для случая простых отрезков с дугами. Тем не менее, был бы рад подсказке, как это сделать. Во второй программе идет накопление объектов в наборе, из которого потом формируется полилиния. Если я отменю сегмент, этот объект из набора тоже исчезнет?

Последний раз редактировалось Profan, 17.02.2009 в 18:43.
Profan вне форума  
 
Непрочитано 17.02.2009, 21:23
#14
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,990
<phrase 1= Отправить сообщение для VVA с помощью Skype™


Profan, Отменять сегменты последовательно?
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Автор темы   Непрочитано 17.02.2009, 22:19
#15
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


VVA, наверное последовательно, как при отрисовке полилинии. Правда, я себе не очень представляю отмену дугового сегмента, который получился сопряжением...
Profan вне форума  
 
Непрочитано 17.02.2009, 23:32
#16
Дима_

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


Цитата:
Сообщение от Profan Посмотреть сообщение
Да какой, блин, геморрой с привязками? Пользователь рисовал подобную трассу отрезками с нужными ему привязками или с отключенными привязками и никакого геморроя у него не образовалось...
В том-то и беда, что сейчас не образовались а в самый нужный момент и не заметишь как провод "в воздухе" висит. Попробуй в приложенном примере не меняя масштаб и не врашая вид, соедини линией центр большей окружности и любой из углов прямоугольника (с включенными привязками). Вначале при помощи
Код:
[Выделить все]
(vl-cmdf "_line" (getpoint) (getpoint) "")
, а потом
Код:
[Выделить все]
(entmakex (list (cons 0 "line") (cons 10 (getpoint)) (cons 11 (getpoint))))
.
Вложения
Тип файла: dwg
DWG 2004
пример косяков с привязками.dwg (30.8 Кб, 2284 просмотров)
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 18.02.2009, 06:34
#17
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


Цитата:
Сообщение от Дима_ Посмотреть сообщение
В том-то и беда, что сейчас не образовались а в самый нужный момент и не заметишь как провод "в воздухе" висит.
Дима_, да я в принципе не спорю с тем фактом, что неправильно установленные привязки могут сыграть плохую роль при отрисовке объектов. Но в данном случае отрисовка производится вообще при выключенных привязках, а эту операцию мои заказчики выполняют нажатием клавиши F3. Вообще, отрисовку сетей они производят фактически на глазок, вдоль стен помещений и изредка могут временно включить привязку при подводке к какому-нибудь распределителю. В большинстве случаев отрисовка производится в режиме ОРТО, но иногда и при выключенным режиме ОРТО, что выполняется нажатием клавиши Shift. И вот тут есть своя проблема: клавиша Shift является клавишей временной замены (переключателем режима ОРТО). Но в то же время при нажатой клавише Shift радиус сопряжения временно сбрасывается в 0 - вот проблема, с которой я еще не разобрался. Или вот отмена последнего отрисованного сегмена в случае циклического выполнения команд с переназначением координат точек. А то - какие-то привязки. Задача специализированная. Конечно, если к ней подходить, как к некой абстрактной задаче отрисовки с неопределенными условиями - тогда можно и поизгаляться с предвосхищениям всех мыслимых условий. Но, может, к этому я еще вернусь, пока надо решить несколько принципиальных вопросов, возможно у заказчиков (пользователей) появятся дополнительные пожелания.
Profan вне форума  
 
Непрочитано 18.02.2009, 12:17
#18
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,990
<phrase 1= Отправить сообщение для VVA с помощью Skype™


Profan, Вот вариант с отменой. Добавил коментарии, должно быть понятно.
Остановлюсь на основном моменте. При отмене с помощью UNDO восстанавливается и состояние системных переменных, в том числе и USER*
Поэтому
1. С помощью UNDOMARKS контролируем счетчик отмен, чтобы не отменить лишнего
2. Запоминаем X последней точки в USERR1, Y в USERR2. В случае отмены последнюю точку восстанавливает из этих переменных
3. Для сопряжения запоминаем метку (5 код dxf) последнего отрезка в переменной USERS2, в переменную USERS1 запоминаем предыдущее значение USERS2. Это позволит начать сопрягать начиная с 2 отрезков.
4. Для вызова сопряжения используем vl-cmdf. В случае невозможности сопрячь отрезки заданным радиусом не произойдет аварийного завершения команды.
Вот как-то так
Код:
[Выделить все]
;;;********** SETI.LSP ***********************************
;;; Программа отрисовки сети из сопряженных отрезков.
;;; Автор Громов В.В. 2009 г.
;;; Корректировка для опции Отмени (UNDO)
;;; Владимир Азарко (VVA) 
;;; Макрос для загрузки:
;;; ^C^C(if (not C:СЕТИ)(load "seti"));СЕТИ;
;;; ^C^C(if (not C:СЕТИ_ПЛ)(load "seti"));СЕТИ_ПЛ;
;;;
 
(defun C:СЕТИ_ПЛ ()(seti t))
(defun C:СЕТИ ()(seti nil))
(princ "\n Ввести в командной строке СЕТИ_ПЛ или СЕТИ")
(defun seti ( toPline / echo rd pt1 pt2 ent1 ent2 U_M *error* old_FRD eLast ss)
;;;Функция seti - отрисовка сетей
;;; Аргумент toPline = t - собирать в полилинию
;;;          toPline = nil - нет
  (vl-load-com)
  ;;;Объявляем локальную ф-цию *error*
  (defun *error* (msg / image_set)
;;;Прерываем активную команду  
(while (> (getvar "CMDACTIVE") 0)(command))
(princ msg)
(setvar "FILLETRAD" old_FRD)
(setvar "USERS1" "")  ;;;Чистим переменные
(setvar "USERS2" "")  ;;;Чистим переменные
 (princ)
  )
;;;Проверяем установки UNDO и устанавливает All control
  (setq U_M (getvar "UNDOCTL"))
  (cond
    ((= (logand U_M 1) 0)(command "_.UNDO" "_All"))  ;;; Отключено UNDO
    ((= (logand U_M 3) 3)(command "_.UNDO" "_Control" "_All")) ;;; Разрешена отмена одной операции
    (t nil)
  ) ;_ end of cond
(setq U_M (getvar "UNDOMARKS")) ;;;VVA Запоминаем счетчик отмен UNDO
(setq old_FRD  (getvar "FILLETRAD"))
(setvar "USERS1" "")  ;;;Чистим переменные
(setvar "USERS2" "")  ;;;Чистим переменные
(setq echo (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(if toPline  
;;; Запоминаем в eLast последний примитив
(if (null(setq eLast (entlast)))
    (progn (entmake '((0 . "point") (10 0.0 0.0 0.0)))
       (setq eLast (entlast))(entdel eLast)))
  )
(if (not(numberp *RDS*))(setq *RDS* (getvar "FILLETRAD")))
(princ "\n Радиус сопряжения <")(princ  *RDS*)(princ ">: ")
(if (setq rd (getint))(setq *RDS* rd)(setq rd *RDS*))
(setvar "FILLETRAD" rd)  
(initget 7)
(setq pt1 (getpoint "\n Начальная точка: "))
(initget "Отмени Undo _Undo Undo")
(while (setq pt2 (getpoint pt1 "\nСледующая точка [Отмени] <выход>: "))
  (cond
     ((listp pt2) ;_Указана точка
      ;;;Запоминаем в переменных USERR1 и USERR2 X и Y указанной точки
      ;;;в мировых координатах. Это позволит пользователю прозрачно менять ПСК
      (setvar "USERR1" (car (trans pt1 1 0))) ;;;Запоминаем X точки pt1 в МСК
      (setvar "USERR2" (cadr (trans pt1 1 0)));;;Запоминаем Y точки pt1 в МСК
      (command "_.UNDO" "_M")                 ;;;Ставим метку UNDO
      (command "_.LINE" "_none" pt1 "_none" pt2 "")
      (setvar "USERS1" (getvar "USERS2"))  ;;;Перемещаем метку 2-го примитива в 1-й
      (setvar "USERS2" (cdr(assoc 5 (entget (entlast))))) ;;Метка последнего примитива
      (if (and (setq ent1 (handent (getvar "USERS1")))  ;;; Примитив существует
               (setq ent2 (handent (getvar "USERS2")))  ;;; Примитив существует
               (entget ent1)  ;;; Примитив не удален
               (entget ent2)  ;;; Примитив не удален
               )
        (vl-cmdf "_.FILLET"  ent1 ent2)
 
        ;;;Сопрягаем
        )
      (setq pt1 pt2)
      )
     ((= pt2 "Undo")
      (if (< U_M (getvar "UNDOMARKS")) ;;;Если есть что отменять
        (progn
       (command "_.UNDO" "_B")
       (setq pt1 (list (getvar "USERR1") (getvar "USERR2")))
           (setvar "LASTPOINT" (setq pt1 (trans pt1 0 1)))
          )
        (alert "Отменять больше нечего")
        )
      )
     (t nil)
     )
 (initget "Отмени Undo _Undo Undo")
)
  ;;;Нужно собрать все в полилинию
  (if (and toPline eLast)
    (progn
     (setq ss (ssadd))
     (while (setq  eLast (entnext  eLast))(ssadd  eLast ss))
     (if (= (sslength ss) 0)(setq ss nil)) ;;; Пустой набор
     (if ss ;;;что-то есть
       (if (and (getvar "PEDITACCEPT") (= (getvar "PEDITACCEPT") 1))
         (vl-cmdf "_pedit" "_Multiple" ss "" "_Join" 0 "")
         (vl-cmdf "_pedit" "_Multiple" ss "" "_Y" "_Join" 0 "")
         )
       )
     (setq ss nil)
      )
    )
(setvar "CMDECHO" echo)
(setvar "FILLETRAD" old_FRD)
(princ)
)
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Автор темы   Непрочитано 18.02.2009, 12:25
#19
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


VVA, спасибо. Поработаю с программой, покажу пользователям, потом поделюсь впечатлениями.
Profan вне форума  
 
Автор темы   Непрочитано 19.02.2009, 15:18
#20
Profan


 
Регистрация: 25.12.2005
Москва
Сообщений: 13,627


VVA, прими мою благодарность и благодарность моих друзей, все довольны и счастливы. В некоторый момент показалось, что твоя программа конфликтует с СПДС, но потом вяснилось, что все дело в настройках СПДС (там текущий масштаб типа линий все время сбрасывался в 1, в результате чего наши отрезки и дуги отрисовывались не так, как предполагалось).
Profan вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Готовые программы > LISP. Отрисовка произвольной трассы из отрезков и дуг.

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нужен LISP для суммы длин отрезков линни ilka_t LISP 219 10.09.2019 10:22
Lisp (отрисовка колонны) не работает dextron3 LISP 5 26.07.2008 20:14