Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)
> Александр Ривилис
Преогромнейшее спасибо.
Пока ошибок не замечено.
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → Готовые программы → ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)
> Александр Ривилис
Преогромнейшее спасибо.
Пока ошибок не замечено.
> ShaggyDoc
Возможно Вам это будет интересно. Это плод анализа dwg-файлов версии 2004...2007. Заниматься анализом чертежей версии R14...2002 я не стал, т.к. есть стандартные dwgprops для них. С налету не смог разобраться в каком формате хранятся даты, но думаю, что это не существенно. Наличие AutoCAD на компьютере не обяхательно. Этот код легко переписать на другие языки программирования. Структура данных в AutoCAD 2007 отличается только тем, что строки хранятся в уникоде. Возможно он кому-то и пригодится, т.к. аналогов в интернете я не нашел.
////////////////////////////////////////////////////////////////////////// // Реализация DwgProps для AutoCAD 2004...2007 (возможно и дальше, // если сохранится структура dwg-файла). ////////////////////////////////////////////////////////////////////////// #include <io.h> #include <sys/stat.h> #include <fcntl.h> #include <malloc.h> #include <stdlib.h> #include <vector> #include <string> // // Имена стандартных свойств чертежа // const char *stdPropNames[] = { "title", "subject", "author", "keywords", "comments", "lastSavedBy", "revisionNumber", "hyperlinkBase" }; class DwgProps { struct record { WORD len; union { char c[32767]; wchar_t w[32767]; }; }; public: DwgProps() { for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames[0]); i++) { m_stdProps.push_back(""); } stimes[0]=stimes[1]=stimes[2]=0; }; ~DwgProps() {} int load(const char *fname); // data items const char *title() const {return m_stdProps[0].c_str(); } const char *subject() const {return m_stdProps[1].c_str(); } const char *author() const {return m_stdProps[2].c_str(); } const char *keywords() const {return m_stdProps[3].c_str(); } const char *comments() const {return m_stdProps[4].c_str(); } const char *lastSavedBy() const {return m_stdProps[5].c_str(); } const char *revisionNumber() const {return m_stdProps[6].c_str(); } const char *hyperlinkBase() const {return m_stdProps[7].c_str(); } const char *customName(int idx) const { return ((idx >= 0 && idx < (int)m_custPropNames.size())?m_custPropNames[idx].c_str():0); } const char *customValue(int idx) const { return ((idx >= 0 && idx < (int)m_custPropValues.size())?m_custPropValues[idx].c_str():0); } const char *customValue(const char *name) const { for (int i=0; i < (int)m_custPropNames.size(); i++) { if (m_custPropNames[i] == name) return m_custPropValues[i].c_str(); } return 0; } int customNumber() const { return (int) m_custPropNames.size(); } const __int64 inDwg() const { return stimes[0];} // Не поддерживается const __int64 created() const { return stimes[1];} // Не поддерживается const __int64 updated() const { return stimes[2];} // Не поддерживается private: // data std::vector<std::string> m_stdProps; std::vector<std::string> m_custPropNames; std::vector<std::string> m_custPropValues; __int64 stimes[3]; }; inline int DwgProps::load(const char * fname) { bool unicode = false; int h; char buf[32767]; memset(buf,0,sizeof(buf)); if ((h = _open(fname,_O_BINARY|_O_RDONLY)) == -1) return 0; char ACADVER[7]; if (_read(h,ACADVER,sizeof(ACADVER)) <= 0) { _close(h); return 0; } if (atoi(ACADVER+2) < 1018) { // AutoCAD R14,2000...2002 обрабатывать не будем _close(h); return 0; } if (atoi(ACADVER+2) >= 1021) { // AutoCAD 2007... строки в Unicode unicode = true; } // Указатель перемещаем на WORD, содержащий смещение DwgProps if (_lseek(h,0x20,SEEK_SET) == -1) { _close(h); return 0; } // Считываем смещение DwgProps WORD offset_dwgprops = 0; if (_read(h,&offset_dwgprops,sizeof(offset_dwgprops)) <= 0) { _close(h); return 0; } long begin_offset = offset_dwgprops, cur_offset = offset_dwgprops; // Устанавливаем указатель на начало DwgProps if (_lseek(h,offset_dwgprops,SEEK_SET) == -1) { _close(h); return 0; } // Теперь можно читать длины и сами строки: record rec; for (int i=0; i < sizeof(stdPropNames)/sizeof(stdPropNames[0]); i++) { if (_read(h,&rec,sizeof(record)) == -1) { _close(h); return 0; } if (unicode) { WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL); m_stdProps[i] = buf; } else { m_stdProps[i] = rec.c; } cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len)); if (_lseek(h,cur_offset,SEEK_SET) == -1) { _close(h); return 0; } } // Пропускаем 24 байта - три поля по 8 байт - это даты в непонятном формате for (int i=0; i < 3; i++) { if (_read(h,&(stimes[i]),sizeof(__int64)) == -1) { _close(h); return 0; } } cur_offset += 3*sizeof(__int64); if (_lseek(h,cur_offset,SEEK_SET) == -1) { _close(h); return 0; } // Читаем количество собственных (custom) переменных WORD nCust = 0; if (_read(h,&nCust,sizeof(nCust)) <= 0) { _close(h); return 0; } cur_offset += sizeof(WORD); for (int i=0; i < nCust; i++) { // Считываем имя переменной if (_read(h,&rec,sizeof(record)) == -1) {_close(h); return 0;} if (unicode) { WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL); m_custPropNames.push_back(buf); } else { m_custPropNames.push_back(rec.c); } cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len)); if (_lseek(h,cur_offset,SEEK_SET) == -1) { _close(h); return 0; } if (_read(h,&rec,sizeof(record)) == -1) {_close(h); return 0;} if (unicode) { WideCharToMultiByte(CP_ACP,0,rec.w,rec.len,buf,rec.len,0,NULL); m_custPropValues.push_back(buf); } else { m_custPropValues.push_back(rec.c); } cur_offset += (rec.len*((unicode)?2:1) + sizeof(rec.len)); if (_lseek(h,cur_offset,SEEK_SET) == -1) {_close(h); return 0;} } _close(h); return 1; } //----------------------------------------- // Пример использования класса DwgProps //----------------------------------------- // const char * valid(const char *s) { return s ? s : ""; } // // void main(int argc, char *argv[]) // { // DwgProps p; // // if ( argc < 2 ) { // fprintf(stderr, "Usage: pscan file [file ...]\n"); // return; // } // // // loop over files // for ( int f = 1; f < argc; f++ ) { // printf("%s\n", argv[f]); // // if ( p.load(argv[f]) ) { // // print list of tags // printf(" Title: [%s]\n", valid(p.title())); // printf(" Subject: [%s]\n", valid(p.subject())); // printf(" Author: [%s]\n", valid(p.author())); // printf(" Comments: [%s]\n", valid(p.comments())); // printf(" Keywords: [%s]\n", valid(p.keywords())); // printf(" HyperlinkBase: [%s]\n", valid(p.hyperlinkBase())); // printf(" LastSavedBy: [%s]\n", valid(p.lastSavedBy())); // printf(" RevisionNo.: [%s]\n", valid(p.revisionNumber())); // for ( int i = 0; i < p.customNumber(); i++ ) { // printf(" Custom Name[%d]: [%s]\n", i, valid(p.customName(i))); // printf(" Custom Value[%d]: [%s]\n", i, valid(p.customValue(i))); // } // } // } // }
> Александр Ривилис
Спасибо. Поразбираюсь.
> Александр Ривилис
Можно скромную поправочку для класса DwgProps?
Может вместо
// Считываем смещение DwgProps WORD offset_dwgprops = 0;
сделать
// Считываем смещение DwgProps DWORD offset_dwgprops = 0;
А то с некоторыми файлами проблема при загрузке.
Не могли бы Вы привести обработку для версий 14...2006?
> vektor
По поводу DWORD - пришлите мне на e-mail такие чертежи. Интересно посмотреть - мне не попадались. А заодно и чертежи с DWGPROPS в которых есть Custom Props в тех форматах (R14...2002), которые моя программа не понимает - на досуге посмотрю.
Алескандр, а нельзя ли сделать так, чтобы функция getdwgprops изменяя Summary Info не открытого файла, сохраняла бы его preview. Т.е после работы этой функции preview затирается, а хотельось бы, чтобы оставалось. Возможно ли это вообще?
> serzh
Вообще это сделать использовав документированные возможности нельзя, но я подумаю. :)
Сделал сохранение preview - не очень эстетично, но лучше чем ничего.
Реализовал более эстетичный метод сохранения preview.
Уважаемый Александр Ривилис
А можно подробнее описать как прочитать файлы AutoCAD 2000.
.............
Это плод анализа dwg-файлов версии 2004...2007. Заниматься анализом чертежей версии R14...2002 я не стал, т.к. есть стандартные dwgprops для них.
.............
https://www.caduser.ru/forum/post128779.html#p128779
Александр Ривилис,
Спасибо за программу! Вот только обновил Акад до 2010, а тут она не работает...
Можно попросить Вас обновить и программу?
Спасибо.
Обновил, но не проверял. Находится там же.
Александр Ривилис,
Я проверил, на 2010 работает.
Спасибо за оперативность! Пользуюсь многими Вашими программами и жить стало легче ;)
Вы замечательный человек!
Александр Ривилис,
Спасибо Вам за программу!
Скажите пожалуйста, можно ли считать метаданные файлов AutoCAD средствами только AutoLISP, не прибегая к языку Object ARX?
При попытке считать информацию из файла, лежащего не в корне диска "C" выдаётся сообщение "nil".
Это не учтено в Вашей программе?
При попытке считать информацию из файла, лежащего не в корне диска "C" выдаётся сообщение "nil". Это не учтено в Вашей программе?
Программа работает вне зависимости от того, где находится dwg-файл. Проверяйте:
1) правильно ли задан путь к dwg-файлу;
2) версию dwg-файла (т.е. может ли его открыть текущая версия AutoCAD)/
Александр Ривилис,
пробовал на 2007 и на 2010-ой версиях ACAD, версии файлов соответствующие.
Считывает только из корня диска (не только "C"), к примеру:
(getdwgprops "E:\\222.dwg") - всё хорошо;
(getdwgprops "E:\\xyz\222.dwg") или (getdwgprops "E:\xyz\222.dwg") не воспринимается (думал, что дело в кириллице в названиях папок - поменял, всё равно не открывает).
Исправьте меня, пожалуйста, если я что-то не так делаю.
(getdwgprops "E:\\xyz\222.dwg") или (getdwgprops "E:\xyz\222.dwg") не воспринимается (думал, что дело в кириллице в названиях папок - поменял, всё равно не открывает). Исправьте меня, пожалуйста, если я что-то не так делаю.
Должно быть (getdwgprops "E:\\xyz\\222.dwg") (двойной обратный слэш).
Спасибо, Александр,
для меня немного неожиданный синтаксис.
Можно ещё пару вопросов:
1) как обратиться к конкретному параметру в самом AutoCAD (в частности для записи его в текстовый файл)?
2) какую библиотеку .dll и команду в ней Вы используете в своей программе?
для меня немного неожиданный синтаксис.
Стандартный синтаксис для строк в Autolisp и всех C-подобных языках.
P.S.: Остальных вопросов не понял, да и не место для них в этом разделе.
Здравствуйте, вопрос к А.Ривилис.
Давно и успешно испольую getdwgpropsd для себя в маленьком lisp-е для типовых проектов. Хочу поделиться ею с ребятами, которые мне помогают.Но у них установлен Zwcad. И если с моим кодом, в основном математиескими операторами, проблем нет, то с getdwgprops, использующей библиотеку ***.arx китайский САПР не совместим. Необходимо конвертация из ***.arx в совметимую ***.zrx. Для меня это дремучий лес. Правильно я понимаю, в основном с уроков школьной информатики, библиотека ***.arx используестя для использования, допустим getdwgprops как "внутренней процедуры". Так вот, как мне добраться до lisp-кода стоящим конкретно за Вашей коммандой setdwgprops. Путь с конвертацией для меня непосилен. Заранее благодарен.
Так вот, как мне добраться до lisp-кода стоящим конкретно за Вашей коммандой setdwgprops.
Код написан на C++, а не на lisp'е. С Zwcad не знаком и пытаться переписывать под него не вижу смысла. Тем более, что там понадобится иметь его SDK и т.д. и т.п.
Спасибо за ответ. Программа на Acad, тем не менее, оч.полезная
Здравствуйте Александр.
Благодарю за программку.
Возник вопрос по синтаксису setdwgprops:
если просто копировать [list_summary_info] из вывода getdwgprops и вставить напр. так:
(setdwgprops (("Title" "Тестовый чертеж") ("Subject" "Чертеж (/"Название/")") ("Параметр" "а это его значение")) T)
То консоль пишет *ошибка: неверная функция: "Subject"*
Автокад 2010, 32, файл соотв-й.
Кавычки из темы убирал, скобки из списка убирал, не помогает..
Сейяас попробую с указанием пути файла..
С уважением, Дмитрий
Как говорится, "почувствуй разницу"
(setdwgprops '(("Title" "Тестовый чертеж") ("Subject" "Чертеж (\"Название\")") ("Параметр" "а это его значение")) T)
Как говорится, "почувствуй разницу"
(setdwgprops '(("Title" "Тестовый чертеж") ("Subject" "Чертеж (/"Название/")") ("Параметр" "а это его значение")) T)
Ну, допустим, апостроф я заметил сразу, другое дело, что с указанием пути к чертежу все работает, а для пустого пути (т.е. для текущего чертежа) - нет.
Форумы CADUser → Программирование → Готовые программы → ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)
Форум работает на PunBB, при поддержке Informer Technologies, Inc