<commit_before>/*
Copyright (C) 2016 iNuron NV

This file is part of Open vStorage Open Source Edition (OSE), as available from

    http://www.openvstorage.org and
    http://www.openvstorage.com.

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)
as published by the Free Software Foundation, in version 3 as it comes
in the <LICENSE.txt> file of the Open vStorage OSE distribution.

Open vStorage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY of any kind.
*/

#include "manifest_cache.h"

namespace alba {
namespace proxy_client {

ManifestCache &ManifestCache::getInstance() {
  static ManifestCache instance;
  return instance;
}

static size_t _manifest_cache_capacity = 10000;
void ManifestCache::set_capacity(size_t capacity) {
  _manifest_cache_capacity = capacity;
}

void ManifestCache::add(std::string namespace_, std::string object_name,
                        std::shared_ptr<Manifest> mfp) {
  ALBA_LOG(DEBUG, "ManifestCache::add");

  std::shared_ptr<manifest_cache> mcp = nullptr;
  std::shared_ptr<std::mutex> mp = nullptr;
  {
    std::lock_guard<std::mutex> lock(_level1_mutex);
    auto it1 = _level1.find(namespace_);

    if (it1 == _level1.end()) {
      ALBA_LOG(INFO, "ManifestCache::add namespace:'"
                         << namespace_ << "' : new manifest cache");
      std::shared_ptr<manifest_cache> mc(new manifest_cache);
      std::shared_ptr<std::mutex> mm(new std::mutex);
      auto p = std::make_pair(mc, mm);
      _level1[namespace_] = std::move(p);
      it1 = _level1.find(namespace_);
    } else {
      ALBA_LOG(DEBUG, "ManifestCache::add namespace:'"
                          << namespace_ << "' : existing manifest cache");
    }
    const auto &v = it1->second;
    mcp = v.first;
    mp = v.second;
  }

  manifest_cache &manifest_cache = *mcp;
  std::mutex &m = *mp;
  {
    std::lock_guard<std::mutex> lock(m);
    auto it2 = manifest_cache.find(object_name);
    if (it2 != manifest_cache.end()) {
      manifest_cache.erase(it2);
    }

    if (manifest_cache.size() > _manifest_cache_capacity) {
      auto it_victim = manifest_cache.begin();
      auto victim = it_victim->first;
      using namespace alba::stuff;
      ALBA_LOG(DEBUG, "cache '" << namespace_ << "' full("
                                << _manifest_cache_capacity
                                << "), evicting victim: " << victim);
      manifest_cache.erase(it_victim);
    }

    manifest_cache[object_name] = std::move(mfp);
  }
}

std::shared_ptr<Manifest> ManifestCache::find(const std::string &namespace_,
                                              const std::string &object_name) {
  std::pair<std::shared_ptr<manifest_cache>, std::shared_ptr<std::mutex>> vp;
  {
    std::lock_guard<std::mutex> g(_level1_mutex);
    auto it = _level1.find(namespace_);
    if (it == _level1.end()) {
      return nullptr;
    } else {
      vp = it->second;
    }
  }
  auto &map = *vp.first;
  auto &mm = *vp.second;
  {
    std::lock_guard<std::mutex> g(mm);
    const auto &map_it = map.find(object_name);
    if (map_it == map.end()) {
      return nullptr;
    } else {
      return map_it->second;
    }
  }
}

void ManifestCache::invalidate_namespace(const std::string &namespace_) {
  ALBA_LOG(DEBUG, "ManifestCache::invalidate_namespace(" << namespace_ << ")");
  std::lock_guard<std::mutex> g(_level1_mutex);
  auto it = _level1.find(namespace_);
  if (it != _level1.end()) {
    _level1.erase(it);
  }
}
}
}
<commit_msg>pick random victim<commit_after>/*
Copyright (C) 2016 iNuron NV

This file is part of Open vStorage Open Source Edition (OSE), as available from

    http://www.openvstorage.org and
    http://www.openvstorage.com.

This file is free software; you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)
as published by the Free Software Foundation, in version 3 as it comes
in the <LICENSE.txt> file of the Open vStorage OSE distribution.

Open vStorage is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY of any kind.
*/

#include "manifest_cache.h"

namespace alba {
namespace proxy_client {

ManifestCache &ManifestCache::getInstance() {
  static ManifestCache instance;
  return instance;
}

static size_t _manifest_cache_capacity = 10000;
void ManifestCache::set_capacity(size_t capacity) {
  _manifest_cache_capacity = capacity;
}

void ManifestCache::add(std::string namespace_, std::string object_name,
                        std::shared_ptr<Manifest> mfp) {
  ALBA_LOG(DEBUG, "ManifestCache::add");

  std::shared_ptr<manifest_cache> mcp = nullptr;
  std::shared_ptr<std::mutex> mp = nullptr;
  {
    std::lock_guard<std::mutex> lock(_level1_mutex);
    auto it1 = _level1.find(namespace_);

    if (it1 == _level1.end()) {
      ALBA_LOG(INFO, "ManifestCache::add namespace:'"
                         << namespace_ << "' : new manifest cache");
      std::shared_ptr<manifest_cache> mc(new manifest_cache);
      std::shared_ptr<std::mutex> mm(new std::mutex);
      auto p = std::make_pair(mc, mm);
      _level1[namespace_] = std::move(p);
      it1 = _level1.find(namespace_);
    } else {
      ALBA_LOG(DEBUG, "ManifestCache::add namespace:'"
                          << namespace_ << "' : existing manifest cache");
    }
    const auto &v = it1->second;
    mcp = v.first;
    mp = v.second;
  }

  manifest_cache &manifest_cache = *mcp;
  std::mutex &m = *mp;
  {
    std::lock_guard<std::mutex> lock(m);
    auto it2 = manifest_cache.find(object_name);
    if (it2 != manifest_cache.end()) {
      manifest_cache.erase(it2);
    }

    if (manifest_cache.size() > _manifest_cache_capacity) {
      auto it_victim = manifest_cache.begin();
      int size = manifest_cache.size();
      if (size > 0) {
        std::advance(it_victim, rand() % size); // O(size) :(
      }
      auto victim = it_victim->first;
      using namespace alba::stuff;
      ALBA_LOG(DEBUG, "cache '" << namespace_ << "' full("
                                << _manifest_cache_capacity
                                << "), evicting victim: " << victim);
      manifest_cache.erase(it_victim);
    }

    manifest_cache[object_name] = std::move(mfp);
  }
}

std::shared_ptr<Manifest> ManifestCache::find(const std::string &namespace_,
                                              const std::string &object_name) {
  std::pair<std::shared_ptr<manifest_cache>, std::shared_ptr<std::mutex>> vp;
  {
    std::lock_guard<std::mutex> g(_level1_mutex);
    auto it = _level1.find(namespace_);
    if (it == _level1.end()) {
      return nullptr;
    } else {
      vp = it->second;
    }
  }
  auto &map = *vp.first;
  auto &mm = *vp.second;
  {
    std::lock_guard<std::mutex> g(mm);
    const auto &map_it = map.find(object_name);
    if (map_it == map.end()) {
      return nullptr;
    } else {
      return map_it->second;
    }
  }
}

void ManifestCache::invalidate_namespace(const std::string &namespace_) {
  ALBA_LOG(DEBUG, "ManifestCache::invalidate_namespace(" << namespace_ << ")");
  std::lock_guard<std::mutex> g(_level1_mutex);
  auto it = _level1.find(namespace_);
  if (it != _level1.end()) {
    _level1.erase(it);
  }
}
}
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxextension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include "test.h"

void wxExAppTestFixture::setUp()
{
  m_Grid = new wxExGrid(wxTheApp->GetTopWindow());
  m_ListView = new wxExListView(wxTheApp->GetTopWindow());
  m_Notebook = new wxExNotebook(wxTheApp->GetTopWindow(), NULL);
  m_STC = new wxExSTC(wxTheApp->GetTopWindow(), wxExFileName("test.h"));
  m_STCShell = new wxExSTCShell(wxTheApp->GetTopWindow());
  m_SVN = new wxExSVN(SVN_STAT, "test.h");
}

void wxExAppTestFixture::testConstructors()
{
}

void wxExAppTestFixture::testMethods()
{
  // test wxExApp
  CPPUNIT_ASSERT(wxExApp::GetConfig() != NULL);
  CPPUNIT_ASSERT(wxExApp::GetLexers() != NULL);
  CPPUNIT_ASSERT(wxExApp::GetPrinter() != NULL);
  CPPUNIT_ASSERT(!wxExTool::GetToolInfo().empty());

  // test wxExGrid
  CPPUNIT_ASSERT(m_Grid->CreateGrid(5, 5));
  m_Grid->SelectAll();
  m_Grid->SetGridCellValue(wxGridCellCoords(0, 0), "test");
  CPPUNIT_ASSERT(m_Grid->GetCellValue(0, 0) == "test");
  m_Grid->SetCellsValue(wxGridCellCoords(0, 0), "test1\ttest2\ntest3\ttest4\n");
  CPPUNIT_ASSERT(m_Grid->GetCellValue(0, 0) == "test1");

  // test wxExListView
  m_ListView->SetSingleStyle(wxLC_REPORT); // wxLC_ICON);
  m_ListView->InsertColumn("String", wxExColumn::COL_STRING);
  m_ListView->InsertColumn("Number", wxExColumn::COL_INT);
  CPPUNIT_ASSERT(m_ListView->FindColumn("String") == 0);
  CPPUNIT_ASSERT(m_ListView->FindColumn("Number") == 1);

  // test wxExNotebook (parent should not be NULL)
  wxWindow* page1 = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);
  wxWindow* page2 = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);

  CPPUNIT_ASSERT(m_Notebook->AddPage(page1, "key1") != NULL);
  CPPUNIT_ASSERT(m_Notebook->AddPage(page2, "key2") != NULL);
  CPPUNIT_ASSERT(m_Notebook->AddPage(page1, "key1") == NULL);
  CPPUNIT_ASSERT(m_Notebook->GetKeyByPage(page1) == "key1");
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("key1") == page1);
  CPPUNIT_ASSERT(m_Notebook->SetPageText("key1", "keyx", "hello"));
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("keyx") == page1);
  CPPUNIT_ASSERT(m_Notebook->DeletePage("keyx"));
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("keyx") == NULL);

  // test wxExSTC
  CPPUNIT_ASSERT(m_STC->GetFileName().GetFullName() == "test.h");
  // do the same test as with wxExFile in base for a binary file
  CPPUNIT_ASSERT(m_STC->Open(wxExFileName("../base/test.bin")));
  const wxCharBuffer& buffer = m_STC->GetTextRaw();
  wxLogMessage(buffer.data());
  CPPUNIT_ASSERT(buffer.length() == 40);

  // test wxExSTCShell
  m_STCShell->Prompt("test1");
  m_STCShell->Prompt("test2");
  m_STCShell->Prompt("test3");
  m_STCShell->Prompt("test4");
  // Prompting does not add a command to history...
  // TODO: Make a better test.
  CPPUNIT_ASSERT(!m_STCShell->GetHistory().Contains("test4"));

  // test wxExSVN
  CPPUNIT_ASSERT(m_SVN->Execute(false) == 0); // do not use a dialog
  // The output depends on the svn stat, of course,
  // so do not assert on it.
  m_SVN->GetOutput();

  // test various wxEx methods that need the app
  const wxString header = wxExHeader(wxExFileName("test.h"), m_Config, "hello test");
  CPPUNIT_ASSERT(header.Contains("hello test"));

  // test util
  CPPUNIT_ASSERT(wxExClipboardAdd("test"));
  CPPUNIT_ASSERT(wxExClipboardGet() == "test");
  CPPUNIT_ASSERT(wxExGetNumberOfLines("test\ntest\n") == 3);
  CPPUNIT_ASSERT(wxExGetLineNumberFromText("test on line: 1200") == 1200);
  CPPUNIT_ASSERT(wxExLog("hello from wxextension test"));
  CPPUNIT_ASSERT(!wxExMatchesOneOf(wxFileName("test.txt"), "*.cpp"));
  CPPUNIT_ASSERT(wxExMatchesOneOf(wxFileName("test.txt"), "*.cpp;*.txt"));
  CPPUNIT_ASSERT(wxExSkipWhiteSpace("t     es   t") == "t es t");
}

void wxExAppTestFixture::tearDown()
{
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxextension test suite")
{
  addTest(new CppUnit::TestCaller<wxExAppTestFixture>(
    "testConstructors",
    &wxExAppTestFixture::testConstructors));

  addTest(new CppUnit::TestCaller<wxExAppTestFixture>(
    "testMethods",
    &wxExAppTestFixture::testMethods));
}
<commit_msg>fixed compile error, but test still not ok, it does not return<commit_after>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxextension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include "test.h"

void wxExAppTestFixture::setUp()
{
  m_Grid = new wxExGrid(wxTheApp->GetTopWindow());
  m_ListView = new wxExListView(wxTheApp->GetTopWindow());
  m_Notebook = new wxExNotebook(wxTheApp->GetTopWindow(), NULL);
  m_STC = new wxExSTC(wxTheApp->GetTopWindow(), wxExFileName("test.h"));
  m_STCShell = new wxExSTCShell(wxTheApp->GetTopWindow());
  m_SVN = new wxExSVN(SVN_STAT, "test.h");
}

void wxExAppTestFixture::testConstructors()
{
}

void wxExAppTestFixture::testMethods()
{
  // test wxExApp
  CPPUNIT_ASSERT(wxExApp::GetConfig() != NULL);
  CPPUNIT_ASSERT(wxExApp::GetLexers() != NULL);
  CPPUNIT_ASSERT(wxExApp::GetPrinter() != NULL);
  CPPUNIT_ASSERT(!wxExTool::GetToolInfo().empty());

  // test wxExGrid
  CPPUNIT_ASSERT(m_Grid->CreateGrid(5, 5));
  m_Grid->SelectAll();
  m_Grid->SetGridCellValue(wxGridCellCoords(0, 0), "test");
  CPPUNIT_ASSERT(m_Grid->GetCellValue(0, 0) == "test");
  m_Grid->SetCellsValue(wxGridCellCoords(0, 0), "test1\ttest2\ntest3\ttest4\n");
  CPPUNIT_ASSERT(m_Grid->GetCellValue(0, 0) == "test1");

  // test wxExListView
  m_ListView->SetSingleStyle(wxLC_REPORT); // wxLC_ICON);
  m_ListView->InsertColumn("String", wxExColumn::COL_STRING);
  m_ListView->InsertColumn("Number", wxExColumn::COL_INT);
  CPPUNIT_ASSERT(m_ListView->FindColumn("String") == 0);
  CPPUNIT_ASSERT(m_ListView->FindColumn("Number") == 1);

  // test wxExNotebook (parent should not be NULL)
  wxWindow* page1 = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);
  wxWindow* page2 = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);

  CPPUNIT_ASSERT(m_Notebook->AddPage(page1, "key1") != NULL);
  CPPUNIT_ASSERT(m_Notebook->AddPage(page2, "key2") != NULL);
  CPPUNIT_ASSERT(m_Notebook->AddPage(page1, "key1") == NULL);
  CPPUNIT_ASSERT(m_Notebook->GetKeyByPage(page1) == "key1");
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("key1") == page1);
  CPPUNIT_ASSERT(m_Notebook->SetPageText("key1", "keyx", "hello"));
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("keyx") == page1);
  CPPUNIT_ASSERT(m_Notebook->DeletePage("keyx"));
  CPPUNIT_ASSERT(m_Notebook->GetPageByKey("keyx") == NULL);

  // test wxExSTC
  CPPUNIT_ASSERT(m_STC->GetFileName().GetFullName() == "test.h");
  // do the same test as with wxExFile in base for a binary file
  CPPUNIT_ASSERT(m_STC->Open(wxExFileName("../base/test.bin")));
  const wxCharBuffer& buffer = m_STC->GetTextRaw();
  wxLogMessage(buffer.data());
  CPPUNIT_ASSERT(buffer.length() == 40);

  // test wxExSTCShell
  m_STCShell->Prompt("test1");
  m_STCShell->Prompt("test2");
  m_STCShell->Prompt("test3");
  m_STCShell->Prompt("test4");
  // Prompting does not add a command to history...
  // TODO: Make a better test.
  CPPUNIT_ASSERT(!m_STCShell->GetHistory().Contains("test4"));

  // test wxExSVN
  CPPUNIT_ASSERT(m_SVN->Execute(false) == 0); // do not use a dialog
  // The output depends on the svn stat, of course,
  // so do not assert on it.
  m_SVN->GetOutput();

  // test various wxEx methods that need the app
  const wxString header = wxExHeader(wxExFileName("test.h"), wxExApp::GetConfig(), "hello test");
  CPPUNIT_ASSERT(header.Contains("hello test"));

  // test util
  CPPUNIT_ASSERT(wxExClipboardAdd("test"));
  CPPUNIT_ASSERT(wxExClipboardGet() == "test");
  CPPUNIT_ASSERT(wxExGetNumberOfLines("test\ntest\n") == 3);
  CPPUNIT_ASSERT(wxExGetLineNumberFromText("test on line: 1200") == 1200);
  CPPUNIT_ASSERT(wxExLog("hello from wxextension test"));
  CPPUNIT_ASSERT(!wxExMatchesOneOf(wxFileName("test.txt"), "*.cpp"));
  CPPUNIT_ASSERT(wxExMatchesOneOf(wxFileName("test.txt"), "*.cpp;*.txt"));
  CPPUNIT_ASSERT(wxExSkipWhiteSpace("t     es   t") == "t es t");
}

void wxExAppTestFixture::tearDown()
{
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxextension test suite")
{
  addTest(new CppUnit::TestCaller<wxExAppTestFixture>(
    "testConstructors",
    &wxExAppTestFixture::testConstructors));

  addTest(new CppUnit::TestCaller<wxExAppTestFixture>(
    "testMethods",
    &wxExAppTestFixture::testMethods));
}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "gtest/gtest.h"
#include "MooseFunctor.h"
#include "FaceInfo.h"
#include "libmesh/elem.h"
#include "libmesh/quadrature_gauss.h"

using namespace libMesh;
using namespace Moose;

template <typename T>
class TestFunctor : public FunctorBase<T>
{
public:
  using typename FunctorBase<T>::FunctorType;
  using typename FunctorBase<T>::FunctorReturnType;
  using typename FunctorBase<T>::ValueType;
  using typename FunctorBase<T>::GradientType;
  using typename FunctorBase<T>::DotType;

  TestFunctor() = default;

private:
  ValueType evaluate(const Moose::ElemArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const Moose::ElemFromFaceArg &, unsigned int) const override final
  {
    return 0;
  }
  ValueType evaluate(const Moose::FaceArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const Moose::SingleSidedFaceArg &, unsigned int) const override final
  {
    return 0;
  }
  ValueType evaluate(const Moose::ElemQpArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const Moose::ElemSideQpArg &, unsigned int) const override final { return 0; }
};

TEST(MooseFunctorTest, testArgs)
{
  TestFunctor<Real> test;
  Node node0(0);
  node0.set_id(0);
  Node node1(1);
  node1.set_id(1);
  Node node2(2);
  node2.set_id(2);
  auto elem = Elem::build(EDGE2);
  elem->set_node(0) = &node0;
  elem->set_node(1) = &node1;
  auto neighbor = Elem::build(EDGE2);
  neighbor->set_node(0) = &node1;
  neighbor->set_node(1) = &node2;
  elem->set_neighbor(1, neighbor.get());
  FaceInfo fi(elem.get(), 1, neighbor.get());
  QGauss qrule(1, CONSTANT);

  auto elem_arg = Moose::ElemArg{elem.get(), false, false};
  auto face = Moose::FaceArg({&fi,
                              FV::LimiterType::CentralDifference,
                              true,
                              false,
                              false,
                              INVALID_BLOCK_ID,
                              INVALID_BLOCK_ID});
  auto single_face = Moose::SingleSidedFaceArg(
      {&fi, FV::LimiterType::CentralDifference, true, false, false, INVALID_BLOCK_ID});
  auto elem_from_face = Moose::ElemFromFaceArg({elem.get(), &fi, false, false, INVALID_BLOCK_ID});
  auto elem_qp = std::make_tuple(elem.get(), 0, &qrule);
  auto elem_side_qp = std::make_tuple(elem.get(), 0, 0, &qrule);

  auto test_dot = [&test](const auto & arg)
  {
    try
    {
      test.dot(arg);
      ASSERT_TRUE(false);
    }
    catch (std::runtime_error & e)
    {
      ASSERT_TRUE(std::string(e.what()).find("not implemented") != std::string::npos);
    }
  };

  test_dot(elem_arg);
  test_dot(face);
  test_dot(single_face);
  test_dot(elem_from_face);
  test_dot(elem_qp);
  test_dot(elem_side_qp);

  auto test_gradient = [&test](const auto & arg)
  {
    try
    {
      test.gradient(arg);
      ASSERT_TRUE(false);
    }
    catch (std::runtime_error & e)
    {
      ASSERT_TRUE(std::string(e.what()).find("not implemented") != std::string::npos);
    }
  };

  test_gradient(elem_arg);
  test_gradient(face);
  test_gradient(single_face);
  test_gradient(elem_from_face);
  test_gradient(elem_qp);
  test_gradient(elem_side_qp);

  ConstantFunctor<Real> cf(2);
  EXPECT_EQ(cf(elem_arg), 2);
  EXPECT_EQ(cf(elem_from_face), 2);
  EXPECT_EQ(cf(face), 2);
  EXPECT_EQ(cf(single_face), 2);
  EXPECT_EQ(cf(elem_from_face), 2);
  EXPECT_EQ(cf(elem_qp), 2);
  EXPECT_EQ(cf(elem_side_qp), 2);

  auto constant_gradient_test = [&cf](const auto & arg)
  {
    const auto result = cf.gradient(arg);
    for (const auto i : make_range(unsigned(LIBMESH_DIM)))
      EXPECT_EQ(result(i), 0);
  };
  constant_gradient_test(elem_arg);
  constant_gradient_test(elem_from_face);
  constant_gradient_test(face);
  constant_gradient_test(single_face);
  constant_gradient_test(elem_from_face);
  constant_gradient_test(elem_qp);
  constant_gradient_test(elem_side_qp);

  EXPECT_EQ(cf.dot(elem_arg), 0);
  EXPECT_EQ(cf.dot(elem_from_face), 0);
  EXPECT_EQ(cf.dot(face), 0);
  EXPECT_EQ(cf.dot(single_face), 0);
  EXPECT_EQ(cf.dot(elem_from_face), 0);
  EXPECT_EQ(cf.dot(elem_qp), 0);
  EXPECT_EQ(cf.dot(elem_side_qp), 0);
}
<commit_msg>Unit test VectorComponentFunctor<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "gtest/gtest.h"
#include "MooseFunctor.h"
#include "FaceInfo.h"
#include "VectorComponentFunctor.h"
#include "GreenGaussGradient.h"
#include "MeshGeneratorMesh.h"
#include "GeneratedMeshGenerator.h"
#include "AppFactory.h"
#include "libmesh/elem.h"
#include "libmesh/quadrature_gauss.h"
#include "libmesh/type_tensor.h"

using namespace libMesh;
using namespace Moose;
using namespace FV;

template <typename T>
class TestFunctor : public FunctorBase<T>
{
public:
  using typename FunctorBase<T>::ValueType;

  TestFunctor() = default;

private:
  ValueType evaluate(const ElemArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const ElemFromFaceArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const FaceArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const SingleSidedFaceArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const ElemQpArg &, unsigned int) const override final { return 0; }
  ValueType evaluate(const ElemSideQpArg &, unsigned int) const override final { return 0; }
};

template <typename T>
class WithGradientTestFunctor : public TestFunctor<T>
{
public:
  using typename TestFunctor<T>::GradientType;

  WithGradientTestFunctor(const MooseMesh & mesh) : _mesh(mesh) {}

  bool isExtrapolatedBoundaryFace(const FaceInfo & fi) const override { return !fi.neighborPtr(); }

private:
  using TestFunctor<T>::evaluateGradient;
  GradientType evaluateGradient(const ElemArg & elem_arg, unsigned int) const override final
  {
    return greenGaussGradient(elem_arg, *this, true, _mesh);
  }

  GradientType evaluateGradient(const FaceArg & face, unsigned int) const override final
  {
    const auto & fi = *face.fi;
    if (!isExtrapolatedBoundaryFace(fi))
    {
      const auto elem_arg = face.makeElem();
      const auto elem_gradient = this->gradient(elem_arg);
      const auto neighbor_arg = face.makeNeighbor();
      const auto linear_interp_gradient =
          fi.gC() * elem_gradient + (1 - fi.gC()) * this->gradient(neighbor_arg);
      return linear_interp_gradient +
             outer_product(((*this)(neighbor_arg) - (*this)(elem_arg)) / fi.dCFMag() -
                               linear_interp_gradient * fi.eCF(),
                           fi.eCF());
    }

    // One term expansion
    if (!fi.neighborPtr())
      return this->gradient(face.makeElem());
    else
      return this->gradient(face.makeNeighbor());
  }

  const MooseMesh & _mesh;
};

TEST(MooseFunctorTest, testArgs)
{
  TestFunctor<Real> test;
  Node node0(0);
  node0.set_id(0);
  Node node1(1);
  node1.set_id(1);
  Node node2(2);
  node2.set_id(2);
  auto elem = Elem::build(EDGE2);
  elem->set_node(0) = &node0;
  elem->set_node(1) = &node1;
  auto neighbor = Elem::build(EDGE2);
  neighbor->set_node(0) = &node1;
  neighbor->set_node(1) = &node2;
  elem->set_neighbor(1, neighbor.get());
  FaceInfo fi(elem.get(), 1, neighbor.get());
  QGauss qrule(1, CONSTANT);

  auto elem_arg = ElemArg{elem.get(), false, false};
  auto face = FaceArg({&fi,
                       LimiterType::CentralDifference,
                       true,
                       false,
                       false,
                       INVALID_BLOCK_ID,
                       INVALID_BLOCK_ID});
  auto single_face = SingleSidedFaceArg(
      {&fi, LimiterType::CentralDifference, true, false, false, INVALID_BLOCK_ID});
  auto elem_from_face = ElemFromFaceArg({elem.get(), &fi, false, false, INVALID_BLOCK_ID});
  auto elem_qp = std::make_tuple(elem.get(), 0, &qrule);
  auto elem_side_qp = std::make_tuple(elem.get(), 0, 0, &qrule);

  // Test not-implemented errors
  {
    auto test_dot = [&test](const auto & arg)
    {
      try
      {
        test.dot(arg);
        ASSERT_TRUE(false);
      }
      catch (std::runtime_error & e)
      {
        ASSERT_TRUE(std::string(e.what()).find("not implemented") != std::string::npos);
      }
    };

    test_dot(elem_arg);
    test_dot(face);
    test_dot(single_face);
    test_dot(elem_from_face);
    test_dot(elem_qp);
    test_dot(elem_side_qp);

    auto test_gradient = [&test](const auto & arg)
    {
      try
      {
        test.gradient(arg);
        ASSERT_TRUE(false);
      }
      catch (std::runtime_error & e)
      {
        ASSERT_TRUE(std::string(e.what()).find("not implemented") != std::string::npos);
      }
    };

    test_gradient(elem_arg);
    test_gradient(face);
    test_gradient(single_face);
    test_gradient(elem_from_face);
    test_gradient(elem_qp);
    test_gradient(elem_side_qp);
  }

  auto zero_gradient_test = [](const auto & functor, const auto & arg)
  {
    const auto result = functor.gradient(arg);
    for (const auto i : make_range(unsigned(LIBMESH_DIM)))
      EXPECT_EQ(result(i), 0);
  };

  // Test ConstantFunctor
  {
    ConstantFunctor<Real> cf(2);
    EXPECT_EQ(cf(elem_arg), 2);
    EXPECT_EQ(cf(elem_from_face), 2);
    EXPECT_EQ(cf(face), 2);
    EXPECT_EQ(cf(single_face), 2);
    EXPECT_EQ(cf(elem_from_face), 2);
    EXPECT_EQ(cf(elem_qp), 2);
    EXPECT_EQ(cf(elem_side_qp), 2);

    zero_gradient_test(cf, elem_arg);
    zero_gradient_test(cf, elem_from_face);
    zero_gradient_test(cf, face);
    zero_gradient_test(cf, single_face);
    zero_gradient_test(cf, elem_from_face);
    zero_gradient_test(cf, elem_qp);
    zero_gradient_test(cf, elem_side_qp);

    EXPECT_EQ(cf.dot(elem_arg), 0);
    EXPECT_EQ(cf.dot(elem_from_face), 0);
    EXPECT_EQ(cf.dot(face), 0);
    EXPECT_EQ(cf.dot(single_face), 0);
    EXPECT_EQ(cf.dot(elem_from_face), 0);
    EXPECT_EQ(cf.dot(elem_qp), 0);
    EXPECT_EQ(cf.dot(elem_side_qp), 0);
  }

  // Test VectorComponentFunctor
  {
    const char * argv[2] = {"foo", "\0"};

    MultiMooseEnum coord_type_enum("XYZ RZ RSPHERICAL", "XYZ");

    const auto nx = 2;
    auto app = AppFactory::createAppShared("MooseUnitApp", 1, (char **)argv);
    auto * factory = &app->getFactory();
    std::string mesh_type = "MeshGeneratorMesh";

    std::shared_ptr<MeshGeneratorMesh> mesh;
    {
      InputParameters params = factory->getValidParams(mesh_type);
      mesh = factory->create<MeshGeneratorMesh>(mesh_type, "moose_mesh", params);
    }

    app->actionWarehouse().mesh() = mesh;

    {
      std::unique_ptr<MeshBase> lm_mesh;
      InputParameters params = factory->getValidParams("GeneratedMeshGenerator");
      params.set<unsigned int>("nx") = nx;
      params.set<unsigned int>("ny") = nx;
      params.set<MooseEnum>("dim") = "2";
      auto mesh_gen =
          factory->create<GeneratedMeshGenerator>("GeneratedMeshGenerator", "mesh_gen", params);
      lm_mesh = mesh_gen->generate();
      mesh->setMeshBase(std::move(lm_mesh));
    }

    mesh->prepare();
    mesh->setCoordSystem({}, coord_type_enum);
    // Build the face info
    const auto & all_fi = mesh->allFaceInfo();
    mesh->computeFaceInfoFaceCoords();

    WithGradientTestFunctor<RealVectorValue> vec_test_func(*mesh);
    VectorComponentFunctor<Real> vec_comp(vec_test_func, 0);
    EXPECT_EQ(vec_comp(elem_arg), 0);
    EXPECT_EQ(vec_comp(elem_from_face), 0);
    EXPECT_EQ(vec_comp(face), 0);
    EXPECT_EQ(vec_comp(single_face), 0);
    EXPECT_EQ(vec_comp(elem_from_face), 0);
    EXPECT_EQ(vec_comp(elem_qp), 0);
    EXPECT_EQ(vec_comp(elem_side_qp), 0);

    const auto & mesh_fi = all_fi.front();
    const auto vec_elem_arg = ElemArg{&mesh_fi.elem(), false, false};
    auto vec_face_arg =
        FaceArg({&mesh_fi,
                 LimiterType::CentralDifference,
                 true,
                 false,
                 false,
                 mesh_fi.elem().subdomain_id(),
                 mesh_fi.neighborPtr() ? mesh_fi.neighbor().subdomain_id() : INVALID_BLOCK_ID});
    zero_gradient_test(vec_comp, vec_elem_arg);
    zero_gradient_test(vec_comp, vec_face_arg);
  }
}
<|endoftext|>


<commit_before>#include "layers/layer_z.h"

#include "core/exception.h"
#include "core/ptree_utils.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

/**
 * @brief class for testing layer Z initialization, the main, SEM learning algorithm
 */
class LayerZInitTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        nb_afferents_ = 50;
        PTree params;
        params.put(LayerZ::PARAM_NB_AFFERENTS, nb_afferents_);
        params.put(LayerZ::PARAM_NB_OUTPUT_NODES, 10);
        config_.Params(params);

        // IO
        config_.Input(LayerZ::KEY_INPUT_SPIKES, NAME_INPUT_SPIKES);

        config_.Output(LayerZ::KEY_OUTPUT_SPIKES, NAME_OUTPUT_SPIKES);
        config_.Output(LayerZ::KEY_OUTPUT_MEMBRANE_POT, NAME_OUTPUT_MEM_POT);
    }

    // members
    LayerZ to_;             ///< test object
    LayerConfig config_;    ///< default layer configuration

    int nb_afferents_;
    // name of keys in signal
    static const string NAME_INPUT_SPIKES;      ///< no. of afferent spikes
    static const string NAME_OUTPUT_SPIKES;     ///< no. of output spikes/size of output layer
    static const string NAME_OUTPUT_MEM_POT;    ///< membrane potential
};
// initialize static members
const string LayerZInitTest::NAME_INPUT_SPIKES  = "in";
const string LayerZInitTest::NAME_OUTPUT_SPIKES = "out";
const string LayerZInitTest::NAME_OUTPUT_MEM_POT = "mem_pot";

/**
 * @brief test validation of missing params
 */
TEST_F(LayerZInitTest, MissingParams)
{
    // remove key to output nodes
    PTree params = config_.Params();
    params.erase(LayerZ::PARAM_NB_OUTPUT_NODES);
    config_.Params(params);

    LayerZ to;
    EXPECT_THROW(to.Reset(config_), std::exception);
}

/**
 * @brief test parameter validation
 */
TEST_F(LayerZInitTest, InvalidParams)
{
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_DELTA_T, -0.1f);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_DELTA_T, 0.f);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_DELTA_T, -0.f);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_LEN_HISTORY, -3);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_LEN_HISTORY, 0);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_NB_AFFERENTS, 0);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_NB_AFFERENTS, -3);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
    {
        PTree params = config_.Params();
        params.put(LayerZ::PARAM_WTA_FREQ, -1);
        config_.Params(params);

        LayerZ to;
        EXPECT_THROW(to.Reset(config_), ExceptionValueError);
    }
}

TEST_F(LayerZInitTest, IONames)
{
    LayerConfig cfg;
    cfg.Params(config_.Params());
    {
        LayerZ to;
        EXPECT_THROW(to.IONames(cfg), std::exception);
    }
    {
        cfg.Input(LayerZ::KEY_INPUT_SPIKES, NAME_INPUT_SPIKES);
        LayerZ to;
        EXPECT_THROW(to.IONames(cfg), std::exception) << "still missing required output spikes";
    }
    {
        cfg.Output(LayerZ::KEY_OUTPUT_SPIKES, NAME_OUTPUT_SPIKES);
        LayerZ to;
        EXPECT_NO_THROW(to.IONames(cfg)) << "all required IO names present";
    }
}
<commit_msg>turn InvalidParams test into value-parameterized test<commit_after>#include "layers/layer_z.h"

#include "core/exception.h"
#include "core/ptree_utils.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

// name of keys in signal
const string NAME_INPUT_SPIKES  = "in";          ///< no. of afferent spikes
const string NAME_OUTPUT_SPIKES = "out";         ///< no. of output spikes/size of output layer
const string NAME_OUTPUT_MEM_POT = "mem_pot";    ///< membrane potential

/**
 * @brief mixin for testing layer Z, the main, SEM learning algorithm
 * Because we expect to test using fixutres as well as parametrized tests
 * Since these two test types are derived differently mixins solves the problem of defining a common base
 * The solution is adopted from this StackOverflow post:
 * @see http://stackoverflow.com/questions/3152326/google-test-parameterized-tests-which-use-an-existing-test-fixture-class
 *
 * T specifies test type (fixture or parameterized)
 */
template <class T> class LayerZTestBase : public T
{
protected:
    virtual void SetUp()
    {
        nb_afferents_ = 50;
        params_ = PTree();
        params_.put(LayerZ::PARAM_NB_AFFERENTS, nb_afferents_);
        params_.put(LayerZ::PARAM_NB_OUTPUT_NODES, 10);
        config_.Params(params_);

        // IO
        config_.Input(LayerZ::KEY_INPUT_SPIKES, NAME_INPUT_SPIKES);

        config_.Output(LayerZ::KEY_OUTPUT_SPIKES, NAME_OUTPUT_SPIKES);
        config_.Output(LayerZ::KEY_OUTPUT_MEMBRANE_POT, NAME_OUTPUT_MEM_POT);
    }

    // members
    LayerConfig config_;    ///< default layer configuration
    PTree params_;          ///< default params

    int nb_afferents_;
};

/**
 * @brief class for testing layer z initialization routines
 */
class LayerZInitTest : public LayerZTestBase<testing::Test >
{
protected:
    // members
    LayerZ to_;  ///< test object
};

/**
 * @brief test validation of missing params
 */
TEST_F(LayerZInitTest, MissingParams)
{
    // remove key to output nodes
    params_.erase(LayerZ::PARAM_NB_OUTPUT_NODES);
    config_.Params(params_);

    EXPECT_THROW(LayerZ().Reset(config_), std::exception);
}

TEST_F(LayerZInitTest, IONames)
{
    LayerConfig cfg;
    cfg.Params(config_.Params());
    {
        LayerZ to;
        EXPECT_THROW(to.IONames(cfg), std::exception);
    }
    {
        cfg.Input(LayerZ::KEY_INPUT_SPIKES, NAME_INPUT_SPIKES);
        LayerZ to;
        EXPECT_THROW(to.IONames(cfg), std::exception) << "still missing required output spikes";
    }
    {
        cfg.Output(LayerZ::KEY_OUTPUT_SPIKES, NAME_OUTPUT_SPIKES);
        LayerZ to;
        EXPECT_NO_THROW(to.IONames(cfg)) << "all required IO names present";
    }
}

typedef std::pair<std::string, float > TParamPairSF; /// convinience typdef to use as test params below

/**
 * @brief Parameterized test for testing layer z parameter value validation
 * Using paramterized tests allows us to try different value more easily
 */
class LayerZParamsTest : public LayerZTestBase<testing::TestWithParam<TParamPairSF > >
{
protected:
};

// if you're using QTCreator, don't mind the ..._EvalGenerator_ warning at the bottom
INSTANTIATE_TEST_CASE_P(TestWithParams,
                        LayerZParamsTest,
                        testing::Values(TParamPairSF(LayerZ::PARAM_DELTA_T, -1.f),
                                        TParamPairSF(LayerZ::PARAM_DELTA_T, -0.f),
                                        TParamPairSF(LayerZ::PARAM_DELTA_T, 0.f),
                                        TParamPairSF(LayerZ::PARAM_LEN_HISTORY, -3),
                                        TParamPairSF(LayerZ::PARAM_LEN_HISTORY, 0),
                                        TParamPairSF(LayerZ::PARAM_NB_AFFERENTS, 0),
                                        TParamPairSF(LayerZ::PARAM_NB_AFFERENTS, -3),
                                        TParamPairSF(LayerZ::PARAM_WTA_FREQ, -0.001f),
                                        TParamPairSF(LayerZ::PARAM_WTA_FREQ, -1.f)));

TEST_P(LayerZParamsTest, InvalidParams)
{
    TParamPairSF tp = GetParam();
    params_.put(tp.first, tp.second);
    config_.Params(params_);
    EXPECT_THROW(LayerZ().Reset(config_), ExceptionValueError);
}
<|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 <djszapi@archlinux.us>
 *
 * 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 "objectmanager.h"

#include "selectionmanager.h"
#include "newobjectcommand.h"
#include "deleteobjectcommand.h"
#include "propertychangedcommand.h"
#include "historymanager.h"

#include "core/debughelper.h"

#include "engine/gameproject.h"
#include "engine/gameobject.h"
#include "engine/scene.h"
#include "engine/game.h"
#include "engine/component.h"

#include <KDE/KLocalizedString>
#include <KDE/KMimeType>
#include <KDE/KDirWatch>

#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

using namespace GluonCreator;

template<> GLUON_CREATOR_VISIBILITY ObjectManager* GluonCore::Singleton<ObjectManager>::m_instance = 0;

QString
ObjectManager::humanifyClassName( const QString& fixThis, bool justRemoveNamespace ) const
{
    QString fixedString;
    const QString classname = fixThis.right( fixThis.length() - fixThis.lastIndexOf( ':' ) - 1 );
    if( justRemoveNamespace )
        return classname;
    const int length = classname.size();
    for( int i = 0; i < length; ++i )
    {
        const QChar current = classname.at( i );
        if( i == 0 )
        {
            // Always upper-case the first word, whether it is or not...
            fixedString = current.toUpper();
        }
        else
        {
            if( current.isUpper() )
            {
                fixedString = fixedString % ' ' % current;
            }
            else
            {
                fixedString = fixedString % current;
            }
        }
    }
    return fixedString;
}

GluonEngine::Asset* ObjectManager::createNewAsset( const QString& fileName, const QString& className, const QString& name )
{
    DEBUG_BLOCK
    GluonCore::GluonObject* newChild = 0;
    if( className.isEmpty() )
    {
        KMimeType::Ptr type = KMimeType::findByFileContent( fileName );
        DEBUG_TEXT( QString( "Creating asset for file %1 of mimetype %2" ).arg( fileName ).arg( type->name() ) );
        newChild = GluonCore::GluonObjectFactory::instance()->instantiateObjectByMimetype( type->name() );
    }
    else
    {
        newChild = GluonCore::GluonObjectFactory::instance()->instantiateObjectByName( className );
    }

    GluonEngine::Asset* newAsset = qobject_cast< GluonEngine::Asset* >( newChild );
    if( newAsset )
    {
        setupAsset( newAsset, fileName, name );
        return newAsset;
    }

    return 0;
}

void ObjectManager::setupAsset( GluonEngine::Asset* newAsset, const QString& fileName, const QString& name )
{
    GluonEngine::Game::instance()->gameProject()->addChild( newAsset );
    newAsset->setGameProject( GluonEngine::Game::instance()->gameProject() );

    QFileInfo info( fileName );
    if( name.isNull() )
    {
        newAsset->setName( info.fileName() );
    }
    else
    {
        newAsset->setName( name );
    }

    if( !QDir::current().exists( "Assets" ) )
        QDir::current().mkdir( "Assets" );

    QUrl newLocation( QString( "Assets/%1" ).arg( newAsset->fullyQualifiedFileName() ) );

    QFile( fileName ).copy( newLocation.toLocalFile() );

    newAsset->setFile( newLocation );
    newAsset->load();

    QString path( newAsset->absolutePath() );
    m_assets.insert( path, newAsset );
    KDirWatch::self()->addFile( path );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newAsset ) );
}

void ObjectManager::changeProperty( GluonCore::GluonObject* object, QString& property, QVariant& oldValue, QVariant& newValue )
{
    HistoryManager::instance()->addCommand( new PropertyChangedCommand( object, property, oldValue, newValue ) );
}

GluonEngine::Component* ObjectManager::createNewComponent( const QString& type, GluonEngine::GameObject* parent )
{
    DEBUG_BLOCK
    GluonCore::GluonObject* newObj = GluonCore::GluonObjectFactory::instance()->instantiateObjectByName( type );
    if( newObj )
    {
        newObj->setName( humanifyClassName( newObj->metaObject()->className(), true ) );

        GluonEngine::Component* comp = qobject_cast<GluonEngine::Component*>( newObj );
        parent->addComponent( comp );

        // Initialize the component
        comp->initialize();

        emit newComponent( comp );

        HistoryManager::instance()->addCommand( new NewObjectCommand( comp ) );

        return comp;
    }
    return 0;
}

GluonEngine::GameObject* ObjectManager::createNewGameObject()
{
    DEBUG_FUNC_NAME
    GluonEngine::GameObject* newObj = new GluonEngine::GameObject();
    newObj->setName( humanifyClassName( newObj->metaObject()->className(), false ) );
    DEBUG_TEXT( QString( "Creating object: %1" ).arg( newObj->name() ) );

    SelectionManager::SelectionList selection = SelectionManager::instance()->selection();
    if( selection.size() > 0 )
    {
        GluonEngine::GameObject* obj = qobject_cast<GluonEngine::GameObject*>( selection.at( 0 ) );
        if( obj )
        {
            DEBUG_TEXT( QString( "Item %1 selected in Scene tree - assign new object as child" ).arg( obj->fullyQualifiedName() ) );
            obj->addChild( newObj );
        }
    }

    if( newObj->parentGameObject() == 0 )
    {
        DEBUG_TEXT( QString( "No parent game object yet - assign as child to Scene root" ) );
        GluonEngine::Game::instance()->currentScene()->sceneContents()->addChild( newObj );
    }

    emit newGameObject( newObj );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newObj ) );

    return newObj;
}

void ObjectManager::deleteGameObject( GluonEngine::GameObject* object )
{
    if(!object && !object->parentGameObject())
    {
        qDebug() << "No parent game object for the object specified for deleting";
    }

    if (!object->parentGameObject()->removeChild(object))
        qDebug() << "Could not add the game object to the scene tree";

    emit gameObjectDeleted();
    HistoryManager::instance()->addCommand( new DeleteObjectCommand( object, object->parentGameObject() ) );
}

GluonEngine::Scene* ObjectManager::createNewScene()
{
    GluonEngine::Scene* newScn = new GluonEngine::Scene();
    newScn->setName( i18n( "NewScene" ) );
    newScn->setGameProject( GluonEngine::Game::instance()->gameProject() );
    GluonEngine::Game::instance()->gameProject()->addChild( newScn );

    emit newScene( newScn );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newScn ) );

    return newScn;
}

void ObjectManager::watchCurrentAssets()
{
    DEBUG_FUNC_NAME
    QObjectList assets = GluonEngine::Game::instance()->gameProject()->children();
    foreach( QObject* child, assets )
    {
        GluonEngine::Asset* asset = qobject_cast<GluonEngine::Asset*>( child );
        if( asset )
        {
            QString path( asset->absolutePath() );
            DEBUG_TEXT( QString( "Watching %1 for changes." ).arg( path ) );
            KDirWatch::self()->addFile( path );
            m_assets.insert( path, asset );
        }
    }
}

void ObjectManager::assetDirty( const QString& file)
{
    GluonEngine::Asset* asset = m_assets.value(file);
    if( asset )
    {
        asset->reload();
        GluonEngine::Game::instance()->drawAll();
    }
}

void ObjectManager::assetDeleted( const QString& file)
{
    m_assets.remove(file);
    KDirWatch::self()->removeFile( file );
    QFileInfo fi(file);
    if( fi.isFile())
    {
        QFile::remove(file);
    }
    else if( fi.isDir())
    {
        QDir d;
        d.rmpath(file);
    }
}

void ObjectManager::assetDeleted( GluonEngine::Asset* asset )
{
    assetDeleted( asset->absolutePath() );
}

ObjectManager::ObjectManager()
{
    m_objectId = 0;
    m_sceneId = 0;

    connect( KDirWatch::self(), SIGNAL( dirty( const QString& ) ), SLOT( assetDirty( const QString& ) ) );
    connect( KDirWatch::self(), SIGNAL( created( const QString& ) ), SLOT( assetDirty( const QString& ) ) );
}

ObjectManager::~ObjectManager()
{

}
<commit_msg>New assets are given a different name if it already exists<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (c) 2011 Laszlo Papp <djszapi@archlinux.us>
 *
 * 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 "objectmanager.h"

#include "selectionmanager.h"
#include "newobjectcommand.h"
#include "deleteobjectcommand.h"
#include "propertychangedcommand.h"
#include "historymanager.h"

#include "core/debughelper.h"

#include "engine/gameproject.h"
#include "engine/gameobject.h"
#include "engine/scene.h"
#include "engine/game.h"
#include "engine/component.h"

#include <KDE/KLocalizedString>
#include <KDE/KMimeType>
#include <KDE/KDirWatch>

#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

using namespace GluonCreator;

template<> GLUON_CREATOR_VISIBILITY ObjectManager* GluonCore::Singleton<ObjectManager>::m_instance = 0;

QString
ObjectManager::humanifyClassName( const QString& fixThis, bool justRemoveNamespace ) const
{
    QString fixedString;
    const QString classname = fixThis.right( fixThis.length() - fixThis.lastIndexOf( ':' ) - 1 );
    if( justRemoveNamespace )
        return classname;
    const int length = classname.size();
    for( int i = 0; i < length; ++i )
    {
        const QChar current = classname.at( i );
        if( i == 0 )
        {
            // Always upper-case the first word, whether it is or not...
            fixedString = current.toUpper();
        }
        else
        {
            if( current.isUpper() )
            {
                fixedString = fixedString % ' ' % current;
            }
            else
            {
                fixedString = fixedString % current;
            }
        }
    }
    return fixedString;
}

GluonEngine::Asset* ObjectManager::createNewAsset( const QString& fileName, const QString& className, const QString& name )
{
    DEBUG_BLOCK
    GluonCore::GluonObject* newChild = 0;
    if( className.isEmpty() )
    {
        KMimeType::Ptr type = KMimeType::findByFileContent( fileName );
        DEBUG_TEXT( QString( "Creating asset for file %1 of mimetype %2" ).arg( fileName ).arg( type->name() ) );
        newChild = GluonCore::GluonObjectFactory::instance()->instantiateObjectByMimetype( type->name() );
    }
    else
    {
        newChild = GluonCore::GluonObjectFactory::instance()->instantiateObjectByName( className );
    }

    GluonEngine::Asset* newAsset = qobject_cast< GluonEngine::Asset* >( newChild );
    if( newAsset )
    {
        setupAsset( newAsset, fileName, name );
        return newAsset;
    }

    return 0;
}

void ObjectManager::setupAsset( GluonEngine::Asset* newAsset, const QString& fileName, const QString& name )
{
    GluonEngine::Game::instance()->gameProject()->addChild( newAsset );
    newAsset->setGameProject( GluonEngine::Game::instance()->gameProject() );

    QFileInfo info( fileName );
    if( name.isNull() )
    {
        newAsset->setName( info.fileName() );
    }
    else
    {
        newAsset->setName( name );
    }

    if( !QDir::current().exists( "Assets" ) )
        QDir::current().mkdir( "Assets" );

    QUrl newLocation( QString( "Assets/%1" ).arg( newAsset->fullyQualifiedFileName() ) );

    int i = 0;
    QStringList theSplitName = newAsset->name().split('.');
    QString firstName = theSplitName.takeAt(0);
    while(QFile::exists(newLocation.toLocalFile()))
    {
        i++;
        QString newName = firstName.append( QString( " (%1)." ).arg( i ) ).append( theSplitName.join(".") );
        newAsset->setName( newName );
        newLocation = QUrl( QString( "Assets/%1" ).arg( newAsset->fullyQualifiedFileName() ) );
    }

    QFile( fileName ).copy( newLocation.toLocalFile() );

    newAsset->setFile( newLocation );
    newAsset->load();

    QString path( newAsset->absolutePath() );
    m_assets.insert( path, newAsset );
    KDirWatch::self()->addFile( path );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newAsset ) );
}

void ObjectManager::changeProperty( GluonCore::GluonObject* object, QString& property, QVariant& oldValue, QVariant& newValue )
{
    HistoryManager::instance()->addCommand( new PropertyChangedCommand( object, property, oldValue, newValue ) );
}

GluonEngine::Component* ObjectManager::createNewComponent( const QString& type, GluonEngine::GameObject* parent )
{
    DEBUG_BLOCK
    GluonCore::GluonObject* newObj = GluonCore::GluonObjectFactory::instance()->instantiateObjectByName( type );
    if( newObj )
    {
        newObj->setName( humanifyClassName( newObj->metaObject()->className(), true ) );

        GluonEngine::Component* comp = qobject_cast<GluonEngine::Component*>( newObj );
        parent->addComponent( comp );

        // Initialize the component
        comp->initialize();

        emit newComponent( comp );

        HistoryManager::instance()->addCommand( new NewObjectCommand( comp ) );

        return comp;
    }
    return 0;
}

GluonEngine::GameObject* ObjectManager::createNewGameObject()
{
    DEBUG_FUNC_NAME
    GluonEngine::GameObject* newObj = new GluonEngine::GameObject();
    newObj->setName( humanifyClassName( newObj->metaObject()->className(), false ) );
    DEBUG_TEXT( QString( "Creating object: %1" ).arg( newObj->name() ) );

    SelectionManager::SelectionList selection = SelectionManager::instance()->selection();
    if( selection.size() > 0 )
    {
        GluonEngine::GameObject* obj = qobject_cast<GluonEngine::GameObject*>( selection.at( 0 ) );
        if( obj )
        {
            DEBUG_TEXT( QString( "Item %1 selected in Scene tree - assign new object as child" ).arg( obj->fullyQualifiedName() ) );
            obj->addChild( newObj );
        }
    }

    if( newObj->parentGameObject() == 0 )
    {
        DEBUG_TEXT( QString( "No parent game object yet - assign as child to Scene root" ) );
        GluonEngine::Game::instance()->currentScene()->sceneContents()->addChild( newObj );
    }

    emit newGameObject( newObj );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newObj ) );

    return newObj;
}

void ObjectManager::deleteGameObject( GluonEngine::GameObject* object )
{
    if(!object && !object->parentGameObject())
    {
        qDebug() << "No parent game object for the object specified for deleting";
    }

    if (!object->parentGameObject()->removeChild(object))
        qDebug() << "Could not add the game object to the scene tree";

    emit gameObjectDeleted();
    HistoryManager::instance()->addCommand( new DeleteObjectCommand( object, object->parentGameObject() ) );
}

GluonEngine::Scene* ObjectManager::createNewScene()
{
    GluonEngine::Scene* newScn = new GluonEngine::Scene();
    newScn->setName( i18n( "NewScene" ) );
    newScn->setGameProject( GluonEngine::Game::instance()->gameProject() );
    GluonEngine::Game::instance()->gameProject()->addChild( newScn );

    emit newScene( newScn );

    HistoryManager::instance()->addCommand( new NewObjectCommand( newScn ) );

    return newScn;
}

void ObjectManager::watchCurrentAssets()
{
    DEBUG_FUNC_NAME
    QObjectList assets = GluonEngine::Game::instance()->gameProject()->children();
    foreach( QObject* child, assets )
    {
        GluonEngine::Asset* asset = qobject_cast<GluonEngine::Asset*>( child );
        if( asset )
        {
            QString path( asset->absolutePath() );
            DEBUG_TEXT( QString( "Watching %1 for changes." ).arg( path ) );
            KDirWatch::self()->addFile( path );
            m_assets.insert( path, asset );
        }
    }
}

void ObjectManager::assetDirty( const QString& file)
{
    GluonEngine::Asset* asset = m_assets.value(file);
    if( asset )
    {
        asset->reload();
        GluonEngine::Game::instance()->drawAll();
    }
}

void ObjectManager::assetDeleted( const QString& file)
{
    m_assets.remove(file);
    KDirWatch::self()->removeFile( file );
    QFileInfo fi(file);
    if( fi.isFile())
    {
        QFile::remove(file);
    }
    else if( fi.isDir())
    {
        QDir d;
        d.rmpath(file);
    }
}

void ObjectManager::assetDeleted( GluonEngine::Asset* asset )
{
    assetDeleted( asset->absolutePath() );
}

ObjectManager::ObjectManager()
{
    m_objectId = 0;
    m_sceneId = 0;

    connect( KDirWatch::self(), SIGNAL( dirty( const QString& ) ), SLOT( assetDirty( const QString& ) ) );
    connect( KDirWatch::self(), SIGNAL( created( const QString& ) ), SLOT( assetDirty( const QString& ) ) );
}

ObjectManager::~ObjectManager()
{

}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <ros/package.h>
#include <cvt_ros/RGBDSubscriber.h>
#include <tf2_ros/transform_listener.h>

#include <cvt/cl/OpenCL.h>
#include <cvt/cl/CLPlatform.h>
#include <cvt/vision/TSDFVolume.h>
#include <cvt/vision/CameraCalibration.h>

using namespace cvt_ros;

class TSDFMeshing : public RGBDSubscriber
{
    public:
        TSDFMeshing() :
            RGBDSubscriber(),
            _tfListener( _tfBuffer ),
            _volume( 0 ),
            _factorDepthToMeter( (float)(0xFFFF) / 1000.0f ),
            _nMaps( 0 )
        {
            init();
        }

        TSDFMeshing( const cvt::Matrix3f& intrinsics ) :
            RGBDSubscriber( intrinsics ),
            _tfListener( _tfBuffer ),
            _volume( 0 ),
            _factorDepthToMeter( (float)(0xFFFF) / 1000.0f ),
            _nMaps( 0 )
        {
            init();
        }

    private:
        typedef std::vector<cvt::CLPlatform> CLPlatformVec;

        tf2_ros::Buffer             _tfBuffer;
        tf2_ros::TransformListener  _tfListener;
        std::string                 _base, _moving;
        ros::Duration               _timeout;
        cvt::Matrix4f               _gridToWorld;
        cvt::TSDFVolume*            _volume;
        float                       _factorDepthToMeter;
        uint32_t                    _nMaps;
        CLPlatformVec               _platforms;

        void init()
        {
            ros::NodeHandle nh( "~" );
            _moving = "direct_vo";
            _base = "world";
            double dt = 0.4;

            nh.param<std::string>( "moving_frame", _moving, _moving );
            nh.param<std::string>( "base_frame", _base, _base );

            ROS_INFO( "BASE: %s", _base.c_str() );
            ROS_INFO( "MOVING: %s", _moving.c_str() );

            nh.param<double>( "time_out", dt, dt );
            _timeout.fromSec( dt );

            cvt::CLPlatform::get( _platforms );
            cvt::CL::setDefaultDevice( _platforms[ 0 ].defaultDevice() );

            createTSDF( 2, 2, 2, 0.004f );
            _volume->clear();
        }

        void imageCallback( const cvt::Image& rgb, const cvt::Image& depth )
        {
            cvt::Image depthCL;
            depth.convert( depthCL, cvt::IFormat::GRAY_UINT16, cvt::IALLOCATOR_CL );

            try {
                geometry_msgs::TransformStamped transform = _tfBuffer.lookupTransform( _moving, _base, _rgbHeader.stamp, _timeout );
                cvt::Quaternionf q;
                q.x = transform.transform.rotation.x;
                q.y = transform.transform.rotation.y;
                q.z = transform.transform.rotation.z;
                q.w = transform.transform.rotation.w;

                cvt::Matrix4f pose( q.toMatrix3() );
                pose[ 0 ][ 3 ] = transform.transform.translation.x;
                pose[ 1 ][ 3 ] = transform.transform.translation.y;
                pose[ 2 ][ 3 ] = transform.transform.translation.z;

                // Add to the TSDF
                std::cout << _intrinsics << std::endl;
                _volume->addDepthMap( _intrinsics, pose, depthCL, _factorDepthToMeter );
                _nMaps++;
                ROS_INFO( "Volume contains %d depthmaps", _nMaps );
            } catch ( const tf2::TransformException& e ){
                ROS_WARN( "Error in transform lookup: %s", e.what() );
                return;
            }

            // TODO: publish / display current mesh -> not in each step
            if( _nMaps % 200 == 0 ){
                cvt::SceneMesh mesh( "TSDF_MESH" );
                _volume->toSceneMesh( mesh );

                mesh.transform( _gridToWorld );

                meshToOBJ( "tsdf.obj", mesh );
            }
        }

        void createTSDF( uint32_t size_x, uint32_t size_y, uint32_t size_z, float resolution )
        {
            // compute the number of needed "Voxels"
            int nx = size_x / resolution;
            if( nx > 512 ){
                nx = 512;
                resolution = ( float )size_x / ( float )nx;
            }

            int ny = size_y / resolution;
            if( ny > 512 ){
                ny = 512;
                resolution = ( float )size_y / ( float )ny;
                nx = size_x / resolution;
            }

            int nz = size_z / resolution;
            if( nz > 512 ){
                nz = 512;
                resolution = ( float )size_z / ( float )nz;
                nx = size_x / resolution;
                ny = size_y / resolution;
            }

            ROS_INFO( "%d, %d, %d", nx, ny, nz );

            _gridToWorld = cvt::Matrix4f( resolution, 0.0f, 0.0f, -( float )size_x / 2.0f,
                                          0.0f, resolution, 0.0f, -( float )size_y / 2.0f,
                                          0.0f, 0.0f, resolution,  ( float )0.0f,
                                          0.0f, 0.0f, 0.0f, 1.0f );
            std::cout << "GRID2WORLD: " <<_gridToWorld << std::endl;

//            _gridToWorld = cvt::Matrix4f( 2.0f / ( float )( 512 ), 0.0f, 0.0f,  -0.25f,
//                                  0.0f, 2.0f / ( float )( 512 ), 0.0f, -1.5f,
//                                  0.0f, 0.0f, 2.0f / ( float ) ( 512 ), -0.5f,
//                                  0.0f, 0.0f, 0.0f, 0.25 );
//            _gridToWorld *= 4.0f;

            if( _volume != 0 ){
                delete _volume;
            }
            _volume = new cvt::TSDFVolume( _gridToWorld, nx, ny, nz, 15.0f * resolution );
            //_volume = new cvt::TSDFVolume( _gridToWorld, 512, 512, 512, 0.07f );
        }

        void meshToOBJ( const cvt::String& file, const cvt::SceneMesh& mesh  ) const
        {
            FILE* f = fopen( file.c_str(), "wb" );

            ROS_INFO( "MESH: vertices -> %ul, normals -> %lu, faces -> %ul", mesh.vertexSize(), mesh.normalSize(), mesh.faceSize() );

            for( size_t idx = 0; idx < mesh.vertexSize(); idx++ ) {
                cvt::Vector3f vtx = mesh.vertex( idx );
                fprintf( f, "v %f %f %f\n", vtx.x, vtx.y, vtx.z );
            }

            for( size_t idx = 0; idx < mesh.normalSize(); idx++ ) {
                cvt::Vector3f vtx = mesh.normal( idx );
                fprintf( f, "vn %f %f %f\n", vtx.x, vtx.y, vtx.z );
            }

            const unsigned int* faces = mesh.faces();
            for( size_t idx = 0; idx < mesh.faceSize(); idx++ ) {
                fprintf( f, "f %d//%d %d//%d %d//%d\n", *( faces) + 1, *( faces) + 1,
                                                        *( faces + 1 ) + 1, *( faces + 1 ) + 1,
                                                        *( faces + 2 ) + 1, *( faces + 2 ) + 1 );
                faces += 3;
            }

            fclose( f );
        }
};

int main( int argc, char* argv[] )
{
    ros::init( argc, argv, "tsdf_meshing");

    ros::NodeHandle nh( "~" );

    bool useCalibFile = false;
    std::string filename = "xtion_rgb.xml";

    nh.param<std::string>( "calib_file", filename, filename );
    nh.param<bool>( "use_calib_file", useCalibFile, useCalibFile );
    ROS_INFO( "Using Calibration file: %d", useCalibFile );

    if( useCalibFile ){
        try {
            // load calibration
            cvt::String resourcePath;
            resourcePath.sprintf( "%s/resources/%s", ros::package::getPath( "cvt_ros" ).c_str(), filename.c_str() );
            ROS_INFO( "Calibration file: %s", resourcePath.c_str() );
            cvt::CameraCalibration calib;
            calib.load( resourcePath.c_str() );

            TSDFMeshing mesher( calib.intrinsics() );
            ros::spin();

        } catch( cvt::Exception& e ){
            ROS_ERROR( "%s", e.what() );
            return 1;
        }
    } else {
        TSDFMeshing mesher;
        ros::spin();
    }

    return 0;
}
<commit_msg>	modified:   src/tsdf_meshing.cpp<commit_after>#include <ros/ros.h>
#include <ros/package.h>
#include <cvt_ros/RGBDSubscriber.h>
#include <tf2_ros/transform_listener.h>

#include <cvt/cl/OpenCL.h>
#include <cvt/cl/CLPlatform.h>
#include <cvt/vision/TSDFVolume.h>
#include <cvt/vision/CameraCalibration.h>

using namespace cvt_ros;

class TSDFMeshing : public RGBDSubscriber
{
    public:
        TSDFMeshing() :
            RGBDSubscriber(),
            _tfListener( _tfBuffer ),
            _volume( 0 ),
            _factorDepthToMeter( (float)(0xFFFF) / 1000.0f ),
            _nMaps( 0 )
        {
            init();
        }

        TSDFMeshing( const cvt::Matrix3f& intrinsics ) :
            RGBDSubscriber( intrinsics ),
            _tfListener( _tfBuffer ),
            _volume( 0 ),
            _factorDepthToMeter( (float)(0xFFFF) / 1000.0f ),
            _nMaps( 0 )
        {
            init();
        }

    private:
        typedef std::vector<cvt::CLPlatform> CLPlatformVec;

        tf2_ros::Buffer             _tfBuffer;
        tf2_ros::TransformListener  _tfListener;
        std::string                 _base, _moving;
        ros::Duration               _timeout;
        cvt::Matrix4f               _gridToWorld;
        cvt::TSDFVolume*            _volume;
        float                       _factorDepthToMeter;
        uint32_t                    _nMaps;
        CLPlatformVec               _platforms;

        void init()
        {
            ros::NodeHandle nh( "~" );
            _moving = "direct_vo";
            _base = "world";
            double dt = 0.4;

            nh.param<std::string>( "moving_frame", _moving, _moving );
            nh.param<std::string>( "base_frame", _base, _base );

            ROS_INFO( "BASE: %s", _base.c_str() );
            ROS_INFO( "MOVING: %s", _moving.c_str() );

            nh.param<double>( "time_out", dt, dt );
            _timeout.fromSec( dt );

            cvt::CLPlatform::get( _platforms );
            cvt::CL::setDefaultDevice( _platforms[ 0 ].defaultDevice() );

            createTSDF( 2, 2, 2, 0.004f );
            _volume->clear();
        }

        void imageCallback( const cvt::Image& rgb, const cvt::Image& depth )
        {
            cvt::Image depthCL;
            depth.convert( depthCL, cvt::IFormat::GRAY_UINT16, cvt::IALLOCATOR_CL );

            try {
                geometry_msgs::TransformStamped transform = _tfBuffer.lookupTransform( _moving, _base, _rgbHeader.stamp, _timeout );
                cvt::Quaternionf q;
                q.x = transform.transform.rotation.x;
                q.y = transform.transform.rotation.y;
                q.z = transform.transform.rotation.z;
                q.w = transform.transform.rotation.w;

                cvt::Matrix4f pose( q.toMatrix3() );
                pose[ 0 ][ 3 ] = transform.transform.translation.x;
                pose[ 1 ][ 3 ] = transform.transform.translation.y;
                pose[ 2 ][ 3 ] = transform.transform.translation.z;

                // Add to the TSDF
                std::cout << _intrinsics << std::endl;
                _volume->addDepthMap( _intrinsics, pose, depthCL, _factorDepthToMeter );
                _nMaps++;
                ROS_INFO( "Volume contains %d depthmaps", _nMaps );
            } catch ( const tf2::TransformException& e ){
                ROS_WARN( "Error in transform lookup: %s", e.what() );
                return;
            }

            // TODO: publish / display current mesh -> not in each step
            if( _nMaps % 200 == 0 ){
                cvt::SceneMesh mesh( "TSDF_MESH" );
                _volume->toSceneMesh( mesh );

                mesh.transform( _gridToWorld );

                meshToOBJ( "tsdf.obj", mesh );
            }
        }

        void createTSDF( uint32_t size_x, uint32_t size_y, uint32_t size_z, float resolution )
        {
            // compute the number of needed "Voxels"
            int nx = size_x / resolution;
            if( nx > 512 ){
                nx = 512;
                resolution = ( float )size_x / ( float )nx;
            }

            int ny = size_y / resolution;
            if( ny > 512 ){
                ny = 512;
                resolution = ( float )size_y / ( float )ny;
                nx = size_x / resolution;
            }

            int nz = size_z / resolution;
            if( nz > 512 ){
                nz = 512;
                resolution = ( float )size_z / ( float )nz;
                nx = size_x / resolution;
                ny = size_y / resolution;
            }

            ROS_INFO( "%d, %d, %d", nx, ny, nz );

            _gridToWorld = cvt::Matrix4f( resolution, 0.0f, 0.0f, -( float )size_x / 2.0f,
                                          0.0f, resolution, 0.0f, -( float )size_y / 2.0f,
                                          0.0f, 0.0f, resolution,  ( float )0.0f,
                                          0.0f, 0.0f, 0.0f, 1.0f );
            std::cout << "GRID2WORLD: " <<_gridToWorld << std::endl;

//            _gridToWorld = cvt::Matrix4f( 2.0f / ( float )( 512 ), 0.0f, 0.0f,  -0.25f,
//                                  0.0f, 2.0f / ( float )( 512 ), 0.0f, -1.5f,
//                                  0.0f, 0.0f, 2.0f / ( float ) ( 512 ), -0.5f,
//                                  0.0f, 0.0f, 0.0f, 0.25 );
//            _gridToWorld *= 4.0f;

            if( _volume != 0 ){
                delete _volume;
            }
            _volume = new cvt::TSDFVolume( _gridToWorld, nx, ny, nz, 15.0f * resolution );
            //_volume = new cvt::TSDFVolume( _gridToWorld, 512, 512, 512, 0.07f );
        }

        void meshToOBJ( const cvt::String& file, const cvt::SceneMesh& mesh  ) const
        {
            FILE* f = fopen( file.c_str(), "wb" );

            ROS_INFO( "MESH: vertices -> %zd, normals -> %zd, faces -> %zd", mesh.vertexSize(), mesh.normalSize(), mesh.faceSize() );

            for( size_t idx = 0; idx < mesh.vertexSize(); idx++ ) {
                cvt::Vector3f vtx = mesh.vertex( idx );
                fprintf( f, "v %f %f %f\n", vtx.x, vtx.y, vtx.z );
            }

            for( size_t idx = 0; idx < mesh.normalSize(); idx++ ) {
                cvt::Vector3f vtx = mesh.normal( idx );
                fprintf( f, "vn %f %f %f\n", vtx.x, vtx.y, vtx.z );
            }

            const unsigned int* faces = mesh.faces();
            for( size_t idx = 0; idx < mesh.faceSize(); idx++ ) {
                fprintf( f, "f %d//%d %d//%d %d//%d\n", *( faces) + 1, *( faces) + 1,
                                                        *( faces + 1 ) + 1, *( faces + 1 ) + 1,
                                                        *( faces + 2 ) + 1, *( faces + 2 ) + 1 );
                faces += 3;
            }

            fclose( f );
        }
};

int main( int argc, char* argv[] )
{
    ros::init( argc, argv, "tsdf_meshing");

    ros::NodeHandle nh( "~" );

    bool useCalibFile = false;
    std::string filename = "xtion_rgb.xml";

    nh.param<std::string>( "calib_file", filename, filename );
    nh.param<bool>( "use_calib_file", useCalibFile, useCalibFile );
    ROS_INFO( "Using Calibration file: %d", useCalibFile );

    if( useCalibFile ){
        try {
            // load calibration
            cvt::String resourcePath;
            resourcePath.sprintf( "%s/resources/%s", ros::package::getPath( "cvt_ros" ).c_str(), filename.c_str() );
            ROS_INFO( "Calibration file: %s", resourcePath.c_str() );
            cvt::CameraCalibration calib;
            calib.load( resourcePath.c_str() );

            TSDFMeshing mesher( calib.intrinsics() );
            ros::spin();

        } catch( cvt::Exception& e ){
            ROS_ERROR( "%s", e.what() );
            return 1;
        }
    } else {
        TSDFMeshing mesher;
        ros::spin();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 by Marc Boris Duerner, Tommi Maekitalo
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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 <cxxtools/http/socket.h>
#include <cxxtools/http/server.h>
#include <cxxtools/log.h>
#include <cassert>

log_define("cxxtools.http.socket")

namespace cxxtools {

namespace http {

void Socket::ParseEvent::onMethod(const std::string& method)
{
    _request.method(method);
}

void Socket::ParseEvent::onUrl(const std::string& url)
{
    _request.url(url);
}

void Socket::ParseEvent::onUrlParam(const std::string& q)
{
    _request.qparams(q);
}

Socket::Socket(SelectorBase& selector, Server& server)
    : TcpSocket(server),
      _server(server),
      _parseEvent(_request),
      _parser(_parseEvent, false),
      _responder(0)
{
    log_info("connection accepted from " << getPeerAddr());

    _stream.attachDevice(*this);
    _stream.buffer().beginRead();
    cxxtools::connect(_stream.buffer().inputReady, *this, &Socket::onInput);
    cxxtools::connect(_stream.buffer().outputReady, *this, &Socket::onOutput);
    cxxtools::connect(_timer.timeout, *this, &Socket::onTimeout);

    _timer.start(_server.readTimeout());

    addSelector(selector);
}

Socket::~Socket()
{
    if (_responder)
        _responder->release();
}

void Socket::removeSelector()
{
    TcpSocket::setSelector(0);
    _timer.setSelector(0);
}

void Socket::addSelector(SelectorBase& selector)
{
    selector.add(*this);
    selector.add(_timer);
}

void Socket::onInput(StreamBuffer& sb)
{
    log_trace("onInput");
    log_debug(this << " read data from " << getPeerAddr());

    if (sb.in_avail() == 0 || sb.device()->eof())
    {
        log_debug("end of stream");
        close();
        delete this;
        return;
    }

    _timer.start(_server.readTimeout());
    if ( _responder == 0 )
    {
        _parser.advance(sb);

        if (_parser.fail())
        {
            _responder = _server.getDefaultResponder(_request);
            _responder->replyError(_reply.body(), _request, _reply,
                std::runtime_error("invalid http header"));
            _responder->release();
            _responder = 0;

            sendReply();

            onOutput(sb);
            return;
        }

        if (_parser.end())
        {
            _responder = _server.getResponder(_request);
            try
            {
                _responder->beginRequest(_stream, _request);
            }
            catch (const std::exception& e)
            {
                _reply.setHeader("Connection", "close");
                _responder->replyError(_reply.body(), _request, _reply, e);
                _responder->release();
                _responder = 0;
                sendReply();

                onOutput(sb);
                return;
            }

            _contentLength = _request.header().contentLength();
            if (_contentLength == 0)
            {
                _server.addReadySockets(this);
                return;
            }

        }
        else
        {
            sb.beginRead();
        }
    }

    if (_responder)
    {
        if (sb.in_avail() > 0)
        {
            try
            {
                std::size_t s = _responder->readBody(_stream);
                assert(s > 0);
                _contentLength -= s;
            }
            catch (const std::exception& e)
            {
                _reply.setHeader("Connection", "close");
                _responder->replyError(_reply.body(), _request, _reply, e);
                _responder->release();
                _responder = 0;
                sendReply();

                onOutput(sb);
                return;
            }
        }

        if (_contentLength <= 0)
        {
            _server.addReadySockets(this);
        }
        else
        {
            sb.beginRead();
        }
    }
}

bool Socket::doReply()
{
    log_trace("http::Socket::doReply");
    try
    {
        _responder->reply(_reply.body(), _request, _reply);
    }
    catch (const std::exception& e)
    {
        log_warn("responder reported error: " << e.what());
        _reply.clear();
        _responder->replyError(_reply.body(), _request, _reply, e);
    }

    _responder->release();
    _responder = 0;

    sendReply();

    return onOutput(_stream.buffer());
}

bool Socket::onOutput(StreamBuffer& sb)
{
    log_trace("onOutput");

    log_debug(this << " send data to " << getPeerAddr());

    sb.beginWrite();

    if ( sb.out_avail() )
    {
        _timer.start(_server.writeTimeout());
    }
    else
    {
        bool keepAlive = _request.header().keepAlive();

        if (keepAlive)
        {
            std::string connection = _reply.getHeader("Connection");

            if (connection == "close"
              || (connection.empty()
                    && (_reply.header().httpVersionMajor() < 1
                     || _reply.header().httpVersionMinor() < 1)))
            {
                keepAlive = false;
            }
        }

        if (keepAlive)
        {
            log_debug("do keep alive");
            _timer.start(_server.keepAliveTimeout());
            _request.clear();
            _reply.clear();
            _parser.reset(false);
            _stream.buffer().beginRead();
        }
        else
        {
            log_debug("don't do keep alive");
            close();
            delete this;
            return false;
        }
    }

    return true;
}

void Socket::onTimeout()
{
    log_debug("timeout");
    close();
    delete this;
}

void Socket::sendReply()
{
    const std::string contentLength = "Content-Length";
    const std::string server = "Server";
    const std::string connection = "Connection";
    const std::string date = "Date";

    _stream << "HTTP/"
        << _reply.header().httpVersionMajor() << '.'
        << _reply.header().httpVersionMinor() << ' '
        << _reply.header().httpReturnCode() << ' '
        << _reply.header().httpReturnText() << "\r\n";

    for (ReplyHeader::const_iterator it = _reply.header().begin();
        it != _reply.header().end(); ++it)
    {
        _stream << it->first << ": " << it->second << "\r\n";
    }

    if (!_reply.header().hasHeader(contentLength))
    {
        _stream << "Content-Length: " << _reply.bodySize() << "\r\n";
    }

    if (!_reply.header().hasHeader(server))
    {
        _stream << "Server: cxxtools-Net-Server\r\n";
    }

    if (!_reply.header().hasHeader(connection))
    {
        _stream << "Connection: "
                << (_request.header().keepAlive() ? "keep-alive" : "close")
                << "\r\n";
    }

    if (!_reply.header().hasHeader(date))
    {
        _stream << "Date: " << MessageHeader::htdateCurrent() << "\r\n";
    }

    _stream << "\r\n";

    _reply.sendBody(_stream);

}

} // namespace http

} // namespace cxxtools
<commit_msg>do not debug-output this pointer - it is mostly useless<commit_after>/*
 * Copyright (C) 2009 by Marc Boris Duerner, Tommi Maekitalo
 *
 * 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.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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 <cxxtools/http/socket.h>
#include <cxxtools/http/server.h>
#include <cxxtools/log.h>
#include <cassert>

log_define("cxxtools.http.socket")

namespace cxxtools {

namespace http {

void Socket::ParseEvent::onMethod(const std::string& method)
{
    _request.method(method);
}

void Socket::ParseEvent::onUrl(const std::string& url)
{
    _request.url(url);
}

void Socket::ParseEvent::onUrlParam(const std::string& q)
{
    _request.qparams(q);
}

Socket::Socket(SelectorBase& selector, Server& server)
    : TcpSocket(server),
      _server(server),
      _parseEvent(_request),
      _parser(_parseEvent, false),
      _responder(0)
{
    log_info("connection accepted from " << getPeerAddr());

    _stream.attachDevice(*this);
    _stream.buffer().beginRead();
    cxxtools::connect(_stream.buffer().inputReady, *this, &Socket::onInput);
    cxxtools::connect(_stream.buffer().outputReady, *this, &Socket::onOutput);
    cxxtools::connect(_timer.timeout, *this, &Socket::onTimeout);

    _timer.start(_server.readTimeout());

    addSelector(selector);
}

Socket::~Socket()
{
    if (_responder)
        _responder->release();
}

void Socket::removeSelector()
{
    TcpSocket::setSelector(0);
    _timer.setSelector(0);
}

void Socket::addSelector(SelectorBase& selector)
{
    selector.add(*this);
    selector.add(_timer);
}

void Socket::onInput(StreamBuffer& sb)
{
    log_trace("onInput");
    log_debug(this << " read data from " << getPeerAddr());

    if (sb.in_avail() == 0 || sb.device()->eof())
    {
        log_debug("end of stream");
        close();
        delete this;
        return;
    }

    _timer.start(_server.readTimeout());
    if ( _responder == 0 )
    {
        _parser.advance(sb);

        if (_parser.fail())
        {
            _responder = _server.getDefaultResponder(_request);
            _responder->replyError(_reply.body(), _request, _reply,
                std::runtime_error("invalid http header"));
            _responder->release();
            _responder = 0;

            sendReply();

            onOutput(sb);
            return;
        }

        if (_parser.end())
        {
            _responder = _server.getResponder(_request);
            try
            {
                _responder->beginRequest(_stream, _request);
            }
            catch (const std::exception& e)
            {
                _reply.setHeader("Connection", "close");
                _responder->replyError(_reply.body(), _request, _reply, e);
                _responder->release();
                _responder = 0;
                sendReply();

                onOutput(sb);
                return;
            }

            _contentLength = _request.header().contentLength();
            if (_contentLength == 0)
            {
                _server.addReadySockets(this);
                return;
            }

        }
        else
        {
            sb.beginRead();
        }
    }

    if (_responder)
    {
        if (sb.in_avail() > 0)
        {
            try
            {
                std::size_t s = _responder->readBody(_stream);
                assert(s > 0);
                _contentLength -= s;
            }
            catch (const std::exception& e)
            {
                _reply.setHeader("Connection", "close");
                _responder->replyError(_reply.body(), _request, _reply, e);
                _responder->release();
                _responder = 0;
                sendReply();

                onOutput(sb);
                return;
            }
        }

        if (_contentLength <= 0)
        {
            _server.addReadySockets(this);
        }
        else
        {
            sb.beginRead();
        }
    }
}

bool Socket::doReply()
{
    log_trace("http::Socket::doReply");
    try
    {
        _responder->reply(_reply.body(), _request, _reply);
    }
    catch (const std::exception& e)
    {
        log_warn("responder reported error: " << e.what());
        _reply.clear();
        _responder->replyError(_reply.body(), _request, _reply, e);
    }

    _responder->release();
    _responder = 0;

    sendReply();

    return onOutput(_stream.buffer());
}

bool Socket::onOutput(StreamBuffer& sb)
{
    log_trace("onOutput");

    log_debug("send data to " << getPeerAddr());

    sb.beginWrite();

    if ( sb.out_avail() )
    {
        _timer.start(_server.writeTimeout());
    }
    else
    {
        bool keepAlive = _request.header().keepAlive();

        if (keepAlive)
        {
            std::string connection = _reply.getHeader("Connection");

            if (connection == "close"
              || (connection.empty()
                    && (_reply.header().httpVersionMajor() < 1
                     || _reply.header().httpVersionMinor() < 1)))
            {
                keepAlive = false;
            }
        }

        if (keepAlive)
        {
            log_debug("do keep alive");
            _timer.start(_server.keepAliveTimeout());
            _request.clear();
            _reply.clear();
            _parser.reset(false);
            _stream.buffer().beginRead();
        }
        else
        {
            log_debug("don't do keep alive");
            close();
            delete this;
            return false;
        }
    }

    return true;
}

void Socket::onTimeout()
{
    log_debug("timeout");
    close();
    delete this;
}

void Socket::sendReply()
{
    const std::string contentLength = "Content-Length";
    const std::string server = "Server";
    const std::string connection = "Connection";
    const std::string date = "Date";

    _stream << "HTTP/"
        << _reply.header().httpVersionMajor() << '.'
        << _reply.header().httpVersionMinor() << ' '
        << _reply.header().httpReturnCode() << ' '
        << _reply.header().httpReturnText() << "\r\n";

    for (ReplyHeader::const_iterator it = _reply.header().begin();
        it != _reply.header().end(); ++it)
    {
        _stream << it->first << ": " << it->second << "\r\n";
    }

    if (!_reply.header().hasHeader(contentLength))
    {
        _stream << "Content-Length: " << _reply.bodySize() << "\r\n";
    }

    if (!_reply.header().hasHeader(server))
    {
        _stream << "Server: cxxtools-Net-Server\r\n";
    }

    if (!_reply.header().hasHeader(connection))
    {
        _stream << "Connection: "
                << (_request.header().keepAlive() ? "keep-alive" : "close")
                << "\r\n";
    }

    if (!_reply.header().hasHeader(date))
    {
        _stream << "Date: " << MessageHeader::htdateCurrent() << "\r\n";
    }

    _stream << "\r\n";

    _reply.sendBody(_stream);

}

} // namespace http

} // namespace cxxtools
<|endoftext|>