Как создать маркер c использованием acadЛИСП? - Страница 2
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Как создать маркер c использованием acadЛИСП?

Как создать маркер c использованием acadЛИСП?

Ответ
Поиск в этой теме
Непрочитано 03.09.2009, 09:26
Как создать маркер c использованием acadЛИСП?
Serge_BN
 
инженер
 
Оренбург
Регистрация: 18.04.2007
Сообщений: 71

Маркер или выноска, которая имеет следующий формат
Код:
[Выделить все]
маркер: однострочный_текст
;
однострочный_текст:префикс дефис инфиксы постфикс
;
префикс: текст
;
дефис: пусто
  | пробел
  | '-'
  | '.'
;
инфиксы: пусто
  | инфикс разделитель
  | инфикс разделитель инфиксы
;
инфикс: целое
;
разделитель: '.'
  | '-'
  | '/'
;
постфикс: целое
;
При этом постфикс начинается с 0 и при каждой последующей вставке увеличивается на 1
при смене префикса либо инфикса постфикс сбрасывается в 0.
Вначале выполнения команды задаются все ~фиксы, количество инфиксов, т.е. желательно, просто ввести К-1.1.0, либо ткнуть в существующий маркер, команда должна его распознать и от него продолжить далее. По умолчанию, например (U-1.1.0).
Соответственно должна быть предусмотрена возможность изменения префикса, инфикса при выполнении команды.
Так же должна быть возможность задать произвольный постфикс.

Последний раз редактировалось Serge_BN, 07.09.2009 в 08:48.
Просмотров: 4573
 
Непрочитано 11.09.2009, 12:46
#21
CB

Конструирование в области нефтеразведки
 
Регистрация: 10.02.2006
Гомель
Сообщений: 321


Практически все, что написано выше достаточно легко реализуется в LISP'е. Просто для начала сильно много информации. Начнем с mfind:
Код:
[Выделить все]
;ищем ВСЕ маркеры, соответствующие нашему синтаксису
(ssget "_X" (list '(0 . "TEXT") (cons 1 "@*#")))
;ищем маркеры, соответствующие нашему синтаксису и начинающиеся на P1.1.
(ssget "_X" (list '(0 . "TEXT") (cons 1 "P1.1.*#")))
Ну и т.д.
С сортировкой не совсем ясно...
Сортируем по убыванию
Код:
[Выделить все]
(vl-sort '("P1.1.5" "P1.1.2" "P1.3.1" "P1.2.100") '<)
;->("P1.1.2" "P1.1.5" "P1.2.100" "P1.3.1")
или надо по другому? Приведи конкретный пример.
CB вне форума  
 
Автор темы   Непрочитано 11.09.2009, 13:34
#22
Serge_BN

инженер
 
Регистрация: 18.04.2007
Оренбург
Сообщений: 71


Код:
[Выделить все]
;ищем ВСЕ маркеры, соответствующие нашему синтаксису
(ssget "_X" (list '(0 . "TEXT") (cons 1 "@*#")))
;ищем маркеры, соответствующие нашему синтаксису и начинающиеся на P1.1.
(ssget "_X" (list '(0 . "TEXT") (cons 1 "P1.1.*#")))
Чудесно, выразительность, мощь и при этом какой-то, что-ли аскетизм этого языка меня поражают, плюс профессионализм. Жаль, что не пришлось познакомиться с ним раньше (с языком, да и с СВ тоже ).

Вот здесь будем поступать как изложено в правилах для функции >.
Тогда вот это
Код:
[Выделить все]
(vl-sort '("P1.1.5" "P1.1.2" "P1.3.1" "P1.2.100") '<)
;->("P1.1.2" "P1.1.5" "P1.2.100" "P1.3.1")
все правильно, только наоборот, первым элементом в списке должен быть "Р1.3.1" он как раз наибольший. Наоборот может быть и не обязательно. Просто мне кажется, что извлечь первый элемент списка проще чем последний, но это уж дело техники.
Примеры. К1.2.100 < К1.3.0, K1.2.100 < K1.2.101, K1.2.100 < K2.1.100
Получается, что вес инфикса тем больше чем левее он записан.
Код:
[Выделить все]
i^n > i^n-1> ...> i^1>i^0
где i - инфикс, n - номер инфикса в выражении нулевой разряд n справа как при арабской записи чисел.

Присмотрелся вот к этому
Код:
[Выделить все]
;ищем ВСЕ маркеры, соответствующие нашему синтаксису
(ssget "_X" (list '(0 . "TEXT") (cons 1 "@*#")))
@*# ищет все тексты начинающиеся с буквы (@), за которой следуют буквы (@*), за которыми следует цифра. А как тогда АА1.А.1? Оно попадет в набор, но не будет являться тем что надо. Мне все-таки кажется, что надо как-то прикрутить именно проверку выражения на соответствие грамматике, инче будет много лишнего в наборе.
И еще, по инфиксам.
1.2.3. - это не один большой инфикс, это, все-таки три разных инфикса 1, 2, 3. Где наибольшим весом обладает 1( первый инфикс), а инфикс 3 обладает наименьшим весом из приведенных 1.2.3.

Последний раз редактировалось Serge_BN, 11.09.2009 в 14:24.
Serge_BN вне форума  
 
Непрочитано 14.09.2009, 11:54
#23
CB

Конструирование в области нефтеразведки
 
Регистрация: 10.02.2006
Гомель
Сообщений: 321


Цитата:
Присмотрелся вот к этому
Ты абсолютно прав, но все же в набор попадет меньше "мусора"...
Дальше этот набор нужно уточнить на соответствие грамматике, причем именно на этом этапе необходимо определиться как задавать маску выбора. Ведь наверняка придется искать маркеры с конкретным "префиксом" и "инфиксом", чтобы менять "постфикс".
Что касается сортировки, тут все ясно. Где-то на этом форуме мне попадался код, который выложил или VVA или kpblc для корректрой сортировки текста с цифрами. Я попытался ускорить его, но по моему не совсем удачно. Если дадут ссылку на тот лисп, можно его использовать, а пока привожу свой вариант (алгоритм тот же):
Код:
[Выделить все]
(defun SortMaker (lst / count i i1)
 (setq count 0)
 (foreach str lst
  (setq i 0)
  (while (wcmatch (substr str (1+ i)) "*#*")
   (while (wcmatch (substr str (setq i (1+ i)) 1) "~#"))
   (setq i1 i)
   (while (wcmatch (substr str (setq i1 (1+ i1)) 1) "#"))
   (setq count (max count (- i1 i))
         i     i1
   ) ;_  setq
  ) ;_  while
 ) ;_  foreach
 (mapcar
  '(lambda (x) (nth x lst))
  (vl-sort-i
   (mapcar
    '(lambda (str / buf s)
      (setq i   0
            i1  1
            buf ""
      ) ;_  setq
      (while (wcmatch (substr str (1+ i)) "*#*")
       (while (wcmatch (substr str (setq i (1+ i)) 1) "~#"))
       (setq buf (strcat buf (substr str i1 (- i i1)))
             i1  i
       ) ;_  setq
       (while
        (wcmatch (substr str (setq i1 (1+ i1)) 1) "#")
       ) ;_  while
       (setq s (substr str i (- i1 i))
             i i1
       ) ;_  setq
       (while (< (strlen s) count) (setq s (strcat "0" s)))
       (setq buf (strcat buf s))
      ) ;_  while
      (strcat buf (substr str (1+ i)))
     ) ;_  lambda
    lst
   ) ;_  mapcar
   '<
  ) ;_  vl-sort-i
 ) ;_  mapcar
) ;_  defun
;;;(SortMaker '("P-2.1.5" "P-1.1.5" "P-100.2.1" "P-1.1.3" "P-100.1.1" "P-1.1.10" "P-1.1.20" "P-1.5.2" "P-1.6.1"))
-> ("P-1.1.3" "P-1.1.5" "P-1.1.10" "P-1.1.20" "P-1.5.2" "P-1.6.1" "P-2.1.5" "P-100.1.1" "P-100.2.1")
Цитата:
извлечь первый элемент списка проще чем последний
первый элемент (car lst), последний - (last lst)
CB вне форума  
 
Автор темы   Непрочитано 14.09.2009, 15:25
#24
Serge_BN

инженер
 
Регистрация: 18.04.2007
Оренбург
Сообщений: 71


Цитата:
Дальше этот набор нужно уточнить на соответствие грамматике, причем именно на этом этапе необходимо определиться как задавать маску выбора. Ведь наверняка придется искать маркеры с конкретным "префиксом" и "инфиксом", чтобы менять "постфикс".
Надо подумать.
Цитата:
Что касается сортировки, тут все ясно.
Ну насчет сортировки давай уточним. Собственно сортировка вовсе не нужна. Я упомянул сортировку просто потому, что обычно так и делают, если нужно найти первый или последний элемент последовательности.
Но, задача состоит в том чтобы найти первый/последний элемент и для этого не всегда надо делать сортировку.
Рассмотрим несколько подробнее то, среди чего нам надо найти первый/последний элемент.
1. Обзовем эту функцию mfind_last, mfind_first - найти последний, найти первый. Это для того, чтобы было однозначно ясно что мы делаем.
2. Передавать этим функциям будем список строк, где каждая строка имеет вид:
префикс дефис? (инфикс разделитель)* постфикс
Где-то там перед вызовом mfind_last у нас имеется список всех маркеров. Из них надо сделать список маркеров только тех, у которых префикс равен образцу.
Тогда mfind_last фильтрацией маркеров заниматься уже не будет.
И, теперь префикс в сортировке может и не участвовать.
Мы его просто будем игнорировать.
3. Далее идет старший по весу инфикс. Поэтому мы можем отбросить все маркеры, у которых старший по весу инфикс меньше наибольшего в последовательности.
Алгоритм простой. Берем первый в последовательности старший инфикс и сравниваем его со следующим маркером. Если следующий больше текущего, то в качестве образца (текущего) берем его, иначе оставляем текущий. Т.о. мы найдем наибольший старший инфикс.
После чего создадим новый список маркеров, у которых старший инфикс равен наибольшему. Все остальные маркеры рассматривать не имеет смысла.
4. К новому списку применяем п. 3.
5. До тех пор, пока не дойдем до постфикса и к постфиксу применим опять п.3 и в результате получим маркер с наибольшим весом, или последний в последовательности. В результате мы получим список с одним единственным искомым наибольшим элементом.
6. Для mfind_first делает все так же, только ищем наименьший.

Теперь вернемся к первой задаче. Как задавать маску для поиска?
Думаю, что это не сложно. Префикс у нас отвечает за тип маркера (элемента) и задается либо явным указанием префикса DD*, BTH*, BTK* и т.д. либо его можно задать *, тогда программа должна сформировать столько списков маркеров, сколько типов префиксов найдет в чертеже. Соответственно и инфиксы - DD1.*, DD1.2* и т.д до того уровня детализации, который мне необходим, вплодь до DD1.2.7 - конкретный маркер.
Программа должна находить все, что попадает в шаблон и возвращать упорядоченный по возрастанию список маркеров.
Собственно в работе все это не очень-то и нужно. Данная задача возникает из необходимости иметь непрерывные последовательности маркеров. А в работе возникают ситуации, когда в последовательности маркера имеются дыры либо дубликаты. Эти случаи необходимо распознавать и приводить к упорядоченной непрерывной последовательности. Под непрерывной последовательностью я понимаю такую последовательность маркеров, которая пронумерована без дыр и дубликатов с шагом 1.
Может возникнуть задача объединить несколько наборов маркеров в одну последовательность. например, DD1.2* DD2.1 в последовательность DD1.0.*. Но сдесь так же можно задать список последовательностей и список содержащий целевой маркер. (src1 src2)(dst).
Serge_BN вне форума  
 
Непрочитано 14.09.2009, 16:18
#25
CB

Конструирование в области нефтеразведки
 
Регистрация: 10.02.2006
Гомель
Сообщений: 321


Да это все все ясно, не понято что делать в таком случае:
Пусть на чертеже есть маркеры P-1.1 P-1.5 и P-1.1.7
1. Маска поиска - P-1.*#
2. Все три маркера попали в набор
3. С первыми двумя понятно - P-1.5 маркер с наибольшим весом
Вопрос - что делать с третьим, ведь это маркер совершенно другого типа???
CB вне форума  
 
Автор темы   Непрочитано 15.09.2009, 09:14
#26
Serge_BN

инженер
 
Регистрация: 18.04.2007
Оренбург
Сообщений: 71


Цитата:
Вопрос - что делать с третьим, ведь это маркер совершенно другого типа???
Вопрос хороший. И на него есть такой же хороший ответ.
1. Обычно с схемах автоматизации, СС, СКС таких ситуаций не встречается. Не встречается потому, что маркировкой управляет инженер-конструктор и он прекрасно соображает, что если устройства будут промаркированы таким образом, то будут весьма плачевные последствия.
2. Если же, все-таки такая ситуация встретилась.
Можно делать отсев по количеству инфиксов, т.е. Р-1.2, Р-1.1.2 и Р-1.1.1.2 это будут разные маркеры и они не должны попасть в один набор. А маску для отбора можно будет задавать так Р?1.#+., где Р- это префикс, ? - возможный символ дефиса из набора '-','.',' ','', 1 - значение старшего инфикса, . - разделитель, #+ -инфикс, любое количество непрерывных цифр, . - разделитель. Вот последний разделитель как раз и скажет что надо производить отбор только тех маркеров, у которых только два инфикса.
Другой пример. Р-#+.#+. это почти тоже, что и предыдущий маркер, только в наборе будут присутствовать маркеры с любым старшим инфиксом.
Если же убрать последнюю точку, то в набор попадут какие попало маркеры Р-1.2, Р-1.2.3.4.100 и все что угодно с любым хвостом. Поэтому и присутствуют в маркере синтаксические конструкции - разделитель и инфикс. Для того, что бы каждый раз знать, что вот здесь закончился инфикс, или, другими словами, это самый младший инфикс, за которым следует постфикс. Это и есть решение данной проблемы. Реализация может быть разной, например, фильтр по количеству инфиксов. Может встретиться маркер типа D1, D2, т.е. в нем отсутствует инфикс. Его шаблон может быть D#+ без точек, это значит префикс за которым непосредственно следует постфикс. В конструкции P-1.2.#+ символы #+ означают тоже постфикс, который есть целое число.
Примечание. Везде, где я пишу #+, подразумевается # это цифра (0|1|2|3|4|5|6|7|8|9), + говорит о том что цифр может хотя бы одна и более.
* - говорит о том, что в контексте #* цифр может и не быть, либо быть сколько угодно. Хотя сама по себе * означает вообще все что угодно.
В доказательсто того, что это будет работать можно было бы вывести несколько теорем о свойствах маркеров такого типа, но я думаю, что приведенных рассуждений достаточно. Хотя, можно подумать и над математикой в смысле вывода свойств маркеров, формулировки и доказательству теорем и т.д. Тем более, если еще вспомнить, что программирование это в первую очередь математика а потом уже кодирование.

Последний раз редактировалось Serge_BN, 15.09.2009 в 09:24.
Serge_BN вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Как создать маркер c использованием acadЛИСП?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как в Акад 2006 программно создать подшивку с заданным набор kp+ Программирование 4 16.03.2009 23:23
Как создать функцию с необязательным вводом параметра Krieger Программирование 2 14.02.2009 11:49
SW подскажите как создать радиальное отверстие Chives SolidWorks 23 17.12.2008 00:54
Как создать виртуальный принтер Владислав Кулигин Компьютерная и бытовая техника, электроника и инструмент 4 03.01.2008 17:54
Юмор 2007 Огурец Разное 1172 29.12.2007 11:16