ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why does adding AcDbRegion to AcDbDatabase after booleanOperar return eWrongDatabase?

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
dziwve67853
305 Views, 4 Replies

Why does adding AcDbRegion to AcDbDatabase after booleanOperar return eWrongDatabase?

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 

Labels (1)
4 REPLIES 4
Message 2 of 5
tbrammer
in reply to: dziwve67853

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.

Message 3 of 5
dziwve67853
in reply to: dziwve67853

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.

Message 4 of 5
tbrammer
in reply to: dziwve67853

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.

Message 5 of 5
dziwve67853
in reply to: dziwve67853

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

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report