Revive some temporarily disabled features in de 0.6 branch

This commit is contained in:
Thomas Krijnen
2018-09-07 14:08:56 +02:00
parent 03da7bc6e4
commit 0df4edff01
12 changed files with 244 additions and 351 deletions
+26 -75
View File
@@ -33,6 +33,7 @@
#include "../serializers/XmlSerializer.h"
#include "../serializers/SvgSerializer.h"
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include <Standard_Version.hxx>
@@ -119,16 +120,9 @@ static std::stringstream log_stream;
void write_log(bool);
/// @todo make the filters non-global
/*
IfcGeom::entity_filter entity_filter; // Entity filter is used always by default.
IfcGeom::layer_filter layer_filter;
const std::string NAME_ARG = "Name", GUID_ARG = "GlobalId", DESC_ARG = "Description", TAG_ARG = "Tag";
boost::array<std::string, 4> supported_args = { { NAME_ARG, GUID_ARG, DESC_ARG, TAG_ARG } };
IfcGeom::string_arg_filter guid_filter(IfcSchema::Type::IfcRoot, 0); // IfcRoot.GlobalId
// Note: skipping IfcRoot OwnerHistory, argument index 1
IfcGeom::string_arg_filter name_filter(IfcSchema::Type::IfcRoot, 2); // IfcRoot.Name
IfcGeom::string_arg_filter desc_filter(IfcSchema::Type::IfcRoot, 3); // IfcRoot.Description
IfcGeom::string_arg_filter tag_filter(IfcSchema::Type::IfcProxy, 8, IfcSchema::Type::IfcElement, 7); // IfcProxy.Tag & IfcElement.Tag
IfcGeom::attribute_filter attribute_filter;
struct geom_filter
{
@@ -151,7 +145,6 @@ struct exclusion_traverse_filter : public geom_filter { exclusion_traverse_filte
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&);
*/
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap);
@@ -179,13 +172,11 @@ int main(int argc, char** argv)
double deflection_tolerance;
/*
inclusion_filter include_filter;
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()
@@ -232,14 +223,13 @@ int main(int argc, char** argv)
("enable-layerset-slicing",
"Specifies whether to enable the slicing of products according "
"to their associated IfcMaterialLayerSet.")
/*
("include", po::value<inclusion_filter>(&include_filter)->multitoken(),
"Specifies that the entities that match a specific filtering criteria are to be included in the geometrical output:\n"
"Specifies that the instances that match a specific filtering criteria are to be included in the geometrical output:\n"
"1) 'entities': the following list of types should be included. SVG output defaults "
"to IfcSpace to be included. The entity names are handled case-insensitively.\n"
"2) 'layers': the entities that are assigned to presentation layers of which names "
"2) 'layers': the instances that are assigned to presentation layers of which names "
"match the given values should be included.\n"
"3) 'arg <ArgumentName>': the following list of values for that specific argument should be included. "
"3) 'attribute <AttributeName>': products whose value for <AttributeName> should be included\n. "
"Currently supported arguments are GlobalId, Name, Description, and Tag.\n\n"
"The values for 'layers' and 'arg' are handled case-sensitively (wildcards supported)."
"--include and --exclude cannot be placed right before input file argument and "
@@ -258,8 +248,7 @@ int main(int argc, char** argv)
"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.");
*/
"See --include, --include+, --exclude, and --exclude+ for more details.")
("no-normals",
"Disables computation of normals. Saves time and file size and is useful "
"in instances where you're going to recompute normals for the exported "
@@ -490,7 +479,6 @@ 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) {
@@ -514,14 +502,10 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
if (!entity_filter.values.empty()) { entity_filter.update_description(); Logger::Notice(entity_filter.description); }
if (!entity_filter.entity_names.empty()) { entity_filter.update_description(); Logger::Notice(entity_filter.description); }
if (!layer_filter.values.empty()) { layer_filter.update_description(); Logger::Notice(layer_filter.description); }
if (!guid_filter.values.empty()) { guid_filter.update_description(); Logger::Notice(guid_filter.description); }
if (!name_filter.values.empty()) { name_filter.update_description(); Logger::Notice(name_filter.description); }
if (!desc_filter.values.empty()) { desc_filter.update_description(); Logger::Notice(desc_filter.description); }
if (!tag_filter.values.empty()) { tag_filter.update_description(); Logger::Notice(tag_filter.description); }
*/
if (!attribute_filter.attribute_name.empty()) { attribute_filter.update_description(); Logger::Notice(layer_filter.description); }
SerializerSettings settings;
/// @todo Make APPLY_DEFAULT_MATERIALS configurable? Quickly tested setting this to false and using obj exporter caused the program to crash and burn.
settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true);
@@ -629,7 +613,7 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file);
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs);
if (!context_iterator.initialize()) {
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
/// and for a case we found no entities that satisfy our filtering criteria.
@@ -663,7 +647,6 @@ int main(int argc, char** argv)
throw std::runtime_error("needs more work");
/*
if (!quiet) Logger::Status("Computing bounds...");
context_iterator.compute_bounds();
if (!quiet) Logger::Status("Done!");
@@ -672,7 +655,6 @@ int main(int argc, char** argv)
offset[0] = -center.X();
offset[1] = -center.Y();
offset[2] = -center.Z();
*/
} else {
if (sscanf(offset_str.c_str(), "%lf;%lf;%lf", &offset[0], &offset[1], &offset[2]) != 3) {
std::cerr << "[Error] Invalid use of --model-offset\n";
@@ -826,7 +808,6 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
}
/*
bool append_filter(const std::string& type, const std::vector<std::string>& values, geom_filter& filter)
{
geom_filter temp;
@@ -910,9 +891,6 @@ void parse_filter(geom_filter &filter, const std::vector<std::string>& values)
} else if (type == "arg") {
filter.type = geom_filter::ENTITY_ARG;
filter.arg = *(values.begin() + 1);
if (std::find(supported_args.begin(), supported_args.end(), filter.arg) == supported_args.end()) {
throw po::validation_error(po::validation_error::invalid_option_value);
}
} else {
throw po::validation_error(po::validation_error::invalid_option_value);
}
@@ -958,65 +936,38 @@ void validate(boost::any& v, const std::vector<std::string>& values, exclusion_t
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>& filters, const std::string& output_extension)
{
std::vector<IfcGeom::filter_t> filter_funcs;
BOOST_FOREACH(const geom_filter& f, filters) {
for(auto& f: filters) {
if (f.type == geom_filter::ENTITY_TYPE) {
entity_filter.include = f.include;
entity_filter.traverse = f.traverse;
try {
entity_filter.populate(f.values);
} catch (const IfcParse::IfcException& e) {
std::cerr << "[Error] " << e.what() << std::endl;
return std::vector<IfcGeom::filter_t>();
}
entity_filter.entity_names = f.values;
} else if (f.type == geom_filter::LAYER_NAME) {
layer_filter.include = f.include;
layer_filter.traverse = f.traverse;
layer_filter.populate(f.values);
} else if (f.type == geom_filter::ENTITY_ARG) {
if (f.arg == GUID_ARG) {
guid_filter.include = f.include;
guid_filter.traverse = f.traverse;
guid_filter.populate(f.values);
} else if (f.arg == NAME_ARG) {
name_filter.include = f.include;
name_filter.traverse = f.traverse;
name_filter.populate(f.values);
} else if (f.arg == DESC_ARG) {
desc_filter.include = f.include;
desc_filter.traverse = f.traverse;
desc_filter.populate(f.values);
} else if (f.arg == TAG_ARG) {
tag_filter.include = f.include;
tag_filter.traverse = f.traverse;
tag_filter.populate(f.values);
}
attribute_filter.include = f.include;
attribute_filter.traverse = f.traverse;
attribute_filter.attribute_name = f.arg;
attribute_filter.populate(f.values);
}
}
// If no entity names are specified these are the defaults to skip from output
if (entity_filter.values.empty()) {
try {
std::set<std::string> entities;
entities.insert("IfcSpace");
if (output_extension == ".svg") {
entity_filter.include = true;
} else {
entities.insert("IfcOpeningElement");
}
entity_filter.populate(entities);
} catch (const IfcParse::IfcException& e) {
std::cerr << "[Error] " << e.what() << std::endl;
return std::vector<IfcGeom::filter_t>();
if (entity_filter.entity_names.empty()) {
std::set<std::string> entities;
entities.insert("IfcSpace");
if (output_extension == ".svg") {
entity_filter.include = true;
} else {
entities.insert("IfcOpeningElement");
}
entity_filter.entity_names = entities;
}
if (!layer_filter.values.empty()) { filter_funcs.push_back(boost::ref(layer_filter)); }
if (!entity_filter.values.empty()) { filter_funcs.push_back(boost::ref(entity_filter)); }
if (!guid_filter.values.empty()) { filter_funcs.push_back(boost::ref(guid_filter)); }
if (!name_filter.values.empty()) { filter_funcs.push_back(boost::ref(name_filter)); }
if (!desc_filter.values.empty()) { filter_funcs.push_back(boost::ref(desc_filter)); }
if (!tag_filter.values.empty()) { filter_funcs.push_back(boost::ref(tag_filter)); }
if (!entity_filter.entity_names.empty()) { filter_funcs.push_back(boost::ref(entity_filter)); }
if (!attribute_filter.values.empty()) { filter_funcs.push_back(boost::ref(attribute_filter)); }
return filter_funcs;
}
*/
-2
View File
@@ -221,8 +221,6 @@ public:
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
static IfcSchema::IfcObjectDefinition* get_decomposing_entity(IfcSchema::IfcProduct*);
template <typename P, typename PP>
IfcGeom::BRepElement<P, PP>* create_brep_for_representation_and_product(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
+2 -57
View File
@@ -1332,7 +1332,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and
int parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product);
IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product)->as<IfcSchema::IfcObjectDefinition>();
if (parent_object) {
parent_id = parent_object->data().id();
}
@@ -1499,7 +1499,7 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_represen
{
int parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product);
IfcSchema::IfcObjectDefinition* parent_object = get_decomposing_entity(product)->as<IfcSchema::IfcObjectDefinition>();
if (parent_object) {
parent_id = parent_object->data().id();
}
@@ -1541,61 +1541,6 @@ IfcGeom::BRepElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_represen
);
}
IfcSchema::IfcObjectDefinition* IfcGeom::Kernel::get_decomposing_entity(IfcSchema::IfcProduct* product) {
IfcSchema::IfcObjectDefinition* parent = 0;
// In case of an opening element, parent to the RelatingBuildingElement
if ( product->declaration().is(IfcSchema::IfcOpeningElement::Class() ) ) {
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product;
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements();
if ( voids->size() ) {
IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin();
parent = ifc_void->RelatingBuildingElement();
}
} else if ( product->declaration().is(IfcSchema::IfcElement::Class() ) ) {
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product;
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids();
// In case of a RelatedBuildingElement parent to the opening element
if ( fills->size() ) {
for ( IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++ it ) {
IfcSchema::IfcRelFillsElement* fill = *it;
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement();
if ( product == ifc_objectdef ) continue;
parent = ifc_objectdef;
}
}
// Else simply parent to the containing structure
if (!parent) {
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure();
if ( parents->size() ) {
IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin();
parent = container->RelatingStructure();
}
}
}
// Parent decompositions to the RelatingObject
if (!parent) {
IfcEntityList::ptr parents = product->data().getInverse((&IfcSchema::IfcRelAggregates::Class()), -1);
parents->push(product->data().getInverse((&IfcSchema::IfcRelNests::Class()), -1));
for ( IfcEntityList::it it = parents->begin(); it != parents->end(); ++ it ) {
IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it;
IfcSchema::IfcObjectDefinition* ifc_objectdef;
#ifdef USE_IFC4
if (decompose->declaration().is(IfcSchema::IfcRelAggregates::Class())) {
ifc_objectdef = ((IfcSchema::IfcRelAggregates*)decompose)->RelatingObject();
} else {
continue;
}
#else
ifc_objectdef = decompose->RelatingObject();
#endif
if ( product == ifc_objectdef ) continue;
parent = ifc_objectdef;
}
}
return parent;
}
template IFC_GEOM_API IfcGeom::BRepElement<float, float>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::BRepElement<float, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, double>(
@@ -14,8 +14,8 @@ namespace IfcGeom {
namespace {
template <typename P, typename PP>
struct MAKE_TYPE_NAME(factory_t) {
IfcGeom::IteratorImplementation<P, PP>* operator()(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) const {
return new IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<P, PP>(settings, file);
IfcGeom::IteratorImplementation<P, PP>* operator()(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters) const {
return new IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<P, PP>(settings, file, filters);
}
};
}
+4 -33
View File
@@ -80,8 +80,8 @@
#include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom/IfcGeomFilter.h"
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcgeom_schema_agnostic/IteratorImplementation.h"
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
@@ -156,15 +156,6 @@ namespace IfcGeom {
typedef P Precision;
typedef PP PlacementPrecision;
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, IfcParse::IfcFile* file, std::vector<IfcGeom::filter_t>& filters)
: settings(settings)
, ifc_file(file)
, owns_ifc_file(false)
, filters_(filters)
{
_initialize();
}
bool initialize() {
try {
initUnits();
@@ -614,7 +605,7 @@ namespace IfcGeom {
ifc_product = ifc_entity->as<IfcSchema::IfcProduct>();
parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product);
IfcSchema::IfcObjectDefinition* parent_object = kernel.get_decomposing_entity(ifc_product)->as<IfcSchema::IfcObjectDefinition>();
if (parent_object) {
parent_id = parent_object->data().id();
}
@@ -721,31 +712,11 @@ namespace IfcGeom {
bool owns_ifc_file;
public:
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, IfcParse::IfcFile* file)
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters)
: settings(settings)
, ifc_file(file)
, owns_ifc_file(false)
{
_initialize();
}
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, const std::string& filename)
: settings(settings)
, ifc_file(new IfcParse::IfcFile(filename))
, owns_ifc_file(true)
{
_initialize();
}
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, void* data, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile(data, length))
, owns_ifc_file(true)
{
_initialize();
}
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, std::istream& filestream, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile(filestream, length))
, owns_ifc_file(true)
, filters_(filters)
{
_initialize();
}
@@ -23,7 +23,8 @@
#ifndef IFCGEOMFILTER_H
#define IFCGEOMFILTER_H
#include "IfcGeom.h"
#include "Kernel.h"
#include "../ifcparse/IfcFile.h"
#include <boost/foreach.hpp>
#include <boost/function.hpp>
@@ -33,15 +34,13 @@
#include <functional>
namespace IfcGeom
{
namespace IfcGeom {
/// The filter function (free or member function) or function object (use boost::ref() to reference to it)
/// should return true if the geometry for the product is wanted to be included in the output.
/// http://www.boost.org/doc/libs/1_62_0/doc/html/function/tutorial.html
typedef boost::function<bool(IfcSchema::IfcProduct*)> filter_t;
typedef boost::function<bool(IfcUtil::IfcBaseEntity*)> filter_t;
struct filter
{
struct filter {
filter() : include(false), traverse(false) {}
filter(bool incl, bool trav) : include(incl), traverse(trav) {}
/// Should the product be included (true) or excluded (false).
@@ -52,8 +51,7 @@ namespace IfcGeom
/// Optional description for the filtering criteria of this filter.
std::string description;
bool match(IfcSchema::IfcProduct* prod, const filter_t& pred) const
{
bool match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) const {
bool is_match = pred(prod);
if (!is_match && traverse) {
is_match = traverse_match(prod, pred);
@@ -61,46 +59,38 @@ namespace IfcGeom
return is_match == include;
}
static bool traverse_match(IfcSchema::IfcProduct* prod, const filter_t& pred)
{
throw std::runtime_error("todo");
/*
IfcSchema::IfcProduct* parent, *current = prod;
while ((parent = dynamic_cast<IfcSchema::IfcProduct*>(IfcGeom::Kernel::get_decomposing_entity(current))) != 0) {
static bool traverse_match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) {
IfcUtil::IfcBaseEntity* parent, *current = prod;
while ((parent = IfcGeom::Kernel::get_decomposing_entity(current)) != nullptr) {
if (pred(parent)) {
return true;
}
current = parent;
}
*/
return false;
}
};
struct wildcard_filter : public filter
{
struct wildcard_filter : public filter {
wildcard_filter() : filter(false, false) {}
wildcard_filter(bool include, bool traverse, const std::set<std::string>& patterns)
: filter(include, traverse)
{
: filter(include, traverse) {
populate(patterns);
}
std::set<boost::regex> values;
void populate(const std::set<std::string>& patterns)
{
void populate(const std::set<std::string>& patterns) {
values.clear();
BOOST_FOREACH(const std::string &pattern, patterns) {
for(auto& pattern: patterns) {
values.insert(wildcard_string_to_regex(pattern));
}
}
bool match(const std::string &str) const { return match_values(values, str); }
static bool match_values(const std::set<boost::regex>& values, const std::string &str)
{
BOOST_FOREACH(const boost::regex& r, values) {
static bool match_values(const std::set<boost::regex>& values, const std::string &str) {
for(auto& r: values) {
if (boost::regex_match(str, r)) {
return true;
}
@@ -108,11 +98,10 @@ namespace IfcGeom
return false;
}
static boost::regex wildcard_string_to_regex(std::string str)
{
static boost::regex wildcard_string_to_regex(std::string str) {
// Escape all non-"*?" regex special chars
static const std::string special_chars = "\\^.$|()[]+/";
BOOST_FOREACH(char c, special_chars) {
for(auto c: special_chars) {
std::string char_str(1, c);
boost::replace_all(str, char_str, "\\" + char_str);
}
@@ -124,127 +113,78 @@ namespace IfcGeom
};
/// @note supports only string arguments for now
struct string_arg_filter : public wildcard_filter
{
// Using this for now in order to overcome the fact that different classes have the argument at different indices.
typedef std::map<const IfcParse::declaration*, unsigned short> arg_map_t;
arg_map_t args;
struct attribute_filter : public wildcard_filter {
std::string attribute_name;
/// @todo Take only attribute name when IfcBaseClass and IfcLateBoundEntity are merged.
string_arg_filter(arg_map_t args) : args(args) { assert_arguments(); }
string_arg_filter(const IfcParse::declaration* type, unsigned short index) { args[type] = index; assert_arguments(); }
string_arg_filter(
const IfcParse::declaration* type1, unsigned short index1,
const IfcParse::declaration* type2, unsigned short index2)
{
args[type1] = index1;
args[type2] = index2;
assert_arguments();
}
attribute_filter() {}
attribute_filter(const std::string& attribute_name)
: attribute_name(attribute_name) {}
/// @todo this won't be needed when we have the generic argument name access
void assert_arguments()
{
// TODO
#if 0
for (arg_map_t::const_iterator it = args.begin(); it != args.end(); ++it) {
IfcEntityInstanceData dummy(it->first);
IfcUtil::IfcBaseClass* base = IfcSchema::SchemaEntity(&dummy);
assert(it->second < base->getArgumentCount() && "Argument index out of bounds");
assert(base->getArgumentType(it->second) == IfcUtil::Argument_STRING && "Argument type not string");
delete base;
std::string value(IfcUtil::IfcBaseEntity* prod) const {
try {
return (std::string) *prod->get(attribute_name);
} catch (...) {
// Either
// (a) not an attribute name for this entity instance
// (b) not a string attribute
// (c) null for this entity instance
// @todo: validate the filters with a reference to the schema
// probably in IfcGeomIteratorImplementation
return "<invalid>";
}
#endif
}
std::string value(IfcSchema::IfcProduct* prod) const
{
for (arg_map_t::const_iterator it = args.begin(); it != args.end(); ++it) {
if (prod->declaration().is(*it->first) && it->second < prod->data().getArgumentCount() &&
prod->data().getArgument(it->second)->type() == IfcUtil::Argument_STRING) {
Argument *arg = prod->data().getArgument(it->second);
if (!arg->isNull()) {
return *arg;
}
}
}
return "";
}
bool match(IfcUtil::IfcBaseEntity* prod) const {
return wildcard_filter::match(value(prod));
}
bool match(IfcSchema::IfcProduct* prod) const { return wildcard_filter::match(value(prod)); }
bool operator()(IfcSchema::IfcProduct* prod) const
{
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
// @note bind1st() and mem_fun() deprecated in C++11, use bind() and mem_fn() when migrating to C++11.
return filter::match(prod, std::bind1st(std::mem_fun(&string_arg_filter::match), this));
return filter::match(prod, std::bind1st(std::mem_fun(&attribute_filter::match), this));
}
void update_description()
{
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude");
std::vector<std::string> patterns;
BOOST_FOREACH(const boost::regex& r, values) {
for (auto& r : values) {
patterns.push_back("\"" + r.str() + "\"");
}
// TODO
#if 0
for (arg_map_t::const_iterator it = args.begin(); it != args.end(); ++it) {
IfcEntityInstanceData dummy(it->first);
IfcUtil::IfcBaseClass* base = IfcSchema::SchemaEntity(&dummy);
try {
ss << " " << IfcSchema::ToString::Class()(it->first) << "." << base->declaration().as_entity()->all_attributes()[it->second]->name();
} catch (const std::exception& e) {
Logger::Error(e);
}
delete base;
}
#endif
ss << " " << attribute_name;
ss << " values " << boost::algorithm::join(patterns, " ");
description = ss.str();
}
};
struct layer_filter : public wildcard_filter
{
typedef std::map<std::string, IfcSchema::IfcPresentationLayerAssignment*> layer_map_t;
struct layer_filter : public wildcard_filter {
typedef std::map<std::string, IfcUtil::IfcBaseEntity*> layer_map_t;
layer_filter() {}
layer_filter(bool include, bool traverse, const std::set<std::string>& patterns)
: wildcard_filter(include, traverse, patterns)
{
}
: wildcard_filter(include, traverse, patterns) {}
bool match(IfcSchema::IfcProduct* prod) const
{
throw std::runtime_error("todo");
/*
bool match(IfcUtil::IfcBaseEntity* prod) const {
layer_map_t layers = IfcGeom::Kernel::get_layers(prod);
return std::find_if(layers.begin(), layers.end(), wildcards_match(values)) != layers.end();
*/
}
bool operator()(IfcSchema::IfcProduct* prod) const
{
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&layer_filter::match), this));
}
struct wildcards_match
{
struct wildcards_match {
wildcards_match(const std::set<boost::regex>& patterns) : patterns(patterns) {}
bool operator()(const layer_map_t::value_type& layer_map_value) const
{
bool operator()(const layer_map_t::value_type& layer_map_value) const {
return wildcard_filter::match_values(patterns, layer_map_value.first);
}
std::set<boost::regex> patterns;
};
void update_description()
{
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " layers";
std::vector<std::string> str_values;
@@ -256,62 +196,35 @@ namespace IfcGeom
}
};
struct entity_filter : public filter
{
struct entity_filter : public filter {
std::set<std::string> entity_names;
entity_filter() {}
entity_filter(bool include, bool traverse/*, const std::set<std::string>& types*/)
entity_filter(bool include, bool traverse, const std::set<std::string>& entity_names)
: filter(include, traverse)
{
//populate(types);
}
, entity_names(entity_names) {}
std::set<const IfcParse::declaration*> values;
void populate(const std::set<std::string>&)
{
// TODO
#if 0
values.clear();
BOOST_FOREACH(const std::string& type, types) {
const IfcParse::declaration* ty;
try {
ty = IfcSchema::FromString::Class()(boost::to_upper_copy(type));
} catch (const IfcParse::IfcException&) {
throw IfcParse::IfcException("'" + type + "' does not name a valid IFC entity");
}
values.insert(ty);
/// @todo Add child classes so that containment in set can be in O(log n)
}
#endif
}
bool match(IfcSchema::IfcProduct* prod) const
{
bool match(IfcUtil::IfcBaseEntity* prod) const {
// The set is iterated over to able to filter on subtypes.
BOOST_FOREACH(const IfcParse::declaration* type, values) {
if (prod->declaration().is(*type)) {
for (auto& name : entity_names) {
if (prod->declaration().is(name)) {
return true;
}
}
return false;
}
bool operator()(IfcSchema::IfcProduct* prod) const
{
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&entity_filter::match), this));
}
void update_description()
{
// TODO
#if 0
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " entities";
BOOST_FOREACH(IfcSchema::Enum::Class() type, values) {
ss << " " << IfcSchema::ToString::Class()(type);
for (auto& name : entity_names) {
ss << " " << name;
}
description = ss.str();
#endif
}
};
}
+16 -1
View File
@@ -78,6 +78,8 @@ namespace IfcGeom {
IfcParse::IfcFile* file_;
IfcGeom::IteratorSettings settings_;
std::vector<IfcGeom::filter_t> filters_;
IteratorImplementation<P, PP>* implementation_;
public:
@@ -85,7 +87,15 @@ namespace IfcGeom {
: file_(file)
, settings_(settings)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), settings, file);
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), settings, file, filters_);
}
Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters)
: file_(file)
, settings_(settings)
, filters_(filters)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), settings, file, filters_);
}
bool initialize() {
@@ -94,6 +104,11 @@ namespace IfcGeom {
int progress() const { return implementation_->progress(); }
void compute_bounds() { implementation_->compute_bounds(); }
const gp_XYZ& bounds_min() const { return implementation_->bounds_min(); }
const gp_XYZ& bounds_max() const { return implementation_->bounds_max(); }
const std::string& unit_name() const { return implementation_->getUnitName(); }
double unit_magnitude() const { return implementation_->getUnitMagnitude(); }
@@ -31,14 +31,14 @@ void IteratorFactoryImplementation<P, PP>::bind(const std::string& schema_name,
}
template <typename P, typename PP>
IfcGeom::IteratorImplementation<P, PP>* IteratorFactoryImplementation<P, PP>::construct(const std::string& schema_name, const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) {
IfcGeom::IteratorImplementation<P, PP>* IteratorFactoryImplementation<P, PP>::construct(const std::string& schema_name, const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
typename std::map<std::string, typename get_factory_type<P, PP>::type>::const_iterator it;
it = this->find(schema_name_lower);
if (it == this->end()) {
throw IfcParse::IfcException("No geometry iterator registered for " + schema_name);
}
return it->second(settings, file);
return it->second(settings, file, filters);
}
@@ -1,9 +1,12 @@
#ifndef ITERATOR_IMPLEMENTATION_H
#define ITERATOR_IMPLEMENTATION_H
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include <gp_XYZ.hxx>
#include <boost/function.hpp>
#include <map>
@@ -20,9 +23,9 @@ namespace IfcGeom {
class BRepElement;
}
typedef boost::function2<IfcGeom::IteratorImplementation<float, float>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*> iterator_float_float_fn;
typedef boost::function2<IfcGeom::IteratorImplementation<float, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*> iterator_float_double_fn;
typedef boost::function2<IfcGeom::IteratorImplementation<double, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*> iterator_double_double_fn;
typedef boost::function3<IfcGeom::IteratorImplementation<float, float>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_float_float_fn;
typedef boost::function3<IfcGeom::IteratorImplementation<float, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_float_double_fn;
typedef boost::function3<IfcGeom::IteratorImplementation<double, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_double_double_fn;
template <typename P, typename PP>
struct get_factory_type {};
@@ -47,7 +50,7 @@ class IteratorFactoryImplementation : public std::map<std::string, typename get_
public:
IteratorFactoryImplementation();
void bind(const std::string& schema_name, typename get_factory_type<P, PP>::type fn);
IfcGeom::IteratorImplementation<P, PP>* construct(const std::string& schema_name, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*);
IfcGeom::IteratorImplementation<P, PP>* construct(const std::string& schema_name, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&);
};
template <typename P, typename PP>
@@ -59,6 +62,9 @@ namespace IfcGeom {
class IteratorImplementation {
public:
virtual bool initialize() = 0;
virtual void compute_bounds() = 0;
virtual const gp_XYZ& bounds_min() const = 0;
virtual const gp_XYZ& bounds_max() const = 0;
virtual int progress() const = 0;
virtual const std::string& getUnitName() const = 0;
virtual double getUnitMagnitude() const = 0;
+116
View File
@@ -47,3 +47,119 @@ IfcGeom::Kernel* IfcGeom::impl::KernelFactoryImplementation::construct(const std
}
return it->second(file);
}
#define CREATE_GET_DECOMPOSING_ENTITY(IfcSchema) \
\
IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduct* product) { \
IfcSchema::IfcObjectDefinition* parent = 0; \
\
/* In case of an opening element, parent to the RelatingBuildingElement */ \
if (product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { \
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; \
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); \
if (voids->size()) { \
IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); \
parent = ifc_void->RelatingBuildingElement(); \
} \
} else if (product->declaration().is(IfcSchema::IfcElement::Class())) { \
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; \
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); \
/* In case of a RelatedBuildingElement parent to the opening element */ \
if (fills->size()) { \
for (IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++it) { \
IfcSchema::IfcRelFillsElement* fill = *it; \
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); \
if (product == ifc_objectdef) continue; \
parent = ifc_objectdef; \
} \
} \
/* Else simply parent to the containing structure */ \
if (!parent) { \
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); \
if (parents->size()) { \
IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin(); \
parent = container->RelatingStructure(); \
} \
} \
} \
\
/* Parent decompositions to the RelatingObject */ \
if (!parent) { \
IfcEntityList::ptr parents = product->data().getInverse((&IfcSchema::IfcRelAggregates::Class()), -1); \
parents->push(product->data().getInverse((&IfcSchema::IfcRelNests::Class()), -1)); \
for (IfcEntityList::it it = parents->begin(); it != parents->end(); ++it) { \
IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it; \
IfcUtil::IfcBaseEntity* ifc_objectdef; \
\
ifc_objectdef = get_RelatingObject(decompose); \
\
if (product == ifc_objectdef) continue; \
parent = ifc_objectdef->as<IfcSchema::IfcObjectDefinition>(); \
} \
} \
return parent; \
}
namespace {
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc4::IfcRelDecomposes* decompose) {
Ifc4::IfcRelAggregates* aggr = decompose->as<Ifc4::IfcRelAggregates>();
if (aggr != nullptr) {
return aggr->RelatingObject();
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc2x3::IfcRelDecomposes* decompose) {
return decompose->RelatingObject();
}
CREATE_GET_DECOMPOSING_ENTITY(Ifc2x3);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4);
}
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
namespace {
template <typename Schema>
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers_impl(typename Schema::IfcProduct* prod) {
std::map<std::string, IfcUtil::IfcBaseEntity*> layers;
if (prod->hasRepresentation()) {
IfcEntityList::ptr r = IfcParse::traverse(prod->Representation());
typename Schema::IfcRepresentation::list::ptr representations = r->as<typename Schema::IfcRepresentation>();
for (typename Schema::IfcRepresentation::list::it it = representations->begin(); it != representations->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = (*it)->LayerAssignments();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
typename Schema::IfcRepresentationItem::list::ptr items = r->as<typename Schema::IfcRepresentationItem>();
for (typename Schema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = getLayerAssignments(*it)->template as<typename Schema::IfcPresentationLayerAssignment>();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
}
return layers;
}
}
std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_layers_impl<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_layers_impl<Ifc4>(inst->as<Ifc4::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
+2 -24
View File
@@ -95,30 +95,8 @@ namespace IfcGeom {
static int count(const TopoDS_Shape&, TopAbs_ShapeEnum);
template <typename Schema>
static std::map<std::string, typename Schema::IfcPresentationLayerAssignment*> get_layers(typename Schema::IfcProduct* prod) {
std::map<std::string, typename Schema::IfcPresentationLayerAssignment*> layers;
if (prod->hasRepresentation()) {
IfcEntityList::ptr r = IfcParse::traverse(prod->Representation());
typename Schema::IfcRepresentation::list::ptr representations = r->as<typename Schema::IfcRepresentation>();
for (typename Schema::IfcRepresentation::list::it it = representations->begin(); it != representations->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = (*it)->LayerAssignments();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
typename Schema::IfcRepresentationItem::list::ptr items = r->as<typename Schema::IfcRepresentationItem>();
for (typename Schema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = getLayerAssignments(*it)->template as<typename Schema::IfcPresentationLayerAssignment>();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
}
return layers;
}
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*);
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers(IfcUtil::IfcBaseEntity*);
};
namespace impl {
@@ -308,8 +308,8 @@ ptree& descend(IfcSchema::IfcObjectDefinition* product, ptree& tree) {
}
if (product->declaration().is(IfcSchema::IfcProduct::Class())) {
std::map<std::string, IfcSchema::IfcPresentationLayerAssignment*> layers = IfcGeom::Kernel::get_layers<IfcSchema>(product->as<IfcSchema::IfcProduct>());
for (std::map<std::string, IfcSchema::IfcPresentationLayerAssignment*>::const_iterator it = layers.begin(); it != layers.end(); ++it) {
std::map<std::string, IfcUtil::IfcBaseEntity*> layers = IfcGeom::Kernel::get_layers(product);
for (std::map<std::string, IfcUtil::IfcBaseEntity*>::const_iterator it = layers.begin(); it != layers.end(); ++it) {
// IfcPresentationLayerAssignments don't have GUIDs (only optional Identifier) so use name as the ID.
// Note that the IfcPresentationLayerAssignment passed here doesn't really matter as as_link is true
// for the format_entity_instance() call.