More work

This commit is contained in:
Thomas Krijnen
2019-08-16 17:40:13 +02:00
parent dae35f59ce
commit ddeaf5a375
52 changed files with 4083 additions and 4184 deletions
+15 -14
View File
@@ -21,12 +21,12 @@
#define IFCSHAPELIST_H
#include "../../ifcgeom/schema_agnostic/IfcGeomRenderStyles.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/settings.h"
#include "../../ifcgeom/taxonomy.h"
namespace IfcGeom {
namespace ifcopenshell { namespace geometry {
namespace Representation {
template <typename P>
class IFC_GEOM_API Triangulation;
}
@@ -44,8 +44,8 @@ namespace IfcGeom {
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 Triangulate(const ifcopenshell::geometry::settings & settings, const ifcopenshell::geometry::ConversionResultPlacement* place, ifcopenshell::geometry::Representation::Triangulation* 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;
@@ -57,16 +57,16 @@ namespace IfcGeom {
int id;
ConversionResultPlacement* placement;
ConversionResultShape* shape;
const SurfaceStyle* style;
ifcopenshell::geometry::taxonomy::style style;
public:
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape, const SurfaceStyle* style)
ConversionResult(int id, const ConversionResultPlacement* placement, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style& 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(placement->clone()), shape(shape->clone()) {}
ConversionResult(int id, const ConversionResultShape* shape, const ifcopenshell::geometry::taxonomy::style& 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) {}
: id(id), placement(0), shape(shape->clone()) {}
void append(const ConversionResultPlacement* trsf) {
if (placement == 0) {
placement = trsf->clone();
@@ -83,12 +83,13 @@ namespace IfcGeom {
}
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* newStyle) { style = newStyle; }
// @todo
bool hasStyle() const { return style.diffuse.is_initialized(); }
const ifcopenshell::geometry::taxonomy::style& Style() const { return style; }
void setStyle(const ifcopenshell::geometry::taxonomy::style& newStyle) { style = newStyle; }
int ItemId() const { return id; }
};
typedef std::vector<ConversionResult> ConversionResults;
}
}}
#endif
+413
View File
@@ -0,0 +1,413 @@
#include "Converter.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
ifcopenshell::geometry::Converter::Converter(const std::string& geometry_library, IfcParse::IfcFile* file) {
kernel_ = kernels::impl::kernel_implementations().construct(geometry_library, file);
mapping_ = impl::mapping_implementations().construct(file);
}
ifcopenshell::geometry::NativeElement* ifcopenshell::geometry::Converter::create_brep_for_representation_and_product(
const ifcopenshell::geometry::settings& settings, IfcUtil::IfcBaseEntity* representation, IfcUtil::IfcBaseEntity* product) {
std::stringstream representation_id_builder;
const std::string product_type = product->declaration().name();
// @todo
element_settings s(settings, 1.0 /*getValue(GV_LENGTH_UNIT) */, product_type);
int parent_id = -1;
try {
IfcUtil::IfcBaseEntity* parent_object = mapping_->get_decomposing_entity(product);
if (parent_object) {
parent_id = parent_object->data().id();
}
} catch (const std::exception& e) {
Logger::Error(e);
}
ConversionResultPlacement* trsf = nullptr;
try {
convert_placement(product, trsf);
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to construct placement");
}
const std::string guid = product->get_value<std::string>("GlobalId");
const std::string name = product->get_value_or<std::string>("Name", "");
representation_id_builder << representation->data().id();
ifcopenshell::geometry::Representation::BRep* shape;
ifcopenshell::geometry::ConversionResults shapes;
auto rep_item = mapping_->map(representation);
auto placement = mapping_->map(product);
kernel_->convert(rep_item, shapes);
shape = new ifcopenshell::geometry::Representation::BRep(s, representation_id_builder.str(), shapes);
return new NativeElement(
product->data().id(),
parent_id,
name,
product_type,
guid,
// @todo
"",
trsf,
boost::shared_ptr<ifcopenshell::geometry::Representation::BRep>(shape),
product
);
/*
std::stringstream representation_id_builder;
representation_id_builder << representation->data().id();
ifcopenshell::geometry::kernels::Representation::BRep* shape;
ifcopenshell::geometry::kernels::ConversionResults shapes;
if (!convert_shapes(representation, shapes)) {
return 0;
}
if (settings.get(IteratorSettings::APPLY_LAYERSETS)) {
if (apply_layerset(product, shapes)) {
IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations();
for (IfcSchema::IfcRelAssociates::list::it it = associations->begin(); it != associations->end(); ++it) {
IfcSchema::IfcRelAssociatesMaterial* associates_material = (**it).as<IfcSchema::IfcRelAssociatesMaterial>();
if (associates_material) {
unsigned layerset_id = associates_material->RelatingMaterial()->data().id();
representation_id_builder << "-layerset-" << layerset_id;
break;
}
}
}
}
bool material_style_applied = false;
const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
if (single_material) {
const ifcopenshell::geometry::kernels::SurfaceStyle* s = get_style(single_material);
for (ifcopenshell::geometry::kernels::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle() && s) {
it->setStyle(s);
material_style_applied = true;
}
}
} else {
bool some_items_without_style = false;
for (ifcopenshell::geometry::kernels::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
if (!it->hasStyle()) {
some_items_without_style = true;
break;
}
}
if (some_items_without_style) {
Logger::Warning("No material and surface styles for:", product);
}
}
if (material_style_applied) {
representation_id_builder << "-material-" << single_material->data().id();
}
ConversionResultPlacement* trsf = nullptr;
try {
convert_placement(product->ObjectPlacement(), trsf);
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to construct placement");
}
// Does the IfcElement have any IfcOpenings?
// Note that openings for IfcOpeningElements are not processed
IfcSchema::IfcRelVoidsElement::list::ptr openings = find_openings(product)->as<IfcSchema::IfcRelVoidsElement>();
const std::string product_type = product->declaration().name();
ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type);
if (!settings.get(ifcopenshell::geometry::kernels::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) {
representation_id_builder << "-openings";
for (IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++it) {
representation_id_builder << "-" << (*it)->data().id();
}
ifcopenshell::geometry::kernels::ConversionResults opened_shapes;
bool caught_error = false;
try {
convert_openings(product, openings, shapes, trsf, opened_shapes);
} catch (const std::exception& e) {
Logger::Message(Logger::LOG_ERROR, std::string("Error processing openings for: ") + e.what() + ":", product);
caught_error = true;
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Error processing openings for:", product);
}
if (caught_error && opened_shapes.size() < shapes.size()) {
opened_shapes = shapes;
}
if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for (ifcopenshell::geometry::kernels::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++it) {
it->prepend(trsf);
}
trsf = nullptr;
representation_id_builder << "-world-coords";
}
shape = new ifcopenshell::geometry::kernels::Representation::BRep(element_settings, representation_id_builder.str(), opened_shapes);
} else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
for (ifcopenshell::geometry::kernels::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
it->prepend(trsf);
}
trsf = nullptr;
representation_id_builder << "-world-coords";
shape = new ifcopenshell::geometry::kernels::Representation::BRep(element_settings, representation_id_builder.str(), shapes);
} else {
shape = new ifcopenshell::geometry::kernels::Representation::BRep(element_settings, representation_id_builder.str(), shapes);
}
std::string context_string = "";
if (representation->hasRepresentationIdentifier()) {
context_string = representation->RepresentationIdentifier();
} else if (representation->ContextOfItems()->hasContextType()) {
context_string = representation->ContextOfItems()->ContextType();
}
auto elem = new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
product_type,
guid,
context_string,
trsf,
boost::shared_ptr<ifcopenshell::geometry::kernels::Representation::BRep>(shape),
product
);
if (settings.get(IteratorSettings::VALIDATE_QUANTITIES)) {
validate_quantities(product, elem->geometry());
}
return elem;
*/
}
/*
template <typename P, typename PP>
ifcopenshell::geometry::kernels::NativeElement<P, PP>* ifcopenshell::geometry::kernels::AbstractKernel::create_brep_for_processed_representation(
const IteratorSettings& //* settings /, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
ifcopenshell::geometry::kernels::NativeElement<P, PP>* brep) {
int parent_id = -1;
try {
IfcUtil::IfcBaseEntity* parent_object = get_decomposing_entity(product);
if (parent_object && parent_object->as<IfcSchema::IfcObjectDefinition>()) {
parent_id = parent_object->data().id();
}
} catch (const std::exception& e) {
Logger::Error(e);
}
const std::string name = product->hasName() ? product->Name() : "";
const std::string guid = product->GlobalId();
ConversionResultPlacement* trsf = nullptr;
try {
convert_placement(product->ObjectPlacement(), trsf);
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to construct placement");
}
std::string context_string = "";
if (representation->hasRepresentationIdentifier()) {
context_string = representation->RepresentationIdentifier();
} else if (representation->ContextOfItems()->hasContextType()) {
context_string = representation->ContextOfItems()->ContextType();
}
const std::string product_type = product->declaration().name();
return new NativeElement<P, PP>(
product->data().id(),
parent_id,
name,
product_type,
guid,
context_string,
trsf,
brep->geometry_pointer(),
product
);
}
*/
//#include "../../ifcparse/Ifc2x3.h"
//#include "../../ifcparse/Ifc4.h"
//
//// @todo remove
//#include "../../ifcgeom/schema_agnostic/opencascade/OpenCascadeConversionResult.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 ConversionResultShape* s_, int t_, bool unique) {
// // @todo make kernel agnostic
// const TopoDS_Shape& s = ((OpenCascadeShape*) s_)->shape();
// TopAbs_ShapeEnum t = (TopAbs_ShapeEnum) t_;
//
// 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 ConversionResultShape* s_) {
// // @todo make kernel agnostic
// const TopoDS_Shape& s = ((OpenCascadeShape*) s_)->shape();
// OpenCascadeShape Ss(s);
//
// int nv = count(&Ss, (int) TopAbs_VERTEX, true);
// int ne = count(&Ss, (int) TopAbs_EDGE, true);
// int nf = count(&Ss, (int) 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*);
//#ifdef IFOPSH_USE_CGAL
//extern void init_KernelImplementation_cgal_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
//extern void init_KernelImplementation_cgal_Ifc4(IfcGeom::impl::KernelFactoryImplementation*);
//#endif
//
//IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() {
// init_KernelImplementation_opencascade_Ifc2x3(this);
// init_KernelImplementation_opencascade_Ifc4(this);
//#ifdef IFOPSH_USE_CGAL
// init_KernelImplementation_cgal_Ifc2x3(this);
// init_KernelImplementation_cgal_Ifc4(this);
//#endif
//}
//
//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);
//}
//
//
//IfcUtil::IfcBaseEntity* IfcGeom::Kernel::get_decomposing_entity(IfcUtil::IfcBaseEntity* inst, bool include_openings) {
// if (inst->as<Ifc2x3::IfcProduct>()) {
// return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>(), include_openings);
// } else if (inst->as<Ifc4::IfcProduct>()) {
// return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>(), include_openings);
// } else if (inst->declaration().name() == "IfcProject") {
// return nullptr;
// } else {
// throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
// }
//}
//
//namespace {
// 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->template 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;
// }
// }
// }
// 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 ConversionResultShape* s_) {
// // @todo make kernel agnostic
// const TopoDS_Shape& a = ((OpenCascadeShape*) s_)->shape();
//
// if (a.ShapeType() == TopAbs_COMPOUND || a.ShapeType() == TopAbs_SOLID) {
// TopoDS_Iterator it(a);
// for (; it.More(); it.Next()) {
// OpenCascadeShape s(it.Value());
// if (!is_manifold(&s)) {
// 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;
// }
//}
@@ -2,19 +2,21 @@
#define ITERATOR_KERNEL_H
#include "../../ifcparse/IfcFile.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/settings.h"
#include "../../ifcgeom/schema_agnostic/ConversionResult.h"
#include "../../ifcgeom/abstract_mapping.h"
#include "../../ifcgeom/kernel_agnostic/AbstractKernel.h"
#include <boost/function.hpp>
namespace IfcGeom {
namespace ifcopenshell { namespace geometry {
template <typename P, typename PP>
class NativeElement;
class Kernel {
class Converter {
private:
Kernel* implementation_;
abstract_mapping* mapping_;
kernels::AbstractKernel* kernel_;
public:
// Tolerances and settings for various geometrical operations:
@@ -47,10 +49,13 @@ namespace IfcGeom {
GV_DIMENSIONALITY
};
Kernel(const std::string& geometry_library, IfcParse::IfcFile* file_ = 0);
Converter(const std::string& geometry_library, IfcParse::IfcFile* file);
virtual ~Kernel() {}
~Converter() {}
abstract_mapping* mapping() const { return mapping_; }
/*
virtual void setValue(GeomValue var, double value) {
implementation_->setValue(var, value);
}
@@ -58,43 +63,42 @@ namespace IfcGeom {
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);
ifcopenshell::geometry::ConversionResults convert(IfcUtil::IfcBaseClass* item) {
auto geom_item = mapping_->map(item);
ifcopenshell::geometry::ConversionResults results;
kernel_->convert(geom_item, results);
return results;
}
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, ConversionResultPlacement*& trsf) {
return implementation_->convert_placement(item, trsf);
bool convert_placement(IfcUtil::IfcBaseClass* item, ifcopenshell::geometry::ConversionResultPlacement*& trsf) {
throw std::runtime_error("not implemented");
// return implementation_->convert_placement(item, trsf);
}
static int count(const ConversionResultShape*, int, bool unique=false);
static int surface_genus(const ConversionResultShape*);
ifcopenshell::geometry::NativeElement* create_brep_for_representation_and_product(const ifcopenshell::geometry::settings& settings, IfcUtil::IfcBaseEntity* representation, IfcUtil::IfcBaseEntity* product);
ifcopenshell::geometry::NativeElement* create_brep_for_processed_representation(const ifcopenshell::geometry::settings& settings, IfcUtil::IfcBaseEntity* representation, IfcUtil::IfcBaseEntity* product, ifcopenshell::geometry::NativeElement* brep);
static bool is_manifold(const ConversionResultShape*);
/*
static int count(const ifcopenshell::geometry::ConversionResultShape*, int, bool unique=false);
static int surface_genus(const ifcopenshell::geometry::ConversionResultShape*);
static bool is_manifold(const ifcopenshell::geometry::ConversionResultShape*);
static IfcUtil::IfcBaseEntity* get_decomposing_entity(IfcUtil::IfcBaseEntity*, bool include_openings=true);
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
+37 -43
View File
@@ -27,18 +27,17 @@
#include "../../ifcparse/Argument.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/settings.h"
#include "ifc_geom_api.h"
namespace IfcGeom {
namespace ifcopenshell { namespace geometry {
template <typename P>
class Matrix {
private:
std::vector<P> _data;
std::vector<double> _data;
public:
Matrix(const ElementSettings& settings, const IfcGeom::ConversionResultPlacement* trsf) {
Matrix(const element_settings& 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
@@ -49,30 +48,29 @@ namespace IfcGeom {
const double trsf_value = (trsf == nullptr)
? (i == j ? 1. : 0.)
: trsf->Value(j,i);
const double matrix_value = (i == 4 && settings.get(IteratorSettings::CONVERT_BACK_UNITS))
const double matrix_value = (i == 4 && settings.get(settings::CONVERT_BACK_UNITS))
? trsf_value / settings.unit_magnitude()
: trsf_value;
_data.push_back(static_cast<P>(matrix_value));
_data.push_back(static_cast<double>(matrix_value));
}
}
}
const std::vector<P>& data() const { return _data; }
const std::vector<double>& data() const { return _data; }
};
template <typename P>
class Transformation {
private:
ElementSettings settings_;
element_settings settings_;
ConversionResultPlacement* trsf_;
Matrix<P> matrix_;
Matrix matrix_;
public:
Transformation(const ElementSettings& settings, const IfcGeom::ConversionResultPlacement* trsf)
Transformation(const element_settings& settings, const ConversionResultPlacement* trsf)
: settings_(settings)
, trsf_(trsf ? trsf->clone() : nullptr)
, matrix_(settings, trsf)
{}
const IfcGeom::ConversionResultPlacement* data() const { return trsf_; }
const Matrix<P>& matrix() const { return matrix_; }
const ConversionResultPlacement* data() const { return trsf_; }
const Matrix& matrix() const { return matrix_; }
Transformation inverted() const {
return Transformation(settings_, trsf_->inverted());
@@ -83,7 +81,6 @@ namespace IfcGeom {
}
};
template <typename P = double, typename PP = P>
class Element {
private:
int _id;
@@ -93,17 +90,17 @@ namespace IfcGeom {
std::string _guid;
std::string _context;
std::string _unique_id;
Transformation<PP> _transformation;
Transformation _transformation;
IfcUtil::IfcBaseEntity* product_;
std::vector<const IfcGeom::Element<P, PP>*> _parents;
std::vector<const Element*> _parents;
public:
friend bool operator == (const Element<P, PP> & element1, const Element<P, PP> & element2) {
friend bool operator == (const Element & element1, const Element & 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) {
friend bool operator < (const Element & element1, const Element & 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);
@@ -127,13 +124,13 @@ namespace IfcGeom {
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; }
const Transformation& 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; }
const std::vector<const Element*> parents() const { return _parents; }
void SetParents(std::vector<const Element*> 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 IfcGeom::ConversionResultPlacement* trsf, IfcUtil::IfcBaseEntity* product)
Element(const element_settings& 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)
{
@@ -162,17 +159,16 @@ namespace IfcGeom {
virtual ~Element() {}
};
template <typename P = double, typename PP = P>
class NativeElement : public Element<P, PP> {
class NativeElement : public Element {
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 IfcGeom::ConversionResultPlacement* trsf, const boost::shared_ptr<Representation::BRep>& geometry,
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)
: Element(geometry->settings() ,id, parent_id, name, type, guid, context, trsf, product)
, _geometry(geometry)
{}
@@ -184,19 +180,18 @@ namespace IfcGeom {
NativeElement& operator=(const NativeElement& other);
};
template <typename P = double, typename PP = P>
class TriangulationElement : public Element<P, PP> {
class TriangulationElement : public Element {
private:
boost::shared_ptr< Representation::Triangulation<P> > _geometry;
boost::shared_ptr<Representation::Triangulation> _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())))
const Representation::Triangulation& geometry() const { return *_geometry; }
const boost::shared_ptr< Representation::Triangulation >& geometry_pointer() const { return _geometry; }
TriangulationElement(const NativeElement& shape_model)
: Element(shape_model)
, _geometry(boost::shared_ptr<Representation::Triangulation >(new Representation::Triangulation(shape_model.geometry())))
{}
TriangulationElement(const Element<P, PP>& element, const boost::shared_ptr<Representation::Triangulation<P> >& geometry)
: Element<P, PP>(element)
TriangulationElement(const Element& element, const boost::shared_ptr<Representation::Triangulation >& geometry)
: Element(element)
, _geometry(geometry)
{}
private:
@@ -204,14 +199,13 @@ namespace IfcGeom {
TriangulationElement& operator=(const TriangulationElement& other);
};
template <typename P = double, typename PP = P>
class SerializedElement : public Element<P, PP> {
class SerializedElement : public Element {
private:
Representation::Serialization* _geometry;
public:
const Representation::Serialization& geometry() const { return *_geometry; }
SerializedElement(const NativeElement<P, PP>& shape_model)
: Element<P, PP>(shape_model)
SerializedElement(const NativeElement& shape_model)
: Element(shape_model)
, _geometry(new Representation::Serialization(shape_model.geometry()))
{}
virtual ~SerializedElement() {
@@ -221,6 +215,6 @@ namespace IfcGeom {
SerializedElement(const SerializedElement& other);
SerializedElement& operator=(const SerializedElement& other);
};
}
}}
#endif
+9 -3
View File
@@ -23,8 +23,9 @@
#ifndef IFCGEOMFILTER_H
#define IFCGEOMFILTER_H
#include "../../ifcgeom/schema_agnostic/Kernel.h"
#include "../../ifcgeom/kernel_agnostic/AbstractKernel.h"
#include "../../ifcparse/IfcFile.h"
#include "../../ifcgeom/abstract_mapping.h"
#include <boost/foreach.hpp>
#include <boost/function.hpp>
@@ -65,7 +66,11 @@ namespace IfcGeom {
bool traverse_match(IfcUtil::IfcBaseEntity* prod, const filter_t& pred) const
{
IfcUtil::IfcBaseEntity* parent, *current = prod;
while ((parent = IfcGeom::Kernel::get_decomposing_entity(current, traverse_openings)) != nullptr) {
// @todo examine if this can indeed be static. For now usage is only
// in IfcConvert so invocation is bound to a single file with a single
// schema.
static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->data().file);
while ((parent = mapping->get_decomposing_entity(current, traverse_openings)) != nullptr) {
if (pred(parent)) {
return true;
}
@@ -170,7 +175,8 @@ namespace IfcGeom {
: wildcard_filter(include, traverse, patterns) {}
bool match(IfcUtil::IfcBaseEntity* prod) const {
layer_map_t layers = IfcGeom::Kernel::get_layers(prod);
static auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(prod->data().file);
layer_map_t layers = mapping->get_layers(prod);
return std::find_if(layers.begin(), layers.end(), wildcards_match(values)) != layers.end();
}
@@ -1,130 +0,0 @@
/********************************************************************************
* *
* 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, const std::string& geometry_library="opencascade", int num_threads = 1)
: file_(file)
, settings_(settings)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), geometry_library, settings, file, filters_, num_threads);
}
Iterator(const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters, const std::string& geometry_library = "opencascade", int num_threads = 1)
: file_(file)
, settings_(settings)
, filters_(filters)
{
implementation_ = iterator_implementations<P, PP>().construct(file_->schema()->name(), geometry_library, settings, file, filters_, num_threads);
}
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 @@
#include "IfcGeomIteratorImplementation.h"
@@ -0,0 +1,617 @@
/********************************************************************************
* *
* 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). *
* *
* ifcopenshell::geometry::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 *
* *
* ifcopenshell::geometry::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 *
* *
* ifcopenshell::geometry::Iterator::initialize() *
* finds the most suitable representation contexts. Returns true iff *
* at least a single representation will process successfully *
* *
* ifcopenshell::geometry::Iterator::get() *
* returns a pointer to the current ifcopenshell::geometry::Element *
* *
* ifcopenshell::geometry::Iterator::next() *
* returns true iff a following entity is available for a successive call to *
* ifcopenshell::geometry::Iterator::get() *
* *
* ifcopenshell::geometry::Iterator::progress() *
* returns an int in [0..100] that indicates the overall progress *
* *
********************************************************************************/
#ifndef IFCGEOMITERATOR_H
#define IFCGEOMITERATOR_H
#include <map>
#include <set>
#include <vector>
#include <limits>
#include <algorithm>
#include <atomic>
#include <future>
#include <thread>
#include <chrono>
#include <boost/algorithm/string.hpp>
#include <gp_Mat.hxx>
#include <gp_Mat2d.hxx>
#include <gp_GTrsf.hxx>
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include "../../ifcparse/macros.h"
#include "../../ifcparse/IfcFile.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
#include "../../ifcgeom/settings.h"
#include "../../ifcgeom/schema_agnostic/ConversionResult.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomFilter.h"
#include "../../ifcgeom/kernel_agnostic/AbstractKernel.h"
#include "../../ifcgeom/schema_agnostic/Converter.h"
#define INCLUDE_SCHEMA(x) STRINGIFY(../../ifcparse/x.h)
#include INCLUDE_SCHEMA(IfcSchema)
#undef INCLUDE_SCHEMA
#include <atomic>
// 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 {
ifcopenshell::geometry::Element* process_based_on_settings(
const ifcopenshell::geometry::settings& settings,
ifcopenshell::geometry::NativeElement* elem,
ifcopenshell::geometry::TriangulationElement* previous=nullptr)
{
if (settings.get(ifcopenshell::geometry::settings::USE_BREP_DATA)) {
try {
return new ifcopenshell::geometry::SerializedElement(*elem);
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Getting a serialized element from model failed.");
return nullptr;
}
} else if (!settings.get(ifcopenshell::geometry::settings::DISABLE_TRIANGULATION)) {
try {
if (!previous) {
return new ifcopenshell::geometry::TriangulationElement(*elem);
} else {
return new ifcopenshell::geometry::TriangulationElement(*elem, previous->geometry_pointer());
}
} catch (...) {
Logger::Message(Logger::LOG_ERROR, "Getting a triangulation element from model failed.");
return nullptr;
}
} else {
return elem;
}
}
void create_element(
ifcopenshell::geometry::Converter* converter,
const ifcopenshell::geometry::settings& settings,
ifcopenshell::geometry::geometry_conversion_task* rep)
{
IfcUtil::IfcBaseEntity* representation = rep->representation;
IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *rep->products->begin();
auto brep = converter->create_brep_for_representation_and_product(settings, representation, product);
if (!brep) {
return;
}
auto elem = process_based_on_settings(settings, brep);
if (!elem) {
return;
}
rep->breps = { brep };
rep->elements = { elem };
for (auto it = rep->products->begin() + 1; it != rep->products->end(); ++it) {
auto brep2 = converter->create_brep_for_processed_representation(settings, representation, (IfcUtil::IfcBaseEntity*) *it, brep);
if (brep2) {
auto elem2 = process_based_on_settings(settings, brep, dynamic_cast<ifcopenshell::geometry::TriangulationElement*>(elem));
if (elem2) {
rep->breps.push_back(brep2);
rep->elements.push_back(elem2);
}
}
}
}
}
namespace ifcopenshell { namespace geometry {
class Iterator {
private:
int num_threads_;
std::atomic<int> progress_;
std::vector<geometry_conversion_task> tasks_;
std::vector<geometry_conversion_task>::iterator task_iterator_;
std::vector<ifcopenshell::geometry::Element*> all_processed_elements_;
std::vector<ifcopenshell::geometry::NativeElement*> all_processed_native_elements_;
size_t task_result_index_;
std::string geometry_library_;
Iterator(const Iterator&); // N/I
Iterator& operator=(const Iterator&); // N/I
Converter* converter_;
settings settings_;
IfcParse::IfcFile* ifc_file;
int done;
int total;
std::string unit_name;
double unit_magnitude;
gp_XYZ bounds_min_;
gp_XYZ bounds_max_;
std::vector<filter_t> filters_;
/// @todo public/private sections all over the place: move all public to the beginning of the class
public:
bool initialize() {
converter_->mapping()->get_representations(tasks_, filters_, settings_);
if (tasks_.size() == 0) {
Logger::Warning("No representations encountered, aborting");
return false;
}
task_iterator_ = tasks_.begin();
done = 0;
total = tasks_.size();
if (num_threads_ != 1) {
process_concurrently();
} else {
if (!create()) {
return false;
}
}
return true;
}
void process_concurrently() {
size_t conc_threads = num_threads_;
if (conc_threads > tasks_.size()) {
conc_threads = tasks_.size();
}
std::vector<Converter*> kernel_pool;
kernel_pool.reserve(conc_threads);
for (unsigned i = 0; i < conc_threads; ++i) {
kernel_pool.push_back(new Converter(geometry_library_, ifc_file));
}
std::vector<std::future<void>> threadpool;
int old_progress = -1;
int processed = 0;
Logger::ProgressBar(0);
for (auto& rep : tasks_) {
Converter* K = nullptr;
if (threadpool.size() < kernel_pool.size()) {
K = kernel_pool[threadpool.size()];
}
while (threadpool.size() == conc_threads) {
for (int i = 0; i < (int)threadpool.size(); i++) {
std::future<void> &fu = threadpool[i];
std::future_status status;
status = fu.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
fu.get();
processed += 1;
progress_ = processed * 50 / tasks_.size();
if (progress_ != old_progress) {
Logger::ProgressBar(progress_);
old_progress = progress_;
}
std::swap(threadpool[i], threadpool.back());
threadpool.pop_back();
std::swap(kernel_pool[i], kernel_pool.back());
K = kernel_pool.back();
break;
} // if
} // for
} // while
std::future<void> fu = std::async(std::launch::async, create_element, K, std::ref(settings_), &rep);
threadpool.emplace_back(std::move(fu));
}
for (std::future<void> &fu : threadpool) {
fu.get();
processed += 1;
progress_ = processed * 50 / tasks_.size();
if (progress_ != old_progress) {
Logger::ProgressBar(progress_);
old_progress = progress_;
}
}
for (auto& rep : tasks_) {
all_processed_elements_.insert(all_processed_elements_.end(), rep.elements.begin(), rep.elements.end());
all_processed_native_elements_.insert(all_processed_native_elements_.end(), rep.breps.begin(), rep.breps.end());
}
task_result_index_ = 0;
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(all_processed_elements_.size()) +
" objects) ");
}
/// Computes model's bounding box (bounds_min and bounds_max).
/// @note Can take several minutes for large files.
void compute_bounds()
{
// @todo
/*
for (int i = 1; i < 4; ++i) {
bounds_min_.SetCoord(i, std::numeric_limits<double>::infinity());
bounds_max_.SetCoord(i, -std::numeric_limits<double>::infinity());
}
IfcSchema::IfcProduct::list::ptr products = ifc_file->instances_by_type<IfcSchema::IfcProduct>();
for (IfcSchema::IfcProduct::list::it iter = products->begin(); iter != products->end(); ++iter) {
IfcSchema::IfcProduct* product = *iter;
if (product->hasObjectPlacement()) {
// Use a fresh trsf every time in order to prevent the result to be concatenated
ConversionResultPlacement* trsf;
bool success = false;
try {
success = kernel->convert_placement(product->ObjectPlacement(), trsf);
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to construct placement");
}
if (!success) {
continue;
}
double X, Y, Z;
trsf->TranslationPart(X, Y, Z);
bounds_min_.SetX(std::min(bounds_min_.X(), X));
bounds_min_.SetY(std::min(bounds_min_.Y(), Y));
bounds_min_.SetZ(std::min(bounds_min_.Z(), Z));
bounds_max_.SetX(std::max(bounds_max_.X(), X));
bounds_max_.SetY(std::max(bounds_max_.Y(), Y));
bounds_max_.SetZ(std::max(bounds_max_.Z(), Z));
}
}
*/
}
int progress() const {
if (num_threads_ == 1) {
return 100 * done / total;
} else {
return progress_;
}
}
const std::string& getUnitName() const { return unit_name; }
/// @note Double always as per IFC specification.
double getUnitMagnitude() const { return unit_magnitude; }
std::string getLog() const { return Logger::GetLog(); }
IfcParse::IfcFile* file() const { return ifc_file; }
const std::vector<ifcopenshell::geometry::filter_t>& filters() const { return filters_; }
std::vector<ifcopenshell::geometry::filter_t>& filters() { return filters_; }
const gp_XYZ& bounds_min() const { return bounds_min_; }
const gp_XYZ& bounds_max() const { return bounds_max_; }
private:
// Move to the next IfcRepresentation
void _nextShape() {
++task_iterator_;
++done;
}
IfcUtil::IfcBaseClass* create_shape_model_for_next_entity() {
geometry_conversion_task* task = nullptr;
while (task_iterator_ != tasks_.end()) {
task = &*task_iterator_++;
create_element(converter_, settings_, task);
if (task->elements.empty()) {
task = nullptr;
} else {
break;
}
}
if (task) {
all_processed_elements_.insert(all_processed_elements_.end(), task->elements.begin(), task->elements.end());
all_processed_native_elements_.insert(all_processed_native_elements_.end(), task->breps.begin(), task->breps.end());
return (*task->products)[0];
} else {
return nullptr;
}
}
public:
/// Moves to the next shape representation, create its geometry, and returns the associated product.
/// Use get() to retrieve the created geometry.
IfcUtil::IfcBaseClass* next() {
if (num_threads_ != 1) {
task_result_index_++;
if (task_result_index_ == all_processed_elements_.size()) {
return nullptr;
} else {
return all_processed_elements_[task_result_index_]->product();
}
} else {
// Increment the iterator over the list of products using the current
// shape representation
++task_result_index_;
if (task_result_index_ == all_processed_elements_.size()) {
return create();
}
}
}
/// Gets the representation of the current geometrical entity.
Element* get()
{
// TODO: Test settings and throw
Element* ret = 0;
ret = all_processed_elements_[task_result_index_];
// If we want to organize the element considering their hierarchy
if (settings_.get(settings::SEARCH_FLOOR))
{
// We are going to build a vector with the element parents.
// First, create the parent vector
std::vector<const ifcopenshell::geometry::Element*> parents;
// if the element has a parent
if (ret->parent_id() != -1)
{
const ifcopenshell::geometry::Element* parent_object = NULL;
bool hasParent = true;
// get the parent
try {
parent_object = get_object(ret->parent_id());
} catch (const std::exception& e) {
Logger::Error(e);
hasParent = false;
}
// Add the previously found parent to the vector
if (hasParent) parents.insert(parents.begin(), parent_object);
// We need to find all the parents
while (parent_object != NULL && hasParent && parent_object->parent_id() != -1)
{
// Find the next parent
try {
parent_object = get_object(parent_object->parent_id());
} catch (const std::exception& e) {
Logger::Error(e);
hasParent = false;
}
// Add the previously found parent to the vector
if (hasParent) parents.insert(parents.begin(), parent_object);
hasParent = hasParent && parent_object->parent_id() != -1;
}
// when done push the parent list in the Element object
ret->SetParents(parents);
}
}
return ret;
}
/// Gets the native (Open Cascade) representation of the current geometrical entity.
NativeElement* get_native()
{
return all_processed_native_elements_[task_result_index_];
}
const Element* get_object(int id) {
// @todo
return nullptr;
/*
ConversionResultPlacement* trsf;
int parent_id = -1;
std::string instance_type, product_name, product_guid;
IfcSchema::IfcProduct* ifc_product = 0;
try {
IfcUtil::IfcBaseClass* ifc_entity = ifc_file->instance_by_id(id);
instance_type = ifc_entity->declaration().name();
if (ifc_entity->declaration().is(IfcSchema::IfcRoot::Class())) {
IfcSchema::IfcRoot* ifc_root = ifc_entity->as<IfcSchema::IfcRoot>();
product_guid = ifc_root->GlobalId();
product_name = ifc_root->hasName() ? ifc_root->Name() : "";
}
if (ifc_entity->declaration().is(IfcSchema::IfcProduct::Class())) {
ifc_product = ifc_entity->as<IfcSchema::IfcProduct>();
parent_id = -1;
try {
IfcSchema::IfcObjectDefinition* parent_object = kernel->get_decomposing_entity(ifc_product)->template as<IfcSchema::IfcObjectDefinition>();
if (parent_object) {
parent_id = parent_object->data().id();
}
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to find decomposing entity");
}
try {
kernel->convert_placement(ifc_product->ObjectPlacement(), trsf);
} catch (const std::exception& e) {
Logger::Error(e);
} catch (...) {
Logger::Error("Failed to construct placement");
}
}
} catch (const std::exception& e) {
Logger::Error(e);
} catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
Logger::Error(e.GetMessageString());
} else {
Logger::Error("Unknown error returning product");
}
} catch (...) {
Logger::Error("Unknown error returning product");
}
ElementSettings element_settings(settings, unit_magnitude, instance_type);
Element* ifc_object = new Element(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product);
return ifc_object;
*/
}
IfcUtil::IfcBaseClass* create() {
IfcUtil::IfcBaseClass* product = nullptr;
try {
product = create_shape_model_for_next_entity();
} catch (const std::exception& e) {
Logger::Error(e);
} catch (const Standard_Failure& e) {
if (e.GetMessageString() && strlen(e.GetMessageString())) {
Logger::Error(e.GetMessageString());
} else {
Logger::Error("Unknown error creating geometry");
}
} catch (...) {
Logger::Error("Unknown error creating geometry");
}
return product;
}
private:
void _initialize() {
unit_name = "METER";
unit_magnitude = 1.f;
// @todo
/*
kernel->setValue(ifcopenshell::geometry::Kernel::GV_MAX_FACES_TO_ORIENT, settings.get(settings::SEW_SHELLS) ? std::numeric_limits<double>::infinity() : -1);
kernel->setValue(ifcopenshell::geometry::Kernel::GV_DIMENSIONALITY, (settings.get(settings::INCLUDE_CURVES)
? (settings.get(settings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.));
if (settings.get(settings::BUILDING_LOCAL_PLACEMENT)) {
if (settings.get(settings::SITE_LOCAL_PLACEMENT)) {
Logger::Message(Logger::LOG_WARNING, "building-local-placement takes precedence over site-local-placement");
}
kernel->set_conversion_placement_rel_to(&IfcSchema::IfcBuilding::Class());
} else if (settings.get(settings::SITE_LOCAL_PLACEMENT)) {
kernel->set_conversion_placement_rel_to(&IfcSchema::IfcSite::Class());
}
*/
}
bool owns_ifc_file;
public:
Iterator(const std::string& geometry_library, const settings& settings, IfcParse::IfcFile* file, const std::vector<ifcopenshell::geometry::filter_t>& filters, int num_threads)
: settings_(settings)
, ifc_file(file)
, filters_(filters)
, owns_ifc_file(false)
, num_threads_(num_threads)
, geometry_library_(geometry_library)
{
_initialize();
}
~Iterator() {
if (owns_ifc_file) {
delete ifc_file;
}
if (settings_.get(settings::DISABLE_TRIANGULATION)) {
for (auto& p : all_processed_native_elements_) {
delete p;
}
}
for (auto& p : all_processed_elements_) {
delete p;
}
}
};
}}
#endif
@@ -1,160 +0,0 @@
/********************************************************************************
* *
* 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
@@ -1,35 +0,0 @@
/********************************************************************************
* *
* 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; }
@@ -1,51 +0,0 @@
/********************************************************************************
* *
* 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
@@ -21,6 +21,7 @@
#define IFCGEOMRENDERSTYLES_H
#include "../../ifcgeom/schema_agnostic/ifc_geom_api.h"
#include "../../ifcgeom/taxonomy.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/replace.hpp>
@@ -29,72 +30,7 @@
#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 const ifcopenshell::geometry::taxonomy::style& get_default_style(const std::string& ifc_type);
IFC_GEOM_API void set_default_style_file(const std::string& json_file);
}
@@ -20,13 +20,12 @@
#ifndef IFCGEOMREPRESENTATION_H
#define IFCGEOMREPRESENTATION_H
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
#include "../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
#include "../../ifcgeom/settings.h"
#include "../../ifcgeom/schema_agnostic/ConversionResult.h"
#include <map>
namespace IfcGeom {
namespace ifcopenshell { namespace geometry {
namespace Representation {
@@ -34,37 +33,37 @@ namespace IfcGeom {
Representation(const Representation&); //N/A
Representation& operator =(const Representation&); //N/A
protected:
const ElementSettings settings_;
const element_settings settings_;
public:
explicit Representation(const ElementSettings& settings)
explicit Representation(const element_settings& settings)
: settings_(settings)
{}
const ElementSettings& settings() const { return settings_; }
const element_settings& settings() const { return settings_; }
virtual ~Representation() {}
};
class IFC_GEOM_API BRep : public Representation {
private:
std::string id_;
const IfcGeom::ConversionResults shapes_;
const ifcopenshell::geometry::ConversionResults shapes_;
BRep(const BRep& other);
BRep& operator=(const BRep& other);
public:
BRep(const ElementSettings& settings, const std::string& id, const IfcGeom::ConversionResults& shapes)
BRep(const element_settings& settings, const std::string& id, const ifcopenshell::geometry::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_; }
ifcopenshell::geometry::ConversionResults::const_iterator begin() const { return shapes_.begin(); }
ifcopenshell::geometry::ConversionResults::const_iterator end() const { return shapes_.end(); }
const ifcopenshell::geometry::ConversionResults& shapes() const { return shapes_; }
const std::string& id() const { return id_; }
IfcGeom::ConversionResultShape* as_compound(bool force_meters = false) const;
ifcopenshell::geometry::ConversionResultShape* as_compound(bool force_meters = false) const;
bool calculate_volume(double&) const;
bool calculate_surface_area(double&) const;
bool calculate_projected_surface_area(const IfcGeom::ConversionResultPlacement* ax, double& along_x, double& along_y, double& along_z) const;
bool calculate_projected_surface_area(const ifcopenshell::geometry::ConversionResultPlacement* ax, double& along_x, double& along_y, double& along_z) const;
};
class IFC_GEOM_API Serialization : public Representation {
@@ -84,57 +83,55 @@ namespace IfcGeom {
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<double, std::pair<double, double> > 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<double> _verts;
std::vector<int> _faces;
std::vector<int> _edges;
std::vector<P> _normals;
std::vector<P> uvs_;
std::vector<double> _normals;
std::vector<double> uvs_;
std::vector<int> _material_ids;
std::vector<Material> _materials;
std::vector<ifcopenshell::geometry::taxonomy::style> _materials;
VertexKeyMap welds;
public:
const std::string& id() const { return id_; }
const std::vector<P>& verts() const { return _verts; }
const std::vector<double>& 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<double>& normals() const { return _normals; }
const std::vector<double>& uvs() const { return uvs_; }
const std::vector<int>& material_ids() const { return _material_ids; }
const std::vector<Material>& materials() const { return _materials; }
const std::vector<ifcopenshell::geometry::taxonomy::style>& 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 ) {
for ( ifcopenshell::geometry::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);
std::vector<ifcopenshell::geometry::taxonomy::style>::const_iterator jt = std::find(_materials.begin(), _materials.end(), iit->Style());
if (jt == _materials.end()) {
surface_style_id = (int)_materials.size();
_materials.push_back(adapter);
_materials.push_back(iit->Style());
} 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 (settings().get(ifcopenshell::geometry::settings::APPLY_DEFAULT_MATERIALS) && surface_style_id == -1) {
const ifcopenshell::geometry::taxonomy::style& material = IfcGeom::get_default_style(settings().element_type());
std::vector<ifcopenshell::geometry::taxonomy::style>::const_iterator mit = std::find(_materials.begin(), _materials.end(), material);
if (mit == _materials.end()) {
surface_style_id = (int)_materials.size();
_materials.push_back(material);
@@ -150,16 +147,16 @@ namespace IfcGeom {
/// 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)
static std::vector<double> box_project_uvs(const std::vector<double> &vertices, const std::vector<double> &normals)
{
std::vector<P> uvs;
std::vector<double> 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];
double n_x = normals[v_idx], n_y = normals[v_idx + 1], n_z = normals[v_idx + 2];
double 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;
@@ -181,13 +178,13 @@ namespace IfcGeom {
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 addVertex(int material_index, double X, double Y, double Z) {
const bool convert = settings().get(ifcopenshell::geometry::settings::CONVERT_BACK_UNITS);
X = static_cast<double>(convert ? (X / settings().unit_magnitude()) : X);
Y = static_cast<double>(convert ? (Y / settings().unit_magnitude()) : Y);
Z = static_cast<double>(convert ? (Z / settings().unit_magnitude()) : Z);
int i = (int) _verts.size() / 3;
if (settings().get(IteratorSettings::WELD_VERTICES)) {
if (settings().get(ifcopenshell::geometry::settings::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;
@@ -207,7 +204,7 @@ namespace IfcGeom {
edges_temp.push_back(e);
}
inline void addNormal(P X, P Y, P Z) {
inline void addNormal(double X, double Y, double Z) {
_normals.push_back(X);
_normals.push_back(Y);
_normals.push_back(Z);
@@ -233,6 +230,6 @@ namespace IfcGeom {
};
}
}
}}
#endif
@@ -1,47 +0,0 @@
#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 std::string& geometry_library, const IfcGeom::IteratorSettings& settings, IfcParse::IfcFile* file, const std::vector<IfcGeom::filter_t>& filters, int num_threads) {
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(geometry_library, settings, file, filters, num_threads);
}
template class IteratorFactoryImplementation<float, float>;
template class IteratorFactoryImplementation<float, double>;
template class IteratorFactoryImplementation<double, double>;
@@ -1,81 +0,0 @@
#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::function5<IfcGeom::IteratorImplementation<float, float>*, const std::string&, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&, int> iterator_float_float_fn;
typedef boost::function5<IfcGeom::IteratorImplementation<float, double>*, const std::string&, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&, int> iterator_float_double_fn;
typedef boost::function5<IfcGeom::IteratorImplementation<double, double>*, const std::string&, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&, int> 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 std::string& geometry_library, const IfcGeom::IteratorSettings&, IfcParse::IfcFile*, const std::vector<IfcGeom::filter_t>&, int);
};
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
-268
View File
@@ -1,268 +0,0 @@
#include "Kernel.h"
#include "../../ifcparse/Ifc2x3.h"
#include "../../ifcparse/Ifc4.h"
// @todo remove
#include "../../ifcgeom/schema_agnostic/opencascade/OpenCascadeConversionResult.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 ConversionResultShape* s_, int t_, bool unique) {
// @todo make kernel agnostic
const TopoDS_Shape& s = ((OpenCascadeShape*) s_)->shape();
TopAbs_ShapeEnum t = (TopAbs_ShapeEnum) t_;
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 ConversionResultShape* s_) {
// @todo make kernel agnostic
const TopoDS_Shape& s = ((OpenCascadeShape*) s_)->shape();
OpenCascadeShape Ss(s);
int nv = count(&Ss, (int) TopAbs_VERTEX, true);
int ne = count(&Ss, (int) TopAbs_EDGE, true);
int nf = count(&Ss, (int) 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*);
#ifdef IFOPSH_USE_CGAL
extern void init_KernelImplementation_cgal_Ifc2x3(IfcGeom::impl::KernelFactoryImplementation*);
extern void init_KernelImplementation_cgal_Ifc4(IfcGeom::impl::KernelFactoryImplementation*);
#endif
IfcGeom::impl::KernelFactoryImplementation::KernelFactoryImplementation() {
init_KernelImplementation_opencascade_Ifc2x3(this);
init_KernelImplementation_opencascade_Ifc4(this);
#ifdef IFOPSH_USE_CGAL
init_KernelImplementation_cgal_Ifc2x3(this);
init_KernelImplementation_cgal_Ifc4(this);
#endif
}
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, bool include_openings) {\
IfcSchema::IfcObjectDefinition* parent = 0; \
\
/* In case of an opening element, parent to the RelatingBuildingElement */ \
if (include_openings && 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() && include_openings) { \
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, bool include_openings) {
if (inst->as<Ifc2x3::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc2x3::IfcProduct>(), include_openings);
} else if (inst->as<Ifc4::IfcProduct>()) {
return get_decomposing_entity_impl(inst->as<Ifc4::IfcProduct>(), include_openings);
} else if (inst->declaration().name() == "IfcProject") {
return nullptr;
} else {
throw IfcParse::IfcException("Unexpected entity " + inst->declaration().name());
}
}
namespace {
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->template 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;
}
}
}
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 ConversionResultShape* s_) {
// @todo make kernel agnostic
const TopoDS_Shape& a = ((OpenCascadeShape*) s_)->shape();
if (a.ShapeType() == TopAbs_COMPOUND || a.ShapeType() == TopAbs_SOLID) {
TopoDS_Iterator it(a);
for (; it.More(); it.Next()) {
OpenCascadeShape s(it.Value());
if (!is_manifold(&s)) {
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->template as<typename Schema::IfcObjectDefinition>();
for (;;) {
auto decomposes = obdef->Decomposes()->generalize();
if (decomposes->size() != 1) break;
typename Schema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->template 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());
}
}
+46 -47
View File
@@ -7,49 +7,49 @@
namespace pt = boost::property_tree;
static std::map<std::string, IfcGeom::SurfaceStyle> default_materials;
static IfcGeom::SurfaceStyle default_material;
static std::map<std::string, ifcopenshell::geometry::taxonomy::style> default_materials;
static ifcopenshell::geometry::taxonomy::style 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("IfcSite", ifcopenshell::geometry::taxonomy::style("IfcSite")));
default_materials["IfcSite"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcSlab", ifcopenshell::geometry::taxonomy::style("IfcSlab")));
default_materials["IfcSlab"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcWallStandardCase", ifcopenshell::geometry::taxonomy::style("IfcWallStandardCase")));
default_materials["IfcWallStandardCase"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcWall", ifcopenshell::geometry::taxonomy::style("IfcWall")));
default_materials["IfcWall"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcWindow", ifcopenshell::geometry::taxonomy::style("IfcWindow")));
default_materials["IfcWindow"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcDoor", ifcopenshell::geometry::taxonomy::style("IfcDoor")));
default_materials["IfcDoor"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcBeam", ifcopenshell::geometry::taxonomy::style("IfcBeam")));
default_materials["IfcBeam"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcRailing", ifcopenshell::geometry::taxonomy::style("IfcRailing")));
default_materials["IfcRailing"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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("IfcMember", ifcopenshell::geometry::taxonomy::style("IfcMember")));
default_materials["IfcMember"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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_materials.insert(std::make_pair("IfcPlate", ifcopenshell::geometry::taxonomy::style("IfcPlate")));
default_materials["IfcPlate"].diffuse.reset(ifcopenshell::geometry::taxonomy::colour(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_material = ifcopenshell::geometry::taxonomy::style("DefaultMaterial");
default_material.diffuse.reset(ifcopenshell::geometry::taxonomy::colour(0.7, 0.7, 0.7));
default_materials_initialized = true;
}
boost::optional<IfcGeom::SurfaceStyle::ColorComponent> read_colour_component(const boost::optional<pt::ptree&> list) {
boost::optional<ifcopenshell::geometry::taxonomy::colour> read_colour_component(const boost::optional<pt::ptree&> list) {
if (!list) {
return boost::none;
}
@@ -65,7 +65,7 @@ boost::optional<IfcGeom::SurfaceStyle::ColorComponent> read_colour_component(con
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]);
return ifcopenshell::geometry::taxonomy::colour(rgb[0], rgb[1], rgb[2]);
}
void IfcGeom::set_default_style_file(const std::string& json_file) {
@@ -78,46 +78,45 @@ void IfcGeom::set_default_style_file(const std::string& json_file) {
for (pt::ptree::value_type &material_pair : root) {
std::string name = material_pair.first;
default_materials.insert(std::make_pair(name, IfcGeom::SurfaceStyle(name)));
default_materials.insert(std::make_pair(name, ifcopenshell::geometry::taxonomy::style(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);
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);
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"));
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");
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("*");
std::map<std::string, ifcopenshell::geometry::taxonomy::style>::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();
ifcopenshell::geometry::taxonomy::style 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) {
const ifcopenshell::geometry::taxonomy::style& 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);
std::map<std::string, ifcopenshell::geometry::taxonomy::style>::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();
default_materials.insert(std::make_pair(s, ifcopenshell::geometry::taxonomy::style(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;
return it->second;
}
@@ -36,75 +36,76 @@
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
namespace IfcGeom {
namespace ifcopenshell {
namespace geometry {
class OpenCascadePlacement : public ConversionResultPlacement {
public:
OpenCascadePlacement(const gp_GTrsf& trsf)
: trsf_(trsf) {}
class OpenCascadePlacement : public ConversionResultPlacement {
public:
OpenCascadePlacement(const gp_GTrsf& trsf)
: trsf_(trsf) {}
const gp_GTrsf& trsf() const { return trsf_; }
operator const gp_GTrsf& () { return trsf_; }
const gp_GTrsf& trsf() const { return trsf_; }
operator const gp_GTrsf& () { return trsf_; }
virtual double Value(int i, int j) const {
return trsf_.Value(i, j);
}
virtual double Value(int i, int j) const {
return trsf_.Value(i, j);
}
virtual void Multiply(const ConversionResultPlacement* other) {
trsf_.Multiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual void Multiply(const ConversionResultPlacement* other) {
trsf_.Multiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual void PreMultiply(const ConversionResultPlacement* other) {
trsf_.PreMultiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual void PreMultiply(const ConversionResultPlacement* other) {
trsf_.PreMultiply(((OpenCascadePlacement*)other)->trsf_);
}
virtual ConversionResultPlacement* clone() const {
return new OpenCascadePlacement(trsf_);
}
virtual ConversionResultPlacement* clone() const {
return new OpenCascadePlacement(trsf_);
}
virtual ConversionResultPlacement* inverted() const {
return new OpenCascadePlacement(trsf_.Inverted());
}
virtual ConversionResultPlacement* inverted() const {
return new OpenCascadePlacement(trsf_.Inverted());
}
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->trsf_));
}
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->trsf_));
}
virtual void TranslationPart(double& X, double& Y, double& Z) const {
X = trsf_.TranslationPart().X();
Y = trsf_.TranslationPart().Y();
Z = trsf_.TranslationPart().Z();
}
private:
gp_GTrsf trsf_;
};
class OpenCascadeShape : public ConversionResultShape {
public:
OpenCascadeShape(const TopoDS_Shape& shape)
: shape_(shape)
{}
virtual void TranslationPart(double& X, double& Y, double& Z) const {
X = trsf_.TranslationPart().X();
Y = trsf_.TranslationPart().Y();
Z = trsf_.TranslationPart().Z();
}
private:
gp_GTrsf trsf_;
};
const TopoDS_Shape& shape() const { return shape_; }
operator const TopoDS_Shape& () { return shape_; }
class OpenCascadeShape : public ConversionResultShape {
public:
OpenCascadeShape(const TopoDS_Shape& shape)
: shape_(shape) {}
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<float>* t, int surface_style_id) const;
const TopoDS_Shape& shape() const { return shape_; }
operator const TopoDS_Shape& () { return shape_; }
virtual void Triangulate(const IfcGeom::IteratorSettings & settings, const IfcGeom::ConversionResultPlacement * place, IfcGeom::Representation::Triangulation<double>* t, int surface_style_id) const;
virtual void Triangulate(const settings & settings, const ConversionResultPlacement * place, Representation::Triangulation<float>* t, int surface_style_id) const;
virtual void Serialize(std::string&) const {
throw std::runtime_error("Not implemented");
}
virtual void Triangulate(const settings & settings, const ConversionResultPlacement * place, Representation::Triangulation<double>* t, int surface_style_id) const;
virtual ConversionResultShape* clone() const {
return new OpenCascadeShape(shape_);
}
virtual void Serialize(std::string&) const {
throw std::runtime_error("Not implemented");
}
virtual int surface_genus() const;
private:
TopoDS_Shape shape_;
};
virtual ConversionResultShape* clone() const {
return new OpenCascadeShape(shape_);
}
virtual int surface_genus() const;
private:
TopoDS_Shape shape_;
};
}
}
#endif