/***************************************************************************
 *   Copyright (C) 2006 by Harish Kukreja                                  *
 *   harish.kukreja@gmail.com                                              *
 *                                                                         *
 *   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.             *
 ***************************************************************************/

//
// C++ Interface: objects
//
// Description: Headers for various physical Objects that are found in the Physiks interaction
//              environment.
//
// Author: Harish Kukreja <harish.kukreja@gmail.com>, (C) 2006
//
// Copyright: See COPYING file that comes with this distribution
//
//

#ifndef _OBJECTS_H_
#define _OBJECTS_H_

#include "physiks_export.h"
#include "physiksvector.h"

namespace Physiks {

/** \class PhysicalObject
 * \brief The fundamental dynamic element of a simulation. */
class PHYSIKS_EXPORT PhysicalObject {
  public:
    PHYSCALAR mass;
    PHYSCALAR charge;
    Vector position;
    Vector velocity;

    /** \brief  Default parameterless constructor. Mass and charge are initialised to 0, and
     * all vectors are initialised to the zero vector. */
    PhysicalObject();

    /** \brief Copy constructor.    */
    PhysicalObject(const PhysicalObject &part);

    /** \brief  Explicit constructor.
     * \param   mass    the object's mass.
     * \param   charge  the object's charge.
     * \param   position    the object's initial position in n-space.
     * \param   velocity    the object's initial velocity in n-space. */
    PhysicalObject(PHYSCALAR mass, PHYSCALAR charge, const Vector &position, const Vector &velocity);

    virtual ~PhysicalObject();
};

//=============================================================================

class PHYSIKS_EXPORT RigidBody : public PhysicalObject {
  public:
    Vector angular_velocity;

    /** \brief  Default parameterless constructor. In addition to the initialisations of
     * PhysicalObject's parameterless constructor, angular_velocity is initialised to the zero.
     * vector. */
    RigidBody();

    /** \brief  Copy constructor.   */
    RigidBody(const RigidBody &init);

    /** \brief  Explicit constructor.
     * \param   angular_velocity    the extended object's angular velocity. */
    RigidBody(PHYSCALAR mass, PHYSCALAR charge, const Vector &position, const Vector &velocity,
        const Vector &angular_velocity);

    virtual ~RigidBody();
};

//=============================================================================

class PHYSIKS_EXPORT Sphere : public RigidBody {
  public:
    /** \brief  Default parameterless constructor. In addition to the initialisations of
     * RigidBody's parameterless constructor, radius is initialised to 1. */
    Sphere();

    /** \brief  Copy constructor.   */
    Sphere(const Sphere &sph);

    /** \brief  Explicit constructor.
     * \param   radius  the spherical object's radius. */
    Sphere(PHYSCALAR mass, PHYSCALAR charge, const Vector &position, const Vector &velocity,
        const Vector &angular_velocity, PHYSCALAR radius);

    virtual ~Sphere();


    /** The sphere's radius.    */
    PHYSCALAR radius;
};

//=============================================================================

class PHYSIKS_EXPORT Plane : public RigidBody {
  protected:
    /** \brief  Flag controlling the nature of the plane's interactions with other objects.
     *
     * If true, the plane is taken to be infinite (i.e. the set of ALL linear combinations of
     * the two basis vectors. Otherwise, it is restricted to the set of all linear combinations
     * of the two basis vectors with coefficients <= 1. In this way, the length and breadth of
     * the bounded plane are specified by the magnitudes of basis_vec1 and basis_vec2. */
    bool unbounded;

    Vector normal_vec;

    /** One of the plane's two basis vectors. */
    Vector basis_vec1;

    /** The second of the plane's two basis vectors. */
    Vector basis_vec2;

  public:

    Plane(const Vector &normal, const Vector &origin);

    /** \brief  Copy constructor    */
    Plane(const Plane &plane);

    /** \brief  Explicit constructor.
     * \param   vec1    Basis vector 1 for the plane.
     * \param   vec2    Basis vector 2 for the plane.
     * \param   origin  the common base of vec1 and vec2.   */
    Plane(const Vector &vec1, const Vector &vec2, const Vector &origin);

    virtual ~Plane();


    /** \brief  Set the plane's unbounded flag.
     * \param   flag    true if the plane must be bounded, false otherwise. */
    void bounded(bool flag);

    /** \brief  Returns the value of the plane's ``bounded'' flag
     * \return  True if the plane is bounded, false otherwise. */
    bool bounded() const;


    /** Returns a unit vector normal to this plane  */
    Vector normal() const;
};

}   // End of namespace Physiks

#endif
