Teigha 内核:OdGsView 交互模式

简介

交互模式是 Teigha 图形系统的一项新功能。如果绘图过程耗时过长,它允许自动中断绘图过程。当然,在这种情况下,绘图不会完全完成,但此功能对于多次连续重绘非常有用,因为中间重绘的结果并不那么重要。

使用交互模式

交互模式通过 OdGsView API 控制。但是,如果相应的设备不支持此模式,则此模式无效。OdGsBaseVectorizeDevice 的以下方法检查设备是否支持此模式:

bool supportInteractiveViewMode() const;

此外,OdGsBaseVectorizeDevice 有一个方法允许您手动更改交互模式的支持:

void setSupportInteractiveViewMode( bool );

OdGsView API 为交互模式提供了以下方法:

  • virtual void beginInteractivityMode( double frameRateInHz )

    此方法启用视图交互模式。frameRateInHz 指定所需的帧速率 (FPS)。此值定义了每秒所需的最小帧数。换句话说,如果您想限制每次重绘操作所需的时间(例如,“不超过 X 秒”),frameRateInHz 应该是此时间限制的倒数比率 (1 / X)。

  • virtual bool isInInteractivity() const

    如果此视图处于交互模式,则返回 true。

  • virtual double interactivityFrameRate() const

    返回在 beginInteractivityMode() 中指定的所需帧速率。

  • virtual void endInteractivity()

    此方法禁用视图交互模式。

实现细节

当视图处于交互模式时,每次调用 OdGsBaseVectorizer::beginViewVectorization(通常来自 OdGsDevice::update())时,都会启动一个特殊计时器,该计时器将在 OdGsBaseVectorizer::endViewVectorization 中停止。每次对 OdGsBaseVectorizer::renderAbort 的请求都会检查此计时器。如果经过的时间超过 1 / interactivityFrameRate(),OdGsBaseVectorizer::renderAbort() 将返回 true,并且渲染循环将被中断。

交互模式有一些限制:

  • 由于此模式基于 OdGsBaseVectorizer::renderAbort(),如果设备不支持 renderAbort() 功能,则此模式无效。
  • 由于此模式在 OdGsNode 级别工作,如果绘图只包含少量大型(绘制时间长)节点(例如外部参照),则可能没有视觉效果。
  • 有时渲染循环无法通过 renderAbort() 中断,只能被抑制。在这种情况下,交互模式仍然有效,但最终帧速率可能与预设值不同。

目前 Teigha 支持以下设备的交互模式:WinGDI、WinDirectX 和 WinOpenGL。

示例

OdaMfcApp 示例应用程序将交互模式用于 Orbit 命令。控制台命令“interactivity”允许您禁用或启用此模式并更改所需的帧速率:

image1

交互模式的用法可以在 TD_DrawingExamplesCommon 的 EditorObject.cpp 中找到。我们使用一个辅助类来启用和禁用交互模式:

class ViewInteractivityMode
{
  bool      m_enabled;
  OdGsView* m_pView;
public:
  ViewInteractivityMode( OdRxVariantValue enable, OdRxVariantValue frameRate, OdGsView* pView )
  {
    m_enabled = false;
    m_pView = pView;
    if( !enable.isNull() )
    {
      m_enabled = (bool)(enable);
      if( m_enabled && !frameRate.isNull() )
      {
        double rate = (double)(( (frameRate.get())->getDouble() ));
        pView->beginInteractivity( rate );
      }
    }
  }
  ~ViewInteractivityMode()
  {
    if( m_enabled ) m_pView->endInteractivity();
  }
};

ViewInteractivityMode 的构造函数启用(如果需要)交互模式,析构函数禁用它。

函数 OdEx3dOrbitCmd::execute 在进入事件循环之前创建 ViewInteractivityMode 的实例:

void OdEx3dOrbitCmd::execute(OdEdCommandContext* pCmdCtx)
{
  OdDbCommandContextPtr pDbCmdCtx(pCmdCtx);
  OdDbDatabasePtr pDb = pDbCmdCtx->database();
  OdSmartPtr<OdDbUserIO> pIO = pDbCmdCtx->userIO();
  
  OdDbObjectPtr pVpObj = pDb->activeViewportId().safeOpenObject(OdDb::kForWrite);
  OdDbAbstractViewportDataPtr pAVD(pVpObj);

  OdGsView* pView = pAVD->gsView(pVpObj);  

  // There is one special case: layout with enabled 'draw viewports first' mode
  {
    if (!pDb->getTILEMODE())
    {
      OdDbLayoutPtr pLayout = pDb->currentLayoutId().openObject();
      if (pLayout->drawViewportsFirst())
      {
        if (pView->device()->viewAt(pView->device()->numViews() - 1) == pView)
          pView = pView->device()->viewAt(0);
      }
    }
  }
  //

  OdRxVariantValue interactiveMode = (OdRxVariantValue)pCmdCtx->arbitraryData( OD_T("OdaMfcApp InteractiveMode" ) );
  OdRxVariantValue interactiveFrameRate = (OdRxVariantValue)pCmdCtx->arbitraryData( OD_T("OdaMfcApp InteractiveFrameRate" ) );
  ViewInteractivityMode mode( interactiveMode, interactiveFrameRate, pView );

  OdStaticRxObject<RTOrbitTracker> tracker;
  for(;;)
  {
    try
    {
      tracker.init(pView, pIO->getPoint(OD_T("Press ESC or ENTER to exit."),
        OdEd::kInpThrowEmpty|OdEd::kGptNoUCS|OdEd::kGptNoOSnap|OdEd::kGptBeginDrag, 0, OdString::kEmpty, &tracker));
      pIO->getPoint(OD_T("Press ESC or ENTER to exit."),
        OdEd::kInpThrowEmpty|OdEd::kGptNoUCS|OdEd::kGptNoOSnap|OdEd::kGptEndDrag, 0, OdString::kEmpty, &tracker);
      tracker.reset();
    }
    catch(const OdEdCancel)
    {
      break;
    }
  }
}

当函数结束时,ViewInteractivityMode 的实例会自动删除,这将调用 OdGsView::endInteractivity()。

下面是一些示例。在第一个示例中,帧速率足够小,因此在执行 Orbit 命令时会显示所有实体:

image2

此处帧速率增加,因此绘图的某些部分消失了:

image3

此处帧速率再次增加,因此只显示了原始实体中的少数几个:

image4

 

今天就开始行动

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

免费试用