////////////////////////////////////////////////////////////////////// /******************************************************************** 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 #include //#include "xacgi.h" //#include "arxtools.h" //#include "Xgcom.h" //#include "findfile.h" #include "CompareDwg.h" #include "DwgCompareDlg.h" #include #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); } } CDataEntityList::~CDataEntityList() { for (int n=0; n* p = m_dataDList[n]; if (p != NULL) { delete p; p = NULL; } } m_dataDList.clear(); } int CDataEntityList::Length() const { return (int)m_dataDList.size(); } DList& 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 &lstArea1 = dataList1[i]; DList &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 &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 &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;jerase(); 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; nisKindOf(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 &lstDwg1, DList &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个比对速度会比较慢(推荐使用局部比对命令),是否继续比对?:"), szYes); if(_tcsicmp(szYes, _T("Y")) != 0) return FALSE;*/ } DList lstDel; // 7.下面开始比对, 首先把第一张图完全一致的线段置为白色。 long i=0; for(i=0;isetDimclre(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;ierase(); } 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::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; }