<commit_before>/*=========================================================================

Program:   BlueBerry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "berryHelpPluginActivator.h"

#include "berryHelpContentView.h"
#include "berryHelpIndexView.h"
#include "berryHelpSearchView.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpPerspective.h"

#include "berryQHelpEngineConfiguration.h"
#include "berryQHelpEngineWrapper.h"

#include <berryPlatformUI.h>

#include <service/event/ctkEventConstants.h>

#include <QtPlugin>
#include <QDir>
#include <QDateTime>

namespace berry {

class HelpPerspectiveListener : public IPerspectiveListener
{
public:

  Events::Types GetPerspectiveEventTypes() const;

  void PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective);
  void PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId);
};

class HelpWindowListener : public IWindowListener
{
public:

  HelpWindowListener();
  ~HelpWindowListener();

  void WindowClosed(IWorkbenchWindow::Pointer window);
  void WindowOpened(IWorkbenchWindow::Pointer window);

private:

  // We use the same perspective listener for every window
  IPerspectiveListener::Pointer perspListener;
};

HelpPluginActivator* HelpPluginActivator::instance = 0;

HelpPluginActivator::HelpPluginActivator()
  : pluginListener(0)
{
  this->instance = this;
}

HelpPluginActivator::~HelpPluginActivator()
{
  instance = 0;
}

void
HelpPluginActivator::start(ctkPluginContext* context)
{
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpContentView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpIndexView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpSearchView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpEditor, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpPerspective, context)

  QFileInfo qhcInfo = context->getDataFile("qthelpcollection.qhc");
  helpEngine.reset(new QHelpEngineWrapper(qhcInfo.absoluteFilePath()));
  if (!helpEngine->setupData())
  {
    BERRY_ERROR << "QHelpEngine set-up failed: " << helpEngine->error().toStdString();
    return;
  }

  helpEngineConfiguration.reset(new QHelpEngineConfiguration(context, *helpEngine.data()));

  delete pluginListener;
  pluginListener = new QCHPluginListener(context, helpEngine.data());
  context->connectPluginListener(pluginListener, SLOT(pluginChanged(ctkPluginEvent)));

  // register all QCH files from all the currently installed plugins
  pluginListener->processPlugins();

  helpEngine->initialDocSetupDone();

  // Register a wnd listener which registers a perspective listener for each
  // new window. The perspective listener opens the help home page in the window
  // if no other help page is opened yet.
  wndListener = IWindowListener::Pointer(new HelpWindowListener());
  PlatformUI::GetWorkbench()->AddWindowListener(wndListener);

  // Register an event handler for CONTEXTHELP_REQUESTED events
  helpContextHandler.reset(new HelpContextHandler);
  ctkDictionary helpHandlerProps;
  helpHandlerProps.insert(ctkEventConstants::EVENT_TOPIC, "org/blueberry/ui/help/CONTEXTHELP_REQUESTED");
  context->registerService<ctkEventHandler>(helpContextHandler.data(), helpHandlerProps);
}

void
HelpPluginActivator::stop(ctkPluginContext* /*context*/)
{
  delete pluginListener;
  pluginListener = 0;

  if (PlatformUI::IsWorkbenchRunning())
  {
    PlatformUI::GetWorkbench()->RemoveWindowListener(wndListener);
  }
  wndListener = 0;
}

HelpPluginActivator *HelpPluginActivator::getInstance()
{
  return instance;
}

QHelpEngineWrapper& HelpPluginActivator::getQHelpEngine()
{
  return *helpEngine;
}

void HelpPluginActivator::linkActivated(IWorkbenchPage::Pointer page, const QUrl &link)
{
  IEditorInput::Pointer input(new HelpEditorInput(link));

  // see if an editor with the same input is already open
  IEditorPart::Pointer reuseEditor = page->FindEditor(input);
  if (reuseEditor)
  {
    // just activate it
    page->Activate(reuseEditor);
  }
  else
  {
    // reuse the currently active editor, if it is a HelpEditor
    reuseEditor = page->GetActiveEditor();
    if (reuseEditor.IsNotNull() && page->GetReference(reuseEditor)->GetId() == HelpEditor::EDITOR_ID)
    {
      page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
      page->Activate(reuseEditor);
    }
    else
    {
      // get the last used HelpEditor instance
      std::vector<IEditorReference::Pointer> editors =
          page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID);
      if (editors.empty())
      {
        // no HelpEditor is currently open, create a new one
        page->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
      else
      {
        // reuse an existing editor
        reuseEditor = editors.front()->GetEditor(false);
        page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
        page->Activate(reuseEditor);
      }
    }
  }
}

QCHPluginListener::QCHPluginListener(ctkPluginContext* context, QHelpEngine* helpEngine)
  : delayRegistration(true), context(context), helpEngine(helpEngine)
{}

void QCHPluginListener::processPlugins()
{
  QMutexLocker lock(&mutex);
  processPlugins_unlocked();
}

void QCHPluginListener::pluginChanged(const ctkPluginEvent& event)
{
  QMutexLocker lock(&mutex);
  if (delayRegistration)
  {
    this->processPlugins_unlocked();
    return;
  }

  /* Only should listen for RESOLVED and UNRESOLVED events.
   *
   * When a plugin is updated the Framework will publish an UNRESOLVED and
   * then a RESOLVED event which should cause the plugin to be removed
   * and then added back into the registry.
   *
   * When a plugin is uninstalled the Framework should publish an UNRESOLVED
   * event and then an UNINSTALLED event so the plugin will have been removed
   * by the UNRESOLVED event before the UNINSTALLED event is published.
   */
  QSharedPointer<ctkPlugin> plugin = event.getPlugin();
  switch (event.getType())
  {
    case ctkPluginEvent::RESOLVED :
      addPlugin(plugin);
      break;
    case ctkPluginEvent::UNRESOLVED :
      removePlugin(plugin);
      break;
  }
}

void QCHPluginListener::processPlugins_unlocked()
{
  if (!delayRegistration) return;

  foreach (QSharedPointer<ctkPlugin> plugin, context->getPlugins())
  {
    if (isPluginResolved(plugin))
      addPlugin(plugin);
    else
      removePlugin(plugin);
  }

  delayRegistration = false;
}

bool QCHPluginListener::isPluginResolved(QSharedPointer<ctkPlugin> plugin)
{
  return (plugin->getState() & (ctkPlugin::RESOLVED | ctkPlugin::ACTIVE | ctkPlugin::STARTING | ctkPlugin::STOPPING)) != 0;
}

void QCHPluginListener::removePlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  if (qchDirInfo.exists())
  {
    QDir qchDir(qchDirInfo.absoluteFilePath());
    QStringList qchEntries = qchDir.entryList(QStringList("*.qch"));
    QStringList qchFiles;
    foreach(QString qchEntry, qchEntries)
    {
      qchFiles << qchDir.absoluteFilePath(qchEntry);
    }
    // unregister the cached qch files
    foreach(QString qchFile, qchFiles)
    {
      QString namespaceName = QHelpEngineCore::namespaceName(qchFile);
      if (namespaceName.isEmpty())
      {
        BERRY_ERROR << "Could not get the namespace for qch file " << qchFile.toStdString();
        continue;
      }
      else
      {
        if (!helpEngine->unregisterDocumentation(namespaceName))
        {
          BERRY_ERROR << "Unregistering qch namespace " << namespaceName.toStdString() << " failed: " << helpEngine->error().toStdString();
        }
      }
    }
    // clean the directory
    foreach(QString qchEntry, qchEntries)
    {
      qchDir.remove(qchEntry);
    }
  }
}

void QCHPluginListener::addPlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  QUrl location(plugin->getLocation());
  QFileInfo pluginFileInfo(location.toLocalFile());

  if (!qchDirInfo.exists() || qchDirInfo.lastModified() < pluginFileInfo.lastModified())
  {
    removePlugin(plugin);

    if (!qchDirInfo.exists())
    {
      QDir().mkpath(qchDirInfo.absoluteFilePath());
    }

    QStringList localQCHFiles;
    QStringList resourceList = plugin->findResources("/", "*.qch", true);
    foreach(QString resource, resourceList)
    {
      QByteArray content = plugin->getResource(resource);
      QFile localFile(qchDirInfo.absoluteFilePath() + "/" + resource.section('/', -1));
      localFile.open(QIODevice::WriteOnly);
      localFile.write(content);
      localFile.close();
      if (localFile.error() != QFile::NoError)
      {
        BERRY_WARN << "Error writing " << localFile.fileName().toStdString()
                   << ": " << localFile.errorString().toStdString();
      }
      else
      {
        localQCHFiles << localFile.fileName();
      }
    }

    foreach(QString qchFile, localQCHFiles)
    {
      if (!helpEngine->registerDocumentation(qchFile))
      {
        BERRY_ERROR << "Registering qch file " << qchFile.toStdString() << " failed: " << helpEngine->error().toStdString();
      }
    }
  }

}

IPerspectiveListener::Events::Types HelpPerspectiveListener::GetPerspectiveEventTypes() const
{
  return Events::OPENED | Events::CHANGED;
}

void HelpPerspectiveListener::PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective)
{
  // if no help editor is opened, open one showing the home page
  if (perspective->GetId() == HelpPerspective::ID &&
      page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID).empty())
  {
    IEditorInput::Pointer input(new HelpEditorInput());
    page->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpPerspectiveListener::PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId)
{
  if (perspective->GetId() == HelpPerspective::ID && changeId == IWorkbenchPage::CHANGE_RESET)
  {
    PerspectiveOpened(page, perspective);
  }
}

HelpWindowListener::HelpWindowListener()
  : perspListener(new HelpPerspectiveListener())
{
  // Register perspective listener for already opened windows
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->AddPerspectiveListener(perspListener);
  }
}

HelpWindowListener::~HelpWindowListener()
{
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->RemovePerspectiveListener(perspListener);
  }
}

void HelpWindowListener::WindowClosed(IWorkbenchWindow::Pointer window)
{
  window->RemovePerspectiveListener(perspListener);
}

void HelpWindowListener::WindowOpened(IWorkbenchWindow::Pointer window)
{
  window->AddPerspectiveListener(perspListener);
}

void HelpContextHandler::handleEvent(const ctkEvent &event)
{
  struct _runner : public Poco::Runnable
  {
    _runner(const ctkEvent& ev) : ev(ev) {}

    void run()
    {
      QUrl helpUrl;
      if (ev.containsProperty("url"))
      {
        helpUrl = QUrl(ev.getProperty("url").toString());
      }
      else
      {
        helpUrl = contextUrl();
      }

      HelpPluginActivator::linkActivated(PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(),
                                         helpUrl);
      delete this;
    }

    QUrl contextUrl() const
    {
      berry::IWorkbench* currentWorkbench = berry::PlatformUI::GetWorkbench();
      if (currentWorkbench)
      {
        berry::IWorkbenchWindow::Pointer currentWorkbenchWindow = currentWorkbench->GetActiveWorkbenchWindow();
        if (currentWorkbenchWindow)
        {
          berry::IWorkbenchPage::Pointer currentPage = currentWorkbenchWindow->GetActivePage();
          if (currentPage)
          {
            berry::IWorkbenchPart::Pointer currentPart = currentPage->GetActivePart();
            if (currentPart)
            {
              QString pluginID = QString::fromStdString(currentPart->GetSite()->GetPluginId());
              QString viewID = QString::fromStdString(currentPart->GetSite()->GetId());
              QString loc = "qthelp://" + pluginID + "/bundle/%1";

              QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
              QUrl contextUrl(loc.arg(viewID.replace(".", "_")));
              QUrl url = helpEngine.findFile(contextUrl);
              if (url.isValid()) return url;
              else
              {
                BERRY_INFO << "Context help url invalid: " << contextUrl.toString().toStdString();
              }
              url = helpEngine.findFile(QUrl(loc.arg("index.html")));
              return url;
            }
          }
        }
      }
      return QUrl();
    }

    ctkEvent ev;
  };
  // sync with GUI thread
  Display::GetDefault()->AsyncExec(new _runner(event));
}

}

Q_EXPORT_PLUGIN2(org_blueberry_ui_qt_help, berry::HelpPluginActivator)
<commit_msg>Show home page instead of the index.html from an unrelated plug-in.<commit_after>/*=========================================================================

Program:   BlueBerry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "berryHelpPluginActivator.h"

#include "berryHelpContentView.h"
#include "berryHelpIndexView.h"
#include "berryHelpSearchView.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpPerspective.h"

#include "berryQHelpEngineConfiguration.h"
#include "berryQHelpEngineWrapper.h"

#include <berryPlatformUI.h>

#include <service/event/ctkEventConstants.h>

#include <QtPlugin>
#include <QDir>
#include <QDateTime>

namespace berry {

class HelpPerspectiveListener : public IPerspectiveListener
{
public:

  Events::Types GetPerspectiveEventTypes() const;

  void PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective);
  void PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId);
};

class HelpWindowListener : public IWindowListener
{
public:

  HelpWindowListener();
  ~HelpWindowListener();

  void WindowClosed(IWorkbenchWindow::Pointer window);
  void WindowOpened(IWorkbenchWindow::Pointer window);

private:

  // We use the same perspective listener for every window
  IPerspectiveListener::Pointer perspListener;
};

HelpPluginActivator* HelpPluginActivator::instance = 0;

HelpPluginActivator::HelpPluginActivator()
  : pluginListener(0)
{
  this->instance = this;
}

HelpPluginActivator::~HelpPluginActivator()
{
  instance = 0;
}

void
HelpPluginActivator::start(ctkPluginContext* context)
{
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpContentView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpIndexView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpSearchView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpEditor, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpPerspective, context)

  QFileInfo qhcInfo = context->getDataFile("qthelpcollection.qhc");
  helpEngine.reset(new QHelpEngineWrapper(qhcInfo.absoluteFilePath()));
  if (!helpEngine->setupData())
  {
    BERRY_ERROR << "QHelpEngine set-up failed: " << helpEngine->error().toStdString();
    return;
  }

  helpEngineConfiguration.reset(new QHelpEngineConfiguration(context, *helpEngine.data()));

  delete pluginListener;
  pluginListener = new QCHPluginListener(context, helpEngine.data());
  context->connectPluginListener(pluginListener, SLOT(pluginChanged(ctkPluginEvent)));

  // register all QCH files from all the currently installed plugins
  pluginListener->processPlugins();

  helpEngine->initialDocSetupDone();

  // Register a wnd listener which registers a perspective listener for each
  // new window. The perspective listener opens the help home page in the window
  // if no other help page is opened yet.
  wndListener = IWindowListener::Pointer(new HelpWindowListener());
  PlatformUI::GetWorkbench()->AddWindowListener(wndListener);

  // Register an event handler for CONTEXTHELP_REQUESTED events
  helpContextHandler.reset(new HelpContextHandler);
  ctkDictionary helpHandlerProps;
  helpHandlerProps.insert(ctkEventConstants::EVENT_TOPIC, "org/blueberry/ui/help/CONTEXTHELP_REQUESTED");
  context->registerService<ctkEventHandler>(helpContextHandler.data(), helpHandlerProps);
}

void
HelpPluginActivator::stop(ctkPluginContext* /*context*/)
{
  delete pluginListener;
  pluginListener = 0;

  if (PlatformUI::IsWorkbenchRunning())
  {
    PlatformUI::GetWorkbench()->RemoveWindowListener(wndListener);
  }
  wndListener = 0;
}

HelpPluginActivator *HelpPluginActivator::getInstance()
{
  return instance;
}

QHelpEngineWrapper& HelpPluginActivator::getQHelpEngine()
{
  return *helpEngine;
}

void HelpPluginActivator::linkActivated(IWorkbenchPage::Pointer page, const QUrl &link)
{
  IEditorInput::Pointer input(new HelpEditorInput(link));

  // see if an editor with the same input is already open
  IEditorPart::Pointer reuseEditor = page->FindEditor(input);
  if (reuseEditor)
  {
    // just activate it
    page->Activate(reuseEditor);
  }
  else
  {
    // reuse the currently active editor, if it is a HelpEditor
    reuseEditor = page->GetActiveEditor();
    if (reuseEditor.IsNotNull() && page->GetReference(reuseEditor)->GetId() == HelpEditor::EDITOR_ID)
    {
      page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
      page->Activate(reuseEditor);
    }
    else
    {
      // get the last used HelpEditor instance
      std::vector<IEditorReference::Pointer> editors =
          page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID);
      if (editors.empty())
      {
        // no HelpEditor is currently open, create a new one
        page->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
      else
      {
        // reuse an existing editor
        reuseEditor = editors.front()->GetEditor(false);
        page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
        page->Activate(reuseEditor);
      }
    }
  }
}

QCHPluginListener::QCHPluginListener(ctkPluginContext* context, QHelpEngine* helpEngine)
  : delayRegistration(true), context(context), helpEngine(helpEngine)
{}

void QCHPluginListener::processPlugins()
{
  QMutexLocker lock(&mutex);
  processPlugins_unlocked();
}

void QCHPluginListener::pluginChanged(const ctkPluginEvent& event)
{
  QMutexLocker lock(&mutex);
  if (delayRegistration)
  {
    this->processPlugins_unlocked();
    return;
  }

  /* Only should listen for RESOLVED and UNRESOLVED events.
   *
   * When a plugin is updated the Framework will publish an UNRESOLVED and
   * then a RESOLVED event which should cause the plugin to be removed
   * and then added back into the registry.
   *
   * When a plugin is uninstalled the Framework should publish an UNRESOLVED
   * event and then an UNINSTALLED event so the plugin will have been removed
   * by the UNRESOLVED event before the UNINSTALLED event is published.
   */
  QSharedPointer<ctkPlugin> plugin = event.getPlugin();
  switch (event.getType())
  {
    case ctkPluginEvent::RESOLVED :
      addPlugin(plugin);
      break;
    case ctkPluginEvent::UNRESOLVED :
      removePlugin(plugin);
      break;
  }
}

void QCHPluginListener::processPlugins_unlocked()
{
  if (!delayRegistration) return;

  foreach (QSharedPointer<ctkPlugin> plugin, context->getPlugins())
  {
    if (isPluginResolved(plugin))
      addPlugin(plugin);
    else
      removePlugin(plugin);
  }

  delayRegistration = false;
}

bool QCHPluginListener::isPluginResolved(QSharedPointer<ctkPlugin> plugin)
{
  return (plugin->getState() & (ctkPlugin::RESOLVED | ctkPlugin::ACTIVE | ctkPlugin::STARTING | ctkPlugin::STOPPING)) != 0;
}

void QCHPluginListener::removePlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  if (qchDirInfo.exists())
  {
    QDir qchDir(qchDirInfo.absoluteFilePath());
    QStringList qchEntries = qchDir.entryList(QStringList("*.qch"));
    QStringList qchFiles;
    foreach(QString qchEntry, qchEntries)
    {
      qchFiles << qchDir.absoluteFilePath(qchEntry);
    }
    // unregister the cached qch files
    foreach(QString qchFile, qchFiles)
    {
      QString namespaceName = QHelpEngineCore::namespaceName(qchFile);
      if (namespaceName.isEmpty())
      {
        BERRY_ERROR << "Could not get the namespace for qch file " << qchFile.toStdString();
        continue;
      }
      else
      {
        if (!helpEngine->unregisterDocumentation(namespaceName))
        {
          BERRY_ERROR << "Unregistering qch namespace " << namespaceName.toStdString() << " failed: " << helpEngine->error().toStdString();
        }
      }
    }
    // clean the directory
    foreach(QString qchEntry, qchEntries)
    {
      qchDir.remove(qchEntry);
    }
  }
}

void QCHPluginListener::addPlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  QUrl location(plugin->getLocation());
  QFileInfo pluginFileInfo(location.toLocalFile());

  if (!qchDirInfo.exists() || qchDirInfo.lastModified() < pluginFileInfo.lastModified())
  {
    removePlugin(plugin);

    if (!qchDirInfo.exists())
    {
      QDir().mkpath(qchDirInfo.absoluteFilePath());
    }

    QStringList localQCHFiles;
    QStringList resourceList = plugin->findResources("/", "*.qch", true);
    foreach(QString resource, resourceList)
    {
      QByteArray content = plugin->getResource(resource);
      QFile localFile(qchDirInfo.absoluteFilePath() + "/" + resource.section('/', -1));
      localFile.open(QIODevice::WriteOnly);
      localFile.write(content);
      localFile.close();
      if (localFile.error() != QFile::NoError)
      {
        BERRY_WARN << "Error writing " << localFile.fileName().toStdString()
                   << ": " << localFile.errorString().toStdString();
      }
      else
      {
        localQCHFiles << localFile.fileName();
      }
    }

    foreach(QString qchFile, localQCHFiles)
    {
      if (!helpEngine->registerDocumentation(qchFile))
      {
        BERRY_ERROR << "Registering qch file " << qchFile.toStdString() << " failed: " << helpEngine->error().toStdString();
      }
    }
  }

}

IPerspectiveListener::Events::Types HelpPerspectiveListener::GetPerspectiveEventTypes() const
{
  return Events::OPENED | Events::CHANGED;
}

void HelpPerspectiveListener::PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective)
{
  // if no help editor is opened, open one showing the home page
  if (perspective->GetId() == HelpPerspective::ID &&
      page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID).empty())
  {
    IEditorInput::Pointer input(new HelpEditorInput());
    page->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpPerspectiveListener::PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId)
{
  if (perspective->GetId() == HelpPerspective::ID && changeId == IWorkbenchPage::CHANGE_RESET)
  {
    PerspectiveOpened(page, perspective);
  }
}

HelpWindowListener::HelpWindowListener()
  : perspListener(new HelpPerspectiveListener())
{
  // Register perspective listener for already opened windows
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->AddPerspectiveListener(perspListener);
  }
}

HelpWindowListener::~HelpWindowListener()
{
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->RemovePerspectiveListener(perspListener);
  }
}

void HelpWindowListener::WindowClosed(IWorkbenchWindow::Pointer window)
{
  window->RemovePerspectiveListener(perspListener);
}

void HelpWindowListener::WindowOpened(IWorkbenchWindow::Pointer window)
{
  window->AddPerspectiveListener(perspListener);
}

void HelpContextHandler::handleEvent(const ctkEvent &event)
{
  struct _runner : public Poco::Runnable
  {
    _runner(const ctkEvent& ev) : ev(ev) {}

    void run()
    {
      QUrl helpUrl;
      if (ev.containsProperty("url"))
      {
        helpUrl = QUrl(ev.getProperty("url").toString());
      }
      else
      {
        helpUrl = contextUrl();
      }

      HelpPluginActivator::linkActivated(PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(),
                                         helpUrl);
      delete this;
    }

    QUrl contextUrl() const
    {
      berry::IWorkbench* currentWorkbench = berry::PlatformUI::GetWorkbench();
      if (currentWorkbench)
      {
        berry::IWorkbenchWindow::Pointer currentWorkbenchWindow = currentWorkbench->GetActiveWorkbenchWindow();
        if (currentWorkbenchWindow)
        {
          berry::IWorkbenchPage::Pointer currentPage = currentWorkbenchWindow->GetActivePage();
          if (currentPage)
          {
            berry::IWorkbenchPart::Pointer currentPart = currentPage->GetActivePart();
            if (currentPart)
            {
              QString pluginID = QString::fromStdString(currentPart->GetSite()->GetPluginId());
              QString viewID = QString::fromStdString(currentPart->GetSite()->GetId());
              QString loc = "qthelp://" + pluginID + "/bundle/%1.html";

              QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
              QUrl contextUrl(loc.arg(viewID.replace(".", "_")));
              QUrl url = helpEngine.findFile(contextUrl);
              if (url.isValid()) return url;
              else
              {
                BERRY_INFO << "Context help url invalid: " << contextUrl.toString().toStdString();
              }
              // Try to get the index.html file of the plug-in contributing the
              // currently active part.
              QUrl pluginIndexUrl(loc.arg("index"));
              url = helpEngine.findFile(pluginIndexUrl);
              if (url != pluginIndexUrl)
              {
                // Use the default page instead of another index.html
                // (merged via the virtual folder property).
                url = QUrl();
              }
              return url;
            }
          }
        }
      }
      return QUrl();
    }

    ctkEvent ev;
  };
  // sync with GUI thread
  Display::GetDefault()->AsyncExec(new _runner(event));
}

}

Q_EXPORT_PLUGIN2(org_blueberry_ui_qt_help, berry::HelpPluginActivator)
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkKullbackLeiblerCompareHistogramImageToImageMetricTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.h"
#include "itkImage.h"
#include "itkImageRegionIterator.h"

#include "itkAffineTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkTimeProbesCollectorBase.h"
#include "vnl/vnl_sample.h"

#include <iostream>

/**
 *  This test uses two 2D-Gaussians (standard deviation RegionSize/2)
 *  One is shifted by 5 pixels from the other.
 *
 *  This test computes the KullbackLeibler information value and derivatives
 *  for various shift values in (-10,10).
 *
 */

int itkKullbackLeiblerCompareHistogramImageToImageMetricTest(int, char* [] )
{

//------------------------------------------------------------
// Create four simple images
//------------------------------------------------------------

  //Allocate Images
  typedef itk::Image<unsigned char,2>           MovingImageType;
  typedef itk::Image<unsigned char,2>           FixedImageType;
  typedef itk::Image<unsigned char,2>           TrainingMovingImageType;
  typedef itk::Image<unsigned char,2>           TrainingFixedImageType;

  enum { ImageDimension = MovingImageType::ImageDimension };

  MovingImageType::SizeType size = {{100,100}};
  MovingImageType::IndexType index = {{0,0}};
  MovingImageType::RegionType region;
  region.SetSize( size );
  region.SetIndex( index );

  MovingImageType::Pointer imgMoving = MovingImageType::New();
  imgMoving->SetLargestPossibleRegion( region );
  imgMoving->SetBufferedRegion( region );
  imgMoving->SetRequestedRegion( region );
  imgMoving->Allocate();

  FixedImageType::Pointer imgFixed = FixedImageType::New();
  imgFixed->SetLargestPossibleRegion( region );
  imgFixed->SetBufferedRegion( region );
  imgFixed->SetRequestedRegion( region );
  imgFixed->Allocate();

  MovingImageType::Pointer imgTrainingMoving = MovingImageType::New();
  imgTrainingMoving->SetLargestPossibleRegion( region );
  imgTrainingMoving->SetBufferedRegion( region );
  imgTrainingMoving->SetRequestedRegion( region );
  imgTrainingMoving->Allocate();

  FixedImageType::Pointer imgTrainingFixed = FixedImageType::New();
  imgTrainingFixed->SetLargestPossibleRegion( region );
  imgTrainingFixed->SetBufferedRegion( region );
  imgTrainingFixed->SetRequestedRegion( region );
  imgTrainingFixed->Allocate();

  // Fill images with a 2D gaussian
  typedef  itk::ImageRegionIterator<MovingImageType>
    ReferenceIteratorType;
  typedef  itk::ImageRegionIterator<FixedImageType>
    TargetIteratorType;
  typedef  itk::ImageRegionIterator<TrainingMovingImageType>
    TrainingReferenceIteratorType;
  typedef  itk::ImageRegionIterator<TrainingFixedImageType>
    TrainingTargetIteratorType;

  itk::Point<double,2> center;
  center[0] = (double)region.GetSize()[0]/2.0;
  center[1] = (double)region.GetSize()[1]/2.0;

  const double s = (double)region.GetSize()[0]/2.0;
  const double mag = (double)200.0;
  const double noisemag = (double)10.0;

  itk::Point<double,2>  p;
  itk::Vector<double,2> d;

  // Set the displacement
  itk::Vector<double,2> displacement;
  displacement[0] = 5;
  displacement[1] = 0;

  ReferenceIteratorType ri(imgMoving,region);
  TargetIteratorType ti(imgFixed,region);
  TrainingReferenceIteratorType gri(imgTrainingMoving,region);
  TrainingTargetIteratorType gti(imgTrainingFixed,region);

  ri.Begin();
  while(!ri.IsAtEnd())
    {
    p[0] = ri.GetIndex()[0];
    p[1] = ri.GetIndex()[1];
    d = p-center;
    d += displacement;
    const double x = d[0];
    const double y = d[1];
    ri.Set( (unsigned char) ( mag * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ri;
    }

  ti.Begin();
  while(!ti.IsAtEnd())
    {
    p[0] = ti.GetIndex()[0];
    p[1] = ti.GetIndex()[1];
    d = p-center;
    const double x = d[0];
    const double y = d[1];
    ti.Set( (unsigned char) ( mag * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ti;
    }

  vnl_sample_reseed(2334237);

  gri.Begin();
  while(!gri.IsAtEnd())
    {
    p[0] = gri.GetIndex()[0];
    p[1] = gri.GetIndex()[1];
    d = p-center;
    //    d += displacement;
    const double x = d[0];
    const double y = d[1];
    gri.Set( (unsigned char) (( mag * exp( - ( x*x + y*y )/(s*s) ) )  +
      vnl_sample_normal(0.0, noisemag)));
    ++gri;
    }

  gti.Begin();
  while(!gti.IsAtEnd())
    {
    p[0] = gti.GetIndex()[0];
    p[1] = gti.GetIndex()[1];
    d = p-center;
    const double x = d[0];
    const double y = d[1];
    gti.Set( (unsigned char) (( mag * exp( - ( x*x + y*y )/(s*s) ) )  +
      vnl_sample_normal(0.0, noisemag)));
    ++gti;
    }

//-----------------------------------------------------------
// Set up a transformer
//-----------------------------------------------------------
  typedef itk::AffineTransform<
    double, ImageDimension > TransformType;
  typedef TransformType::ParametersType ParametersType;

  TransformType::Pointer transformer    = TransformType::New();
  TransformType::Pointer TrainingTransform = TransformType::New();
  transformer->SetIdentity();
  TrainingTransform->SetIdentity();

//------------------------------------------------------------
// Set up a interpolator
//------------------------------------------------------------
  typedef itk::LinearInterpolateImageFunction< MovingImageType, double >
    InterpolatorType;

  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  InterpolatorType::Pointer TrainingInterpolator = InterpolatorType::New();

//------------------------------------------------------------
// Set up the metric
//------------------------------------------------------------
  typedef itk::KullbackLeiblerCompareHistogramImageToImageMetric<
    FixedImageType, MovingImageType > MetricType;

  MetricType::Pointer metric = MetricType::New();

  // connect the interpolator
  metric->SetInterpolator( interpolator );

  // connect the transform
  metric->SetTransform( transformer );

  // connect the images to the metric
  metric->SetFixedImage( imgFixed );
  metric->SetMovingImage( imgMoving );

  // set the standard deviations
  //metric->SetFixedImageStandardDeviation( 5.0 );
  //metric->SetMovingImageStandardDeviation( 5.0 );

  // set the number of samples to use
  // metric->SetNumberOfSpatialSamples( 100 );

  unsigned int nBins = 64;
  MetricType::HistogramType::SizeType histSize;
  histSize[0] = nBins;
  histSize[1] = nBins;
  metric->SetHistogramSize(histSize);

  // Set scales for derivative calculation.
  typedef MetricType::ScalesType ScalesType;
  ScalesType scales(transformer->GetNumberOfParameters());

  for (unsigned int k = 0; k < transformer ->GetNumberOfParameters(); k++)
    scales[k] = 1;

  metric->SetDerivativeStepLengthScales(scales);

  // set the region over which to compute metric
  metric->SetFixedImageRegion( imgFixed->GetBufferedRegion() );

//------------------------------------------------------------
// Set up the metric
//------------------------------------------------------------

  metric->SetTrainingInterpolator( TrainingInterpolator );
  metric->SetTrainingFixedImage( imgTrainingFixed );
  metric->SetTrainingMovingImage( imgTrainingMoving );
  metric->SetTrainingFixedImageRegion( imgTrainingFixed->GetBufferedRegion() );
  metric->SetTrainingTransform( TrainingTransform );

  // initialize the metric before use
  metric->Initialize();

//------------------------------------------------------------
// Set up a affine transform parameters
//------------------------------------------------------------
  unsigned int numberOfParameters = transformer->GetNumberOfParameters();
  ParametersType parameters( numberOfParameters );

  // set the parameters to the identity
  unsigned long count = 0;

     // initialize the linear/matrix part
  for( unsigned int row = 0; row < ImageDimension; row++ )
    {
    for( unsigned int col = 0; col < ImageDimension; col++ )
      {
      parameters[count] = 0;
      if( row == col )
        {
        parameters[count] = 1;
        }
      ++count;
      }
    }

     // initialize the offset/vector part
  for( unsigned int k = 0; k < ImageDimension; k++ )
    {
    parameters[count] = 0;
    ++count;
    }

//---------------------------------------------------------
// Print out KullbackLeibler values
// for parameters[4] = {-10,10}
//---------------------------------------------------------

  MetricType::MeasureType measure;
  MetricType::DerivativeType derivative( numberOfParameters );

  itk::TimeProbesCollectorBase   collector;
  collector.Start("Loop");

  std::cout << "param[4]\tKullbackLeibler\tdKullbackLeibler/dparam[4]" << std::endl;

  for( double trans = -10; trans <= 4; trans += 0.5 )
    {
    parameters[4] = trans;
    metric->GetValueAndDerivative( parameters, measure, derivative );

    std::cout << trans << "\t" << measure << "\t" << derivative[4] <<std::endl;

    // exercise the other functions
    metric->GetValue( parameters );
    metric->GetDerivative( parameters, derivative );

    }
  collector.Stop("Loop");
  collector.Report();

//-------------------------------------------------------
// exercise misc member functions
//-------------------------------------------------------
  std::cout << "Name of class: " <<
    metric->GetNameOfClass() << std::endl;
//  std::cout << "No. of samples used = " <<
//    metric->GetNumberOfSpatialSamples() << std::endl;
//  std::cout << "Fixed image std dev = " <<
//    metric->GetFixedImageStandardDeviation() << std::endl;
//  std::cout << "Moving image std dev = " <<
//    metric->GetMovingImageStandardDeviation() << std::endl;

  metric->Print( std::cout );

//  itk::KernelFunction::Pointer theKernel = metric->GetKernelFunction();
//  metric->SetKernelFunction( theKernel );
//  theKernel->Print( std::cout );

//  std::cout << "Try causing a exception by making std dev too small";
//  std::cout << std::endl;
//  metric->SetFixedImageStandardDeviation( 0.001 );
//  try
//    {
//    metric->Initialize();
//    std::cout << "Value = " << metric->GetValue( parameters );
//    std::cout << std::endl;
//    }
//  catch(itk::ExceptionObject &err)
//    {
//    std::cout << "Caught the exception." << std::endl;
//    std::cout << err << std::endl;
//    }
//
//  // reset standard deviation
//  metric->SetFixedImageStandardDeviation( 5.0 );

  std::cout << "Try causing a exception by making fixed image NULL";
  std::cout << std::endl;
  metric->SetFixedImage( NULL );
  try
    {
    metric->Initialize();
    std::cout << "Value = " << metric->GetValue( parameters );
    std::cout << std::endl;
    }
  catch( itk::ExceptionObject &err)
    {
    std::cout << "Caught the exception." << std::endl;
    std::cout << err << std::endl;
    }

  return EXIT_SUCCESS;

}

<commit_msg>FIX: Bug #520. The previous implementation didn't correspond to the referenced      paper. The modification were posted by the author (of the classes) Samson Timoner.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkKullbackLeiblerCompareHistogramImageToImageMetricTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.h"
#include "itkImage.h"
#include "itkImageRegionIterator.h"

#include "itkAffineTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkTimeProbesCollectorBase.h"
#include "vnl/vnl_sample.h"

#include <iostream>

/**
 *  This test uses two 2D-Gaussians (standard deviation RegionSize/2)
 *  One is shifted by 5 pixels from the other.
 *
 *  This test computes the KullbackLeibler information value and derivatives
 *  for various shift values in (-10,10).
 *
 */

int itkKullbackLeiblerCompareHistogramImageToImageMetricTest(int, char* [] )
{

//------------------------------------------------------------
// Create four simple images
//------------------------------------------------------------

  //Allocate Images
  typedef itk::Image<unsigned char,2>           MovingImageType;
  typedef itk::Image<unsigned char,2>           FixedImageType;
  typedef itk::Image<unsigned char,2>           TrainingMovingImageType;
  typedef itk::Image<unsigned char,2>           TrainingFixedImageType;

  enum { ImageDimension = MovingImageType::ImageDimension };

  MovingImageType::SizeType size = {{100,100}};
  MovingImageType::IndexType index = {{0,0}};
  MovingImageType::RegionType region;
  region.SetSize( size );
  region.SetIndex( index );

  MovingImageType::Pointer imgMoving = MovingImageType::New();
  imgMoving->SetLargestPossibleRegion( region );
  imgMoving->SetBufferedRegion( region );
  imgMoving->SetRequestedRegion( region );
  imgMoving->Allocate();

  FixedImageType::Pointer imgFixed = FixedImageType::New();
  imgFixed->SetLargestPossibleRegion( region );
  imgFixed->SetBufferedRegion( region );
  imgFixed->SetRequestedRegion( region );
  imgFixed->Allocate();

  MovingImageType::Pointer imgTrainingMoving = MovingImageType::New();
  imgTrainingMoving->SetLargestPossibleRegion( region );
  imgTrainingMoving->SetBufferedRegion( region );
  imgTrainingMoving->SetRequestedRegion( region );
  imgTrainingMoving->Allocate();

  FixedImageType::Pointer imgTrainingFixed = FixedImageType::New();
  imgTrainingFixed->SetLargestPossibleRegion( region );
  imgTrainingFixed->SetBufferedRegion( region );
  imgTrainingFixed->SetRequestedRegion( region );
  imgTrainingFixed->Allocate();

  // Fill images with a 2D gaussian
  typedef  itk::ImageRegionIterator<MovingImageType>
    ReferenceIteratorType;
  typedef  itk::ImageRegionIterator<FixedImageType>
    TargetIteratorType;
  typedef  itk::ImageRegionIterator<TrainingMovingImageType>
    TrainingReferenceIteratorType;
  typedef  itk::ImageRegionIterator<TrainingFixedImageType>
    TrainingTargetIteratorType;

  itk::Point<double,2> center;
  center[0] = (double)region.GetSize()[0]/2.0;
  center[1] = (double)region.GetSize()[1]/2.0;

  const double s = (double)region.GetSize()[0]/2.0;
  const double mag = (double)200.0;
  const double noisemag = (double)0.0; // ended up yielding best results

  itk::Point<double,2>  p;
  itk::Vector<double,2> d;

  // Set the displacement
  itk::Vector<double,2> displacement;
  displacement[0] = 5;
  displacement[1] = 0;

  ReferenceIteratorType ri(imgMoving,region);
  TargetIteratorType ti(imgFixed,region);
  TrainingReferenceIteratorType gri(imgTrainingMoving,region);
  TrainingTargetIteratorType gti(imgTrainingFixed,region);

  ri.Begin();
  while(!ri.IsAtEnd())
    {
    p[0] = ri.GetIndex()[0];
    p[1] = ri.GetIndex()[1];
    d = p-center;
    d += displacement;
    const double x = d[0];
    const double y = d[1];
    ri.Set( (unsigned char) ( mag * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ri;
    }

  ti.Begin();
  while(!ti.IsAtEnd())
    {
    p[0] = ti.GetIndex()[0];
    p[1] = ti.GetIndex()[1];
    d = p-center;
    const double x = d[0];
    const double y = d[1];
    ti.Set( (unsigned char) ( mag * exp( - ( x*x + y*y )/(s*s) ) ) );
    ++ti;
    }

  vnl_sample_reseed(2334237);

  gri.Begin();
  while(!gri.IsAtEnd())
    {
    p[0] = gri.GetIndex()[0];
    p[1] = gri.GetIndex()[1];
    d = p-center;
    //    d += displacement;
    const double x = d[0];
    const double y = d[1];
    gri.Set( (unsigned char) (( mag * exp( - ( x*x + y*y )/(s*s) ) )  +
      vnl_sample_normal(0.0, noisemag)));
    ++gri;
    }

  gti.Begin();
  while(!gti.IsAtEnd())
    {
    p[0] = gti.GetIndex()[0];
    p[1] = gti.GetIndex()[1];
    d = p-center;
    const double x = d[0];
    const double y = d[1];
    gti.Set( (unsigned char) (( mag * exp( - ( x*x + y*y )/(s*s) ) )  +
      vnl_sample_normal(0.0, noisemag)));
    ++gti;
    }

//-----------------------------------------------------------
// Set up a transformer
//-----------------------------------------------------------
  typedef itk::AffineTransform<
    double, ImageDimension > TransformType;
  typedef TransformType::ParametersType ParametersType;

  TransformType::Pointer transformer    = TransformType::New();
  TransformType::Pointer TrainingTransform = TransformType::New();
  transformer->SetIdentity();
  TrainingTransform->SetIdentity();

//------------------------------------------------------------
// Set up a interpolator
//------------------------------------------------------------
  typedef itk::LinearInterpolateImageFunction< MovingImageType, double >
    InterpolatorType;

  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  InterpolatorType::Pointer TrainingInterpolator = InterpolatorType::New();

//------------------------------------------------------------
// Set up the metric
//------------------------------------------------------------
  typedef itk::KullbackLeiblerCompareHistogramImageToImageMetric<
    FixedImageType, MovingImageType > MetricType;

  MetricType::Pointer metric = MetricType::New();

  // connect the interpolator
  metric->SetInterpolator( interpolator );

  // connect the transform
  metric->SetTransform( transformer );

  // connect the images to the metric
  metric->SetFixedImage( imgFixed );
  metric->SetMovingImage( imgMoving );

  // set the standard deviations
  //metric->SetFixedImageStandardDeviation( 5.0 );
  //metric->SetMovingImageStandardDeviation( 5.0 );

  // set the number of samples to use
  // metric->SetNumberOfSpatialSamples( 100 );

  unsigned int nBins = 64;
  MetricType::HistogramType::SizeType histSize;
  histSize[0] = nBins;
  histSize[1] = nBins;
  metric->SetHistogramSize(histSize);

  // Set scales for derivative calculation.
  typedef MetricType::ScalesType ScalesType;
  ScalesType scales(transformer->GetNumberOfParameters());

  for (unsigned int k = 0; k < transformer ->GetNumberOfParameters(); k++)
    scales[k] = 1;

  metric->SetDerivativeStepLengthScales(scales);

  // set the region over which to compute metric
  metric->SetFixedImageRegion( imgFixed->GetBufferedRegion() );

//------------------------------------------------------------
// Set up the metric
//------------------------------------------------------------

  metric->SetTrainingInterpolator( TrainingInterpolator );
  metric->SetTrainingFixedImage( imgTrainingFixed );
  metric->SetTrainingMovingImage( imgTrainingMoving );
  metric->SetTrainingFixedImageRegion( imgTrainingFixed->GetBufferedRegion() );
  metric->SetTrainingTransform( TrainingTransform );

  // initialize the metric before use
  metric->Initialize();

//------------------------------------------------------------
// Set up a affine transform parameters
//------------------------------------------------------------
  unsigned int numberOfParameters = transformer->GetNumberOfParameters();
  ParametersType parameters( numberOfParameters );

  // set the parameters to the identity
  unsigned long count = 0;

     // initialize the linear/matrix part
  for( unsigned int row = 0; row < ImageDimension; row++ )
    {
    for( unsigned int col = 0; col < ImageDimension; col++ )
      {
      parameters[count] = 0;
      if( row == col )
        {
        parameters[count] = 1;
        }
      ++count;
      }
    }

     // initialize the offset/vector part
  for( unsigned int k = 0; k < ImageDimension; k++ )
    {
    parameters[count] = 0;
    ++count;
    }

//---------------------------------------------------------
// Print out KullbackLeibler values
// for parameters[4] = {-10,10}
//---------------------------------------------------------

  MetricType::MeasureType measure;
  MetricType::DerivativeType derivative( numberOfParameters );

  itk::TimeProbesCollectorBase   collector;
  collector.Start("Loop");

  std::cout << "param[4]\tKullbackLeibler\tdKullbackLeibler/dparam[4]" << std::endl;

  for( double trans = -10; trans <= 4; trans += 0.5 )
    {
    parameters[4] = trans;
    metric->GetValueAndDerivative( parameters, measure, derivative );

    std::cout << trans << "\t" << measure << "\t" << derivative[4] <<std::endl;

    // exercise the other functions
    metric->GetValue( parameters );
    metric->GetDerivative( parameters, derivative );

    }
  collector.Stop("Loop");
  collector.Report();

//-------------------------------------------------------
// exercise misc member functions
//-------------------------------------------------------
  std::cout << "Name of class: " <<
    metric->GetNameOfClass() << std::endl;
//  std::cout << "No. of samples used = " <<
//    metric->GetNumberOfSpatialSamples() << std::endl;
//  std::cout << "Fixed image std dev = " <<
//    metric->GetFixedImageStandardDeviation() << std::endl;
//  std::cout << "Moving image std dev = " <<
//    metric->GetMovingImageStandardDeviation() << std::endl;

  metric->Print( std::cout );

//  itk::KernelFunction::Pointer theKernel = metric->GetKernelFunction();
//  metric->SetKernelFunction( theKernel );
//  theKernel->Print( std::cout );

//  std::cout << "Try causing a exception by making std dev too small";
//  std::cout << std::endl;
//  metric->SetFixedImageStandardDeviation( 0.001 );
//  try
//    {
//    metric->Initialize();
//    std::cout << "Value = " << metric->GetValue( parameters );
//    std::cout << std::endl;
//    }
//  catch(itk::ExceptionObject &err)
//    {
//    std::cout << "Caught the exception." << std::endl;
//    std::cout << err << std::endl;
//    }
//
//  // reset standard deviation
//  metric->SetFixedImageStandardDeviation( 5.0 );

  std::cout << "Try causing a exception by making fixed image NULL";
  std::cout << std::endl;
  metric->SetFixedImage( NULL );
  try
    {
    metric->Initialize();
    std::cout << "Value = " << metric->GetValue( parameters );
    std::cout << std::endl;
    }
  catch( itk::ExceptionObject &err)
    {
    std::cout << "Caught the exception." << std::endl;
    std::cout << err << std::endl;
    }

  return EXIT_SUCCESS;

}

<|endoftext|>


<commit_before>#include "demand_matrix_input.h"

#include <gflags/gflags.h>
#include <stddef.h>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <map>
#include <random>
#include <string>

#include "ncode/common.h"
#include "ncode/file.h"
#include "ncode/logging.h"
#include "ncode/net/net_common.h"
#include "ncode/net/net_gen.h"
#include "ncode/strutil.h"
#include "topology_input.h"

DEFINE_string(tm_root, "", "Root for traffic matrix file(s). Required.");
DEFINE_string(
    topology_root, "",
    "Root for topologies. If empty will be set to the same as tm_root.");
DEFINE_uint64(tm_per_topology, std::numeric_limits<uint64_t>::max(),
              "How many TMs to choose for each topology");
DEFINE_uint64(seed, 1,
              "Seed used when choosing TMs for each topology. Set to 0 to "
              "disable random choice of TMs.");
DEFINE_uint64(topology_size_limit, 100000,
              "Topologies with size more than this will be skipped");
DEFINE_uint64(topology_delay_limit_ms, 10,
              "Topologies with diameter less than this limit will be skipped");

static constexpr char kDemandsExtension[] = ".demands";
static constexpr char kTopologyExtension[] = ".graph";

using namespace std::chrono;

namespace ctr {

static std::string FindTopologyFileForDemandFileOrDie(
    const std::string& demand_file,
    const std::vector<std::string>& topology_files) {
  std::string base = nc::File::ExtractFileName(demand_file);
  std::string demand_base =
      nc::StringReplace(base, kDemandsExtension, kTopologyExtension, true);

  std::string to_return = "";
  for (const auto& file : topology_files) {
    std::string top_base = nc::File::ExtractFileName(file);
    top_base = nc::StringReplace(top_base, kTopologyExtension, "", true);
    top_base = nc::StrCat(top_base, "_");

    if (nc::HasPrefixString(demand_base, top_base) ||
        nc::HasSuffixString(demand_base, top_base)) {
      if (to_return.size() < file.size()) {
        to_return = file;
      }
    }
  }

  CHECK(to_return != "") << "Unable to find topology for file " << demand_file;
  return to_return;
}

static std::map<std::string, std::vector<std::string>> GetTopologyToDemands(
    size_t* topology_count, size_t* tm_count) {
  std::string tm_root = FLAGS_tm_root;
  CHECK(tm_root != "");
  std::string top_root =
      FLAGS_topology_root == "" ? FLAGS_tm_root : FLAGS_topology_root;

  std::vector<std::string> traffic_matrices =
      nc::File::GetFilesWithExtension(tm_root, kDemandsExtension);
  std::vector<std::string> topologies =
      nc::File::GetFilesWithExtension(top_root, kTopologyExtension);

  std::map<std::string, std::vector<std::string>> out;
  for (const std::string& tm_file : traffic_matrices) {
    std::string topology_file =
        FindTopologyFileForDemandFileOrDie(tm_file, topologies);
    out[topology_file].emplace_back(tm_file);
  }
  *tm_count = traffic_matrices.size();
  *topology_count = out.size();

  return out;
}

std::pair<std::vector<TopologyAndFilename>,
          std::vector<DemandMatrixAndFilename>>
GetDemandMatrixInputs(bool skip_trivial) {
  // Inputs.
  std::vector<TopologyAndFilename> topologies_out;
  std::vector<DemandMatrixAndFilename> demands_out;

  // Randomness to pick tms for each topology.
  std::mt19937 rnd(FLAGS_seed);

  size_t topology_count;
  size_t tm_count;
  std::map<std::string, std::vector<std::string>> topology_to_demands =
      GetTopologyToDemands(&topology_count, &tm_count);
  LOG(INFO) << "Will load " << tm_count << " TMs from " << topology_count
            << " topologies";
  for (auto& topology_and_demands : topology_to_demands) {
    const std::string& topology_file = topology_and_demands.first;
    std::vector<std::string>& demands_for_topology =
        topology_and_demands.second;

    std::vector<std::string> node_order;
    nc::net::GraphBuilder builder = nc::net::LoadRepetitaOrDie(
        nc::File::ReadFileToStringOrDie(topology_file), &node_order);
    builder.RemoveMultipleLinks();

    auto graph = nc::make_unique<nc::net::GraphStorage>(builder);
    nc::net::GraphStats stats = graph->Stats();
    CHECK(!stats.sp_delay_percentiles.empty());
    if (stats.sp_delay_percentiles.back() == nc::net::Delay::max()) {
      LOG(INFO) << "Skipping " << topology_file << " graph partitioned ";
      continue;
    }

    size_t node_count = graph->AllNodes().Count();
    if (node_count > FLAGS_topology_size_limit) {
      LOG(INFO) << "Skipping " << topology_file << " / " << topology_file
                << " size limit " << FLAGS_topology_size_limit << " vs "
                << node_count;
      continue;
    }

    nc::net::Delay diameter = graph->Stats().sp_delay_percentiles.back();
    if (diameter < milliseconds(FLAGS_topology_delay_limit_ms)) {
      LOG(INFO) << "Skipping " << topology_file << " / " << topology_file
                << " delay limit " << FLAGS_topology_delay_limit_ms
                << "ms vs diameter delay "
                << duration_cast<milliseconds>(diameter).count() << "ms";
      continue;
    }

    if (FLAGS_seed != 0) {
      std::shuffle(demands_for_topology.begin(), demands_for_topology.end(),
                   rnd);
    }

    demands_for_topology.resize(
        std::min(demands_for_topology.size(),
                 static_cast<size_t>(FLAGS_tm_per_topology)));
    for (const std::string& demand_file : demands_for_topology) {
      std::unique_ptr<nc::lp::DemandMatrix> demand_matrix =
          nc::lp::DemandMatrix::LoadRepetitaFileOrDie(demand_file, node_order,
                                                      graph.get());
      if (!demand_matrix) {
        LOG(INFO) << "Skipping " << demand_file << " inconsistent TM";
        continue;
      }

      if (skip_trivial) {
        const std::map<std::string, std::string>& props =
            demand_matrix->properties();
        const std::string& trivial = nc::FindOrDie(props, "trivial");
        if (trivial == "true") {
          LOG(INFO) << "Skipping " << demand_file << " trivially satisfiable";
          continue;
        }
      }

      demands_out.emplace_back(topology_file, demand_file,
                               std::move(demand_matrix));
    }

    topologies_out.emplace_back(std::move(graph), node_order, topology_file);
  }

  return {std::move(topologies_out), std::move(demands_out)};
}

}  // namespace ctr
<commit_msg>updated net_mock<commit_after>#include "demand_matrix_input.h"

#include <gflags/gflags.h>
#include <stddef.h>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <map>
#include <random>
#include <string>

#include "ncode/common.h"
#include "ncode/file.h"
#include "ncode/logging.h"
#include "ncode/net/net_common.h"
#include "ncode/net/net_gen.h"
#include "ncode/strutil.h"
#include "topology_input.h"

DEFINE_string(tm_root, "", "Root for traffic matrix file(s). Required.");
DEFINE_string(
    topology_root, "",
    "Root for topologies. If empty will be set to the same as tm_root.");
DEFINE_uint64(tm_per_topology, std::numeric_limits<uint64_t>::max(),
              "How many TMs to choose for each topology");
DEFINE_uint64(seed, 1,
              "Seed used when choosing TMs for each topology. Set to 0 to "
              "disable random choice of TMs.");
DEFINE_uint64(topology_size_limit, 100000,
              "Topologies with size more than this will be skipped");
DEFINE_uint64(topology_delay_limit_ms, 10,
              "Topologies with diameter less than this limit will be skipped");

static constexpr char kDemandsExtension[] = ".demands";
static constexpr char kTopologyExtension[] = ".graph";

using namespace std::chrono;

namespace ctr {

static std::string FindTopologyFileForDemandFileOrDie(
    const std::string& demand_file,
    const std::vector<std::string>& topology_files) {
  std::string base = nc::File::ExtractFileName(demand_file);
  std::string demand_base =
      nc::StringReplace(base, kDemandsExtension, kTopologyExtension, true);

  std::string to_return = "";
  for (const auto& file : topology_files) {
    std::string top_base = nc::File::ExtractFileName(file);
    top_base = nc::StringReplace(top_base, kTopologyExtension, "", true);
    top_base = nc::StrCat(top_base, "_");

    if (nc::HasPrefixString(demand_base, top_base) ||
        nc::HasSuffixString(demand_base, top_base)) {
      if (to_return.size() < file.size()) {
        to_return = file;
      }
    }
  }

  CHECK(to_return != "") << "Unable to find topology for file " << demand_file;
  return to_return;
}

static std::map<std::string, std::vector<std::string>> GetTopologyToDemands(
    size_t* topology_count, size_t* tm_count) {
  std::string tm_root = FLAGS_tm_root;
  CHECK(tm_root != "");
  std::string top_root =
      FLAGS_topology_root == "" ? FLAGS_tm_root : FLAGS_topology_root;

  std::vector<std::string> traffic_matrices =
      nc::File::GetFilesWithExtension(tm_root, kDemandsExtension);
  std::vector<std::string> topologies =
      nc::File::GetFilesWithExtension(top_root, kTopologyExtension);

  std::map<std::string, std::vector<std::string>> out;
  for (const std::string& tm_file : traffic_matrices) {
    std::string topology_file =
        FindTopologyFileForDemandFileOrDie(tm_file, topologies);
    out[topology_file].emplace_back(tm_file);
  }
  *tm_count = traffic_matrices.size();
  *topology_count = out.size();

  return out;
}

std::pair<std::vector<TopologyAndFilename>,
          std::vector<DemandMatrixAndFilename>>
GetDemandMatrixInputs(bool skip_trivial) {
  // Inputs.
  std::vector<TopologyAndFilename> topologies_out;
  std::vector<DemandMatrixAndFilename> demands_out;

  // Randomness to pick tms for each topology.
  std::mt19937 rnd(FLAGS_seed);

  size_t topology_count;
  size_t tm_count;
  std::map<std::string, std::vector<std::string>> topology_to_demands =
      GetTopologyToDemands(&topology_count, &tm_count);
  LOG(INFO) << "Will load " << tm_count << " TMs from " << topology_count
            << " topologies";
  for (auto& topology_and_demands : topology_to_demands) {
    const std::string& topology_file = topology_and_demands.first;
    std::vector<std::string>& demands_for_topology =
        topology_and_demands.second;

    std::vector<std::string> node_order;
    nc::net::GraphBuilder builder = nc::net::LoadRepetitaOrDie(
        nc::File::ReadFileToStringOrDie(topology_file), &node_order);
    builder.RemoveMultipleLinks();

    auto graph = nc::make_unique<nc::net::GraphStorage>(builder);
    nc::net::GraphStats stats = graph->Stats();
    CHECK(!stats.sp_delay_percentiles.empty());
    if (stats.sp_delay_percentiles.back() == nc::net::Delay::max()) {
      LOG(INFO) << "Skipping " << topology_file << " graph partitioned ";
      continue;
    }

    size_t node_count = graph->AllNodes().Count();
    if (node_count > FLAGS_topology_size_limit) {
      LOG(INFO) << "Skipping " << topology_file << " / " << topology_file
                << " size limit " << FLAGS_topology_size_limit << " vs "
                << node_count;
      continue;
    }

    nc::net::Delay diameter = graph->Stats().sp_delay_percentiles.back();
    if (diameter < milliseconds(FLAGS_topology_delay_limit_ms)) {
      LOG(INFO) << "Skipping " << topology_file << " / " << topology_file
                << " delay limit " << FLAGS_topology_delay_limit_ms
                << "ms vs diameter delay "
                << duration_cast<milliseconds>(diameter).count() << "ms";
      continue;
    }

    if (FLAGS_seed != 0) {
      std::shuffle(demands_for_topology.begin(), demands_for_topology.end(),
                   rnd);
    }

    demands_for_topology.resize(
        std::min(demands_for_topology.size(),
                 static_cast<size_t>(FLAGS_tm_per_topology)));
    for (const std::string& demand_file : demands_for_topology) {
      std::unique_ptr<nc::lp::DemandMatrix> demand_matrix =
          nc::lp::DemandMatrix::LoadRepetitaFileOrDie(demand_file, node_order,
                                                      graph.get());
      if (!demand_matrix) {
        LOG(INFO) << "Skipping " << demand_file << " inconsistent TM";
        continue;
      }

      if (skip_trivial) {
        const std::map<std::string, std::string>& props =
            demand_matrix->properties();

        bool trivial;
        if (nc::ContainsKey(props, "trivial")) {
          const std::string& trivial_str = nc::FindOrDie(props, "trivial");
          trivial = trivial_str == "true";
        } else {
          trivial = demand_matrix->IsTriviallySatisfiable();
        }

        if (trivial) {
          LOG(INFO) << "Skipping " << demand_file << " trivially satisfiable";
          continue;
        }
      }

      demands_out.emplace_back(topology_file, demand_file,
                               std::move(demand_matrix));
    }

    topologies_out.emplace_back(std::move(graph), node_order, topology_file);
  }

  return {std::move(topologies_out), std::move(demands_out)};
}

}  // namespace ctr
<|endoftext|>


<commit_before>#ifdef _MSC_VER
#include "All.h"
#include "Common.cpp"
#include "WhisperPeer.cpp"
#endif
<commit_msg>Windows updates.<commit_after>#ifdef _MSC_VER
#include "All.h"
#include "Common.cpp"
#include "WhisperPeer.cpp"
#include "WhisperHost.cpp"
#include "Message.cpp"
#include "Interface.cpp"
#endif
<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2016, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Florian Hauer */

#include <ompl/base/spaces/RealVectorStateSpace.h>
#include <ompl/geometric/planners/rrt/RRTstar.h>
#include <ompl/geometric/planners/rrt/RRTX.h>
#include <ompl/geometric/planners/rrt/RRTsharp.h>
#include <ompl/tools/benchmark/Benchmark.h>
#include <ompl/base/objectives/PathLengthOptimizationObjective.h>

#include <boost/math/constants/constants.hpp>
#include <boost/format.hpp>
#include <fstream>

class ValidityChecker : public ompl::base::StateValidityChecker
{
public:
    ValidityChecker(const ompl::base::SpaceInformationPtr &si): ompl::base::StateValidityChecker(si.get()) {}

    bool isValid(const ompl::base::State* state) const
    {
        const ompl::base::RealVectorStateSpace::StateType* state2D =
            state->as<ompl::base::RealVectorStateSpace::StateType>();

        double sum=0;
        for(unsigned i = 0; i<si_->getStateSpace()->as<ompl::base::RealVectorStateSpace>()->getDimension(); ++i)
            sum += state2D->values[i] * state2D->values[i];

        return sqrt(sum) > 0.1;
    }
};

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        std::cout << "Usage: " << argv[0] << " dimensionOfTheProblem" << std::endl;
        exit(0);
    }
    int dim = atoi(argv[1]);

    ompl::base::StateSpacePtr space(new ompl::base::RealVectorStateSpace(dim));
    ompl::geometric::SimpleSetup ss(space);
    space->as<ompl::base::RealVectorStateSpace>()->setBounds(-1,1);

    ss.setStateValidityChecker(ompl::base::StateValidityCheckerPtr(new ValidityChecker(ss.getSpaceInformation())));

    ompl::base::ScopedState<> start(space), goal(space);
    for(int i = 0; i < dim; ++i)
    {
        start[i] = -1;
        goal[i] = 1;
    }

    ss.setStartAndGoalStates(start, goal);

    // by default, use the Benchmark class
    double runtime_limit = 5, memory_limit = 1024;
    int run_count = 100;
    ompl::tools::Benchmark::Request request(runtime_limit, memory_limit, run_count, 0.05, true, true, false, false);
    ompl::tools::Benchmark b(ss, "Diagonal");

    double range = 0.1*sqrt(dim);

    ompl::base::OptimizationObjectivePtr lengthObj(new ompl::base::PathLengthOptimizationObjective(ss.getSpaceInformation()));
    ompl::base::OptimizationObjectivePtr oop;
    oop = (0.5 / sqrt(dim)) * lengthObj;

    ss.setOptimizationObjective(oop);

    bool knn=true;

    ompl::base::PlannerPtr rrtstar(new ompl::geometric::RRTstar(ss.getSpaceInformation()));
    rrtstar->as<ompl::geometric::RRTstar>()->setName("RRT*");
    rrtstar->as<ompl::geometric::RRTstar>()->setDelayCC(true);
    //rrtstar->as<ompl::geometric::RRTstar>()->setFocusSearch(true);
    rrtstar->as<ompl::geometric::RRTstar>()->setRange(range);
    rrtstar->as<ompl::geometric::RRTstar>()->setKNearest(knn);
    b.addPlanner(rrtstar);
    ompl::base::PlannerPtr rrtsh(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    b.addPlanner(rrtsh);
    /*ompl::base::PlannerPtr rrtsh3(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh3->as<ompl::geometric::RRTsharp>()->setName("RRT#v3");
    rrtsh3->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh3->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    rrtsh3->as<ompl::geometric::RRTsharp>()->setVariant(3);
    b.addPlanner(rrtsh3);
    ompl::base::PlannerPtr rrtsh2(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh2->as<ompl::geometric::RRTsharp>()->setName("RRT#v2");
    rrtsh2->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh2->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    rrtsh2->as<ompl::geometric::RRTsharp>()->setVariant(2);
    b.addPlanner(rrtsh2);*/
    ompl::base::PlannerPtr rrtX1(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX1->as<ompl::geometric::RRTX>()->setName("RRTX0.1");
    rrtX1->as<ompl::geometric::RRTX>()->setEpsilon(0.1);
    rrtX1->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX1->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX1->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX1);
    ompl::base::PlannerPtr rrtX2(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX2->as<ompl::geometric::RRTX>()->setName("RRTX0.01");
    rrtX2->as<ompl::geometric::RRTX>()->setEpsilon(0.01);
    rrtX2->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX2->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX2->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX2);
    ompl::base::PlannerPtr rrtX3(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX3->as<ompl::geometric::RRTX>()->setName("RRTX0.001");
    rrtX3->as<ompl::geometric::RRTX>()->setEpsilon(0.001);
    rrtX3->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX3->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX3->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX3);
    b.benchmark(request);
    b.saveResultsToFile(boost::str(boost::format("Diagonal.log")).c_str());

    exit(0);
}
<commit_msg>fixing license<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2016, Georgia Institute of Technology
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Florian Hauer */

#include <ompl/base/spaces/RealVectorStateSpace.h>
#include <ompl/geometric/planners/rrt/RRTstar.h>
#include <ompl/geometric/planners/rrt/RRTX.h>
#include <ompl/geometric/planners/rrt/RRTsharp.h>
#include <ompl/tools/benchmark/Benchmark.h>
#include <ompl/base/objectives/PathLengthOptimizationObjective.h>

#include <boost/math/constants/constants.hpp>
#include <boost/format.hpp>
#include <fstream>

class ValidityChecker : public ompl::base::StateValidityChecker
{
public:
    ValidityChecker(const ompl::base::SpaceInformationPtr &si): ompl::base::StateValidityChecker(si.get()) {}

    bool isValid(const ompl::base::State* state) const
    {
        const ompl::base::RealVectorStateSpace::StateType* state2D =
            state->as<ompl::base::RealVectorStateSpace::StateType>();

        double sum=0;
        for(unsigned i = 0; i<si_->getStateSpace()->as<ompl::base::RealVectorStateSpace>()->getDimension(); ++i)
            sum += state2D->values[i] * state2D->values[i];

        return sqrt(sum) > 0.1;
    }
};

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        std::cout << "Usage: " << argv[0] << " dimensionOfTheProblem" << std::endl;
        exit(0);
    }
    int dim = atoi(argv[1]);

    ompl::base::StateSpacePtr space(new ompl::base::RealVectorStateSpace(dim));
    ompl::geometric::SimpleSetup ss(space);
    space->as<ompl::base::RealVectorStateSpace>()->setBounds(-1,1);

    ss.setStateValidityChecker(ompl::base::StateValidityCheckerPtr(new ValidityChecker(ss.getSpaceInformation())));

    ompl::base::ScopedState<> start(space), goal(space);
    for(int i = 0; i < dim; ++i)
    {
        start[i] = -1;
        goal[i] = 1;
    }

    ss.setStartAndGoalStates(start, goal);

    // by default, use the Benchmark class
    double runtime_limit = 5, memory_limit = 1024;
    int run_count = 100;
    ompl::tools::Benchmark::Request request(runtime_limit, memory_limit, run_count, 0.05, true, true, false, false);
    ompl::tools::Benchmark b(ss, "Diagonal");

    double range = 0.1*sqrt(dim);

    ompl::base::OptimizationObjectivePtr lengthObj(new ompl::base::PathLengthOptimizationObjective(ss.getSpaceInformation()));
    ompl::base::OptimizationObjectivePtr oop;
    oop = (0.5 / sqrt(dim)) * lengthObj;

    ss.setOptimizationObjective(oop);

    bool knn=true;

    ompl::base::PlannerPtr rrtstar(new ompl::geometric::RRTstar(ss.getSpaceInformation()));
    rrtstar->as<ompl::geometric::RRTstar>()->setName("RRT*");
    rrtstar->as<ompl::geometric::RRTstar>()->setDelayCC(true);
    //rrtstar->as<ompl::geometric::RRTstar>()->setFocusSearch(true);
    rrtstar->as<ompl::geometric::RRTstar>()->setRange(range);
    rrtstar->as<ompl::geometric::RRTstar>()->setKNearest(knn);
    b.addPlanner(rrtstar);
    ompl::base::PlannerPtr rrtsh(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    b.addPlanner(rrtsh);
    /*ompl::base::PlannerPtr rrtsh3(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh3->as<ompl::geometric::RRTsharp>()->setName("RRT#v3");
    rrtsh3->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh3->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    rrtsh3->as<ompl::geometric::RRTsharp>()->setVariant(3);
    b.addPlanner(rrtsh3);
    ompl::base::PlannerPtr rrtsh2(new ompl::geometric::RRTsharp(ss.getSpaceInformation()));
    rrtsh2->as<ompl::geometric::RRTsharp>()->setName("RRT#v2");
    rrtsh2->as<ompl::geometric::RRTsharp>()->setRange(range);
    rrtsh2->as<ompl::geometric::RRTsharp>()->setKNearest(knn);
    rrtsh2->as<ompl::geometric::RRTsharp>()->setVariant(2);
    b.addPlanner(rrtsh2);*/
    ompl::base::PlannerPtr rrtX1(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX1->as<ompl::geometric::RRTX>()->setName("RRTX0.1");
    rrtX1->as<ompl::geometric::RRTX>()->setEpsilon(0.1);
    rrtX1->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX1->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX1->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX1);
    ompl::base::PlannerPtr rrtX2(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX2->as<ompl::geometric::RRTX>()->setName("RRTX0.01");
    rrtX2->as<ompl::geometric::RRTX>()->setEpsilon(0.01);
    rrtX2->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX2->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX2->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX2);
    ompl::base::PlannerPtr rrtX3(new ompl::geometric::RRTX(ss.getSpaceInformation()));
    rrtX3->as<ompl::geometric::RRTX>()->setName("RRTX0.001");
    rrtX3->as<ompl::geometric::RRTX>()->setEpsilon(0.001);
    rrtX3->as<ompl::geometric::RRTX>()->setRange(range);
    //rrtX3->as<ompl::geometric::RRTX>()->setVariant(3);
    rrtX3->as<ompl::geometric::RRTX>()->setKNearest(knn);
    b.addPlanner(rrtX3);
    b.benchmark(request);
    b.saveResultsToFile(boost::str(boost::format("Diagonal.log")).c_str());

    exit(0);
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      controller_console_options.cpp
  \author      (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief       RDO
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "app/rdo_studio_console/controller_console_options.h"
#include "app/rdo_studio_console/controller_console_options_config.h"
// --------------------------------------------------------------------------------

RDOControllerConsoleOptions::RDOControllerConsoleOptions(int argc, char *argv[])
{
	po::options_description options_header(RDO_STUDIO_CONSOLE_PROGRAMM_NAME + NOP_STRING + VERSION_COMMAND_SHORT +
		RDO_STUDIO_CONSOLE_VERSION + NOP_STRING + SYSTEM_OS + RDO_SITE);

	po::options_description options_general(_T("General options"));
	create_general_options(options_general);

	po::options_description options_additional(_T("Compatibility options (skipped in console version)"));
	create_additional_options(options_additional);

	m_options.add(options_header);
	m_options.add(options_general);
	m_options.add(options_additional);

	try
	{
		po::store(po::parse_command_line(argc, argv, m_options), m_variables);
		po::notify(m_variables);
	}
	catch (CREF(std::exception) e)
	{
		std::cout << _T("command line error: ") << e.what() << std::endl;
	}
}

void RDOControllerConsoleOptions::parseQuery()
{
	if (m_variables.empty() || m_variables.count(CHELP_COMMAND) ||
		(!m_variables.count(LANGUAGE_COMMAND) || !m_variables.count(VERSION_COMMAND) || !m_variables.count(INPUT_MODEL_COMMAND)))
	{
		std::cout << m_options << std::endl;
	}
	else if (m_variables.count(LANGUAGE_COMMAND))
	{
		std::cout << _T("rdo language v") + RDO_LANGUAGE_VERSION << std::endl;
	}
	else if (m_variables.count(VERSION_COMMAND))
	{
		std::cout << RDO_STUDIO_CONSOLE_PROGRAMM_NAME + NOP_STRING + VERSION_COMMAND_SHORT + RDO_STUDIO_CONSOLE_VERSION << std::endl;
	}
}

void RDOControllerConsoleOptions::getModelName(tstring& model_name)
{
	if(m_variables.count(INPUT_MODEL_COMMAND))
	{
		//! @todo added control input data
		model_name = m_variables[INPUT_MODEL_COMMAND].as<tstring>();
		return;
	}
	model_name = _T("");
}

void RDOControllerConsoleOptions::create_general_options(po::options_description& options)
{
	options.add_options()
		((INPUT_MODEL_COMMAND + COMMA_STRING + INPUT_MODEL_COMMAND_SHORT).c_str(), po::value<tstring>(), MODEL_COMMENT.c_str())
		((VERSION_COMMAND + COMMA_STRING + VERSION_COMMAND_SHORT).c_str(), VERSION_COMMENT.c_str())
		((CHELP_COMMAND + COMMA_STRING + HELP_COMMAND_SHORT).c_str(), HELP_COMMENT.c_str())
		((LANGUAGE_COMMAND + COMMA_STRING + LANGUAGE_COMMAND_SHORT).c_str(), LANGUAGE_COMMENT.c_str());
}

void RDOControllerConsoleOptions::create_additional_options(po::options_description& options)
{
	options.add_options()
		(AUTO_RUN_COMMAND.c_str(), AUTO_RUN_COMMENT.c_str())
		(AUTO_EXIT_COMMAND.c_str(), AUTO_EXIT_COMMENT.c_str())
		(DONT_CLOSE_IF_ERROR_COMMAND.c_str(), DONT_CLOSE_IF_ERROR_COMMENT.c_str())
		(PLUGIN_START_COMMAND.c_str(), PLUGIN_START_COMMENT.c_str())
		(PLUGIN_AUTO_EXIT_COMMAND.c_str(), PLUGIN_AUTO_EXIT_COMMENT.c_str());
}
<commit_msg> - fixed error processing command line options<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      controller_console_options.cpp
  \author      (lord.tiran@gmail.com)
  \date      26.10.2011
  \brief       RDO
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "app/rdo_studio_console/controller_console_options.h"
#include "app/rdo_studio_console/controller_console_options_config.h"
// --------------------------------------------------------------------------------

RDOControllerConsoleOptions::RDOControllerConsoleOptions(int argc, char *argv[])
{
	po::options_description options_header(RDO_STUDIO_CONSOLE_PROGRAMM_NAME + NOP_STRING + VERSION_COMMAND_SHORT +
		RDO_STUDIO_CONSOLE_VERSION + NOP_STRING + SYSTEM_OS + RDO_SITE);

	po::options_description options_general(_T("General options"));
	create_general_options(options_general);

	po::options_description options_additional(_T("Compatibility options (skipped in console version)"));
	create_additional_options(options_additional);

	m_options.add(options_header);
	m_options.add(options_general);
	m_options.add(options_additional);

	try
	{
		po::store(po::parse_command_line(argc, argv, m_options), m_variables);
		po::notify(m_variables);
	}
	catch (CREF(std::exception) e)
	{
		std::cout << _T("command line error: ") << e.what() << std::endl;
	}
}

void RDOControllerConsoleOptions::parseQuery()
{
	if (m_variables.empty() || m_variables.count(CHELP_COMMAND) &&
		!m_variables.count(LANGUAGE_COMMAND) && !m_variables.count(VERSION_COMMAND))
	{
		std::cout << m_options << std::endl;
	}
	else if (m_variables.count(LANGUAGE_COMMAND))
	{
		std::cout << _T("rdo language v") + RDO_LANGUAGE_VERSION << std::endl;
	}
	else if (m_variables.count(VERSION_COMMAND))
	{
		std::cout << RDO_STUDIO_CONSOLE_PROGRAMM_NAME + NOP_STRING + VERSION_COMMAND_SHORT + RDO_STUDIO_CONSOLE_VERSION << std::endl;
	}
}

void RDOControllerConsoleOptions::getModelName(tstring& model_name)
{
	if(m_variables.count(INPUT_MODEL_COMMAND))
	{
		//! @todo added control input data
		model_name = m_variables[INPUT_MODEL_COMMAND].as<tstring>();
		return;
	}
	model_name = _T("");
}

void RDOControllerConsoleOptions::create_general_options(po::options_description& options)
{
	options.add_options()
		((INPUT_MODEL_COMMAND + COMMA_STRING + INPUT_MODEL_COMMAND_SHORT).c_str(), po::value<tstring>(), MODEL_COMMENT.c_str())
		((VERSION_COMMAND + COMMA_STRING + VERSION_COMMAND_SHORT).c_str(), VERSION_COMMENT.c_str())
		((CHELP_COMMAND + COMMA_STRING + HELP_COMMAND_SHORT).c_str(), HELP_COMMENT.c_str())
		((LANGUAGE_COMMAND + COMMA_STRING + LANGUAGE_COMMAND_SHORT).c_str(), LANGUAGE_COMMENT.c_str());
}

void RDOControllerConsoleOptions::create_additional_options(po::options_description& options)
{
	options.add_options()
		(AUTO_RUN_COMMAND.c_str(), AUTO_RUN_COMMENT.c_str())
		(AUTO_EXIT_COMMAND.c_str(), AUTO_EXIT_COMMENT.c_str())
		(DONT_CLOSE_IF_ERROR_COMMAND.c_str(), DONT_CLOSE_IF_ERROR_COMMENT.c_str())
		(PLUGIN_START_COMMAND.c_str(), PLUGIN_START_COMMENT.c_str())
		(PLUGIN_AUTO_EXIT_COMMAND.c_str(), PLUGIN_AUTO_EXIT_COMMENT.c_str());
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2007 Vincent Ricard <magic@magicninja.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "strigiconfig.h"
#include "xbmthroughanalyzer.h"
#include "analysisresult.h"
#include "fieldtypes.h"

using namespace std;
using namespace Strigi;

// AnalyzerFactory
const string XbmThroughAnalyzerFactory::widthFieldName("image.width");
const string XbmThroughAnalyzerFactory::heightFieldName("image.height");
const string XbmThroughAnalyzerFactory::xHotFieldName("cursor.hot_spot.x");
const string XbmThroughAnalyzerFactory::yHotFieldName("cursor.hot_spot.y");

void
XbmThroughAnalyzerFactory::registerFields(FieldRegister& reg) {
    widthField = reg.registerField(widthFieldName,
        FieldRegister::integerType, 1, 0);
    heightField = reg.registerField(heightFieldName,
        FieldRegister::integerType, 1, 0);
    xHotField = reg.registerField(xHotFieldName,
        FieldRegister::integerType, 1, 0);
    yHotField = reg.registerField(yHotFieldName,
        FieldRegister::integerType, 1, 0);
}

// Analyzer
void
XbmThroughAnalyzer::setIndexable(AnalysisResult* i) {
    analysisResult = i;
}

/**
 * @returns the next offset, @c -1 if an error occurred.
 */
int32_t
processLine(const char* buf, int32_t bufSize, int32_t offset, int32_t& data) {
    // check we have a '#define'
    if (bufSize < offset+7 || strncmp(buf + offset, "#define", 7)) {
        return -1;
    }

    // skip spaces
    int32_t i = offset + 7;
    while (i < bufSize && (buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip the name of the define (should be /.*_width/ or /.*_height/ or /.*_x_hot/ or /.*_y_hot/)
    while (i < bufSize && !(buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip spaces
    while (i < bufSize && (buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    // check if we have a valid data
    if (i >= bufSize || !isdigit(buf[i]))
        return -1;

    // read the data
    data = 0;
    while (i < bufSize && isdigit(buf[i])) {
        data = (data * 10) + buf[i] - '0';
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip eol
    while (i < bufSize && (buf[i] == '\n' || buf[i] == '\r')) {
        i++;
    }

    return i;
}

InputStream*
XbmThroughAnalyzer::connectInputStream(InputStream* in) {
    const int32_t nreq = 16;
    int32_t nextOffset = 0;
    const char* buf;

    int32_t nread = in->read(buf, nreq, -1);
    in->reset(0);

    if (nread < nreq) {
        return in;
    }

    int32_t width;
    nextOffset = processLine(buf, nread, nextOffset, width);
    if (nextOffset == -1) {
        return in;
    }
    int32_t height;
    nextOffset = processLine(buf, nread, nextOffset, height);
    if (nextOffset == -1) {
        return in;
    }

    analysisResult->addValue(factory->widthField, width);
    analysisResult->addValue(factory->heightField, height);

    // these both fields are optional
    int32_t xHot;
    nextOffset = processLine(buf, nread, nextOffset, xHot);
    if (nextOffset != -1) {
        int32_t yHot;
        nextOffset = processLine(buf, nread, nextOffset, yHot);
        if (nextOffset != -1) {
            analysisResult->addValue(factory->xHotField, xHot);
            analysisResult->addValue(factory->yHotField, yHot);
        }
    }

    return in;
}

bool
XbmThroughAnalyzer::isReadyWithStream() {
    return true;
}

//Factory
class Factory : public AnalyzerFactoryFactory {
public:
    list<StreamThroughAnalyzerFactory*>
    streamThroughAnalyzerFactories() const {
        list<StreamThroughAnalyzerFactory*> af;
        af.push_back(new XbmThroughAnalyzerFactory());
        return af;
    }
};

STRIGI_ANALYZER_FACTORY(Factory)
<commit_msg>check for stream == 0 in the analyzer<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2007 Vincent Ricard <magic@magicninja.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "strigiconfig.h"
#include "xbmthroughanalyzer.h"
#include "analysisresult.h"
#include "fieldtypes.h"

using namespace std;
using namespace Strigi;

// AnalyzerFactory
const string XbmThroughAnalyzerFactory::widthFieldName("image.width");
const string XbmThroughAnalyzerFactory::heightFieldName("image.height");
const string XbmThroughAnalyzerFactory::xHotFieldName("cursor.hot_spot.x");
const string XbmThroughAnalyzerFactory::yHotFieldName("cursor.hot_spot.y");

void
XbmThroughAnalyzerFactory::registerFields(FieldRegister& reg) {
    widthField = reg.registerField(widthFieldName,
        FieldRegister::integerType, 1, 0);
    heightField = reg.registerField(heightFieldName,
        FieldRegister::integerType, 1, 0);
    xHotField = reg.registerField(xHotFieldName,
        FieldRegister::integerType, 1, 0);
    yHotField = reg.registerField(yHotFieldName,
        FieldRegister::integerType, 1, 0);
}

// Analyzer
void
XbmThroughAnalyzer::setIndexable(AnalysisResult* i) {
    analysisResult = i;
}

/**
 * @returns the next offset, @c -1 if an error occurred.
 */
int32_t
processLine(const char* buf, int32_t bufSize, int32_t offset, int32_t& data) {
    // check we have a '#define'
    if (bufSize < offset+7 || strncmp(buf + offset, "#define", 7)) {
        return -1;
    }

    // skip spaces
    int32_t i = offset + 7;
    while (i < bufSize && (buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip the name of the define (should be /.*_width/ or /.*_height/ or /.*_x_hot/ or /.*_y_hot/)
    while (i < bufSize && !(buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip spaces
    while (i < bufSize && (buf[i] == ' ' || buf[i] == '\t')) {
        i++;
    }
    // check if we have a valid data
    if (i >= bufSize || !isdigit(buf[i]))
        return -1;

    // read the data
    data = 0;
    while (i < bufSize && isdigit(buf[i])) {
        data = (data * 10) + buf[i] - '0';
        i++;
    }
    if (i >= bufSize)
        return -1;

    // skip eol
    while (i < bufSize && (buf[i] == '\n' || buf[i] == '\r')) {
        i++;
    }

    return i;
}

InputStream*
XbmThroughAnalyzer::connectInputStream(InputStream* in) {
    if (in == 0) return in;
    const int32_t nreq = 16;
    int32_t nextOffset = 0;
    const char* buf;

    int32_t nread = in->read(buf, nreq, -1);
    in->reset(0);

    if (nread < nreq) {
        return in;
    }

    int32_t width;
    nextOffset = processLine(buf, nread, nextOffset, width);
    if (nextOffset == -1) {
        return in;
    }
    int32_t height;
    nextOffset = processLine(buf, nread, nextOffset, height);
    if (nextOffset == -1) {
        return in;
    }

    analysisResult->addValue(factory->widthField, width);
    analysisResult->addValue(factory->heightField, height);

    // these both fields are optional
    int32_t xHot;
    nextOffset = processLine(buf, nread, nextOffset, xHot);
    if (nextOffset != -1) {
        int32_t yHot;
        nextOffset = processLine(buf, nread, nextOffset, yHot);
        if (nextOffset != -1) {
            analysisResult->addValue(factory->xHotField, xHot);
            analysisResult->addValue(factory->yHotField, yHot);
        }
    }

    return in;
}

bool
XbmThroughAnalyzer::isReadyWithStream() {
    return true;
}

//Factory
class Factory : public AnalyzerFactoryFactory {
public:
    list<StreamThroughAnalyzerFactory*>
    streamThroughAnalyzerFactories() const {
        list<StreamThroughAnalyzerFactory*> af;
        af.push_back(new XbmThroughAnalyzerFactory());
        return af;
    }
};

STRIGI_ANALYZER_FACTORY(Factory)
<|endoftext|>