547 lines
18 KiB
C++
547 lines
18 KiB
C++
#include "pch.h"
|
||
#include "CreoManager.h"
|
||
#include <wfcAssembly.h>
|
||
#include <pfcBase.h>
|
||
#include <pfcGlobal.h>
|
||
#include <pfcExport.h>
|
||
#include <stdcols.h>
|
||
#include <ctime>
|
||
#include <sstream>
|
||
#include <iomanip>
|
||
#include <fstream>
|
||
#include <windows.h>
|
||
|
||
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 "Model is null";
|
||
}
|
||
|
||
pfcModelDescriptor_ptr descr = model->GetDescr();
|
||
if (!descr) {
|
||
return "No descriptor";
|
||
}
|
||
|
||
// 使用origin路径获取文件大小
|
||
xstring origin = model->GetOrigin();
|
||
std::string origin_str = XStringToString(origin);
|
||
if (!origin_str.empty()) {
|
||
return GetFileSize(origin_str);
|
||
}
|
||
|
||
return "No origin path";
|
||
}
|
||
catch (...) {
|
||
return "Exception in GetModelFileSize";
|
||
}
|
||
}
|
||
|
||
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++;
|
||
}
|
||
|
||
// 获取所有组件
|
||
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) {
|
||
pfcModel_ptr comp_model = comp_path->GetLeaf();
|
||
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;
|
||
} |