将 OdDb 几何体和 SAT 数据转换为 DirectShape

本文解释了如何将基于 B-Rep(例如 OdDb3dSolid、OdDbRegion 等)的 OdDb 实体和 SAT 数据转换为 BimRv DirectShape 实体。

与任何其他转换一样,此转换使用 OdBrepBuilderFiller 执行。然而,OdDb 实体拓扑与 DirectShape 实体非常不同。DirectShape 不允许周期性面和边,因此像完整球体或完整圆这样的实体是不可能的。此外,OdDb 拓扑可以有分离循环,因此没有接缝边,需要复杂的修复。转换通过中间转换为 ODA Solid Modeler 的 OdMdBody 来执行。OdMdBody 在 OdDb 和 DirectShape 之间存在限制;虽然它允许周期性面和边,但它禁止分离循环并要求接缝边。

颜色和材质转换

DirectShape 没有颜色,而是使用材质。OdDb 面材质目前不支持,但面颜色支持 RGB 和颜色索引。要转换它们,请将 OdBaseMaterialAndColorHelper 的实例传递给 OdBrepBuilderFiller。您可以使用 OdDb2BmMaterialAndColorHelper 将实体从 .dwg 文件转换为 OdMdBody,并从 OdMdBody 转换为 DirectShape。如果您使用 SAT 数据,可以使用 OdSat2MdForBmMaterialAndColorHelper 和 OdMd2BmFromSatMaterialAndColorHelper 分别将 SAT 转换为 OdMdBody,以及将 OdMdBody 转换为 DirectShape。面颜色会原样转换为 OdMdBody。DirectShape 会创建一个带有此颜色的新材质。输入实体颜色直接传递给 DirectShape,绕过 OdMdBody。

算法

以下部分包含一个转换为 DirectShape 的示例。

  1. 从输入文件获取 OdBrBrep。
    对于 .dwg 文件,使用 brep() 方法:
    OdDbDatabasePtr pDwgDb = pHostApp->readFile(fileName);
    OdDbBlockTableRecordPtr pMs = pDwgDb->getModelSpaceId().safeOpenObject(OdDb::kForWrite);
    for (OdDbObjectIteratorPtr pObjIt = pMs->newIterator(); !pObjIt->done(); pObjIt->step())
    {
      OdDbEntityPtr inputEntity = pObjIt->entity();
      if (!inputEntity.isNull())
      {
        OdBrBrep brep;
        BrepType bType = kOpenShell;
        if (inputEntity->isA() == OdDbRegion::desc())
        {
          OdDbRegionPtr pBody = inputEntity;
          pBody->brep(brep);
        }
        /*other geometry types of OdDbEntity*/
    
        /*conversion*/
      }
    }
    对于 SAT 文件,使用 acisIn() 方法获取 OdDbEntity 或使用 ISATConverter:
    for (unsigned idx = 0; idx < out.size(); ++idx)
    {
      OdBrBrep brep;
      ISATConverter* pIS = out[idx];
      brep.set(pIS->getIBr());
      /*conversion*/
    }
  2. 使用 OdBrepBuilderFiller 将 OdBrBrep 转换为 OdMdBody:
    OdBrepBuilder mdBrepBuilder;
    std::unique_ptr attribSetter(createDwgAttribSetter());
    initMDBrepBuilder(mdBrepBuilder, bType, attribSetter.get());
    
    OdGeMatrix3d mx;
    bool hasTransform = brep.getTransformation(mx);
    
    OdBrepBuilderFiller BBFiller;
    BBFiller.params().setupFor(OdBrepBuilderFillerParams::kBrepAcisDwg, OdBrepBuilderFillerParams::kBrepMd);
    OdResult res = BBFiller.initFrom(mdBrepBuilder, brep);
    if (res == eOk)
    {
      mdBrepBuilder.enableValidator(false);
      OdMdBodyResultPtr pMdBody;
      try
      {
        pMdBody = OdMdBodyResult::cast(mdBrepBuilder.finish());
      }
      catch (...)
      {
        res = eGeneralModelingFailure;
      }
    }
  3. 将 OdMdBody 中的拓扑更改为 BimRv 格式并获取新的 OdBrBrep:
    OdBrBrep mdBrep;
    if (eOk == res && !pMdBody.isNull())
    {
      if (hasTransform)
        res = transformMdBody(pMdBody, mx);
      if (eOk == res)
      {
        res = convertToBimRvFormat(pMdBody);
        if (eOk == res)
        {
          res = getBrepFromMdBody(pMdBody, mdBrep);
        }
      }
    }
  4. 将 OdBrBrep 转换为 DirectShape 并将其添加到 BimRv 数据库:
    OdBrepBuilder bmBrepBuilder;
    res = pBmDb->appServices()->brepBuilder(bmBrepBuilder, bType);
    if (res == eOk)
    {
      BBFiller.params().setupFor(OdBrepBuilderFillerParams::kBrepAcisDwg, pDwgDb, pBmDb);
      res = BBFiller.initFrom(bmBrepBuilder, mdBrep, bmMaterialHelper);
      if (res == eOk)
      {
        try
        {
          OdBmGeometryPtr resultGeometry = OdBmGeometry::cast(bmBrepBuilder.finish());
          if (!resultGeometry.isNull())
          {
            OdArray aFaces;
            resultGeometry->getFaces(aFaces);
            OdArray aEdges;
            resultGeometry->getEdges(aEdges);
            if (aFaces.size() != 0 || aEdges.size() != 0) 
            {
              ODBM_TRANSACTION_BEGIN(t, pBmDb)
                t.start();
                 OdBmGNodePtrArray nodes;
                nodes.append(resultGeometry);
                OdBmDirectShapePtr pDirectShape = OdBmDirectShape::createObject();
                OdBmObjectId retId = pBmDb->addElement(pDirectShape);
                pDirectShape->setOwningElementId(pBmDb->getOwnerFamilyId());
                res = pDirectShape->setShape(nodes);
                t.commit();
              ODBM_TRANSACTION_END()
            }
          }
        }
        catch (...)
        {
          res = eGeneralModelingFailure;
        }
      }
    }

示例

您可以在 DwgDirectShapeImportEx 和 SatDirectShapeImportEx 示例中找到示例,这些示例随存档提供,可在 CommonApplications/BimRv 目录中找到。这些示例包含将基于 .dwg 文件中的 B-Rep 实体或 SAT 文件中的 SAT 数据的 OdDb 实体转换为 RVT 或 RFA 文件中的 DirectShape 的代码。它们需要一个空的 RFA 或 RVT 文件来获取 BimRv 的输入数据库。

今天就开始行动

免费试用 ODA 软件 60 天。
无风险,无需信用卡。

免费试用