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>
157 lines
5.9 KiB
C++
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;
|
|
}
|