//
// Created by martin on 28. 3. 2021.
//

#ifndef ARC_MATRIX_ELLIPSEVALIDATION_H
#define ARC_MATRIX_ELLIPSEVALIDATION_H

#include <eigen3/Eigen/Core>
#include <opencv2/core.hpp>
#include "ArcExtraction.h"
#include "DP.h"
#include "utility.h"

//class ellipseValidation {
//
//};

/**
 * transforms a general ellipse equation into semi-axis size
 * @param ellipseEQ general ellipse equation
 * @param major decides whether to calculate major or minor axis
 * @return major/minor axis size
 */
double semiAxis(Eigen::Matrix<double, 6, 1> &ellipseEQ, bool major);

/**
 * calculates centre point of the ellipse from general ellipse equation
 * @param ellipseEQ general ellipse equation
 * @return center coordinates
 */
cv::Point2i centre(Eigen::Matrix<double, 6, 1> &ellipseEQ) ;

/**
 * calculates the angle between the ellipse and vector (1,0);
 * @param ellipseEQ general ellipse equation
 * @return angle between ellipse and vector (1,0);
 */
double angle(Eigen::Matrix<double, 6, 1> &ellipseEQ);

//cv::Point2i sampling_point(const double &major_axis, const double &minor_axis,const double &angle ,cv::Point2i ellipse_centre, int index);
/**
 * calculates the position of the sampling point
 * @param major_axis major axis of the ellipse
 * @param minor_axis minor axis of the ellipse
 * @param angle angle of the ellipse
 * @param ellipse_centre center point of the ellips
 * @param index index of the current sampling point
 * @param N_v number of all sampling points on the ellipse
 * @return position of the sampling point
 */
cv::Point2i sampling_point(const double &major_axis, const double &minor_axis,const double &angle ,cv::Point2i ellipse_centre, int index, int N_v);


/**
 * calculates shape index as shown in eq. 10 in the original paper
 * @param ellipseEQ parametric ellipse equation
 * @param theta treshold theta_arc
 * @return true if ellipse has correct shape
 */
bool ShapeIndex (const ellipseParameters &ellipseEQ, const double theta);

/**
 * checks whether the sampling point landed near a ellipse pixel
 * @param V_i sampling point
 * @param edges edges of the original image
 * @return true if sampling point landed near the ellipse pixel
 */
bool location_index(cv::Point2i V_i ,const cv::Mat& edges);


/**
 * calculates the gradient index according to eq. 11 from the original paper
 * @param major_axis major axis size of the ellipse
 * @param minor_axis minor axis size of the ellipse
 * @param angle rotation of the ellipse
 * @param ellipse_centre center point of the ellipse
 * @param d_tol tolerance of the tangent estimator
 * @param index is an index of current sampling point
 * @param N_V count of sampling points
 * @return gradient index
 */
double gradient_index (double major_axis, double minor_axis , double angle, cv::Point2i ellipse_centre, double d_tol,int index,int N_V);

/**
 * calculates weight index according to eq. 12 from the original paper
 * @param major_axis major axis size of the ellipse
 * @param minor_axis minor axis size of the ellipse
 * @param angle rotation of the ellipse
 * @return weight index
 */
double weight_index (double major_axis, double minor_axis, double angle) ;

/**
 * calculates the count of sampling points needed for verification
 * @param major_axis major axis size of the ellipse
 * @param minor_axis minor axis size of the ellipse
 * @return count of the sampling points
 */
int sampling_points_count(double major_axis, double minor_axis);

/**
 * takes general ellipse equation and transforms it into parametric equation
 * @param ellipseEQ general ellipse equation
 * @return parametric equation.
 */
ellipseParameters ellipse_equation(Eigen::Matrix<double, 6, 1> &ellipseEQ);




/**
 * scores the ellipse
 * @param ellipseEQ general ellipse equation
 * @param params ellipse parameters
 * @param canny
 * @param theta
 * @return
 */
double score(Eigen::Matrix<double, 6, 1> &ellipseEQ, const ellipseParameters & params , cv::Mat & canny,const double theta);



#endif //ARC_MATRIX_ELLIPSEVALIDATION_H
