#ifndef CT_SCALARMINMAXMANAGER_H #define CT_SCALARMINMAXMANAGER_H #include #include template class CT_ScalarMinMaxManager { public: CT_ScalarMinMaxManager() { } ~CT_ScalarMinMaxManager() { for(const Backup* backup : mMinMaxByMask) { qDeleteAll(backup->mMinMaxAttributes.begin(), backup->mMinMaxAttributes.end()); delete backup; } } template void registerAttribute(ATT* attribute, SCALART min, SCALART max) { Backup* globalBackup = mMinMaxByMask.value(attribute->mask(), nullptr); if(globalBackup == nullptr) { globalBackup = new BackupT(min, max); mMinMaxByMask.insert(attribute->mask(), globalBackup); } else { BackupT* globalBackupCasted = static_cast*>(globalBackup); globalBackupCasted->mMin = qMin(globalBackupCasted->mMin, min); globalBackupCasted->mMax = qMax(globalBackupCasted->mMax, max); } globalBackup->mMinMaxAttributes.insert(attribute, new BackupT(min, max)); } template void updateAttribute(ATT* attribute, SCALART min, SCALART max) { Backup* globalBackup = mMinMaxByMask.value(attribute->mask(), nullptr); if(globalBackup == nullptr) return; Backup* attBackup = globalBackup->mMinMaxAttributes.value(attribute, nullptr); if(attBackup == nullptr) return; // update the local static_cast*>(attBackup)->mMin = min; static_cast*>(attBackup)->mMax = max; // update the global BackupT* globalBackupCasted = static_cast*>(globalBackup); globalBackupCasted->mMin = min; globalBackupCasted->mMax = max; for(const Backup* backup : globalBackupCasted->mMinMaxAttributes) { const BackupT* casted = static_cast*>(backup); globalBackupCasted->mMin = qMin(globalBackupCasted->mMin, casted->mMin); globalBackupCasted->mMax = qMax(globalBackupCasted->mMax, casted->mMax); } } template void unregisterAttribute(ATT* attribute) { Backup* globalBackup = mMinMaxByMask.value(attribute->mask(), nullptr); if(globalBackup == nullptr) return; delete globalBackup->mMinMaxAttributes.take(attribute); if(globalBackup->mMinMaxAttributes.isEmpty()) { delete mMinMaxByMask.take(attribute->mask()); return; } BackupT* firstAttBackupCasted = static_cast*>(globalBackup->mMinMaxAttributes.begin().value()); // update the global BackupT* globalBackupCasted = static_cast*>(globalBackup); globalBackupCasted->mMin = firstAttBackupCasted->mMin; globalBackupCasted->mMax = firstAttBackupCasted->mMax; for(const Backup* backup : globalBackupCasted->mMinMaxAttributes) { const BackupT* casted = static_cast*>(backup); globalBackupCasted->mMin = qMin(globalBackupCasted->mMin, casted->mMin); globalBackupCasted->mMax = qMax(globalBackupCasted->mMax, casted->mMax); } } template SCALART min(const ATT* attribute) const { Backup* globalBackup = mMinMaxByMask.value(attribute->mask(), nullptr); if(globalBackup == nullptr) return SCALART(); Backup* attBackup = globalBackup->mMinMaxAttributes.value(attribute, nullptr); if(attBackup == nullptr) return SCALART(); return static_cast*>(attBackup)->mMin; } template SCALART max(const ATT* attribute) const { Backup* globalBackup = mMinMaxByMask.value(attribute->mask(), nullptr); if(globalBackup == nullptr) return SCALART(); Backup* attBackup = globalBackup->mMinMaxAttributes.value(attribute, nullptr); if(attBackup == nullptr) return SCALART(); return static_cast*>(attBackup)->mMax; } static void InitMinMax(SCALAR& min, SCALAR& max) { InternalInitMinMaxIfBool(min, max, std::integral_constant::value>()); } private: class Backup { public: virtual ~Backup() {} QHash mMinMaxAttributes; }; template class BackupT : public Backup { public: BackupT(SCALART min, SCALART max) : mMin(min), mMax(max) {} SCALART mMin; SCALART mMax; }; QHash mMinMaxByMask; static void InternalInitMinMaxIfBool(SCALAR& min, SCALAR& max, std::true_type) { min = true; max = false; } static void InternalInitMinMaxIfBool(SCALAR& min, SCALAR& max, std::false_type) { InternalInitMinMax(min, max, std::integral_constant::is_signed>()); } static void InternalInitMinMax(SCALAR& min, SCALAR& max, std::true_type) { min = std::numeric_limits::max(); max = -std::numeric_limits::max(); } static void InternalInitMinMax(SCALAR& min, SCALAR& max, std::false_type) { min = std::numeric_limits::max(); max = std::numeric_limits::min(); } }; #endif // CT_SCALARMINMAXMANAGER_H