Why does adding AcDbRegion to AcDbDatabase after booleanOperar return eWrongDatabase?

dziwve67853
Enthusiast
Enthusiast

Why does adding AcDbRegion to AcDbDatabase after booleanOperar return eWrongDatabase?

dziwve67853
Enthusiast
Enthusiast
static AcDbRegion* GetRegion(AcGePoint3d cenPt)
{		
	AcDbRegion* pRegion = NULL;
	
	AcDbCircle* pCircle = new AcDbCircle(cenPt,AcGeVector3d::kZAxis,10);
	AcDbVoidPtrArray curveSegments;curveSegments.append(pCircle);
	AcDbVoidPtrArray regions;
	Acad::ErrorStatus es = AcDbRegion::createFromCurves(curveSegments,regions);
	delete pCircle;pCircle = NULL;
	if(Acad::eOk == es && regions.length()>0)
	{
		AcDbRegion* pTmpRegion = (AcDbRegion*)regions[0];
		if(pTmpRegion)
		{
			pRegion = (AcDbRegion*)pTmpRegion->clone();
		}
	}
	for(int i=0;i<regions.length();++i)
	{
		delete (AcRxObject*)regions[i];
	}
	return pRegion;
}

static AcDbObjectId PostToModelSpace(AcDbEntity* pEnt,AcDbDatabase *pDb = acdbCurDwg())
{
	Acad::ErrorStatus es;
	AcDbObjectId entId = AcDbObjectId::kNull;
	AcDbBlockTable * pBlockTable = NULL;
	pEnt->setDatabaseDefaults(pDb);
	es = pDb->getBlockTable(pBlockTable, AcDb::kForRead); 
	if (es != Acad::eOk)
	{
		return entId;
	}

	AcDbBlockTableRecord *pBlockTableRecord = NULL;
	es = pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,AcDb::kForWrite);
	pBlockTable->close();
	if (es != Acad::eOk)
	{
		return entId;
	}
	es = pBlockTableRecord->appendAcDbEntity(entId, pEnt);
	pBlockTableRecord->close();
	pEnt->close();
	return entId;
}

Acad::ErrorStatus es;
AcDbRegion* pRegion1 = GetRegion(AcGePoint3d(0,0,0));
AcDbRegion* pRegion2 = GetRegion(AcGePoint3d(10,0,0));
if(pRegion1 && pRegion2)
{
	es = pRegion1->booleanOper(AcDb::kBoolUnite,pRegion2);
	if(Acad::eOk == es && pRegion2->isNull())
	{
		delete pRegion2;pRegion2 = NULL;
	}
}
AcDbRegion* pTmp = (AcDbRegion*)pRegion1->clone();
AcDbObjectId id1 = PostToModelSpace(pTmp,acdbCurDwg());
AcDbDatabase* pDb = new AcDbDatabase(true,false);
pRegion1->setDatabaseDefaults(pDb);
AcDbObjectId id2 = PostToModelSpace(pRegion1,pDb);
pDb->saveAs(_T("D:\\Region.dwg"));delete pDb;

return;

 

id1 is ok.id2 is null;

 

@tbrammer @daniel_cadext @Alexander.Rivilis 

0 Likes
Reply
Accepted solutions (1)
243 Views
4 Replies
Replies (4)

tbrammer
Advisor
Advisor

AcDbObject::clone() creates a "shallow copy" of the AcDbObject. So it is not safe to append clones to a different database. Your code works for simple entities like AcDbLine - but I would not recomment to do this anyway.

You should use AcDbDatabase::wblockCloneObjects(..) to copy objects from one DB to another.

 

 


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

0 Likes

dziwve67853
Enthusiast
Enthusiast

AcDbRegion* pTmp = (AcDbRegion*)pRegion1->clone();
AcDbObjectId id1 = PostToModelSpace(pTmp,acdbCurDwg());
These two lines prove that they can be added to the current database normally. Even without these two lines, pRegion1 cannot be added to pDb normally.

0 Likes

tbrammer
Advisor
Advisor
Accepted solution

Correct. A clone is a clone. It doesn't matter which one you add to the DB.
But since it is a shallow clone, some internal references of the regions point to the same internal data.

So as soon as you add one of the two regions to the database you must delete the second one.

 

tbrammer_1-1732783403723.png

 

This is what happens when you clone() region 1 and append the clone to the DB :

 

tbrammer_2-1732783420923.png

 

Region 1 depends on the internal data that is now tied to region2 and the DB.

It makes no difference whether you add region 1 or region 2 to the DB. In both cases you must delete the other region. Some simple entities like AcDbLine don't have references like this. But you can't rely on this.

The safe way is to use deep cloning. This guarantees that all internal data is copied as well.

 

 


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

0 Likes

dziwve67853
Enthusiast
Enthusiast

I use wblockCloneObjects to do it.It works well.Thank you!

0 Likes