Stp2Glb/src/main.cpp
sladro 096812b7d2 feat: add HTTP/HTTPS URL input support for STP files
Add capability to download STP files directly from HTTP/HTTPS URLs in both CLI and HTTP server modes.

Changes:
- Add http_downloader module for downloading files from URLs
- Extend GlobalConfig to track downloaded files
- Update CLI parameter processing to detect and handle URLs
- Enhance HTTP server to accept URL parameter alongside file upload
- Implement automatic cleanup of downloaded temporary files
- Add comprehensive usage documentation (USAGE.md)

Usage examples:
  CLI: STP2GLB.exe --stp https://example.com/model.stp --glb output.glb
  API: curl -X POST http://localhost:8080/convert -F "url=https://example.com/model.stp"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 17:19:35 +08:00

157 lines
5.9 KiB
C++

// Check if the platform is Unix-based
#if defined(__unix__) || defined(__unix)
#include <cstdint>
#endif // Unix platform check
#include <filesystem>
#include "CLI/CLI.hpp"
#include "config_structs.h"
#include <chrono>
#include "cadit/occt/debug.h"
#include "cadit/occt/convert.h"
#include "cadit/occt/bsplinesurf.h"
#include "cadit/occt/helpers.h"
#include "config_utils.h"
#include "http_server.h"
void print_status(const GlobalConfig& config) {
std::cout << "STP2GLB Converter" << "\n";
std::cout << "STP File: " << config.stpFile << "\n";
std::cout << "GLB File: " << config.glbFile << "\n\n";
std::cout << "Tessellation Parameters: " << "\n";
std::cout << "Linear Deflection: " << config.linearDeflection << "\n";
std::cout << "Angular Deflection: " << config.angularDeflection << "\n";
std::cout << "Relative Deflection: " << config.relativeDeflection << "\n\n";
std::cout << "Debug Parameters: " << "\n";
std::cout << "Debug Mode: " << config.debug_mode << "\n";
std::cout << "Solid Only: " << config.solidOnly << "\n";
std::cout << "Max Geometry Num: " << config.max_geometry_num << "\n";
std::cout << "Tessellation Timeout: " << config.tessellation_timout << "\n\n";
// Debug output
if (!config.filter_names_include.empty())
{
std::cout << "Included Filter Names:" << std::endl;
for (const auto& name : config.filter_names_include)
{
std::cout << name << std::endl;
}
}
if (!config.filter_names_exclude.empty())
{
std::cout << "Excluded Filter Names:" << std::endl;
for (const auto& name : config.filter_names_exclude)
{
std::cout << name << std::endl;
}
}
}
int main(int argc, char* argv[])
{
CLI::App app{"STEP to GLB converter"};
app.add_flag("--server", "Run as HTTP server");
app.add_option("--port", "Server port")->default_val(8080);
app.add_option("--host", "Server host")->default_val("0.0.0.0");
app.add_option("--max-file-size", "Maximum file size in MB")->default_val(500);
app.add_option("--stp", "STEP filepath");
app.add_option("--glb", "GLB filepath");
app.add_option("--lin-defl", "Linear deflection")->default_val(0.5)->check(CLI::Range(0.0, 1.0));
app.add_option("--ang-defl", "Angular deflection")->default_val(0.8)->check(CLI::Range(0.0, 1.0));
app.add_flag("--rel-defl", "Relative deflection");
app.add_flag("--debug", "Debug mode. Slower (and experimental), but provides more information about which STEP entities that failed to convert");
app.add_flag("--solid-only", "Solid only");
app.add_option("--max-geometry-num", "Maximum number of geometries to convert")->default_val(0);
app.add_option("--filter-names-include", "Include Filter name. Command separated list")->default_val("");
app.add_option("--filter-names-file-include", "Include Filter name file")->default_val("");
app.add_option("--filter-names-exclude", "Exclude Filter name. Command separated list")->default_val("");
app.add_option("--filter-names-file-exclude", "Exclude Filter name file")->default_val("");
app.add_option("--tessellation-timeout", "Tessellation timeout")->default_val(30);
CLI11_PARSE(app, argc, argv);
const bool server_mode = app.get_option("--server")->as<bool>();
if (server_mode) {
GlobalConfig config;
config.linearDeflection = app.get_option("--lin-defl")->as<double>();
config.angularDeflection = app.get_option("--ang-defl")->as<double>();
config.relativeDeflection = app.get_option("--rel-defl")->as<bool>();
config.debug_mode = false;
config.solidOnly = false;
config.max_geometry_num = 0;
config.tessellation_timout = app.get_option("--tessellation-timeout")->as<int>();
config.serverConfig.enable_server = true;
config.serverConfig.port = app.get_option("--port")->as<int>();
config.serverConfig.host = app.get_option("--host")->as<std::string>();
config.serverConfig.max_file_size_mb = app.get_option("--max-file-size")->as<size_t>();
config.serverConfig.temp_dir = "./temp";
config.serverConfig.output_dir = "./output";
try {
start_http_server(config);
} catch (const std::exception& ex) {
std::cerr << "Server error: " << ex.what() << "\n";
return 1;
}
return 0;
}
app.get_option("--stp")->required();
app.get_option("--glb")->required();
GlobalConfig config;
try {
config = process_parameters(app);
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << "\n";
return 1;
}
print_status(config);
std::cout << "\n";
std::cout << "Starting conversion..." << "\n";
const auto start = std::chrono::high_resolution_clock::now();
try {
if (config.buildConfig.build_bspline_surf)
make_a_bspline_surf(config);
if (config.debug_mode == 1)
debug_stp_to_glb(config);
else
{
convert_stp_to_glb(config);
}
} catch (std::exception& ex) {
std::cerr << "Error: " << ex.what() << "\n";
return 1;
}
const auto stop = std::chrono::high_resolution_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
const double seconds = static_cast<double>(duration.count()) / 1e6;
std::cout << "STP converted in: " << std::fixed << std::setprecision(2) << seconds << " seconds" << "\n";
// Clean up downloaded temporary file
if (config.is_downloaded_from_url) {
try {
if (std::filesystem::exists(config.stpFile)) {
std::filesystem::remove(config.stpFile);
std::cout << "Cleaned up downloaded file: " << config.stpFile << "\n";
}
} catch (const std::exception& ex) {
std::cerr << "Warning: Failed to clean up downloaded file: " << ex.what() << "\n";
}
}
return 0;
}