#include "FeatureSampleConfig.h" #include namespace MeshLib { FeatureSampleConfig FeatureSampleConfig::FromCommandLine(int argc, char** argv) { cxxopts::Options options("FeatureSample", "Feature sampling for 3D meshes"); options.add_options() ("i,input", "input mesh (obj/off format)", cxxopts::value()) ("f,feature", "input feature file (fea format)", cxxopts::value()) ("p,pointcloud", "input pointcloud", cxxopts::value()) ("pf", "face of input pointcloud", cxxopts::value()) ("o,output", "output mesh/points", cxxopts::value()) ("k,mask", "output mask file", cxxopts::value()) ("fs", "feature samples", cxxopts::value()) ("ns", "non-feature samples", cxxopts::value()) ("m,mode", "processing mode", cxxopts::value()) ("c,color", "use coloring", cxxopts::value()) ("mp", "max patches per cluster", cxxopts::value()) ("cot", "use cotangent weight", cxxopts::value()) ("s,sigma", "position noise sigma", cxxopts::value()) ("sn", "normal noise sigma", cxxopts::value()) ("csg", "generate csg tree", cxxopts::value()) ("convex", "is first layer convex", cxxopts::value()) ("r,repairturn", "repair turn vertex", cxxopts::value()) ("verbose", "verbose level", cxxopts::value()) ("strict", "strict mode") ("repairtree", "repair tree feature") ("h,help", "print help"); auto result = options.parse(argc, argv); if (result.count("help")) { std::cout << options.help() << std::endl; exit(0); } FeatureSampleConfig config; // 检查必需参数 if (!result.count("m") || !result.count("i") || !result.count("o")) { throw std::runtime_error("Missing required parameters"); } // 设置文件路径 config.files.input_mesh = result["i"].as(); config.files.output_file = result["o"].as(); if (result.count("f")) config.files.input_feature = result["f"].as(); if (result.count("p")) config.files.input_pointcloud = result["p"].as(); if (result.count("pf")) config.files.input_pointcloud_face = result["pf"].as(); if (result.count("k")) config.files.output_mask = result["k"].as(); // 设置采样参数 if (result.count("fs")) config.sampling.feature_samples = result["fs"].as(); if (result.count("ns")) config.sampling.nonfeature_samples = result["ns"].as(); if (result.count("s")) config.sampling.sigma = result["s"].as(); if (result.count("sn")) config.sampling.sigma_normal = result["sn"].as(); if (result.count("cot")) config.sampling.use_cotweight = result["cot"].as(); // 设置处理选项 config.processing.mode = result["m"].as(); if (result.count("c")) config.processing.use_color = result["c"].as(); if (result.count("mp")) config.processing.max_patches = result["mp"].as(); if (result.count("csg")) config.processing.generate_csg = result["csg"].as(); if (result.count("convex")) config.processing.is_convex = result["convex"].as(); if (result.count("r")) config.processing.repair_turn = result["r"].as(); if (result.count("verbose")) config.processing.verbose = result["verbose"].as(); if (result.count("strict")) config.processing.strict_mode = true; if (result.count("repairtree")) config.processing.repair_tree = true; return config; } bool FeatureSampleConfig::Validate() const { // 检查文件路径 if (files.input_mesh.empty() || files.output_file.empty()) { return false; } // 检查采样参数 if (sampling.feature_samples < 0 || sampling.nonfeature_samples < 0) { return false; } // 检查处理模式 if (processing.mode != 0 && processing.mode != 1) { return false; } return true; } } // namespace MeshLib