mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
IfcConvert --filter-file: Specifies a filter file that describes the used filtering criteria.
This commit is contained in:
committed by
Thomas Krijnen
parent
1751cf1c95
commit
0adcb9ae20
@@ -144,6 +144,8 @@ struct inclusion_traverse_filter : public geom_filter { inclusion_traverse_filte
|
||||
struct exclusion_filter : public geom_filter { exclusion_filter() : geom_filter(false, false) {} };
|
||||
struct exclusion_traverse_filter : public geom_filter { exclusion_traverse_filter() : geom_filter(false, true) {} };
|
||||
|
||||
size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_traverse_filter&, exclusion_filter&, exclusion_traverse_filter&);
|
||||
void parse_filter(geom_filter &, const std::vector<std::string>&);
|
||||
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -165,6 +167,7 @@ int main(int argc, char** argv)
|
||||
inclusion_traverse_filter include_traverse_filter;
|
||||
exclusion_filter exclude_filter;
|
||||
exclusion_traverse_filter exclude_traverse_filter;
|
||||
std::string filter_filename;
|
||||
|
||||
po::options_description geom_options("Geometry options");
|
||||
geom_options.add_options()
|
||||
@@ -240,7 +243,12 @@ int main(int argc, char** argv)
|
||||
"Sets the deflection tolerance of the mesher, 1e-3 by default if not specified.")
|
||||
("generate-uvs",
|
||||
"Generates UVs (texture coordinates) by using simple box projection. Requires normals. "
|
||||
"Not guaranteed to work properly if used with --weld-vertices.");
|
||||
"Not guaranteed to work properly if used with --weld-vertices.")
|
||||
("filter-file", po::value<std::string>(&filter_filename),
|
||||
"Specifies a filter file that describes the used filtering criteria. Supported formats "
|
||||
"are '--include=arg GlobalId ...' and 'include arg GlobalId ...'. Spaces and tabs can be used as delimeters."
|
||||
"Multiple filters of same type with different values can be inserted on their own lines. "
|
||||
"See --include, --include+, --exclude, and --exclude+ for more details.");
|
||||
|
||||
std::string bounds, offset_str;
|
||||
#ifdef HAVE_ICU
|
||||
@@ -411,6 +419,9 @@ int main(int argc, char** argv)
|
||||
Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR);
|
||||
|
||||
IfcParse::IfcFile ifc_file;
|
||||
/// @todo Do not read/initialize the file just yet. We got many potential error and
|
||||
/// exit points below and reading/initializing at this point can stall up to tens of
|
||||
/// seconds if the file is very large.
|
||||
if (!ifc_file.Init(input_filename)) {
|
||||
Logger::Error("Unable to parse input file '" + input_filename + "'");
|
||||
return EXIT_FAILURE;
|
||||
@@ -431,6 +442,16 @@ int main(int argc, char** argv)
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
if (!filter_filename.empty()) {
|
||||
size_t num_filters = read_filters_from_file(filter_filename, include_filter, include_traverse_filter, exclude_filter, exclude_traverse_filter);
|
||||
if (num_filters) {
|
||||
Logger::Notice(boost::lexical_cast<std::string>(num_filters) + " filters read from '" + filter_filename + "'.");
|
||||
} else {
|
||||
std::cerr << "[Error] No filters read from '" + filter_filename + "'.\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/// @todo Clean up this filter code further.
|
||||
std::vector<geom_filter> used_filters;
|
||||
if (include_filter.type != geom_filter::UNUSED) { used_filters.push_back(include_filter); }
|
||||
@@ -655,6 +676,76 @@ void write_log() {
|
||||
}
|
||||
}
|
||||
|
||||
bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter)
|
||||
{
|
||||
geom_filter temp;
|
||||
parse_filter(temp, values);
|
||||
// Merge values only if type and arg match.
|
||||
if ((filter.type != geom_filter::UNUSED && filter.type != temp.type) || (!filter.arg.empty() && filter.arg != temp.arg)) {
|
||||
std::cerr << "[Error] Multiple '" << type << "' filters specified with different criteria\n";
|
||||
return false;
|
||||
}
|
||||
filter.type = temp.type;
|
||||
filter.values.insert(temp.values.begin(), temp.values.end());
|
||||
filter.arg = temp.arg;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t read_filters_from_file(
|
||||
const std::string& filename,
|
||||
inclusion_filter& include_filter,
|
||||
inclusion_traverse_filter& include_traverse_filter,
|
||||
exclusion_filter& exclude_filter,
|
||||
exclusion_traverse_filter& exclude_traverse_filter)
|
||||
{
|
||||
std::ifstream filter_file(filename.c_str());
|
||||
if (!filter_file.is_open()) {
|
||||
std::cerr << "[Error] Unable to open filter file '" + filename + "'\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t line_number = 1, num_filters = 0;
|
||||
for (std::string line; std::getline(filter_file, line); ++line_number) {
|
||||
boost::trim(line);
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> values;
|
||||
boost::split(values, line, boost::is_any_of("\t "), boost::token_compress_on);
|
||||
if (values.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string type = values.front();
|
||||
values.erase(values.begin());
|
||||
// Support both "--include=arg GlobalId 1VQ5n5$RrEbPk8le4ZCI81" and "include arg GlobalId 1VQ5n5$RrEbPk8le4ZCI81"
|
||||
// and tolerate extraneous whitespace.
|
||||
boost::trim_left_if(type, boost::is_any_of("-"));
|
||||
size_t equal_pos = type.find('=');
|
||||
if (equal_pos != std::string::npos) {
|
||||
std::string value = type.substr(equal_pos + 1);
|
||||
type = type.substr(0, equal_pos);
|
||||
values.insert(values.begin(), value);
|
||||
}
|
||||
|
||||
try {
|
||||
if (type == "include") { if (append_filter("include", values, include_filter)) { ++num_filters; } }
|
||||
else if (type == "include+") { if (append_filter("include+", values, include_traverse_filter)) { ++num_filters; } }
|
||||
else if (type == "exclude") { if (append_filter("exclude", values, exclude_filter)) { ++num_filters; } }
|
||||
else if (type == "exclude+") { if (append_filter("exclude+", values, exclude_traverse_filter)) { ++num_filters; } }
|
||||
else {
|
||||
std::cerr << "[Error] Invalid filtering type at line " + boost::lexical_cast<std::string>(line_number) + "\n";
|
||||
return 0;
|
||||
}
|
||||
} catch(...) {
|
||||
std::cerr << "[Error] Unable to parse filter at line " + boost::lexical_cast<std::string>(line_number) + ".\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return num_filters;
|
||||
}
|
||||
|
||||
void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
|
||||
{
|
||||
if (values.size() == 0) {
|
||||
@@ -679,7 +770,7 @@ void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
|
||||
|
||||
void validate(boost::any& v, const std::vector<std::string>& values, inclusion_filter*, int)
|
||||
{
|
||||
/// @todo For now only single --include or --exclude supported. Support having multiple.
|
||||
/// @todo For now only single --include, --include+, --exclude, or --exclude+ supported. Support having multiple.
|
||||
po::validators::check_first_occurrence(v);
|
||||
inclusion_filter filter;
|
||||
parse_filter(filter, values);
|
||||
|
||||
Reference in New Issue
Block a user