mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 22:11:36 +00:00
First slice plug-in refactor
This commit is contained in:
@@ -562,6 +562,8 @@ if(NOT Boost_VERSION LESS 105800)
|
|||||||
add_definitions(-DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE)
|
add_definitions(-DBOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(../src/plugin plugin)
|
||||||
|
|
||||||
add_subdirectory(../src/ifcparse ifcparse)
|
add_subdirectory(../src/ifcparse ifcparse)
|
||||||
set(IFCOPENSHELL_LIBRARIES IfcParse)
|
set(IFCOPENSHELL_LIBRARIES IfcParse)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "../ifcgeom/ConversionSettings.h"
|
#include "../ifcgeom/ConversionSettings.h"
|
||||||
#include "../ifcgeom/abstract_mapping.h"
|
#include "../ifcgeom/abstract_mapping.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
static const double ALMOST_ZERO = 1.e-9;
|
static const double ALMOST_ZERO = 1.e-9;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -79,6 +81,12 @@ namespace ifcopenshell {
|
|||||||
const std::string& geometry_library() const {
|
const std::string& geometry_library() const {
|
||||||
return geometry_library_;
|
return geometry_library_;
|
||||||
}
|
}
|
||||||
|
virtual std::string_view backend_id() const {
|
||||||
|
return geometry_library_;
|
||||||
|
}
|
||||||
|
virtual bool accepts(const IfcGeom::ConversionResultShape& shape) const {
|
||||||
|
return shape.backend_id() == backend_id();
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool supports_boolean_operations() const = 0;
|
virtual bool supports_boolean_operations() const = 0;
|
||||||
|
|
||||||
@@ -238,4 +246,4 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ file(GLOB SCHEMA_AGNOSTIC_CPP_FILES *.cpp)
|
|||||||
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
|
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
|
||||||
|
|
||||||
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
|
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
|
||||||
|
add_library(geometry ALIAS IfcGeom)
|
||||||
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
@@ -23,11 +24,11 @@ endif()
|
|||||||
find_package(Eigen3 REQUIRED)
|
find_package(Eigen3 REQUIRED)
|
||||||
|
|
||||||
if(WASM_BUILD)
|
if(WASM_BUILD)
|
||||||
target_link_libraries(IfcGeom ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT} "Eigen3::Eigen")
|
target_link_libraries(IfcGeom plugin ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT} "Eigen3::Eigen")
|
||||||
else()
|
else()
|
||||||
target_link_libraries(IfcGeom IfcParse ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT} "Eigen3::Eigen")
|
target_link_libraries(IfcGeom plugin IfcParse ${kernel_libraries} ${mapping_libraries} ${CMAKE_THREAD_LIBS_INIT} "Eigen3::Eigen")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(FILES ${SCHEMA_AGNOSTIC_H_FILES}
|
install(FILES ${SCHEMA_AGNOSTIC_H_FILES}
|
||||||
DESTINATION ${INCLUDEDIR}/ifcgeom
|
DESTINATION ${INCLUDEDIR}/ifcgeom
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "../ifcgeom/taxonomy.h"
|
#include "../ifcgeom/taxonomy.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -253,6 +254,7 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
class IFC_GEOM_API ConversionResultShape {
|
class IFC_GEOM_API ConversionResultShape {
|
||||||
public:
|
public:
|
||||||
|
virtual std::string_view backend_id() const = 0;
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int item_id, int surface_style_id) const = 0;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int item_id, int surface_style_id) const = 0;
|
||||||
IfcGeom::Representation::Triangulation* Triangulate(const ifcopenshell::geometry::Settings& settings) const;
|
IfcGeom::Representation::Triangulation* Triangulate(const ifcopenshell::geometry::Settings& settings) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const = 0;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const = 0;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class SerializerSettings : public SettingsContainer <
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class stream_or_filename {
|
class IFC_GEOM_API stream_or_filename {
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<std::ofstream> ofs_;
|
std::shared_ptr<std::ofstream> ofs_;
|
||||||
std::shared_ptr<std::ostringstream> oss_;
|
std::shared_ptr<std::ostringstream> oss_;
|
||||||
@@ -139,7 +139,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GeometrySerializer : public Serializer {
|
class IFC_GEOM_API GeometrySerializer : public Serializer {
|
||||||
public:
|
public:
|
||||||
enum read_type { READ_BREP, READ_TRIANGULATION };
|
enum read_type { READ_BREP, READ_TRIANGULATION };
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ protected:
|
|||||||
ifcopenshell::geometry::SerializerSettings settings_;
|
ifcopenshell::geometry::SerializerSettings settings_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WriteOnlyGeometrySerializer : public GeometrySerializer {
|
class IFC_GEOM_API WriteOnlyGeometrySerializer : public GeometrySerializer {
|
||||||
public:
|
public:
|
||||||
WriteOnlyGeometrySerializer(const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings) : GeometrySerializer(geometry_settings, settings) {}
|
WriteOnlyGeometrySerializer(const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings) : GeometrySerializer(geometry_settings, settings) {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
add_subdirectory(schema)
|
add_subdirectory(schema)
|
||||||
|
|
||||||
add_library(geometry_serializer STATIC Serialization.cpp)
|
add_library(geometry_serializer Serialization.cpp)
|
||||||
|
add_library(opencascade_geometry_ifc_writer ALIAS geometry_serializer)
|
||||||
set_target_properties(geometry_serializer PROPERTIES COMPILE_FLAGS "-DIFC_GEOMSERIALIZATION_EXPORTS")
|
set_target_properties(geometry_serializer PROPERTIES COMPILE_FLAGS "-DIFC_GEOMSERIALIZATION_EXPORTS")
|
||||||
target_link_libraries(geometry_serializer ${geometry_serializer_libraries} IfcParse)
|
target_link_libraries(geometry_serializer plugin ${geometry_serializer_libraries} IfcParse)
|
||||||
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} "geometry_serializer" ${geometry_serializer_libraries})
|
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} "geometry_serializer" ${geometry_serializer_libraries})
|
||||||
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} PARENT_SCOPE)
|
set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} PARENT_SCOPE)
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,108 @@
|
|||||||
#include "Serialization.h"
|
#include "Serialization.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include "../../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
|
||||||
|
|
||||||
#include <boost/preprocessor/stringize.hpp>
|
|
||||||
#include <boost/preprocessor/seq/for_each.hpp>
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
|
||||||
|
|
||||||
#include "../../ifcparse/file.h"
|
#include "../../ifcparse/file.h"
|
||||||
|
|
||||||
#define EXTERNAL_DEFS_1(r, data, elem) \
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
express::Base BOOST_PP_CAT(tesselate_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, double deflection);
|
#include <boost/preprocessor/stringize.hpp>
|
||||||
|
#include <boost/preprocessor/seq/for_each.hpp>
|
||||||
|
|
||||||
#define EXTERNAL_DEFS_2(r, data, elem) \
|
#include <mutex>
|
||||||
express::Base BOOST_PP_CAT(serialise_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, bool advanced);
|
|
||||||
|
|
||||||
#define CONDITIONAL_CALL(r, data, elem) \
|
namespace {
|
||||||
if (schema_name_lower == BOOST_PP_STRINGIZE(BOOST_PP_CAT(elem,))) { \
|
std::string writer_schema_key(const std::string& schema_name) {
|
||||||
return BOOST_PP_CAT(METHOD_NAME, elem)(f, shape, arg_2); \
|
return boost::to_upper_copy(schema_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS_1, , SCHEMA_SEQ);
|
ifcopenshell::plugin::module builtin_writer_module(const std::string& schema_name) {
|
||||||
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS_2, , SCHEMA_SEQ);
|
ifcopenshell::plugin::metadata metadata;
|
||||||
|
metadata.kind_ = ifcopenshell::plugin::kind::opencascade_geometry_ifc_writer;
|
||||||
|
metadata.id = "geometry.ifc_writer." + boost::to_lower_copy(schema_name);
|
||||||
|
metadata.schema = schema_name;
|
||||||
|
return ifcopenshell::plugin::module::builtin(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
#define METHOD_NAME tesselate_Ifc
|
const ifcopenshell::geometry::OpenCascadeShape& require_opencascade_shape(const IfcGeom::ConversionResultShape& shape) {
|
||||||
|
const auto* oc_shape = dynamic_cast<const ifcopenshell::geometry::OpenCascadeShape*>(&shape);
|
||||||
|
if (!oc_shape) {
|
||||||
|
throw ifcopenshell::exception("OpenCascade geometry IFC writer requires an opencascade conversion result shape");
|
||||||
|
}
|
||||||
|
return *oc_shape;
|
||||||
|
}
|
||||||
|
|
||||||
express::Base IfcGeom::tesselate(ifcopenshell::file& f, const TopoDS_Shape& shape, double arg_2) {
|
template <express::Base(*Fn)(ifcopenshell::file&, const TopoDS_Shape&, bool)>
|
||||||
auto schema_name = f.schema()->name();
|
express::Base serialise_adapter(ifcopenshell::file& f, const IfcGeom::ConversionResultShape& shape, bool advanced) {
|
||||||
|
return Fn(f, require_opencascade_shape(shape).shape(), advanced);
|
||||||
|
}
|
||||||
|
|
||||||
// @todo an ugly hack to guarantee schemas are initialised.
|
template <express::Base(*Fn)(ifcopenshell::file&, const TopoDS_Shape&, double)>
|
||||||
// @todo is this still needed? parsing a file should have initialized the schemas already.
|
express::Base tesselate_adapter(ifcopenshell::file& f, const IfcGeom::ConversionResultShape& shape, double deflection) {
|
||||||
try {
|
return Fn(f, require_opencascade_shape(shape).shape(), deflection);
|
||||||
ifcopenshell::schema_by_name("IFC2X3");
|
}
|
||||||
} catch (ifcopenshell::exception&) {}
|
|
||||||
|
|
||||||
const std::string schema_name_lower = boost::to_lower_copy(schema_name.substr(3));
|
|
||||||
|
|
||||||
BOOST_PP_SEQ_FOR_EACH(CONDITIONAL_CALL, , SCHEMA_SEQ);
|
|
||||||
|
|
||||||
throw ifcopenshell::exception("No geometry serialization available for " + schema_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef METHOD_NAME
|
#define EXTERNAL_TESSELATE(r, data, elem) \
|
||||||
#define METHOD_NAME serialise_Ifc
|
express::Base BOOST_PP_CAT(tesselate_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, double deflection);
|
||||||
|
|
||||||
express::Base IfcGeom::serialise(ifcopenshell::file& f, const TopoDS_Shape& shape, bool arg_2) {
|
#define EXTERNAL_SERIALISE(r, data, elem) \
|
||||||
auto schema_name = f.schema()->name();
|
express::Base BOOST_PP_CAT(serialise_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, bool advanced);
|
||||||
|
|
||||||
// @todo an ugly hack to guarantee schemas are initialised.
|
#define BIND_WRITER(r, data, elem) \
|
||||||
try {
|
registry.bind(BOOST_PP_STRINGIZE(BOOST_PP_CAT(Ifc, elem)), \
|
||||||
ifcopenshell::schema_by_name("IFC2X3");
|
&serialise_adapter<BOOST_PP_CAT(serialise_Ifc, elem)>, \
|
||||||
} catch (ifcopenshell::exception&) {}
|
&tesselate_adapter<BOOST_PP_CAT(tesselate_Ifc, elem)>, \
|
||||||
|
builtin_writer_module(BOOST_PP_STRINGIZE(BOOST_PP_CAT(Ifc, elem))));
|
||||||
|
|
||||||
const std::string schema_name_lower = boost::to_lower_copy(schema_name.substr(3));
|
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_TESSELATE, , SCHEMA_SEQ)
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_SERIALISE, , SCHEMA_SEQ)
|
||||||
|
|
||||||
BOOST_PP_SEQ_FOR_EACH(CONDITIONAL_CALL, , SCHEMA_SEQ);
|
IfcGeom::opencascade_geometry_ifc_writer_registry& IfcGeom::opencascade_geometry_ifc_writer_registry_instance() {
|
||||||
|
static opencascade_geometry_ifc_writer_registry registry;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, []() {
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(BIND_WRITER, , SCHEMA_SEQ)
|
||||||
|
});
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
throw ifcopenshell::exception("No geometry serialization available for " + schema_name);
|
void IfcGeom::opencascade_geometry_ifc_writer_registry::bind(const std::string& schema_name, serialise_fn serialise, tesselate_fn tesselate, const ifcopenshell::plugin::module& module) {
|
||||||
}
|
entry entry;
|
||||||
|
entry.serialise_ = serialise;
|
||||||
|
entry.tesselate_ = tesselate;
|
||||||
|
entry.module_ = module;
|
||||||
|
entries_[writer_schema_key(schema_name)] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::opencascade_geometry_ifc_writer_registry::tesselate(ifcopenshell::file& f, const ConversionResultShape& shape, double deflection) const {
|
||||||
|
const auto iter = entries_.find(writer_schema_key(f.schema()->name()));
|
||||||
|
if (iter == entries_.end()) {
|
||||||
|
throw ifcopenshell::exception("No geometry serialization available for " + f.schema()->name());
|
||||||
|
}
|
||||||
|
return iter->second.tesselate_(f, shape, deflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::opencascade_geometry_ifc_writer_registry::serialise(ifcopenshell::file& f, const ConversionResultShape& shape, bool advanced) const {
|
||||||
|
const auto iter = entries_.find(writer_schema_key(f.schema()->name()));
|
||||||
|
if (iter == entries_.end()) {
|
||||||
|
throw ifcopenshell::exception("No geometry serialization available for " + f.schema()->name());
|
||||||
|
}
|
||||||
|
return iter->second.serialise_(f, shape, advanced);
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::tesselate(ifcopenshell::file& f, const ConversionResultShape& shape, double deflection) {
|
||||||
|
return opencascade_geometry_ifc_writer_registry_instance().tesselate(f, shape, deflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::serialise(ifcopenshell::file& f, const ConversionResultShape& shape, bool advanced) {
|
||||||
|
return opencascade_geometry_ifc_writer_registry_instance().serialise(f, shape, advanced);
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::tesselate(ifcopenshell::file& f, const TopoDS_Shape& shape, double deflection) {
|
||||||
|
ifcopenshell::geometry::OpenCascadeShape converted(shape);
|
||||||
|
return tesselate(f, converted, deflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
express::Base IfcGeom::serialise(ifcopenshell::file& f, const TopoDS_Shape& shape, bool advanced) {
|
||||||
|
ifcopenshell::geometry::OpenCascadeShape converted(shape);
|
||||||
|
return serialise(f, converted, advanced);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,49 @@
|
|||||||
|
#ifndef IFC_GEOM_SERIALIZATION_H
|
||||||
|
#define IFC_GEOM_SERIALIZATION_H
|
||||||
|
|
||||||
#include "../../ifcparse/express.h"
|
#include "../../ifcparse/express.h"
|
||||||
|
#include "../../plugin/plugin.h"
|
||||||
|
#include "../../ifcgeom/ConversionResult.h"
|
||||||
|
|
||||||
#include "ifc_geomserialization_api.h"
|
#include "ifc_geomserialization_api.h"
|
||||||
|
|
||||||
#include <TopoDS_Shape.hxx>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class TopoDS_Shape;
|
||||||
|
|
||||||
|
namespace ifcopenshell {
|
||||||
|
class file;
|
||||||
|
}
|
||||||
|
|
||||||
namespace IfcGeom {
|
namespace IfcGeom {
|
||||||
|
class IFC_GEOMSERIALIZATION_API opencascade_geometry_ifc_writer_registry {
|
||||||
|
public:
|
||||||
|
typedef boost::function3<express::Base, ifcopenshell::file&, const ConversionResultShape&, double> tesselate_fn;
|
||||||
|
typedef boost::function3<express::Base, ifcopenshell::file&, const ConversionResultShape&, bool> serialise_fn;
|
||||||
|
|
||||||
|
void bind(const std::string& schema_name, serialise_fn serialise, tesselate_fn tesselate, const ifcopenshell::plugin::module& module = ifcopenshell::plugin::module());
|
||||||
|
express::Base tesselate(ifcopenshell::file& f, const ConversionResultShape& shape, double deflection) const;
|
||||||
|
express::Base serialise(ifcopenshell::file& f, const ConversionResultShape& shape, bool advanced) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct entry {
|
||||||
|
serialise_fn serialise_;
|
||||||
|
tesselate_fn tesselate_;
|
||||||
|
ifcopenshell::plugin::module module_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, entry> entries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
IFC_GEOMSERIALIZATION_API opencascade_geometry_ifc_writer_registry& opencascade_geometry_ifc_writer_registry_instance();
|
||||||
|
|
||||||
|
IFC_GEOMSERIALIZATION_API express::Base tesselate(ifcopenshell::file& f, const ConversionResultShape& shape, double deflection);
|
||||||
|
IFC_GEOMSERIALIZATION_API express::Base serialise(ifcopenshell::file& f, const ConversionResultShape& shape, bool advanced);
|
||||||
IFC_GEOMSERIALIZATION_API express::Base tesselate(ifcopenshell::file& f, const TopoDS_Shape& shape, double deflection);
|
IFC_GEOMSERIALIZATION_API express::Base tesselate(ifcopenshell::file& f, const TopoDS_Shape& shape, double deflection);
|
||||||
IFC_GEOMSERIALIZATION_API express::Base serialise(ifcopenshell::file& f, const TopoDS_Shape& shape, bool advanced);
|
IFC_GEOMSERIALIZATION_API express::Base serialise(ifcopenshell::file& f, const TopoDS_Shape& shape, bool advanced);
|
||||||
} // namespace IfcGeom
|
} // namespace IfcGeom
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -20,9 +20,10 @@
|
|||||||
#ifndef SERIALIZER_H
|
#ifndef SERIALIZER_H
|
||||||
#define SERIALIZER_H
|
#define SERIALIZER_H
|
||||||
|
|
||||||
|
#include "ifc_geom_api.h"
|
||||||
#include "../ifcparse/file.h"
|
#include "../ifcparse/file.h"
|
||||||
|
|
||||||
class Serializer {
|
class IFC_GEOM_API Serializer {
|
||||||
public:
|
public:
|
||||||
virtual ~Serializer() {}
|
virtual ~Serializer() {}
|
||||||
|
|
||||||
@@ -32,4 +33,4 @@ public:
|
|||||||
virtual void setFile(ifcopenshell::file*) = 0;
|
virtual void setFile(ifcopenshell::file*) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,47 +4,80 @@
|
|||||||
|
|
||||||
#include <boost/preprocessor/stringize.hpp>
|
#include <boost/preprocessor/stringize.hpp>
|
||||||
#include <boost/preprocessor/seq/for_each.hpp>
|
#include <boost/preprocessor/seq/for_each.hpp>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#ifndef SCHEMA_SEQ
|
#ifndef SCHEMA_SEQ
|
||||||
static_assert(false, "A boost preprocessor sequence of schema identifiers is needed for this file to compile.");
|
static_assert(false, "A boost preprocessor sequence of schema identifiers is needed for this file to compile.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Declares the schema-based external kernel initialization routines:
|
||||||
|
// - extern void init_MappingImplementation_Ifc2x3(IfcGeom::impl::mapping_registry*);
|
||||||
|
// - ...
|
||||||
|
#define EXTERNAL_DEFS(r, data, elem) \
|
||||||
|
extern void BOOST_PP_CAT(init_MappingImplementation_Ifc, elem)(ifcopenshell::geometry::impl::mapping_registry*);
|
||||||
|
|
||||||
|
// Declares the schema-based external iterator initialization routines:
|
||||||
|
// - init_MappingImplementation_Ifc2x3(this);
|
||||||
|
// - ...
|
||||||
|
#define CALL_DEFS(r, data, elem) \
|
||||||
|
BOOST_PP_CAT(init_MappingImplementation_Ifc, elem)(®istry);
|
||||||
|
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS, , SCHEMA_SEQ)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string mapping_key(const std::string& schema_name) {
|
||||||
|
return boost::to_lower_copy(schema_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module builtin_mapping_module(const std::string& schema_name) {
|
||||||
|
ifcopenshell::plugin::metadata metadata;
|
||||||
|
metadata.kind_ = ifcopenshell::plugin::kind::mapping;
|
||||||
|
metadata.id = "geometry.mapping." + boost::to_lower_copy(schema_name);
|
||||||
|
metadata.schema = schema_name;
|
||||||
|
return ifcopenshell::plugin::module::builtin(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::geometry::impl::mapping_registry& ifcopenshell::geometry::impl::mapping_registry_instance() {
|
||||||
|
static mapping_registry registry;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, []() {
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(CALL_DEFS, , SCHEMA_SEQ)
|
||||||
|
});
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::geometry::impl::mapping_registry::bind(const std::string& schema_name, ifcopenshell::geometry::impl::mapping_fn fn, const plugin::module& module) {
|
||||||
|
auto& entry = entries_[mapping_key(schema_name)];
|
||||||
|
entry.fn_ = fn;
|
||||||
|
entry.module_ = module.meta().id.empty() ? builtin_mapping_module(schema_name) : module;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::geometry::abstract_mapping* ifcopenshell::geometry::impl::mapping_registry::construct(ifcopenshell::file* file, Settings& s) {
|
||||||
|
const std::string schema_name_lower = boost::to_lower_copy(file->schema()->name());
|
||||||
|
const auto it = entries_.find(schema_name_lower);
|
||||||
|
if (it == entries_.end()) {
|
||||||
|
throw ifcopenshell::exception("No geometry mapping registered for " + schema_name_lower);
|
||||||
|
}
|
||||||
|
auto new_mapping = it->second.fn_(file, s);
|
||||||
|
new_mapping->initialize_settings();
|
||||||
|
return new_mapping;
|
||||||
|
}
|
||||||
|
|
||||||
ifcopenshell::geometry::impl::MappingFactoryImplementation& ifcopenshell::geometry::impl::mapping_implementations() {
|
ifcopenshell::geometry::impl::MappingFactoryImplementation& ifcopenshell::geometry::impl::mapping_implementations() {
|
||||||
static MappingFactoryImplementation impl;
|
static MappingFactoryImplementation impl;
|
||||||
return impl;
|
return impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declares the schema-based external kernel initialization routines:
|
|
||||||
// - extern void init_MappingImplementation_Ifc2x3(IfcGeom::impl::MappingFactoryImplementation*);
|
|
||||||
// - ...
|
|
||||||
#define EXTERNAL_DEFS(r, data, elem) \
|
|
||||||
extern void BOOST_PP_CAT(init_MappingImplementation_Ifc, elem)(ifcopenshell::geometry::impl::MappingFactoryImplementation*);
|
|
||||||
|
|
||||||
// Declares the schema-based external iterator initialization routines:
|
|
||||||
// - init_MappingImplementation_Ifc2x3(this);
|
|
||||||
// - ...
|
|
||||||
#define CALL_DEFS(r, data, elem) \
|
|
||||||
BOOST_PP_CAT(init_MappingImplementation_Ifc, elem)(this);
|
|
||||||
|
|
||||||
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS, , SCHEMA_SEQ)
|
|
||||||
|
|
||||||
ifcopenshell::geometry::impl::MappingFactoryImplementation::MappingFactoryImplementation() {
|
ifcopenshell::geometry::impl::MappingFactoryImplementation::MappingFactoryImplementation() {
|
||||||
BOOST_PP_SEQ_FOR_EACH(CALL_DEFS, , SCHEMA_SEQ)
|
mapping_registry_instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::geometry::impl::MappingFactoryImplementation::bind(const std::string& schema_name, ifcopenshell::geometry::impl::mapping_fn fn) {
|
void ifcopenshell::geometry::impl::MappingFactoryImplementation::bind(const std::string& schema_name, ifcopenshell::geometry::impl::mapping_fn fn) {
|
||||||
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
|
mapping_registry_instance().bind(schema_name, fn, builtin_mapping_module(schema_name));
|
||||||
this->insert(std::make_pair(schema_name_lower, fn));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ifcopenshell::geometry::abstract_mapping* ifcopenshell::geometry::impl::MappingFactoryImplementation::construct(ifcopenshell::file* file, Settings& s) {
|
ifcopenshell::geometry::abstract_mapping* ifcopenshell::geometry::impl::MappingFactoryImplementation::construct(ifcopenshell::file* file, Settings& s) {
|
||||||
const std::string schema_name_lower = boost::to_lower_copy(file->schema()->name());
|
return mapping_registry_instance().construct(file, s);
|
||||||
std::map<std::string, ifcopenshell::geometry::impl::mapping_fn>::const_iterator it;
|
|
||||||
it = this->find(schema_name_lower);
|
|
||||||
if (it == end()) {
|
|
||||||
throw ifcopenshell::exception("No geometry mapping registered for " + schema_name_lower);
|
|
||||||
}
|
|
||||||
auto new_mapping = it->second(file, s);
|
|
||||||
new_mapping->initialize_settings();
|
|
||||||
return new_mapping;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "../ifcparse/express.h"
|
#include "../ifcparse/express.h"
|
||||||
#include "../ifcgeom/taxonomy.h"
|
#include "../ifcgeom/taxonomy.h"
|
||||||
#include "../ifcgeom/ConversionSettings.h"
|
#include "../ifcgeom/ConversionSettings.h"
|
||||||
|
#include "../plugin/plugin.h"
|
||||||
|
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
@@ -79,7 +80,23 @@ namespace geometry {
|
|||||||
namespace impl {
|
namespace impl {
|
||||||
typedef boost::function2<abstract_mapping*, ifcopenshell::file*, Settings&> mapping_fn;
|
typedef boost::function2<abstract_mapping*, ifcopenshell::file*, Settings&> mapping_fn;
|
||||||
|
|
||||||
class IFC_GEOM_API MappingFactoryImplementation : public std::map<std::string, mapping_fn> {
|
class IFC_GEOM_API mapping_registry {
|
||||||
|
public:
|
||||||
|
void bind(const std::string& schema_name, mapping_fn fn, const plugin::module& module = plugin::module());
|
||||||
|
abstract_mapping* construct(ifcopenshell::file* file, Settings& settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct entry {
|
||||||
|
mapping_fn fn_;
|
||||||
|
plugin::module module_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, entry> entries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
IFC_GEOM_API mapping_registry& mapping_registry_instance();
|
||||||
|
|
||||||
|
class IFC_GEOM_API MappingFactoryImplementation {
|
||||||
public:
|
public:
|
||||||
MappingFactoryImplementation();
|
MappingFactoryImplementation();
|
||||||
void bind(const std::string& schema_name, mapping_fn);
|
void bind(const std::string& schema_name, mapping_fn);
|
||||||
|
|||||||
+2
-132
@@ -21,52 +21,7 @@
|
|||||||
#define HYBRID_KERNEL_H
|
#define HYBRID_KERNEL_H
|
||||||
|
|
||||||
#include "AbstractKernel.h"
|
#include "AbstractKernel.h"
|
||||||
|
#include "kernel_registry.h"
|
||||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
|
||||||
#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h"
|
|
||||||
#undef Handle
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_CGAL
|
|
||||||
#include "../ifcgeom/kernels/cgal/CgalKernel.h"
|
|
||||||
#undef CGAL_KERNEL_H
|
|
||||||
#undef CGALCONVERSIONRESULT_H
|
|
||||||
#define IFOPSH_SIMPLE_KERNEL
|
|
||||||
#include "../ifcgeom/kernels/cgal/CgalKernel.h"
|
|
||||||
#undef CgalKernel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_MANIFOLD
|
|
||||||
#include "../ifcgeom/kernels/manifold/ManifoldKernel.h"
|
|
||||||
#endif
|
|
||||||
#include "../ifcgeom/kernels/passthrough/PassthroughKernel.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
inline bool is_valid_for_kernel(const ifcopenshell::geometry::kernels::AbstractKernel* k, const IfcGeom::ConversionResult& shp) {
|
|
||||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
|
||||||
if (k->geometry_library() == "opencascade") {
|
|
||||||
return dynamic_cast<ifcopenshell::geometry::OpenCascadeShape*>(shp.Shape().get()) != nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef IFOPSH_WITH_CGAL
|
|
||||||
if (k->geometry_library() == "cgal-simple") {
|
|
||||||
return dynamic_cast<ifcopenshell::geometry::SimpleCgalShape*>(shp.Shape().get()) != nullptr;
|
|
||||||
}
|
|
||||||
if (k->geometry_library() == "cgal") {
|
|
||||||
return dynamic_cast<ifcopenshell::geometry::CgalShape*>(shp.Shape().get()) != nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef IFOPSH_WITH_MANIFOLD
|
|
||||||
if (k->geometry_library() == "manifold") {
|
|
||||||
return dynamic_cast<ifcopenshell::geometry::ManifoldShape*>(shp.Shape().get()) != nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (k->geometry_library() == "passthrough") {
|
|
||||||
return dynamic_cast<ifcopenshell::geometry::PassthroughShape*>(shp.Shape().get()) != nullptr;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ifcopenshell {
|
namespace ifcopenshell {
|
||||||
namespace geometry {
|
namespace geometry {
|
||||||
@@ -154,7 +109,7 @@ namespace ifcopenshell {
|
|||||||
for (auto& k : kernels_) {
|
for (auto& k : kernels_) {
|
||||||
bool is_valid = true;
|
bool is_valid = true;
|
||||||
for (auto& s : entity_shapes) {
|
for (auto& s : entity_shapes) {
|
||||||
if (!is_valid_for_kernel(k.get(), s)) {
|
if (!k->accepts(*s.Shape())) {
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -182,91 +137,6 @@ namespace ifcopenshell {
|
|||||||
return new HybridKernel(geometry_library(), file_, const_cast<Settings&>(settings()), std::move(ks));
|
return new HybridKernel(geometry_library(), file_, const_cast<Settings&>(settings()), std::move(ks));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<AbstractKernel> construct(ifcopenshell::file* file, const std::string& geometry_library, Settings& conv_settings) {
|
|
||||||
std::string geometry_library_lower = boost::to_lower_copy(geometry_library);
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
|
||||||
if (geometry_library_lower == "opencascade") {
|
|
||||||
return std::make_unique<IfcGeom::OpenCascadeKernel>(conv_settings);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_CGAL
|
|
||||||
if (geometry_library_lower == "cgal") {
|
|
||||||
return std::make_unique<CgalKernel>(conv_settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geometry_library_lower == "cgal-simple") {
|
|
||||||
return std::make_unique<SimpleCgalKernel>(conv_settings);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_MANIFOLD
|
|
||||||
if (geometry_library_lower == "manifold") {
|
|
||||||
return std::make_unique<ManifoldKernel>(conv_settings);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (geometry_library_lower == "passthrough") {
|
|
||||||
return std::make_unique<PassthroughKernel>(conv_settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geometry_library_lower.rfind("hybrid-", 0) == 0) {
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("hybrid"));
|
|
||||||
std::vector<std::unique_ptr<AbstractKernel>> kernels;
|
|
||||||
while (!geometry_library_lower.empty()) {
|
|
||||||
if (geometry_library_lower.find("-", 0) == 0) {
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("-"));
|
|
||||||
} else {
|
|
||||||
throw ifcopenshell::exception("Invalid hybrid kernel " + geometry_library);
|
|
||||||
}
|
|
||||||
auto n = kernels.size();
|
|
||||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
|
||||||
if (geometry_library_lower.find("opencascade", 0) == 0) {
|
|
||||||
kernels.emplace_back(new IfcGeom::OpenCascadeKernel(conv_settings));
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("opencascade"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IFOPSH_WITH_CGAL
|
|
||||||
if (geometry_library_lower.find("cgal-simple", 0) == 0) {
|
|
||||||
kernels.emplace_back(new SimpleCgalKernel(conv_settings));
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("cgal-simple"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geometry_library_lower.find("cgal", 0) == 0) {
|
|
||||||
kernels.emplace_back(new CgalKernel(conv_settings));
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("cgal"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef IFOPSH_WITH_MANIFOLD
|
|
||||||
if (geometry_library_lower.find("manifold", 0) == 0) {
|
|
||||||
kernels.emplace_back(new ManifoldKernel(conv_settings));
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("manifold"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (geometry_library_lower.find("passthrough", 0) == 0) {
|
|
||||||
kernels.emplace_back(new PassthroughKernel(conv_settings));
|
|
||||||
geometry_library_lower = geometry_library_lower.substr(strlen("passthrough"));
|
|
||||||
}
|
|
||||||
if (kernels.size() != n + 1) {
|
|
||||||
throw ifcopenshell::exception("Invalid hybrid kernel " + geometry_library);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = kernels.begin(); it != kernels.end(); ++it) {
|
|
||||||
(**it).propagate_exceptions = it == kernels.begin();
|
|
||||||
(**it).partial_success_is_success = it == kernels.end() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!kernels.empty()) {
|
|
||||||
return std::make_unique<HybridKernel>(geometry_library, file, conv_settings, std::move(kernels));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw ifcopenshell::exception("No geometry kernel registered for " + geometry_library);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "kernel_registry.h"
|
||||||
|
|
||||||
|
#include "../ifcgeom/hybrid_kernel.h"
|
||||||
|
#include "../ifcparse/file.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||||
|
#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h"
|
||||||
|
#undef Handle
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IFOPSH_WITH_CGAL
|
||||||
|
#include "../ifcgeom/kernels/cgal/CgalKernel.h"
|
||||||
|
#undef CGAL_KERNEL_H
|
||||||
|
#undef CGALCONVERSIONRESULT_H
|
||||||
|
#define IFOPSH_SIMPLE_KERNEL
|
||||||
|
#include "../ifcgeom/kernels/cgal/CgalKernel.h"
|
||||||
|
#undef CgalKernel
|
||||||
|
#undef IFOPSH_SIMPLE_KERNEL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IFOPSH_WITH_MANIFOLD
|
||||||
|
#include "../ifcgeom/kernels/manifold/ManifoldKernel.h"
|
||||||
|
#endif
|
||||||
|
#include "../ifcgeom/kernels/passthrough/PassthroughKernel.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string kernel_key(const std::string& backend_id) {
|
||||||
|
return boost::to_lower_copy(backend_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module builtin_kernel_module(const std::string& backend_id) {
|
||||||
|
ifcopenshell::plugin::metadata metadata;
|
||||||
|
metadata.kind_ = ifcopenshell::plugin::kind::kernel;
|
||||||
|
metadata.id = "geometry.kernel." + kernel_key(backend_id);
|
||||||
|
return ifcopenshell::plugin::module::builtin(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_builtin_kernels(ifcopenshell::geometry::kernels::kernel_registry& registry) {
|
||||||
|
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||||
|
ifcopenshell::geometry::kernels::kernel_info opencascade_info;
|
||||||
|
opencascade_info.backend_id = "opencascade";
|
||||||
|
opencascade_info.supports_boolean_operations = true;
|
||||||
|
registry.bind(opencascade_info, [](ifcopenshell::file*, ifcopenshell::geometry::Settings& settings) { return new IfcGeom::OpenCascadeKernel(settings); }, builtin_kernel_module("opencascade"));
|
||||||
|
#endif
|
||||||
|
#ifdef IFOPSH_WITH_CGAL
|
||||||
|
ifcopenshell::geometry::kernels::kernel_info cgal_info;
|
||||||
|
cgal_info.backend_id = "cgal";
|
||||||
|
cgal_info.supports_boolean_operations = true;
|
||||||
|
registry.bind(cgal_info, [](ifcopenshell::file*, ifcopenshell::geometry::Settings& settings) { return new ifcopenshell::geometry::kernels::CgalKernel(settings); }, builtin_kernel_module("cgal"));
|
||||||
|
|
||||||
|
ifcopenshell::geometry::kernels::kernel_info cgal_simple_info;
|
||||||
|
cgal_simple_info.backend_id = "cgal-simple";
|
||||||
|
cgal_simple_info.supports_boolean_operations = false;
|
||||||
|
registry.bind(cgal_simple_info, [](ifcopenshell::file*, ifcopenshell::geometry::Settings& settings) { return new ifcopenshell::geometry::kernels::SimpleCgalKernel(settings); }, builtin_kernel_module("cgal-simple"));
|
||||||
|
#endif
|
||||||
|
#ifdef IFOPSH_WITH_MANIFOLD
|
||||||
|
ifcopenshell::geometry::kernels::kernel_info manifold_info;
|
||||||
|
manifold_info.backend_id = "manifold";
|
||||||
|
manifold_info.supports_boolean_operations = true;
|
||||||
|
registry.bind(manifold_info, [](ifcopenshell::file*, ifcopenshell::geometry::Settings& settings) { return new ifcopenshell::geometry::kernels::ManifoldKernel(settings); }, builtin_kernel_module("manifold"));
|
||||||
|
#endif
|
||||||
|
ifcopenshell::geometry::kernels::kernel_info passthrough_info;
|
||||||
|
passthrough_info.backend_id = "passthrough";
|
||||||
|
passthrough_info.supports_boolean_operations = false;
|
||||||
|
registry.bind(passthrough_info, [](ifcopenshell::file*, ifcopenshell::geometry::Settings& settings) { return new ifcopenshell::geometry::kernels::PassthroughKernel(settings); }, builtin_kernel_module("passthrough"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::geometry::kernels::kernel_registry::bind(const kernel_info& info, create_fn create, const plugin::module& module) {
|
||||||
|
entry entry;
|
||||||
|
entry.info_ = info;
|
||||||
|
entry.create_ = create;
|
||||||
|
entry.module_ = module;
|
||||||
|
entries_[kernel_key(info.backend_id)] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ifcopenshell::geometry::kernels::kernel_registry::has(const std::string& backend_id) const {
|
||||||
|
return entries_.find(kernel_key(backend_id)) != entries_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ifcopenshell::geometry::kernels::AbstractKernel> ifcopenshell::geometry::kernels::kernel_registry::create(const std::string& backend_id, ifcopenshell::file* file, Settings& settings) const {
|
||||||
|
const auto iter = entries_.find(kernel_key(backend_id));
|
||||||
|
if (iter == entries_.end()) {
|
||||||
|
throw ifcopenshell::exception("No geometry kernel registered for " + backend_id);
|
||||||
|
}
|
||||||
|
return std::unique_ptr<AbstractKernel>(iter->second.create_(file, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ifcopenshell::geometry::kernels::kernel_info> ifcopenshell::geometry::kernels::kernel_registry::kernels() const {
|
||||||
|
std::vector<kernel_info> result;
|
||||||
|
for (const auto& pair : entries_) {
|
||||||
|
result.push_back(pair.second.info_);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::geometry::kernels::kernel_registry& ifcopenshell::geometry::kernels::kernel_registry_instance() {
|
||||||
|
static kernel_registry registry;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, register_builtin_kernels, std::ref(registry));
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ifcopenshell::geometry::kernels::AbstractKernel> ifcopenshell::geometry::kernels::construct(ifcopenshell::file* file, const std::string& geometry_library, Settings& settings) {
|
||||||
|
auto geometry_library_lower = boost::to_lower_copy(geometry_library);
|
||||||
|
auto& registry = kernel_registry_instance();
|
||||||
|
|
||||||
|
if (registry.has(geometry_library_lower)) {
|
||||||
|
return registry.create(geometry_library_lower, file, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry_library_lower.rfind("hybrid-", 0) == 0) {
|
||||||
|
geometry_library_lower = geometry_library_lower.substr(strlen("hybrid"));
|
||||||
|
std::vector<std::unique_ptr<AbstractKernel>> kernels;
|
||||||
|
while (!geometry_library_lower.empty()) {
|
||||||
|
if (geometry_library_lower.find("-", 0) == 0) {
|
||||||
|
geometry_library_lower = geometry_library_lower.substr(strlen("-"));
|
||||||
|
} else {
|
||||||
|
throw ifcopenshell::exception("Invalid hybrid kernel " + geometry_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string matched_backend_id;
|
||||||
|
for (const auto& info : registry.kernels()) {
|
||||||
|
const auto backend_id = kernel_key(info.backend_id);
|
||||||
|
if (geometry_library_lower.rfind(backend_id, 0) == 0 && backend_id.size() > matched_backend_id.size()) {
|
||||||
|
matched_backend_id = backend_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched_backend_id.empty()) {
|
||||||
|
throw ifcopenshell::exception("Invalid hybrid kernel " + geometry_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
kernels.push_back(registry.create(matched_backend_id, file, settings));
|
||||||
|
geometry_library_lower = geometry_library_lower.substr(matched_backend_id.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = kernels.begin(); it != kernels.end(); ++it) {
|
||||||
|
(**it).propagate_exceptions = it == kernels.begin();
|
||||||
|
(**it).partial_success_is_success = it == kernels.end() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kernels.empty()) {
|
||||||
|
return std::make_unique<HybridKernel>(geometry_library, file, settings, std::move(kernels));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ifcopenshell::exception("No geometry kernel registered for " + geometry_library);
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef KERNEL_REGISTRY_H
|
||||||
|
#define KERNEL_REGISTRY_H
|
||||||
|
|
||||||
|
#include "../ifcgeom/AbstractKernel.h"
|
||||||
|
#include "../plugin/plugin.h"
|
||||||
|
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ifcopenshell {
|
||||||
|
class file;
|
||||||
|
|
||||||
|
namespace geometry {
|
||||||
|
namespace kernels {
|
||||||
|
|
||||||
|
struct IFC_GEOM_API kernel_info {
|
||||||
|
std::string backend_id;
|
||||||
|
bool supports_boolean_operations = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IFC_GEOM_API kernel_registry {
|
||||||
|
public:
|
||||||
|
typedef boost::function2<AbstractKernel*, ifcopenshell::file*, Settings&> create_fn;
|
||||||
|
|
||||||
|
void bind(const kernel_info& info, create_fn create, const plugin::module& module = plugin::module());
|
||||||
|
bool has(const std::string& backend_id) const;
|
||||||
|
std::unique_ptr<AbstractKernel> create(const std::string& backend_id, ifcopenshell::file* file, Settings& settings) const;
|
||||||
|
std::vector<kernel_info> kernels() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct entry {
|
||||||
|
kernel_info info_;
|
||||||
|
create_fn create_;
|
||||||
|
plugin::module module_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, entry> entries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
IFC_GEOM_API kernel_registry& kernel_registry_instance();
|
||||||
|
IFC_GEOM_API std::unique_ptr<AbstractKernel> construct(ifcopenshell::file* file, const std::string& geometry_library, Settings& settings);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -208,6 +208,13 @@ namespace ifcopenshell { namespace geometry {
|
|||||||
|
|
||||||
operator const cgal_shape_t& () const { to_poly(); return *shape_; }
|
operator const cgal_shape_t& () const { to_poly(); return *shape_; }
|
||||||
const cgal_shape_t& poly() const { to_poly(); return *shape_; }
|
const cgal_shape_t& poly() const { to_poly(); return *shape_; }
|
||||||
|
virtual std::string_view backend_id() const {
|
||||||
|
#ifdef IFOPSH_SIMPLE_KERNEL
|
||||||
|
return "cgal-simple";
|
||||||
|
#else
|
||||||
|
return "cgal";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
||||||
@@ -284,6 +291,13 @@ namespace ifcopenshell { namespace geometry {
|
|||||||
shape_.reset(new halfspace_tree_plane<Kernel_>(shape));
|
shape_.reset(new halfspace_tree_plane<Kernel_>(shape));
|
||||||
planes_.push_back(shape);
|
planes_.push_back(shape);
|
||||||
}
|
}
|
||||||
|
virtual std::string_view backend_id() const {
|
||||||
|
#ifdef IFOPSH_SIMPLE_KERNEL
|
||||||
|
return "cgal-simple";
|
||||||
|
#else
|
||||||
|
return "cgal";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
|
|
||||||
const std::vector<ManifoldPart>& parts() const { return parts_; }
|
const std::vector<ManifoldPart>& parts() const { return parts_; }
|
||||||
std::optional<manifold::Manifold> as_manifold() const;
|
std::optional<manifold::Manifold> as_manifold() const;
|
||||||
|
virtual std::string_view backend_id() const { return "manifold"; }
|
||||||
|
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ namespace ifcopenshell {
|
|||||||
|
|
||||||
const TopoDS_Shape& shape() const { return shape_; }
|
const TopoDS_Shape& shape() const { return shape_; }
|
||||||
operator const TopoDS_Shape& () { return shape_; }
|
operator const TopoDS_Shape& () { return shape_; }
|
||||||
|
virtual std::string_view backend_id() const { return "opencascade"; }
|
||||||
|
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
||||||
@@ -113,4 +114,4 @@ namespace ifcopenshell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
explicit PassthroughShape(std::vector<PassthroughPart>&& parts);
|
explicit PassthroughShape(std::vector<PassthroughPart>&& parts);
|
||||||
|
|
||||||
const std::vector<PassthroughPart>& parts() const { return parts_; }
|
const std::vector<PassthroughPart>& parts() const { return parts_; }
|
||||||
|
virtual std::string_view backend_id() const { return "passthrough"; }
|
||||||
|
|
||||||
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
virtual void Triangulate(ifcopenshell::geometry::Settings settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int item_id, int surface_style_id) const;
|
||||||
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MAKE_INIT_FN(MappingImplementation)(ifcopenshell::geometry::impl::MappingFactoryImplementation* mapping) {
|
void MAKE_INIT_FN(MappingImplementation)(ifcopenshell::geometry::impl::mapping_registry* mapping) {
|
||||||
static const std::string schema_name = STRINGIFY(IfcSchema);
|
static const std::string schema_name = STRINGIFY(IfcSchema);
|
||||||
POSTFIX_SCHEMA(factory_t) factory;
|
POSTFIX_SCHEMA(factory_t) factory;
|
||||||
mapping->bind(schema_name, factory);
|
mapping->bind(schema_name, factory);
|
||||||
|
|||||||
@@ -590,7 +590,7 @@ const std::string& ifcopenshell::geometry::taxonomy::kind_to_string(kinds k) {
|
|||||||
return values[k];
|
return values[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic_uint32_t item::counter_(0);
|
IFC_GEOM_API std::atomic_uint32_t item::counter_(0);
|
||||||
|
|
||||||
void ifcopenshell::geometry::taxonomy::item::print(std::ostream& o, int indent) const {
|
void ifcopenshell::geometry::taxonomy::item::print(std::ostream& o, int indent) const {
|
||||||
o << std::string(indent, ' ') << kind_to_string(kind()) << std::endl;
|
o << std::string(indent, ' ') << kind_to_string(kind()) << std::endl;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ list(APPEND IFCPARSE_CPP_FILES
|
|||||||
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
|
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
|
||||||
|
|
||||||
add_library(IfcParse ${IFCPARSE_FILES})
|
add_library(IfcParse ${IFCPARSE_FILES})
|
||||||
|
add_library(parse ALIAS IfcParse)
|
||||||
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
|
||||||
if(IFCXML_SUPPORT)
|
if(IFCXML_SUPPORT)
|
||||||
@@ -49,9 +50,9 @@ if(IFCXML_SUPPORT)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WASM_BUILD)
|
if(WASM_BUILD)
|
||||||
target_link_libraries(IfcParse ${BCRYPT_LIBRARIES})
|
target_link_libraries(IfcParse plugin ${BCRYPT_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
target_link_libraries(IfcParse ${Boost_LIBRARIES} ${BCRYPT_LIBRARIES})
|
target_link_libraries(IfcParse plugin ${Boost_LIBRARIES} ${BCRYPT_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# CMake installation targets
|
# CMake installation targets
|
||||||
|
|||||||
@@ -25,11 +25,12 @@
|
|||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "ifc_parse_api.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(IFCOPENSHELL_BRANCH) && defined(IFCOPENSHELL_COMMIT)
|
#if defined(IFCOPENSHELL_BRANCH) && defined(IFCOPENSHELL_COMMIT)
|
||||||
const char *IFCOPENSHELL_VERSION = STRINGIFY(IFCOPENSHELL_BRANCH) "-" STRINGIFY(IFCOPENSHELL_COMMIT);
|
IFC_PARSE_API const char *IFCOPENSHELL_VERSION = STRINGIFY(IFCOPENSHELL_BRANCH) "-" STRINGIFY(IFCOPENSHELL_COMMIT);
|
||||||
#else
|
#else
|
||||||
const char *IFCOPENSHELL_VERSION = "0.8.0";
|
IFC_PARSE_API const char *IFCOPENSHELL_VERSION = "0.8.0";
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
extern const char *IFCOPENSHELL_VERSION;
|
extern IFC_PARSE_API const char *IFCOPENSHELL_VERSION;
|
||||||
|
|
||||||
namespace ifcopenshell {
|
namespace ifcopenshell {
|
||||||
|
|
||||||
@@ -59,6 +59,9 @@ class IFC_PARSE_API spf_lexer {
|
|||||||
mutable size_t pool_index = 0;
|
mutable size_t pool_index = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
spf_lexer(const spf_lexer&) = delete;
|
||||||
|
spf_lexer& operator=(const spf_lexer&) = delete;
|
||||||
|
|
||||||
std::string& get_temp_string() const;
|
std::string& get_temp_string() const;
|
||||||
void reset_pool() const {
|
void reset_pool() const {
|
||||||
pool_index = 0;
|
pool_index = 0;
|
||||||
|
|||||||
+110
-100
@@ -22,6 +22,7 @@
|
|||||||
#include "express.h"
|
#include "express.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#ifdef HAS_SCHEMA_2x3
|
#ifdef HAS_SCHEMA_2x3
|
||||||
#include "schemas/Ifc2x3.h"
|
#include "schemas/Ifc2x3.h"
|
||||||
@@ -128,7 +129,60 @@ ifcopenshell::entity::~entity() {
|
|||||||
delete inverse_attribute;
|
delete inverse_attribute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static std::map<std::string, const ifcopenshell::schema_definition*> schemas;
|
namespace {
|
||||||
|
std::string schema_key(const std::string& schema_name) {
|
||||||
|
return boost::to_upper_copy(schema_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module builtin_schema_module(const std::string& schema_name) {
|
||||||
|
ifcopenshell::plugin::metadata metadata;
|
||||||
|
metadata.kind_ = ifcopenshell::plugin::kind::parse_schema;
|
||||||
|
metadata.id = "parse.schema." + boost::to_lower_copy(schema_name);
|
||||||
|
metadata.schema = schema_name;
|
||||||
|
return ifcopenshell::plugin::module::builtin(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_builtin_schemas(ifcopenshell::schema_registry& registry) {
|
||||||
|
registry.bind("HEADER_SECTION_SCHEMA", &Header_section_schema::get_schema, &Header_section_schema::clear_schema, builtin_schema_module("HEADER_SECTION_SCHEMA"));
|
||||||
|
#ifdef HAS_SCHEMA_2x3
|
||||||
|
registry.bind("IFC2X3", &Ifc2x3::get_schema, &Ifc2x3::clear_schema, builtin_schema_module("IFC2X3"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4
|
||||||
|
registry.bind("IFC4", &Ifc4::get_schema, &Ifc4::clear_schema, builtin_schema_module("IFC4"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x1
|
||||||
|
registry.bind("IFC4X1", &Ifc4x1::get_schema, &Ifc4x1::clear_schema, builtin_schema_module("IFC4X1"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x2
|
||||||
|
registry.bind("IFC4X2", &Ifc4x2::get_schema, &Ifc4x2::clear_schema, builtin_schema_module("IFC4X2"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_rc1
|
||||||
|
registry.bind("IFC4X3_RC1", &Ifc4x3_rc1::get_schema, &Ifc4x3_rc1::clear_schema, builtin_schema_module("IFC4X3_RC1"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_rc2
|
||||||
|
registry.bind("IFC4X3_RC2", &Ifc4x3_rc2::get_schema, &Ifc4x3_rc2::clear_schema, builtin_schema_module("IFC4X3_RC2"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_rc3
|
||||||
|
registry.bind("IFC4X3_RC3", &Ifc4x3_rc3::get_schema, &Ifc4x3_rc3::clear_schema, builtin_schema_module("IFC4X3_RC3"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_rc4
|
||||||
|
registry.bind("IFC4X3_RC4", &Ifc4x3_rc4::get_schema, &Ifc4x3_rc4::clear_schema, builtin_schema_module("IFC4X3_RC4"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3
|
||||||
|
registry.bind("IFC4X3", &Ifc4x3::get_schema, &Ifc4x3::clear_schema, builtin_schema_module("IFC4X3"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_tc1
|
||||||
|
registry.bind("IFC4X3_TC1", &Ifc4x3_tc1::get_schema, &Ifc4x3_tc1::clear_schema, builtin_schema_module("IFC4X3_TC1"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_add1
|
||||||
|
registry.bind("IFC4X3_ADD1", &Ifc4x3_add1::get_schema, &Ifc4x3_add1::clear_schema, builtin_schema_module("IFC4X3_ADD1"));
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_SCHEMA_4x3_add2
|
||||||
|
registry.bind("IFC4X3_ADD2", &Ifc4x3_add2::get_schema, &Ifc4x3_add2::clear_schema, builtin_schema_module("IFC4X3_ADD2"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ifcopenshell::schema_definition::schema_definition(const std::string& name, const std::vector<const declaration*>& declarations)
|
ifcopenshell::schema_definition::schema_definition(const std::string& name, const std::vector<const declaration*>& declarations)
|
||||||
: name_(name)
|
: name_(name)
|
||||||
@@ -151,7 +205,7 @@ ifcopenshell::schema_definition::schema_definition(const std::string& name, cons
|
|||||||
entities_.push_back((**it).as_entity());
|
entities_.push_back((**it).as_entity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
schemas[name_] = this;
|
register_schema(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ifcopenshell::schema_definition::~schema_definition() {
|
ifcopenshell::schema_definition::~schema_definition() {
|
||||||
@@ -161,111 +215,67 @@ ifcopenshell::schema_definition::~schema_definition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::register_schema(schema_definition* schema) {
|
void ifcopenshell::register_schema(schema_definition* schema) {
|
||||||
schemas.insert({boost::to_upper_copy(schema->name()), schema});
|
schema_registry_instance().bind(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::schema_registry& ifcopenshell::schema_registry_instance() {
|
||||||
|
static schema_registry registry;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, register_builtin_schemas, std::ref(registry));
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::schema_registry::bind(const std::string& schema_name, get_schema_fn get, clear_schema_fn clear, const plugin::module& module) {
|
||||||
|
auto& entry = entries_[schema_key(schema_name)];
|
||||||
|
entry.get_ = get;
|
||||||
|
entry.clear_ = clear;
|
||||||
|
entry.module_ = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::schema_registry::bind(schema_definition* schema) {
|
||||||
|
auto& entry = entries_[schema_key(schema->name())];
|
||||||
|
entry.schema_ = schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ifcopenshell::schema_definition* ifcopenshell::schema_registry::get(const std::string& schema_name) {
|
||||||
|
auto iter = entries_.find(schema_key(schema_name));
|
||||||
|
if (iter == entries_.end()) {
|
||||||
|
throw ifcopenshell::exception("No schema named " + schema_name);
|
||||||
|
}
|
||||||
|
if (!iter->second.schema_ && iter->second.get_) {
|
||||||
|
iter->second.schema_ = &iter->second.get_();
|
||||||
|
}
|
||||||
|
if (!iter->second.schema_) {
|
||||||
|
throw ifcopenshell::exception("No schema named " + schema_name);
|
||||||
|
}
|
||||||
|
return iter->second.schema_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> ifcopenshell::schema_registry::names() const {
|
||||||
|
std::vector<std::string> names;
|
||||||
|
for (const auto& pair : entries_) {
|
||||||
|
names.push_back(pair.first);
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::schema_registry::clear() {
|
||||||
|
for (auto& pair : entries_) {
|
||||||
|
if (pair.second.clear_) {
|
||||||
|
pair.second.clear_();
|
||||||
|
}
|
||||||
|
pair.second.schema_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ifcopenshell::schema_definition* ifcopenshell::schema_by_name(const std::string& name) {
|
const ifcopenshell::schema_definition* ifcopenshell::schema_by_name(const std::string& name) {
|
||||||
// TODO: initialize automatically somehow
|
return schema_registry_instance().get(name);
|
||||||
Header_section_schema::get_schema();
|
|
||||||
#ifdef HAS_SCHEMA_2x3
|
|
||||||
Ifc2x3::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4
|
|
||||||
Ifc4::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x1
|
|
||||||
Ifc4x1::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x2
|
|
||||||
Ifc4x2::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc1
|
|
||||||
Ifc4x3_rc1::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc2
|
|
||||||
Ifc4x3_rc2::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc3
|
|
||||||
Ifc4x3_rc3::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc4
|
|
||||||
Ifc4x3_rc4::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3
|
|
||||||
Ifc4x3::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_tc1
|
|
||||||
Ifc4x3_tc1::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_add1
|
|
||||||
Ifc4x3_add1::get_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_add2
|
|
||||||
Ifc4x3_add2::get_schema();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::map<std::string, const ifcopenshell::schema_definition*>::const_iterator iter = schemas.find(boost::to_upper_copy(name));
|
|
||||||
if (iter == schemas.end()) {
|
|
||||||
throw ifcopenshell::exception("No schema named " + name);
|
|
||||||
}
|
|
||||||
return iter->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ifcopenshell::schema_names() {
|
std::vector<std::string> ifcopenshell::schema_names() {
|
||||||
// Load schema modules
|
return schema_registry_instance().names();
|
||||||
try {
|
|
||||||
ifcopenshell::schema_by_name("IFC2X3");
|
|
||||||
} catch (ifcopenshell::exception&) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate vector with map keys
|
|
||||||
std::vector<std::string> return_value;
|
|
||||||
for (auto& pair : schemas) {
|
|
||||||
return_value.push_back(pair.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::clear_schemas() {
|
void ifcopenshell::clear_schemas() {
|
||||||
#ifdef HAS_SCHEMA_2x3
|
schema_registry_instance().clear();
|
||||||
Ifc2x3::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4
|
|
||||||
Ifc4::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x1
|
|
||||||
Ifc4x1::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x2
|
|
||||||
Ifc4x2::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc1
|
|
||||||
Ifc4x3_rc1::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc2
|
|
||||||
Ifc4x3_rc2::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc3
|
|
||||||
Ifc4x3_rc3::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_rc4
|
|
||||||
Ifc4x3_rc4::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3
|
|
||||||
Ifc4x3::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_tc1
|
|
||||||
Ifc4x3_tc1::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_add1
|
|
||||||
Ifc4x3_add1::clear_schema();
|
|
||||||
#endif
|
|
||||||
#ifdef HAS_SCHEMA_4x3_add2
|
|
||||||
Ifc4x3_add2::clear_schema();
|
|
||||||
#endif
|
|
||||||
Header_section_schema::clear_schema();
|
|
||||||
|
|
||||||
// Schemas are owned by their respective modules in a unique_ptr, so just clear the map
|
|
||||||
schemas.clear();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,13 @@
|
|||||||
#define IFCSCHEMA_H
|
#define IFCSCHEMA_H
|
||||||
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "../plugin/plugin.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -497,6 +499,30 @@ class IFC_PARSE_API schema_definition {
|
|||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IFC_PARSE_API schema_registry {
|
||||||
|
public:
|
||||||
|
typedef const schema_definition& (*get_schema_fn)();
|
||||||
|
typedef void (*clear_schema_fn)();
|
||||||
|
|
||||||
|
void bind(const std::string& schema_name, get_schema_fn get, clear_schema_fn clear, const plugin::module& module = plugin::module());
|
||||||
|
void bind(schema_definition* schema);
|
||||||
|
const schema_definition* get(const std::string& schema_name);
|
||||||
|
std::vector<std::string> names() const;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct entry {
|
||||||
|
const schema_definition* schema_ = nullptr;
|
||||||
|
get_schema_fn get_ = nullptr;
|
||||||
|
clear_schema_fn clear_ = nullptr;
|
||||||
|
plugin::module module_;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, entry> entries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
IFC_PARSE_API schema_registry& schema_registry_instance();
|
||||||
|
|
||||||
IFC_PARSE_API const schema_definition* schema_by_name(const std::string& schema_name);
|
IFC_PARSE_API const schema_definition* schema_by_name(const std::string& schema_name);
|
||||||
|
|
||||||
IFC_PARSE_API std::vector<std::string> schema_names();
|
IFC_PARSE_API std::vector<std::string> schema_names();
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
file(GLOB PLUGIN_H_FILES *.h)
|
||||||
|
file(GLOB PLUGIN_CPP_FILES *.cpp)
|
||||||
|
|
||||||
|
add_library(plugin ${PLUGIN_CPP_FILES} ${PLUGIN_H_FILES})
|
||||||
|
set_target_properties(plugin PROPERTIES
|
||||||
|
COMPILE_FLAGS "-DPLUGIN_EXPORTS"
|
||||||
|
VERSION "${PROJECT_VERSION}"
|
||||||
|
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(plugin PRIVATE
|
||||||
|
BOOST_DLL_USE_STD_FS
|
||||||
|
PLUGIN_IFCOPENSHELL_VERSION="${PROJECT_VERSION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(plugin PRIVATE ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
install(TARGETS plugin)
|
||||||
|
|
||||||
|
install(FILES ${PLUGIN_H_FILES}
|
||||||
|
DESTINATION ${INCLUDEDIR}/plugin
|
||||||
|
)
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
#include <boost/dll/shared_library.hpp>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using plugin_abi_fn = ifcopenshell::plugin::abi_info(*)();
|
||||||
|
using plugin_metadata_fn = ifcopenshell::plugin::metadata(*)();
|
||||||
|
|
||||||
|
std::string compiler_id() {
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
return "msvc";
|
||||||
|
#elif defined(__clang__)
|
||||||
|
return "clang";
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return "gcc";
|
||||||
|
#else
|
||||||
|
return "unknown";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string compiler_version() {
|
||||||
|
#if defined(_MSC_FULL_VER)
|
||||||
|
return std::to_string(_MSC_FULL_VER);
|
||||||
|
#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
|
||||||
|
return std::to_string(__clang_major__) + "." + std::to_string(__clang_minor__) + "." + std::to_string(__clang_patchlevel__);
|
||||||
|
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||||
|
return std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__);
|
||||||
|
#else
|
||||||
|
return "unknown";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_debug_build() {
|
||||||
|
#if defined(NDEBUG)
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ifcopenshell::plugin::module::data {
|
||||||
|
metadata metadata_;
|
||||||
|
std::filesystem::path path_;
|
||||||
|
std::shared_ptr<boost::dll::shared_library> library_;
|
||||||
|
};
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module::module()
|
||||||
|
: data_(std::make_shared<data>())
|
||||||
|
{}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module::module(const metadata& metadata)
|
||||||
|
: data_(std::make_shared<data>())
|
||||||
|
{
|
||||||
|
data_->metadata_ = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module::module(std::shared_ptr<data> data)
|
||||||
|
: data_(std::move(data))
|
||||||
|
{}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module ifcopenshell::plugin::module::builtin(const metadata& metadata) {
|
||||||
|
return module(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ifcopenshell::plugin::metadata& ifcopenshell::plugin::module::meta() const {
|
||||||
|
return data_->metadata_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::filesystem::path& ifcopenshell::plugin::module::path() const {
|
||||||
|
return data_->path_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ifcopenshell::plugin::module::is_dynamic() const {
|
||||||
|
return data_->library_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ifcopenshell::plugin::module::is_loaded() const {
|
||||||
|
return data_->library_ && data_->library_->is_loaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::manager::manager() = default;
|
||||||
|
|
||||||
|
void ifcopenshell::plugin::manager::add_search_path(const std::filesystem::path& path) {
|
||||||
|
search_paths_.push_back(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::filesystem::path>& ifcopenshell::plugin::manager::search_paths() const {
|
||||||
|
return search_paths_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::module ifcopenshell::plugin::manager::load(const std::filesystem::path& path) const {
|
||||||
|
auto library = std::make_shared<boost::dll::shared_library>(path, boost::dll::load_mode::default_mode);
|
||||||
|
auto abi = library->get_alias<plugin_abi_fn>("ifcopenshell_plugin_abi_v1")();
|
||||||
|
validate_abi(abi);
|
||||||
|
auto metadata = library->get_alias<plugin_metadata_fn>("ifcopenshell_plugin_metadata_v1")();
|
||||||
|
|
||||||
|
auto data = std::make_shared<module::data>();
|
||||||
|
data->metadata_ = metadata;
|
||||||
|
data->path_ = path;
|
||||||
|
data->library_ = std::move(library);
|
||||||
|
return module(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ifcopenshell::plugin::abi_info ifcopenshell::plugin::host_abi() {
|
||||||
|
abi_info abi;
|
||||||
|
abi.debug_build = is_debug_build();
|
||||||
|
abi.compiler_id = compiler_id();
|
||||||
|
abi.compiler_version = compiler_version();
|
||||||
|
abi.ifcopenshell_version = PLUGIN_IFCOPENSHELL_VERSION;
|
||||||
|
return abi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifcopenshell::plugin::validate_abi(const abi_info& abi) {
|
||||||
|
const auto host = host_abi();
|
||||||
|
if (abi.plugin_api_version == host.plugin_api_version &&
|
||||||
|
abi.pointer_size == host.pointer_size &&
|
||||||
|
abi.debug_build == host.debug_build &&
|
||||||
|
abi.compiler_id == host.compiler_id &&
|
||||||
|
abi.compiler_version == host.compiler_version) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << "Incompatible plugin ABI";
|
||||||
|
stream << " (plugin api " << abi.plugin_api_version << ", host api " << host.plugin_api_version << ")";
|
||||||
|
stream << " (plugin compiler " << abi.compiler_id << " " << abi.compiler_version;
|
||||||
|
stream << ", host compiler " << host.compiler_id << " " << host.compiler_version << ")";
|
||||||
|
stream << " (plugin pointer size " << abi.pointer_size << ", host pointer size " << host.pointer_size << ")";
|
||||||
|
stream << " (plugin debug " << abi.debug_build << ", host debug " << host.debug_build << ")";
|
||||||
|
throw std::runtime_error(stream.str());
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCOPENSHELL_PLUGIN_H
|
||||||
|
#define IFCOPENSHELL_PLUGIN_H
|
||||||
|
|
||||||
|
#include "plugin_api.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ifcopenshell {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
enum class kind {
|
||||||
|
parse_schema,
|
||||||
|
mapping,
|
||||||
|
kernel,
|
||||||
|
document_serializer,
|
||||||
|
geometry_serializer,
|
||||||
|
opencascade_geometry_ifc_writer
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PLUGIN_API abi_info {
|
||||||
|
uint32_t plugin_api_version = 1;
|
||||||
|
uint32_t pointer_size = sizeof(void*);
|
||||||
|
bool debug_build = false;
|
||||||
|
std::string compiler_id;
|
||||||
|
std::string compiler_version;
|
||||||
|
std::string ifcopenshell_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PLUGIN_API metadata {
|
||||||
|
kind kind_ = kind::kernel;
|
||||||
|
std::string id;
|
||||||
|
std::string schema;
|
||||||
|
std::string format;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PLUGIN_API module {
|
||||||
|
public:
|
||||||
|
module();
|
||||||
|
explicit module(const metadata& metadata);
|
||||||
|
|
||||||
|
static module builtin(const metadata& metadata);
|
||||||
|
|
||||||
|
const metadata& meta() const;
|
||||||
|
const std::filesystem::path& path() const;
|
||||||
|
bool is_dynamic() const;
|
||||||
|
bool is_loaded() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct data;
|
||||||
|
std::shared_ptr<data> data_;
|
||||||
|
|
||||||
|
explicit module(std::shared_ptr<data> data);
|
||||||
|
|
||||||
|
friend class manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PLUGIN_API manager {
|
||||||
|
public:
|
||||||
|
manager();
|
||||||
|
|
||||||
|
void add_search_path(const std::filesystem::path& path);
|
||||||
|
const std::vector<std::filesystem::path>& search_paths() const;
|
||||||
|
|
||||||
|
module load(const std::filesystem::path& path) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::filesystem::path> search_paths_;
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_API abi_info host_abi();
|
||||||
|
PLUGIN_API void validate_abi(const abi_info& abi);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef PLUGIN_API_H
|
||||||
|
#define PLUGIN_API_H
|
||||||
|
|
||||||
|
#ifdef IFC_SHARED_BUILD
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef PLUGIN_EXPORTS
|
||||||
|
#define PLUGIN_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define PLUGIN_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define PLUGIN_API __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define PLUGIN_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@ file(GLOB SERIALIZERS_CPP_FILES *.cpp)
|
|||||||
set(SERIALIZERS_FILES ${SERIALIZERS_H_FILES} ${SERIALIZERS_CPP_FILES})
|
set(SERIALIZERS_FILES ${SERIALIZERS_H_FILES} ${SERIALIZERS_CPP_FILES})
|
||||||
|
|
||||||
add_library(Serializers ${SERIALIZERS_FILES})
|
add_library(Serializers ${SERIALIZERS_FILES})
|
||||||
|
add_library(serialization ALIAS Serializers)
|
||||||
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
set(SERIALIZER_SCHEMA_LIBRARIES Serializers ${SERIALIZER_SCHEMA_LIBRARIES} PARENT_SCOPE)
|
set(SERIALIZER_SCHEMA_LIBRARIES Serializers ${SERIALIZER_SCHEMA_LIBRARIES} PARENT_SCOPE)
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ endif()
|
|||||||
target_link_libraries(Serializers
|
target_link_libraries(Serializers
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES}
|
${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES}
|
||||||
IfcGeom ${OpenCASCADE_LIBRARIES} ${kernel_libraries} IfcParse
|
IfcGeom ${OpenCASCADE_LIBRARIES} IfcParse
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS Serializers)
|
install(TARGETS Serializers)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ set(SERIALIZERS_S_FILES ${SERIALIZERS_S_H_FILES} ${SERIALIZERS_S_CPP_FILES})
|
|||||||
foreach(schema ${SCHEMA_VERSIONS})
|
foreach(schema ${SCHEMA_VERSIONS})
|
||||||
add_library(Serializers_ifc${schema} OBJECT ${SERIALIZERS_S_FILES})
|
add_library(Serializers_ifc${schema} OBJECT ${SERIALIZERS_S_FILES})
|
||||||
set(SERIALIZER_SCHEMA_LIBRARIES ${SERIALIZER_SCHEMA_LIBRARIES} Serializers_ifc${schema})
|
set(SERIALIZER_SCHEMA_LIBRARIES ${SERIALIZER_SCHEMA_LIBRARIES} Serializers_ifc${schema})
|
||||||
set_target_properties(Serializers_ifc${schema} PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS -DIfcSchema=Ifc${schema}")
|
set_target_properties(Serializers_ifc${schema} PROPERTIES COMPILE_FLAGS "-DSERIALIZERS_EXPORTS -DIfcSchema=Ifc${schema}")
|
||||||
if(WASM_BUILD)
|
if(WASM_BUILD)
|
||||||
target_link_libraries(Serializers_ifc${schema} ${HDF5_LIBRARIES})
|
target_link_libraries(Serializers_ifc${schema} ${HDF5_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
|
|||||||
Reference in New Issue
Block a user