/***************************************************************************
**
**  This file is part of DinverDCCore.
**
**  DinverDCCore 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.
**
**  DinverDCCore 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2019-01-25
**  Copyright: 2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "LinearProfile.h"

namespace DinverDCCore {

  /*!
    \class LinearProfile LinearProfile.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  /*!
    Return false, no need to set depths after a modification of bottom value
  */
  bool LinearProfile::setBottomValue(double v)
  {
    _alpha=v-_vt/(_zb-_zt);
    return false;
  }

  double LinearProfile::bottomValue() const
  {
    return _vt+_alpha*thickness();
  }

  void LinearProfile::setDepths(int topIndex, Profile& p)
  {
    _dz=(bottomDepth()-_zt)/static_cast<double>(_n);
    int n1=_n-1;
    for(int i=0; i<n1; i++) {
      p.setDepth(topIndex+i, _zt+static_cast<double>(i+1)*_dz);
    }
    p.setDepth(topIndex+n1, _zb);
  }

  void LinearProfile::setValues(int topIndex, Profile& p)
  {
    double z0=_zt+0.5*_dz;
    for(int i=0; i<_n; i++) {
      int di=topIndex+i;
      p.setValue(di, _vt+_alpha*(p.depths()[di]-z0));
    }
  }

  /*!
    top and bottom depths must be fixed, topValue also.
    If \a depth falls exactly on one of profile's predefined depths,
    choose the highest index to get the lowest possible gradient value.
  */
  void LinearProfile::setMinimumGradient(double value, double depth)
  {
    ASSERT(depth>=_zt && depth<=bottomDepth());
    int index=qFloor((depth-_zt)/_dz);
    double iDepth=_zt+static_cast<double>(index+1)*_dz;
    _alpha=(value-_vt)/(iDepth-_zt-0.5*_dz);
  }

  /*!
    top and bottom depths must be fixed, topValue also.
    If \a depth falls exactly on one of profile's predefined depths,
    choose the lowest index to get the highest possible gradient value.
  */
  void LinearProfile::setMaximumGradient(double value, double depth)
  {
    ASSERT(depth>=_zt && depth<=bottomDepth());
    int index=qFloor((depth-_zt)/_dz);
    double iDepth=_zt+static_cast<double>(index)*_dz;
    if(depth>iDepth) {
      iDepth+=_dz;
    }
    _alpha=(value-_vt)/(iDepth-_zt-0.5*_dz);
  }

  /*!
    top and bottom depths must be fixed, gradient also.
    If \a depth falls exactly on one of profile's predefined depths,
    choose the highest index to get the lowest possible top value.
  */
  void LinearProfile::setMinimumTopValue(double value, double depth)
  {
    ASSERT(depth>=_zt && depth<=bottomDepth());
    int index=qFloor((depth-_zt)/_dz);
    double iDepth=_zt+static_cast<double>(index+1)*_dz;
    _vt=value-_alpha*(iDepth-_zt-0.5*_dz);
  }

  /*!
    top and bottom depths must be fixed, gradient also.
    If \a depth falls exactly on one of profile's predefined depths,
    choose the lowest index to get the highest possible top value.
  */
  void LinearProfile::setMaximumTopValue(double value, double depth)
  {
    ASSERT(depth>=_zt && depth<=bottomDepth());
    int index=qFloor((depth-_zt)/_dz);
    double iDepth=_zt+static_cast<double>(index)*_dz;
    if(depth>iDepth) {
      iDepth+=_dz;
    }
    _vt=value-_alpha*(iDepth-_zt-0.5*_dz);
  }

} // namespace DinverDCCore

