newer 发表于 2021-1-8 13:07:52

Copying an existing block entity with new block name and definition


问题:
I want to copy an existing block reference, however, the new block reference,
while identical to the original block reference, will have a different name. How
is this achieved?

解答:
1. Select the block reference (AcDbBlockReference) you want to copy.

2. Get the block reference's definition, which is an AcDbBlockTableRecord, by
using the blockTableRecord() function.

3. Iterate through the entities that make up the block definition and copy these
entities into anew block table record (AcDbBlockTableRecord).

4. Using the new block table record, create an instance (AcdbBlockReference) of
the block definition and place that block reference into model space. (The
sample code that follows demonstrates how this is achieved. In addition, there
is an attached sample ObjectARX project that defines an AutoCAD XCOPY command.)

5. In the TEST.DWG drawing that is included with the application, select a block
reference named BLKTEST. The XCOPY command will create an identical block
reference as the BLKTEST block but with a different name.

6. After executing the XCOPY command, move the new block reference as it will be
placed on top of the original block reference. Note the call to DeepCloneObjects
in the user-defined cloneBlockRecord function. The ObjectARX DeepCloneObjects
will copy the entities and the attribute definitions that make up the block
definition.

For more information on DeepCloneObjects, refer to the ObjectARX documentation.
For more information on DeepCloning, refer to the API technical paper
"DeepCloning in AutoCAD 2000" document on the ADN web site.


void asdkgtxxxcopy()
{
            // TODO: Implement the command
            AcDbEntity *pEnt = NULL;
            AcDbBlockReference *pRef = NULL;
            AcDbObjectId objId, blockId, idNewBlock, blockRefLayId, newRefId;
            AcGePoint3d basepoint;
            AcGeScale3d scalefact;
            AcGeVector3d vector;
            double rotationang;
            ads_name ename;
            ads_point pt;


            if( acedEntSel ("\nSelect the Block Reference", ename, pt) != RTNORM)
            {
                        return;
            }

            acdbGetObjectId (objId, ename);

            acdbOpenObject (pEnt, objId, AcDb::kForRead);

            // Is pEnt really a block reference entity?

            pRef = AcDbBlockReference::cast(pEnt);
            if(pRef != NULL)
            {
                        blockId = pRef->blockTableRecord();

                        idNewBlock = cloneBlockRecord(blockId, "MYBLOCKCLONED");

                        basepoint = pRef->position();
                        scalefact = pRef->scaleFactors();
                        vector = pRef->normal();
                        rotationang = pRef->rotation();
                        blockRefLayId = pRef->layerId();      
                        pRef->close();
                        newRefId = createInsertForBlock(idNewBlock,
                                                                        basepoint,
                                                                        scalefact,
                                                                        rotationang,
                                                                        vector,
                                                                        objId,
                                                                        blockRefLayId);
            } // if

            // pRef and pEnt point to the same object
            pEnt->close();
}


AcDbObjectId cloneBlockRecord(AcDbObjectId from, char *to)
{
            AcDbBlockTable *pBlockTable;
            AcDbBlockTableRecord *pBlockTableRecord;
            AcGePoint3d tempOrigin;
            AcDbObjectIdArray arrayId;
            AcDbBlockTableRecordIterator *pIter;
            AcDbObjectId objId, tableId, blockTargetId;
            AcDbDatabase *pDB;
            AcDbIdMapping idMap;

            char buffer;


            pDB = acdbHostApplicationServices()->workingDatabase();

            acdbOpenAcDbObject ((AcDbObject *&)pBlockTableRecord, from,
AcDb::kForRead);
            tempOrigin = pBlockTableRecord->origin();   
            pBlockTableRecord->newIterator(pIter);
            while (!pIter->done())
            {
                        pIter->getEntityId(objId);
                        arrayId.append(objId);
                        pIter->step();
            }
            delete pIter ;

            tableId = pBlockTableRecord->ownerId();
            pBlockTableRecord->close();


            pDB->getBlockTable(pBlockTable, AcDb::kForRead);

            strcpy(buffer, to);
            if(pBlockTable->has(buffer))
            {
                        for (int i = 0; i < 255; i++)
                        {
                                    sprintf(buffer, "%s%d", to, i);
                                    if(!pBlockTable->has(buffer))
                                    {
                                                break;
                                    }
                        }
            }

            pBlockTable->upgradeOpen ();
            pBlockTableRecord = new AcDbBlockTableRecord;
            pBlockTableRecord->setName(buffer);
            pBlockTableRecord->setOrigin(tempOrigin);

            pBlockTable->add(blockTargetId, pBlockTableRecord);
            pBlockTableRecord->close();
            pBlockTable->close();

            pDB->deepCloneObjects(arrayId, blockTargetId, idMap);

            return blockTargetId;
}

AcDbObjectId createInsertForBlock (AcDbObjectId blockId, AcGePoint3d basePoint,
                                                   AcGeScale3d scaleFactor, double rotationAng,
                                                   AcGeVector3d vector, AcDbObjectId ownerRefId,
                                                   AcDbObjectId blockRefLayId)
{
            AcDbDatabase *pDB;
            AcDbBlockReference *pBlkRef;
            AcDbBlockTable *pBlockTable;
            AcDbBlockTableRecord *pBlockTableRecord;
            AcDbObjectId newEntId;
            AcDbBlockTableRecord *pBlockDef;
            AcDbBlockTableRecordIterator *pIterator;
            AcDbBlockReference *pOriginalRef;
            AcDbObjectIterator *pIterRef;
            AcDbEntity *pEnt;
            AcDbAttributeDefinition *pAttdef;

            pDB = acdbHostApplicationServices()->workingDatabase();

            pBlkRef = new AcDbBlockReference;   
            pBlkRef->setBlockTableRecord(blockId);
            pBlkRef->setNormal(vector);
            pBlkRef->setPosition(basePoint);
            pBlkRef->setScaleFactors(scaleFactor);
            pBlkRef->setRotation(rotationAng);
            pBlkRef->setLayer(blockRefLayId, Adesk::kFalse);


            pDB->getBlockTable(pBlockTable, AcDb::kForRead);


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

            pBlockTableRecord->appendAcDbEntity(newEntId, pBlkRef);
            pBlockTableRecord->close();

            acdbOpenObject(pBlockDef, blockId, AcDb::kForRead);

            pBlockDef->newIterator(pIterator);   

            //____iterating original block ref for attributes
            acdbOpenObject(pOriginalRef,ownerRefId,AcDb::kForRead);
            pIterRef =pOriginalRef->attributeIterator ();   
            pOriginalRef->close();


            for(pIterator->start(); !pIterator->done(); pIterator->step())
            {
                        pIterator->getEntity(pEnt, AcDb::kForRead);
                        pAttdef = AcDbAttributeDefinition::cast (pEnt);
                        if (pAttdef != NULL && !pAttdef->isConstant())
                        {         
                                    //____iteration of original block ref continues...
                                    AcDbObject *pObj;
                                    AcDbObjectId ida;
                                    AcDbAttribute *pAtt;
                                    AcDbObjectId attId;

                                    ida = pIterRef->objectId();
                                    acdbOpenObject(pObj, ida, AcDb::kForRead);
                                    pAtt = AcDbAttribute::cast(pObj->clone());
                                    pObj->close();

                                    pAtt->setTextString("XXX");
                                    pBlkRef->appendAttribute(attId, pAtt);
                                    pAtt->close();
                                    pIterRef->step();
                        }

                        pEnt->close();
            }

            delete pIterator;         
            delete pIterRef;
            pBlockDef->close();
            pBlkRef->close();

            return newEntId;
}


页: [1]
查看完整版本: Copying an existing block entity with new block name and definition