Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

> Александр Ривилис
Преогромнейшее спасибо.
Пока ошибок не замечено.

Re: 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)));
//       }
//     }
//   }
// }

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

> Александр Ривилис
Спасибо. Поразбираюсь.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

> Александр Ривилис
Можно скромную поправочку для класса DwgProps?
Может вместо

  // Считываем смещение DwgProps
  WORD offset_dwgprops = 0;

сделать

  // Считываем смещение DwgProps
  DWORD offset_dwgprops = 0;

А то с некоторыми файлами проблема при загрузке.
Не могли бы Вы привести обработку для версий 14...2006?

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

> vektor
По поводу DWORD - пришлите мне на e-mail такие чертежи. Интересно посмотреть - мне не попадались. А заодно и чертежи с DWGPROPS в которых есть Custom Props в тех форматах (R14...2002), которые моя программа не понимает - на досуге посмотрю.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Алескандр, а нельзя ли сделать так, чтобы функция getdwgprops изменяя Summary Info не открытого файла, сохраняла бы его preview. Т.е после работы этой функции preview затирается, а хотельось бы, чтобы оставалось. Возможно ли это вообще?

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

> serzh
Вообще это сделать использовав документированные возможности нельзя, но я подумаю. :)

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Сделал сохранение preview - не очень эстетично, но лучше чем ничего.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Реализовал более эстетичный метод сохранения preview.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Уважаемый Александр Ривилис
А можно подробнее описать как прочитать файлы AutoCAD 2000.


Александр Ривилис пишет:

.............
Это плод анализа dwg-файлов версии 2004...2007. Заниматься анализом чертежей версии R14...2002 я не стал, т.к. есть стандартные dwgprops для них.
.............
https://www.caduser.ru/forum/post128779.html#p128779

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Александр Ривилис,
Спасибо за программу! Вот только обновил Акад до 2010, а тут она не работает...
Можно попросить Вас обновить и программу?
Спасибо.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Обновил, но не проверял. Находится там же.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Александр Ривилис,
Я проверил, на 2010 работает.
Спасибо за оперативность! Пользуюсь многими Вашими программами и жить стало легче ;)
Вы замечательный человек!

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Александр Ривилис,
Спасибо Вам за программу!
Скажите пожалуйста, можно ли считать метаданные файлов AutoCAD средствами только AutoLISP, не прибегая к языку Object ARX?
При попытке считать информацию из файла, лежащего не в корне диска "C" выдаётся сообщение "nil".
Это не учтено в Вашей программе?

(изменено: Александр Ривилис, 8 мая 2011г. 22:03:21)

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Павел пишет:

При попытке считать информацию из файла, лежащего не в корне диска "C" выдаётся сообщение "nil". Это не учтено в Вашей программе?

Программа работает вне зависимости от того, где находится dwg-файл. Проверяйте:
1) правильно ли задан путь к dwg-файлу;
2) версию dwg-файла (т.е. может ли его открыть текущая версия AutoCAD)/

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Александр Ривилис,
пробовал на 2007 и на 2010-ой версиях ACAD, версии файлов соответствующие.
Считывает только из корня диска (не только "C"), к примеру:
(getdwgprops "E:\\222.dwg") - всё хорошо;
(getdwgprops "E:\\xyz\222.dwg") или (getdwgprops "E:\xyz\222.dwg") не воспринимается (думал, что дело в кириллице в названиях папок - поменял, всё равно не открывает).
Исправьте меня, пожалуйста, если я что-то не так делаю.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Павел пишет:

(getdwgprops "E:\\xyz\222.dwg") или (getdwgprops "E:\xyz\222.dwg") не воспринимается (думал, что дело в кириллице в названиях папок - поменял, всё равно не открывает). Исправьте меня, пожалуйста, если я что-то не так делаю.

Должно быть (getdwgprops "E:\\xyz\\222.dwg") (двойной обратный слэш).

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Спасибо, Александр,
для меня немного неожиданный синтаксис.
Можно ещё пару вопросов:
1) как обратиться к конкретному параметру в самом AutoCAD (в частности для записи его в текстовый файл)?
2) какую библиотеку .dll и команду в ней Вы используете в своей программе?

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Павел пишет:

для меня немного неожиданный синтаксис.

Стандартный синтаксис для строк в Autolisp и всех C-подобных языках.
P.S.: Остальных вопросов не понял, да и не место для них в этом разделе.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Здравствуйте, вопрос к А.Ривилис.
Давно и успешно испольую getdwgpropsd для себя в маленьком lisp-е для типовых проектов. Хочу поделиться ею с ребятами, которые мне помогают.Но у них установлен Zwcad. И если с моим кодом, в основном математиескими операторами, проблем нет, то с getdwgprops, использующей библиотеку ***.arx китайский САПР не совместим. Необходимо конвертация из ***.arx в совметимую ***.zrx. Для меня это дремучий лес. Правильно я понимаю, в основном с уроков школьной информатики, библиотека ***.arx используестя для использования, допустим getdwgprops как "внутренней процедуры". Так вот, как мне добраться до lisp-кода стоящим конкретно за Вашей коммандой setdwgprops. Путь с конвертацией для меня непосилен. Заранее благодарен.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Евгений  Каплуновский пишет:

Так вот, как мне добраться до lisp-кода стоящим конкретно за Вашей коммандой setdwgprops.

Код написан на C++, а не на lisp'е. С Zwcad не знаком и пытаться переписывать под него не вижу смысла. Тем более, что там понадобится иметь его SDK и т.д. и т.п.

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Спасибо за ответ. Программа на Acad, тем не менее, оч.полезная

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Здравствуйте Александр.
Благодарю за программку.
Возник вопрос по синтаксису setdwgprops:
если просто копировать [list_summary_info] из вывода getdwgprops и вставить напр. так:

(setdwgprops (("Title" "Тестовый чертеж") ("Subject" "Чертеж (/"Название/")") ("Параметр" "а это его значение")) T)

То консоль пишет *ошибка: неверная функция: "Subject"*
Автокад 2010, 32, файл соотв-й.
Кавычки из темы убирал, скобки из списка убирал, не помогает..
Сейяас попробую с указанием пути файла..

С уважением, Дмитрий

(изменено: Кулик Алексей aka kpblc, 8 августа 2014г. 14:40:06)

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Как говорится, "почувствуй разницу"

(setdwgprops '(("Title" "Тестовый чертеж") ("Subject" "Чертеж (\"Название\")") ("Параметр" "а это его значение")) T)

Re: ObjectARX. Получение/изменение из AutoLisp свойств чертежа (Summary Info)

Кулик Алексей aka kpblc пишет:

Как говорится, "почувствуй разницу"

(setdwgprops '(("Title" "Тестовый чертеж") ("Subject" "Чертеж (/"Название/")") ("Параметр" "а это его значение")) T)

Ну, допустим, апостроф я заметил сразу, другое дело, что с указанием пути к чертежу все работает, а для пустого пути (т.е. для текущего чертежа) - нет.