CreoPluging9.0/Shrinkwrap90Manager.cpp
2026-01-15 16:23:23 +08:00

122 lines
3.8 KiB
C++

#include "pch.h"
#include "Shrinkwrap90Manager.h"
#include "Creo90Manager.h"
#include "CreoOtk.h"
#include <filesystem>
#include <sstream>
#include <stdexcept>
namespace {
std::string EnsurePrtExtension(std::string path) {
std::filesystem::path p(path);
if (!p.has_extension()) {
p.replace_extension(".prt");
}
return p.string();
}
} // namespace
ShrinkwrapShellResult Shrinkwrap90Manager::ExportShell(const ShrinkwrapShellRequest& req) {
if (req.output_file_path.empty()) {
throw std::runtime_error("output_file_path is required");
}
if (req.quality < 1 || req.quality > 10) {
throw std::runtime_error("quality must be in [1,10]");
}
if (req.small_surface_percentage < 0.0) {
throw std::runtime_error("small_surface_percentage must be >= 0");
}
Creo90Manager creo;
pfcSession_ptr session = creo.GetSession();
if (!session) {
throw std::runtime_error("Creo session not available");
}
pfcSolid_ptr source = creo.GetCurrentSolid();
if (!source) {
throw std::runtime_error("current model is not a solid (part/assembly) or no model is active");
}
std::string outPathS = EnsurePrtExtension(req.output_file_path);
std::filesystem::path outPath(outPathS);
std::string stem = outPath.stem().string();
std::string modelName = SanitizeCreoModelName(stem);
if (modelName.empty()) modelName = "shrinkwrap";
pfcPart_ptr outputPart = session->CreatePart(modelName.c_str());
pfcModel_ptr outputModel = pfcModel::cast(outputPart);
pfcShrinkwrapMergedSolidInstructions_ptr instr = pfcShrinkwrapMergedSolidInstructions::Create(outputModel);
instr->SetQuality(req.quality);
instr->SetAutoHoleFilling(req.fill_holes ? xtrue : xfalse);
instr->SetIgnoreSmallSurfaces(req.ignore_small_surfaces ? xtrue : xfalse);
instr->SetSmallSurfPercentage(req.small_surface_percentage);
instr->SetIgnoreQuilts(req.ignore_quilts ? xtrue : xfalse);
instr->SetIgnoreSkeleton(req.ignore_skeleton ? xtrue : xfalse);
instr->SetAssignMassProperties(req.assign_mass_properties ? xtrue : xfalse);
pfcShrinkwrapExportInstructions_ptr exportInstr = pfcShrinkwrapExportInstructions::cast(instr);
source->ExportShrinkwrap(exportInstr);
std::string dir = outPath.parent_path().string();
pfcModelDescriptor_ptr descr = pfcModelDescriptor::Create(pfcMDL_PART, modelName.c_str(), nullptr);
descr->SetPath(dir.c_str());
outputPart->Backup(descr);
std::filesystem::path actualOutPath = outPath.parent_path() / (modelName + ".prt");
ShrinkwrapShellResult res;
res.output_path = actualOutPath.string();
std::error_code ec;
uintmax_t bytes = std::filesystem::file_size(actualOutPath, ec);
if (ec) bytes = 0;
res.file_size = FormatFileSize(bytes);
res.execution_time = ""; // 由上层填充
return res;
}
std::string Shrinkwrap90Manager::SanitizeCreoModelName(const std::string& fileStem) {
std::string out;
out.reserve(fileStem.size());
for (unsigned char uc : fileStem) {
char c = static_cast<char>(uc);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-') {
out.push_back(c);
} else if (c == ' ') {
out.push_back('_');
}
}
if (!out.empty() && (out[0] >= '0' && out[0] <= '9')) {
out.insert(out.begin(), '_');
}
if (out.size() > 31) {
out.resize(31);
}
return out;
}
std::string Shrinkwrap90Manager::FormatFileSize(uintmax_t bytes) {
std::ostringstream oss;
double mb = static_cast<double>(bytes) / (1024.0 * 1024.0);
oss.setf(std::ios::fixed);
oss.precision(1);
oss << mb << " MB";
return oss.str();
}
std::string Shrinkwrap90Manager::FormatHhMmSs(long long totalSeconds) {
if (totalSeconds < 0) totalSeconds = 0;
long long h = totalSeconds / 3600;
long long m = (totalSeconds % 3600) / 60;
long long s = totalSeconds % 60;
char buf[32];
sprintf_s(buf, "%02lld:%02lld:%02lld", h, m, s);
return std::string(buf);
}