mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-30 16:43:00 +00:00
First slice plug-in refactor
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
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")
|
||||
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} PARENT_SCOPE)
|
||||
|
||||
|
||||
@@ -1,59 +1,108 @@
|
||||
#include "Serialization.h"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include "../../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
|
||||
#include "../../ifcparse/file.h"
|
||||
|
||||
#define EXTERNAL_DEFS_1(r, data, elem) \
|
||||
express::Base BOOST_PP_CAT(tesselate_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, double deflection);
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
|
||||
#define EXTERNAL_DEFS_2(r, data, elem) \
|
||||
express::Base BOOST_PP_CAT(serialise_Ifc, elem)(ifcopenshell::file&, const TopoDS_Shape& shape, bool advanced);
|
||||
#include <mutex>
|
||||
|
||||
#define CONDITIONAL_CALL(r, data, elem) \
|
||||
if (schema_name_lower == BOOST_PP_STRINGIZE(BOOST_PP_CAT(elem,))) { \
|
||||
return BOOST_PP_CAT(METHOD_NAME, elem)(f, shape, arg_2); \
|
||||
namespace {
|
||||
std::string writer_schema_key(const std::string& schema_name) {
|
||||
return boost::to_upper_copy(schema_name);
|
||||
}
|
||||
|
||||
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS_1, , SCHEMA_SEQ);
|
||||
BOOST_PP_SEQ_FOR_EACH(EXTERNAL_DEFS_2, , SCHEMA_SEQ);
|
||||
ifcopenshell::plugin::module builtin_writer_module(const std::string& schema_name) {
|
||||
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) {
|
||||
auto schema_name = f.schema()->name();
|
||||
template <express::Base(*Fn)(ifcopenshell::file&, const TopoDS_Shape&, bool)>
|
||||
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.
|
||||
// @todo is this still needed? parsing a file should have initialized the schemas already.
|
||||
try {
|
||||
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);
|
||||
template <express::Base(*Fn)(ifcopenshell::file&, const TopoDS_Shape&, double)>
|
||||
express::Base tesselate_adapter(ifcopenshell::file& f, const IfcGeom::ConversionResultShape& shape, double deflection) {
|
||||
return Fn(f, require_opencascade_shape(shape).shape(), deflection);
|
||||
}
|
||||
}
|
||||
|
||||
#undef METHOD_NAME
|
||||
#define METHOD_NAME serialise_Ifc
|
||||
#define EXTERNAL_TESSELATE(r, data, elem) \
|
||||
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) {
|
||||
auto schema_name = f.schema()->name();
|
||||
#define EXTERNAL_SERIALISE(r, data, elem) \
|
||||
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.
|
||||
try {
|
||||
ifcopenshell::schema_by_name("IFC2X3");
|
||||
} catch (ifcopenshell::exception&) {}
|
||||
#define BIND_WRITER(r, data, elem) \
|
||||
registry.bind(BOOST_PP_STRINGIZE(BOOST_PP_CAT(Ifc, elem)), \
|
||||
&serialise_adapter<BOOST_PP_CAT(serialise_Ifc, elem)>, \
|
||||
&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 "../../plugin/plugin.h"
|
||||
#include "../../ifcgeom/ConversionResult.h"
|
||||
|
||||
#include "ifc_geomserialization_api.h"
|
||||
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class TopoDS_Shape;
|
||||
|
||||
namespace ifcopenshell {
|
||||
class file;
|
||||
}
|
||||
|
||||
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 serialise(ifcopenshell::file& f, const TopoDS_Shape& shape, bool advanced);
|
||||
} // namespace IfcGeom
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user