/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK 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.
 *
 * CamiTK 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/


#ifndef GEOMETRIC_OBJECT_H
#define GEOMETRIC_OBJECT_H

// -- Core stuff
#include "CamiTKAPI.h"

// -- vtk stuff
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>

// -- vtk stuff Classes
class vtkPolyDataAlgorithm;
class vtkActor;

namespace camitk {
/**
 * @ingroup group_sdk_libraries_core_component
 *
 * @brief
 * A geometric object allows one to create geometric object (sphere, arrow, ...) that can be
 * added directly in the scene using getActor().
 *
 * This is a pure vtk wrapper class (no Core stuff).
 *
 *
 */

class  CAMITK_API GeometricObject {
public:

    /// the geometric type
    enum Geometry {
        ARROW,  ///< an arrow
        SPHERE ///< a sphere (this is also the default)
    };

    /// possible direction of an object
    enum Direction {
        X, ///< the object in the X direction, size = 0.1
        Y, ///< the object in the Y direction, size = 0.1
        Z, ///< the object in the Z direction, size = 0.1
        USER_DEFINED /// < the object direction is defined by the user
    };

    /** constructor by default of a geometric object of type given in parameters.
      * position at origin, direction DEFINED_BY_USER = (1.0, 1.0, 1.0), size = 0.1, color = reddish.
      */
    GeometricObject(Geometry);

    /** build a geometric object of a geometric object of type given in parameters
      * and at a particular position,.
      * direction DEFINED_BY_USER = (1.0, 1.0, 1.0), size = 0.1, color = reddish.
      */
    GeometricObject(Geometry, const double, const double, const double);

    /** build a geometric object of type given in parameter
      * and along the direction also given as parameter.
      * position at origin, size = 0.1, color = reddish
      */
    GeometricObject(Geometry, Direction);

    /** build a geometric object of type given in parameter, and
      * using a given bounding box (array containing in this order: [xmin,xmax, ymin,ymax, zmin,zmax]).
      * The position is the (xmin, ymin, zmin) of the bounding box, size = 0.1, color = reddish.
      */
    GeometricObject(Geometry, float boundingBox[6]);

    /// destructor
    virtual ~GeometricObject();

    /// get the representation as a vtk actor
    vtkSmartPointer<vtkActor> getActor();

    /// Set the position of the geometric object
    void setPosition(const double, const double, const double);

    /// Set the direction of the geometric object
    void setDirection(const double, const double, const double);

    /// Set the color of the geometric object
    void setColor(const double, const double, const double);

    /** Set the size of the geometric object (can be used in different
      * way depending o the geometry).
      * This method automatically calls sizeChanged().
      */
    void setSize(const double);

    /// return the type
    Geometry getType() const;

private:

    /// Bounding box of the object [xmin,xmax, ymin,ymax, zmin,zmax]
    float bounds[6];

    /// Direction of the geometric object (sometimes has no particular meaning, e.g. for a sphere)
    Direction myDirection;

    /// the actor
    vtkSmartPointer<vtkActor> myActor;

    /// the mapper
    vtkSmartPointer<vtkPolyDataMapper> myMapper;

    /// the creator of the geometry
    vtkSmartPointer<vtkPolyDataAlgorithm> mySource;

    /// the geometric type
    Geometry myType;

    /// Initialisation of everything
    void init();

    /// initialize the attributes to default values
    void defaultValues();
};

inline GeometricObject::Geometry GeometricObject::getType() const {
    return myType;
}

}

#endif

