| 771 | //------------------------------------------------------------------------------ |
| 772 | template <typename U> |
| 773 | void SampleProminentValues(std::vector<std::vector<vtkVariant>>& uniques, vtkIdType maxId, int nc, |
| 774 | vtkIdType nt, int blockSize, vtkIdType numberOfBlocks, U* ptr, unsigned int maxDiscreteValues) |
| 775 | { |
| 776 | std::vector<std::set<U, CompareWithNaN<U>>> typeSpecificUniques; |
| 777 | std::set<std::vector<U>> typeSpecificUniqueTuples; |
| 778 | typeSpecificUniques.resize(nc); |
| 779 | // I. Accumulate samples for all components plus the tuple, |
| 780 | // either for the full array or a random subset. |
| 781 | if (numberOfBlocks * blockSize > maxId / 2) |
| 782 | { // Awwww, just do the whole array already! |
| 783 | AccumulateSampleValues( |
| 784 | ptr, nc, 0, nt, typeSpecificUniques, typeSpecificUniqueTuples, maxDiscreteValues); |
| 785 | } |
| 786 | else |
| 787 | { // Choose random blocks |
| 788 | vtkNew<vtkMinimalStandardRandomSequence> seq; |
| 789 | // test different blocks each time we're called: |
| 790 | seq->SetSeed(static_cast<int>(seq->GetMTime()) ^ 0xdeadbeef); |
| 791 | vtkIdType totalBlockCount = nt / blockSize + (nt % blockSize ? 1 : 0); |
| 792 | std::set<vtkIdType> startTuples; |
| 793 | // Sort the list of blocks we'll search to maintain cache coherence. |
| 794 | for (int i = 0; i < numberOfBlocks; ++i, seq->Next()) |
| 795 | { |
| 796 | vtkIdType startTuple = static_cast<vtkIdType>(seq->GetValue() * totalBlockCount) * blockSize; |
| 797 | startTuples.insert(startTuple); |
| 798 | } |
| 799 | // Now iterate over the blocks, accumulating unique values and tuples. |
| 800 | std::set<vtkIdType>::iterator blkIt; |
| 801 | for (blkIt = startTuples.begin(); blkIt != startTuples.end(); ++blkIt) |
| 802 | { |
| 803 | vtkIdType startTuple = *blkIt; |
| 804 | vtkIdType endTuple = startTuple + blockSize; |
| 805 | endTuple = endTuple < nt ? endTuple : nt; |
| 806 | bool endEarly = AccumulateSampleValues(ptr, nc, startTuple, endTuple, typeSpecificUniques, |
| 807 | typeSpecificUniqueTuples, maxDiscreteValues); |
| 808 | if (endEarly) |
| 809 | break; |
| 810 | } |
| 811 | } |
| 812 | |
| 813 | // II. Convert type-specific sets of unique values into non-type-specific |
| 814 | // vectors of vtkVariants for storage in array information. |
| 815 | |
| 816 | // Handle per-component uniques first |
| 817 | for (int i = 0; i < nc; ++i) |
| 818 | { |
| 819 | std::back_insert_iterator<std::vector<vtkVariant>> bi(uniques[i]); |
| 820 | std::copy(typeSpecificUniques[i].begin(), typeSpecificUniques[i].end(), bi); |
| 821 | } |
| 822 | |
| 823 | // Now squash any tuple-wide uniques into |
| 824 | // the final entry of the outer vector. |
| 825 | typename std::set<std::vector<U>>::iterator si; |
| 826 | for (si = typeSpecificUniqueTuples.begin(); si != typeSpecificUniqueTuples.end(); ++si) |
| 827 | { |
| 828 | std::back_insert_iterator<std::vector<vtkVariant>> bi(uniques[nc]); |
| 829 | std::copy(si->begin(), si->end(), bi); |
| 830 | } |