std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& interleavedArrays, const UnsignedInt stride) {
    CORRADE_ASSERT(stride != 0, "MeshTools::combineIndexArrays(): stride can't be zero", {});
    CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {});

    /* Hash map with index combinations, containing just indices into
       interleavedArrays vector, hashing and comparison is done using IndexHash
       and IndexEqual functors. Reserving more buckets than necessary (i.e. as
       if each combination was unique). */
    std::unordered_map<UnsignedInt, UnsignedInt, IndexHash, IndexEqual> indexCombinations(
        interleavedArrays.size()/stride,
        IndexHash(interleavedArrays, stride),
        IndexEqual(interleavedArrays, stride));

    /* Make the index combinations unique. Original indices into original
       `interleavedArrays` array were 0, 1, 2, 3, ..., `combinedIndices`
       contains new ones into new (shorter) `newInterleavedArrays` array. */
    std::vector<UnsignedInt> combinedIndices;
    combinedIndices.reserve(interleavedArrays.size()/stride);
    std::vector<UnsignedInt> newInterleavedArrays;
    for(std::size_t oldIndex = 0, end = interleavedArrays.size()/stride; oldIndex != end; ++oldIndex) {
        /* Try to insert new index combination to the map */
        const auto result = indexCombinations.emplace(oldIndex, indexCombinations.size());

        /* Add the (either new or already existing) index to resulting index array */
        combinedIndices.push_back(result.first->second);

        /* If this is new combination, copy it to new interleaved arrays */
        if(result.second) newInterleavedArrays.insert(newInterleavedArrays.end(),
            interleavedArrays.begin()+oldIndex*stride,
            interleavedArrays.begin()+(oldIndex+1)*stride);
    }

    CORRADE_INTERNAL_ASSERT(combinedIndices.size() == interleavedArrays.size()/stride &&
                            newInterleavedArrays.size() <= interleavedArrays.size());

    return {std::move(combinedIndices), std::move(newInterleavedArrays)};
}
Exemple #2
0
 explicit
 SpatialIndex(float epsilon) :
     _index(0u, IndexHash(epsilon), IndexEqual(epsilon))
 {
 }