#include "StdAfx.h" #include "ExternRefClone.h" #include "DbEquipment.h" #include "DbPump.h" #include "DbPool.h" #include void CloneExternRefEnts() { // 选取克隆外部参照 Entity entExternRef; RBList rbBlk(RTDXF0, _T("INSERT"), NULL); while(true) { if (SelectEntity(_T("\n外部参照<退出>:"), entExternRef, rbBlk) != RTNORM) { return; } if (IsExternalBlock(entExternRef)) { break; } acutPrintf(_T("\n不是外部参照请重新选择!")); } ExternRefClone eRc; eRc.SetExternRef(entExternRef); Entity ent; TCHAR chKey; EntData data; std::vector > vecEnt; int nRet = eRc.SelectEnt(_T("\n请选择参考图元进行克隆[单体克隆(A)]<退出>:"), ent, data, _T("A"), chKey); if (nRet == RTNORM) // 按图元拷贝同图层同类实体 { PickSet ss(SS_FREE); ss += ent; vecEnt.push_back(std::make_pair(ent, data)); Entity entTemp; entTemp = ss[0l]; while (eRc.SelectEnt(_T("\n请选择下一个参考实体"), entTemp, data) == RTNORM) { if (ss.IsInclude(entTemp)) { continue; } vecEnt.push_back(std::make_pair(entTemp, data)); } eRc.CloneByCondition(vecEnt); } else if (nRet == RTKWORD) // 单体克隆 选择什么拷贝什么 { vecEnt.push_back(std::make_pair(ent, data)); PickSet ss(SS_FREE); Entity entTemp; while (eRc.SelectEnt(_T("\n请选择克隆实体"), entTemp, data) == RTNORM) { if (ss.IsInclude(entTemp)) { continue; } ss += entTemp; vecEnt.push_back(std::make_pair(entTemp, data)); } eRc.CloneBySel(vecEnt); } } int ExternRefClone::SelectEnt( const CString &sTip, Entity &ent, EntData &data, const CString &sKeyWord, TCHAR &chKey ) { ads_point ptResult; ads_matrix xformres; resbuf* refstkres = NULL; int nRet = RTNORM; INITGET_BEG(0, sKeyWord); nRet = acedNEntSelP(sTip, ent, ptResult, 0, xformres, &refstkres); INITGET_END(); if (refstkres != NULL) { ads_relrb(refstkres); } memcpy(&data.mat, xformres, sizeof(AcGeMatrix3d)); data.ptPick = ptResult; if (nRet == RTKWORD) { TCHAR szKey[256]; acedGetInput(szKey); if (_tcslen(szKey) > 0) { chKey = szKey[0]; } } return nRet; } int ExternRefClone::SelectEnt( const CString &sTip, Entity &ent, EntData &data) { ads_point ptResult; ads_matrix xformres; resbuf* refstkres = NULL; int nRet = acedNEntSelP(sTip, ent, ptResult, 0, xformres, &refstkres); if (refstkres != NULL) { ads_relrb(refstkres); } memcpy(&data.mat, xformres, sizeof(AcGeMatrix3d)); data.ptPick = ptResult; return nRet; } void ExternRefClone::CloneByCondition( std::vector > &vecEnt ) { // 当选择的拷贝实体中包括图块时,需修改选择的实体信息 UpdateSelectionSet(vecEnt); // 获得拷贝条件 std::vector vecCdn; GetCloneCondition(vecEnt, vecCdn); // 绘制同图层同类型的外部参照中的实体 int nCloneNum = 0; DrawEntity(m_entExternRef, vecCdn, nCloneNum); // 统计克隆实体个数 CString sCloneNum; sCloneNum.Format(_T("\n成功克隆%d个实体!"), nCloneNum); acutPrintf(sCloneNum); } void ExternRefClone::CloneBySel( std::vector > &vecEnt ) { // 当选择的拷贝实体中包括图块时,需修改选择的实体信息 UpdateSelectionSet(vecEnt); AcGeMatrix3d mat; OPENOBJ_BEGIN(m_entExternRef, AcDb::kForRead, AcDbBlockReference, pRef); if (pRef != NULL) { mat = pRef->blockTransform(); } OPENOBJ_END(); // 拷贝选择实体 AcDbObjectId id; std::vector >::iterator it, itEnd = vecEnt.end(); // 成功克隆实体个数 int nCloneNum = 0; const std::vector vecCdn; for (it = vecEnt.begin(); it != itEnd; ++it) { Acad::ErrorStatus st = acdbGetObjectId(id, it->first); AcDbEntity *pEnt = NULL; st = acdbOpenObject(pEnt, id, AcDb::kForRead); if(pEnt != NULL) { AcDbEntity *pCloneEnt = NULL; CloneEntity(pEnt, vecCdn, nCloneNum, pCloneEnt); if (pCloneEnt != NULL) { pCloneEnt->transformBy(it->second.mat); AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); if (pRef != NULL) { mat = pRef->blockTransform(); pCloneEnt->transformBy(mat.invert()); } AddToCurrentSpace(pCloneEnt, Adesk::kTrue); ++nCloneNum; } pEnt->close(); } } CString sCloneNum; sCloneNum.Format(_T("\n成功克隆%d个实体!"), nCloneNum); acutPrintf(sCloneNum); } AcDbObjectId ExternRefClone::CreateCloneLayer( const CString &sLayer ) { AcDbObjectId idCloneLayer; // 克隆图层名 CString sCloneLayer = sLayer; UpdateCString(sCloneLayer); // 判断图层是否存在 AcDbLayerTable *pTbl = NULL; acdbCurDwg()->getLayerTable(pTbl, AcDb::kForRead); if (pTbl != NULL) { AcDbLayerTableIterator *it = NULL; pTbl->newIterator(it); AcDbLayerTableRecord *pRec = NULL; for (it->start(); !it->done(); it->step()) { it->getRecord(pRec, AcDb::kForRead); if (pRec == NULL) { continue; } TCHAR *pszName = NULL; pRec->getName(pszName); if (sCloneLayer.CompareNoCase(pszName) == 0) { idCloneLayer = pRec->objectId(); pRec->close(); break; } pRec->close(); } delete it; pTbl->close(); // 找到图层 if (!idCloneLayer.isNull()) { return idCloneLayer; } } // 图层不存在时,克隆实体图层 AcDbObjectId idLayer = GetLayerIdFromString(sLayer); AcDbLayerTableRecord *pRec = NULL; acdbOpenObject(pRec, idLayer, AcDb::kForRead); if (pRec != NULL) { AcDbLayerTableRecord *pNewRec = new AcDbLayerTableRecord; pNewRec->setName(sCloneLayer); AcDbObjectId idCloneLinetype = CreateCloneLinetype(pRec->linetypeObjectId()); pNewRec->setLinetypeObjectId(idCloneLinetype); pNewRec->setLineWeight(pRec->lineWeight()); pNewRec->setColor(pRec->color()); acdbCurDwg()->getLayerTable(pTbl, AcDb::kForWrite); if (pTbl != NULL) { pTbl->add(idCloneLayer, pNewRec); pNewRec->close(); pTbl->close(); } pRec->close(); } return idCloneLayer; } void ExternRefClone::SetExternRef( Entity &ent ) { m_entExternRef = ent; } void ExternRefClone::DrawEntity( Entity &entBlkRef, const std::vector &vecCdn, int &nDrawNum ) { OPENOBJ_BEGIN(m_entExternRef, AcDb::kForRead, AcDbBlockReference, pRef); if (pRef != NULL) { DrawEntity(pRef, vecCdn, nDrawNum); } OPENOBJ_END(); } void ExternRefClone::DrawEntity( AcDbBlockReference *pRef, const std::vector &vecCdn, int &nDrawNum ) { if (vecCdn.empty()) { return; } AcDbVoidPtrArray arPtr; pRef->explode(arPtr); int nLen = arPtr.length(); AcDbEntity *pEnt = NULL; CString sLayer; AcDbObjectId idLayer; for (int i = 0; i < nLen; ++i) { pEnt = AcDbEntity::cast((AcRxObject*)arPtr[i]); if (pEnt == NULL) { continue; } AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); if (pRef != NULL) // 处理图块中的外部参照 { if (IsExternRef(pRef->blockTableRecord())) { DrawEntity(pRef, vecCdn, nDrawNum); continue; } } CloneCondition data; GetCloneCondition(pEnt, data); if (FindCloneCondition(vecCdn, data)) // 满足克隆条件 { AcDbEntity *pCloneEnt = NULL; CloneEntity(pEnt, vecCdn, nDrawNum, pCloneEnt); if (pCloneEnt != NULL) { AddToCurrentSpace(pCloneEnt, Adesk::kTrue); ++nDrawNum; } } } ReleaseEntSet(arPtr); } bool ExternRefClone::IsExternRef( const AcDbObjectId &idRec ) { bool bExternBlk = false; AcDbBlockTableRecord *pRec = NULL; acdbOpenObject(pRec, idRec, AcDb::kForRead); if (pRec != NULL) { TCHAR *pszName = NULL; pRec->getName(pszName); if (pRec->isFromExternalReference()) { bExternBlk = true; } pRec->close(); } return bExternBlk; } bool ExternRefClone::IsOrdinaryRef( const AcDbObjectId &idRec ) { bool bBlk = false; AcDbBlockTableRecord *pRec = NULL; acdbOpenObject(pRec, idRec, AcDb::kForRead); if (pRec != NULL) { TCHAR *pszName = NULL; pRec->getName(pszName); CString sName = pszName; if (sName.CompareNoCase(ACDB_MODEL_SPACE) != 0) { bBlk = true; } pRec->close(); } return bBlk; } bool ExternRefClone::GetBlkId( const AcDbObjectId &idRec, const EntData &data, AcDbObjectId &idBlk ) { // 获得所有外部参照 AcDbObjectIdArray arrIds; OPENOBJ_BEGIN(idRec, AcDb::kForRead, AcDbBlockTableRecord, pRec); if (pRec != NULL) { pRec->getBlockReferenceIds(arrIds); } OPENOBJ_END(); // 选择的外部参照中的图块插入点 XPoint ptIns(0.0, 0.0, 0.0); ptIns.TransformBy(data.mat); // 找出包含pt点的外部参照,并获得图层名,图块名 int nLen = arrIds.length(); AcDbBlockReference *pRef = NULL; AcGeMatrix3d mat; XPoint ptLoc; for(int i = 0; i < nLen; ++i) { acdbOpenObject(pRef, arrIds[i], AcDb::kForWrite); if (pRef != NULL) { mat = data.mat * pRef->blockTransform().inverse(); ptLoc = pRef->position(); pRef->close(); ptLoc.TransformBy(mat); if(ptLoc.Distance2d(ptIns) < 0.001) { idBlk = arrIds[i]; return true; } } } return false; } void ExternRefClone::UpdateSelectionSet( std::vector > &vecSelEnt ) { std::vector >::iterator it, itEnd = vecSelEnt.end(); AcDbObjectId idOwner, idBlk; for (it = vecSelEnt.begin(); it != itEnd; ++it) { OPENOBJ_BEGIN(it->first, AcDb::kForRead, AcDbEntity, pEnt); if (pEnt != NULL) { // 实体是否为普通图块的组成部分 idOwner = pEnt->ownerId(); if(!IsOrdinaryRef(idOwner)) { continue; } // 获得实体所属图块id if (GetBlkId(idOwner,it->second, idBlk)) { // 将选择实体修改为图块 acdbGetAdsName(it->first.name, idBlk); } } OPENOBJ_END(); } } void ExternRefClone::GetCloneCondition( std::vector > &vecSelEnt, std::vector &vecCdn ) { std::vector >::iterator it, itEnd = vecSelEnt.end(); CloneCondition data; for (it = vecSelEnt.begin(); it != itEnd; ++it) { OPENOBJ_BEGIN(it->first, AcDb::kForRead, AcDbEntity, pEnt); if (pEnt != NULL) { GetCloneCondition(pEnt, data); if (!FindCloneCondition(vecCdn, data)) { vecCdn.push_back(data); } } OPENOBJ_END(); } } void ExternRefClone::GetCloneCondition( AcDbEntity *pEnt, CloneCondition &data ) { TCHAR *pszLayer = pEnt->layer(); data.sLayer = pszLayer; delete pszLayer; pszLayer = NULL; int nIndex = data.sLayer.Find(_T("|")); if (nIndex > -1) { int nLen = data.sLayer.GetLength(); data.sLayer = data.sLayer.Right(nLen - nIndex - 1); } } bool ExternRefClone::FindCloneCondition( const std::vector &vecCdn, const CloneCondition &data ) { std::vector::const_iterator it, itEnd = vecCdn.end(); it = std::find(vecCdn.begin(), itEnd, data); if (it != itEnd) { return true; } return false; } inline void ExternRefClone::UpdateCString( CString &sText, const CString &sTok /*= _T("|")*/ ) { int nIndex = sText.Find(sTok); if(nIndex > -1) { int nLen = sText.GetLength() ; sText = sText.Right(nLen - nIndex - 1); } } AcDbObjectId ExternRefClone::CreateCloneBlkRecord( const CString &sBlkName ) { AcDbObjectId idCloneBlk; // 图块名 CString sCloneBlkName = sBlkName; UpdateCString(sCloneBlkName); // 查看块表记录是否存在 idCloneBlk = GetBlkIdByName(sCloneBlkName); if (!idCloneBlk.isNull()) { return idCloneBlk; } // 创建新块 AcDbObjectId idBlk = GetBlkIdByName(sBlkName); AcDbBlockTableRecord *pRec = NULL; acdbOpenObject(pRec, idBlk, AcDb::kForRead); if (pRec != NULL) { AcDbBlockTableRecord *pNewRec = new AcDbBlockTableRecord; AcDbBlockTableRecordIterator *it = NULL; pRec->newIterator(it); pRec->close(); for (it->start(); !it->done(); it->step()) { AcDbEntity *pEnt = NULL; it->getEntity(pEnt, AcDb::kForRead); if (pEnt == NULL) { continue; } AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); if (pRef != NULL) { CString sName = GetBlkNameById(pRef->blockTableRecord()); AcDbObjectId idRec = CreateCloneBlkRecord(sName); AcDbBlockReference *pNewRef = new AcDbBlockReference; pNewRef->setPosition(pRef->position()); pNewRef->setRotation(pRef->rotation()); pNewRef->setScaleFactors(pRef->scaleFactors()); pNewRef->setBlockTransform(pRef->blockTransform()); pNewRef->setBlockTableRecord(idRec); pNewRec->appendAcDbEntity(pNewRef); pNewRef->close(); pRef->close(); continue; } AcDbEntity *pNewEnt = static_cast(pEnt->clone()); pNewRec->appendAcDbEntity(pNewEnt); pNewEnt->close(); pEnt->close(); } delete it; pNewRec->setName(sCloneBlkName); pNewRec->setOrigin(pRec->origin()); AcDbBlockTable *pTbl = NULL; acdbCurDwg()->getBlockTable(pTbl, AcDb::kForWrite); if (pTbl != NULL) { pTbl->add(idCloneBlk, pNewRec); pNewRec->close(); pTbl->close(); } } return idCloneBlk; } void ExternRefClone::CloneEntity( const AcDbEntity *pEnt,const std::vector &vecCdn, int &nDrawNum, AcDbEntity *&pCloneEnt ) { ASSERT(pEnt != NULL); pCloneEnt = NULL; while(true) { // 图块 AcDbBlockReference *pRef = AcDbBlockReference::cast(pEnt); if (pRef != NULL) { // 创建普通图块 CString sBlkName = GetBlkNameById(pRef->blockTableRecord()); AcDbObjectId idRec = CreateCloneBlkRecord(sBlkName); if (idRec.isNull()) { return; } AcDbBlockReference *pNewRef = new AcDbBlockReference; pNewRef->setBlockTableRecord(idRec); pNewRef->transformBy(pRef->blockTransform()); pNewRef->setPosition(pRef->position()); pCloneEnt = pNewRef; break; } // 水泵 TDbPump *pPump = TDbPump::cast(pEnt); if (pPump != NULL) { AcDbObjectId idBlk2d = pPump->GetBlock2d(); AcDbObjectId idBlk3d = pPump->GetBlock3d(); CString sBlk2dName = GetBlkNameById(idBlk2d); CString sBlk3dName = GetBlkNameById(idBlk3d); idBlk2d = CreateCloneBlkRecord(sBlk2dName); idBlk3d = CreateCloneBlkRecord(sBlk3dName); TDbPump *pNewPump = static_cast(pPump->clone()); pNewPump->SetBlock2d(idBlk2d); pNewPump->SetBlock3d(idBlk3d); pCloneEnt = pNewPump; break; } // 水池 TDbPool *pPool = TDbPool::cast(pEnt); if (pPool != NULL) { AcDbObjectId idBlk2d = pPool->GetBlock2d(); AcDbObjectId idBlk3d = pPool->GetBlock3d(); CString sBlk2dName = GetBlkNameById(idBlk2d); CString sBlk3dName = GetBlkNameById(idBlk3d); idBlk2d = CreateCloneBlkRecord(sBlk2dName); idBlk3d = CreateCloneBlkRecord(sBlk3dName); TDbPool *pNewPool = static_cast(pPool->clone()); pNewPool->SetBlock2d(idBlk2d); pNewPool->SetBlock3d(idBlk3d); pCloneEnt = pNewPool; break; } // 设备 TDbEquipment *pEuqip = TDbEquipment::cast(pEnt); if (pEuqip != NULL) { AcDbObjectId idBlk2d = pEuqip->GetBlock2d(); AcDbObjectId idBlk3d = pEuqip->GetBlock3d(); CString sBlk2dName = GetBlkNameById(idBlk2d); CString sBlk3dName = GetBlkNameById(idBlk3d); idBlk2d = CreateCloneBlkRecord(sBlk2dName); idBlk3d = CreateCloneBlkRecord(sBlk3dName); TDbEquipment *pNewEquip = static_cast(pEuqip->clone()); pNewEquip->SetBlock2d(idBlk2d); pNewEquip->SetBlock3d(idBlk3d); pCloneEnt = pNewEquip; break; } // 门窗 TDbOpening *pOpen = TDbOpening::cast(pEnt); if (pOpen != NULL) { AcDbObjectId idBlk2d = pOpen->m_nIdStyle2d; AcDbObjectId idBlk3d = pOpen->m_nIdStyle3d; CString sBlk2dName = GetBlkNameById(idBlk2d); CString sBlk3dName = GetBlkNameById(idBlk3d); idBlk2d = CreateCloneBlkRecord(sBlk2dName); idBlk3d = CreateCloneBlkRecord(sBlk3dName); TDbOpening *pNewOpen = static_cast(pOpen->clone()); pNewOpen->m_nIdStyle2d = idBlk2d; pNewOpen->m_nIdStyle3d = idBlk3d; pCloneEnt = pNewOpen; break; } // 非块实体包含块 if (IsIncludeBlk(pEnt)) { return; } // 普通实体,不包含块 pCloneEnt = static_cast(pEnt->clone()); break; } // 克隆实体图层 TCHAR *pszLayer = pEnt->layer(); CString sLayerName = pszLayer; delete pszLayer; AcDbObjectId idLayer = CreateCloneLayer(sLayerName); pCloneEnt->setLayer(idLayer); // 设置线型 AcDbObjectId idCloneLinetype = CreateCloneLinetype(pEnt->linetypeId()); pCloneEnt->setLinetype(idCloneLinetype); } CString ExternRefClone::GetLinetypeName( const AcDbObjectId &idLinetype ) { CString sLinetypeName; AcDbLinetypeTableRecord *pRec = NULL; acdbOpenObject(pRec, idLinetype, AcDb::kForRead); if (pRec != NULL) { TCHAR *pszName = NULL; pRec->getName(pszName); sLinetypeName = pszName; delete pszName; pRec->close(); } return sLinetypeName; } bool ExternRefClone::IsIncludeBlk( const AcDbEntity *pEnt ) { AcDbVoidPtrArray arrPtrs; pEnt->explode(arrPtrs); int nLen = arrPtrs.length(); AcDbEntity *pNewEnt = NULL; AcDbBlockReference *pRef = NULL; for (int i = 0; i < nLen; ++i) { pNewEnt = static_cast(arrPtrs[i]); if (pEnt == NULL) { continue; } // 包含块 pRef = AcDbBlockReference::cast(pNewEnt); if (pRef != NULL) { ReleaseEntSet(arrPtrs); return true; } if (IsIncludeBlk(pNewEnt)) { ReleaseEntSet(arrPtrs); return true; } } ReleaseEntSet(arrPtrs); return false; } AcDbObjectId ExternRefClone::CreateCloneLinetype( const AcDbObjectId &idLinetype ) { CString sLinetypeName = GetLinetypeName(idLinetype); UpdateCString(sLinetypeName); AcDbObjectId idCloneLinetype = GetLinetypeIdFromString(sLinetypeName); if (idCloneLinetype.isNull()) { idCloneLinetype = GetLinetypeIdFromString(_T("CONTINUOUS")); } return idCloneLinetype; }