IfcConvert --filter-file: Specifies a filter file that describes the used filtering criteria.

This commit is contained in:
Stinkfist0
2017-05-19 18:10:20 +03:00
committed by Thomas Krijnen
parent 1751cf1c95
commit 0adcb9ae20
+93 -2
View File
@@ -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);