Commit 00190b40 authored by Michaël Roynard's avatar Michaël Roynard
Browse files

Fix clip view

parent 6966d55d
......@@ -2,8 +2,13 @@
#include <mln/core/image/image.hpp>
#include <mln/core/image/view/adaptor.hpp>
#include <mln/core/rangev3/view/filter.hpp>
#include <mln/core/rangev3/view/remove_if.hpp>
#include <mln/core/rangev3/view/transform.hpp>
#include <range/v3/algorithm/set_algorithm.hpp>
#include <range/v3/empty.hpp>
#include <type_traits>
......@@ -13,7 +18,7 @@ namespace mln
template <class I, class D>
class clip_view : public image_adaptor<I>, public experimental::Image<clip_view<I, D>>
{
D m_domain;
D m_subdomain;
public:
/// Type definitions
......@@ -23,6 +28,7 @@ namespace mln
using typename clip_view::image_adaptor::reference;
using typename clip_view::image_adaptor::value_type;
using domain_type = D;
/// \}
static_assert(std::is_convertible_v<::ranges::range_value_t<D>, point_type>,
"Domain value type must be convertible to image point type.");
......@@ -45,24 +51,24 @@ namespace mln
/// \}
public:
clip_view(I ima, D domain)
clip_view(I ima, D subdomain)
: clip_view::image_adaptor{std::move(ima)}
, m_domain{std::move(domain)}
, m_subdomain{std::move(subdomain)}
{
// FIXME: possibly assert that domain is included in ima.domain()
mln_precondition(::ranges::includes(std::move(ima).domain(), std::move(subdomain)));
}
template <class I2, class D2>
clip_view(const clip_view<I2, D2>& other, mln::init)
: clip_view::image_adaptor{static_cast<I>(other.base().template ch_value<value_type>())}
, m_domain{other.m_domain}
, m_subdomain{other.m_subdomain}
{
}
template <class I2, class D2>
clip_view(const clip_view<I2, D2>& other, const value_type& v)
: clip_view::image_adaptor{static_cast<I>((other.base().template ch_value<value_type>()).init(v))}
, m_domain{other.m_domain}
, m_subdomain{other.m_subdomain}
{
}
......@@ -74,18 +80,18 @@ namespace mln
return {*this};
}
const D& domain() const { return this->m_domain; }
domain_type domain() const { return m_subdomain; }
auto new_values()
{
auto g = [this](point_type p) -> reference { return this->base().at(p); };
return mln::ranges::view::transform(this->m_domain, g);
return mln::ranges::view::transform(m_subdomain, g);
}
auto new_pixels()
{
auto g = [this](point_type p) -> new_pixel_type { return this->base().new_pixel_at(p); };
return mln::ranges::view::transform(this->m_domain, g);
return mln::ranges::view::transform(m_subdomain, g);
}
......@@ -104,7 +110,7 @@ namespace mln
template <typename Ret = reference>
std::enable_if_t<accessible::value, Ret> operator()(point_type p)
{
mln_precondition(m_domain.has(p));
mln_precondition(domain().has(p));
mln_precondition(this->base().domain().has(p));
return this->base()(p);
}
......@@ -116,7 +122,7 @@ namespace mln
template <typename Ret = new_pixel_type>
std::enable_if_t<accessible::value, Ret> new_pixel(point_type p)
{
mln_precondition(m_domain.has(p));
mln_precondition(domain().has(p));
mln_precondition(this->base().domain().has(p));
return this->base().new_pixel(p);
}
......@@ -133,8 +139,6 @@ namespace mln
template <typename dummy = I>
std::enable_if_t<(indexable::value && accessible::value), image_index_t<dummy>> index_of_point(point_type p) const
{
mln_precondition(m_domain.has(p));
mln_precondition(this->base().domain().has(p));
return this->base().index_of_point(p);
}
......
......@@ -7,7 +7,6 @@
#include <mln/core/rangev3/view/remove_if.hpp>
#include <range/v3/empty.hpp>
#include <range/v3/size.hpp>
#include <range/v3/utility/functional.hpp>
#include <type_traits>
......@@ -135,7 +134,7 @@ namespace mln
template <typename Ret = reference>
std::enable_if_t<accessible::value, Ret> operator()(point_type p)
{
mln_precondition(this->base().domain().has(p));
mln_precondition(domain().has(p));
mln_precondition(std::invoke(f, this->base()(p)));
return this->base()(p);
}
......@@ -147,7 +146,7 @@ namespace mln
template <typename Ret = new_pixel_type>
std::enable_if_t<accessible::value, Ret> new_pixel(point_type p)
{
mln_precondition(this->base().domain().has(p));
mln_precondition(domain().has(p));
mln_precondition(std::invoke(f, this->base().at(p)));
return this->base().new_pixel(p);
}
......
......@@ -2,13 +2,11 @@
#include <mln/core/algorithm/fill.hpp>
#include <mln/core/algorithm/iota.hpp>
#include <mln/core/image/image2d.hpp>
#include <mln/core/image/private/image_operators.hpp>
#include <mln/core/image/private/where.hpp>
#include <mln/core/image/view/clip.hpp>
#include <mln/io/imprint.hpp>
#include <gtest/gtest.h>
namespace mln
{
......@@ -73,59 +71,6 @@ TEST(Core, SubImage_sub_domain_with_box)
static_assert(std::is_same<decltype(ima | box2d()), image2d<int>>::value);
}
TEST(Core, SubImage_sub_domain)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<int> ima(5, 5);
{
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42} //
};
iota(ima, 0);
mln::fill(view::clip(ima, experimental::where(ima > 10)), 42);
ASSERT_TRUE(all_of(ima == ref));
}
{
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 11, 12, 13, 14}, //
{15, 16, 17, 18, 19}, //
{20, 42, 42, 42, 42} //
};
iota(ima, 0);
// FIXME:
// here where ima < 20 isn't a sub domain of ima > 10.
// Should it be so ? Or should we compute the intersection of both ?
// TODO: fix clip_view
// mln::fill(view::clip(view::clip(ima, experimental::where(ima > 10)), experimental::where(ima < 20)), 42);
// ASSERT_TRUE(all_of(ima == ref));
}
{
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42}, //
{20, 21, 22, 23, 24} //
};
iota(ima, 0);
mln::fill(view::clip(ima, experimental::where(ima > 10 && ima < 20)), 42);
ASSERT_TRUE(all_of(ima == ref));
}
}
// This should throw because
// where(ima < 20) is not included in where(ima > 10)
// This test is disabled because Boost Unit Test does not
......
#include <mln/core/algorithm/all_of.hpp>
#include <mln/core/algorithm/fill.hpp>
#include <mln/core/algorithm/iota.hpp>
#include <mln/core/concept/new/archetype/image.hpp>
#include <mln/core/image/image2d.hpp>
#include <mln/core/image/private/image_operators.hpp>
#include <mln/core/image/private/where.hpp>
#include <mln/core/image/view/clip.hpp>
#include <fixtures/ImageCompare/image_compare.hpp>
......@@ -138,6 +140,66 @@ TEST(View, clip_other_a_box2d)
ASSERT_TRUE(mln::all_of(ima == ref));
}
TEST(Core, Clip_where)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<int> ima(5, 5);
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42} //
};
mln::iota(ima, 0);
mln::fill(view::clip(ima, experimental::where(ima > 10)), 42);
ASSERT_TRUE(all_of(ima == ref));
}
TEST(Core, Clip_wherex2_joints)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<int> ima(5, 5);
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 11, 12, 13, 14}, //
{15, 16, 17, 18, 19}, //
{20, 42, 42, 42, 42} //
};
mln::iota(ima, 0);
mln::fill(view::clip(view::clip(ima, experimental::where(ima > 10)), experimental::where(ima > 20)), 42);
ASSERT_TRUE(all_of(ima == ref));
}
TEST(Core, Clip_where_and)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<int> ima(5, 5);
image2d<int> ref = {
{0, 1, 2, 3, 4}, //
{5, 6, 7, 8, 9}, //
{10, 42, 42, 42, 42}, //
{42, 42, 42, 42, 42}, //
{20, 21, 22, 23, 24} //
};
mln::iota(ima, 0);
mln::fill(view::clip(ima, experimental::where(ima > 10 && ima < 20)), 42);
ASSERT_TRUE(all_of(ima == ref));
}
PYLENE_CONCEPT_TS_ASSERT(
(mln::concepts::AccessibleImage<mln::clip_view<mln::archetypes::AccessibleImage, mln::archetypes::Domain>>), "");
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment