Crazy factory implementation

This commit is contained in:
Thomas Krijnen
2017-12-19 20:24:00 +01:00
parent a792a7e2c7
commit f4463d2935
8 changed files with 179 additions and 53 deletions
+12 -15
View File
@@ -551,20 +551,11 @@ if(NOT MSVC)
endif()
endif()
set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom_ifc2x3 IfcGeom_ifc4)
set(IFCOPENSHELL_LIBRARIES IfcParse IfcGeom IfcGeom_ifc2x3 IfcGeom_ifc4 Iterator)
# IfcParse
file(GLOB IFCPARSE_H_FILES ../src/ifcparse/*.h)
file(GLOB IFCPARSE_CPP_FILES ../src/ifcparse/*.cpp)
foreach(IFC_RELEASE ${IFC_RELEASE_NOT_USED})
files_for_ifc_version(${IFC_RELEASE} SOURCE_FILES_NOT_USED)
foreach(SOURCE_FILE ${SOURCE_FILES_NOT_USED})
list(REMOVE_ITEM IFCPARSE_CPP_FILES ${SOURCE_FILE})
list(REMOVE_ITEM IFCPARSE_H_FILES ${SOURCE_FILE})
endforeach()
endforeach()
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
add_library(IfcParse ${IFCPARSE_FILES})
@@ -582,16 +573,22 @@ set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES})
add_library(IfcGeom_ifc2x3 ${IFCGEOM_FILES})
add_library(IfcGeom_ifc4 ${IFCGEOM_FILES})
set_target_properties(IfcGeom_ifc2x3 PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
set_target_properties(IfcGeom_ifc4 PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
set_target_properties(IfcGeom_ifc2x3 PROPERTIES COMPILE_FLAGS -DIfcSchema=Ifc2x3)
set_target_properties(IfcGeom_ifc2x3 PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc2x3")
# TODO: Detect based on IfcSchema
set_target_properties(IfcGeom_ifc4 PROPERTIES COMPILE_FLAGS "-DIfcSchema=Ifc4 -DUSE_IFC4")
set_target_properties(IfcGeom_ifc4 PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc4 -DUSE_IFC4")
TARGET_LINK_LIBRARIES(IfcGeom_ifc2x3 IfcParse ${OPENCASCADE_LIBRARIES})
TARGET_LINK_LIBRARIES(IfcGeom_ifc4 IfcParse ${OPENCASCADE_LIBRARIES})
# Iterator
file(GLOB ITERATOR_H_FILES ../src/iterator/*.h)
file(GLOB ITERATOR_CPP_FILES ../src/iterator/*.cpp)
set(ITERATOR_FILES ${ITERATOR_H_FILES} ${ITERATOR_CPP_FILES})
add_library(Iterator ${ITERATOR_FILES})
set_target_properties(Iterator PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
TARGET_LINK_LIBRARIES(Iterator IfcGeom_ifc2x3 IfcGeom_ifc4)
# IfcConvert
file(GLOB IFCCONVERT_CPP_FILES ../src/ifcconvert/*.cpp)
file(GLOB IFCCONVERT_H_FILES ../src/ifcconvert/*.h)
+1 -1
View File
@@ -124,7 +124,7 @@ namespace IfcGeom {
const std::string& context() const { return _context; }
const std::string& unique_id() const { return _unique_id; }
const Transformation<P>& transformation() const { return _transformation; }
IfcSchema::IfcProduct* product() const { return product_; }
IfcUtil::IfcBaseClass* product() const { return product_; }
const std::vector<const IfcGeom::Element<P>*> parents() const { return _parents; }
void SetParents(std::vector<const IfcGeom::Element<P>*> newparents) { _parents = newparents; }
+22 -12
View File
@@ -123,15 +123,15 @@ namespace IfcGeom
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<IfcSchema::Enum::Class(), unsigned short> arg_map_t;
typedef std::map<const IfcParse::declaration*, unsigned short> arg_map_t;
arg_map_t args;
/// @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(IfcSchema::Enum::Class() type, unsigned short index) { args[type] = index; assert_arguments(); }
string_arg_filter(const IfcParse::declaration* type, unsigned short index) { args[type] = index; assert_arguments(); }
string_arg_filter(
IfcSchema::Enum::Class() type1, unsigned short index1,
IfcSchema::Enum::Class() type2, unsigned short index2)
const IfcParse::declaration* type1, unsigned short index1,
const IfcParse::declaration* type2, unsigned short index2)
{
args[type1] = index1;
args[type2] = index2;
@@ -141,7 +141,8 @@ namespace IfcGeom
/// @todo this won't be needed when we have the generic argument name access
void assert_arguments()
{
#ifndef NDEBUG
// 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);
@@ -155,7 +156,7 @@ namespace IfcGeom
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() &&
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()) {
@@ -184,9 +185,11 @@ namespace IfcGeom
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);
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) {
@@ -194,6 +197,7 @@ namespace IfcGeom
}
delete base;
}
#endif
ss << " values " << boost::algorithm::join(patterns, " ");
description = ss.str();
@@ -254,13 +258,15 @@ namespace IfcGeom
//populate(types);
}
std::set<IfcSchema::Enum::Class()> values;
std::set<const IfcParse::declaration*> values;
void populate(const std::set<std::string>& types)
void populate(const std::set<std::string>&)
{
// TODO
#if 0
values.clear();
foreach(const std::string& type, types) {
IfcSchema::Enum::Class() ty;
const IfcParse::declaration* ty;
try {
ty = IfcSchema::FromString::Class()(boost::to_upper_copy(type));
} catch (const IfcParse::IfcException&) {
@@ -269,13 +275,14 @@ namespace IfcGeom
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
{
// The set is iterated over to able to filter on subtypes.
foreach(IfcSchema::Enum::Class() type, values) {
if (prod->declaration().is(type)) {
foreach(const IfcParse::declaration* type, values) {
if (prod->declaration().is(*type)) {
return true;
}
}
@@ -289,12 +296,15 @@ namespace IfcGeom
void update_description()
{
// TODO
#if 0
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " entities";
foreach(IfcSchema::Enum::Class() type, values) {
ss << " " << IfcSchema::ToString::Class()(type);
}
description = ss.str();
#endif
}
};
}
@@ -0,0 +1,33 @@
#include "IfcGeomIteratorImplementation.h"
#include "../iterator/IteratorImplementation.h"
namespace IfcGeom {
template class MAKE_TYPE_NAME(IteratorImplementation_)<float>;
template class MAKE_TYPE_NAME(IteratorImplementation_)<double>;
}
#define MAKE_INIT_FN__(a, b) init_ ## a ## b
#define MAKE_INIT_FN_(a, b) MAKE_INIT_FN__(a, b)
#define MAKE_INIT_FN(t) MAKE_INIT_FN_(t, IfcSchema)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
void MAKE_INIT_FN(IteratorImplementation_)() {
static const std::string schema_name = TOSTRING(IfcSchema);
struct {
IteratorImplementation<float>* operator()(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) const {
return new IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<float>(settings, file);
}
} factory_float;
struct {
IteratorImplementation<double>* operator()(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file) const {
return new IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<double>(settings, file);
}
} factory_double;
static Registrar< IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<float> > float_registration(schema_name, factory_float);
static Registrar< IfcGeom::MAKE_TYPE_NAME(IteratorImplementation_)<double> > double_registration(schema_name, factory_double);
}
@@ -82,6 +82,8 @@
#include "../ifcgeom/IfcRepresentationShapeItem.h"
#include "../ifcgeom/IfcGeomFilter.h"
#include "../iterator/IteratorImplementation.h"
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
#ifdef min
#undef min
@@ -90,13 +92,18 @@
#undef max
#endif
#define MAKE_TYPE_NAME__(a, b) a ## b
#define MAKE_TYPE_NAME_(a, b) MAKE_TYPE_NAME__(a, b)
#define MAKE_TYPE_NAME(t) MAKE_TYPE_NAME_(t, IfcSchema)
namespace IfcGeom {
template <typename P>
class Iterator {
class MAKE_TYPE_NAME(IteratorImplementation_) : public IteratorImplementation<P> {
private:
Iterator(const Iterator&); // N/I
Iterator& operator=(const Iterator&); // N/I
MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
Kernel kernel;
IteratorSettings settings;
@@ -136,7 +143,7 @@ namespace IfcGeom {
};
void initUnits() {
IfcSchema::IfcProject::list::ptr projects = ifc_file->entitiesByType<IfcSchema::IfcProject>();
IfcSchema::IfcProject::list::ptr projects = ifc_file->instances_by_type<IfcSchema::IfcProject>();
if (projects->size() == 1) {
IfcSchema::IfcProject* project = *projects->begin();
std::pair<std::string, double> length_unit = kernel.initializeUnits(project->UnitsInContext());
@@ -147,7 +154,9 @@ namespace IfcGeom {
/// @todo public/private sections all over the place: move all public to the beginning of the class
public:
Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file, std::vector<IfcGeom::filter_t>& filters)
typedef P Precision;
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)
@@ -191,7 +200,7 @@ namespace IfcGeom {
IfcSchema::IfcGeometricRepresentationContext::list::it it;
IfcSchema::IfcGeometricRepresentationSubContext::list::it jt;
IfcSchema::IfcGeometricRepresentationContext::list::ptr contexts =
ifc_file->entitiesByType<IfcSchema::IfcGeometricRepresentationContext>();
ifc_file->instances_by_type<IfcSchema::IfcGeometricRepresentationContext>();
IfcSchema::IfcGeometricRepresentationContext::list::ptr filtered_contexts (new IfcSchema::IfcGeometricRepresentationContext::list);
@@ -286,7 +295,7 @@ namespace IfcGeom {
bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity());
}
IfcSchema::IfcProduct::list::ptr products = ifc_file->entitiesByType<IfcSchema::IfcProduct>();
IfcSchema::IfcProduct::list::ptr products = ifc_file->instances_by_type<IfcSchema::IfcProduct>();
for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) {
IfcSchema::IfcProduct* product = *iter;
if (product->hasObjectPlacement()) {
@@ -493,7 +502,7 @@ namespace IfcGeom {
/// Moves to the next shape representation, create its geometry, and returns the associated product.
/// Use get() to retrieve the created geometry.
IfcSchema::IfcProduct* next() {
IfcUtil::IfcBaseClass* next() {
// Increment the iterator over the list of products using the current
// shape representation
if (ifcproducts) {
@@ -575,8 +584,8 @@ namespace IfcGeom {
IfcSchema::IfcProduct* ifc_product = 0;
try {
IfcUtil::IfcBaseClass* ifc_entity = ifc_file->entityById(id);
instance_type = IfcSchema::ToString::Class()(ifc_entity->declaration().type());
IfcUtil::IfcBaseClass* ifc_entity = ifc_file->instance_by_id(id);
instance_type = ifc_entity->declaration().name();
if (ifc_entity->declaration().is(IfcSchema::IfcRoot::Class())) {
IfcSchema::IfcRoot* ifc_root = ifc_entity->as<IfcSchema::IfcRoot>();
@@ -624,7 +633,7 @@ namespace IfcGeom {
return ifc_object;
}
IfcSchema::IfcProduct* create() {
IfcUtil::IfcBaseClass* create() {
IfcGeom::BRepElement<P>* next_shape_model = 0;
IfcGeom::SerializedElement<P>* next_serialization = 0;
IfcGeom::TriangulationElement<P>* next_triangulation = 0;
@@ -684,45 +693,42 @@ namespace IfcGeom {
kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES)
? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
if (settings.get(IteratorSettings::SITE_LOCAL_PLACEMENT)) {
kernel.set_conversion_placement_rel_to(IfcSchema::IfcSite::Class());
kernel.set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class());
}
}
bool owns_ifc_file;
public:
Iterator(const IteratorSettings& settings, IfcParse::IfcFile* file)
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, IfcParse::IfcFile* file)
: settings(settings)
, ifc_file(file)
, owns_ifc_file(false)
{
_initialize();
}
Iterator(const IteratorSettings& settings, const std::string& filename)
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, const std::string& filename)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
, ifc_file(new IfcParse::IfcFile(filename))
, owns_ifc_file(true)
{
ifc_file->Init(filename);
_initialize();
}
Iterator(const IteratorSettings& settings, void* data, int length)
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, void* data, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
, ifc_file(new IfcParse::IfcFile(data, length))
, owns_ifc_file(true)
{
ifc_file->Init(data, length);
_initialize();
}
Iterator(const IteratorSettings& settings, std::istream& filestream, int length)
MAKE_TYPE_NAME(IteratorImplementation_)(const IteratorSettings& settings, std::istream& filestream, int length)
: settings(settings)
, ifc_file(new IfcParse::IfcFile)
, ifc_file(new IfcParse::IfcFile(filestream, length))
, owns_ifc_file(true)
{
ifc_file->Init(filestream, length);
_initialize();
}
~Iterator() {
~MAKE_TYPE_NAME(IteratorImplementation_)() {
if (owns_ifc_file) {
delete ifc_file;
}
+2 -2
View File
@@ -48,8 +48,8 @@ private:
static const char* severity_strings[];
static boost::optional<IfcUtil::IfcBaseClass*> current_product;
public:
template <typename Schema>
static void SetProduct(boost::optional<typename Schema::IfcProduct*> product) {
static void SetProduct(boost::optional<IfcUtil::IfcBaseClass*> product) {
current_product = product;
}
+26
View File
@@ -0,0 +1,26 @@
#include "IteratorImplementation.h"
template <typename P>
IteratorFactoryImplementation<P>& iterator_implementations() {
static IteratorFactoryImplementation<P> impl;
return impl;
}
template IteratorFactoryImplementation<float>& iterator_implementations<float>();
template IteratorFactoryImplementation<double>& iterator_implementations<double>();
#define INIT(a) extern void init_##a(); init_##a();
template <typename P>
IteratorFactoryImplementation<P>::IteratorFactoryImplementation() {
INIT(IteratorImplementation_Ifc2x3);
INIT(IteratorImplementation_Ifc4);
}
template <class P>
void IteratorFactoryImplementation<P>::bind(const std::string& schema_name, typename get_factory_type<P>::type fn) {
this->insert(std::make_pair(schema_name, fn));
}
template IteratorFactoryImplementation<float>;
template IteratorFactoryImplementation<double>;
+54
View File
@@ -0,0 +1,54 @@
#ifndef ITERATOR_IMPLEMENTATION_H
#define ITERATOR_IMPLEMENTATION_H
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeomIteratorSettings.h"
#include <boost/function.hpp>
#include <map>
#include <string>
template <typename P>
class IteratorImplementation;
typedef boost::function2<IteratorImplementation<float>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*> iterator_float_fn;
typedef boost::function2<IteratorImplementation<double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*> iterator_double_fn;
template <typename P>
struct get_factory_type {};
template <>
struct get_factory_type<float> {
typedef iterator_float_fn type;
};
template <>
struct get_factory_type<double> {
typedef iterator_double_fn type;
};
template <typename P>
class IteratorFactoryImplementation : public std::map<std::string, typename get_factory_type<P>::type> {
public:
IteratorFactoryImplementation();
void bind(const std::string& schema_name, typename get_factory_type<P>::type fn);
};
template <typename P>
IteratorFactoryImplementation<P>& iterator_implementations();
template <class T>
class Registrar {
public:
Registrar(const std::string& schema_name, const typename get_factory_type<typename T::Precision>::type& fn) {
iterator_implementations<typename T::Precision>().bind(schema_name, fn);
}
};
template <typename T>
class IteratorImplementation {
};
#endif