TEST_F(NumLibSpatialFunctionHex, InterpolationPolyline)
{
    const std::vector<std::size_t> vec_point_ids = {{0, 4}};
    const std::vector<double> vec_point_values = {{0., 100.}};
    std::vector<double> expected = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}};

    NumLib::LinearInterpolationAlongPolyline interpolate(
        *_ply0, vec_point_ids, vec_point_values, std::numeric_limits<double>::epsilon(), std::numeric_limits<double>::max());
    const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs();
    std::vector<double> interpolated_values(vec_node_ids.size());
    NodeIDtoNodeObject<NumLib::LinearInterpolationAlongPolyline> task(*_msh, interpolate);
    std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task);

    ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon());
}
TEST_F(NumLibSpatialFunctionQuad, Linear)
{
    // f(x,y,z) = 1 + 2x + 3y + 4z
    std::array<double,4> f_coeff = {{1, 2, 3, 4}};
    MathLib::LinearFunction<double,3> linear_f(f_coeff);
    std::vector<double> expected = {{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21}};

    NumLib::SpatialFunctionLinear f(linear_f);
    const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs();
    std::vector<double> interpolated_values(vec_node_ids.size());
    NodeIDtoNodeObject<NumLib::SpatialFunctionLinear> task(*_msh, f);
    std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task);

    ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon());
}
TEST_F(NumLibSpatialFunctionHex, InterpolationSurface)
{
    const std::vector<std::size_t> vec_point_ids = {{0, 3, 7, 4}};
    const std::vector<double> vec_point_values = {{0., 100., 100., 0.}};
    std::vector<double> expected(std::pow(_number_of_subdivisions_per_direction+1, 2));
    for (std::size_t i=0; i<expected.size(); i++) {
        expected[i] = (i%(_number_of_subdivisions_per_direction+1)) * 10;
    }

    NumLib::LinearInterpolationOnSurface interpolate(*_sfc1, vec_point_ids, vec_point_values, std::numeric_limits<double>::max());
    const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongSurface(*_sfc1).getNodeIDs();
    std::vector<double> interpolated_values(vec_node_ids.size());
    NodeIDtoNodeObject<NumLib::LinearInterpolationOnSurface> task(*_msh, interpolate);
    std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task);

    ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<float>::epsilon());
}
TEST_F(NumLibSpatialFunctionHex, Linear)
{
    // f(x,y,z) = 1 + 2x + 3y + 4z
    std::array<double,4> f_coeff = {{1, 2, 3, 4}};
    MathLib::LinearFunction<double,3> linear_f(f_coeff);
    std::vector<double> expected(std::pow(_number_of_subdivisions_per_direction+1, 2));
    const double dL = _geometric_size / _number_of_subdivisions_per_direction;
    for (std::size_t i=0; i<expected.size(); i++) {
        double x = 0;
        double y = (i%(_number_of_subdivisions_per_direction+1)) * dL;
        double z = (i/(_number_of_subdivisions_per_direction+1)) * dL;
        expected[i] = f_coeff[0] + f_coeff[1]*x + f_coeff[2]*y + f_coeff[3]*z;
    }

    NumLib::SpatialFunctionLinear f(linear_f);
    const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongSurface(*_sfc1).getNodeIDs();
    std::vector<double> interpolated_values(vec_node_ids.size());
    NodeIDtoNodeObject<NumLib::SpatialFunctionLinear> task(*_msh, f);
    std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task);

    ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon());
}
void SingleParticle2dx::Methods::RealSpaceProjectionMethod::calculateProjection(SingleParticle2dx::DataStructures::Orientation& o, SingleParticle2dx::DataStructures::Projection2d& p)
{
	p.resetData();
	Eigen::Matrix3f rot = SingleParticle2dx::Utilities::UtilityFunctions::determineRotation(o);
	size_type n = p.getSizeX();
	
	size_type x1, y1;
	value_type dx, dy;
	value_type ii, jj;
	Vector3d n_vec, new_vec;
		
	Vector3d n_sizehalf;
	n_sizehalf << n/2, n/2, n/2;

	real_array2d_type real_data_2d;
	real_data_2d.resize( boost::extents[n][n] );
	SingleParticle2dx::Utilities::DataContainerFunctions::resetData(&real_data_2d);
	
	real_array3d_type real_data_3d;
	real_data_3d.resize( boost::extents[n][n][n] );
	m_context->getRealSpaceData(real_data_3d);
	
	std::vector<value_type> interpolated_values (4, value_type(0) );
	size_type i, j, k;
	
	for(i=0; i<n; i++)
	{
		for(j=0; j<n; j++)
		{
			for(k=0; k<n; k++)
			{
				n_vec << i, j, k;
				n_vec -= n_sizehalf;
				new_vec = rot*n_vec;
				new_vec += n_sizehalf;
				
				ii = new_vec[0];
				jj = new_vec[1];
				
				//if ( (ii<0) || (jj<0) || (ii>=(n-1)) || (jj>=(n-1)) )
				//{
				//	continue;
				//}
				
				if (ii<0)
				{
					ii += n;
				}
				
				if (jj<0)
				{
					jj += n;
				}
				
				if (ii >= n)
				{
					ii -= n;
				}
				
				if (jj >= n)
				{
					jj -= n;
				}
				
				x1 = floor(ii);
				y1 = floor(jj);
					
				dx = 1 - ii + x1;
				dy = 1 - jj + y1;
				
				interpolate2d(dx, dy, real_data_3d[i][j][k], interpolated_values);
				real_data_2d[x1][y1] += interpolated_values[0];
				real_data_2d[x1+1][y1] += interpolated_values[1];
				real_data_2d[x1][y1+1] += interpolated_values[2];
				real_data_2d[x1+1][y1+1] += interpolated_values[3];
			}
		}
	}
		
	p.setFourierSpaceData(&real_data_2d);
	p.normalizeRealSpace();
	p.setOrientation(o);
}