Browse Source

MeshTools: removeDuplicatesIndexedInPlace() for type-erased indices.

Next step is a variant operating directly on a MeshData.
pull/445/head
Vladimír Vondruš 6 years ago
parent
commit
dec7904db1
  1. 12
      src/Magnum/MeshTools/RemoveDuplicates.cpp
  2. 32
      src/Magnum/MeshTools/RemoveDuplicates.h
  3. 126
      src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp

12
src/Magnum/MeshTools/RemoveDuplicates.cpp

@ -157,4 +157,16 @@ std::size_t removeDuplicatesIndexedInPlace(const Containers::StridedArrayView1D<
return removeDuplicatesIndexedInPlaceImplementation(indices, data);
}
std::size_t removeDuplicatesIndexedInPlace(const Containers::StridedArrayView2D<char>& indices, const Containers::StridedArrayView2D<char>& data) {
CORRADE_ASSERT(indices.isContiguous<1>(), "MeshTools::removeDuplicatesIndexedInPlace(): second index view dimension is not contiguous", {});
if(indices.size()[1] == 4)
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedInt>(indices), data);
else if(indices.size()[1] == 2)
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedShort>(indices), data);
else {
CORRADE_ASSERT(indices.size()[1] == 1, "MeshTools::removeDuplicatesIndexedInPlace(): expected index type size 1, 2 or 4 but got" << indices.size()[1], {});
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedByte>(indices), data);
}
}
}}

32
src/Magnum/MeshTools/RemoveDuplicates.h

@ -145,6 +145,17 @@ MAGNUM_MESHTOOLS_EXPORT std::size_t removeDuplicatesIndexedInPlace(const Contain
*/
MAGNUM_MESHTOOLS_EXPORT std::size_t removeDuplicatesIndexedInPlace(const Containers::StridedArrayView1D<UnsignedByte>& indices, const Containers::StridedArrayView2D<char>& data);
/**
@brief Remove duplicates from indexed data in-place on a type-erased index array
@m_since_latest
Expects that the second dimension of @p indices is contiguous and represents
the actual 1/2/4-byte index type. Based on its size then calls one of the
@ref removeDuplicatesIndexedInPlace(const Containers::StridedArrayView1D<UnsignedInt>&)
etc. overloads.
*/
MAGNUM_MESHTOOLS_EXPORT std::size_t removeDuplicatesIndexedInPlace(const Containers::StridedArrayView2D<char>& indices, const Containers::StridedArrayView2D<char>& data);
/**
@brief Remove duplicate floating-point vector data from given array in-place
@param[in,out] data Data array, duplicate items will be cut away with order
@ -273,6 +284,27 @@ template<class IndexType, class Vector> std::size_t removeDuplicatesIndexedInPla
return dataSize;
}
/**
@brief Remove duplicates from indexed data in-place on a type-erased index array
@m_since_latest
Expects that the second dimension of @p indices is contiguous and represents
the actual 1/2/4-byte index type. Based on its size then calls
@ref removeDuplicatesIndexedInPlace(const Containers::StridedArrayView1D<IndexType>&, const Containers::StridedArrayView1D<Vector>&, typename Vector::Type)
with a concrete index type.
*/
template<class Vector> std::size_t removeDuplicatesIndexedInPlace(const Containers::StridedArrayView2D<char>& indices, const Containers::StridedArrayView1D<Vector>& data, typename Vector::Type epsilon = Math::TypeTraits<typename Vector::Type>::epsilon()) {
CORRADE_ASSERT(indices.isContiguous<1>(), "MeshTools::removeDuplicatesIndexedInPlace(): second index view dimension is not contiguous", {});
if(indices.size()[1] == 4)
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedInt>(indices), data, epsilon);
else if(indices.size()[1] == 2)
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedShort>(indices), data, epsilon);
else {
CORRADE_ASSERT(indices.size()[1] == 1, "MeshTools::removeDuplicatesIndexedInPlace(): expected index type size 1, 2 or 4 but got" << indices.size()[1], {});
return removeDuplicatesIndexedInPlace(Containers::arrayCast<1, UnsignedByte>(indices), data, epsilon);
}
}
template<class Vector> std::pair<Containers::Array<UnsignedInt>, std::size_t> removeDuplicatesInPlace(const Containers::StridedArrayView1D<Vector>& data, typename Vector::Type epsilon) {
/* A trivial index array that'll be remapped and returned after */
Containers::Array<UnsignedInt> indices{Containers::NoInit, data.size()};

126
src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp

@ -43,6 +43,9 @@ struct RemoveDuplicatesTest: TestSuite::Tester {
void removeDuplicatesIndexedInPlaceSmallType();
void removeDuplicatesIndexedInPlaceEmptyIndices();
void removeDuplicatesIndexedInPlaceEmptyIndicesVertices();
template<class T> void removeDuplicatesIndexedInPlaceErased();
void removeDuplicatesIndexedInPlaceErasedNonContiguous();
void removeDuplicatesIndexedInPlaceErasedWrongIndexSize();
void removeDuplicatesFuzzyInPlace();
#ifdef MAGNUM_BUILD_DEPRECATED
@ -52,6 +55,9 @@ struct RemoveDuplicatesTest: TestSuite::Tester {
void removeDuplicatesFuzzyIndexedInPlaceSmallType();
void removeDuplicatesFuzzyIndexedInPlaceEmptyIndices();
void removeDuplicatesFuzzyIndexedInPlaceEmptyIndicesVertices();
template<class T> void removeDuplicatesFuzzyIndexedInPlaceErased();
void removeDuplicatesFuzzyIndexedInPlaceErasedNonContiguous();
void removeDuplicatesFuzzyIndexedInPlaceErasedWrongIndexSize();
/* this is additionally regression-tested in PrimitivesIcosphereTest */
};
@ -66,6 +72,11 @@ RemoveDuplicatesTest::RemoveDuplicatesTest() {
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceSmallType,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceEmptyIndices,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceEmptyIndicesVertices,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErased<UnsignedByte>,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErased<UnsignedShort>,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErased<UnsignedInt>,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErasedNonContiguous,
&RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErasedWrongIndexSize,
&RemoveDuplicatesTest::removeDuplicatesFuzzyInPlace,
#ifdef MAGNUM_BUILD_DEPRECATED
@ -76,7 +87,12 @@ RemoveDuplicatesTest::RemoveDuplicatesTest() {
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlace<UnsignedInt>,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceSmallType,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceEmptyIndices,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceEmptyIndicesVertices});
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceEmptyIndicesVertices,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErased<UnsignedByte>,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErased<UnsignedShort>,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErased<UnsignedInt>,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErasedNonContiguous,
&RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErasedWrongIndexSize});
}
void RemoveDuplicatesTest::removeDuplicates() {
@ -183,6 +199,57 @@ void RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceEmptyIndicesVertices()
Containers::StridedArrayView1D<UnsignedInt>{}, {}), 0);
}
template<class T> void RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErased() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
T indices[]{3, 2, 0, 1, 7, 6, 4, 2, 5, 0};
Int data[]{-15, 32, 24, -15, 15, 7541, 24, 32};
std::size_t count = MeshTools::removeDuplicatesIndexedInPlace(
Containers::arrayCast<2, char>(Containers::arrayView(indices)),
Containers::arrayCast<2, char>(Containers::arrayView(data)));
CORRADE_COMPARE_AS(Containers::arrayView(indices),
Containers::arrayView<T>({0, 2, 0, 1, 1, 2, 3, 2, 4, 0}),
TestSuite::Compare::Container);
CORRADE_COMPARE_AS(Containers::arrayView(data).prefix(count),
Containers::arrayView<Int>({-15, 32, 24, 15, 7541}),
TestSuite::Compare::Container);
}
void RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErasedNonContiguous() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
char indices[6*4]{};
Int data[1]{};
std::stringstream out;
Error redirectError{&out};
MeshTools::removeDuplicatesIndexedInPlace(
Containers::StridedArrayView2D<char>{indices, {6, 2}, {4, 2}},
Containers::arrayCast<2, char>(Containers::arrayView(data)));
CORRADE_COMPARE(out.str(),
"MeshTools::removeDuplicatesIndexedInPlace(): second index view dimension is not contiguous\n");
}
void RemoveDuplicatesTest::removeDuplicatesIndexedInPlaceErasedWrongIndexSize() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
char indices[6*3]{};
Int data[1]{};
std::stringstream out;
Error redirectError{&out};
MeshTools::removeDuplicatesIndexedInPlace(
Containers::StridedArrayView2D<char>{indices, {6, 3}},
Containers::arrayCast<2, char>(Containers::arrayView(data)));
CORRADE_COMPARE(out.str(),
"MeshTools::removeDuplicatesIndexedInPlace(): expected index type size 1, 2 or 4 but got 3\n");
}
void RemoveDuplicatesTest::removeDuplicatesFuzzyInPlace() {
/* Numbers with distance 1 should be merged, numbers with distance 2 should
be kept. Testing both even-odd and odd-even sequence to verify that
@ -284,6 +351,63 @@ void RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceEmptyIndicesVertic
CORRADE_COMPARE((MeshTools::removeDuplicatesIndexedInPlace<UnsignedInt, Vector2i>({}, {}, 2)), 0);
}
template<class T> void RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErased() {
setTestCaseTemplateName(Math::TypeTraits<T>::name());
/* Same as above, but with an explicit index buffer */
T indices[]{3, 2, 0, 1, 2, 3};
Vector2i data[]{
{1, 0},
{2, 1},
{0, 4},
{1, 5}
};
std::size_t count = MeshTools::removeDuplicatesIndexedInPlace(
Containers::arrayCast<2, char>(Containers::arrayView(indices)),
Containers::stridedArrayView(data), 2);
CORRADE_COMPARE_AS(Containers::arrayView(indices),
Containers::arrayView<T>({1, 1, 0, 0, 1, 1}),
TestSuite::Compare::Container);
CORRADE_COMPARE_AS(Containers::arrayView(data).prefix(count),
Containers::arrayView<Vector2i>({{1, 0}, {0, 4}}),
TestSuite::Compare::Container);
}
void RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErasedNonContiguous() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
char indices[6*4]{};
Vector2i data[1];
std::stringstream out;
Error redirectError{&out};
MeshTools::removeDuplicatesIndexedInPlace(
Containers::StridedArrayView2D<char>{indices, {6, 2}, {4, 2}},
Containers::stridedArrayView(data), 2);
CORRADE_COMPARE(out.str(),
"MeshTools::removeDuplicatesIndexedInPlace(): second index view dimension is not contiguous\n");
}
void RemoveDuplicatesTest::removeDuplicatesFuzzyIndexedInPlaceErasedWrongIndexSize() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
char indices[6*3]{};
Vector2i data[1];
std::stringstream out;
Error redirectError{&out};
MeshTools::removeDuplicatesIndexedInPlace(
Containers::StridedArrayView2D<char>{indices, {6, 3}},
Containers::stridedArrayView(data), 2);
CORRADE_COMPARE(out.str(),
"MeshTools::removeDuplicatesIndexedInPlace(): expected index type size 1, 2 or 4 but got 3\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::MeshTools::Test::RemoveDuplicatesTest)

Loading…
Cancel
Save