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

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

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

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

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

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

Код:
[Выделить все]
 (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
Как мне в этот набор добавить еще и "СпецСтрИзд"?
Просмотров: 6406
 
Непрочитано 22.01.2020, 13:42
#21
Кулик Алексей aka kpblc
Moderator

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


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


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


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


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


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


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


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


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


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


Цитата:
Сообщение от Сет Посмотреть сообщение
Не хотелось бы углубленно что-то сейчас изучать.
ну там очень глубоко и не надо для начала - объявление переменных, циклы, массивы - а потом втянетесь..)) Вот как будет выглядеть возможный пример реализации на .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,606


Цитата:
Сообщение от Сергей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,499


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


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


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


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


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


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


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


Цитата:
Сообщение от Сергей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,499


кстати, только запрос точки вставки и спасает от конфликта асинхронного исполнения внешней программы через 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,606


Цитата:
Сообщение от 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,606


Цитата:
Сообщение от 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,499


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


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


Так, я сейчас перезапустил автокад. В 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,499


Цитата:
Сообщение от Сет Посмотреть сообщение
затем, если у меня где-то происходит сбой работы программы из-за каких-то моих непредусмотренных задуманным алгоритмом действий - этот файл автоматически не закрывается и повторный вызов команды 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
С.-Петербург
Сообщений: 40,408


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