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

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

Как создать набор из блоков двух типов? Помогите откорректировать программу.

Ответ
Поиск в этой теме
Непрочитано 13.01.2020, 16:17
Как создать набор из блоков двух типов? Помогите откорректировать программу.
Сет
 
Регистрация: 19.11.2014
Сообщений: 2,435

Пользуюсь не своей программой по подсчету массы элементов в спецификации. Каждая строка спецификации - это блок с атрибутами. Среди прочих атрибутов есть такие, где хранятся данные о "Количестве" и "Массе единицы". Программа формирует набор из блоков и проходит по каждому блоку, считывая "Количество" и "Массу единицы", перемножает их и суммирует.

Вот как выглядит полный текст программы:

Код:
[Выделить все]
 (defun c:cs_calculate_weight (/ ss sorted ss_length i block attributes attribute sum_weight weight nof)  
(if (= (type (setq ss (vl-catch-all-apply (function (lambda () (ssget '((2 . "СпецСтр")))))))) 'pickset)
	(setq sorted (vl-sort (
		(lambda (/ tab item)
			(repeat
			        (setq tab  nil
				item (sslength ss)
				) ;_ end setq
				(setq tab (cons (ssname ss (setq item (1- item))) tab))
			) ;_ end repeat
		) ;_ end of LAMBDA
		)
		(function (lambda (a b) (> (caddr (assoc 10 (entget a))) (caddr (assoc 10 (entget b))))))
	)) ;_ end of vl-sort
) ;_ end of if
(setq ss_length (sslength ss))
(setq sum_weight 0) 
(setq i 0)
(repeat ss_length
	(setq block (vlax-ename->vla-object (nth i sorted)))
	(setq attributes (vlax-variant-value (vla-GetAttributes block)))
	(setq nof (atof (vl-string-translate "," "." (vla-get-TextString (vlax-safearray-get-element attributes 3)))))
        (setq weight (atof (vl-string-translate "," "." (vla-get-TextString (vlax-safearray-get-element attributes 4)))))
	(setq sum_weight (+ sum_weight (* nof weight)))
	(setq i (1+ i))
) ; repeat
(princ (strcat "Общая масса: " (rtos sum_weight)))
(alert (strcat "Общая масса: " (rtos sum_weight)))
(princ)  
) ; defun
Имя блоков строк спецификации - "СпецСтр". Сейчас мне нужно в набор блоков включить еще один - "СпецСтрИзд". Он отличается от "СпецСтр" только взаимным расположением атрибутов. Как я понимаю набор из блоков формируется в этом фрагменте кода:

Код:
[Выделить все]
 (if (= (type (setq ss (vl-catch-all-apply (function (lambda () (ssget '((2 . "СпецСтр")))))))) 'pickset)
	(setq sorted (vl-sort (
		(lambda (/ tab item)
			(repeat
			        (setq tab  nil
				item (sslength ss)
				) ;_ end setq
				(setq tab (cons (ssname ss (setq item (1- item))) tab))
			) ;_ end repeat
		) ;_ end of LAMBDA
		)
		(function (lambda (a b) (> (caddr (assoc 10 (entget a))) (caddr (assoc 10 (entget b))))))
	)) ;_ end of vl-sort
) ;_ end of if
Как мне в этот набор добавить еще и "СпецСтрИзд"?
Просмотров: 6191
 
Непрочитано 22.01.2020, 13:42
#21
Кулик Алексей aka kpblc
Moderator

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


Для начала - ты запускаешь приложение (которого, кроме как у тебя, ни у кого нет), и не факт, что ты дожидаешься окончания его работы.
Что это приложение делает - тайна великая и мраком покрытая. Особенно почему было невозможно всю задачу сделать на одном языке.
И как-то ковырять три сотни строк кода, учитывая невозможность повторения ситуации, лично у меня желания нет.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 22.01.2020, 14:05
#22
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от ciril Посмотреть сообщение
Повторю хороший совет, пройдите сами в отладчике, видно будет, когда функция пытается выполнить значение атрибута.
Да я очень поверхностно знаком с ЛИСПом и методами отладки функций.


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Для начала - ты запускаешь приложение (которого, кроме как у тебя, ни у кого нет), и не факт, что ты дожидаешься окончания его работы.
Что это приложение делает - тайна великая и мраком покрытая. Особенно почему было невозможно всю задачу сделать на одном языке.
И как-то ковырять три сотни строк кода, учитывая невозможность повторения ситуации, лично у меня желания нет.
Я сам эту программку Specification.exe сделал чисто для себя. На С++. На одном языке реализовать все - не научился. Знаю, что можно было работать с Автокадом через ObjectArx, но там требуется гораздо больше времени на изучение, чем на ЛИСП. Понимаю, что информации в моем вопросе много и сложно в ней разобраться, но может просто при беглом просмотре выявляется очевидная причина ошибки из поста 5. Все таки ошибка довольно специфическая как мне кажется.
Сет вне форума  
 
Непрочитано 22.01.2020, 14:27
#23
Сергей812


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


Сет, может вам C# + NET API попробовать? После С++ это попроще будет, чем в лиспе разбираться, имхо.
Сергей812 вне форума  
 
Автор темы   Непрочитано 22.01.2020, 14:52
#24
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
Сет, может вам C# + NET API попробовать? После С++ это попроще будет, чем в лиспе разбираться, имхо.
Не хотелось бы углубленно что-то сейчас изучать. Я редко делаю какие-то примочки для автокада. Вот когда-то был сделал программку для заполнения спецификаций, все хорошо работало. А тут захотел расширить функционал - добавил строку спецификаций для изделий - блок "СпецСтрИзд". Сама-то эта строчка нормально формируется, но вот с подсчетом суммы по всем строчкам возникла проблема.
Сет вне форума  
 
Непрочитано 22.01.2020, 16:14
#25
Сергей812


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


Цитата:
Сообщение от Сет Посмотреть сообщение
Не хотелось бы углубленно что-то сейчас изучать.
ну там очень глубоко и не надо для начала - объявление переменных, циклы, массивы - а потом втянетесь..)) Вот как будет выглядеть возможный пример реализации на .Net функции подсчета общей массы аналогичный вашему коду в шапке темы:
Код:
[Выделить все]
 
// AutoCAD
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;


namespace calculate_weight
{
    public class CommandsClass
    {
        [CommandMethod("cs_calculate_weight")]
        public void Cs_calculate_weight()
        {
            // Получаем текущий документ, его БД чертежа и редактор
            Document lAcadDoc = Application.DocumentManager.MdiActiveDocument;
            Database lAcadDb = lAcadDoc.Database;
            Editor lAcadEd = lAcadDoc.Editor;
            // Общий обработчик ошибок
            try
            {
                // Задаем фильтр выборки: вставки блоки, имеющие атрибуты
                // и с именами, начинающимися на СпецСтр 
                SelectionFilter lSelectionFilter = new SelectionFilter(
                    new TypedValue[3]
                    {
                    new TypedValue(0, "INSERT"),
                    new TypedValue(66, 1),
                    new TypedValue(2, "СпецСтр*")
                    });
                // Запрашиваем выборку блоков с учетом ранее сформированного фильтра
                PromptSelectionResult lPromptSelectionResult = 
                    lAcadEd.SelectAll(lSelectionFilter);
                // Если выборка прошла неудачно 
                if (lPromptSelectionResult.Status != PromptStatus.OK)
                {
                    lAcadEd.WriteMessage(
                        "\nНе удалось получить выборку блоков строк спецификации!");
                    return;
                }
                // Счетчик количества блоков
                int lCounterBlocks = 0;
                // Локальная переменная для преобразования, счетчик общей массы
                double lWeight, lCounterWeight = 0;
                // Открываем транзакцию
                using (Transaction lAcadTran = lAcadDb.TransactionManager.StartTransaction())
                {
                    // В цикле по идентификаторам вставок блоков
                    foreach (ObjectId lIdBlockRef in lPromptSelectionResult.Value.GetObjectIds())
                    {
                        // Получаем вставку блока
                        BlockReference lBlockReference = (BlockReference)
                            lAcadTran.GetObject(lIdBlockRef, OpenMode.ForRead);
                        // Получаем его коллекцию атрибутов
                        AttributeCollection lAttributeCollection = 
                            lBlockReference.AttributeCollection;
                        // В подцикле по коллекции атрибутов текущей вставки блока
                        foreach (ObjectId lIdAttr in lAttributeCollection)
                        {
                            // Получаем вставку атрибута
                            AttributeReference lAttributeReference = (AttributeReference)
                                lAcadTran.GetObject(lIdAttr, OpenMode.ForRead);
                            // Если обнаружен искомый атрибут
                            if (lAttributeReference.Tag.Equals("МАССА"))
                            {
                                // Если преобразование прошло успешно
                                if (double.TryParse(lAttributeReference.TextString, out lWeight))
                                {
                                    // Учитываем массу в общем счетчике
                                    lCounterWeight += lWeight;
                                    // Учитываем обработанный блок
                                    lCounterBlocks++;
                                    // Выходим из подцикла по атрибутам
                                    break;
                                }
                                else
                                {
                                    lAcadEd.WriteMessage("\nОшибка при преобразования массы!");
                                    return;
                                }
                            }
                        }
                    }
                    // Подтверждаем транзакцию
                    lAcadTran.Commit();
                }
                // Выводим результаты
                lAcadEd.WriteMessage("\nОбработано блоков: {0} ; Общая масса: {1}",
                    lCounterBlocks, lCounterWeight.ToString(".000"));
            }
            catch (System.Exception ex)
            {
                // Выводим сообщение об ошибке
                lAcadEd.WriteMessage(
                    "\nВ ходе подсчета общей массы произошла ошибка: {0}", ex.Message);
            }
        }

    }
}


насколько понятнее кода на лиспе?)

Цитата:
Сообщение от Сет Посмотреть сообщение
А тут захотел расширить функционал - добавил строку спецификаций для изделий - блок "СпецСтрИзд". Сама-то эта строчка нормально формируется, но вот с подсчетом суммы по всем строчкам возникла проблема.
чтобы вносить изменения, причем в значительно части заимствованный чужой код - это надо вникать достаточно глубоко в лисп, имхо. Иначе так и будет - "то хвост увязнет, то клюв..."
Сергей812 вне форума  
 
Непрочитано 22.01.2020, 16:18
#26
ciril

САПР
 
Регистрация: 29.09.2011
СПб
Сообщений: 283


Цитата:
Сообщение от Сет Посмотреть сообщение
Да я очень поверхностно знаком с ЛИСПом и методами отладки функций.
Открываешь чертеж с блоками, на которых вылезает ошибка, из него вызываешь _vlide, там в меню отладка метишь пункт "прервать на ошибке", открываешь lsp с функцией, вызывающей ошибку, загружаешь из код из редактора Ctrl+Alt+E, переключаешься в чертеж, вызываешь функцию, когда выбросит на ошибке, вызываешь окно поиска ошибок Ctrl+Shift+R, копируешь содержимое в журнал, копируешь из журнала сюда, продолжаешь обсуждать здесь причину возникновения ошибки.

----- добавлено через 58 сек. -----
Цитата:
Сообщение от Сергей812 Посмотреть сообщение
насколько понятнее кода на лиспе?)
На порядок понятнее лисп будет
__________________
На работе было скучно:shout:
ciril вне форума  
 
Автор темы   Непрочитано 22.01.2020, 17:29
#27
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
насколько понятнее кода на лиспе?)
Привычнее конечно, но это ж нужно знать все эти классы автокада, их методы и свойства.

Цитата:
Сообщение от ciril Посмотреть сообщение
Открываешь чертеж с блоками, на которых вылезает ошибка, из него вызываешь _vlide, там в меню отладка метишь пункт "прервать на ошибке", открываешь lsp с функцией, вызывающей ошибку, загружаешь из код из редактора Ctrl+Alt+E, переключаешься в чертеж, вызываешь функцию, когда выбросит на ошибке, вызываешь окно поиска ошибок Ctrl+Shift+R, копируешь содержимое в журнал, копируешь из журнала сюда, продолжаешь обсуждать здесь причину возникновения ошибки.
Не знаю правильно ли все сделал (опечатка в выделенном тексте видимо), получилось вот так (вложение).
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 13
Размер:	52.3 Кб
ID:	222257  
Сет вне форума  
 
Непрочитано 22.01.2020, 17:45
#28
Сергей812


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


Offtop:
Цитата:
Сообщение от Сет Посмотреть сообщение
Привычнее конечно, но это ж нужно знать все эти классы автокада, их методы и свойства.
Аутодеск не делает из этого секрета
частичные русскоязычные переводы - сайт Бушмана Андрея (на года не обращайте внимание - большая часть актуальна до сих пор), официальный сайт разработчиков. Нашли нужный пример, забили в поисковик по первой ссылке нужные названия классов и получили их описание - на английском, но разобраться можно.


----- добавлено через ~15 мин. -----
и крякозябры кириллические из редактора лиспа уберите - первый рецепт из поста №8
Сергей812 вне форума  
 
Автор темы   Непрочитано 22.01.2020, 18:16
#29
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
и крякозябры кириллические из редактора лиспа уберите - первый рецепт из поста №8
У меня Автокад 2020, не нашел у него файла VLIDE.DSK.
Сет вне форума  
 
Непрочитано 22.01.2020, 18:19
#30
Сергей812


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


а рецепт в последней ссылке в последнем посте той же ветки?
Сергей812 вне форума  
 
Автор темы   Непрочитано 22.01.2020, 19:39
#31
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
а рецепт в последней ссылке в последнем посте той же ветки?
Это помогло. Собственно вот результат действий по посту 26.
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 16
Размер:	70.4 Кб
ID:	222262  
Сет вне форума  
 
Непрочитано 22.01.2020, 22:25
#32
ciril

САПР
 
Регистрация: 29.09.2011
СПб
Сообщений: 283


Теперь правый клик по [2] и выбери перейти к месту вызова функции и где это выложи, и значение параметра функции.
Но вообще, ничего, что эта ошибка отличается от той, что в посте 5?

----- добавлено через ~3 мин. -----
По [2] в окне ошибок.
__________________
На работе было скучно:shout:
ciril вне форума  
 
Непрочитано 22.01.2020, 22:49
#33
Сергей812


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


кстати, только запрос точки вставки и спасает от конфликта асинхронного исполнения внешней программы через startapp)
Сергей812 вне форума  
 
Непрочитано 22.01.2020, 23:18
#34
ciril

САПР
 
Регистрация: 29.09.2011
СПб
Сообщений: 283


В определение функции cs_numeration в список локальных переменных type добавь:

004 (defun c:cs_add_specification (/ point file mode block сюда-добавь-type)
009 (setq type (read-line file))

Это из листинга в посте 19.

Offtop: Наверное, ибо предположения с телефона.
У тебя в этом виде 009 связывается переменная type (сейчас глобальная) с прочитанной строкой, а в момент [02] она выполняется. И у тебя строки в файле по разному в двух случаях формировались.
[32] тоже выполни, и посмотри значение type
__________________
На работе было скучно:shout:

Последний раз редактировалось ciril, 22.01.2020 в 23:46.
ciril вне форума  
 
Автор темы   Непрочитано 23.01.2020, 00:32
#35
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от ciril Посмотреть сообщение
Теперь правый клик по [2] и выбери перейти к месту вызова функции и где это выложи, и значение параметра функции.
Вложение.

----- добавлено через ~1 мин. -----
Цитата:
Сообщение от ciril Посмотреть сообщение
Но вообще, ничего, что эта ошибка отличается от той, что в посте 5?
Да нет, ошибка вроде такая же. Внешне так же выглядит и появляется в тот же момент.

----- добавлено через ~3 мин. -----
Цитата:
Сообщение от ciril Посмотреть сообщение
В определение функции cs_numeration в список локальных переменных type добавь:

004 (defun c:cs_add_specification (/ point file mode block сюда-добавь-type)
009 (setq type (read-line file))

Это из листинга в посте 19.
А это же другая функция - нумерация строк спецификации. Она, кстати, тоже перестает работать вместе с cs_calculate_weight с той же самой ошибкой.
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 6
Размер:	85.1 Кб
ID:	222270  
Сет вне форума  
 
Автор темы   Непрочитано 23.01.2020, 00:38
#36
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от ciril Посмотреть сообщение
В определение функции cs_numeration в список локальных переменных type добавь:

004 (defun c:cs_add_specification (/ point file mode block сюда-добавь-type)
009 (setq type (read-line file))
Добавил эту переменную, при программном добавлении блока со строкой спецификации (cs_add_specification), выскочило вот такое сообщение.
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный1.png
Просмотров: 8
Размер:	4.5 Кб
ID:	222271  
Сет вне форума  
 
Непрочитано 23.01.2020, 00:41
#37
Сергей812


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


в справку смотрите хоть иногда)
type
Сергей812 вне форума  
 
Автор темы   Непрочитано 23.01.2020, 00:50
#38
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Так, я сейчас перезапустил автокад. В cs_add_specification добавлена переменная type. Добавляю в чертеж блоки строк спецификации - функция суммирования работает без ошибок. Надо завтра посмотреть будет ли эта ошибка появляться снова.

Кстати, подскажите с одной вещью, если это не сложно. У меня весь этот набор функций по работе со строками спецификаций практически не защищен от возникающих ошибок. Например я в функции cs_add_specification открываю файл spec.txt:

Код:
[Выделить все]
 (setq file (open "D:\\MyAutoCAD\\spec.txt" "r"))
затем, если у меня где-то происходит сбой работы программы из-за каких-то моих непредусмотренных задуманным алгоритмом действий - этот файл автоматически не закрывается и повторный вызов команды cs_add_specification уже не срабатывает, выдается сообщение с ошибкой, что файл spec.txt используется. Как бы мне по простому отлавливать всяческие ошибки в этом коде и автоматически закрывать файл spec.txt в случае их возникновения?
Сет вне форума  
 
Непрочитано 23.01.2020, 01:13
#39
Сергей812


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


Цитата:
Сообщение от Сет Посмотреть сообщение
затем, если у меня где-то происходит сбой работы программы из-за каких-то моих непредусмотренных задуманным алгоритмом действий - этот файл автоматически не закрывается и повторный вызов команды cs_add_specification уже не срабатывает, выдается сообщение с ошибкой, что файл spec.txt используется.
просто по нормальному не должно быть ожидания ввода от пользователя во время работы с файлом, либо серьезно обкручивать интерфейс проверками. А так у вас через startapp запущена внешняя программа, а дальше как повезет - успеет внешняя программа отработать до выбора точки вставки - вся программа работает штатно, не успеет - результат непредсказуемый. Плюс еще переопределяете стандартные функции своими переменными, и что там еще в коде делаете...
Сергей812 вне форума  
 
Непрочитано 23.01.2020, 08:09
#40
Кулик Алексей aka kpblc
Moderator

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


ciril, type - зарезервированное слово.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Как создать набор из блоков двух типов? Помогите откорректировать программу.

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Требуется написать программу для автоматической расстановки блоков по полилинии. Mozgolom Поиск исполнителей 0 30.12.2019 15:50
Как создать одно 3д тело из двух цветов (или материалов)? Loksana AutoCAD 5 26.01.2018 14:30
народ помогите создать линию проектируемой телефонной канализации ОлегD AutoCAD 13 23.08.2011 19:30
Подсчет и сортировка блоков на текущем слое. Помогите отредактировать. Kortes Программирование 17 26.03.2010 18:46
Как создать сопряжение двух швеллеров по косому срезу BM60 AutoCAD 3 24.04.2009 14:56