Link.h

#pragma once


#include "PositionAndPostureChangeEventArgs.h"


namespace Core
{
    ref class Link;
    ref class Joint;
    ref class Shape;

    ref class ConnectionRelation;

    typedef array< Link^ > Links;
    typedef array< Robotics::PositionVector^ > PositionVectors;

    typedef System::Collections::Generic::List< Link^ > LinkList;


    /// リンク
    [ System::ComponentModel::TypeConverter( CustomProperty::DisplayNameTypeConverter::typeid ) ]   // プロパティ表示の変換
    public ref class Link
    {
    // Construction --------------------------------------------------------
    public:
        Link( Core::Joint^ joint, System::Xml::XmlElement^ element );

        ~Link() { Link::!Link(); }
        !Link();


    // Operation -----------------------------------------------------------
    public:
        void SetPositionAndPosture( Robotics::PositionVector^ position, Robotics::RotationMatrix^ posture );
        void SetPositionAndPostureForcibly( Robotics::PositionVector^ position, Robotics::RotationMatrix^ posture );

        Robotics::PositionVector^ GetCenterOfGravityInWorldPosition();

        Robotics::PositionVector^ GetBottomOfShape();
        PositionVectors^ GetAbsolutePositionOfVertices();

        double CalculateTorque( Robotics::PositionVector^ force, Robotics::PositionVector^ pointOfAction );

        void AddOwnToRouteToBody( LinkList^ route );
        void AddOwnToRouteToEnd( LinkList^ route );

        bool IsSupportingPhase();
        bool IsBody() { return( this == Body); }
        bool IsStandard() { return( this == Standard ); }


        void CreateFigure( Microsoft::DirectX::Direct3D::Device^ device );
        void RenderMechanismModel( Microsoft::DirectX::Direct3D::Device^ device );
        void RenderRealModel( Microsoft::DirectX::Direct3D::Device^ device );

    private:
        Robotics::PositionVector^ GetCenterOfGravityInLocalPosition();


    // Event Handler -------------------------------------------------------
    private:
        void OnMechanicsChanged( System::Object^ sender, System::EventArgs^ e );
        void JointPositionChanged( System::Object^ sender, System::EventArgs^ e );

        void SetFigure( System::Object^ sender, System::EventArgs^ e );


    // Event ---------------------------------------------------------------
    public:

    // static
        static event System::EventHandler^ AbsolutePositionChanged;    ///< 絶対位置の変更イベント
        static event System::EventHandler^ PostureChanged;             ///< 姿勢の変更イベント

        static event PositionAndPostureChangeEventHandler^ PositionAndPostureChanged; ///< 位置と姿勢の変更イベント
        static event System::EventHandler^ StandardChanged;                           ///< 基準リンクの変更イベント

        static event System::EventHandler^ MechanicsChanged;           ///< 構造変化イベント


    // Attribute ===========================================================
    private:
        Joint^ m_joint;     ///< 関節
        Shape^ m_shape;     ///< 形状

        ConnectionRelation^ m_connectionRelation;     ///< 接続関係
        Robotics::RotationMatrix^ m_posture;          ///< 姿勢 (ワールド座標系)

        Robotics::PositionVector^ m_centerOfGravity;  ///< 重心[ m ] (ローカル座標系 [関節に対する位置] )
        double m_mass;                                ///< 質量[ kg ]

        Microsoft::DirectX::Direct3D::VertexBuffer^ m_figure;   ///< 図形


    // static
    public:
        literal double GroundHeight = 0.001;    ///< 接地しているとみなす高さ[ m ]

    private:
        static Link^ m_body;       ///< 胴体
        static Link^ m_standard;   ///< 基準リンク(計算の基準)


        /// @todo
        /// 胴体をクラスとして抽出する。


    // Property ------------------------------------------------------------
    public:
        /// 名称
        [ System::ComponentModel::CategoryAttribute( "全般" ) ]
        [ CustomProperty::DisplayName( "名称" ) ]
        property System::String^ Name
        {
            System::String^ get();
            void set( System::String^ value );
        }


        /// 関節
        [ CustomProperty::DisplayName( "関節" ) ]
        property Joint^ Joint
        {
            Core::Joint^ get()
            {
                return m_joint;
            }
        }

        /// 形状
        [ CustomProperty::DisplayName( "形状" ) ]
        property Shape^ Shape
        {
            Core::Shape^ get()
            {
                return m_shape;
            }
        }


        /// 接続関係
        [ System::ComponentModel::CategoryAttribute( "全般" ) ]
        [ CustomProperty::DisplayName( "接続関係" ) ]
        property ConnectionRelation^ Connection
        {
            ConnectionRelation^ get()
            {
                return m_connectionRelation;
            }
            void set( ConnectionRelation^ value )
            {
                m_connectionRelation = value;
            }
        }


        /// 絶対位置[ m ] (ワールド座標系)
        [ System::ComponentModel::Browsable( false ) ]  // 参照不可
        property Robotics::PositionVector^ AbsolutePosition
        {
            Robotics::PositionVector^ get();

        private:
            void set( Robotics::PositionVector^ value );
        }


        /// 姿勢 (ワールド座標系)
        [ System::ComponentModel::Browsable( false ) ]  // 参照不可
        property Robotics::RotationMatrix^ Posture
        {
            Robotics::RotationMatrix^ get()
            {
                return m_posture;
            }
            void set( Robotics::RotationMatrix^ value );
        }


        /// 軸方向 (ワールド座標系)
        [ System::ComponentModel::Browsable( false ) ]  // 参照不可
        property Robotics::AxisVector^ AxialDirection
        {
            Robotics::AxisVector^ get();
        }


        /// 重心[ m ] (ローカル座標系)
        [ System::ComponentModel::CategoryAttribute( "全般" ) ]
        [ CustomProperty::DisplayName( "重心" ) ]
        [ System::ComponentModel::Description( "関節に対する相対位置を表します。" ) ]
        property Robotics::PositionVector^ CenterOfGravity
        {
            Robotics::PositionVector^ get()
            {
                return m_centerOfGravity;
            }
            void set( Robotics::PositionVector^ value );
        }

        /// 質量[ kg ]
        [ System::ComponentModel::CategoryAttribute( "全般" ) ]
        [ CustomProperty::DisplayName( "質量" ) ]
        property double Mass
        {
            double get()
            {
                return m_mass;
            }
            void set( double value );
        }


    // static

        /// 胴体
        static property Link^ Body
        {
            Link^ get()
            {
                return m_body;
            }
            void set( Link^ value );
        }

        /// 基準リンク(計算の基準)
        static property Link^ Standard
        {
            Link^ get()
            {
                return m_standard;
            }
            void set( Link^ value );
        }
    };
}