<commit_before>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17

// <vector>

// template <class T, class Allocator, class Predicate>
//   typename vector<T, Allocator>::size_type
//   erase_if(vector<T, Allocator>& c, Predicate pred);

//#include <vector>

//#include "test_macros.h"
//#include "test_allocator.h"
//#include "min_allocator.h"

template <class S, class Pred>
void test0(S s, Pred p, S expected, size_t expected_erased_count) {
  ASSERT_SAME_TYPE(typename S::size_type, decltype(erase_if(s, p)));
  assert(expected_erased_count == erase_if(s, p));
  assert(s == expected);
}

template <typename S>
void test()
{
    auto is1 = [](auto v) { return v == 1;};
    auto is2 = [](auto v) { return v == 2;};
    auto is3 = [](auto v) { return v == 3;};
    auto is4 = [](auto v) { return v == 4;};
    auto True  = [](auto) { return true; };
    auto False = [](auto) { return false; };

    test0(S(), is1, S(), 0);

    test0(S({1}), is1, S(), 1);
    test0(S({1}), is2, S({1}), 0);

    test0(S({1, 2}), is1, S({2}), 1);
    test0(S({1, 2}), is2, S({1}), 1);
    test0(S({1, 2}), is3, S({1, 2}), 0);
    test0(S({1, 1}), is1, S(), 2);
    test0(S({1, 1}), is3, S({1, 1}), 0);

    test0(S({1, 2, 3}), is1, S({2, 3}), 1);
    test0(S({1, 2, 3}), is2, S({1, 3}), 1);
    test0(S({1, 2, 3}), is3, S({1, 2}), 1);
    test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0);

    test0(S({1, 1, 1}), is1, S(), 3);
    test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0);
    test0(S({1, 1, 2}), is1, S({2}), 2);
    test0(S({1, 1, 2}), is2, S({1, 1}), 1);
    test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0);
    test0(S({1, 2, 2}), is1, S({2, 2}), 1);
    test0(S({1, 2, 2}), is2, S({1}), 2);
    test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0);

    test0(S({1, 2, 3}), True, S(), 3);
    test0(S({1, 2, 3}), False, S({1, 2, 3}), 0);
}

void main()
{
    test<vector<int>>();
#ifdef LIBCPP_TEST_MIN_ALLOCATOR
    test<vector<int, min_allocator<int>>> ();
#endif
    test<vector<int, test_allocator<int>>> ();

    test<vector<long>>();
    test<vector<double>>();
}
<commit_msg>Consistent container erasure<commit_after>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17

// <vector>

// template <class T, class Allocator, class Predicate>
//   typename vector<T, Allocator>::size_type
//   erase_if(vector<T, Allocator>& c, Predicate pred);

//#include <vector>

//#include "test_macros.h"
//#include "test_allocator.h"
//#include "min_allocator.h"

template <class S, class Pred>
void test0(S s, Pred p, S expected, size_t expected_erased_count) {
  ASSERT_SAME_TYPE(typename S::size_type, decltype(erase_if(s, p)));
  assert(expected_erased_count == erase_if(s, p));
  assert(s == expected);
}

template <typename S>
void test()
{
    using V = typename S::value_type;
    auto is1 = [](V v) { return v == 1;};
    auto is2 = [](V v) { return v == 2;};
    auto is3 = [](V v) { return v == 3;};
    auto is4 = [](V v) { return v == 4;};
    auto True  = [](V) { return true; };
    auto False = [](V) { return false; };

    test0(S(), is1, S(), 0);

    test0(S({1}), is1, S(), 1);
    test0(S({1}), is2, S({1}), 0);

    test0(S({1, 2}), is1, S({2}), 1);
    test0(S({1, 2}), is2, S({1}), 1);
    test0(S({1, 2}), is3, S({1, 2}), 0);
    test0(S({1, 1}), is1, S(), 2);
    test0(S({1, 1}), is3, S({1, 1}), 0);

    test0(S({1, 2, 3}), is1, S({2, 3}), 1);
    test0(S({1, 2, 3}), is2, S({1, 3}), 1);
    test0(S({1, 2, 3}), is3, S({1, 2}), 1);
    test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0);

    test0(S({1, 1, 1}), is1, S(), 3);
    test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0);
    test0(S({1, 1, 2}), is1, S({2}), 2);
    test0(S({1, 1, 2}), is2, S({1, 1}), 1);
    test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0);
    test0(S({1, 2, 2}), is1, S({2, 2}), 1);
    test0(S({1, 2, 2}), is2, S({1}), 2);
    test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0);

    test0(S({1, 2, 3}), True, S(), 3);
    test0(S({1, 2, 3}), False, S({1, 2, 3}), 0);
}

void main()
{
    test<vector<int>>();
#ifdef LIBCPP_TEST_MIN_ALLOCATOR
    test<vector<int, min_allocator<int>>> ();
#endif
    test<vector<int, test_allocator<int>>> ();

    test<vector<long>>();
    test<vector<double>>();
}
<|endoftext|>


<commit_before>#include "SelectSpritesOP.h"

#include "common/Rect.h"
#include "dataset/TextSprite.h"
#include "dataset/FontSprite.h"
#include "dataset/SymbolMgr.h"
#include "dataset/SpriteFactory.h"
#include "component/AbstractEditCMPT.h"
#include "view/PropertySettingPanel.h"
#include "view/SpritePropertySetting.h"
#include "view/MultiSpritesPropertySetting.h"
#include "view/TextPropertySetting.h"
#include "view/FontPropertySetting.h"
#include "view/MultiSpritesImpl.h"
#include "view/GLCanvas.h"
#include "render/DrawSelectedSpriteVisitor.h"
#include "render/PrimitiveDraw.h"
#include "render/style_config.h"

#include <wx/clipbrd.h>
#include <sstream>

namespace d2d
{

SelectSpritesOP::SelectSpritesOP(EditPanel* editPanel, MultiSpritesImpl* spritesImpl,
								 PropertySettingPanel* propertyPanel/* = NULL*/, AbstractEditCMPT* callback/* = NULL*/)
	: DrawRectangleOP(editPanel)
	, m_callback(callback)
	, m_spritesImpl(spritesImpl)
	, m_propertyPanel(propertyPanel)
	, m_bDraggable(true)
{
	m_selection = spritesImpl->getSpriteSelection();
	m_selection->Retain();

	m_firstPos.setInvalid();
}

SelectSpritesOP::~SelectSpritesOP()
{
	m_selection->Clear();
	m_selection->Release();
}

bool SelectSpritesOP::onKeyDown(int keyCode)
{
	if (DrawRectangleOP::onKeyDown(keyCode)) return true;

	if (wxGetKeyState(WXK_CONTROL) && wxGetKeyState(WXK_CONTROL_X))
	{
		pasteToSelection();
		m_spritesImpl->removeSpriteSelection();
		return true;
	}
	else if (wxGetKeyState(WXK_CONTROL) && (keyCode == 'c' || keyCode == 'C'))
	{
		pasteToSelection();
		return true;
	}
	else if (wxGetKeyState(WXK_CONTROL) && wxGetKeyState(WXK_CONTROL_V))
	{
		copyFromSelection();
		return true;
	}

	return false;
}

bool SelectSpritesOP::onMouseLeftDown(int x, int y)
{
 	m_bDraggable = true;

	Vector pos = m_editPanel->transPosScreenToProject(x, y);
	ISprite* selected = selectByPos(pos);
	if (selected && selected->editable)
	{
		if (wxGetKeyState(WXK_CONTROL))
		{
			if (m_selection->IsExist(selected))
				m_selection->Remove(selected);
			else
			{
				m_selection->Add(selected);
				if (m_propertyPanel)
				{
					if (m_selection->Size() == 1)
						m_propertyPanel->setPropertySetting(createPropertySetting(selected));
					else if (m_selection->Size() > 1)
					{
						std::vector<ISprite*> sprites;
						m_selection->Traverse(FetchAllVisitor<ISprite>(sprites));
						m_propertyPanel->setPropertySetting(createPropertySetting(sprites));
					}
					else
						m_propertyPanel->setPropertySetting(createPropertySetting(NULL));
				}
			}
		}
		else
		{
			if (!m_selection->IsExist(selected) && !wxGetKeyState(WXK_SPACE))
			{
				m_selection->Clear();
				m_selection->Add(selected);
				if (m_propertyPanel)
					m_propertyPanel->setPropertySetting(createPropertySetting(selected));
			}
		}
		m_firstPos.setInvalid();

		if (m_callback)
			m_callback->updateControlValue();
	}
	else
	{
		DrawRectangleOP::onMouseLeftDown(x, y);
		m_firstPos = pos;
		if (wxGetKeyState(WXK_CONTROL))
			m_bDraggable = false;
		else
			m_selection->Clear();
		m_editPanel->Refresh();
	}

	return false;
}

bool SelectSpritesOP::onMouseLeftUp(int x, int y)
{
	if (DrawRectangleOP::onMouseLeftUp(x, y)) return true;

	m_bDraggable = true;

	if (m_firstPos.isValid())
	{
		Vector end = m_editPanel->transPosScreenToProject(x, y);
		Rect rect(m_firstPos, end);
		std::vector<ISprite*> sprites;
		m_spritesImpl->querySpritesByRect(rect, m_firstPos.x < end.x, sprites);
		if (wxGetKeyState(WXK_CONTROL))
		{
			for (size_t i = 0, n = sprites.size(); i < n; ++i)
			{
				d2d::ISprite* sprite = sprites[i];
				if (m_selection->IsExist(sprite)) {
					m_selection->Remove(sprites[i]);
				} else {
					m_selection->Add(sprites[i]);
				}
			}
		}
		else
		{
			for (size_t i = 0, n = sprites.size(); i < n; ++i) {
				m_selection->Add(sprites[i]);
			}
		}

		if (m_propertyPanel)
		{
			if (m_selection->Size() == 1)
				m_propertyPanel->setPropertySetting(createPropertySetting(sprites[0]));
			else if (m_selection->Size() > 1)
				m_propertyPanel->setPropertySetting(createPropertySetting(sprites));
			else
				m_propertyPanel->setPropertySetting(createPropertySetting(NULL));
		}

		m_firstPos.setInvalid();

		if (m_callback)
			m_callback->updateControlValue();
	}

//	enableRightTap(m_selection->empty());

	return false;
}

bool SelectSpritesOP::onMouseRightDown(int x, int y)
{
	m_rightFirstScrPos.set(x, y);

	enableRightTap(m_selection->IsEmpty());

	if (DrawRectangleOP::onMouseRightDown(x, y)) return true;

	return false;
}

bool SelectSpritesOP::onMouseRightUp(int x, int y)
{
	// select
	if (m_rightFirstScrPos == Vector(x, y))
	{
		Vector pos = m_editPanel->transPosScreenToProject(x, y);
		d2d::ISprite* sprite = m_spritesImpl->querySpriteByPos(pos);
		if (sprite)
		{
			m_selection->Clear();
			m_selection->Add(sprite);
			enableRightTap(m_selection->IsEmpty());
			m_editPanel->Refresh();
		}
	}

	if (DrawRectangleOP::onMouseRightUp(x, y)) return true;

	return false;
}

bool SelectSpritesOP::onMouseDrag(int x, int y)
{
	if (DrawRectangleOP::onMouseDrag(x, y)) return true;

	return !m_bDraggable;
}

bool SelectSpritesOP::onDraw() const
{
	m_selection->Traverse(DrawSelectedSpriteVisitor(Colorf(1, 0, 0)));

	if (m_firstPos.isValid() && m_currPos.isValid())
	{
		if (m_currPos.x > m_firstPos.x)
		{
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_ALL);
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_BOUND);
		}
		else
		{
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_PART);
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_BOUND);
		}
	}

// 	if (DrawRectangleOP::onDraw()) return true;

	return false;
}

bool SelectSpritesOP::clear()
{
	if (DrawRectangleOP::clear()) return true;

	m_selection->Clear();
	m_firstPos.setInvalid();

	return false;
}

IPropertySetting* SelectSpritesOP::createPropertySetting(ISprite* sprite) const
{
	if (TextSprite* text = dynamic_cast<TextSprite*>(sprite))
		return new TextPropertySetting(m_editPanel, text);
	else if (FontSprite* font = dynamic_cast<FontSprite*>(sprite))
		return new FontPropertySetting(m_editPanel, font);
	else if (sprite)
		return new SpritePropertySetting(m_editPanel, sprite);
	else
		return NULL;
}

IPropertySetting* SelectSpritesOP::createPropertySetting(const std::vector<ISprite*>& sprites) const
{
	return new MultiSpritesPropertySetting(m_editPanel, sprites);
}

ISprite* SelectSpritesOP::selectByPos(const Vector& pos) const
{
	ISprite* selected = NULL;
	std::vector<ISprite*> sprites;
	m_spritesImpl->getSpriteSelection()->Traverse(FetchAllVisitor<ISprite>(sprites));
	for (int i = 0, n = sprites.size(); i < n; ++i)
	{
		if (sprites[i]->isContain(pos)) {
			selected = sprites[i];
			break;
		}
	}
	if (!selected) {
		selected = m_spritesImpl->querySpriteByPos(pos);
	}
	return selected;
}

void SelectSpritesOP::pasteToSelection() const
{
	std::vector<ISprite*> sprites;
	m_selection->Traverse(FetchAllVisitor<ISprite>(sprites));
	Json::Value value;
	for (int i = 0, n = sprites.size(); i < n; ++i)
	{
		Json::Value& sval = value["sprite"][i];
		d2d::ISprite* s = sprites[i];
		if (wxTheClipboard->Open())
		{
			sval["filename"] = s->getSymbol().getFilepath().ToStdString();
			s->store(sval);
			sval["name"] = s->name;
		}
	}
	Json::StyledStreamWriter writer;
	std::stringstream ss;
	writer.write(ss, value);
	wxTheClipboard->SetData(new wxTextDataObject(ss.str()));
	wxTheClipboard->Close();
}

void SelectSpritesOP::copyFromSelection()
{
	if (wxTheClipboard->Open())
	{
		if (wxTheClipboard->IsSupported( wxDF_TEXT ))
		{
			wxTextDataObject data;
			wxTheClipboard->GetData( data );

			Json::Value value;
			Json::Reader reader;
			std::string test = data.GetText().ToStdString();
			reader.parse(data.GetText().ToStdString(), value);

			m_selection->Clear();

			int i = 0;
			Json::Value sval = value["sprite"][i++];
			while (!sval.isNull()) {
				std::string filepath = sval["filename"].asString();
				ISymbol* symbol = SymbolMgr::Instance()->fetchSymbol(filepath);
				// for snapshoot
				symbol->RefreshThumbnail(filepath);
				ISprite* sprite = SpriteFactory::Instance()->create(symbol);
				sprite->name = sval["name"].asString();
				symbol->Release();
				sprite->load(sval);
				m_spritesImpl->insertSprite(sprite);
				m_selection->Add(sprite);
				m_propertyPanel->setPropertySetting(createPropertySetting(sprite));

				sval = value["sprite"][i++];
			}

			m_editPanel->getCanvas()->resetViewport();
		}
		wxTheClipboard->Close();
	}
}

} // d2d<commit_msg>[FIXED] 选择时没有过滤掉!editable的，IDataContainer不止被ISprite继承<commit_after>#include "SelectSpritesOP.h"

#include "common/Rect.h"
#include "dataset/TextSprite.h"
#include "dataset/FontSprite.h"
#include "dataset/SymbolMgr.h"
#include "dataset/SpriteFactory.h"
#include "component/AbstractEditCMPT.h"
#include "view/PropertySettingPanel.h"
#include "view/SpritePropertySetting.h"
#include "view/MultiSpritesPropertySetting.h"
#include "view/TextPropertySetting.h"
#include "view/FontPropertySetting.h"
#include "view/MultiSpritesImpl.h"
#include "view/GLCanvas.h"
#include "render/DrawSelectedSpriteVisitor.h"
#include "render/PrimitiveDraw.h"
#include "render/style_config.h"

#include <wx/clipbrd.h>
#include <sstream>

namespace d2d
{

SelectSpritesOP::SelectSpritesOP(EditPanel* editPanel, MultiSpritesImpl* spritesImpl,
								 PropertySettingPanel* propertyPanel/* = NULL*/, AbstractEditCMPT* callback/* = NULL*/)
	: DrawRectangleOP(editPanel)
	, m_callback(callback)
	, m_spritesImpl(spritesImpl)
	, m_propertyPanel(propertyPanel)
	, m_bDraggable(true)
{
	m_selection = spritesImpl->getSpriteSelection();
	m_selection->Retain();

	m_firstPos.setInvalid();
}

SelectSpritesOP::~SelectSpritesOP()
{
	m_selection->Clear();
	m_selection->Release();
}

bool SelectSpritesOP::onKeyDown(int keyCode)
{
	if (DrawRectangleOP::onKeyDown(keyCode)) return true;

	if (wxGetKeyState(WXK_CONTROL) && wxGetKeyState(WXK_CONTROL_X))
	{
		pasteToSelection();
		m_spritesImpl->removeSpriteSelection();
		return true;
	}
	else if (wxGetKeyState(WXK_CONTROL) && (keyCode == 'c' || keyCode == 'C'))
	{
		pasteToSelection();
		return true;
	}
	else if (wxGetKeyState(WXK_CONTROL) && wxGetKeyState(WXK_CONTROL_V))
	{
		copyFromSelection();
		return true;
	}

	return false;
}

bool SelectSpritesOP::onMouseLeftDown(int x, int y)
{
 	m_bDraggable = true;

	Vector pos = m_editPanel->transPosScreenToProject(x, y);
	ISprite* selected = selectByPos(pos);
	if (selected)
	{
		assert(selected->editable);
		if (wxGetKeyState(WXK_CONTROL))
		{
			if (m_selection->IsExist(selected))
				m_selection->Remove(selected);
			else
			{
				m_selection->Add(selected);
				if (m_propertyPanel)
				{
					if (m_selection->Size() == 1)
						m_propertyPanel->setPropertySetting(createPropertySetting(selected));
					else if (m_selection->Size() > 1)
					{
						std::vector<ISprite*> sprites;
						m_selection->Traverse(FetchAllVisitor<ISprite>(sprites));
						m_propertyPanel->setPropertySetting(createPropertySetting(sprites));
					}
					else
						m_propertyPanel->setPropertySetting(createPropertySetting(NULL));
				}
			}
		}
		else
		{
			if (!m_selection->IsExist(selected) && !wxGetKeyState(WXK_SPACE))
			{
				m_selection->Clear();
				m_selection->Add(selected);
				if (m_propertyPanel)
					m_propertyPanel->setPropertySetting(createPropertySetting(selected));
			}
		}
		m_firstPos.setInvalid();

		if (m_callback)
			m_callback->updateControlValue();
	}
	else
	{
		DrawRectangleOP::onMouseLeftDown(x, y);
		m_firstPos = pos;
		if (wxGetKeyState(WXK_CONTROL))
			m_bDraggable = false;
		else
			m_selection->Clear();
		m_editPanel->Refresh();
	}

	return false;
}

bool SelectSpritesOP::onMouseLeftUp(int x, int y)
{
	if (DrawRectangleOP::onMouseLeftUp(x, y)) return true;

	m_bDraggable = true;

	if (m_firstPos.isValid())
	{
		Vector end = m_editPanel->transPosScreenToProject(x, y);
		Rect rect(m_firstPos, end);
		std::vector<ISprite*> sprites;
		m_spritesImpl->querySpritesByRect(rect, m_firstPos.x < end.x, sprites);
		if (wxGetKeyState(WXK_CONTROL))
		{
			for (size_t i = 0, n = sprites.size(); i < n; ++i)
			{
				d2d::ISprite* sprite = sprites[i];
				if (m_selection->IsExist(sprite)) {
					m_selection->Remove(sprites[i]);
				} else {
					m_selection->Add(sprites[i]);
				}
			}
		}
		else
		{
			for (size_t i = 0, n = sprites.size(); i < n; ++i) {
				m_selection->Add(sprites[i]);
			}
		}

		if (m_propertyPanel)
		{
			if (m_selection->Size() == 1)
				m_propertyPanel->setPropertySetting(createPropertySetting(sprites[0]));
			else if (m_selection->Size() > 1)
				m_propertyPanel->setPropertySetting(createPropertySetting(sprites));
			else
				m_propertyPanel->setPropertySetting(createPropertySetting(NULL));
		}

		m_firstPos.setInvalid();

		if (m_callback)
			m_callback->updateControlValue();
	}

//	enableRightTap(m_selection->empty());

	return false;
}

bool SelectSpritesOP::onMouseRightDown(int x, int y)
{
	m_rightFirstScrPos.set(x, y);

	enableRightTap(m_selection->IsEmpty());

	if (DrawRectangleOP::onMouseRightDown(x, y)) return true;

	return false;
}

bool SelectSpritesOP::onMouseRightUp(int x, int y)
{
	// select
	if (m_rightFirstScrPos == Vector(x, y))
	{
		Vector pos = m_editPanel->transPosScreenToProject(x, y);
		d2d::ISprite* sprite = m_spritesImpl->querySpriteByPos(pos);
		if (sprite)
		{
			m_selection->Clear();
			m_selection->Add(sprite);
			enableRightTap(m_selection->IsEmpty());
			m_editPanel->Refresh();
		}
	}

	if (DrawRectangleOP::onMouseRightUp(x, y)) return true;

	return false;
}

bool SelectSpritesOP::onMouseDrag(int x, int y)
{
	if (DrawRectangleOP::onMouseDrag(x, y)) return true;

	return !m_bDraggable;
}

bool SelectSpritesOP::onDraw() const
{
	m_selection->Traverse(DrawSelectedSpriteVisitor(Colorf(1, 0, 0)));

	if (m_firstPos.isValid() && m_currPos.isValid())
	{
		if (m_currPos.x > m_firstPos.x)
		{
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_ALL);
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_BOUND);
		}
		else
		{
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_PART);
			PrimitiveDraw::rect(m_firstPos, m_currPos, SELECT_BOUND);
		}
	}

// 	if (DrawRectangleOP::onDraw()) return true;

	return false;
}

bool SelectSpritesOP::clear()
{
	if (DrawRectangleOP::clear()) return true;

	m_selection->Clear();
	m_firstPos.setInvalid();

	return false;
}

IPropertySetting* SelectSpritesOP::createPropertySetting(ISprite* sprite) const
{
	if (TextSprite* text = dynamic_cast<TextSprite*>(sprite))
		return new TextPropertySetting(m_editPanel, text);
	else if (FontSprite* font = dynamic_cast<FontSprite*>(sprite))
		return new FontPropertySetting(m_editPanel, font);
	else if (sprite)
		return new SpritePropertySetting(m_editPanel, sprite);
	else
		return NULL;
}

IPropertySetting* SelectSpritesOP::createPropertySetting(const std::vector<ISprite*>& sprites) const
{
	return new MultiSpritesPropertySetting(m_editPanel, sprites);
}

ISprite* SelectSpritesOP::selectByPos(const Vector& pos) const
{
	ISprite* selected = NULL;
	std::vector<ISprite*> sprites;
	m_spritesImpl->getSpriteSelection()->Traverse(FetchAllVisitor<ISprite>(sprites));
	for (int i = 0, n = sprites.size(); i < n; ++i)
	{
		if (sprites[i]->isContain(pos)) {
			selected = sprites[i];
			break;
		}
	}
	if (!selected) {
		ISprite* spr = m_spritesImpl->querySpriteByPos(pos);
		if (!spr || !spr->editable) {
			std::vector<ISprite*> sprites;
			m_spritesImpl->querySpritesByRect(Rect(pos, 1, 1), false, sprites);
			if (!sprites.empty()) {
				selected = sprites.back();
			}
		} else {
			selected = spr;
		}
	}
	return selected;
}

void SelectSpritesOP::pasteToSelection() const
{
	std::vector<ISprite*> sprites;
	m_selection->Traverse(FetchAllVisitor<ISprite>(sprites));
	Json::Value value;
	for (int i = 0, n = sprites.size(); i < n; ++i)
	{
		Json::Value& sval = value["sprite"][i];
		d2d::ISprite* s = sprites[i];
		if (wxTheClipboard->Open())
		{
			sval["filename"] = s->getSymbol().getFilepath().ToStdString();
			s->store(sval);
			sval["name"] = s->name;
		}
	}
	Json::StyledStreamWriter writer;
	std::stringstream ss;
	writer.write(ss, value);
	wxTheClipboard->SetData(new wxTextDataObject(ss.str()));
	wxTheClipboard->Close();
}

void SelectSpritesOP::copyFromSelection()
{
	if (wxTheClipboard->Open())
	{
		if (wxTheClipboard->IsSupported( wxDF_TEXT ))
		{
			wxTextDataObject data;
			wxTheClipboard->GetData( data );

			Json::Value value;
			Json::Reader reader;
			std::string test = data.GetText().ToStdString();
			reader.parse(data.GetText().ToStdString(), value);

			m_selection->Clear();

			int i = 0;
			Json::Value sval = value["sprite"][i++];
			while (!sval.isNull()) {
				std::string filepath = sval["filename"].asString();
				ISymbol* symbol = SymbolMgr::Instance()->fetchSymbol(filepath);
				// for snapshoot
				symbol->RefreshThumbnail(filepath);
				ISprite* sprite = SpriteFactory::Instance()->create(symbol);
				sprite->name = sval["name"].asString();
				symbol->Release();
				sprite->load(sval);
				m_spritesImpl->insertSprite(sprite);
				m_selection->Add(sprite);
				m_propertyPanel->setPropertySetting(createPropertySetting(sprite));

				sval = value["sprite"][i++];
			}

			m_editPanel->getCanvas()->resetViewport();
		}
		wxTheClipboard->Close();
	}
}

} // d2d<|endoftext|>


<commit_before>#include "FontPropertySetting.h"
#include "PropertySettingPanel.h"

#include "dataset/FontSprite.h"

#include <wx/propgrid/advprops.h>

namespace d2d
{

const wxChar* FontPropertySetting::HORI_ALIGN_LABELS[] = {
	wxT("left"), wxT("right"), wxT("center"), wxT("auto"), NULL };
const wxChar* FontPropertySetting::VERT_ALIGN_LABELS[] = {
	wxT("top"), wxT("bottom"), wxT("center"), wxT("auto"), NULL };

FontPropertySetting::FontPropertySetting(EditPanel* editPanel, FontSprite* sprite)
	: SpritePropertySetting(editPanel, sprite)
{
	m_type = wxT("Font");
}

void FontPropertySetting::onPropertyGridChange(const wxString& name, const wxAny& value)
{
	SpritePropertySetting::onPropertyGridChange(name, value);

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	if (name == wxT("Font"))
		sprite->font = wxANY_AS(value, wxString);
	else if (name == wxT("Edge")) {
		sprite->has_edge = wxANY_AS(value, bool);
	}
	else if (name == wxT("FontColor")) {
		wxColour col = wxANY_AS(value, wxColour);
		sprite->color.set(col.Red() / 255.0f, col.Green() / 255.0f, col.Blue() / 255.0f, col.Alpha() / 255.0f);
	}
	else if (name == wxT("AlignHori"))
		sprite->align_hori = HoriAlignType(wxANY_AS(value, int));
	else if (name == wxT("AlignVert"))
		sprite->align_vert = VertAlignType(wxANY_AS(value, int));
	else if (name == wxT("FontSize"))
		sprite->size = wxANY_AS(value, float);
	else if (name == wxT("LabelWidth")) {
		sprite->width = wxANY_AS(value, float);
		sprite->buildBounding();
	}
	else if (name == wxT("LabelHeight")) {
		sprite->height = wxANY_AS(value, float);
		sprite->buildBounding();
	} else if (name == wxT("Filename")) {
		std::string str = wxANY_AS(value, wxString);
		sprite->loadFont(str);
	} else if (name == wxT("TextContent")) {
		std::string str = wxANY_AS(value, wxString);
		sprite->SetTextContent(str);
	}
}

void FontPropertySetting::enablePropertyGrid(PropertySettingPanel* panel, bool bEnable)
{
	SpritePropertySetting::enablePropertyGrid(panel, bEnable);

	wxPropertyGrid* pg = panel->getPG();
	pg->GetProperty(wxT("Font"))->Enable(bEnable);
	pg->GetProperty(wxT("FontColor"))->Enable(bEnable);
	pg->GetProperty(wxT("AlignHori"))->Enable(bEnable);
	pg->GetProperty(wxT("AlignVert"))->Enable(bEnable);
	pg->GetProperty(wxT("FontSize"))->Enable(bEnable);
	pg->GetProperty(wxT("LabelWidth"))->Enable(bEnable);
	pg->GetProperty(wxT("LabelHeight"))->Enable(bEnable);
	pg->GetProperty(wxT("Filename"))->Enable(bEnable);
	pg->GetProperty(wxT("TextContent"))->Enable(bEnable);
}

void FontPropertySetting::updateProperties(wxPropertyGrid* pg)
{
	SpritePropertySetting::updateProperties(pg);

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	pg->GetProperty(wxT("Font"))->SetValue(sprite->font);

	wxColour col = wxColour(sprite->color.r*255, sprite->color.g*255, sprite->color.b*255, sprite->color.a*255);
	pg->SetPropertyValueString(wxT("FontColor"), col.GetAsString());

	pg->GetProperty(wxT("AlignHori"))->SetValue(HORI_ALIGN_LABELS[sprite->align_hori]);
	pg->GetProperty(wxT("AlignVert"))->SetValue(VERT_ALIGN_LABELS[sprite->align_vert]);
	pg->GetProperty(wxT("FontSize"))->SetValue(sprite->size);
	pg->GetProperty(wxT("LabelWidth"))->SetValue(sprite->width);
	pg->GetProperty(wxT("LabelHeight"))->SetValue(sprite->height);
	pg->GetProperty(wxT("Filename"))->SetValue(sprite->filename);
	pg->GetProperty(wxT("TextContent"))->SetValue(sprite->GetTextContext());
}

void FontPropertySetting::initProperties(wxPropertyGrid* pg)
{
	SpritePropertySetting::initProperties(pg);

	pg->Append(new wxPropertyCategory("FONT", wxPG_LABEL));

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	pg->Append(new wxStringProperty(wxT("Font"), wxPG_LABEL, sprite->font));

	pg->Append(new wxBoolProperty(wxT("Edge"), wxPG_LABEL, sprite->has_edge));

	wxColour col = wxColour(sprite->addCol.r*255, sprite->addCol.g*255, sprite->addCol.b*255, sprite->addCol.a*255);
	pg->Append(new wxColourProperty(wxT("FontColor"), wxPG_LABEL, col));
	pg->SetPropertyAttribute("FontColor", "HasAlpha", true);

	wxEnumProperty* horiAlignProp = new wxEnumProperty(wxT("AlignHori"), wxPG_LABEL, HORI_ALIGN_LABELS);
	horiAlignProp->SetValue(HORI_ALIGN_LABELS[sprite->align_hori]);
	pg->Append(horiAlignProp);

	wxEnumProperty* vertAlignProp = new wxEnumProperty(wxT("AlignVert"), wxPG_LABEL, VERT_ALIGN_LABELS);
	vertAlignProp->SetValue(VERT_ALIGN_LABELS[sprite->align_vert]);
	pg->Append(vertAlignProp);

	pg->Append(new wxFloatProperty(wxT("FontSize"), wxPG_LABEL, sprite->size));
	pg->Append(new wxFloatProperty(wxT("LabelWidth"), wxPG_LABEL, sprite->width));
	pg->Append(new wxFloatProperty(wxT("LabelHeight"), wxPG_LABEL, sprite->height));
	pg->Append(new wxStringProperty(wxT("Filename"), wxPG_LABEL, sprite->filename));
	pg->Append(new wxStringProperty(wxT("TextContent"), wxPG_LABEL, sprite->GetTextContext()));
}

}<commit_msg>[FIXED] FontPropertySetting Edge项<commit_after>#include "FontPropertySetting.h"
#include "PropertySettingPanel.h"

#include "dataset/FontSprite.h"

#include <wx/propgrid/advprops.h>

namespace d2d
{

const wxChar* FontPropertySetting::HORI_ALIGN_LABELS[] = {
	wxT("left"), wxT("right"), wxT("center"), wxT("auto"), NULL };
const wxChar* FontPropertySetting::VERT_ALIGN_LABELS[] = {
	wxT("top"), wxT("bottom"), wxT("center"), wxT("auto"), NULL };

FontPropertySetting::FontPropertySetting(EditPanel* editPanel, FontSprite* sprite)
	: SpritePropertySetting(editPanel, sprite)
{
	m_type = wxT("Font");
}

void FontPropertySetting::onPropertyGridChange(const wxString& name, const wxAny& value)
{
	SpritePropertySetting::onPropertyGridChange(name, value);

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	if (name == wxT("Font"))
		sprite->font = wxANY_AS(value, wxString);
	else if (name == wxT("Edge")) {
		sprite->has_edge = wxANY_AS(value, bool);
	}
	else if (name == wxT("FontColor")) {
		wxColour col = wxANY_AS(value, wxColour);
		sprite->color.set(col.Red() / 255.0f, col.Green() / 255.0f, col.Blue() / 255.0f, col.Alpha() / 255.0f);
	}
	else if (name == wxT("AlignHori"))
		sprite->align_hori = HoriAlignType(wxANY_AS(value, int));
	else if (name == wxT("AlignVert"))
		sprite->align_vert = VertAlignType(wxANY_AS(value, int));
	else if (name == wxT("FontSize"))
		sprite->size = wxANY_AS(value, float);
	else if (name == wxT("LabelWidth")) {
		sprite->width = wxANY_AS(value, float);
		sprite->buildBounding();
	}
	else if (name == wxT("LabelHeight")) {
		sprite->height = wxANY_AS(value, float);
		sprite->buildBounding();
	} else if (name == wxT("Filename")) {
		std::string str = wxANY_AS(value, wxString);
		sprite->loadFont(str);
	} else if (name == wxT("TextContent")) {
		std::string str = wxANY_AS(value, wxString);
		sprite->SetTextContent(str);
	}
}

void FontPropertySetting::enablePropertyGrid(PropertySettingPanel* panel, bool bEnable)
{
	SpritePropertySetting::enablePropertyGrid(panel, bEnable);

	wxPropertyGrid* pg = panel->getPG();
	pg->GetProperty(wxT("Font"))->Enable(bEnable);
	pg->GetProperty(wxT("Edge"))->Enable(bEnable);
	pg->GetProperty(wxT("FontColor"))->Enable(bEnable);
	pg->GetProperty(wxT("AlignHori"))->Enable(bEnable);
	pg->GetProperty(wxT("AlignVert"))->Enable(bEnable);
	pg->GetProperty(wxT("FontSize"))->Enable(bEnable);
	pg->GetProperty(wxT("LabelWidth"))->Enable(bEnable);
	pg->GetProperty(wxT("LabelHeight"))->Enable(bEnable);
	pg->GetProperty(wxT("Filename"))->Enable(bEnable);
	pg->GetProperty(wxT("TextContent"))->Enable(bEnable);
}

void FontPropertySetting::updateProperties(wxPropertyGrid* pg)
{
	SpritePropertySetting::updateProperties(pg);

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	pg->GetProperty(wxT("Font"))->SetValue(sprite->font);

	pg->GetProperty(wxT("Edge"))->SetValue(sprite->has_edge);

	wxColour col = wxColour(sprite->color.r*255, sprite->color.g*255, sprite->color.b*255, sprite->color.a*255);
	pg->SetPropertyValueString(wxT("FontColor"), col.GetAsString());

	pg->GetProperty(wxT("AlignHori"))->SetValue(HORI_ALIGN_LABELS[sprite->align_hori]);
	pg->GetProperty(wxT("AlignVert"))->SetValue(VERT_ALIGN_LABELS[sprite->align_vert]);
	pg->GetProperty(wxT("FontSize"))->SetValue(sprite->size);
	pg->GetProperty(wxT("LabelWidth"))->SetValue(sprite->width);
	pg->GetProperty(wxT("LabelHeight"))->SetValue(sprite->height);
	pg->GetProperty(wxT("Filename"))->SetValue(sprite->filename);
	pg->GetProperty(wxT("TextContent"))->SetValue(sprite->GetTextContext());
}

void FontPropertySetting::initProperties(wxPropertyGrid* pg)
{
	SpritePropertySetting::initProperties(pg);

	pg->Append(new wxPropertyCategory("FONT", wxPG_LABEL));

	FontSprite* sprite = static_cast<FontSprite*>(m_sprite);
	pg->Append(new wxStringProperty(wxT("Font"), wxPG_LABEL, sprite->font));

	pg->Append(new wxBoolProperty(wxT("Edge"), wxPG_LABEL, sprite->has_edge));

	wxColour col = wxColour(sprite->addCol.r*255, sprite->addCol.g*255, sprite->addCol.b*255, sprite->addCol.a*255);
	pg->Append(new wxColourProperty(wxT("FontColor"), wxPG_LABEL, col));
	pg->SetPropertyAttribute("FontColor", "HasAlpha", true);

	wxEnumProperty* horiAlignProp = new wxEnumProperty(wxT("AlignHori"), wxPG_LABEL, HORI_ALIGN_LABELS);
	horiAlignProp->SetValue(HORI_ALIGN_LABELS[sprite->align_hori]);
	pg->Append(horiAlignProp);

	wxEnumProperty* vertAlignProp = new wxEnumProperty(wxT("AlignVert"), wxPG_LABEL, VERT_ALIGN_LABELS);
	vertAlignProp->SetValue(VERT_ALIGN_LABELS[sprite->align_vert]);
	pg->Append(vertAlignProp);

	pg->Append(new wxFloatProperty(wxT("FontSize"), wxPG_LABEL, sprite->size));
	pg->Append(new wxFloatProperty(wxT("LabelWidth"), wxPG_LABEL, sprite->width));
	pg->Append(new wxFloatProperty(wxT("LabelHeight"), wxPG_LABEL, sprite->height));
	pg->Append(new wxStringProperty(wxT("Filename"), wxPG_LABEL, sprite->filename));
	pg->Append(new wxStringProperty(wxT("TextContent"), wxPG_LABEL, sprite->GetTextContext()));
}

}<|endoftext|>


<commit_before>#include <iostream>
#include "ros/ros.h"
#include "sensor_msgs/PointCloud2.h"
#include "sensor_msgs/NavSatFix.h"
#include "sensor_msgs/Imu.h"
#include "nav_msgs/Odometry.h"
#include "laser_transform_core.h"

using std::string;

int main (int argc, char **argv)
{
  ros::init(argc, argv, "laser_transform");
  ros::NodeHandle n;

  // Declare variables thar can be modified by launch file or command line.
  int rate;
  bool imu_msgs;
  bool gps_msgs;
  string pcl_in_topic;
  string pcl_out_topic;
  string imu_topic;
  string gps_topic;
  //string odo_topic;

  // Create a new LaserTransformer object.
  LaserTransform *node_lt = new LaserTransform();

  node_lt->init();

  // while using different parameters.
  ros::NodeHandle private_node_handle_("~");
  private_node_handle_.param("rate", rate, int(10));
  private_node_handle_.param("imu_msgs", imu_msgs, bool(false));
  private_node_handle_.param("gps_msgs", gps_msgs, bool(false));
  private_node_handle_.param("pcl_in_topic", pcl_in_topic, string("/cloud"));
  private_node_handle_.param("pcl_out_topic", pcl_out_topic, string("/cloud_world"));
  private_node_handle_.param("imu_topic", imu_topic, string("/imu/data"));
  private_node_handle_.param("gps_topic", gps_topic, string("/gps/fix"));

  // Create a subscriber
  ros::Subscriber sub_message = n.subscribe(pcl_in_topic.c_str(), 1000, &LaserTransform::messageCallback, node_lt);

  // Create odometry subscriber
  ros::Subscriber sub_odometry = n.subscribe("/odometry/filtered", 50, &LaserTransform::odometryCallback, node_lt);

  // Create a publisher and name the topic
  ros::Publisher pub_message = n.advertise<sensor_msgs::PointCloud2>(pcl_out_topic.c_str(), 50);

  // Create a publisher for IMU msgs
  ros::Publisher imu_pub = n.advertise<sensor_msgs::Imu>(imu_topic.c_str(), 50);

  // Create a publisher for GPS msgs
  ros::Publisher gps_pub = n.advertise<sensor_msgs::NavSatFix>(gps_topic.c_str(), 50);

  ros::Rate r(rate);

  while (n.ok())
  {
    node_lt->publishMessage(&pub_message);
    if (imu_msgs)
      node_lt->publishImuMessage(&imu_pub);
    if (gps_msgs)
      node_lt->publishNavSatFixMessage(&gps_pub);
    ros::spinOnce();
    r.sleep();
  }

  return 0;
  // end main
}
<commit_msg>add imu convergence parameter<commit_after>#include <iostream>
#include "ros/ros.h"
#include "sensor_msgs/PointCloud2.h"
#include "sensor_msgs/NavSatFix.h"
#include "sensor_msgs/Imu.h"
#include "nav_msgs/Odometry.h"
#include "laser_transform_core.h"

using std::string;

int main (int argc, char **argv)
{
  ros::init(argc, argv, "laser_transform");
  ros::NodeHandle n;

  // Declare variables thar can be modified by launch file or command line.
  int rate;
  int imu_convergence_speed;
  bool imu_msgs;
  bool gps_msgs;
  string pcl_in_topic;
  string pcl_out_topic;
  string imu_topic;
  string gps_topic;
  //string odo_topic;

  // Create a new LaserTransformer object.
  LaserTransform *node_lt = new LaserTransform();

  node_lt->init();

  // while using different parameters.
  ros::NodeHandle private_node_handle_("~");
  private_node_handle_.param("rate", rate, int(10));
  private_node_handle_.param("imu_msgs", imu_msgs, bool(true));
  private_node_handle_.param("gps_msgs", gps_msgs, bool(false));
  private_node_handle_.param("pcl_in_topic", pcl_in_topic, string("/cloud"));
  private_node_handle_.param("pcl_out_topic", pcl_out_topic, string("/cloud_world"));
  private_node_handle_.param("imu_topic", imu_topic, string("/imu/data"));
  private_node_handle_.param("gps_topic", gps_topic, string("/gps/fix"));
  private_node_handle_.param("imu_convergence_speed", imu_convergence_speed, int(20));

  // Create a subscriber
  ros::Subscriber sub_message = n.subscribe(pcl_in_topic.c_str(), 1000, &LaserTransform::pclCallback, node_lt);

  // Create odometry subscriber
  ros::Subscriber sub_odometry = n.subscribe("/odometry/filtered", 50, &LaserTransform::odometryCallback, node_lt);

  // Create a publisher and name the topic
  ros::Publisher pub_message = n.advertise<sensor_msgs::PointCloud2>(pcl_out_topic.c_str(), 50);

  // Create a publisher for IMU msgs
  ros::Publisher imu_pub = n.advertise<sensor_msgs::Imu>(imu_topic.c_str(), 50);

  // Create a publisher for GPS msgs
  ros::Publisher gps_pub = n.advertise<sensor_msgs::NavSatFix>(gps_topic.c_str(), 50);

  ros::Rate r(rate);

  while (n.ok())
  {
    node_lt->publishPclMessage(&pub_message);
    if (imu_msgs)
      node_lt->publishImuMessage(&imu_pub);
    if (gps_msgs)
      node_lt->publishNavSatFixMessage(&gps_pub);
    ros::spinOnce();
    r.sleep();
  }

  return 0;
  // end main
}
<|endoftext|>


<commit_before>#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <iostream>
#include <cassert>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  size_t n = 1;

  auto int_ready   = agency::detail::make_ready_future(0);
  auto void_ready  = agency::detail::make_ready_future();

  auto futures = std::make_tuple(std::move(void_ready), std::move(int_ready));

  std::mutex mut;
  executor_type exec;
  std::future<int> fut = agency::new_executor_traits<executor_type>::template when_all_execute_and_select<1>(exec, [&mut](int& x)
  {
    mut.lock();
    x += 1;
    mut.unlock();
  },
  std::move(futures));

  auto got = fut.get();

  assert(got == n);
  assert(exec.valid());
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();
  test<multi_agent_async_execute_returning_void_executor>();

  test<multi_agent_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_default_container_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<commit_msg>Test multi_agent_execute_with_shared_inits_returning_void_executor with test_single_agent_when_all_execute_and_select.cpp<commit_after>#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <iostream>
#include <cassert>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  size_t n = 1;

  auto int_ready   = agency::detail::make_ready_future(0);
  auto void_ready  = agency::detail::make_ready_future();

  auto futures = std::make_tuple(std::move(void_ready), std::move(int_ready));

  std::mutex mut;
  executor_type exec;
  std::future<int> fut = agency::new_executor_traits<executor_type>::template when_all_execute_and_select<1>(exec, [&mut](int& x)
  {
    mut.lock();
    x += 1;
    mut.unlock();
  },
  std::move(futures));

  auto got = fut.get();

  assert(got == n);
  assert(exec.valid());
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();
  test<multi_agent_async_execute_returning_void_executor>();

  test<multi_agent_execute_with_shared_inits_returning_user_defined_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_default_container_executor>();
  test<multi_agent_execute_with_shared_inits_returning_void_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUT: {ADS40RoiSmall.png}
//    OUTPUT: {TextureOutput.tif}, {pretty_TextureOutput.png}
//    2 1 1
//  Software Guide : EndCommandLineArgs

#include "itkExceptionObject.h"
#include "otbImage.h"
#include "itkVector.h"
#include "itkConstNeighborhoodIterator.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

#include "otbTextureFunctors.h"
#include "otbFunctionWithNeighborhoodToImageFilter.h"
#include "otbTextureImageFunction.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  if ( argc != 7 )
  {
    std::cerr << "Usage: " << argv[0] << " <inputImage> ";
    std::cerr << " <outputImage> <outputRescaled> ";
    std::cerr << " <radius> <xOffset> <yOffset> ";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const char* infname   = argv[1];
  const char* outfname  = argv[2];
  const char* outprettyfname  = argv[3];

  const unsigned int radius  =  static_cast<unsigned int>(atoi(argv[4]));
  const unsigned int xOffset =  static_cast<unsigned int>(atoi(argv[5]));
  const unsigned int yOffset =  static_cast<unsigned int>(atoi(argv[6]));

  typedef double PixelType;
  const int Dimension = 2;
  typedef otb::Image<PixelType,Dimension> ImageType;
  typedef itk::ConstNeighborhoodIterator<ImageType>  IteratorType;
  typedef itk::Vector< PixelType > VectorType;

  typedef otb::Functor::ContrastTextureFunctor<IteratorType, VectorType>
                                                             FunctorType;

  typedef otb::TextureImageFunction<ImageType, FunctorType> FunctionType;
  typedef otb::FunctionWithNeighborhoodToImageFilter<ImageType,
                                          ImageType, FunctionType> FilterType;
  typedef ImageType::OffsetType OffsetType;
  typedef otb::ImageFileReader<ImageType>  ReaderType;
  typedef otb::ImageFileWriter<ImageType> WriterType;

  // Instantiating object
  FilterType::Pointer textureFilter = FilterType::New();
  ReaderType::Pointer reader  = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(infname);
  writer->SetFileName(outfname);

  textureFilter->SetInput(reader->GetOutput());
  ImageType::SizeType tRadius;
  tRadius[0] = radius;
  tRadius[1] = radius;
  textureFilter->SetRadius(tRadius);
  OffsetType offset;
  offset[0] =  xOffset;
  offset[1] =  yOffset;

  textureFilter->SetOffset(offset);
  writer->SetInput(textureFilter->GetOutput());

  writer->Update();

 // Pretty image creation for printing

  typedef otb::Image<unsigned char, Dimension>                                           OutputPrettyImageType;
  typedef otb::ImageFileWriter<OutputPrettyImageType>                                    WriterPrettyOutputType;
  typedef itk::RescaleIntensityImageFilter< ImageType, OutputPrettyImageType>      RescalerOutputType;

  RescalerOutputType::Pointer     outputRescaler     = RescalerOutputType::New();
  WriterPrettyOutputType::Pointer prettyOutputWriter = WriterPrettyOutputType::New();
  outputRescaler->SetInput( textureFilter->GetOutput() );
  outputRescaler->SetOutputMinimum(0);
  outputRescaler->SetOutputMaximum(255);
  prettyOutputWriter->SetFileName( outprettyfname );
  prettyOutputWriter->SetInput( outputRescaler->GetOutput() );

  prettyOutputWriter->Update();

  return EXIT_SUCCESS;
}
<commit_msg>ENH : change texture call in example after template change<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

//  Software Guide : BeginCommandLineArgs
//    INPUT: {ADS40RoiSmall.png}
//    OUTPUT: {TextureOutput.tif}, {pretty_TextureOutput.png}
//    2 1 1
//  Software Guide : EndCommandLineArgs

#include "itkExceptionObject.h"
#include "otbImage.h"
#include "itkVector.h"
#include "itkConstNeighborhoodIterator.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

#include "otbTextureFunctors.h"
#include "otbFunctionWithNeighborhoodToImageFilter.h"
#include "otbTextureImageFunction.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  if ( argc != 7 )
  {
    std::cerr << "Usage: " << argv[0] << " <inputImage> ";
    std::cerr << " <outputImage> <outputRescaled> ";
    std::cerr << " <radius> <xOffset> <yOffset> ";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const char* infname   = argv[1];
  const char* outfname  = argv[2];
  const char* outprettyfname  = argv[3];

  const unsigned int radius  =  static_cast<unsigned int>(atoi(argv[4]));
  const unsigned int xOffset =  static_cast<unsigned int>(atoi(argv[5]));
  const unsigned int yOffset =  static_cast<unsigned int>(atoi(argv[6]));

  typedef double PixelType;
  const int Dimension = 2;
  typedef otb::Image<PixelType,Dimension> ImageType;
  typedef itk::ConstNeighborhoodIterator<ImageType>  IteratorType;
  typedef itk::Vector< PixelType > VectorType;

  typedef otb::Functor::ContrastTextureFunctor<PixelType, PixelType> FunctorType;

  typedef otb::TextureImageFunction<ImageType, FunctorType> FunctionType;
  typedef otb::FunctionWithNeighborhoodToImageFilter<ImageType,
                                          ImageType, FunctionType> FilterType;
  typedef ImageType::OffsetType OffsetType;
  typedef otb::ImageFileReader<ImageType>  ReaderType;
  typedef otb::ImageFileWriter<ImageType> WriterType;

  // Instantiating object
  FilterType::Pointer textureFilter = FilterType::New();
  ReaderType::Pointer reader  = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(infname);
  writer->SetFileName(outfname);

  textureFilter->SetInput(reader->GetOutput());
  ImageType::SizeType tRadius;
  tRadius[0] = radius;
  tRadius[1] = radius;
  textureFilter->SetRadius(tRadius);
  OffsetType offset;
  offset[0] =  xOffset;
  offset[1] =  yOffset;

  textureFilter->SetOffset(offset);
  writer->SetInput(textureFilter->GetOutput());

  writer->Update();

 // Pretty image creation for printing

  typedef otb::Image<unsigned char, Dimension>                                           OutputPrettyImageType;
  typedef otb::ImageFileWriter<OutputPrettyImageType>                                    WriterPrettyOutputType;
  typedef itk::RescaleIntensityImageFilter< ImageType, OutputPrettyImageType>      RescalerOutputType;

  RescalerOutputType::Pointer     outputRescaler     = RescalerOutputType::New();
  WriterPrettyOutputType::Pointer prettyOutputWriter = WriterPrettyOutputType::New();
  outputRescaler->SetInput( textureFilter->GetOutput() );
  outputRescaler->SetOutputMinimum(0);
  outputRescaler->SetOutputMaximum(255);
  prettyOutputWriter->SetFileName( outprettyfname );
  prettyOutputWriter->SetInput( outputRescaler->GetOutput() );

  prettyOutputWriter->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <Beard/utility.hpp>
#include <Beard/ui/packing.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Widget/Base.hpp>
#include <Beard/ui/debug.hpp>

#include <utility>

namespace Beard {
namespace ui {
namespace Widget {

// class Base implementation

Base::~Base() noexcept = default;

// implementation

void
Base::push_action_graph_impl(
	ui::Widget::set_type& /*set*/
) noexcept {
	/* Do nothing. */
}

void
Base::set_input_control_impl(
	bool const enabled
) noexcept {
	m_flags.set(ui::Widget::Flags::input_control, enabled);
}

void
Base::cache_geometry_impl() noexcept {
	/* Do nothing. */
}

void
Base::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	if (cache) {
		cache_geometry();
	}
	ui::reflow(area, get_geometry());
}

bool
Base::handle_event_impl(
	ui::Event const& /*event*/
) noexcept {
	return false;
}

void
Base::render_impl(
	ui::Widget::RenderData& /*rd*/
) noexcept {
	/* Do nothing. */
}

signed
Base::num_children_impl() const noexcept {
	return 0;
}

ui::Widget::SPtr
Base::get_child_impl(
	index_type const /*index*/
) {
	return nullptr;
}

bool
Base::handle_event(
	ui::Event const& event
) noexcept {
	if (
		// Avoid SPtr construction if we can
		signal_event_filter.is_bound() &&
		signal_event_filter(
			std::move(shared_from_this()),
			event
		)
	) {
		return true;
	}
	return handle_event_impl(event);
}

void
Base::render(
	ui::Widget::RenderData& rd
) noexcept {
	if (!is_visible()) {
		return;
	}
	if (rd.get_boolean(ui::property_frame_debug_enabled)) {
		ui::geom_debug_render(
			rd.terminal,
			get_geometry(),
			tty::Color::term_default,
			is_focused()
		);
	}
	render_impl(rd);
}

// properties

void
Base::update_depth(
	ui::Widget::SPtr const& parent
) noexcept {
	if (type == ui::Widget::Type::Root) {
		m_depth = -1;
		return;
	} else if (parent) {
		m_depth = parent->get_depth() + 1;
	} else {
		m_depth = 0;
	}
	for (signed index = 0; index < num_children(); ++index) {
		auto const child = get_child(index);
		if (child) {
			child->update_depth(shared_from_this());
		}
	}
}

void
Base::set_parent(
	ui::Widget::SPtr const& widget
) noexcept {
	m_parent = widget;
	update_depth(widget);
}

void
Base::set_visible(
	bool const visible
) noexcept {
	if (is_visible() != visible) {
		m_flags.set(ui::Widget::Flags::visible, visible);
		queue_actions(
			ui::UpdateActions::flag_parent |
			ui::UpdateActions::reflow |
			ui::UpdateActions::render
		);
	}
}

void
Base::set_focused(
	bool const focused
) noexcept {
	if (is_focused() != focused) {
		ui::Event event;
		event.type = ui::EventType::focus_changed;
		event.focus_changed.previous = is_focused();
		m_flags.set(ui::Widget::Flags::focused, focused);
		if (!handle_event(event)) {
			queue_actions(
				ui::UpdateActions::flag_noclear |
				ui::UpdateActions::render
			);
		}
	}
}

// operations

inline constexpr bool
is_clearing_render(
	ui::UpdateActions const actions
) noexcept {
	return
		ui::UpdateActions::render
		== (actions & (ui::UpdateActions::render | ui::UpdateActions::flag_noclear))
	;
}

inline ui::UpdateActions
join_actions(
	ui::UpdateActions const x,
	ui::UpdateActions const y
) {
	if (is_clearing_render(x) || is_clearing_render(y)) {
		return (x | y) & ~ui::UpdateActions::flag_noclear;
	} else {
		return x | y;
	}
}

void
Base::queue_actions(
	ui::UpdateActions actions
) {
	if (enum_cast(actions & ui::UpdateActions::mask_actions)) {
		if (!is_action_queued()) {
			get_root()->get_context().enqueue_widget(shared_from_this());
		}
		actions = join_actions(actions, get_queued_actions());
		if (enum_cast(actions & ui::UpdateActions::flag_parent) && has_parent()) {
			get_parent()->queue_actions(
				actions & ~ui::UpdateActions::flag_parent
			);
		}
		m_flags.set_masked(
			mask_ua,
			static_cast<ui::Widget::Flags>(enum_cast(actions) << shift_ua)
		);
		set_action_queued(true);
	}
}

void
Base::clear_actions(
	bool const dequeue
) {
	if (dequeue) {
		get_root()->get_context().dequeue_widget(shared_from_this());
	}
	m_flags.remove(mask_ua);
	set_action_queued(false);
}

void
Base::push_action_graph(
	ui::Widget::set_type& set,
	ui::UpdateActions actions
) noexcept {
	actions &= ~ui::UpdateActions::flag_parent;
	auto const prev_actions = get_queued_actions() & ~ui::UpdateActions::flag_parent;
	m_flags.set_masked(
		mask_ua,
		static_cast<ui::Widget::Flags>(enum_cast(actions) << shift_ua)
	);
	if (set.insert(this).second || actions != prev_actions) {
		push_action_graph_impl(set);
	}
}

} // namespace Widget
} // namespace ui
} // namespace Beard
<commit_msg>ui::Widget::Base: corrected type comparison in update_depth().¹<commit_after>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <Beard/utility.hpp>
#include <Beard/ui/packing.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Widget/Base.hpp>
#include <Beard/ui/debug.hpp>

#include <utility>

namespace Beard {
namespace ui {
namespace Widget {

// class Base implementation

Base::~Base() noexcept = default;

// implementation

void
Base::push_action_graph_impl(
	ui::Widget::set_type& /*set*/
) noexcept {
	/* Do nothing. */
}

void
Base::set_input_control_impl(
	bool const enabled
) noexcept {
	m_flags.set(ui::Widget::Flags::input_control, enabled);
}

void
Base::cache_geometry_impl() noexcept {
	/* Do nothing. */
}

void
Base::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	if (cache) {
		cache_geometry();
	}
	ui::reflow(area, get_geometry());
}

bool
Base::handle_event_impl(
	ui::Event const& /*event*/
) noexcept {
	return false;
}

void
Base::render_impl(
	ui::Widget::RenderData& /*rd*/
) noexcept {
	/* Do nothing. */
}

signed
Base::num_children_impl() const noexcept {
	return 0;
}

ui::Widget::SPtr
Base::get_child_impl(
	index_type const /*index*/
) {
	return nullptr;
}

bool
Base::handle_event(
	ui::Event const& event
) noexcept {
	if (
		// Avoid SPtr construction if we can
		signal_event_filter.is_bound() &&
		signal_event_filter(
			std::move(shared_from_this()),
			event
		)
	) {
		return true;
	}
	return handle_event_impl(event);
}

void
Base::render(
	ui::Widget::RenderData& rd
) noexcept {
	if (!is_visible()) {
		return;
	}
	if (rd.get_boolean(ui::property_frame_debug_enabled)) {
		ui::geom_debug_render(
			rd.terminal,
			get_geometry(),
			tty::Color::term_default,
			is_focused()
		);
	}
	render_impl(rd);
}

// properties

void
Base::update_depth(
	ui::Widget::SPtr const& parent
) noexcept {
	if (m_type == ui::Widget::Type::Root) {
		m_depth = -1;
		return;
	} else if (parent) {
		m_depth = parent->get_depth() + 1;
	} else {
		m_depth = 0;
	}
	for (signed index = 0; index < num_children(); ++index) {
		auto const child = get_child(index);
		if (child) {
			child->update_depth(shared_from_this());
		}
	}
}

void
Base::set_parent(
	ui::Widget::SPtr const& widget
) noexcept {
	m_parent = widget;
	update_depth(widget);
}

void
Base::set_visible(
	bool const visible
) noexcept {
	if (is_visible() != visible) {
		m_flags.set(ui::Widget::Flags::visible, visible);
		queue_actions(
			ui::UpdateActions::flag_parent |
			ui::UpdateActions::reflow |
			ui::UpdateActions::render
		);
	}
}

void
Base::set_focused(
	bool const focused
) noexcept {
	if (is_focused() != focused) {
		ui::Event event;
		event.type = ui::EventType::focus_changed;
		event.focus_changed.previous = is_focused();
		m_flags.set(ui::Widget::Flags::focused, focused);
		if (!handle_event(event)) {
			queue_actions(
				ui::UpdateActions::flag_noclear |
				ui::UpdateActions::render
			);
		}
	}
}

// operations

inline constexpr bool
is_clearing_render(
	ui::UpdateActions const actions
) noexcept {
	return
		ui::UpdateActions::render
		== (actions & (ui::UpdateActions::render | ui::UpdateActions::flag_noclear))
	;
}

inline ui::UpdateActions
join_actions(
	ui::UpdateActions const x,
	ui::UpdateActions const y
) {
	if (is_clearing_render(x) || is_clearing_render(y)) {
		return (x | y) & ~ui::UpdateActions::flag_noclear;
	} else {
		return x | y;
	}
}

void
Base::queue_actions(
	ui::UpdateActions actions
) {
	if (enum_cast(actions & ui::UpdateActions::mask_actions)) {
		if (!is_action_queued()) {
			get_root()->get_context().enqueue_widget(shared_from_this());
		}
		actions = join_actions(actions, get_queued_actions());
		if (enum_cast(actions & ui::UpdateActions::flag_parent) && has_parent()) {
			get_parent()->queue_actions(
				actions & ~ui::UpdateActions::flag_parent
			);
		}
		m_flags.set_masked(
			mask_ua,
			static_cast<ui::Widget::Flags>(enum_cast(actions) << shift_ua)
		);
		set_action_queued(true);
	}
}

void
Base::clear_actions(
	bool const dequeue
) {
	if (dequeue) {
		get_root()->get_context().dequeue_widget(shared_from_this());
	}
	m_flags.remove(mask_ua);
	set_action_queued(false);
}

void
Base::push_action_graph(
	ui::Widget::set_type& set,
	ui::UpdateActions actions
) noexcept {
	actions &= ~ui::UpdateActions::flag_parent;
	auto const prev_actions = get_queued_actions() & ~ui::UpdateActions::flag_parent;
	m_flags.set_masked(
		mask_ua,
		static_cast<ui::Widget::Flags>(enum_cast(actions) << shift_ua)
	);
	if (set.insert(this).second || actions != prev_actions) {
		push_action_graph_impl(set);
	}
}

} // namespace Widget
} // namespace ui
} // namespace Beard
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Implementation of ROOT data file writer module
 * @copyright Copyright (c) 2017 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

#include "ROOTObjectWriterModule.hpp"

#include <fstream>
#include <string>
#include <utility>

#include <TBranchElement.h>
#include <TClass.h>

#include "core/config/ConfigReader.hpp"
#include "core/utils/file.h"
#include "core/utils/log.h"
#include "core/utils/type.h"

#include "objects/Object.hpp"
#include "objects/objects.h"

using namespace allpix;

ROOTObjectWriterModule::ROOTObjectWriterModule(Configuration& config, Messenger* messenger, GeometryManager* geo_mgr)
    : Module(config), geo_mgr_(geo_mgr) {
    // Bind to all messages
    messenger->registerListener(this, &ROOTObjectWriterModule::receive);
}
/**
 * @note Objects cannot be stored in smart pointers due to internal ROOT logic
 */
ROOTObjectWriterModule::~ROOTObjectWriterModule() {
    // Delete all object pointers
    for(auto& index_data : write_list_) {
        delete index_data.second;
    }
}

void ROOTObjectWriterModule::init() {
    // Create output file
    output_file_name_ =
        createOutputFile(allpix::add_file_extension(config_.get<std::string>("file_name", "data"), "root"), true);
    output_file_ = std::make_unique<TFile>(output_file_name_.c_str(), "RECREATE");
    output_file_->cd();

    // Read include and exclude list
    if(config_.has("include") && config_.has("exclude")) {
        throw InvalidValueError(config_, "exclude", "include and exclude parameter are mutually exclusive");
    } else if(config_.has("include")) {
        auto inc_arr = config_.getArray<std::string>("include");
        include_.insert(inc_arr.begin(), inc_arr.end());
    } else if(config_.has("exclude")) {
        auto exc_arr = config_.getArray<std::string>("exclude");
        exclude_.insert(exc_arr.begin(), exc_arr.end());
    }
}

void ROOTObjectWriterModule::receive(std::shared_ptr<BaseMessage> message, std::string message_name) { // NOLINT
    try {
        const BaseMessage* inst = message.get();
        std::string name_str = " without a name";
        if(!message_name.empty()) {
            name_str = " named " + message_name;
        }
        LOG(TRACE) << "ROOT object writer received " << allpix::demangle(typeid(*inst).name()) << name_str;

        // Get the detector name
        std::string detector_name;
        if(message->getDetector() != nullptr) {
            detector_name = message->getDetector()->getName();
        }

        // Read the object
        auto object_array = message->getObjectArray();
        if(!object_array.empty()) {
            keep_messages_.push_back(message);

            const Object& first_object = object_array[0];
            std::type_index type_idx = typeid(first_object);

            // Create a new branch of the correct type if this message was not received before
            auto index_tuple = std::make_tuple(type_idx, detector_name, message_name);
            if(write_list_.find(index_tuple) == write_list_.end()) {

                auto* cls = TClass::GetClass(typeid(first_object));

                // Remove the allpix prefix
                std::string class_name = cls->GetName();
                std::string apx_namespace = "allpix::";
                size_t ap_idx = class_name.find(apx_namespace);
                if(ap_idx != std::string::npos) {
                    class_name.replace(ap_idx, apx_namespace.size(), "");
                }

                // Check if this message should be kept
                if((!include_.empty() && include_.find(class_name) == include_.end()) ||
                   (!exclude_.empty() && exclude_.find(class_name) != exclude_.end())) {
                    LOG(TRACE) << "ROOT object writer ignored message with object " << allpix::demangle(typeid(*inst).name())
                               << " because it has been excluded or not explicitly included";
                    return;
                }

                // Add vector of objects to write to the write list
                write_list_[index_tuple] = new std::vector<Object*>();
                auto addr = &write_list_[index_tuple];

                if(trees_.find(class_name) == trees_.end()) {
                    // Create new tree
                    output_file_->cd();
                    trees_.emplace(
                        class_name,
                        std::make_unique<TTree>(class_name.c_str(), (std::string("Tree of ") + class_name).c_str()));
                }

                std::string branch_name = detector_name;
                if(!message_name.empty()) {
                    branch_name += "_";
                    branch_name += message_name;
                }

                trees_[class_name]->Bronch(
                    branch_name.c_str(), (std::string("std::vector<") + cls->GetName() + "*>").c_str(), addr);
            }

            // Fill the branch vector
            for(Object& object : object_array) {
                ++write_cnt_;
                write_list_[index_tuple]->push_back(&object);
            }
        }

    } catch(MessageWithoutObjectException& e) {
        const BaseMessage* inst = message.get();
        LOG(WARNING) << "ROOT object writer cannot process message of type" << allpix::demangle(typeid(*inst).name())
                     << " with name " << message_name;
    }
}

void ROOTObjectWriterModule::run(unsigned int) {
    LOG(TRACE) << "Writing new objects to tree";
    output_file_->cd();

    // Fill the tree with the current received messages
    for(auto& tree : trees_) {
        tree.second->Fill();
    }

    // Clear the current message list
    for(auto& index_data : write_list_) {
        index_data.second->clear();
    }
    // Clear the messages we have to keep because they contain the internal pointers
    keep_messages_.clear();
}

void ROOTObjectWriterModule::finalize() {
    LOG(TRACE) << "Writing objects to file";
    output_file_->cd();

    int branch_count = 0;
    for(auto& tree : trees_) {
        // Update statistics
        branch_count += tree.second->GetListOfBranches()->GetEntries();
    }

    // Create main config directory
    TDirectory* config_dir = output_file_->mkdir("config");
    config_dir->cd();

    // Get the config manager
    ConfigManager* conf_manager = getConfigManager();

    // Save the main configuration to the output file
    auto global_dir = config_dir->mkdir("Allpix");
    LOG(TRACE) << "Writing global configuration";

    // Loop over all values in the global configuration
    for(auto& key_value : conf_manager->getGlobalConfiguration().getAll()) {
        global_dir->WriteObject(&key_value.second, key_value.first.c_str());
    }

    // Save the instance configuration to the output file
    for(auto& config : conf_manager->getInstanceConfigurations()) {
        // Create a new directory per section, using the unique module name
        auto unique_name = config.get<std::string>("unique_name");
        auto section_dir = config_dir->mkdir(unique_name.c_str());
        LOG(TRACE) << "Writing configuration for: " << unique_name;

        // Loop over all values in the section
        for(auto& key_value : config.getAll()) {
            // Skip the unique name and input / output if empty
            if(key_value.first == "unique_name") {
                continue;
            }
            if((key_value.first == "input" || key_value.first == "output") && key_value.second.empty()) {
                continue;
            }
            section_dir->WriteObject(&key_value.second, key_value.first.c_str());
        }
    }

    // Save the detectors to the output file
    // FIXME Possibly the format to save the geometry should be more flexible
    auto detectors_dir = output_file_->mkdir("detectors");
    detectors_dir->cd();
    for(auto& detector : geo_mgr_->getDetectors()) {
        auto detector_dir = detectors_dir->mkdir(detector->getName().c_str());

        auto position = detector->getPosition();
        detector_dir->WriteObject(&position, "position");
        auto orientation = detector->getOrientation();
        detector_dir->WriteObject(&orientation, "orientation");

        auto model_dir = detector_dir->mkdir("model");
        // FIXME This saves the model every time again also for models that appear multiple times
        auto model_configs = detector->getModel()->getConfigurations();
        std::map<std::string, int> count_configs;
        for(auto& model_config : model_configs) {
            auto model_config_dir = model_dir;
            if(!model_config.getName().empty()) {
                model_config_dir = model_dir->mkdir(
                    (model_config.getName() + "_" + std::to_string(count_configs[model_config.getName()])).c_str());
                count_configs[model_config.getName()]++;
            }

            for(auto& key_value : model_config.getAll()) {
                model_config_dir->WriteObject(&key_value.second, key_value.first.c_str());
            }
        }
    }

    // Finish writing to output file
    output_file_->Write();

    // Print statistics
    LOG(STATUS) << "Wrote " << write_cnt_ << " objects to " << branch_count << " branches in file:" << std::endl
                << output_file_name_;
}
<commit_msg>ROOTObjectWriter: store detector models in separate directory<commit_after>/**
 * @file
 * @brief Implementation of ROOT data file writer module
 * @copyright Copyright (c) 2017 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

#include "ROOTObjectWriterModule.hpp"

#include <fstream>
#include <string>
#include <utility>

#include <TBranchElement.h>
#include <TClass.h>

#include "core/config/ConfigReader.hpp"
#include "core/utils/file.h"
#include "core/utils/log.h"
#include "core/utils/type.h"

#include "objects/Object.hpp"
#include "objects/objects.h"

using namespace allpix;

ROOTObjectWriterModule::ROOTObjectWriterModule(Configuration& config, Messenger* messenger, GeometryManager* geo_mgr)
    : Module(config), geo_mgr_(geo_mgr) {
    // Bind to all messages
    messenger->registerListener(this, &ROOTObjectWriterModule::receive);
}
/**
 * @note Objects cannot be stored in smart pointers due to internal ROOT logic
 */
ROOTObjectWriterModule::~ROOTObjectWriterModule() {
    // Delete all object pointers
    for(auto& index_data : write_list_) {
        delete index_data.second;
    }
}

void ROOTObjectWriterModule::init() {
    // Create output file
    output_file_name_ =
        createOutputFile(allpix::add_file_extension(config_.get<std::string>("file_name", "data"), "root"), true);
    output_file_ = std::make_unique<TFile>(output_file_name_.c_str(), "RECREATE");
    output_file_->cd();

    // Read include and exclude list
    if(config_.has("include") && config_.has("exclude")) {
        throw InvalidValueError(config_, "exclude", "include and exclude parameter are mutually exclusive");
    } else if(config_.has("include")) {
        auto inc_arr = config_.getArray<std::string>("include");
        include_.insert(inc_arr.begin(), inc_arr.end());
    } else if(config_.has("exclude")) {
        auto exc_arr = config_.getArray<std::string>("exclude");
        exclude_.insert(exc_arr.begin(), exc_arr.end());
    }
}

void ROOTObjectWriterModule::receive(std::shared_ptr<BaseMessage> message, std::string message_name) { // NOLINT
    try {
        const BaseMessage* inst = message.get();
        std::string name_str = " without a name";
        if(!message_name.empty()) {
            name_str = " named " + message_name;
        }
        LOG(TRACE) << "ROOT object writer received " << allpix::demangle(typeid(*inst).name()) << name_str;

        // Get the detector name
        std::string detector_name;
        if(message->getDetector() != nullptr) {
            detector_name = message->getDetector()->getName();
        }

        // Read the object
        auto object_array = message->getObjectArray();
        if(!object_array.empty()) {
            keep_messages_.push_back(message);

            const Object& first_object = object_array[0];
            std::type_index type_idx = typeid(first_object);

            // Create a new branch of the correct type if this message was not received before
            auto index_tuple = std::make_tuple(type_idx, detector_name, message_name);
            if(write_list_.find(index_tuple) == write_list_.end()) {

                auto* cls = TClass::GetClass(typeid(first_object));

                // Remove the allpix prefix
                std::string class_name = cls->GetName();
                std::string apx_namespace = "allpix::";
                size_t ap_idx = class_name.find(apx_namespace);
                if(ap_idx != std::string::npos) {
                    class_name.replace(ap_idx, apx_namespace.size(), "");
                }

                // Check if this message should be kept
                if((!include_.empty() && include_.find(class_name) == include_.end()) ||
                   (!exclude_.empty() && exclude_.find(class_name) != exclude_.end())) {
                    LOG(TRACE) << "ROOT object writer ignored message with object " << allpix::demangle(typeid(*inst).name())
                               << " because it has been excluded or not explicitly included";
                    return;
                }

                // Add vector of objects to write to the write list
                write_list_[index_tuple] = new std::vector<Object*>();
                auto addr = &write_list_[index_tuple];

                if(trees_.find(class_name) == trees_.end()) {
                    // Create new tree
                    output_file_->cd();
                    trees_.emplace(
                        class_name,
                        std::make_unique<TTree>(class_name.c_str(), (std::string("Tree of ") + class_name).c_str()));
                }

                std::string branch_name = detector_name;
                if(!message_name.empty()) {
                    branch_name += "_";
                    branch_name += message_name;
                }

                trees_[class_name]->Bronch(
                    branch_name.c_str(), (std::string("std::vector<") + cls->GetName() + "*>").c_str(), addr);
            }

            // Fill the branch vector
            for(Object& object : object_array) {
                ++write_cnt_;
                write_list_[index_tuple]->push_back(&object);
            }
        }

    } catch(MessageWithoutObjectException& e) {
        const BaseMessage* inst = message.get();
        LOG(WARNING) << "ROOT object writer cannot process message of type" << allpix::demangle(typeid(*inst).name())
                     << " with name " << message_name;
    }
}

void ROOTObjectWriterModule::run(unsigned int) {
    LOG(TRACE) << "Writing new objects to tree";
    output_file_->cd();

    // Fill the tree with the current received messages
    for(auto& tree : trees_) {
        tree.second->Fill();
    }

    // Clear the current message list
    for(auto& index_data : write_list_) {
        index_data.second->clear();
    }
    // Clear the messages we have to keep because they contain the internal pointers
    keep_messages_.clear();
}

void ROOTObjectWriterModule::finalize() {
    LOG(TRACE) << "Writing objects to file";
    output_file_->cd();

    int branch_count = 0;
    for(auto& tree : trees_) {
        // Update statistics
        branch_count += tree.second->GetListOfBranches()->GetEntries();
    }

    // Create main config directory
    TDirectory* config_dir = output_file_->mkdir("config");
    config_dir->cd();

    // Get the config manager
    ConfigManager* conf_manager = getConfigManager();

    // Save the main configuration to the output file
    auto global_dir = config_dir->mkdir("Allpix");
    LOG(TRACE) << "Writing global configuration";

    // Loop over all values in the global configuration
    for(auto& key_value : conf_manager->getGlobalConfiguration().getAll()) {
        global_dir->WriteObject(&key_value.second, key_value.first.c_str());
    }

    // Save the instance configuration to the output file
    for(auto& config : conf_manager->getInstanceConfigurations()) {
        // Create a new directory per section, using the unique module name
        auto unique_name = config.get<std::string>("unique_name");
        auto section_dir = config_dir->mkdir(unique_name.c_str());
        LOG(TRACE) << "Writing configuration for: " << unique_name;

        // Loop over all values in the section
        for(auto& key_value : config.getAll()) {
            // Skip the unique name and input / output if empty
            if(key_value.first == "unique_name") {
                continue;
            }
            if((key_value.first == "input" || key_value.first == "output") && key_value.second.empty()) {
                continue;
            }
            section_dir->WriteObject(&key_value.second, key_value.first.c_str());
        }
    }

    // Save the detectors to the output file
    auto detectors_dir = output_file_->mkdir("detectors");
    auto models_dir = output_file_->mkdir("models");
    for(auto& detector : geo_mgr_->getDetectors()) {
        detectors_dir->cd();
        auto detector_dir = detectors_dir->mkdir(detector->getName().c_str());

        auto position = detector->getPosition();
        detector_dir->WriteObject(&position, "position");
        auto orientation = detector->getOrientation();
        detector_dir->WriteObject(&orientation, "orientation");

        // Store the detector model
        std::string model_name = "model_" + detector->getName();
        detector_dir->WriteObject(&model_name, "type");
        models_dir->cd();
        auto model_dir = models_dir->mkdir(model_name.c_str());

        // FIXME This saves the model every time again also for models that appear multiple times
        auto model_configs = detector->getModel()->getConfigurations();
        std::map<std::string, int> count_configs;
        for(auto& model_config : model_configs) {
            auto model_config_dir = model_dir;
            if(!model_config.getName().empty()) {
                model_config_dir = model_dir->mkdir(
                    (model_config.getName() + "_" + std::to_string(count_configs[model_config.getName()])).c_str());
                count_configs[model_config.getName()]++;
            }

            for(auto& key_value : model_config.getAll()) {
                model_config_dir->WriteObject(&key_value.second, key_value.first.c_str());
            }
        }
    }

    // Finish writing to output file
    output_file_->Write();

    // Print statistics
    LOG(STATUS) << "Wrote " << write_cnt_ << " objects to " << branch_count << " branches in file:" << std::endl
                << output_file_name_;
}
<|endoftext|>