<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2019, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include <iostream>

#include "problems/cvrp/operators/two_opt.h"

namespace vroom {
namespace cvrp {

TwoOpt::TwoOpt(const Input& input,
               const utils::SolutionState& sol_state,
               RawRoute& s_route,
               Index s_vehicle,
               Index s_rank,
               RawRoute& t_route,
               Index t_vehicle,
               Index t_rank)
  : Operator(input,
             sol_state,
             s_route,
             s_vehicle,
             s_rank,
             t_route,
             t_vehicle,
             t_rank) {
  assert(s_vehicle != t_vehicle);
  assert(s_route.size() >= 1);
  assert(t_route.size() >= 1);
  assert(s_rank < s_route.size());
  assert(t_rank < t_route.size());
}

void TwoOpt::compute_gain() {
  const auto& m = _input.get_matrix();
  const auto& v_source = _input.vehicles[s_vehicle];
  const auto& v_target = _input.vehicles[t_vehicle];

  Index s_index = _input.jobs[s_route[s_rank]].index();
  Index t_index = _input.jobs[t_route[t_rank]].index();
  Index last_s = _input.jobs[s_route.back()].index();
  Index last_t = _input.jobs[t_route.back()].index();
  stored_gain = 0;
  Index new_last_s = last_t;
  Index new_last_t = last_s;

  // Cost of swapping route for vehicle s_vehicle after step
  // s_rank with route for vehicle t_vehicle after step
  // t_rank.

  // Basic costs in case we really swap jobs and not only the end of
  // the route. Otherwise remember that last job does not change.
  if (s_rank < s_route.size() - 1) {
    Index next_index = _input.jobs[s_route[s_rank + 1]].index();
    stored_gain += m[s_index][next_index];
    stored_gain -= m[t_index][next_index];
  } else {
    new_last_t = t_index;
  }
  if (t_rank < t_route.size() - 1) {
    Index next_index = _input.jobs[t_route[t_rank + 1]].index();
    stored_gain += m[t_index][next_index];
    stored_gain -= m[s_index][next_index];
  } else {
    new_last_s = s_index;
  }

  // Handling end route cost change because vehicle ends can be
  // different or none.
  if (v_source.has_end()) {
    auto end_s = v_source.end.get().index();
    stored_gain += m[last_s][end_s];
    stored_gain -= m[new_last_s][end_s];
  }
  if (v_target.has_end()) {
    auto end_t = v_target.end.get().index();
    stored_gain += m[last_t][end_t];
    stored_gain -= m[new_last_t][end_t];
  }

  gain_computed = true;
}

bool TwoOpt::is_valid() {
  bool valid = (_sol_state.bwd_skill_rank[s_vehicle][t_vehicle] <= s_rank + 1);

  valid &= (_sol_state.bwd_skill_rank[t_vehicle][s_vehicle] <= t_rank + 1);

  auto t_delivery = target.delivery_in_range(t_rank + 1, t_route.size());
  auto t_pickup = target.pickup_in_range(t_rank + 1, t_route.size());

  valid &= source.is_valid_addition_for_capacity_margins(_input,
                                                         t_pickup,
                                                         t_delivery,
                                                         s_rank + 1,
                                                         s_route.size());

  auto s_delivery = source.delivery_in_range(s_rank + 1, s_route.size());
  auto s_pickup = source.pickup_in_range(s_rank + 1, s_route.size());

  valid &= target.is_valid_addition_for_capacity_margins(_input,
                                                         s_pickup,
                                                         s_delivery,
                                                         t_rank + 1,
                                                         t_route.size());

  valid &= source.is_valid_addition_for_capacity_inclusion(_input,
                                                           t_delivery,
                                                           t_route.begin() +
                                                             t_rank + 1,
                                                           t_route.end(),
                                                           s_rank + 1,
                                                           s_route.size());

  valid &= target.is_valid_addition_for_capacity_inclusion(_input,
                                                           s_delivery,
                                                           s_route.begin() +
                                                             s_rank + 1,
                                                           s_route.end(),
                                                           t_rank + 1,
                                                           t_route.size());

  return valid;
}

void TwoOpt::apply() {
  auto nb_source = s_route.size() - 1 - s_rank;

  t_route.insert(t_route.begin() + t_rank + 1,
                 s_route.begin() + s_rank + 1,
                 s_route.end());
  s_route.erase(s_route.begin() + s_rank + 1, s_route.end());
  s_route.insert(s_route.end(),
                 t_route.begin() + t_rank + 1 + nb_source,
                 t_route.end());
  t_route.erase(t_route.begin() + t_rank + 1 + nb_source, t_route.end());
}

std::vector<Index> TwoOpt::addition_candidates() const {
  return {s_vehicle, t_vehicle};
}

std::vector<Index> TwoOpt::update_candidates() const {
  return {s_vehicle, t_vehicle};
}

} // namespace cvrp
} // namespace vroom
<commit_msg>Header cleanup.<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2019, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "problems/cvrp/operators/two_opt.h"

namespace vroom {
namespace cvrp {

TwoOpt::TwoOpt(const Input& input,
               const utils::SolutionState& sol_state,
               RawRoute& s_route,
               Index s_vehicle,
               Index s_rank,
               RawRoute& t_route,
               Index t_vehicle,
               Index t_rank)
  : Operator(input,
             sol_state,
             s_route,
             s_vehicle,
             s_rank,
             t_route,
             t_vehicle,
             t_rank) {
  assert(s_vehicle != t_vehicle);
  assert(s_route.size() >= 1);
  assert(t_route.size() >= 1);
  assert(s_rank < s_route.size());
  assert(t_rank < t_route.size());
}

void TwoOpt::compute_gain() {
  const auto& m = _input.get_matrix();
  const auto& v_source = _input.vehicles[s_vehicle];
  const auto& v_target = _input.vehicles[t_vehicle];

  Index s_index = _input.jobs[s_route[s_rank]].index();
  Index t_index = _input.jobs[t_route[t_rank]].index();
  Index last_s = _input.jobs[s_route.back()].index();
  Index last_t = _input.jobs[t_route.back()].index();
  stored_gain = 0;
  Index new_last_s = last_t;
  Index new_last_t = last_s;

  // Cost of swapping route for vehicle s_vehicle after step
  // s_rank with route for vehicle t_vehicle after step
  // t_rank.

  // Basic costs in case we really swap jobs and not only the end of
  // the route. Otherwise remember that last job does not change.
  if (s_rank < s_route.size() - 1) {
    Index next_index = _input.jobs[s_route[s_rank + 1]].index();
    stored_gain += m[s_index][next_index];
    stored_gain -= m[t_index][next_index];
  } else {
    new_last_t = t_index;
  }
  if (t_rank < t_route.size() - 1) {
    Index next_index = _input.jobs[t_route[t_rank + 1]].index();
    stored_gain += m[t_index][next_index];
    stored_gain -= m[s_index][next_index];
  } else {
    new_last_s = s_index;
  }

  // Handling end route cost change because vehicle ends can be
  // different or none.
  if (v_source.has_end()) {
    auto end_s = v_source.end.get().index();
    stored_gain += m[last_s][end_s];
    stored_gain -= m[new_last_s][end_s];
  }
  if (v_target.has_end()) {
    auto end_t = v_target.end.get().index();
    stored_gain += m[last_t][end_t];
    stored_gain -= m[new_last_t][end_t];
  }

  gain_computed = true;
}

bool TwoOpt::is_valid() {
  bool valid = (_sol_state.bwd_skill_rank[s_vehicle][t_vehicle] <= s_rank + 1);

  valid &= (_sol_state.bwd_skill_rank[t_vehicle][s_vehicle] <= t_rank + 1);

  auto t_delivery = target.delivery_in_range(t_rank + 1, t_route.size());
  auto t_pickup = target.pickup_in_range(t_rank + 1, t_route.size());

  valid &= source.is_valid_addition_for_capacity_margins(_input,
                                                         t_pickup,
                                                         t_delivery,
                                                         s_rank + 1,
                                                         s_route.size());

  auto s_delivery = source.delivery_in_range(s_rank + 1, s_route.size());
  auto s_pickup = source.pickup_in_range(s_rank + 1, s_route.size());

  valid &= target.is_valid_addition_for_capacity_margins(_input,
                                                         s_pickup,
                                                         s_delivery,
                                                         t_rank + 1,
                                                         t_route.size());

  valid &= source.is_valid_addition_for_capacity_inclusion(_input,
                                                           t_delivery,
                                                           t_route.begin() +
                                                             t_rank + 1,
                                                           t_route.end(),
                                                           s_rank + 1,
                                                           s_route.size());

  valid &= target.is_valid_addition_for_capacity_inclusion(_input,
                                                           s_delivery,
                                                           s_route.begin() +
                                                             s_rank + 1,
                                                           s_route.end(),
                                                           t_rank + 1,
                                                           t_route.size());

  return valid;
}

void TwoOpt::apply() {
  auto nb_source = s_route.size() - 1 - s_rank;

  t_route.insert(t_route.begin() + t_rank + 1,
                 s_route.begin() + s_rank + 1,
                 s_route.end());
  s_route.erase(s_route.begin() + s_rank + 1, s_route.end());
  s_route.insert(s_route.end(),
                 t_route.begin() + t_rank + 1 + nb_source,
                 t_route.end());
  t_route.erase(t_route.begin() + t_rank + 1 + nb_source, t_route.end());
}

std::vector<Index> TwoOpt::addition_candidates() const {
  return {s_vehicle, t_vehicle};
}

std::vector<Index> TwoOpt::update_candidates() const {
  return {s_vehicle, t_vehicle};
}

} // namespace cvrp
} // namespace vroom
<|endoftext|>


<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SceneManager.h"
#include "Scene.h"
#include "core/Engine.h"
#include "Node.h"

namespace ouzel
{
    namespace scene
    {
        SceneManager::SceneManager()
        {
            sharedEngine->getEventDispatcher()->addEventHandler(eventHandler);
            eventHandler.windowHandler = std::bind(&SceneManager::handleWindow, this, std::placeholders::_1, std::placeholders::_2);
            eventHandler.mouseHandler = std::bind(&SceneManager::handleMouse, this, std::placeholders::_1, std::placeholders::_2);
            eventHandler.touchHandler = std::bind(&SceneManager::handleTouch, this, std::placeholders::_1, std::placeholders::_2);
        }

        SceneManager::~SceneManager()
        {
            sharedEngine->getEventDispatcher()->removeEventHandler(eventHandler);
        }

        void SceneManager::setScene(const ScenePtr& newScene)
        {
            if (scene != newScene)
            {
                scene = newScene;

                if (scene)
                {
                    scene->recalculateProjection();
                }
            }
        }

        void SceneManager::draw()
        {
            if (scene)
            {
                scene->draw();
            }
        }

        void SceneManager::recalculateProjection()
        {
            if (scene)
            {
                scene->recalculateProjection();
            }
        }

        bool SceneManager::handleWindow(Event::Type type, const WindowEvent&)
        {
            if (type == Event::Type::WINDOW_SIZE_CHANGE ||
                type == Event::Type::WINDOW_FULLSCREEN_CHANGE)
            {
                recalculateProjection();
            }

            return true;
        }

        bool SceneManager::handleMouse(Event::Type type, const MouseEvent& event)
        {
            if (scene)
            {
                switch (type)
                {
                    case Event::Type::MOUSE_DOWN:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerDownOnNode(0, node, event.position);
                        break;
                    }
                    case Event::Type::MOUSE_UP:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(0, node, event.position);
                        break;
                    }
                    case Event::Type::MOUSE_MOVE:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerEnterNode(0, node, event.position);

                        if (scene::NodePtr pointerDownOnNode = getPointerDownOnNode(0))
                        {
                            pointerDragNode(0, pointerDownOnNode, event.position);
                        }
                        break;
                    }
                    default:
                        break;
                }
            }

            return true;
        }

        bool SceneManager::handleTouch(Event::Type type, const TouchEvent& event)
        {
            if (scene)
            {
                switch (type)
                {
                    case Event::Type::TOUCH_BEGIN:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerDownOnNode(event.touchId, node, event.position);
                        break;
                    }
                    case Event::Type::TOUCH_END:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(event.touchId, node, event.position);
                        break;
                    }
                    case Event::Type::TOUCH_MOVE:
                    {
                        if (scene::NodePtr pointerDownOnNode = getPointerDownOnNode(event.touchId))
                        {
                            pointerDragNode(event.touchId, pointerDownOnNode, event.position);
                        }
                        break;
                    }
                    case Event::Type::TOUCH_CANCEL:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(event.touchId, node, event.position);
                        break;
                    }
                    default:
                        break;
                }
            }

            return true;
        }

        scene::NodePtr SceneManager::getPointerOnNode(uint64_t pointerId) const
        {
            scene::NodePtr result;

            auto i = pointerOnNodes.find(pointerId);

            if (i != pointerOnNodes.end() && !i->second.expired())
            {
                result = i->second.lock();
            }

            return result;
        }

        scene::NodePtr SceneManager::getPointerDownOnNode(uint64_t pointerId) const
        {
            scene::NodePtr result;

            auto i = pointerDownOnNodes.find(pointerId);

            if (i != pointerDownOnNodes.end() && !i->second.expired())
            {
                result = i->second.lock();
            }

            return result;
        }

        void SceneManager::pointerEnterNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            scene::NodePtr pointerOnNode = getPointerOnNode(pointerId);

            if (pointerOnNode)
            {
                if (pointerOnNode == node)
                {
                    return;
                }
                else
                {
                    pointerLeaveNode(pointerId, pointerOnNode, position);
                }
            }

            pointerOnNodes[pointerId] = node;

            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_ENTER_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }

        void SceneManager::pointerLeaveNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_LEAVE_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }

            pointerOnNodes.erase(pointerId);
        }

        void SceneManager::pointerDownOnNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            pointerDownOnNodes[pointerId] = node;

            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_PRESS_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }

        void SceneManager::pointerUpOnNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            scene::NodePtr pointerDownOnNode = getPointerDownOnNode(pointerId);

            if (pointerDownOnNode && pointerDownOnNode->isReceivingInput())
            {
                Event releaseEvent;
                releaseEvent.type = Event::Type::UI_RELEASE_NODE;

                releaseEvent.uiEvent.node = pointerDownOnNode;
                releaseEvent.uiEvent.position = pointerDownOnNode->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(releaseEvent);

                if (pointerDownOnNode == node)
                {
                    Event clickEvent;
                    clickEvent.type = Event::Type::UI_CLICK_NODE;

                    clickEvent.uiEvent.node = pointerDownOnNode;
                    clickEvent.uiEvent.position = pointerDownOnNode->convertWorldToLocal(position);

                    sharedEngine->getEventDispatcher()->dispatchEvent(clickEvent);
                }
            }

            pointerDownOnNodes.erase(pointerId);
        }

        void SceneManager::pointerDragNode(uint64_t, const scene::NodePtr& node, const Vector2& position)
        {
            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_DRAG_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }
    } // namespace scene
} // namespace ouzel
<commit_msg>Implement node enter/leave for touch events<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SceneManager.h"
#include "Scene.h"
#include "core/Engine.h"
#include "Node.h"

namespace ouzel
{
    namespace scene
    {
        SceneManager::SceneManager()
        {
            sharedEngine->getEventDispatcher()->addEventHandler(eventHandler);
            eventHandler.windowHandler = std::bind(&SceneManager::handleWindow, this, std::placeholders::_1, std::placeholders::_2);
            eventHandler.mouseHandler = std::bind(&SceneManager::handleMouse, this, std::placeholders::_1, std::placeholders::_2);
            eventHandler.touchHandler = std::bind(&SceneManager::handleTouch, this, std::placeholders::_1, std::placeholders::_2);
        }

        SceneManager::~SceneManager()
        {
            sharedEngine->getEventDispatcher()->removeEventHandler(eventHandler);
        }

        void SceneManager::setScene(const ScenePtr& newScene)
        {
            if (scene != newScene)
            {
                scene = newScene;

                if (scene)
                {
                    scene->recalculateProjection();
                }
            }
        }

        void SceneManager::draw()
        {
            if (scene)
            {
                scene->draw();
            }
        }

        void SceneManager::recalculateProjection()
        {
            if (scene)
            {
                scene->recalculateProjection();
            }
        }

        bool SceneManager::handleWindow(Event::Type type, const WindowEvent&)
        {
            if (type == Event::Type::WINDOW_SIZE_CHANGE ||
                type == Event::Type::WINDOW_FULLSCREEN_CHANGE)
            {
                recalculateProjection();
            }

            return true;
        }

        bool SceneManager::handleMouse(Event::Type type, const MouseEvent& event)
        {
            if (scene)
            {
                switch (type)
                {
                    case Event::Type::MOUSE_DOWN:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerDownOnNode(0, node, event.position);
                        break;
                    }
                    case Event::Type::MOUSE_UP:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(0, node, event.position);
                        break;
                    }
                    case Event::Type::MOUSE_MOVE:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerEnterNode(0, node, event.position);

                        if (scene::NodePtr pointerDownOnNode = getPointerDownOnNode(0))
                        {
                            pointerDragNode(0, pointerDownOnNode, event.position);
                        }
                        break;
                    }
                    default:
                        break;
                }
            }

            return true;
        }

        bool SceneManager::handleTouch(Event::Type type, const TouchEvent& event)
        {
            if (scene)
            {
                switch (type)
                {
                    case Event::Type::TOUCH_BEGIN:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerDownOnNode(event.touchId, node, event.position);
                        break;
                    }
                    case Event::Type::TOUCH_END:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(event.touchId, node, event.position);
                        break;
                    }
                    case Event::Type::TOUCH_MOVE:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerEnterNode(0, node, event.position);

                        if (scene::NodePtr pointerDownOnNode = getPointerDownOnNode(event.touchId))
                        {
                            pointerDragNode(event.touchId, pointerDownOnNode, event.position);
                        }
                        break;
                    }
                    case Event::Type::TOUCH_CANCEL:
                    {
                        scene::NodePtr node = scene->pickNode(event.position);
                        pointerUpOnNode(event.touchId, node, event.position);
                        break;
                    }
                    default:
                        break;
                }
            }

            return true;
        }

        scene::NodePtr SceneManager::getPointerOnNode(uint64_t pointerId) const
        {
            scene::NodePtr result;

            auto i = pointerOnNodes.find(pointerId);

            if (i != pointerOnNodes.end() && !i->second.expired())
            {
                result = i->second.lock();
            }

            return result;
        }

        scene::NodePtr SceneManager::getPointerDownOnNode(uint64_t pointerId) const
        {
            scene::NodePtr result;

            auto i = pointerDownOnNodes.find(pointerId);

            if (i != pointerDownOnNodes.end() && !i->second.expired())
            {
                result = i->second.lock();
            }

            return result;
        }

        void SceneManager::pointerEnterNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            scene::NodePtr pointerOnNode = getPointerOnNode(pointerId);

            if (pointerOnNode)
            {
                if (pointerOnNode == node)
                {
                    return;
                }
                else
                {
                    pointerLeaveNode(pointerId, pointerOnNode, position);
                }
            }

            pointerOnNodes[pointerId] = node;

            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_ENTER_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }

        void SceneManager::pointerLeaveNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_LEAVE_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }

            pointerOnNodes.erase(pointerId);
        }

        void SceneManager::pointerDownOnNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            pointerDownOnNodes[pointerId] = node;

            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_PRESS_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }

        void SceneManager::pointerUpOnNode(uint64_t pointerId, const scene::NodePtr& node, const Vector2& position)
        {
            scene::NodePtr pointerDownOnNode = getPointerDownOnNode(pointerId);

            if (pointerDownOnNode && pointerDownOnNode->isReceivingInput())
            {
                Event releaseEvent;
                releaseEvent.type = Event::Type::UI_RELEASE_NODE;

                releaseEvent.uiEvent.node = pointerDownOnNode;
                releaseEvent.uiEvent.position = pointerDownOnNode->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(releaseEvent);

                if (pointerDownOnNode == node)
                {
                    Event clickEvent;
                    clickEvent.type = Event::Type::UI_CLICK_NODE;

                    clickEvent.uiEvent.node = pointerDownOnNode;
                    clickEvent.uiEvent.position = pointerDownOnNode->convertWorldToLocal(position);

                    sharedEngine->getEventDispatcher()->dispatchEvent(clickEvent);
                }
            }

            pointerDownOnNodes.erase(pointerId);
        }

        void SceneManager::pointerDragNode(uint64_t, const scene::NodePtr& node, const Vector2& position)
        {
            if (node && node->isReceivingInput())
            {
                Event event;
                event.type = Event::Type::UI_DRAG_NODE;

                event.uiEvent.node = node;
                event.uiEvent.position = node->convertWorldToLocal(position);

                sharedEngine->getEventDispatcher()->dispatchEvent(event);
            }
        }
    } // namespace scene
} // namespace ouzel
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include "object.hh"
#include "string_object.hh"

namespace tadpole {

class Chunk;

class FunctionObject final : public BaseObject {
  StringObject* name_{};
  sz_t arity_{};
  sz_t upvalues_count_{};
  Chunk* chunk_{};
public:
  FunctionObject(StringObject* name = nullptr) noexcept;
  virtual ~FunctionObject();

  inline FunctionObject* name() const noexcept { return name_; }
  inline const char* name_asstr() const noexcept { return name_ ? name_->cstr() : "<tadpole>"; }
  inline void set_name(StringObject* name) noexcept { name_ = name; }
  inline sz_t arity() const noexcept { return arity_; }
  inline sz_t inc_arity() noexcept { return arity_++; }
  inline sz_t upvalues_count() const noexcept { return upvalues_count_; }
  inline sz_t inc_upvalues_count() noexcept { return upvalues_count_++; }
  inline Chunk* chunk() const noexcept { return chunk_; }

  virtual str_t stringify() const override;
  virtual void iter_children(ObjectVisitor&& visitor) override;

  static FunctionObject* create(StringObject* name = nullptr);
};

}
<commit_msg>:construction: chore(function-object): add function object implementation<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include "object.hh"
#include "string_object.hh"

namespace tadpole {

class Chunk;

class FunctionObject final : public BaseObject {
  StringObject* name_{};
  sz_t arity_{};
  sz_t upvalues_count_{};
  Chunk* chunk_{};
public:
  FunctionObject(StringObject* name = nullptr) noexcept;
  virtual ~FunctionObject();

  inline StringObject* name() const noexcept { return name_; }
  inline const char* name_asstr() const noexcept { return name_ ? name_->cstr() : "<tadpole>"; }
  inline void set_name(StringObject* name) noexcept { name_ = name; }
  inline sz_t arity() const noexcept { return arity_; }
  inline sz_t inc_arity() noexcept { return arity_++; }
  inline sz_t upvalues_count() const noexcept { return upvalues_count_; }
  inline sz_t inc_upvalues_count() noexcept { return upvalues_count_++; }
  inline Chunk* chunk() const noexcept { return chunk_; }

  virtual str_t stringify() const override;
  virtual void iter_children(ObjectVisitor&& visitor) override;

  static FunctionObject* create(StringObject* name = nullptr);
};

}
<|endoftext|>


<commit_before>/** \file    add_isbns_or_issns_to_articles.cc
 *  \brief   A tool for adding missing ISBN's (field 020$a) or ISSN's (field 773$x)to articles entries,
 *           in MARC-21 data.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2018, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
#include <cstring>
#include "MARC.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << progname << " master_marc_input marc_output\n";
    std::cerr << "  Adds host/parent/journal ISBNs and ISSNs to article entries found in the\n";
    std::cerr << "  master_marc_input and writes this augmented file as marc_output.  The ISBNs and ISSNs are\n";
    std::cerr << "  extracted from superior entries found in master_marc_input.\n";
    std::exit(EXIT_FAILURE);
}

void PopulateParentIdToISBNAndISSNMap(
    MARC::Reader * const marc_reader,
    std::unordered_map<std::string, std::string> * const parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting extraction of ISBN's and ISSN's.");

    unsigned count(0), extracted_isbn_count(0), extracted_issn_count(0);
    std::string err_msg;
    while (const MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isSerial() and not record.isMonograph())
            continue;

        // Try to see if we have an ISBN:
        const auto field_020(record.findTag("020"));
        if (field_020 != record.end()) {
            const std::string isbn(field_020->getFirstSubfieldWithCode('a'));
            if (not isbn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = isbn;
                ++extracted_isbn_count;
                continue;
            }
        } else
            continue;

        std::string issn;
        // 1. First try to get an ISSN from 029$a, (according to the BSZ's PICA-to-MARC mapping
        // documentation this contains the "authorised" ISSN) but only if the indicators are correct:
        for (const auto &_029_field : record.getTagRange("029")) {
            const auto subfields(_029_field.getSubfields());

            // We only want fields with indicators 'x' and 'a':
            if (_029_field.getIndicator1() != 'x' or _029_field.getIndicator2() != 'a')
                continue;

            issn = subfields.getFirstSubfieldWithCode('a');
            if (not issn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                ++extracted_issn_count;
            }
        }

        // 2. If we don't already have an ISSN check 022$a as a last resort:
        if (issn.empty()) {
            const auto field_022(record.findTag("022"));
            if (field_022 != record.end()) {
                issn = field_022->getFirstSubfieldWithCode('a');
                if (not issn.empty()) {
                    (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                    ++extracted_issn_count;
                }
            }
        }
    }

    if (not err_msg.empty())
        LOG_ERROR(err_msg);

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Extracted " + std::to_string(extracted_isbn_count) + " ISBNs.");
    LOG_INFO("Extracted " + std::to_string(extracted_issn_count) + " ISSNs.");
}

void AddMissingISBNsOrISSNsToArticleEntries(MARC::Reader * const marc_reader,
                                            MARC::Writer * const marc_writer, const std::unordered_map<std::string,
                                            std::string> &parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting augmentation of article entries.");

    unsigned count(0), isbns_added(0), issns_added(0), missing_host_record_ctrl_num_count(0),
             missing_isbn_or_issn_count(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isArticle()) {
            marc_writer->write(record);
            continue;
        }

        const auto _773_field(record.findTag("773"));
        if (_773_field == record.end()) {
            marc_writer->write(record);
            continue;
        }

        auto subfields(_773_field->getSubfields());
        if (subfields.hasSubfield('x')) {
            marc_writer->write(record);
            continue;
        }

        if (not subfields.hasSubfield('w')) {       // Record control number of Host Item Entry.
            marc_writer->write(record);
            ++missing_host_record_ctrl_num_count;
            continue;
        }

        std::string host_id(subfields.getFirstSubfieldWithCode('w'));
        if (StringUtil::StartsWith(host_id, "(DE-576)"))
            host_id = host_id.substr(8);
        const auto &parent_isbn_or_issn_iter(parent_id_to_isbn_and_issn_map.find(host_id));
        if (parent_isbn_or_issn_iter == parent_id_to_isbn_and_issn_map.end()) {
            marc_writer->write(record);
            ++missing_isbn_or_issn_count;
            continue;
        }

        if (MiscUtil::IsPossibleISSN(parent_isbn_or_issn_iter->second)) {
            subfields.addSubfield('x', parent_isbn_or_issn_iter->second);
            _773_field->setSubfields(subfields);
            ++issns_added;
        } else { // Deal with ISBNs.
            auto _020_field(record.findTag("020"));
            if (_020_field == record.end()) {
                record.insertField("020", { { 'a', parent_isbn_or_issn_iter->second } });
                ++isbns_added;
            } else if (_020_field->getFirstSubfieldWithCode('a').empty()) {
                _020_field->appendSubfield('a', parent_isbn_or_issn_iter->second);
                ++isbns_added;
            }
        }
        marc_writer->write(record);
    }

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Added ISBN's to " + std::to_string(isbns_added) + " article record(s).");
    LOG_INFO("Added ISSN's to " + std::to_string(issns_added) + " article record(s).");
    LOG_INFO(std::to_string(missing_host_record_ctrl_num_count) +
             " articles had missing host record control number(s).");
    LOG_INFO("For " + std::to_string(missing_isbn_or_issn_count) + " articles no host ISBN nor ISSN was found.");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc < 3)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string marc_output_filename(argv[2]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Master input file name equals output file name!");

    auto marc_reader(MARC::Reader::Factory(marc_input_filename));
    auto marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_map<std::string, std::string> parent_id_to_isbn_and_issn_map;
    PopulateParentIdToISBNAndISSNMap(marc_reader.get(), &parent_id_to_isbn_and_issn_map);
    marc_reader->rewind();

    AddMissingISBNsOrISSNsToArticleEntries(marc_reader.get(), marc_writer.get(),
                                           parent_id_to_isbn_and_issn_map);

    return EXIT_SUCCESS;
}
<commit_msg>Inherit open access status from parent.<commit_after>/** \file    add_isbns_or_issns_to_articles.cc
 *  \brief   A tool for adding missing ISBN's (field 020$a) or ISSN's (field 773$x)to articles entries,
 *           in MARC-21 data.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2018, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
#include <cstring>
#include "MARC.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << progname << " master_marc_input marc_output\n";
    std::cerr << "  Adds host/parent/journal ISBNs and ISSNs to article entries found in the\n";
    std::cerr << "  master_marc_input and writes this augmented file as marc_output.  The ISBNs and ISSNs are\n";
    std::cerr << "  extracted from superior entries found in master_marc_input.\n";
    std::exit(EXIT_FAILURE);
}

struct RecordInfo {
    std::string isbn_or_issn_;
    bool is_open_access_;
};

void PopulateParentIdToISBNAndISSNMap(MARC::Reader * const marc_reader,
                                      std::unordered_map<std::string, RecordInfo> * const parent_id_to_isbn_issn_and_open_access_status_map)
{
    LOG_INFO("Starting extraction of ISBN's and ISSN's.");

    unsigned count(0), extracted_isbn_count(0), extracted_issn_count(0);
    std::string err_msg;
    while (const MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isSerial() and not record.isMonograph())
            continue;

        // Try to see if we have an ISBN:
        const auto field_020(record.findTag("020"));
        if (field_020 != record.end()) {
            const std::string isbn(field_020->getFirstSubfieldWithCode('a'));
            if (not isbn.empty()) {
                (*parent_id_to_isbn_issn_and_open_access_status_map)[record.getControlNumber()] = { isbn, MARC::IsOpenAccess(record) };
                ++extracted_isbn_count;
                continue;
            }
        } else
            continue;

        std::string issn;
        // 1. First try to get an ISSN from 029$a, (according to the BSZ's PICA-to-MARC mapping
        // documentation this contains the "authorised" ISSN) but only if the indicators are correct:
        for (const auto &_029_field : record.getTagRange("029")) {
            const auto subfields(_029_field.getSubfields());

            // We only want fields with indicators 'x' and 'a':
            if (_029_field.getIndicator1() != 'x' or _029_field.getIndicator2() != 'a')
                continue;

            issn = subfields.getFirstSubfieldWithCode('a');
            if (not issn.empty()) {
                (*parent_id_to_isbn_issn_and_open_access_status_map)[record.getControlNumber()] = { issn, MARC::IsOpenAccess(record) };
                ++extracted_issn_count;
            }
        }

        // 2. If we don't already have an ISSN check 022$a as a last resort:
        if (issn.empty()) {
            const auto field_022(record.findTag("022"));
            if (field_022 != record.end()) {
                issn = field_022->getFirstSubfieldWithCode('a');
                if (not issn.empty()) {
                    (*parent_id_to_isbn_issn_and_open_access_status_map)[record.getControlNumber()] = { issn, MARC::IsOpenAccess(record) };
                    ++extracted_issn_count;
                }
            }
        }
    }

    if (not err_msg.empty())
        LOG_ERROR(err_msg);

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Extracted " + std::to_string(extracted_isbn_count) + " ISBNs.");
    LOG_INFO("Extracted " + std::to_string(extracted_issn_count) + " ISSNs.");
}

void AddMissingISBNsOrISSNsToArticleEntries(
    MARC::Reader * const marc_reader, MARC::Writer * const marc_writer,
    const std::unordered_map<std::string, RecordInfo> &parent_id_to_isbn_issn_and_open_access_status_map)
{
    LOG_INFO("Starting augmentation of article entries.");

    unsigned count(0), isbns_added(0), issns_added(0), missing_host_record_ctrl_num_count(0), missing_isbn_or_issn_count(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isArticle()) {
            marc_writer->write(record);
            continue;
        }

        const auto _773_field(record.findTag("773"));
        if (_773_field == record.end()) {
            marc_writer->write(record);
            continue;
        }

        auto subfields(_773_field->getSubfields());
        if (subfields.hasSubfield('x')) {
            marc_writer->write(record);
            continue;
        }

        if (not subfields.hasSubfield('w')) {       // Record control number of Host Item Entry.
            marc_writer->write(record);
            ++missing_host_record_ctrl_num_count;
            continue;
        }

        std::string host_id(subfields.getFirstSubfieldWithCode('w'));
        if (StringUtil::StartsWith(host_id, "(DE-576)"))
            host_id = host_id.substr(8);
        const auto &parent_isbn_or_issn_iter(parent_id_to_isbn_issn_and_open_access_status_map.find(host_id));
        if (parent_isbn_or_issn_iter == parent_id_to_isbn_issn_and_open_access_status_map.end()) {
            marc_writer->write(record);
            ++missing_isbn_or_issn_count;
            continue;
        }

        if (MiscUtil::IsPossibleISSN(parent_isbn_or_issn_iter->second.isbn_or_issn_)) {
            subfields.addSubfield('x', parent_isbn_or_issn_iter->second.isbn_or_issn_);
            _773_field->setSubfields(subfields);
            ++issns_added;
        } else { // Deal with ISBNs.
            auto _020_field(record.findTag("020"));
            if (_020_field == record.end()) {
                record.insertField("020", { { 'a', parent_isbn_or_issn_iter->second.isbn_or_issn_ } });
                ++isbns_added;
            } else if (_020_field->getFirstSubfieldWithCode('a').empty()) {
                _020_field->appendSubfield('a', parent_isbn_or_issn_iter->second.isbn_or_issn_);
                ++isbns_added;
            }
        }

        // If parent is open access and we're not, add it!
        if (parent_isbn_or_issn_iter->second.is_open_access_ and not MARC::IsOpenAccess(record))
            record.insertField("655", { { 'a', "Open Access" } }, /* indicator1 = */' ', /* indicator2 = */'4');

        marc_writer->write(record);
    }

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Added ISBN's to " + std::to_string(isbns_added) + " article record(s).");
    LOG_INFO("Added ISSN's to " + std::to_string(issns_added) + " article record(s).");
    LOG_INFO(std::to_string(missing_host_record_ctrl_num_count) +
             " articles had missing host record control number(s).");
    LOG_INFO("For " + std::to_string(missing_isbn_or_issn_count) + " articles no host ISBN nor ISSN was found.");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc < 3)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string marc_output_filename(argv[2]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Master input file name equals output file name!");

    auto marc_reader(MARC::Reader::Factory(marc_input_filename));
    auto marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_map<std::string, RecordInfo> parent_id_to_isbn_issn_and_open_access_status_map;
    PopulateParentIdToISBNAndISSNMap(marc_reader.get(), &parent_id_to_isbn_issn_and_open_access_status_map);
    marc_reader->rewind();

    AddMissingISBNsOrISSNsToArticleEntries(marc_reader.get(), marc_writer.get(), parent_id_to_isbn_issn_and_open_access_status_map);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*       Copyright 2007 by F. Heinrich, B. Seppke, Ullrich Koethe       */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#include <iostream>
#include <functional>
#include <cmath>
#include "unittest.hxx"

#include "vigra/seededregiongrowing3d.hxx"

using namespace vigra;

struct SeededRegionGrowing3DTest
{
    typedef vigra::MultiArray<3,int> IntVolume;
    typedef vigra::MultiArray<3,double> DoubleVolume;

    SeededRegionGrowing3DTest()
    : vol1(IntVolume::difference_type(5,5,5)),distvol1(DoubleVolume::difference_type(5,5,5)),distvol2(DoubleVolume::difference_type(4,4,4)),vol2(DoubleVolume::difference_type(4,4,4)),vol3(IntVolume::difference_type(5,5,5))
    {
        static const int in1[] = { 0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 1, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 2, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0};

        IntVolume::iterator i = vol1.begin();
        IntVolume::iterator end = vol1.end();
        const int * p = in1;

        for(; i != end; ++i, ++p)
        {
            *i=*p;
        }

        for(int z=0; z<5; ++z)
            for(int y=0; y<5; ++y)
                for(int x=0; x<5; ++x){
                    distvol1(x,y,z)=std::min( ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-0.0)*(z-0.0)),
                                              ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-4.0)*(z-4.0)) );
                }

        static const double in2[] = { 0.0, 0.0, 0.0, 0.0,
                                      0.0, 1.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 2.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0};

        DoubleVolume::iterator id = vol2.begin();
        DoubleVolume::iterator endd = vol2.end();
        const double * pd = in2;

        for(; id != endd; ++id, ++pd)
        {
            *id=*pd;
        }

        for(int z=0; z<4; ++z)
            for(int y=0; y<4; ++y)
                for(int x=0; x<4; ++x){
                    distvol2(x,y,z)=std::min( ((x-1.0)*(x-1.0)+(y-1.0)*(y-1.0)+(z-0.0)*(z-0.0)),
                                              ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-3.0)*(z-3.0)) );
                }

        static const int in3[] = { 1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 3, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4};

        i = vol3.begin();
        end = vol3.end();
        p = in3;

        for(; i != end; ++i, ++p)
        {
            *i=*p;
        }

    }

    struct DirectCostFunctor
    {
        typedef double argument_type;
        typedef double result_type;
        typedef double cost_type;

        void operator()(double const &) {}

        double const & cost(double const & v) const
        {
            return v;
        }
    };

    void voronoiTest()
    {
        DoubleVolume res(vol2);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(2);
        seededRegionGrowing3D(srcMultiArrayRange(distvol2), srcMultiArray(vol2),
                              destMultiArray(res), cost, CompleteGrow);

        DoubleVolume::iterator i = res.begin();

        int x,y,z;

        for(z=0; z<4; ++z)
        {
            for(y=0; y<4; ++y)
            {
                for(x=0; x<4; ++x)
                {
                    double dist = *i++;
                    double dist1 = VIGRA_CSTD::sqrt((1.0 - x)*(1.0 - x) +
                                                    (1.0 - y)*(1.0 - y) +
                                                    (0.0 - z)*(0.0 - z)  );

                    double dist2 = VIGRA_CSTD::sqrt((2.0 - x)*(2.0 - x) +
                                                    (2.0 - y)*(2.0 - y) +
                                                    (3.0 - z)*(3.0 - z)  );

                    double desired = (dist1 <= dist2) ? 1 : 2;

                    if(VIGRA_CSTD::fabs(dist1 - dist2) > 1e-10)
                        shouldEqual(dist, desired);
                }
            }
        }
    }

    void voronoiTestWithBorder()
    {

        static const int desired[] = {  1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,

                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,

                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,

                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,

                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2};

        IntVolume res(vol1);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(2);
        seededRegionGrowing3D(srcMultiArrayRange(distvol1), srcMultiArray(vol1),
                              destMultiArray(res), cost, KeepContours);

        //int c=1;
        //for(IntVolume::iterator iter=res.begin(); iter!=res.end(); ++iter, ++c){
        //    std::cerr << *iter << ", ";
        //    if(c%5==0) std::cerr << std::endl;
        //    if(c%25==0) std::cerr << std::endl;
        //}

        shouldEqualSequence(res.begin(), res.end(), desired);

    }

    void simpleTest()
    {
        IntVolume res(vol3);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(4);
        seededRegionGrowing3D(srcMultiArrayRange(vol3), srcMultiArray(vol3),
                              destMultiArray(res), cost, CompleteGrow);

        shouldEqualSequence(res.begin(), res.end(), vol3.begin());
    }

    IntVolume vol1, vol3;
    DoubleVolume vol2, distvol1, distvol2;
};

struct SimpleAnalysisTestSuite
: public vigra::test_suite
{
    SimpleAnalysisTestSuite()
    : vigra::test_suite("SimpleAnalysisTestSuite")
    {
        add( testCase( &SeededRegionGrowing3DTest::voronoiTest));
        add( testCase( &SeededRegionGrowing3DTest::voronoiTestWithBorder));
        add( testCase( &SeededRegionGrowing3DTest::simpleTest));
    }
};

int main(int argc, char ** argv)
{
    SimpleAnalysisTestSuite test;

    int failed = test.run(vigra::testsToBeExecuted(argc, argv));

    std::cout << test.report() << std::endl;
    return (failed != 0);
}

<commit_msg>fixed test suite name SeededRegionGrowing3DTestSuite<commit_after>/************************************************************************/
/*                                                                      */
/*       Copyright 2007 by F. Heinrich, B. Seppke, Ullrich Koethe       */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#include <iostream>
#include <functional>
#include <cmath>
#include "unittest.hxx"

#include "vigra/seededregiongrowing3d.hxx"

using namespace vigra;

struct SeededRegionGrowing3DTest
{
    typedef vigra::MultiArray<3,int> IntVolume;
    typedef vigra::MultiArray<3,double> DoubleVolume;

    SeededRegionGrowing3DTest()
    : vol1(IntVolume::difference_type(5,5,5)),distvol1(DoubleVolume::difference_type(5,5,5)),distvol2(DoubleVolume::difference_type(4,4,4)),vol2(DoubleVolume::difference_type(4,4,4)),vol3(IntVolume::difference_type(5,5,5))
    {
        static const int in1[] = { 0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 1, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,

                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 2, 0, 0,
                                   0, 0, 0, 0, 0,
                                   0, 0, 0, 0, 0};

        IntVolume::iterator i = vol1.begin();
        IntVolume::iterator end = vol1.end();
        const int * p = in1;

        for(; i != end; ++i, ++p)
        {
            *i=*p;
        }

        for(int z=0; z<5; ++z)
            for(int y=0; y<5; ++y)
                for(int x=0; x<5; ++x){
                    distvol1(x,y,z)=std::min( ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-0.0)*(z-0.0)),
                                              ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-4.0)*(z-4.0)) );
                }

        static const double in2[] = { 0.0, 0.0, 0.0, 0.0,
                                      0.0, 1.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,

                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 2.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0};

        DoubleVolume::iterator id = vol2.begin();
        DoubleVolume::iterator endd = vol2.end();
        const double * pd = in2;

        for(; id != endd; ++id, ++pd)
        {
            *id=*pd;
        }

        for(int z=0; z<4; ++z)
            for(int y=0; y<4; ++y)
                for(int x=0; x<4; ++x){
                    distvol2(x,y,z)=std::min( ((x-1.0)*(x-1.0)+(y-1.0)*(y-1.0)+(z-0.0)*(z-0.0)),
                                              ((x-2.0)*(x-2.0)+(y-2.0)*(y-2.0)+(z-3.0)*(z-3.0)) );
                }

        static const int in3[] = { 1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 3, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   1, 1, 1, 1, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 2, 2, 2, 1,
                                   1, 1, 1, 1, 1,

                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4,
                                   4, 4, 4, 4, 4};

        i = vol3.begin();
        end = vol3.end();
        p = in3;

        for(; i != end; ++i, ++p)
        {
            *i=*p;
        }

    }

    struct DirectCostFunctor
    {
        typedef double argument_type;
        typedef double result_type;
        typedef double cost_type;

        void operator()(double const &) {}

        double const & cost(double const & v) const
        {
            return v;
        }
    };

    void voronoiTest()
    {
        DoubleVolume res(vol2);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(2);
        seededRegionGrowing3D(srcMultiArrayRange(distvol2), srcMultiArray(vol2),
                              destMultiArray(res), cost, CompleteGrow);

        DoubleVolume::iterator i = res.begin();

        int x,y,z;

        for(z=0; z<4; ++z)
        {
            for(y=0; y<4; ++y)
            {
                for(x=0; x<4; ++x)
                {
                    double dist = *i++;
                    double dist1 = VIGRA_CSTD::sqrt((1.0 - x)*(1.0 - x) +
                                                    (1.0 - y)*(1.0 - y) +
                                                    (0.0 - z)*(0.0 - z)  );

                    double dist2 = VIGRA_CSTD::sqrt((2.0 - x)*(2.0 - x) +
                                                    (2.0 - y)*(2.0 - y) +
                                                    (3.0 - z)*(3.0 - z)  );

                    double desired = (dist1 <= dist2) ? 1 : 2;

                    if(VIGRA_CSTD::fabs(dist1 - dist2) > 1e-10)
                        shouldEqual(dist, desired);
                }
            }
        }
    }

    void voronoiTestWithBorder()
    {

        static const int desired[] = {  1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,

                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,
                                        1, 1, 1, 1, 1,

                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,
                                        0, 0, 0, 0, 0,

                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,

                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2,
                                        2, 2, 2, 2, 2};

        IntVolume res(vol1);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(2);
        seededRegionGrowing3D(srcMultiArrayRange(distvol1), srcMultiArray(vol1),
                              destMultiArray(res), cost, KeepContours);

        //int c=1;
        //for(IntVolume::iterator iter=res.begin(); iter!=res.end(); ++iter, ++c){
        //    std::cerr << *iter << ", ";
        //    if(c%5==0) std::cerr << std::endl;
        //    if(c%25==0) std::cerr << std::endl;
        //}

        shouldEqualSequence(res.begin(), res.end(), desired);

    }

    void simpleTest()
    {
        IntVolume res(vol3);

        vigra::ArrayOfRegionStatistics<DirectCostFunctor> cost(4);
        seededRegionGrowing3D(srcMultiArrayRange(vol3), srcMultiArray(vol3),
                              destMultiArray(res), cost, CompleteGrow);

        shouldEqualSequence(res.begin(), res.end(), vol3.begin());
    }

    IntVolume vol1, vol3;
    DoubleVolume vol2, distvol1, distvol2;
};

struct SeededRegionGrowing3DTestSuite
: public vigra::test_suite
{
    SeededRegionGrowing3DTestSuite()
    : vigra::test_suite("SeededRegionGrowing3DTestSuite")
    {
        add( testCase( &SeededRegionGrowing3DTest::voronoiTest));
        add( testCase( &SeededRegionGrowing3DTest::voronoiTestWithBorder));
        add( testCase( &SeededRegionGrowing3DTest::simpleTest));
    }
};

int main(int argc, char ** argv)
{
    SeededRegionGrowing3DTestSuite test;

    int failed = test.run(vigra::testsToBeExecuted(argc, argv));

    std::cout << test.report() << std::endl;
    return (failed != 0);
}

<|endoftext|>


<commit_before>/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2008-2014. All Rights Reserved.
 *
 * The contents of this file are subject to the Erlang Public License,
 * Version 1.1, (the "License"); you may not use this file except in
 * compliance with the License. You should have received a copy of the
 * Erlang Public License along with this software. If not, it can be
 * retrieved online at http://www.erlang.org/.
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * %CopyrightEnd%
 */

#include <stdio.h>
#include <string.h>
#ifndef _WIN32
#include <dlfcn.h>
#else
#include <windows.h>
#endif
#include "wxe_impl.h"
#include "wxe_return.h"
#include "wxe_gl.h"

/* ****************************************************************************
 * Opengl context management *
 * ****************************************************************************/

int erl_gl_initiated = FALSE;
ErlDrvTermData gl_active = 0;
wxeGLC glc;

typedef void (*WXE_GL_DISPATCH) (int, char *, ErlDrvPort, ErlDrvTermData, char **, int *);
WXE_GL_DISPATCH wxe_gl_dispatch;

#ifdef _WIN32
#define RTLD_LAZY 0
typedef HMODULE DL_LIB_P;
void * dlsym(HMODULE Lib, const char *func) {
  void * funcp;
  if((funcp = (void *) GetProcAddress(Lib, func)))
    return funcp;
  else
    return (void *) wglGetProcAddress(func);
}

HMODULE dlopen(const char *path, int unused) {
  WCHAR * DLL;
  int len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
  DLL = (WCHAR *) malloc(len * sizeof(WCHAR));
  MultiByteToWideChar(CP_ACP, 0, path, -1, DLL, len);
  HMODULE lib = LoadLibrary(DLL);
  free(DLL);
  return lib;
}

void dlclose(HMODULE Lib) {
  FreeLibrary(Lib);
}
#else
typedef void * DL_LIB_P;
#endif

void wxe_initOpenGL(wxeReturn rt, char *bp) {
  DL_LIB_P LIBhandle;
  int (*init_opengl)(void *);
#ifdef _WIN32
  void * erlCallbacks = &WinDynDriverCallbacks;
#else
  void * erlCallbacks = NULL;
#endif

  if(erl_gl_initiated == FALSE) {
    if((LIBhandle = dlopen(bp, RTLD_LAZY))) {
      *(void **) (&init_opengl) = dlsym(LIBhandle, "egl_init_opengl");
      wxe_gl_dispatch = (WXE_GL_DISPATCH) dlsym(LIBhandle, "egl_dispatch");
      if(init_opengl && wxe_gl_dispatch) {
	(*init_opengl)(erlCallbacks);
	rt.addAtom((char *) "ok");
	rt.add(wxString::FromAscii("initiated"));
	rt.addTupleCount(2);
	erl_gl_initiated = TRUE;
      } else {
	wxString msg;
	msg.Printf(wxT("In library: "));
	msg += wxString::FromAscii(bp);
	msg += wxT(" functions: ");
	if(!init_opengl)
	  msg += wxT("egl_init_opengl ");
	if(!wxe_gl_dispatch)
	  msg += wxT("egl_dispatch ");
	rt.addAtom((char *) "error");
	rt.add(msg);
	rt.addTupleCount(2);
      }
    } else {
      wxString msg;
      msg.Printf(wxT("Could not load dll: "));
      msg += wxString::FromAscii(bp);
      rt.addAtom((char *) "error");
      rt.add(msg);
      rt.addTupleCount(2);
    }
  } else {
    rt.addAtom((char *) "ok");
    rt.add(wxString::FromAscii("already initilized"));
    rt.addTupleCount(2);
  }
  rt.send();
}

void setActiveGL(ErlDrvTermData caller, wxGLCanvas *canvas)
{
  gl_active = caller;
  glc[caller] = canvas;
}

void deleteActiveGL(wxGLCanvas *canvas)
{
  gl_active = 0;
  wxeGLC::iterator it;
  for(it = glc.begin(); it != glc.end(); ++it) {
    if(it->second == canvas) {
      it->second = (wxGLCanvas *) 0;
    }
  }
}

void gl_dispatch(int op, char *bp,ErlDrvTermData caller,WXEBinRef *bins[]){
  if(caller != gl_active) {
    wxGLCanvas * current = glc[caller];
    if(current) { gl_active = caller; current->SetCurrent();}
    else {
      ErlDrvTermData rt[] = // Error msg
	{ERL_DRV_ATOM, driver_mk_atom((char *) "_egl_error_"),
	 ERL_DRV_INT,  (ErlDrvTermData) op,
	 ERL_DRV_ATOM, driver_mk_atom((char *) "no_gl_context"),
	 ERL_DRV_TUPLE,3};
      erl_drv_send_term(WXE_DRV_PORT,caller,rt,8);
      return ;
    }
  };
  char * bs[3];
  int bs_sz[3];
  for(int i=0; i<3; i++) {
    if(bins[i]) {
      bs[i] = bins[i]->base;
      bs_sz[i] = bins[i]->size;
    }
    else
      bs[i] = NULL;
  }
  wxe_gl_dispatch(op, bp, WXE_DRV_PORT_HANDLE, caller, bs, bs_sz);
}

<commit_msg>wx: Optimize OpenGL invocations<commit_after>/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2008-2014. All Rights Reserved.
 *
 * The contents of this file are subject to the Erlang Public License,
 * Version 1.1, (the "License"); you may not use this file except in
 * compliance with the License. You should have received a copy of the
 * Erlang Public License along with this software. If not, it can be
 * retrieved online at http://www.erlang.org/.
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * %CopyrightEnd%
 */

#include <stdio.h>
#include <string.h>
#ifndef _WIN32
#include <dlfcn.h>
#else
#include <windows.h>
#endif
#include "wxe_impl.h"
#include "wxe_return.h"
#include "wxe_gl.h"

/* ****************************************************************************
 * Opengl context management *
 * ****************************************************************************/

int erl_gl_initiated = FALSE;
ErlDrvTermData gl_active = 0;
wxeGLC glc;

typedef void (*WXE_GL_DISPATCH) (int, char *, ErlDrvPort, ErlDrvTermData, char **, int *);
WXE_GL_DISPATCH wxe_gl_dispatch;

#ifdef _WIN32
#define RTLD_LAZY 0
typedef HMODULE DL_LIB_P;
void * dlsym(HMODULE Lib, const char *func) {
  void * funcp;
  if((funcp = (void *) GetProcAddress(Lib, func)))
    return funcp;
  else
    return (void *) wglGetProcAddress(func);
}

HMODULE dlopen(const char *path, int unused) {
  WCHAR * DLL;
  int len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
  DLL = (WCHAR *) malloc(len * sizeof(WCHAR));
  MultiByteToWideChar(CP_ACP, 0, path, -1, DLL, len);
  HMODULE lib = LoadLibrary(DLL);
  free(DLL);
  return lib;
}

void dlclose(HMODULE Lib) {
  FreeLibrary(Lib);
}
#else
typedef void * DL_LIB_P;
#endif

void wxe_initOpenGL(wxeReturn rt, char *bp) {
  DL_LIB_P LIBhandle;
  int (*init_opengl)(void *);
#ifdef _WIN32
  void * erlCallbacks = &WinDynDriverCallbacks;
#else
  void * erlCallbacks = NULL;
#endif

  if(erl_gl_initiated == FALSE) {
    if((LIBhandle = dlopen(bp, RTLD_LAZY))) {
      *(void **) (&init_opengl) = dlsym(LIBhandle, "egl_init_opengl");
      wxe_gl_dispatch = (WXE_GL_DISPATCH) dlsym(LIBhandle, "egl_dispatch");
      if(init_opengl && wxe_gl_dispatch) {
	(*init_opengl)(erlCallbacks);
	rt.addAtom((char *) "ok");
	rt.add(wxString::FromAscii("initiated"));
	rt.addTupleCount(2);
	erl_gl_initiated = TRUE;
      } else {
	wxString msg;
	msg.Printf(wxT("In library: "));
	msg += wxString::FromAscii(bp);
	msg += wxT(" functions: ");
	if(!init_opengl)
	  msg += wxT("egl_init_opengl ");
	if(!wxe_gl_dispatch)
	  msg += wxT("egl_dispatch ");
	rt.addAtom((char *) "error");
	rt.add(msg);
	rt.addTupleCount(2);
      }
    } else {
      wxString msg;
      msg.Printf(wxT("Could not load dll: "));
      msg += wxString::FromAscii(bp);
      rt.addAtom((char *) "error");
      rt.add(msg);
      rt.addTupleCount(2);
    }
  } else {
    rt.addAtom((char *) "ok");
    rt.add(wxString::FromAscii("already initilized"));
    rt.addTupleCount(2);
  }
  rt.send();
}

void setActiveGL(ErlDrvTermData caller, wxGLCanvas *canvas)
{
  gl_active = caller;
  glc[caller] = canvas;
}

void deleteActiveGL(wxGLCanvas *canvas)
{
  gl_active = 0;
  wxeGLC::iterator it;
  for(it = glc.begin(); it != glc.end(); ++it) {
    if(it->second == canvas) {
      it->second = (wxGLCanvas *) 0;
    }
  }
}

void gl_dispatch(int op, char *bp,ErlDrvTermData caller,WXEBinRef *bins[]){
  if(caller != gl_active) {
    wxGLCanvas * current = glc[caller];
    if(current) {
      if(current != glc[gl_active]) {
	gl_active = caller;
	current->SetCurrent();
      }
    } else {
      ErlDrvTermData rt[] = // Error msg
	{ERL_DRV_ATOM, driver_mk_atom((char *) "_egl_error_"),
	 ERL_DRV_INT,  (ErlDrvTermData) op,
	 ERL_DRV_ATOM, driver_mk_atom((char *) "no_gl_context"),
	 ERL_DRV_TUPLE,3};
      erl_drv_send_term(WXE_DRV_PORT,caller,rt,8);
      return ;
    }
  };
  char * bs[3];
  int bs_sz[3];
  for(int i=0; i<3; i++) {
    if(bins[i]) {
      bs[i] = bins[i]->base;
      bs_sz[i] = bins[i]->size;
    }
    else
      bs[i] = NULL;
  }
  wxe_gl_dispatch(op, bp, WXE_DRV_PORT_HANDLE, caller, bs, bs_sz);
}

<|endoftext|>


<commit_before>/// @file
/// @author uentity
/// @date 30.03.2020
/// @brief BS tree node events handling
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include "node_actor.h"
#include "ev_listener_actor.h"
#include "../serialize/tree_impl.h"

#include <bs/kernel/radio.h>
#include <bs/log.h>
#include <bs/serialize/cafbind.h>
#include <bs/serialize/tree.h>

NAMESPACE_BEGIN(blue_sky::tree)

auto node::subscribe(event_handler f, Event listen_to) const -> std::uint64_t {
	using namespace kernel::radio;
	using namespace allow_enumops;
	using baby_t = ev_listener_actor<node>;

	static const auto handler_impl = [](
		baby_t* self, auto& weak_root, const caf::actor& subn_actor, Event ev, prop::propdict params
	) {
		if(auto r = weak_root.lock()) {
			// reconstruct subnode via node impl
			auto subnode = node::nil();
			if(subn_actor) {
				actorf<sp_nimpl>(subn_actor, kernel::radio::timeout(), a_impl())
				.map([&](const sp_nimpl& subn_impl) { subnode = subn_impl->super_engine(); });
			}
			// invoke callback
			self->f(std::move(r), std::move(subnode), ev, std::move(params));
		}
		else // if root source is dead, quit
			self->quit();
	};

	auto make_ev_character = [weak_root = weak_ptr(*this), listen_to](baby_t* self) {
		auto res = caf::message_handler{};
		if(enumval(listen_to & Event::LinkRenamed)) {
			const auto renamed_impl = [=](
				const caf::actor& subn_actor, auto& lid, auto& new_name, auto& old_name
			) {
				//bsout() << "*-* node: fired LinkRenamed event" << bs_end;
				handler_impl(self, weak_root, subn_actor, Event::LinkRenamed, {
					{"link_id", lid},
					{"new_name", std::move(new_name)},
					{"prev_name", std::move(old_name)}
				});
			};

			// this node leaf was renamed
			res = res.or_else(
				[=] (
					a_ack, const lid_type& lid, a_lnk_rename, std::string new_name, std::string old_name
				) {
					renamed_impl({}, lid, new_name, old_name);
				}
			);
			// deeper subtree leaf was renamed
			res = res.or_else(
				[=] (
					a_ack, const caf::actor& src, const lid_type& lid,
					a_lnk_rename, std::string new_name, std::string old_name
				) {
					renamed_impl(src, lid, new_name, old_name);
				}
			);
			bsout() << "*-* node: subscribed to LinkRenamed event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkStatusChanged)) {
			const auto status_impl = [=](
				const caf::actor& subn_actor, auto& lid, auto req, auto new_s, auto prev_s
			) {
				//bsout() << "*-* node: fired LinkStatusChanged event" << bs_end;
				handler_impl(self, weak_root, subn_actor, Event::LinkStatusChanged, {
					{"link_id", lid},
					{"request", prop::integer(req)},
					{"new_status", prop::integer(new_s)},
					{"prev_status", prop::integer(prev_s)}
				});
			};

			// this node leaf status changed
			res = res.or_else(
				[=](
					a_ack, const lid_type& lid,
					a_lnk_status, Req req, ReqStatus new_s, ReqStatus prev_s
				) {
					status_impl({}, lid, req, new_s, prev_s);
				}
			);
			// deeper subtree leaf status changed
			res = res.or_else(
				[=](
					a_ack, const caf::actor& src, const lid_type& lid,
					a_lnk_status, Req req, ReqStatus new_s, ReqStatus prev_s
				) {
					status_impl(src, lid, req, new_s, prev_s);
				}
			);
			bsout() << "*-* node: subscribed to LinkStatusChanged event" << bs_end;
		}

		if(enumval(listen_to & Event::DataModified)) {
			const auto datamod_impl = [=](
				const caf::actor& subn_actor, auto& lid, tr_result::box&& tres_box
			) {
				//bsout() << "*-* node: fired DataModified event" << bs_end;
				auto params = prop::propdict{{ "link_id", lid }};
				if(auto tres = tr_result{std::move(tres_box)})
					params.merge_props(extract_info(std::move(tres)));
				else
					params["error"] = to_string(extract_err(std::move(tres)));
				handler_impl(self, weak_root, subn_actor, Event::DataModified, std::move(params));
			};

			// this node leaf data changed
			res = res.or_else(
				[=](a_ack, const lid_type& lid, a_data, tr_result::box trbox) {
					datamod_impl({}, lid, std::move(trbox));
				}
			);
			// deeper subtree leaf status changed
			res = res.or_else(
				[=](a_ack, const caf::actor& src, const lid_type& lid, a_data, tr_result::box trbox) {
					datamod_impl(src, lid, std::move(trbox));
				}
			);
			bsout() << "*-* node: subscribed to DataModified event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkInserted)) {
			res = res.or_else(
				// insert
				[=](
					a_ack, const caf::actor& src, a_node_insert,
					const lid_type& lid, std::size_t pos
				) {
					//bsout() << "*-* node: fired LinkInserted event" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkInserted, {
						{"link_id", lid},
						{"pos", (prop::integer)pos}
					});
				},
				// move
				[=](
					a_ack, const caf::actor& src, a_node_insert,
					const lid_type& lid, std::size_t to_idx, std::size_t from_idx
				) {
					//bsout() << "*-* node: fired LinkInserted event (move)" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkInserted, {
						{"link_id", lid},
						{"to_idx", (prop::integer)to_idx},
						{"from_idx", (prop::integer)from_idx}
					});
				}
			);
			bsout() << "*-* node: subscribed to LinkInserted event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkErased)) {
			res = res.or_else(
				[=](
					a_ack, const caf::actor& src, a_node_erase, lids_v lids
				) {
					//bsout() << "*-* node: fired LinkErased event" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkErased, {
						{"lids", std::move(lids)}
					});
				}
			);
			bsout() << "*-* node: subscribed to LinkErased event" << bs_end;
		}

		return res;
	};

	// make shiny new subscriber actor and place into parent's room
	auto baby = system().spawn<baby_t>(raw_actor().address(), std::move(f), std::move(make_ev_character));
	// ensure it has started & properly initialized
	if(auto res = actorf<std::uint64_t>(
		*factor(), pimpl()->actor(*this), infinite, a_subscribe(), std::move(baby)
	))
		return *res;
	else
		throw res.error();
}

auto node::unsubscribe(std::uint64_t event_cb_id) -> void {
	kernel::radio::bye_actor(event_cb_id);
}

NAMESPACE_END(blue_sky::tree)
<commit_msg>tree/node/events: disable debug prints<commit_after>/// @file
/// @author uentity
/// @date 30.03.2020
/// @brief BS tree node events handling
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include "node_actor.h"
#include "ev_listener_actor.h"
#include "../serialize/tree_impl.h"

#include <bs/kernel/radio.h>
#include <bs/log.h>
#include <bs/serialize/cafbind.h>
#include <bs/serialize/tree.h>

NAMESPACE_BEGIN(blue_sky::tree)

auto node::subscribe(event_handler f, Event listen_to) const -> std::uint64_t {
	using namespace kernel::radio;
	using namespace allow_enumops;
	using baby_t = ev_listener_actor<node>;

	static const auto handler_impl = [](
		baby_t* self, auto& weak_root, const caf::actor& subn_actor, Event ev, prop::propdict params
	) {
		if(auto r = weak_root.lock()) {
			// reconstruct subnode via node impl
			auto subnode = node::nil();
			if(subn_actor) {
				actorf<sp_nimpl>(subn_actor, kernel::radio::timeout(), a_impl())
				.map([&](const sp_nimpl& subn_impl) { subnode = subn_impl->super_engine(); });
			}
			// invoke callback
			self->f(std::move(r), std::move(subnode), ev, std::move(params));
		}
		else // if root source is dead, quit
			self->quit();
	};

	auto make_ev_character = [weak_root = weak_ptr(*this), listen_to](baby_t* self) {
		auto res = caf::message_handler{};
		if(enumval(listen_to & Event::LinkRenamed)) {
			const auto renamed_impl = [=](
				const caf::actor& subn_actor, auto& lid, auto& new_name, auto& old_name
			) {
				//bsout() << "*-* node: fired LinkRenamed event" << bs_end;
				handler_impl(self, weak_root, subn_actor, Event::LinkRenamed, {
					{"link_id", lid},
					{"new_name", std::move(new_name)},
					{"prev_name", std::move(old_name)}
				});
			};

			// this node leaf was renamed
			res = res.or_else(
				[=] (
					a_ack, const lid_type& lid, a_lnk_rename, std::string new_name, std::string old_name
				) {
					renamed_impl({}, lid, new_name, old_name);
				}
			);
			// deeper subtree leaf was renamed
			res = res.or_else(
				[=] (
					a_ack, const caf::actor& src, const lid_type& lid,
					a_lnk_rename, std::string new_name, std::string old_name
				) {
					renamed_impl(src, lid, new_name, old_name);
				}
			);
			//bsout() << "*-* node: subscribed to LinkRenamed event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkStatusChanged)) {
			const auto status_impl = [=](
				const caf::actor& subn_actor, auto& lid, auto req, auto new_s, auto prev_s
			) {
				//bsout() << "*-* node: fired LinkStatusChanged event" << bs_end;
				handler_impl(self, weak_root, subn_actor, Event::LinkStatusChanged, {
					{"link_id", lid},
					{"request", prop::integer(req)},
					{"new_status", prop::integer(new_s)},
					{"prev_status", prop::integer(prev_s)}
				});
			};

			// this node leaf status changed
			res = res.or_else(
				[=](
					a_ack, const lid_type& lid,
					a_lnk_status, Req req, ReqStatus new_s, ReqStatus prev_s
				) {
					status_impl({}, lid, req, new_s, prev_s);
				}
			);
			// deeper subtree leaf status changed
			res = res.or_else(
				[=](
					a_ack, const caf::actor& src, const lid_type& lid,
					a_lnk_status, Req req, ReqStatus new_s, ReqStatus prev_s
				) {
					status_impl(src, lid, req, new_s, prev_s);
				}
			);
			//bsout() << "*-* node: subscribed to LinkStatusChanged event" << bs_end;
		}

		if(enumval(listen_to & Event::DataModified)) {
			const auto datamod_impl = [=](
				const caf::actor& subn_actor, auto& lid, tr_result::box&& tres_box
			) {
				//bsout() << "*-* node: fired DataModified event" << bs_end;
				auto params = prop::propdict{{ "link_id", lid }};
				if(auto tres = tr_result{std::move(tres_box)})
					params.merge_props(extract_info(std::move(tres)));
				else
					params["error"] = to_string(extract_err(std::move(tres)));
				handler_impl(self, weak_root, subn_actor, Event::DataModified, std::move(params));
			};

			// this node leaf data changed
			res = res.or_else(
				[=](a_ack, const lid_type& lid, a_data, tr_result::box trbox) {
					datamod_impl({}, lid, std::move(trbox));
				}
			);
			// deeper subtree leaf status changed
			res = res.or_else(
				[=](a_ack, const caf::actor& src, const lid_type& lid, a_data, tr_result::box trbox) {
					datamod_impl(src, lid, std::move(trbox));
				}
			);
			//bsout() << "*-* node: subscribed to DataModified event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkInserted)) {
			res = res.or_else(
				// insert
				[=](
					a_ack, const caf::actor& src, a_node_insert,
					const lid_type& lid, std::size_t pos
				) {
					//bsout() << "*-* node: fired LinkInserted event" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkInserted, {
						{"link_id", lid},
						{"pos", (prop::integer)pos}
					});
				},
				// move
				[=](
					a_ack, const caf::actor& src, a_node_insert,
					const lid_type& lid, std::size_t to_idx, std::size_t from_idx
				) {
					//bsout() << "*-* node: fired LinkInserted event (move)" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkInserted, {
						{"link_id", lid},
						{"to_idx", (prop::integer)to_idx},
						{"from_idx", (prop::integer)from_idx}
					});
				}
			);
			//bsout() << "*-* node: subscribed to LinkInserted event" << bs_end;
		}

		if(enumval(listen_to & Event::LinkErased)) {
			res = res.or_else(
				[=](
					a_ack, const caf::actor& src, a_node_erase, lids_v lids
				) {
					//bsout() << "*-* node: fired LinkErased event" << bs_end;
					handler_impl(self, weak_root, src, Event::LinkErased, {
						{"lids", std::move(lids)}
					});
				}
			);
			//bsout() << "*-* node: subscribed to LinkErased event" << bs_end;
		}

		return res;
	};

	// make shiny new subscriber actor and place into parent's room
	auto baby = system().spawn<baby_t>(raw_actor().address(), std::move(f), std::move(make_ev_character));
	// ensure it has started & properly initialized
	if(auto res = actorf<std::uint64_t>(
		*factor(), pimpl()->actor(*this), infinite, a_subscribe(), std::move(baby)
	))
		return *res;
	else
		throw res.error();
}

auto node::unsubscribe(std::uint64_t event_cb_id) -> void {
	kernel::radio::bye_actor(event_cb_id);
}

NAMESPACE_END(blue_sky::tree)
<|endoftext|>


<commit_before>#ifndef QPROJECTM_CONFIG_DIALOG_HPP
#include "ui_QProjectMConfigDialog.h"
#include "QProjectM_MainWindow.hpp"

class QProjectMConfigDialog : public QDialog {

	Q_OBJECT

	public:
		QProjectMConfigDialog(const std::string & configFile, QProjectMWidget * widget, QWidget * parent = 0, Qt::WindowFlags f = 0);
	private:
		void loadConfig();

	private slots:
		void saveConfig();
		void buttonBoxHandler(QAbstractButton * button);

	private:
		 const std::string _configFile;
		 QProjectMWidget * _qprojectMWidget;
		 Ui::QProjectMConfigDialog _ui;
		 void populateTextureSizeComboBox();
	signals:
		void projectM_Reset();
};
#endif
<commit_msg>fixed ifndef header include bug in config dialog hpp<commit_after>#ifndef QPROJECTM_CONFIG_DIALOG_HPP
#define QPROJECTM_CONFIG_DIALOG_HPP
#include "ui_QProjectMConfigDialog.h"
#include "QProjectM_MainWindow.hpp"

class QProjectMConfigDialog : public QDialog {

	Q_OBJECT

	public:
		QProjectMConfigDialog(const std::string & configFile, QProjectMWidget * widget, QWidget * parent = 0, Qt::WindowFlags f = 0);
	private:
		void loadConfig();

	private slots:
		void saveConfig();
		void buttonBoxHandler(QAbstractButton * button);

	private:
		 const std::string _configFile;
		 QProjectMWidget * _qprojectMWidget;
		 Ui::QProjectMConfigDialog _ui;
		 void populateTextureSizeComboBox();
	signals:
		void projectM_Reset();
};
#endif
<|endoftext|>