<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: bootstrap.hxx,v $
 * $Revision: 1.28 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#define CONFIGMGR_BOOTSTRAP_HXX_

#include "bootstrapcontext.hxx"

// ---------------------------------------------------------------------------------------
#define CONFIGMGR_INIFILE                   SAL_CONFIGFILE("configmgr")
#define BOOTSTRAP_ITEM_INIFILE              "CFG_INIFILE"
// ---------------------------------------------------------------------------------------
// standard settings
#define SETTING_UNOSERVICE                  "BackendService"
#define SETTING_UNOWRAPPER                  "BackendWrapper"
#define SETTING_OFFLINE                     "Offline"
#define SETTING_LOCALE_NEW                  "Locale"
#define SETTING_ASYNC_NEW                   "EnableAsync"
#define SETTING_INIFILE                     "Inifile"

// Prefixes
#define CONTEXT_MODULE_PREFIX_              "/modules/com.sun.star.configuration/"
#define CONTEXT_SECTION_BOOTSTRAP_          "bootstrap/"
#define CONTEXT_ITEM_PREFIX_                CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_BOOTSTRAP_
#define BOOTSTRAP_ITEM_PREFIX_              "CFG_"

// special internal context values
#define CONTEXT_SECTION_INTERNAL_           "factory/"
#define CONTEXT_INTERNAL_PREFIX_            CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_INTERNAL_
#define CONTEXT_ITEM_ADMINFLAG              CONTEXT_INTERNAL_PREFIX_"isAdminConfiguration"
#define CONTEXT_ITEM_BOOTSTRAP_ERROR        CONTEXT_INTERNAL_PREFIX_"theBootstrapError"

#define CONTEXT_ITEM_IS_WRAPPER_CONTEXT     CONTEXT_INTERNAL_PREFIX_"isWrapperContext"
#define CONTEXT_ITEM_IS_BOOTSTRAP_CONTEXT   CONTEXT_INTERNAL_PREFIX_"isBootstrapContext"

// ---------------------------------------------------------------------------------------
#define A_DefaultProviderSingletonName "com.sun.star.configuration.theDefaultProvider"
#define K_DefaultBackendSingletonName       "com.sun.star.configuration.backend.theDefaultBackend"
#define A_BootstrapContextSingletonName     "com.sun.star.configuration.bootstrap.theBootstrapContext"
// -------------------------------------------------------------------------
#define A_DefaultProviderServiceAndImplName     "com.sun.star.configuration.DefaultProvider"
#define K_DefaultBackendServiceAndImplName         "com.sun.star.configuration.backend.DefaultBackend"
// ---------------------------------------------------------------------------------------
namespace configmgr
{
    // -----------------------------------------------------------------------------------

    namespace uno = ::com::sun::star::uno;
    namespace lang = ::com::sun::star::lang;
    namespace beans = ::com::sun::star::beans;
    using ::rtl::OUString;
    // -----------------------------------------------------------------------------------

    /** Customized ComponentContext for configuration bootstrap data and runtime arguments
    */
    class BootstrapContext : public ComponentContext
    {
    // creation and destruction
    private:
        friend uno::Reference<uno::XInterface> SAL_CALL
            instantiateBootstrapContext( Context const& xContext );

        // constructor
        BootstrapContext(Context const & _xContext);

        // two-phase construct
        void initialize();

    protected:
        using ComponentContext::initialize;

    public:
         // XServiceInfo
        virtual rtl::OUString SAL_CALL getImplementationName()
            throw (uno::RuntimeException) ;
        virtual sal_Bool SAL_CALL supportsService(
            const rtl::OUString& aServiceName)
            throw (uno::RuntimeException) ;
        virtual uno::Sequence<rtl::OUString> SAL_CALL
            getSupportedServiceNames(void) throw (uno::RuntimeException) ;

        typedef uno::Sequence < beans::NamedValue >             Overrides;
        /** Constructs a Context based on the given arguments and context.
            @param _xContext
                The base context of this component context.

            @param _aArguments
                The arguments used to create this component context.
        */
        static Context createWrapper(Context const & _xContext, Overrides const & _aOverrides);

        /** Checks, if the given context is a wrapper.
            @param _xContext
                The context that is checked.
        */
        static sal_Bool isWrapper(Context const & _xContext);

        /** Retrieves the BootstrapContext for the given non-bootstrap context.
            @param _xContext
                The context from which the bootstrap context should be retrieved.

        */
        static Context get(Context const & _xContext);

        /// Destroys this BootstrapContext
        ~BootstrapContext();

        // gets the INI that should be used for bootstrap data by default
        static OUString getDefaultConfigurationBootstrapURL();

    // interface implementations
    public:
    // XComponentContext
        /** Retrieves a value from this context.

            @param Name
                The name of the value to retrieve.
                A prefix of "com.sun.star.configuration.bootstrap." is stripped/ignored

            @returns
                The requested value, or <VOID/> if the value is not found.
        */
        virtual uno::Any SAL_CALL
            getValueByName( const OUString& Name )
                throw (uno::RuntimeException);

    public: // used by ArgumentHelper
        static OUString makeContextName (OUString const & _aShortName);

    private:
        static OUString makeBootstrapName(OUString const & _aLongName);
        uno::Any makeBootstrapException();
    };
// -----------------------------------------------------------------------------
    class ContextReader
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;
        explicit
        ContextReader(Context const & context);

    // the underlying contexts
        sal_Bool hasBootstrapContext()          const { return m_fullcontext.is(); }
        Context const & getBootstrapContext()   const { return m_fullcontext; }
        Context const & getBaseContext()        const { return m_basecontext; }
        Context const & getBestContext()        const { return m_fullcontext.is() ? m_fullcontext : m_basecontext; }

        uno::Reference< lang::XMultiComponentFactory > getServiceManager() const;

        /** Checks, if the given context is a BootstrapContext.
            @param _xContext
                The context that is checked.
        */
        static bool isBootstrapContext(Context const & context);

        /** Checks, if the given context has the given 'admin' flag setting..
            @param _xContext
                The context that is checked.
        */
        static bool testAdminService(Context const & context, bool bAdmin);

    // general settings
        sal_Bool    isUnoBackend() const;

        sal_Bool    hasUnoBackendService() const;
        sal_Bool    hasUnoBackendWrapper() const;

        sal_Bool    hasLocale() const;
        sal_Bool    hasAsyncSetting() const;
        sal_Bool    hasOfflineSetting() const;

        OUString    getUnoBackendService() const;
        OUString    getUnoBackendWrapper() const;

        OUString    getLocale() const;
        sal_Bool    getAsyncSetting() const;
        sal_Bool    getOfflineSetting() const;

    // internal settings - should only ever be in configmgr::BootstrapContext instances
        // get a special setting
        sal_Bool    isAdminService() const;

        // access to error diagnostics
        sal_Bool    isBootstrapValid() const;
        uno::Any    getBootstrapError() const;
    private:
        sal_Bool hasSetting(OUString const & _aSetting) const;
        sal_Bool getBoolSetting(OUString const & _aSetting, sal_Bool bValue) const;
        OUString getStringSetting(OUString const & _aSetting, OUString aValue) const;
        uno::Any getSetting(OUString const & _aSetting) const;
    private:
        Context m_basecontext;
        Context m_fullcontext;
    };
    //------------------------------------------------------------------------

    class ArgumentHelper
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;

        explicit
        ArgumentHelper(Context const & context)
        : m_context(context)
        , m_bHasBackendArguments(false)
        {}

        bool hasBackendArguments() const { return m_bHasBackendArguments; }
        bool checkBackendArgument(beans::NamedValue const & aAdjustedValue);

        bool filterAndAdjustArgument(beans::NamedValue & rValue);

        static
        bool extractArgument(beans::NamedValue & rValue, uno::Any const & aArgument);

        static beans::NamedValue makeAdminServiceOverride(sal_Bool bAdmin);
    private:
        Context m_context; // context used to strip identical arguments
        bool m_bHasBackendArguments;
    };
// -----------------------------------------------------------------------------------

}

#endif // CONFIGMGR_BOOTSTRAP_HXX_

<commit_msg>INTEGRATION: CWS sb88 (1.28.10); FILE MERGED 2008/06/03 15:29:48 sb 1.28.10.1: #i89553 applied patch by cmc<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: bootstrap.hxx,v $
 * $Revision: 1.29 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#define CONFIGMGR_BOOTSTRAP_HXX_

#include "bootstrapcontext.hxx"

// ---------------------------------------------------------------------------------------
#define CONFIGMGR_INIFILE                   SAL_CONFIGFILE("configmgr")
#define BOOTSTRAP_ITEM_INIFILE              "CFG_INIFILE"
// ---------------------------------------------------------------------------------------
// standard settings
#define SETTING_UNOSERVICE                  "BackendService"
#define SETTING_UNOWRAPPER                  "BackendWrapper"
#define SETTING_OFFLINE                     "Offline"
#define SETTING_LOCALE_NEW                  "Locale"
#define SETTING_ASYNC_NEW                   "EnableAsync"
#define SETTING_INIFILE                     "Inifile"

// Prefixes
#define CONTEXT_MODULE_PREFIX_              "/modules/com.sun.star.configuration/"
#define CONTEXT_SECTION_BOOTSTRAP_          "bootstrap/"
#define CONTEXT_ITEM_PREFIX_                CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_BOOTSTRAP_
#define BOOTSTRAP_ITEM_PREFIX_              "CFG_"

// special internal context values
#define CONTEXT_SECTION_INTERNAL_           "factory/"
#define CONTEXT_INTERNAL_PREFIX_            CONTEXT_MODULE_PREFIX_ CONTEXT_SECTION_INTERNAL_
#define CONTEXT_ITEM_ADMINFLAG              CONTEXT_INTERNAL_PREFIX_"isAdminConfiguration"
#define CONTEXT_ITEM_BOOTSTRAP_ERROR        CONTEXT_INTERNAL_PREFIX_"theBootstrapError"

#define CONTEXT_ITEM_IS_WRAPPER_CONTEXT     CONTEXT_INTERNAL_PREFIX_"isWrapperContext"
#define CONTEXT_ITEM_IS_BOOTSTRAP_CONTEXT   CONTEXT_INTERNAL_PREFIX_"isBootstrapContext"

// ---------------------------------------------------------------------------------------
#define A_DefaultProviderSingletonName "com.sun.star.configuration.theDefaultProvider"
#define K_DefaultBackendSingletonName       "com.sun.star.configuration.backend.theDefaultBackend"
#define A_BootstrapContextSingletonName     "com.sun.star.configuration.bootstrap.theBootstrapContext"
// -------------------------------------------------------------------------
#define A_DefaultProviderServiceAndImplName     "com.sun.star.configuration.DefaultProvider"
#define K_DefaultBackendServiceAndImplName         "com.sun.star.configuration.backend.DefaultBackend"
// ---------------------------------------------------------------------------------------
namespace configmgr
{
    // -----------------------------------------------------------------------------------

    namespace uno = ::com::sun::star::uno;
    namespace lang = ::com::sun::star::lang;
    namespace beans = ::com::sun::star::beans;
    using ::rtl::OUString;
    // -----------------------------------------------------------------------------------

    /** Customized ComponentContext for configuration bootstrap data and runtime arguments
    */
    class BootstrapContext : public ComponentContext
    {
    // creation and destruction
    private:
        friend uno::Reference<uno::XInterface> SAL_CALL
            instantiateBootstrapContext( Context const& xContext );

        // constructor
        BootstrapContext(Context const & _xContext);

        // two-phase construct
        void initialize();

    protected:
        using ComponentContext::initialize;

    public:
         // XServiceInfo
        virtual rtl::OUString SAL_CALL getImplementationName()
            throw (uno::RuntimeException) ;
        virtual sal_Bool SAL_CALL supportsService(
            const rtl::OUString& aServiceName)
            throw (uno::RuntimeException) ;
        virtual uno::Sequence<rtl::OUString> SAL_CALL
            getSupportedServiceNames(void) throw (uno::RuntimeException) ;

        typedef uno::Sequence < beans::NamedValue >             Overrides;
        /** Constructs a Context based on the given arguments and context.
            @param _xContext
                The base context of this component context.

            @param _aArguments
                The arguments used to create this component context.
        */
        static Context createWrapper(Context const & _xContext, Overrides const & _aOverrides);

        /** Checks, if the given context is a wrapper.
            @param _xContext
                The context that is checked.
        */
        static sal_Bool isWrapper(Context const & _xContext);

        /** Retrieves the BootstrapContext for the given non-bootstrap context.
            @param _xContext
                The context from which the bootstrap context should be retrieved.

        */
        static Context get(Context const & _xContext);

        /// Destroys this BootstrapContext
        ~BootstrapContext();

        // gets the INI that should be used for bootstrap data by default
        static OUString getDefaultConfigurationBootstrapURL();

    // interface implementations
    public:
    // XComponentContext
        /** Retrieves a value from this context.

            @param Name
                The name of the value to retrieve.
                A prefix of "com.sun.star.configuration.bootstrap." is stripped/ignored

            @returns
                The requested value, or <VOID/> if the value is not found.
        */
        virtual uno::Any SAL_CALL
            getValueByName( const OUString& Name )
                throw (uno::RuntimeException);

    public: // used by ArgumentHelper
        static OUString makeContextName (OUString const & _aShortName);

    private:
        static OUString makeBootstrapName(OUString const & _aLongName);
        uno::Any makeBootstrapException();
    };
// -----------------------------------------------------------------------------
    class ContextReader
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;
        explicit
        ContextReader(Context const & context);

    // the underlying contexts
        sal_Bool hasBootstrapContext()          const { return m_fullcontext.is(); }
        Context const & getBootstrapContext()   const { return m_fullcontext; }
        Context const & getBaseContext()        const { return m_basecontext; }
        Context const & getBestContext()        const { return m_fullcontext.is() ? m_fullcontext : m_basecontext; }

        uno::Reference< lang::XMultiComponentFactory > getServiceManager() const;

        /** Checks, if the given context has the given 'admin' flag setting..
            @param _xContext
                The context that is checked.
        */
        static bool testAdminService(Context const & context, bool bAdmin);

    // general settings
        sal_Bool    isUnoBackend() const;

        sal_Bool    hasUnoBackendService() const;
        sal_Bool    hasUnoBackendWrapper() const;

        sal_Bool    hasLocale() const;
        sal_Bool    hasAsyncSetting() const;
        sal_Bool    hasOfflineSetting() const;

        OUString    getUnoBackendService() const;
        OUString    getUnoBackendWrapper() const;

        OUString    getLocale() const;
        sal_Bool    getAsyncSetting() const;
        sal_Bool    getOfflineSetting() const;

    // internal settings - should only ever be in configmgr::BootstrapContext instances
        // get a special setting
        sal_Bool    isAdminService() const;

        // access to error diagnostics
        sal_Bool    isBootstrapValid() const;
        uno::Any    getBootstrapError() const;
    private:
        sal_Bool hasSetting(OUString const & _aSetting) const;
        sal_Bool getBoolSetting(OUString const & _aSetting, sal_Bool bValue) const;
        OUString getStringSetting(OUString const & _aSetting, OUString aValue) const;
        uno::Any getSetting(OUString const & _aSetting) const;
    private:
        Context m_basecontext;
        Context m_fullcontext;
    };
    //------------------------------------------------------------------------

    class ArgumentHelper
    {
    public:
        typedef uno::Reference< uno::XComponentContext > Context;

        explicit
        ArgumentHelper(Context const & context)
        : m_context(context)
        , m_bHasBackendArguments(false)
        {}

        bool hasBackendArguments() const { return m_bHasBackendArguments; }
        bool checkBackendArgument(beans::NamedValue const & aAdjustedValue);

        bool filterAndAdjustArgument(beans::NamedValue & rValue);

        static
        bool extractArgument(beans::NamedValue & rValue, uno::Any const & aArgument);

        static beans::NamedValue makeAdminServiceOverride(sal_Bool bAdmin);
    private:
        Context m_context; // context used to strip identical arguments
        bool m_bHasBackendArguments;
    };
// -----------------------------------------------------------------------------------

}

#endif // CONFIGMGR_BOOTSTRAP_HXX_

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////
// slip.hpp -- SLIP Protocol Class
// Date: Fri May 16 19:54:36 2014  Warren Gay ve3wwg
///////////////////////////////////////////////////////////////////////
//
// SLIP protocol object :
//
// This is useful for "framing" serial binary messages between the
// local host processor and the remote host.
//
// I/O is performed through user provided read and write callbacks.
//
// NOTES:
//
//  1.  This implements the standard uncompressed SLIP by default.
//  2.  A non-SLIP standard 8-bit CRC can be automatically appended
//      to each packet written when enabled by enable_crc8(true).
//      Each packet received will have the last byte checked (not returned)
//      to see if it matches the calculated CRC. A failed status of
//      ES_CRC is returned if it does not match.
//  3.  This particular software copy is intended to be used by POSIX systems
//      communicating with AVR/Teensy systems (over a serial connection,
//      which may be Bluetooth).

#ifndef SLIP_HPP
#define SLIP_HPP

#include <stdint.h>

extern "C" {
	typedef uint8_t (*slipread_t)();        // Read byte user routine
	typedef void (*slipwrite_t)(uint8_t b); // Write byte user routine
}

class SLIP {
	slipread_t		read_b;		// Routine to fetch data with
	slipwrite_t		write_b;	// Routine to write data with
	bool			use_crc8;	// Include CRC8 in packet

	void write_encoded(uint8_t b);		// Write encoded byte

public:	enum Status {
		ES_Ok = 0,			// Success
		ES_Trunc,			// Packet was too long for buffer (truncated)
		ES_Protocol,			// Protocol error
		ES_CRC				// CRC Failure
	};

	SLIP(slipread_t read_func,slipwrite_t write_func);
	bool enable_crc8(bool on);
	void write(const void *buffer,unsigned length);
	Status read(void *buffer,unsigned buflen,unsigned& retlength);
};

#endif // SLIP_HPP

// End slip.hpp
<commit_msg>Replaced by subproject<commit_after><|endoftext|>


<commit_before>/// @file Environment.cpp
/// @brief Manages environment-related reX-logic, e.g. world time and lightning.
/// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "RexLogicModule.h"
#include "Environment/Environment.h"
#include "Foundation.h"
#include "EC_OgreEnvironment.h"
#include "SceneManager.h"

namespace RexLogic
{

Environment::Environment(RexLogicModule *owner) : owner_(owner)
{
}

Environment::~Environment()
{
}

void Environment::FindCurrentlyActiveEnvironment()
{
    Scene::ScenePtr scene = owner_->GetCurrentActiveScene();
    for(Scene::SceneManager::iterator iter = scene->begin();
        iter != scene->end(); ++iter)
    {
        Scene::Entity &entity = **iter;
        Foundation::ComponentInterfacePtr envComponent = entity.GetComponent("EC_OgreEnvironment");
        if (envComponent.get())
            cachedEnvironmentEntity_ = scene->GetEntity(entity.GetId());
    }
}

Scene::EntityWeakPtr Environment::GetEnvironmentEntity()
{
    return cachedEnvironmentEntity_;
}

void Environment::CreateEnvironment()
{
    Scene::ScenePtr active_scene = owner_->GetCurrentActiveScene();
    Scene::EntityPtr entity = active_scene->CreateEntity(active_scene->GetNextFreeId());
    entity->AddEntityComponent(owner_->GetFramework()->GetComponentManager()->CreateComponent("EC_OgreEnvironment"));

    cachedEnvironmentEntity_ = entity;
}

///\todo Remove this when Caelum is working ok.
bool test = true;

bool Environment::HandleOSNE_SimulatorViewerTimeMessage(ProtocolUtilities::NetworkEventInboundData *data)
{
    ProtocolUtilities::NetInMessage &msg = *data->message;
    msg.ResetReading();

    ///\ secPerDay,secPerYear, sunPhase seems to be zero, at least with 0.4 server
    usecSinceStart_ = (time_t)msg.ReadU64();
    secPerDay_ = msg.ReadU32();
    secPerYear_ = msg.ReadU32();
    sunDirection_ = msg.ReadVector3();
    sunPhase_ = msg.ReadF32();
    sunAngVelocity_ = msg.ReadVector3();

    FindCurrentlyActiveEnvironment();
    Foundation::ComponentPtr component = GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment");
    if (!component)
        return false;

    // Update the sunlight direction and angle velocity.
    ///\note Not needed anymore as we use Caleum now.
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (component.get());
//    env.SetSunDirection(-sunDirection_);

    /** \note
     *  It's not necessary to update the environment time every time SimulatorViewerTimeMessage is received
     *  (about every tenth second that is) because the Caleum system has its own perception of time. But let's
     *  do it anyways for now.
     */
    if (test)
    {
        env.SetTime(usecSinceStart_);
        test = false;
    }

    return false;
}

void Environment::UpdateVisualEffects(Core::f64 frametime)
{
    FindCurrentlyActiveEnvironment();
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment").get());
    env.UpdateVisualEffects(frametime);
}

bool Environment::UseCaelum()
{
    FindCurrentlyActiveEnvironment();
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment").get());
    return env.IsCaleumUsed();
}

}
<commit_msg>Fixed bug which caused time to be wrong after login-logout-re-login-sequence.<commit_after>/// @file Environment.cpp
/// @brief Manages environment-related reX-logic, e.g. world time and lightning.
/// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "RexLogicModule.h"
#include "Environment/Environment.h"
#include "Foundation.h"
#include "EC_OgreEnvironment.h"
#include "SceneManager.h"

namespace RexLogic
{

Environment::Environment(RexLogicModule *owner) :
    owner_(owner),
    usecSinceStart_(0),
    secPerDay_(0),
    secPerYear_(0),
    sunDirection_(Vector3()),
    sunPhase_(0),
    sunAngVelocity_(0)
{
}

Environment::~Environment()
{
}

void Environment::FindCurrentlyActiveEnvironment()
{
    Scene::ScenePtr scene = owner_->GetCurrentActiveScene();
    for(Scene::SceneManager::iterator iter = scene->begin();
        iter != scene->end(); ++iter)
    {
        Scene::Entity &entity = **iter;
        Foundation::ComponentInterfacePtr envComponent = entity.GetComponent("EC_OgreEnvironment");
        if (envComponent.get())
            cachedEnvironmentEntity_ = scene->GetEntity(entity.GetId());
    }
}

Scene::EntityWeakPtr Environment::GetEnvironmentEntity()
{
    return cachedEnvironmentEntity_;
}

void Environment::CreateEnvironment()
{
    Scene::ScenePtr active_scene = owner_->GetCurrentActiveScene();
    Scene::EntityPtr entity = active_scene->CreateEntity(active_scene->GetNextFreeId());
    entity->AddEntityComponent(owner_->GetFramework()->GetComponentManager()->CreateComponent("EC_OgreEnvironment"));

    cachedEnvironmentEntity_ = entity;
}

bool Environment::HandleOSNE_SimulatorViewerTimeMessage(ProtocolUtilities::NetworkEventInboundData *data)
{
    ProtocolUtilities::NetInMessage &msg = *data->message;
    msg.ResetReading();

    ///\todo    secPerDay,secPerYear, sunPhase seems to be zero, at least with 0.4 server
    ///         Investigate what't the case with newer servers.
    ///         Also usecSinceStart seems to be the default one i.e. server doesn't add its time zone
    ///         difference to it so we add it in Caelum. If the newer servers add it, don't do it anymore
    ///         in Caelum.
    time_t usec = (time_t)msg.ReadU64();
    secPerDay_ = msg.ReadU32();
    secPerYear_ = msg.ReadU32();
    sunDirection_ = msg.ReadVector3();
    sunPhase_ = msg.ReadF32();
    sunAngVelocity_ = msg.ReadVector3();

    FindCurrentlyActiveEnvironment();
    Foundation::ComponentPtr component = GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment");
    if (!component)
        return false;

    // Update the sunlight direction and angle velocity.
    ///\note Not needed anymore as we use Caleum now.
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (component.get());
//    env.SetSunDirection(-sunDirection_);

    /** \note
     *  It's not necessary to update the environment time every time SimulatorViewerTimeMessage is received
     *  (about every tenth second that is) because the Caleum system has its own perception of time. To it just once.
     */
    if (usecSinceStart_ == 0)
    {
        usecSinceStart_ = usec;
        env.SetTime(usecSinceStart_);
    }

    return false;
}

void Environment::UpdateVisualEffects(Core::f64 frametime)
{
    FindCurrentlyActiveEnvironment();
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment").get());
    env.UpdateVisualEffects(frametime);
}

bool Environment::UseCaelum()
{
    FindCurrentlyActiveEnvironment();
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (GetEnvironmentEntity().lock()->GetComponent("EC_OgreEnvironment").get());
    return env.IsCaleumUsed();
}

}
<|endoftext|>


<commit_before>
#include <iostream>
#include <sstream>
#include <array>
#include <string>
#include <type_traits>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <glbinding/Meta.h>
#include <glbinding/ContextInfo.h>
#include <glbinding/Version.h>
#include <glbinding/Binding.h>

#include <glbinding/gl/types.h>
#include <glbinding/gl/enum.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/boolean.h>

using namespace gl;
using namespace glbinding;

namespace
{

    void error(int errnum, const char * errmsg)
    {
        std::cerr << errnum << ": " << errmsg << std::endl;
    }

    static const std::array<GLfloat, 9> identity3{ { 1.f, 0.f, 0.f,  0.f, 1.f, 0.f,  0.f, 0.f, 1.f } };
    static const std::array<GLfloat, 16> identity4{ { 1.f, 0.f, 0.f, 0.f,  0.f, 1.f, 0.f, 0.f,  0.f, 0.f, 1.f, 0.f,  0.f, 0.f, 0.f, 1.f } };

    template <typename T>
    void glrequest(const GLenum pname, T * data);

    template <>
    void glrequest<GLboolean>(const GLenum pname, GLboolean * data)
    {
        glGetBooleanv(pname, data);
    }

    template <>
    void glrequest<GLenum>(const GLenum pname, GLenum * data)
    {
        glGetIntegerv(pname, reinterpret_cast<GLint *>(data));
    }

    template <>
    void glrequest<GLint>(const GLenum pname, GLint * data)
    {
        glGetIntegerv(pname, data);
    }

    template <>
    void glrequest<GLfloat>(const GLenum pname, GLfloat * data)
    {
        glGetFloatv(pname, data);
    }

	template <>
	void glrequest<GLdouble>(const GLenum pname, GLdouble * data)
	{
		glGetDoublev(pname, data);
	}

    template <typename T, int count>
    struct identity
    {
        static bool valid(const std::array<T, count> &)
        {
            return false;
        }
        static std::string str()
        {
            return "";
        }
    };

    template <>
    struct identity<GLfloat, 9>
    {
        static bool valid(const std::array<GLfloat, 9> & data)
        {
            return identity3 == data;
        }
        static std::string str()
        {
            return "identity3";
        }
    };

    template <>
    struct identity<GLfloat, 16>
    {
        static bool valid(const std::array<GLfloat, 16> & data)
        {
            return identity4 == data;
        }
        static std::string str()
        {
            return "identity4";
        }
    };

    template <typename T, int count>
    std::string string(const std::array<T, count> & data)
    {
        std::stringstream stream;

        if (identity<T, count>::valid(data))
            stream << identity<T, count>::str();
        else
        {
            if (data.size() > 1)
                stream << "(";

            for (int i = 0; i < count; ++i)
            {
                stream << data[i];
                if (i + 1 < count)
                    stream << ", ";
            }

            if (data.size() > 1)
                stream << ")";
        }

        return stream.str();
    }

    template <typename T, int count>
    void request(const GLenum pname, std::array<T, count> & data)
    {
        glrequest<T>(pname, data.data());

        static const size_t MAX_PSTRING_LENGTH { 37 };    // actually, it's 44 / average is 23,
                                                          // but 37 works for 452 of 462 glGet enums (98%)

        const std::string pstring{ glbinding::Meta::getString(pname) };
        const std::string spaces{ std::string(MAX_PSTRING_LENGTH - pstring.length(), ' ') };

        if (glGetError() != gl::GL_NO_ERROR)
        {
            std::cout << "\t" << pstring << spaces << " = NOT AVAILABLE" << std::endl;
            return;
        }
        std::cout << "\t" << glbinding::Meta::getString(pname) << spaces << " = " << string<T, count>(data);
    }

    template <typename T, int count>
    void requestState(const GLenum pname)
    {
        std::array<T, count> data;
        request<T, count>(pname, data);

        std::cout << std::endl;
    }

    template <typename T, int count>
    void requestState(const GLenum pname, const std::array<T, count> & expected)
    {
        std::array<T, count> data;
        request<T, count>(pname, data);

        if (!expected.empty() && expected != data)
            std::cout << ", expected " << string<T, count>(expected);

        std::cout << std::endl;
    }
}

int main(int argc, const char * argv[])
{
    if (!Meta::stringsByGL())
    {
        std::cout << "Strings by GL not supported (enable through OPTION_STRINGS_BY_GL)" << std::endl;

        return 1;
    }
#ifndef __APPLE__
    if (argc == 2 && (std::string(argv[1]).compare("--help") || std::string(argv[1]).compare("-h")))
    {
        std::cout << "Usage: " << argv[0] << " [MAJOR_VERSION MINOR_VERSION [CORE [FORWARD_COMPATIBLE]]]" << std::endl;

        return 1;
    }
#endif

    if (!glfwInit())
        return 1;

    glfwSetErrorCallback(error);

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_VISIBLE, false);

#ifdef __APPLE__
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
    if (argc >= 3)
    {
        int majorVersion = atoi(argv[1]);
        int minorVersion = atoi(argv[2]);

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, majorVersion);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minorVersion);
    }

    if (argc >= 4)
    {
        int core = atoi(argv[3]);

        glfwWindowHint(GLFW_OPENGL_PROFILE, core ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_ANY_PROFILE);
    }

    if (argc >= 5)
    {
        int forwardComaptability = atoi(argv[3]);

        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, forwardComaptability ? true : false);
    }
#endif

    GLFWwindow * window = glfwCreateWindow(320, 240, "", nullptr, nullptr);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwHideWindow(window);

    glfwMakeContextCurrent(window);

    Binding::initialize();

    std::cout << std::endl << "[QUERYING STATE VALUES]" << std::endl;

    std::cout << std::endl << "Matrix Stack States" << std::endl;
    requestState<GLenum   , 1>(GL_MATRIX_MODE, { { GL_MODELVIEW } });
    requestState<GLfloat  , 16>(GL_COLOR_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_MODELVIEW_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_PROJECTION_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_TEXTURE_MATRIX, identity4);
    requestState<GLint    , 1>(GL_COLOR_MATRIX_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MODELVIEW_STACK_DEPTH);
    requestState<GLint    , 1>(GL_PROJECTION_STACK_DEPTH);
    requestState<GLint    , 1>(GL_TEXTURE_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_MODELVIEW_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_PROJECTION_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_TEXTURE_STACK_DEPTH);

    std::cout << std::endl << "Viewport States" << std::endl;
    requestState<GLint    , 4>(GL_VIEWPORT);
    requestState<GLint    , 2>(GL_MAX_VIEWPORT_DIMS);

    std::cout << std::endl << "Pixel Sotre States" << std::endl;
    requestState<GLboolean, 1>(GL_PACK_SWAP_BYTES, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_PACK_LSB_FIRST, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_PACK_ROW_LENGTH, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_IMAGE_HEIGHT, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_ROWS, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_PIXELS, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_IMAGES, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_ALIGNMENT, { { 4 } });
    requestState<GLboolean, 1>(GL_UNPACK_SWAP_BYTES, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_UNPACK_LSB_FIRST, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_UNPACK_ROW_LENGTH, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_IMAGE_HEIGHT, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_ROWS, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_PIXELS, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_IMAGES, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_ALIGNMENT, { { 4 } });

    std::cout << std::endl << "Pixel Transfer States" << std::endl;
    requestState<GLboolean, 1>(GL_MAP_COLOR, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_MAP_STENCIL, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_INDEX_SHIFT, { { 0 } });
    requestState<GLint    , 1>(GL_INDEX_OFFSET, { { 0 } });
    requestState<GLint    , 1>(GL_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_DEPTH_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_ALPHA_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_DEPTH_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_ALPHA_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_ALPHA_BIAS, { { 0 } });

    std::cout << std::endl << "Pixel Zoom States" << std::endl;
    requestState<GLfloat  , 1>(GL_ZOOM_X, { { 1 } });
    requestState<GLfloat  , 1>(GL_ZOOM_Y, { { 1 } });

    std::cout << std::endl << "Pixel Map States" << std::endl;
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_I_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_S_TO_S_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_R_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_G_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_B_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_A_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_R_TO_R_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_G_TO_G_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_B_TO_B_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_A_TO_A_SIZE, { { 1 } });

    std::cout << std::endl << "Read Buffer States" << std::endl;
    requestState<GLenum   , 1>(GL_READ_BUFFER);

    std::cout << std::endl << std::endl << "[QUERYING STATE VALUES - UNGROUPED/TODO]" << std::endl;

    std::cout << std::endl
        << "OpenGL Version:  " << ContextInfo::version() << std::endl
        << "OpenGL Vendor:   " << ContextInfo::vendor() << std::endl
        << "OpenGL Renderer: " << ContextInfo::renderer() << std::endl
        << "OpenGL Revision: " << Meta::glRevision() << " (gl.xml)" << std::endl << std::endl;

    glfwTerminate();
    return 0;
}
<commit_msg>Add guard clause for GLenum names longer than 37 characters.<commit_after>
#include <iostream>
#include <sstream>
#include <array>
#include <string>
#include <type_traits>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <glbinding/Meta.h>
#include <glbinding/ContextInfo.h>
#include <glbinding/Version.h>
#include <glbinding/Binding.h>

#include <glbinding/gl/types.h>
#include <glbinding/gl/enum.h>
#include <glbinding/gl/functions.h>
#include <glbinding/gl/boolean.h>

using namespace gl;
using namespace glbinding;

namespace
{

    void error(int errnum, const char * errmsg)
    {
        std::cerr << errnum << ": " << errmsg << std::endl;
    }

    static const std::array<GLfloat, 9> identity3{ { 1.f, 0.f, 0.f,  0.f, 1.f, 0.f,  0.f, 0.f, 1.f } };
    static const std::array<GLfloat, 16> identity4{ { 1.f, 0.f, 0.f, 0.f,  0.f, 1.f, 0.f, 0.f,  0.f, 0.f, 1.f, 0.f,  0.f, 0.f, 0.f, 1.f } };

    template <typename T>
    void glrequest(const GLenum pname, T * data);

    template <>
    void glrequest<GLboolean>(const GLenum pname, GLboolean * data)
    {
        glGetBooleanv(pname, data);
    }

    template <>
    void glrequest<GLenum>(const GLenum pname, GLenum * data)
    {
        glGetIntegerv(pname, reinterpret_cast<GLint *>(data));
    }

    template <>
    void glrequest<GLint>(const GLenum pname, GLint * data)
    {
        glGetIntegerv(pname, data);
    }

    template <>
    void glrequest<GLfloat>(const GLenum pname, GLfloat * data)
    {
        glGetFloatv(pname, data);
    }

	template <>
	void glrequest<GLdouble>(const GLenum pname, GLdouble * data)
	{
		glGetDoublev(pname, data);
	}

    template <typename T, int count>
    struct identity
    {
        static bool valid(const std::array<T, count> &)
        {
            return false;
        }
        static std::string str()
        {
            return "";
        }
    };

    template <>
    struct identity<GLfloat, 9>
    {
        static bool valid(const std::array<GLfloat, 9> & data)
        {
            return identity3 == data;
        }
        static std::string str()
        {
            return "identity3";
        }
    };

    template <>
    struct identity<GLfloat, 16>
    {
        static bool valid(const std::array<GLfloat, 16> & data)
        {
            return identity4 == data;
        }
        static std::string str()
        {
            return "identity4";
        }
    };

    template <typename T, int count>
    std::string string(const std::array<T, count> & data)
    {
        std::stringstream stream;

        if (identity<T, count>::valid(data))
            stream << identity<T, count>::str();
        else
        {
            if (data.size() > 1)
                stream << "(";

            for (int i = 0; i < count; ++i)
            {
                stream << data[i];
                if (i + 1 < count)
                    stream << ", ";
            }

            if (data.size() > 1)
                stream << ")";
        }

        return stream.str();
    }

    template <typename T, int count>
    void request(const GLenum pname, std::array<T, count> & data)
    {
        glrequest<T>(pname, data.data());

        static const size_t MAX_PSTRING_LENGTH { 37 };    // actually, it's 44 / average is 23,
                                                          // but 37 works for 452 of 462 glGet enums (98%)

        const std::string pstring{ glbinding::Meta::getString(pname) };
		const std::string spaces{ std::string((glbinding::Meta::getString(pname).length() > 37) ? 1 : (MAX_PSTRING_LENGTH - pstring.length()), ' ') };

        if (glGetError() != gl::GL_NO_ERROR)
        {
            std::cout << "\t" << pstring << spaces << " = NOT AVAILABLE" << std::endl;
            return;
        }
        std::cout << "\t" << glbinding::Meta::getString(pname) << spaces << " = " << string<T, count>(data);
    }

    template <typename T, int count>
    void requestState(const GLenum pname)
    {
        std::array<T, count> data;
        request<T, count>(pname, data);

        std::cout << std::endl;
    }

    template <typename T, int count>
    void requestState(const GLenum pname, const std::array<T, count> & expected)
    {
        std::array<T, count> data;
        request<T, count>(pname, data);

        if (!expected.empty() && expected != data)
            std::cout << ", expected " << string<T, count>(expected);

        std::cout << std::endl;
    }
}

int main(int argc, const char * argv[])
{
    if (!Meta::stringsByGL())
    {
        std::cout << "Strings by GL not supported (enable through OPTION_STRINGS_BY_GL)" << std::endl;

        return 1;
    }
#ifndef __APPLE__
    if (argc == 2 && (std::string(argv[1]).compare("--help") || std::string(argv[1]).compare("-h")))
    {
        std::cout << "Usage: " << argv[0] << " [MAJOR_VERSION MINOR_VERSION [CORE [FORWARD_COMPATIBLE]]]" << std::endl;

        return 1;
    }
#endif

    if (!glfwInit())
        return 1;

    glfwSetErrorCallback(error);

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_VISIBLE, false);

#ifdef __APPLE__
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
    if (argc >= 3)
    {
        int majorVersion = atoi(argv[1]);
        int minorVersion = atoi(argv[2]);

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, majorVersion);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minorVersion);
    }

    if (argc >= 4)
    {
        int core = atoi(argv[3]);

        glfwWindowHint(GLFW_OPENGL_PROFILE, core ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_ANY_PROFILE);
    }

    if (argc >= 5)
    {
        int forwardComaptability = atoi(argv[3]);

        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, forwardComaptability ? true : false);
    }
#endif

    GLFWwindow * window = glfwCreateWindow(320, 240, "", nullptr, nullptr);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwHideWindow(window);

    glfwMakeContextCurrent(window);

    Binding::initialize();

    std::cout << std::endl << "[QUERYING STATE VALUES]" << std::endl;

    std::cout << std::endl << "Matrix Stack States" << std::endl;
    requestState<GLenum   , 1>(GL_MATRIX_MODE, { { GL_MODELVIEW } });
    requestState<GLfloat  , 16>(GL_COLOR_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_MODELVIEW_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_PROJECTION_MATRIX, identity4);
    requestState<GLfloat  , 16>(GL_TEXTURE_MATRIX, identity4);
    requestState<GLint    , 1>(GL_COLOR_MATRIX_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MODELVIEW_STACK_DEPTH);
    requestState<GLint    , 1>(GL_PROJECTION_STACK_DEPTH);
    requestState<GLint    , 1>(GL_TEXTURE_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_MODELVIEW_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_PROJECTION_STACK_DEPTH);
    requestState<GLint    , 1>(GL_MAX_TEXTURE_STACK_DEPTH);

    std::cout << std::endl << "Viewport States" << std::endl;
    requestState<GLint    , 4>(GL_VIEWPORT);
    requestState<GLint    , 2>(GL_MAX_VIEWPORT_DIMS);

    std::cout << std::endl << "Pixel Sotre States" << std::endl;
    requestState<GLboolean, 1>(GL_PACK_SWAP_BYTES, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_PACK_LSB_FIRST, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_PACK_ROW_LENGTH, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_IMAGE_HEIGHT, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_ROWS, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_PIXELS, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_SKIP_IMAGES, { { 0 } });
    requestState<GLint    , 1>(GL_PACK_ALIGNMENT, { { 4 } });
    requestState<GLboolean, 1>(GL_UNPACK_SWAP_BYTES, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_UNPACK_LSB_FIRST, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_UNPACK_ROW_LENGTH, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_IMAGE_HEIGHT, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_ROWS, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_PIXELS, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_SKIP_IMAGES, { { 0 } });
    requestState<GLint    , 1>(GL_UNPACK_ALIGNMENT, { { 4 } });

    std::cout << std::endl << "Pixel Transfer States" << std::endl;
    requestState<GLboolean, 1>(GL_MAP_COLOR, { { GL_FALSE } });
    requestState<GLboolean, 1>(GL_MAP_STENCIL, { { GL_FALSE } });
    requestState<GLint    , 1>(GL_INDEX_SHIFT, { { 0 } });
    requestState<GLint    , 1>(GL_INDEX_OFFSET, { { 0 } });
    requestState<GLint    , 1>(GL_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_DEPTH_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_ALPHA_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_DEPTH_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_COLOR_MATRIX_ALPHA_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_RED_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_GREEN_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_BLUE_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_ALPHA_SCALE, { { 1 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_RED_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_GREEN_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_BLUE_BIAS, { { 0 } });
    requestState<GLint    , 1>(GL_POST_CONVOLUTION_ALPHA_BIAS, { { 0 } });

    std::cout << std::endl << "Pixel Zoom States" << std::endl;
    requestState<GLfloat  , 1>(GL_ZOOM_X, { { 1 } });
    requestState<GLfloat  , 1>(GL_ZOOM_Y, { { 1 } });

    std::cout << std::endl << "Pixel Map States" << std::endl;
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_I_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_S_TO_S_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_R_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_G_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_B_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_I_TO_A_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_R_TO_R_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_G_TO_G_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_B_TO_B_SIZE, { { 1 } });
    requestState<GLint    , 1>(GL_PIXEL_MAP_A_TO_A_SIZE, { { 1 } });

    std::cout << std::endl << "Read Buffer States" << std::endl;
    requestState<GLenum   , 1>(GL_READ_BUFFER);

    std::cout << std::endl << std::endl << "[QUERYING STATE VALUES - UNGROUPED/TODO]" << std::endl;

    std::cout << std::endl
        << "OpenGL Version:  " << ContextInfo::version() << std::endl
        << "OpenGL Vendor:   " << ContextInfo::vendor() << std::endl
        << "OpenGL Renderer: " << ContextInfo::renderer() << std::endl
        << "OpenGL Revision: " << Meta::glRevision() << " (gl.xml)" << std::endl << std::endl;

    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>/*
 *  qi_vfa_prep.cpp
 *
 *  Copyright (c) 2019 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <type_traits>
#include <unsupported/Eigen/MatrixFunctions>

// #define QI_DEBUG_BUILD 1

#include "Args.h"
#include "ImageIO.h"
#include "Macro.h"
#include "Model.h"
#include "ModelFitFilter.h"
#include "SequenceBase.h"
#include "SimulateModel.h"
#include "Util.h"

struct MUPASequence : QI::SequenceBase {
    double                   TR, Tramp, FA;
    int                      SPS;
    std::vector<std::string> prep_type;
    std::vector<double>      prep_time;
    QI_SEQUENCE_DECLARE(MUPA);
    Eigen::Index size() const override { return prep_type.size(); };
};
void from_json(const json &j, MUPASequence &s) {
    j.at("TR").get_to(s.TR);
    j.at("Tramp").get_to(s.Tramp);
    s.FA = j.at("FA").get<double>() * M_PI / 180.0;
    j.at("SPS").get_to(s.SPS);
    j.at("prep_type").get_to(s.prep_type);
    j.at("prep_time").get_to(s.prep_time);
}

void to_json(json &j, const MUPASequence &s) {
    j = json{{"TR", s.TR},
             {"Tramp", s.Tramp},
             {"FA", s.FA * 180 / M_PI},
             {"SPS", s.SPS},
             {"prep_type", s.prep_type},
             {"prep_time", s.prep_time}};
}

struct MUPAModel {
    using DataType      = double;
    using ParameterType = double;

    static constexpr int NV = 3; // Number of varying parameters
    static constexpr int ND = 0; // Number of derived parameters
    static constexpr int NF = 0; // Number of fixed parameters
    static constexpr int NI = 1; // Number of inputs

    using VaryingArray = QI_ARRAYN(ParameterType, NV); // Type for the varying parameter array
    using FixedArray   = QI_ARRAYN(ParameterType, NF); // Type for the fixed parameter array

    // Sequence paramter structs
    MUPASequence &sequence;

    // Fitting start point and bounds
    // The PD will be scaled by the fitting function to keep parameters roughly the same magnitude
    VaryingArray const start{30., 1., 0.1};
    VaryingArray const bounds_lo{1, 0.01, 0.01};
    VaryingArray const bounds_hi{150, 10.0, 10.0};

    std::array<std::string, NV> const varying_names{"PD", "T1", "T2"};
    std::array<std::string, NF> const fixed_names{};
    // If fixed parameters not supplied, use these default values
    FixedArray const fixed_defaults{};

    template <typename Derived>
    auto signal(Eigen::ArrayBase<Derived> const &v, FixedArray const &) const
        -> QI_ARRAY(typename Derived::Scalar) {
        using T     = typename Derived::Scalar;
        using Mat33 = Eigen::Matrix<T, 3, 3>;
        using Mat44 = Eigen::Matrix<T, 4, 4>;
        T const &PD = v[0];
        T const &R1 = 1. / v[1];
        T const &R2 = 1. / v[2];

        auto const Relax = [&PD, &R1, &R2](double const t) {
            Mat44 R;
            R << -R2, 0, 0, 0,      //
                0, -R2, 0, 0,       //
                0, 0, -R1, PD * R1, //
                0, 0, 0, 0;
            Mat44 eRt = (R * t).exp();
            return eRt;
        };

        auto const RF = [](double const a, double const ph) {
            auto const ca = cos(a);
            auto const sa = sin(a);
            // I got the definition of the rotation matrix around the wrong axis,
            // so rotate the axis
            auto const      ux = cos(ph - M_PI_2);
            auto const      uy = sin(ph - M_PI_2);
            Eigen::Matrix4d A;
            A << ca + ux * ux * (1 - ca), ux * uy * (1 - ca), -uy * sa, 0., //
                ux * uy * (1 - ca), ca + uy * uy * (1 - ca), ux * sa, 0.,   //
                uy * sa, -ux * sa, ca, 0.,                                  //
                0., 0., 0., 1.;
            return A;
        };

        auto const A     = RF(sequence.FA, 0);
        auto const R     = Relax(sequence.TR);
        auto const S     = Eigen::DiagonalMatrix<double, 4, 4>({0, 0, 1., 1.}).toDenseMatrix();
        auto const ramp  = Relax(sequence.Tramp);
        auto const RUFIS = S * R * A;
        auto const seg2  = RUFIS.pow(sequence.SPS / 2.0);
        auto const seg   = ramp * seg2 * seg2 * ramp;
        // First calculate the system matrix
        Mat44 X = Mat44::Identity();
        for (int is = 0; is < sequence.size(); is++) {
            double const tprep = sequence.prep_time[is];
            if (sequence.prep_type[is] == "inversion") {
                auto const I  = RF(M_PI, 0);
                auto const TI = Relax(tprep);
                X             = S * TI * I * X;
                QI_DBMAT(I);
                QI_DBMAT(TI);
                QI_DBMAT(X);
            } else if (sequence.prep_type[is] == "t2-prep") {
                auto const TD = RF(M_PI_2, 0);
                auto const TE = Relax(tprep);
                auto const TU = RF(-M_PI_2, 0);
                X             = S * TU * TE * TD * X;
                QI_DBMAT(TD);
                QI_DBMAT(TE);
                QI_DBMAT(TU);
                QI_DBMAT(X);
            } else if (sequence.prep_type[is] == "delay") {
                auto const D = Relax(tprep);
                X            = D * X;
                QI_DBMAT(D);
                QI_DBMAT(X);
            }
            X = seg * X;
        }

        // Solve for steady-state and re-augment
        Mat33           Xr    = (X - Mat44::Identity()).template topLeftCorner<3, 3>();
        Eigen::Vector3d b     = -X.template topRightCorner<3, 1>();
        Eigen::Vector3d m_ss  = Xr.partialPivLu().solve(b);
        Eigen::Vector4d m_aug = Eigen::Vector4d::Ones();
        m_aug.head(3)         = m_ss;
        QI_DBVEC(m_ss);
        // Now loop through the segments and record the signal for each
        Eigen::ArrayXd sig(sequence.size());
        for (int is = 0; is < sequence.size(); is++) {
            double const tprep = sequence.prep_time[is];
            if (sequence.prep_type[is] == "inversion") {
                auto const I  = RF(M_PI, 0);
                auto const TI = Relax(tprep);
                m_aug         = S * TI * I * m_aug;
            } else if (sequence.prep_type[is] == "t2-prep") {
                auto const TD = RF(M_PI / 2, 0);
                auto const TE = Relax(tprep);
                auto const TU = RF(-M_PI / 2, 0);
                m_aug         = S * TU * TE * TD * m_aug;
            } else if (sequence.prep_type[is] == "delay") {
                auto const D = Relax(tprep);
                m_aug        = D * m_aug;
            }
            m_aug            = seg2 * ramp * m_aug;
            auto const m_sig = A * m_aug;
            sig[is]          = m_sig[0]; // Real part
            m_aug            = ramp * seg2 * m_aug;
        }
        QI_DB(PD);
        QI_DB(1 / R1);
        QI_DB(1 / R2);
        QI_DBVEC(sig);
        return sig;
    }
};

template <> struct QI::NoiseFromModelType<MUPAModel> : QI::RealNoise {};

struct MUPACost {
    MUPAModel const &     model;
    MUPAModel::FixedArray fixed;
    QI_ARRAY(double) const data;

    template <typename T> bool operator()(T const *const vin, T *rin) const {
        Eigen::Map<QI_ARRAYN(T, MUPAModel::NV) const> const varying(vin);
        Eigen::Map<QI_ARRAY(T)>                             residuals(rin, data.rows());
        residuals = data - model.signal(varying, fixed);
        QI_DBVEC(residuals);
        return true;
    }
};

struct MUPAFit {
    // Boilerplate information required by ModelFitFilter
    static const bool Blocked = false; // = input is in blocks and outputs have multiple entries
    static const bool Indexed = false; // = the voxel index will be passed to the fit
    using RMSErrorType        = double;
    using FlagType            = int; // Almost always the number of iterations

    using ModelType = MUPAModel;
    ModelType model;

    // Have to tell the ModelFitFilter how many volumes we expect in each input
    int input_size(const int) const { return model.sequence.size(); }

    // This has to match the function signature that will be called in ModelFitFilter (which depends
    // on Blocked/Indexed. The return type is a simple struct indicating success, and on failure
    // also the reason for failure
    QI::FitReturnType
    fit(std::vector<Eigen::ArrayXd> const &inputs,    // Input: signal data
        Eigen::ArrayXd const &             fixed,     // Input: Fixed parameters
        ModelType::VaryingArray &          varying,   // Output: Varying parameters
        RMSErrorType &                     rmse,      // Output: root-mean-square error
        std::vector<Eigen::ArrayXd> &      residuals, // Optional output: point residuals
        FlagType &                         iterations /* Usually iterations */) const {
        // First scale down the raw data so that PD will be roughly the same magnitude as other
        // parameters This is important for numerical stability in the optimiser

        QI_DBVEC(inputs[0]);

        double scale = inputs[0].maxCoeff();
        QI_DB(scale);
        if (scale < std::numeric_limits<double>::epsilon()) {
            varying = ModelType::VaryingArray::Zero();
            rmse    = 0.0;
            return {false, "Maximum data value was zero or less"};
        }
        Eigen::ArrayXd const data = inputs[0] / scale;

        // Setup Ceres
        ceres::Problem problem;
        using VFADiff =
            ceres::NumericDiffCostFunction<MUPACost, ceres::CENTRAL, ceres::DYNAMIC, ModelType::NV>;
        auto *vfa_prep_cost = new VFADiff(
            new MUPACost{model, fixed, data}, ceres::TAKE_OWNERSHIP, model.sequence.size());
        ceres::LossFunction *loss = new ceres::HuberLoss(1.0); // Don't know if this helps
        // This is where the parameters and cost functions actually get added to Ceres
        problem.AddResidualBlock(vfa_prep_cost, loss, varying.data());

        // Set up parameter bounds
        for (int i = 0; i < ModelType::NV; i++) {
            problem.SetParameterLowerBound(varying.data(), i, model.bounds_lo[i]);
            problem.SetParameterUpperBound(varying.data(), i, model.bounds_hi[i]);
        }

        ceres::Solver::Options options;
        ceres::Solver::Summary summary;
        options.max_num_iterations  = 30;
        options.function_tolerance  = 1e-5;
        options.gradient_tolerance  = 1e-6;
        options.parameter_tolerance = 1e-4;
        options.logging_type        = ceres::SILENT;

        varying = model.start;
        ceres::Solve(options, &problem, &summary);
        if (!summary.IsSolutionUsable()) {
            return {false, summary.FullReport()};
        }

        Eigen::ArrayXd const residual = (data - model.signal(varying, fixed)) * scale;
        rmse                          = sqrt(residual.square().mean());
        if (residuals.size() > 0) {
            residuals[0] = residual;
        }
        varying[0] *= scale; // Multiply signals/proton density back up
        QI_DBVEC(varying);
        iterations = summary.iterations.size();
        return {true, ""};
    }
};

/*
 * Main
 */
int mupa_main(int argc, char **argv) {
    Eigen::initParallel();
    args::ArgumentParser          parser("Calculates PD/T1/T2 from MUPA data "
                                "data.\nhttp://github.com/spinicist/QUIT");
    args::Positional<std::string> input_path(parser, "INPUT", "Input MUPA file");

    QI_COMMON_ARGS;

    QI::ParseArgs(parser, argc, argv, verbose, threads);

    QI::CheckPos(input_path);

    QI::Log(verbose, "Reading sequence parameters");
    json doc = json_file ? QI::ReadJSON(json_file.Get()) : QI::ReadJSON(std::cin);

    MUPASequence sequence(doc["MUPA"]);
    MUPAModel    model{sequence};
    if (simulate) {
        QI::SimulateModel<MUPAModel, false>(
            doc, model, {}, {input_path.Get()}, verbose, simulate.Get());
    } else {
        MUPAFit fit{model};
        auto fit_filter = QI::ModelFitFilter<MUPAFit>::New(&fit, verbose, resids, subregion.Get());
        fit_filter->ReadInputs({input_path.Get()}, {}, mask.Get());
        fit_filter->Update();
        fit_filter->WriteOutputs(prefix.Get() + "MUPA_");
    }
    QI::Log(verbose, "Finished.");
    return EXIT_SUCCESS;
}
<commit_msg>ENH Switch to geometric sum for MUPA segment<commit_after>/*
 *  qi_vfa_prep.cpp
 *
 *  Copyright (c) 2019 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <type_traits>
#include <unsupported/Eigen/MatrixFunctions>

// #define QI_DEBUG_BUILD 1

#include "Args.h"
#include "ImageIO.h"
#include "Macro.h"
#include "Model.h"
#include "ModelFitFilter.h"
#include "SequenceBase.h"
#include "SimulateModel.h"
#include "Util.h"

struct MUPASequence : QI::SequenceBase {
    double                   TR, Tramp, FA;
    int                      SPS;
    std::vector<std::string> prep_type;
    std::vector<double>      prep_time;
    QI_SEQUENCE_DECLARE(MUPA);
    Eigen::Index size() const override { return prep_type.size(); };
};
void from_json(const json &j, MUPASequence &s) {
    j.at("TR").get_to(s.TR);
    j.at("Tramp").get_to(s.Tramp);
    s.FA = j.at("FA").get<double>() * M_PI / 180.0;
    j.at("SPS").get_to(s.SPS);
    j.at("prep_type").get_to(s.prep_type);
    j.at("prep_time").get_to(s.prep_time);
}

void to_json(json &j, const MUPASequence &s) {
    j = json{{"TR", s.TR},
             {"Tramp", s.Tramp},
             {"FA", s.FA * 180 / M_PI},
             {"SPS", s.SPS},
             {"prep_type", s.prep_type},
             {"prep_time", s.prep_time}};
}

struct MUPAModel {
    using DataType      = double;
    using ParameterType = double;

    static constexpr int NV = 3; // Number of varying parameters
    static constexpr int ND = 0; // Number of derived parameters
    static constexpr int NF = 0; // Number of fixed parameters
    static constexpr int NI = 1; // Number of inputs

    using VaryingArray = QI_ARRAYN(ParameterType, NV); // Type for the varying parameter array
    using FixedArray   = QI_ARRAYN(ParameterType, NF); // Type for the fixed parameter array

    // Sequence paramter structs
    MUPASequence &sequence;

    // Fitting start point and bounds
    // The PD will be scaled by the fitting function to keep parameters roughly the same magnitude
    VaryingArray const start{30., 1., 0.1};
    VaryingArray const bounds_lo{1, 0.01, 0.01};
    VaryingArray const bounds_hi{150, 10.0, 10.0};

    std::array<std::string, NV> const varying_names{"PD", "T1", "T2"};
    std::array<std::string, NF> const fixed_names{};
    // If fixed parameters not supplied, use these default values
    FixedArray const fixed_defaults{};

    template <typename Derived>
    auto signal(Eigen::ArrayBase<Derived> const &v, FixedArray const &) const
        -> QI_ARRAY(typename Derived::Scalar) {
        using T    = typename Derived::Scalar;
        using Vec3 = Eigen::Vector<T, 3>;
        // using Vec4  = Eigen::Vector<T, 4>;
        using Mat33 = Eigen::Matrix<T, 3, 3>;
        using Mat44 = Eigen::Matrix<T, 4, 4>;
        T const &PD = v[0];
        T const &R1 = 1. / v[1];
        T const &R2 = 1. / v[2];

        auto const Relax = [&PD, &R1, &R2](double const t) {
            Mat44 R;
            R << -R2, 0, 0, 0,      //
                0, -R2, 0, 0,       //
                0, 0, -R1, PD * R1, //
                0, 0, 0, 0;
            Mat44 eRt = (R * t).exp();
            return eRt;
        };

        auto const RF = [](double const a, double const ph) {
            auto const ca = cos(a);
            auto const sa = sin(a);
            // I got the definition of the rotation matrix around the wrong axis,
            // so rotate the axis
            auto const      ux = cos(ph - M_PI_2);
            auto const      uy = sin(ph - M_PI_2);
            Eigen::Matrix4d A;
            A << ca + ux * ux * (1 - ca), ux * uy * (1 - ca), -uy * sa, 0., //
                ux * uy * (1 - ca), ca + uy * uy * (1 - ca), ux * sa, 0.,   //
                uy * sa, -ux * sa, ca, 0.,                                  //
                0., 0., 0., 1.;
            return A;
        };

        auto const  A     = RF(sequence.FA, 0);
        auto const  R     = Relax(sequence.TR);
        auto const  S     = Eigen::DiagonalMatrix<double, 4, 4>({0, 0, 1., 1.}).toDenseMatrix();
        Mat44 const ramp  = Relax(sequence.Tramp);
        Mat44 const RUFIS = S * R * A;
        Mat44 const seg   = RUFIS.pow(sequence.SPS);
        // First calculate the system matrix
        Mat44 X = Mat44::Identity();
        for (int is = 0; is < sequence.size(); is++) {
            double const tprep = sequence.prep_time[is];
            if (sequence.prep_type[is] == "inversion") {
                auto const I  = RF(M_PI, 0);
                auto const TI = Relax(tprep);
                X             = S * TI * I * X;
            } else if (sequence.prep_type[is] == "t2-prep") {
                auto const TD = RF(M_PI_2, 0);
                auto const TE = Relax(tprep);
                auto const TU = RF(-M_PI_2, 0);
                X             = S * TU * TE * TD * X;
            } else if (sequence.prep_type[is] == "delay") {
                auto const D = Relax(tprep);
                X            = D * X;
            }
            X = ramp * seg * ramp * X;
        }

        // Solve for steady-state and re-augment
        Mat33           Xr    = (X - Mat44::Identity()).template topLeftCorner<3, 3>();
        Eigen::Vector3d b     = -X.template topRightCorner<3, 1>();
        Eigen::Vector3d m_ss  = Xr.partialPivLu().solve(b);
        Eigen::Vector4d m_aug = Eigen::Vector4d::Ones();
        m_aug.head(3)         = m_ss;
        QI_DBVEC(m_ss);
        // Now loop through the segments and record the signal for each
        Eigen::ArrayXd sig(sequence.size());
        for (int is = 0; is < sequence.size(); is++) {
            double const tprep = sequence.prep_time[is];
            if (sequence.prep_type[is] == "inversion") {
                auto const I  = RF(M_PI, 0);
                auto const TI = Relax(tprep);
                m_aug         = S * TI * I * m_aug;
            } else if (sequence.prep_type[is] == "t2-prep") {
                auto const TD = RF(M_PI / 2, 0);
                auto const TE = Relax(tprep);
                auto const TU = RF(-M_PI / 2, 0);
                m_aug         = S * TU * TE * TD * m_aug;
            } else if (sequence.prep_type[is] == "delay") {
                auto const D = Relax(tprep);
                m_aug        = D * m_aug;
            }
            m_aug = ramp * m_aug;
            // Geometric Sum formula to get average
            Mat44 const LHS = (Mat44::Identity() - RUFIS);
            QI_DBMAT(LHS);
            Vec3 const RHS = ((Mat44::Identity() - seg) * m_aug).template head<3>() -
                             (sequence.SPS * LHS.template topRightCorner<3, 1>());
            QI_DBVEC(RHS);
            Vec3 const m_gm =
                LHS.template topLeftCorner<3, 3>().partialPivLu().solve(RHS) / sequence.SPS;
            QI_DBVEC(m_gm);
            sig[is] = m_gm[2] * sin(sequence.FA);
            QI_DB(sig[is]);
            m_aug = ramp * seg * m_aug;
        }
        QI_DB(PD);
        QI_DB(1 / R1);
        QI_DB(1 / R2);
        QI_DBVEC(sig);
        return sig;
    }
};

template <> struct QI::NoiseFromModelType<MUPAModel> : QI::RealNoise {};

struct MUPACost {
    MUPAModel const &     model;
    MUPAModel::FixedArray fixed;
    QI_ARRAY(double) const data;

    template <typename T> bool operator()(T const *const vin, T *rin) const {
        Eigen::Map<QI_ARRAYN(T, MUPAModel::NV) const> const varying(vin);
        Eigen::Map<QI_ARRAY(T)>                             residuals(rin, data.rows());
        residuals = data - model.signal(varying, fixed);
        QI_DBVEC(residuals);
        return true;
    }
};

struct MUPAFit {
    // Boilerplate information required by ModelFitFilter
    static const bool Blocked = false; // = input is in blocks and outputs have multiple entries
    static const bool Indexed = false; // = the voxel index will be passed to the fit
    using RMSErrorType        = double;
    using FlagType            = int; // Almost always the number of iterations

    using ModelType = MUPAModel;
    ModelType model;

    // Have to tell the ModelFitFilter how many volumes we expect in each input
    int input_size(const int) const { return model.sequence.size(); }

    // This has to match the function signature that will be called in ModelFitFilter (which depends
    // on Blocked/Indexed. The return type is a simple struct indicating success, and on failure
    // also the reason for failure
    QI::FitReturnType
    fit(std::vector<Eigen::ArrayXd> const &inputs,    // Input: signal data
        Eigen::ArrayXd const &             fixed,     // Input: Fixed parameters
        ModelType::VaryingArray &          varying,   // Output: Varying parameters
        RMSErrorType &                     rmse,      // Output: root-mean-square error
        std::vector<Eigen::ArrayXd> &      residuals, // Optional output: point residuals
        FlagType &                         iterations /* Usually iterations */) const {
        // First scale down the raw data so that PD will be roughly the same magnitude as other
        // parameters This is important for numerical stability in the optimiser

        QI_DBVEC(inputs[0]);

        double scale = inputs[0].maxCoeff();
        QI_DB(scale);
        if (scale < std::numeric_limits<double>::epsilon()) {
            varying = ModelType::VaryingArray::Zero();
            rmse    = 0.0;
            return {false, "Maximum data value was zero or less"};
        }
        Eigen::ArrayXd const data = inputs[0] / scale;

        // Setup Ceres
        ceres::Problem problem;
        using VFADiff =
            ceres::NumericDiffCostFunction<MUPACost, ceres::CENTRAL, ceres::DYNAMIC, ModelType::NV>;
        auto *vfa_prep_cost = new VFADiff(
            new MUPACost{model, fixed, data}, ceres::TAKE_OWNERSHIP, model.sequence.size());
        ceres::LossFunction *loss = new ceres::HuberLoss(1.0); // Don't know if this helps
        // This is where the parameters and cost functions actually get added to Ceres
        problem.AddResidualBlock(vfa_prep_cost, loss, varying.data());

        // Set up parameter bounds
        for (int i = 0; i < ModelType::NV; i++) {
            problem.SetParameterLowerBound(varying.data(), i, model.bounds_lo[i]);
            problem.SetParameterUpperBound(varying.data(), i, model.bounds_hi[i]);
        }

        ceres::Solver::Options options;
        ceres::Solver::Summary summary;
        options.max_num_iterations  = 30;
        options.function_tolerance  = 1e-5;
        options.gradient_tolerance  = 1e-6;
        options.parameter_tolerance = 1e-4;
        options.logging_type        = ceres::SILENT;

        varying = model.start;
        ceres::Solve(options, &problem, &summary);
        if (!summary.IsSolutionUsable()) {
            return {false, summary.FullReport()};
        }

        Eigen::ArrayXd const residual = (data - model.signal(varying, fixed)) * scale;
        rmse                          = sqrt(residual.square().mean());
        if (residuals.size() > 0) {
            residuals[0] = residual;
        }
        varying[0] *= scale; // Multiply signals/proton density back up
        QI_DBVEC(varying);
        iterations = summary.iterations.size();
        return {true, ""};
    }
};

/*
 * Main
 */
int mupa_main(int argc, char **argv) {
    Eigen::initParallel();
    args::ArgumentParser          parser("Calculates PD/T1/T2 from MUPA data "
                                "data.\nhttp://github.com/spinicist/QUIT");
    args::Positional<std::string> input_path(parser, "INPUT", "Input MUPA file");

    QI_COMMON_ARGS;

    QI::ParseArgs(parser, argc, argv, verbose, threads);

    QI::CheckPos(input_path);

    QI::Log(verbose, "Reading sequence parameters");
    json doc = json_file ? QI::ReadJSON(json_file.Get()) : QI::ReadJSON(std::cin);

    MUPASequence sequence(doc["MUPA"]);
    MUPAModel    model{sequence};
    if (simulate) {
        QI::SimulateModel<MUPAModel, false>(
            doc, model, {}, {input_path.Get()}, verbose, simulate.Get());
    } else {
        MUPAFit fit{model};
        auto fit_filter = QI::ModelFitFilter<MUPAFit>::New(&fit, verbose, resids, subregion.Get());
        fit_filter->ReadInputs({input_path.Get()}, {}, mask.Get());
        fit_filter->Update();
        fit_filter->WriteOutputs(prefix.Get() + "MUPA_");
    }
    QI::Log(verbose, "Finished.");
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/// HEADER
#include "transform_cloud.h"

/// PROJECT
#include <csapex/msg/io.h>
#include <csapex_transform/transform_message.h>
#include <csapex/model/node_modifier.h>
#include <csapex/utility/register_apex_plugin.h>

/// SYSTEM
#include <boost/mpl/for_each.hpp>

CSAPEX_REGISTER_CLASS(csapex::TransformCloud, csapex::Node)

using namespace csapex;
using namespace csapex::connection_types;

TransformCloud::TransformCloud()
{
}

void TransformCloud::setup(NodeModifier& node_modifier)
{
    input_cloud_ = node_modifier.addInput<PointCloudMessage>("PointCloud");
    input_transform_ = node_modifier.addInput<TransformMessage>("Transformation");

    output_ = node_modifier.addOutput<PointCloudMessage>("PointCloud");
}

void TransformCloud::process()
{
    PointCloudMessage::ConstPtr msg = msg::getMessage<PointCloudMessage>(input_cloud_);

    boost::apply_visitor (PointCloudMessage::Dispatch<TransformCloud>(this, msg), msg->value);
}

template <class PointT>
void TransformCloud::inputCloud(typename pcl::PointCloud<PointT>::ConstPtr cloud)
{
    TransformMessage::ConstPtr transform = msg::getMessage<TransformMessage>(input_transform_);
    const tf::Transform& t = transform->value;

    typename pcl::PointCloud<PointT>::Ptr out(new pcl::PointCloud<PointT>);
    out->header = cloud->header;
    out->width = cloud->width;
    out->height = cloud->height;
    out->is_dense = cloud->is_dense;

    std::size_t N = cloud->points.size();
    out->points.resize(N);

    for(std::size_t i = 0; i < N; ++i) {
        PointT pt = cloud->points[i];
        tf::Quaternion q = t.getRotation();
        tf::Vector3 tr = t.getOrigin();

        tf::Vector3 p(pt.x, pt.y, pt.z);

//        tf::Vector3 tfd =  tf::quatRotate(q, p) + tr;
        tf::Vector3 tfd = t * p;
        pt.x = tfd.x();
        pt.y = tfd.y();
        pt.z = tfd.z();
        out->points[i] = pt;
    }

    std::string frame = cloud->header.frame_id;

    if(frame == transform->child_frame) {
        frame = transform->frame_id;
    }

    PointCloudMessage::Ptr msg(new PointCloudMessage(frame, cloud->header.stamp));
    msg->value = out;

    msg::publish(output_, msg);
}
<commit_msg>minor<commit_after>/// HEADER
#include "transform_cloud.h"

/// PROJECT
#include <csapex/msg/io.h>
#include <csapex_transform/transform_message.h>
#include <csapex/model/node_modifier.h>
#include <csapex/utility/register_apex_plugin.h>

/// SYSTEM
#include <boost/mpl/for_each.hpp>

CSAPEX_REGISTER_CLASS(csapex::TransformCloud, csapex::Node)

using namespace csapex;
using namespace csapex::connection_types;

TransformCloud::TransformCloud()
{
}

void TransformCloud::setup(NodeModifier& node_modifier)
{
    input_cloud_ = node_modifier.addInput<PointCloudMessage>("PointCloud");
    input_transform_ = node_modifier.addInput<TransformMessage>("Transformation");

    output_ = node_modifier.addOutput<PointCloudMessage>("PointCloud");
}

void TransformCloud::process()
{
    PointCloudMessage::ConstPtr msg = msg::getMessage<PointCloudMessage>(input_cloud_);

    boost::apply_visitor (PointCloudMessage::Dispatch<TransformCloud>(this, msg), msg->value);
}

template <class PointT>
void TransformCloud::inputCloud(typename pcl::PointCloud<PointT>::ConstPtr cloud)
{
    TransformMessage::ConstPtr transform = msg::getMessage<TransformMessage>(input_transform_);
    const tf::Transform& t = transform->value;

    typename pcl::PointCloud<PointT>::Ptr out(new pcl::PointCloud<PointT>);
    out->header = cloud->header;
    out->width = cloud->width;
    out->height = cloud->height;
    out->is_dense = cloud->is_dense;

    std::size_t N = cloud->points.size();
    out->points.resize(N);

    for(std::size_t i = 0; i < N; ++i) {
        PointT pt = cloud->points[i];

        tf::Vector3 p(pt.x, pt.y, pt.z);

        tf::Vector3 tfd = t * p;
        pt.x = tfd.x();
        pt.y = tfd.y();
        pt.z = tfd.z();
        out->points[i] = pt;
    }

    std::string frame = cloud->header.frame_id;

    if(frame == transform->child_frame) {
        frame = transform->frame_id;
    }

    PointCloudMessage::Ptr msg(new PointCloudMessage(frame, cloud->header.stamp));
    msg->value = out;

    msg::publish(output_, msg);
}
<|endoftext|>


<commit_before><commit_msg>Set 'remote_fonts_enabled' to true in test_shell. Chrome has it off by default, but we don't want to lose the test coverage for dynamic font support. So, we turn it on in test_shell.<commit_after><|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <memory>
#include <utility>
#include <functional>
#include "Indexer.hpp"

namespace Core
{
	template <typename Key, typename Object, class IndexerClass>
	class VectorIndexer
	{
	public:
		using IndexerType = IndexerClass;
		using VectorType = std::vector<Object>;

		VectorIndexer() : _vector(), _map() {}

		Object& Add(const Key& key, Object&& object)
		{
			return Add(key, object);
		}

		Object& Add(const Key& key, Object& object)
		{
			_vector.push_back(object);

			uint idx = _vector.size() - 1;
			_map.Add(key, idx);

			return _vector[idx];
		}

		const Object& Add(const Key& key, const Object& object)
		{
			return Add(key, const_cast<Object&>(object));
		}

		const Object& Get(unsigned int index) const
		{
			return _vector[index];
		}

		Object& Get(unsigned int index)
		{
			return const_cast<Object&>(static_cast<const VectorIndexer<Key, Object, IndexerType>*>(this)->Get(index));
		}

		const Object* Find(const Key& key) const
		{
			uint findIndex = _map.Find(key);
			bool isFound = findIndex != decltype(_map)::FailIndex();
			return isFound ? &Get(findIndex) : nullptr;
		}

		Object* Find(const Key& key)
		{
			return const_cast<Object*>(static_cast<const VectorIndexer<Key, Object, IndexerType>*>(this)->Find(key));
		}

		void Delete(const Key& key)
		{
			uint findIdx = _map.Find(key);
			if (findIdx == IndexerType::FailIndex())
				return;

			uint ereaseIdx = findIdx;
			_vector.erase(_vector.begin() + ereaseIdx);
			_map.Delete(key);
		}

		void DeleteAll()
		{
			_vector.clear();
			_map.DeleteAll();
		}

		inline const std::vector<Object>& GetVector() const { return _vector; }
		inline const IndexerType GetIndexer() const { return _map; }

		GET_CONST_ACCESSOR(Size, unsigned int, _vector.size());

	private:
		std::vector<Object>     _vector;
		IndexerType				_map;
	};

	template<typename Key, typename Object>
	using VectorMap = VectorIndexer<Key, Object, IndexMap<Key>>;
	template<typename Key, typename Object>
	using VectorHashMap = VectorIndexer<Key, Object, IndexHashMap<Key>>;
}
<commit_msg>VectorIndexer - 코드 정리<commit_after>#pragma once

#include <vector>
#include <memory>
#include <utility>
#include <functional>
#include "Indexer.hpp"

namespace Core
{
	template <typename Key, typename Object, class IndexerClass>
	class VectorIndexer
	{
	public:
		using IndexerType	= IndexerClass;
		using VectorType	= std::vector<Object>;

		VectorIndexer() : _vector(), _indexer() {}

		Object& Add(const Key& key, Object&& object)
		{
			return Add(key, object);
		}

		Object& Add(const Key& key, Object& object)
		{
			uint idx = _vector.size();
			_indexer.Add(key, idx);

			_vector.push_back(object);
			return _vector[idx];
		}

		const Object& Add(const Key& key, const Object& object)
		{
			return Add(key, const_cast<Object&>(object));
		}

		const Object& Get(unsigned int index) const
		{
			return _vector[index];
		}

		Object& Get(unsigned int index)
		{
			return const_cast<Object&>(static_cast<const VectorIndexer<Key, Object, IndexerType>*>(this)->Get(index));
		}

		const Object* Find(const Key& key) const
		{
			uint findIndex = _indexer.Find(key);
			bool isFound = findIndex != decltype(_indexer)::FailIndex();
			return isFound ? &Get(findIndex) : nullptr;
		}

		Object* Find(const Key& key)
		{
			return const_cast<Object*>(static_cast<const VectorIndexer<Key, Object, IndexerType>*>(this)->Find(key));
		}

		void Delete(const Key& key)
		{
			uint findIdx = _indexer.Find(key);
			if (findIdx == IndexerType::FailIndex())
				return;

			uint ereaseIdx = findIdx;
			_vector.erase(_vector.begin() + ereaseIdx);
			_indexer.Delete(key);
		}

		void DeleteAll()
		{
			_vector.clear();
			_indexer.DeleteAll();
		}

		GET_CONST_ACCESSOR(Vector,		const auto&,	_vector);
		GET_CONST_ACCESSOR(Indexer,		const auto&,	_indexer);
		GET_CONST_ACCESSOR(Size,		unsigned int,	_vector.size());

	private:
		std::vector<Object>     _vector;
		IndexerType				_indexer;
	};

	template<typename Key, typename Object>
	using VectorMap = VectorIndexer<Key, Object, IndexMap<Key>>;
	template<typename Key, typename Object>
	using VectorHashMap = VectorIndexer<Key, Object, IndexHashMap<Key>>;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * 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.
 *
 * 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.
 */

#include "BezierConstruction.h"

using namespace choreograph;
using namespace cinder;

void BezierConstruction::setup()
{
  mCurvePoints = {
    vec2( 100, 600 ),
    vec2( 100, 100 ),
    vec2( 1180, 100 ),
    vec2( 1180, 600 )
  };

  const float duration = 1.5f;

  // Ramp from anchor point to control point.
  auto ramp_a = makeRamp( mCurvePoints[0], mCurvePoints[1], duration );
  // Ramp from control point to anchor point.
  auto ramp_b = makeRamp( mCurvePoints[2], mCurvePoints[3], duration );

  // Lerp between control ramps.
  auto bezier_point = makeBlend<vec2>( ramp_a, ramp_b, 0.0f );

  timeline().setAutoRemove( false );

  timeline().apply<vec2>( &mControlA, ramp_a );
  timeline().apply<vec2>( &mControlB, ramp_b );
  timeline().apply( bezier_point->getMixOutput() ).then<RampTo>( 1.0f, duration );
  timeline().apply<vec2>( &mCurvePoint, bezier_point )
    .startFn( [this] ( Motion<vec2> &m ) {
      mSegments.clear();
    } )
    .updateFn( [this] ( vec2 &pos ) {
      mSegments.push_back( pos );
    } )
    .finishFn( [this] ( Motion<vec2> &m ) {
      timeline().cue( [this] {
        timeline().setTime( 0.0f );
      }, 0.5f ).continuous( false );
    } );

  Color first( 1.0f, 0.1f, 0.05f );
  Color curve( 1.0f, 0.0f, 1.0f );
}

void BezierConstruction::update( double dt )
{
  timeline().step( dt );
}

void BezierConstruction::draw()
{
  gl::ScopedColor color( Color::white() );
  Color curveColor( 1.0f, 1.0f, 0.0f );
  Color controlColor( 1.0f, 0.0f, 1.0f );
  Color lineColor( 0.0f, 1.0f, 1.0f );
  Color futureColor( 1.0f, 1.0f, 1.0f );

  // Draw our curve.
  gl::color( lineColor );
  gl::begin( GL_LINE_STRIP );
  for( auto &segment : mSegments ) {
    gl::vertex( segment );
  }
  gl::end();

  // Draw our curve's static control points.
  for( auto &point : mCurvePoints ) {
    gl::drawSolidCircle( point, 6.0f );
  }

  // Draw the paths traveled by our animating control points.
  gl::drawLine( mCurvePoints[0], mCurvePoints[1] );
  gl::drawLine( mCurvePoints[2], mCurvePoints[3] );

  // Draw our animating control points.
  gl::color( controlColor );
  gl::drawStrokedCircle( mControlA, 10.0f );
  gl::drawStrokedCircle( mControlB, 10.0f );

  // Draw our curve point's tangent line.
  gl::color( futureColor );
  gl::drawLine( mCurvePoint, mControlB );
  gl::color( curveColor );
  gl::drawLine( mControlA, mCurvePoint );
  // And our leading curve point.
  gl::drawStrokedCircle( mCurvePoint, 12.0f );
}
<commit_msg>Add first point of bezier curve.<commit_after>/*
 * Copyright (c) 2014 David Wicks, sansumbrella.com
 * 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.
 *
 * 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.
 */

#include "BezierConstruction.h"

using namespace choreograph;
using namespace cinder;

void BezierConstruction::setup()
{
  mCurvePoints = {
    vec2( 100, 600 ),
    vec2( 100, 100 ),
    vec2( 1180, 100 ),
    vec2( 1180, 600 )
  };

  const float duration = 1.5f;

  // Ramp from anchor point to control point.
  auto ramp_a = makeRamp( mCurvePoints[0], mCurvePoints[1], duration );
  // Ramp from control point to anchor point.
  auto ramp_b = makeRamp( mCurvePoints[2], mCurvePoints[3], duration );

  // Lerp between control ramps.
  auto bezier_point = makeBlend<vec2>( ramp_a, ramp_b, 0.0f );

  timeline().setAutoRemove( false );

  timeline().apply<vec2>( &mControlA, ramp_a );
  timeline().apply<vec2>( &mControlB, ramp_b );
  timeline().apply( bezier_point->getMixOutput() ).then<RampTo>( 1.0f, duration );
  timeline().apply<vec2>( &mCurvePoint, bezier_point )
    .startFn( [this] ( Motion<vec2> &m ) {
      mSegments.clear();
      mSegments.push_back( mCurvePoints[0] );
    } )
    .updateFn( [this] ( vec2 &pos ) {
      mSegments.push_back( pos );
    } )
    .finishFn( [this] ( Motion<vec2> &m ) {
      timeline().cue( [this] {
        timeline().setTime( 0.0f );
      }, 0.5f ).continuous( false );
    } );

  Color first( 1.0f, 0.1f, 0.05f );
  Color curve( 1.0f, 0.0f, 1.0f );
}

void BezierConstruction::update( double dt )
{
  timeline().step( dt );
}

void BezierConstruction::draw()
{
  gl::ScopedColor color( Color::white() );
  Color curveColor( 1.0f, 1.0f, 0.0f );
  Color controlColor( 1.0f, 0.0f, 1.0f );
  Color lineColor( 0.0f, 1.0f, 1.0f );
  Color futureColor( 1.0f, 1.0f, 1.0f );

  // Draw our curve.
  gl::color( lineColor );
  gl::begin( GL_LINE_STRIP );
  for( auto &segment : mSegments ) {
    gl::vertex( segment );
  }
  gl::end();

  // Draw our curve's static control points.
  for( auto &point : mCurvePoints ) {
    gl::drawSolidCircle( point, 6.0f );
  }

  // Draw the paths traveled by our animating control points.
  gl::drawLine( mCurvePoints[0], mCurvePoints[1] );
  gl::drawLine( mCurvePoints[2], mCurvePoints[3] );

  // Draw our animating control points.
  gl::color( controlColor );
  gl::drawStrokedCircle( mControlA, 10.0f );
  gl::drawStrokedCircle( mControlB, 10.0f );

  // Draw our curve point's tangent line.
  gl::color( futureColor );
  gl::drawLine( mCurvePoint, mControlB );
  gl::color( curveColor );
  gl::drawLine( mControlA, mCurvePoint );
  // And our leading curve point.
  gl::drawStrokedCircle( mCurvePoint, 12.0f );
}
<|endoftext|>