<commit_before>// @(#)root/eve7:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/REveDataSimpleProxyBuilder.hxx>

#include <ROOT/REveDataCollection.hxx>
#include <ROOT/REveCompound.hxx>
#include <ROOT/REveScene.hxx>
#include <ROOT/RLogger.hxx>
#include <cassert>
#include <TClass.h>

using namespace ROOT::Experimental;

REveDataSimpleProxyBuilder::REveDataSimpleProxyBuilder()
{}

REveDataSimpleProxyBuilder::~REveDataSimpleProxyBuilder()
{
   for (auto &p : m_products) {
      for (auto &compound : p->m_elements->RefChildren())
         compound->DecDenyDestroy();
   }
}

void REveDataSimpleProxyBuilder::Clean()
{
   for (auto &p : m_products) {
      auto spbIt = fProductMap.find(p->m_elements);
      if (spbIt != fProductMap.end()) {
         REveElement *product = p->m_elements;
         for (auto &compound : product->RefChildren()) {
            REveCollectionCompound *collComp = dynamic_cast<REveCollectionCompound *>(compound);
            collComp->DestroyElements();
         }
         (spbIt)->second->lastChildIdx=0;
         (spbIt)->second->map.clear();
      }
   }

   CleanLocal();
}

//______________________________________________________________________________
REveCollectionCompound*
REveDataSimpleProxyBuilder::CreateCompound(bool set_color, bool propagate_color_to_all_children)
{
   REveCollectionCompound *c = new REveCollectionCompound(Collection());
   c->IncDenyDestroy();
   c->CSCImplySelectAllChildren();
   c->SetPickable(true);
   if (set_color)
   {
      c->SetMainColor(Collection()->GetMainColor());
      c->SetMainTransparency(Collection()->GetMainTransparency());
   }
   if (propagate_color_to_all_children)
   {
      c->CSCApplyMainColorToAllChildren();
      c->CSCApplyMainTransparencyToAllChildren();
   }
   else
   {
      c->CSCApplyMainColorToMatchingChildren();
      c->CSCApplyMainTransparencyToMatchingChildren();
   }
   return c;
}

//______________________________________________________________________________
REveCompound *REveDataSimpleProxyBuilder::GetHolder(REveElement *product, int idx)
{
   SPBProduct *spb = nullptr;

   // printf("REveDataSimpleProxyBuilder::GetHolder begin %s %d \n", Collection()->GetCName(), idx);

   auto it = fProductMap.find(product);
   if (it != fProductMap.end()) {
      spb = it->second;
   } else {
      spb = new SPBProduct;
      fProductMap.emplace(product, spb);
   }

   REveCollectionCompound *itemHolder = nullptr;

   auto pmIt = spb->map.find(idx);
   if (pmIt != spb->map.end()) {
      itemHolder = pmIt->second;
      // printf("GetHolder already in map %d \n", idx);
   } else {
      if (product->NumChildren() > idx) {
         auto cIt = std::next(product->RefChildren().begin(), idx);
         itemHolder = dynamic_cast<REveCollectionCompound *>(*cIt);
         // printf("GetHolder isreused %d \n", idx);
      }
      if (!itemHolder) {
         itemHolder = CreateCompound(true, true);
         product->AddElement(itemHolder);
         // printf("Creating new holder\n");
      }
      spb->lastChildIdx = idx;
      spb->map.emplace(idx, itemHolder);
      itemHolder->SetMainColor(Collection()->GetDataItem(idx)->GetMainColor());
      std::string name(TString::Format("%s %d", Collection()->GetCName(), idx));
      itemHolder->SetName(name);
   }

   return itemHolder;
}

void
REveDataSimpleProxyBuilder::Build(const REveDataCollection *collection,
                                  REveElement* product, const REveViewContext* vc)
{
   // printf("REveDataSimpleProxyBuilder::Build %s %d\n", collection->GetCName(), collection->GetNItems());
   auto size = collection->GetNItems();
   for (int index = 0; index < size; ++index)
   {
      const REveDataItem* di = Collection()->GetDataItem(index);
      if (di->GetRnrSelf() && !di->GetFiltered())
      {
         REveCompound *itemHolder = GetHolder(product, index);
         Build(collection->GetDataPtr(index), index, itemHolder, vc);
      }
   }
}

void
REveDataSimpleProxyBuilder::BuildViewType(const REveDataCollection* collection,
                                          REveElement* product, const std::string& viewType, const REveViewContext* vc)
{
   auto size = collection->GetNItems();
   for (int index = 0; index < size; ++index)
   {
      auto di = Collection()->GetDataItem(index);
      if (di->GetRnrSelf() && !di->GetFiltered())
      {
         REveCompound *itemHolder = GetHolder(product, index);
         BuildViewType(collection->GetDataPtr(index), index, itemHolder, viewType, vc);
      }
   }
   //      printf("END Build view type [%s] product size %d\n",viewType.c_str(), product->NumChildren());
}

//______________________________________________________________________________

namespace
{
   void applyColorAttrToChildren(REveElement* p) {
      for (auto &it: p->RefChildren())
      {
         REveElement* c = it;
         if (c->GetMainColor() != p->GetMainColor())
         {
            c->SetMainColor(p->GetMainColor());
         }
         applyColorAttrToChildren(c);
      }
   }
}

void REveDataSimpleProxyBuilder::ModelChanges(const REveDataCollection::Ids_t &iIds, Product *p)
{
   for (auto itemIdx : iIds) {
      const REveDataItem *item = Collection()->GetDataItem(itemIdx);
      bool visible = ((!item->GetFiltered()) && item->GetRnrSelf()) && Collection()->GetRnrSelf();

      auto sit = fProductMap.find(p->m_elements);
      if (sit == fProductMap.end())
         return;

      auto spb = sit->second;
      REveCompound *holder = nullptr;
      auto hmit = spb->map.find(itemIdx);
      if (hmit != spb->map.end())
         holder = hmit->second;

      bool createHolder = visible && !holder;

      if (createHolder) {
         holder = GetHolder(p->m_elements, itemIdx);

         if (HaveSingleProduct())
            Build(Collection()->GetDataPtr(itemIdx), itemIdx, holder, p->m_viewContext);
         else

            applyColorAttrToChildren(holder);
         p->m_elements->ProjectChild(holder);
      } else if (holder) {
         holder->SetRnrSelf(visible);
         holder->SetRnrChildren(visible);
         holder->SetMainColor(item->GetMainColor());
         applyColorAttrToChildren(holder);
         LocalModelChanges(itemIdx, holder, p->m_viewContext);
      }
   }
}
//______________________________________________________________________________

bool
REveDataSimpleProxyBuilder::VisibilityModelChanges(int idx, REveElement* iCompound, const std::string& viewType, const REveViewContext* vc)
{
   const REveDataItem *item = Collection()->GetDataItem(idx);
   bool returnValue = false;

   if (item->GetVisible() ) {
      if (HaveSingleProduct())
         Build(Collection()->GetDataPtr(idx), idx, iCompound, vc);
      else
         BuildViewType(Collection()->GetDataPtr(idx), idx, iCompound, viewType, vc);
      returnValue = true;
   }
   return returnValue;
}

//______________________________________________________________________________

void REveDataSimpleProxyBuilder::FillImpliedSelected(REveElement::Set_t &impSet, Product* p)
{
   for (auto &s : Collection()->GetItemList()->RefSelectedSet()) {
      // printf("Fill implied selected %d \n", s);
      auto spb = fProductMap[p->m_elements];
      auto it = spb->map.find(s);
      if (it != spb->map.end()) {
         // printf("Fill implied selected %s \n", it->second->GetCName());
         it->second->FillImpliedSelectedSet(impSet);
      }
   }
}

//==============================================================================

//==============================================================================

//==============================================================================

REveCollectionCompound::REveCollectionCompound(REveDataCollection* c)
{
   fCollection = c;
   SetSelectionMaster(fCollection);
}

//______________________________________________________________________________

REveCollectionCompound::~REveCollectionCompound()
{
   // deny destroy ??
}

//______________________________________________________________________________

REveElement *REveCollectionCompound::GetSelectionMaster()
{
   static const REveException eh("REveCollectionCompound::GetSelectionMaster()");

   if (!fCollection->GetScene()->IsAcceptingChanges())
      return fCollection->GetItemList();

   fCollection->GetItemList()->RefSelectedSet().clear();
   try {

      std::size_t found = fName.find_last_of(" ");
      if (found == std::string::npos)
      {
         throw(eh + TString::Format("Can't retrive item index from %s", fName.c_str()));
      }
      std::string idss = fName.substr(found + 1);
      int idx = stoi(idss);
      // printf("REveCollectionCompound::GetSelectionMaster %d\n", idx);
      fCollection->GetItemList()->RefSelectedSet().insert(idx);
   } catch (std::exception& e) {
       R__LOG_ERROR(REveLog()) << "REveCollectionCompound::GetSelectionMaster " << e.what() << std::endl;
       fCollection->GetItemList()->RefSelectedSet().insert(0);
   }
   return fCollection->GetItemList();
}
<commit_msg>Fix bug in visibility change update.<commit_after>// @(#)root/eve7:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2020

/*************************************************************************
 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/REveDataSimpleProxyBuilder.hxx>

#include <ROOT/REveDataCollection.hxx>
#include <ROOT/REveCompound.hxx>
#include <ROOT/REveScene.hxx>
#include <ROOT/RLogger.hxx>
#include <cassert>
#include <TClass.h>

using namespace ROOT::Experimental;

REveDataSimpleProxyBuilder::REveDataSimpleProxyBuilder()
{}

REveDataSimpleProxyBuilder::~REveDataSimpleProxyBuilder()
{
   for (auto &p : m_products) {
      for (auto &compound : p->m_elements->RefChildren())
         compound->DecDenyDestroy();
   }
}

void REveDataSimpleProxyBuilder::Clean()
{
   for (auto &p : m_products) {
      auto spbIt = fProductMap.find(p->m_elements);
      if (spbIt != fProductMap.end()) {
         REveElement *product = p->m_elements;
         for (auto &compound : product->RefChildren()) {
            REveCollectionCompound *collComp = dynamic_cast<REveCollectionCompound *>(compound);
            collComp->DestroyElements();
         }
         (spbIt)->second->lastChildIdx=0;
         (spbIt)->second->map.clear();
      }
   }

   CleanLocal();
}

//______________________________________________________________________________
REveElement *REveDataSimpleProxyBuilder::CreateProduct(const std::string &viewType, const REveViewContext *viewContext)
{
   REveElement *productEl = REveDataProxyBuilderBase::CreateProduct(viewType, viewContext);
   auto it = fProductMap.find(productEl);
   if (it == fProductMap.end())
      fProductMap.emplace(productEl, new SPBProduct);
   return productEl;
}
//______________________________________________________________________________
REveCollectionCompound*
REveDataSimpleProxyBuilder::CreateCompound(bool set_color, bool propagate_color_to_all_children)
{
   REveCollectionCompound *c = new REveCollectionCompound(Collection());
   c->IncDenyDestroy();
   c->CSCImplySelectAllChildren();
   c->SetPickable(true);
   if (set_color)
   {
      c->SetMainColor(Collection()->GetMainColor());
      c->SetMainTransparency(Collection()->GetMainTransparency());
   }
   if (propagate_color_to_all_children)
   {
      c->CSCApplyMainColorToAllChildren();
      c->CSCApplyMainTransparencyToAllChildren();
   }
   else
   {
      c->CSCApplyMainColorToMatchingChildren();
      c->CSCApplyMainTransparencyToMatchingChildren();
   }
   return c;
}

//______________________________________________________________________________
REveCompound *REveDataSimpleProxyBuilder::GetHolder(REveElement *product, int idx)
{
   SPBProduct *spb = nullptr;

   // printf("REveDataSimpleProxyBuilder::GetHolder begin %s %d \n", Collection()->GetCName(), idx);

   auto it = fProductMap.find(product);
   if (it != fProductMap.end()) {
      spb = it->second;
   } else {
      spb = new SPBProduct;
      fProductMap.emplace(product, spb);
   }

   REveCollectionCompound *itemHolder = nullptr;

   auto pmIt = spb->map.find(idx);
   if (pmIt != spb->map.end()) {
      itemHolder = pmIt->second;
      // printf("GetHolder already in map %d \n", idx);
   } else {
      if (product->NumChildren() > idx) {
         auto cIt = std::next(product->RefChildren().begin(), idx);
         itemHolder = dynamic_cast<REveCollectionCompound *>(*cIt);
         // printf("GetHolder isreused %d \n", idx);
      }
      if (!itemHolder) {
         itemHolder = CreateCompound(true, true);
         product->AddElement(itemHolder);
         // printf("Creating new holder\n");
      }
      spb->lastChildIdx = idx;
      spb->map.emplace(idx, itemHolder);
      itemHolder->SetMainColor(Collection()->GetDataItem(idx)->GetMainColor());
      std::string name(TString::Format("%s %d", Collection()->GetCName(), idx));
      itemHolder->SetName(name);
   }

   return itemHolder;
}

void
REveDataSimpleProxyBuilder::Build(const REveDataCollection *collection,
                                  REveElement* product, const REveViewContext* vc)
{
   // printf("REveDataSimpleProxyBuilder::Build %s %d\n", collection->GetCName(), collection->GetNItems());
   auto size = collection->GetNItems();
   for (int index = 0; index < size; ++index)
   {
      const REveDataItem* di = Collection()->GetDataItem(index);
      if (di->GetRnrSelf() && !di->GetFiltered())
      {
         REveCompound *itemHolder = GetHolder(product, index);
         Build(collection->GetDataPtr(index), index, itemHolder, vc);
      }
   }
}

void
REveDataSimpleProxyBuilder::BuildViewType(const REveDataCollection* collection,
                                          REveElement* product, const std::string& viewType, const REveViewContext* vc)
{
   auto size = collection->GetNItems();
   for (int index = 0; index < size; ++index)
   {
      auto di = Collection()->GetDataItem(index);
      if (di->GetRnrSelf() && !di->GetFiltered())
      {
         REveCompound *itemHolder = GetHolder(product, index);
         BuildViewType(collection->GetDataPtr(index), index, itemHolder, viewType, vc);
      }
   }
   //      printf("END Build view type [%s] product size %d\n",viewType.c_str(), product->NumChildren());
}

//______________________________________________________________________________

namespace
{
   void applyColorAttrToChildren(REveElement* p) {
      for (auto &it: p->RefChildren())
      {
         REveElement* c = it;
         if (c->GetMainColor() != p->GetMainColor())
         {
            c->SetMainColor(p->GetMainColor());
         }
         applyColorAttrToChildren(c);
      }
   }
}

void REveDataSimpleProxyBuilder::ModelChanges(const REveDataCollection::Ids_t &iIds, Product *p)
{
   for (auto itemIdx : iIds) {
      const REveDataItem *item = Collection()->GetDataItem(itemIdx);
      bool visible = ((!item->GetFiltered()) && item->GetRnrSelf()) && Collection()->GetRnrSelf();

      auto sit = fProductMap.find(p->m_elements);
      if (sit == fProductMap.end()) {
         std::error << "REveDataSimpleProxyBuilder::ModelChanges product not found!\n";
         return;
      }
      auto spb = sit->second;
      REveCompound *holder = nullptr;
      auto hmit = spb->map.find(itemIdx);
      if (hmit != spb->map.end())
         holder = hmit->second;

      bool createHolder = visible && !holder;

      if (createHolder) {
         holder = GetHolder(p->m_elements, itemIdx);

         if (HaveSingleProduct())
            Build(Collection()->GetDataPtr(itemIdx), itemIdx, holder, p->m_viewContext);
         else
            BuildViewType(Collection()->GetDataPtr(itemIdx), itemIdx, holder, p->m_viewType,  p->m_viewContext);

         applyColorAttrToChildren(holder);
         p->m_elements->ProjectChild(holder);
      } else if (holder) {
         holder->SetRnrSelf(visible);
         holder->SetRnrChildren(visible);
         holder->SetMainColor(item->GetMainColor());
         applyColorAttrToChildren(holder);
         LocalModelChanges(itemIdx, holder, p->m_viewContext);
      }
   }
}
//______________________________________________________________________________

bool
REveDataSimpleProxyBuilder::VisibilityModelChanges(int idx, REveElement* iCompound, const std::string& viewType, const REveViewContext* vc)
{
   const REveDataItem *item = Collection()->GetDataItem(idx);
   bool returnValue = false;

   if (item->GetVisible() ) {
      if (HaveSingleProduct())
         Build(Collection()->GetDataPtr(idx), idx, iCompound, vc);
      else
         BuildViewType(Collection()->GetDataPtr(idx), idx, iCompound, viewType, vc);
      returnValue = true;
   }
   return returnValue;
}

//______________________________________________________________________________

void REveDataSimpleProxyBuilder::FillImpliedSelected(REveElement::Set_t &impSet, Product* p)
{
   for (auto &s : Collection()->GetItemList()->RefSelectedSet()) {
      // printf("Fill implied selected %d \n", s);
      auto spb = fProductMap[p->m_elements];
      auto it = spb->map.find(s);
      if (it != spb->map.end()) {
         // printf("Fill implied selected %s \n", it->second->GetCName());
         it->second->FillImpliedSelectedSet(impSet);
      }
   }
}

//==============================================================================

//==============================================================================

//==============================================================================

REveCollectionCompound::REveCollectionCompound(REveDataCollection* c)
{
   fCollection = c;
   SetSelectionMaster(fCollection);
}

//______________________________________________________________________________

REveCollectionCompound::~REveCollectionCompound()
{
   // deny destroy ??
}

//______________________________________________________________________________

REveElement *REveCollectionCompound::GetSelectionMaster()
{
   static const REveException eh("REveCollectionCompound::GetSelectionMaster()");

   if (!fCollection->GetScene()->IsAcceptingChanges())
      return fCollection->GetItemList();

   fCollection->GetItemList()->RefSelectedSet().clear();
   try {

      std::size_t found = fName.find_last_of(" ");
      if (found == std::string::npos)
      {
         throw(eh + TString::Format("Can't retrive item index from %s", fName.c_str()));
      }
      std::string idss = fName.substr(found + 1);
      int idx = stoi(idss);
      // printf("REveCollectionCompound::GetSelectionMaster %d\n", idx);
      fCollection->GetItemList()->RefSelectedSet().insert(idx);
   } catch (std::exception& e) {
       R__LOG_ERROR(REveLog()) << "REveCollectionCompound::GetSelectionMaster " << e.what() << std::endl;
       fCollection->GetItemList()->RefSelectedSet().insert(0);
   }
   return fCollection->GetItemList();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>
#include <libport/unistd.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#ifdef STATIC_BUILD
# include <urbi/umain.hh>
#endif

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val = "")
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

static std::string
urbi_getenv(const std::string& self,
            std::string var,
            const std::string& val = "")
{
  var = "URBI_" + var;
  const char* res = getenv(var.c_str());
  if (res)
  {
    std::cerr << self << ": obeying to " << var << " = " << res << std::endl;
    return res;
  }
  else
    return val;
}

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)               \
  do {                                          \
    if (debug())                                \
      URBI_ROOT_ECHO(Self << ": " << S);        \
  } while (0)

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
# define RTLD_LAZY 0
# define RTLD_NOW 0
# define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return static_cast<void*>(GetProcAddress(module, name));
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos = lib.find(':');

  if ((pos = lib.find(':')) == lib.npos)
  {
    res.push_back(lib);
    return res;
  }

  do
  {
    std::string s = lib.substr(0, pos);
    if (pos != lib.npos)
    {
      lib = lib.substr(pos + 1, lib.npos);
      pos = lib.find(':');
    }
    else
      lib.clear();

#ifdef WIN32
    // Colon could be used as a path separator under cygwin and as a volume
    // separator under windows.
    if (s[0] == '\\' && !res.empty())
    {
      std::string& back = res.back();
      size_t back_len = back.length();

      // In case we split "c:\foo" into "c" and "\foo", glue them
      // together again.
      if (back_len == 1)
        back += ':' + s;

      // In case we split "bar;c:\foo" into "bar;c" and "\foo", split them
      // into "bar" and "c:\foo"
      else if (back_len >= 2 && back[back_len - 2] == ';')
      {
        s = std::string("") + back[back_len - 1] + ':' + s;
        back = back.substr(0, back_len - 2);
        res.push_back(s);
      }
    }
    else
      res.push_back(s);
#else
    res.push_back(s);
#endif

  } while (!lib.empty());

  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), sizeof path - 1);
  path[sizeof path - 1] = 0;
  while (readlink(path, path, sizeof path) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/// Find \a prog in $PATH.
/// \param logname  the prefix for log messages
/// \param prog     the program to look for (.exe will be appended on Windows)
/// \return  The full path to the parent of the directory that contains
///          \a prog, or "" if not found.
static
std::string
find_program(const std::string& logname,
             std::string prog)
{
#ifdef WIN32
  size_t pos = prog.find_last_of("/\\");
  {
    size_t dot = prog.find_last_of(".");
    if (dot == prog.npos || prog.substr(dot + 1) != "exe")
      prog += ".exe";
  }
#else
  size_t pos = prog.rfind('/');
#endif
  if (pos == std::string::npos)
  {
    struct stat stats;
    std::string dir, file;
    bool found = false;

#ifdef WIN32
    URBI_ROOT_DEBUG(logname,
                    "check if invoked from the current directory");

    {
      char *dir_buf = getcwd(0, 0);
      std::string dir(dir_buf);
      free(dir_buf);
      file = dir / prog;
    }

    found = stat(file.c_str(), &stats) == 0;
    if (!found)
    {
      URBI_ROOT_DEBUG(logname, "not found: " << file);
#endif
      URBI_ROOT_DEBUG(logname,
                      "check if invoked from the path");
      strings_type path = split(mygetenv("PATH"));
      foreach (const std::string& dir_, path)
      {
        file = dir_ / prog;
        found = stat(file.c_str(), &stats) == 0;
        if (found)
        {
          dir = dir_;
          break;
        }
        URBI_ROOT_DEBUG(logname, "not found: " << file);
      }
#ifdef WIN32
    }
#endif

    if (found)
    {
      URBI_ROOT_DEBUG(logname, "found: " << file);
      std::string res = dir / "..";
      URBI_ROOT_DEBUG(logname, "root directory is: " << res);
      return res;
    }
  }
  else
  {
    std::string res = prog.substr(0, pos) / "..";
    URBI_ROOT_DEBUG(logname,
                    "invoked with a path, setting root to parent directory: "
                    << res);
    return res;
  }
  return "";
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = urbi_getenv(program, "ROOT");
  if (uroot.empty())
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);
    root_ = find_program(program_, argv0);
  }
  else
  {
    root_ = uroot;
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg4urbi");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
#ifdef LIBPORT_ENABLE_SERIALIZATION
    handle_libserialize_ = library_load("serialize");
#endif
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base, const std::string& env_suffix)
{
  std::string envvar;
  if (env_suffix.empty())
    envvar = "ROOT_LIB" + base;
  else
    envvar = "ROOT_LIB" + env_suffix;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            urbi_getenv(program_, envvar,
                        root() / libdir / "lib" + base + library_suffix()));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / LIBPORT_LIBDIRNAME / "gostai";
}

std::string
UrbiRoot::doc_dir() const
{
  return urbi_getenv(program_, "DOC", share_dir() / "doc");
}

std::string
UrbiRoot::share_dir() const
{
  return urbi_getenv(program_, "SHARE", root() / "share" / "gostai");
}

std::vector<std::string>
UrbiRoot::uobjects_path() const
{
  std::vector<std::string> res;
  if (!library_suffix().empty())
    res.push_back(core_path() / "uobjects" + library_suffix());
  res.push_back(core_path() / "uobjects");
  return res;
}

std::string
UrbiRoot::library_suffix() const
{
  return LIBPORT_LIBSFX;
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            urbi_getenv(program_, "ROOT_LIBPLUGIN",
                        core_path() / "engine" / "libuobject"+library_suffix()),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            urbi_getenv(program_, "ROOT_LIBREMOTE",
                        core_path() / "remote" / "libuobject"+library_suffix()),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
#ifdef STATIC_BUILD
  return ::urbi_main_args(args, *this, block, errors);
#else
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
#endif
}
<commit_msg>urbi: less verbosity when URBI_* are defined.<commit_after>/*
 * Copyright (C) 2009-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>
#include <libport/unistd.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#ifdef STATIC_BUILD
# include <urbi/umain.hh>
#endif

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

static std::string
mygetenv(const std::string& var, const std::string& val = "");

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)               \
  do {                                          \
    if (debug())                                \
      URBI_ROOT_ECHO(Self << ": " << S);        \
  } while (0)

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val)
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

static std::string
urbi_getenv(const std::string& logname,
            std::string var,
            const std::string& val = "")
{
  var = "URBI_" + var;
  const char* res = getenv(var.c_str());
  if (res)
  {
    URBI_ROOT_DEBUG(logname, "obeying to " << var << " = " << res);
    return res;
  }
  else
    return val;
}

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
# define RTLD_LAZY 0
# define RTLD_NOW 0
# define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return static_cast<void*>(GetProcAddress(module, name));
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos = lib.find(':');

  if ((pos = lib.find(':')) == lib.npos)
  {
    res.push_back(lib);
    return res;
  }

  do
  {
    std::string s = lib.substr(0, pos);
    if (pos != lib.npos)
    {
      lib = lib.substr(pos + 1, lib.npos);
      pos = lib.find(':');
    }
    else
      lib.clear();

#ifdef WIN32
    // Colon could be used as a path separator under cygwin and as a volume
    // separator under windows.
    if (s[0] == '\\' && !res.empty())
    {
      std::string& back = res.back();
      size_t back_len = back.length();

      // In case we split "c:\foo" into "c" and "\foo", glue them
      // together again.
      if (back_len == 1)
        back += ':' + s;

      // In case we split "bar;c:\foo" into "bar;c" and "\foo", split them
      // into "bar" and "c:\foo"
      else if (back_len >= 2 && back[back_len - 2] == ';')
      {
        s = std::string("") + back[back_len - 1] + ':' + s;
        back = back.substr(0, back_len - 2);
        res.push_back(s);
      }
    }
    else
      res.push_back(s);
#else
    res.push_back(s);
#endif

  } while (!lib.empty());

  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), sizeof path - 1);
  path[sizeof path - 1] = 0;
  while (readlink(path, path, sizeof path) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/// Find \a prog in $PATH.
/// \param logname  the prefix for log messages
/// \param prog     the program to look for (.exe will be appended on Windows)
/// \return  The full path to the parent of the directory that contains
///          \a prog, or "" if not found.
static
std::string
find_program(const std::string& logname,
             std::string prog)
{
#ifdef WIN32
  size_t pos = prog.find_last_of("/\\");
  {
    size_t dot = prog.find_last_of(".");
    if (dot == prog.npos || prog.substr(dot + 1) != "exe")
      prog += ".exe";
  }
#else
  size_t pos = prog.rfind('/');
#endif
  if (pos == std::string::npos)
  {
    struct stat stats;
    std::string dir, file;
    bool found = false;

#ifdef WIN32
    URBI_ROOT_DEBUG(logname,
                    "check if invoked from the current directory");

    {
      char *dir_buf = getcwd(0, 0);
      std::string dir(dir_buf);
      free(dir_buf);
      file = dir / prog;
    }

    found = stat(file.c_str(), &stats) == 0;
    if (!found)
    {
      URBI_ROOT_DEBUG(logname, "not found: " << file);
#endif
      URBI_ROOT_DEBUG(logname,
                      "check if invoked from the path");
      strings_type path = split(mygetenv("PATH"));
      foreach (const std::string& dir_, path)
      {
        file = dir_ / prog;
        found = stat(file.c_str(), &stats) == 0;
        if (found)
        {
          dir = dir_;
          break;
        }
        URBI_ROOT_DEBUG(logname, "not found: " << file);
      }
#ifdef WIN32
    }
#endif

    if (found)
    {
      URBI_ROOT_DEBUG(logname, "found: " << file);
      std::string res = dir / "..";
      URBI_ROOT_DEBUG(logname, "root directory is: " << res);
      return res;
    }
  }
  else
  {
    std::string res = prog.substr(0, pos) / "..";
    URBI_ROOT_DEBUG(logname,
                    "invoked with a path, setting root to parent directory: "
                    << res);
    return res;
  }
  return "";
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = urbi_getenv(program, "ROOT");
  if (uroot.empty())
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);
    root_ = find_program(program_, argv0);
  }
  else
  {
    root_ = uroot;
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg4urbi");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
#ifdef LIBPORT_ENABLE_SERIALIZATION
    handle_libserialize_ = library_load("serialize");
#endif
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base, const std::string& env_suffix)
{
  std::string envvar;
  if (env_suffix.empty())
    envvar = "ROOT_LIB" + base;
  else
    envvar = "ROOT_LIB" + env_suffix;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            urbi_getenv(program_, envvar,
                        root() / libdir / "lib" + base + library_suffix()));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / LIBPORT_LIBDIRNAME / "gostai";
}

std::string
UrbiRoot::doc_dir() const
{
  return urbi_getenv(program_, "DOC", share_dir() / "doc");
}

std::string
UrbiRoot::share_dir() const
{
  return urbi_getenv(program_, "SHARE", root() / "share" / "gostai");
}

std::vector<std::string>
UrbiRoot::uobjects_path() const
{
  std::vector<std::string> res;
  if (!library_suffix().empty())
    res.push_back(core_path() / "uobjects" + library_suffix());
  res.push_back(core_path() / "uobjects");
  return res;
}

std::string
UrbiRoot::library_suffix() const
{
  return LIBPORT_LIBSFX;
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            urbi_getenv(program_, "ROOT_LIBPLUGIN",
                        core_path() / "engine" / "libuobject"+library_suffix()),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            urbi_getenv(program_, "ROOT_LIBREMOTE",
                        core_path() / "remote" / "libuobject"+library_suffix()),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
#ifdef STATIC_BUILD
  return ::urbi_main_args(args, *this, block, errors);
#else
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
#endif
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>
#include <libport/unistd.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#ifdef STATIC_BUILD
# include <urbi/umain.hh>
#endif
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val = "")
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || mygetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos = lib.find(':');

  if ((pos = lib.find(':')) == lib.npos)
  {
    res.push_back(lib);
    return res;
  }

  do
  {
    std::string s = lib.substr(0, pos);
    if (pos != lib.npos)
    {
      lib = lib.substr(pos + 1, lib.npos);
      pos = lib.find(':');
    }
    else
      lib.clear();

#ifdef WIN32
    // Colon could be used as a path separator under cygwin and as a volume
    // separator under windows.
    if (s[0] == '\\' && !res.empty())
    {
      std::string& back = res.back();
      size_t back_len = back.length();

      // In case we split "c:\foo" into "c" and "\foo", glue them
      // together again.
      if (back_len == 1)
        back += ':' + s;

      // In case we split "bar;c:\foo" into "bar;c" and "\foo", split them
      // into "bar" and "c:\foo"
      else if (back_len >= 2 && back[back_len - 2] == ';')
      {
        s = std::string("") + back[back_len - 1] + ':' + s;
        back = back.substr(0, back_len - 2);
        res.push_back(s);
      }
    }
    else
      res.push_back(s);
#else
    res.push_back(s);
#endif

  } while (!lib.empty());

  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = mygetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
    {
      size_t dot = argv0.find_last_of(".");
      if (dot == argv0.npos || argv0.substr(dot + 1) != "exe")
        argv0 += ".exe";
    }
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      struct stat stats;
      std::string dir, file;
      bool found = false;

#ifdef WIN32
      URBI_ROOT_DEBUG(program_,
                      "check if invoked from the current directory");

      {
        char *dir_buf = getcwd(0, 0);
        std::string dir(dir_buf);
        free(dir_buf);
        file = dir / argv0;
      }

      if (!(found = stat(file.c_str(), &stats) == 0))
      {
        URBI_ROOT_DEBUG(program_, "not found: " << file);
#endif
        URBI_ROOT_DEBUG(program_,
                        "check if invoked from the path");
        strings_type path = split(mygetenv("PATH"));
        foreach (const std::string& dir_, path)
        {
          file = dir_ / argv0;
          if (found = (stat(file.c_str(), &stats) == 0))
          {
            dir = dir_;
            break;
          }
          URBI_ROOT_DEBUG(program_, "not found: " << file);
        }
#ifdef WIN32
      }
#endif

      if (found)
      {
        URBI_ROOT_DEBUG(program_, "found: " << file);
        root_ = dir / "..";
        URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) / "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
#ifdef LIBPORT_ENABLE_SERIALIZATION
    handle_libserialize_ = library_load("serialize");
#endif
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base)
{
  std::string envvar = "URBI_ROOT_LIB" + base;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            mygetenv(envvar,
                     root() / libdir / "lib" + base + LIBPORT_LIBSFX));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / LIBPORT_LIBDIRNAME / "gostai";
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() / "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root() / "share" / "gostai";
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            mygetenv("URBI_ROOT_LIBPLUGIN",
                     core_path() / "engine" / "libuobject" LIBPORT_LIBSFX),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            mygetenv("URBI_ROOT_LIBREMOTE",
                     core_path() / "remote" / "libuobject" LIBPORT_LIBSFX),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
#ifdef STATIC_BUILD
  return ::urbi_main_args(args, *this, block, errors);
#else
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
#endif
}
<commit_msg>Avoid assignment in if conditions.<commit_after>/*
 * Copyright (C) 2009-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>
#include <libport/unistd.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#ifdef STATIC_BUILD
# include <urbi/umain.hh>
#endif
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val = "")
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || mygetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos = lib.find(':');

  if ((pos = lib.find(':')) == lib.npos)
  {
    res.push_back(lib);
    return res;
  }

  do
  {
    std::string s = lib.substr(0, pos);
    if (pos != lib.npos)
    {
      lib = lib.substr(pos + 1, lib.npos);
      pos = lib.find(':');
    }
    else
      lib.clear();

#ifdef WIN32
    // Colon could be used as a path separator under cygwin and as a volume
    // separator under windows.
    if (s[0] == '\\' && !res.empty())
    {
      std::string& back = res.back();
      size_t back_len = back.length();

      // In case we split "c:\foo" into "c" and "\foo", glue them
      // together again.
      if (back_len == 1)
        back += ':' + s;

      // In case we split "bar;c:\foo" into "bar;c" and "\foo", split them
      // into "bar" and "c:\foo"
      else if (back_len >= 2 && back[back_len - 2] == ';')
      {
        s = std::string("") + back[back_len - 1] + ':' + s;
        back = back.substr(0, back_len - 2);
        res.push_back(s);
      }
    }
    else
      res.push_back(s);
#else
    res.push_back(s);
#endif

  } while (!lib.empty());

  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = mygetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
    {
      size_t dot = argv0.find_last_of(".");
      if (dot == argv0.npos || argv0.substr(dot + 1) != "exe")
        argv0 += ".exe";
    }
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      struct stat stats;
      std::string dir, file;
      bool found = false;

#ifdef WIN32
      URBI_ROOT_DEBUG(program_,
                      "check if invoked from the current directory");

      {
        char *dir_buf = getcwd(0, 0);
        std::string dir(dir_buf);
        free(dir_buf);
        file = dir / argv0;
      }

      found = stat(file.c_str(), &stats) == 0;
      if (!found)
      {
        URBI_ROOT_DEBUG(program_, "not found: " << file);
#endif
        URBI_ROOT_DEBUG(program_,
                        "check if invoked from the path");
        strings_type path = split(mygetenv("PATH"));
        foreach (const std::string& dir_, path)
        {
          file = dir_ / argv0;
          found = stat(file.c_str(), &stats) == 0;
          if (found)
          {
            dir = dir_;
            break;
          }
          URBI_ROOT_DEBUG(program_, "not found: " << file);
        }
#ifdef WIN32
      }
#endif

      if (found)
      {
        URBI_ROOT_DEBUG(program_, "found: " << file);
        root_ = dir / "..";
        URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) / "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
#ifdef LIBPORT_ENABLE_SERIALIZATION
    handle_libserialize_ = library_load("serialize");
#endif
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base)
{
  std::string envvar = "URBI_ROOT_LIB" + base;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            mygetenv(envvar,
                     root() / libdir / "lib" + base + LIBPORT_LIBSFX));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / LIBPORT_LIBDIRNAME / "gostai";
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() / "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root() / "share" / "gostai";
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            mygetenv("URBI_ROOT_LIBPLUGIN",
                     core_path() / "engine" / "libuobject" LIBPORT_LIBSFX),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            mygetenv("URBI_ROOT_LIBREMOTE",
                     core_path() / "remote" / "libuobject" LIBPORT_LIBSFX),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
#ifdef STATIC_BUILD
  return ::urbi_main_args(args, *this, block, errors);
#else
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
#endif
}
<|endoftext|>


<commit_before>/*****************************************************************************************************
USAGE:
./opencv_annotation -images <folder location> -annotations <ouput file>

Created by: Puttemans Steven
*****************************************************************************************************/

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>

#include <fstream>
#include <iostream>

using namespace std;
using namespace cv;

// Function prototypes
void on_mouse(int, int, int, int, void*);
string int2string(int);
void get_annotations(Mat, stringstream*);

// Public parameters
Mat image;
int roi_x0 = 0, roi_y0 = 0, roi_x1 = 0, roi_y1 = 0, num_of_rec = 0;
bool start_draw = false;

// Window name for visualisation purposes
const string window_name="OpenCV Based Annotation Tool";

// FUNCTION : Mouse response for selecting objects in images
// If left button is clicked, start drawing a rectangle as long as mouse moves
// Stop drawing once a new left click is detected by the on_mouse function
void on_mouse(int event, int x, int y, int , void * )
{
    // Action when left button is clicked
    if(event == EVENT_LBUTTONDOWN)
    {
        if(!start_draw)
        {
            roi_x0 = x;
            roi_y0 = y;
            start_draw = true;
        } else {
            roi_x1 = x;
            roi_y1 = y;
            start_draw = false;
        }
    }
    // Action when mouse is moving
    if((event == EVENT_MOUSEMOVE) && start_draw)
    {
        // Redraw bounding box for annotation
        Mat current_view;
        image.copyTo(current_view);
        rectangle(current_view, Point(roi_x0,roi_y0), Point(x,y), Scalar(0,0,255));
        imshow(window_name, current_view);
    }
}

// FUNCTION : snippet to convert an integer value to a string using a clean function
// instead of creating a stringstream each time inside the main code
string int2string(int num)
{
    stringstream temp_stream;
    temp_stream << num;
    return temp_stream.str();
}

// FUNCTION : given an image containing positive object instances, add all the object
// annotations to a known stringstream
void get_annotations(Mat input_image, stringstream* output_stream)
{
    // Make it possible to exit the annotation
    bool stop = false;

    // Reset the num_of_rec element at each iteration
    // Make sure the global image is set to the current image
    num_of_rec = 0;
    image = input_image;

    // Init window interface and couple mouse actions
    namedWindow(window_name, WINDOW_AUTOSIZE);
    setMouseCallback(window_name, on_mouse);

    imshow(window_name, image);
    stringstream temp_stream;
    int key_pressed = 0;

    do
    {
        // Keys for processing
        // You need to select one for confirming a selection and one to continue to the next image
        // Based on the universal ASCII code of the keystroke: http://www.asciitable.com/
        //      c = 99		    add rectangle to current image
        //	    n = 110		    save added rectangles and show next image
        //	    <ESC> = 27      exit program
        key_pressed = 0xFF & waitKey(0);
        switch( key_pressed )
        {
        case 27:
                destroyWindow(window_name);
                stop = true;
        case 99:
                // Add a rectangle to the list
                num_of_rec++;
                // Draw initiated from top left corner
                if(roi_x0<roi_x1 && roi_y0<roi_y1)
                {
                    temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y0) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y1-roi_y0);
                }
                // Draw initiated from bottom right corner
                if(roi_x0>roi_x1 && roi_y0>roi_y1)
                {
                    temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y1) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y0-roi_y1);
                }
                // Draw initiated from top right corner
                if(roi_x0>roi_x1 && roi_y0<roi_y1)
                {
                    temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y0) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y1-roi_y0);
                }
                // Draw initiated from bottom left corner
                if(roi_x0<roi_x1 && roi_y0>roi_y1)
                {
                    temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y1) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y0-roi_y1);
                }

                rectangle(input_image, Point(roi_x0,roi_y0), Point(roi_x1,roi_y1), Scalar(0,255,0), 1);

                break;
        }

        // Check if escape has been pressed
        if(stop)
        {
            break;
        }
    }
    // Continue as long as the next image key has not been pressed
    while(key_pressed != 110);

    // If there are annotations AND the next image key is pressed
    // Write the image annotations to the file
    if(num_of_rec>0 && key_pressed==110)
    {
        *output_stream << " " << num_of_rec << temp_stream.str() << endl;
    }

    // Close down the window
    destroyWindow(window_name);
}

int main( int argc, const char** argv )
{
    // Read in the input arguments
    string image_folder;
    string annotations;
    for(int i = 1; i < argc; ++i )
    {
        if( !strcmp( argv[i], "-images" ) )
        {
            image_folder = argv[++i];
        }
        else if( !strcmp( argv[i], "-annotations" ) )
        {
            annotations = argv[++i];
        }
    }

    // Create the outputfilestream
    ofstream output(annotations.c_str());

    // Return the image filenames inside the image folder
    vector<String> filenames;
    String folder(image_folder);
    glob(folder, filenames);

    // Loop through each image stored in the images folder
    // Create and temporarily store the annotations
    // At the end write everything to the annotations file
    for (size_t i = 0; i < filenames.size(); i++){
        // Read in an image
        Mat current_image = imread(filenames[i]);

        // Perform annotations & generate corresponding output
        stringstream output_stream;
        get_annotations(current_image, &output_stream);

        // Store the annotations, write to the output file
        if (output_stream.str() != ""){
            output << filenames[i] << output_stream.str();
        }
    }

    return 0;
}
<commit_msg>info on how to use the tool<commit_after>/*****************************************************************************************************
USAGE:
./opencv_annotation -images <folder location> -annotations <ouput file>

Created by: Puttemans Steven
*****************************************************************************************************/

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>

#include <fstream>
#include <iostream>

using namespace std;
using namespace cv;

// Function prototypes
void on_mouse(int, int, int, int, void*);
string int2string(int);
void get_annotations(Mat, stringstream*);

// Public parameters
Mat image;
int roi_x0 = 0, roi_y0 = 0, roi_x1 = 0, roi_y1 = 0, num_of_rec = 0;
bool start_draw = false;

// Window name for visualisation purposes
const string window_name="OpenCV Based Annotation Tool";

// FUNCTION : Mouse response for selecting objects in images
// If left button is clicked, start drawing a rectangle as long as mouse moves
// Stop drawing once a new left click is detected by the on_mouse function
void on_mouse(int event, int x, int y, int , void * )
{
    // Action when left button is clicked
    if(event == EVENT_LBUTTONDOWN)
    {
        if(!start_draw)
        {
            roi_x0 = x;
            roi_y0 = y;
            start_draw = true;
        } else {
            roi_x1 = x;
            roi_y1 = y;
            start_draw = false;
        }
    }
    // Action when mouse is moving
    if((event == EVENT_MOUSEMOVE) && start_draw)
    {
        // Redraw bounding box for annotation
        Mat current_view;
        image.copyTo(current_view);
        rectangle(current_view, Point(roi_x0,roi_y0), Point(x,y), Scalar(0,0,255));
        imshow(window_name, current_view);
    }
}

// FUNCTION : snippet to convert an integer value to a string using a clean function
// instead of creating a stringstream each time inside the main code
string int2string(int num)
{
    stringstream temp_stream;
    temp_stream << num;
    return temp_stream.str();
}

// FUNCTION : given an image containing positive object instances, add all the object
// annotations to a known stringstream
void get_annotations(Mat input_image, stringstream* output_stream)
{
    // Make it possible to exit the annotation
    bool stop = false;

    // Reset the num_of_rec element at each iteration
    // Make sure the global image is set to the current image
    num_of_rec = 0;
    image = input_image;

    // Init window interface and couple mouse actions
    namedWindow(window_name, WINDOW_AUTOSIZE);
    setMouseCallback(window_name, on_mouse);

    imshow(window_name, image);
    stringstream temp_stream;
    int key_pressed = 0;

    do
    {
        // Keys for processing
        // You need to select one for confirming a selection and one to continue to the next image
        // Based on the universal ASCII code of the keystroke: http://www.asciitable.com/
        //      c = 99		    add rectangle to current image
        //	    n = 110		    save added rectangles and show next image
        //	    <ESC> = 27      exit program
        key_pressed = 0xFF & waitKey(0);
        switch( key_pressed )
        {
        case 27:
                destroyWindow(window_name);
                stop = true;
        case 99:
                // Add a rectangle to the list
                num_of_rec++;
                // Draw initiated from top left corner
                if(roi_x0<roi_x1 && roi_y0<roi_y1)
                {
                    temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y0) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y1-roi_y0);
                }
                // Draw initiated from bottom right corner
                if(roi_x0>roi_x1 && roi_y0>roi_y1)
                {
                    temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y1) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y0-roi_y1);
                }
                // Draw initiated from top right corner
                if(roi_x0>roi_x1 && roi_y0<roi_y1)
                {
                    temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y0) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y1-roi_y0);
                }
                // Draw initiated from bottom left corner
                if(roi_x0<roi_x1 && roi_y0>roi_y1)
                {
                    temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y1) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y0-roi_y1);
                }

                rectangle(input_image, Point(roi_x0,roi_y0), Point(roi_x1,roi_y1), Scalar(0,255,0), 1);

                break;
        }

        // Check if escape has been pressed
        if(stop)
        {
            break;
        }
    }
    // Continue as long as the next image key has not been pressed
    while(key_pressed != 110);

    // If there are annotations AND the next image key is pressed
    // Write the image annotations to the file
    if(num_of_rec>0 && key_pressed==110)
    {
        *output_stream << " " << num_of_rec << temp_stream.str() << endl;
    }

    // Close down the window
    destroyWindow(window_name);
}

int main( int argc, const char** argv )
{
    // If no arguments are given, then supply some information on how this tool works
    if( argc == 1 ){
        cout << "Usage: " << argv[0] << endl;
        cout << " -images <folder_location> [example - /data/testimages/]" << endl;
        cout << " -annotations <ouput_file> [example - /data/annotations.txt]" << endl;

        return -1;
    }

    // Read in the input arguments
    string image_folder;
    string annotations;
    for(int i = 1; i < argc; ++i )
    {
        if( !strcmp( argv[i], "-images" ) )
        {
            image_folder = argv[++i];
        }
        else if( !strcmp( argv[i], "-annotations" ) )
        {
            annotations = argv[++i];
        }
    }

    // Create the outputfilestream
    ofstream output(annotations.c_str());

    // Return the image filenames inside the image folder
    vector<String> filenames;
    String folder(image_folder);
    glob(folder, filenames);

    // Loop through each image stored in the images folder
    // Create and temporarily store the annotations
    // At the end write everything to the annotations file
    for (size_t i = 0; i < filenames.size(); i++){
        // Read in an image
        Mat current_image = imread(filenames[i]);

        // Perform annotations & generate corresponding output
        stringstream output_stream;
        get_annotations(current_image, &output_stream);

        // Store the annotations, write to the output file
        if (output_stream.str() != ""){
            output << filenames[i] << output_stream.str();
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifdef _WIN32
#define M_PI 3.14
#endif

#include <cmath>
#include <iostream>
#include <fstream>

#include "Body.hpp"

#define G 9.82 // TODO: Get the right number
#define DENSITY 20 // kg/m^3

using namespace sf;
using namespace std;

Body::Body(Vector2f pos, int m, Vector2f dir)
	: position(pos), direction(dir), mass(m)
{
	if (mass <= 0)
	{
		cout << "FATAL ERROR: MASS <= 0" << endl;
	}

	// Radius
	float volume = mass / DENSITY;
	radius = cbrt((3*volume)/(4*M_PI));

	if (radius < 1)
	{
		radius = 1;
	}

	shape.setRadius(radius);
	shape.setFillColor(Color::Red);
}

void Body::move(float dt)
{
	position += direction * dt;
}

void Body::applyGravityOf(const Body &b, float dt)
{
    float r = getDistanceTo(b);

    if (r <= 0)
    {
    	return;
    }

    float F = (G*mass*b.mass) / (r*r);

    // Make the force proportional to the mass
    F /= mass;

	// Get the unit vector to the other body
	Vector2f to_Body(b.position - position);
	to_Body = to_Body / r;

    // Apply the force in the direction of the other body
    direction += (to_Body * F) * dt;
}

float Body::getDistanceTo(const Body &p)
{
    Vector2f a = position;
	Vector2f b = p.position;
    Vector2f c = b - a;

    return sqrt(c.x*c.x + c.y * c.y);
}

void Body::draw(RenderWindow &window)
{
	shape.setPosition(position);
	window.draw(shape);
}

bool Body::collideWith(const Body &p)
{
	Vector2f a = position;
	Vector2f b = p.position;
	float d = (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);

	float r1 = shape.getRadius();
	float r2 = p.shape.getRadius();
	if (d > (r1+r2)*(r1+r2))
		return false;
	return true;
}

bool Body::contains(const Vector2f &point)
{
    Vector2f a = position;
    Vector2f b = point;
    Vector2f c = b - a;

    if ((c.x*c.x + c.y * c.y) <= shape.getRadius()*shape.getRadius())
    {
        return true;
    }

    return false;
}
<commit_msg>radius is now log(mass)<commit_after>#ifdef _WIN32
#define M_PI 3.14
#endif

#include <cmath>
#include <iostream>
#include <fstream>

#include "Body.hpp"

#define G 9.82 // TODO: Get the right number
#define DENSITY 20 // kg/m^3

using namespace sf;
using namespace std;

Body::Body(Vector2f pos, int m, Vector2f dir)
	: position(pos), direction(dir), mass(m)
{
	if (mass <= 0)
	{
		cout << "FATAL ERROR: MASS <= 0" << endl;
	}

	// Radius
	radius = log(mass);
	/*
	float volume = mass / DENSITY;
	radius = cbrt((3*volume)/(4*M_PI));
	*/

	if (radius < 1)
	{
		radius = 1;
	}

	shape.setRadius(radius);
	shape.setFillColor(Color::Red);
}

void Body::move(float dt)
{
	position += direction * dt;
}

void Body::applyGravityOf(const Body &b, float dt)
{
    float r = getDistanceTo(b);

    if (r <= 0)
    {
    	return;
    }

    float F = (G*mass*b.mass) / (r*r);

    // Make the force proportional to the mass
    F /= mass;

	// Get the unit vector to the other body
	Vector2f to_Body(b.position - position);
	to_Body = to_Body / r;

    // Apply the force in the direction of the other body
    direction += (to_Body * F) * dt;
}

float Body::getDistanceTo(const Body &p)
{
    Vector2f a = position;
	Vector2f b = p.position;
    Vector2f c = b - a;

    return sqrt(c.x*c.x + c.y * c.y);
}

void Body::draw(RenderWindow &window)
{
	shape.setPosition(position);
	window.draw(shape);
}

bool Body::collideWith(const Body &p)
{
	Vector2f a = position;
	Vector2f b = p.position;
	float d = (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);

	float r1 = shape.getRadius();
	float r2 = p.shape.getRadius();
	if (d > (r1+r2)*(r1+r2))
		return false;
	return true;
}

bool Body::contains(const Vector2f &point)
{
    Vector2f a = position;
    Vector2f b = point;
    Vector2f c = b - a;

    if ((c.x*c.x + c.y * c.y) <= shape.getRadius()*shape.getRadius())
    {
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Laszlo Papp <lpapp@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "configdialog.h"
#include <creator/pluginmanager.h>

#include <KCMUtils/KPluginSelector>
#include <KConfigGui/KConfigSkeleton>
#include <KI18n/KLocalizedString>

using namespace GluonCreator;

ConfigDialog::ConfigDialog( QWidget* parent, const QString& name, KConfigSkeleton* config ): KConfigDialog( parent, name, config )
{
    QList<KPluginInfo> plugins = PluginManager::instance()->pluginInfos();

    m_plugins = new KPluginSelector();
    m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Docks" ), QString( "dock" ) );
    m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Tools" ), QString( "tool" ) );
    m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Others" ), QString() );

    addPage( m_plugins, i18n( "Plugins" ), "gluon" );
    connect( m_plugins, SIGNAL(changed(bool)), SLOT(enableButtonApply(bool)) );
}

ConfigDialog::~ConfigDialog()
{

}

void ConfigDialog::accept()
{
    m_plugins->save();
    PluginManager::instance()->loadPlugins();
    QDialog::accept();
}
<commit_msg>apps/creator: Disable plugin config dialog, needs porting<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Laszlo Papp <lpapp@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "configdialog.h"
#include <creator/pluginmanager.h>

#include <KCMUtils/KPluginSelector>
#include <KConfigGui/KConfigSkeleton>
#include <KI18n/KLocalizedString>

using namespace GluonCreator;

ConfigDialog::ConfigDialog( QWidget* parent, const QString& name, KConfigSkeleton* config ): KConfigDialog( parent, name, config )
{
//     QList<KPluginInfo> plugins = PluginManager::instance()->pluginInfos();
//
//     m_plugins = new KPluginSelector();
//     m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Docks" ), QString( "dock" ) );
//     m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Tools" ), QString( "tool" ) );
//     m_plugins->addPlugins( plugins, KPluginSelector::ReadConfigFile, i18n( "Others" ), QString() );
//
//     addPage( m_plugins, i18n( "Plugins" ), "gluon" );
//     connect( m_plugins, SIGNAL(changed(bool)), SLOT(enableButtonApply(bool)) );
}

ConfigDialog::~ConfigDialog()
{

}

void ConfigDialog::accept()
{
//     m_plugins->save();
//     PluginManager::instance()->loadPlugins();
    QDialog::accept();
}
<|endoftext|>