feat: add subassembly_path param to hierarchy-statistics API
This commit is contained in:
parent
b95031026a
commit
20467b2c72
@ -10,6 +10,7 @@
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
||||
HierarchyStatisticsAnalyzer& HierarchyStatisticsAnalyzer::Instance() {
|
||||
static HierarchyStatisticsAnalyzer instance;
|
||||
@ -42,51 +43,81 @@ HierarchyStatisticsResult HierarchyStatisticsAnalyzer::AnalyzeHierarchyStatistic
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string current_model_name;
|
||||
try {
|
||||
xstring filename_xstr = current_model->GetFileName();
|
||||
result.model_name = creoManager.XStringToString(filename_xstr);
|
||||
current_model_name = creoManager.XStringToString(filename_xstr);
|
||||
} catch (...) {
|
||||
result.model_name = "unknown_model";
|
||||
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 (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";
|
||||
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 {
|
||||
result.error_message = "Current model is neither a part nor an assembly";
|
||||
return result;
|
||||
// 指定了子装配体路径
|
||||
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";
|
||||
}
|
||||
|
||||
wfcWAssembly_ptr assembly = wfcWAssembly::cast(current_model);
|
||||
if (!assembly) {
|
||||
result.error_message = "Failed to cast model to assembly";
|
||||
if (!target_assembly) {
|
||||
result.error_message = "Failed to get target 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);
|
||||
AnalyzeAssemblyLevel(target_assembly, 1, result.level_statistics, result.total_levels);
|
||||
|
||||
// Clean results: remove levels with 0 components
|
||||
std::map<int, int> cleaned_statistics;
|
||||
for (const auto& stat : result.level_statistics) {
|
||||
if (stat.second > 0) {
|
||||
@ -95,7 +126,6 @@ HierarchyStatisticsResult HierarchyStatisticsAnalyzer::AnalyzeHierarchyStatistic
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -113,6 +143,113 @@ HierarchyStatisticsResult HierarchyStatisticsAnalyzer::AnalyzeHierarchyStatistic
|
||||
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;
|
||||
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <wfcAssembly.h>
|
||||
#include "CreoManager.h"
|
||||
|
||||
// 层级统计请求结构
|
||||
struct HierarchyStatisticsRequest {
|
||||
std::string project_name; // 可选的项目名称,默认使用当前模型名
|
||||
std::string project_name; // 可选的项目名称,默认使用当前模型名
|
||||
std::string subassembly_path; // 可选的子装配体路径,如 "top.asm/sub.asm"
|
||||
};
|
||||
|
||||
// 层级统计结果结构
|
||||
@ -42,6 +44,9 @@ private:
|
||||
// 递归分析装配体层级
|
||||
void AnalyzeAssemblyLevel(wfcWAssembly_ptr assembly, int level, std::map<int, int>& statistics, int& maxLevel);
|
||||
|
||||
// 根据路径查找子装配体
|
||||
wfcWAssembly_ptr FindSubassemblyByPath(wfcWAssembly_ptr root_assembly, const std::string& path, const std::string& model_name);
|
||||
|
||||
// 获取当前时间字符串
|
||||
std::string GetCurrentTimeString();
|
||||
};
|
||||
|
||||
@ -1702,6 +1702,12 @@ HttpResponse HierarchyStatisticsHandler(const HttpRequest& request) {
|
||||
stats_request.project_name = project_name_str;
|
||||
}
|
||||
|
||||
// 提取subassembly_path参数(可选)
|
||||
std::string subassembly_path_str = ExtractJsonValue(request.body, "subassembly_path");
|
||||
if (!subassembly_path_str.empty()) {
|
||||
stats_request.subassembly_path = subassembly_path_str;
|
||||
}
|
||||
|
||||
// 执行层级统计分析
|
||||
HierarchyStatisticsResult result = HierarchyStatisticsAnalyzer::Instance().AnalyzeHierarchyStatistics(stats_request);
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user