/*
    C++ Mesh Generation Library
    Copyright (c) 2000echet <eric at bechet dot ca>

    This file is part of the C++ Mesh Generation Library.

    See the NOTICE & LICENSE files for conditions.
*/
#ifndef FM_FINDMINITPATH_H
#define FM_FINDMINITPATH_H

#include "gmshNode.h"
#include "gmshElement.h"
#include "FastMarching.h"
#include "SpeedFunctor.h"
#include "ExportFunctor.h"
#include "SPoint3.h"
#include <vector>
#include "GModel.h"
#include "GmshGlobal.h"
#include "SPointToDouble.h"
#include "FMField.h"


class FindMiniPath : public FieldSet
{

  FastMarch_c fastM;
  FMSpeedConstant Speed;
  FM::FMModel *Model;

protected:

 /** 
   * Compute the point at the center of the geodesic (SPoint3 pt), using the isocurves of sum and difference.
   * 
   * @param[in] valdep,valarr double distance from departure and arrival
   * @param[in] val1,val2 double& value in field (1,2) of SPoint3 pos
   * @param[in] pt SPoint3 is the minipoint returned
   * @param[in] f1,f2 int index in list fields of the fields containing the sum (f1) and the difference (f2).
   * @param[in] singular bool enable break due to singularity
   * @return int there is a singular point, returns 1, otherwise return 0. If singular point, it is stored in SPoint3 pt.
  */
  int getMiniPoint(double valdep,double valarr,double& val1,double& val2,SPoint3 &pt,int f1,int f2,bool singular);

  /**
   * Check if there are singular points and return the first one
   * 
   * @param[in] valdep,valarr double distance from departure and arrival
   * @param[in] val1,val2 double& value in field (1,2) of SPoint3 pos
   * @param[in] pos SPoint3 point at the middle of the geodesic or
   * @param[in] f1,f2 int fields concerned (indexes in fields)
   * @param[in] crv double relative curvature
   * @return int singular point. If no singular points, return 0.
  */
  int getSingularPoint(double valdep,double valarr,double& val1,double& val2,SPoint3 &pos,int f1, int f2,double crv);

public :

  /**
   * Constructor
  */
  FindMiniPath(const FMField& f1,const FMField& f2, FM::FMModel *Model_) : Model(Model_),Speed(1.0),fastM(Speed) {addField(f1);addField(f2);}

  /**
   * Constructor with FMModel as input.
   * FMM set by default (Speed = 1); see FastMarch_c
   * 
   * @param[in] Model  FM::FMModel (requires reading msh file with GMsh API)
   * 
  */
  FindMiniPath(FM::FMModel *Model_) : Model(Model_),Speed(1.0),fastM(Speed) {}

  /**
   * Generate msh results file from the FMM for both dep and arr points.
   * 
   * @param[in] dep,arr SPoint3 points of departure and arrival
   * @param[in] singular bool enable handling of singularities 
   * 
   * @param[out] val1_,val2_ double* distance from departure and arrival according to field (1,2)
   * @param[out] valmid1_,valmid2_ double* value in field (1,2) of SPoint3 pos (distane from departure and arrival)
   * @param[out] pos SPoint3 point at the center of the geodesic
   * 
   * @return double Absolut error for mid point wrt/ sum of distance
  */
  double getLength(SPoint3 dep, SPoint3 arr, double* val1_, double* val2_, bool singular, double* valmid1_, double* valmid2_,SPoint3 &pos);

  void Clear(void) { fastM.Clear(); clearFields();}
};


#endif //FM_FINDMINITPATH_H