mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 05:52:33 +00:00
More work
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user