/******************************************************************************** * * * 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 . * * * ********************************************************************************/ #ifndef ABSTRACT_KERNEL_H #define ABSTRACT_KERNEL_H #include "../ifcparse/macros.h" #include "../ifcparse/IfcLogger.h" #include "../ifcgeom/ifc_geom_api.h" #include "../ifcgeom/IfcGeomRepresentation.h" #include "../ifcgeom/taxonomy.h" #include "../ifcgeom/ConversionSettings.h" #include "../ifcgeom/abstract_mapping.h" static const double ALMOST_ZERO = 1.e-9; template inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance = ALMOST_ZERO) { return fabs(a - b) < tolerance; } namespace ifcopenshell { #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable: 4275) #endif class IFC_GEOM_API not_implemented_error : public std::exception { public: const char* what() const noexcept override; }; class IFC_GEOM_API not_supported_error : public std::exception { public: const char* what() const noexcept override; }; #if defined(_MSC_VER) #pragma warning(pop) #endif namespace geometry { namespace kernels { class IFC_GEOM_API AbstractKernel { private: std::unordered_map cache_; protected: std::string geometry_library_; Settings settings_; Logger& logger_; public: bool propagate_exceptions = false; bool partial_success_is_success = true; AbstractKernel(const std::string& geometry_library, const Settings& settings, Logger& logger = Logger::Root()) : geometry_library_(geometry_library) , settings_(settings) , logger_(logger) {} virtual ~AbstractKernel() = default; virtual bool convert(const taxonomy::ptr, IfcGeom::ConversionResults&); const Settings& settings() const; const std::string& geometry_library() const { return geometry_library_; } Logger& logger() const { return logger_; } virtual bool supports_boolean_operations() const = 0; virtual bool convert_impl(const taxonomy::matrix4::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::point3::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::direction3::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::line::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::circle::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::ellipse::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::bspline_curve::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::edge::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::loop::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::shell::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::face::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::extrusion::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::node::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::colour::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::boolean_result::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::plane::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::offset_curve::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::revolve::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::bspline_surface::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::cylinder::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::sphere::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::torus::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::solid::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::sweep_along_curve::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::loft::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual bool convert_impl(const taxonomy::collection::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const taxonomy::function_item::ptr item, IfcGeom::ConversionResults& cs); virtual bool convert_impl(const taxonomy::functor_item::ptr item, IfcGeom::ConversionResults& cs); virtual bool convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs); virtual bool convert_impl(const taxonomy::gradient_function::ptr item, IfcGeom::ConversionResults& cs); virtual bool convert_impl(const taxonomy::cant_function::ptr item, IfcGeom::ConversionResults& cs); virtual bool convert_impl(const taxonomy::offset_function::ptr item, IfcGeom::ConversionResults& cs); /* virtual void set_offset(const std::array &p_offset); virtual void set_rotation(const std::array &p_rotation); */ virtual bool apply_layerset(IfcGeom::ConversionResults&, const ifcopenshell::geometry::layerset_information&) { throw not_implemented_error(); } virtual bool apply_folded_layerset(IfcGeom::ConversionResults&, const ifcopenshell::geometry::layerset_information&, const std::map&) { throw not_implemented_error(); } virtual bool convert_openings(const IfcUtil::IfcBaseEntity* entity, const std::vector>& openings, const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes) = 0; virtual bool unify_shapes(const IfcGeom::ConversionResults&, IfcGeom::ConversionResults&) { throw not_implemented_error(); } virtual AbstractKernel* clone(Logger& logger) const = 0; }; } } } namespace { /* A compile-time for loop over the taxonomy kinds */ template struct dispatch_conversion { static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, ifcopenshell::geometry::taxonomy::kinds item_kind, const ifcopenshell::geometry::taxonomy::ptr& item, IfcGeom::ConversionResults& results) { if (N == item_kind) { auto concrete_item = std::static_pointer_cast>(item); return kernel->convert_impl(concrete_item, results); } else { return dispatch_conversion::dispatch(kernel, item_kind, item, results); } } }; template <> struct dispatch_conversion { static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, ifcopenshell::geometry::taxonomy::kinds, const ifcopenshell::geometry::taxonomy::ptr& item, IfcGeom::ConversionResults&) { std::string created_from; if (item->instance) { created_from = " (created from " + item->instance->declaration().name() + ")"; } kernel->logger().Error("UNS", 1, "No support for " + ifcopenshell::geometry::taxonomy::kind_to_string(item->kind()) + created_from + " in kernel " + kernel->geometry_library()); return false; } }; template struct dispatch_with_upgrade { static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, const ifcopenshell::geometry::taxonomy::ptr& item, IfcGeom::ConversionResults& results) { auto concrete_item = ifcopenshell::geometry::taxonomy::template dcast>(item); if (concrete_item) { return kernel->convert_impl(concrete_item, results); } else { return dispatch_with_upgrade::dispatch(kernel, item, results); } } }; template <> struct dispatch_with_upgrade { static bool dispatch(ifcopenshell::geometry::kernels::AbstractKernel* kernel, const ifcopenshell::geometry::taxonomy::ptr& item, IfcGeom::ConversionResults&) { std::string created_from; if (item->instance) { created_from = " (created from " + item->instance->declaration().name() + ")"; } kernel->logger().Error("UNS", 2, "No support (after considering item upgrade) for " + ifcopenshell::geometry::taxonomy::kind_to_string(item->kind()) + created_from + " in kernel " + kernel->geometry_library()); return false; } }; template struct TupleTypeIndex; template struct TupleTypeIndex> { static const std::size_t value = 0; }; template struct TupleTypeIndex> { static const std::size_t value = 1 + TupleTypeIndex>::value; }; /* A compile-time for loop over the curve kinds */ template struct dispatch_curve_creation { static bool dispatch(const ifcopenshell::geometry::taxonomy::ptr& item, T& visitor) { constexpr auto KindIndex = TupleTypeIndex, ifcopenshell::geometry::taxonomy::impl::KindsTuple>::value; if (item->kind() == KindIndex) { auto concrete_item = std::static_pointer_cast>(item); visitor(concrete_item); return true; } else { return dispatch_curve_creation::dispatch(item, visitor); } } }; template struct dispatch_curve_creation { static bool dispatch(const ifcopenshell::geometry::taxonomy::ptr& item, T&) { Logger::Root().Error("GEO", 28, "No conversion for " + std::to_string(item->kind())); return false; } }; /* A compile-time for loop over the curve kinds */ template struct dispatch_surface_creation { static bool dispatch(const ifcopenshell::geometry::taxonomy::ptr& item, T& visitor) { auto v = ifcopenshell::geometry::taxonomy::template dcast>(item); if (v && item->kind() == v->kind()) { visitor(v); return true; } else { return dispatch_surface_creation::dispatch(item, visitor); } } }; template struct dispatch_surface_creation { static bool dispatch(const ifcopenshell::geometry::taxonomy::ptr& item, T&) { Logger::Root().Error("GEO", 29, "No conversion for " + std::to_string(item->kind())); return false; } }; } #endif