вставка блоков

Автор Тема: вставка блоков  (Прочитано 21800 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
вставка блоков
« : 04-12-2013, 13:23:32 »
даже не знаю в чем дело. короче говоря, ситуация такая (упрощенно :) )
есть окошко с кнопочками. за каждой кнопочкой закреплена вставка соответствующего блока (блок может быть динамическим).
сами блоки находятся в файле, например, c:\aaa\data.dwg, ну и естественно имеют уникальные имена.
по нажатию на кнопочку отрабатывает функция
drawSign(_T("динблок1"),_T("C:\\aaa\\data.dwg"),0.2); //динблок1 - имя блока, C:\\aaa\\data.dwg - в каком файле искать блок, 0.2 - масштаб

за этой функцией скрывается следующее:
Код - C++ [Выбрать]
  1. AcDbObjectId importBlockToCurDWGDatabase(const ACHAR *pBlockName, const ACHAR *pFileName)
  2. {
  3.         Acad::ErrorStatus es=Acad::eOk;
  4.         AcDbObjectId idImported; // ID нашего нового блока
  5.         AcDbDatabase* pWorkDatabase = acdbHostApplicationServices()->workingDatabase();
  6.         AcAxDocLock docLock(pWorkDatabase);
  7.         AcDbDatabase* pBlockDatabase = new AcDbDatabase(false,true);
  8.         es = pBlockDatabase->readDwgFile(pFileName);
  9.         if(es!=Acad::eOk){delete pBlockDatabase;return NULL;}
  10.        
  11.         try
  12.         {
  13.                 AcDbBlockTable* pBlockTable;
  14.                 es=pBlockDatabase->getSymbolTable(pBlockTable,AcDb::kForRead);
  15.                 if(es!=Acad::eOk){delete pBlockDatabase;return NULL;}
  16.          
  17.                 AcDbObjectId idInsRecord;      
  18.                 es=pBlockTable->getAt(pBlockName,idInsRecord);
  19.                 pBlockTable->close();
  20.                 if(es!=Acad::eOk){delete pBlockDatabase;return NULL;} // нет такого блока
  21.          
  22.                 AcDbDatabase* pTempDB;
  23.                 es=pBlockDatabase->wblock(pTempDB,idInsRecord);
  24.                 if(es!=Acad::eOk){delete pBlockDatabase;return NULL;} // не скопировался блок в пустую базу
  25.          
  26.                 es=pWorkDatabase->insert(idImported,pBlockName,pTempDB);
  27.                 delete pTempDB;
  28.                 if(es!=Acad::eOk){delete pBlockDatabase;return NULL;} // не вставилась пустая база с блоком в нашу текущую базу
  29.         }catch(...){delete pBlockDatabase;return NULL;}
  30.  
  31.         delete pBlockDatabase;
  32.         return idImported;
  33. }
  34.  
  35. void drawSign(CString blockName, CString blockFilePath, double scale)
  36. {
  37.         AcDbObjectId newBlockTableId;
  38.         AcGePoint3d insPnt;
  39.  
  40.         acdbHostApplicationServices()->enableMessageDisplay(false);
  41.         newBlockTableId = importBlockToCurDWGDatabase(blockName.GetString(),blockFilePath.GetString());
  42.         acdbHostApplicationServices()->enableMessageDisplay(true);
  43.         if (newBlockTableId.isNull())
  44.         {
  45.                 acedAlert(_T("Данный блок не найден"));
  46.                 return;
  47.         }
  48.        
  49.         acedCommand(RTSTR,_T("_ucsicon"),RTSTR,_T("_off"),0); // значек СК
  50.         acedCommand (RTSTR, _T("_ucs"),RTSTR,_T("_v"),0);
  51.         AcDbDatabase* pWorkDatabase = acdbHostApplicationServices()->workingDatabase();
  52.         AcAxDocLock docLock(pWorkDatabase);
  53.  
  54.         int osnap = acdbHostApplicationServices()->workingAppSysvars()->osmode();
  55.         acdbHostApplicationServices()->workingAppSysvars()->setOsmode(64 + 512);
  56.         if(acedGetPoint(NULL,_T("\nТочка вставки: "),asDblArray (insPnt))!=RTNORM)
  57.         {
  58.                 acdbHostApplicationServices()->workingAppSysvars()->setOsmode(osnap);
  59.                 acedCommand(RTSTR,_T("_ucs"),RTSTR,_T("_p"),0);
  60.                 acedCommand(RTSTR,_T("_ucsicon"),RTSTR,_T("_on"),0);
  61.                 return;
  62.         }
  63.  
  64.         AcDbBlockReference *blockReference = new AcDbBlockReference(insPnt,newBlockTableId);
  65.         blockReference->setRotation(0.0);
  66.         blockReference->setNormal (AcGeVector3d (0.0, 0.0, 1.0)) ;
  67.         blockReference->setScaleFactors(AcGeScale3d(scale));
  68.         AcGeMatrix3d matUcs;
  69.         acedGetCurrentUCS(matUcs);
  70.         blockReference->transformBy(matUcs);
  71.         postToDb(blockReference); // запись экзкмпляра блока в БД чертежа
  72.  
  73.         acdbHostApplicationServices()->workingAppSysvars()->setOsmode(osnap);
  74.         acedCommand(RTSTR,_T("_ucs"),RTSTR,_T("_p"),0);
  75.         acedCommand(RTSTR,_T("_ucsicon"),RTSTR,_T("_on"),0);
  76.         acedPostCommandPrompt();
  77. }
  78.  

если вставлять блоки в чертеж через drawSign (т.е. нажимать кнопочку), то вставляются всегда хорошо, но пользователи люди ... и им намного "проще" найти нужный блок в одном из их чертежей, а не клацнуть на кнопочку. после того как они его находят в куче своих чертежей, они Ctrl+C\Ctrl+V блок в новый чертеж. и, о чудо, у некоторых блоков умирает порядок прорисовки и после вставки вместо правильно начерченного блока получается мешанина отрезков и штриховок.
пробовал повторить сам ручками. картина та же. при вставке с кнопочки всегда все ok, а вот при копировании (причем без разницы в новый чертеж или в тот же) порядок прорисовки игнорируется.

может что-то не так с моим кодом? дело в том, что если ручками открыть файл C:\aaa\data.dwg, вставить туда этот блок (вставка->блок. блоков в самом чертеже нет. они только в БД чертежа), а потом скопировать его в буфер, то в другие чертежи (если там еще не было вхождения такого блока) всё вставляется правильно.
« Последнее редактирование: 24-11-2014, 19:03:03 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #1 : 04-12-2013, 13:45:56 »
Проверь копируется ли у тебя связанная с AcDbBlockTableRecord AcDbSortentsTable (отвечает за порядок прорисовки). Она содержится в ExtDictionary у AcDbBlockTableRecord с ключом "ACAD_SORTENTS". Если нет, то тебе придётся её самостоятельно скопировать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #2 : 04-12-2013, 14:15:40 »
пробежался arxdbg. взял правильно отрисованный блок и неправильно. результаты одинаковые
- на самом ВСТАВЛЕННОМ блоке (Entity Info) в Extension dictionary только AcDbBlockRepresentation
- в database \ BlockTable \ имя_блока в Extension dictionary есть ACAD_SORTENTS, ACAD_ENHANCEDBLOCK и AcDbDynamicBlockRoundTripPurgePrevent

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #3 : 04-12-2013, 14:59:53 »
результаты одинаковые
1) Одинаково и содержимое AcDbSortentsTable?
2) Такое происходит только с динамическими блоками?
3) Такое происходит в трёх последних версиях AutoCAD?
Если удастся всё это формально записать с минимальным примером кода (проект) и dwg-файла с блоками - будем трясти ADN DevHelp
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #4 : 04-12-2013, 18:42:24 »
1. ну в пределах допустимого. блоки то разные ), так что handle, owner и entity name - разные
2. за простые ничего сказать не могу (простых почти нет :), а на те что есть никто не жаловался). так что будем считать, что только динамические.
3. начиная с 2010 акада по 2014. чтоб все работало начиная с 2010 автокада, версия файла с блоками - 2010.
4. еще иногда слетает динамика после копирования. допустим есть столбики, которые идут массивом при растяжке. вставили через "кнопочку", потянули, все ок. скопировали, вставили рядом через Ctrl+C\Ctrl+V. потянули, а остается только первый столбик, хотя точка растяжки уходит туда, куда клацнул (у меня dwg файлика нет. нада скататься взять. но видел собственными глазами). и самое интересное, происходит это ТОЛЬКО с редактируемым экземпляром блока. столбики в остальных экземпляров блока находятся там где и должны и после регенерации. а вот если начать растягивать и другие подобные блоки, то такой же косяк происходит и на них.

PS: а проектик подготовлю, это не проблема. только на следующей неделе. сейчас весь в разъездах )))

Цитировать
будем трясти ADN DevHelp
ну да, ток исправлять то ЭТО в 2010 автокаде никто не будет, если это баг. а пользуются уже сейчас. эх, опять заплатки делать ))). так что ооочень сильно надеюсь, что это я что-то намудрил

а пока что dwg с блоком. можете попробовать его скопировать в новый чертеж средствами автокада. у меня штриховка всегда идет на передний план. хотя про копировании внутри одного чертежа все ок.
http://yadi.sk/d/9vhcJ2BaDnjKE
« Последнее редактирование: 04-12-2013, 19:00:46 от Николай Горлов »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #5 : 05-12-2013, 02:13:58 »
а пока что dwg с блоком. можете попробовать его скопировать в новый чертеж средствами автокада. у меня штриховка всегда идет на передний план. хотя про копировании внутри одного чертежа все ок.
Это я подтверждаю (AutoCAD 2014 SP1). Интересно теперь посмотреть на исходный файл с блоком, для которого этот баг не воспроизводится и посмотреть разницу между блоками.

Обрати внимание на эти два рисунка. Сначала я выяснил метку штриховки в блоке - 426, затем стал искать её в таблице SORTENTS - она там есть, но где-то в середине, что очень странно. По логике она должна быть или в начале или в конце.




Если же я копирую через буфер обмена в другой чертеж, то я получаю метку штриховки 249, а в SORTENTS для этого блока метки 249 нет вообще. В ней все метки очень удачно оказались двузначные. У меня создалось впечатление, что уже в dynblock.dwg SORTENTS для блока некорректная, т.е. метки ссылаются не на те примитивы. Ну а потом при копировании происходит трансляция меток, которая всё портит окончательно.

« Последнее редактирование: 05-12-2013, 02:56:38 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #6 : 06-12-2013, 13:21:46 »
Увы, врядли я найду исходный файл с блоком. Могу описать механизм. Вручную рисуются куча блоков разными людьми в разных файлах. Потом программно они просто копируются из тех файлов в один наш.
копируются функцией (но конкретно эта функция ни на что не влияет, т.к. непосредственно в ней идут только проверки):
Код - C++ [Выбрать]
  1. int importBlockToSheetDWG(const ACHAR *pBlockName, const ACHAR *pBlockFile, const ACHAR *pSheetDWGFile)
  2. //pBlockName - имя блока, pBlockFile - файл из которого будем его брать, pSheetDWGFile - файл в который этот блок нужно скопировать
  3. {
  4.         Acad::ErrorStatus es=Acad::eOk;
  5.         AcDbDatabase* pWorkDatabase = acdbHostApplicationServices()->workingDatabase();
  6.         AcDbDatabase* pSheetDatabase = new AcDbDatabase(false,true);
  7.         AcAxDocLock docLock(pSheetDatabase);
  8.         es = pSheetDatabase->readDwgFile(pSheetDWGFile);
  9.         if(es!=Acad::eOk){delete pSheetDatabase;return 0;}
  10.  
  11.         AcDbBlockTable* pBlockTable;
  12.         es=pSheetDatabase->getSymbolTable(pBlockTable,AcDb::kForRead);
  13.         if(es!=Acad::eOk){delete pSheetDatabase;return NULL;}
  14.  
  15.         AcDbObjectId idInsRecord;      
  16.         es=pBlockTable->getAt(pBlockName,idInsRecord);
  17.         pBlockTable->close();
  18.         if(es==Acad::eOk){delete pSheetDatabase;return 2;} // такой блок уже есть. перезаписывать не нужно
  19.  
  20.         acdbHostApplicationServices()->setWorkingDatabase(pSheetDatabase);
  21.         acdbHostApplicationServices()->enableMessageDisplay(false);
  22.         AcDbObjectId iId = importBlockToCurDWGDatabase(pBlockName, pBlockFile);
  23.         acdbHostApplicationServices()->enableMessageDisplay(true);
  24.         acdbHostApplicationServices()->setWorkingDatabase(pWorkDatabase);
  25.         if (!iId.isNull())
  26.         { // сохраняем в формате 2010 акада
  27.                 pSheetDatabase->saveAs(pSheetDWGFile,true,AcDb::kDHL_1024);
  28.         }
  29.         delete pSheetDatabase;
  30.         if (!iId.isNull()) return 1;
  31.         else return 0;
  32. }
  33.  

реализация importBlockToCurDWGDatabase - в моем первом посте.
так что во всем процессе участвуют три мои функции:
- importBlockToCurDWGDatabase
- importBlockToSheetDWG
- drawSign

и автокадовский динамический блок, созданный в голом автокаде без каки-либо дополнительных средств.

и если предположить, что автокадовский блок автокадом создавался правильно :):):), то проблема в одной из моих функций.

просто иногда достаточно если отрисовка идет без учета сортировки просто открыть акадом наш файл, вставить блочек внутри него, зайти в его редакторование и поставить штриховку принудительно еще раз на задний план. потом сохранить чертеж, закрыть его. и проблема может исчезнуть. но дело в том, что может и НЕ исчезнуть. в общем на следующей неделе постараюсь смастерить демо проектик и найти dwg с блоком, который в исходном состоянии работает, а после пробега трех функций начинает чудесить :).
ну и еще интересно, если баг в моих функциях, почему неправильно рисуются не все блоки (уже больше 1000 шт., так что точного количества не знаю) а только некоторые из них? чудеса :):):)
« Последнее редактирование: 24-11-2014, 19:04:47 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #7 : 06-12-2013, 20:20:06 »
в общем на следующей неделе постараюсь смастерить демо проектик и найти dwg с блоком, который в исходном состоянии работает, а после пробега трех функций начинает чудесить :)
Давай. А то как видишь без поллитры (т.е. dwg-файла и проекта) с этим делом не разобраться.  Как-то с этой таблицей сортировки совсем непонятно ;)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #8 : 09-12-2013, 13:48:51 »
и так. вроде бы все получилось
http://yadi.sk/d/NY3SHnKtDzxeN
dwg нада кинуть в корень диска С (по умолчанию, если не редактировать пути в проекте).
в проекте 2 команды.
первая - выдерает блок из файла blockfile.dwg и копирует его в c:\mydwg.dwg (файл создается, .если его нет по указанному пути)
вторая - вставляет блок из mydwg.dwg в чертеж

PS: блок в файле blockfile лежит хороший. проверил. вставляется нормально в любой чистый чертеж правильно. после копирования его в mydwg в чертеж командой вставляется правильно, но если его там скопировать ручками и утянуть в другой чертеж, то штриховка вылазит на передний план.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #9 : 09-12-2013, 19:14:43 »
блок в файле blockfile лежит хороший. проверил. вставляется нормально в любой чистый чертеж правильно.
Неа. Я скопировал этот блок вручную (через буфер обмена) в другой чертеж - штриховка вылетела наверх. Метка у штриховки в исходном чертеже - 426 (в SORTENTS я такую метку не нашел)
Потом внутри блока отправил штриховку вниз, сохранил блок и выполнил сброс блока - метка у штриховки поменялось на 5FD (в SORTENTS метка появилась), но это не помогло - штриховка упрямо вылезала наверх.
Дальше я сделал такой эксперимент. Удалили для этого блока SORTENTS и отправил штриховку вниз. После этого этот блок нормально (вручную) скопировался в новый чертеж.
Осталось проверить с твоей программой.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #10 : 09-12-2013, 20:10:24 »
Проверил с твоей программой (уточняю - проверял в AutoCAD 2014 SP1 x86). Блок вставился нормально и так же нормально скопировался в новый пустой чертеж.
Прикладываю твой проект (я его немного обанглоязычил на случай передачи в ADN DevHelp) и чертеж с блоком.

P.S.: Кстати, когда архивируешь проект - не забывай выходить из VS
« Последнее редактирование: 09-12-2013, 20:32:39 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #11 : 10-12-2013, 12:32:13 »
Цитировать
Неа. Я скопировал этот блок вручную (через буфер обмена) в другой чертеж - штриховка вылетела наверх
как это ни смешно звучит, но после этих слов и я проверил. и у меня тоже штриховка вылетела на передний план. хотя до этого три раза проверял переоткрывая автокад и всё было ок. а сегодня перегрузил компьютер )))
сегодня новые чудеса. взял и переименовал mydwg в blockfile и выполнил свои две команды (пересоздал mydwg и вставил блок в файл) тестового проекта. блок начал вставляться простым копированием правильно в любой чертеж.

Цитировать
Проверил с твоей программой (уточняю - проверял в AutoCAD 2014 SP1 x86). Блок вставился нормально и так же нормально скопировался в новый пустой чертеж.
говоря проще, моя программная часть тут не при чем. так? всё зависит от начальной корявости блока, созданного самим автокадом? если это так, то есть ли способ (не очень болезненный :) ) исправлять корявые блоки "на лету" перед затягиванием их в mydwg?

PS:
Цитировать
на случай передачи в ADN DevHelp
на них то у меня надежды мало. не так сильно я с ними дружу :):):). :) уберу ка я всё лишнее
так что заплатки, заплатки и еще раз заплатки.
« Последнее редактирование: 10-12-2013, 16:12:19 от Николай Горлов »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #12 : 10-12-2013, 15:07:51 »
говоря проще, моя программная часть тут не при чем. так? всё зависит от начальной корявости блока, созданного самим автокадом?
Похоже что именно так.
всё зависит от начальной корявости блока, созданного самим автокадом? если это так, то есть ли способ (не очень болезненный :) ) исправлять корявые блоки "на лету" перед затягиванием их в mydwg?
Ну в данном случае корявость была в SORTENTS. Можно конечно её попытаться поправить на лету если сможешь понять что в ней не так. То есть проделать эти же операции вручную.
но на них то у меня надежды мало
В данном случае если бы я сам не нашел причину ошибки, то отправил в ADN DevHelp и рассчитывал бы не на исправление бага, а на workaround, который бы получил от команды инженеров.
P.S.: Обсуждать работу ADN DevHelp на этом форуме мы не будем - читай справа вверху в шапке форума при чьей поддержке этот форум функционирует. 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай ГорловАвтор темы

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Re: вставка блоков
« Ответ #13 : 10-12-2013, 16:22:34 »
:( а DevHelp то у меня не работает, и как вспоминаю уже давненько. помню, пытался настроить, но плюнул.
Account Is Not Linked to an Active Subscription Contract и всё. дальше не пускает. пробовал и с adn-овского аккаунта и с автодесковского форумного. так что workaround (танец с бубном) будет мучительно долгим

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13832
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: вставка блоков
« Ответ #14 : 10-12-2013, 16:49:09 »
а DevHelp то у меня не работает
По этому поводу как исправить напишу в личку.
Но вообще-то этот форум создан как раз для того, чтобы мы (Администрация) брали на себя в случае, когда сами не можем помочь, функцию передачи вопросов в ADN DevHelp.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение