EnergyEfficiencyPanel.cpp

#include "StdAfx.h"
#include "EnergyEfficiencyPanel.h"


#include "Motion.h"
#include "Pose.h"


using namespace Core;
using namespace Robotics;

using namespace System;
using namespace System::Diagnostics;


/// [ Constructor ]
EnergyEfficiencyPanel::EnergyEfficiencyPanel( Motion^ motion )
{
    // コンポーネントを初期化する
    InitializeComponent();


    // グラフの枠を取得する
    ZedGraph::GraphPane^ graphPane = m_zedGraph->GraphPane;

    graphPane->Title->IsVisible = false;  // タイトル
    graphPane->Legend->IsVisible = false; // 凡例
    graphPane->Y2Axis->IsVisible = true;  // 第2のY軸の表示

    // 大きな格子の表示
    graphPane->XAxis->MajorGrid->IsVisible = true;
    graphPane->YAxis->MajorGrid->IsVisible = true;

    // 軸ラベル
    graphPane->XAxis->Title->Text = "時間[sec]";
    graphPane->YAxis->Title->Text = "エネルギー効率[m/J]";
    graphPane->Y2Axis->Title->Text = "エネルギー[J]";

    // 軸ラベルの太字
    graphPane->XAxis->Title->FontSpec->IsBold = false;
    graphPane->YAxis->Title->FontSpec->IsBold = false;
    graphPane->Y2Axis->Title->FontSpec->IsBold = false;


    Drawing::Color efficiencyColor = Drawing::Color::Green; // エネルギー効率の色
    Drawing::Color energyColor = Drawing::Color::Red;       // エネルギーの色

    // ... スケールの文字の色
    graphPane->YAxis->Scale->FontSpec->FontColor = efficiencyColor;
    graphPane->Y2Axis->Scale->FontSpec->FontColor = energyColor;

    // ... 軸ラベルの文字の色
    graphPane->YAxis->Title->FontSpec->FontColor = efficiencyColor;
    graphPane->Y2Axis->Title->FontSpec->FontColor = energyColor;

    // 反対側の軸の表示
    graphPane->YAxis->MajorTic->IsOpposite = false;
    graphPane->YAxis->MinorTic->IsOpposite = false;
    graphPane->Y2Axis->MajorTic->IsOpposite = false;
    graphPane->Y2Axis->MinorTic->IsOpposite = false;

    /// @note
    /// 第2の軸を表示するときには、反対側の軸を非表示にする。


    // 軸の範囲
    graphPane->YAxis->Scale->Max = 0.1;
    graphPane->YAxis->Scale->Min = 0.0;

    graphPane->Y2Axis->Scale->Max = 2.0;
    graphPane->Y2Axis->Scale->Min = 0.0;

    /// @todo
    /// グラフの値から適切に設定されるようにする。


    // モーションの変更イベントに登録する
    motion->Changed += gcnew System::EventHandler( this, &EnergyEfficiencyPanel::MotionChanged );

    // モーションの変更イベントを呼び出し、フィールドを初期化する
    MotionChanged( motion, nullptr );
}

/// [ Destructor ]
EnergyEfficiencyPanel::~EnergyEfficiencyPanel()
{
    if( components != nullptr )
    {
        delete components;
    }
}


#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void EnergyEfficiencyPanel::InitializeComponent(void)
{
    this->components = (gcnew System::ComponentModel::Container());
    this->m_zedGraph = (gcnew ZedGraph::ZedGraphControl());
    this->SuspendLayout();
    //
    // m_zedGraph
    //
    this->m_zedGraph->Dock = System::Windows::Forms::DockStyle::Fill;
    this->m_zedGraph->EditButtons = System::Windows::Forms::MouseButtons::None;
    this->m_zedGraph->IsEnableHZoom = false;
    this->m_zedGraph->IsEnableVZoom = false;
    this->m_zedGraph->IsEnableWheelZoom = false;
    this->m_zedGraph->IsShowContextMenu = false;
    this->m_zedGraph->Location = System::Drawing::Point(0, 0);
    this->m_zedGraph->Name = L"m_zedGraph";
    this->m_zedGraph->ScrollGrace = 0;
    this->m_zedGraph->ScrollMaxX = 0;
    this->m_zedGraph->ScrollMaxY = 0;
    this->m_zedGraph->ScrollMaxY2 = 0;
    this->m_zedGraph->ScrollMinX = 0;
    this->m_zedGraph->ScrollMinY = 0;
    this->m_zedGraph->ScrollMinY2 = 0;
    this->m_zedGraph->Size = System::Drawing::Size(292, 272);
    this->m_zedGraph->TabIndex = 0;
    //
    // EnergyEfficiencyPanel
    //
    this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
    this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    this->ClientSize = System::Drawing::Size(292, 272);
    this->CloseButton = false;
    this->Controls->Add(this->m_zedGraph);
    this->DockAreas = static_cast<WeifenLuo::WinFormsUI::Docking::DockAreas>(((WeifenLuo::WinFormsUI::Docking::DockAreas::Float | WeifenLuo::WinFormsUI::Docking::DockAreas::DockTop)
        | WeifenLuo::WinFormsUI::Docking::DockAreas::DockBottom));
    this->HideOnClose = true;
    this->Name = L"EnergyEfficiencyPanel";
    this->ShowHint = WeifenLuo::WinFormsUI::Docking::DockState::DockBottomAutoHide;
    this->Text = L"EnergyEfficiency";
    this->ResumeLayout(false);

}
#pragma endregion


/// モーションが変更された
void EnergyEfficiencyPanel::MotionChanged( System::Object^ sender, System::EventArgs^ )
{
    // 引数から目的とする型を取得する。
    Motion^ motion = safe_cast< Motion^ >( sender );

    // グラフの点を生成する
    ZedGraph::PointPairList^ energyPoint = gcnew ZedGraph::PointPairList();
    ZedGraph::PointPairList^ efficiencyPoint = gcnew ZedGraph::PointPairList();


    for( int i = 0; i < motion->PoseCount; i++ )
    {
        // ポーズの電力とモーションの単位時間を積算してエネルギー(電力量)を求める
        double energy = motion[ i ]->ElectricPower * Motion::UnitTime;


        // リンクの変位を取得する
        const int bodyIndex = 0;    // 胴体のインデックス番号
        PositionVector^ displacement = motion->GetDisplacementOfLink( i, bodyIndex );

        // ... X方向の変位をエネルギーで除して、エネルギー効率を求める
        double efficiency = displacement->X / energy;


        /// @todo
        /// エネルギー効率の指標を、何を基準にするか選択できるようにする。


        // グラフの点を追加する
        energyPoint->Add( i * Motion::UnitTime, energy );
        efficiencyPoint->Add( i * Motion::UnitTime, efficiency );
    }


    // グラフの枠を取得する
    ZedGraph::GraphPane^ graphPane = m_zedGraph->GraphPane;

    // ... グラフを消去する
    graphPane->CurveList->Clear();
    graphPane->GraphObjList->Clear();


    // グラフの色を スケールの色から取得する
    Drawing::Color efficiencyColor = graphPane->YAxis->Scale->FontSpec->FontColor;
    Drawing::Color energyColor = graphPane->Y2Axis->Scale->FontSpec->FontColor;

    // ... グラフの線を追加する
    ZedGraph::LineItem^ curve;
    curve = graphPane->AddCurve( "Efficiency", efficiencyPoint, efficiencyColor, ZedGraph::SymbolType::None );
    curve = graphPane->AddCurve( "Energy", energyPoint, energyColor, ZedGraph::SymbolType::None );
    curve->IsY2Axis = true;                 // 第2のY軸に指定


    // 現在の時間を表すラインを生成する
    ZedGraph::LineObj^ currentTimeLine = gcnew ZedGraph::LineObj(
        Drawing::Color::Orange,         // 色
        motion->CurrentTime,
        graphPane->YAxis->Scale->Min,
        motion->CurrentTime,
        graphPane->YAxis->Scale->Max
        );

    // ... グラフのオブジェクトに追加する
    graphPane->GraphObjList->Add( currentTimeLine );


    double graphSize = ( energyPoint->Count - 1 ) * Motion::UnitTime;  // グラフの大きさ
    if( graphPane->XAxis->Scale->Max != graphSize )
    {
        // X軸の最大値とグラフの大きさが異なっているならば、一致させる
        graphPane->XAxis->Scale->Max = graphSize;

        // ... 軸が変化したことを通知する
        m_zedGraph->AxisChange();
    }

    // 表示を更新する
    m_zedGraph->Invalidate();
}