Files
envi-code/SourceCode/Code2026/tg_shs/shs_public/CompareDwg.cpp
T
2026-09-28 15:28:50 +08:00

1459 lines
35 KiB
C++

//////////////////////////////////////////////////////////////////////
/********************************************************************
created: 2007/12/12
created: 12:12:2007 12:47
filename: f:\tg_dev\水电开发\tch_public\comparedwg.cpp
file path: f:\tg_dev\水电开发\tch_public
file base: comparedwg
file ext: cpp
author: 沈睿
purpose: dwg进行比对
*********************************************************************/
#include "stdafx.h"
#include <dbidmap.h>
#include <actrans.h>
//#include "xacgi.h"
//#include "arxtools.h"
//#include "Xgcom.h"
//#include "findfile.h"
#include "CompareDwg.h"
#include "DwgCompareDlg.h"
#include <AcExtensionModule.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//主函数
void CompareDwgCmd()
{
CCompareDwg cmpDwg;
cmpDwg.DoCompareFile();
}
//////////////////////////////////////////////////////////////////////////
//class CDataEntityList
CDataEntityList::CDataEntityList()
{
m_dataDList.clear();
}
CDataEntityList::CDataEntityList( int nCount )
{
m_dataDList.clear();
if(nCount <= 0)
{
return;
}
for (int i=0; i<nCount; i++)
{
m_dataDList.push_back(new DList<TCompareEntity>);
}
}
CDataEntityList::~CDataEntityList()
{
for (int n=0; n<Length(); n++)
{
DList<TCompareEntity>* p = m_dataDList[n];
if (p != NULL)
{
delete p;
p = NULL;
}
}
m_dataDList.clear();
}
int CDataEntityList::Length() const
{
return (int)m_dataDList.size();
}
DList<TCompareEntity>& CDataEntityList::operator[]( int n )
{
return (*(m_dataDList[n]));
}
//////////////////////////////////////////////////////////////////////////
//class CCompareDwg
CCompareDwg::CCompareDwg( void )
{
}
CCompareDwg::~CCompareDwg( void )
{
}
BOOL CCompareDwg::DoCompareFile()
{
AcApDocument* pDoc = acDocManager->curDocument();
acDocManager->lockDocument(pDoc);
//加载文件
CDwgCompareDbMgr * pMgr1 = new CDwgCompareDbMgr();
CDwgCompareDbMgr * pMgr2 = new CDwgCompareDbMgr();
CAcModuleResourceOverride vTemp;
CDwgCompareDlg dlgCmp(pMgr1, pMgr2, 0);
if(dlgCmp.DoModal() == IDOK)
{
//开始比对
clock_t startTimeG, finishTimeG; //计时
double durationG;
startTimeG = clock();
m_bCmpBlockRef = dlgCmp.m_bCmpBlock; //设置是否比对块
m_bCmpHatch = dlgCmp.m_bCmpHatch; //设置是否比对填充
m_bCmpXref = dlgCmp.m_bCmpXref; //设置是否比对外部参照
m_iRow = dlgCmp.m_iRowCount; //设置分块行列数
m_iCol = dlgCmp.m_iColumnCount;
if(DoCompareFile(pMgr1, pMgr2))
{
ads_command(RTSTR, _T(".ZOOM"), RTSTR, _T("E"), NULL);
acedPostCommand(_T("REGEN\n"));
}
finishTimeG = clock();
durationG = (double)(finishTimeG - startTimeG) / CLOCKS_PER_SEC;
CString csTemp;
csTemp.Format(_T("\n文件1加载用时:%lf秒..\n[%s]"), dlgCmp.m_timeLoadFile1, pMgr1->GetFilePath());
acutPrintf(csTemp);
//WriteLogFile(dlgCmp.m_timeLoadFile1, csTemp);
csTemp.Format(_T("\n文件2加载用时:%lf秒..\n[%s]"), dlgCmp.m_timeLoadFile2, pMgr2->GetFilePath());
acutPrintf(csTemp);
//WriteLogFile(dlgCmp.m_timeLoadFile2, csTemp);
acutPrintf(_T("\n图纸比对用时:%lf秒.."), durationG);
//WriteLogFile(durationG);//比对信息写入记录文件
}
delete pMgr1;
pMgr1 =NULL;
delete pMgr2;
pMgr2 = NULL;
acDocManager->unlockDocument(pDoc);
return TRUE;
}
void CCompareDwg::SetRowCol( int iRow, int iCol )
{
m_iRow = iRow;
m_iCol = iCol;
if(m_iRow<1)
{
m_iRow=1;
}
if(m_iCol<1)
{
m_iCol=1;
}
}
BOOL CCompareDwg::DoCompareFile( CDwgCompareDbMgr * pDbMgr1, CDwgCompareDbMgr * pDbMgr2 )
{
if (pDbMgr1==NULL || pDbMgr2==NULL)
{
return FALSE;
}
//ads_command(RTSTR, _T(".PURGE"), RTSTR, _T("ALL"), RTSTR, _T(""), RTSTR, _T("N"), NULL);
AcDbObjectId idBlock1 = AcDbObjectId::kNull;
AcDbObjectId idBlock2 = AcDbObjectId::kNull;
//图纸1插入图中
idBlock1 = InitBlockByFile(pDbMgr1);
if(idBlock1.isNull())
{
return FALSE;
}
//把这个图块插入图中
XPoint ptIns;
//使用原点作为插入点
AcDbBlockReference *pInsert=new AcDbBlockReference(ptIns, idBlock1);
if (pInsert == NULL)
{
return FALSE;
}
AcDbObjectId idInsert=AddToCurrentSpace(pInsert, Adesk::kFalse);
if(!idInsert)
{
delete pInsert;
return FALSE;
}
//计算这个块的外包
AcDbExtents extBlk1;
pInsert->getGeomExtents(extBlk1);
pInsert->close();//关闭
//图纸2插入图中
idBlock2 = InitBlockByFile(pDbMgr2);
if(idBlock2.isNull())
{
return FALSE;
}
AcDbBlockReference *pInsert2=new AcDbBlockReference(ptIns, idBlock2);
if (pInsert2 == NULL)
{
return FALSE;
}
AcDbObjectId idInsert2=AddToCurrentSpace(pInsert2, Adesk::kFalse);
if(!idInsert2)
{
delete pInsert2;
return FALSE;
}
//计算这个块的外包
AcDbExtents extBlk2;
pInsert2->getGeomExtents(extBlk2);
pInsert2->close();//关闭
//解除所有图层特殊状态后再计算外包
BOOL bStatus = ResetAllLayerStatus();
//插入两个图块后执行清理
//ads_command(RTSTR, _T(".PURGE"), RTSTR, _T("ALL"), RTSTR, _T(""), RTSTR, _T("N"), NULL);
ads_command(RTSTR, _T(".ZOOM"), RTSTR, _T("E"), RTNONE);
//ads_command(RTSTR, _T("_REGEN"), NULL);
//计算外包,需要在炸开处理前计算
//因为炸开过程中同时对实体计算分块
// SetExtent();
/*AcDbExtents extDb1(pDbMgr1->GetDb()->extmin(), pDbMgr1->GetDb()->extmax());
AcDbExtents extDb2(pDbMgr2->GetDb()->extmin(), pDbMgr2->GetDb()->extmax());
//先设置比对外包为两个DB的
m_extBlk = extDb1;
m_extBlk.addExt(extDb2);
//SetExtent中,全图不改m_extBlk,局部使用参数
SetExtent(extBlk1, extBlk2);*/
SetExtent(extBlk1, extBlk2);
int iLength = m_iCol*m_iRow; //分块数目
CDataEntityList dataList1(iLength), dataList2(iLength);
/*取满足条件的图层和解除所有图层特殊状态不冲突
*获取比对图层是在原来的DB对象中进行的,解锁是当前图纸,涉及到3个DB
*/
//炸开块1,删除被炸开的实体,添加炸开后的实体到这个块中
//炸开过程中同时分块
OPENOBJ_BEGIN(idBlock1, AcDb::kForWrite, AcDbBlockTableRecord , pRec);
if(pRec)
{
DeepExplodeBlock(pRec, pDbMgr1, dataList1, 1);
}
OPENOBJ_END();
acutPrintf(_T("\n块 1 分析完成..."));
//炸开块2,删除被炸开的实体,添加炸开后的实体到这个块中
OPENOBJ_BEGIN(idBlock2, AcDb::kForWrite, AcDbBlockTableRecord , pRec);
if(pRec)
{
DeepExplodeBlock(pRec, pDbMgr2, dataList2, 2);
}
OPENOBJ_END();
acutPrintf(_T("\n块 2 分析完成..."));
m_iCountEnt =0;
int iLen1= dataList1.Length();
int iLen2= dataList2.Length();
int iLen = (iLen1>iLen2) ? iLen2 : iLen1; //取较小的, iLen1应该等于iLen2
acedSetStatusBarProgressMeter(_T("比对中..."), 0, iLen);
for (int i=0; i<iLen; i++)
{
acedSetStatusBarProgressMeterPos(i);
DList<TCompareEntity> &lstArea1 = dataList1[i];
DList<TCompareEntity> &lstArea2 = dataList2[i];
if (lstArea1.Length() <= 0 || lstArea2.Length() <= 0)
{
continue;
}
long lenList1=lstArea1.Length();
long lenList2=lstArea2.Length();
acutPrintf(_T("\n区域[%d]比对:[%d]*[%d]"), i, lenList1, lenList2);
CompareCurve(lstArea1, lstArea2);
}
acedRestoreStatusBar();
acutPrintf(_T("\n比对完成..."));
#ifdef _DEBUG
PrintInfo();//输出统计信息
#endif // _DEBUG
PrintInfo();//输出统计信息
return TRUE;
}
BOOL CCompareDwg::DoCompareFile( CString csFileName1, CString csFileName2, CString csBlkName1, CString csBlkName2 )
{
//加载文件
clock_t startTime, finishTime; //计时
double duration;
startTime = clock();
CDwgCompareDbMgr * pMgr1 = new CDwgCompareDbMgr();
if (!pMgr1->LoadFile(csBlkName1, csFileName1))
{
return FALSE;
}
CDwgCompareDbMgr * pMgr2 = new CDwgCompareDbMgr();
if (!pMgr2->LoadFile(csBlkName2, csFileName2))
{
return FALSE;
}
finishTime = clock();
duration = (double)(finishTime - startTime) / CLOCKS_PER_SEC;
CDwgCompareDlg dlgCmp(pMgr1, pMgr2, 2);
if(dlgCmp.DoModal() == IDOK)
{
//开始比对
clock_t startTimeG, finishTimeG; //计时
double durationG;
startTimeG = clock();
m_bCmpBlockRef = dlgCmp.m_bCmpBlock; //设置是否比对块
m_bCmpHatch = dlgCmp.m_bCmpHatch; //设置是否比对填充
m_bCmpXref = dlgCmp.m_bCmpXref; //设置是否比对外部参照
m_iRow = dlgCmp.m_iRowCount; //设置分块行列数
m_iCol = dlgCmp.m_iColumnCount;
if(DoCompareFile(pMgr1, pMgr2))
{
ads_command(RTSTR, _T(".ZOOM"), RTSTR, _T("E"), NULL);
acedPostCommand(_T("REGEN\n"));
}
finishTimeG = clock();
durationG = (double)(finishTimeG - startTimeG) / CLOCKS_PER_SEC;
CString csTemp;
csTemp.Format(_T("\n文件加载用时:%lf秒..\n[%s]\n[%s]"), duration, pMgr1->GetFilePath(), pMgr2->GetFilePath());
acutPrintf(csTemp);
//WriteLogFile(duration, csTemp);
acutPrintf(_T("\n图纸比对用时:%lf秒.."), durationG);
//WriteLogFile(durationG);//比对信息写入记录文件
}
delete pMgr1;
pMgr1 =NULL;
delete pMgr2;
pMgr2 = NULL;
return TRUE;
}
AcDbObjectId CCompareDwg::InitBlockByFile( CDwgCompareDbMgr * pDbMgr )
{
AcDbObjectId id = AcDbObjectId::kNull;
if (pDbMgr == NULL)
{
return id;
}
AcDbDatabase *pDb=NULL;
CString sFileName = pDbMgr->GetFileName();
XDbBlockTableRec blk(sFileName, AcDb::kForRead, pDb);
if(!blk)
{
if(!pDb)
pDb=acdbCurDwg();
AcDbDatabase * pDbInsert = pDbMgr->GetDb();
AcDbBlockTable* pBlockTable = NULL;
pDbInsert->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableIterator *pIterator=NULL;
Acad::ErrorStatus es1=pBlockTable->newIterator(pIterator);
pBlockTable->close();
if(es1==Acad::eOk && pIterator != NULL)
{
int len = 0;
int i=0;
for(pIterator->start(); !pIterator->done(); pIterator->step())
{
len++;
//外部参照加载
AcDbBlockTableRecord *pRec=NULL;
if(pIterator->getRecord(pRec, AcDb::kForWrite)==Acad::eOk && pRec)
{
const TCHAR *rName=NULL;
pRec->getName(rName);
BOOL bXref = pRec->isFromExternalReference();
pRec->close();
if (m_bCmpXref && bXref)
{
//关闭pRec,先Reload,再Bind
// Acad::ErrorStatus es = acedXrefReload(rName, true, pDbInsert);
Acad::ErrorStatus es = acedXrefReload(rName, true);
if (es == Acad::eOk)
{
// es = acedXrefBind(rName, false, true, pDbInsert);
es = acedXrefBind(rName, false, true);
}
}
}
}
acedSetStatusBarProgressMeter(_T("导入文件中..."), 0, len);
for(pIterator->start(); !pIterator->done(); pIterator->step())
{
acedSetStatusBarProgressMeterPos(i);
i++;
AcDbBlockTableRecord *pRec=NULL;
if(pIterator->getRecord(pRec, AcDb::kForWrite)==Acad::eOk && pRec)
{
const TCHAR *rName=NULL;
pRec->getName(rName);
BOOL bMspace=(_tcsicmp(rName, ACDB_MODEL_SPACE)==0 || _tcsicmp(rName, ACDB_PAPER_SPACE)==0);
if(!bMspace)
{
CString csName = rName;
csName = csName + _T("-") + sFileName;
pRec->setName(csName);
}
pRec->close();
}
}
delete pIterator;
acedRestoreStatusBar();
}
pDb->insert(id, sFileName, pDbInsert);
}
else
{
id=blk.m_pBlockTableRec->objectId();
}
return id;
}
void CCompareDwg::ProcessBlk( AcDbObjectId idBlock, int iColIdx, CDataEntityList &lstDwgRow )
{
int nLenLst = lstDwgRow.Length();
//遍历炸开后的块,进行分块
AcDbBlockTableRecordIterator *pIterator = NULL;
OPENOBJ_BEGIN(idBlock, AcDb::kForWrite, AcDbBlockTableRecord , pRec);
if(pRec)
{
pRec->newIterator(pIterator);
}
OPENOBJ_END();
for(pIterator->start(); !pIterator->done(); pIterator->step())
{
AcDbEntity *pEnt = NULL;
Acad::ErrorStatus es = pIterator->getEntity(pEnt, AcDb::kForWrite);
if(es == Acad::eOk && pEnt != NULL)
{
//设置图层 颜色
pEnt->setLayer(_T("0"));
pEnt->setColorIndex(iColIdx);
//根据外包计算列表下标
AcDbExtents bExtent;
pEnt->getGeomExtents(bExtent);
//处理字体缺失,文字外包不准确问题
AcDbText *pTextTemp = NULL;
if ( pTextTemp = AcDbText::cast(pEnt) )
{
bExtent.set(pTextTemp->position(), pTextTemp->position());
}
//int nIndex = GetIndexOfArea(bExtent);
int nIndex = GetIndexOfArea(bExtent, nLenLst);
//超出范围的实体不进行比对
if (nIndex<0 || nIndex>=nLenLst)
{
pEnt->close();
continue;
}
DList<TCompareEntity> &lstDwg = lstDwgRow[nIndex];
AcDbObjectId id = pEnt->objectId();
AcDbBlockReference *pBlockRef = NULL;
AcDbLine *pLine = NULL;
AcDbArc *pArc = NULL;
AcDbCircle *pCir = NULL;
AcDbPoint *pt = NULL;
AcDbSolid *pSolid = NULL;
AcDbText *pText = NULL;
AcDbAlignedDimension *pDim = NULL;
XCurveSegment seg;
if(pLine = AcDbLine::cast(pEnt))
{
XLine line(XPoint(pLine->startPoint()), XPoint(pLine->endPoint()));
seg = line;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pArc = AcDbArc::cast(pEnt))
{
AcGePoint3d ptStart, ptEnd;
pArc->getStartPoint(ptStart);
pArc->getEndPoint(ptEnd);
double dAng(0), dLen(0);
pArc->getDistAtPoint(ptEnd, dLen);
dAng = dLen / pArc->radius();
XArc arc(XPoint(ptStart), XPoint(ptStart), dAng);
seg = arc;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pCir = AcDbCircle::cast(pEnt))
{
AcGePoint3d ptCen = pCir->center();
XCircle cir(XPoint(ptCen), pCir->radius());
seg = cir;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pt = AcDbPoint::cast(pEnt))
{
TCompareEntity *pNew = new TCompareEntity(pt->position());
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pSolid = AcDbSolid::cast(pEnt))
{
AcGePoint3d p1, p2, p3, p4;
pSolid->getPointAt(0, p1);
pSolid->getPointAt(1, p2);
pSolid->getPointAt(2, p3);
pSolid->getPointAt(3, p4);
TCompareEntity *pNew = new TCompareEntity(p1, p2, p3, p4);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pText = AcDbText::cast(pEnt))
{
TCHAR *szText = pText->textString();
CString csText = szText;
delete szText;
AcGePoint3d ptLoc = pText->position();
TCompareEntity *pNew = new TCompareEntity(ptLoc, pText->height(), csText);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pDim = AcDbAlignedDimension::cast(pEnt))
{
TCHAR *szText = pDim->dimensionText();
CString csText = szText;
delete szText;
AcGePoint3d ptLoc = pDim->dimLinePoint();
AcGePoint3d p1 = pDim->xLine1Point();
AcGePoint3d p2 = pDim->xLine2Point();
TCompareEntity *pNew = new TCompareEntity(ptLoc, p1, p2, csText);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else
{
//如果不是以上图元,有可能复杂图元没有完全炸碎,这里简化处理,将他们删除显示
//打印实体类型
//acutPrintf(_T("\n复杂图元:name[%s],dxfName[%s]"), pEnt->isA()->name(), pEnt->isA()->dxfName());
//m_mapOtherEnt[pEnt->isA()->name()]++;
m_mapOtherEnt[pEnt->isA()->dxfName()]++;
pEnt->erase();
}
pEnt->close();
}
}
delete pIterator;
}
void CCompareDwg::ProcessEnt( AcDbEntity * pEnt, int iColIdx, CDataEntityList &lstData )
{
//pEnt已是打开状态,不再打开或关闭
if (pEnt == NULL)
{
return;
}
int nLenLst = lstData.Length();
//设置图层 颜色
Acad::ErrorStatus es = pEnt->setLayer(_T("0"));
es = pEnt->setColorIndex(iColIdx);
//根据外包计算列表下标
AcDbExtents bExtent;
es = pEnt->getGeomExtents(bExtent);
//标注获取外包失败
if (es == Acad::eInvalidExtents && pEnt->isKindOf(AcDbAlignedDimension::desc()))
{
AcDbAlignedDimension * pDim = AcDbAlignedDimension::cast(pEnt);
if (pDim == NULL)
{
return;
}
bExtent.set(pDim->dimLinePoint(), pDim->dimLinePoint());
//设置标注文字颜色20130609
pDim->setColorIndex(iColIdx);
AcCmColor clr;
clr.setColorIndex(iColIdx);
pDim->setDimclre(clr);
pDim->setDimclrd(clr);
pDim->setDimclrt(clr);
}
//处理字体缺失,文字外包不准确问题
AcDbText *pTextTemp = NULL;
if ( pTextTemp = AcDbText::cast(pEnt) )
{
bExtent.set(pTextTemp->position(), pTextTemp->position());
}
int nIndex = GetIndexOfArea(bExtent, nLenLst);
//超出范围的实体不进行比对
if (nIndex<0 || nIndex>=nLenLst)
{
return;
}
DList<TCompareEntity> &lstDwg = lstData[nIndex];
AcDbObjectId id = pEnt->objectId();
AcDbLine *pLine = NULL;
AcDbArc *pArc = NULL;
AcDbCircle *pCir = NULL;
AcDbPoint *pt = NULL;
AcDbSolid *pSolid = NULL;
AcDbText *pText = NULL;
AcDbAlignedDimension *pDim = NULL;
XCurveSegment seg;
if(pLine = AcDbLine::cast(pEnt))
{
XLine line(XPoint(pLine->startPoint()), XPoint(pLine->endPoint()));
seg = line;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pArc = AcDbArc::cast(pEnt))
{
AcGePoint3d ptStart, ptEnd;
pArc->getStartPoint(ptStart);
pArc->getEndPoint(ptEnd);
double dAng(0), dLen(0);
pArc->getDistAtPoint(ptEnd, dLen);
dAng = dLen / pArc->radius();
XArc arc(XPoint(ptStart), XPoint(ptStart), dAng);
seg = arc;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pCir = AcDbCircle::cast(pEnt))
{
AcGePoint3d ptCen = pCir->center();
XCircle cir(XPoint(ptCen), pCir->radius());
seg = cir;
TCompareEntity *pNew = new TCompareEntity(seg);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pt = AcDbPoint::cast(pEnt))
{
TCompareEntity *pNew = new TCompareEntity(pt->position());
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pSolid = AcDbSolid::cast(pEnt))
{
AcGePoint3d p1, p2, p3, p4;
pSolid->getPointAt(0, p1);
pSolid->getPointAt(1, p2);
pSolid->getPointAt(2, p3);
pSolid->getPointAt(3, p4);
TCompareEntity *pNew = new TCompareEntity(p1, p2, p3, p4);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pText = AcDbText::cast(pEnt))
{
TCHAR *szText = pText->textString();
CString csText = szText;
delete szText;
AcGePoint3d ptLoc = pText->position();
TCompareEntity *pNew = new TCompareEntity(ptLoc, pText->height(), csText);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else if(pDim = AcDbAlignedDimension::cast(pEnt))
{
TCHAR *szText = pDim->dimensionText();
CString csText = szText;
delete szText;
AcGePoint3d ptLoc = pDim->dimLinePoint();
AcGePoint3d p1 = pDim->xLine1Point();
AcGePoint3d p2 = pDim->xLine2Point();
TCompareEntity *pNew = new TCompareEntity(ptLoc, p1, p2, csText);
pNew->m_id = id;
lstDwg.Append(pNew);
}
else
{
//如果不是以上图元,有可能复杂图元没有完全炸碎,这里简化处理,将他们删除显示
//打印实体类型
//acutPrintf(_T("\n复杂图元:name[%s],dxfName[%s]"), pEnt->isA()->name(), pEnt->isA()->dxfName());
//m_mapOtherEnt[pEnt->isA()->name()]++;
m_mapOtherEnt[pEnt->isA()->dxfName()]++;
pEnt->erase();
}
}
BOOL CCompareDwg::DeepExplodeBlock( AcDbBlockTableRecord *pRec, CDwgCompareDbMgr * pDbMgr, CDataEntityList & dataList, int iColIdx )
{
if (pRec==NULL || pDbMgr==NULL)
{
return FALSE;
}
AcDbBlockTableRecordIterator *pRecIter=NULL;
if(pRec->newIterator(pRecIter)!=Acad::eOk || !pRecIter)
return FALSE;
std::vector< CString > vtlayer;
pDbMgr->GetCmpLayer(vtlayer);
//对块表记录中的对象进行分解
AcDbVoidPtrArray arpNewSet;
AcDbObjectIdArray arrId;
for(pRecIter->start(); !pRecIter->done(); pRecIter->step())
{
AcDbEntity *pEnt=NULL;
Acad::ErrorStatus es = pRecIter->getEntity(pEnt, AcDb::kForWrite);
ASSERT(pEnt);
if(es==Acad::eOk && pEnt != NULL)
{
BOOL bDelete = FALSE;
if (!m_bCmpBlockRef && pEnt->isKindOf(AcDbBlockReference::desc()))
{
//删除块
bDelete = TRUE;
}
else if (!m_bCmpHatch && pEnt->isKindOf(AcDbHatch::desc()))
{
//删除填充
bDelete = TRUE;
}
else
{
//根据图层过滤,炸开后的实体不进行过滤
std::vector< CString >::iterator itrFind = find(vtlayer.begin(), vtlayer.end(), pEnt->layer());
if (itrFind == vtlayer.end())
{
bDelete =TRUE;
}
}
if (bDelete)
{
pEnt->erase();
pEnt->close();
continue;
}
int iRet = ExplodeEntity(pEnt, arpNewSet);
if(iRet == 1)
{
//循环炸碎对象, 如果能分解, 就把该对象删除
AcDbObjectId id = pEnt->objectId();
if ( !id.isNull() )
{
arrId.append(id);
}
//但现在不能删除, 因为自定义实体还有依赖关系. 先存放起来
}
else
{
//计算分块
ProcessEnt(pEnt, iColIdx, dataList);
}
pEnt->close();
}
}
delete pRecIter;
//对块表中的上华对象(复杂对象)进行删除
for(int j=0;j<arrId.length();j++)
{
AcDbEntity *pEnt=NULL;
AcDbObjectId id = arrId[j];
acdbOpenAcDbEntity(pEnt, id, AcDb::kForWrite);
if(pEnt != NULL)
{
pEnt->erase();
pEnt->close();
}
}
//把新对象加入图块记录中,同时计算分块
int idx = arpNewSet.length();
while((--idx) >= 0)
{
AcDbEntity* pNewEnt = (AcDbEntity*)arpNewSet[idx];
if (pNewEnt != NULL)
{
Acad::ErrorStatus es = pRec->appendAcDbEntity(pNewEnt);
VERIFY(es==Acad::eOk);
if (es == Acad::eOk)
{
//计算分块
ProcessEnt(pNewEnt, iColIdx, dataList);
pNewEnt->close();
}
//添加失败则删除临时实体
else
{
delete pNewEnt;
pNewEnt = NULL;
}
}
}
return TRUE;
}
int CCompareDwg::ExplodeEntity( AcDbEntity* pEnt, AcDbVoidPtrArray& arpNewSet )
{
if(pEnt == NULL)
return 0;
/*if(pEnt->isKindOf(AcDbDimension::desc()))
{
return 0;
}*/
if(m_bCmpBlockRef && pEnt->isKindOf(AcDbBlockReference::desc()))
{
//对于图块特殊处理, 因为炸开后, 属性字不能正常显示, 这里新生成一个文字
AcDbBlockReference *pInsert = (AcDbBlockReference *)pEnt;
CreateAttributeText(pInsert, arpNewSet);
}
AcDbVoidPtrArray entSet;
Acad::ErrorStatus es = pEnt->explode(entSet);
if (es == 600)//Acad::eInvalidObjectId sys17
{
//返回-1,如果是炸开后的临时实体直接delete
return -1;
}
int num=entSet.length();
if(num == 0)
{
//不能再炸开, 说明是简单对象, 返回0,如果是炸开后的临时实体则加入数据库
return 0;
}
//块参照内标注位置处理
BOOL bBlkRef = FALSE;
AcGePoint3d ptPosBlkRef;
if(pEnt->isKindOf(AcDbBlockReference::desc()))
{
bBlkRef = TRUE;
ptPosBlkRef = ((AcDbBlockReference *)pEnt)->position();
}
for(int n=0; n<num; n++)
{
AcDbEntity *pNewEnt=(AcDbEntity *)entSet[n];
if(pNewEnt == NULL)
continue;
//不比对块参照和填充
if (!m_bCmpBlockRef && pNewEnt->isKindOf(AcDbBlockReference::desc()))
{
delete pNewEnt;
pNewEnt = NULL;
continue;
}
else if (!m_bCmpHatch && pNewEnt->isKindOf(AcDbHatch::desc()))
{
delete pNewEnt;
pNewEnt = NULL;
continue;
}
//块参照内标注位置处理
if (bBlkRef && pNewEnt->isKindOf(AcDbDimension::desc()))
{
//炸开块后,标注位置根据块位置移动
AcGeMatrix3d mat;
//块相对原点的位移
mat.setToTranslation(ptPosBlkRef-AcGePoint3d(0,0,0));
pNewEnt->transformBy(mat);
// pNewEnt->recordGraphicsModified();
}
int ret = ExplodeEntity(pNewEnt, arpNewSet);
if(ret == 1 || ret == -1)
{
delete pNewEnt; //如果还能删除, delete掉父实体, 不会内存泄漏
pNewEnt = NULL;
}
else
{
arpNewSet.append(pNewEnt);//最末端实体, 直接加入链表
}
}
return 1;
}
BOOL CCompareDwg::CompareCurve( DList<TCompareEntity> &lstDwg1, DList<TCompareEntity> &lstDwg2 )
{
long len=lstDwg1.Length();
long lenLst2=lstDwg2.Length();
//acutPrintf(_T("\n此区域比对:[%d]*[%d]"), len, lenLst2);
if(len > 10000)
{
m_iCountEnt++;
acutPrintf( _T("\n图元数量超过10000个比对速度比较慢,此区域比较数量%ld个..."), len);
/*TCHAR szYes[256];
int ret = ads_getstring(0, _T("\n图纸太大,图元数量超过10000个比对速度会比较慢(推荐使用局部比对命令),是否继续比对?<N>:"), szYes);
if(_tcsicmp(szYes, _T("Y")) != 0)
return FALSE;*/
}
DList<AcDbObjectId> lstDel;
// 7.下面开始比对, 首先把第一张图完全一致的线段置为白色。
long i=0;
for(i=0;i<len;i++)
{
if (lstDwg1[i] == NULL)
{
continue;
}
TCompareEntity curve = *lstDwg1[i];
long len2=lstDwg2.Length();
for(long j=0;j<len2;j++)
{
if (lstDwg2[j] == NULL)
{
continue;
}
TCompareEntity curve2 = *lstDwg2[j];
if(curve == curve2)
{
//首先检查有没有重合的线,已经在删除队列内了
BOOL bFindDeled = FALSE;
long len3 = lstDel.Length();
for(long m=0;m<lstDel.Length();m++)
{
AcDbObjectId idDel = *lstDel[m];
if(curve2.m_id == idDel)
{
bFindDeled = TRUE;
break;
}
}
if(bFindDeled)
continue;//继续比对
OPENOBJ_BEGIN(curve.m_id, AcDb::kForWrite, AcDbEntity, pEnt);
if(pEnt)
{
AcDbAlignedDimension *pDim = NULL;
//修改尺寸的颜色
if(pDim = AcDbAlignedDimension::cast(pEnt))
{
AcCmColor color;
color.setColorIndex(7);
pDim->setDimclre(color);
pDim->setDimclrd(color);
AcDbObjectId idDimRec = pDim->dimBlockId();
//修改尺寸块记录的颜色
AcDbBlockTableRecordIterator *pDimIterator = NULL;
OPENOBJ_BEGIN(idDimRec, AcDb::kForRead, AcDbBlockTableRecord , pRec);
if(pRec)
{
pRec->newIterator(pDimIterator);
}
OPENOBJ_END();
for(pDimIterator->start(); !pDimIterator->done(); pDimIterator->step())
{
AcDbEntity *pEntDim = NULL;
pDimIterator->getEntity(pEntDim, AcDb::kForWrite);
if(pEntDim)
{
pEntDim->setLayer(_T("0"));
pEntDim->setColorIndex(7);
pEntDim->close();
}
}
delete pDimIterator;
}
pEnt->setColorIndex(7);
pEnt->recordGraphicsModified();
}
OPENOBJ_END();
lstDel.Append(new AcDbObjectId(curve2.m_id));
break;
}
}
}
// 8.把第二张图重复的图元删除
for(i=0;i<lstDel.Length();i++)
{
if ( (*lstDel[i]).isNull() )
{
continue;
}
OPENOBJ_BEGIN(*lstDel[i], AcDb::kForWrite, AcDbEntity, pEnt);
if(pEnt)
{
pEnt->erase();
}
OPENOBJ_END();
}
return TRUE;
}
void CCompareDwg::CreateAttributeText( AcDbBlockReference * pInsert, AcDbVoidPtrArray& arpNewSet )
{
if (pInsert == NULL)
{
return;
}
AcDbObjectIterator *pAttrIterator = NULL;
pAttrIterator = pInsert->attributeIterator();
if(pAttrIterator != NULL)
{
for (pAttrIterator->start();!pAttrIterator->done();pAttrIterator->step())
{
AcDbObjectId att_id;
att_id = pAttrIterator->objectId();
AcDbEntity *pEnt2 = NULL;
AcDbAttribute *pAtt = NULL;
acdbOpenAcDbEntity(pEnt2, att_id, AcDb::kForRead);
if(pEnt2 != NULL)
{
pAtt = AcDbAttribute::cast(pEnt2);
if(pAtt && !pAtt->isInvisible()) //不可见不处理
{
AcDbText *pText = new AcDbText;
pText->copyFrom(pAtt);
TCHAR *szText2 = pAtt->textString();
pText->setTextString(szText2);
delete szText2;
szText2 = NULL;
pText->setHorizontalMode(pAtt->horizontalMode());
pText->setVerticalMode(pAtt->verticalMode());
pText->setPosition(pAtt->position());
pText->setAlignmentPoint(pAtt->alignmentPoint());
pText->setTextStyle(pAtt->textStyle());
pText->setHeight(pAtt->height());
arpNewSet.append(pText);
}
pEnt2->close();
}
}
delete pAttrIterator;
}
}
void CCompareDwg::SetExtent()
{
//使用当前图纸外包
m_extBlk.set(acdbCurDwg()->extmin(), acdbCurDwg()->extmax());
//根据外包计算分块单位,对图纸分割
m_dUnitX = ( m_extBlk.maxPoint().x - m_extBlk.minPoint().x ) / m_iCol;
m_dUnitY = ( m_extBlk.maxPoint().y - m_extBlk.minPoint().y ) / m_iRow;
}
void CCompareDwg::SetExtent( const AcDbExtents & ext1, const AcDbExtents & ext2 )
{
if (m_iCmpType == 2)
{
//版本比对使用传进来的外包
m_extBlk = ext1;
m_extBlk.addExt(ext2);
//根据外包计算分块单位,分割选择区域
m_dUnitX = ( m_extBlk.maxPoint().x - m_extBlk.minPoint().x ) / m_iCol;
m_dUnitY = ( m_extBlk.maxPoint().y - m_extBlk.minPoint().y ) / m_iRow;
}
else
{
SetExtent();
}
}
BOOL CCompareDwg::ResetAllLayerStatus()
{
AcDbLayerTable * pLayerTab = NULL;
Acad::ErrorStatus es = acdbCurDwg()->getLayerTable(pLayerTab, AcDb::kForRead);
if (es!=Acad::eOk || pLayerTab==NULL)
{
return FALSE;
}
AcDbLayerTableIterator * pIte = NULL;
es = pLayerTab->newIterator(pIte);
pLayerTab->close();
if (es!=Acad::eOk || pIte==NULL)
{
return FALSE;
}
for (pIte->start(); !pIte->done(); pIte->step())
{
AcDbLayerTableRecord * pLayerRec = NULL;
es = pIte->getRecord(pLayerRec, AcDb::kForWrite);
if (es!=Acad::eOk || pLayerRec==NULL)
{
continue;
}
pLayerRec->setIsOff(false);
pLayerRec->setIsFrozen(false);
pLayerRec->setIsLocked(false);
pLayerRec->close();
}
delete pIte;
return TRUE;
}
void CCompareDwg::PrintInfo()
{
//没有处理的实体类型
std::map<CString, int>::iterator itor= m_mapOtherEnt.begin();
for ( ; itor!=m_mapOtherEnt.end(); itor++)
{
//m_mapOtherEnt[(*itor).first];
acutPrintf(_T("\nName[%s],Count[%d]"), itor->first, itor->second);
}
if (m_iCountEnt>0)
{
acutPrintf(_T("\n第一张图纸中超过10000个实体的区域有[%d]个,建议增加分块数..."), m_iCountEnt);
}
}
int CCompareDwg::GetIndexOfArea( AcDbExtents & extEnt )
{
/*double dX = (extEnt.minPoint().x + extEnt.maxPoint().x) /2 - m_extBlk.minPoint().x;
double dY = (extEnt.minPoint().y + extEnt.maxPoint().y) /2 - m_extBlk.minPoint().y;*/
double dX = extEnt.minPoint().x - m_extBlk.minPoint().x;
double dY = extEnt.minPoint().y - m_extBlk.minPoint().y;
//误差不超过一个分割单位大小
if(dX>-m_dUnitX && dX<1e-15)
{
dX = 0.0;
}
if(dY>-m_dUnitY && dY<1e-15)
{
dY = 0.0;
}
dX /= m_dUnitX;
dY /= m_dUnitY;
int nIndex = (int)(floor(dY) * m_iCol + floor(dX));
return nIndex;
}
int CCompareDwg::GetIndexOfArea( AcDbExtents & extEnt, int iMaxValue )
{
int nIndex = GetIndexOfArea(extEnt);
//放到第一个区域
if (nIndex<0 && nIndex>-m_iCol)
{
nIndex = 0;
}
//超出范围不太多,在误差允许范围
else if (nIndex>=iMaxValue && nIndex<=iMaxValue+m_iCol)
{
nIndex = iMaxValue-1;
}
//超出范围太多不处理
else if (nIndex>iMaxValue+m_iCol || nIndex<-m_iCol)
{
nIndex = -1;
}
return nIndex;
}
void CCompareDwg::WriteLogFile( double dTimeSecond )
{
//比对记录
//CString g_csLogFile = _T("C:\\DwgCompare_LogFile_图纸比对记录.txt");
CStdioFile file;
CFileFind find;
if (find.FindFile(g_csLogFile))
{
if (!file.Open(g_csLogFile, CFile::modeWrite))
{
return;
}
}
else
{
if (!file.Open(g_csLogFile,CFile::modeCreate | CFile::modeWrite))
{
return;
}
}
CString csLog = _T("");
CString csTemp = _T("\r\nBegin**********************");
csLog += csTemp;
SYSTEMTIME t;
GetLocalTime(&t);
csTemp.Format(_T("[%d-%d-%d %d:%d:%d:%d]"), t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
csLog += csTemp;
csTemp.Format(_T("\r\n分块比对时间:%lf秒"), dTimeSecond);
csLog += csTemp;
csTemp.Format(_T("\r\n行数:%d, 列数:%d"), m_iCol, m_iRow);
csLog += csTemp;
csTemp.Format(_T("\r\n块:%d, 填充:%d, 外部参照:%d"), m_bCmpBlockRef, m_bCmpHatch, m_bCmpXref);
csLog += csTemp;
csTemp = _T("\r\nEnd**********************");
csLog += csTemp;
file.SeekToEnd();
file.WriteString(csLog);
file.Close();
}
void CCompareDwg::WriteLogFile( double dTimeSecond, CString csInfo )
{
//比对记录
//CString g_csLogFile = _T("C:\\DwgCompare_LogFile_图纸比对记录.txt");
CStdioFile file;
CFileFind find;
if (find.FindFile(g_csLogFile))
{
if (!file.Open(g_csLogFile, CFile::modeWrite))
{
return;
}
}
else
{
if (!file.Open(g_csLogFile,CFile::modeCreate | CFile::modeWrite))
{
return;
}
}
CString csLog = _T("");
CString csTemp = _T("\r\nBegin**********************");
csLog += csTemp;
SYSTEMTIME t;
GetLocalTime(&t);
csTemp.Format(_T("[%d-%d-%d %d:%d:%d:%d]"), t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
csLog += csTemp;
csLog += csInfo;
csTemp = _T("\r\nEnd**********************");
csLog += csTemp;
file.SeekToEnd();
file.WriteString(csLog);
file.Close();
}
//////////////////////////////////////////////////////////////////////////
//class CComparePartOfDwg
CComparePartOfDwg::CComparePartOfDwg( void )
{
}
CComparePartOfDwg::~CComparePartOfDwg( void )
{
}
BOOL CComparePartOfDwg::DoComparePartOfFile(Entity ent, CString & csPath)
{
csPath.Empty();
//选取另一个文件
CAcModuleResourceOverride vTemp;
CString csFileName2;
CFileDialog dlg(TRUE,_T("*.dwg"),csFileName2,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("Drawing(*.dwg) |*.dwg||"), acedGetAcadFrame());
TCHAR strDlgTitle[] = _T("选择要比对的DWG文件");
dlg.m_ofn.lpstrTitle = strDlgTitle;
if(dlg.DoModal()!=IDOK)
{
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
XPoly2D poly(ent);
PickSet ss(SS_FREE);
poly.TransUCS(Groups(0), Groups(1));//Groups(0) wcs, Groups(1) ucs
RBList rbFence = poly.Fence();
XPoint ptLow3, ptUp3;
poly.GetExtend(ptLow3, ptUp3);
Acad::ErrorStatus es = AssureInCurrentView(ptLow3, ptUp3);
ss.Get(_T("CP"), rbFence, NULL, RBList());
ss-= ent;
AcDbObjectIdArray aryObj;
ss.AsIdArray(aryObj);
if (aryObj.length()<1)
{
return FALSE;
}
clock_t startTime, finishTime; //计时
double duration1, duration2;
startTime = clock();
//导出多段线内的实体
CString csFilePath1;
csFilePath1 = acDocManager->curDocument()->fileName();
CDwgCompareDbMgr mgr1;
AcDbDatabase * pDbCur = acdbCurDwg();
if (!mgr1.LoadDb(csFilePath1, pDbCur, aryObj, AcGePoint3d(0,0,0)))
//if (!mgr1.LoadFile(csFilePath1, csFilePath1, poly))
{
return FALSE;
}
finishTime = clock();
duration1 = (double)(finishTime - startTime) / CLOCKS_PER_SEC;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
startTime = clock();
//读取另一个文件
CDwgCompareDbMgr mgr2;
if (!mgr2.LoadFile(dlg.GetFileName(), dlg.GetPathName(), poly))
{
return FALSE;
}
finishTime = clock();
duration2 = (double)(finishTime - startTime) / CLOCKS_PER_SEC;
//////////////////////////////////////////////////////////////////////////
CDwgCompareDlg dlgCmp(&mgr1, &mgr2, 1);
if(dlgCmp.DoModal() == IDOK)
{
clock_t startTimeG, finishTimeG; //计时
double durationG;
startTimeG = clock();
PickSet ssNew(SS_FREE);
ssNew.IncludeBegin();
m_bCmpBlockRef = dlgCmp.m_bCmpBlock; //设置是否比对块
m_bCmpHatch = dlgCmp.m_bCmpHatch; //设置是否比对填充
m_bCmpXref = dlgCmp.m_bCmpXref; //设置是否比对外部参照
m_iRow = dlgCmp.m_iRowCount; //设置分块行列数
m_iCol = dlgCmp.m_iColumnCount;
DoCompareFile(&mgr1, &mgr2);
ssNew.IncludeEnd();
XPoint ptIns;
TCHAR dwgPrefix[256]=_T("");
GetTempPath(255, dwgPrefix);
if(dwgPrefix[_tcslen(dwgPrefix)-1]!=_T('\\'))
_tcscat(dwgPrefix, _T("\\"));
CString csTempFile;
csTempFile.Format(_T("%sCompareDwg.dwg"), dwgPrefix);
if(FindFile(csTempFile))
{
if (!DeleteFile(csTempFile))
{
return FALSE;
}
}
// 将对比的结果导出到一个临时文件中
BOOL ret = arxWBlock(ssNew, csTempFile, ptIns);
//错误说明:由于把结果文件CompareDwg.dwg置为了当前窗口, 所以在不切换窗口的情况下, 原图的内容和结果图一样
//解决方法:把删除原图的所有相关记录的代码提前到打开结果图代码前
//修改人、修改时间 LLJ 2010-02-05
// 删除本图所有相关记录
ssNew.Erase();
ads_command(RTSTR, _T(".PURGE"), RTSTR, _T("ALL"), RTSTR, _T(""), RTSTR, _T("N"), NULL);
/*if(ret != 0)
{
AcApDocument* pDoc = acDocManager->curDocument();
acDocManager->lockDocument(pDoc);
acDocManager->executeInApplicationContext(OpenDwgFile, (void *)(const TCHAR *)csTempFile);
acDocManager->unlockDocument(pDoc);
}*/
if(ret != 0)
{
csPath = csTempFile;
}
finishTimeG = clock();
durationG = (double)(finishTimeG - startTimeG) / CLOCKS_PER_SEC;
CString csTemp;
csTemp.Format(_T("\n局部比对文件1加载用时:%lf秒..\n[%s]"), duration1, mgr1.GetFilePath());
acutPrintf(csTemp);
//WriteLogFile(duration1, csTemp);
csTemp.Format(_T("\n局部比对文件2加载用时:%lf秒..\n[%s]"), duration2, mgr2.GetFilePath());
acutPrintf(csTemp);
//WriteLogFile(duration2, csTemp);
acutPrintf(_T("\n局部比对用时:%lf秒.."), durationG);
//WriteLogFile(durationG);//比对信息写入记录文件
}
return TRUE;
}
int CComparePartOfDwg::GetIndexOfArea( AcDbExtents & extEnt, int iMaxValue )
{
double dX = extEnt.minPoint().x - m_extBlk.minPoint().x;
double dY = extEnt.minPoint().y - m_extBlk.minPoint().y;
//局部比对精确计算
if(dX>-1 && dX<1e-15)
{
dX = 0.0;
}
if(dY>-1 && dY<1e-15)
{
dY = 0.0;
}
dX /= m_dUnitX;
dY /= m_dUnitY;
int nIndex = (int)(floor(dY) * m_iCol + floor(dX));
if (nIndex>=iMaxValue && nIndex<=iMaxValue+m_iCol)
{
nIndex = iMaxValue-1;
}
return nIndex;
}
void CComparePartOfDwg::SetExtent( const AcDbExtents & ext1, const AcDbExtents & ext2 )
{
//局部比对使用传进来的外包
m_extBlk = ext1;
m_extBlk.addExt(ext2);
//根据外包计算分块单位,分割选择区域
m_dUnitX = ( m_extBlk.maxPoint().x - m_extBlk.minPoint().x ) / m_iCol;
m_dUnitY = ( m_extBlk.maxPoint().y - m_extBlk.minPoint().y ) / m_iRow;
}