text:
/*
 * This is part of the fl library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2015 Max Planck Society,
 * 				 Autonomous Motion Department,
 * 			     Institute for Intelligent Systems
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file joint_sensor_iid_test.cpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#include <gtest/gtest.h>
#include "../../typecast.hpp"

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <fl/util/types.hpp>
#include <fl/model/sensor/linear_gaussian_sensor.hpp>
#include <fl/model/sensor/joint_sensor_iid.hpp>

template <typename TestType>
class JointSensorIidTest:
    public testing::Test
{
public:
    enum : signed int
    {
        LocalStateDim = TestType::Parameter::StateDim,
        LocalObsrvDim = TestType::Parameter::ObsrvDim,
        LocalNoiseDim = TestType::Parameter::ObsrvDim,
        Count = TestType::Parameter::LocalModelCount,

        LocalStateSize = fl::TestSize<LocalStateDim, TestType>::Value,
        LocalObsrvSize = fl::TestSize<LocalObsrvDim, TestType>::Value,
        LocalNoiseSize = fl::TestSize<LocalNoiseDim, TestType>::Value,
        Size = fl::TestSize<Count, TestType>::Value
    };

    // Local model types
    typedef Eigen::Matrix<fl::Real, LocalStateSize, 1> LocalState;
    typedef Eigen::Matrix<fl::Real, LocalObsrvSize, 1> LocalObsrv;
    typedef fl::LinearGaussianSensor<LocalObsrv, LocalState> LocalModel;
    typedef typename LocalModel::Noise LocalNoise;

    // Joint model types
    typedef fl::JointSensor<
                fl::MultipleOf<LocalModel, Size>
            > JointModel;

    typedef typename JointModel::Obsrv Obsrv;
    typedef typename JointModel::Noise Noise;
    typedef typename JointModel::State State;

    enum : signed int
    {
        StateDim = LocalStateDim,
        ObsrvDim = LocalObsrvDim * Count,
        NoiseDim = LocalNoiseDim * Count,

        StateSize = fl::TestSize<StateDim, TestType>::Value,
        ObsrvSize = fl::TestSize<ObsrvDim, TestType>::Value,
        NoiseSize = fl::TestSize<NoiseDim, TestType>::Value
    };

    JointSensorIidTest()
        : joint_model(create_joint_sensor(create_local_model())),
          noise_normal_gaussian(NoiseDim)
    { }

    State zero_state() { return State::Zero(LocalStateDim); }
    Obsrv zero_obsrv() { return Obsrv::Zero(LocalObsrvDim); }
    Noise zero_noise() { return Noise::Zero(LocalNoiseDim); }

    State rand_state() { return State::Random(LocalStateDim); }
    Obsrv rand_obsrv() { return Obsrv::Random(LocalObsrvDim); }
    Noise rand_noise() { return noise_normal_gaussian.sample(); }

    LocalModel create_local_model()
    {
        return LocalModel(LocalObsrvDim, LocalStateDim);
    }

    template <typename LocalSensor>
    JointModel create_joint_sensor(LocalSensor&& local_model)
    {
        return JointModel(local_model, Count);
    }

    void init_dimension_test()
    {
        EXPECT_EQ(joint_model.obsrv_dimension(), ObsrvDim);
        EXPECT_EQ(joint_model.noise_dimension(), NoiseDim);
        EXPECT_EQ(joint_model.state_dimension(), StateDim);
    }

    void observation()
    {
        auto y = joint_model.observation(rand_state(), rand_noise());

        EXPECT_EQ(y.size(), ObsrvDim);
        for (int i = 0; i < y.size(); ++i)
        {
            EXPECT_NE(y[i], 0.);
        }
    }

    void nested_joint_model()
    {
        // nested joint model type taking multiple of JointModel
        typedef fl::JointSensor<
                    fl::MultipleOf<JointModel, Size>
                >  OuterJointModel;

        auto nested_joint =
            OuterJointModel(
                create_joint_sensor(create_local_model()), Count);

        EXPECT_EQ(nested_joint.obsrv_dimension(), ObsrvDim * Count);
        EXPECT_EQ(nested_joint.noise_dimension(), NoiseDim * Count);
        EXPECT_EQ(nested_joint.state_dimension(), StateDim);
    }

//    void probability()
//    {
//        auto x = State::Random(StateDim).eval();
//        auto y = Obsrv::Random(ObsrvDim).eval();

//        auto body_prob = body_model.probability(y, x);
//        auto tail_prob = tail_model.probability(y, x);
//        auto body_tail_prob = body_tail_model.probability(y, x);

//        ASSERT_DOUBLE_EQ((body_prob + tail_prob)/2., body_tail_prob);
//    }

//    void log_probability()
//    {
//        auto x = State::Random(StateDim).eval();
//        auto y = Obsrv::Random(ObsrvDim).eval();

//        auto body_prob = body_model.probability(y, x);
//        auto tail_prob = tail_model.probability(y, x);
//        auto body_tail_log_prob = body_tail_model.log_probability(y, x);

//        ASSERT_DOUBLE_EQ(std::log((body_prob + tail_prob)/2.),
//                         body_tail_log_prob);
//    }

protected:
    JointModel joint_model;
    fl::StandardGaussian<Noise> noise_normal_gaussian;
};

template <int ModelCount, int ObsrvDimension, int StateDimension>
struct Dimensions
{
    enum: signed int
    {
        ObsrvDim = ObsrvDimension,
        StateDim = StateDimension,
        LocalModelCount = ModelCount
    };
};

typedef ::testing::Types<
            fl::StaticTest<Dimensions<1, 1, 1>>,
            fl::StaticTest<Dimensions<2, 1, 1>>,
            fl::StaticTest<Dimensions<10, 1, 1>>,
            fl::StaticTest<Dimensions<1, 2, 1>>,
            fl::StaticTest<Dimensions<2, 3, 2>>,
            fl::StaticTest<Dimensions<10, 11, 1>>,
            fl::DynamicTest<Dimensions<1, 1, 1>>,
            fl::DynamicTest<Dimensions<2, 1, 1>>,
            fl::DynamicTest<Dimensions<10, 1, 1>>,
            fl::DynamicTest<Dimensions<1, 2, 1>>,
            fl::DynamicTest<Dimensions<2, 3, 2>>,
            fl::DynamicTest<Dimensions<10, 11, 1>>
        > TestTypes;

TYPED_TEST_CASE(JointSensorIidTest, TestTypes);

TYPED_TEST(JointSensorIidTest, init_dimension)
{
    TestFixture::init_dimension_test();
}

TYPED_TEST(JointSensorIidTest, observation)
{
    TestFixture::observation();
}

TYPED_TEST(JointSensorIidTest, nested_joint_model)
{
    TestFixture::nested_joint_model();
}

max_stars_repo_name: aeolusbot-tommyliu/fl

max_issues_repo_name: aeolusbot-tommyliu/fl

max_forks_repo_name: aeolusbot-tommyliu/fl


text:
/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <orea/engine/observationmode.hpp>
#include <orea/engine/valuationengine.hpp>
#include <orea/simulation/simmarket.hpp>
#include <ored/portfolio/optionwrapper.hpp>
#include <ored/portfolio/portfolio.hpp>
#include <ored/portfolio/structuredtradeerror.hpp>
#include <ored/utilities/log.hpp>
#include <ored/utilities/parsers.hpp>
#include <ored/utilities/progressbar.hpp>
#include <ored/utilities/to_string.hpp>

#include <boost/timer/timer.hpp>
#include <ql/errors.hpp>

using namespace QuantLib;
using namespace QuantExt;
using namespace std;
using namespace ore::data;
using boost::timer::cpu_timer;
using boost::timer::default_places;

namespace ore {
namespace analytics {

ValuationEngine::ValuationEngine(const Date& today, const boost::shared_ptr<DateGrid>& dg,
                                 const boost::shared_ptr<SimMarket>& simMarket,
                                 const set<std::pair<string, boost::shared_ptr<ModelBuilder>>>& modelBuilders)
    : today_(today), dg_(dg), simMarket_(simMarket), modelBuilders_(modelBuilders) {

    QL_REQUIRE(dg_->size() > 0, "Error, DateGrid size must be > 0");
    QL_REQUIRE(today <= dg_->dates().front(), "ValuationEngine: Error today ("
                                                  << today << ") must not be later than first DateGrid date "
                                                  << dg_->dates().front());
    QL_REQUIRE(simMarket_, "ValuationEngine: Error, Null SimMarket");
}

void ValuationEngine::recalibrateModels() {
    ObservationMode::Mode om = ObservationMode::instance().mode();
    for (auto const& b : modelBuilders_) {
        if (om == ObservationMode::Mode::Disable)
            b.second->forceRecalculate();
        b.second->recalibrate();
    }
}

void ValuationEngine::buildCube(const boost::shared_ptr<data::Portfolio>& portfolio,
                                boost::shared_ptr<analytics::NPVCube> outputCube,
                                vector<boost::shared_ptr<ValuationCalculator>> calculators, bool mporStickyDate,
                                boost::shared_ptr<analytics::NPVCube> outputCubeNettingSet,
                                boost::shared_ptr<analytics::NPVCube> outputCptyCube,
                                vector<boost::shared_ptr<CounterpartyCalculator>> cptyCalculators) {

    LOG("Build cube with mporStickyDate=" << mporStickyDate);

    QL_REQUIRE(portfolio->size() > 0, "ValuationEngine: Error portfolio is empty");

    QL_REQUIRE(outputCube->numIds() == portfolio->trades().size(),
               "cube x dimension (" << outputCube->numIds() << ") "
                                    << "different from portfolio size (" << portfolio->trades().size() << ")");

    QL_REQUIRE(outputCube->numDates() == dg_->valuationDates().size(),
               "cube y dimension (" << outputCube->numDates() << ") "
                                    << "different from number of valuation dates (" << dg_->valuationDates().size()
                                    << ")");

    if (outputCptyCube) {
        QL_REQUIRE(outputCptyCube->numIds() == portfolio->counterparties().size() + 1,
                   "cptyCube x dimension (" << outputCptyCube->numIds() << "minus 1) "
                                            << "different from portfolio counterparty size ("
                                            << portfolio->counterparties().size() << ")");

        QL_REQUIRE(outputCptyCube->numDates() == dg_->dates().size(), "outputCptyCube y dimension ("
                                                                          << outputCptyCube->numDates() << ") "
                                                                          << "different from number of time steps ("
                                                                          << dg_->dates().size() << ")");
    }

    LOG("Starting ValuationEngine for " << portfolio->size() << " trades, " << outputCube->samples() << " samples and "
                                        << dg_->size() << " dates.");

    ObservationMode::Mode om = ObservationMode::instance().mode();
    Real updateTime = 0.0;
    Real pricingTime = 0.0;
    Real fixingTime = 0.0;

    // Loop is Samples, Dates, Trades
    const auto& dates = dg_->dates();
    const auto& trades = portfolio->trades();
    auto& counterparties = outputCptyCube ? outputCptyCube->ids() : vector<string>();
    std::vector<bool> tradeHasError(trades.size(), false);
    LOG("Initialise state objects...");
    Size numFRC = 0;
    // initialise state objects for each trade (required for path-dependent derivatives in particular)
    for (Size i = 0; i < trades.size(); i++) {
        QL_REQUIRE(trades[i]->npvCurrency() != "", "NPV currency not set for trade " << trades[i]->id());

        DLOG("Initialise wrapper for trade " << trades[i]->id());
        trades[i]->instrument()->initialise(dates);

        recalibrateModels();

        // T0 values
        try {
            for (auto calc : calculators)
                calc->calculateT0(trades[i], i, simMarket_, outputCube, outputCubeNettingSet);
        } catch (const std::exception& e) {
            string expMsg = string("T0 valuation error: ") + e.what();
            ALOG(StructuredTradeErrorMessage(trades[i]->id(), trades[i]->tradeType(), "ScenarioValuation",
                                             expMsg.c_str()));
            tradeHasError[i] = true;
        }

        if (om == ObservationMode::Mode::Unregister) {
            for (const Leg& leg : trades[i]->legs()) {
                for (Size n = 0; n < leg.size(); n++) {
                    boost::shared_ptr<FloatingRateCoupon> frc = boost::dynamic_pointer_cast<FloatingRateCoupon>(leg[n]);
                    if (frc) {
                        frc->unregisterWith(frc->index());
                        trades[i]->instrument()->qlInstrument()->unregisterWith(frc);
                        // Unregister with eval dates
                        frc->unregisterWith(Settings::instance().evaluationDate());
                        frc->index()->unregisterWith(Settings::instance().evaluationDate());
                        trades[i]->instrument()->qlInstrument()->unregisterWith(Settings::instance().evaluationDate());
                    }
                }
            }
        }
    }
    LOG("Total number of swaps = " << portfolio->size());
    LOG("Total number of FRC = " << numFRC);

    simMarket_->fixingManager()->initialise(portfolio, simMarket_);

    cpu_timer timer;
    cpu_timer loopTimer;

    // We call Cube::samples() each time her to allow for dynamic stopping times
    // e.g. MC convergence tests
    for (Size sample = 0; sample < outputCube->samples(); ++sample) {
        updateProgress(sample, outputCube->samples());

        for (auto& trade : trades)
            trade->instrument()->reset();

        // loop over Dates, increase cubeDateIndex for each valuation date we hit
        int cubeDateIndex = -1;
        for (Size i = 0; i < dates.size(); ++i) {
            Date d = dates[i];

            // Process auxiliary close-out dates first (may coincide with a valuation date, see below)
            // Store result at same cubeDateIndex as the previous valuation date's result, but at different cube depth
            // Differences to valuation date processing above:
            // Update valuation date and fixings, trades exercisable depending on stickiness
            bool scenarioUpdated = false;
            if (dg_->isCloseOutDate()[i]) {
                timer.start();

                // update market
                simMarket_->preUpdate();
                if (!mporStickyDate)
                    simMarket_->updateDate(d);
                simMarket_->updateScenario(d);
                scenarioUpdated = true;
                simMarket_->postUpdate(d, !mporStickyDate); // with fixings only if not sticky

                recalibrateModels();

                timer.stop();
                updateTime += timer.elapsed().wall * 1e-9;

                // loop over trades
                timer.start();
                if (mporStickyDate) // switch off if sticky
                    tradeExercisable(false, trades);
                QL_REQUIRE(cubeDateIndex >= 0,
                           "negative cube date index, ensure that the date grid starts with a valuation date");
                runCalculators(true, trades, tradeHasError, calculators, outputCube, outputCubeNettingSet, d,
                               cubeDateIndex, sample, simMarket_->label());
                if (mporStickyDate) // switch on again, if sticky
                    tradeExercisable(true, trades);
                timer.stop();
                pricingTime += timer.elapsed().wall * 1e-9;
            }

            // process a valuation date as usual
            if (dg_->isValuationDate()[i]) {
                timer.start();

                cubeDateIndex++;

                // All the steps below from preUpdate() to updateAsd(d) are combined in update(d), but we decompose as
                // follows simMarket_->update(d);
                simMarket_->preUpdate();
                simMarket_->updateDate(d);
                // We can skip this step, if we have done that above in the close-out date section
                if (!scenarioUpdated)
                    simMarket_->updateScenario(d);
                // Always with fixing update here, in contrast to the close-out date section
                simMarket_->postUpdate(d, true);
                // Aggregation scenario data update on valuation dates only
                simMarket_->updateAsd(d);

                recalibrateModels();

                timer.stop();
                updateTime += timer.elapsed().wall * 1e-9;

                timer.start();
                // loop over trades
                runCalculators(false, trades, tradeHasError, calculators, outputCube, outputCubeNettingSet, d,
                               cubeDateIndex, sample, simMarket_->label());
                // loop over counterparty names
                runCalculators(false, counterparties, cptyCalculators, outputCptyCube, d, cubeDateIndex, sample);
                timer.stop();
                pricingTime += timer.elapsed().wall * 1e-9;
            }
        }

        timer.start();
        simMarket_->fixingManager()->reset();
        fixingTime += timer.elapsed().wall * 1e-9;
    }

    simMarket_->reset();
    updateProgress(outputCube->samples(), outputCube->samples());
    loopTimer.stop();
    LOG("ValuationEngine completed: loop " << setprecision(2) << loopTimer.format(2, "%w") << " sec, "
                                           << "pricing " << pricingTime << " sec, "
                                           << "update " << updateTime << " sec "
                                           << "fixing " << fixingTime);

    // for trades with errors set all output cube values to zero

    for (Size i = 0; i < trades.size(); ++i) {
        if (tradeHasError[i]) {
            ALOG("setting all results in output cube to zero for trade '"
                 << trades[i]->id() << "' since there was at least one error during simulation");
            for (Size index = 0; index < outputCube->depth(); ++index) {
                outputCube->setT0(0.0, i, index);
                for (Size dateIndex = 0; dateIndex < dates.size(); ++dateIndex) {
                    for (Size sample = 0; sample < outputCube->samples(); ++sample) {
                        outputCube->set(0.0, i, dateIndex, sample, index);
                    }
                }
            }
        }
    }
}

void ValuationEngine::runCalculators(bool isCloseOutDate, const std::vector<boost::shared_ptr<Trade>>& trades,
                                     std::vector<bool>& tradeHasError,
                                     const std::vector<boost::shared_ptr<ValuationCalculator>>& calculators,
                                     boost::shared_ptr<analytics::NPVCube>& outputCube,
                                     boost::shared_ptr<analytics::NPVCube>& outputCubeNettingSet, const Date& d,
                                     const Size cubeDateIndex, const Size sample, const string& label) {
    ObservationMode::Mode om = ObservationMode::instance().mode();
    // loop over trades
    for (Size j = 0; j < trades.size(); ++j) {
        if (tradeHasError[j])
            continue;
        auto trade = trades[j];
        // We can avoid checking mode here and always call updateQlInstruments()
        if (om == ObservationMode::Mode::Disable)
            trade->instrument()->updateQlInstruments();
        try {
            for (auto calc : calculators)
                calc->calculate(trade, j, simMarket_, outputCube, outputCubeNettingSet, d, cubeDateIndex, sample,
                                isCloseOutDate);
        } catch (const std::exception& e) {
            string expMsg = "date = " + ore::data::to_string(io::iso_date(d)) +
                            ", sample = " + ore::data::to_string(sample) + ", label = " + label + ": " + e.what();
            ALOG(StructuredTradeErrorMessage(trade->id(), trade->tradeType(), "ScenarioValuation", expMsg.c_str()));
            tradeHasError[j] = true;
        }
    }
}

void ValuationEngine::runCalculators(bool isCloseOutDate, const std::vector<std::string>& counterparties,
                                     const std::vector<boost::shared_ptr<CounterpartyCalculator>>& calculators,
                                     boost::shared_ptr<analytics::NPVCube>& cptyCube, const Date& d,
                                     const Size cubeDateIndex, const Size sample) {
    // loop over counterparties
    for (Size j = 0; j < counterparties.size(); ++j) {
        auto counterparty = counterparties[j];
        for (auto calc : calculators)
            calc->calculate(counterparty, j, simMarket_, cptyCube, d, cubeDateIndex, sample, isCloseOutDate);
    }
}

void ValuationEngine::tradeExercisable(bool enable, const std::vector<boost::shared_ptr<Trade>>& trades) {
    for (Size j = 0; j < trades.size(); ++j) {
        auto t = boost::dynamic_pointer_cast<OptionWrapper>(trades[j]->instrument());
        if (t != nullptr) {
            if (enable)
                t->enableExercise();
            else
                t->disableExercise();
        }
    }
}
} // namespace analytics
} // namespace ore

ext: cpp

max_stars_repo_name: mrslezak/Engine

max_issues_repo_name: mrslezak/Engine

max_forks_repo_name: mrslezak/Engine


text:
#include <boost/program_options.hpp>
#include <iostream>

#include <core/ipc.h>
#include "service.pb.h"

class Service_client : Core::IPC_client
{
public:
  Service_client(const std::string& instance_id) :
    Core::IPC_client(std::string("ipc:///tmp//ipc_memory_") + instance_id)
  {
  }

  void allocate_dma_memory(size_t size)
  {
    using namespace ipc_protocol;

    AllocDmaMemory msg;
  }

  void session_request()
  {
    using namespace ipc_protocol;

    /* create session */
    CreateSessionRequest msg;
    msg.mutable_hdr()->set_type(ipc_protocol::MessageType::__CreateSessionRequest);
    msg.mutable_hdr()->set_auth_id("authid"); //_connection.auth_id());
    msg.mutable_hdr()->set_auth_token("authtok");
    msg.set_session_type(SessionType::SharedIOSlab);
    msg.set_slab_id("myslab");
    msg.set_memory_size(33);
    msg.set_storage_size(1);
    msg.set_virtual_size(2);
    std::string out_str;
    size_t      reply_msg_len = 0;
    assert(msg.SerializeToString(&out_str));

    void *reply_msg = send_and_wait(out_str.c_str(),
                                    out_str.length(),
                                    &reply_msg_len);

    CreateSessionReply reply;
    reply.ParseFromArray(reply_msg, reply_msg_len);

    if (reply.status() != 0) {
      throw Constructor_exception("session creation failed.");
    }

  }
};

int main(int argc, char * argv[])
{
  try {
    namespace po = boost::program_options;
    po::options_description desc("Options");
    desc.add_options()
      ("help", "Show help")
      ("endpoint", po::value<std::string>(), "Endpoint name (IPC)")
      ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc),  vm);

    if(vm.count("help") || vm.count("endpoint")==0 )
      std::cout << desc;

    {

      Service_client svc(vm["endpoint"].as<std::string>());

      for(unsigned i=0;i<5;i++) {
        sleep(1);
        svc.session_request();
      }
    }
  }
  catch(...) {
    return -1;
  }

  return 0;
}

max_stars_repo_name: fengggli/comanche

max_issues_repo_name: fengggli/comanche

max_forks_repo_name: fengggli/comanche


text:
/**
 * \file
 * \author stvdedal@gmail.com
 *
 * \brief
 * Subgraphs, mappings between Mined and Input graphs
 */
#ifndef GSPAN_SUBGRAPH_TREE_H_
#define GSPAN_SUBGRAPH_TREE_H_

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/property_map.hpp>

#include <boost/assert.hpp>

#include <vector>
#include <limits>

namespace gspan {

/**
 * \brief
 * Subgraphs, mappings between Mined and Input graphs
 * based on single-linked list
 */
template <typename IG, typename MG>
class subgraph_tree {
public:
    typedef IG InputGraph;
    typedef MG MinedGraph;
    typedef boost::graph_traits<InputGraph> IGT;
    typedef boost::graph_traits<MinedGraph> MGT;

    subgraph_tree(const typename MGT::edge_descriptor& mined_edge,
                  const typename IGT::edge_descriptor& input_edge,
                  const MinedGraph* mined_graph,
                  const InputGraph* input_graph);

    subgraph_tree(const typename MGT::edge_descriptor& mined_edge,
                  const typename IGT::edge_descriptor& input_edge,
                  const MinedGraph* mined_graph,
                  const subgraph_tree* prev);

    const InputGraph*
    input_graph() const
    {
        return _ig;
    }

    /// @name map Mined graph vertex to Input graph vertex
    ///@{
    using InputGraphVerts = std::vector<typename IGT::vertex_descriptor>;
    using InputGraphVertsIter = typename InputGraphVerts::const_iterator;
    using MinedGraphVertIdMap = typename
                                boost::property_map<MinedGraph, boost::vertex_index_t>::const_type;
    using Mined2InputVertMap =
        boost::iterator_property_map<InputGraphVertsIter, MinedGraphVertIdMap>;

    Mined2InputVertMap
    m2i_vert_map() const;
    ///@}

    /// @name map Mined graph edge to Input graph edge
    ///@{
    using InputGraphEdges = std::vector<typename IGT::edge_descriptor>;
    using InputGraphEdgesIter = typename InputGraphEdges::const_iterator;
    using MinedGraphEdgeIdMap = typename
                                boost::property_map<MinedGraph, boost::edge_index_t>::const_type;
    using Mined2InputEdgeMap =
        boost::iterator_property_map<InputGraphEdgesIter, MinedGraphEdgeIdMap>;

    Mined2InputEdgeMap
    m2i_edge_map() const;
    ///@}

    /// @name map Input graph vertex to Mined graph vertex
    ///@{
    using MinedGraphVerts = std::vector<typename MGT::vertex_descriptor>;
    using MinedGraphVertsIter = typename MinedGraphVerts::const_iterator;
    using InputGraphVertIdMap = typename
                                boost::property_map<InputGraph, boost::vertex_index_t>::const_type;
    using Input2MinedVertMap =
        boost::iterator_property_map<MinedGraphVertsIter, InputGraphVertIdMap>;

    Input2MinedVertMap
    i2m_vert_map() const;
    ///@}

    /// @name map Input graph edge to Mined graph edge
    ///@{
    using MinedGraphEdges = std::vector<typename MGT::edge_descriptor>;
    using MinedGraphEdgesIter = typename MinedGraphEdges::const_iterator;
    using InputGraphEdgeIdMap = typename
                                boost::property_map<InputGraph, boost::edge_index_t>::const_type;
    using Input2MinedEdgeMap =
        boost::iterator_property_map<MinedGraphEdgesIter, InputGraphEdgeIdMap>;

    Input2MinedEdgeMap
    i2m_edge_map() const;
    ///@}

    /// subgraphs is automorphic if they belong to the same graph
    /// and contains the same set of edges
    static bool
    is_automorphic(const subgraph_tree& lhs, const subgraph_tree& rhs);

private:
    const subgraph_tree* _prev;

    const MinedGraph* _mg;
    const InputGraph* _ig;

    typename MGT::edge_descriptor _mg_edge;
    typename IGT::edge_descriptor _ig_edge;

    /// size  == num_vertices(MinedGraph)
    /// indexed by MinedGraph vertex_index
    /// values are InputGraph vertex_descriptor
    InputGraphVerts _ig_vertices;

    /// size == num_edges(MinedGraph)
    /// indexed by MinedGraph edge_index
    /// values are InputGraph edge_descriptor
    InputGraphEdges _ig_edges;

    /// size == num_vertices(InputGraph)
    /// indexed by InputGraph vertex_index
    /// values are MinedGraph vertex_descriptor
    MinedGraphVerts _mg_vertices;

    /// size == num_edges(InputGraph)
    /// indexed by InputGraph edge_index
    /// values are MinedGraph edge_descriptor
    MinedGraphEdges _mg_edges;

    /// size == num_edges(InputGraph)
    /// indexed by InputGraph edge_index
    /// values: true edge exists in MG
    ///         false edge is free
    std::vector<char> _edge_flags;
};

//
// the first edge
//
template <typename IG, typename MG>
subgraph_tree<IG, MG>::subgraph_tree(const typename MGT::edge_descriptor&
                                     mined_edge,
                                     const typename IGT::edge_descriptor& input_edge,
                                     const MinedGraph* mined_graph,
                                     const InputGraph* input_graph)
    : _prev(nullptr), _mg(mined_graph), _ig(input_graph), _mg_edge(mined_edge),
      _ig_edge(input_edge), _ig_vertices(), _ig_edges(), _mg_vertices(),
      _mg_edges(), _edge_flags()
{
    MinedGraphVertIdMap mvi = get(boost::vertex_index_t(), *_mg);
    InputGraphVertIdMap ivi = get(boost::vertex_index_t(), *_ig);
    InputGraphEdgeIdMap iei = get(boost::edge_index_t(), *_ig);

    // map Mined graph vertex to Input graph vertex
    _ig_vertices.resize(2);
    _ig_vertices[get(mvi, source(_mg_edge, *_mg))] = source(_ig_edge, *_ig);
    _ig_vertices[get(mvi, target(_mg_edge, *_mg))] = target(_ig_edge, *_ig);

    // map Mined graph edge to Input graph edge
    _ig_edges.push_back(_ig_edge);

    // map Input graph vertex to Mined graph vertex
    _mg_vertices.resize(num_vertices(*_ig), InputGraph::null_vertex());
    _mg_vertices[get(ivi, source(_ig_edge, *_ig))] = source(_mg_edge, *_mg);
    _mg_vertices[get(ivi, target(_ig_edge, *_ig))] = target(_mg_edge, *_mg);

    // map Input graph edge to Mined graph edge
    _mg_edges.resize(num_edges(
                         *_ig)); // value is default constructed MinedGraph::edge_descriptor
    _mg_edges[get(iei, _ig_edge)] = _mg_edge;

    _edge_flags.resize(num_edges(*_ig));
    _edge_flags[get(iei, _ig_edge)] = true;
}

//
// the all other edges
//
template <typename IG, typename MG>
subgraph_tree<IG, MG>::subgraph_tree(const typename MGT::edge_descriptor&
                                     mined_edge,
                                     const typename IGT::edge_descriptor& input_edge,
                                     const MinedGraph* mined_graph,
                                     const subgraph_tree* prev)
    : _prev(prev), _mg(mined_graph), _ig(prev->_ig), _mg_edge(mined_edge),
      _ig_edge(input_edge), _ig_vertices(prev->_ig_vertices),
      _ig_edges(prev->_ig_edges), _mg_vertices(prev->_mg_vertices),
      _mg_edges(prev->_mg_edges), _edge_flags(prev->_edge_flags)
{
    MinedGraphVertIdMap mvi = get(boost::vertex_index_t(), *_mg);
    InputGraphVertIdMap ivi = get(boost::vertex_index_t(), *_ig);
    InputGraphEdgeIdMap iei = get(boost::edge_index_t(), *_ig);

    BOOST_ASSERT(get(mvi, target(_mg_edge, *_mg)) <= _ig_vertices.size());

    // map Mined graph vertex to Input graph vertex
    if (get(mvi, target(_mg_edge, *_mg)) == _ig_vertices.size()) {
        _ig_vertices.resize(_ig_vertices.size() + 1);
        _ig_vertices[get(mvi, target(_mg_edge, *_mg))] = target(_ig_edge, *_ig);
    }

    // map Mined graph edge to Input graph edge
    _ig_edges.push_back(_ig_edge);

    // map Input graph vertex to Mined graph vertex
    _mg_vertices[get(ivi, source(_ig_edge, *_ig))] = source(_mg_edge, *_mg);
    _mg_vertices[get(ivi, target(_ig_edge, *_ig))] = target(_mg_edge, *_mg);

    // map Input graph edge to Mined graph edge
    _mg_edges[get(iei, _ig_edge)] = _mg_edge;

    _edge_flags[get(iei, _ig_edge)] = true;
}

template <typename IG, typename MG>
typename subgraph_tree<IG, MG>::Mined2InputVertMap
subgraph_tree<IG, MG>::m2i_vert_map() const
{
    return Mined2InputVertMap(_ig_vertices.begin(),
                              get(boost::vertex_index_t(), *_mg));
}

template <typename IG, typename MG>
typename subgraph_tree<IG, MG>::Mined2InputEdgeMap
subgraph_tree<IG, MG>::m2i_edge_map() const
{
    return Mined2InputEdgeMap(_ig_edges.begin(),
                              get(boost::edge_index_t(), *_mg));
}

template <typename IG, typename MG>
typename subgraph_tree<IG, MG>::Input2MinedVertMap
subgraph_tree<IG, MG>::i2m_vert_map() const
{
    return Input2MinedVertMap(_mg_vertices.begin(),
                              get(boost::vertex_index_t(), *_ig));
}

template <typename IG, typename MG>
typename subgraph_tree<IG, MG>::Input2MinedEdgeMap
subgraph_tree<IG, MG>::i2m_edge_map() const
{
    return Input2MinedEdgeMap(_mg_edges.begin(),
                              get(boost::edge_index_t(), *_ig));
}

template <typename IG, typename MG>
bool
subgraph_tree<IG, MG>::is_automorphic(const subgraph_tree& lhs,
                                      const subgraph_tree& rhs)
{
    if (lhs._ig != rhs._ig)
        return false;
    BOOST_ASSERT(lhs._edge_flags.size() == rhs._edge_flags.size());
    return lhs._edge_flags == rhs._edge_flags;
}

template <typename IG, typename MG>
bool
is_automorphic(const subgraph_tree<IG, MG>& lhs,
               const subgraph_tree<IG, MG>& rhs)
{
    return subgraph_tree<IG, MG>::is_automorphic(lhs, rhs);
}

template <typename IG, typename MG>
bool
is_automorphic(const subgraph_tree<IG, MG>* lhs,
               const subgraph_tree<IG, MG>* rhs)
{
    return is_automorphic(*lhs, *rhs);
}

template <typename SBG, typename MGV>
auto
get_v_ig(const SBG& s, MGV&& v_mg)
{
    return get(s.m2i_vert_map(), v_mg);
}

template <typename SBG, typename MGE>
auto
get_e_ig(const SBG& s, MGE&& e_mg)
{
    return get(s.m2i_edge_map(), e_mg);
}

template <typename SBG, typename IGV>
auto
get_v_mg(const SBG& s, IGV&& v_ig)
{
    return get(s.i2m_vert_map(), v_ig);
}

template <typename SBG, typename IGE>
auto
get_e_mg(const SBG& s, IGE&& e_ig)
{
    return get(s.i2m_edge_map(), e_ig);
}

} // end namespace gspan

#endif

ext: hpp

max_stars_repo_name: dtchuink/DFG-Pattern-Generator

max_issues_repo_name: dtchuink/DFG-Pattern-Generator

max_forks_repo_name: dtchuink/DFG-Pattern-Generator


text:
/*
 * This file is part of the statismo library.
 *
 * Author: Marcel Luethi (marcel.luethi@unibas.ch)
 *
 * Copyright (c) 2011 University of Basel
 * All rights reserved.
 *
 * 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 of conditions 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 materials provided with the distribution.
 *
 * Neither the name of the project's author nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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.
 *
 */

#ifndef __PCAModelBuilder_TXX
#define __PCAModelBuilder_TXX

#include "PCAModelBuilder.h"

#include <iostream>

#include <Eigen/SVD>
#include <Eigen/Eigenvalues>

#include "CommonTypes.h"
#include "Exceptions.h"

namespace statismo {

template <typename T>
PCAModelBuilder<T>::PCAModelBuilder()
    : Superclass() {
}

template <typename T>
typename PCAModelBuilder<T>::StatisticalModelType*
PCAModelBuilder<T>::BuildNewModel(const DataItemListType& sampleDataList, double noiseVariance, bool computeScores, EigenValueMethod method) const {

    unsigned n = sampleDataList.size();
    if (n <= 0) {
        throw StatisticalModelException("Provided empty sample set. Cannot build the sample matrix");
    }

    unsigned p = sampleDataList.front()->GetSampleVector().rows();
    const Representer<T>* representer = sampleDataList.front()->GetRepresenter();

    // Compute the mean vector mu
    VectorType mu = VectorType::Zero(p);

    for (typename DataItemListType::const_iterator it = sampleDataList.begin();
            it != sampleDataList.end();  ++it) {
        assert((*it)->GetSampleVector().rows() == p); // all samples must have same number of rows
        assert((*it)->GetRepresenter() == representer); // all samples have the same representer
        mu += (*it)->GetSampleVector();
    }
    mu /= n;

    // Build the mean free sample matrix X0
    MatrixType X0(n, p);
    unsigned i = 0;
    for (typename DataItemListType::const_iterator it = sampleDataList.begin();
            it != sampleDataList.end(); ++it) {
        X0.row(i++) = (*it)->GetSampleVector() - mu;
    }

    // build the model
    StatisticalModelType* model = BuildNewModelInternal(representer, X0, mu, noiseVariance, method);

    // compute the scores if requested
    MatrixType scores;
    if (computeScores) {
        scores = this->ComputeScores(sampleDataList, model);
    }

    typename BuilderInfo::ParameterInfoList bi;
    bi.push_back(BuilderInfo::KeyValuePair("NoiseVariance ", Utils::toString(noiseVariance)));

    typename BuilderInfo::DataInfoList dataInfo;
    i = 0;
    for (typename DataItemListType::const_iterator it = sampleDataList.begin();
            it != sampleDataList.end();
            ++it, i++) {
        std::ostringstream os;
        os << "URI_" << i;
        dataInfo.push_back(BuilderInfo::KeyValuePair(os.str().c_str(),(*it)->GetDatasetURI()));
    }

    // finally add meta data to the model info
    BuilderInfo builderInfo("PCAModelBuilder", dataInfo, bi);

    ModelInfo::BuilderInfoList biList;
    biList.push_back(builderInfo);

    ModelInfo info(scores, biList);
    model->SetModelInfo(info);

    return model;
}

template <typename T>
typename PCAModelBuilder<T>::StatisticalModelType*
PCAModelBuilder<T>::BuildNewModelInternal(const Representer<T>* representer, const MatrixType& X0, const VectorType& mu,
        double noiseVariance, EigenValueMethod method) const {

    unsigned n = X0.rows();
    unsigned p = X0.cols();

    switch(method) {
    case JacobiSVD:

        typedef Eigen::JacobiSVD<MatrixType> SVDType;
        typedef Eigen::JacobiSVD<MatrixTypeDoublePrecision> SVDDoublePrecisionType;

        // We destinguish the case where we have more variables than samples and
        // the case where we have more samples than variable.
        // In the first case we compute the (smaller) inner product matrix instead of the full covariance matrix.
        // It is known that this has the same non-zero singular values as the covariance matrix.
        // Furthermore, it is possible to compute the corresponding eigenvectors of the covariance matrix from the
        // decomposition.

        if (n < p) {
            // we compute the eigenvectors of the covariance matrix by computing an SVD of the
            // n x n inner product matrix 1/(n-1) X0X0^T
            MatrixType Cov = X0 * X0.transpose() * 1.0/(n-1);
            SVDDoublePrecisionType SVD(Cov.cast<double>(), Eigen::ComputeThinV);
            VectorType singularValues = SVD.singularValues().cast<ScalarType>();
            MatrixType V = SVD.matrixV().cast<ScalarType>();

            unsigned numComponentsAboveTolerance = ((singularValues.array() - noiseVariance - Superclass::TOLERANCE) > 0).count();

            // there can be at most n-1 nonzero singular values in this case. Everything else must be due to numerical inaccuracies
            unsigned numComponentsToKeep = std::min(numComponentsAboveTolerance, n - 1);
            // compute the pseudo inverse of the square root of the singular values
            // which is then needed to recompute the PCA basis
            VectorType singSqrt = singularValues.array().sqrt();
            VectorType singSqrtInv = VectorType::Zero(singSqrt.rows());
            for (unsigned i = 0; i < numComponentsToKeep; i++) {
                assert(singSqrt(i) > Superclass::TOLERANCE);
                singSqrtInv(i) = 1.0 / singSqrt(i);
            }

            if (numComponentsToKeep == 0) {
                throw StatisticalModelException("All the eigenvalues are below the given tolerance. Model cannot be built.");
            }

            // we recover the eigenvectors U of the full covariance matrix from the eigenvectors V of the inner product matrix.
            // We use the fact that if we decompose X as X=UDV^T, then we get X^TX = UD^2U^T and XX^T = VD^2V^T (exploiting the orthogonormality
            // of the matrix U and V from the SVD). The additional factor sqrt(n-1) is to compensate for the 1/sqrt(n-1) in the formula
            // for the covariance matrix.

            MatrixType pcaBasis = X0.transpose() * V * singSqrtInv.asDiagonal();
            pcaBasis /= sqrt(n - 1.0);
            pcaBasis.conservativeResize(Eigen::NoChange, numComponentsToKeep);

            VectorType sampleVarianceVector = singularValues.topRows(numComponentsToKeep);
            VectorType pcaVariance = (sampleVarianceVector - VectorType::Ones(numComponentsToKeep) * noiseVariance);

            StatisticalModelType* model = StatisticalModelType::Create(representer, mu, pcaBasis, pcaVariance, noiseVariance);

            return model;
        } else {
            // we compute an SVD of the full p x p  covariance matrix 1/(n-1) X0^TX0 directly
            SVDType SVD(X0.transpose() * X0, Eigen::ComputeThinU);
            VectorType singularValues = SVD.singularValues();
            singularValues /= (n - 1.0);
            unsigned numComponentsToKeep = ((singularValues.array() - noiseVariance - Superclass::TOLERANCE) > 0).count();
            MatrixType pcaBasis = SVD.matrixU();

            pcaBasis.conservativeResize(Eigen::NoChange, numComponentsToKeep);

            if (numComponentsToKeep == 0) {
                throw StatisticalModelException("All the eigenvalues are below the given tolerance. Model cannot be built.");
            }

            VectorType sampleVarianceVector = singularValues.topRows(numComponentsToKeep);
            VectorType pcaVariance = (sampleVarianceVector - VectorType::Ones(numComponentsToKeep) * noiseVariance);
            StatisticalModelType* model = StatisticalModelType::Create(representer, mu, pcaBasis, pcaVariance, noiseVariance);
            return model;
        }
        break;

    case SelfAdjointEigenSolver: {
        // we compute the eigenvalues/eigenvectors of the full p x p  covariance matrix 1/(n-1) X0^TX0 directly

        typedef Eigen::SelfAdjointEigenSolver<MatrixType> SelfAdjointEigenSolver;
        SelfAdjointEigenSolver es;
        es.compute(X0.transpose() * X0);
        VectorType eigenValues = es.eigenvalues().reverse(); // SelfAdjointEigenSolver orders the eigenvalues in increasing order
        eigenValues /= (n -1.0);

        unsigned numComponentsToKeep = ((eigenValues.array() - noiseVariance - Superclass::TOLERANCE) > 0).count();
        MatrixType pcaBasis = es.eigenvectors().rowwise().reverse();
        pcaBasis.conservativeResize(Eigen::NoChange, numComponentsToKeep);

        if (numComponentsToKeep == 0) {
            throw StatisticalModelException("All the eigenvalues are below the given tolerance. Model cannot be built.");
        }

        VectorType sampleVarianceVector = eigenValues.topRows(numComponentsToKeep);
        VectorType pcaVariance = (sampleVarianceVector - VectorType::Ones(numComponentsToKeep) * noiseVariance);
        StatisticalModelType* model = StatisticalModelType::Create(representer, mu, pcaBasis, pcaVariance, noiseVariance);
        return model;
    }
    break;

    default:
        throw StatisticalModelException("Unrecognized decomposition/eigenvalue solver method.");
        return 0;
        break;
    }
}

} // namespace statismo

#endif

ext: hxx


text:
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/static_assert.hpp>

using namespace boost::python;

template <class T>
void assert_borrowed_ptr(T const& x)
{
    BOOST_STATIC_ASSERT(boost::python::detail::is_borrowed_ptr<T>::value);
}

template <class T>
void assert_not_borrowed_ptr(T const& x)
{
    BOOST_STATIC_ASSERT(!boost::python::detail::is_borrowed_ptr<T>::value);
}

int main()
{
    assert_borrowed_ptr(borrowed((PyObject*)0));
    assert_borrowed_ptr(borrowed((PyTypeObject*)0));
    assert_borrowed_ptr((detail::borrowed<PyObject> const*)0);
    assert_borrowed_ptr((detail::borrowed<PyObject> volatile*)0);
    assert_borrowed_ptr((detail::borrowed<PyObject> const volatile*)0);
    assert_not_borrowed_ptr((PyObject*)0);
    assert_not_borrowed_ptr(0);
    return 0;
}


text:
/*
 * @Description: 前端里程计算法
 * @Author: Ren Qian
 * @Date: 2020-02-04 18:53:06
 */
#include "lidar_localization/front_end/front_end.hpp"

#include <fstream>
#include <boost/filesystem.hpp>
#include <pcl/common/transforms.h>
#include <pcl/io/pcd_io.h>
#include "glog/logging.h"

#include "lidar_localization/global_defination/global_defination.h"

namespace lidar_localization {
FrontEnd::FrontEnd()
    :local_map_ptr_(new CloudData::CLOUD()),
     global_map_ptr_(new CloudData::CLOUD()),
     result_cloud_ptr_(new CloudData::CLOUD()) {

    InitWithConfig();
}

bool FrontEnd::InitWithConfig() {
    std::string config_file_path = WORK_SPACE_PATH + "/config/front_end/config.yaml";
    YAML::Node config_node = YAML::LoadFile(config_file_path);

    InitDataPath(config_node);
    InitRegistration(registration_ptr_, config_node);
    InitFilter("local_map", local_map_filter_ptr_, config_node);
    InitFilter("frame", frame_filter_ptr_, config_node);
    InitFilter("display", display_filter_ptr_, config_node);

    return true;
}

bool FrontEnd::InitParam(const YAML::Node& config_node) {
    key_frame_distance_ = config_node["key_frame_distance"].as<float>();
    local_frame_num_ = config_node["local_frame_num"].as<int>();

    return true;
}

bool FrontEnd::InitDataPath(const YAML::Node& config_node) {
    data_path_ = config_node["data_path"].as<std::string>();
    if (data_path_ == "./") {
        data_path_ = WORK_SPACE_PATH;
    }
    data_path_ += "/slam_data";

    if (boost::filesystem::is_directory(data_path_)) {
        boost::filesystem::remove_all(data_path_);
    }

    boost::filesystem::create_directory(data_path_);
    if (!boost::filesystem::is_directory(data_path_)) {
        LOG(WARNING) << "Cannot create directory " << data_path_ << "!";
        return false;
    } else {
        LOG(INFO) << "Point Cloud Map Output Path: " << data_path_;
    }

    std::string key_frame_path = data_path_ + "/key_frames";
    boost::filesystem::create_directory(data_path_ + "/key_frames");
    if (!boost::filesystem::is_directory(key_frame_path)) {
        LOG(WARNING) << "Cannot create directory " << key_frame_path << "!";
        return false;
    } else {
        LOG(INFO) << "Key Frames Output Path: " << key_frame_path << std::endl << std::endl;
    }

    return true;
}

bool FrontEnd::InitRegistration(std::shared_ptr<RegistrationInterface>& registration_ptr, const YAML::Node& config_node) {
    std::string registration_method = config_node["registration_method"].as<std::string>();
    LOG(INFO) << "Point Cloud Registration Method: " << registration_method;

    if (registration_method == "NDT") {
        registration_ptr = std::make_shared<NDTRegistration>(config_node[registration_method]);
    } else if (registration_method == "ICP") {
        registration_ptr = std::make_shared<ICPRegistration>(config_node[registration_method]);
    }
    /*
    TODO: register your custom implementation here
    else if (registration_method == "YOUR_CUSTOM_REGISTRATION_METHOD") {
        registration_ptr = nullptr;
    }
     */
    else {
        LOG(ERROR) << "Point cloud registration method " << registration_method << " NOT FOUND!";
        return false;
    }

    return true;
}

bool FrontEnd::InitFilter(std::string filter_user, std::shared_ptr<CloudFilterInterface>& filter_ptr, const YAML::Node& config_node) {
    std::string filter_mothod = config_node[filter_user + "_filter"].as<std::string>();
    LOG(INFO) << filter_user << "Point Cloud Filter Method: " << filter_mothod;

    if (filter_mothod == "voxel_filter") {
        filter_ptr = std::make_shared<VoxelFilter>(config_node[filter_mothod][filter_user]);
    } else {
        LOG(ERROR) << "Point cloud filter method " << filter_mothod << " NOT FOUND!";
        return false;
    }

    return true;
}

bool FrontEnd::Update(const CloudData& cloud_data, Eigen::Matrix4f& cloud_pose) {
    current_frame_.cloud_data.time = cloud_data.time;
    std::vector<int> indices;
    pcl::removeNaNFromPointCloud(*cloud_data.cloud_ptr, *current_frame_.cloud_data.cloud_ptr, indices);

    CloudData::CLOUD_PTR filtered_cloud_ptr(new CloudData::CLOUD());
    frame_filter_ptr_->Filter(current_frame_.cloud_data.cloud_ptr, filtered_cloud_ptr);

    static Eigen::Matrix4f step_pose = Eigen::Matrix4f::Identity();
    static Eigen::Matrix4f last_pose = init_pose_;
    static Eigen::Matrix4f predict_pose = init_pose_;
    static Eigen::Matrix4f last_key_frame_pose = init_pose_;

    // 局部地图容器中没有关键帧，代表是第一帧数据
    // 此时把当前帧数据作为第一个关键帧，并更新局部地图容器和全局地图容器
    if (local_map_frames_.size() == 0) {
        current_frame_.pose = init_pose_;
        UpdateWithNewFrame(current_frame_);
        cloud_pose = current_frame_.pose;
        return true;
    }

    // 不是第一帧，就正常匹配
    registration_ptr_->ScanMatch(filtered_cloud_ptr, predict_pose, result_cloud_ptr_, current_frame_.pose);
    cloud_pose = current_frame_.pose;

    // 更新相邻两帧的相对运动
    step_pose = last_pose.inverse() * current_frame_.pose;
    predict_pose = current_frame_.pose * step_pose;
    last_pose = current_frame_.pose;

    // 匹配之后根据距离判断是否需要生成新的关键帧，如果需要，则做相应更新
    if (fabs(last_key_frame_pose(0,3) - current_frame_.pose(0,3)) +
        fabs(last_key_frame_pose(1,3) - current_frame_.pose(1,3)) +
        fabs(last_key_frame_pose(2,3) - current_frame_.pose(2,3)) > key_frame_distance_) {
        UpdateWithNewFrame(current_frame_);
        last_key_frame_pose = current_frame_.pose;
    }

    return true;
}

bool FrontEnd::SetInitPose(const Eigen::Matrix4f& init_pose) {
    init_pose_ = init_pose;
    return true;
}

bool FrontEnd::UpdateWithNewFrame(const Frame& new_key_frame) {
    // 把关键帧点云存储到硬盘里，节省内存
    std::string file_path = data_path_ + "/key_frames/key_frame_" + std::to_string(global_map_frames_.size()) + ".pcd";
    pcl::io::savePCDFileBinary(file_path, *new_key_frame.cloud_data.cloud_ptr);

    Frame key_frame = new_key_frame;
    // 这一步的目的是为了把关键帧的点云保存下来
    // 由于用的是共享指针，所以直接复制只是复制了一个指针而已
    // 此时无论你放多少个关键帧在容器里，这些关键帧点云指针都是指向的同一个点云
    key_frame.cloud_data.cloud_ptr.reset(new CloudData::CLOUD(*new_key_frame.cloud_data.cloud_ptr));
    CloudData::CLOUD_PTR transformed_cloud_ptr(new CloudData::CLOUD());

    // 更新局部地图
    local_map_frames_.push_back(key_frame);
    while (local_map_frames_.size() > static_cast<size_t>(local_frame_num_)) {
        local_map_frames_.pop_front();
    }
    local_map_ptr_.reset(new CloudData::CLOUD());
    for (size_t i = 0; i < local_map_frames_.size(); ++i) {
        pcl::transformPointCloud(*local_map_frames_.at(i).cloud_data.cloud_ptr,
                                 *transformed_cloud_ptr,
                                 local_map_frames_.at(i).pose);
        *local_map_ptr_ += *transformed_cloud_ptr;
    }
    has_new_local_map_ = true;

    // 更新ndt匹配的目标点云
    // 关键帧数量还比较少的时候不滤波，因为点云本来就不多，太稀疏影响匹配效果
    if (local_map_frames_.size() < 10) {
        registration_ptr_->SetInputTarget(local_map_ptr_);
    } else {
        CloudData::CLOUD_PTR filtered_local_map_ptr(new CloudData::CLOUD());
        local_map_filter_ptr_->Filter(local_map_ptr_, filtered_local_map_ptr);
        registration_ptr_->SetInputTarget(filtered_local_map_ptr);
    }

    // 保存所有关键帧信息在容器里
    // 存储之前，点云要先释放，因为已经存到了硬盘里，不释放也达不到节省内存的目的
    key_frame.cloud_data.cloud_ptr.reset(new CloudData::CLOUD());
    global_map_frames_.push_back(key_frame);

    return true;
}

bool FrontEnd::SaveMap() {
    global_map_ptr_.reset(new CloudData::CLOUD());

    std::string key_frame_path = "";
    CloudData::CLOUD_PTR key_frame_cloud_ptr(new CloudData::CLOUD());
    CloudData::CLOUD_PTR transformed_cloud_ptr(new CloudData::CLOUD());

    for (size_t i = 0; i < global_map_frames_.size(); ++i) {
        key_frame_path = data_path_ + "/key_frames/key_frame_" + std::to_string(i) + ".pcd";
        pcl::io::loadPCDFile(key_frame_path, *key_frame_cloud_ptr);

        pcl::transformPointCloud(*key_frame_cloud_ptr,
                                *transformed_cloud_ptr,
                                global_map_frames_.at(i).pose);
        *global_map_ptr_ += *transformed_cloud_ptr;
    }

    std::string map_file_path = data_path_ + "/map.pcd";
    pcl::io::savePCDFileBinary(map_file_path, *global_map_ptr_);
    has_new_global_map_ = true;

    return true;
}

bool FrontEnd::GetNewLocalMap(CloudData::CLOUD_PTR& local_map_ptr) {
    if (has_new_local_map_) {
        display_filter_ptr_->Filter(local_map_ptr_, local_map_ptr);
        return true;
    }
    return false;
}

bool FrontEnd::GetNewGlobalMap(CloudData::CLOUD_PTR& global_map_ptr) {
    if (has_new_global_map_) {
        has_new_global_map_ = false;
        display_filter_ptr_->Filter(global_map_ptr_, global_map_ptr);
        global_map_ptr_.reset(new CloudData::CLOUD());
        return true;
    }
    return false;
}

bool FrontEnd::GetCurrentScan(CloudData::CLOUD_PTR& current_scan_ptr) {
    display_filter_ptr_->Filter(result_cloud_ptr_, current_scan_ptr);
    return true;
}
}


text:
#ifndef DATE_TIME_TZ_DB_BASE_HPP__
#define DATE_TIME_TZ_DB_BASE_HPP__

/* Copyright (c) 2003-2005 CrystalClear Software, Inc.
 * Subject to the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 * Author: Jeff Garland, Bart Garst
 * $Date$
 */

#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include <boost/tokenizer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/date_time/compiler_config.hpp>
#include <boost/date_time/time_zone_names.hpp>
#include <boost/date_time/time_zone_base.hpp>
#include <boost/date_time/time_parsing.hpp>

namespace boost {
  namespace date_time {

    //! Exception thrown when tz database cannot locate requested data file
    class data_not_accessible : public std::logic_error
    {
     public:
       data_not_accessible() :
         std::logic_error(std::string("Unable to locate or access the required datafile."))
       {}
       data_not_accessible(const std::string& filespec) :
         std::logic_error(std::string("Unable to locate or access the required datafile. Filespec: " + filespec))
       {}
    };

    //! Exception thrown when tz database locates incorrect field structure in data file
    class bad_field_count : public std::out_of_range
    {
     public:
       bad_field_count(const std::string& s) :
         std::out_of_range(s)
      {}
    };

    //! Creates a database of time_zones from csv datafile
    /*! The csv file containing the zone_specs used by the
     * tz_db_base is intended to be customized by the
     * library user. When customizing this file (or creating your own) the
     * file must follow a specific format.
     *
     * This first line is expected to contain column headings and is therefore
     * not processed by the tz_db_base.
     *
     * Each record (line) must have eleven fields. Some of those fields can
     * be empty. Every field (even empty ones) must be enclosed in
     * double-quotes.
     * Ex:
     * @code
     * "America/Phoenix" <- string enclosed in quotes
     * ""                <- empty field
     * @endcode
     *
     * Some fields represent a length of time. The format of these fields
     * must be:
     * @code
     * "{+|-}hh:mm[:ss]" <- length-of-time format
     * @endcode
     * Where the plus or minus is mandatory and the seconds are optional.
     *
     * Since some time zones do not use daylight savings it is not always
     * necessary for every field in a zone_spec to contain a value. All
     * zone_specs must have at least ID and GMT offset. Zones that use
     * daylight savings must have all fields filled except:
     * STD ABBR, STD NAME, DST NAME. You should take note
     * that DST ABBR is mandatory for zones that use daylight savings
     * (see field descriptions for further details).
     *
     * ******* Fields and their description/details *********
     *
     * ID:
     * Contains the identifying string for the zone_spec. Any string will
     * do as long as it's unique. No two ID's can be the same.
     *
     * STD ABBR:
     * STD NAME:
     * DST ABBR:
     * DST NAME:
     * These four are all the names and abbreviations used by the time
     * zone being described. While any string will do in these fields,
     * care should be taken. These fields hold the strings that will be
     * used in the output of many of the local_time classes.
     * Ex:
     * @code
     * time_zone nyc = tz_db.time_zone_from_region("America/New_York");
     * local_time ny_time(date(2004, Aug, 30), IS_DST, nyc);
     * cout << ny_time.to_long_string() << endl;
     * // 2004-Aug-30 00:00:00 Eastern Daylight Time
     * cout << ny_time.to_short_string() << endl;
     * // 2004-Aug-30 00:00:00 EDT
     * @endcode
     *
     * NOTE: The exact format/function names may vary - see local_time
     * documentation for further details.
     *
     * GMT offset:
     * This is the number of hours added to utc to get the local time
     * before any daylight savings adjustments are made. Some examples
     * are: America/New_York offset -5 hours, & Africa/Cairo offset +2 hours.
     * The format must follow the length-of-time format described above.
     *
     * DST adjustment:
     * The amount of time added to gmt_offset when daylight savings is in
     * effect. The format must follow the length-of-time format described
     * above.
     *
     * DST Start Date rule:
     * This is a specially formatted string that describes the day of year
     * in which the transition take place. It holds three fields of it's own,
     * separated by semicolons.
     * The first field indicates the "nth" weekday of the month. The possible
     * values are: 1 (first), 2 (second), 3 (third), 4 (fourth), 5 (fifth),
     * and -1 (last).
     * The second field indicates the day-of-week from 0-6 (Sun=0).
     * The third field indicates the month from 1-12 (Jan=1).
     *
     * Examples are: "-1;5;9"="Last Friday of September",
     * "2;1;3"="Second Monday of March"
     *
     * Start time:
     * Start time is the number of hours past midnight, on the day of the
     * start transition, the transition takes place. More simply put, the
     * time of day the transition is made (in 24 hours format). The format
     * must follow the length-of-time format described above with the
     * exception that it must always be positive.
     *
     * DST End date rule:
     * See DST Start date rule. The difference here is this is the day
     * daylight savings ends (transition to STD).
     *
     * End time:
     * Same as Start time.
     */
    template<class time_zone_type, class rule_type>
    class tz_db_base {
    public:
      /* Having CharT as a template parameter created problems
       * with posix_time::duration_from_string. Templatizing
       * duration_from_string was not possible at this time, however,
       * it should be possible in the future (when poor compilers get
       * fixed or stop being used).
       * Since this class was designed to use CharT as a parameter it
       * is simply typedef'd here to ease converting in back to a
       * parameter the future */
      typedef char char_type;

      typedef typename time_zone_type::base_type time_zone_base_type;
      typedef typename time_zone_type::time_duration_type time_duration_type;
      typedef time_zone_names_base<char_type> time_zone_names;
      typedef boost::date_time::dst_adjustment_offsets<time_duration_type> dst_adjustment_offsets;
      typedef std::basic_string<char_type> string_type;

      //! Constructs an empty database
      tz_db_base() {}

      //! Process csv data file, may throw exceptions
      /*! May throw bad_field_count exceptions */
      void load_from_stream(std::istream &in)
      {
        std::string  buff;
        while( std::getline(in, buff)) {
          parse_string(buff);
        }
      }

      //! Process csv data file, may throw exceptions
      /*! May throw data_not_accessible, or bad_field_count exceptions */
      void load_from_file(const std::string& pathspec)
      {
        std::string  buff;

        std::ifstream ifs(pathspec.c_str());
        if(!ifs){
          boost::throw_exception(data_not_accessible(pathspec));
        }
        std::getline(ifs, buff); // first line is column headings
        this->load_from_stream(ifs);
      }

      //! returns true if record successfully added to map
      /*! Takes a region name in the form of "America/Phoenix", and a
       * time_zone object for that region. The id string must be a unique
       * name that does not already exist in the database. */
      bool add_record(const string_type& region,
                      boost::shared_ptr<time_zone_base_type> tz)
      {
        typename map_type::value_type p(region, tz);
        return (m_zone_map.insert(p)).second;
      }

      //! Returns a time_zone object built from the specs for the given region
      /*! Returns a time_zone object built from the specs for the given
       * region. If region does not exist a local_time::record_not_found
       * exception will be thrown */
      boost::shared_ptr<time_zone_base_type>
      time_zone_from_region(const string_type& region) const
      {
        // get the record
        typename map_type::const_iterator record = m_zone_map.find(region);
        if(record == m_zone_map.end()){
          return boost::shared_ptr<time_zone_base_type>(); //null pointer
        }
        return record->second;
      }

      //! Returns a vector of strings holding the time zone regions in the database
      std::vector<std::string> region_list() const
      {
        typedef std::vector<std::string> vector_type;
        vector_type regions;
        typename map_type::const_iterator itr = m_zone_map.begin();
        while(itr != m_zone_map.end()) {
          regions.push_back(itr->first);
          ++itr;
        }
        return regions;
      }

    private:
      typedef std::map<string_type, boost::shared_ptr<time_zone_base_type> > map_type;
      map_type m_zone_map;

      // start and end rule are of the same type
      typedef typename rule_type::start_rule::week_num week_num;

      /* TODO: mechanisms need to be put in place to handle different
       * types of rule specs. parse_rules() only handles nth_kday
       * rule types. */

      //! parses rule specs for transition day rules
      rule_type* parse_rules(const string_type& sr, const string_type& er) const
      {
        using namespace gregorian;
        // start and end rule are of the same type,
        // both are included here for readability
        typedef typename rule_type::start_rule start_rule;
        typedef typename rule_type::end_rule end_rule;

        // these are: [start|end] nth, day, month
        int s_nth = 0, s_d = 0, s_m = 0;
        int e_nth = 0, e_d = 0, e_m = 0;
        split_rule_spec(s_nth, s_d, s_m, sr);
        split_rule_spec(e_nth, e_d, e_m, er);

        typename start_rule::week_num s_wn, e_wn;
        s_wn = get_week_num(s_nth);
        e_wn = get_week_num(e_nth);

        return new rule_type(start_rule(s_wn,
                                        static_cast<unsigned short>(s_d),
                                        static_cast<unsigned short>(s_m)),
                             end_rule(e_wn,
                                      static_cast<unsigned short>(e_d),
                                      static_cast<unsigned short>(e_m)));
      }
      //! helper function for parse_rules()
      week_num get_week_num(int nth) const
      {
        typedef typename rule_type::start_rule start_rule;
        switch(nth){
        case 1:
          return start_rule::first;
        case 2:
          return start_rule::second;
        case 3:
          return start_rule::third;
        case 4:
          return start_rule::fourth;
        case 5:
        case -1:
          return start_rule::fifth;
        default:
          // shouldn't get here - add error handling later
          break;
        }
        return start_rule::fifth; // silence warnings
      }

      //! splits the [start|end]_date_rule string into 3 ints
      void split_rule_spec(int& nth, int& d, int& m, string_type rule) const
      {
        typedef boost::char_separator<char_type, std::char_traits<char_type> > char_separator_type;
        typedef boost::tokenizer<char_separator_type,
                                 std::basic_string<char_type>::const_iterator,
                                 std::basic_string<char_type> > tokenizer;
        typedef boost::tokenizer<char_separator_type,
                                 std::basic_string<char_type>::const_iterator,
                                 std::basic_string<char_type> >::iterator tokenizer_iterator;

        const char_type sep_char[] = { ';', '\0'};
        char_separator_type sep(sep_char);
        tokenizer tokens(rule, sep); // 3 fields

        if ( std::distance ( tokens.begin(), tokens.end ()) != 3 ) {
          std::ostringstream msg;
          msg << "Expecting 3 fields, got "
              << std::distance ( tokens.begin(), tokens.end ())
              << " fields in line: " << rule;
          boost::throw_exception(bad_field_count(msg.str()));
        }

        tokenizer_iterator tok_iter = tokens.begin();
        nth = std::atoi(tok_iter->c_str()); ++tok_iter;
        d   = std::atoi(tok_iter->c_str()); ++tok_iter;
        m   = std::atoi(tok_iter->c_str());
      }

      //! Take a line from the csv, turn it into a time_zone_type.
      /*! Take a line from the csv, turn it into a time_zone_type,
       * and add it to the map. Zone_specs in csv file are expected to
       * have eleven fields that describe the time zone. Returns true if
       * zone_spec successfully added to database */
      bool parse_string(string_type& s)
      {
        std::vector<string_type> result;
        typedef boost::token_iterator_generator<boost::escaped_list_separator<char_type>, string_type::const_iterator, string_type >::type token_iter_type;

        token_iter_type i = boost::make_token_iterator<string_type>(s.begin(), s.end(),boost::escaped_list_separator<char_type>());

        token_iter_type end;
        while (i != end) {
          result.push_back(*i);
          i++;
        }

        enum db_fields { ID, STDABBR, STDNAME, DSTABBR, DSTNAME, GMTOFFSET,
                         DSTADJUST, START_DATE_RULE, START_TIME, END_DATE_RULE,
                         END_TIME, FIELD_COUNT };

        //take a shot at fixing gcc 4.x error
        const unsigned int expected_fields = static_cast<unsigned int>(FIELD_COUNT);
        if (result.size() != expected_fields) {
          std::ostringstream msg;
          msg << "Expecting " << FIELD_COUNT << " fields, got "
            << result.size() << " fields in line: " << s;
          boost::throw_exception(bad_field_count(msg.str()));
          BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return false); // should never reach
        }

        // initializations
        bool has_dst = true;
        if(result[DSTABBR] == std::string()){
          has_dst = false;
        }

        // start building components of a time_zone
        time_zone_names names(result[STDNAME], result[STDABBR],
                              result[DSTNAME], result[DSTABBR]);

        time_duration_type utc_offset =
          str_from_delimited_time_duration<time_duration_type,char_type>(result[GMTOFFSET]);

        dst_adjustment_offsets adjust(time_duration_type(0,0,0),
                                      time_duration_type(0,0,0),
                                      time_duration_type(0,0,0));

        boost::shared_ptr<rule_type> rules;

        if(has_dst){
          adjust = dst_adjustment_offsets(
                                          str_from_delimited_time_duration<time_duration_type,char_type>(result[DSTADJUST]),
                                          str_from_delimited_time_duration<time_duration_type,char_type>(result[START_TIME]),
                                          str_from_delimited_time_duration<time_duration_type,char_type>(result[END_TIME])
                                          );

          rules =
            boost::shared_ptr<rule_type>(parse_rules(result[START_DATE_RULE],
                                                     result[END_DATE_RULE]));
        }
        string_type id(result[ID]);
        boost::shared_ptr<time_zone_base_type> zone(new time_zone_type(names, utc_offset, adjust, rules));
        return (add_record(id, zone));

      }

    };

} } // namespace

#endif // DATE_TIME_TZ_DB_BASE_HPP__

max_stars_repo_name: sbrown-uhd/hazelcast-cpp-client

max_issues_repo_name: sbrown-uhd/hazelcast-cpp-client

max_forks_repo_name: sbrown-uhd/hazelcast-cpp-client


text:
//
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BEAST_HTTP_IMPL_SERIALIZER_IPP
#define BEAST_HTTP_IMPL_SERIALIZER_IPP

#include <beast/core/detail/buffers_ref.hpp>
#include <beast/http/error.hpp>
#include <beast/http/status.hpp>
#include <beast/core/detail/config.hpp>
#include <boost/assert.hpp>
#include <ostream>

namespace beast {
namespace http {

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
void
serializer<isRequest, Body, Fields, ChunkDecorator>::
frdinit(std::true_type)
{
    frd_.emplace(m_, m_.version, m_.method());
}

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
void
serializer<isRequest, Body, Fields, ChunkDecorator>::
frdinit(std::false_type)
{
    frd_.emplace(m_, m_.version, m_.result_int());
}

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
template<class T1, class T2, class Visit>
inline
void
serializer<isRequest, Body, Fields, ChunkDecorator>::
do_visit(error_code& ec, Visit& visit)
{
    // VFALCO work-around for missing variant::emplace
    pv_.~variant();
    new(&pv_) decltype(pv_){
        T1{limit_, boost::get<T2>(v_)}};
    visit(ec, beast::detail::make_buffers_ref(
        boost::get<T1>(pv_)));
}

//------------------------------------------------------------------------------

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
serializer<isRequest, Body, Fields, ChunkDecorator>::
serializer(value_type& m)
    : m_(m)
    , rd_(m_)
{
}

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
serializer<isRequest, Body, Fields, ChunkDecorator>::
serializer(value_type& m, ChunkDecorator const& d)
    : m_(m)
    , rd_(m_)
    , d_(d)
{
}

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
template<class Visit>
void
serializer<isRequest, Body, Fields, ChunkDecorator>::
next(error_code& ec, Visit&& visit)
{
    using boost::asio::buffer_size;
    using beast::detail::make_buffers_ref;
    switch(s_)
    {
    case do_construct:
    {
        frdinit(std::integral_constant<bool,
            isRequest>{});
        keep_alive_ = m_.keep_alive();
        chunked_ = m_.chunked();
        if(chunked_)
            goto go_init_c;
        s_ = do_init;
        BEAST_FALLTHROUGH;
    }

    case do_init:
    {
        rd_.init(ec);
        if(ec)
            return;
        if(split_)
            goto go_header_only;
        auto result = rd_.get(ec);
        if(ec == error::need_more)
            goto go_header_only;
        if(ec)
            return;
        if(! result)
            goto go_header_only;
        more_ = result->second;
        v_ = cb2_t{
            boost::in_place_init,
            frd_->get(),
            result->first};
        s_ = do_header;
        BEAST_FALLTHROUGH;
    }

    case do_header:
        do_visit<pcb2_t, cb2_t>(ec, visit);
        break;

    go_header_only:
        v_ = cb1_t{frd_->get()};
        s_ = do_header_only;
    case do_header_only:
        do_visit<pcb1_t, cb1_t>(ec, visit);
        break;

    case do_body:
        s_ = do_body + 1;
        BEAST_FALLTHROUGH;

    case do_body + 1:
    {
        auto result = rd_.get(ec);
        if(ec)
            return;
        if(! result)
            goto go_complete;
        more_ = result->second;
        v_ = cb3_t{result->first};
        s_ = do_body + 2;
        BEAST_FALLTHROUGH;
    }

    case do_body + 2:
        do_visit<pcb3_t, cb3_t>(ec, visit);
        break;

    //----------------------------------------------------------------------

         go_init_c:
    s_ = do_init_c;
    case do_init_c:
    {
        rd_.init(ec);
        if(ec)
            return;
        if(split_)
            goto go_header_only_c;
        auto result = rd_.get(ec);
        if(ec == error::need_more)
            goto go_header_only_c;
        if(ec)
            return;
        if(! result)
            goto go_header_only_c;
        more_ = result->second;
    #ifndef BEAST_NO_BIG_VARIANTS
        if(! more_)
        {
            // do it all in one buffer
            v_ = cb7_t{
                boost::in_place_init,
                frd_->get(),
                detail::chunk_header{
                    buffer_size(result->first)},
                [&]()
                {
                    auto sv = d_(result->first);
                    return boost::asio::const_buffers_1{
                        sv.data(), sv.size()};

                }(),
                detail::chunk_crlf(),
                result->first,
                detail::chunk_crlf(),
                detail::chunk_final(),
                [&]()
                {
                    auto sv = d_(
                        boost::asio::null_buffers{});
                    return boost::asio::const_buffers_1{
                        sv.data(), sv.size()};

                }(),
                detail::chunk_crlf()};
            goto go_all_c;
        }
    #endif
        v_ = cb4_t{
            boost::in_place_init,
            frd_->get(),
            detail::chunk_header{
                buffer_size(result->first)},
            [&]()
            {
                auto sv = d_(result->first);
                return boost::asio::const_buffers_1{
                    sv.data(), sv.size()};

            }(),
            detail::chunk_crlf(),
            result->first,
            detail::chunk_crlf()};
        s_ = do_header_c;
        BEAST_FALLTHROUGH;
    }

    case do_header_c:
        do_visit<pcb4_t, cb4_t>(ec, visit);
        break;

    go_header_only_c:
        v_ = cb1_t{frd_->get()};
        s_ = do_header_only_c;
    case do_header_only_c:
        do_visit<pcb1_t, cb1_t>(ec, visit);
        break;

    case do_body_c:
        s_ = do_body_c + 1;
        BEAST_FALLTHROUGH;

    case do_body_c + 1:
    {
        auto result = rd_.get(ec);
        if(ec)
            return;
        if(! result)
            goto go_final_c;
        more_ = result->second;
    #ifndef BEAST_NO_BIG_VARIANTS
        if(! more_)
        {
            // do it all in one buffer
            v_ = cb6_t{
                boost::in_place_init,
                detail::chunk_header{
                    buffer_size(result->first)},
                [&]()
                {
                    auto sv = d_(result->first);
                    return boost::asio::const_buffers_1{
                        sv.data(), sv.size()};

                }(),
                detail::chunk_crlf(),
                result->first,
                detail::chunk_crlf(),
                detail::chunk_final(),
                [&]()
                {
                    auto sv = d_(
                        boost::asio::null_buffers{});
                    return boost::asio::const_buffers_1{
                        sv.data(), sv.size()};

                }(),
                detail::chunk_crlf()};
            goto go_body_final_c;
        }
    #endif
        v_ = cb5_t{
            boost::in_place_init,
            detail::chunk_header{
                buffer_size(result->first)},
            [&]()
            {
                auto sv = d_(result->first);
                return boost::asio::const_buffers_1{
                    sv.data(), sv.size()};

            }(),
            detail::chunk_crlf(),
            result->first,
            detail::chunk_crlf()};
        s_ = do_body_c + 2;
        BEAST_FALLTHROUGH;
    }

    case do_body_c + 2:
        do_visit<pcb5_t, cb5_t>(ec, visit);
        break;

#ifndef BEAST_NO_BIG_VARIANTS
    go_body_final_c:
        s_ = do_body_final_c;
    case do_body_final_c:
        do_visit<pcb6_t, cb6_t>(ec, visit);
        break;

    go_all_c:
        s_ = do_all_c;
    case do_all_c:
        do_visit<pcb7_t, cb7_t>(ec, visit);
        break;
#endif

    go_final_c:
    case do_final_c:
        v_ = cb8_t{
            boost::in_place_init,
            detail::chunk_final(),
            [&]()
            {
                auto sv = d_(
                    boost::asio::null_buffers{});
                return boost::asio::const_buffers_1{
                    sv.data(), sv.size()};

            }(),
            detail::chunk_crlf()};
        s_ = do_final_c + 1;
        BEAST_FALLTHROUGH;

    case do_final_c + 1:
        do_visit<pcb8_t, cb8_t>(ec, visit);
        break;

    //----------------------------------------------------------------------

    default:
    case do_complete:
        BOOST_ASSERT(false);
        break;

    go_complete:
        s_ = do_complete;
        break;
    }
}

template<bool isRequest, class Body,
    class Fields, class ChunkDecorator>
void
serializer<isRequest, Body, Fields, ChunkDecorator>::
consume(std::size_t n)
{
    using boost::asio::buffer_size;
    switch(s_)
    {
    case do_header:
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb2_t>(v_)));
        boost::get<cb2_t>(v_).consume(n);
        if(buffer_size(boost::get<cb2_t>(v_)) > 0)
            break;
        header_done_ = true;
        v_ = boost::blank{};
        if(! more_)
            goto go_complete;
        s_ = do_body + 1;
        break;

    case do_header_only:
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb1_t>(v_)));
        boost::get<cb1_t>(v_).consume(n);
        if(buffer_size(boost::get<cb1_t>(v_)) > 0)
            break;
        frd_ = boost::none;
        header_done_ = true;
        if(! split_)
            goto go_complete;
        s_ = do_body;
        break;

    case do_body + 2:
    {
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb3_t>(v_)));
        boost::get<cb3_t>(v_).consume(n);
        if(buffer_size(boost::get<cb3_t>(v_)) > 0)
            break;
        v_ = boost::blank{};
        if(! more_)
            goto go_complete;
        s_ = do_body + 1;
        break;
    }

    //----------------------------------------------------------------------

    case do_header_c:
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb4_t>(v_)));
        boost::get<cb4_t>(v_).consume(n);
        if(buffer_size(boost::get<cb4_t>(v_)) > 0)
            break;
        header_done_ = true;
        v_ = boost::blank{};
        if(more_)
            s_ = do_body_c + 1;
        else
            s_ = do_final_c;
        break;

    case do_header_only_c:
    {
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb1_t>(v_)));
        boost::get<cb1_t>(v_).consume(n);
        if(buffer_size(boost::get<cb1_t>(v_)) > 0)
            break;
        frd_ = boost::none;
        header_done_ = true;
        if(! split_)
        {
            s_ = do_final_c;
            break;
        }
        s_ = do_body_c;
        break;
    }

    case do_body_c + 2:
        BOOST_ASSERT(n <= buffer_size(
            boost::get<cb5_t>(v_)));
        boost::get<cb5_t>(v_).consume(n);
        if(buffer_size(boost::get<cb5_t>(v_)) > 0)
            break;
        v_ = boost::blank{};
        if(more_)
            s_ = do_body_c + 1;
        else
            s_ = do_final_c;
        break;

#ifndef BEAST_NO_BIG_VARIANTS
    case do_body_final_c:
    {
        auto& b = boost::get<cb6_t>(v_);
        BOOST_ASSERT(n <= buffer_size(b));
        b.consume(n);
        if(buffer_size(b) > 0)
            break;
        v_ = boost::blank{};
        s_ = do_complete;
        break;
    }

    case do_all_c:
    {
        auto& b = boost::get<cb7_t>(v_);
        BOOST_ASSERT(n <= buffer_size(b));
        b.consume(n);
        if(buffer_size(b) > 0)
            break;
        header_done_ = true;
        v_ = boost::blank{};
        s_ = do_complete;
        break;
    }
#endif

    case do_final_c + 1:
        BOOST_ASSERT(buffer_size(
            boost::get<cb8_t>(v_)));
        boost::get<cb8_t>(v_).consume(n);
        if(buffer_size(boost::get<cb8_t>(v_)) > 0)
            break;
        v_ = boost::blank{};
        goto go_complete;

    //----------------------------------------------------------------------

    default:
        BOOST_ASSERT(false);
    case do_complete:
        break;

    go_complete:
        s_ = do_complete;
        break;
    }
}

} // http
} // beast

#endif

ext: ipp


text:
//
// Licensed to Green Energy Corp (www.greenenergycorp.com) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Green Enery Corp licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
#include "AsyncTaskGroup.h"

#include "AsyncTaskBase.h"
#include "AsyncTaskPeriodic.h"
#include "AsyncTaskNonPeriodic.h"
#include "AsyncTaskContinuous.h"
#include "AsyncTaskScheduler.h"
#include "Exception.h"

#include "ITimerSource.h"

#include <boost/foreach.hpp>
#include <boost/bind.hpp>

using namespace boost::posix_time;

namespace apl
{

AsyncTaskGroup::AsyncTaskGroup(ITimerSource* apTimerSrc, ITimeSource* apTimeSrc) :
	mIsRunning(false),
	mShutdown(false),
	mpTimerSrc(apTimerSrc),
	mpTimeSrc(apTimeSrc),
	mpTimer(NULL)
{

}

AsyncTaskGroup::~AsyncTaskGroup()
{
	this->Shutdown();

	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		delete p;
	}
}

AsyncTaskBase* AsyncTaskGroup::Add(millis_t aPeriod, millis_t aRetryDelay, int aPriority, const TaskHandler& arCallback, const std::string& arName)
{
	AsyncTaskBase* pTask;
	if(aPeriod >= 0)
		pTask = new AsyncTaskPeriodic(aPeriod, aRetryDelay, aPriority, arCallback, this, arName);
	else
		pTask = new AsyncTaskNonPeriodic(aRetryDelay, aPriority, arCallback, this, arName);

	mTaskVec.push_back(pTask);
	return pTask;
}

void AsyncTaskGroup::ResetTasks(int aMask)
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		if(!p->IsRunning() && (p->GetFlags() & aMask)) p->Reset();
	}
}

AsyncTaskContinuous* AsyncTaskGroup::AddContinuous(int aPriority, const TaskHandler& arCallback, const std::string& arName)
{
	AsyncTaskContinuous* pTask = new AsyncTaskContinuous(aPriority, arCallback, this, arName);
	mTaskVec.push_back(pTask);
	return pTask;
}

void AsyncTaskGroup::Remove(AsyncTaskBase* apTask)
{
	for(TaskVec::iterator i = mTaskVec.begin(); i != mTaskVec.end(); ++i) {
		if(*i == apTask) {
			delete *i;
			mTaskVec.erase(i);
			return;
		}
	}
	throw ArgumentException(LOCATION, "Task not found");
}

void AsyncTaskGroup::Shutdown()
{
	if(mpTimer) {
		mpTimer->Cancel();
		mpTimer = NULL;
	}

	mShutdown = true;
}

void AsyncTaskGroup::Enable()
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		p->SilentEnable();
	}
	this->CheckState();
}

void AsyncTaskGroup::Disable()
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		p->SilentDisable();
	}
	this->CheckState();
}

void AsyncTaskGroup::Enable(int aMask)
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		if((p->GetFlags() & aMask) != 0) p->SilentEnable();
	}
	this->CheckState();
}

void AsyncTaskGroup::Disable(int aMask)
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		if((p->GetFlags() & aMask) != 0) p->SilentDisable();
	}
	this->CheckState();
}

AsyncTaskBase* AsyncTaskGroup::GetNext(const boost::posix_time::ptime& arTime)
{
	this->Update(arTime);
	TaskVec::iterator max = max_element(mTaskVec.begin(), mTaskVec.end(), AsyncTaskBase::LessThanGroupLevel);

	AsyncTaskBase* pRet = NULL;
	if(max != mTaskVec.end()) {
		AsyncTaskBase* p = *max;
		if(!p->IsRunning() && p->IsEnabled()) pRet = p;
	}

	return pRet;
}

void AsyncTaskGroup::CheckState()
{
	if(!mShutdown) {
		ptime now = GetUTC();
		AsyncTaskBase* pTask = GetNext(now);

		if(pTask == NULL) return;
		if(pTask->NextRunTime() == max_date_time) return;

		if(pTask->NextRunTime() <= now) {
			mIsRunning = true;
			pTask->Dispatch();
		} else {
			this->RestartTimer(pTask->NextRunTime());
		}
	}
}

void AsyncTaskGroup::OnCompletion()
{
	if(!mIsRunning) throw InvalidStateException(LOCATION, "Not running");
	mIsRunning = false;
	this->CheckState();
}

boost::posix_time::ptime AsyncTaskGroup::GetUTC() const
{
	return mpTimeSrc->GetUTC();
}

void AsyncTaskGroup::Update(const boost::posix_time::ptime& arTime)
{
	BOOST_FOREACH(AsyncTaskBase * p, mTaskVec) {
		p->UpdateTime(arTime);
	}
}

void AsyncTaskGroup::RestartTimer(const boost::posix_time::ptime& arTime)
{
	if(mpTimer != NULL) {
		if(mpTimer->ExpiresAt() != arTime) {
			mpTimer->Cancel();
			mpTimer = NULL;
		}
	}

	if(mpTimer == NULL)
		mpTimer = mpTimerSrc->Start(arTime, boost::bind(&AsyncTaskGroup::OnTimerExpiration, this));
}

void AsyncTaskGroup::OnTimerExpiration()
{
	mpTimer = NULL;
	this->CheckState();
}

} // end ns


text:
#ifndef INCLUDE_ACKWARD_CORE_DETAIL_TUPLE_HPP
#define INCLUDE_ACKWARD_CORE_DETAIL_TUPLE_HPP

#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/python/extract.hpp>

#include <ackward/core/Util.hpp>

/* These are the guts of the tuple conversion routines.

   Mostly it's just a bunch of boost::preprocessor machination that
   builds up the (relatively) simple converters between python tuples
   and C++ tuples.
 */

namespace ackward {
namespace core {
namespace detail {

// This defines the maximum number of arguments for which a
// tuple-converter template will be created. You can define it
// externally if you want.
#ifndef ACKWARD_CORE_TUPLE_CONVERTER_SIZE_LIMIT
#define ACKWARD_CORE_TUPLE_CONVERTER_SIZE_LIMIT 11
#endif

#define ACKWARD_CORE_DETAIL_TUPLE_CONVERT_ELEMENT_FROM_PYOBJECT(z, n, _) \
boost::python::extract<typename boost::tuples::element<n, Tuple>::type>(boost::python::object(boost::python::handle<>(boost::python::borrowed(PyTuple_GetItem(obj_ptr, n)))))

#define ACKWARD_CORE_DETAIL_TUPLE_CONVERT_ELEMENT_FROM_OBJECT(z, n, _) \
boost::python::extract<typename boost::tuples::element<n, Tuple>::type>(t[n])

#define ACKWARD_CORE_DETAIL_GET_TUPLE_ELEMENT_CPP(z, n, _) boost::get<n>(t)

/* These are the details of the tuple conversion process. See
 * ackward/core/Tuple.hpp for the public functions.
 */

template <typename Tuple, int Length>
class ConvertTuple {};

#define ACKWARD_CORE_DETAIL_CONVERT_TUPLE(z, size, _) \
template <typename Tuple>                                 \
struct ConvertTuple<Tuple, size> {                        \
    Tuple operator()(boost::python::tuple t) {            \
        return Tuple(                                                   \
            BOOST_PP_ENUM(size, ACKWARD_CORE_DETAIL_TUPLE_CONVERT_ELEMENT_FROM_OBJECT, 1) \
            );                                                          \
    }                                                                   \
                                                                        \
    boost::python::tuple operator()(const Tuple&  t) {                  \
        return boost::python::make_tuple(                               \
            BOOST_PP_ENUM(size, ACKWARD_CORE_DETAIL_GET_TUPLE_ELEMENT_CPP, 1) \
            );                                                          \
    }                                                                   \
};

BOOST_PP_REPEAT_FROM_TO(1, ACKWARD_CORE_TUPLE_CONVERTER_SIZE_LIMIT, ACKWARD_CORE_DETAIL_CONVERT_TUPLE, _)

template <typename Tuple, int Size>
struct convert_tuple {
    static PyObject* convert(const Tuple& t);
};

#define ACKWARD_CORE_DETAIL_TUPLE_CHECK_ELEMENT_CONVERTIBLE(z, n, _) \
    {                                                         \
        PyObject* elem_ptr = PyTuple_GetItem(obj_ptr, n);               \
                                                                        \
        if (!fromPythonConvertible<typename boost::tuples::element<n, Tuple>::type>(elem_ptr)) \
            return 0;                                                   \
    }

#define ACKWARD_CORE_DETAIL_AUTO_CONVERT_TUPLE(z, size, _)                          \
template <typename Tuple>                                               \
struct convert_tuple<Tuple, size> {                                     \
    static PyObject* convert(const Tuple& t) {                          \
        using namespace boost::python;                                  \
                                                                        \
        tuple rval =                                                    \
            make_tuple(                                                 \
                BOOST_PP_ENUM(size, ACKWARD_CORE_DETAIL_GET_TUPLE_ELEMENT_CPP, _) \
                );                                                      \
                                                                        \
        return incref(rval.ptr());                                      \
    }                                                                   \
                                                                        \
    static void* convertible(PyObject* obj_ptr) {                       \
        using namespace boost::python;                                  \
                                                                        \
        if (!PyTuple_Check(obj_ptr)) return 0;                          \
        if (!PyTuple_Size(obj_ptr) == size) return 0;                   \
                                                                        \
        BOOST_PP_REPEAT(size, ACKWARD_CORE_DETAIL_TUPLE_CHECK_ELEMENT_CONVERTIBLE, _) \
                                                                        \
            return obj_ptr;                                             \
    }                                                                   \
                                                                        \
    static void construct(                                              \
        PyObject* obj_ptr,                                              \
        boost::python::converter::rvalue_from_python_stage1_data* data) \
        {                                                               \
            using namespace boost::python;                              \
                                                                        \
            void* storage = (                                           \
                (converter::rvalue_from_python_storage<Tuple>*)         \
                data)->storage.bytes;                                   \
                                                                        \
            new (storage) Tuple(                                        \
                BOOST_PP_ENUM(size, ACKWARD_CORE_DETAIL_TUPLE_CONVERT_ELEMENT_FROM_PYOBJECT, _) \
                );                                                      \
                                                                        \
            data->convertible = storage;                                \
        }                                                               \
};

BOOST_PP_REPEAT_FROM_TO(1, ACKWARD_CORE_TUPLE_CONVERTER_SIZE_LIMIT, ACKWARD_CORE_DETAIL_AUTO_CONVERT_TUPLE, _)

} // namespace detail
} // namespace core
} // namespace ackward

#endif

max_stars_repo_name: abingham/ackward

max_issues_repo_name: abingham/ackward

max_forks_repo_name: abingham/ackward


text:
#pragma once
#include "scene.hxx"
#include "camera.hxx"
//#include "infiniteplane.hxx"
#include "shader.hxx"
#include "util.hxx"
#include "light.hxx"

#include <vector>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <unordered_map>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

#ifdef _MSC_VER
// Warnings generated by yaml-cpp. Hopefully they are harmless. They don't look like it ... :-/
#pragma warning (disable: 4251)
#pragma warning (disable: 4373)
#pragma warning (disable: 4275)
#endif
#include <yaml-cpp/yaml.h>

namespace scenereader
{

using RadianceOrImportance::AreaEmitter;

namespace fs = boost::filesystem;

using Transform = Eigen::Transform<double, 3, Eigen::Affine>;

// TODO: Rename this
template<class Thing>
class SymbolTable
{
  Thing currentThing;
  std::unordered_map<std::string, Thing> things;
  std::string name_of_this_table;
public:
  SymbolTable(const std::string &_name) :
    currentThing{}, name_of_this_table(_name)
  {}

  int size() const
  {
    return isize(things);
  }

  const auto& name() const { return name_of_this_table;  }

  void activate(const std::string &name)
  {
    auto it = things.find(name);
    if (it != things.end())
    {
      currentThing = it->second;
    }
    else
    {
      char buffer[1024];
      std::snprintf(buffer, 1024, "Error: %s %s not defined. Define it in the NFF file prior to referencing it.", this->name_of_this_table.c_str(), name.c_str());
      throw std::runtime_error(buffer);
    }
  }

  void set_and_activate(const char* name, Thing thing)
  {
    currentThing = thing;
    things[name] = thing;
  }

  Thing operator()() const
  {
    return currentThing;
  }

  std::optional<Thing> operator[](const char *name) const
  {
    auto it = things.find(name);
    if (it == things.end())
      return {};
    else
      return it->second;
  }

  std::optional<Thing> operator[](const std::string &name) const
  {
    return this->operator[](name.c_str());
  }
};

class GlobalContext
{
  std::unordered_map<Material, MaterialIndex, Material::Hash> to_material_index;
  std::vector<fs::path> search_paths;
  Scene* scene;
  RenderingParameters* params;
  fs::path filename;

public:
  GlobalContext(Scene &scene_, RenderingParameters *params_, const fs::path &path_hint);
  auto& GetScene() const { return *scene; }
  auto* GetParams() const { return params; }
  auto GetFilename() const { return filename; }
  fs::path MakeFullPath(const fs::path &filename) const;
};

struct Scope
{
  SymbolTable<Shader*> shaders;
  SymbolTable<Medium*> mediums;
  SymbolTable<AreaEmitter*> areaemitters;
  std::unordered_map<std::string, Material> materials;
  Transform currentTransform;

  Scope() :
    shaders("Shader"),
    mediums("Medium"),
    areaemitters("AreaEmitter"),
    currentTransform{ Transform::Identity() }
  {
  }

  void InsertAndActivate(const std::string& name, Shader* item) { shaders.set_and_activate(name.c_str(), item); }
  void InsertAndActivate(const std::string& name, Medium* item) { mediums.set_and_activate(name.c_str(), item); }
  void InsertAndActivate(const std::string& name, AreaEmitter* item) { areaemitters.set_and_activate(name.c_str(), item); }
  template<class U>
  inline auto Lookup(const std::string &key) const;
};

template<>
inline auto Scope::Lookup<Shader>(const std::string &key) const { return shaders[key.c_str()]; }
template<>
inline auto Scope::Lookup<Medium>(const std::string &key) const { return mediums[key.c_str()]; }
template<>
inline auto Scope::Lookup<AreaEmitter>(const std::string &key) const { return areaemitters[key.c_str()]; }

void AddDefaultMaterials(Scope &scope, const Scene &scene);

inline auto NormalTrafo(const Transform &trafo)
{
  return trafo.linear().inverse().transpose().eval();
}

namespace assimp
{

using MaterialGetter = std::function<Material(const std::optional<std::string> &)>;

void Read(Scene &scene, Transform model_transform, MaterialGetter material_getter, bool material_assignment_by_object_names, const fs::path &filename_path);

} // namespace assimp

} // namespace scenereader

namespace YAML
{

// Adapted from https://github.com/jbeder/yaml-cpp/wiki/Tutorial
template<>
struct convert<Double3> {
  static bool decode(const Node& node, Double3& rhs) {
    if (!node.IsSequence() || node.size() != 3) {
      return false;
    }
    rhs[0] = node[0].as<double>();
    rhs[1] = node[1].as<double>();
    rhs[2] = node[2].as<double>();
    return true;
  }
};

template<>
struct convert<RGB> {
  static bool decode(const Node& node, RGB& rhs) {
    if (!node.IsSequence() || (node.size() != 3 && node.size() != 1)) {
      return false;
    }
    rhs[0] = RGBScalar{ node[0].as<double>() };
    if (node.size() == 3)
    {
      rhs[1] = RGBScalar{ node[1].as<double>() };
      rhs[2] = RGBScalar{ node[2].as<double>() };
    }
    else
    {
      rhs[1] = rhs[2] = rhs[0];
    }
    return true;
  }
};

}

max_stars_repo_name: DaWelter/NaiveTrace

max_issues_repo_name: DaWelter/NaiveTrace

max_forks_repo_name: DaWelter/NaiveTrace