/*
 *  abstract_directions.hpp
 *
 *	Author(s): Tamas D. Nagy
 *	Created on: 2017-11-08
 *
 */

#ifndef ABSTRACT_DIRECTIONS_HPP_
#define ABSTRACT_DIRECTIONS_HPP_

#include <iostream>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/Quaternion.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <cmath>
#include <irob_utils/utils.hpp>

namespace saf {

typedef enum CoordinateFrame {WORLD, CAMERA, ROBOT} CoordinateFrame;

template <CoordinateFrame CF, class T>
class BaseDirections {
   public:
   		static const T UP;
   		static const T DOWN;
   		static const T FORWARD;
   		static const T BACKWARD;
   		static const T LEFT;
   		static const T RIGHT;
};

/*
 *	CAMERA
 */

// Eigen::Vector3d
template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			UP = Eigen::Vector3d(0.0, -1.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			DOWN = Eigen::Vector3d(0.0, 1.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			FORWARD = Eigen::Vector3d(0.0, 0.0, 1.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			BACKWARD = Eigen::Vector3d(0.0, 0.0, -1.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			LEFT = Eigen::Vector3d(-1.0, 0.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			RIGHT = Eigen::Vector3d(1.0, 0.0, 0.0);

// geometry_msgs::Point
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			UP
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			UP);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			DOWN
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			DOWN);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			FORWARD
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			FORWARD);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			BACKWARD
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			BACKWARD);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			LEFT
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			LEFT);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::CAMERA, geometry_msgs::Point>::
			RIGHT
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::CAMERA, Eigen::Vector3d>::
			RIGHT);

/*
 *	ROBOT
 */

// Eigen::Vector3d
template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			UP = Eigen::Vector3d(0.0, 0.0, 1.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			DOWN = Eigen::Vector3d(0.0, 0.0, -1.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			FORWARD = Eigen::Vector3d(0.0, -1.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			BACKWARD = Eigen::Vector3d(0.0, 1.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			LEFT = Eigen::Vector3d(1.0, 0.0, 0.0);

template<>
const Eigen::Vector3d
		BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			RIGHT = Eigen::Vector3d(-1.0, 0.0, 0.0);

// geometry_msgs::Point
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			UP
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			UP);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			DOWN
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			DOWN);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			FORWARD
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			FORWARD);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			BACKWARD
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			BACKWARD);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			LEFT
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			LEFT);
template<>
const geometry_msgs::Point
		BaseDirections<CoordinateFrame::ROBOT, geometry_msgs::Point>::
			RIGHT
			= wrapToMsg<geometry_msgs::Point, Eigen::Vector3d>
			(BaseDirections<CoordinateFrame::ROBOT, Eigen::Vector3d>::
			RIGHT);

/*
 * --------------------------------------------------------------------------
 */

template <CoordinateFrame CF, class T>
class BaseOrientations {
   public:
   		// The first word is corresponding to the main direction,
   		// the second to the rotation of the tool axis -- the open/close
   		// direction of the jaws

   		static const T UP_FORWARD;
   		static const T UP_SIDEWAYS;

   		static const T DOWN_FORWARD;
   		static const T DOWN_SIDEWAYS;

   		static const T FORWARD_HORIZONTAL;
   		static const T FORWARD_VERTICAL;

   		static const T BACKWARD_HORIZONTAL;
   		static const T BACKWARD_VERTICAL;

   		static const T LEFT_HORIZONTAL;
   		static const T LEFT_VERTICAL;

   		static const T RIGHT_HORIZONTAL;
   		static const T RIGHT_VERTICAL;
};

/*
 *	ROBOT
 */

// Eigen::Quaternion<double>
template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			UP_FORWARD = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			UP_SIDEWAYS = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			DOWN_FORWARD = Eigen::Quaternion<double>(0.0, 1.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			DOWN_SIDEWAYS =
      Eigen::Quaternion<double>(0.0, -0.7071, 0.7071, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			FORWARD_HORIZONTAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			FORWARD_VERTICAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			BACKWARD_HORIZONTAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			BACKWARD_VERTICAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			RIGHT_HORIZONTAL =
			Eigen::Quaternion<double>(0.0, 0.7071, 0.0, -0.7071);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			RIGHT_VERTICAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			LEFT_HORIZONTAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

template<>
const Eigen::Quaternion<double>
		BaseOrientations<CoordinateFrame::ROBOT, Eigen::Quaternion<double>>::
			LEFT_VERTICAL = Eigen::Quaternion<double>(0.0, 0.0, 0.0, 0.0);

}
#endif


/**
 * \file topological_search.hpp
 *
 * This library contains two simple nearest-neighbor search algorithms implemented
 * as functor templates. This library contains, in fact, three algorithms.
 *
 * First, a simple min_dist_linear_search algorithm is provided which is similar to std::min_element
 * except that it stores and compares the best distance value associated to the best iterator
 * to the current one (it is a simple linear search that avoid recomputation of the distance
 * at every iteration, which would be required if std::min_element was used instead).
 *
 * Second, a linear_neighbor_search algorithm is provided which simply does an exhaustive linear
 * search through all the vertices of a graph to find the nearest one to a given point, in a given
 * topology (as of topologies in the Boost Graph Library). This algorithms simply wraps the
 * min_dist_linear_search with the required distance and comparison function.
 *
 * Third, a best_only_neighbor_search algorithm is provided which is an approximation to an
 * exhaustive linear search by picking a number of random vertices from the graph and performing
 * a best only search down the graph to find the "nearest-neighbor". This is, of course, not going
 * to find the nearest-neighbor, but can significantly cut down on query time if finding the
 * nearest neighbor is not a strict requirement in the algorithm.
 *
 * \author Sven Mikael Persson <mikael.s.persson@gmail.com>
 * \date February 2011
 */

/*
 *    Copyright 2011 Sven Mikael Persson
 *
 *    THIS SOFTWARE IS DISTRIBUTED UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE v3 (GPLv3).
 *
 *    This file is part of ReaK.
 *
 *    ReaK 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 3 of the License, or
 *    (at your option) any later version.
 *
 *    ReaK 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 ReaK (as LICENSE in the root folder).
 *    If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef REAK_TOPOLOGICAL_SEARCH_HPP
#define REAK_TOPOLOGICAL_SEARCH_HPP

#include <boost/bind.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topology.hpp>
#include <boost/graph/properties.hpp>

#include <vector>
#include <algorithm>

  /**
   * This function template is similar to std::min_element but can be used when the comparison
   * involves computing a derived quantity (a.k.a. distance). This algorithm will search for the
   * the element in the range [first,last) which has the "smallest" distance (of course, both the
   * distance metric and comparison can be overriden to perform something other than the canonical
   * Euclidean distance and less-than comparison, which would yield the element with minimum distance).
   * \tparam DistanceValue The value-type for the distance measures.
   * \tparam ForwardIterator The forward-iterator type.
   * \tparam GetDistanceFunction The functor type to compute the distance measure.
   * \tparam CompareFunction The functor type that can compare two distance measures (strict weak-ordering).
   * \param first Start of the range in which to search.
   * \param last One element past the last element in the range in which to search.
   * \param distance A callable object that returns a DistanceValue for a given element from the ForwardIterator dereferencing.
   * \param compare A callable object that returns true if the first element is the preferred one (less-than) of the two.
   * \param inf A DistanceValue which represents infinity (i.e. the very worst value with which to initialize the search).
   * \return The iterator to the best element in the range (best is defined as the one which would compare favorably to all the elements in the range with respect to the distance metric).
   */
  template <typename DistanceValue,
	    typename ForwardIterator,
            typename GetDistanceFunction,
	    typename CompareFunction>
  inline ForwardIterator min_dist_linear_search(ForwardIterator first,
						ForwardIterator last,
						GetDistanceFunction distance,
						CompareFunction compare,
						DistanceValue inf = std::numeric_limits<DistanceValue>::infinity()) {
    if(first == last) return last;
    DistanceValue d_best = inf;
    ForwardIterator result = last;
    for(; first != last; ++first) {
      DistanceValue d = distance(*first);
      if(compare(d, d_best)) {
	d_best = d;
	result = first;
      };
    };
    return result;
  };

  /**
   * This function template is a specialization of min_dist_linear_search for the default comparison
   * function which is the less-than operator.
   * \tparam DistanceValue The value-type for the distance measures.
   * \tparam ForwardIterator The forward-iterator type.
   * \tparam GetDistanceFunction The functor type to compute the distance measure.
   * \param first Start of the range in which to search.
   * \param last One element past the last element in the range in which to search.
   * \param distance A callable object that returns a DistanceValue for a given element from the ForwardIterator dereferencing.
   * \param inf A DistanceValue which represents infinity (i.e. the very worst value with which to initialize the search).
   * \return The iterator to the best element in the range (best is defined as the one which would compare favorably to all the elements in the range with respect to the distance metric).
   */
  template <typename DistanceValue, typename ForwardIterator, typename GetDistanceFunction>
  inline ForwardIterator min_dist_linear_search(ForwardIterator first,
						ForwardIterator last,
						GetDistanceFunction distance,
						DistanceValue inf = std::numeric_limits<DistanceValue>::infinity()) {
    return min_dist_linear_search(first,last,distance,std::less<DistanceValue>(),inf);
  };

  /**
   * This function template is similar to std::min_element but can be used when the comparison
   * involves computing a derived quantity (a.k.a. distance). This algorithm will search for the
   * the elements in the range [first,last) with the "smallest" distances (of course, both the
   * distance metric and comparison can be overriden to perform something other than the canonical
   * Euclidean distance and less-than comparison, which would yield the element with minimum distance).
   * This function will fill the output container with a number of nearest-neighbors.
   * \tparam DistanceValue The value-type for the distance measures.
   * \tparam ForwardIterator The forward-iterator type.
   * \tparam OutputContainer The container type which can contain the list of nearest-neighbors (STL like container, with iterators, insert, size, and pop_back).
   * \tparam GetDistanceFunction The functor type to compute the distance measure.
   * \tparam CompareFunction The functor type that can compare two distance measures (strict weak-ordering).
   * \param first Start of the range in which to search.
   * \param last One element past the last element in the range in which to search.
   * \param output The container that will have the sorted list of elements with the smallest distance.
   * \param distance A callable object that returns a DistanceValue for a given element from the ForwardIterator dereferencing.
   * \param compare A callable object that returns true if the first element is the preferred one (less-than) of the two.
   * \param max_neighbors The maximum number of elements of smallest distance to output in the sorted list.
   * \param radius The maximum distance value for which an element qualifies to be part of the output list.
   */
  template <typename DistanceValue,
	    typename ForwardIterator,
	    typename OutputContainer,
            typename GetDistanceFunction,
	    typename CompareFunction>
  inline void min_dist_linear_search(ForwardIterator first,
				     ForwardIterator last,
				     OutputContainer& output,
				     GetDistanceFunction distance,
				     CompareFunction compare,
				     unsigned int max_neighbors = 1,
				     DistanceValue radius = std::numeric_limits<DistanceValue>::infinity()) {
    output.clear();
    if(first == last) return;
    std::vector<DistanceValue> output_dist;
    for(; first != last; ++first) {
      DistanceValue d = distance(*first);
      if(!compare(d, radius))
	continue;
      typename std::vector<DistanceValue>::iterator it_lo = std::lower_bound(output_dist.begin(),output_dist.end(),d,compare);
      if((it_lo != output_dist.end()) || (output_dist.size() < max_neighbors)) {
	output_dist.insert(it_lo, d);
	typename OutputContainer::iterator itv = output.begin();
	for(typename std::vector<DistanceValue>::iterator it = output_dist.begin(); (itv != output.end()) && (it != it_lo); ++itv,++it) ;
	output.insert(itv, *first);
	if(output.size() > max_neighbors) {
	  output.pop_back();
	  output_dist.pop_back();
	};
      };
    };
  };

  /**
   * This function template is similar to std::min_element but can be used when the comparison
   * involves computing a derived quantity (a.k.a. distance). This algorithm will search for the
   * the element in the range [first,last) which has the "smallest" distance (of course, both the
   * distance metric and comparison can be overriden to perform something other than the canonical
   * Euclidean distance and less-than comparison, which would yield the element with minimum distance).
   * \tparam DistanceValue The value-type for the distance measures.
   * \tparam ForwardIterator The forward-iterator type.
   * \tparam OutputContainer The container type which can contain the list of nearest-neighbors (STL like container, with iterators, insert, size, and pop_back).
   * \tparam GetDistanceFunction The functor type to compute the distance measure.
   * \param first Start of the range in which to search.
   * \param last One element past the last element in the range in which to search.
   * \param output The container that will have the sorted list of elements with the smallest distance.
   * \param distance A callable object that returns a DistanceValue for a given element from the ForwardIterator dereferencing.
   * \param max_neighbors The maximum number of elements of smallest distance to output in the sorted list.
   * \param radius The maximum distance value for which an element qualifies to be part of the output list.
   */
  template <typename DistanceValue,
	    typename ForwardIterator,
	    typename OutputContainer,
            typename GetDistanceFunction>
  inline void min_dist_linear_search(ForwardIterator first,
				     ForwardIterator last,
				     OutputContainer& output,
				     GetDistanceFunction distance,
				     unsigned int max_neighbors = 1,
				     DistanceValue radius = std::numeric_limits<DistanceValue>::infinity()) {
    min_dist_linear_search(first,last,output,distance,std::less<DistanceValue>(),max_neighbors,radius);
  };

  /**
   * This functor template performs a linear nearest-neighbor search through a graph by invoquing
   * the distance function of an underlying topology. The call operator will return the vertex
   * of the graph whose position value is closest to a given position value.
   * \tparam CompareFunction The functor type that can compare two distance measures (strict weak-ordering).
   */
  template <typename CompareFunction = std::less<double> >
  struct linear_neighbor_search {

    CompareFunction m_compare;
    /**
     * Default constructor.
     * \param compare The comparison functor for ordering the distances (strict weak ordering).
     */
    linear_neighbor_search(CompareFunction compare = CompareFunction()) : m_compare(compare) { };

    /**
     * This function template computes the topological distance between a position and the position of a
     * vertex of a graph. This function is used as a helper to the call-operator overloads.
     * \tparam Vertex The vertex descriptor type.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated with each vertex.
     * \param p A position in the space.
     * \param u A vertex which has a position associated to it, via the position property-map.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     */
    template <typename Vertex, typename Topology, typename PositionMap>
    double distance(const typename boost::property_traits<PositionMap>::value_type& p,
                    Vertex u, const Topology& space, PositionMap position) const {
      return space.distance(p, get(position, u));
    };

    /**
     * This call-operator finds the nearest vertex of a graph, to a given position.
     * \tparam Graph The graph type which can contain the vertices, should model boost::VertexListGraphConcept.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated with each vertex.
     * \param p A position in the space, to which the nearest-neighbor is sought.
     * \param g A graph containing the vertices from which to find the nearest-neighbor.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     */
    template <typename Graph, typename Topology, typename PositionMap>
    typename boost::graph_traits<Graph>::vertex_descriptor operator()(const typename boost::property_traits<PositionMap>::value_type& p,
								      Graph& g,
								      const Topology& space,
								      PositionMap position) {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIter;
      VertexIter ui,ui_end; tie(ui,ui_end) = vertices(g);
      return *(min_dist_linear_search(ui,ui_end,boost::bind(&linear_neighbor_search::distance<Vertex,Topology,PositionMap>,this,p,_1,space,position),m_compare,std::numeric_limits<double>::infinity()));
    };

    /**
     * This call-operator finds the nearest vertices of a graph, to a given position.
     * \tparam Graph The graph type which can contain the vertices, should
     *         model boost::VertexListGraphConcept.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated
     *         with each vertex.
     * \tparam OutputContainer The container type which can contain the list of
     *         nearest-neighbors (STL like container, with iterators, insert, size, and pop_back).
     * \param p A position in the space, to which the nearest-neighbors are sought.
     * \param output The container for the list of nearest-neighbors, the output of this
     *        function, and will be sorted from the nearest neighbor in increasing order.
     * \param g A graph containing the vertices from which to find the nearest-neighbors.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     * \param max_neighbors The maximum number of neighbors to have in the list.
     * \param radius The minimum distance around the position that a vertex should be in to be
     *        considered a neighbor.
     */
    template <typename Graph, typename Topology, typename PositionMap, typename OutputContainer>
    void operator()(const typename boost::property_traits<PositionMap>::value_type& p,
		    OutputContainer& output,
                    Graph& g,
		    const Topology& space,
		    PositionMap position,
		    unsigned int max_neighbors = 1,
		    double radius = std::numeric_limits<double>::infinity())
    {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIter;
      VertexIter ui,ui_end; tie(ui,ui_end) = boost::vertices(g);
      min_dist_linear_search(ui,ui_end,output,
                             boost::bind(&linear_neighbor_search::distance<Vertex,Topology,PositionMap>,
                                                          this,p,_1,space,position),
                             m_compare,max_neighbors,radius);
    };
  };

  /**
   * This functor template performs a best-only nearest-neighbor search through a tree by invoquing
   * the distance function of an underlying topology. The call operator will return the vertex
   * of the graph whose position value is likely to be closest to a given position value. This
   * algorithm is approximate. It will select a M vertices from the graph from which it starts
   * a best-only search, where M is obtained as M = number_of_vertices / m_vertex_num_divider.
   * \tparam CompareFunction The functor type that can compare two distance measures (strict weak-ordering).
   */
  template <typename CompareFunction = std::less<double> >
  struct best_only_neighbor_search {

    unsigned int m_vertex_num_divider;
    CompareFunction m_compare;
    /**
     * Default constructor.
     * \param aVertexNumDivider The division factor (should be greater than 1) which determines the
     *        fraction of the total number of vertices that is used to stem the best-only searches.
     *        Typical values are between 4 and 10.
     * \param compare The comparison functor for ordering the distances (strict weak ordering).
     */
    best_only_neighbor_search(unsigned int aVertexNumDivider = 10,
			      CompareFunction compare = CompareFunction()) :
                              m_vertex_num_divider(aVertexNumDivider), m_compare(compare) { };

    /**
     * This function template computes the topological distance between a position and the position of a
     * vertex of a graph. This function is used as a helper to the call-operator overloads.
     * \tparam Vertex The vertex descriptor type.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated with each vertex.
     * \param p A position in the space.
     * \param u A vertex which has a position associated to it, via the position property-map.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     */
    template <typename Vertex, typename Topology, typename PositionMap>
    double distance(const typename boost::property_traits<PositionMap>::value_type& p,
                    Vertex u, const Topology& space, PositionMap position) const {
      return space.distance(p, get(position, u));
    };

    template <typename Graph, typename Topology, typename PositionMap>
    void search(const typename boost::property_traits<PositionMap>::value_type& p,
		typename boost::graph_traits<Graph>::vertex_descriptor& u,
		double& d_min, Graph& g, const Topology& space, PositionMap position) {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      typedef typename boost::graph_traits<Graph>::out_edge_iterator EdgeIter;
      d_min = distance(p,u,space,position);
      while(boost::out_degree(u,g)) {
        Vertex v_min = u;
        EdgeIter ei, ei_end;
        for(boost::tie(ei,ei_end) = boost::out_edges(u,g); ei != ei_end; ++ei) {
          Vertex v = boost::target(*ei,g); double d_v = distance(p,v,space,position);
          if(m_compare(d_v,d_min)) {
            d_min = d_v; v_min = v;
          };
        };
        if(v_min == u)
          return;
        u = v_min;
      };
      return;
    };

    /**
     * This call-operator finds the nearest vertex of a graph, to a given position.
     * \tparam Graph The graph type which can contain the vertices, should
     *         model boost::VertexListGraphConcept and boost::IncidenceGraphConcept.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated with each vertex.
     * \param p A position in the space, to which the nearest-neighbor is sought.
     * \param g A graph containing the vertices from which to find the nearest-neighbor,
     *        should be tree-structured.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     */
    template <typename Graph, typename Topology, typename PositionMap>
    typename boost::graph_traits<Graph>::vertex_descriptor operator()(const typename boost::property_traits<PositionMap>::value_type& p,
								      Graph& g, const Topology& space, PositionMap position) {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      if(m_vertex_num_divider == 0)
	m_vertex_num_divider = 1;
      Vertex u_min = boost::vertex(std::rand() % boost::num_vertices(g),g);
      double d_min;
      search(p,u_min,d_min,g,space,position);
      for(unsigned int i = 0; i < boost::num_vertices(g) / m_vertex_num_divider; ++i) {
        double d_v; Vertex v = boost::vertex(std::rand() % boost::num_vertices(g),g);
        search(p,v,d_v,g,space,position);
        if(m_compare(d_v,d_min)) {
          d_min = d_v; u_min = v;
        };
      };
      return u_min;
    };

    template <typename Graph, typename Topology, typename PositionMap, typename OutputContainer>
    void search(const typename boost::property_traits<PositionMap>::value_type& p,
		typename boost::graph_traits<Graph>::vertex_descriptor u, OutputContainer& output, std::vector<double>& output_dist,
		double d_min, Graph& g, const Topology& space, PositionMap position, unsigned int max_neighbors, double radius) {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      typedef typename boost::graph_traits<Graph>::out_edge_iterator EdgeIter;
      if(m_compare(d_min, radius)) {
        std::vector<double>::iterator it_lo = std::lower_bound(output_dist.begin(),output_dist.end(),d_min,m_compare);
        if((it_lo != output_dist.end()) || (output_dist.size() < max_neighbors)) {
 	  output_dist.insert(it_lo, d_min);
	  typename OutputContainer::iterator itv = output.begin();
	  for(std::vector<double>::iterator it = output_dist.begin(); (itv != output.end()) && (it != it_lo); ++itv,++it) ;
	  output.insert(itv, u);
	  if(output.size() > max_neighbors) {
	    output.pop_back();
	    output_dist.pop_back();
	  };
        };
      };
      EdgeIter ei, ei_end;
      for(boost::tie(ei,ei_end) = boost::out_edges(u,g); ei != ei_end; ++ei) {
	Vertex v = boost::target(*ei,g); double d_v = distance(p,v,space,position);
	if(m_compare(d_v,d_min))
	  search(p,v,output,output_dist,d_v,g,space,position,max_neighbors,radius);
      };
    };

    /**
     * This call-operator finds the nearest vertices of a graph, to a given position.
     * \tparam Graph The graph type which can contain the vertices, should
     *         model boost::VertexListGraphConcept and boost::IncidenceGraphConcept.
     * \tparam Topology The topology type which contains the positions.
     * \tparam PositionMap The property-map type which can store the position associated
     *         with each vertex.
     * \tparam OutputContainer The container type which can contain the list of
     *         nearest-neighbors (STL like container, with iterators, insert, size, and pop_back).
     * \param p A position in the space, to which the nearest-neighbors are sought.
     * \param output The container for the list of nearest-neighbors, the output of this
     *        function, and will be sorted from the nearest neighbor in increasing order.
     * \param g A graph containing the vertices from which to find the nearest-neighbors,
     *        should be tree-structured.
     * \param space The topology objects which define the space in which the positions reside.
     * \param position The property-map which can retrieve the position associated to each vertex.
     * \param max_neighbors The maximum number of neighbors to have in the list.
     * \param radius The minimum distance around the position that a vertex should be in to be
     *        considered a neighbor.
     */
    template <typename Graph, typename Topology, typename PositionMap, typename OutputContainer>
    void operator()(const typename boost::property_traits<PositionMap>::value_type& p, OutputContainer& output,
		    Graph& g, const Topology& space, PositionMap position, unsigned int max_neighbors = 1, double radius = std::numeric_limits<double>::infinity()) {
      typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
      output.clear();
      std::vector<double> output_dist;
      if(m_vertex_num_divider == 0)
	m_vertex_num_divider = 1;
      for(unsigned int i = 0; i < boost::num_vertices(g) / m_vertex_num_divider; ++i) {
        Vertex v = boost::vertex(std::rand() % boost::num_vertices(g),g);
	double d_v = distance(p,v,space,position);
        search(p,v,output,output_dist,d_v,g,space,position,max_neighbors,radius);
      };
    };
  };

#endif


/* ========================================================================== */
/* === Demo/cholmod_simple ================================================== */
/* ========================================================================== */

/* -----------------------------------------------------------------------------
 * CHOLMOD/Demo Module.  Copyright (C) 2005-2006, Timothy A. Davis
 * -------------------------------------------------------------------------- */

/* Read in a real symmetric or complex Hermitian matrix from stdin in
 * MatrixMarket format, solve Ax=b where b=[1 1 ... 1]', and print the residual.
 * Usage: cholmod_simple < matrixfile
 */
#include <iostream>
#include <vector>

#include <Eigen/Sparse>
#include <Eigen/Dense>
#include <Eigen/CholmodSupport>

Eigen::MatrixXd generate_A()
{
    Eigen::MatrixXd mat = Eigen::MatrixXd::Identity(10, 10);
    for(size_t rows = 0; rows < 10; ++rows)
    {
        for(size_t cols = 0; cols < 10; ++ cols)
        {
            mat(rows, cols) = (double) rand() / RAND_MAX/ 20;
        }
    }

    // mat = Eigen::MatrixXd::Identity(10, 10);

    return mat;
}

Eigen::SparseMatrix<double> convert_to_sparse(Eigen::MatrixXd &mat)
{
    Eigen::SparseMatrix<double> sparse_mat = mat.sparseView();
    return sparse_mat;
}

int main (void)
{
    Eigen::MatrixXd A = generate_A();

    Eigen::MatrixXd dense_lhs = A.transpose() * A;

    Eigen::SparseMatrix<double> lhs = convert_to_sparse(dense_lhs);
    std::cout << "dense lhs:" << dense_lhs << std::endl;
    Eigen::VectorXd rhs = Eigen::VectorXd::Ones(10);

    Eigen::CholmodSupernodalLLT<Eigen::SparseMatrix<double>> solver;
    solver.compute(lhs);
    if(solver.info()!=Eigen::Success) {
    // decomposition failed
    }
    Eigen::MatrixXd x = solver.solve(rhs);
    if(solver.info()!=Eigen::Success) {
    }

    std::cout << "x: " << x << std::endl;

    return (0) ;
}


// BLAS level 2 -- complex numbers

#include <iostream>
#include <complex>
#include <boost/numeric/bindings/blas/level1.hpp>
#include <boost/numeric/bindings/blas/level2.hpp>
#include <boost/numeric/bindings/ublas/vector.hpp>
#include <boost/numeric/bindings/ublas/matrix.hpp>
#include <boost/numeric/bindings/ublas/matrix_proxy.hpp>
#include <boost/numeric/bindings/conj.hpp>
#include <boost/numeric/bindings/io.hpp>
#include <boost/numeric/bindings/noop.hpp>
#ifdef F_USE_STD_VECTOR
#include <boost/numeric/bindings/std/vector.hpp>
#endif
#include "utils.h"

namespace ublas = boost::numeric::ublas;
namespace blas = boost::numeric::bindings::blas;

using std::cout;
using std::endl;

typedef double real_t;
typedef std::complex<real_t> cmplx_t;

#ifndef F_USE_STD_VECTOR
typedef ublas::vector<cmplx_t> vct_t;
typedef ublas::matrix<cmplx_t, ublas::row_major> m_t;
#else
typedef ublas::vector<cmplx_t, std::vector<cmplx_t> > vct_t;
typedef ublas::matrix<cmplx_t, ublas::column_major, std::vector<cmplx_t> > m_t;
#endif

int main() {

  cout << endl;

  vct_t vx (2);
  blas::set( 1, vx );
  std::cout << "vx " << bindings::noop( vx ) << std::endl;
  vct_t vy (4); // vector size can be larger
                // than corresponding matrix size
  blas::set( 0, vy );
  std::cout << "vy " << bindings::noop( vy ) << std::endl;
  cout << endl;

  m_t m (3, 2);
  init_m (m, kpp (1));
  print_m (m, "m");
  cout << endl;

  // vy = m vx
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  cout << endl;

  m (0, 0) = cmplx_t (0., 1.);
  m (0, 1) = cmplx_t (0., 2.);
  m (1, 0) = cmplx_t (0., 3.);
  m (1, 1) = cmplx_t (0., 4.);
  m (2, 0) = cmplx_t (0., 5.);
  m (2, 1) = cmplx_t (0., 6.);
  print_m (m, "m");
  cout << endl;

  // vy = m vx
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  cout << endl;

  m (0, 0) = cmplx_t (-1., 1.);
  m (0, 1) = cmplx_t (-2., 2.);
  m (1, 0) = cmplx_t (-3., 3.);
  m (1, 1) = cmplx_t (-4., 4.);
  m (2, 0) = cmplx_t (-5., 5.);
  m (2, 1) = cmplx_t (-6., 6.);
  print_m (m, "m");
  cout << endl;

  // vy = m vx
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, m, vx, 0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  cout << endl;

  blas::set ( 1, vx );
  std::cout << "vx " << bindings::noop( vx ) << std::endl;

  // vy = m vx
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  cout << endl;

  blas::set ( cmplx_t (1, 1), vx );
  std::cout << "vx " << bindings::noop( vx ) << std::endl;

  // vy = m vx
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, m, vx, 0.0, vy);
  std::cout << "m vx " << bindings::noop( vy ) << std::endl;
  cout << endl;

  // vx = m^H vy
  blas::set ( cmplx_t (-1,-1), vy );
  std::cout << "vy " << bindings::noop( vy ) << std::endl;
  blas::gemv ( 1.0, bindings::conj(m), vy, 0.0, vx);
  std::cout << "m^H vy " << bindings::noop( vx ) << std::endl;
  cout << endl;

  m_t mx (2, 2);
  m_t my (3, 2);

  ublas::matrix_column<m_t> mxc0 (mx, 0),
                            mxc1 (mx, 1);
  ublas::matrix_column<m_t> myc0 (my, 0),
                            myc1 (my, 1);

  blas::set ( cmplx_t (1, 0), mxc0 );
  blas::set ( cmplx_t (0, 0), mxc1 );
  blas::set ( cmplx_t (0, 0), myc0 );
  blas::set ( cmplx_t (0, 0), myc1 );

  print_m (mx, "mx");
  cout << endl;
  print_m (my, "my");
  cout << endl;

  // my[.,0] = m mx[.,0]
  blas::gemv ( 1.0, m, mxc0, 0.0, myc0);
  print_m (my, "m mx[.,0]");

  cout << endl;

}


/*
Copyright (c) 2020 ETH Zurich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Author: Katrin Lasinger
*/

#define _USE_MATH_DEFINES

#include <numeric>
#include <vector>
#include <algorithm>
#include <omp.h>
#include "mex.h"
#include <math.h>

#include <Eigen/Dense>
using namespace Eigen;

/// matlab calling
void proj2d ( int nlhs, mxArray *plhs[],
                int nrhs, const mxArray *prhs[])
{

  typedef double Scalar;

  Scalar *part = (Scalar*)mxGetPr(prhs[0]);

  Scalar *P_vec = (Scalar*)mxGetPr(prhs[1]);

  Matrix<Scalar, 3, 4> P;

  for(int j=0;j<4;j++)
    for (int i=0;i<3;i++)
		P(i,j) = P_vec[i+j*3];

  const mwSize* dims = mxGetDimensions(prhs[0]);
  size_t numpart = dims[1]; // list of points
  size_t partDim = dims[0]; // featureDim

  plhs[0] = mxCreateDoubleMatrix(2,numpart, mxREAL);
  Scalar* part2d = (Scalar*)mxGetPr(plhs[0]);

  plhs[1] = mxCreateDoubleMatrix(3,numpart, mxREAL);
  Scalar* xhom = (Scalar*)mxGetPr(plhs[1]);

#pragma omp parallel for //schedule (static)
  for (long long i = 0; i < numpart; i++)
  {

	Vector4d pt;
	pt << part[i*3],part[i*3+1], part[i*3+2], 1;

	Vector3d pt2d_hom;
	pt2d_hom = P * pt;

	xhom[i*3] =pt2d_hom(0);
	xhom[i*3+1] = pt2d_hom(1);
	xhom[i*3+2] = pt2d_hom(2);
	part2d[i*2] = pt2d_hom(0) / pt2d_hom(2);
	part2d[i*2+1] = pt2d_hom(1) / pt2d_hom(2);

  }

}


#ifndef DatabaseChart_hpp
#define DatabaseChart_hpp

#include <QOpenGLWidget>
#include <QSharedPointer>
#include <QVector>
#include <QSettings>
#include <QtCharts>
#include <armadillo>
#include <functional>
#include <UMF/ComputeHistogram.hpp>
#include <UMF/CurveNormalization.hpp>
#include <UMF/Evaluate1D.hpp>
#include <AA/FeaturesExtractor.hpp>

namespace GUI{
	class DatabaseLine : public QLineSeries {

		Q_OBJECT

		Q_PROPERTY(double Minimum MEMBER m_Minimum READ getMinimum WRITE setMinimum NOTIFY parameterChanged)
		Q_PROPERTY(double Maximum MEMBER m_Maximum READ getMaximum WRITE setMaximum NOTIFY parameterChanged)
		Q_PROPERTY(int NumPoints MEMBER m_NumPoints READ getNumPoints WRITE setNumPoints NOTIFY parameterChanged)
		Q_PROPERTY(CurveType Type MEMBER m_Type READ getType WRITE setType NOTIFY parameterChanged)
		Q_PROPERTY(QVector<double> Coefficients MEMBER m_Coefficients READ getCoefficients WRITE setCoefficients NOTIFY parameterChanged)
		Q_PROPERTY(QList<QVector<double>> Features MEMBER m_Features READ getFeatures WRITE setFeatures NOTIFY featuresChanged)

	public:
		enum CurveType {
			Gaussian,
			GaussianExp
		};
		Q_ENUM(CurveType);

	private:
		double m_Minimum = 0.0;
		double m_Maximum = 1.0;
		int m_NumPoints = 100;
		CurveType m_Type = GaussianExp;
		QVector<double> m_Coefficients = {5.0, 0.3, 0.1, 0.1};
		QList<QVector<double>> m_Features;

	public:
		DatabaseLine(QObject* parente = Q_NULLPTR);

		double getMinimum() const {return m_Minimum;};
		double getMaximum() const {return m_Maximum;};
		int getNumPoints() const {return m_NumPoints;};
		CurveType getType() const {return m_Type;};
		QVector<double> getCoefficients() const {return m_Coefficients;};
		QList<QVector<double>> getFeatures() const {return m_Features;};

		void setMinimum(double min){m_Minimum=min; update(); Q_EMIT parameterChanged();};
		void setMaximum(double max){m_Maximum=max; update(); Q_EMIT parameterChanged();};
		void setNumPoints(int n_points){m_NumPoints=n_points; update(); Q_EMIT parameterChanged();};
		void setType(CurveType type){m_Type=type; update(); Q_EMIT parameterChanged();};
		void setCoefficients(QVector<double> coeff){m_Coefficients=coeff; update(); Q_EMIT parameterChanged();};
		void setFeatures(QList<QVector<double>> features){m_Features=features; Q_EMIT featuresChanged();};
		void addFeatures(QVector<double> features){m_Features << features; Q_EMIT featuresChanged();};

		static QVector<double> linspace(double min, double max, int points);
		static QVector<double> regspace(double min, double max, double step);

		static QColor genNewColor();

	Q_SIGNALS:
		Q_SIGNAL void parameterChanged();
		Q_SIGNAL void featuresChanged();

		public Q_SLOTS:
		Q_SLOT void update();

	};

	class QHistogramSeries : public QAreaSeries {

		Q_OBJECT

		Q_PROPERTY(QVector<double> X MEMBER m_X READ getX WRITE setX NOTIFY XChanged)
		Q_PROPERTY(QVector<double> Y MEMBER m_Y READ getY WRITE setY NOTIFY YChanged)

	private:
		QVector<double> m_X, m_Y;

		void tryBuildSeries();

	public:
		QHistogramSeries(QObject *parent = Q_NULLPTR):QAreaSeries(parent){};
		QHistogramSeries(QVector<double> X, QVector<double> Y);

		QVector<double> getX() const {return m_X;};
		QVector<double> getY() const {return m_Y;};

		void setX(QVector<double> X){m_X=X; tryBuildSeries(); Q_EMIT XChanged();};
		void setY(QVector<double> Y){m_Y=Y; tryBuildSeries(); Q_EMIT YChanged();};

	Q_SIGNALS:
		Q_SIGNAL void XChanged();
		Q_SIGNAL void YChanged();
	};

	class InteractiveChart : public QtCharts::QChartView {

		Q_OBJECT

		/** The zoom factor; 1/zoomFactor is used to zoom out. */
		const double zoomFactor = 1.2;

		/** The scrolling speed. */
		const double moveFactor = 0.3;

		/** Reimplementation of the QChartView::keyPressEvent to handle keyboard interaction (zoom and scroll). */
		void keyPressEvent(QKeyEvent *event);

	public:
		InteractiveChart(QWidget* parent = Q_NULLPTR);
	};

	class DatabaseChart : public InteractiveChart {

		Q_OBJECT

	public:
		/** Constructor with initial settings. */
		DatabaseChart(QWidget* parent = Q_NULLPTR);

		void updateViewWith(QAbstractSeries*);

		public Q_SLOTS:
		/** Compute and plot the histogram in the chart.
		 This function is an overload.
		 @param[in] x Bars positions.
		 @param[in] y Bars height.*/
		Q_SLOT void plotHistogram(QVector<double> X,
								  QVector<double> Y,
								  QString Name = "",
								  QColor Color = QColor::fromRgb(-1, -1, -1));

		/** Plot a gaussian curve, given its coefficients.
		 This function is an overload. The gaussian function is
		 of the form
		 \f[
		 f(x) = c_1 e^{\frac{(x-c_1)^2}{2c_3^2}}
		 \f]
		 where \f$ c_1 \f$, \f$ c_2 \f$ and \f$ c_3 \f$ are the parameters.
		 @param[in] coefficients Coefficients of the gaussian function.
		 @param[in] domain The set of points which the function must be evalutated on.
		 */
		Q_SLOT QLineSeries* plotCurve(QVector<double> X,
									  QVector<double> Y,
									  QString Name = "",
									  QColor Color = QColor::fromRgb(-1, -1, -1));

		Q_SLOT void addSpot(double);

		Q_SLOT void plotParametricCurve(QVector<double> Parameters,
										double min,
										double max,
										DatabaseLine::CurveType type,
										QString Name = "",
										QColor Color = QColor::fromRgb(-1, -1, -1));

	Q_SIGNALS:
		Q_SIGNAL void raise(QString);
	};

	/** Class to show audio signals in time domain. */
	class ChartRecWidget : public InteractiveChart {

		Q_OBJECT

	public:
		/** Constructs an instance and customizes its appearance. */
		ChartRecWidget(QWidget* parent = Q_NULLPTR);

		/** Convert a series index to the corresponding x value.
		 By default the function only casts the input value to double.
		 @sa addSeries, valueToYAxis
		 */
		std::function<double(int)> indexToXAxis = [](int i){return double(i);};

		/** Convert a series value to the corresponding y value.
		 By default the function only casts the input value to double.
		 @sa addSeries, indexToXAxis
		 */
		std::function<double(double)> valueToYAxis = [](double y){return y;};

		public Q_SLOTS:

		/** Add a series to the chart and adjust axes accordingly.
		 The data given as input contains only y-values, but not their corresponding
		 position on the x-axis; to insert a new series in the chart the position of a value
		 in the given array is interpreted as x, and the method indexConversion is used to rescale
		 the position. Subclasses can override indexConversion to convert an array index to
		 the real x position of the value.
		 To adjust the axes the function updateAxes is called, and it can be overridden by
		 subclasses to manage different behaviour.
		 @sa updateAxes, display, indexConversion
		 */
		Q_SLOT void addSeries(QVector<double> newData);

		Q_SLOT void addPoints(QVector<int> newData);

	Q_SIGNALS:
		Q_SIGNAL void raise(QString errorMsg);
	};
}

QDataStream& operator<<(QDataStream&, const GUI::DatabaseLine::CurveType&);
QDataStream& operator<<(QDataStream&, const GUI::DatabaseLine&);

QDataStream& operator>>(QDataStream&, GUI::DatabaseLine::CurveType&);
QDataStream& operator>>(QDataStream&, GUI::DatabaseLine&);

#endif /* DatabaseChart_hpp */