2013-03-24 10:48:39 +00: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/>. *
* *
********************************************************************************/
# ifndef GEOMETRYSERIALIZER_H
# define GEOMETRYSERIALIZER_H
2023-03-21 20:15:01 +01:00
# include "../ifcgeom/Serializer.h"
# include "../ifcgeom/IfcGeomElement.h"
2023-10-24 14:12:42 +02:00
# include <fstream>
2013-03-24 10:48:39 +00:00
2023-11-15 10:32:20 +01:00
namespace ifcopenshell {
namespace geometry {
inline namespace settings {
struct UseElementNames : public SettingBase < UseElementNames , bool > {
static constexpr const char * const name = " use-element-names " ;
static constexpr const char * const description = " Use entity instance IfcRoot.Name instead of unique IDs for naming elements upon serialization. "
" Applicable for OBJ, DAE, STP, and SVG output. " ;
static constexpr bool defaultvalue = false ;
} ;
struct UseElementGuids : public SettingBase < UseElementGuids , bool > {
static constexpr const char * const name = " use-element-guids " ;
static constexpr const char * const description = " Use entity instance IfcRoot.GlobalId instead of unique IDs for naming elements upon serialization. "
" Applicable for OBJ, DAE, STP, and SVG output. " ;
static constexpr bool defaultvalue = false ;
} ;
struct UseElementStepIds : public SettingBase < UseElementStepIds , bool > {
static constexpr const char * const name = " use-element-step-ids " ;
static constexpr const char * const description = " Use the numeric step identifier (entity instance name) for naming elements upon serialization. "
" Applicable for OBJ, DAE, STP, and SVG output. " ;
static constexpr bool defaultvalue = false ;
} ;
struct UseElementTypes : public SettingBase < UseElementTypes , bool > {
static constexpr const char * const name = " use-element-types " ;
static constexpr const char * const description = " Use element types instead of unique IDs for naming elements upon serialization. "
" Applicable to DAE output. " ;
static constexpr bool defaultvalue = false ;
} ;
struct UseYUp : public SettingBase < UseYUp , bool > {
static constexpr const char * const name = " y-up " ;
static constexpr const char * const description = " Change the 'up' axis to positive Y, default is Z UP. Applicable to OBJ output. " ;
static constexpr bool defaultvalue = false ;
} ;
2023-10-03 21:26:00 +02:00
struct WriteGltfEcef : public SettingBase < WriteGltfEcef , bool > {
static constexpr const char * const name = " ecef " ;
static constexpr const char * const description = " Write glTF in Earth-Centered Earth-Fixed coordinates. Requires PROJ. " ;
static constexpr bool defaultvalue = false ;
} ;
2023-11-15 10:32:20 +01:00
struct FloatingPointDigits : public SettingBase < FloatingPointDigits , int > {
static constexpr const char * const name = " digits " ;
static constexpr const char * const description = " Sets the precision to be used to format floating-point values, 15 by default. "
" Use a negative value to use the system's default precision (should be 6 typically). "
" Applicable for OBJ and DAE output. For DAE output, value >= 15 means that up to 16 decimals are used, "
" and any other value means that 6 or 7 decimals are used. " ;
2023-12-11 13:29:20 +01:00
static constexpr int defaultvalue = 15 ;
2023-11-15 10:32:20 +01:00
} ;
2024-09-28 14:46:57 +02:00
struct BaseUri : public SettingBase < BaseUri , std : : string > {
static constexpr const char * const name = " base-uri " ;
static constexpr const char * const description = " Base URI for products to be used in RDF-based serializations. " ;
} ;
2024-10-08 20:57:27 +02:00
struct WktUseSection : public SettingBase < WktUseSection , bool > {
static constexpr const char * const name = " wkt-use-section " ;
static constexpr const char * const description = " Use a geometrical section rather than full polyhedral output and footprint in TTL WKT " ;
static constexpr bool defaultvalue = false ;
} ;
2025-11-17 18:25:51 +01:00
struct SeparateZUpNode : public SettingBase < SeparateZUpNode , bool > {
static constexpr const char * const name = " separate-z-up-node " ;
static constexpr const char * const description = " Introduce a separate Z-Up node into the GlTF hierarchy instead of multiplying the transform into the root node matrices " ;
static constexpr bool defaultvalue = false ;
} ;
2023-11-15 10:32:20 +01:00
}
class SerializerSettings : public SettingsContainer <
// @todo should we use tuple_cat here to unify the settings into a single class?
2025-11-17 18:25:51 +01:00
std : : tuple < UseElementNames , UseElementGuids , UseElementStepIds , UseElementTypes , UseYUp , WriteGltfEcef , FloatingPointDigits , BaseUri , WktUseSection , SeparateZUpNode > >
2023-11-15 10:32:20 +01:00
{ } ;
}
}
2017-01-11 12:00:51 +02:00
2021-07-11 15:01:31 +02:00
class stream_or_filename {
private :
std : : shared_ptr < std : : ofstream > ofs_ ;
std : : shared_ptr < std : : ostringstream > oss_ ;
boost : : optional < std : : string > filename_ ;
public :
std : : ostream & stream ;
stream_or_filename ( const std : : string & fn )
: ofs_ ( new std : : ofstream ( IfcUtil : : path : : from_utf8 ( fn ) . c_str ( ) ) )
, stream ( * ofs_ )
{ }
stream_or_filename ( )
: oss_ ( new std : : ostringstream )
, stream ( * oss_ )
{ }
std : : string get_value ( ) const {
return oss_ - > str ( ) ;
}
boost : : optional < std : : string > filename ( ) const {
return filename_ ;
}
bool is_ready ( ) {
if ( ofs_ ) {
return ofs_ - > is_open ( ) ;
} else {
return true ;
}
}
} ;
2015-02-06 13:07:50 +00:00
class GeometrySerializer : public Serializer {
2013-03-24 10:48:39 +00:00
public :
2021-10-18 11:38:01 +02:00
enum read_type { READ_BREP , READ_TRIANGULATION } ;
2023-11-15 10:32:20 +01:00
GeometrySerializer ( const ifcopenshell : : geometry : : Settings & geometry_settings , const ifcopenshell : : geometry : : SerializerSettings & settings )
: geometry_settings_ ( geometry_settings )
, settings_ ( settings )
{ }
2013-03-24 10:48:39 +00:00
virtual ~ GeometrySerializer ( ) { }
2015-02-06 13:07:50 +00:00
virtual bool isTesselated ( ) const = 0 ;
2021-07-11 15:00:59 +02:00
virtual void write ( const IfcGeom : : TriangulationElement * o ) = 0 ;
virtual void write ( const IfcGeom : : BRepElement * o ) = 0 ;
2013-12-31 14:10:38 +00:00
virtual void setUnitNameAndMagnitude ( const std : : string & name , float magnitude ) = 0 ;
2021-11-02 11:39:49 +01:00
virtual IfcGeom : : Element * read ( IfcParse : : IfcFile & f , const std : : string & guid , const std : : string & representation_id , read_type rt = READ_BREP ) = 0 ;
2016-03-10 11:35:32 +02:00
2023-11-15 10:32:20 +01:00
const ifcopenshell : : geometry : : SerializerSettings & settings ( ) const { return settings_ ; }
ifcopenshell : : geometry : : SerializerSettings & settings ( ) { return settings_ ; }
const ifcopenshell : : geometry : : Settings & geometry_settings ( ) const { return geometry_settings_ ; }
ifcopenshell : : geometry : : Settings & geometry_settings ( ) { return geometry_settings_ ; }
2016-03-10 11:35:32 +02:00
2018-06-07 14:34:25 +03:00
/// Returns ID for the object depending on the used setting.
2021-07-11 15:00:59 +02:00
virtual std : : string object_id ( const IfcGeom : : Element * o )
2018-06-07 14:34:25 +03:00
{
2023-11-15 10:32:20 +01:00
if ( settings_ . get < ifcopenshell : : geometry : : settings : : UseElementGuids > ( ) . get ( ) ) return o - > guid ( ) ;
if ( settings_ . get < ifcopenshell : : geometry : : settings : : UseElementNames > ( ) . get ( ) ) return o - > name ( ) ;
if ( settings_ . get < ifcopenshell : : geometry : : settings : : UseElementStepIds > ( ) . get ( ) ) return " id- " + boost : : lexical_cast < std : : string > ( o - > id ( ) ) ;
2020-08-16 14:35:39 +02:00
return o - > unique_id ( ) ;
2018-06-07 14:34:25 +03:00
}
2016-03-10 11:35:32 +02:00
protected :
2023-11-15 10:32:20 +01:00
ifcopenshell : : geometry : : Settings geometry_settings_ ;
ifcopenshell : : geometry : : SerializerSettings settings_ ;
2013-03-24 10:48:39 +00:00
} ;
2021-10-18 11:38:01 +02:00
class WriteOnlyGeometrySerializer : public GeometrySerializer {
public :
2023-11-15 10:32:20 +01:00
WriteOnlyGeometrySerializer ( const ifcopenshell : : geometry : : Settings & geometry_settings , const ifcopenshell : : geometry : : SerializerSettings & settings ) : GeometrySerializer ( geometry_settings , settings ) { }
2021-10-18 11:38:01 +02:00
2021-11-02 11:39:49 +01:00
virtual IfcGeom : : Element * read ( IfcParse : : IfcFile & , const std : : string & , const std : : string & , read_type = READ_BREP ) {
2021-10-18 11:38:01 +02:00
throw std : : runtime_error ( " Not supported " ) ;
} ;
} ;
2016-03-10 11:35:32 +02:00
# endif