#include "pch.h" #include "HierarchyStatisticsAnalyzer.h" #include #include #include #include #include #include #include #include #include #include HierarchyStatisticsAnalyzer& HierarchyStatisticsAnalyzer::Instance() { static HierarchyStatisticsAnalyzer instance; return instance; } std::string HierarchyStatisticsAnalyzer::GetCurrentTimeString() { auto now = std::time(nullptr); std::tm* localTime = std::localtime(&now); std::ostringstream oss; oss << std::put_time(localTime, "%Y-%m-%d %H:%M:%S"); return oss.str(); } HierarchyStatisticsResult HierarchyStatisticsAnalyzer::AnalyzeHierarchyStatistics(const HierarchyStatisticsRequest& request) { HierarchyStatisticsResult result; auto& creoManager = CreoManager::Instance(); CreoManager::SessionInfo sessionInfo = creoManager.GetSessionInfo(); if (!sessionInfo.is_valid) { result.error_message = "Creo session not available"; return result; } try { pfcModel_ptr current_model = sessionInfo.session->GetCurrentModel(); if (!current_model) { result.error_message = "No current model loaded"; return result; } try { xstring filename_xstr = current_model->GetFileName(); result.model_name = creoManager.XStringToString(filename_xstr); } catch (...) { result.model_name = "unknown_model"; } if (!request.project_name.empty()) { result.model_name = request.project_name; } pfcModelType model_type = current_model->GetType(); if (model_type == pfcMDL_PART) { result.model_type = "part"; result.total_levels = 1; result.level_statistics[0] = 1; // Part itself counts as 1 result.success = true; result.message = "Part model has no hierarchy"; result.analysis_time = GetCurrentTimeString(); return result; } else if (model_type == pfcMDL_ASSEMBLY) { result.model_type = "assembly"; } else { result.error_message = "Current model is neither a part nor an assembly"; return result; } wfcWAssembly_ptr assembly = wfcWAssembly::cast(current_model); if (!assembly) { result.error_message = "Failed to cast model to assembly"; return result; } result.level_statistics.clear(); result.total_levels = 0; // Level 0: root assembly itself, always 1 result.level_statistics[0] = 1; result.total_levels = 1; // Analyze components starting from level 1 AnalyzeAssemblyLevel(assembly, 1, result.level_statistics, result.total_levels); // Clean results: remove levels with 0 components std::map cleaned_statistics; for (const auto& stat : result.level_statistics) { if (stat.second > 0) { cleaned_statistics[stat.first] = stat.second; } } result.level_statistics = cleaned_statistics; // Update total levels (max non-zero level + 1) if (!cleaned_statistics.empty()) { result.total_levels = cleaned_statistics.rbegin()->first + 1; } result.success = true; result.message = "Hierarchy statistics analysis completed"; result.analysis_time = GetCurrentTimeString(); } catch (const std::exception& e) { result.error_message = "Exception during analysis: " + std::string(e.what()); } catch (...) { result.error_message = "Unknown exception during hierarchy statistics analysis"; } return result; } void HierarchyStatisticsAnalyzer::AnalyzeAssemblyLevel(wfcWAssembly_ptr assembly, int level, std::map& statistics, int& maxLevel) { if (!assembly) return; try { pfcFeatures_ptr features = assembly->ListFeaturesByType(xfalse, pfcFEATTYPE_COMPONENT); if (!features) return; int features_count = features->getarraysize(); if (features_count <= 0) return; // Initialize statistics for current level if not exists if (statistics.find(level) == statistics.end()) { statistics[level] = 0; } // Count components at current level statistics[level] += features_count; // Update max level if (level > maxLevel) { maxLevel = level; } // Traverse all components, recurse for sub-assemblies for (int i = 0; i < features_count; i++) { try { pfcFeature_ptr feature = features->get(i); if (!feature) continue; pfcComponentFeat_ptr compFeat = pfcComponentFeat::cast(feature); if (!compFeat) continue; pfcModel_ptr childModel = nullptr; try { auto modelDescr = compFeat->GetModelDescr(); if (modelDescr) { auto& creoManager2 = CreoManager::Instance(); CreoManager::SessionInfo sessionInfo = creoManager2.GetSessionInfo(); if (sessionInfo.is_valid && sessionInfo.session) { childModel = sessionInfo.session->GetModelFromDescr(modelDescr); if (!childModel) { try { childModel = sessionInfo.session->RetrieveModelWithOpts(modelDescr, nullptr); } catch (...) { } } } } } catch (...) { } if (childModel) { // Only recurse for sub-assemblies if (childModel->GetType() == pfcMDL_ASSEMBLY) { wfcWAssembly_ptr childAssembly = wfcWAssembly::cast(childModel); if (childAssembly) { // Recurse to analyze next level AnalyzeAssemblyLevel(childAssembly, level + 1, statistics, maxLevel); } } } } catch (...) { continue; } } } catch (...) { } }