Create and Insert Blocks? Create and Insert AnonBlock?

Create and Insert Blocks? Create and Insert AnonBlock?

1127204185
Advocate Advocate
645 Views
3 Replies
Message 1 of 4

Create and Insert Blocks? Create and Insert AnonBlock?

1127204185
Advocate
Advocate
static void MyGroupMyCommand () {
	ads_name ss = { 0 };
	int ret = acedSSGet(NULL, NULL, NULL, NULL, ss);		
	AcDbObjectIdArray ids;
	if (RTNORM == ret)
	{
		long len = 0;
		acedSSLength(ss, &len);
		for (long i = 0L; i < len; ++i)
		{
			ads_name ename = { 0 };
			acedSSName(ss, i, ename);
			AcDbObjectId id = AcDbObjectId::kNull;
			acdbGetObjectId(id, ename);
			ids.append(id);
	   }
		acedSSFree(ss);
	}
	CreateBlock1(_T("TTT"),ids,AcGeScale3d(1,1,1),0);  // Create and Insert Blocks
AcDbObjectId AnonblockId ;
CreateAnonBlock(ids,AnonblockId);
 }

static AcDbObjectId CreateBlock1(const CString &blkName, const AcDbObjectIdArray &idObjectArray,const AcGeScale3d &m_aScale,const double &m_angle)
 {
	 AcDbBlockTable *pBlkTbl = NULL;
	 acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);
	 AcDbBlockTableRecord *pBlkRcd = new AcDbBlockTableRecord();
	 pBlkRcd->setName(blkName);

	 AcDbObjectId blkDefId;
	 pBlkTbl->add(blkDefId, pBlkRcd);
	 pBlkTbl->close();
	 AcDbObjectId entId;
	 for (INT32 i = 0; i < idObjectArray.length(); i++)
	 {
	 AcDbEntity *pEntity = NULL;
	 acdbOpenAcDbEntity(pEntity, idObjectArray.at(i), AcDb::kForRead);
	 pBlkRcd->appendAcDbEntity(entId, pEntity);
	 }
	 pBlkRcd->close();
	 AcDbBlockReference *pBlkRef = new AcDbBlockReference(AcGePoint3d::kOrigin, entId);
	 pBlkRef->setScaleFactors(m_aScale);
	 PostToModelSpace(pBlkRef);
	 pBlkRef->setRotation (m_angle) ;
	 return entId;
 }

static Acad::ErrorStatus CreateAnonBlock(AcArray<AcDbObjectId> &selectedIds, AcDbObjectId &idAnonBlock)
        {
                Acad::ErrorStatus es;
                AcDbBlockTable *pBlockTable = NULL;

                AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();

                AcDbBlockTableRecord *pAnonBlock = NULL;
                if( idAnonBlock == AcDbObjectId::kNull )
                {
                        if ((es = pDb->getBlockTable(pBlockTable, AcDb::kForWrite))
                                != Acad::eOk)
                        {
                                acutPrintf(L"Could not open block table 无法打开块表.\n");
                                return es;
                        }

                        AcDbBlockTableRecord* pAnonBlock = new AcDbBlockTableRecord;
                        if(!pAnonBlock)
                        {
                                acutPrintf(L"Could not create new block table record.无法创建新的块表记录\n");
                                return Acad::eNullObjectPointer;
                        }
                        if((es = pAnonBlock->setName(_T("*U"))) != Acad::eOk)
                        {
                                acutPrintf(L"Could not name anonymous block.无法命名匿名块\n");
                                return es;
                        }
                        if((es = pBlockTable->add(idAnonBlock, pAnonBlock)) != Acad::eOk)
                        {
                                acutPrintf(L"Could not add anonymous block to block table.无法将匿名块添加到块表\n");
                                return es;
                        }

                        if((es = pBlockTable->close()) != Acad::eOk)
                        {
                                acutPrintf(L"Could not close block table.\n");
                                return es;
                        }
                        if((es = pAnonBlock->close()) != Acad::eOk)
                        {
                                acutPrintf(L"Could not close block table record.\n");
                                return es;
                        }
                }

                AcDbObjectPointer<AcDbBlockTableRecord> pAnonBlockObjectPtr(idAnonBlock, AcDb::kForWrite);

                if((es = pAnonBlockObjectPtr.openStatus()) != Acad::eOk)
                {
                        acutPrintf(L"Could not open anonymous block.\n");
                        return es;
                }


                for(int cnt = 0; cnt < selectedIds.length(); cnt++)
                {
                        AcDbObjectId entId = selectedIds.at(cnt);

                        AcDbObjectPointer<AcDbEntity> pEntity(entId, AcDb::kForRead);
                        if(Acad::eOk == pEntity.openStatus())
                        {
                                AcDbEntity *pCloneEnt = (AcDbEntity *) pEntity->clone();
                               
                                if((es = pAnonBlockObjectPtr->appendAcDbEntity(pCloneEnt)) != Acad::eOk)
                                {
                                        acutPrintf(L"Could not append entity to anonymous block.\n");
                                        return es;
                                }

                                if((es = pCloneEnt->close()) != Acad::eOk)
                                {
                                        acutPrintf(L"Could not close entity.\n");
                                        return es;
                                }
                        }
                }

                return Acad::eOk;
        }
0 Likes
Accepted solutions (2)
646 Views
3 Replies
Replies (3)
Message 2 of 4

tbrammer
Advisor
Advisor

There are three bugs in CreateBlock1(..):

1.) You are trying to append entities that are already in modelspace to the new block. You can't do that! Instead clone() the entities and insert their clones - just like you do it in CreateAnonBlock().

 

2.) You are passing the wrong ObjectId to  new AcDbBlockReference(.., entId).

It must be new AcDbBlockReference(.., blkDefId).

 

3.) I assume that PostToModelSpace(entity) closes entity. So you must call

pBlkRef->setRotation(m_angle) before PostToModelSpace(pBlkRef).

f your PostToModelSpace(entity) doesn't close the entity you have to close it yourself!

 

The function CreateAnonBlock() is OK as far as I can see. It creates the unnamed block - but it doesn't append a BREF to it in the modelspace. 

 

Below is working code. Note that the BREFs overlap the original entities:

 

Acad::ErrorStatus PostToModelSpace(AcDbEntity* pEntity)
{
	AcDbObjectId objId;
    AcDbBlockTable *pBlockTable;
    AcDbBlockTableRecord *pSpaceRecord;

    acdbHostApplicationServices()->workingDatabase()
        ->getSymbolTable(pBlockTable, AcDb::kForRead);

    pBlockTable->getAt(ACDB_MODEL_SPACE, pSpaceRecord,
        AcDb::kForWrite);

    pBlockTable->close();

    pSpaceRecord->appendAcDbEntity(objId, pEntity);

    pEntity->close();
    pSpaceRecord->close();

    return Acad::eOk;
}

static AcDbObjectId CreateBlock1(const CString &blkName, const AcDbObjectIdArray &idObjectArray, const AcGeScale3d &m_aScale, const double &m_angle)
{
	Acad::ErrorStatus es;
	AcDbBlockTable *pBlkTbl = NULL;
	acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);
	AcDbBlockTableRecord *pBlkRcd = new AcDbBlockTableRecord();
	es = pBlkRcd->setName(blkName);

	AcDbObjectId blkDefId;
	pBlkTbl->add(blkDefId, pBlkRcd);
	pBlkTbl->close();
	AcDbObjectId entId;
	for (INT32 i = 0; i < idObjectArray.length(); i++)
	{
		AcDbEntity *pEntity = NULL;
		acdbOpenAcDbEntity(pEntity, idObjectArray.at(i), AcDb::kForRead);
		//TB: You can't append an entity to another block that is already in the modelspace.
		//Instead clone it and append the clone:
		AcDbEntity *pNewEntity = AcDbEntity::cast(pEntity->clone());
		pEntity->close();
		es = pBlkRcd->appendAcDbEntity(entId, pNewEntity);
		if (es)
			delete pNewEntity;
		else
			pNewEntity->close();
	}
	pBlkRcd->close();

	AcDbBlockReference *pBlkRef = new AcDbBlockReference(AcGePoint3d::kOrigin, blkDefId); //TB was entId
	pBlkRef->setScaleFactors(m_aScale);
	//TB: I assume that PostToModelSpace(ent) closes the entity. So you must...
	pBlkRef->setRotation(m_angle); // ...do this _before_ PostToModelSpace(). 
	PostToModelSpace(pBlkRef);
	return entId;
}

static Acad::ErrorStatus CreateAnonBlock(AcArray<AcDbObjectId> &selectedIds, AcDbObjectId &idAnonBlock)
{
	Acad::ErrorStatus es;
	AcDbBlockTable *pBlockTable = NULL;

	AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();

	AcDbBlockTableRecord *pAnonBlock = NULL;
	if (idAnonBlock == AcDbObjectId::kNull)
	{
		if ((es = pDb->getBlockTable(pBlockTable, AcDb::kForWrite))
			!= Acad::eOk)
		{
			acutPrintf(L"Could not open block table 无法打开块表.\n");
			return es;
		}

		AcDbBlockTableRecord *pAnonBlock = new AcDbBlockTableRecord;
		if (!pAnonBlock)
		{
			acutPrintf(L"Could not create new block table record.无法创建新的块表记录\n");
			return Acad::eNullObjectPointer;
		}
		if ((es = pAnonBlock->setName(_T("*U"))) != Acad::eOk)
		{
			acutPrintf(L"Could not name anonymous block.无法命名匿名块\n");
			return es;
		}
		if ((es = pBlockTable->add(idAnonBlock, pAnonBlock)) != Acad::eOk)
		{
			acutPrintf(L"Could not add anonymous block to block table.无法将匿名块添加到块表\n");
			return es;
		}

		if ((es = pBlockTable->close()) != Acad::eOk)
		{
			acutPrintf(L"Could not close block table.\n");
			return es;
		}
		if ((es = pAnonBlock->close()) != Acad::eOk)
		{
			acutPrintf(L"Could not close block table record.\n");
			return es;
		}
	}

	AcDbObjectPointer<AcDbBlockTableRecord> pAnonBlockObjectPtr(idAnonBlock, AcDb::kForWrite);

	if ((es = pAnonBlockObjectPtr.openStatus()) != Acad::eOk)
	{
		acutPrintf(L"Could not open anonymous block.\n");
		return es;
	}


	for (int cnt = 0; cnt < selectedIds.length(); cnt++)
	{
		AcDbObjectId entId = selectedIds.at(cnt);

		AcDbObjectPointer<AcDbEntity> pEntity(entId, AcDb::kForRead);
		if (Acad::eOk == pEntity.openStatus())
		{
			AcDbEntity *pCloneEnt = (AcDbEntity *)pEntity->clone();

			if ((es = pAnonBlockObjectPtr->appendAcDbEntity(pCloneEnt)) != Acad::eOk)
			{
				acutPrintf(L"Could not append entity to anonymous block.\n");
				return es;
			}

			if ((es = pCloneEnt->close()) != Acad::eOk)
			{
				acutPrintf(L"Could not close entity.\n");
				return es;
			}
		}
	}

	return Acad::eOk;
}

// MyCommand / MC
static void MyGroupMyCommand() {
	ads_name ss = { 0 };
	int ret = acedSSGet(NULL, NULL, NULL, NULL, ss);
	AcDbObjectIdArray ids;
	if (RTNORM == ret)
	{
		Adesk::Int32 len = 0;
		acedSSLength(ss, &len);
		for (long i = 0L; i < len; ++i)
		{
			ads_name ename = { 0 };
			acedSSName(ss, i, ename);
			AcDbObjectId id = AcDbObjectId::kNull;
			acdbGetObjectId(id, ename);
			ids.append(id);
		}
		acedSSFree(ss);
	}
	CreateBlock1(_T("TTT"), ids, AcGeScale3d(1, 1, 1), 0);  // Create and Insert Blocks
	AcDbObjectId AnonblockId;
	CreateAnonBlock(ids, AnonblockId); // You don't insert a BREF to AnonblockId

	AcDbBlockReference *pBlkRef = new AcDbBlockReference(AcGePoint3d::kOrigin, AnonblockId); //TB was entId
	PostToModelSpace(pBlkRef);
}

 


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes
Message 3 of 4

1127204185
Advocate
Advocate
Accepted solution

 

 

thank you!

Not reserved  ids。Only blocks!

I don't know if this is right!

Why must pEntity->clone()

 

 

 

 

static Acad::ErrorStatus CreateAnonBlock(AcArray<AcDbObjectId> &selectedIds, AcDbObjectId &idAnonBlock)
 {
	 Acad::ErrorStatus es;
	 AcDbBlockTable *pBlockTable = NULL;

	 AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();

	 AcDbBlockTableRecord *pAnonBlock = NULL;
	 if (idAnonBlock == AcDbObjectId::kNull)
	 {
		 if ((es = pDb->getBlockTable(pBlockTable, AcDb::kForWrite))
			 != Acad::eOk)
		 {
			 acutPrintf(L"Could not open block table 无法打开块表.\n");
			 return es;
		 }

		 AcDbBlockTableRecord *pAnonBlock = new AcDbBlockTableRecord;
		 if (!pAnonBlock)
		 {
			 acutPrintf(L"Could not create new block table record.无法创建新的块表记录\n");
			 return Acad::eNullObjectPointer;
		 }
		 if ((es = pAnonBlock->setName(_T("*U"))) != Acad::eOk)
		 {
			 acutPrintf(L"Could not name anonymous block.无法命名匿名块\n");
			 return es;
		 }
		 if ((es = pBlockTable->add(idAnonBlock, pAnonBlock)) != Acad::eOk)
		 {
			 acutPrintf(L"Could not add anonymous block to block table.无法将匿名块添加到块表\n");
			 return es;
		 }

		 if ((es = pBlockTable->close()) != Acad::eOk)
		 {
			 acutPrintf(L"Could not close block table.\n");
			 return es;
		 }
		 if ((es = pAnonBlock->close()) != Acad::eOk)
		 {
			 acutPrintf(L"Could not close block table record.\n");
			 return es;
		 }
	 }

	 AcDbObjectPointer<AcDbBlockTableRecord> pAnonBlockObjectPtr(idAnonBlock, AcDb::kForWrite);

	 if ((es = pAnonBlockObjectPtr.openStatus()) != Acad::eOk)
	 {
		 acutPrintf(L"Could not open anonymous block.\n");
		 return es;
	 }


	 for (int cnt = 0; cnt < selectedIds.length(); cnt++)
	 {
		 AcDbObjectId entId = selectedIds.at(cnt);

		 AcDbObjectPointer<AcDbEntity> pEntity(entId, AcDb::kForWrite);
		 if (Acad::eOk == pEntity.openStatus())
		 {
			 AcDbEntity *pCloneEnt = (AcDbEntity *)pEntity->clone();

			 if ((es = pAnonBlockObjectPtr->appendAcDbEntity(pCloneEnt)) != Acad::eOk)
			 {
				 acutPrintf(L"Could not append entity to anonymous block.\n");
				 return es;
			 }

			 if ((es = pCloneEnt->close()) != Acad::eOk)
			 {
				 acutPrintf(L"Could not close entity.\n");
				 return es;
			 }
          pEntity->erase();
		  pEntity->close();
		 }
	 }

	 return Acad::eOk;
 }


 static AcDbObjectId CreateBlock1(const CString &blkName, const AcDbObjectIdArray &idObjectArray, const AcGeScale3d &m_aScale, const double &m_angle)
 {
	 Acad::ErrorStatus es;
	 AcDbBlockTable *pBlkTbl = NULL;
	 acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);
	 AcDbBlockTableRecord *pBlkRcd = new AcDbBlockTableRecord();
	 es = pBlkRcd->setName(blkName);

	 AcDbObjectId blkDefId;
	 pBlkTbl->add(blkDefId, pBlkRcd);
	 pBlkTbl->close();
	 AcDbObjectId entId;
	 for (INT32 i = 0; i < idObjectArray.length(); i++)
	 {
		 AcDbEntity *pEntity = NULL;
		 acdbOpenAcDbEntity(pEntity, idObjectArray.at(i), AcDb::kForWrite);
		 //TB: You can't append an entity to another block that is already in the modelspace.
		 //Instead clone it and append the clone:
		 AcDbEntity *pNewEntity = AcDbEntity::cast(pEntity->clone());
		 es = pBlkRcd->appendAcDbEntity(entId, pNewEntity);
		 if (es)
			 delete pNewEntity;
		 else
			 pNewEntity->close();
		 pEntity->erase();
		 pEntity->close();
	 }
	 pBlkRcd->close();

	 AcDbBlockReference *pBlkRef = new AcDbBlockReference(AcGePoint3d::kOrigin, blkDefId); //TB was entId
	 pBlkRef->setScaleFactors(m_aScale);
	 //TB: I assume that PostToModelSpace(ent) closes the entity. So you must...
	 pBlkRef->setRotation(m_angle); // ...do this _before_ PostToModelSpace(). 
	 PostToModelSpace(pBlkRef);
	 return entId;
 }

 

 

 

 

0 Likes
Message 4 of 4

tbrammer
Advisor
Advisor
Accepted solution

>  Why must pEntity->clone()

 

See my comment

//TB: You can't append an entity to another block that is already in the modelspace.

You tried to append the entities that you selected to another block.  But these entities are alredy in the modelspace block. So you must either append clones from these entities or use

AcDbBlockTableRecord::assumeOwnershipOf(const AcDbObjectIdArray &entitiesToMove);

To move them from the modelspace to another block.


Thomas Brammer ● Software Developer ● imos AGLinkedIn
If an answer solves your problem please [ACCEPT SOLUTION]. Otherwise explain why not.

0 Likes