1939 lines
47 KiB
C++
1939 lines
47 KiB
C++
#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<AcDbEntity*> 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<AcDbEntity*, AcDbEntityArray> &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<AecDbEntityCommon*>(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<AecDbEntityCommon *>(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<AecDbEntityCommon *>(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;
|
|
}
|
|
|
|
|
|
|