admin 发表于 2024-3-14 20:12:14

[每日一码] 查找多个AcDbLine的所有交点

// These are template classes to allow AcGePoint3d do be used as a Key do CMap class
const double 采用dTol = 0.0001;

template<> UINT AFXAPI HashKey<AcGePoint3d> (AcGePoint3d key)
{
      CString sPoint;
      sPoint.Format(采用T("%f,%f,%f"),key.x, key.y ,key.z);

      UINT iHash = (NULL == &key) ? 0 : HashKey((LPCSTR)sPoint.GetBuffer());
      return iHash;
}

template<> BOOL AFXAPI CompareElements<AcGePoint3d, AcGePoint3d>
(const AcGePoint3d* pElement1, const AcGePoint3d* pElement2)
{
      if ((pElement1 == NULL) || (pElement2 == NULL))
                return false;

      AcGeTol gTol;
      gTol.setEqualPoint(采用dTol); // Point comparison tolerance
      return (pElement1->isEqualTo(*pElement2,gTol));
}


Next, we will collect the AcDbLine entities in ModelSpace:

普通浏览复制代码
// Collect lines from ModelSpace
Acad::ErrorStatus es;
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecordPointer pBTR(acdbSymUtil()->blockModelSpaceId(pDb),AcDb::kForWrite);

AcDbBlockTableRecordIterator *pIter = NULL;
pBTR->newIterator(pIter, true);
AcDbObjectIdArray arrLines;

while(!pIter->done())
{
      AcDbEntity *pEnt = NULL;
      es = pIter->getEntity(pEnt, AcDb::kForRead);
      if (es == Acad::eOk)
      {
                if (pEnt->isKindOf(AcDbLine::desc()))
                        arrLines.append(pEnt->objectId());

                pEnt->close();
      }

      pIter->step(true);
}
delete pIter;
pIter = NULL;

if (arrLines.length() == 0)
{
      acutPrintf(采用T("There are no lines in Model Space!\n"));
      return;
}
else
{
      acutPrintf(采用T("We've found %d lines in Model Space!\nChecking intersection with tolerance %f...\n"),
                arrLines.length(), 采用dTol);
}


Ok, with the lines collected we will then build our CMap with the information we need:

普通浏览复制代码
// Process lines in pairs
CMap<AcGePoint3d,AcGePoint3d,AcDbObjectIdArray,AcDbObjectIdArray&> mapLines;

acdbTransactionManager->startTransaction();
for (int i=0; i<arrLines.length()-1; i++)
{
      AcDbLine* pLineA = NULL;
      if (acdbTransactionManager->getObject((AcDbObject*&)pLineA,arrLines<i>, AcDb::kForRead) == Acad::eOk)
      {
                for (int j=i+1; j<arrLines.length(); j++)
                {
                        AcDbLine* pLineB = NULL;
                        if (acdbTransactionManager->getObject((AcDbObject*&)pLineB,arrLines, AcDb::kForRead) == Acad::eOk)
                        {
                              AcGePoint3dArray arrPts;
                              if (pLineA->intersectWith(pLineB,AcDb::kOnBothOperands,arrPts) == Acad::eOk)
                              {
                                        if (arrPts.length() > 0)
                                        {
                                                for (int p=0; p<arrPts.length(); p++)
                                                {
                                                      AcDbObjectIdArray arrExist;
                                                      if (mapLines.Lookup(arrPts,arrExist) == TRUE)
                                                      {
                                                                // Existing point...
                                                                if (arrExist.contains(pLineA->objectId()) == false)
                                                                        mapLines].append(pLineA->objectId());

                                                                if (arrExist.contains(pLineB->objectId()) == false)
                                                                        mapLines].append(pLineB->objectId());
                                                      }
                                                      else
                                                      {
                                                                // New point...
                                                                AcDbObjectIdArray arrNewEnts;
                                                                arrNewEnts.append(pLineA->objectId());
                                                                arrNewEnts.append(pLineB->objectId());
                                                                mapLines.SetAt(arrPts,arrNewEnts);
                                                      }
                                                }
                                        }
                              }
                        }
                }
      }
}

acdbTransactionManager->endTransaction();


To demonstrate the use of this information, we then use our CMap data to create AcDbPoint entities on ModeSpace and also print a small report at the command prompt:

普通浏览复制代码
// Just as demonstration, walk through points and add an AcDbPoint entity to ModelSpace then print the info
POSITION pos = mapLines.GetStartPosition();
while (pos)
{
      AcGePoint3d ptKey(0,0,0);
      AcDbObjectIdArray arrEnts;
      mapLines.GetNextAssoc(pos,ptKey, arrEnts);

      AcDbPoint* ptEnt = new AcDbPoint(ptKey);
      AcDbObjectId idPointEnt;
      pBTR->appendAcDbEntity(idPointEnt,ptEnt);
      ptEnt->close();

      CString sEnts;
      for (int e=0; e<arrEnts.length(); e++)
      {
                ACHAR pBuff = 采用T("");
                arrEnts.handle().getIntoAsciiBuffer(pBuff);
                CString sBuff;
                sBuff.Format( (e==arrEnts.length()-1) ? 采用T("%s"): 采用T("%s,"), pBuff);
                sEnts += sBuff;
      }

      CString sPromptReport;
      sPromptReport.Format(采用T("Point (%.4f, %.4f, %.4f) - Entities [%s]\n"),ptKey.x, ptKey.y, ptKey.z, sEnts);
      acutPrintf(sPromptReport);
}
页: [1]
查看完整版本: [每日一码] 查找多个AcDbLine的所有交点