text:
/*
 * GridTools
 *
 * Copyright (c) 2014-2019, ETH Zurich
 * All rights reserved.
 *
 * Please, refer to the LICENSE file in the root directory.
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */
#ifndef INCLUDED_GHEX_TL_CALLBACK_COMMUNICATOR_HPP
#define INCLUDED_GHEX_TL_CALLBACK_COMMUNICATOR_HPP

#include <deque>
#include <vector>
#include <algorithm>
#include <memory>
#include <type_traits>
#include <tuple>
#include <boost/callable_traits.hpp>
#include <boost/optional.hpp>
#include "./shared_message_buffer.hpp"

/** @brief checks the arguments of callback function object */
#define GHEX_CHECK_CALLBACK                                                                   \
    using args_t = boost::callable_traits::args_t<CallBack>;                                  \
    using arg0_t = std::tuple_element_t<0, args_t>;                                           \
    using arg1_t = std::tuple_element_t<1, args_t>;                                           \
    using arg2_t = std::tuple_element_t<2, args_t>;                                           \
    static_assert(std::tuple_size<args_t>::value==3,                                          \
        "callback must have 3 arguments");                                                    \
    static_assert(std::is_convertible<arg1_t,rank_type>::value,                               \
        "rank_type is not convertible to second callback argument type");                     \
    static_assert(std::is_convertible<arg2_t,tag_type>::value,                                \
        "tag_type is not convertible to third callback argument type");                       \
    static_assert(std::is_convertible<arg0_t,typename element_type::message_arg_type>::value, \
        "first callback argument type is not a message_type");

namespace gridtools
{
    namespace ghex
    {
        namespace tl {

            /** callback_communicator is a class to dispatch send and receive operations to. Each operation can
              * optionally be tied to a user defined callback function / function object. The payload of each
              * send/receive operation must be a ghex::shared_message_buffer<Allocator>.
              * This class will keep a (shallow) copy of each message, thus it is safe to release the message at
              * the caller's site.
              *
              * The user defined callback must define void operator()(message_type,rank_type,tag_type), where
              * message_type is a shared_message_buffer that can be cheaply copied/moved from within the callback body
              * if needed.
              *
              * The communication must be explicitely progressed using the member function progress.
              *
              * An instance of this class is
              * - a move-only.
              * - not thread-safe
              *
              * If unprogressed operations remain at time of destruction, std::terminate will be called.
              *
              * @tparam Communicator underlying transport communicator
              * @tparam Allocator    allocator type used for allocating shared message buffers */
            template<class Communicator, class Allocator = std::allocator<unsigned char>>
            class callback_communicator
            {
            public: // member types

                using communicator_type = Communicator;
                using future_type       = typename communicator_type::template future<void>;
                using tag_type          = typename communicator_type::tag_type;
                using rank_type         = typename communicator_type::rank_type;
                using allocator_type    = Allocator;
                using message_type      = shared_message_buffer<allocator_type>;

            private: // member types

                // necessary meta information for each send/receive operation
                struct element_type
                {
                    using message_arg_type = message_type;
                    std::function<void(message_arg_type, rank_type, tag_type)> m_cb;
                    rank_type    m_rank;
                    tag_type     m_tag;
                    future_type  m_future;
                    message_type m_msg;
                };
                using send_element_type   = element_type;
                using recv_element_type   = element_type;
                //using send_container_type = std::deque<send_element_type>;
                //using recv_container_type = std::deque<recv_element_type>;
                using send_container_type = std::vector<send_element_type>;
                using recv_container_type = std::vector<recv_element_type>;

            private: // members

                communicator_type   m_comm;
                allocator_type      m_alloc;
                send_container_type m_sends;
                recv_container_type m_recvs;

            public: // ctors

                /** @brief construct from a basic transport communicator
                  * @param comm  the underlying transport communicator
                  * @param alloc the allocator instance to be used for constructing messages */
                callback_communicator(const communicator_type& comm, allocator_type alloc = allocator_type{})
                : m_comm(comm), m_alloc(alloc)
                {
                    m_sends.reserve(128);
                    m_recvs.reserve(128);
                }

                callback_communicator(communicator_type&& comm, allocator_type alloc = allocator_type{})
                : m_comm(std::move(comm)), m_alloc(alloc)
                {
                    m_sends.reserve(128);
                    m_recvs.reserve(128);
                }

                callback_communicator(allocator_type alloc = allocator_type{})
                : m_comm{typename communicator_type::traits{}}, m_alloc(alloc)
                {
                    m_sends.reserve(128);
                    m_recvs.reserve(128);
                }

                callback_communicator(const callback_communicator&) = delete;
                callback_communicator(callback_communicator&&) = default;

                /** terminates the program if the queues are not empty */
                ~callback_communicator()
                {
                    //if (m_sends.size() != 0 || m_recvs.size() != 0)
                    //{
                    //    std::terminate();
                    //}
                }

            public: // synchronization

                void barrier() { m_comm.barrier(); }
                void flush() { }

            public: // queries

                auto rank() const noexcept { return m_comm.rank(); }
                auto size() const noexcept { return m_comm.size(); }

                /** returns the number of unprocessed send handles in the queue. */
                std::size_t pending_sends() const { return m_sends.size(); }
                /** returns the number of unprocessed recv handles in the queue. */
                std::size_t pending_recvs() const { return m_recvs.size(); }

            public: // get a message

                /** get a message with size n from the communicator */
                message_type make_message(std::size_t n = 0u) const
                {
                    return { m_alloc, n };
                }

            public: // send

                /** @brief Send a message to a destination with the given tag and register a callback which will be
                  * invoked when the send operation is completed.
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(message_type,rank_type,tag_type)
                  * @param msg Message to be sent
                  * @param dst Destination of the message
                  * @param tag Tag associated with the message
                  * @param cb  Callback function object */
                template<typename CallBack>
                void send(const message_type& msg, rank_type dst, tag_type tag, CallBack&& cb)
                {
                    GHEX_CHECK_CALLBACK
                    auto& element =
                        *m_sends.insert(
                            m_sends.end(),
                            send_element_type{std::forward<CallBack>(cb), dst, tag, future_type{}, msg});
                    element.m_future = std::move( m_comm.send(element.m_msg, dst, tag) );
                }

                /** @brief Send a message without registering a callback. */
                void send(const message_type& msg, rank_type dst, tag_type tag)
                {
                    send(msg,dst,tag,[](message_type,rank_type,tag_type){});
                }

                /** @brief Send a message to multiple destinations with the same rank an register an associated callback.
                  * @tparam Neighs Range over rank_type
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(rank_type,tag_type,message_type)
                  * @param msg Message to be sent
                  * @param neighs Range of destination ranks
                  * @param tag Tag associated with the message
                  * @param cb Callback function object */
                template <typename Neighs, typename CallBack>
                void send_multi(const message_type& msg, Neighs const &neighs, int tag, CallBack&& cb)
                {
                    GHEX_CHECK_CALLBACK
                    using cb_type = typename std::remove_cv<typename std::remove_reference<CallBack>::type>::type;
                    auto cb_ptr = std::make_shared<cb_type>( std::forward<CallBack>(cb) );
                    for (auto id : neighs)
                        send(msg, id, tag,
                                [cb_ptr](message_type m, rank_type r, tag_type t)
                                {
                                    // if (cb_ptr->use_count == 1)
                                    (*cb_ptr)(std::move(m),r,t);
                                });
                }

                /** @brief Send a message to multiple destinations without registering a callback */
                template <typename Neighs>
                void send_multi(const message_type& msg, Neighs const &neighs, int tag)
                {
                    send_multi(msg,neighs,tag,[](message_type, rank_type,tag_type){});
                }

            public: // recieve

                /** @brief Receive a message from a source rank with the given tag and register a callback which will
                  * be invoked when the receive operation is completed.
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(message_type,rank_type,tag_type)
                  * @param msg Message where data will be received
                  * @param src Source of the message
                  * @param tag Tag associated with the message
                  * @param cb  Callback function object */
                template<typename CallBack>
                void recv(message_type& msg, rank_type src, tag_type tag, CallBack&& cb)
                {
                    GHEX_CHECK_CALLBACK
                    auto& element = *m_recvs.insert(m_recvs.end(), recv_element_type{std::forward<CallBack>(cb), src, tag,
                                                                                future_type{}, msg});
                    element.m_future = std::move( m_comm.recv(element.m_msg, src, tag) );
                }

                /** @brief Receive a message with length size (storage is allocated accordingly). */
                template<typename CallBack>
                void recv(std::size_t size, rank_type src, tag_type tag, CallBack&& cb)
                {
                    recv(message_type{size,m_alloc}, src, tag, std::forward<CallBack>(cb));
                }

                /** @brief Receive a message without registering a callback. */
                void recv(message_type& msg, rank_type src, tag_type tag)
                {
                    recv(msg,src,tag,[](message_type,rank_type,tag_type){});
                }

            public: // progress

                /** @brief Progress the communication. This function checks whether any receive and send operation is
                  * completed and calls the associated callback (if it exists).
                  * @return returns false if all registered operations have been completed.*/
                bool progress()
                {
                    const auto sends_completed = run(m_sends);
                    const auto recvs_completed = run(m_recvs);
                    const auto completed = sends_completed && recvs_completed;
                    return !completed;
                }

                /** @brief Progress the communication. This function checks whether any receive and send operation is
                  * completed and calls the associated callback (if it exists). When all registered operations have
                  * been completed this function checks for further unexpected incoming messages which will be received
                  * in a newly allocated shared_message_buffer and returned to the user through invocation of the
                  * provided callback.
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(message_type,rank_type,tag_type)
                  * @param unexpected_cb callback function object
                  * @return returns false if all registered operations have been completed. */
                template<typename CallBack>
                bool progress(CallBack&& unexpected_cb)
                {
                    GHEX_CHECK_CALLBACK
                    const auto not_completed = progress();
                    if (!not_completed)
                    {
                        if (auto o = m_comm.template recv_any_source_any_tag<message_type>(m_alloc))
                        {
                            auto t = o->get();
                            unexpected_cb(std::move(std::get<0>(t)),std::get<1>(t),std::get<2>(t));
                        }
                    }
                    return not_completed;
                }

            public: // attach/detach

                /** @brief Deregister a send operation from this object which matches the given destination and tag.
                  * If such operation is found the callback will be discared and the message will be returned to the
                  * caller together with a future on which completion can be awaited.
                  * @param dst Destination of the message
                  * @param tag Tag associated with the message
                  * @return Either a pair of future and message or none */
                boost::optional<std::pair<future_type,message_type>> detach_send(rank_type dst, tag_type tag)
                {
                    return detach(dst,tag,m_sends);
                }

                /** @brief Deregister a receive operation from this object which matches the given destination and tag.
                  * If such operation is found the callback will be discared and the message will be returned to the
                  * caller together with a future on which completion can be awaited.
                  * @param src Source of the message
                  * @param tag Tag associated with the message
                  * @return Either a pair of future and message or none */
                boost::optional<std::pair<future_type,message_type>> detach_recv(rank_type src, tag_type tag)
                {
                    return detach(src,tag,m_recvs);
                }

                /** @brief Register a send operation with this object with future, destination and tag and associate it
                  * with a callback. This is the inverse operation of detach. Note, that attaching of a send operation
                  * originating from the underlying basic communicator is supported.
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(message_type,rank_type,tag_type)
                  * @param fut future object
                  * @param msg message data
                  * @param dst destination rank
                  * @param tag associated tag
                  * @param cb  Callback function object */
                template<typename CallBack>
                void attach_send(future_type&& fut, message_type msg, rank_type dst, tag_type tag, CallBack&& cb)
                {
                    GHEX_CHECK_CALLBACK
                    m_sends.push_back( send_element_type{ std::forward<CallBack>(cb), dst, tag, std::move(fut), std::move(msg) } );
                }

                /** @brief Register a send without associated callback. */
                void attach_send(future_type&& fut, message_type msg, rank_type dst, tag_type tag)
                {
                    m_sends.push_back( recv_element_type{ [](message_type,rank_type,tag_type){}, dst, tag, std::move(fut), std::move(msg) } );
                }

                /** @brief Register a receive operation with this object with future, source and tag and associate it
                  * with a callback. This is the inverse operation of detach. Note, that attaching of a recv operation
                  * originating from the underlying basic communicator is supported.
                  * @tparam CallBack User defined callback class which defines
                  *                  void Callback::operator()(message_type,rank_type,tag_type)
                  * @param fut future object
                  * @param msg message data
                  * @param dst source rank
                  * @param tag associated tag
                  * @param cb  Callback function object */
                template<typename CallBack>
                void attach_recv(future_type&& fut, message_type msg, rank_type src, tag_type tag, CallBack&& cb)
                {
                    GHEX_CHECK_CALLBACK
                    m_recvs.push_back( send_element_type{ std::forward<CallBack>(cb), src, tag, std::move(fut), std::move(msg) } );
                }

                /** @brief Register a receive without associated callback. */
                void attach_recv(future_type&& fut, message_type msg, rank_type src, tag_type tag)
                {
                    m_recvs.push_back( send_element_type{ [](message_type,rank_type,tag_type){}, src, tag, std::move(fut), std::move(msg) } );
                }

            public: // cancel

                /** @brief Deregister all operations from this object and attempt to cancel the communication.
                  * @return true if cancelling was successful. */
                bool cancel()
                {
                    const auto s = cancel_sends();
                    const auto r = cancel_recvs();
                    return s && r;
                }

                /** @brief Deregister all send operations from this object and attempt to cancel the communication.
                  * @return true if cancelling was successful. */
                bool cancel_sends() { return cancel(m_sends); }

                /** @brief Deregister all recv operations from this object and attempt to cancel the communication.
                  * @return true if cancelling was successful. */
                bool cancel_recvs() { return cancel(m_recvs); }

            private: // implementation

                template<typename Deque>
                bool run(Deque& d)
                {
                    /*const unsigned int size = d.size();
                    for (unsigned int i=0; i<size; ++i)
                    {
                        auto element = std::move(d.front());
                        d.pop_front();

                        if (element.m_future.ready())
                        {
                            //element.m_future.wait();
                            element.m_cb(std::move(element.m_msg), element.m_rank, element.m_tag);
                            //break;
                        }
                        else
                        {
                            d.push_back(std::move(element));
                        }
                    }
                    return (d.size()==0u);
                    */
                    for (unsigned int i=0; i<d.size(); ++i)
                    {
                        auto& element = d[i];
                        if (element.m_future.ready())
                        {
                            element.m_cb(std::move(element.m_msg), element.m_rank, element.m_tag);
                            if (i+1 < d.size())
                            {
                                element = std::move(d.back());
                                --i;
                            }
                            d.resize(d.size()-1);
                        }
                    }
                    return (d.size()==0u);
                }

                template<typename Deque>
                boost::optional<std::pair<future_type,message_type>> detach(rank_type rank, tag_type tag, Deque& d)
                {
                    auto it = std::find_if(d.begin(), d.end(),
                        [rank, tag](auto const& x)
                        {
                            return (x.m_rank == rank && x.m_tag == tag);
                        });
                    if (it != d.end())
                    {
                        //auto cb =  std::move(it->m_cb);
                        auto fut = std::move(it->m_future);
                        auto msg = std::move(it->m_msg);
                        //d.erase(it);
                        if (it+1 != d.end())
                        {
                            *it = std::move(d.back());
                        }
                        d.resize(d.size()-1);
                        return std::pair<future_type,message_type>{std::move(fut), std::move(msg)};
                    }
                    return boost::none;
                }

                template<typename Deque>
                bool cancel(Deque& d)
                {
                    bool result = true;
                    const unsigned int size = d.size();
                    for (unsigned int i=0; i<size; ++i)
                    {
                        //auto element = std::move(d.front());
                        //d.pop_front();
                        auto& element = d[i];
                        auto& fut = element.m_future;
                        if (!fut.ready())
                            result = result && fut.cancel();
                        //else
                        //    fut.wait();
                    }
                    d.resize(0);
                    return result;
                }
            };

        } // namespace tl
    } // namespace ghex
}// namespace gridtools

#endif /* INCLUDED_GHEX_TL_CALLBACK_COMMUNICATOR_HPP */

max_stars_repo_name: boeschf/GHEX-OLD

max_issues_repo_name: boeschf/GHEX-OLD

max_forks_repo_name: boeschf/GHEX-OLD


text:
#include "schedule_params.h"
#include "../configuration.h"
#include <boost/container/flat_set.hpp>
#include <range/v3/action/insert.hpp>
#include <range/v3/range/operations.hpp>
#include <range/v3/to_container.hpp>
#include <range/v3/view/enumerate.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/transform.hpp>

namespace {
using namespace angonoka;

using stun::ScheduleParams;
using AgentPerformance = decltype(ScheduleParams::agent_performance);
using TaskDuration = decltype(ScheduleParams::task_duration);
using AvailableAgents = decltype(ScheduleParams::available_agents);
using Dependencies = decltype(ScheduleParams::dependencies);

using ranges::to;
using ranges::actions::insert;
using ranges::views::enumerate;
using ranges::views::transform;

/**
    Construct the packed agent performance map from an array of
    Agents.

    @param agents Array of Agents

    @return Agent performance map
*/
AgentPerformance agent_performance(const Agents& agents)
{
    Expects(!agents.empty());

    return agents
        | transform([](auto&& a) { return a.performance.average(); })
        | to<AgentPerformance>();
}

/**
    Construct the packed task duration map from an array of tasks.

    Task durations are normalized to bring the ideal makespan closer
    to 1.

    @param tasks        Array of Tasks
    @param agent_count  Total number of agents

    @return Task duration map and a duration multiplier
*/
std::tuple<TaskDuration, float>
task_duration(const Tasks& tasks, int agent_count)
{
    Expects(!tasks.empty());
    Expects(agent_count > 0);

    TaskDuration durations;
    durations.reserve(tasks.size());
    float total{0.F};
    for (auto&& t : tasks) {
        durations.emplace_back(t.duration.average().count());
        total += durations.back();
    }
    durations.shrink_to_fit();

    // Average duration *per agent*, assuming every agent has the
    // performance of 1.0 and all tasks can be evenly distributed.
    const auto average_duration
        = total / static_cast<float>(agent_count);
    for (auto& d : durations) d /= average_duration;

    Ensures(durations.size() == tasks.size());

    return {std::move(durations), average_duration};
}

/**
    Construct the packed available agents map from Configuration.

    @param config High-level configuration

    @return Available agents map
*/
AvailableAgents available_agents(const Configuration& config)
{
    using stun::int16;

    Expects(!config.tasks.empty());
    Expects(!config.agents.empty());

    std::vector<int16> data;
    std::vector<int16> sizes;

    for (auto&& task : config.tasks) {
        int16 agent_count{0};
        for (auto&& [agent_index, agent] : enumerate(config.agents)) {
            if (!can_work_on(agent, task)) continue;
            ++agent_count;
            data.emplace_back(agent_index);
        }
        sizes.emplace_back(agent_count);
    }
    data.shrink_to_fit();

    Ensures(sizes.size() == config.tasks.size());

    return {std::move(data), sizes};
}

/**
    Construct the packed dependency map from Tasks.

    @param tasks Array of Tasks

    @return Dependency map.
*/
Dependencies dependencies(const Tasks& tasks)
{
    using stun::int16;

    Expects(!tasks.empty());

    std::vector<int16> data;
    std::vector<int16> sizes;

    for (auto&& task : tasks) {
        insert(data, data.end(), task.dependencies);
        sizes.emplace_back(task.dependencies.size());
    }
    data.shrink_to_fit();

    Ensures(sizes.size() == tasks.size());

    return {std::move(data), sizes};
}
} // namespace

namespace angonoka::stun {
using boost::container::flat_set;

Vector2D::Vector2D(
    std::vector<int16>&& data,
    std::vector<span<int16>>&& spans) noexcept
    : data{std::move(data)}
    , spans{std::move(spans)}
{
}

void Vector2D::clear() noexcept
{
    data.clear();
    spans.clear();
}

Vector2D::Vector2D() noexcept = default;
Vector2D::Vector2D(const Vector2D& other)
{
    if (other.empty()) return;
    data = other.data;
    spans = other.spans;
    if (data.empty()) return;
    const auto* const front_ptr = other.data.data();
    for (auto& s : spans) {
        if (s.empty()) continue;
        const auto* const p = s.data();
        const auto d = std::distance(front_ptr, p);
        s = {std::next(data.data(), d), s.size()};
    }

    Ensures(other.size() == size());
}

Vector2D::Vector2D(
    std::vector<int16>&& data,
    span<const int16> sizes) noexcept
    : data{std::move(data)}
{
    if (sizes.empty()) return;
    auto* head = this->data.data();
    for (auto&& size : sizes) {
        spans.emplace_back(
            std::exchange(head, std::next(head, size)),
            size);
    }

    Ensures(std::ssize(spans) == sizes.size());
}

[[nodiscard]] std::size_t Vector2D::size() const noexcept
{
    return spans.size();
}

[[nodiscard]] bool Vector2D::empty() const noexcept
{
    return spans.empty();
}

Vector2D& Vector2D::operator=(const Vector2D& other)
{
    *this = Vector2D{other};
    return *this;
}

Vector2D::Vector2D(Vector2D&& other) noexcept = default;
Vector2D& Vector2D::operator=(Vector2D&& other) noexcept
{
    if (&other == this) return *this;
    data = std::move(other.data);
    spans = std::move(other.spans);
    return *this;
}
Vector2D::~Vector2D() noexcept = default;

/**
    Walks the dependency tree recursively.

    As we construct the initial (naive) schedule we have to make sure
    that we don't schedule tasks before their dependencies. This
    function schedules task dependencies before their dependants,
    recursively.

    @param schedule     Partially formed schedule
    @param tasks        Set of unexplored tasks
    @param task_index   Index of the current task
    @param params       An instance of ScheduleParams
*/
void push_task(
    std::vector<ScheduleItem>& schedule,
    flat_set<int16>& tasks,
    int16 task_index,
    const ScheduleParams& params)
{
    Expects(!tasks.empty());
    Expects(
        tasks.size() + schedule.size()
        == params.task_duration.size());

    if (!tasks.contains(task_index)) return;
    const auto idx = static_cast<std::size_t>(task_index);
    for (auto&& dep_index : params.dependencies[idx])
        push_task(schedule, tasks, dep_index, params);
    schedule.emplace_back(ScheduleItem{
        .task_id = task_index,
        .agent_id = params.available_agents[idx][0]});
    tasks.erase(task_index);

    Ensures(
        tasks.size() + schedule.size()
        == params.task_duration.size());
}

std::vector<ScheduleItem>
initial_schedule(const ScheduleParams& params)
{
    using ranges::front;
    using ranges::views::iota;

    Expects(!params.task_duration.empty());

    std::vector<ScheduleItem> schedule;
    schedule.reserve(params.task_duration.size());
    auto tasks = iota(0L, std::ssize(params.task_duration))
        | ranges::to<flat_set<int16>>();
    while (!tasks.empty())
        push_task(schedule, tasks, front(tasks), params);

    Ensures(schedule.size() == params.task_duration.size());

    return schedule;
}

ScheduleParams to_schedule_params(const Configuration& config)
{
    Expects(!config.agents.empty());
    Expects(!config.tasks.empty());

    auto&& [task_duration_, duration_multiplier] = task_duration(
        config.tasks,
        static_cast<int>(config.agents.size()));
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wbraced-scalar-init"
    return {
        .agent_performance{agent_performance(config.agents)},
        .task_duration{std::move(task_duration_)},
        .available_agents{available_agents(config)},
        .dependencies{dependencies(config.tasks)},
        .duration_multiplier{duration_multiplier}};
#pragma clang diagnostic pop
}
} // namespace angonoka::stun

ext: cpp

max_stars_repo_name: coffee-lord/angonoka

max_issues_repo_name: coffee-lord/angonoka

max_forks_repo_name: coffee-lord/angonoka


text:
/// @file position.hpp
#pragma once

#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <cmath>
#include <iosfwd>
#include "adm/elements/position_types.hpp"
#include "adm/elements/screen_edge_lock.hpp"
#include "adm/detail/type_traits.hpp"
#include "adm/export.h"
#ifndef M_PI
#define M_PI 3.14159265359f
#endif

namespace adm {

  /// @brief Tag for SphericalPosition class
  struct SphericalPositionTag {};
  /**
   * @brief ADM parameter class to specify a spherical position
   */
  class SphericalPosition {
   public:
    typedef SphericalPositionTag tag;

    /// @brief Constructor without optional parameters
    ADM_EXPORT SphericalPosition(Azimuth azimuth = Azimuth(0.f),
                                 Elevation elevation = Elevation(0.f));
    /**
     * @brief Constructor template
     *
     * Templated constructor which accepts a variable number of ADM parameters
     * in random order after the mandatory ADM parameters.
     */
    template <typename... Parameters>
    SphericalPosition(Azimuth azimuth, Elevation elevation,
                      Parameters... optionalNamedArgs);

    /**
     * @brief ADM parameter getter template
     *
     * Templated getter with the wanted ADM parameter type as template
     * argument. If currently no value is available trying to get the adm
     * parameter will result in an exception. Check with the has method before
     */
    template <typename Parameter>
    Parameter get() const;

    /**
     * @brief ADM parameter has template
     *
     * Templated has method with the ADM parameter type as template argument.
     * Returns true if the ADM parameter is set or has a default value.
     */
    template <typename Parameter>
    bool has() const;

    /**
     * @brief ADM parameter isDefault template
     *
     * Templated isDefault method with the ADM parameter type as template
     * argument. Returns true if the ADM parameter is the default value.
     */
    template <typename Parameter>
    bool isDefault() const;

    /// @brief Azimuth setter
    ADM_EXPORT void set(Azimuth azimuth);
    /// @brief Elevation setter
    ADM_EXPORT void set(Elevation elevation);
    /// @brief Distance setter
    ADM_EXPORT void set(Distance distance);
    /// @brief ScreenEdgeLock setter
    ADM_EXPORT void set(ScreenEdgeLock screenEdgeLock);

    /**
     * @brief ADM parameter unset template
     *
     * Templated unset method with the ADM parameter type as template
     * argument. Removes an ADM parameter if it is optional or resets it to
     * the default value if there is one.
     */
    template <typename Parameter>
    void unset();

    /**
     * @brief Print overview to ostream
     */
    void print(std::ostream& os) const;

   private:
    ADM_EXPORT Azimuth get(detail::ParameterTraits<Azimuth>::tag) const;
    ADM_EXPORT Elevation get(detail::ParameterTraits<Elevation>::tag) const;
    ADM_EXPORT Distance get(detail::ParameterTraits<Distance>::tag) const;
    ADM_EXPORT ScreenEdgeLock
        get(detail::ParameterTraits<ScreenEdgeLock>::tag) const;

    ADM_EXPORT bool has(detail::ParameterTraits<Azimuth>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<Elevation>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<Distance>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<ScreenEdgeLock>::tag) const;

    template <typename Tag>
    bool isDefault(Tag) const {
      return false;
    }
    ADM_EXPORT bool isDefault(detail::ParameterTraits<Distance>::tag) const;

    ADM_EXPORT void unset(detail::ParameterTraits<Distance>::tag);
    ADM_EXPORT void unset(detail::ParameterTraits<ScreenEdgeLock>::tag);

    Azimuth azimuth_;
    Elevation elevation_;
    boost::optional<Distance> distance_;
    boost::optional<ScreenEdgeLock> screenEdgeLock_;

    static const Distance distanceDefault_;
  };

  /// @brief Tag for CartesianPosition class
  struct CartesianPositionTag {};
  /// @brief ADM parameter class to specify a cartesian position
  class CartesianPosition {
   public:
    typedef CartesianPositionTag tag;

    /// @brief Constructor without optional parameters
    ADM_EXPORT CartesianPosition(X x = X(0.f), Y y = Y(1.f));

    /**
     * @brief Constructor template
     *
     * Templated constructor which accepts a variable number of ADM parameters
     * in random order after the mandatory ADM parameters.
     */
    template <typename... Parameters>
    CartesianPosition(X x, Y y, Parameters... optionalNamedArgs);

    /**
     * @brief ADM parameter getter template
     *
     * Templated getter with the wanted ADM parameter type as template
     * argument. If currently no value is available trying to get the adm
     * parameter will result in an exception. Check with the has method before
     */
    template <typename Parameter>
    Parameter get() const;

    /**
     * @brief ADM parameter has template
     *
     * Templated has method with the ADM parameter type as template argument.
     * Returns true if the ADM parameter is set or has a default value.
     */
    template <typename Parameter>
    bool has() const;

    /**
     * @brief ADM parameter isDefault template
     *
     * Templated isDefault method with the ADM parameter type as template
     * argument. Returns true if the ADM parameter is the default value.
     */
    template <typename Parameter>
    bool isDefault() const;

    /// @brief X setter
    ADM_EXPORT void set(X x);
    /// @brief Y setter
    ADM_EXPORT void set(Y y);
    /// @brief Z setter
    ADM_EXPORT void set(Z z);
    /// @brief ScreenEdgeLock setter
    ADM_EXPORT void set(ScreenEdgeLock screenEdgeLock);

    /**
     * @brief ADM parameter unset template
     *
     * Templated unset method with the ADM parameter type as template
     * argument. Removes an ADM parameter if it is optional or resets it to
     * the default value if there is one.
     */
    template <typename Parameter>
    void unset();

    /**
     * @brief Print overview to ostream
     */
    void print(std::ostream& os) const;

   private:
    ADM_EXPORT X get(detail::ParameterTraits<X>::tag) const;
    ADM_EXPORT Y get(detail::ParameterTraits<Y>::tag) const;
    ADM_EXPORT Z get(detail::ParameterTraits<Z>::tag) const;
    ADM_EXPORT ScreenEdgeLock
        get(detail::ParameterTraits<ScreenEdgeLock>::tag) const;

    ADM_EXPORT bool has(detail::ParameterTraits<X>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<Y>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<Z>::tag) const;
    ADM_EXPORT bool has(detail::ParameterTraits<ScreenEdgeLock>::tag) const;

    template <typename Tag>
    bool isDefault(Tag) const {
      return false;
    }
    ADM_EXPORT bool isDefault(detail::ParameterTraits<Z>::tag) const;

    ADM_EXPORT void unset(detail::ParameterTraits<Z>::tag);
    ADM_EXPORT void unset(detail::ParameterTraits<ScreenEdgeLock>::tag);

    X x_;
    Y y_;
    boost::optional<Z> z_;
    boost::optional<ScreenEdgeLock> screenEdgeLock_;

    static const Z zDefault_;
  };

  ///@brief Type to hold a SphericalPosition or CartesianPosition
  typedef boost::variant<SphericalPosition, CartesianPosition> Position;
  ADD_TRAIT(Position, PositionTag);

  // ---- Free functions ---- //

  /// @brief Helper function to check if a ::Position is spherical
  ADM_EXPORT bool isSpherical(const Position& position);
  /// @brief Helper function to check if a ::Position is cartesian
  ADM_EXPORT bool isCartesian(const Position& position);

  // ---- Implementation ---- //

  template <typename... Parameters>
  SphericalPosition::SphericalPosition(Azimuth azimuth, Elevation elevation,
                                       Parameters... optionalNamedArgs)
      : azimuth_(azimuth), elevation_(elevation) {
    detail::setNamedOptionHelper(
        this, std::forward<Parameters>(optionalNamedArgs)...);
  }

  template <typename Parameter>
  Parameter SphericalPosition::get() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return get(Tag());
  }

  template <typename Parameter>
  bool SphericalPosition::has() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return has(Tag());
  }

  template <typename Parameter>
  bool SphericalPosition::isDefault() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return isDefault(Tag());
  }

  template <typename Parameter>
  void SphericalPosition::unset() {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return unset(Tag());
  }

  template <typename... Parameters>
  CartesianPosition::CartesianPosition(X x, Y y,
                                       Parameters... optionalNamedArgs)
      : x_(x), y_(y) {
    detail::setNamedOptionHelper(
        this, std::forward<Parameters>(optionalNamedArgs)...);
  }

  template <typename Parameter>
  Parameter CartesianPosition::get() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return get(Tag());
  }

  template <typename Parameter>
  bool CartesianPosition::has() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return has(Tag());
  }

  template <typename Parameter>
  bool CartesianPosition::isDefault() const {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return isDefault(Tag());
  }

  template <typename Parameter>
  void CartesianPosition::unset() {
    typedef typename detail::ParameterTraits<Parameter>::tag Tag;
    return unset(Tag());
  }

}  // namespace adm

ext: hpp

max_stars_repo_name: rsjtaylor/libadm

max_issues_repo_name: rsjtaylor/libadm

max_forks_repo_name: rsjtaylor/libadm


text:
#include <cctbx/boost_python/flex_fwd.h>

#include <boost/python/module.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/enum.hpp>

#include <iostream>
#include <rstbx/simulation/sim_xfel1.h>

namespace rstbx { namespace boost_python { namespace {

  void
  init_simulation_module() {
    using namespace boost::python;

    typedef return_value_policy<return_by_value> rbv;

    class_<xfel1>("xfel1",init<>())
      .def("set_indices",&xfel1::set_indices)
      .def("set_intensities",&xfel1::set_intensities)
      .def("select_proximal_indices",&xfel1::select_proximal_indices,
        (arg_("half_edge"),
         arg_("detector_distance_m"),
         arg_("pixel_size_m"),
         arg_("orientation"),
         arg_("mosaicity_full_width"),
         arg_("bandpass_full_width"),arg_("wavelength_m"),
         arg_("limiting_resolution_Ang")))
      .def("raw_diffraction",&xfel1::raw_diffraction,
        (arg_("selection"),arg_("pixels"),
         arg_("mosaic_domains"),
         arg_("detector_distance_m"),
         arg_("pixel_size_m"),
         arg_("darwin_factor")
         ))
      .add_property("indices_all",make_getter(&xfel1::indices_all, rbv()))
      .add_property("intensities_all",make_getter(&xfel1::intensities_all, rbv()))
      .add_property("spots", make_getter(&xfel1::spots, rbv()))
      .add_property("signals", make_getter(&xfel1::selection_raw_counts, rbv()))
      .add_property("partialities", make_getter(&xfel1::selection_partiality, rbv()))
    ;
  }

}}} // namespace rstbx::boost_python::<anonymous>

BOOST_PYTHON_MODULE(rstbx_simulation_ext)
{
  rstbx::boost_python::init_simulation_module();
}


text:
#include "Opts.h"
#include "OptsAccumulator.h"
#include "Logger.h"
#include "IOUtil.h"
#include "version.h"

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/join.hpp>
#include <sstream>
#include <thread>

Opts::Opts()
{
}

Opts::~Opts()
{
}

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

void Opts::initializeOnce(int argc, char *argv[])
{
	Opts & opts = getInstance();

	boost::program_options::options_description description("Usage", 250);

	unsigned threads = std::thread::hardware_concurrency();
	if (threads == 0)
	{
		std::cerr << "Could not detect number of cores. Defaulting to one thread." << std::endl;
		threads = 1;
	}

	// find path of binary

	char result[4096];
	unsigned count = readlink( "/proc/self/exe", result, 4096);
	std::string selfExe(result, (count > 0) ? count : 0);

	// find execution and asset paths

    boost::filesystem::path path(selfExe);
    boost::filesystem::path fullPath = boost::filesystem::canonical(boost::filesystem::system_complete(path));
    opts._execPath = fullPath.parent_path().string();
    opts._sharePath = opts._execPath + "/../share/acdc";

    std::vector<std::string> params(argv+1, argv+argc);
    opts._cliCall = fullPath.string() + " " + boost::algorithm::join(params, " ");

    // build boost program arguments

	description.add_options()
	    ("help,h", "Display this help message")
	    ("version,V", "Display the software version")
	    ("verbose,v", accumulator<int>(&(opts._logLevel))->implicit_value(1), "Verbose output (use -vv for more or -vvv for maximum verbosity)")
	    ("quiet,q", "No output")
	    ("random-seed,R", boost::program_options::value<unsigned>(), "Random seed number for reproducible results")
	    ("input-fasta,i", boost::program_options::value<std::string>(), "Input FASTA file")
	    ("input-list,I", boost::program_options::value<std::string>(), "File with a list of input FASTA files, one per line")
	    ("tsne-dimension,d", boost::program_options::value<unsigned>()->default_value(2), "T-SNE dimension")
	    ("tsne-pca-dimension,u", boost::program_options::value<unsigned>()->default_value(50), "T-SNE initial PCA dimension")
	    ("tsne-perplexity,p", boost::program_options::value<unsigned>(), "T-SNE perplexity (overrides automatic estimation)")
	    ("tsne-theta,t", boost::program_options::value<float>()->default_value(0.5), "T-SNE parameter 'theta' of the underlying Barnes-Hut approximation")
	    ("min-contig-length,m", boost::program_options::value<unsigned>()->default_value(0), "Minimal length of contigs to consider for analysis")
	    ("window-kmer-length,k", boost::program_options::value<unsigned>()->default_value(4), "Length of the k-mers in the sequence vectorizer window")
	    ("window-width,w", boost::program_options::value<unsigned>(), "Width of the sliding sequence vectorizer window (overrides automatic estimation using number of target points)")
	    ("window-step,s", boost::program_options::value<unsigned>(), "Step of the sliding sequence vectorizer window (overrides automatic estimation using number of target points)")
	    ("target-num-points,n", boost::program_options::value<unsigned>()->default_value(1000), "Approximate number of target points for estimating window parameters")
	    ("num-bootstraps,b", boost::program_options::value<unsigned>()->default_value(10), "Number of bootstraps")
	    ("bootstrap-ratio,r", boost::program_options::value<double>()->default_value(0.75), "Bootstrap subsampling ratio")
	    ("num-threads,T", boost::program_options::value<unsigned>()->default_value(threads), "Number of threads for bootstrap analysis  (default: detect number of cores)")
	    ("output-dir,o", boost::program_options::value<std::string>()->default_value("./results"), "Result output directory")
	    ("kraken-db,K", boost::program_options::value<std::string>()->default_value(""), "Database to use for Kraken classification")
	    ("aggressive-threshold,a", boost::program_options::value<unsigned>()->default_value(5000), "Aggressive threshold: Treat clusters having a bp size below this threshold as outliers. (Default = 0 = aggressive mode disabled)")
	    ("taxonomy-file,x", boost::program_options::value<std::string>()->default_value(""), "File with external taxonomy information")
	    ("target-taxonomy,X", boost::program_options::value<std::string>()->default_value(""), "Target taxonomy identifier, supports regular expressions")
	    ;

	boost::program_options::variables_map vm;
	boost::program_options::parsed_options parsed = boost::program_options::command_line_parser(argc, argv).options(description).allow_unregistered().run();
	boost::program_options::store(parsed, vm);
	boost::program_options::notify(vm);

	// initialize members from variables map

	std::stringstream ss;
	ss << description;
	opts._helpDesc = ss.str();

	if(vm.count("quiet"))
	{
		opts._logLevel = -1;
	} else
	{
		opts._logLevel = std::min(opts._logLevel, 3);
	}

	opts._needsVersion = vm.count("version");
	opts._version = ACDC_VERSION;
	opts._needsHelp = vm.count("help");

	if(vm.count("random-seed"))
	{
		opts._randomSeed = vm["random-seed"].as<unsigned>();
	} else
	{
		opts._randomSeed = time(NULL);
	}
	std::srand(Opts::randomSeed());

	if (vm.count("input-list"))
	{
		std::string fastaListFile = vm["input-list"].as<std::string>();
		boost::algorithm::trim(fastaListFile);
		opts._inputFASTAs = IOUtil::fileLinesToVec(fastaListFile);
	} else if (vm.count("input-fasta"))
	{
		std::string singleFasta = vm["input-fasta"].as<std::string>();
		boost::algorithm::trim(singleFasta);
		opts._inputFASTAs.push_back(singleFasta);
	}
	opts._tsneDim = vm["tsne-dimension"].as<unsigned>();
	opts._tsnePcaDim = vm["tsne-pca-dimension"].as<unsigned>();
	if (vm.count("tsne-perplexity"))
	{
		opts._tsnePerplexity = vm["tsne-perplexity"].as<unsigned>();
	}
	opts._tsneTheta = vm["tsne-theta"].as<float>();
	opts._minContigLength = vm["min-contig-length"].as<unsigned>();
	opts._minContigLength = std::max(100u, opts._minContigLength);
	opts._windowKmerLength = vm["window-kmer-length"].as<unsigned>();
	if (vm.count("window-width"))
	{
		opts._windowWidth = vm["window-width"].as<unsigned>();
	}
	if (vm.count("window-step"))
	{
		opts._windowStep = vm["window-step"].as<unsigned>();
	}
	opts._targetNumPoints = vm["target-num-points"].as<unsigned>();
	opts._numThreads = vm["num-threads"].as<unsigned>();
	opts._numThreads = std::max(1u, opts._numThreads);
	opts._numBootstraps = vm["num-bootstraps"].as<unsigned>();
	opts._numBootstraps = std::max(1u, opts._numBootstraps);
	opts._bootstrapRatio = vm["bootstrap-ratio"].as<double>();
	opts._outputDir = vm["output-dir"].as<std::string>();
	opts._krakenDb = vm["kraken-db"].as<std::string>();
	opts._aggressiveThreshold = vm["aggressive-threshold"].as<unsigned>();
	opts._taxonomyFile = vm["taxonomy-file"].as<std::string>();
	opts._targetTaxonomy = vm["target-taxonomy"].as<std::string>();
}

std::map <std::string, std::string> Opts::parameters()
{
	std::map <std::string, std::string> params;
	params["execPath"] = Opts::getInstance()._execPath;
	params["sharePath"] = Opts::getInstance()._sharePath;
	params["cliCall"] = Opts::getInstance()._cliCall;
	params["randomSeed"] = std::to_string(Opts::getInstance()._randomSeed);
	params["needsHelp"] = std::to_string(Opts::getInstance()._needsHelp);
	params["needsVersion"] = std::to_string(Opts::getInstance()._needsVersion);
	params["logLevel"] = std::to_string(Opts::getInstance()._logLevel);
	params["tsneDim"] = std::to_string(Opts::getInstance()._tsneDim);
	params["tsnePcaDim"] = std::to_string(Opts::getInstance()._tsnePcaDim);
	params["tsnePerplexity"] = std::to_string(Opts::getInstance()._tsnePerplexity);
	params["tsneTheta"] = std::to_string(Opts::getInstance()._tsneTheta);
	params["minContigLength"] = std::to_string(Opts::getInstance()._minContigLength);
	params["windowKmerLength"] = std::to_string(Opts::getInstance()._windowKmerLength);
	params["windowWidth"] = std::to_string(Opts::getInstance()._windowWidth);
	params["windowStep"] = std::to_string(Opts::getInstance()._windowStep);
	params["targetNumPoints"] = std::to_string(Opts::getInstance()._targetNumPoints);
	params["numThreads"] = std::to_string(Opts::getInstance()._numThreads);
	params["numBootstraps"] = std::to_string(Opts::getInstance()._numBootstraps);
	params["bootstrapRatio"] = std::to_string(Opts::getInstance()._bootstrapRatio);
	params["outputDir"] = Opts::getInstance()._outputDir;
	params["krakenDb"] = Opts::getInstance()._krakenDb;
	params["aggressiveThreshold"] = std::to_string(Opts::getInstance()._aggressiveThreshold);
	params["taxonomyFile"] = Opts::getInstance()._taxonomyFile;
	params["targetTaxonomy"] = Opts::getInstance()._targetTaxonomy;
	return params;
}

std::string Opts::execPath()
{
	return Opts::getInstance()._execPath;
}

std::string Opts::sharePath()
{
	return Opts::getInstance()._sharePath;
}

std::string Opts::cliCall()
{
	return Opts::getInstance()._cliCall;
}

bool Opts::needsHelp()
{
	return Opts::getInstance()._needsHelp;
}

bool Opts::needsVersion()
{
	return Opts::getInstance()._needsVersion;
}

std::string Opts::version()
{
	return Opts::getInstance()._version;
}

unsigned Opts::logLevel()
{
	return Opts::getInstance()._logLevel;
}

std::string Opts::helpDesc()
{
	return Opts::getInstance()._helpDesc;
}

unsigned Opts::randomSeed()
{
	return Opts::getInstance()._randomSeed;
}

std::vector<std::string> Opts::inputFASTAs()
{
	return Opts::getInstance()._inputFASTAs;
}

unsigned Opts::tsneDim()
{
	return Opts::getInstance()._tsneDim;
}

unsigned Opts::tsnePcaDim()
{
	return Opts::getInstance()._tsnePcaDim;
}

unsigned Opts::tsnePerplexity()
{
	return Opts::getInstance()._tsnePerplexity;
}

float Opts::tsneTheta()
{
	return Opts::getInstance()._tsneTheta;
}

unsigned Opts::minContigLength()
{
	return Opts::getInstance()._minContigLength;
}

unsigned Opts::windowKmerLength()
{
	return Opts::getInstance()._windowKmerLength;
}

unsigned Opts::windowWidth()
{
	return Opts::getInstance()._windowWidth;
}

unsigned Opts::windowStep()
{
	return Opts::getInstance()._windowStep;
}

unsigned Opts::targetNumPoints()
{
	return Opts::getInstance()._targetNumPoints;
}

unsigned Opts::numThreads()
{
	return Opts::getInstance()._numThreads;
}

unsigned Opts::numBootstraps()
{
	return Opts::getInstance()._numBootstraps;
}

double Opts::bootstrapRatio()
{
	return Opts::getInstance()._bootstrapRatio;
}

std::string Opts::outputDir()
{
	return Opts::getInstance()._outputDir;
}

std::string Opts::krakenDb()
{
	return Opts::getInstance()._krakenDb;
}

unsigned Opts::aggressiveThreshold()
{
	return Opts::getInstance()._aggressiveThreshold;
}

std::string Opts::taxonomyFile()
{
	return Opts::getInstance()._taxonomyFile;
}

std::string Opts::targetTaxonomy()
{
	return Opts::getInstance()._targetTaxonomy;
}


text:
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
//
// 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 http://mozilla.org/MPL/2.0/.

#include "ViewerCore.h"
#include "ViewerData.h"
#include "gl.h"
#include "../quat_to_mat.h"
#include "../snap_to_fixed_up.h"
#include "../look_at.h"
#include "../frustum.h"
#include "../ortho.h"
#include "../massmatrix.h"
#include "../barycenter.h"
#include "../PI.h"
#include <Eigen/Geometry>
#include <iostream>

IGL_INLINE void igl::opengl::ViewerCore::align_camera_center(
	const Eigen::MatrixXd& V,
	const Eigen::MatrixXi& F)
{
	if (V.rows() == 0)
		return;

	get_scale_and_shift_to_fit_mesh(V, F, camera_base_zoom, camera_base_translation);
	// Rather than crash on empty mesh...
	if (V.size() > 0)
	{
		object_scale = (V.colwise().maxCoeff() - V.colwise().minCoeff()).norm();
	}
}

IGL_INLINE void igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(
	const Eigen::MatrixXd& V,
	const Eigen::MatrixXi& F,
	float& zoom,
	Eigen::Vector3f& shift)
{
	if (V.rows() == 0)
		return;

	Eigen::MatrixXd BC;
	if (F.rows() <= 1)
	{
		BC = V;
	}
	else
	{
		igl::barycenter(V, F, BC);
	}
	return get_scale_and_shift_to_fit_mesh(BC, zoom, shift);
}

IGL_INLINE void igl::opengl::ViewerCore::align_camera_center(
	const Eigen::MatrixXd& V)
{
	if (V.rows() == 0)
		return;

	get_scale_and_shift_to_fit_mesh(V, camera_base_zoom, camera_base_translation);
	// Rather than crash on empty mesh...
	if (V.size() > 0)
	{
		object_scale = (V.colwise().maxCoeff() - V.colwise().minCoeff()).norm();
	}
}

IGL_INLINE void igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(
	const Eigen::MatrixXd& V,
	float& zoom,
	Eigen::Vector3f& shift)
{
	if (V.rows() == 0)
		return;

	auto min_point = V.colwise().minCoeff();
	auto max_point = V.colwise().maxCoeff();
	auto centroid = (0.5 * (min_point + max_point)).eval();
	shift.setConstant(0);
	shift.head(centroid.size()) = -centroid.cast<float>();
	zoom = 2.0 / (max_point - min_point).array().abs().maxCoeff();
}

IGL_INLINE void igl::opengl::ViewerCore::clear_framebuffers()
{
	// The glScissor call ensures we only clear this core's buffers,
	// (in case the user wants different background colors in each viewport.)
	glScissor(viewport(0), viewport(1), viewport(2), viewport(3));
	glEnable(GL_SCISSOR_TEST);
	glClearColor(background_color[0],
		background_color[1],
		background_color[2],
		background_color[3]);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDisable(GL_SCISSOR_TEST);
}

IGL_INLINE void igl::opengl::ViewerCore::draw(
	Eigen::Matrix4f& worldMat,
	ViewerData& data,
	bool update_matrices)
{
	using namespace std;
	using namespace Eigen;

	if (depth_test)
		glEnable(GL_DEPTH_TEST);
	else
		glDisable(GL_DEPTH_TEST);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	/* Bind and potentially refresh mesh/line/point data */
	if (data.dirty)
	{
		data.updateGL(data, data.invert_normals, data.meshgl);
		data.dirty = MeshGL::DIRTY_NONE;
	}
	data.meshgl.bind_mesh();

	// Initialize uniform
	glViewport(viewport(0), viewport(1), viewport(2), viewport(3));

	if (update_matrices)
	{
		view = Eigen::Matrix4f::Identity();
		proj = Eigen::Matrix4f::Identity();
		norm = Eigen::Matrix4f::Identity();

		float width = viewport(2);
		float height = viewport(3);

		// Set view
		look_at(camera_eye, camera_center, camera_up, view);
		view = view
			* (trackball_angle * Eigen::Scaling(camera_zoom * camera_base_zoom)
				* Eigen::Translation3f(camera_translation + camera_base_translation)).matrix() * worldMat * data.MakeTrans();

		norm = view.inverse().transpose();

		// Set projection
		if (orthographic)
		{
			float length = (camera_eye - camera_center).norm();
			float h = tan(camera_view_angle / 360.0 * igl::PI) * (length);
			ortho(-h * width / height, h * width / height, -h, h, camera_dnear, camera_dfar, proj);
		}
		else
		{
			float fH = tan(camera_view_angle / 360.0 * igl::PI) * camera_dnear;
			float fW = fH * (double)width / (double)height;
			frustum(-fW, fW, -fH, fH, camera_dnear, camera_dfar, proj);
		}
	}

	// Send transformations to the GPU
	GLint viewi = glGetUniformLocation(data.meshgl.shader_mesh, "view");
	GLint proji = glGetUniformLocation(data.meshgl.shader_mesh, "proj");
	GLint normi = glGetUniformLocation(data.meshgl.shader_mesh, "normal_matrix");
	glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
	glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
	glUniformMatrix4fv(normi, 1, GL_FALSE, norm.data());

	// Light parameters
	GLint specular_exponenti = glGetUniformLocation(data.meshgl.shader_mesh, "specular_exponent");
	GLint light_position_eyei = glGetUniformLocation(data.meshgl.shader_mesh, "light_position_eye");
	GLint lighting_factori = glGetUniformLocation(data.meshgl.shader_mesh, "lighting_factor");
	GLint fixed_colori = glGetUniformLocation(data.meshgl.shader_mesh, "fixed_color");
	GLint texture_factori = glGetUniformLocation(data.meshgl.shader_mesh, "texture_factor");

	glUniform1f(specular_exponenti, data.shininess);
	glUniform3fv(light_position_eyei, 1, light_position.data());
	glUniform1f(lighting_factori, lighting_factor); // enables lighting
	glUniform4f(fixed_colori, 0.0, 0.0, 0.0, 0.0);

	if (data.V.rows() > 0)
	{
		// Render fill
		if (is_set(data.show_faces))
		{
			// Texture
			glUniform1f(texture_factori, is_set(data.show_texture) ? 1.0f : 0.0f);
			data.meshgl.draw_mesh(true);
			glUniform1f(texture_factori, 0.0f);
		}

		// Render wireframe
		if (is_set(data.show_lines))
		{
			glLineWidth(data.line_width);
			glUniform4f(fixed_colori,
				data.line_color[0],
				data.line_color[1],
				data.line_color[2], 1.0f);
			data.meshgl.draw_mesh(false);
			glUniform4f(fixed_colori, 0.0f, 0.0f, 0.0f, 0.0f);
		}
	}

	if (is_set(data.show_overlay))
	{
		if (is_set(data.show_overlay_depth))
			glEnable(GL_DEPTH_TEST);
		else
			glDisable(GL_DEPTH_TEST);

		if (data.lines.rows() > 0)
		{
			data.meshgl.bind_overlay_lines();
			viewi = glGetUniformLocation(data.meshgl.shader_overlay_lines, "view");
			proji = glGetUniformLocation(data.meshgl.shader_overlay_lines, "proj");

			glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
			glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
			// This must be enabled, otherwise glLineWidth has no effect
			glEnable(GL_LINE_SMOOTH);
			glLineWidth(data.line_width);

			data.meshgl.draw_overlay_lines();
		}

		if (data.points.rows() > 0)
		{
			data.meshgl.bind_overlay_points();
			viewi = glGetUniformLocation(data.meshgl.shader_overlay_points, "view");
			proji = glGetUniformLocation(data.meshgl.shader_overlay_points, "proj");

			glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
			glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
			glPointSize(data.point_size);

			data.meshgl.draw_overlay_points();
		}

		glEnable(GL_DEPTH_TEST);
	}

}

IGL_INLINE void igl::opengl::ViewerCore::UpdateUniforms(Eigen::Matrix4f& worldMat, ViewerData& data, bool update_matrices)
{

}

IGL_INLINE void igl::opengl::ViewerCore::draw_buffer(Eigen::Matrix4f& worldMat, ViewerData& data,
	bool update_matrices,
	Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>& R,
	Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>& G,
	Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>& B,
	Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>& A)
{
	assert(R.rows() == G.rows() && G.rows() == B.rows() && B.rows() == A.rows());
	assert(R.cols() == G.cols() && G.cols() == B.cols() && B.cols() == A.cols());

	unsigned width = R.rows();
	unsigned height = R.cols();

	// https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing
	unsigned int framebuffer;
	glGenFramebuffers(1, &framebuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
	// create a multisampled color attachment texture
	unsigned int textureColorBufferMultiSampled;
	glGenTextures(1, &textureColorBufferMultiSampled);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled);
	glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, width, height, GL_TRUE);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled, 0);
	// create a (also multisampled) renderbuffer object for depth and stencil attachments
	unsigned int rbo;
	glGenRenderbuffers(1, &rbo);
	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
	glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
	assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	// configure second post-processing framebuffer
	unsigned int intermediateFBO;
	glGenFramebuffers(1, &intermediateFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, intermediateFBO);
	// create a color attachment texture
	unsigned int screenTexture;
	glGenTextures(1, &screenTexture);
	glBindTexture(GL_TEXTURE_2D, screenTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);	// we only need a color buffer
	assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

	// Clear the buffer
	glClearColor(background_color(0), background_color(1), background_color(2), 0.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	// Save old viewport
	Eigen::Vector4f viewport_ori = viewport;
	viewport << 0, 0, width, height;
	// Draw
	draw(worldMat, data, update_matrices);
	// Restore viewport
	viewport = viewport_ori;

	glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO);
	glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

	glBindFramebuffer(GL_FRAMEBUFFER, intermediateFBO);
	// Copy back in the given Eigen matrices
	GLubyte* pixels = (GLubyte*)calloc(width * height * 4, sizeof(GLubyte));
	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

	// Clean up
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glDeleteTextures(1, &screenTexture);
	glDeleteTextures(1, &textureColorBufferMultiSampled);
	glDeleteFramebuffers(1, &framebuffer);
	glDeleteFramebuffers(1, &intermediateFBO);
	glDeleteRenderbuffers(1, &rbo);

	int count = 0;
	for (unsigned j = 0; j < height; ++j)
	{
		for (unsigned i = 0; i < width; ++i)
		{
			R(i, j) = pixels[count * 4 + 0];
			G(i, j) = pixels[count * 4 + 1];
			B(i, j) = pixels[count * 4 + 2];
			A(i, j) = pixels[count * 4 + 3];
			++count;
		}
	}
	// Clean up
	free(pixels);
}

IGL_INLINE void igl::opengl::ViewerCore::set_rotation_type(
	const igl::opengl::ViewerCore::RotationType& value)
{
	using namespace Eigen;
	using namespace std;
	const RotationType old_rotation_type = rotation_type;
	rotation_type = value;
	if (rotation_type == ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP &&
		old_rotation_type != ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
	{
		snap_to_fixed_up(Quaternionf(trackball_angle), trackball_angle);
	}
}

IGL_INLINE void igl::opengl::ViewerCore::set(unsigned int& property_mask, bool value) const
{
	if (!value)
		unset(property_mask);
	else
		property_mask |= id;
}

IGL_INLINE void igl::opengl::ViewerCore::unset(unsigned int& property_mask) const
{
	property_mask &= ~id;
}

IGL_INLINE void igl::opengl::ViewerCore::toggle(unsigned int& property_mask) const
{
	property_mask ^= id;
}

IGL_INLINE bool igl::opengl::ViewerCore::is_set(unsigned int property_mask) const
{
	return (property_mask & id);
}

IGL_INLINE igl::opengl::ViewerCore::ViewerCore()
{
	// Default colors
	background_color << 0.3f, 0.3f, 0.5f, 1.0f;

	// Default lights settings
	light_position << 0.0f, 0.3f, 0.0f;
	lighting_factor = 1.0f; //on

	// Default trackball
	trackball_angle = Eigen::Quaternionf::Identity();
	set_rotation_type(ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP);

	// Camera parameters
	camera_base_zoom = 1.0f;
	camera_zoom = 1.0f;
	orthographic = false;
	camera_view_angle = 45.0;
	camera_dnear = 1.0;
	camera_dfar = 100.0;
	camera_base_translation << 0, 0, 0;
	camera_translation << 0, 0, 0;
	camera_eye << 0, 0, 5;
	camera_center << 0, 0, 0;
	camera_up << 0, 1, 0;

	depth_test = true;

	is_animating = false;
	animation_max_fps = 30.;

	viewport.setZero();
}

IGL_INLINE void igl::opengl::ViewerCore::init()
{
}

IGL_INLINE void igl::opengl::ViewerCore::shut()
{
}

max_stars_repo_name: Savyonsh/EngineForAnimationCourse

max_issues_repo_name: Savyonsh/EngineForAnimationCourse

max_forks_repo_name: Savyonsh/EngineForAnimationCourse


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_ONEMINUS_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_ONEMINUS_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!

    @ingroup group-arithmetic
    Function object implementing oneminus capabilities

    Returns the one minus the entry, saturated in the entry type.

    @par semantic:
    For any given value @c x of type @c T:

    @code
    T r = oneminus(x);
    @endcode

    For signed type is similar to:

    @code
    T r = 1-x
    @endcode

    For unsigned type it is equivalent (due to saturation) to:

    @code
    T r = x == 0 ? 1 : 0
    @endcode

  **/
  const boost::dispatch::functor<tag::oneminus_> oneminus = {};
} }
#endif

#include <boost/simd/function/scalar/oneminus.hpp>
#include <boost/simd/function/simd/oneminus.hpp>

#endif