#include "pch.h" #include "HierarchyStatisticsAnalyzer.h" #include #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; } std::string current_model_name; try { xstring filename_xstr = current_model->GetFileName(); current_model_name = creoManager.XStringToString(filename_xstr); } catch (...) { current_model_name = "unknown_model"; } result.model_name = current_model_name; if (!request.project_name.empty()) { result.model_name = request.project_name; } pfcModelType model_type = current_model->GetType(); wfcWAssembly_ptr target_assembly = nullptr; if (request.subassembly_path.empty()) { // 没有指定子装配体路径,使用当前模型 if (model_type == pfcMDL_PART) { result.model_type = "part"; result.total_levels = 1; result.level_statistics[0] = 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"; target_assembly = wfcWAssembly::cast(current_model); } else { result.error_message = "Current model is neither a part nor an assembly"; return result; } } else { // 指定了子装配体路径 if (model_type != pfcMDL_ASSEMBLY) { result.error_message = "Current model is not an assembly"; return result; } wfcWAssembly_ptr root_assembly = wfcWAssembly::cast(current_model); if (!root_assembly) { result.error_message = "Failed to cast model to assembly"; return result; } target_assembly = FindSubassemblyByPath(root_assembly, request.subassembly_path, current_model_name); if (!target_assembly) { result.error_message = "Subassembly not found at path: " + request.subassembly_path; return result; } // 更新模型名称为子装配体名称 try { pfcModel_ptr target_model = pfcModel::cast(target_assembly); if (target_model) { xstring filename_xstr = target_model->GetFileName(); result.model_name = creoManager.XStringToString(filename_xstr); } } catch (...) {} result.model_type = "assembly"; } if (!target_assembly) { result.error_message = "Failed to get target assembly"; return result; } result.level_statistics.clear(); result.total_levels = 0; result.level_statistics[0] = 1; result.total_levels = 1; AnalyzeAssemblyLevel(target_assembly, 1, result.level_statistics, result.total_levels); 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; 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; } wfcWAssembly_ptr HierarchyStatisticsAnalyzer::FindSubassemblyByPath(wfcWAssembly_ptr root_assembly, const std::string& subassembly_path, const std::string& current_model_name) { if (!root_assembly || subassembly_path.empty()) { return nullptr; } auto& creoManager = CreoManager::Instance(); try { // 解析路径 std::vector path_segments; std::string path = subassembly_path; std::replace(path.begin(), path.end(), '\\', '/'); std::istringstream iss(path); std::string segment; while (std::getline(iss, segment, '/')) { if (!segment.empty()) { path_segments.push_back(segment); } } if (path_segments.empty()) { return nullptr; } // 如果第一段是当前模型名,跳过它 size_t start_index = 0; if (!current_model_name.empty() && !path_segments.empty()) { std::string first_seg = path_segments[0]; std::string model_name = current_model_name; std::transform(first_seg.begin(), first_seg.end(), first_seg.begin(), ::tolower); std::transform(model_name.begin(), model_name.end(), model_name.begin(), ::tolower); if (first_seg == model_name) { start_index = 1; } } if (start_index >= path_segments.size()) { return root_assembly; } wfcWAssembly_ptr current_assembly = root_assembly; for (size_t i = start_index; i < path_segments.size(); ++i) { std::string target = path_segments[i]; std::string target_lower = target; std::transform(target_lower.begin(), target_lower.end(), target_lower.begin(), ::tolower); pfcFeatures_ptr features = current_assembly->ListFeaturesByType(xfalse, pfcFEATTYPE_COMPONENT); if (!features) return nullptr; int count = features->getarraysize(); bool found = false; for (int j = 0; j < count; ++j) { try { pfcFeature_ptr feature = features->get(j); if (!feature) continue; pfcComponentFeat_ptr compFeat = pfcComponentFeat::cast(feature); if (!compFeat) continue; auto modelDescr = compFeat->GetModelDescr(); if (!modelDescr) continue; xstring filename_xstr = modelDescr->GetFileName(); std::string comp_name = creoManager.XStringToString(filename_xstr); std::string comp_lower = comp_name; std::transform(comp_lower.begin(), comp_lower.end(), comp_lower.begin(), ::tolower); if (comp_lower == target_lower) { pfcModel_ptr child_model = nullptr; CreoManager::SessionInfo sessionInfo = creoManager.GetSessionInfo(); if (sessionInfo.is_valid && sessionInfo.session) { child_model = sessionInfo.session->GetModelFromDescr(modelDescr); if (!child_model) { try { child_model = sessionInfo.session->RetrieveModelWithOpts(modelDescr, nullptr); } catch (...) {} } } if (child_model && child_model->GetType() == pfcMDL_ASSEMBLY) { current_assembly = wfcWAssembly::cast(child_model); found = true; break; } else if (i == path_segments.size() - 1) { return nullptr; // 最后一段但不是装配体 } } } catch (...) { continue; } } if (!found) return nullptr; } return current_assembly; } catch (...) { return nullptr; } } 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 (...) { } }