Browse Source

MeshTools: make a version of duplicate() not dependent on std::vector.

Provide a version taking StridedArrayView instead, taking an arbitrary
view and also arbitrary index type. Also introduce duplicateInto() which
doesn't even allocate, but rather writes the output to pre-existing
location.
pull/229/head
Vladimír Vondruš 7 years ago
parent
commit
61397afc31
  1. 5
      doc/changelog.dox
  2. 58
      src/Magnum/MeshTools/Duplicate.h
  3. 1
      src/Magnum/MeshTools/Test/CMakeLists.txt
  4. 64
      src/Magnum/MeshTools/Test/DuplicateTest.cpp

5
doc/changelog.dox

@ -133,6 +133,11 @@ See also:
@ref Math::UnderlyingTypeOf utility @ref Math::UnderlyingTypeOf utility
- Added batch versions of @ref Math::isInf() and @ref Math::isNan() - Added batch versions of @ref Math::isInf() and @ref Math::isNan()
@subsubsection changelog-latest-new-meshtools MeshTools library
- @ref MeshTools::duplicateInto() alternative to @ref MeshTools::duplicate()
that writes the output to an existing location
@subsubsection changelog-latest-new-platform Platform libraries @subsubsection changelog-latest-new-platform Platform libraries
- @ref Platform::Sdl2Application and @ref Platform::GlfwApplication are now - @ref Platform::Sdl2Application and @ref Platform::GlfwApplication are now

58
src/Magnum/MeshTools/Duplicate.h

@ -26,30 +26,70 @@
*/ */
/** @file /** @file
* @brief Function @ref Magnum::MeshTools::duplicate() * @brief Function @ref Magnum::MeshTools::duplicate(), @ref Magnum::MeshTools::duplicateInto()
*/ */
#include <vector> #include <vector>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include "Magnum/Types.h" #include "Magnum/Magnum.h"
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
#ifndef DOXYGEN_GENERATING_OUTPUT
/* Fwdecl so we can have duplicateInto() ordered after duplicate() */
template<class IndexType, class T> void duplicateInto(const Containers::StridedArrayView1D<const IndexType>&, const Containers::StridedArrayView1D<const T>&, const Containers::StridedArrayView1D<T>&);
#endif
/** /**
@brief Duplicate data using index array @brief Duplicate data using given index array
Converts indexed array to non-indexed, for example data `{a, b, c, d}` with Converts indexed array to non-indexed, for example data `{a, b, c, d}` with
index array `{1, 1, 0, 3, 2, 2}` will be converted to `{b, b, a, d, c, c}`. index array `{1, 1, 0, 3, 2, 2}` will be converted to `{b, b, a, d, c, c}`.
The resulting array size is the same as size of @p indices, expects that all
indices are in range for the @p data array.
If you want to fill an existing memory (or, for example a @ref std::vector),
use @ref duplicateInto().
@see @ref removeDuplicates(), @ref combineIndexedArrays() @see @ref removeDuplicates(), @ref combineIndexedArrays()
*/ */
template<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& data) { template<class IndexType, class T> Containers::Array<T> duplicate(const Containers::StridedArrayView1D<const IndexType>& indices, const Containers::StridedArrayView1D<const T>& data) {
std::vector<T> out; Containers::Array<T> out{Containers::NoInit, indices.size()};
out.reserve(indices.size()); duplicateInto<IndexType, T>(indices, data, out);
for(const UnsignedInt index: indices) { return out;
CORRADE_ASSERT(index < data.size(), "MeshTools::duplicate(): index out of range", out); }
out.push_back(data[index]);
/**
@brief Duplicate data using an index array into given output array
@param[in] indices Index array to use
@param[in] data Input data
@param[out] out Where to store the output
A variant of @ref duplicate() that fills existing memory instead of allocating
a new array.
*/
template<class IndexType, class T> void duplicateInto(const Containers::StridedArrayView1D<const IndexType>& indices, const Containers::StridedArrayView1D<const T>& data, const Containers::StridedArrayView1D<T>& out) {
CORRADE_ASSERT(out.size() == indices.size(),
"MeshTools::duplicateInto(): bad output size, expected" << indices.size() << "but got" << out.size(), );
for(std::size_t i = 0; i != indices.size(); ++i) {
const std::size_t index = indices[i];
CORRADE_ASSERT(index < data.size(), "MeshTools::duplicateInto(): index" << index << "out of bounds for" << data.size() << "elements", );
out[i] = data[index];
} }
}
/**
@brief Duplicate data using given index array
Like @ref duplicate(const Containers::StridedArrayView1D<const IndexType>&, const Containers::StridedArrayView1D<const T>&),
but putting the result into a @ref std::vector.
*/
template<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& data) {
std::vector<T> out(indices.size());
duplicateInto<UnsignedInt, T>(indices, data, out);
return out; return out;
} }

1
src/Magnum/MeshTools/Test/CMakeLists.txt

@ -37,6 +37,7 @@ corrade_add_test(MeshToolsTransformTest TransformTest.cpp LIBRARIES MagnumMeshTo
# Graceful assert for testing # Graceful assert for testing
set_property(TARGET set_property(TARGET
MeshToolsCombineIndexedArraysTest MeshToolsCombineIndexedArraysTest
MeshToolsDuplicateTest
MeshToolsInterleaveTest MeshToolsInterleaveTest
MeshToolsSubdivideTest MeshToolsSubdivideTest
APPEND PROPERTY COMPILE_DEFINITIONS "CORRADE_GRACEFUL_ASSERT") APPEND PROPERTY COMPILE_DEFINITIONS "CORRADE_GRACEFUL_ASSERT")

64
src/Magnum/MeshTools/Test/DuplicateTest.cpp

@ -23,7 +23,10 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#include <sstream>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/Duplicate.h"
@ -34,15 +37,72 @@ struct DuplicateTest: TestSuite::Tester {
explicit DuplicateTest(); explicit DuplicateTest();
void duplicate(); void duplicate();
void duplicateOutOfBounds();
void duplicateStl();
void duplicateInto();
void duplicateIntoWrongSize();
}; };
DuplicateTest::DuplicateTest() { DuplicateTest::DuplicateTest() {
addTests({&DuplicateTest::duplicate}); addTests({&DuplicateTest::duplicate,
&DuplicateTest::duplicateOutOfBounds,
&DuplicateTest::duplicateStl,
&DuplicateTest::duplicateInto,
&DuplicateTest::duplicateIntoWrongSize});
} }
void DuplicateTest::duplicate() { void DuplicateTest::duplicate() {
constexpr UnsignedByte indices[]{1, 1, 0, 3, 2, 2};
constexpr Int data[]{-7, 35, 12, -18};
CORRADE_COMPARE_AS((MeshTools::duplicate<UnsignedByte, Int>(indices, data)),
(Containers::Array<Int>{Containers::InPlaceInit, {
35, 35, -7, -18, 12, 12
}}), TestSuite::Compare::Container);
}
void DuplicateTest::duplicateOutOfBounds() {
constexpr UnsignedByte indices[]{1, 1, 0, 4, 2, 2};
constexpr Int data[]{-7, 35, 12, -18};
std::ostringstream out;
Error redirectError{&out};
MeshTools::duplicate<UnsignedByte, Int>(indices, data);
CORRADE_COMPARE(out.str(),
"MeshTools::duplicateInto(): index 4 out of bounds for 4 elements\n");
}
void DuplicateTest::duplicateStl() {
CORRADE_COMPARE(MeshTools::duplicate({1, 1, 0, 3, 2, 2}, std::vector<int>{-7, 35, 12, -18}), CORRADE_COMPARE(MeshTools::duplicate({1, 1, 0, 3, 2, 2}, std::vector<int>{-7, 35, 12, -18}),
(std::vector<Int>{35, 35, -7, -18, 12, 12})); (std::vector<Int>{35, 35, -7, -18, 12, 12}));
}
void DuplicateTest::duplicateInto() {
constexpr UnsignedByte indices[]{1, 1, 0, 3, 2, 2};
constexpr Int data[]{-7, 35, 12, -18};
Int output[6];
MeshTools::duplicateInto<UnsignedByte, Int>(indices, data, output);
CORRADE_COMPARE_AS(Containers::arrayView<const Int>(output),
(Containers::Array<Int>{Containers::InPlaceInit, {
35, 35, -7, -18, 12, 12
}}), TestSuite::Compare::Container);
}
void DuplicateTest::duplicateIntoWrongSize() {
constexpr UnsignedByte indices[]{1, 1, 0, 3, 2, 2};
constexpr Int data[]{-7, 35, 12, -18};
Int output[5];
std::ostringstream out;
Error redirectError{&out};
MeshTools::duplicateInto<UnsignedByte, Int>(indices, data, output);
CORRADE_COMPARE(out.str(),
"MeshTools::duplicateInto(): bad output size, expected 6 but got 5\n");
} }
}}}} }}}}

Loading…
Cancel
Save