//  Aerodynamic_Device.cc - a particle that produces drag and lift.
//
//  Copyright (C) 2002 Sam Varner
//
//  This file is part of Vamos Automotive Simulator.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program 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 General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include <vamos/body/Aerodynamic_Device.h>
#include <vamos/geometry/Constants.h>
#include <cmath>

using namespace Vamos_Geometry;

//* Class Aerodynamic_Device

//** Constructor
Vamos_Body::
Aerodynamic_Device::Aerodynamic_Device (const Three_Vector& position) :
  Particle (0.0, position)
{
}

// Calculate the drag and lift due to WIND_VECTOR.  WIND_VECTOR is
// supplied by the Body in the Body's frame.
void Vamos_Body::
Aerodynamic_Device::wind (const Three_Vector& wind_vector, double density)
{
  m_wind_vector = wind_vector;
  m_density = density;
}

//-----------------------------------------------------------------------------
//* Class Drag

//** Constructor
Vamos_Body::
Drag::Drag (const Three_Vector& position,
			double frontal_area, double drag_coefficient) :
  Aerodynamic_Device (position),
  m_frontal_area (frontal_area),
  m_drag_coefficient (drag_coefficient)
{
}

// Find and store the forces, impulses, and torques for the current
// configuration.
void Vamos_Body::
Drag::find_forces ()
{
  // Calculate the drag and lift forces.
  m_force = 0.5 * m_density * m_drag_coefficient * m_frontal_area
	* m_wind_vector * m_wind_vector.abs ();
}

//-----------------------------------------------------------------------------
//* Class Wing

//** Constructor
Vamos_Body::
Wing::Wing (const Three_Vector& position,
			double frontal_area, double drag_coefficient,
			double surface_area, double lift_coefficient,
			double efficiency) :
  Drag (position, frontal_area, drag_coefficient),
  m_surface_area (surface_area),
  m_lift_coefficient (lift_coefficient),
  m_efficiency (efficiency)
{
}

// Find and store the forces, impulses, and torques for the current
// configuration.
void Vamos_Body::
Wing::find_forces ()
{
  Drag::find_forces ();

  const double wind_speed = std::abs (m_wind_vector.dot (Three_Vector::X));
  const double k = 0.5 * m_density * wind_speed * wind_speed;
  double lift = k * m_lift_coefficient * m_surface_area;
  double drag = -m_lift_coefficient * lift * (1.0 -  m_efficiency);

  m_force += Three_Vector (drag, 0.0, lift);
}
