Skip to content

Commit

Permalink
Merge pull request #1042 from Geode-solutions/fix/array_attribute_int…
Browse files Browse the repository at this point in the history
…erpolation

fix(AttributeInterpolation): Added the interpolation of attributes of…
  • Loading branch information
MelchiorSchuh authored Nov 5, 2024
2 parents a49a686 + 8f3d29d commit 42beb16
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 25 deletions.
28 changes: 28 additions & 0 deletions include/geode/basic/attribute_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,34 @@ namespace geode
IMPLICIT_ATTRIBUTE_LINEAR_INTERPOLATION( float );
IMPLICIT_ATTRIBUTE_LINEAR_INTERPOLATION( double );

#define IMPLICIT_ARRAY_ATTRIBUTE_LINEAR_INTERPOLATION( Type ) \
template < size_t array_size > \
struct AttributeLinearInterpolationImpl< std::array< Type, array_size > > \
{ \
template < template < typename > class Attribute > \
[[nodiscard]] static std::array< Type, array_size > compute( \
const AttributeLinearInterpolation& interpolator, \
const Attribute< std::array< Type, array_size > >& attribute ) \
{ \
std::array< Type, array_size > result; \
result.fill( 0 ); \
for( const auto vertex_id : Indices{ interpolator.indices_ } ) \
{ \
const auto& array_value = \
attribute.value( interpolator.indices_[vertex_id] ); \
for( const auto position : Indices{ array_value } ) \
{ \
result[position] += interpolator.lambdas_[vertex_id] \
* array_value[position]; \
} \
} \
return result; \
} \
}

IMPLICIT_ARRAY_ATTRIBUTE_LINEAR_INTERPOLATION( float );
IMPLICIT_ARRAY_ATTRIBUTE_LINEAR_INTERPOLATION( double );

/*!
* Helper struct to convert an Attribute value to generic float.
* This struct may be customized for a given type.
Expand Down
2 changes: 1 addition & 1 deletion include/geode/geometry/point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ namespace geode
struct AttributeLinearInterpolationImpl< Point< dimension > >
{
template < template < typename > class Attribute >
static Point< dimension > compute(
[[nodiscard]] static Point< dimension > compute(
const AttributeLinearInterpolation &interpolator,
const Attribute< Point< dimension > > &attribute )
{
Expand Down
126 changes: 102 additions & 24 deletions tests/basic/test-attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,14 @@ void test_int_variable_attribute( geode::AttributeManager& manager )
variable_attribute->set_value( 3, 3 );

const auto attribute = manager.find_attribute< int >( "int" );
OPENGEODE_EXCEPTION(
attribute->value( 3 ) == 3, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION(
attribute->value( 6 ) == 12, "[Test] Should be equal to 12" );
OPENGEODE_EXCEPTION( attribute->value( 3 ) == 3,
"[Test] Int variable value 3 should be equal to 3" );
OPENGEODE_EXCEPTION( attribute->value( 6 ) == 12,
"[Test] Int variable value 6 should be equal to 12" );

variable_attribute->set_value( 3, 5 );
OPENGEODE_EXCEPTION(
attribute->value( 3 ) == 5, "[Test] Should be equal to 5" );
OPENGEODE_EXCEPTION( attribute->value( 3 ) == 5,
"[Test] Int variable value 3 should be equal to 5" );
}

void test_foo_sparse_attribute( geode::AttributeManager& manager )
Expand All @@ -193,8 +193,8 @@ void test_foo_sparse_attribute( geode::AttributeManager& manager )
"[Test] Should be equal to 0" );
OPENGEODE_EXCEPTION( sparse_attribute->value( 3 ).double_ == 12.4,
"[Test] Should be equal to 12.4" );
OPENGEODE_EXCEPTION(
sparse_attribute->value( 3 ).int_ == 3, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION( sparse_attribute->value( 3 ).int_ == 3,
"[Test] Foo sparse value should be equal to 3" );
}

void test_double_sparse_attribute( geode::AttributeManager& manager )
Expand All @@ -210,10 +210,10 @@ void test_double_sparse_attribute( geode::AttributeManager& manager )
manager.interpolate_attribute_value( { { 1, 7 }, { 0.5, 0.3 } }, 4 );

auto attribute = manager.find_attribute< double >( "double" );
OPENGEODE_EXCEPTION(
attribute->value( 2 ) == 3, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION(
attribute->value( 3 ) == 3, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION( attribute->value( 2 ) == 3,
"[Test] Double sparse value 2 should be equal to 3" );
OPENGEODE_EXCEPTION( attribute->value( 3 ) == 3,
"[Test] Double sparse value 3 should be equal to 3" );
OPENGEODE_EXCEPTION(
attribute->value( 4 ) == 8.1, "[Test] Should be equal to 8.1" );
OPENGEODE_EXCEPTION(
Expand All @@ -226,6 +226,80 @@ void test_double_sparse_attribute( geode::AttributeManager& manager )
attribute->value( 3 ) == 5, "[Test] Should be equal to 5" );
}

void test_double_array_attribute( geode::AttributeManager& manager )
{
auto array_attribute =
manager.find_or_create_attribute< geode::VariableAttribute,
std::array< double, 3 > >(
"array_double_3", { { 10., 11., 12. } }, { true, true } );
OPENGEODE_EXCEPTION( array_attribute->default_value()[0] == 10.,
"[Test] Wrong default value" );
OPENGEODE_EXCEPTION( array_attribute->default_value()[1] == 11.,
"[Test] Wrong default value" );
OPENGEODE_EXCEPTION( array_attribute->default_value()[2] == 12.,
"[Test] Wrong default value" );
array_attribute->set_value( 3, { { 1., 2., 3. } } );
array_attribute->set_value( 7, { { 2., 5., 7. } } );
manager.assign_attribute_value( 3, 2 );
manager.interpolate_attribute_value( { { 1, 7 }, { 0.5, 0.3 } }, 4 );

auto attribute =
manager.find_attribute< std::array< double, 3 > >( "array_double_3" );
OPENGEODE_EXCEPTION( attribute->value( 2 )[0] == 1.,
"[Test] Value [2,0] Should be equal to 1., not ",
attribute->value( 2 )[0] );
OPENGEODE_EXCEPTION( attribute->value( 2 )[1] == 2.,
"[Test] Value [2,1] Should be equal to 2., not ",
attribute->value( 2 )[1] );
OPENGEODE_EXCEPTION( attribute->value( 2 )[2] == 3.,
"[Test] Value [2,2] Should be equal to 3., not ",
attribute->value( 2 )[2] );
OPENGEODE_EXCEPTION( attribute->value( 3 )[0] == 1.,
"[Test] Value [3,0] Should be equal to 1., not ",
attribute->value( 3 )[0] );
OPENGEODE_EXCEPTION( attribute->value( 3 )[1] == 2.,
"[Test] Value [3,1] Should be equal to 2., not ",
attribute->value( 3 )[1] );
OPENGEODE_EXCEPTION( attribute->value( 3 )[2] == 3.,
"[Test] Value [3,2] Should be equal to 3., not ",
attribute->value( 3 )[2] );
OPENGEODE_EXCEPTION( attribute->value( 4 )[0] == 5.6,
"[Test] Value [4,0] Should be equal to 5.6, not ",
attribute->value( 4 )[0] );
OPENGEODE_EXCEPTION( attribute->value( 4 )[1] == 7.,
"[Test] Value [4,1] Should be equal to 7., not ",
attribute->value( 4 )[1] );
OPENGEODE_EXCEPTION( attribute->value( 4 )[2] == 8.1,
"[Test] Value [4,2] Should be equal to 8.1, not ",
attribute->value( 4 )[2] );
OPENGEODE_EXCEPTION( attribute->value( 6 )[0] == 10.,
"[Test] Value [6,0] Should be equal to 10., not ",
attribute->value( 6 )[0] );
OPENGEODE_EXCEPTION( attribute->value( 6 )[1] == 11.,
"[Test] Value [6,1] Should be equal to 11., not ",
attribute->value( 6 )[1] );
OPENGEODE_EXCEPTION( attribute->value( 6 )[2] == 12.,
"[Test] Value [6,2] Should be equal to 12., not ",
attribute->value( 6 )[2] );
OPENGEODE_EXCEPTION( attribute->value( 7 )[0] == 2.,
"[Test] Value [7,0] Should be equal to 2., not ",
attribute->value( 7 )[0] );
OPENGEODE_EXCEPTION( attribute->value( 7 )[1] == 5.,
"[Test] Value [7,1] Should be equal to 5., not ",
attribute->value( 7 )[1] );
OPENGEODE_EXCEPTION( attribute->value( 7 )[2] == 7.,
"[Test] Value [7,2] Should be equal to 7., not ",
attribute->value( 7 )[2] );

array_attribute->set_value( 3, { 2., 5., 5. } );
OPENGEODE_EXCEPTION(
attribute->value( 3 )[0] == 2., "[Test] Should be equal to 2." );
OPENGEODE_EXCEPTION(
attribute->value( 3 )[1] == 5., "[Test] Should be equal to 5." );
OPENGEODE_EXCEPTION(
attribute->value( 3 )[2] == 5., "[Test] Should be equal to 5." );
}

void test_bool_variable_attribute( geode::AttributeManager& manager )
{
auto variable_attribute =
Expand Down Expand Up @@ -479,20 +553,23 @@ void test_permutation( geode::AttributeManager& manager )
manager.permute_elements( permutation );

const auto int_attribute = manager.find_attribute< int >( "int" );
OPENGEODE_EXCEPTION(
int_attribute->value( 3 ) == 12, "[Test] Should be equal to 12" );
OPENGEODE_EXCEPTION(
int_attribute->value( 0 ) == 5, "[Test] Should be equal to 5" );
OPENGEODE_EXCEPTION(
int_attribute->value( 8 ) == 5, "[Test] Should be equal to 5" );
OPENGEODE_EXCEPTION( int_attribute->value( 3 ) == 12,
"[Test] Attribute value 3 should be equal to 12" );
OPENGEODE_EXCEPTION( int_attribute->value( 0 ) == 5,
"[Test] Attribute value 0 should be equal to 5" );
OPENGEODE_EXCEPTION( int_attribute->value( 8 ) == 5,
"[Test] Attribute value 8 should be equal to 5" );

auto double_attribute = manager.find_attribute< double >( "double" );
OPENGEODE_EXCEPTION(
double_attribute->value( 2 ) == 12, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION(
double_attribute->value( 4 ) == 3, "[Test] Should be equal to 3" );
OPENGEODE_EXCEPTION(
double_attribute->value( 7 ) == 8.1, "[Test] Should be equal to 8.1" );
OPENGEODE_EXCEPTION( double_attribute->value( 2 ) == 12,
"[Test] Attribute value 2 should be equal to 3, not ",
double_attribute->value( 2 ) );
OPENGEODE_EXCEPTION( double_attribute->value( 4 ) == 3,
"[Test] Attribute value 4 should be equal to 3, not ",
double_attribute->value( 4 ) );
OPENGEODE_EXCEPTION( double_attribute->value( 7 ) == 8.1,
"[Test] Attribute value 7 should be equal to 8.1, not ",
double_attribute->value( 7 ) );
}

void test()
Expand Down Expand Up @@ -527,6 +604,7 @@ void test()
manager.resize( 10 );
OPENGEODE_EXCEPTION(
manager.nb_elements() == 10, "[Test] Manager should have 10 elements" );
test_double_array_attribute( manager );
manager.clear();
test_number_of_attributes( manager, 0 );
}
Expand Down
37 changes: 37 additions & 0 deletions tests/geometry/test-point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*
*/

#include <geode/basic/attribute_manager.hpp>
#include <geode/basic/logger.hpp>

#include <geode/geometry/point.hpp>
Expand Down Expand Up @@ -54,10 +55,46 @@ void test_operators()
OPENGEODE_EXCEPTION( answer / 2 == p, "[Test] Points should be equal" );
}

void test_interpolation()
{
geode::AttributeManager manager;
manager.resize( 10 );
auto attribute = manager.find_or_create_attribute< geode::VariableAttribute,
geode::Point< 3 > >(
"point_3", geode::Point3D{ { 10., 11., 12. } }, { false, true } );
OPENGEODE_EXCEPTION( attribute->default_value().value( 0 ) == 10.,
"[Test] Wrong default value" );
OPENGEODE_EXCEPTION( attribute->default_value().value( 1 ) == 11.,
"[Test] Wrong default value" );
OPENGEODE_EXCEPTION( attribute->default_value().value( 2 ) == 12.,
"[Test] Wrong default value" );
attribute->set_value( 3, geode::Point3D{ { 1., 2., 3. } } );
attribute->set_value( 7, geode::Point3D{ { 2., 5., 7. } } );
manager.interpolate_attribute_value( { { 1, 7 }, { 0.5, 0.3 } }, 4 );

OPENGEODE_EXCEPTION(
attribute->value( 3 ).inexact_equal( geode::Point3D{ { 1., 2., 3. } } ),
"[Test] Value 3 Should be equal to [ 1., 2., 3. ], not ",
attribute->value( 3 ).string() );
OPENGEODE_EXCEPTION( attribute->value( 4 ).inexact_equal(
geode::Point3D{ { 5.6, 7., 8.1 } } ),
"[Test] Value 4 Should be equal to [ 5.6, 7., 8.1 ], not ",
attribute->value( 4 ).string() );
OPENGEODE_EXCEPTION(
attribute->value( 6 ).inexact_equal( geode::Point3D{ { 10, 11, 12 } } ),
"[Test] Value 6 Should be equal to [ 10, 11, 12 ], not ",
attribute->value( 6 ).string() );
OPENGEODE_EXCEPTION(
attribute->value( 7 ).inexact_equal( geode::Point3D{ { 2., 5., 7. } } ),
"[Test] Value 7 Should be equal to [ 2., 5., 7. ], not ",
attribute->value( 7 ).string() );
}

void test()
{
test_comparison();
test_operators();
test_interpolation();
}

OPENGEODE_TEST( "point" )

0 comments on commit 42beb16

Please sign in to comment.