CreoOtkPluging/HierarchyStatisticsAnalyzer.cpp

323 lines
12 KiB
C++

#include "pch.h"
#include "HierarchyStatisticsAnalyzer.h"
#include <pfcGlobal.h>
#include <pfcSession.h>
#include <wfcSession.h>
#include <pfcModel.h>
#include <pfcFeature.h>
#include <pfcComponentFeat.h>
#include <wfcAssembly.h>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <algorithm>
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<int, int> 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<std::string> 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<int, int>& 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 (...) {
}
}