2025-09-26 14:24:49 +02:00
/********************************************************************************
* *
* 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/>. *
* *
********************************************************************************/
2023-03-21 20:15:01 +01:00
# 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"
2025-09-26 14:24:49 +02:00
# include "../ifcgeom/abstract_mapping.h"
2023-03-21 20:15:01 +01:00
static const double ALMOST_ZERO = 1.e-9 ;
template < typename T >
inline static bool ALMOST_THE_SAME ( const T & a , const T & b , double tolerance = ALMOST_ZERO ) {
return fabs ( a - b ) < tolerance ;
}
2024-10-09 13:14:49 +02:00
namespace ifcopenshell {
2025-10-03 14:00:20 +00:00
# if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4275)
# endif
2024-10-09 13:14:49 +02:00
class IFC_GEOM_API not_implemented_error : public std : : exception {
public :
2025-10-03 14:00:20 +00:00
const char * what ( ) const noexcept override ;
2024-10-09 13:14:49 +02:00
} ;
class IFC_GEOM_API not_supported_error : public std : : exception {
public :
2025-10-03 14:00:20 +00:00
const char * what ( ) const noexcept override ;
2024-10-09 13:14:49 +02:00
} ;
2025-10-03 14:00:20 +00:00
# if defined(_MSC_VER)
# pragma warning(pop)
# endif
2024-10-09 13:14:49 +02:00
namespace geometry { namespace kernels {
2023-03-21 20:15:01 +01:00
class IFC_GEOM_API AbstractKernel {
2025-05-18 22:14:22 +02:00
private :
std : : unordered_map < taxonomy : : item : : ptr , IfcGeom : : ConversionResults , ifcopenshell : : geometry : : taxonomy : : hash_functor , ifcopenshell : : geometry : : taxonomy : : equal_functor > cache_ ;
2023-03-21 20:15:01 +01:00
protected :
2024-04-29 21:03:33 +02:00
std : : string geometry_library_ ;
2023-11-15 10:32:20 +01:00
Settings settings_ ;
2026-06-10 18:30:54 +02:00
Logger & logger_ ;
2023-03-21 20:15:01 +01:00
public :
2024-10-09 13:14:49 +02:00
bool propagate_exceptions = false ;
2025-04-29 22:03:18 +02:00
bool partial_success_is_success = true ;
2024-10-09 13:14:49 +02:00
2026-06-10 18:30:54 +02:00
AbstractKernel ( const std : : string & geometry_library , const Settings & settings , Logger & logger = Logger : : Root ( ) )
2024-04-29 21:03:33 +02:00
: geometry_library_ ( geometry_library )
2026-06-10 18:30:54 +02:00
, settings_ ( settings )
, logger_ ( logger ) { }
2023-03-21 20:15:01 +01:00
2025-03-25 18:34:10 +01:00
virtual ~ AbstractKernel ( ) = default ;
2024-04-29 21:03:33 +02:00
virtual bool convert ( const taxonomy : : ptr , IfcGeom : : ConversionResults & ) ;
2023-11-15 10:32:20 +01:00
const Settings & settings ( ) const ;
2024-04-29 21:03:33 +02:00
const std : : string & geometry_library ( ) const {
return geometry_library_ ;
}
2026-06-10 18:30:54 +02:00
Logger & logger ( ) const { return logger_ ; }
2023-03-21 20:15:01 +01:00
2025-09-26 14:24:49 +02:00
virtual bool supports_boolean_operations ( ) const = 0 ;
2024-10-09 13:14:49 +02:00
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 ( ) ; }
2023-07-27 16:42:06 +08:00
virtual bool convert_impl ( const taxonomy : : collection : : ptr , IfcGeom : : ConversionResults & ) ;
2025-01-02 11:10:56 -08:00
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 ) ;
2023-03-21 20:15:01 +01:00
/*
virtual void set_offset(const std::array<double, 3> &p_offset);
virtual void set_rotation(const std::array<double, 4> &p_rotation);
*/
2024-10-09 13:14:49 +02:00
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 < IfcUtil : : IfcBaseEntity * , ifcopenshell : : geometry : : layerset_information > & ) { throw not_implemented_error ( ) ; }
2023-07-27 16:42:06 +08:00
virtual bool convert_openings ( const IfcUtil : : IfcBaseEntity * entity , const std : : vector < std : : pair < taxonomy : : ptr , ifcopenshell : : geometry : : taxonomy : : matrix4 > > & openings ,
2023-03-21 20:15:01 +01:00
const IfcGeom : : ConversionResults & entity_shapes , const ifcopenshell : : geometry : : taxonomy : : matrix4 & entity_trsf , IfcGeom : : ConversionResults & cut_shapes ) = 0 ;
2024-10-09 13:14:49 +02:00
virtual bool unify_shapes ( const IfcGeom : : ConversionResults & , IfcGeom : : ConversionResults & ) { throw not_implemented_error ( ) ; }
2023-03-21 20:15:01 +01:00
2026-06-11 21:04:44 +02:00
virtual AbstractKernel * clone ( Logger & logger ) const = 0 ;
2025-09-26 14:24:49 +02:00
} ;
2023-03-21 20:15:01 +01:00
}
}
}
namespace {
/* A compile-time for loop over the taxonomy kinds */
template < size_t N >
struct dispatch_conversion {
2025-08-06 09:19:38 +02:00
static bool dispatch ( ifcopenshell : : geometry : : kernels : : AbstractKernel * kernel , ifcopenshell : : geometry : : taxonomy : : kinds item_kind , const ifcopenshell : : geometry : : taxonomy : : ptr & item , IfcGeom : : ConversionResults & results ) {
2023-12-19 12:38:22 +01:00
if ( N = = item_kind ) {
2024-09-12 11:13:59 +05:00
auto concrete_item = std : : static_pointer_cast < ifcopenshell : : geometry : : taxonomy : : type_by_kind : : type < N > > ( item ) ;
2023-03-21 20:15:01 +01:00
return kernel - > convert_impl ( concrete_item , results ) ;
} else {
2023-12-19 12:38:22 +01:00
return dispatch_conversion < N + 1 > : : dispatch ( kernel , item_kind , item , results ) ;
2023-03-21 20:15:01 +01:00
}
}
} ;
template < >
struct dispatch_conversion < ifcopenshell : : geometry : : taxonomy : : type_by_kind : : max > {
2026-05-27 14:55:25 +02:00
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 ( ) + " ) " ;
}
2026-06-10 18:30:54 +02:00
kernel - > logger ( ) . Error ( " UNS " , 1 , " No support for " + ifcopenshell : : geometry : : taxonomy : : kind_to_string ( item - > kind ( ) ) + created_from + " in kernel " + kernel - > geometry_library ( ) ) ;
2023-03-21 20:15:01 +01:00
return false ;
}
} ;
2024-09-11 17:46:11 +05:00
template < size_t N >
struct dispatch_with_upgrade {
2025-08-06 09:19:38 +02:00
static bool dispatch ( ifcopenshell : : geometry : : kernels : : AbstractKernel * kernel , const ifcopenshell : : geometry : : taxonomy : : ptr & item , IfcGeom : : ConversionResults & results ) {
2024-09-11 18:24:24 +05:00
auto concrete_item = ifcopenshell : : geometry : : taxonomy : : template dcast < ifcopenshell : : geometry : : taxonomy : : upgrades : : type < N > > ( item ) ;
2024-09-11 17:46:11 +05:00
if ( concrete_item ) {
return kernel - > convert_impl ( concrete_item , results ) ;
} else {
return dispatch_with_upgrade < N + 1 > : : dispatch ( kernel , item , results ) ;
}
}
} ;
template < >
2024-09-11 18:24:24 +05:00
struct dispatch_with_upgrade < ifcopenshell : : geometry : : taxonomy : : upgrades : : max > {
2026-05-27 14:55:25 +02:00
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 ( ) + " ) " ;
}
2026-06-10 18:30:54 +02:00
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 ( ) ) ;
2024-09-11 17:46:11 +05:00
return false ;
}
} ;
2024-08-23 20:36:47 +02:00
template < class T , class Tuple >
struct TupleTypeIndex ;
template < class T , class . . . Types >
struct TupleTypeIndex < T , std : : tuple < T , Types . . . > > {
static const std : : size_t value = 0 ;
} ;
template < class T , class U , class . . . Types >
struct TupleTypeIndex < T , std : : tuple < U , Types . . . > > {
static const std : : size_t value = 1 + TupleTypeIndex < T , std : : tuple < Types . . . > > : : value ;
} ;
2023-03-21 20:15:01 +01:00
/* A compile-time for loop over the curve kinds */
template < typename T , size_t N = 0 >
struct dispatch_curve_creation {
2025-08-06 09:19:38 +02:00
static bool dispatch ( const ifcopenshell : : geometry : : taxonomy : : ptr & item , T & visitor ) {
2024-08-23 20:36:47 +02:00
constexpr auto KindIndex = TupleTypeIndex < std : : tuple_element_t < N , ifcopenshell : : geometry : : taxonomy : : impl : : CurvesTuple > , ifcopenshell : : geometry : : taxonomy : : impl : : KindsTuple > : : value ;
if ( item - > kind ( ) = = KindIndex ) {
2024-09-27 17:05:55 +05:00
auto concrete_item = std : : static_pointer_cast < ifcopenshell : : geometry : : taxonomy : : curves : : type < N > > ( item ) ;
2024-08-23 20:36:47 +02:00
visitor ( concrete_item ) ;
2023-03-21 20:15:01 +01:00
return true ;
} else {
return dispatch_curve_creation < T , N + 1 > : : dispatch ( item , visitor ) ;
}
}
} ;
template < typename T >
struct dispatch_curve_creation < T , ifcopenshell : : geometry : : taxonomy : : curves : : max > {
2025-08-06 09:19:38 +02:00
static bool dispatch ( const ifcopenshell : : geometry : : taxonomy : : ptr & item , T & ) {
2026-06-10 18:30:54 +02:00
Logger : : Root ( ) . Error ( " GEO " , 28 , " No conversion for " + std : : to_string ( item - > kind ( ) ) ) ;
2023-03-21 20:15:01 +01:00
return false ;
}
} ;
2024-07-03 14:36:35 +02:00
/* A compile-time for loop over the curve kinds */
template < typename T , size_t N = 0 >
struct dispatch_surface_creation {
2025-08-06 09:19:38 +02:00
static bool dispatch ( const ifcopenshell : : geometry : : taxonomy : : ptr & item , T & visitor ) {
2024-07-03 14:36:35 +02:00
auto v = ifcopenshell : : geometry : : taxonomy : : template dcast < ifcopenshell : : geometry : : taxonomy : : surfaces : : type < N > > ( item ) ;
if ( v & & item - > kind ( ) = = v - > kind ( ) ) {
visitor ( v ) ;
return true ;
} else {
return dispatch_surface_creation < T , N + 1 > : : dispatch ( item , visitor ) ;
}
}
} ;
template < typename T >
struct dispatch_surface_creation < T , ifcopenshell : : geometry : : taxonomy : : surfaces : : max > {
2025-08-06 09:19:38 +02:00
static bool dispatch ( const ifcopenshell : : geometry : : taxonomy : : ptr & item , T & ) {
2026-06-10 18:30:54 +02:00
Logger : : Root ( ) . Error ( " GEO " , 29 , " No conversion for " + std : : to_string ( item - > kind ( ) ) ) ;
2024-07-03 14:36:35 +02:00
return false ;
}
} ;
2023-03-21 20:15:01 +01:00
}
2026-06-10 18:30:54 +02:00
# endif