//---------------------------------------------------------
bool CWaterRetentionCapacity::On_Execute(void)
{
	CSG_Shapes	*pInput		= Parameters("SHAPES")->asShapes();
	CSG_Shapes	*pOutput	= Parameters("OUTPUT")->asShapes();

	if( pInput->Get_Field_Count() < 5 )
	{
		Error_Set(_TL("Plot hole data has to provide at the very least five attributes (horizon depth, TF, L, Ar, Mo)."));

		return( false );
	}

	pOutput->Create(SHAPE_TYPE_Point, _TL("Water Retention Capacity"));

	pOutput->Add_Field("CCC"                     , SG_DATATYPE_Double);
	pOutput->Add_Field("CIL"                     , SG_DATATYPE_Double);
	pOutput->Add_Field("Permeability"            , SG_DATATYPE_Double);
	pOutput->Add_Field("Equivalent Moisture"     , SG_DATATYPE_Double);
	pOutput->Add_Field("Water Retention Capacity", SG_DATATYPE_Double);

	//-----------------------------------------------------
	CSG_Grid	*pDEM	= Parameters("DEM")->asGrid();

	CSG_Matrix	Data(5, pInput->Get_Field_Count() / 5);

	for(int iPoint=0; iPoint<pInput->Get_Count(); iPoint++)
	{
		CSG_Shape	*pPoint	= pInput->Get_Shape(iPoint);

		for(int iHorizon=0, n=0; iHorizon<Data.Get_NRows(); iHorizon++, n+=5)
		{
			for(int i=0; i<5; i++)
			{
				Data[iHorizon][i]	= pPoint->asDouble(n + i);
			}
		}

		double	Slope, Aspect;

		if( !pDEM->Get_Gradient(pPoint->Get_Point(0), Slope, Aspect, GRID_RESAMPLING_BSpline) )
		{
			Slope	= 0.0;
		}

		Get_WaterRetention(Data, 1. - tan(Slope), pOutput->Add_Shape(pPoint, SHAPE_COPY_GEOM));
	}

	//-----------------------------------------------------
	CSG_Grid	*pRetention	= Parameters("RETENTION")->asGrid();

	if( pRetention )
	{
		switch( Parameters("INTERPOL")->asInt() )
		{
		default:	// Multlevel B-Spline Interpolation
			SG_RUN_TOOL_ExitOnError("grid_spline", 4,
					SG_TOOL_PARAMETER_SET("SHAPES"           , pOutput)
				&&  SG_TOOL_PARAMETER_SET("FIELD"            , pOutput->Get_Field_Count() - 1)
				&&  SG_TOOL_PARAMETER_SET("TARGET_DEFINITION", 1)	// grid or grid system
				&&  SG_TOOL_PARAMETER_SET("TARGET_OUT_GRID"  , pRetention)
			);
			break;

		case  1:	// Inverse Distance Weighted
			SG_RUN_TOOL_ExitOnError("grid_gridding", 1,
					SG_TOOL_PARAMETER_SET("SHAPES"           , pOutput)
				&&  SG_TOOL_PARAMETER_SET("FIELD"            , pOutput->Get_Field_Count() - 1)
				&&  SG_TOOL_PARAMETER_SET("TARGET_DEFINITION", 1)	// grid or grid system
				&&  SG_TOOL_PARAMETER_SET("TARGET_OUT_GRID"  , pRetention)
				&&  SG_TOOL_PARAMETER_SET("SEARCH_RANGE"     , 1)	// global
				&&  SG_TOOL_PARAMETER_SET("SEARCH_POINTS_ALL", 1)	// all points within search distance
			);
			break;
		}

		if( Parameters("SLOPECORR")->asBool() )
		{
			#pragma omp parallel for
			for(int y=0; y<Get_NY(); y++)
			{
				for(int x=0; x<Get_NX(); x++)
				{
					if( !pRetention->is_NoData(x, y) )
					{
						double	Slope, Aspect;

						if( !pDEM->Get_Gradient(x, y, Slope, Aspect) )
						{
							Slope	= 0.0;
						}

						pRetention->Mul_Value(x, y, 1. - tan(Slope));
					}
				}
			}
		}
	}

	//-----------------------------------------------------
	return( true );
}