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"
2026-03-31 15:32:36 +02:00
# include "../ifcparse/logger.h"
2023-03-21 20:15:01 +01:00
# 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
2026-04-14 13:50:23 +02:00
# include <string_view>
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
2026-08-08 07:42:45 +02:00
namespace geom { namespace kernels {
2023-03-21 20:15:01 +01:00
2026-08-08 07:42:45 +02:00
class IFC_GEOM_API abstract_kernel {
2025-05-18 22:14:22 +02:00
private :
2026-08-08 07:42:45 +02:00
std : : unordered_map < taxonomy : : item : : ptr , ifcopenshell : : geom : : conversion_results , ifcopenshell : : geom : : taxonomy : : hash_functor , ifcopenshell : : geom : : 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_ ;
2026-08-08 07:42:45 +02:00
ifcopenshell : : geom : : settings settings_ ;
2026-07-09 13:30:48 +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-08-08 07:42:45 +02:00
abstract_kernel ( const std : : string & geometry_library , const ifcopenshell : : geom : : 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
2026-08-08 07:42:45 +02:00
virtual ~ abstract_kernel ( ) = default ;
2025-03-25 18:34:10 +01:00
2026-08-08 07:42:45 +02:00
virtual bool convert ( const taxonomy : : ptr , ifcopenshell : : geom : : conversion_results & ) ;
const ifcopenshell : : geom : : settings & settings ( ) const ;
2024-04-29 21:03:33 +02:00
const std : : string & geometry_library ( ) const {
return geometry_library_ ;
}
2026-04-14 13:50:23 +02:00
virtual std : : string_view backend_id ( ) const {
return geometry_library_ ;
}
2026-08-08 07:42:45 +02:00
virtual bool accepts ( const ifcopenshell : : geom : : conversion_result_shape & shape ) const {
2026-04-14 13:50:23 +02:00
return shape . backend_id ( ) = = backend_id ( ) ;
}
2026-07-09 13:30:48 +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 ;
2026-08-08 07:42:45 +02:00
virtual bool convert_impl ( const taxonomy : : matrix4 : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : point3 : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : direction3 : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : line : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : circle : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : ellipse : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : bspline_curve : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : edge : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : loop : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : shell : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : face : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : extrusion : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : node : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : colour : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : boolean_result : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : plane : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : offset_curve : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : revolve : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : bspline_surface : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : cylinder : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : sphere : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : torus : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : solid : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : sweep_along_curve : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : loft : : ptr , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
virtual bool convert_impl ( const taxonomy : : collection : : ptr , ifcopenshell : : geom : : conversion_results & ) ;
virtual bool convert_impl ( const taxonomy : : function_item : : ptr item , ifcopenshell : : geom : : conversion_results & cs ) ;
virtual bool convert_impl ( const taxonomy : : functor_item : : ptr item , ifcopenshell : : geom : : conversion_results & cs ) ;
virtual bool convert_impl ( const taxonomy : : piecewise_function : : ptr item , ifcopenshell : : geom : : conversion_results & cs ) ;
virtual bool convert_impl ( const taxonomy : : gradient_function : : ptr item , ifcopenshell : : geom : : conversion_results & cs ) ;
virtual bool convert_impl ( const taxonomy : : cant_function : : ptr item , ifcopenshell : : geom : : conversion_results & cs ) ;
virtual bool convert_impl ( const taxonomy : : offset_function : : ptr item , ifcopenshell : : geom : : conversion_results & 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);
*/
2026-08-08 07:42:45 +02:00
virtual bool apply_layerset ( ifcopenshell : : geom : : conversion_results & , const ifcopenshell : : geom : : layerset_information & ) { throw not_implemented_error ( ) ; }
virtual bool apply_folded_layerset ( ifcopenshell : : geom : : conversion_results & , const ifcopenshell : : geom : : layerset_information & , const std : : map < express : : base , ifcopenshell : : geom : : layerset_information > & ) { throw not_implemented_error ( ) ; }
virtual bool convert_openings ( const express : : base & entity , const std : : vector < std : : pair < taxonomy : : ptr , ifcopenshell : : geom : : taxonomy : : matrix4 > > & openings ,
const ifcopenshell : : geom : : conversion_results & entity_shapes , const ifcopenshell : : geom : : taxonomy : : matrix4 & entity_trsf , ifcopenshell : : geom : : conversion_results & cut_shapes ) = 0 ;
virtual bool unify_shapes ( const ifcopenshell : : geom : : conversion_results & , ifcopenshell : : geom : : conversion_results & ) { throw not_implemented_error ( ) ; }
2023-03-21 20:15:01 +01:00
2026-08-08 07:42:45 +02:00
virtual abstract_kernel * 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 {
2026-08-08 07:42:45 +02:00
static bool dispatch ( ifcopenshell : : geom : : kernels : : abstract_kernel * kernel , ifcopenshell : : geom : : taxonomy : : kinds item_kind , const ifcopenshell : : geom : : taxonomy : : ptr & item , ifcopenshell : : geom : : conversion_results & results ) {
2023-12-19 12:38:22 +01:00
if ( N = = item_kind ) {
2026-08-08 07:42:45 +02:00
auto concrete_item = std : : static_pointer_cast < ifcopenshell : : geom : : 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 < >
2026-08-08 07:42:45 +02:00
struct dispatch_conversion < ifcopenshell : : geom : : taxonomy : : type_by_kind : : max > {
static bool dispatch ( ifcopenshell : : geom : : kernels : : abstract_kernel * kernel , ifcopenshell : : geom : : taxonomy : : kinds , const ifcopenshell : : geom : : taxonomy : : ptr & item , ifcopenshell : : geom : : conversion_results & ) {
2026-07-09 13:21:39 +02:00
if ( kernel - > partial_success_is_success ) {
2026-05-27 14:55:25 +02:00
std : : string created_from ;
if ( item - > instance ) {
2026-07-09 13:30:48 +02:00
created_from = " (created from " + item - > instance . declaration ( ) . name ( ) + " ) " ;
2026-05-27 14:55:25 +02:00
}
2026-08-08 07:42:45 +02:00
kernel - > logger ( ) . error ( " UNS " , 1 , " No support for " + ifcopenshell : : geom : : taxonomy : : kind_to_string ( item - > kind ( ) ) + created_from + " in kernel " + kernel - > geometry_library ( ) ) ;
2026-05-27 14:55:25 +02:00
}
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 {
2026-08-08 07:42:45 +02:00
static bool dispatch ( ifcopenshell : : geom : : kernels : : abstract_kernel * kernel , const ifcopenshell : : geom : : taxonomy : : ptr & item , ifcopenshell : : geom : : conversion_results & results ) {
auto concrete_item = ifcopenshell : : geom : : taxonomy : : template dcast < ifcopenshell : : geom : : 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 < >
2026-08-08 07:42:45 +02:00
struct dispatch_with_upgrade < ifcopenshell : : geom : : taxonomy : : upgrades : : max > {
static bool dispatch ( ifcopenshell : : geom : : kernels : : abstract_kernel * kernel , const ifcopenshell : : geom : : taxonomy : : ptr & item , ifcopenshell : : geom : : conversion_results & ) {
2026-07-09 13:21:39 +02:00
if ( kernel - > partial_success_is_success ) {
2026-05-27 14:55:25 +02:00
std : : string created_from ;
if ( item - > instance ) {
2026-07-09 13:30:48 +02:00
created_from = " (created from " + item - > instance . declaration ( ) . name ( ) + " ) " ;
2026-05-27 14:55:25 +02:00
}
2026-08-08 07:42:45 +02:00
kernel - > logger ( ) . error ( " UNS " , 2 , " No support (after considering item upgrade) for " + ifcopenshell : : geom : : taxonomy : : kind_to_string ( item - > kind ( ) ) + created_from + " in kernel " + kernel - > geometry_library ( ) ) ;
2026-05-27 14:55:25 +02:00
}
2024-09-11 17:46:11 +05:00
return false ;
}
} ;
2024-08-23 20:36:47 +02:00
template < class T , class Tuple >
2026-08-08 07:42:45 +02:00
struct tuple_type_index ;
2024-08-23 20:36:47 +02:00
template < class T , class . . . Types >
2026-08-08 07:42:45 +02:00
struct tuple_type_index < T , std : : tuple < T , Types . . . > > {
2024-08-23 20:36:47 +02:00
static const std : : size_t value = 0 ;
} ;
template < class T , class U , class . . . Types >
2026-08-08 07:42:45 +02:00
struct tuple_type_index < T , std : : tuple < U , Types . . . > > {
static const std : : size_t value = 1 + tuple_type_index < T , std : : tuple < Types . . . > > : : value ;
2024-08-23 20:36:47 +02:00
} ;
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 {
2026-08-08 07:42:45 +02:00
static bool dispatch ( const ifcopenshell : : geom : : taxonomy : : ptr & item , T & visitor ) {
constexpr auto KindIndex = tuple_type_index < std : : tuple_element_t < N , ifcopenshell : : geom : : taxonomy : : impl : : curves_tuple > , ifcopenshell : : geom : : taxonomy : : impl : : kinds_tuple > : : value ;
2024-08-23 20:36:47 +02:00
if ( item - > kind ( ) = = KindIndex ) {
2026-08-08 07:42:45 +02:00
auto concrete_item = std : : static_pointer_cast < ifcopenshell : : geom : : 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 >
2026-08-08 07:42:45 +02:00
struct dispatch_curve_creation < T , ifcopenshell : : geom : : taxonomy : : curves : : max > {
static bool dispatch ( const ifcopenshell : : geom : : taxonomy : : ptr & item , T & ) {
2026-07-09 13:30:48 +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 {
2026-08-08 07:42:45 +02:00
static bool dispatch ( const ifcopenshell : : geom : : taxonomy : : ptr & item , T & visitor ) {
auto v = ifcopenshell : : geom : : taxonomy : : template dcast < ifcopenshell : : geom : : taxonomy : : surfaces : : type < N > > ( item ) ;
2024-07-03 14:36:35 +02:00
if ( v & & item - > kind ( ) = = v - > kind ( ) ) {
visitor ( v ) ;
return true ;
} else {
return dispatch_surface_creation < T , N + 1 > : : dispatch ( item , visitor ) ;
}
}
} ;
template < typename T >
2026-08-08 07:42:45 +02:00
struct dispatch_surface_creation < T , ifcopenshell : : geom : : taxonomy : : surfaces : : max > {
static bool dispatch ( const ifcopenshell : : geom : : taxonomy : : ptr & item , T & ) {
2026-07-09 13:30:48 +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-04-14 13:50:23 +02:00
# endif