Why the dimensions not show?

Why the dimensions not show?

Anonymous
Not applicable
1,720 Views
11 Replies
Message 1 of 12

Why the dimensions not show?

Anonymous
Not applicable

I use the function wblock to clone some entities from the current document(Doc A) to a new document(Doc B, created while the progress),

es = pTempDb->wblock(pTargetDb, idsNeedClone, AcGePoint3d::kOrigin, AcDb::kDrcReplace);

and the new document is used in another doc(Doc C) by xref.  But in Doc C, the dimensions in Doc B not show, until I redraw all the entities in Doc B.

So after wblock, I redraw all the entities in Doc B using this code

pEnt->recordGraphicsModified(true);

But, the dimensions in a block which is in the Doc B are also not show in Doc C.

 

what the problem? And what should I do?

 

Thank you! 

Happy new year!

0 Likes
Accepted solutions (2)
1,721 Views
11 Replies
Replies (11)
Message 2 of 12

Anonymous
Not applicable

I tried to redraw all the entities in that blockTableRecord, but they still not show.

0 Likes
Message 3 of 12

Alexander.Rivilis
Mentor
Mentor
Without your sample project and sample dwg-file I can not explain this issue.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 4 of 12

Anonymous
Not applicable

Sorry for late response,

I use this code to wblock a dwg-file to a new dwg-file.

es = pTempDb->wblock(pTargetDb, idsNeedClone, AcGePoint3d::kOrigin, AcDb::kDrcReplace);
es = pTargetDb->closeInput(true);
es = acdbSaveAs2004(pTargetDb, strTargetFileFullPath);

In the source file, there is a block like this

QQ截图20170110154935.jpg

 

After I wblock it out to a new dwg-file, the block looks like this

QQ截图20170110155218.jpg

 

But if I open it using refedit, the dimensions appear again.

0 Likes
Message 5 of 12

Alexander.Rivilis
Mentor
Mentor

Without full code I have only one idea. Instead of wblock you can use wblockCloneObjects and after that iterate idMap in order to find new created AcDbDimension's, open it and call recomputeDimBlock method for every dimension.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 6 of 12

Anonymous
Not applicable

the sample code is like this

// - ZHPCDC.TEST command (do not rename)
	static void ZHPCDCTEST(void)
	{
		// Add your code for command ZHPCDC.TEST here
		Acad::ErrorStatus es;
		CString strTargetFileFullPath = TEXT("D:\\test.dwg");

		//create the new file
		AcDbDatabase *pNewDb = new AcDbDatabase(true, false);
		es = pNewDb->saveAs(strTargetFileFullPath);
		delete pNewDb;

		// get the targetDb, sourceDb and tempDb
		AcDbDatabase *pTargetDb = new AcDbDatabase(false);
		pTargetDb->readDwgFile(strTargetFileFullPath);
		AcDbDatabase *pSourceDb = acdbHostApplicationServices()->workingDatabase();
		AcDbDatabase *pTempDb = new AcDbDatabase(true, true);
		es = pSourceDb->wblock(pTempDb);
		// get the entities that need clone
		AcDbObjectIdArray idsNeedClone;
		AcDbBlockTable *pBlkTbl = NULL;
		pTempDb->getBlockTable(pBlkTbl, AcDb::kForRead);
		AcDbBlockTableRecord *pBlkTblRcd = NULL;
		pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForWrite);
		pBlkTbl->close();
		AcDbBlockTableRecordIterator *it = NULL;
		pBlkTblRcd->newIterator(it);
		for (it->start(); !it->done(); it->step())
		{
			AcDbObjectId id;
			if (Acad::eOk != it->getEntityId(id)) continue;
			idsNeedClone.append(id);
		}
		delete it;
		pBlkTblRcd->close();


		// clone from tempDb to targetDb
		pTempDb->wblock(pTargetDb, idsNeedClone, AcGePoint3d::kOrigin, AcDb::kDrcReplace);

		//redraw the entities in targetDb and saveas
		CDwgDatabaseUtil::RedrawAllEntitys(pTargetDb);
		es = pTargetDb->closeInput(true);
		es = acdbSaveAs2004(pTargetDb, strTargetFileFullPath);

		delete pTargetDb;
		delete pTempDb;
	}

and the function 

CDwgDatabaseUtil::RedrawAllEntitys(pTargetDb);

is like this

void CDwgDatabaseUtil::RedrawAllEntitys(AcDbDatabase *pDb)
{
	// 获得块表
	AcDbBlockTable *pBlkTbl = NULL;
	pDb->getBlockTable(pBlkTbl, AcDb::kForRead);

	// 获得模型空间的块表记录
	AcDbBlockTableRecord *pBlkTblRcd = NULL;
	pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead);
	pBlkTbl->close();

	// 创建遍历器,依次访问模型空间的每一个实体
	AcDbBlockTableRecordIterator *it = NULL;
	pBlkTblRcd->newIterator(it);
	for (it->start(); !it->done(); it->step())
	{
		AcDbEntity *pEnt = NULL;
		if (Acad::eOk == it->getEntity(pEnt, AcDb::kForWrite))
		{
			pEnt->recordGraphicsModified(true);
			pEnt->close();
		}
	}
	delete it;
	pBlkTblRcd->close();
}

 

and here is the video to express my problem

 

 
and I tried to call the recomputeDimBlock method like this. But the result is the same...
void CDwgDatabaseUtil::RedrawAllEntitys1(AcDbDatabase *pDb)
{
	// 获取块表
	AcDbBlockTable *pBlkTbl = NULL;
	pDb->getBlockTable(pBlkTbl, AcDb::kForRead);

	// 创建遍历器,依次访问块表中的每条块表记录
	AcDbBlockTableIterator *it = NULL;
	pBlkTbl->newIterator(it);
	for (it->start(); !it->done(); it->step())
	{
		//获取某条块表记录
		AcDbBlockTableRecord *pBlkTblRcd = NULL;
		it->getRecord(pBlkTblRcd, AcDb::kForRead);
		// 创建遍历器,依次访问块表记录中的每一个实体
		AcDbBlockTableRecordIterator *rcdIt = NULL;
		pBlkTblRcd->newIterator(rcdIt);
		for (rcdIt->start(); !rcdIt->done(); rcdIt->step())
		{
			AcDbEntity *pEnt = NULL;
			if (Acad::eOk == rcdIt->getEntity(pEnt, AcDb::kForWrite))
			{
				if (pEnt->isKindOf(AcDbDimension::desc()))
				{
					AcDbDimension *pDim = AcDbDimension::cast(pEnt);
					pDim->recomputeDimBlock(true);
				}
				//pEnt->recordGraphicsModified(true);
				pEnt->close();
			}
		}
		delete rcdIt;
		pBlkTblRcd->close();
	}
	delete it;
	pBlkTbl->close();
}
So what is problem in my code?
0 Likes
Message 7 of 12

Anonymous
Not applicable

The screemcast is so good.

0 Likes
Message 8 of 12

Alexander.Rivilis
Mentor
Mentor
Accepted solution

Try to compare your code with my:

 

 

//-----------------------------------------------------------------------------
//----- acrxEntryPoint.cpp
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
//-----------------------------------------------------------------------------
#define szRDS _RXST("")
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CWblockDimApp : public AcRxArxApp {
public:
  CWblockDimApp () : AcRxArxApp () {}
  virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
    AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg (pkt) ;
    return (retCode) ;
  }
  virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
    AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
    return (retCode) ;
  }

  virtual void RegisterServerComponents () { }
  // - WblockDim.WPTEST command (do not rename)
  static void WblockDimWPTEST(void)
  {
    Acad::ErrorStatus es;
    CString strTargetFileFullPath = TEXT("D:\\test.dwg");

    //create the new file
    AcDbDatabase *pNewDb = new AcDbDatabase(true, false);
    es = pNewDb->saveAs(strTargetFileFullPath);
    delete pNewDb;

    // get the targetDb, sourceDb and tempDb
    AcDbDatabase *pTargetDb = new AcDbDatabase(false);
    pTargetDb->readDwgFile(strTargetFileFullPath);
    AcDbDatabase *pSourceDb = acdbHostApplicationServices()->workingDatabase();
    AcDbDatabase *pTempDb = NULL;
    es = pSourceDb->wblock(pTempDb);
    // get the entities that need clone
    AcDbObjectIdArray idsNeedClone;
    AcDbBlockTable *pBlkTbl = NULL;
    pTempDb->getBlockTable(pBlkTbl, AcDb::kForRead);
    AcDbBlockTableRecord *pBlkTblRcd = NULL;
    pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd, AcDb::kForRead);
    pBlkTbl->close();
    AcDbBlockTableRecordIterator *it = NULL;
    pBlkTblRcd->newIterator(it);
    pBlkTblRcd->close();

    for (it->start(); !it->done(); it->step())
    {
      AcDbObjectId id;
      if (Acad::eOk != it->getEntityId(id)) continue;
      idsNeedClone.append(id);
    }
    delete it;

    // clone from tempDb to targetDb
    pTempDb->wblock(pTargetDb, idsNeedClone, AcGePoint3d::kOrigin, AcDb::kDrcReplace);

    //redraw the entities in targetDb and saveas
    RedrawAllEntities(pTargetDb);
    es = pTargetDb->closeInput(true);
    es = acdbSaveAs2004(pTargetDb, strTargetFileFullPath);

    delete pTargetDb;
    delete pTempDb;

  }
  static void RedrawAllEntities(AcDbDatabase *pDb)
  {
    AcDbDatabase *pCurDb = acdbHostApplicationServices()->workingDatabase();
    acdbHostApplicationServices()->setWorkingDatabase(pDb);
    AcDbBlockTable *pBlkTbl = NULL;
    pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
    AcDbBlockTableIterator *it = NULL;
    pBlkTbl->newIterator(it);
    pBlkTbl->close();

    for (it->start(); !it->done(); it->step())
    {
      AcDbBlockTableRecord *pBlkTblRcd = NULL;
      it->getRecord(pBlkTblRcd, AcDb::kForRead);
      AcDbBlockTableRecordIterator *rcdIt = NULL;
      pBlkTblRcd->newIterator(rcdIt);
      pBlkTblRcd->close();
      for (rcdIt->start(); !rcdIt->done(); rcdIt->step())
      {
        AcDbEntity *pEnt = NULL;
        if (Acad::eOk == rcdIt->getEntity(pEnt, AcDb::kForWrite))
        {
          if (pEnt->isKindOf(AcDbDimension::desc()))
          {
            AcDbDimension *pDim = AcDbDimension::cast(pEnt);
            pDim->recomputeDimBlock(true);
          }
          pEnt->recordGraphicsModified(true);
          pEnt->close();
        }
      }
      delete rcdIt;
    }
    delete it;
    acdbHostApplicationServices()->setWorkingDatabase(pCurDb);
  }
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CWblockDimApp)
ACED_ARXCOMMAND_ENTRY_AUTO(CWblockDimApp, WblockDim, WPTEST, WPTEST, ACRX_CMD_TRANSPARENT, NULL)

 

 

 

 P.S.: You have to close AcDbBlockTable and AcDbBlockTableRecord just they are not needed.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 9 of 12

Alexander.Rivilis
Mentor
Mentor
Accepted solution

Other variant of RedrawAllEntities:

 

static void RedrawAllEntities(AcDbDatabase *pDb)
{
  AcDbBlockTable *pBlkTbl = NULL;
  pDb->getBlockTable(pBlkTbl, AcDb::kForRead);
  AcDbBlockTableIterator *it = NULL;
  if (pBlkTbl) {
    pBlkTbl->newIterator(it);
    pBlkTbl->close();
  }

  if (!it) return;

  AcDbObjectIdArray idsDim, idsTable;

  for (it->start(); !it->done(); it->step())
  {
    AcDbBlockTableRecord *pBlkTblRcd = NULL;
    it->getRecord(pBlkTblRcd, AcDb::kForRead);
    if (pBlkTblRcd) {
      AcDbBlockTableRecordIterator *rcdIt = NULL;
      pBlkTblRcd->newIterator(rcdIt);
      pBlkTblRcd->close();
  
      if (!rcdIt) continue;

      for (rcdIt->start(); !rcdIt->done(); rcdIt->step()) {
        AcDbObjectId id;
        if (rcdIt->getEntityId(id) == Acad::eOk) {
          if (id.objectClass()->isDerivedFrom(AcDbDimension::desc())) {
            idsDim.append(id);
          } else if (id.objectClass()->isDerivedFrom(AcDbTable::desc())) {
            idsTable.append(id);
          }
        }
      }
      delete rcdIt;
    }
  }
  
  delete it;
  
  AcDbDatabase *pWorkDb = acdbHostApplicationServices()->workingDatabase();
  acdbHostApplicationServices()->setWorkingDatabase(pDb);
  
  for (int i = 0; i < idsDim.length(); i++) {
    AcDbObjectPointer<AcDbDimension> pDim(idsDim[i], AcDb::kForWrite);
    if (pDim.openStatus() == Acad::eOk) {
      pDim->recomputeDimBlock(true);
    }
  }

  for (int i = 0; i < idsTable.length(); i++) {
    AcDbObjectPointer<AcDbTable> pTable(idsTable[i], AcDb::kForWrite);
    if (pTable.openStatus() == Acad::eOk) {
      pTable->recomputeTableBlock(true);
    }
  }
  
  acdbHostApplicationServices()->setWorkingDatabase(pWorkDb);

}

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 10 of 12

Anonymous
Not applicable

Thank you, Alex!

And now, it works. Comparing my code with yours, I find the key point is these changes

1. let the pDb to be the working database.

acdbHostApplicationServices()->setWorkingDatabase(pDb);

2. recomputeDimBlock

AcDbDimension *pDim = AcDbDimension::cast(pEnt);
pDim->recomputeDimBlock(true);

 

About the first point, the doc of AcDbDimension::recomputeDimBlock Function is this

Acad::ErrorStatus

recomputeDimBlock(

bool forceUpdate = true);

forceUpdate Input Boolean indicating whether or not to force an update on screen 

This function updates the block table record the dimension references to match any changes made to the dimension since the last time the block table record was updated.

If forceUpdate==true, then the block table record will be updated regardless of whether or not the dimension has had any changes since the last time the block table record was updated. If forceUpdate==false, then the block table record will only be updated if the dimension has been changed since it was opened, is not currently erased, and is not in the middle of an Undo operation.

This function returns Acad::eOk.

But it tells me nothing about the setting og working database. So, my question is, what's the reason to let you change the working database?

0 Likes
Message 11 of 12

Alexander.Rivilis
Mentor
Mentor

3. (very important) I close AcDbBlockTable and AcDbBlockTableRecord immediately after receiving their iterator.

 

>>>But it tells me nothing about the setting og working database. So, my question is, what's the reason to let you change the working database?<<<

 

This is often necessary when working with side AcDbDatabase (not opened in AutoCAD Editor or not current).  But in this case it is not necessary.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 12 of 12

Anonymous
Not applicable
OH, I should try it again without the setting of database.
0 Likes