CreoOtkPluging/CreoManager.cpp
root cd59030b73 实现完整的Creo Web API集成系统
- 添加模块化HTTP服务器架构,支持路由注册和请求处理
- 实现Creo状态检测API,提供连接状态和模型状态实时监控
- 完成STEP格式模型导出功能,支持装配体和零件导出
- 实现装配体层级结构分析,支持无限深度遍历和组件信息提取
- 添加层级组件安全删除功能,使用抑制策略保持装配体完整性
- 集成WebSocket服务器框架,为实时通信和长操作做准备
- 完善JSON处理、日志记录和认证管理基础设施
- 修复OTK API兼容性问题和内存管理优化
- 解决DeleteFeatures崩溃问题,采用SuppressFeatures替代方案

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-19 15:46:25 +08:00

1137 lines
42 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pch.h"
#include "CreoManager.h"
#include <wfcAssembly.h>
#include <pfcBase.h>
#include <pfcGlobal.h>
#include <pfcExport.h>
#include <pfcModel.h>
#include <pfcAssembly.h>
#include <pfcFeature.h>
#include <pfcSolid.h>
#include <wfcSolid.h>
#include <wfcFeatureInstructions.h>
#include <stdcols.h>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <windows.h>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <cstdlib>
#include <algorithm>
#include <functional>
// 构造函数:简化实现
CreoManager::CreoManager() {
// 配置设置可能需要通过config.pro文件或其他方式
// 暂时移除代码中的配置设置
}
CreoManager& CreoManager::Instance() {
static CreoManager instance;
return instance;
}
CreoStatus CreoManager::GetCreoStatus() {
CreoStatus status;
SessionInfo sessionInfo = GetSessionInfo();
status.is_connected = sessionInfo.is_valid;
status.version = sessionInfo.version;
status.build = sessionInfo.build;
if (sessionInfo.is_valid) {
// 获取工作目录
try {
xstring workdir = sessionInfo.session->GetCurrentDirectory();
status.working_directory = XStringToString(workdir);
}
catch (...) {
status.working_directory = "Failed to get working directory";
}
status.session_id = 1;
} else {
status.working_directory = "Failed to connect to Creo";
status.session_id = 0;
}
return status;
}
ModelStatus CreoManager::GetModelStatus() {
ModelStatus status;
SessionInfo sessionInfo = GetSessionInfo();
if (!sessionInfo.is_valid) {
return status;
}
try {
pfcModel_ptr current_model = sessionInfo.session->GetCurrentModel();
if (current_model) {
status.has_model = true;
// 获取模型名称和文件名
try {
xstring name_xstr = current_model->GetFileName();
status.name = XStringToString(name_xstr);
status.filename = status.name;
}
catch (...) {
status.name = "Failed to get model name";
status.filename = "Failed to get filename";
}
// 获取模型类型
try {
pfcModelType model_type = current_model->GetType();
switch (model_type) {
case pfcMDL_PART:
status.type = "Part";
status.is_assembly = false;
break;
case pfcMDL_ASSEMBLY:
status.type = "Assembly";
status.is_assembly = true;
break;
case pfcMDL_DRAWING:
status.type = "Drawing";
status.is_assembly = false;
break;
default:
status.type = "";
status.is_assembly = false;
break;
}
}
catch (...) {
status.type = "Failed to get model type";
status.is_assembly = false;
}
// 获取模型文件大小(装配体统计所有零件和子装配体的总大小)
try {
if (status.is_assembly) {
// 装配体:统计所有组件的文件大小
status.file_size = CalculateAssemblyTotalSize(current_model);
} else {
// 单个零件:直接获取文件大小
status.file_size = GetModelFileSize(current_model);
}
}
catch (...) {
status.file_size = "Exception getting file size";
}
// 获取真实的零件数量和装配体层级
if (status.is_assembly) {
try {
wfcWAssembly_ptr wAssembly = wfcWAssembly::cast(current_model);
if (wAssembly) {
// 获取所有显示的组件
wfcWComponentPaths_ptr components = wAssembly->ListDisplayedComponents();
if (components) {
status.total_parts = components->getarraysize();
} else {
status.total_parts = 0;
}
status.assembly_levels = SafeCalculateAssemblyLevels(wAssembly);
} else {
status.total_parts = 0;
status.assembly_levels = 0;
}
}
catch (...) {
status.total_parts = 0;
status.assembly_levels = 0;
}
} else {
// 非装配体(零件)的真实数据
status.total_parts = 1;
status.assembly_levels = 1;
}
// 解析软件信息
std::string full_version = sessionInfo.version;
size_t space_pos = full_version.find(" ");
if (space_pos != std::string::npos) {
status.software = full_version.substr(0, space_pos);
status.version = full_version.substr(space_pos + 1);
} else {
status.software = "Failed to parse software name";
status.version = "Failed to parse version";
}
// 设置其他信息
status.connection_time = GetCurrentTimeString();
status.open_time = status.connection_time;
status.connection_status = "Connected";
}
}
catch (...) {
status.has_model = false;
status.name = "Failed to access model";
status.filename = "Failed to access model";
status.type = "Failed to access model";
status.is_assembly = false;
status.total_parts = 0;
status.assembly_levels = 0;
status.software = "Failed to access model";
status.version = "Failed to access model";
status.connection_time = "Failed to get time";
status.open_time = "Failed to get time";
status.connection_status = "Failed to get status";
status.file_size = "Failed to access model";
}
return status;
}
bool CreoManager::ShowMessage(const std::string& message) {
SessionInfo sessionInfo = GetSessionInfo();
if (!sessionInfo.is_valid) {
return false;
}
try {
xstring msg_xstr = StringToXString(message);
sessionInfo.wSession->UIShowMessageDialog(msg_xstr, NULL);
return true;
}
catch (...) {
return false;
}
}
std::string CreoManager::XStringToString(const xstring& xstr) {
try {
std::wstring wstr(xstr);
if (wstr.empty()) {
return "";
}
// 使用WideCharToMultiByte进行正确的UTF-8编码转换
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), NULL, 0, NULL, NULL);
if (size_needed <= 0) {
return "";
}
std::string result(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), &result[0], size_needed, NULL, NULL);
return result;
}
catch (...) {
return "";
}
}
xstring CreoManager::StringToXString(const std::string& str) {
try {
if (str.empty()) {
return xstring();
}
// 使用MultiByteToWideChar进行正确的UTF-8解码转换
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.length(), NULL, 0);
if (size_needed <= 0) {
return xstring();
}
std::wstring wstr(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.length(), &wstr[0], size_needed);
return xstring(wstr.c_str());
}
catch (...) {
return xstring();
}
}
std::string CreoManager::GetCurrentTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_tm = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
std::string CreoManager::GetCurrentTimeStringISO() {
std::time_t now = std::time(nullptr);
std::tm* utc_tm = std::gmtime(&now);
std::ostringstream oss;
oss << std::put_time(utc_tm, "%Y-%m-%dT%H:%M:%S");
oss << ".000000Z"; // 添加微秒和UTC标识
return oss.str();
}
CreoManager::SessionInfo CreoManager::GetSessionInfo() {
SessionInfo info;
info.is_valid = false;
try {
info.session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
if (info.session) {
info.wSession = wfcWSession::cast(info.session);
if (info.wSession) {
// 获取版本信息
int version_num = info.wSession->GetReleaseNumericVersion();
xstring date_code = info.wSession->GetDisplayDateCode();
// 尝试获取真实的软件名称
std::string software_name = "Creo"; // 基础名称,如果无法获取更详细的名称
std::ostringstream version_str;
version_str << software_name << " " << version_num << ".0";
info.version = version_str.str();
info.build = XStringToString(date_code);
info.is_valid = true;
} else {
info.version = "Failed to get version";
info.build = "Failed to get build";
}
} else {
info.version = "Failed to connect to Creo";
info.build = "Failed to connect to Creo";
}
}
catch (...) {
info.version = "Failed to get version";
info.build = "Failed to get build";
}
return info;
}
std::string CreoManager::GetFileSize(const std::string& filepath) {
try {
if (filepath.empty()) {
return "Empty filepath";
}
// 复用现有的字符串转换逻辑
xstring xpath = StringToXString(filepath);
std::wstring wpath(xpath);
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
if (GetFileAttributesExW(wpath.c_str(), GetFileExInfoStandard, &fileInfo)) {
LARGE_INTEGER size;
size.HighPart = fileInfo.nFileSizeHigh;
size.LowPart = fileInfo.nFileSizeLow;
double file_size_mb = static_cast<double>(size.QuadPart) / (1024.0 * 1024.0);
std::ostringstream oss;
oss << std::fixed << std::setprecision(1) << file_size_mb << "MB";
return oss.str();
} else {
DWORD error = GetLastError();
std::ostringstream oss;
oss << "File access failed (Error: " << error << ") Path: " << filepath;
return oss.str();
}
}
catch (...) {
return "Exception in GetFileSize";
}
}
int CreoManager::SafeCalculateAssemblyLevels(wfcWAssembly_ptr assembly) {
try {
if (!assembly) {
return 1;
}
// 使用ComponentPath分析装配体层级深度
wfcWComponentPaths_ptr components = assembly->ListDisplayedComponents();
if (!components) {
return 1;
}
int component_count = components->getarraysize();
if (component_count == 0) {
return 1;
}
int max_level = 1;
// 移除组件数量限制,检查所有组件
for (int i = 0; i < component_count; i++) {
try {
wfcWComponentPath_ptr comp_path = components->get(i);
if (comp_path) {
// 使用GetComponentIds获取组件路径
xintsequence_ptr ids = comp_path->GetComponentIds();
if (ids) {
// 路径深度就是装配体层级
int path_depth = ids->getarraysize();
if (path_depth > max_level) {
max_level = path_depth;
}
}
}
}
catch (...) {
// 跳过有问题的组件
continue;
}
}
return max_level;
}
catch (...) {
return 1;
}
}
std::string CreoManager::GetModelFileSize(pfcModel_ptr model) {
try {
if (!model) {
return "0.0MB";
}
// 先检查模型是否可以安全调用GetDescr
try {
pfcModelDescriptor_ptr descr = model->GetDescr();
if (!descr) {
return "0.0MB";
}
} catch (...) {
// 如果GetDescr失败可能是轻量级模型尝试其他方法
try {
xstring origin = model->GetOrigin();
std::string origin_str = XStringToString(origin);
if (!origin_str.empty()) {
return GetFileSize(origin_str);
}
} catch (...) {
// 所有方法都失败,返回默认值
return "0.0MB";
}
return "0.0MB";
}
// 使用origin路径获取文件大小
try {
xstring origin = model->GetOrigin();
std::string origin_str = XStringToString(origin);
if (!origin_str.empty()) {
return GetFileSize(origin_str);
}
} catch (...) {
return "0.0MB";
}
return "0.0MB";
}
catch (...) {
return "0.0MB";
}
}
double CreoManager::ParseMBFromSizeString(const std::string& size_str) {
try {
if (size_str.find("MB") != std::string::npos) {
size_t mb_pos = size_str.find("MB");
std::string size_num = size_str.substr(0, mb_pos);
return std::stod(size_num);
}
return 0.0;
}
catch (...) {
return 0.0;
}
}
std::string CreoManager::CalculateAssemblyTotalSize(pfcModel_ptr model) {
try {
wfcWAssembly_ptr assembly = wfcWAssembly::cast(model);
if (!assembly) {
return "Not an assembly";
}
double total_size_bytes = 0;
int processed_count = 0;
// 首先添加主装配体文件大小
std::string main_size = GetModelFileSize(model);
double main_mb = ParseMBFromSizeString(main_size);
if (main_mb > 0) {
total_size_bytes += main_mb * 1024 * 1024;
processed_count++;
}
// 使用ListDisplayedComponents获取组件保持原有逻辑
wfcWComponentPaths_ptr components = assembly->ListDisplayedComponents();
if (components) {
int component_count = components->getarraysize();
for (int i = 0; i < component_count; i++) {
try {
wfcWComponentPath_ptr comp_path = components->get(i);
if (comp_path) {
pfcSolid_ptr leaf_solid = comp_path->GetLeaf();
if (leaf_solid) {
pfcModel_ptr comp_model = pfcModel::cast(leaf_solid);
if (comp_model) {
std::string comp_size = GetModelFileSize(comp_model);
double comp_mb = ParseMBFromSizeString(comp_size);
if (comp_mb > 0) {
total_size_bytes += comp_mb * 1024 * 1024;
processed_count++;
}
}
}
}
}
catch (...) {
continue;
}
}
}
// 转换为MB并返回
double total_mb = total_size_bytes / (1024.0 * 1024.0);
std::ostringstream oss;
oss << std::fixed << std::setprecision(1) << total_mb << "MB (from " << processed_count << " files)";
return oss.str();
}
catch (...) {
return "Exception in CalculateAssemblyTotalSize";
}
}
ExportResult CreoManager::ExportModelToSTEP(const std::string& export_path, const std::string& geom_flags) {
ExportResult result;
SessionInfo sessionInfo = 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;
}
// 检查导出路径是否有效
if (export_path.empty()) {
result.error_message = "Invalid export path";
return result;
}
// 检查模型类型是否支持导出
pfcModelType model_type = current_model->GetType();
if (model_type != pfcMDL_PART && model_type != pfcMDL_ASSEMBLY) {
result.error_message = "Model type not supported for export";
return result;
}
// 创建几何导出标志
pfcGeomExportFlags_ptr geometryFlags = pfcGeomExportFlags::Create();
// 创建STEP导出指令
pfcSTEPExportInstructions_ptr exportInstructions =
pfcSTEPExportInstructions::Create(geometryFlags);
// 执行导出 - 使用xrstring类型
xrstring export_path_xrstr = export_path.c_str();
current_model->Export(export_path_xrstr, pfcExportInstructions::cast(exportInstructions));
// 检查导出文件是否存在使用Windows API
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
if (GetFileAttributesExA(export_path.c_str(), GetFileExInfoStandard, &fileInfo)) {
result.success = true;
result.export_path = export_path;
result.file_size = GetFileSize(export_path);
result.format = "step";
result.export_time = GetCurrentTimeStringISO();
result.software = "Creo Parametric";
// 获取原始文件信息
try {
xstring name_xstr = current_model->GetFileName();
result.original_file = XStringToString(name_xstr);
} catch (...) {
result.original_file = "Unknown";
}
// 解析目录和文件名
size_t last_slash = export_path.find_last_of("\\/");
if (last_slash != std::string::npos) {
result.dirname = export_path.substr(0, last_slash);
result.filename = export_path.substr(last_slash + 1);
} else {
result.dirname = "";
result.filename = export_path;
}
} else {
result.error_message = "Export file not created";
}
}
catch (...) {
result.error_message = "Export operation failed";
}
return result;
}
// 层级分析主方法
HierarchyAnalysisResult CreoManager::AnalyzeModelHierarchy(const HierarchyAnalysisRequest& request) {
HierarchyAnalysisResult result;
SessionInfo sessionInfo = 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;
}
// 检查是否为装配体
if (current_model->GetType() != pfcMDL_ASSEMBLY) {
result.error_message = "Current model is not an assembly";
return result;
}
// 转换为装配体
wfcWAssembly_ptr assembly = wfcWAssembly::cast(current_model);
if (!assembly) {
result.error_message = "Failed to cast model to assembly";
return result;
}
// 初始化结果SOTA算法
result.project_name = request.project_name.empty() ?
XStringToString(current_model->GetFileName()) : request.project_name;
result.total_levels = 0;
result.total_components = 0;
result.hierarchy.clear();
// 创建根装配体组件信息
ComponentInfo root_component;
// 获取根装配体文件名
try {
xstring filename_xstr = current_model->GetFileName();
root_component.id = XStringToString(filename_xstr);
} catch (...) {
try {
xstring origin = current_model->GetOrigin();
std::string origin_str = XStringToString(origin);
size_t pos = origin_str.find_last_of("/\\");
if (pos != std::string::npos) {
root_component.id = origin_str.substr(pos + 1);
} else {
root_component.id = origin_str;
}
} catch (...) {
root_component.id = "root_assembly.asm";
}
}
// 设置根装配体属性
root_component.name = root_component.id;
root_component.type = "assembly";
root_component.level = 0;
root_component.path = root_component.id;
root_component.full_path = root_component.id;
root_component.file_size = GetModelFileSize(current_model);
root_component.deletion_safety = "forbidden";
root_component.is_visible = true;
root_component.model_type = "MDL_ASSEMBLY";
root_component.children_count = 0; // 将在递归后计算
// 初始化层级0并添加根装配体
result.hierarchy.push_back(std::vector<ComponentInfo>());
result.hierarchy[0].push_back(root_component);
// 使用新的SOTA递归算法分析子组件从层级1开始
AnalyzeAssemblyNode(assembly, 1, root_component.name, root_component.path, result);
// 计算根装配体的children_count
if (result.hierarchy.size() > 1) {
result.hierarchy[0][0].children_count = result.hierarchy[1].size();
}
// 计算最终统计
result.total_levels = result.hierarchy.size();
// 计算总组件数(从所有层级统计)
result.total_components = 0;
for (const auto& level : result.hierarchy) {
result.total_components += level.size();
}
// 设置成功状态
result.success = true;
result.message = "Hierarchy analysis completed";
return result;
} catch (const std::exception& e) {
result.error_message = "Exception during hierarchy analysis: " + std::string(e.what());
} catch (...) {
result.error_message = "Unknown exception during hierarchy analysis";
}
return result;
}
// 评估删除安全性
std::string CreoManager::EvaluateDeletionSafety(const ComponentInfo& component) {
if (component.level == 0) {
return "forbidden"; // 主装配体不能删除
}
if (component.type == "assembly") {
return "risky"; // 子装配体删除有风险
}
return "moderate"; // 零件删除相对安全
}
// 获取组件文件大小 (使用更安全的方法)
std::string CreoManager::GetComponentFileSize(wfcWComponentPath_ptr component_path) {
try {
pfcSolid_ptr leaf_model = component_path->GetLeaf();
if (leaf_model) {
// 使用更安全的转换方法
pfcModel_ptr model = pfcModel::cast(leaf_model);
if (model) {
return GetModelFileSize(model);
}
}
} catch (...) {
// 捕获所有异常,返回默认值
}
return "0.0MB";
}
// 获取模型类型字符串
std::string CreoManager::GetModelTypeString(pfcModelType model_type) {
switch (model_type) {
case pfcMDL_ASSEMBLY:
return "MDL_ASSEMBLY";
case pfcMDL_PART:
return "MDL_PART";
case pfcMDL_DRAWING:
return "MDL_DRAWING";
default:
return "MDL_UNKNOWN";
}
}
// 计算子组件数量
int CreoManager::CountChildComponents(wfcWComponentPath_ptr component_path) {
try {
pfcSolid_ptr leaf_model = component_path->GetLeaf();
if (leaf_model && leaf_model->GetType() == pfcMDL_ASSEMBLY) {
wfcWAssembly_ptr sub_assembly = wfcWAssembly::cast(leaf_model);
if (sub_assembly) {
wfcWComponentPaths_ptr sub_components = sub_assembly->ListDisplayedComponents();
if (sub_components) {
return sub_components->getarraysize();
}
}
}
} catch (...) {
// 忽略错误
}
return 0;
}
// =============== SOTA层级分析算法 ===============
void CreoManager::AnalyzeAssemblyNode(wfcWAssembly_ptr assembly,
int level,
const std::string& parentName,
const std::string& currentPath,
HierarchyAnalysisResult& result) {
if (!assembly) return;
try {
// 更新最大层级深度
if (level + 1 > result.total_levels) {
result.total_levels = level + 1;
}
// 确保层级容器足够大
while (result.hierarchy.size() <= level) {
result.hierarchy.push_back(std::vector<ComponentInfo>());
}
// 使用ListFeaturesByType获取所有组件特征包括隐藏的
pfcFeatures_ptr features = assembly->ListFeaturesByType(xfalse, pfcFEATTYPE_COMPONENT);
if (!features) return;
int features_count = features->getarraysize();
if (features_count <= 0) return;
// 遍历所有组件特征
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 = LoadComponentModel(compFeat);
// 创建组件信息,传递已加载的模型
ComponentInfo component = CreateComponentFromFeature(compFeat, level, parentName, currentPath, childModel);
// 添加到当前层级
result.hierarchy[level].push_back(component);
// 递归处理子装配体
if (component.type == "assembly" && childModel) {
try {
if (childModel->GetType() == pfcMDL_ASSEMBLY) {
wfcWAssembly_ptr childAssembly = wfcWAssembly::cast(childModel);
if (childAssembly) {
// 递归分析子装配体
AnalyzeAssemblyNode(childAssembly, level + 1,
component.name, component.path, result);
}
}
} catch (...) {
// 处理无法加载的子装配体
}
}
} catch (...) {
continue; // 忽略单个组件错误
}
}
// children_count在CreateComponentFromFeature中已经设置
} catch (...) {
// 处理整体错误
}
}
ComponentInfo CreoManager::CreateComponentFromFeature(pfcComponentFeat_ptr compFeat,
int level,
const std::string& parentName,
const std::string& currentPath,
pfcModel_ptr preloadedModel) {
ComponentInfo component;
component.level = level;
component.children_count = 0;
component.is_visible = true;
component.file_size = "0.0MB";
component.deletion_safety = "moderate";
try {
// 获取组件模型描述符
auto modelDescr = compFeat->GetModelDescr();
if (modelDescr) {
// 获取文件名作为ID
xstring filename_xstr = modelDescr->GetFileName();
component.id = XStringToString(filename_xstr);
// 生成显示名称(去掉扩展名并格式化)
component.name = component.id;
size_t ext_pos = component.name.find_last_of(".");
if (ext_pos != std::string::npos) {
component.name = component.name.substr(0, ext_pos);
}
// 格式化显示名称
if (!component.name.empty()) {
component.name[0] = std::toupper(component.name[0]);
for (size_t i = 1; i < component.name.size(); i++) {
if (component.name[i-1] == '_' || component.name[i-1] == ' ') {
component.name[i] = std::toupper(component.name[i]);
} else {
component.name[i] = std::tolower(component.name[i]);
}
}
std::replace(component.name.begin(), component.name.end(), '_', ' ');
}
// 设置组件类型
if (modelDescr->GetType() == pfcMDL_ASSEMBLY) {
component.type = "assembly";
component.model_type = "MDL_ASSEMBLY";
} else {
component.type = "part";
component.model_type = "MDL_PART";
}
// 构建完整路径
if (currentPath.empty()) {
component.path = component.id;
} else {
component.path = currentPath + "/" + component.id;
}
component.full_path = component.path;
// 使用预加载的模型获取文件大小
try {
if (preloadedModel) {
component.file_size = GetModelFileSize(preloadedModel);
// 对于装配体直接计算子组件数量避免重复API调用
if (component.type == "assembly" && preloadedModel->GetType() == pfcMDL_ASSEMBLY) {
wfcWAssembly_ptr assembly = wfcWAssembly::cast(preloadedModel);
if (assembly) {
try {
pfcFeatures_ptr childFeatures = assembly->ListFeaturesByType(xfalse, pfcFEATTYPE_COMPONENT);
if (childFeatures) {
component.children_count = childFeatures->getarraysize();
}
} catch (...) {
component.children_count = 0;
}
}
}
} else {
component.file_size = "0.0MB";
}
} catch (...) {
component.file_size = "0.0MB";
}
}
} catch (...) {
// 使用默认值
component.id = "unknown_component_" + std::to_string(level);
component.name = "Unknown Component";
component.type = "part";
component.path = currentPath + "/" + component.id;
component.full_path = component.path;
}
return component;
}
pfcModel_ptr CreoManager::LoadComponentModel(pfcComponentFeat_ptr compFeat) {
try {
auto modelDescr = compFeat->GetModelDescr();
if (!modelDescr) return nullptr;
SessionInfo sessionInfo = GetSessionInfo();
if (!sessionInfo.is_valid) return nullptr;
// 尝试从会话中获取已加载的模型
try {
return sessionInfo.session->GetModelFromDescr(modelDescr);
} catch (pfcXToolkitError&) {
// 模型未加载返回nullptr
return nullptr;
}
} catch (...) {
return nullptr;
}
}
// 层级删除功能实现
CreoManager::HierarchyDeleteResult CreoManager::DeleteHierarchyComponents(const std::string& project_name, int target_level) {
HierarchyDeleteResult result;
result.target_level = target_level;
SessionInfo sessionInfo = 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;
}
// 检查是否为装配体
if (current_model->GetType() != pfcMDL_ASSEMBLY) {
result.error_message = "Current model is not an assembly";
return result;
}
// 转换为装配体
wfcWAssembly_ptr assembly = wfcWAssembly::cast(current_model);
if (!assembly) {
result.error_message = "Failed to cast model to assembly";
return result;
}
// target_level=2表示保留2层删除第3层的组件
// 层级映射target_level=2 -> 删除level_3 -> currentLevel=2
int deleteLevel = target_level - 1;
// 收集删除统计信息
std::map<int, std::vector<std::string>> componentsToDeleteByLevel;
int total_deleted = 0;
int successful_count = 0;
int failed_count = 0;
// 递归遍历到指定层级直接删除
std::function<void(wfcWAssembly_ptr, int)> deleteAtLevel = [&](wfcWAssembly_ptr currentAssembly, int currentLevel) {
if (!currentAssembly || currentLevel > deleteLevel) return;
try {
pfcFeatures_ptr features = currentAssembly->ListFeaturesByType(xfalse, pfcFEATTYPE_COMPONENT);
// 正常执行,无需调试输出
if (features) {
if (currentLevel == deleteLevel) {
// 在目标层级:获取所有组件并删除
xintsequence_ptr featIds = xintsequence::create();
std::vector<std::string> levelComponents;
for (int i = 0; i < features->getarraysize(); i++) {
pfcFeature_ptr feature = features->get(i);
pfcComponentFeat_ptr compFeat = pfcComponentFeat::cast(feature);
if (compFeat) {
// 记录组件信息用于响应
try {
auto modelDescr = compFeat->GetModelDescr();
if (modelDescr) {
xstring filename_xstr = modelDescr->GetFileName();
std::string filename = XStringToString(filename_xstr);
levelComponents.push_back(filename);
total_deleted++;
}
} catch (...) {
// 忽略获取文件名失败的组件
}
// 添加到删除列表
int featId = feature->GetId();
featIds->append(featId);
}
}
// 执行删除
if (featIds->getarraysize() > 0) {
try {
wfcWSolid_ptr wsolid = wfcWSolid::cast(currentAssembly);
if (wsolid) {
// 使用SuppressFeatures方法更安全地"删除"组件
wfcFeatSuppressOrDeleteOptions_ptr options = wfcFeatSuppressOrDeleteOptions::create();
options->append(wfcFEAT_SUPP_OR_DEL_NO_OPTS);
// 创建重生成指令,允许失败
wfcWRegenInstructions_ptr regenInstr = wfcWRegenInstructions::Create();
// 执行抑制操作(更安全,不会破坏引用关系)
wsolid->SuppressFeatures(featIds, options, regenInstr);
// 手动重生成模型
try {
currentAssembly->Regenerate(nullptr);
} catch (...) {
// 重生成失败不影响抑制操作
}
successful_count += featIds->getarraysize();
// 记录成功抑制的组件 - 累积而不是覆盖
if (componentsToDeleteByLevel.find(deleteLevel + 1) == componentsToDeleteByLevel.end()) {
componentsToDeleteByLevel[deleteLevel + 1] = std::vector<std::string>();
}
componentsToDeleteByLevel[deleteLevel + 1].insert(
componentsToDeleteByLevel[deleteLevel + 1].end(),
levelComponents.begin(),
levelComponents.end()
);
} else {
failed_count += featIds->getarraysize();
}
} catch (...) {
failed_count += featIds->getarraysize();
}
}
} else if (currentLevel < deleteLevel) {
// 还没到目标层级:只对装配体组件继续递归
for (int i = 0; i < features->getarraysize(); i++) {
pfcFeature_ptr feature = features->get(i);
pfcComponentFeat_ptr compFeat = pfcComponentFeat::cast(feature);
if (compFeat) {
auto modelDescr = compFeat->GetModelDescr();
if (modelDescr && modelDescr->GetType() == pfcMDL_ASSEMBLY) {
pfcModel_ptr childModel = LoadComponentModel(compFeat);
if (childModel && childModel->GetType() == pfcMDL_ASSEMBLY) {
wfcWAssembly_ptr childAssembly = wfcWAssembly::cast(childModel);
if (childAssembly) {
deleteAtLevel(childAssembly, currentLevel + 1);
}
}
}
}
}
}
}
} catch (...) {
// 忽略单个装配体的错误
}
};
// 从根装配体开始删除层级0
deleteAtLevel(assembly, 0);
result.deleted_components = componentsToDeleteByLevel;
result.total_deleted = total_deleted;
result.original_levels = 0; // 临时设置,避免异常值
// 删除完成后重新生成模型
if (successful_count > 0) {
try {
assembly->Regenerate(nullptr);
} catch (...) {
// 重新生成失败不影响删除结果
}
}
result.successful = successful_count;
result.failed = failed_count;
result.final_levels = target_level + 1; // 删除后的层级数
if (failed_count == 0) {
result.success = true;
result.message = "All components suppressed successfully (safer than deletion)";
} else {
result.success = (successful_count > 0);
result.message = "Suppression completed with " + std::to_string(failed_count) + " failures";
}
} catch (const std::exception& e) {
result.error_message = "Exception during suppression: " + std::string(e.what());
} catch (...) {
result.error_message = "Unknown error during suppression";
}
return result;
}