Shuffle project structure

This commit is contained in:
Thomas Krijnen
2019-01-18 16:43:38 +01:00
parent 16d6420352
commit 5a7c7ed048
63 changed files with 155 additions and 129 deletions
@@ -20,7 +20,7 @@
#ifndef CGALCONVERSIONRESULT_H
#define CGALCONVERSIONRESULT_H
#include "../../../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
namespace IfcGeom {
@@ -17,9 +17,6 @@
* *
********************************************************************************/
#include "../../../ifcgeom/IfcGeomShapeType.h"
#include "../../../ifcgeom/IfcGeom.h"
#include "CgalKernel.h"
#include "CgalConversionResult.h"
+22 -9
View File
@@ -17,16 +17,13 @@
* *
********************************************************************************/
#include "../../../ifcgeom/IfcGeomShapeType.h"
#include "../../../ifcgeom/IfcGeom.h"
#include "CgalKernel.h"
#include "CgalConversionResult.h"
namespace {
struct MAKE_TYPE_NAME(factory_t) {
IfcGeom::Kernel* operator()(IfcParse::IfcFile* file) const {
IfcGeom::MAKE_TYPE_NAME(Kernel)* k = new IfcGeom::MAKE_TYPE_NAME(Kernel);
IfcGeom::MAKE_TYPE_NAME(CgalKernel)* k = new IfcGeom::MAKE_TYPE_NAME(CgalKernel);
return k;
}
};
@@ -84,7 +81,8 @@ bool IfcGeom::CgalKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
*/
}
IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product(
template <typename P, typename PP>
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_representation_and_product(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
{
IfcGeom::Representation::BRep* shape;
@@ -139,7 +137,7 @@ IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_representat
context_string = representation->ContextOfItems()->ContextType();
}
return new NativeElement<double>(
return new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
@@ -152,9 +150,10 @@ IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_representat
);
}
IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_processed_representation(
template <typename P, typename PP>
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_processed_representation(
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
IfcGeom::NativeElement<double>* brep)
IfcGeom::NativeElement<P, PP>* brep)
{
int parent_id = -1;
try {
@@ -183,7 +182,7 @@ IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_processed_r
const std::string product_type = product->declaration().name();
return new NativeElement<double>(
return new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
@@ -195,3 +194,17 @@ IfcGeom::NativeElement<double>* IfcGeom::CgalKernel::create_brep_for_processed_r
product
);
}
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<double, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, float>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<double, double>(
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
+20 -4
View File
@@ -35,7 +35,16 @@ if ( it != cache.T.end() ) { e = it->second; return true; }
#endif
*/
#include "../../../ifcgeom/IfcGeom.h"
#include "../../../ifcparse/macros.h"
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
// @todo create separate shapetype enum?
#include "../../../ifcgeom/kernels/opencascade/IfcGeomShapeType.h"
#define INCLUDE_SCHEMA(x) STRINGIFY(../../../ifcparse/x.h)
#include INCLUDE_SCHEMA(IfcSchema)
#undef INCLUDE_SCHEMA
typedef void* cgal_shape_t;
typedef void* cgal_face_t;
@@ -55,6 +64,8 @@ namespace IfcGeom {
class IFC_GEOM_API MAKE_TYPE_NAME(CgalKernel) : public Kernel {
public:
MAKE_TYPE_NAME(CgalKernel)() : Kernel("cgal") {}
#ifndef NO_CACHE
CgalCache cache;
#endif
@@ -79,10 +90,15 @@ namespace IfcGeom {
}
virtual bool is_identity_transform(IfcUtil::IfcBaseClass*);
virtual IfcGeom::NativeElement<double>* create_brep_for_representation_and_product(
template <typename P, typename PP>
IfcGeom::NativeElement<P, PP>* create_brep_for_representation_and_product(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
virtual IfcGeom::NativeElement<double>* create_brep_for_processed_representation(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<double>*);
template <typename P, typename PP>
IfcGeom::NativeElement<P, PP>* create_brep_for_processed_representation(
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<P, PP>*);
#include "CgalEntityMappingDeclaration.h"
@@ -48,19 +48,19 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include "../ifcparse/macros.h"
#include "../ifcparse/IfcParse.h"
#include "../ifcparse/IfcBaseClass.h"
#include "../../../ifcparse/macros.h"
#include "../../../ifcparse/IfcParse.h"
#include "../../../ifcparse/IfcBaseClass.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../ifcgeom/IfcGeomShapeType.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeomShapeType.h"
#include "../ifcgeom_schema_agnostic/Kernel.h"
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
#include "OpenCascadeConversionResult.h"
#include "../ifcgeom_schema_agnostic/ifc_geom_api.h"
#include "../../../ifcgeom/schema_agnostic/ifc_geom_api.h"
// Define this in case you want to conserve memory usage at all cost. This has been
// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47
@@ -79,8 +79,9 @@ if ( it != cache.T.end() ) { e = it->second; return true; }
#endif
#define INCLUDE_PARENT_DIR(x) STRINGIFY(../ifcparse/x.h)
#include INCLUDE_PARENT_DIR(IfcSchema)
#define INCLUDE_SCHEMA(x) STRINGIFY(../../../ifcparse/x.h)
#include INCLUDE_SCHEMA(IfcSchema)
#undef INCLUDE_SCHEMA
namespace IfcGeom {
class IFC_GEOM_API geometry_exception : public std::exception {
@@ -228,7 +229,7 @@ private:
public:
MAKE_TYPE_NAME(Kernel)()
: IfcGeom::Kernel(0)
: IfcGeom::Kernel("opencascade", 0)
, deflection_tolerance(0.001)
, wire_creation_tolerance(0.0001)
, point_equality_tolerance(0.00001)
@@ -81,7 +81,7 @@
#include <Geom_BSplineCurve.hxx>
#endif
#include "../ifcgeom/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#define Kernel MAKE_TYPE_NAME(Kernel)
@@ -102,7 +102,7 @@
#include <TColStd_Array1OfInteger.hxx>
#endif
#include "../ifcgeom/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#define Kernel MAKE_TYPE_NAME(Kernel)
@@ -146,11 +146,11 @@
#include <Extrema_ExtPC.hxx>
#include <BRepAdaptor_Curve.hxx>
#include "../ifcparse/macros.h"
#include "../ifcparse/IfcSIPrefix.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeom.h"
#include "../ifcgeom/IfcGeomTree.h"
#include "../../../ifcparse/macros.h"
#include "../../../ifcparse/IfcSIPrefix.h"
#include "../../../ifcparse/IfcFile.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeomTree.h"
#include <memory>
@@ -75,7 +75,7 @@
#include <TopLoc_Location.hxx>
#include "../ifcgeom/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#define Kernel MAKE_TYPE_NAME(Kernel)
@@ -1,5 +1,5 @@
#include "IfcGeomIteratorImplementation.h"
#include "../ifcgeom_schema_agnostic/IteratorImplementation.h"
#include "../../../ifcgeom/schema_agnostic/IteratorImplementation.h"
namespace IfcGeom {
template class MAKE_TYPE_NAME(IteratorImplementation_)<float, float>;
@@ -73,16 +73,16 @@
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include "../ifcparse/IfcFile.h"
#include "../../../ifcparse/IfcFile.h"
#include "../ifcgeom/IfcGeom.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomMaterial.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIteratorSettings.h"
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
#include "../ifcgeom_schema_agnostic/IfcGeomFilter.h"
#include "../ifcgeom_schema_agnostic/IteratorImplementation.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomFilter.h"
#include "../../../ifcgeom/schema_agnostic/IteratorImplementation.h"
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
#ifdef min
@@ -101,7 +101,7 @@
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include "../ifcgeom/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#include <memory>
@@ -20,10 +20,10 @@
#ifndef IFCGEOMTREE_H
#define IFCGEOMTREE_H
#include "../ifcparse/IfcFile.h"
#include "../ifcgeom_schema_agnostic/IfcGeomElement.h"
#include "../ifcgeom_schema_agnostic/IfcGeomIterator.h"
#include "../ifcgeom_schema_agnostic/Kernel.h"
#include "../../../ifcparse/IfcFile.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomIterator.h"
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
#include <NCollection_UBTree.hxx>
#include <BRepBndLib.hxx>
@@ -95,7 +95,7 @@
#include <BRepAdaptor_HCompCurve.hxx>
#include <Approx_Curve3d.hxx>
#include "../ifcgeom/IfcGeom.h"
#include "../../../ifcgeom/kernels/opencascade/IfcGeom.h"
#define Kernel MAKE_TYPE_NAME(Kernel)
@@ -38,8 +38,8 @@
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/IfcParse.h"
#include "../../../ifcparse/IfcBaseClass.h"
#include "../../../ifcparse/IfcParse.h"
SHAPES(IfcShellBasedSurfaceModel);
SHAPES(IfcFaceBasedSurfaceModel);
@@ -34,7 +34,7 @@
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_QuasiUniformDeflection.hxx>
#include "../ifcgeom_schema_agnostic/ConversionResult.h"
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
namespace IfcGeom {
@@ -1,7 +1,7 @@
#include "OpenCascadeConversionResult.h"
#include "../ifcparse/IfcLogger.h"
#include "../ifcgeom_schema_agnostic/IfcGeomRepresentation.h"
#include "../../../ifcparse/IfcLogger.h"
#include "../../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
#include "IfcGeom.h"
@@ -0,0 +1,93 @@
/********************************************************************************
* *
* 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 IFCSHAPELIST_H
#define IFCSHAPELIST_H
#include "../../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
namespace IfcGeom {
namespace Representation {
template <typename P>
class IFC_GEOM_API Triangulation;
}
class IFC_GEOM_API ConversionResultPlacement {
public:
virtual void Multiply(const ConversionResultPlacement*) = 0;
virtual void PreMultiply(const ConversionResultPlacement*) = 0;
virtual ConversionResultPlacement* inverted() const = 0;
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const = 0;
virtual double Value(int i, int j) const = 0;
virtual ConversionResultPlacement* clone() const = 0;
virtual ~ConversionResultPlacement() {}
};
class IFC_GEOM_API ConversionResultShape {
public:
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation<float>* t, int surface_style_id) const = 0;
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement* place, IfcGeom::Representation::Triangulation<double>* t, int surface_style_id) const = 0;
virtual void Serialize(std::string&) const = 0;
virtual ConversionResultShape* clone() const = 0;
virtual int surface_genus() const = 0;
virtual ~ConversionResultShape() {}
};
class IFC_GEOM_API ConversionResult {
private:
int id;
ConversionResultPlacement* placement;
ConversionResultShape* shape;
const SurfaceStyle* style;
public:
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape, const SurfaceStyle* style)
: id(id), placement(placement->clone()), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape)
: id(id), placement(placement->clone()), shape(shape->clone()), style(0) {}
ConversionResult(int id, const ConversionResultShape* shape, const SurfaceStyle* style)
: id(id), placement(0), shape(shape->clone()), style(style) {}
ConversionResult(int id, const ConversionResultShape* shape)
: id(id), placement(0), shape(shape->clone()), style(0) {}
void append(const ConversionResultPlacement* trsf) {
if (placement == 0) {
placement = trsf->clone();
} else {
placement->Multiply(trsf);
}
}
void prepend(const ConversionResultPlacement* trsf) {
if (placement == 0) {
placement = trsf->clone();
} else {
placement->PreMultiply(trsf);
}
}
const ConversionResultShape* Shape() const { return shape; }
const ConversionResultPlacement* Placement() const { return placement; }
bool hasStyle() const { return style != 0; }
const SurfaceStyle& Style() const { return *style; }
void setStyle(const SurfaceStyle* style) { this->style = style; }
int ItemId() const { return id; }
};
typedef std::vector<ConversionResult> ConversionResults;
}
#endif
@@ -0,0 +1,223 @@
/********************************************************************************
* *
* 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 IFCGEOMELEMENT_H
#define IFCGEOMELEMENT_H
#include <string>
#include <algorithm>
#include "../../ifcparse/IfcGlobalId.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "ifc_geom_api.h"
namespace IfcGeom {
template <typename P>
class Matrix {
private:
std::vector<P> _data;
public:
Matrix(const ElementSettings& settings, const ConversionResultPlacement* trsf) {
// Convert the gp_Trsf into a 4x3 Matrix
// Note that in case the CONVERT_BACK_UNITS setting is enabled
// the translation component of the matrix needs to be divided
// by the magnitude of the IFC model length unit because
// internally in IfcOpenShell everything is measured in meters.
for(int i = 1; i < 5; ++i) {
for (int j = 1; j < 4; ++j) {
const double trsf_value = trsf->Value(j,i);
const double matrix_value = i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS)
? trsf_value / settings.unit_magnitude()
: trsf_value;
_data.push_back(static_cast<P>(matrix_value));
}
}
}
const std::vector<P>& data() const { return _data; }
};
template <typename P>
class Transformation {
private:
ElementSettings settings_;
ConversionResultPlacement* trsf_;
Matrix<P> matrix_;
public:
Transformation(const ElementSettings& settings, const ConversionResultPlacement* trsf)
: settings_(settings)
, trsf_(trsf->clone())
, matrix_(settings, trsf)
{}
const ConversionResultPlacement* data() const { return trsf_; }
const Matrix<P>& matrix() const { return matrix_; }
Transformation inverted() const {
return Transformation(settings_, trsf_->inverted());
}
Transformation multiplied(const Transformation& other) const {
return Transformation(settings_, trsf_->multiplied(other.data()));
}
};
template <typename P = double, typename PP = P>
class Element {
private:
int _id;
int _parent_id;
std::string _name;
std::string _type;
std::string _guid;
std::string _context;
std::string _unique_id;
Transformation<PP> _transformation;
IfcUtil::IfcBaseEntity* product_;
std::vector<const IfcGeom::Element<P, PP>*> _parents;
public:
friend bool operator == (const Element<P, PP> & element1, const Element<P, PP> & element2) {
return element1.id() == element2.id();
}
// Use the id to compare, or the elevation is the elements are IfcBuildingStoreys and the elevation is set
friend bool operator < (const Element<P, PP> & element1, const Element<P, PP> & element2) {
if (element1.type() == "IfcBuildingStorey" && element2.type() == "IfcBuildingStorey") {
size_t attr_index = element1.product()->declaration().attribute_index("Elevation");
Argument* elev_attr1 = element1.product()->data().getArgument(attr_index);
Argument* elev_attr2 = element2.product()->data().getArgument(attr_index);
if (!elev_attr1->isNull() && !elev_attr2->isNull()) {
double elev1 = *elev_attr1;
double elev2 = *elev_attr2;
return elev1 < elev2;
}
}
return element1.id() < element2.id();
}
int id() const { return _id; }
int parent_id() const { return _parent_id; }
const std::string& name() const { return _name; }
const std::string& type() const { return _type; }
const std::string& guid() const { return _guid; }
const std::string& context() const { return _context; }
const std::string& unique_id() const { return _unique_id; }
const Transformation<PP>& transformation() const { return _transformation; }
IfcUtil::IfcBaseEntity* product() const { return product_; }
const std::vector<const IfcGeom::Element<P, PP>*> parents() const { return _parents; }
void SetParents(std::vector<const IfcGeom::Element<P, PP>*> newparents) { _parents = newparents; }
Element(const ElementSettings& settings, int id, int parent_id, const std::string& name, const std::string& type,
const std::string& guid, const std::string& context, const ConversionResultPlacement* trsf, IfcUtil::IfcBaseEntity* product)
: _id(id), _parent_id(parent_id), _name(name), _type(type), _guid(guid), _context(context), _transformation(settings, trsf)
, product_(product)
{
std::ostringstream oss;
if (type == "IfcProject") {
oss << "project";
} else {
try {
oss << "product-" << IfcParse::IfcGlobalId(guid).formatted();
} catch (const std::exception& e) {
oss << "product";
Logger::Error(e);
}
}
if (!_context.empty()) {
std::string ctx = _context;
boost::to_lower(ctx);
boost::replace_all(ctx, " ", "-");
oss << "-" << ctx;
}
_unique_id = oss.str();
}
virtual ~Element() {}
};
template <typename P = double, typename PP = P>
class NativeElement : public Element<P, PP> {
private:
boost::shared_ptr<Representation::BRep> _geometry;
public:
const boost::shared_ptr<Representation::BRep>& geometry_pointer() const { return _geometry; }
const Representation::BRep& geometry() const { return *_geometry; }
NativeElement(int id, int parent_id, const std::string& name, const std::string& type, const std::string& guid,
const std::string& context, const ConversionResultPlacement* trsf, const boost::shared_ptr<Representation::BRep>& geometry,
IfcUtil::IfcBaseEntity* product)
: Element<P, PP>(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product)
, _geometry(geometry)
{}
bool calculate_projected_surface_area(double& along_x, double& along_y, double& along_z) const {
return geometry().calculate_projected_surface_area(this->transformation().data(), along_x, along_y, along_z);
}
private:
NativeElement(const NativeElement& other);
NativeElement& operator=(const NativeElement& other);
};
template <typename P = double, typename PP = P>
class TriangulationElement : public Element<P, PP> {
private:
boost::shared_ptr< Representation::Triangulation<P> > _geometry;
public:
const Representation::Triangulation<P>& geometry() const { return *_geometry; }
const boost::shared_ptr< Representation::Triangulation<P> >& geometry_pointer() const { return _geometry; }
TriangulationElement(const NativeElement<P, PP>& shape_model)
: Element<P, PP>(shape_model)
, _geometry(boost::shared_ptr<Representation::Triangulation<P> >(new Representation::Triangulation<P>(shape_model.geometry())))
{}
TriangulationElement(const Element<P, PP>& element, const boost::shared_ptr<Representation::Triangulation<P> >& geometry)
: Element<P, PP>(element)
, _geometry(geometry)
{}
private:
TriangulationElement(const TriangulationElement& other);
TriangulationElement& operator=(const TriangulationElement& other);
};
template <typename P = double, typename PP = P>
class SerializedElement : public Element<P, PP> {
private:
Representation::Serialization* _geometry;
public:
const Representation::Serialization& geometry() const { return *_geometry; }
SerializedElement(const NativeElement<P, PP>& shape_model)
: Element<P, PP>(shape_model)
, _geometry(new Representation::Serialization(shape_model.geometry()))
{}
virtual ~SerializedElement() {
delete _geometry;
}
private:
SerializedElement(const SerializedElement& other);
SerializedElement& operator=(const SerializedElement& other);
};
}
#endif
+232
View File
@@ -0,0 +1,232 @@
/********************************************************************************
* *
* 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/>. *
* *
********************************************************************************/
/** @file IfcGeomFilter.h
@brief A set of predefined product filters for IfcGeom::Iterator */
#ifndef IFCGEOMFILTER_H
#define IFCGEOMFILTER_H
#include "../../ifcgeom/schema_agnostic/Kernel.h"
#include "../../ifcparse/IfcFile.h"
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <functional>
namespace IfcGeom {
/// The filter function (free or member function) or function object (use boost::ref() to reference to it)
/// should return true if the geometry for the product is wanted to be included in the output.
/// http://www.boost.org/doc/libs/1_62_0/doc/html/function/tutorial.html
typedef boost::function<bool(IfcUtil::IfcBaseEntity*)> filter_t;
struct filter {
filter() : include(false), traverse(false) {}
filter(bool incl, bool trav) : include(incl), traverse(trav) {}
/// Should the product be included (true) or excluded (false).
bool include;
/// If traversal requested, traverse to the parents to see if they satisfy the criteria. E.g. we might be looking for
/// children of a storey named "Level 20", or children of entities that have no representation, e.g. IfcCurtainWall.
bool traverse;
/// Optional description for the filtering criteria of this filter.
std::string description;
bool match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) const {
bool is_match = pred(prod);
if (!is_match && traverse) {
is_match = traverse_match(prod, pred);
}
return is_match == include;
}
static bool traverse_match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) {
IfcUtil::IfcBaseEntity* parent, *current = prod;
while ((parent = IfcGeom::Kernel::get_decomposing_entity(current)) != nullptr) {
if (pred(parent)) {
return true;
}
current = parent;
}
return false;
}
};
struct wildcard_filter : public filter {
wildcard_filter() : filter(false, false) {}
wildcard_filter(bool include, bool traverse, const std::set<std::string>& patterns)
: filter(include, traverse) {
populate(patterns);
}
std::set<boost::regex> values;
void populate(const std::set<std::string>& patterns) {
values.clear();
for(auto& pattern: patterns) {
values.insert(wildcard_string_to_regex(pattern));
}
}
bool match(const std::string &str) const { return match_values(values, str); }
static bool match_values(const std::set<boost::regex>& values, const std::string &str) {
for(auto& r: values) {
if (boost::regex_match(str, r)) {
return true;
}
}
return false;
}
static boost::regex wildcard_string_to_regex(std::string str) {
// Escape all non-"*?" regex special chars
static const std::string special_chars = "\\^.$|()[]+/";
for(auto c: special_chars) {
std::string char_str(1, c);
boost::replace_all(str, char_str, "\\" + char_str);
}
// Convert "*?" to their regex equivalents
boost::replace_all(str, "?", ".");
boost::replace_all(str, "*", ".*");
return boost::regex(str);
}
};
/// @note supports only string arguments for now
struct attribute_filter : public wildcard_filter {
std::string attribute_name;
attribute_filter() {}
attribute_filter(const std::string& attribute_name)
: attribute_name(attribute_name) {}
std::string value(IfcUtil::IfcBaseEntity* prod) const {
try {
return (std::string) *prod->get(attribute_name);
} catch (...) {
// Either
// (a) not an attribute name for this entity instance
// (b) not a string attribute
// (c) null for this entity instance
// @todo: validate the filters with a reference to the schema
// probably in IfcGeomIteratorImplementation
return "<invalid>";
}
}
bool match(IfcUtil::IfcBaseEntity* prod) const {
return wildcard_filter::match(value(prod));
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
// @note bind1st() and mem_fun() deprecated in C++11, use bind() and mem_fn() when migrating to C++11.
return filter::match(prod, std::bind1st(std::mem_fun(&attribute_filter::match), this));
}
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude");
std::vector<std::string> patterns;
for (auto& r : values) {
patterns.push_back("\"" + r.str() + "\"");
}
ss << " " << attribute_name;
ss << " values " << boost::algorithm::join(patterns, " ");
description = ss.str();
}
};
struct layer_filter : public wildcard_filter {
typedef std::map<std::string, IfcUtil::IfcBaseEntity*> layer_map_t;
layer_filter() {}
layer_filter(bool include, bool traverse, const std::set<std::string>& patterns)
: wildcard_filter(include, traverse, patterns) {}
bool match(IfcUtil::IfcBaseEntity* prod) const {
layer_map_t layers = IfcGeom::Kernel::get_layers(prod);
return std::find_if(layers.begin(), layers.end(), wildcards_match(values)) != layers.end();
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&layer_filter::match), this));
}
struct wildcards_match {
wildcards_match(const std::set<boost::regex>& patterns) : patterns(patterns) {}
bool operator()(const layer_map_t::value_type& layer_map_value) const {
return wildcard_filter::match_values(patterns, layer_map_value.first);
}
std::set<boost::regex> patterns;
};
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " layers";
std::vector<std::string> str_values;
BOOST_FOREACH(const boost::regex& r, values) {
str_values.push_back(" \"" + r.str() + "\"");
}
ss << boost::algorithm::join(str_values, " ");
description = ss.str();
}
};
struct entity_filter : public filter {
std::set<std::string> entity_names;
entity_filter() {}
entity_filter(bool include, bool traverse, const std::set<std::string>& entity_names)
: filter(include, traverse)
, entity_names(entity_names) {}
bool match(IfcUtil::IfcBaseEntity* prod) const {
// The set is iterated over to able to filter on subtypes.
for (auto& name : entity_names) {
if (prod->declaration().is(name)) {
return true;
}
}
return false;
}
bool operator()(IfcUtil::IfcBaseEntity* prod) const {
return filter::match(prod, std::bind1st(std::mem_fun(&entity_filter::match), this));
}
void update_description() {
std::stringstream ss;
ss << (traverse ? "traverse " : "") << (include ? "include" : "exclude") << " entities";
for (auto& name : entity_names) {
ss << " " << name;
}
description = ss.str();
}
};
}
#endif
@@ -0,0 +1,130 @@
/********************************************************************************
* *
* 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/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
* *
* IfcGeom::Representation::Triangulation is a class that represents a *
* triangulated IfcShapeRepresentation. *
* Triangulation.verts is a 1 dimensional vector of float defining the *
* cartesian coordinates of the vertices of the triangulated shape in the *
* format of [x1,y1,z1,..,xn,yn,zn] *
* Triangulation.faces is a 1 dimensional vector of int containing the *
* indices of the triangles referencing positions in Triangulation.verts *
* Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates*
* the visibility of the edges that span the faces in Triangulation.faces *
* *
* IfcGeom::Element represents the actual IfcBuildingElements. *
* IfcGeomObject.name is the GUID of the element *
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
* IfcGeomObject.mesh is a pointer to an IfcMesh *
* IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the *
* orientation and translation of the mesh in relation to the world origin *
* *
* IfcGeom::Iterator::initialize() *
* finds the most suitable representation contexts. Returns true iff *
* at least a single representation will process successfully *
* *
* IfcGeom::Iterator::get() *
* returns a pointer to the current IfcGeom::Element *
* *
* IfcGeom::Iterator::next() *
* returns true iff a following entity is available for a successive call to *
* IfcGeom::Iterator::get() *
* *
* IfcGeom::Iterator::progress() *
* returns an int in [0..100] that indicates the overall progress *
* *
********************************************************************************/
#ifndef IFCGEOMITERATOR_H
#define IFCGEOMITERATOR_H
#include "../../ifcgeom/schema_agnostic/IteratorImplementation.h"
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
namespace IfcGeom {
template <typename P = double, typename PP = P>
class Iterator {
private:
Iterator(const Iterator&); // N/I
Iterator& operator=(const Iterator&); // N/I
IfcParse::IfcFile* file_;
IfcGeom::IteratorSettings settings_;
std::vector<IfcGeom::filter_t> filters_;
IteratorImplementation<P, PP>* implementation_;
public:
Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file)
: file_(file)
, settings_(settings)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), settings, file, filters_);
}
Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters)
: file_(file)
, settings_(settings)
, filters_(filters)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), settings, file, filters_);
}
bool initialize() {
return implementation_->initialize();
}
int progress() const { return implementation_->progress(); }
void compute_bounds() { implementation_->compute_bounds(); }
const gp_XYZ& bounds_min() const { return implementation_->bounds_min(); }
const gp_XYZ& bounds_max() const { return implementation_->bounds_max(); }
const std::string& unit_name() const { return implementation_->getUnitName(); }
double unit_magnitude() const { return implementation_->getUnitMagnitude(); }
IfcParse::IfcFile* file() const { return implementation_->file(); }
IfcUtil::IfcBaseClass* next() const { return implementation_->next(); }
Element<P, PP>* get() { return implementation_->get(); }
NativeElement<P, PP>* get_native() { return implementation_->get_native(); }
const Element<P, PP>* get_object(int id) { return implementation_->get_object(id); }
IfcUtil::IfcBaseClass* create() { return implementation_->create(); }
};
}
#endif
@@ -0,0 +1,160 @@
/********************************************************************************
* *
* 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 IFCGEOMITERATORSETTINGS_H
#define IFCGEOMITERATORSETTINGS_H
#include "ifc_geom_api.h"
#include "../../ifcparse/IfcException.h"
#include "../../ifcparse/IfcBaseClass.h"
#include "../../ifcparse/IfcLogger.h"
namespace IfcGeom
{
class IFC_GEOM_API IteratorSettings
{
public:
/// Enumeration of setting identifiers. These settings define the
/// behaviour of various aspects of IfcOpenShell.
enum Setting
{
/// Specifies whether vertices are welded, meaning that the coordinates
/// vector will only contain unique xyz-triplets. This results in a
/// manifold mesh which is useful for modelling applications, but might
/// result in unwanted shading artifacts in rendering applications.
WELD_VERTICES = 1,
/// Specifies whether to apply the local placements of building elements
/// directly to the coordinates of the representation mesh rather than
/// to represent the local placement in the 4x3 matrix, which will in that
/// case be the identity matrix.
USE_WORLD_COORDS = 1 << 1,
/// Internally IfcOpenShell measures everything in meters. This settings
/// specifies whether to convert IfcGeomObjects back to the units in which
/// the geometry in the IFC file is specified.
CONVERT_BACK_UNITS = 1 << 2,
/// Specifies whether to use the Open Cascade BREP format for representation
/// items rather than to create triangle meshes. This is useful is IfcOpenShell
/// is used as a library in an application that is also built on Open Cascade.
USE_BREP_DATA = 1 << 3,
/// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
/// TopoDS_Shells or whether to keep them as a loose collection of faces.
SEW_SHELLS = 1 << 4,
/// Specifies whether to compose IfcOpeningElements into a single compound
/// in order to speed up the processing of opening subtractions.
FASTER_BOOLEANS = 1 << 5,
/// Disables the subtraction of IfcOpeningElement representations from
/// the related building element representations.
DISABLE_OPENING_SUBTRACTIONS = 1 << 6,
/// Disables the triangulation of the topological representations. Useful if
/// the client application understands Open Cascade's native format.
DISABLE_TRIANGULATION = 1 << 7,
/// Applies default materials to entity instances without a surface style.
APPLY_DEFAULT_MATERIALS = 1 << 8,
/// Specifies whether to include subtypes of IfcCurve.
INCLUDE_CURVES = 1 << 9,
/// Specifies whether to exclude subtypes of IfcSolidModel and IfcSurface.
EXCLUDE_SOLIDS_AND_SURFACES = 1 << 10,
/// Disables computation of normals. Saves time and file size and is useful
/// in instances where you're going to recompute normals for the exported
/// model in other modelling application in any case.
NO_NORMALS = 1 << 11,
/// Generates UVs by using simple box projection. Requires normals.
/// Applicable for OBJ and DAE output.
GENERATE_UVS = 1 << 12,
/// Specifies whether to slice representations according to associated IfcLayerSets.
APPLY_LAYERSETS = 1 << 13,
/// Search for a parent of type IfcBuildingStorey for each representation
SEARCH_FLOOR = 1 << 14,
///
SITE_LOCAL_PLACEMENT = 1 << 15,
///
BUILDING_LOCAL_PLACEMENT = 1 << 16,
///
VALIDATE_QUANTITIES = 1 << 17,
/// Number of different setting flags.
NUM_SETTINGS = 17
};
/// Used to store logical OR combination of setting flags.
typedef unsigned SettingField;
IteratorSettings()
: settings_(WELD_VERTICES) // OR options that default to true here
, deflection_tolerance_(1.e-3)
{
}
/// Note that this is independent of the IFC length unit, one millimeter by default.
double deflection_tolerance() const { return deflection_tolerance_; }
void set_deflection_tolerance(double value)
{
/// @todo Using deflection tolerance of 1e-6 or smaller hangs the conversion, research more in-depth.
/// This bug can be reproduced e.g. with the Duplex model that can be found from http://www.nibs.org/?page=bsa_commonbimfiles#project1
deflection_tolerance_ = value;
if (deflection_tolerance_ <= 1e-6) {
Logger::Message(Logger::LOG_WARNING, "Deflection tolerance cannot be set to <= 1e-6; using the default value 1e-3");
deflection_tolerance_ = 1e-3;
}
}
/// Get boolean value for a single settings or for a combination of settings.
bool get(SettingField setting) const
{
/// @todo If unknown setting value/combination: throw IfcParse::IfcException("Invalid IteratorSetting")?
return (settings_ & setting) != 0;
}
/// Set boolean value for a single settings or for a combination of settings.
void set(SettingField setting, bool value)
{
/// @todo If unknown setting value/combination: throw IfcParse::IfcException("Invalid IteratorSetting")?
if (value) {
settings_ |= setting;
} else {
settings_ &= ~setting;
}
}
protected:
SettingField settings_;
double deflection_tolerance_;
};
class IFC_GEOM_API ElementSettings : public IteratorSettings
{
public:
ElementSettings(const IteratorSettings& settings,
double unit_magnitude,
const std::string& element_type)
: IteratorSettings(settings)
, unit_magnitude_(unit_magnitude)
, element_type_(element_type)
{
}
double unit_magnitude() const { return unit_magnitude_; }
const std::string& element_type() const { return element_type_; }
private:
double unit_magnitude_;
std::string element_type_;
};
}
#endif
@@ -0,0 +1,35 @@
/********************************************************************************
* *
* 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 "IfcGeomMaterial.h"
static double black[3] = {0.,0.,0.};
IfcGeom::Material::Material(const IfcGeom::SurfaceStyle* style) : style(style) {}
bool IfcGeom::Material::hasDiffuse() const { return style->Diffuse() ? true : false; }
bool IfcGeom::Material::hasSpecular() const { return style->Specular() ? true : false; }
bool IfcGeom::Material::hasTransparency() const { return style->Transparency() ? true : false; }
bool IfcGeom::Material::hasSpecularity() const { return style->Specularity() ? true : false; }
const double* IfcGeom::Material::diffuse() const { if (hasDiffuse()) return &((*style->Diffuse()).R()); else return black; }
const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
const std::string &IfcGeom::Material::name() const { return style->Name(); }
const std::string &IfcGeom::Material::original_name() const { return style->original_name(); }
bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; }
@@ -0,0 +1,51 @@
/********************************************************************************
* *
* 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 IFCGEOMMATERIAL_H
#define IFCGEOMMATERIAL_H
#include <string>
#include "../../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
namespace IfcGeom {
class IFC_GEOM_API Material {
private:
const IfcGeom::SurfaceStyle* style;
public:
explicit Material(const IfcGeom::SurfaceStyle* style = 0); // TODO default constructor for vector?
// Material(const Material& other);
// Material& operator=(const Material& other);
bool hasDiffuse() const;
bool hasSpecular() const;
bool hasTransparency() const;
bool hasSpecularity() const;
const double* diffuse() const;
const double* specular() const;
double transparency() const;
double specularity() const;
const std::string &name() const;
const std::string &original_name() const;
bool operator==(const Material& other) const;
};
}
#endif
@@ -0,0 +1,101 @@
/********************************************************************************
* *
* 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 IFCGEOMRENDERSTYLES_H
#define IFCGEOMRENDERSTYLES_H
#include "../../ifcgeom/schema_agnostic/ifc_geom_api.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/optional.hpp>
#include <sstream>
namespace IfcGeom {
class IFC_GEOM_API SurfaceStyle {
public:
class ColorComponent {
private:
double data[3];
public:
ColorComponent(double r, double g, double b) {
data[0] = r; data[1] = g; data[2] = b;
}
const double& R() const { return data[0]; }
const double& G() const { return data[1]; }
const double& B() const { return data[2]; }
double& R() { return data[0]; }
double& G() { return data[1]; }
double& B() { return data[2]; }
};
private:
std::string name;
std::string original_name_;
boost::optional<int> id;
boost::optional<ColorComponent> diffuse, specular;
boost::optional<double> transparency;
boost::optional<double> specularity;
public:
SurfaceStyle() : name("surface-style") {}
SurfaceStyle(int id) : id(id) {
std::stringstream sstr;
sstr << "surface-style-" << id;
this->name = sstr.str();
}
SurfaceStyle(const std::string& name) : name(name), original_name_(name) {}
SurfaceStyle(int id, const std::string& name) : original_name_(name), id(id)
{
std::stringstream sstr;
std::string sanitized = name;
boost::to_lower(sanitized);
boost::replace_all(sanitized, " ", "-");
sstr << "surface-style-" << id << "-" << sanitized;
this->name = sstr.str();
}
// Not used at this point. In fact, equality testing in the current
// architecture can just as easily be accomplished by comparing the
// pointer addresses of the styles, as they are always referenced
// from out of a global map of some sort.
bool operator==(const SurfaceStyle& other) {
return name == other.name;
}
/// ID name, e.g. "surface-style-66675-metal---aluminium"
const std::string& Name() const { return name; }
/// Original name, if available, e.g. "Metal - Aluminium"
const std::string& original_name() const { return original_name_; }
const boost::optional<ColorComponent>& Diffuse() const { return diffuse; }
const boost::optional<ColorComponent>& Specular() const { return specular; }
const boost::optional<double>& Transparency() const { return transparency; }
const boost::optional<double>& Specularity() const { return specularity; }
boost::optional<ColorComponent>& Diffuse() { return diffuse; }
boost::optional<ColorComponent>& Specular() { return specular; }
boost::optional<double>& Transparency() { return transparency; }
boost::optional<double>& Specularity() { return specularity; }
};
IFC_GEOM_API const SurfaceStyle* get_default_style(const std::string& ifc_type);
IFC_GEOM_API void set_default_style_file(const std::string& json_file);
}
#endif
@@ -0,0 +1,259 @@
/********************************************************************************
* *
* 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 <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#include <Geom_Plane.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include "IfcGeomRepresentation.h"
#include "../../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
#include "../../ifcgeom/schema_agnostic/Kernel.h"
IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
: Representation(brep.settings())
, id_(brep.id())
{
TopoDS_Compound compound = brep.as_compound();
for (IfcGeom::ConversionResults::const_iterator it = brep.begin(); it != brep.end(); ++ it) {
if (it->hasStyle() && it->Style().Diffuse()) {
const IfcGeom::SurfaceStyle::ColorComponent& clr = *it->Style().Diffuse();
surface_styles_.push_back(clr.R());
surface_styles_.push_back(clr.G());
surface_styles_.push_back(clr.B());
} else {
surface_styles_.push_back(-1.);
surface_styles_.push_back(-1.);
surface_styles_.push_back(-1.);
}
if (it->hasStyle() && it->Style().Transparency()) {
surface_styles_.push_back(1. - *it->Style().Transparency());
} else {
surface_styles_.push_back(1.);
}
}
std::stringstream sstream;
BRepTools::Write(compound,sstream);
brep_data_ = sstream.str();
}
// @todo copied from kernel
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t) {
if (t.Form() == gp_Identity) {
return s;
} else {
/// @todo set to 1. and exactly 1. or use epsilon?
if (t.ScaleFactor() != 1.) {
return BRepBuilderAPI_Transform(s, t, true);
} else {
return s.Moved(t);
}
}
}
TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) {
if (t.Form() == gp_Other) {
return BRepBuilderAPI_GTransform(s, t, true);
} else {
return apply_transformation(s, t.Trsf());
}
}
TopoDS_Compound IfcGeom::Representation::BRep::as_compound() const {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
const TopoDS_Shape& s = *(OpenCascadeShape*) it->Shape();
gp_GTrsf trsf;
if (it->Placement()) {
trsf = ((OpenCascadePlacement*)it->Placement())->trsf();
}
if (settings().get(IteratorSettings::CONVERT_BACK_UNITS)) {
gp_Trsf scale;
scale.SetScaleFactor(1.0 / settings().unit_magnitude());
trsf.PreMultiply(scale);
}
const TopoDS_Shape moved_shape = apply_transformation(s, trsf);
builder.Add(compound, moved_shape);
}
return compound;
}
namespace {
void accumulate(const gp_Ax3& ax, const gp_Dir& normal, double area, double& along_x, double& along_y, double& along_z) {
along_x += area * fabs(ax.XDirection().Dot(normal));
along_y += area * fabs(ax.YDirection().Dot(normal));
along_z += area * fabs(ax.Direction().Dot(normal));
}
void surface_area_along_direction(double tol, const TopoDS_Shape& s, const gp_Ax3& ax, double& along_x, double& along_y, double& along_z) {
along_x = along_y = along_z = 0.;
bool meshed = false;
TopExp_Explorer exp(s, TopAbs_FACE);
for (; exp.More(); exp.Next()) {
const TopoDS_Face& face = TopoDS::Face(exp.Current());
Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast(surf);
if (surf->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
GProp_GProps prop_area;
BRepGProp::SurfaceProperties(face, prop_area);
const double area = prop_area.Mass();
accumulate(ax, plane->Position().Direction(), area, along_x, along_y, along_z);
} else {
if (!meshed) {
try {
BRepMesh_IncrementalMesh(s, tol);
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Failed to triangulate shape");
return;
}
meshed = true;
}
TopLoc_Location loc;
Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(face, loc);
if (!tri.IsNull()) {
const TColgp_Array1OfPnt& nodes = tri->Nodes();
std::vector<gp_XYZ> coords;
coords.reserve(nodes.Length());
for (int i = 1; i <= nodes.Length(); ++i) {
coords.push_back(nodes(i).Transformed(loc).XYZ());
}
const Poly_Array1OfTriangle& triangles = tri->Triangles();
for (int i = 1; i <= triangles.Length(); ++i) {
int n1, n2, n3;
if (face.Orientation() == TopAbs_REVERSED) {
triangles(i).Get(n3, n2, n1);
} else {
triangles(i).Get(n1, n2, n3);
}
const gp_XYZ& pt1 = coords[n1 - 1];
const gp_XYZ& pt2 = coords[n2 - 1];
const gp_XYZ& pt3 = coords[n3 - 1];
const gp_Vec v1 = pt2 - pt1;
const gp_Vec v2 = pt3 - pt2;
const gp_Vec v3 = pt1 - pt3;
const gp_Vec normal_vector = v1 ^ v2;
if (normal_vector.Magnitude() > 1.e-9) {
gp_Dir normal = gp_Dir();
double edge_lengths[3] = { v1.Magnitude(), v2.Magnitude(), v3.Magnitude() };
std::sort(&edge_lengths[0], &edge_lengths[2]);
const double& a = edge_lengths[0];
const double& b = edge_lengths[1];
const double& c = edge_lengths[2];
const double area = 0.25 * sqrt((a + (b + c))*(c - (a - b))*(c + (a - b))*(a + (b - c)));
accumulate(ax, normal, area, along_x, along_y, along_z);
}
}
}
}
}
}
}
bool IfcGeom::Representation::BRep::calculate_surface_area(double& area) const {
try {
area = 0.;
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
GProp_GProps prop;
BRepGProp::SurfaceProperties(*(OpenCascadeShape*)it->Shape(), prop);
area += prop.Mass();
}
return true;
} catch (...) {
Logger::Error("Error during calculation of surface area");
return false;
}
}
bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const {
try {
volume = 0.;
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) {
GProp_GProps prop;
BRepGProp::VolumeProperties(*(OpenCascadeShape*)it->Shape(), prop);
volume += prop.Mass();
} else {
return false;
}
}
return true;
} catch (...) {
Logger::Error("Error during calculation of volume");
return false;
}
}
bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const ConversionResultPlacement* place, double & along_x, double & along_y, double & along_z) const {
try {
gp_Trsf trsf = ((OpenCascadePlacement*)place)->trsf().Trsf();
gp_Mat mat = trsf.HVectorialPart();
gp_Ax3 ax(trsf.TranslationPart(), mat.Column(3), mat.Column(1));
along_x = along_y = along_z = 0.;
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
double x, y, z;
surface_area_along_direction(settings().deflection_tolerance(), *(OpenCascadeShape*)it->Shape(), ax, x, y, z);
if (Kernel::is_manifold(*(OpenCascadeShape*)it->Shape())) {
x /= 2.;
y /= 2.;
z /= 2.;
}
along_x += x;
along_y += y;
along_z += z;
}
return true;
} catch (...) {
Logger::Error("Error during calculation of projected surface area");
return false;
}
}
@@ -0,0 +1,255 @@
/********************************************************************************
* *
* 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 IFCGEOMREPRESENTATION_H
#define IFCGEOMREPRESENTATION_H
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepGProp_Face.hxx>
#include <Poly_Triangulation.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TopoDS.hxx>
#include <BRepTools.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_QuasiUniformDeflection.hxx>
#include <Geom_SphericalSurface.hxx>
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
#include "../../ifcgeom/schema_agnostic/ConversionResult.h"
#include <TopoDS_Compound.hxx>
#include <map>
namespace IfcGeom {
namespace Representation {
class IFC_GEOM_API Representation {
Representation(const Representation&); //N/A
Representation& operator =(const Representation&); //N/A
protected:
const ElementSettings settings_;
public:
explicit Representation(const ElementSettings& settings)
: settings_(settings)
{}
const ElementSettings& settings() const { return settings_; }
virtual ~Representation() {}
};
class IFC_GEOM_API BRep : public Representation {
private:
std::string id_;
const IfcGeom::ConversionResults shapes_;
BRep(const BRep& other);
BRep& operator=(const BRep& other);
public:
BRep(const ElementSettings& settings, const std::string& id, const IfcGeom::ConversionResults& shapes)
: Representation(settings)
, id_(id)
, shapes_(shapes)
{}
virtual ~BRep() {}
IfcGeom::ConversionResults::const_iterator begin() const { return shapes_.begin(); }
IfcGeom::ConversionResults::const_iterator end() const { return shapes_.end(); }
const IfcGeom::ConversionResults& shapes() const { return shapes_; }
const std::string& id() const { return id_; }
TopoDS_Compound as_compound() const;
bool calculate_volume(double&) const;
bool calculate_surface_area(double&) const;
bool calculate_projected_surface_area(const ConversionResultPlacement* ax, double& along_x, double& along_y, double& along_z) const;
};
class IFC_GEOM_API Serialization : public Representation {
private:
std::string id_;
std::string brep_data_;
std::vector<double> surface_styles_;
public:
const std::string& brep_data() const { return brep_data_; }
const std::vector<double>& surface_styles() const { return surface_styles_; }
Serialization(const BRep& brep);
virtual ~Serialization() {}
const std::string& id() const { return id_; }
private:
Serialization();
Serialization(const Serialization&);
Serialization& operator=(const Serialization&);
};
template <typename P>
class Triangulation : public Representation {
private:
// A nested pair of floats and a material index to be able to store an XYZ coordinate in a map.
// TODO: Make this a std::tuple when compilers add support for that.
typedef typename std::pair<P, std::pair<P, P> > Coordinate;
typedef typename std::pair<int, Coordinate> VertexKey;
typedef std::map<VertexKey, int> VertexKeyMap;
typedef std::pair<int, int> Edge;
std::string id_;
std::vector<P> _verts;
std::vector<int> _faces;
std::vector<int> _edges;
std::vector<P> _normals;
std::vector<P> uvs_;
std::vector<int> _material_ids;
std::vector<Material> _materials;
VertexKeyMap welds;
public:
const std::string& id() const { return id_; }
const std::vector<P>& verts() const { return _verts; }
const std::vector<int>& faces() const { return _faces; }
const std::vector<int>& edges() const { return _edges; }
const std::vector<P>& normals() const { return _normals; }
const std::vector<P>& uvs() const { return uvs_; }
const std::vector<int>& material_ids() const { return _material_ids; }
const std::vector<Material>& materials() const { return _materials; }
Triangulation(const BRep& shape_model)
: Representation(shape_model.settings())
, id_(shape_model.id())
{
for ( IfcGeom::ConversionResults::const_iterator iit = shape_model.begin(); iit != shape_model.end(); ++ iit ) {
int surface_style_id = -1;
if (iit->hasStyle()) {
Material adapter(&iit->Style());
std::vector<Material>::const_iterator jt = std::find(_materials.begin(), _materials.end(), adapter);
if (jt == _materials.end()) {
surface_style_id = (int)_materials.size();
_materials.push_back(adapter);
} else {
surface_style_id = (int)(jt - _materials.begin());
}
}
if (settings().get(IteratorSettings::APPLY_DEFAULT_MATERIALS) && surface_style_id == -1) {
Material material(IfcGeom::get_default_style(settings().element_type()));
std::vector<Material>::const_iterator mit = std::find(_materials.begin(), _materials.end(), material);
if (mit == _materials.end()) {
surface_style_id = (int)_materials.size();
_materials.push_back(material);
} else {
surface_style_id = (int)(mit - _materials.begin());
}
}
iit->Shape()->Triangulate(settings(), iit->Placement(), this, surface_style_id);
}
}
virtual ~Triangulation() {}
/// Generates UVs for a single mesh using box projection.
/// @todo Very simple impl. Assumes that input vertices and normals match 1:1.
static std::vector<P> box_project_uvs(const std::vector<P> &vertices, const std::vector<P> &normals)
{
std::vector<P> uvs;
uvs.resize(vertices.size() / 3 * 2);
for (size_t uv_idx = 0, v_idx = 0;
uv_idx < uvs.size() && v_idx < vertices.size() && v_idx < normals.size();
uv_idx += 2, v_idx += 3) {
P n_x = normals[v_idx], n_y = normals[v_idx + 1], n_z = normals[v_idx + 2];
P v_x = vertices[v_idx], v_y = vertices[v_idx + 1], v_z = vertices[v_idx + 2];
if (std::abs(n_x) > std::abs(n_y) && std::abs(n_x) > std::abs(n_z)) {
uvs[uv_idx] = v_z;
uvs[uv_idx + 1] = v_y;
}
if (std::abs(n_y) > std::abs(n_x) && std::abs(n_y) > std::abs(n_z)) {
uvs[uv_idx] = v_x;
uvs[uv_idx + 1] = v_z;
}
if (std::abs(n_z) > std::abs(n_x) && std::abs(n_z) > std::abs(n_y)) {
uvs[uv_idx] = v_x;
uvs[uv_idx + 1] = v_y;
}
}
return uvs;
}
public:
// Welds vertices that belong to different faces
int addVertex(int material_index, P X, P Y, P Z) {
const bool convert = settings().get(IteratorSettings::CONVERT_BACK_UNITS);
X = static_cast<P>(convert ? (X / settings().unit_magnitude()) : X);
Y = static_cast<P>(convert ? (Y / settings().unit_magnitude()) : Y);
Z = static_cast<P>(convert ? (Z / settings().unit_magnitude()) : Z);
int i = (int) _verts.size() / 3;
if (settings().get(IteratorSettings::WELD_VERTICES)) {
const VertexKey key = std::make_pair(material_index, std::make_pair(X, std::make_pair(Y, Z)));
typename VertexKeyMap::const_iterator it = welds.find(key);
if ( it != welds.end() ) return it->second;
i = (int) welds.size();
welds[key] = i;
}
_verts.push_back(X);
_verts.push_back(Y);
_verts.push_back(Z);
return i;
}
inline void addEdge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
else edgecount[e] ++;
edges_temp.push_back(e);
}
inline void addNormal(P X, P Y, P Z) {
_normals.push_back(X);
_normals.push_back(Y);
_normals.push_back(Z);
}
inline void addFace(int style, int i0, int i1, int i2) {
_faces.push_back(i0);
_faces.push_back(i1);
_faces.push_back(i2);
_material_ids.push_back(style);
}
inline void registerEdge(int i0, int i1) {
_edges.push_back(i0);
_edges.push_back(i1);
}
private:
Triangulation();
Triangulation(const Triangulation&);
Triangulation& operator=(const Triangulation&);
};
}
}
#endif
@@ -0,0 +1,47 @@
#include "IteratorImplementation.h"
#include <boost/algorithm/string/case_conv.hpp>
template <typename P, typename PP>
IteratorFactoryImplementation<P, PP>& iterator_implementations() {
static IteratorFactoryImplementation<P, PP> impl;
return impl;
}
template IteratorFactoryImplementation<float, float>& iterator_implementations<float, float>();
template IteratorFactoryImplementation<float, double>& iterator_implementations<float, double>();
template IteratorFactoryImplementation<double, double>& iterator_implementations<double, double>();
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc2x3(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
extern void init_IteratorImplementation_Ifc4(IteratorFactoryImplementation<P, PP>*);
template <typename P, typename PP>
IteratorFactoryImplementation<P, PP>::IteratorFactoryImplementation() {
init_IteratorImplementation_Ifc2x3(this);
init_IteratorImplementation_Ifc4(this);
}
template <typename P, typename PP>
void IteratorFactoryImplementation<P, PP>::bind(const std::string& schema_name, typename get_factory_type<P, PP>::type fn) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
this->insert(std::make_pair(schema_name_lower, fn));
}
template <typename P, typename PP>
IfcGeom::IteratorImplementation<P, PP>* IteratorFactoryImplementation<P, PP>::construct(const std::string& schema_name, const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
typename std::map<std::string, typename get_factory_type<P, PP>::type>::const_iterator it;
it = this->find(schema_name_lower);
if (it == this->end()) {
throw IfcParse::IfcException("No geometry iterator registered for " + schema_name);
}
return it->second(settings, file, filters);
}
template class IteratorFactoryImplementation<float, float>;
template class IteratorFactoryImplementation<float, double>;
template class IteratorFactoryImplementation<double, double>;
@@ -0,0 +1,81 @@
#ifndef ITERATOR_IMPLEMENTATION_H
#define ITERATOR_IMPLEMENTATION_H
#include "../../ifcparse/IfcFile.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomFilter.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include <gp_XYZ.hxx>
#include <boost/function.hpp>
#include <map>
#include <string>
namespace IfcGeom {
template <typename P, typename PP>
class IteratorImplementation;
template <typename P, typename PP>
class Element;
template <typename P, typename PP>
class NativeElement;
}
typedef boost::function3<IfcGeom::IteratorImplementation<float, float>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_float_float_fn;
typedef boost::function3<IfcGeom::IteratorImplementation<float, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_float_double_fn;
typedef boost::function3<IfcGeom::IteratorImplementation<double, double>*, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&> iterator_double_double_fn;
template <typename P, typename PP>
struct get_factory_type {};
template <>
struct get_factory_type<float, float> {
typedef iterator_float_float_fn type;
};
template <>
struct get_factory_type<float, double> {
typedef iterator_float_double_fn type;
};
template <>
struct get_factory_type<double, double> {
typedef iterator_double_double_fn type;
};
template <typename P, typename PP>
class IteratorFactoryImplementation : public std::map<std::string, typename get_factory_type<P, PP>::type> {
public:
IteratorFactoryImplementation();
void bind(const std::string& schema_name, typename get_factory_type<P, PP>::type fn);
IfcGeom::IteratorImplementation<P, PP>* construct(const std::string& schema_name, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&);
};
template <typename P, typename PP>
IteratorFactoryImplementation<P, PP>& iterator_implementations();
namespace IfcGeom {
template <typename P, typename PP>
class IteratorImplementation {
public:
virtual bool initialize() = 0;
virtual void compute_bounds() = 0;
virtual const gp_XYZ& bounds_min() const = 0;
virtual const gp_XYZ& bounds_max() const = 0;
virtual int progress() const = 0;
virtual const std::string& getUnitName() const = 0;
virtual double getUnitMagnitude() const = 0;
virtual IfcParse::IfcFile* file() const = 0;
virtual IfcUtil::IfcBaseClass* next() = 0;
virtual Element<P, PP>* get() = 0;
virtual NativeElement<P, PP>* get_native() = 0;
virtual const Element<P, PP>* get_object(int id) = 0;
virtual IfcUtil::IfcBaseClass* create() = 0;
};
}
#endif
+264
View File
@@ -0,0 +1,264 @@
#include "Kernel.h"
#include "../../ifcparse/Ifc2x3.h"
#include "../../ifcparse/Ifc4.h"
#include <TopExp.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
IfcGeom::Kernel::Kernel(const std::string& geometry_library, IfcParse::IfcFile* file) {
if (file != 0) {
if (file->schema() == 0) {
throw IfcParse::IfcException("No schema associated with file");
}
const std::string& schema_name = file->schema()->name();
implementation_ = impl::kernel_implementations().construct(schema_name, geometry_library, file);
}
}
int IfcGeom::Kernel::count(const TopoDS_Shape& s, TopAbs_ShapeEnum t, bool unique) {
if (unique) {
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(s, t, map);
return map.Extent();
} else {
int i = 0;
TopExp_Explorer exp(s, t);
for (; exp.More(); exp.Next()) {
++i;
}
return i;
}
}
int IfcGeom::Kernel::surface_genus(const TopoDS_Shape& s) {
int nv = count(s, TopAbs_VERTEX, true);
int ne = count(s, TopAbs_EDGE, true);
int nf = count(s, TopAbs_FACE, true);
const int euler = nv - ne + nf;
const int genus = (2 - euler) / 2;
return genus;
}
IfcGeom::impl::KernelFactoryImplementation& IfcGeom::impl::kernel_implementations() {
static KernelFactoryImplementation impl;
return impl;
}
extern void init_KernelImplementation_opencascade_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_opencascade_Ifc4(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_cgal_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_cgal_Ifc4(IfcGeom::impl::KernelFactoryImplementation*);
IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() {
init_KernelImplementation_opencascade_Ifc2x3(this);
init_KernelImplementation_opencascade_Ifc4(this);
init_KernelImplementation_cgal_Ifc2x3(this);
init_KernelImplementation_cgal_Ifc4(this);
}
void IfcGeom::impl::KernelFactoryImplementation::bind(const std::string& schema_name, const std::string& geometry_library, IfcGeom::impl::kernel_fn fn) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
this->insert(std::make_pair(std::make_pair(schema_name_lower, geometry_library), fn));
}
IfcGeom::Kernel* IfcGeom::impl::KernelFactoryImplementation::construct(const std::string& schema_name, const std::string& geometry_library, IfcParse::IfcFile* file) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
std::map<std::pair<std::string, std::string>, IfcGeom::impl::kernel_fn>::const_iterator it;
it = this->find(std::make_pair(schema_name_lower, geometry_library));
if (it == end()) {
throw IfcParse::IfcException("No geometry kernel registered for " + schema_name);
}
return it->second(file);
}
#define CREATE_GET_DECOMPOSING_ENTITY(IfcSchema) \
\
IfcSchema::IfcObjectDefinition* get_decomposing_entity_impl(IfcSchema::IfcProduct* product) { \
IfcSchema::IfcObjectDefinition* parent = 0; \
\
/* In case of an opening element, parent to the RelatingBuildingElement */ \
if (product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { \
IfcSchema::IfcOpeningElement* opening = (IfcSchema::IfcOpeningElement*)product; \
IfcSchema::IfcRelVoidsElement::list::ptr voids = opening->VoidsElements(); \
if (voids->size()) { \
IfcSchema::IfcRelVoidsElement* ifc_void = *voids->begin(); \
parent = ifc_void->RelatingBuildingElement(); \
} \
} else if (product->declaration().is(IfcSchema::IfcElement::Class())) { \
IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; \
IfcSchema::IfcRelFillsElement::list::ptr fills = element->FillsVoids(); \
/* In case of a RelatedBuildingElement parent to the opening element */ \
if (fills->size()) { \
for (IfcSchema::IfcRelFillsElement::list::it it = fills->begin(); it != fills->end(); ++it) { \
IfcSchema::IfcRelFillsElement* fill = *it; \
IfcSchema::IfcObjectDefinition* ifc_objectdef = fill->RelatingOpeningElement(); \
if (product == ifc_objectdef) continue; \
parent = ifc_objectdef; \
} \
} \
/* Else simply parent to the containing structure */ \
if (!parent) { \
IfcSchema::IfcRelContainedInSpatialStructure::list::ptr parents = element->ContainedInStructure(); \
if (parents->size()) { \
IfcSchema::IfcRelContainedInSpatialStructure* container = *parents->begin(); \
parent = container->RelatingStructure(); \
} \
} \
} \
\
/* Parent decompositions to the RelatingObject */ \
if (!parent) { \
IfcEntityList::ptr parents = product->data().getInverse((&IfcSchema::IfcRelAggregates::Class()), -1); \
parents->push(product->data().getInverse((&IfcSchema::IfcRelNests::Class()), -1)); \
for (IfcEntityList::it it = parents->begin(); it != parents->end(); ++it) { \
IfcSchema::IfcRelDecomposes* decompose = (IfcSchema::IfcRelDecomposes*)*it; \
IfcUtil::IfcBaseEntity* ifc_objectdef; \
\
ifc_objectdef = get_RelatingObject(decompose); \
\
if (product == ifc_objectdef) continue; \
parent = ifc_objectdef->as<IfcSchema::IfcObjectDefinition>(); \
} \
} \
return parent; \
}
namespace {
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc4::IfcRelDecomposes* decompose) {
Ifc4::IfcRelAggregates* aggr = decompose->as<Ifc4::IfcRelAggregates>();
if (aggr != nullptr) {
return aggr->RelatingObject();
}
return nullptr;
}
IfcUtil::IfcBaseEntity* get_RelatingObject(Ifc2x3::IfcRelDecomposes* decompose) {
return decompose->RelatingObject();
}
CREATE_GET_DECOMPOSING_ENTITY(Ifc2x3);
CREATE_GET_DECOMPOSING_ENTITY(Ifc4);
}
IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
namespace {
// LayerAssignments renamed from plural to singular, LayerAssignment, so work around that
IfcEntityList::ptr getLayerAssignments(Ifc2x3::IfcRepresentationItem* item) {
return item->LayerAssignments()->generalize();
}
IfcEntityList::ptr getLayerAssignments(Ifc4::IfcRepresentationItem* item) {
return item->LayerAssignment()->generalize();
}
template <typename Schema>
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers_impl(typename Schema::IfcProduct* prod) {
std::map<std::string, IfcUtil::IfcBaseEntity*> layers;
if (prod->hasRepresentation()) {
IfcEntityList::ptr r = IfcParse::traverse(prod->Representation());
typename Schema::IfcRepresentation::list::ptr representations = r->as<typename Schema::IfcRepresentation>();
for (typename Schema::IfcRepresentation::list::it it = representations->begin(); it != representations->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = (*it)->LayerAssignments();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
typename Schema::IfcRepresentationItem::list::ptr items = r->as<typename Schema::IfcRepresentationItem>();
for (typename Schema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++it) {
typename Schema::IfcPresentationLayerAssignment::list::ptr a = getLayerAssignments(*it)->template as<typename Schema::IfcPresentationLayerAssignment>();
for (typename Schema::IfcPresentationLayerAssignment::list::it jt = a->begin(); jt != a->end(); ++jt) {
layers[(*jt)->Name()] = *jt;
}
}
}
return layers;
}
}
std::map<std::string, IfcUtil::IfcBaseEntity*> IfcGeom::Kernel::get_layers(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_layers_impl<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_layers_impl<Ifc4>(inst->as<Ifc4::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
bool IfcGeom::Kernel::is_manifold(const TopoDS_Shape& a) {
if (a.ShapeType() == TopAbs_COMPOUND || a.ShapeType() == TopAbs_SOLID) {
TopoDS_Iterator it(a);
for (; it.More(); it.Next()) {
if (!is_manifold(it.Value())) {
return false;
}
}
return true;
} else {
TopTools_IndexedDataMapOfShapeListOfShape map;
TopExp::MapShapesAndAncestors(a, TopAbs_EDGE, TopAbs_FACE, map);
for (int i = 1; i <= map.Extent(); ++i) {
if (map.FindFromIndex(i).Extent() != 2) {
return false;
}
}
return true;
}
}
namespace {
template <typename Schema>
IfcEntityList::ptr find_openings_helper(typename Schema::IfcProduct* product) {
typename IfcEntityList::ptr openings(new IfcEntityList);
if (product->declaration().is(Schema::IfcElement::Class()) && !product->declaration().is(Schema::IfcOpeningElement::Class())) {
typename Schema::IfcElement* element = (typename Schema::IfcElement*)product;
openings = element->HasOpenings()->generalize();
}
// Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements?
typename Schema::IfcObjectDefinition* obdef = product->as<typename Schema::IfcObjectDefinition>();
for (;;) {
auto decomposes = obdef->Decomposes()->generalize();
if (decomposes->size() != 1) break;
typename Schema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->as<typename Schema::IfcRelAggregates>()->RelatingObject();
if (rel_obdef->declaration().is(Schema::IfcElement::Class()) && !rel_obdef->declaration().is(Schema::IfcOpeningElement::Class())) {
typename Schema::IfcElement* element = (typename Schema::IfcElement*)rel_obdef;
openings->push(element->HasOpenings()->generalize());
}
obdef = rel_obdef;
}
return openings;
}
}
IfcEntityList::ptr IfcGeom::Kernel::find_openings(IfcUtil::IfcBaseEntity* inst) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return find_openings_helper<Ifc2x3>(inst->as<Ifc2x3::IfcProduct>());
} else if (inst->as<Ifc4::IfcProduct>()) {
return find_openings_helper<Ifc4>(inst->as<Ifc4::IfcProduct>());
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
+102
View File
@@ -0,0 +1,102 @@
#ifndef ITERATOR_KERNEL_H
#define ITERATOR_KERNEL_H
#include "../../ifcparse/IfcFile.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/schema_agnostic/ConversionResult.h"
#include <boost/function.hpp>
#include <TopExp_Explorer.hxx>
namespace IfcGeom {
template <typename P, typename PP>
class NativeElement;
class Kernel {
private:
Kernel* implementation_;
public:
// Tolerances and settings for various geometrical operations:
enum GeomValue {
// Specifies the deflection of the mesher
// Default: 0.001m / 1mm
GV_DEFLECTION_TOLERANCE,
// Specifies the tolerance of the wire builder, most notably for trimmed curves
// Default: 0.0001m / 0.1mm
GV_WIRE_CREATION_TOLERANCE,
// Specifies the minimal area of a face to be included in an IfcConnectedFaceset
// Read-only
GV_MINIMAL_FACE_AREA,
// Specifies the threshold distance under which cartesian points are deemed equal
// Default: 0.00001m / 0.01mm
GV_POINT_EQUALITY_TOLERANCE,
// The length unit used the creation of TopoDS_Shapes, primarily affects the
// interpretation of IfcCartesianPoints and IfcVector magnitudes
// DefaultL 1.0
GV_LENGTH_UNIT,
// The plane angle unit used for the creation of TopoDS_Shapes, primarily affects
// the interpretation of IfcParamaterValues of IfcTrimmedCurves
// Default: -1.0 (= not set, fist try degrees, then radians)
GV_PLANEANGLE_UNIT,
// The precision used in boolean operations, setting this value too low results
// in artefacts and potentially modelling failures
// Default: 0.00001 (obtained from IfcGeometricRepresentationContext if available)
GV_PRECISION,
// Whether to process shapes of type Face or higher (1) Wire or lower (-1) or all (0)
GV_DIMENSIONALITY
};
Kernel(const std::string& geometry_library, IfcParse::IfcFile* file_ = 0);
virtual ~Kernel() {}
virtual void setValue(GeomValue var, double value) {
implementation_->setValue(var, value);
}
virtual double getValue(GeomValue var) const {
return implementation_->getValue(var);
}
virtual NativeElement<double, double>* convert(
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
IfcUtil::IfcBaseClass* product)
{
return implementation_->convert(settings, representation, product);
}
virtual ConversionResults convert(IfcUtil::IfcBaseClass* item) {
return implementation_->convert(item);
}
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, gp_Trsf& trsf) {
return implementation_->convert_placement(item, trsf);
}
static int count(const TopoDS_Shape&, TopAbs_ShapeEnum, bool unique=false);
static int surface_genus(const TopoDS_Shape&);
static bool is_manifold(const TopoDS_Shape& a);
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*);
static std::map<std::string, IfcUtil::IfcBaseEntity*> get_layers(IfcUtil::IfcBaseEntity*);
static IfcEntityList::ptr find_openings(IfcUtil::IfcBaseEntity* product);
};
namespace impl {
typedef boost::function1<Kernel*, IfcParse::IfcFile*> kernel_fn;
class KernelFactoryImplementation : public std::map<std::pair<std::string, std::string>, kernel_fn> {
public:
KernelFactoryImplementation();
void bind(const std::string& schema_name, const std::string& geometry_library, kernel_fn);
Kernel* construct(const std::string& schema_name, const std::string& geometry_library, IfcParse::IfcFile*);
};
KernelFactoryImplementation& kernel_implementations();
}
}
#endif
@@ -0,0 +1,30 @@
#include "Serialization.h"
#include <boost/algorithm/string/case_conv.hpp>
namespace IfcGeom {
extern IfcUtil::IfcBaseClass* tesselate_Ifc2x3(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* tesselate_Ifc4(const TopoDS_Shape& shape, double deflection);
extern IfcUtil::IfcBaseClass* serialise_Ifc2x3(const TopoDS_Shape& shape, bool advanced);
extern IfcUtil::IfcBaseClass* serialise_Ifc4(const TopoDS_Shape& shape, bool advanced);
}
template <typename Fn, typename T>
IfcUtil::IfcBaseClass* execute_based_on_schema(Fn fn1, Fn fn2, const std::string& schema_name, const TopoDS_Shape& shape, T t) {
const std::string schema_name_lower = boost::to_lower_copy(schema_name);
if (schema_name_lower == "ifc2x3") {
return fn1(shape, t);
} else if (schema_name_lower == "ifc4") {
return fn2(shape, t);
} else {
throw IfcParse::IfcException("No geometry serialization available for " + schema_name);
}
}
IfcUtil::IfcBaseClass* IfcGeom::tesselate(const std::string& schema_name, const TopoDS_Shape& shape, double deflection) {
return execute_based_on_schema(IfcGeom::tesselate_Ifc2x3, IfcGeom::tesselate_Ifc4, schema_name, shape, deflection);
}
IfcUtil::IfcBaseClass* IfcGeom::serialise(const std::string& schema_name, const TopoDS_Shape& shape, bool advanced) {
return execute_based_on_schema(IfcGeom::serialise_Ifc2x3, IfcGeom::serialise_Ifc4, schema_name, shape, advanced);
}
@@ -0,0 +1,12 @@
#include "../../ifcparse/IfcBaseClass.h"
#include "../../ifcgeom/schema_agnostic/ifc_geom_api.h"
#include <TopoDS_Shape.hxx>
#include <string>
namespace IfcGeom {
IFC_GEOM_API IfcUtil::IfcBaseClass* tesselate(const std::string& schema_name, const TopoDS_Shape& shape, double deflection);
IFC_GEOM_API IfcUtil::IfcBaseClass* serialise(const std::string& schema_name, const TopoDS_Shape& shape, bool advanced);
}
@@ -0,0 +1,122 @@
#include "../../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <map>
namespace pt = boost::property_tree;
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials;
static IfcGeom::SurfaceStyle default_material;
static bool default_materials_initialized = false;
void InitDefaultMaterials() {
default_materials.insert(std::make_pair("IfcSite", IfcGeom::SurfaceStyle("IfcSite")));
default_materials["IfcSite"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.65));
default_materials.insert(std::make_pair("IfcSlab", IfcGeom::SurfaceStyle("IfcSlab")));
default_materials["IfcSlab"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.4, 0.4, 0.4));
default_materials.insert(std::make_pair("IfcWallStandardCase", IfcGeom::SurfaceStyle("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWall", IfcGeom::SurfaceStyle("IfcWall")));
default_materials["IfcWall"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.9, 0.9, 0.9));
default_materials.insert(std::make_pair("IfcWindow", IfcGeom::SurfaceStyle("IfcWindow")));
default_materials["IfcWindow"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.8, 0.75));
default_materials["IfcWindow"].Transparency().reset(0.3);
default_materials.insert(std::make_pair("IfcDoor", IfcGeom::SurfaceStyle("IfcDoor")));
default_materials["IfcDoor"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.55, 0.3, 0.15));
default_materials.insert(std::make_pair("IfcBeam", IfcGeom::SurfaceStyle("IfcBeam")));
default_materials["IfcBeam"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.75, 0.7, 0.7));
default_materials.insert(std::make_pair("IfcRailing", IfcGeom::SurfaceStyle("IfcRailing")));
default_materials["IfcRailing"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcMember", IfcGeom::SurfaceStyle("IfcMember")));
default_materials["IfcMember"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.65, 0.6, 0.6));
default_materials.insert(std::make_pair("IfcPlate", IfcGeom::SurfaceStyle("IfcPlate")));
default_materials["IfcPlate"].Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.8, 0.8, 0.8));
default_material = IfcGeom::SurfaceStyle("DefaultMaterial");
default_material.Diffuse().reset(IfcGeom::SurfaceStyle::ColorComponent(0.7, 0.7, 0.7));
default_materials_initialized = true;
}
boost::optional<IfcGeom::SurfaceStyle::ColorComponent> read_colour_component(const boost::optional<pt::ptree&> list) {
if (!list) {
return boost::none;
}
double rgb[3];
int i = 0;
for (pt::ptree::value_type &colour : list.get()) {
if (3 <= i) {
throw std::runtime_error("rgb array over 3 elements large");
}
rgb[i] = colour.second.get_value<double>();
i++;
}
if (i != 3) {
throw std::runtime_error("rgb array less than 3 elements large (was " + std::to_string(i) + ")");
}
return IfcGeom::SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]);
}
void IfcGeom::set_default_style_file(const std::string& json_file) {
if (!default_materials_initialized) InitDefaultMaterials();
default_materials.clear();
pt::ptree root;
pt::read_json(json_file, root);
for (pt::ptree::value_type &material_pair : root) {
std::string name = material_pair.first;
default_materials.insert(std::make_pair(name, IfcGeom::SurfaceStyle(name)));
pt::ptree material = material_pair.second;
boost::optional<pt::ptree&> diffuse = material.get_child_optional("diffuse");
default_materials[name].Diffuse() = read_colour_component(diffuse);
boost::optional<pt::ptree&> specular = material.get_child_optional("specular");
default_materials[name].Specular() = read_colour_component(specular);
if (material.get_child_optional("specular-roughness")) {
default_materials[name].Specularity().reset(1.0 / material.get<double>("specular-roughness"));
}
if (material.get_child_optional("transparency")) {
default_materials[name].Transparency() = material.get<double>("transparency");
}
}
// Is "*" present? If yes, remove it and make it the default style.
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find("*");
if (it != default_materials.end()) {
IfcGeom::SurfaceStyle star = it->second;
default_material.Diffuse() = star.Diffuse();
default_material.Specular() = star.Specular();
default_material.Specularity() = star.Specularity();
default_material.Transparency() = star.Transparency();
default_materials.erase(it);
}
}
const IfcGeom::SurfaceStyle* IfcGeom::get_default_style(const std::string& s) {
if (!default_materials_initialized) InitDefaultMaterials();
std::map<std::string, IfcGeom::SurfaceStyle>::const_iterator it = default_materials.find(s);
if (it == default_materials.end()) {
default_materials.insert(std::make_pair(s, IfcGeom::SurfaceStyle(s)));
default_materials[s].Diffuse() = default_material.Diffuse();
default_materials[s].Specular() = default_material.Specular();
default_materials[s].Specularity() = default_material.Specularity();
default_materials[s].Transparency() = default_material.Transparency();
it = default_materials.find(s);
}
const IfcGeom::SurfaceStyle& surface_style = it->second;
return &surface_style;
}
@@ -0,0 +1,37 @@
/********************************************************************************
* *
* 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 IFC_GEOM_API_H
#define IFC_GEOM_API_H
#ifdef IFC_SHARED_BUILD
#ifdef _WIN32
#ifdef IFC_GEOM_EXPORTS
#define IFC_GEOM_API __declspec(dllexport)
#else
#define IFC_GEOM_API __declspec(dllimport)
#endif
#else // simply assume *nix + GCC-like compiler
#define IFC_GEOM_API __attribute__((visibility("default")))
#endif
#else
#define IFC_GEOM_API
#endif
#endif