2024-03-15 17:26:02 +01: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/>. *
* *
********************************************************************************/
# include "mapping.h"
# define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell : : geometry ;
# include "../../ifcgeom/profile_helper.h"
2024-09-12 11:20:30 +02:00
# include "../../ifcgeom/infra_sweep_helper.h"
2024-03-15 17:26:02 +01:00
# ifdef SCHEMA_HAS_IfcSectionedSolidHorizontal
taxonomy : : ptr mapping : : map_impl ( const IfcSchema : : IfcSectionedSolidHorizontal * inst ) {
2024-03-29 15:53:34 +01:00
std : : vector < cross_section > cross_sections ;
2024-03-15 17:26:02 +01:00
auto dir = map ( inst - > Directrix ( ) ) ;
2024-03-29 15:53:34 +01:00
auto pwf = taxonomy : : dcast < taxonomy : : piecewise_function > ( dir ) ;
if ( ! pwf ) {
// Only implement on alignment curves
2024-07-22 13:21:49 -07:00
Logger : : Warning ( " IfcSectionedSolidHorizontal is only implemented for piecewise function Directrix curves " , inst ) ;
return nullptr ;
2024-03-29 15:53:34 +01:00
}
{
2024-03-15 17:26:02 +01:00
auto css = inst - > CrossSections ( ) ;
auto csps = inst - > CrossSectionPositions ( ) ;
2024-03-29 15:53:34 +01:00
std : : vector < taxonomy : : face : : ptr > faces ;
2024-03-15 17:26:02 +01:00
// The PointByDistanceExpressesions are factored out into (a) a cartesian offset relative to the
// reference frame along a certain curve location (b) the longitude.
// The longitudes determine the range of the sweep and the offsets are interpolated in between
// sweep segments.
std : : vector < Eigen : : Vector3d > profile_offsets ;
std : : vector < double > longitudes ;
for ( auto & cs : * css ) {
2024-03-29 15:53:34 +01:00
faces . push_back ( std : : move ( taxonomy : : cast < taxonomy : : face > ( map ( cs ) ) ) ) ;
2024-03-15 17:26:02 +01:00
}
2024-03-15 20:10:34 +01:00
# ifdef SCHEMA_HAS_IfcPointByDistanceExpression
2024-03-15 17:26:02 +01:00
for ( auto & csp : * csps ) {
auto pbde = csp - > Location ( ) - > as < IfcSchema : : IfcPointByDistanceExpression > ( true ) ;
2024-03-29 15:53:34 +01:00
2024-03-15 17:26:02 +01:00
longitudes . push_back ( * pbde - > DistanceAlong ( ) - > as < IfcSchema : : IfcLengthMeasure > ( true ) * length_unit_ ) ;
// Corresponds to the profile X, Y directions (hopefully).
Eigen : : Vector3d po (
pbde - > OffsetLateral ( ) . get_value_or ( 0. ) ,
// @todo I don't understand whether vertical is an offset relative to the tangent plane or to the global XY plane
pbde - > OffsetVertical ( ) . get_value_or ( 0. ) ,
0.
) ;
profile_offsets . push_back ( po ) ;
}
2024-03-15 20:10:34 +01:00
# else
return nullptr ;
# endif
2024-03-29 15:53:34 +01:00
if ( faces . size ( ) ! = profile_offsets . size ( ) ) {
Logger : : Warning ( " Expected CrossSections and CrossSectionPositions to be equal length, but got " + std : : to_string ( faces . size ( ) ) + " and " + std : : to_string ( profile_offsets . size ( ) ) + " respectively " , inst ) ;
2024-03-15 17:26:02 +01:00
return nullptr ;
}
2024-03-29 15:53:34 +01:00
if ( faces . size ( ) < 2 ) {
Logger : : Warning ( " Expected at least two cross sections, but got " + std : : to_string ( faces . size ( ) ) , inst ) ;
2024-03-15 17:26:02 +01:00
return nullptr ;
}
2024-03-29 15:53:34 +01:00
for ( size_t i = 0 ; i < faces . size ( ) ; + + i ) {
cross_sections . push_back ( { longitudes [ i ] , faces [ i ] , profile_offsets [ i ] } ) ;
}
}
2024-09-12 11:20:30 +02:00
return make_loft ( settings_ , inst , pwf , cross_sections ) ;
2024-03-15 17:26:02 +01:00
}
# endif