#include "stdafx.h" #include "AecDbEntityCommon.h" #include "AecDbObjXDataMap.h" #include "AcGiViewDraw.h" #include "dbobjptr.h" #include "simpleproperty.h" #include "AecGripCback.h" BOOL ReadModelXData(LPCTSTR pszKey, AecDbObjXDataMap& xDataMap, AcDbDatabase* pDb); const Adesk::UInt16 kColorByLayer = 256; static const Adesk::UInt16 kRed = 1; namespace { void FreeBuffer(int n, AcDbVoidPtrArray& arEntPtrs) { AcDbEntity* pEnt = NULL; while (arEntPtrs.length() > n) { pEnt = (AcDbEntity*)arEntPtrs.last(); pEnt->erase(); pEnt->close(); DELETE_PTR(pEnt); arEntPtrs.removeLast(); } } AcGePoint3d MidPoint(AcGePoint3d &pt1, AcGePoint3d &pt2) { return AcGePoint3d((pt1.x + pt2.x) / 2.0, (pt1.y + pt2.y) / 2.0, (pt1.z + pt2.z) / 2.0); } CString IDCreate() { CString sID = _T(""); GUID Guid; static TCHAR szGuid[39]; RPC_WSTR pszGuid = NULL; UuidCreate(&Guid); if (RPC_S_OK != UuidToString(&Guid, &pszGuid)) { return _T(""); } lstrcpyn(szGuid, (TCHAR *)pszGuid, sizeof(szGuid)); RpcStringFree(&pszGuid); szGuid[38] = _T('\0'); sID = szGuid; sID.MakeUpper(); return sID; } } void AecDbEntityCommon::AssertWriteEnabled(Adesk::Boolean autoUndo, Adesk::Boolean recordModified) { FreeBuffer(0, m_ar2DDrableBufPtrs_); FreeBuffer(0, m_ar3DDrableBufPtrs_); m_ar3DDrableBufPtrs_.removeAll(); m_ar2DDrableBufPtrs_.removeAll(); GetMe()->assertWriteEnabled(autoUndo, recordModified); } AecDbEntityCommon::AecDbEntityCommon(void) { m_eExplodeOrDrawType = kWroldDraw; m_nDrawDimCur = -1; } AecDbEntityCommon::~AecDbEntityCommon(void) { FreeBuffer(0, m_ar2DDrableBufPtrs_); FreeBuffer(0, m_ar3DDrableBufPtrs_); } Acad::ErrorStatus AecDbEntityCommon::Draw2d(AcGiDraw & dc) const { return Acad::eOk; } Acad::ErrorStatus AecDbEntityCommon::Draw3d(AcGiDraw & dc) const { return Acad::eOk; } bool AecDbEntityCommon::Draw2DBuffers(AcGiDraw & dc) const { if (m_ar2DDrableBufPtrs_.isEmpty()) return false; for (int i = 0; i < m_ar2DDrableBufPtrs_.length(); ++i) dc.DrawEntity(*(AcDbEntity *)m_ar2DDrableBufPtrs_[i]); return true; } const AcDbVoidPtrArray& AecDbEntityCommon::Get2DBuffer() const { return m_ar2DDrableBufPtrs_; } bool AecDbEntityCommon::Has2DBuffer() const { return !m_ar2DDrableBufPtrs_.isEmpty(); } void AecDbEntityCommon::Add2DBuffer(AcDbEntity * pEnt) const { if (pEnt && m_ar2DDrableBufPtrs_.find(pEnt) == -1) m_ar2DDrableBufPtrs_.append(pEnt); } void AecDbEntityCommon::Add2DBuffer(const AcDbVoidPtrArray & arr) const { for (int i = 0; i < arr.length(); ++i) Add2DBuffer((AcDbEntity *)arr[i]); } bool AecDbEntityCommon::IsIn2DBuffer(AcDbEntity *pEnt) const { if (-1 == m_ar2DDrableBufPtrs_.find(pEnt)) return false; return true; } void AecDbEntityCommon::Clean2DBuffer()const { FreeBuffer(0, m_ar2DDrableBufPtrs_); m_ar2DDrableBufPtrs_.removeAll(); } void AecDbEntityCommon::Clean2DBufferNoDel()const { m_ar2DDrableBufPtrs_.removeAll(); } bool AecDbEntityCommon::Draw3DBuffers(AcGiDraw &dc) const { if (m_ar3DDrableBufPtrs_.isEmpty()) return false; for (int i = 0; i < m_ar3DDrableBufPtrs_.length(); ++i) dc.DrawEntity(*(AcDbEntity *)m_ar3DDrableBufPtrs_[i]); return true; } const AcDbVoidPtrArray& AecDbEntityCommon::Get3DBuffer() const { return m_ar3DDrableBufPtrs_; } bool AecDbEntityCommon::Has3DBuffer() const { return !m_ar3DDrableBufPtrs_.isEmpty(); } void AecDbEntityCommon::Add3DBuffer(AcDbEntity * pEnt) const { if (pEnt && m_ar3DDrableBufPtrs_.find(pEnt) == -1) m_ar3DDrableBufPtrs_.append(pEnt); } void AecDbEntityCommon::Add3DBuffer(const AcDbVoidPtrArray & arr) const { for (int i = 0; i < arr.length(); ++i) Add3DBuffer((AcDbEntity *)arr[i]); } bool AecDbEntityCommon::IsIn3DBuffer(AcDbEntity *pEnt) const { if (-1 == m_ar3DDrableBufPtrs_.find(pEnt)) return false; return true; } void AecDbEntityCommon::Clean3DBuffer()const { FreeBuffer(0, m_ar3DDrableBufPtrs_); m_ar3DDrableBufPtrs_.removeAll(); } void AecDbEntityCommon::Clean3DBufferNoDel()const { m_ar3DDrableBufPtrs_.removeAll(); } Acad::ErrorStatus AecDbEntityCommon::ReCreateDraw2d() { GetMe()->assertWriteEnabled(); Clean2DBuffer(); return Acad::eOk; } Acad::ErrorStatus AecDbEntityCommon::ReCreateDraw3d() { GetMe()->assertWriteEnabled(); Clean3DBuffer(); return Acad::eOk; } int AecDbEntityCommon::GetDrawDimCur() const { return m_nDrawDimCur; } CString AecDbEntityCommon::getUniqueName() const { return _T(""); } int AecDbEntityCommon::GetExplodeMode() const { int nDrawMode = GetDrawMode(); DrawModeType nDrawType = k2Dand3D; int nDraw = GetDrawDimOnType(nDrawMode, nDrawType); if (nDraw == 1) { nDraw = DRAW_2D; } else if (nDraw == 2) { nDraw = DRAW_3D; } else if (nDraw == 3) { ads_point pt; struct resbuf rb; acedGetVar(_T("VIEWDIR"), &rb); ads_point_set(rb.resval.rpoint, pt); ads_point viewDir; acdbUcs2Wcs(pt, viewDir, false); if (fabs(viewDir[X]) > 1.0e-6 || fabs(viewDir[Y]) > 1.0e-6) { nDraw = DRAW_3D; } else { nDraw = DRAW_2D; } } return nDraw; } int AecDbEntityCommon::GetDrawMode() { int nDrawMode = 3; //从命名字典中取,默认3 return nDrawMode; } void AecDbEntityCommon::SetDrawMode(int nMode) { //写入命名字典 } void AecDbEntityCommon::BackupColorIndex(AcDbEntity* pEnt) { if (pEnt != NULL) { struct resbuf* pXData = NULL; pXData = pEnt->xData(_T("COLOR_BK")); if (pXData == NULL) { struct resbuf* pTemp = acutNewRb(AcDb::kDxfRegAppName); acutNewString(_T("COLOR_BK"),pTemp->resval.rstring); pXData = pTemp; struct resbuf* pTempNext = NULL; pTempNext = acutNewRb(AcDb::kDxfXdInteger32); pTempNext->resval.rlong = pEnt->colorIndex(); pTemp->rbnext = pTempNext; pTempNext->rbnext = NULL; acdbRegApp(_T("COLOR_BK")); pEnt->setXData(pXData); acutRelRb(pXData); } } } int AecDbEntityCommon::SetBackupColorIndex(AcDbEntity* pEnt) { int nColor = kColorByLayer; if (pEnt != NULL) { resbuf* pXData = NULL; pXData = pEnt->xData(_T("COLOR_BK")); if (pXData != NULL) { struct resbuf* pTempNext = pXData->rbnext; if (pTempNext != NULL) { if (pTempNext->restype == AcDb::kDxfXdInteger32) { nColor = pTempNext->resval.rint; pEnt->setColorIndex(nColor); // 存在清空 struct resbuf* pTmp = acutNewRb(AcDb::kDxfRegAppName); pEnt->setXData(pTmp); acutRelRb(pXData); acutRelRb(pTmp); } } } } return nColor; } int AecDbEntityCommon::GetDrawDimOnType(int nDrawMode, int nDrawType) const { int nDraw = 0; //0--NONE; 1--2D; 2--3D; 3--2D&3D; if (nDrawMode == DRAW_2D && (nDrawType == k2DOnly || nDrawType == k2Dand3D)) { nDraw = 1; } else if (nDrawMode == DRAW_3D && (nDrawType == k3DOnly || nDrawType == k2Dand3D)) { nDraw = 2; } else if (nDrawMode == (DRAW_2D | DRAW_3D) && nDrawType == k2Dand3D) { nDraw = 3;//转到viewportdraw } else if (nDrawMode == (DRAW_2D | DRAW_3D) && nDrawType == k2DOnly) { nDraw = 1; } else if (nDrawMode == (DRAW_2D | DRAW_3D) && nDrawType == k3DOnly) { nDraw = 2; } return nDraw; } typedef AcArray AcDbEntityArray; void AecDbEntityCommon::PreprocessForHlr(const AcGePoint3d &ptPlnO , const AcGeVector3d &vtPlnN , AcDbEntityArray &ar) const { GetMe()->assertReadEnabled(); return; } void AecDbEntityCommon::ProcessHlrResult(const AcDbEntityArray &ar , const std::map &preAr , AcDbEntityArray &output) const { GetMe()->assertReadEnabled(); AcDbObjectId idLy(GetMe()->layerId()), idLt(GetMe()->linetypeId()); int clr(GetMe()->colorIndex()); const AecDbObjXDataMap *pXData = GetSpecialtyData(); for (int i(0); i < ar.length(); ++i) { AcDbEntity *pEnt((AcDbEntity*)ar[i]->clone()); if (pEnt) { if (pXData) pXData->Write(pEnt, BIMDATA_APP); pEnt->setLayer(idLy); pEnt->setLinetype(idLt); pEnt->setColorIndex(clr); output.append(pEnt); } } } bool AecDbEntityCommon::GetBimInfoTip(CString& sInfoTip) const { return false; } bool AecDbEntityCommon::GetProperties(SimpleProperty::PropertySetByIndex &porpertys) const { GetMe()->assertReadEnabled(); CString sLayer(_T("0")); TCHAR *pLayer = GetMe()->layer(); if (pLayer) { sLayer = pLayer; acutDelString(pLayer); } SimpleProperty::makeAndInsert(porpertys, _T("图层"), sLayer, false); const AecDbObjXDataMap *pData = GetSpecialtyData(); CString sys; if (pData->GetAt(PIPE_SYS, sys)) SimpleProperty::makeAndInsert(porpertys, _T("分系统"), sys, false); return true; } bool AecDbEntityCommon::SetProperties(SimpleProperty::PropertySetByName & properties) { AssertWriteEnabled(); using namespace SimpleProperty; CString sVal(_T("")); if (properties.findAndSet(_T("图层"), sVal)) { GetMe()->setLayer(sVal); } if (properties.findAndSet(_T("分系统"), sVal)) { AecDbObjXDataMap *pData = GetSpecialtyData(AcDb::kForWrite); if (pData) pData->SetAt(PIPE_SYS, sVal); } return true; } double AecDbEntityCommon::GetVolume(bool bIsBody) const { GetMe()->assertReadEnabled(); if (!Has3DBuffer()) { AcGiViewDraw dc(NULL, NULL); Draw3d(dc); } double dVol = 0.0, dVolAll = 0.0, momInertia[3], prodInertia[3], prinMoments[3], radiiGyration[3]; AcGePoint3d ptCen; AcGeVector3d prinAxes[3]; AcDbExtents extents; AcDbVoidPtrArray arEntPtrs; GetDraw3dables(arEntPtrs); AcDbEntity *pEnt = NULL; for (int i = 0; i < arEntPtrs.length(); i++) { pEnt = (AcDbEntity *)arEntPtrs.at(i); AcDb3dSolid *pSolid = AcDb3dSolid::cast(pEnt); if (pSolid != NULL) { pSolid->getMassProp(dVol, ptCen, momInertia, prodInertia, prinMoments, prinAxes, radiiGyration, extents); dVolAll += dVol; } } return dVolAll; } int AecDbEntityCommon::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray &arEntPtrs) const { GetMe()->assertReadEnabled(); AcDbEntity* pEnt = NULL,*pEntT = NULL; const AcDbVoidPtrArray &ar2D = Get2DBuffer(); for (int i = 0;i < ar2D.length();i++) { pEnt = (AcDbEntity*)ar2D.at(i); pEntT = (AcDbEntity*)pEnt->clone(); pEntT->setLayer(GetMe()->layerId()); arEntPtrs.append(pEntT); } return arEntPtrs.length(); } int AecDbEntityCommon::GetDraw3dables(AcDbVoidPtrArray& arEntPtrs,bool bWriteBimInfo) const { GetMe()->assertReadEnabled(); const AecDbObjXDataMap* pXDataMap = GetSpecialtyData(); if (pXDataMap != NULL) { AcDbEntity* pEnt = NULL,*pEntClone = NULL; if (!Has3DBuffer()) { AcGiViewDraw dc(NULL, NULL); Draw3d(dc); } const AcDbVoidPtrArray &ar3D = Get3DBuffer(); for (int i = 0;i < ar3D.length();i++) { pEnt = (AcDbEntity*)ar3D.at(i); pEntClone = (AcDbEntity*)pEnt->clone(); int nColor = 0; if ( pXDataMap->GetAt(_T("COLOR"),nColor) ) { pEntClone->setColorIndex(nColor); } else { pEntClone->setColorIndex(GetMe()->colorIndex()); } pEntClone->setLayer(GetMe()->layerId()); if (bWriteBimInfo) { pXDataMap->Write(pEntClone,_T("BIMDATA")); } arEntPtrs.append(pEntClone); } } return arEntPtrs.length(); } SHJson::WValue& AecDbEntityCommon::ToJson(bool bExprotGeo) const { GetMe()->assertReadEnabled(); using namespace SHJson; WValue &v(m_json); v.SetObject(); addMember(v, _T("__class__"), GetMe()->isA()->name()); addMember(v, _T("__self__"), GetMe()->objectId().asOldId()); addMember(v, _T("__owner__"), 0); const AecDbObjXDataMap *pXMap = GetSpecialtyData(); if (pXMap) { addMember(v, _T("__xdata__"), pXMap->ToJson()); } return v; } bool AecDbEntityCommon::ByJson(const SHJson::WValue &v) { using namespace SHJson; AssertWriteEnabled(); AecDbObjXDataMap *pXMap = GetSpecialtyData(AcDb::kForWrite); if (pXMap) { MCIt it = v.FindMember(_T("__xdata__")); if (it != v.MemberEnd()) return pXMap->ByJson(it->value); } return true; } bool AecDbEntityCommon::GetSectionHatchPattern(CString& sPattern) const { GetMe()->assertReadEnabled(); CString sMat; if (GetSpecialtyData()->GetAt(KEY_SECTION_HATCH, sMat)) { sPattern = sMat; if (sMat == HATCH_NO_NEED) return false; if (sMat != HATCH_DEFAULT) return true; } if ( GetSpecialtyData()->GetAt(KEY_MATERIAL,sMat)) { //以后从外部配置文件中获取 //钢筋混凝土 //石材 //砖墙 //填充墙体 //轻质隔墙 //玻璃幕墙 sPattern = _T("AR-CONC");//默认 if (sMat.CompareNoCase(_T("钢筋混凝土")) == 0) { sPattern = _T("钢筋混凝土"); } else if(sMat.CompareNoCase(_T("混凝土")) == 0) { sPattern = _T("混凝土"); } else if(sMat.CompareNoCase(_T("石材")) == 0) { sPattern = _T("天然石材"); } else if(sMat.CompareNoCase(_T("砖墙")) == 0) { sPattern = _T("普通砖"); } else if(sMat.CompareNoCase(_T("填充墙体")) == 0) { sPattern = _T("钢筋混凝土"); } else if(sMat.CompareNoCase(_T("轻质隔墙")) == 0) { sPattern = _T("混凝土"); } else if(sMat.CompareNoCase(_T("玻璃幕墙")) == 0) { sPattern = _T("玻璃砖墙"); } } return true; } void AecDbEntityCommon::BoolSubtractHide() const { } Acad::ErrorStatus AecDbEntityCommon::subGet3dGeomExtents(AcDbExtents &extents) const { AcDbVoidPtrArray entSet; if (!Has3DBuffer()) { AcGiViewDraw dc(NULL, NULL); Draw3d(dc); } entSet.append(Get3DBuffer()); if (entSet.isEmpty()) return Acad::eNullExtents; BOOL bInit = TRUE; AcGePoint3d ptMax, ptMin; AcDbExtents ext, extT; int len = entSet.length(); for (int i = 0; i < len; i++) { AcDbEntity *pEnt = (AcDbEntity *)entSet[i]; if (pEnt->getGeomExtents(extT) == Acad::eOk) { ext.addExt(extT); } } AcGePoint3d ptLow, ptUp; ptLow = ext.minPoint(); ptUp = ext.maxPoint(); extents.set(ptLow, ptUp); return Acad::eOk; } void AecDbEntityCommon::Add3DBoolSubtract(AcDb3dSolid* pSolidBlackHole) { GetMe()->assertWriteEnabled(); const AcDbVoidPtrArray& ar3D_ = Get3DBuffer(); AcDbVoidPtrArray ar3D; ar3D.append(ar3D_); AcDbEntity* pEnt = NULL; AcDb3dSolid* pSolid = NULL; AcDb3dSolid* pSolidCln = NULL; AcDb3dSolid* pSolidNotGet = NULL; Acad::ErrorStatus es; Adesk::Boolean bSlidInterface = Adesk::kFalse; double dArea1 = 0.0,dArea2 = 0.0; for (int i = 0;i < ar3D.length();i++) { pEnt = (AcDbEntity*)ar3D.at(i); pSolid = AcDb3dSolid::cast(pEnt); if (pSolid != NULL) { pSolidCln = (AcDb3dSolid*)pSolidBlackHole->clone(); //有交集才处理 if ( Acad::eOk == pSolid->checkInterference( pSolidCln,Adesk::kFalse,bSlidInterface,pSolidNotGet)) { pSolid->getArea(dArea1); es = pSolid->booleanOper(AcDb::kBoolSubtract,pSolidCln); pSolid->getArea(dArea2); if ( es == Acad::eOk) { pSolid->recordGraphicsModified(Adesk::kTrue); if ( fabs(dArea1 - dArea2) < 1.e-3)//没有变化,被包含 { ar3D.removeAt(i); m_ar3DDrableBufPtrs_.removeAt(i); i -= 1; } } else if ( es == Acad::eGeneralModelingFailure ) { ar3D.removeAt(i); m_ar3DDrableBufPtrs_.removeAt(i); i -= 1; } //delete pSolidCln; } } } } void AecDbEntityCommon::Remove3DBoolSubtract() { GetMe()->assertWriteEnabled(); //清除3D,重建 Clean3DBuffer(); } void AecDbEntityCommon::AddBlackHole(AcDbObjectId& idHole) { AssertWriteEnabled(); AecDbObjXDataMap* pXdataMap = GetSpecialtyData(AcDb::kForWrite); if (pXdataMap != NULL) { TCHAR szHand[19]; memset(szHand,0,sizeof(szHand) ); idHole.handle().getIntoAsciiBuffer(szHand); CString sKey; sKey.Format(_T("%s_%s"),KEY_HOLE,szHand); pXdataMap->SetAt(sKey,idHole.handle()); } } void AecDbEntityCommon::RemoveBlackHole(AcDbObjectId& idHole) { AssertWriteEnabled(); AecDbObjXDataMap* pXdataMap = GetSpecialtyData(AcDb::kForWrite); if (pXdataMap != NULL) { TCHAR szHand[19]; memset(szHand,0,sizeof(szHand) ); idHole.handle().getIntoAsciiBuffer(szHand); CString sKey; sKey.Format(_T("%s_%s"),KEY_HOLE,szHand); pXdataMap->RemoveAt(sKey); } } void AecDbEntityCommon::DrawBlackHole(AcDbEntity* pSolidEnt) const { AcDb3dSolid* pSolidAll = AcDb3dSolid::cast(pSolidEnt); if (pSolidAll == NULL) return; const AecDbObjXDataMap* pCXDataMap = GetSpecialtyData(); if (pCXDataMap != NULL) { AecDbObjXDataMap* pXDataMap = (AecDbObjXDataMap*)pCXDataMap; AecDbObjXDataMap::It it = pXDataMap->Begin(); AecDbObjXDataMap::It end = pXDataMap->End(); CString sKey; AecXData cVal; memset(&cVal,0,sizeof(AecXData)); AcDbEntity* pEnt = NULL; AcDbHandle hd; AcDbObjectId idHole; for (; it != end; ) { if (!pXDataMap->GetNext(it, sKey, cVal)) break; if (sKey.Find(KEY_HOLE) != -1) { pXDataMap->GetAt(sKey,hd); if ( Acad::eOk == acdbCurDwg()->getAcDbObjectId(idHole,false,hd) ) { if ( Acad::eOk == acdbOpenAcDbEntity(pEnt,idHole,AcDb::kForRead)) { if (IsThisMe(pEnt)) { AecDbEntityCommon *pBlackHole = dynamic_cast(pEnt); if (pBlackHole != NULL) { AcDb3dSolid *pSolidBlackHold = pBlackHole->GetBlackHole(); if (pSolidBlackHold != NULL) { pSolidAll->booleanOper(AcDb::kBoolSubtract, pSolidBlackHold); } } } pEnt->close(); } } } } } } void AecDbEntityCommon::UpdateDrableSpecData(LPCTSTR pszApp,LPCTSTR pszKey,CString& sVal) { GetMe()->assertWriteEnabled(); AecDbObjXDataMap xDataMap; AcDbEntity* pEnt = NULL,*pEntT = NULL; const AcDbVoidPtrArray &ar2D = Get2DBuffer(); for (int i = 0;i < ar2D.length();i++) { pEnt = (AcDbEntity*)ar2D.at(i); if (xDataMap.Read(pEnt,pszApp)) { xDataMap.RemoveAt(pszKey); xDataMap.SetAt(pszKey,sVal); xDataMap.Write(pEnt,pszApp); } } const AcDbVoidPtrArray &ar3D = Get3DBuffer(); for (int i = 0;i < ar3D.length();i++) { pEnt = (AcDbEntity*)ar3D.at(i); if (xDataMap.Read(pEnt,pszApp)) { xDataMap.RemoveAt(pszKey); xDataMap.SetAt(pszKey,sVal); xDataMap.Write(pEnt,pszApp); } } } extern double PixelToWcs(int nPixel); bool AecDbEntityCommon::SubAddHitEditGrip(AcDbGripDataPtrArray &grips) const { GetMe()->assertReadEnabled(); AecGripData *pGrip = NULL; GetPositionGrip(grips.length() - 1, pGrip); if (pGrip != NULL) { AcGePoint3d ptHit = pGrip->ptGrip; ptHit += AcGeVector3d::kXAxis * PixelToWcs(30); AecGripData *pGrip2 = new AecGripData; memset(pGrip2, 0, sizeof(AecGripData)); pGrip2->nIndex = grips.length(); pGrip2->ePos = eHitEdit; pGrip2->nColor = kRed; pGrip2->ptGrip = ptHit; _tcscpy(pGrip2->szTip, _T("点击修改")); _tcscpy(pGrip2->szID, _T("HITEDIT_2023")); pGrip2->pOwner = (AcDbEntity *)GetMe(); pGrip2->idHost = GetMe()->objectId(); AcDbGripData *pGripData = new AcDbGripData; pGripData->setGripPoint(ptHit); pGripData->setAppData((void *)pGrip2); pGripData->setWorldDraw(AecGripCback::WorldDrawfunc); pGripData->setToolTipFunc(AecGripCback::GripToolTipFunc); grips.append(pGripData); return true; } return false; } //不得导出,需要数据,增加特定的获取函数 extern AecDbObjXDataMap g_mapGlobalData; bool AecDbEntityCommon::HitOnGripEdit(const AcDbVoidPtrArray &gripAppData) { AecGripData *pAppData = NULL; AcDbIntArray arIndex; if (gripAppData.isEmpty()) { return Acad::eOk; } pAppData = (AecGripData *)gripAppData.first(); if (pAppData->ePos == eHitEdit) { //命令名 DBL_DXFNAME TCHAR szCmd[65]; _tcscpy(szCmd, _T("DBL_")); _tcscat(szCmd, GetMe()->isA()->dxfName()); //判断命令是否存在 AcEdCommand *pCmd = acedRegCmds->lookupLocalCmd(szCmd); if (pCmd != NULL) { //发送ID 到 USERI; AcDbObjectId id = pAppData->idHost; g_mapGlobalData.SetAt(szCmd, id); acedPostCommand(_T("\x03")); _tcscat(szCmd, _T(" ")); acedPostCommand(szCmd); } else { acutPrintf(_T("\nLocalCmd %s does not exist!"), szCmd); } return true; } return false; } //按分隔符拆字符串。来源:AecDbEntityBase.cpp / AecDbCurveBase.cpp(两族逐字相同) void AecDbEntityCommon::SplitStrintToArray(LPCTSTR pszDescr, CStringArray & arInfo, TCHAR tcSpace) { if (pszDescr == NULL) return; CString sDescr = pszDescr; int nLen = sDescr.GetLength(); int i = 0; CString sText = _T(""); TCHAR tchar = _T('\0'); for (i = 0; i < nLen; i++) { tchar = sDescr.GetAt(i); if (tchar == tcSpace) { if (!sText.IsEmpty()) arInfo.Add(sText); sText = _T(""); } else { sText += tchar; } if (i == nLen - 1 && !sText.IsEmpty()) { arInfo.Add(sText); } } } // 世界绘制:原 AecDbEntityBase::subWorldDraw / AecDbCurveBase::subWorldDraw 逐行一致。 // subWorldDraw 是 AcGiDrawable 的虚函数,本类不在 AcDb 继承链上,只能由两个根各自转发。 Adesk::Boolean AecDbEntityCommon::base_WorldDraw(AcGiWorldDraw *pWd) { GetMe()->assertReadEnabled(); m_eExplodeOrDrawType = kWroldDraw; AcGiViewDraw dc(pWd, NULL); dc.SetDrawRaw(GetMe()); //1.如果是保存代理图形 AcGiRegenType nRegenType = pWd->regenType(); if (nRegenType == kAcGiSaveWorldDrawForProxy) { ads_point pt; struct resbuf rb; acedGetVar(_T("VIEWDIR"),&rb); ads_point_set(rb.resval.rpoint,pt); ads_point viewDir; acdbUcs2Wcs(pt,viewDir,false); if (fabs(viewDir[X]) > 1.0e-6 || fabs(viewDir[Y]) > 1.0e-6) { Draw3d(dc); m_nDrawDimCur = 3; } else { Draw2d(dc); m_nDrawDimCur = 2; } return Adesk::kTrue; } //设属性 dc.SetLayer(_T("0")); dc.SetColor(256); //如果图层关闭 AcDbLayerTableRecordPointer pLayer; if ( Acad::eOk == pLayer.open(GetMe()->layerId(), AcDb::kForRead) ) { if ( pLayer->isOff() ) { return Adesk::kTrue; } } int nDrawMode = GetDrawMode(); DrawModeType nDrawType = k2Dand3D; int nDraw = GetDrawDimOnType(nDrawMode, nDrawType); if (nRegenType == kAcGiSaveWorldDrawForProxy || nRegenType == kAcGiSaveWorldDrawForR12) { if (!!GetMe()->ownerId()) { pWd->subEntityTraits().setSelectionMarker(0); dc.SetColor(GetMe()->colorIndex()); dc.SetLayer(GetMe()->layerId()); } if ((nDrawMode & DRAW_2D) && (nDrawType != k3DOnly)) { Draw2d(dc); m_nDrawDimCur = 2; } else if ((nDrawMode & DRAW_3D) && (nDrawType != k2DOnly)) { Draw3d(dc); m_nDrawDimCur = 3; } return Adesk::kTrue; } return Adesk::kFalse; } // 视口绘制:原 AecDbEntityBase::subViewportDraw / AecDbCurveBase::subViewportDraw 逐行一致。 // 同样是 AcGiDrawable 的虚函数,只能由两个根各自转发。 void AecDbEntityCommon::base_ViewportDraw(AcGiViewportDraw* pMode) { GetMe()->assertReadEnabled(); m_eExplodeOrDrawType = kViewportDraw; AcGiRegenType nRegenType = pMode->regenType(); AcGiViewport &vp = pMode->viewport(); AcGePoint3d ptCamera, ptTarget; vp.getCameraTarget(ptTarget); vp.getCameraLocation(ptCamera); AcGeVector3d vtViewDrt = ptCamera-ptTarget; AcGeVector3d vtViewDir1 = vp.viewDir(); AcGeVector3d vtCamera; vp.getCameraUpVector(vtCamera); vtViewDrt.normalize(); AcGiViewDraw dc(NULL, pMode); dc.SetDrawRaw(GetMe()); // 设属性 dc.SetLayer(_T("0")); dc.SetColor(256); //如果图层关闭 AcDbLayerTableRecordPointer pLayer; if ( Acad::eOk == pLayer.open(GetMe()->layerId(), AcDb::kForRead) ) { if ( pLayer->isOff() ) { return; } } if (!!GetMe()->ownerId()) { pMode->subEntityTraits().setSelectionMarker(0); dc.SetColor(GetMe()->colorIndex()); dc.SetLayer(GetMe()->layerId()); } int nDrawMode = GetDrawMode(); DrawModeType nDrawType = k2Dand3D; int nDraw = GetDrawDimOnType(nDrawMode, nDrawType); if (nDraw == 3) { if ( nRegenType == kAcGiRenderCommand || nRegenType == kAcGiHideOrShadeCommand || vp.isPerspective() || vtViewDrt != AcGeVector3d(0,0,1)) { Draw3d(dc); m_nDrawDimCur = 3; } else { Draw2d(dc); m_nDrawDimCur = 2; } } else if (nDraw == 1) { Draw2d(dc); m_nDrawDimCur = 2; } else if (nDraw == 2) { Draw3d(dc); m_nDrawDimCur = 3; } } // 保存代理实体图元:原两个根的 saveAs 逐行一致。 void AecDbEntityCommon::base_SaveAs(AcGiWorldDraw *pWd, AcDb::SaveType saveType) { AecDbObjXDataMap xDataMap; ReadModelXData(EW_EARTHWORMINIT, xDataMap, NULL); int nSaveToProxy(0); xDataMap.GetAt(_T("SaveToProxy"), nSaveToProxy); if (nSaveToProxy == 0) // 不保存代理图形 return; AcGiRegenType rtype = pWd->regenType(); if (rtype == kAcGiSaveWorldDrawForProxy) { // 走实体自己的 subWorldDraw(子类可能重写),不是 Common 的 base_WorldDraw CallWorldDraw(pWd); } else { GetMe()->AcDbEntity::saveAs(pWd, saveType); } } // 视口绘制标志:原两个根的 subViewportDrawLogicalFlags 逐行一致。 // nBaseFlags 由两个根用 AcDbEntity::subViewportDrawLogicalFlags(vd) 取到后传入—— // 该接口在 AcGiDrawable / AcDbObject 里是 protected,本类不在继承链上取不到。 Adesk::UInt32 AecDbEntityCommon::base_ViewportDrawLogicalFlags(Adesk::UInt32 nBaseFlags) { Adesk::UInt32 nFlagNew = nBaseFlags; int nDrawMode = GetDrawMode(); DrawModeType nDrawType = k2Dand3D; int nDraw = GetDrawDimOnType(nDrawMode, nDrawType); if (nDraw != 3) { nFlagNew |= AcGiDrawable::kDrawableViewIndependentViewportDraw; } else { nFlagNew |= AcGiDrawable::kDrawableRegenDraw; } return nFlagNew; } // 绘制属性:原两个根的 subSetAttributes 逐行一致,同样是 protected,base 结果由根传入。 Adesk::UInt32 AecDbEntityCommon::base_SetAttributes(Adesk::UInt32 nBaseFlags) { int nDrawMode = GetDrawMode(); DrawModeType nDrawType = k2Dand3D; int nDraw = GetDrawDimOnType(nDrawMode, nDrawType); Adesk::UInt32 nFlagNew = nBaseFlags; nFlagNew |= AcGiDrawable::kDrawableViewIndependentViewportDraw; return nFlagNew; } // 炸开:原两个根的 subExplode 逐行一致。 Acad::ErrorStatus AecDbEntityCommon::base_Explode(AcDbVoidPtrArray& entitySet) const { ExplodeOrDrawType& eExplodeType = (ExplodeOrDrawType&)m_eExplodeOrDrawType; eExplodeType = kExplode; int expMode = GetExplodeMode(); if (expMode == 1) { GetDraw2dables(0,entitySet); } else if (expMode == 2) { GetDraw3dables(entitySet); } return Acad::eOk; } // 几何范围:原 AecDbEntityBase::subGetGeomExtents / AecDbCurveBase::subGetGeomExtents 逐行一致。 Acad::ErrorStatus AecDbEntityCommon::base_GetGeomExtents(AcDbExtents& extents) const { AcGePoint3d ptLow, ptUp; AcDbVoidPtrArray entSet; int expMode = GetExplodeMode(); if (expMode == 1) { entSet.append(Get2DBuffer()); } else if (expMode == 2) { entSet.append(Get3DBuffer()); } BOOL bInit = TRUE; AcGePoint3d ptMax,ptMin; AcDbExtents ext,extT; int len = entSet.length(); for (int i = 0; i < len; i++) { AcDbEntity *pEnt = (AcDbEntity *)entSet[i]; if (pEnt->getGeomExtents(extT) == Acad::eOk) { ext.addExt(extT); } } ptLow = ext.minPoint(); ptUp = ext.maxPoint(); extents.set(ptLow, ptUp); return Acad::eOk; } // 对象捕捉点:原两个根的 subGetOsnapPoints(第一个重载)逐行一致。 Acad::ErrorStatus AecDbEntityCommon::base_GetOsnapPoints( AcDb::OsnapMode osnapMode, INT_PTR gsSelectionMark, const AcGePoint3d& ptPick, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const { GetMe()->assertReadEnabled(); AcDbVoidPtrArray entSet; int expMode = GetExplodeMode(); if (expMode == 1) { entSet.append(Get2DBuffer()); } else if (expMode == 2) { entSet.append(Get3DBuffer()); } Acad::ErrorStatus es = Acad::eOk; if (es == Acad::eOk) { int len = entSet.length(); for (int i = 0; i < len; i++) { AcDbEntity *pEnt=(AcDbEntity *)entSet[i]; if (pEnt->isKindOf(AcDbText::desc())) { if (osnapMode == AcDb::kOsModeIns) { snapPoints.append(AcDbText::cast(pEnt)->position()); } else { continue; } } es = pEnt->getOsnapPoints(osnapMode, 0, ptPick, lastPoint, viewXform, snapPoints, geomIds); } es = Acad::eOk; } return Acad::eOk; } Acad::ErrorStatus AecDbEntityCommon::base_DeepClone( AcDbObject* pOwner, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary) const { // You should always pass back pClonedObject == NULL // if, for any reason, you do not actually clone it // during this call. The caller should pass it in // as NULL, but to be safe, we set it here as well. // pClonedObject = NULL; // If this object is in the idMap and is already // cloned, then return. // bool isPrim = false; if (isPrimary) isPrim = true; AcDbIdPair idPair(GetMe()->objectId(), (AcDbObjectId)NULL, false, isPrim); if (idMap.compute(idPair) && (idPair.value() != NULL)) return Acad::eOk; // Create the clone // AcDbEntity *pClone = (AcDbEntity*)GetMe()->isA()->create(); AecDbEntityCommon *pCloneCommon = dynamic_cast(pClone); if (pClone != NULL && pCloneCommon != NULL) pClonedObject = pClone; // set the return value else return Acad::eOutOfMemory; AcDbDeepCloneFiler filer; GetMe()->dwgOut(&filer); filer.seek(0L, AcDb::kSeekFromStart); pClone->dwgIn(&filer); pCloneCommon->NewGUID(); pClone->setLayer(GetMe()->layerId()); bool bOwnerXlated = false; if (isPrimary) { AcDbBlockTableRecord *pBTR = AcDbBlockTableRecord::cast(pOwner); if (pBTR != NULL) { pBTR->appendAcDbEntity(pClone); bOwnerXlated = true; } else { pOwner->database()->addAcDbObject(pClone); } } else { pOwner->database()->addAcDbObject(pClone); pClone->setOwnerId(pOwner->objectId()); bOwnerXlated = true; } // This must be called for all newly created objects // in deepClone. It is turned off by endDeepClone() // after it has translated the references to their // new values. // pClone->setAcDbObjectIdsInFlux(); pClone->disableUndoRecording(true); // Add the new information to the idMap. We can use // the idPair started above. // idPair.setValue(pClonedObject->objectId()); idPair.setIsCloned(Adesk::kTrue); idPair.setIsOwnerXlated(bOwnerXlated); idMap.assign(idPair); // Using the filer list created above, find and clone // any owned objects. // AcDbObjectId id; while (filer.getNextOwnedObject(id)) { AcDbObject *pSubObject(NULL); AcDbObject *pClonedSubObject(NULL); // Some object's references may be set to NULL, // so don't try to clone them. // if (id == NULL) continue; // Open the object and clone it. Note that we now // set "isPrimary" to kFalse here because the object // is being cloned, not as part of the primary set, // but because it is owned by something in the // primary set. // acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead); if (pSubObject == NULL) continue; pClonedSubObject = NULL; pSubObject->deepClone(pClonedObject, pClonedSubObject, idMap, Adesk::kFalse); // If this is a kDcInsert context, the objects // may be "cheapCloned". In this case, they are // "moved" instead of cloned. The result is that // pSubObject and pClonedSubObject will point to // the same object. So, we only want to close // pSubObject if it really is a different object // than its clone. // if (pSubObject != pClonedSubObject) pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. // if (pClonedSubObject != NULL) pClonedSubObject->close(); } //xdataMap 复制 //到mep中找建立新的关系 AecDbObjXDataMap* pXDataMapCloned = pCloneCommon->GetSpecialtyData(); AecDbObjXDataMap* pXDataMap = (AecDbObjXDataMap*)GetSpecialtyData(); if (pXDataMap != NULL && pXDataMapCloned != NULL) { pXDataMapCloned->CopyFrom(pXDataMap); //发送提资需要相同的ID Adesk::Int16 nVal = acdbCurDwg()->useri4(); if (nVal != KEY_NOPROTECT) { int nVt = 0; CString sID = IDCreate(); if (pXDataMapCloned->HasKey(KEY_NO, nVt)) { pXDataMapCloned->SetAt(KEY_NO, sID); } } AecDbObjXDataMap::It it = pXDataMap->Begin(); AecDbObjXDataMap::It end = pXDataMap->End(); CString sKey; CStringArray arHandKeys; AecXData cVal; memset(&cVal,0,sizeof(AecXData)); AcDbObjectId idSrc,idCloned; for (; it != end; ) { if (!pXDataMap->GetNext(it, sKey, cVal)) break; if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard { idSrc.setFromOldId(cVal.nVal); AcDbObject *pSubObject; AcDbObject *pClonedSubObject; // Some object's references may be set to NULL, // so don't try to clone them. // if (idSrc == NULL) continue; AcDbIdPair idPair2(idSrc, (AcDbObjectId)NULL, false, isPrim); if (idMap.compute(idPair2) && (idPair2.value() != NULL)) { if (pXDataMapCloned != NULL) { pXDataMapCloned->RemoveAt(sKey); pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE); } continue; } // Open the object and clone it. Note that we now // set "isPrimary" to kFalse here because the object // is being cloned, not as part of the primary set, // but because it is owned by something in the // primary set. // pSubObject = NULL; acdbOpenAcDbObject(pSubObject, idSrc, AcDb::kForRead); pClonedSubObject = NULL; if (pSubObject != NULL) { //只考虑上华AEC的实体 LPCTSTR pszDxf = pSubObject->isA()->dxfName(); if (_tcsstr(pszDxf, _T("AEC_'")) != NULL) { pSubObject->deepClone(pClonedObject, pClonedSubObject, idMap, Adesk::kFalse); } else { pSubObject->close(); pSubObject = NULL; } } // If this is a kDcInsert context, the objects // may be "cheapCloned". In this case, they are // "moved" instead of cloned. The result is that // pSubObject and pClonedSubObject will point to // the same object. So, we only want to close // pSubObject if it really is a different object // than its clone. // if (pSubObject != NULL && pSubObject != pClonedSubObject) pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. // if (pClonedSubObject != NULL) idCloned = pClonedSubObject->objectId(); if (pClonedSubObject != NULL) pClonedSubObject->close(); if (pXDataMapCloned != NULL && idCloned.isValid()) { pXDataMapCloned->RemoveAt(sKey); pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE); } idCloned = AcDbObjectId::kNull; } else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄 { arHandKeys.Add(sKey); } } //2022-05-04 需要测试 CString sHand; AcDbHandle hd; for (int n = 0; n < arHandKeys.GetSize(); n++) { sKey = arHandKeys.GetAt(n); sHand = sKey; sHand.TrimRight(_T("$H")); AcDbHandle handle(sHand); AcDbObjectId idSrc; if (Acad::eOk == acdbCurDwg()->getAcDbObjectId(idSrc, false, handle)) { AcDbObject *pSubObject; AcDbObject *pClonedSubObject; // Some object's references may be set to NULL, // so don't try to clone them. // if (idSrc == NULL) continue; AcDbIdPair idPair2(idSrc, (AcDbObjectId)NULL, false, isPrim); if (idMap.compute(idPair2) && (idPair2.value() != NULL)) { CString sKeyNew; //sKey.Format(_T("%s$H"),szHand); if (pXDataMapCloned != NULL) { TCHAR szHand[19]; memset(szHand, 0, sizeof(szHand)); idPair2.value().handle().getIntoAsciiBuffer(szHand); sKeyNew.Format(_T("%s$H"), szHand); pXDataMapCloned->RemoveAt(sKey); pXDataMapCloned->SetAt(sKeyNew, szHand); } continue; } // Open the object and clone it. Note that we now // set "isPrimary" to kFalse here because the object // is being cloned, not as part of the primary set, // but because it is owned by something in the // primary set. // pSubObject = NULL; acdbOpenAcDbObject(pSubObject, idSrc, AcDb::kForRead); pClonedSubObject = NULL; if (pSubObject != NULL) { //只考虑上华AEC的实体 LPCTSTR pszDxf = pSubObject->isA()->dxfName(); if (_tcsstr(pszDxf, _T("AEC_'")) != NULL) { pSubObject->deepClone(pClonedObject, pClonedSubObject, idMap, Adesk::kFalse); } else { pSubObject->close(); pSubObject = NULL; } } // If this is a kDcInsert context, the objects // may be "cheapCloned". In this case, they are // "moved" instead of cloned. The result is that // pSubObject and pClonedSubObject will point to // the same object. So, we only want to close // pSubObject if it really is a different object // than its clone. // if (pSubObject != pClonedSubObject) pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. // if (pClonedSubObject != NULL) idCloned = pClonedSubObject->objectId(); if (pClonedSubObject != NULL) pClonedSubObject->close(); if (pXDataMapCloned != NULL && idCloned.isValid()) { CString sKeyNew; TCHAR szHand[19]; memset(szHand, 0, sizeof(szHand)); idCloned.handle().getIntoAsciiBuffer(szHand); sKeyNew.Format(_T("%s$H"), szHand); pXDataMapCloned->RemoveAt(sKey); pXDataMapCloned->SetAt(sKeyNew, szHand); } idCloned = AcDbObjectId::kNull; } } } // Leave pClonedObject open for the caller return Acad::eOk; } Acad::ErrorStatus AecDbEntityCommon::base_WblockClone(AcRxObject* pOwner, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary) const { // You should always pass back pClonedObject == NULL // if, for any reason, you do not actually clone it // during this call. The caller should pass it in // as NULL, but to be safe, we set it here as well. // pClonedObject = NULL; // fast wblock(源库与目标库相同)不做任何克隆,交回 AcDb 一侧。 AcDbDatabase *pDest, *pOrig; idMap.destDb(pDest); idMap.origDb(pOrig); if (pDest == pOrig) return CallAcDbWblockClone(pOwner, pClonedObject, idMap, isPrimary); // If this is an Xref bind operation and this AsdkPoly // entity is in Paper Space, then we don't want to // clone because Xref bind doesn't support cloning // entities in Paper Space. So we simply return // Acad::eOk // AcDbObjectId pspace; AcDbBlockTable *pTable(NULL); GetMe()->database()->getSymbolTable(pTable, AcDb::kForRead); if (pTable == NULL) return Acad::eOk; pTable->getAt(ACDB_PAPER_SPACE, pspace); pTable->close(); if (idMap.deepCloneContext() == AcDb::kDcXrefBind && GetMe()->ownerId() == pspace) return Acad::eOk; // If this object is in the idMap and is already // cloned, then return. // bool isPrim = false; if (isPrimary) isPrim = true; AcDbIdPair idPair(GetMe()->objectId(), (AcDbObjectId)NULL, false, isPrim); if (idMap.compute(idPair) && (idPair.value() != NULL)) return Acad::eOk; // The owner object can be either an AcDbObject, or an // AcDbDatabase. AcDbDatabase is used if the caller is // not the owner of the object being cloned (because it // is being cloned as part of an AcDbHardPointerId // reference). In this case, the correct ownership // will be set during reference translation. So, if // the owner is an AcDbDatabase, then pOwn will be left // NULL here, and is used as a "flag" later. // AcDbObject *pOwn = AcDbObject::cast(pOwner); AcDbDatabase *pDb = AcDbDatabase::cast(pOwner); if (pDb == NULL) pDb = pOwn->database(); // STEP 1: // Create the clone // AcDbEntity *pClone = (AcDbEntity*)GetMe()->isA()->create(); AecDbEntityCommon *pCloneCommon(NULL); if (pClone) { pCloneCommon = dynamic_cast(pClone); if (pCloneCommon != NULL) pClonedObject = pClone; // set the return value else { DELETE_PTR(pClone); return Acad::eOutOfMemory; } } else return Acad::eOutOfMemory; // STEP 2: // If the owner is an AcDbBlockTableRecord, go ahead // and append the clone. If not, but we know who the // owner is, set the clone's ownerId to it. Otherwise, // we set the clone's ownerId to our own ownerId (in // other words, the original owner Id). This Id will // then be used later, in reference translation, as // a key to finding who the new owner should be. This // means that the original owner must also be cloned at // some point during the wblock operation. // EndDeepClone's reference translation aborts if the // owner is not found in the idMap. // // The most common situation where this happens is // AcDbEntity references to Symbol Table Records, such // as the Layer an Entity is on. This is when you will // have to pass in the destination database as the owner // of the Layer Table Record. Since all Symbol Tables // are always cloned in Wblock, you do not need to make // sure that Symbol Table Record owners are cloned. // // However, if the owner is one of your own classes, // then it is up to you to make sure that it gets // cloned. This is probably easiest to do at the end // of this function. Otherwise you may have problems // with recursion when the owner, in turn, attempts // to clone this object as one of its subObjects. // AcDbBlockTableRecord *pBTR = NULL; if (pOwn != NULL) pBTR = AcDbBlockTableRecord::cast(pOwn); if (pBTR != NULL && isPrimary) { pBTR->appendAcDbEntity(pClone); } else { pDb->addAcDbObject(pClonedObject); } // STEP 3: // The AcDbWblockCloneFiler makes a list of // AcDbHardOwnershipIds and AcDbHardPointerIds. These // are the references which must be cloned during a // Wblock operation. // AcDbWblockCloneFiler filer; GetMe()->dwgOut(&filer); // STEP 4: // Rewind the filer and read the data into the clone. // filer.seek(0L, AcDb::kSeekFromStart); pClone->dwgIn(&filer); pCloneCommon->NewGUID(); idMap.assign(AcDbIdPair(GetMe()->objectId(), pClonedObject->objectId(), Adesk::kTrue, isPrim, (Adesk::Boolean)(pOwn != NULL))); pClonedObject->setOwnerId((pOwn != NULL) ? pOwn->objectId() : GetMe()->ownerId()); // STEP 5: // This must be called for all newly created objects // in wblockClone. It is turned off by endDeepClone() // after it has translated the references to their // new values. // pClone->setAcDbObjectIdsInFlux(); // STEP 6: // Add the new information to the idMap. We can use // the idPair started above. We must also let the // idMap entry know whether the clone's owner is // correct, or needs to be translated later. // // STEP 7: // Using the filer list created above, find and clone // any hard references. // AcDbObjectId id; while (filer.getNextHardObject(id)) { AcDbObject *pSubObject(NULL); AcDbObject *pClonedSubObject(NULL); // Some object's references may be set to NULL, // so don't try to clone them. // if (id == NULL) continue; // If the referenced object is from a different // database, such as an xref, do not clone it. // acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead); if (pSubObject == NULL) continue; if (pSubObject->database() != GetMe()->database()) { pSubObject->close(); continue; } // We can find out if this is an AcDbHardPointerId // verses an AcDbHardOwnershipId, by seeing if we // are the owner of the pSubObject. If we are not, // then we cannot pass our clone in as the owner // for the pSubObject's clone. In that case, we // pass in our clone's database (the destination // database). // // Note that we now set "isPrimary" to kFalse here // because the object is being cloned, not as part // of the primary set, but because it is owned by // something in the primary set. // pClonedSubObject = NULL; if (pSubObject->ownerId() == GetMe()->objectId()) { pSubObject->wblockClone(pClone, pClonedSubObject, idMap, Adesk::kFalse); } else { pSubObject->wblockClone(pClone->database(), pClonedSubObject, idMap, Adesk::kFalse); } pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. // if (pClonedSubObject != NULL) pClonedSubObject->close(); } //xdataMap 复制 //到mep中找建立新的关系 AecDbObjXDataMap *pXDataMapCloned = pCloneCommon->GetSpecialtyData(); AecDbObjXDataMap *pXDataMap = (AecDbObjXDataMap *)GetSpecialtyData(); if (pXDataMap != NULL && pXDataMapCloned != NULL) { //发送提资需要相同的ID Adesk::Int16 nVal = acdbCurDwg()->useri4(); if (nVal != KEY_NOPROTECT) { int nVt = 0; CString sID = IDCreate(); if (pXDataMapCloned->HasKey(KEY_NO, nVt)) { pXDataMapCloned->SetAt(KEY_NO, sID); } } AecDbObjXDataMap::It it = pXDataMap->Begin(); AecDbObjXDataMap::It end = pXDataMap->End(); CString sKey; CStringArray arHandKeys; AecXData cVal; memset(&cVal, 0, sizeof(AecXData)); AcDbObjectId idSrc, idCloned; for (; it != end;) { if (!pXDataMap->GetNext(it, sKey, cVal)) break; if (cVal.nVt == AecXData::kTypeSoftId || cVal.nVt == AecXData::kTypeHardId)//soft,hard { idSrc.setFromOldId(cVal.nVal); AcDbObject *pSubObject; AcDbObject *pClonedSubObject; // Some object's references may be set to NULL, // so don't try to clone them. // if (idSrc == NULL) continue; AcDbIdPair idPair2(idSrc, (AcDbObjectId)NULL, false, isPrim); if (idMap.compute(idPair2) && (idPair2.value() != NULL)) { if (pXDataMapCloned != NULL) { pXDataMapCloned->SetAt(sKey, idPair2.value(), cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE); } continue; } // Open the object and clone it. Note that we now // set "isPrimary" to kFalse here because the object // is being cloned, not as part of the primary set, // but because it is owned by something in the // primary set. // acdbOpenAcDbObject(pSubObject, idSrc, AcDb::kForRead); if (pSubObject == NULL) continue; pClonedSubObject = NULL; if (pSubObject->ownerId() == GetMe()->objectId()) { pSubObject->wblockClone(pClone, pClonedSubObject, idMap, Adesk::kFalse); } else { pSubObject->wblockClone(pClone->database(), pClonedSubObject, idMap, Adesk::kFalse); } // If this is a kDcInsert context, the objects // may be "cheapCloned". In this case, they are // "moved" instead of cloned. The result is that // pSubObject and pClonedSubObject will point to // the same object. So, we only want to close // pSubObject if it really is a different object // than its clone. // if (pSubObject != NULL && pSubObject != pClonedSubObject) pSubObject->close(); // The pSubObject may either already have been // cloned, or for some reason has chosen not to be // cloned. In that case, the returned pointer will // be NULL. Otherwise, since we have no immediate // use for it now, we can close the clone. // if (pClonedSubObject != NULL) idCloned = pClonedSubObject->objectId(); if (pClonedSubObject != NULL) pClonedSubObject->close(); if (pXDataMapCloned != NULL && idCloned.isValid()) { pXDataMapCloned->RemoveAt(sKey); pXDataMapCloned->SetAt(sKey, idCloned, cVal.nVt == AecXData::kTypeSoftId ? TRUE : FALSE); } idCloned = AcDbObjectId::kNull; } else if (sKey.Find(_T("$H")) != -1 && cVal.nVt == AecXData::kTypeString)//可能的实体句柄 { arHandKeys.Add(sKey); } } } return Acad::eOk; }