From 70e5606afeda2177d83829f0be6ecca43cbe3466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 19 May 2020 20:31:54 +0200 Subject: [PATCH] MeshTools: add removeDuplicatesFuzzyInPlaceInto(). I need a variant of removeDuplicatesFuzzyInPlace() that doesn't allocate the output array but instead puts the data into a pre-existing location. The discrete / non-fuzzy variant had this already, but this one not. --- src/Magnum/MeshTools/RemoveDuplicates.h | 36 +++++++++++++++---- .../MeshTools/Test/RemoveDuplicatesTest.cpp | 17 +++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/Magnum/MeshTools/RemoveDuplicates.h b/src/Magnum/MeshTools/RemoveDuplicates.h index 99478cb95..ceb770c4b 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.h +++ b/src/Magnum/MeshTools/RemoveDuplicates.h @@ -80,7 +80,7 @@ an index array pointing to original data locations. MAGNUM_MESHTOOLS_EXPORT std::pair, std::size_t> removeDuplicatesInPlace(const Containers::StridedArrayView2D& data); /** -@brief Remove duplicate data from given array in-place +@brief Remove duplicate data from given array in-place into given output index array @param[in,out] data Data array, duplicate items will be cut away with order preserved @param[out] indices Where to put the resulting index array @@ -107,7 +107,7 @@ returns an index array pointing to original data locations. MAGNUM_MESHTOOLS_EXPORT std::pair, std::size_t> removeDuplicates(const Containers::StridedArrayView2D& data); /** -@brief Remove duplicate data from given array +@brief Remove duplicate data from given array into given output index array @param[in] data Data array @param[out] indices Where to put the resulting index array @return Count of unique items in the original @p data array @@ -183,6 +183,21 @@ back into a single one using @ref combineIndexedAttributes(). */ template std::pair, std::size_t> removeDuplicatesFuzzyInPlace(const Containers::StridedArrayView1D& data, typename Vector::Type epsilon = Math::TypeTraits::epsilon()); +/** +@brief Remove duplicate data from given array using fuzzy comparison in-place into given output index array +@param[in,out] data Data array, duplicate items will be cut away with order + preserved +@param[out] indices Where to put the resulting index array +@param[in] epsilon Epsilon value, data closer than this distance will be + melt together +@return Size of unique prefix in the cleaned up @p data array +@m_since_latest + +Same as above, except that the index array is not allocated but put into +@p indices instead. Expects that @p indices has the same size as @p data. +*/ +template std::size_t removeDuplicatesFuzzyInPlaceInto(const Containers::StridedArrayView1D& data, const Containers::StridedArrayView1D& indices, typename Vector::Type epsilon = Math::TypeTraits::epsilon()); + #ifdef MAGNUM_BUILD_DEPRECATED /** @brief Remove duplicate data from a STL vector using fuzzy comparison in-place @@ -336,11 +351,19 @@ data. */ MAGNUM_MESHTOOLS_EXPORT Trade::MeshData removeDuplicates(Trade::MeshData&& data); -template std::pair, std::size_t> removeDuplicatesFuzzyInPlace(const Containers::StridedArrayView1D& data, typename Vector::Type epsilon) { - /* A trivial index array that'll be remapped and returned after */ - Containers::Array indices{Containers::NoInit, data.size()}; +template std::size_t removeDuplicatesFuzzyInPlaceInto(const Containers::StridedArrayView1D& data, const Containers::StridedArrayView1D& indices, typename Vector::Type epsilon) { + CORRADE_ASSERT(indices.size() == data.size(), + "MeshTools::removeDuplicatesFuzzyInPlaceInto(): output index array has" << indices.size() << "elements but expected" << data.size(), {}); + + /* A trivial index array that'll be remapped */ std::iota(indices.begin(), indices.end(), 0); const std::size_t size = removeDuplicatesFuzzyIndexedInPlace(Containers::stridedArrayView(indices), data, epsilon); + return size; +} + +template std::pair, std::size_t> removeDuplicatesFuzzyInPlace(const Containers::StridedArrayView1D& data, typename Vector::Type epsilon) { + Containers::Array indices{Containers::NoInit, data.size()}; + const std::size_t size = removeDuplicatesFuzzyInPlaceInto(data, indices, epsilon); return {std::move(indices), size}; } @@ -348,8 +371,7 @@ template std::pair, std::size_t> re template std::vector removeDuplicates(std::vector& data, typename Vector::Type epsilon) { /* A trivial index array that'll be remapped and returned after */ std::vector indices(data.size()); - std::iota(indices.begin(), indices.end(), 0); - const std::size_t size = removeDuplicatesFuzzyIndexedInPlace(Containers::stridedArrayView(indices), Containers::stridedArrayView(data), epsilon); + const std::size_t size = removeDuplicatesFuzzyInPlaceInto(Containers::stridedArrayView(data), Containers::stridedArrayView(indices), epsilon); data.resize(size); return indices; } diff --git a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp index 31f36632c..c20426086 100644 --- a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp +++ b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp @@ -49,6 +49,7 @@ struct RemoveDuplicatesTest: TestSuite::Tester { void removeDuplicatesIndexedInPlaceErasedWrongIndexSize(); void removeDuplicatesFuzzyInPlace(); + void removeDuplicatesFuzzyInPlaceIntoWrongOutputSize(); #ifdef MAGNUM_BUILD_DEPRECATED void removeDuplicatesFuzzyStl(); #endif @@ -91,6 +92,7 @@ RemoveDuplicatesTest::RemoveDuplicatesTest() { &RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErasedWrongIndexSize, &RemoveDuplicatesTest::removeDuplicatesFuzzyInPlace, + &RemoveDuplicatesTest::removeDuplicatesFuzzyInPlaceIntoWrongOutputSize, #ifdef MAGNUM_BUILD_DEPRECATED &RemoveDuplicatesTest::removeDuplicatesFuzzyStl, #endif @@ -287,6 +289,21 @@ void RemoveDuplicatesTest::removeDuplicatesFuzzyInPlace() { TestSuite::Compare::Container); } +void RemoveDuplicatesTest::removeDuplicatesFuzzyInPlaceIntoWrongOutputSize() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + Vector2 data[8]{}; + UnsignedInt output[7]; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::removeDuplicatesFuzzyInPlaceInto(Containers::stridedArrayView(data), output); + CORRADE_COMPARE(out.str(), + "MeshTools::removeDuplicatesFuzzyInPlaceInto(): output index array has 7 elements but expected 8\n"); +} + #ifdef MAGNUM_BUILD_DEPRECATED void RemoveDuplicatesTest::removeDuplicatesFuzzyStl() { /* Same but with implicit bloat. HEH HEH */