mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 13:04:49 +00:00
Introduce AbstractKernel
This commit is contained in:
@@ -427,7 +427,8 @@ IF(MSVC)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
# Enforce standards-conformance on VS > 2015, older Boost versions fail to compile with this
|
# Enforce standards-conformance on VS > 2015, older Boost versions fail to compile with this
|
||||||
if (MSVC_VERSION GREATER 1900 AND (Boost_MAJOR_VERSION GREATER 1 OR Boost_MINOR_VERSION GREATER 66))
|
if (MSVC_VERSION GREATER 1900 AND (Boost_MAJOR_VERSION GREATER 1 OR Boost_MINOR_VERSION GREATER 66))
|
||||||
add_definitions(-permissive-)
|
# @todo currently fails
|
||||||
|
# add_definitions(-permissive-)
|
||||||
endif()
|
endif()
|
||||||
# Link against the static VC runtime
|
# Link against the static VC runtime
|
||||||
# TODO Make this configurable
|
# TODO Make this configurable
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ int main(int argc, char** argv)
|
|||||||
exclusion_traverse_filter exclude_traverse_filter;
|
exclusion_traverse_filter exclude_traverse_filter;
|
||||||
std::string filter_filename;
|
std::string filter_filename;
|
||||||
std::string default_material_filename;
|
std::string default_material_filename;
|
||||||
|
std::string geometry_kernel;
|
||||||
|
|
||||||
po::options_description ifc_options("IFC options");
|
po::options_description ifc_options("IFC options");
|
||||||
ifc_options.add_options()
|
ifc_options.add_options()
|
||||||
@@ -190,6 +191,8 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
po::options_description geom_options("Geometry options");
|
po::options_description geom_options("Geometry options");
|
||||||
geom_options.add_options()
|
geom_options.add_options()
|
||||||
|
("kernel", po::value<std::string>(&geometry_kernel)->default_value("opencascade"),
|
||||||
|
"Geometry kernel to use (opencascade or cgal).")
|
||||||
("plan",
|
("plan",
|
||||||
"Specifies whether to include curves in the output result. Typically "
|
"Specifies whether to include curves in the output result. Typically "
|
||||||
"these are representations of type Plan or Axis. Excluded by default.")
|
"these are representations of type Plan or Axis. Excluded by default.")
|
||||||
@@ -652,7 +655,7 @@ int main(int argc, char** argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, "cgal");
|
IfcGeom::Iterator<real_t> context_iterator(settings, ifc_file, filter_funcs, geometry_kernel);
|
||||||
if (!context_iterator.initialize()) {
|
if (!context_iterator.initialize()) {
|
||||||
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
/// @todo It would be nice to know and print separate error prints for a case where we found no entities
|
||||||
/// and for a case we found no entities that satisfy our filtering criteria.
|
/// and for a case we found no entities that satisfy our filtering criteria.
|
||||||
|
|||||||
@@ -0,0 +1,557 @@
|
|||||||
|
#include "AbstractKernel.h"
|
||||||
|
|
||||||
|
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||||
|
|
||||||
|
#define AbstractKernel MAKE_TYPE_NAME(AbstractKernel)
|
||||||
|
|
||||||
|
void IfcGeom::AbstractKernel::set_conversion_placement_rel_to(const IfcParse::declaration* type) {
|
||||||
|
placement_rel_to = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcGeom::AbstractKernel::setValue(GeomValue var, double value) {
|
||||||
|
switch (var) {
|
||||||
|
case GV_DEFLECTION_TOLERANCE:
|
||||||
|
deflection_tolerance = value;
|
||||||
|
break;
|
||||||
|
case GV_WIRE_CREATION_TOLERANCE:
|
||||||
|
wire_creation_tolerance = value;
|
||||||
|
break;
|
||||||
|
case GV_POINT_EQUALITY_TOLERANCE:
|
||||||
|
point_equality_tolerance = value;
|
||||||
|
break;
|
||||||
|
case GV_LENGTH_UNIT:
|
||||||
|
ifc_length_unit = value;
|
||||||
|
break;
|
||||||
|
case GV_PLANEANGLE_UNIT:
|
||||||
|
ifc_planeangle_unit = value;
|
||||||
|
break;
|
||||||
|
case GV_PRECISION:
|
||||||
|
modelling_precision = value;
|
||||||
|
break;
|
||||||
|
case GV_DIMENSIONALITY:
|
||||||
|
dimensionality = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"never reach here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double IfcGeom::AbstractKernel::getValue(GeomValue var) const {
|
||||||
|
switch (var) {
|
||||||
|
case GV_DEFLECTION_TOLERANCE:
|
||||||
|
return deflection_tolerance;
|
||||||
|
case GV_WIRE_CREATION_TOLERANCE:
|
||||||
|
return wire_creation_tolerance;
|
||||||
|
case GV_MINIMAL_FACE_AREA:
|
||||||
|
// Considering a right-angled triangle, this about the smallest
|
||||||
|
// area you can obtain without the vertices being confused.
|
||||||
|
return modelling_precision * modelling_precision / 2.;
|
||||||
|
case GV_POINT_EQUALITY_TOLERANCE:
|
||||||
|
return point_equality_tolerance;
|
||||||
|
case GV_LENGTH_UNIT:
|
||||||
|
return ifc_length_unit;
|
||||||
|
break;
|
||||||
|
case GV_PLANEANGLE_UNIT:
|
||||||
|
return ifc_planeangle_unit;
|
||||||
|
break;
|
||||||
|
case GV_PRECISION:
|
||||||
|
return modelling_precision;
|
||||||
|
break;
|
||||||
|
case GV_DIMENSIONALITY:
|
||||||
|
return dimensionality;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(!"never reach here");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcSchema::IfcMaterial* IfcGeom::AbstractKernel::get_single_material_association(const IfcSchema::IfcProduct* product) {
|
||||||
|
IfcSchema::IfcMaterial* single_material = 0;
|
||||||
|
IfcSchema::IfcRelAssociatesMaterial::list::ptr associated_materials = product->HasAssociations()->as<IfcSchema::IfcRelAssociatesMaterial>();
|
||||||
|
if (associated_materials->size() == 1) {
|
||||||
|
IfcSchema::IfcMaterialSelect* associated_material = (*associated_materials->begin())->RelatingMaterial();
|
||||||
|
single_material = associated_material->as<IfcSchema::IfcMaterial>();
|
||||||
|
|
||||||
|
// NB: Single-layer layersets are also considered, regardless of --enable-layerset-slicing, this
|
||||||
|
// in accordance with other viewers.
|
||||||
|
if (!single_material && associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()) {
|
||||||
|
IfcSchema::IfcMaterialLayerSet* layerset = associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()->ForLayerSet();
|
||||||
|
if (layerset->MaterialLayers()->size() == 1) {
|
||||||
|
IfcSchema::IfcMaterialLayer* layer = (*layerset->MaterialLayers()->begin());
|
||||||
|
if (layer->hasMaterial()) {
|
||||||
|
single_material = layer->Material();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return single_material;
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcSchema::IfcRepresentation* IfcGeom::AbstractKernel::representation_mapped_to(const IfcSchema::IfcRepresentation* representation) {
|
||||||
|
IfcSchema::IfcRepresentation* representation_mapped_to = 0;
|
||||||
|
IfcSchema::IfcRepresentationItem::list::ptr items = representation->Items();
|
||||||
|
if (items->size() == 1) {
|
||||||
|
IfcSchema::IfcRepresentationItem* item = *items->begin();
|
||||||
|
if (item->declaration().is(IfcSchema::IfcMappedItem::Class())) {
|
||||||
|
if (item->StyledByItem()->size() == 0) {
|
||||||
|
IfcSchema::IfcMappedItem* mapped_item = item->as<IfcSchema::IfcMappedItem>();
|
||||||
|
if (is_identity_transform(mapped_item->MappingTarget())) {
|
||||||
|
IfcSchema::IfcRepresentationMap* map = mapped_item->MappingSource();
|
||||||
|
if (is_identity_transform(map->MappingOrigin())) {
|
||||||
|
representation_mapped_to = map->MappedRepresentation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return representation_mapped_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcSchema::IfcProduct::list::ptr IfcGeom::AbstractKernel::products_represented_by(const IfcSchema::IfcRepresentation* representation) {
|
||||||
|
IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list);
|
||||||
|
|
||||||
|
IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation->OfProductRepresentation();
|
||||||
|
|
||||||
|
for (IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it) {
|
||||||
|
// http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
|
||||||
|
// IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards.
|
||||||
|
// It will be changed into an ABSTRACT supertype in future releases of IFC.
|
||||||
|
|
||||||
|
// IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
|
||||||
|
// Let's find the IfcProducts that reference the IfcProductRepresentation anyway
|
||||||
|
products->push((*it)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>());
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap();
|
||||||
|
if (maps->size() == 1) {
|
||||||
|
IfcSchema::IfcRepresentationMap* map = *maps->begin();
|
||||||
|
if (is_identity_transform(map->MappingOrigin())) {
|
||||||
|
IfcSchema::IfcMappedItem::list::ptr items = map->MapUsage();
|
||||||
|
for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) {
|
||||||
|
IfcSchema::IfcMappedItem* item = *it;
|
||||||
|
if (item->StyledByItem()->size() != 0) continue;
|
||||||
|
|
||||||
|
if (!is_identity_transform(item->MappingTarget())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr reps = item->data().getInverse((&IfcSchema::IfcRepresentation::Class()), -1)->as<IfcSchema::IfcRepresentation>();
|
||||||
|
for (IfcSchema::IfcRepresentation::list::it jt = reps->begin(); jt != reps->end(); ++jt) {
|
||||||
|
IfcSchema::IfcRepresentation* rep = *jt;
|
||||||
|
if (rep->Items()->size() != 1) continue;
|
||||||
|
IfcSchema::IfcProductRepresentation::list::ptr prodreps_mapped = rep->OfProductRepresentation();
|
||||||
|
for (IfcSchema::IfcProductRepresentation::list::it kt = prodreps_mapped->begin(); kt != prodreps_mapped->end(); ++kt) {
|
||||||
|
IfcSchema::IfcProduct::list::ptr ps = (*kt)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>();
|
||||||
|
products->push(ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const IfcSchema::IfcRepresentationItem* find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item) {
|
||||||
|
if (item->StyledByItem()->size()) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (item->declaration().is(IfcSchema::IfcBooleanClippingResult::Class())) {
|
||||||
|
// All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of
|
||||||
|
// IfcGeometricRepresentationItem
|
||||||
|
item = (IfcSchema::IfcGeometricRepresentationItem*) ((IfcSchema::IfcBooleanClippingResult*) item)->FirstOperand();
|
||||||
|
if (item->StyledByItem()->size()) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well.
|
||||||
|
// But neither are these very prevalent, nor does the current IfcOpenShell style
|
||||||
|
// mechanism enable to conveniently style subshapes, which would be necessary for
|
||||||
|
// distinctly styled union operands.
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::pair<IfcSchema::IfcSurfaceStyle*, T*> _get_surface_style(const IfcSchema::IfcStyledItem* si) {
|
||||||
|
#ifdef USE_IFC4
|
||||||
|
IfcEntityList::ptr style_assignments = si->Styles();
|
||||||
|
for (IfcEntityList::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
||||||
|
if (!(*kt)->declaration().is(IfcSchema::IfcPresentationStyleAssignment::Class())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IfcSchema::IfcPresentationStyleAssignment* style_assignment = (IfcSchema::IfcPresentationStyleAssignment*) *kt;
|
||||||
|
#else
|
||||||
|
IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments = si->Styles();
|
||||||
|
for (IfcSchema::IfcPresentationStyleAssignment::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
||||||
|
IfcSchema::IfcPresentationStyleAssignment* style_assignment = *kt;
|
||||||
|
#endif
|
||||||
|
IfcEntityList::ptr styles = style_assignment->Styles();
|
||||||
|
for (IfcEntityList::it lt = styles->begin(); lt != styles->end(); ++lt) {
|
||||||
|
IfcUtil::IfcBaseClass* style = *lt;
|
||||||
|
if (style->declaration().is(IfcSchema::IfcSurfaceStyle::Class())) {
|
||||||
|
IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style;
|
||||||
|
if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) {
|
||||||
|
IfcEntityList::ptr styles_elements = surface_style->Styles();
|
||||||
|
for (IfcEntityList::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
|
||||||
|
if ((*mt)->declaration().is(T::Class())) {
|
||||||
|
return std::make_pair(surface_style, (T*)*mt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::pair<IfcSchema::IfcSurfaceStyle*, T*> get_surface_style(const IfcSchema::IfcRepresentationItem* representation_item) {
|
||||||
|
// For certain representation items, most notably boolean operands,
|
||||||
|
// a style definition might reside on one of its operands.
|
||||||
|
representation_item = find_item_carrying_style(representation_item);
|
||||||
|
|
||||||
|
if (representation_item->as<IfcSchema::IfcStyledItem>()) {
|
||||||
|
return _get_surface_style<T>(representation_item->as<IfcSchema::IfcStyledItem>());
|
||||||
|
}
|
||||||
|
IfcSchema::IfcStyledItem::list::ptr styled_items = representation_item->StyledByItem();
|
||||||
|
if (styled_items->size()) {
|
||||||
|
// StyledByItem is a SET [0:1] OF IfcStyledItem, so we return after the first IfcStyledItem:
|
||||||
|
return _get_surface_style<T>(*styled_items->begin());
|
||||||
|
}
|
||||||
|
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) {
|
||||||
|
if (colour != 0) {
|
||||||
|
rgb[0] = colour->Red();
|
||||||
|
rgb[1] = colour->Green();
|
||||||
|
rgb[2] = colour->Blue();
|
||||||
|
}
|
||||||
|
return colour != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_colour(IfcSchema::IfcNormalisedRatioMeasure* factor, double* rgb) {
|
||||||
|
if (factor != 0) {
|
||||||
|
const double f = *factor;
|
||||||
|
rgb[0] = rgb[1] = rgb[2] = f;
|
||||||
|
}
|
||||||
|
return factor != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, double* rgb) {
|
||||||
|
if (colour_or_factor == 0) {
|
||||||
|
return false;
|
||||||
|
} else if (colour_or_factor->declaration().is(IfcSchema::IfcColourRgb::Class())) {
|
||||||
|
return process_colour(static_cast<IfcSchema::IfcColourRgb*>(colour_or_factor), rgb);
|
||||||
|
} else if (colour_or_factor->declaration().is(IfcSchema::IfcNormalisedRatioMeasure::Class())) {
|
||||||
|
return process_colour(static_cast<IfcSchema::IfcNormalisedRatioMeasure*>(colour_or_factor), rgb);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::get_style(const IfcSchema::IfcRepresentationItem* item) {
|
||||||
|
return internalize_surface_style(get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::get_style(const IfcSchema::IfcMaterial* material) {
|
||||||
|
IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation();
|
||||||
|
for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) {
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations();
|
||||||
|
IfcSchema::IfcStyledItem::list::ptr styles(new IfcSchema::IfcStyledItem::list);
|
||||||
|
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
||||||
|
styles->push((**it).Items()->as<IfcSchema::IfcStyledItem>());
|
||||||
|
}
|
||||||
|
for (IfcSchema::IfcStyledItem::list::it it = styles->begin(); it != styles->end(); ++it) {
|
||||||
|
const std::pair<IfcSchema::IfcSurfaceStyle*, IfcSchema::IfcSurfaceStyleShading*> ss = get_surface_style<IfcSchema::IfcSurfaceStyleShading>(*it);
|
||||||
|
if (ss.second) {
|
||||||
|
return internalize_surface_style(ss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IfcGeom::SurfaceStyle material_style = IfcGeom::SurfaceStyle(material->data().id(), material->Name());
|
||||||
|
return &(style_cache[material->data().id()] = material_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcGeom::SurfaceStyle* IfcGeom::AbstractKernel::internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_styles) {
|
||||||
|
if (shading_styles.second == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int surface_style_id = shading_styles.first->data().id();
|
||||||
|
std::map<int, SurfaceStyle>::const_iterator it = style_cache.find(surface_style_id);
|
||||||
|
if (it != style_cache.end()) {
|
||||||
|
return &(it->second);
|
||||||
|
}
|
||||||
|
SurfaceStyle surface_style;
|
||||||
|
|
||||||
|
IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>();
|
||||||
|
IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>();
|
||||||
|
|
||||||
|
if (style->hasName()) {
|
||||||
|
surface_style = SurfaceStyle(surface_style_id, style->Name());
|
||||||
|
} else {
|
||||||
|
surface_style = SurfaceStyle(surface_style_id);
|
||||||
|
}
|
||||||
|
double rgb[3];
|
||||||
|
if (process_colour(shading->SurfaceColour(), rgb)) {
|
||||||
|
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
||||||
|
}
|
||||||
|
if (shading_styles.second->declaration().is(IfcSchema::IfcSurfaceStyleRendering::Class())) {
|
||||||
|
IfcSchema::IfcSurfaceStyleRendering* rendering_style = static_cast<IfcSchema::IfcSurfaceStyleRendering*>(shading_styles.second);
|
||||||
|
if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) {
|
||||||
|
SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1, 1, 1));
|
||||||
|
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2]));
|
||||||
|
}
|
||||||
|
if (rendering_style->hasDiffuseTransmissionColour()) {
|
||||||
|
// Not supported
|
||||||
|
}
|
||||||
|
if (rendering_style->hasReflectionColour()) {
|
||||||
|
// Not supported
|
||||||
|
}
|
||||||
|
if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) {
|
||||||
|
surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
||||||
|
}
|
||||||
|
if (rendering_style->hasSpecularHighlight()) {
|
||||||
|
IfcSchema::IfcSpecularHighlightSelect* highlight = rendering_style->SpecularHighlight();
|
||||||
|
if (highlight->declaration().is(IfcSchema::IfcSpecularRoughness::Class())) {
|
||||||
|
double roughness = *((IfcSchema::IfcSpecularRoughness*)highlight);
|
||||||
|
if (roughness >= 1e-9) {
|
||||||
|
surface_style.Specularity().reset(1.0 / roughness);
|
||||||
|
}
|
||||||
|
} else if (highlight->declaration().is(IfcSchema::IfcSpecularExponent::Class())) {
|
||||||
|
surface_style.Specularity().reset(*((IfcSchema::IfcSpecularExponent*)highlight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rendering_style->hasTransmissionColour()) {
|
||||||
|
// Not supported
|
||||||
|
}
|
||||||
|
if (rendering_style->hasTransparency()) {
|
||||||
|
const double d = rendering_style->Transparency();
|
||||||
|
surface_style.Transparency().reset(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &(style_cache[surface_style_id] = surface_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename P, typename PP>
|
||||||
|
IfcGeom::NativeElement<P, PP>* IfcGeom::AbstractKernel::create_brep_for_representation_and_product(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) {
|
||||||
|
std::stringstream representation_id_builder;
|
||||||
|
|
||||||
|
representation_id_builder << representation->data().id();
|
||||||
|
|
||||||
|
IfcGeom::Representation::BRep* shape;
|
||||||
|
IfcGeom::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 IfcGeom::SurfaceStyle* s = get_style(single_material);
|
||||||
|
for (IfcGeom::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 (IfcGeom::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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(IfcGeom::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();
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcGeom::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 (IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++it) {
|
||||||
|
it->prepend(trsf);
|
||||||
|
}
|
||||||
|
trsf = nullptr;
|
||||||
|
representation_id_builder << "-world-coords";
|
||||||
|
}
|
||||||
|
shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), opened_shapes);
|
||||||
|
} else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
|
||||||
|
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
|
||||||
|
it->prepend(trsf);
|
||||||
|
}
|
||||||
|
trsf = nullptr;
|
||||||
|
representation_id_builder << "-world-coords";
|
||||||
|
shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), shapes);
|
||||||
|
} else {
|
||||||
|
shape = new IfcGeom::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<IfcGeom::Representation::BRep>(shape),
|
||||||
|
product
|
||||||
|
);
|
||||||
|
|
||||||
|
if (settings.get(IteratorSettings::VALIDATE_QUANTITIES)) {
|
||||||
|
validate_quantities(product, elem->geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P, typename PP>
|
||||||
|
IfcGeom::NativeElement<P, PP>* IfcGeom::AbstractKernel::create_brep_for_processed_representation(
|
||||||
|
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
|
||||||
|
IfcGeom::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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::AbstractKernel::create_brep_for_representation_and_product<float, float>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::AbstractKernel::create_brep_for_representation_and_product<float, double>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::AbstractKernel::create_brep_for_representation_and_product<double, double>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||||
|
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::AbstractKernel::create_brep_for_processed_representation<float, float>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::AbstractKernel::create_brep_for_processed_representation<float, double>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
|
||||||
|
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::AbstractKernel::create_brep_for_processed_representation<double, double>(
|
||||||
|
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#ifndef ABSTRACT_KERNEL_H
|
||||||
|
#define ABSTRACT_KERNEL_H
|
||||||
|
|
||||||
|
#include "../../ifcparse/macros.h"
|
||||||
|
#include "../../ifcgeom/schema_agnostic/ifc_geom_api.h"
|
||||||
|
#include "../../ifcgeom/schema_agnostic/Kernel.h"
|
||||||
|
#include "../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
|
||||||
|
|
||||||
|
#define INCLUDE_SCHEMA(x) STRINGIFY(../../ifcparse/x.h)
|
||||||
|
#include INCLUDE_SCHEMA(IfcSchema)
|
||||||
|
#undef INCLUDE_SCHEMA
|
||||||
|
|
||||||
|
namespace IfcGeom {
|
||||||
|
|
||||||
|
class IFC_GEOM_API MAKE_TYPE_NAME(AbstractKernel) : public IfcGeom::Kernel {
|
||||||
|
protected:
|
||||||
|
// For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf)
|
||||||
|
const IfcParse::declaration* placement_rel_to;
|
||||||
|
|
||||||
|
double deflection_tolerance;
|
||||||
|
double wire_creation_tolerance;
|
||||||
|
double point_equality_tolerance;
|
||||||
|
double max_faces_to_sew;
|
||||||
|
double ifc_length_unit;
|
||||||
|
double ifc_planeangle_unit;
|
||||||
|
double modelling_precision;
|
||||||
|
double dimensionality;
|
||||||
|
|
||||||
|
std::map<int, SurfaceStyle> style_cache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MAKE_TYPE_NAME(AbstractKernel)(const std::string& geometry_library)
|
||||||
|
: IfcGeom::Kernel(geometry_library, nullptr)
|
||||||
|
, deflection_tolerance(0.001)
|
||||||
|
, wire_creation_tolerance(0.0001)
|
||||||
|
, point_equality_tolerance(0.00001)
|
||||||
|
, max_faces_to_sew(-1.0)
|
||||||
|
, ifc_length_unit(1.0)
|
||||||
|
, ifc_planeangle_unit(-1.0)
|
||||||
|
, modelling_precision(0.00001)
|
||||||
|
, dimensionality(1.)
|
||||||
|
, placement_rel_to(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void set_conversion_placement_rel_to(const IfcParse::declaration* type);
|
||||||
|
virtual void setValue(GeomValue var, double value);
|
||||||
|
virtual double getValue(GeomValue var) const;
|
||||||
|
|
||||||
|
const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*);
|
||||||
|
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);
|
||||||
|
IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*);
|
||||||
|
const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem*);
|
||||||
|
const SurfaceStyle* get_style(const IfcSchema::IfcMaterial*);
|
||||||
|
|
||||||
|
virtual bool is_identity_transform(const IfcUtil::IfcBaseClass*) = 0;
|
||||||
|
virtual bool convert_shapes(const IfcUtil::IfcBaseClass*, IfcGeom::ConversionResults&) = 0;
|
||||||
|
virtual bool apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes) = 0;
|
||||||
|
virtual bool validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep) = 0;
|
||||||
|
virtual bool convert_openings(const IfcSchema::IfcProduct* product, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcGeom::ConversionResults& shapes, const ConversionResultPlacement* trsf, IfcGeom::ConversionResults& opened_shapes) = 0;
|
||||||
|
|
||||||
|
const SurfaceStyle* internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_style);
|
||||||
|
|
||||||
|
template <typename P, typename PP>
|
||||||
|
IfcGeom::NativeElement<P, PP>* create_brep_for_representation_and_product(
|
||||||
|
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
|
||||||
|
|
||||||
|
template <typename P, typename PP>
|
||||||
|
IfcGeom::NativeElement<P, PP>* create_brep_for_processed_representation(
|
||||||
|
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<P, PP>*);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "IfcGeomIteratorImplementation.h"
|
#include "IfcGeomIteratorImplementation.h"
|
||||||
#include "../../ifcgeom/schema_agnostic/IteratorImplementation.h"
|
|
||||||
|
|
||||||
namespace IfcGeom {
|
namespace IfcGeom {
|
||||||
template class MAKE_TYPE_NAME(IteratorImplementation_)<float, float>;
|
template class MAKE_TYPE_NAME(IteratorImplementation_)<float, float>;
|
||||||
|
|||||||
@@ -73,9 +73,9 @@
|
|||||||
#include <gp_Trsf.hxx>
|
#include <gp_Trsf.hxx>
|
||||||
#include <gp_Trsf2d.hxx>
|
#include <gp_Trsf2d.hxx>
|
||||||
|
|
||||||
|
#include "../../ifcparse/macros.h"
|
||||||
#include "../../ifcparse/IfcFile.h"
|
#include "../../ifcparse/IfcFile.h"
|
||||||
|
|
||||||
#include "../../ifcgeom/kernels/opencascade/IfcGeom.h"
|
|
||||||
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||||
#include "../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
|
#include "../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
|
||||||
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
|
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
|
||||||
@@ -84,7 +84,11 @@
|
|||||||
#include "../../ifcgeom/schema_agnostic/IfcGeomFilter.h"
|
#include "../../ifcgeom/schema_agnostic/IfcGeomFilter.h"
|
||||||
#include "../../ifcgeom/schema_agnostic/IteratorImplementation.h"
|
#include "../../ifcgeom/schema_agnostic/IteratorImplementation.h"
|
||||||
|
|
||||||
#include "../../ifcgeom/schema_agnostic/Kernel.h"
|
#include "../../ifcgeom/kernel_agnostic/AbstractKernel.h"
|
||||||
|
|
||||||
|
#define INCLUDE_SCHEMA(x) STRINGIFY(../../ifcparse/x.h)
|
||||||
|
#include INCLUDE_SCHEMA(IfcSchema)
|
||||||
|
#undef INCLUDE_SCHEMA
|
||||||
|
|
||||||
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
|
// The infamous min & max Win32 #defines can leak here from OCE depending on the build configuration
|
||||||
#ifdef min
|
#ifdef min
|
||||||
@@ -103,7 +107,7 @@ namespace IfcGeom {
|
|||||||
MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
|
MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
|
||||||
MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
|
MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
|
||||||
|
|
||||||
MAKE_TYPE_NAME(Kernel)* kernel;
|
MAKE_TYPE_NAME(AbstractKernel)* kernel;
|
||||||
IteratorSettings settings;
|
IteratorSettings settings;
|
||||||
|
|
||||||
IfcParse::IfcFile* ifc_file;
|
IfcParse::IfcFile* ifc_file;
|
||||||
@@ -265,11 +269,11 @@ namespace IfcGeom {
|
|||||||
IfcSchema::IfcProduct* product = *iter;
|
IfcSchema::IfcProduct* product = *iter;
|
||||||
if (product->hasObjectPlacement()) {
|
if (product->hasObjectPlacement()) {
|
||||||
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
||||||
gp_Trsf trsf;
|
ConversionResultPlacement* trsf;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
success = kernel->convert(product->ObjectPlacement(), trsf);
|
success = kernel->convert_placement(product->ObjectPlacement(), trsf);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Logger::Error(e);
|
Logger::Error(e);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -280,13 +284,14 @@ namespace IfcGeom {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gp_XYZ& pos = trsf.TranslationPart();
|
double X, Y, Z;
|
||||||
bounds_min_.SetX(std::min(bounds_min_.X(), pos.X()));
|
trsf->TranslationPart(X, Y, Z);
|
||||||
bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y()));
|
bounds_min_.SetX(std::min(bounds_min_.X(), X));
|
||||||
bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z()));
|
bounds_min_.SetY(std::min(bounds_min_.Y(), Y));
|
||||||
bounds_max_.SetX(std::max(bounds_max_.X(), pos.X()));
|
bounds_min_.SetZ(std::min(bounds_min_.Z(), Z));
|
||||||
bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y()));
|
bounds_max_.SetX(std::max(bounds_max_.X(), X));
|
||||||
bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z()));
|
bounds_max_.SetY(std::max(bounds_max_.Y(), Y));
|
||||||
|
bounds_max_.SetZ(std::max(bounds_max_.Z(), Z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,13 +316,6 @@ namespace IfcGeom {
|
|||||||
private:
|
private:
|
||||||
// Move to the next IfcRepresentation
|
// Move to the next IfcRepresentation
|
||||||
void _nextShape() {
|
void _nextShape() {
|
||||||
// In order to conserve memory and reduce cache insertion times, the cache is
|
|
||||||
// cleared after an arbitrary number of processed representations. This has been
|
|
||||||
// benchmarked extensively: https://github.com/IfcOpenShell/IfcOpenShell/pull/47
|
|
||||||
static const int clear_interval = 64;
|
|
||||||
if (done % clear_interval == clear_interval - 1) {
|
|
||||||
kernel->purge_cache();
|
|
||||||
}
|
|
||||||
ifcproducts.reset();
|
ifcproducts.reset();
|
||||||
++ representation_iterator;
|
++ representation_iterator;
|
||||||
++ done;
|
++ done;
|
||||||
@@ -554,7 +552,7 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Element<P, PP>* get_object(int id) {
|
const Element<P, PP>* get_object(int id) {
|
||||||
gp_Trsf trsf;
|
ConversionResultPlacement* trsf;
|
||||||
int parent_id = -1;
|
int parent_id = -1;
|
||||||
std::string instance_type, product_name, product_guid;
|
std::string instance_type, product_name, product_guid;
|
||||||
IfcSchema::IfcProduct* ifc_product = 0;
|
IfcSchema::IfcProduct* ifc_product = 0;
|
||||||
@@ -584,7 +582,7 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
kernel->convert(ifc_product->ObjectPlacement(), trsf);
|
kernel->convert_placement(ifc_product->ObjectPlacement(), trsf);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Logger::Error(e);
|
Logger::Error(e);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -605,7 +603,7 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
ElementSettings element_settings(settings, unit_magnitude, instance_type);
|
ElementSettings element_settings(settings, unit_magnitude, instance_type);
|
||||||
|
|
||||||
Element<P, PP>* ifc_object = new Element<P, PP>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", new OpenCascadePlacement(trsf), ifc_product);
|
Element<P, PP>* ifc_object = new Element<P, PP>(element_settings, id, parent_id, product_name, instance_type, product_guid, "", trsf, ifc_product);
|
||||||
return ifc_object;
|
return ifc_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,7 +683,7 @@ namespace IfcGeom {
|
|||||||
, filters_(filters)
|
, filters_(filters)
|
||||||
, owns_ifc_file(false)
|
, owns_ifc_file(false)
|
||||||
{
|
{
|
||||||
kernel = (MAKE_TYPE_NAME(Kernel)*) impl::kernel_implementations().construct(file->schema()->name(), geometry_library, file);
|
kernel = (MAKE_TYPE_NAME(AbstractKernel)*) impl::kernel_implementations().construct(file->schema()->name(), geometry_library, file);
|
||||||
// kernel = new Kernel(geometry_library, file);
|
// kernel = new Kernel(geometry_library, file);
|
||||||
_initialize();
|
_initialize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ void MAKE_INIT_FN(KernelImplementation_cgal_)(IfcGeom::impl::KernelFactoryImplem
|
|||||||
|
|
||||||
#define CgalKernel MAKE_TYPE_NAME(CgalKernel)
|
#define CgalKernel MAKE_TYPE_NAME(CgalKernel)
|
||||||
|
|
||||||
bool IfcGeom::CgalKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
|
bool IfcGeom::CgalKernel::is_identity_transform(const IfcUtil::IfcBaseClass* l) {
|
||||||
Logger::Message(Logger::LOG_ERROR, "Not implemented is_identity_transform()");
|
Logger::Message(Logger::LOG_ERROR, "Not implemented is_identity_transform()");
|
||||||
return false;
|
return false;
|
||||||
/*
|
/*
|
||||||
@@ -80,154 +80,15 @@ bool IfcGeom::CgalKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P, typename PP>
|
bool IfcGeom::CgalKernel::apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes) {
|
||||||
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_representation_and_product(
|
throw std::runtime_error("not implemented");
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
|
|
||||||
{
|
|
||||||
IfcGeom::Representation::BRep* shape;
|
|
||||||
IfcGeom::ConversionResults shapes, shapes2;
|
|
||||||
|
|
||||||
if (!convert_shapes(representation, shapes)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.get(IteratorSettings::APPLY_LAYERSETS)) {
|
|
||||||
Logger::Message(Logger::LOG_ERROR, "Not implemented APPLY_LAYERSETS");
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
cgal_placement_t trsf;
|
|
||||||
try {
|
|
||||||
// convert(product->ObjectPlacement(), trsf);
|
|
||||||
} catch (...) {}
|
|
||||||
|
|
||||||
std::stringstream representation_id_builder;
|
|
||||||
representation_id_builder << representation->data().id();
|
|
||||||
|
|
||||||
// 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(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) {
|
|
||||||
Logger::Message(Logger::LOG_ERROR, "Not implemented opening subtractions");
|
|
||||||
}
|
|
||||||
|
|
||||||
shape = new IfcGeom::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();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NativeElement<P, PP>(
|
|
||||||
product->data().id(),
|
|
||||||
parent_id,
|
|
||||||
name,
|
|
||||||
product_type,
|
|
||||||
guid,
|
|
||||||
context_string,
|
|
||||||
new CgalPlacement(trsf),
|
|
||||||
boost::shared_ptr<IfcGeom::Representation::BRep>(shape),
|
|
||||||
product
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P, typename PP>
|
bool IfcGeom::CgalKernel::validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep) {
|
||||||
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_processed_representation(
|
throw std::runtime_error("not implemented");
|
||||||
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
|
|
||||||
IfcGeom::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();
|
|
||||||
|
|
||||||
cgal_placement_t trsf;
|
|
||||||
try {
|
|
||||||
// convert(product->ObjectPlacement(), trsf);
|
|
||||||
} catch (...) {}
|
|
||||||
|
|
||||||
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,
|
|
||||||
new CgalPlacement(trsf),
|
|
||||||
brep->geometry_pointer(),
|
|
||||||
product
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, float>(
|
bool IfcGeom::CgalKernel::convert_openings(const IfcSchema::IfcProduct* product, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcGeom::ConversionResults& shapes, const IfcGeom::ConversionResultPlacement* trsf, IfcGeom::ConversionResults& opened_shapes) {
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
throw std::runtime_error("not implemented");
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<double, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
|
||||||
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, float>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<double, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
|
|
||||||
|
|
||||||
|
|
||||||
void IfcGeom::CgalKernel::setValue(GeomValue var, double value) {
|
|
||||||
switch (var) {
|
|
||||||
case GV_DEFLECTION_TOLERANCE:
|
|
||||||
deflection_tolerance = value;
|
|
||||||
break;
|
|
||||||
case GV_DIMENSIONALITY:
|
|
||||||
dimensionality = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Not implemented for this kernel");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double IfcGeom::CgalKernel::getValue(GeomValue var) const {
|
|
||||||
switch (var) {
|
|
||||||
case GV_DEFLECTION_TOLERANCE:
|
|
||||||
return deflection_tolerance;
|
|
||||||
case GV_DIMENSIONALITY:
|
|
||||||
return dimensionality;
|
|
||||||
}
|
|
||||||
throw std::runtime_error("Not implemented for this kernel");
|
|
||||||
}
|
|
||||||
@@ -36,6 +36,9 @@ if ( it != cache.T.end() ) { e = it->second; return true; }
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../../../ifcparse/macros.h"
|
#include "../../../ifcparse/macros.h"
|
||||||
|
|
||||||
|
#include "../../../ifcgeom/kernel_agnostic/AbstractKernel.h"
|
||||||
|
|
||||||
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
|
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
|
||||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||||
#include "../../../ifcgeom/schema_agnostic/cgal/CgalConversionResult.h"
|
#include "../../../ifcgeom/schema_agnostic/cgal/CgalConversionResult.h"
|
||||||
@@ -55,10 +58,11 @@ namespace IfcGeom {
|
|||||||
std::map<int, cgal_shape_t> Shape;
|
std::map<int, cgal_shape_t> Shape;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IFC_GEOM_API MAKE_TYPE_NAME(CgalKernel) : public Kernel {
|
class IFC_GEOM_API MAKE_TYPE_NAME(CgalKernel) : public MAKE_TYPE_NAME(AbstractKernel) {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MAKE_TYPE_NAME(CgalKernel)() : Kernel("cgal") {}
|
MAKE_TYPE_NAME(CgalKernel)()
|
||||||
|
: MAKE_TYPE_NAME(AbstractKernel)("cgal") {}
|
||||||
|
|
||||||
#ifndef NO_CACHE
|
#ifndef NO_CACHE
|
||||||
CgalCache cache;
|
CgalCache cache;
|
||||||
@@ -72,9 +76,6 @@ namespace IfcGeom {
|
|||||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_t& result);
|
bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_t& result);
|
||||||
bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result);
|
bool convert_face(const IfcUtil::IfcBaseClass* L, cgal_face_t& result);
|
||||||
|
|
||||||
virtual void setValue(GeomValue var, double value);
|
|
||||||
virtual double getValue(GeomValue var) const;
|
|
||||||
|
|
||||||
// bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
|
// bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
|
||||||
|
|
||||||
void purge_cache() {
|
void purge_cache() {
|
||||||
@@ -86,16 +87,10 @@ namespace IfcGeom {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_identity_transform(IfcUtil::IfcBaseClass*);
|
virtual bool is_identity_transform(const IfcUtil::IfcBaseClass*);
|
||||||
|
virtual bool apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes);
|
||||||
template <typename P, typename PP>
|
virtual bool validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep);
|
||||||
IfcGeom::NativeElement<P, PP>* create_brep_for_representation_and_product(
|
virtual bool convert_openings(const IfcSchema::IfcProduct* product, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const IfcGeom::ConversionResults& shapes, const ConversionResultPlacement* trsf, IfcGeom::ConversionResults& opened_shapes);
|
||||||
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
|
|
||||||
|
|
||||||
template <typename P, typename PP>
|
|
||||||
IfcGeom::NativeElement<P, PP>* create_brep_for_processed_representation(
|
|
||||||
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<P, PP>*);
|
|
||||||
|
|
||||||
|
|
||||||
#include "CgalEntityMappingDeclaration.h"
|
#include "CgalEntityMappingDeclaration.h"
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ inline static bool ALMOST_THE_SAME(const T& a, const T& b, double tolerance=ALMO
|
|||||||
#include "../../../ifcparse/IfcParse.h"
|
#include "../../../ifcparse/IfcParse.h"
|
||||||
#include "../../../ifcparse/IfcBaseClass.h"
|
#include "../../../ifcparse/IfcBaseClass.h"
|
||||||
|
|
||||||
|
#include "../../../ifcgeom/kernel_agnostic/AbstractKernel.h"
|
||||||
|
|
||||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
|
#include "../../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
|
||||||
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
|
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
|
||||||
@@ -108,7 +110,7 @@ public:
|
|||||||
std::map<int, TopoDS_Shape> Shape;
|
std::map<int, TopoDS_Shape> Shape;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IFC_GEOM_API MAKE_TYPE_NAME(Kernel) : public IfcGeom::Kernel {
|
class IFC_GEOM_API MAKE_TYPE_NAME(Kernel) : public IfcGeom::MAKE_TYPE_NAME(AbstractKernel) {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -203,46 +205,23 @@ private:
|
|||||||
double epsilon() const {
|
double epsilon() const {
|
||||||
return eps_;
|
return eps_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
double deflection_tolerance;
|
|
||||||
double wire_creation_tolerance;
|
|
||||||
double point_equality_tolerance;
|
|
||||||
double max_faces_to_sew;
|
|
||||||
double ifc_length_unit;
|
|
||||||
double ifc_planeangle_unit;
|
|
||||||
double modelling_precision;
|
|
||||||
double dimensionality;
|
|
||||||
|
|
||||||
#ifndef NO_CACHE
|
#ifndef NO_CACHE
|
||||||
MAKE_TYPE_NAME(Cache) cache;
|
MAKE_TYPE_NAME(Cache) cache;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::map<int, SurfaceStyle> style_cache;
|
|
||||||
|
|
||||||
const SurfaceStyle* internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_style);
|
|
||||||
|
|
||||||
// For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf)
|
|
||||||
const IfcParse::declaration* placement_rel_to;
|
|
||||||
|
|
||||||
faceset_helper* faceset_helper_;
|
faceset_helper* faceset_helper_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MAKE_TYPE_NAME(Kernel)()
|
MAKE_TYPE_NAME(Kernel)()
|
||||||
: IfcGeom::Kernel("opencascade", 0)
|
: IfcGeom::MAKE_TYPE_NAME(AbstractKernel)("opencascade")
|
||||||
, deflection_tolerance(0.001)
|
|
||||||
, wire_creation_tolerance(0.0001)
|
|
||||||
, point_equality_tolerance(0.00001)
|
|
||||||
, max_faces_to_sew(-1.0)
|
|
||||||
, ifc_length_unit(1.0)
|
|
||||||
, ifc_planeangle_unit(-1.0)
|
|
||||||
, modelling_precision(0.00001)
|
|
||||||
, dimensionality(1.)
|
|
||||||
, placement_rel_to(0)
|
|
||||||
, faceset_helper_(nullptr)
|
, faceset_helper_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other) : IfcGeom::Kernel(0) {
|
MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other)
|
||||||
|
: IfcGeom::MAKE_TYPE_NAME(AbstractKernel)("opencascade")
|
||||||
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,8 +246,7 @@ public:
|
|||||||
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
||||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
|
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& result);
|
||||||
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
bool convert_face(const IfcUtil::IfcBaseClass* L, TopoDS_Shape& result);
|
||||||
bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
|
bool convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const ConversionResultPlacement* entity_trsf, ConversionResults& cut_shapes);
|
||||||
bool convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings, const ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, ConversionResults& cut_shapes);
|
|
||||||
void assert_closed_wire(TopoDS_Wire& wire);
|
void assert_closed_wire(TopoDS_Wire& wire);
|
||||||
|
|
||||||
bool convert_layerset(const IfcSchema::IfcProduct*, std::vector<Handle_Geom_Surface>&, std::vector<const SurfaceStyle*>&, std::vector<double>&);
|
bool convert_layerset(const IfcSchema::IfcProduct*, std::vector<Handle_Geom_Surface>&, std::vector<const SurfaceStyle*>&, std::vector<double>&);
|
||||||
@@ -302,8 +280,6 @@ public:
|
|||||||
|
|
||||||
bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end);
|
bool find_wall_end_points(const IfcSchema::IfcWall*, gp_Pnt& start, gp_Pnt& end);
|
||||||
|
|
||||||
IfcSchema::IfcSurfaceStyleShading* get_surface_style(IfcSchema::IfcRepresentationItem* item);
|
|
||||||
const IfcSchema::IfcRepresentationItem* find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item);
|
|
||||||
bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid);
|
bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid);
|
||||||
bool create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid);
|
bool create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid);
|
||||||
bool is_compound(const TopoDS_Shape& shape);
|
bool is_compound(const TopoDS_Shape& shape);
|
||||||
@@ -332,91 +308,25 @@ public:
|
|||||||
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&);
|
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&);
|
||||||
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&);
|
static TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&);
|
||||||
|
|
||||||
bool is_identity_transform(IfcUtil::IfcBaseClass*);
|
virtual bool is_identity_transform(const IfcUtil::IfcBaseClass*);
|
||||||
|
virtual bool apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes);
|
||||||
|
virtual bool validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep);
|
||||||
|
|
||||||
IfcSchema::IfcRepresentation* find_representation(const IfcSchema::IfcProduct*, const std::string&);
|
IfcSchema::IfcRepresentation* find_representation(const IfcSchema::IfcProduct*, const std::string&);
|
||||||
|
|
||||||
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
|
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
|
||||||
|
|
||||||
template <typename P, typename PP>
|
void purge_cache() {
|
||||||
IfcGeom::NativeElement<P, PP>* create_brep_for_representation_and_product(
|
|
||||||
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*);
|
|
||||||
|
|
||||||
template <typename P, typename PP>
|
|
||||||
IfcGeom::NativeElement<P, PP>* create_brep_for_processed_representation(
|
|
||||||
const IteratorSettings&, IfcSchema::IfcRepresentation*, IfcSchema::IfcProduct*, IfcGeom::NativeElement<P, PP>*);
|
|
||||||
|
|
||||||
const IfcSchema::IfcMaterial* get_single_material_association(const IfcSchema::IfcProduct*);
|
|
||||||
IfcSchema::IfcRepresentation* representation_mapped_to(const IfcSchema::IfcRepresentation* representation);
|
|
||||||
IfcSchema::IfcProduct::list::ptr products_represented_by(const IfcSchema::IfcRepresentation*);
|
|
||||||
const SurfaceStyle* get_style(const IfcSchema::IfcRepresentationItem*);
|
|
||||||
const SurfaceStyle* get_style(const IfcSchema::IfcMaterial*);
|
|
||||||
|
|
||||||
template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> _get_surface_style(const IfcSchema::IfcStyledItem* si) {
|
|
||||||
#ifdef USE_IFC4
|
|
||||||
IfcEntityList::ptr style_assignments = si->Styles();
|
|
||||||
for (IfcEntityList::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
|
||||||
if (!(*kt)->declaration().is(IfcSchema::IfcPresentationStyleAssignment::Class())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
IfcSchema::IfcPresentationStyleAssignment* style_assignment = (IfcSchema::IfcPresentationStyleAssignment*) *kt;
|
|
||||||
#else
|
|
||||||
IfcSchema::IfcPresentationStyleAssignment::list::ptr style_assignments = si->Styles();
|
|
||||||
for (IfcSchema::IfcPresentationStyleAssignment::list::it kt = style_assignments->begin(); kt != style_assignments->end(); ++kt) {
|
|
||||||
IfcSchema::IfcPresentationStyleAssignment* style_assignment = *kt;
|
|
||||||
#endif
|
|
||||||
IfcEntityList::ptr styles = style_assignment->Styles();
|
|
||||||
for (IfcEntityList::it lt = styles->begin(); lt != styles->end(); ++lt) {
|
|
||||||
IfcUtil::IfcBaseClass* style = *lt;
|
|
||||||
if (style->declaration().is(IfcSchema::IfcSurfaceStyle::Class())) {
|
|
||||||
IfcSchema::IfcSurfaceStyle* surface_style = (IfcSchema::IfcSurfaceStyle*) style;
|
|
||||||
if (surface_style->Side() != IfcSchema::IfcSurfaceSide::IfcSurfaceSide_NEGATIVE) {
|
|
||||||
IfcEntityList::ptr styles_elements = surface_style->Styles();
|
|
||||||
for (IfcEntityList::it mt = styles_elements->begin(); mt != styles_elements->end(); ++mt) {
|
|
||||||
if ((*mt)->declaration().is(T::Class())) {
|
|
||||||
return std::make_pair(surface_style, (T*) *mt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> std::pair<IfcSchema::IfcSurfaceStyle*, T*> get_surface_style(const IfcSchema::IfcRepresentationItem* representation_item) {
|
|
||||||
// For certain representation items, most notably boolean operands,
|
|
||||||
// a style definition might reside on one of its operands.
|
|
||||||
representation_item = find_item_carrying_style(representation_item);
|
|
||||||
|
|
||||||
if (representation_item->as<IfcSchema::IfcStyledItem>()) {
|
|
||||||
return _get_surface_style<T>(representation_item->as<IfcSchema::IfcStyledItem>());
|
|
||||||
}
|
|
||||||
IfcSchema::IfcStyledItem::list::ptr styled_items = representation_item->StyledByItem();
|
|
||||||
if (styled_items->size()) {
|
|
||||||
// StyledByItem is a SET [0:1] OF IfcStyledItem, so we return after the first IfcStyledItem:
|
|
||||||
return _get_surface_style<T>(*styled_items->begin());
|
|
||||||
}
|
|
||||||
return std::make_pair<IfcSchema::IfcSurfaceStyle*, T*>(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void purge_cache() {
|
|
||||||
// Rather hack-ish, but a stopgap solution to keep memory under control
|
// Rather hack-ish, but a stopgap solution to keep memory under control
|
||||||
// for large files. SurfaceStyles need to be kept at all costs, as they
|
// for large files. SurfaceStyles need to be kept at all costs, as they
|
||||||
// are read later on when serializing Collada files.
|
// are read later on when serializing Collada files.
|
||||||
#ifndef NO_CACHE
|
#ifndef NO_CACHE
|
||||||
cache = MAKE_TYPE_NAME(Cache)();
|
cache = MAKE_TYPE_NAME(Cache)();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_conversion_placement_rel_to(const IfcParse::declaration* type);
|
|
||||||
|
|
||||||
#include "IfcRegisterGeomHeader.h"
|
#include "IfcRegisterGeomHeader.h"
|
||||||
|
|
||||||
virtual void setValue(GeomValue var, double value);
|
|
||||||
virtual double getValue(GeomValue var) const;
|
|
||||||
|
|
||||||
virtual IfcGeom::NativeElement<double>* convert(
|
virtual IfcGeom::NativeElement<double>* convert(
|
||||||
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
|
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
|
||||||
IfcUtil::IfcBaseClass* product)
|
IfcUtil::IfcBaseClass* product)
|
||||||
@@ -433,12 +343,15 @@ public:
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, gp_Trsf& trsf) {
|
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, ConversionResultPlacement*& trsf) {
|
||||||
if (item->as<IfcSchema::IfcObjectPlacement>()) {
|
if (item->as<IfcSchema::IfcObjectPlacement>()) {
|
||||||
return convert(item->as<IfcSchema::IfcObjectPlacement>(), trsf);
|
gp_Trsf occt_trsf;
|
||||||
} else {
|
if (convert(item->as<IfcSchema::IfcObjectPlacement>(), occt_trsf)) {
|
||||||
return false;
|
trsf = new OpenCascadePlacement(occt_trsf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -506,259 +506,6 @@ const TopoDS_Shape& IfcGeom::Kernel::ensure_fit_for_subtraction(const TopoDS_Sha
|
|||||||
return solid;
|
return solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
|
||||||
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
|
|
||||||
|
|
||||||
// TODO: Refactor convert_openings() convert_openings_fast() and convert(IfcBooleanResult) to use
|
|
||||||
// the same code base and conform to the same checks and logging messages.
|
|
||||||
|
|
||||||
// Iterate over IfcOpeningElements
|
|
||||||
IfcGeom::ConversionResults opening_shapes;
|
|
||||||
unsigned int last_size = 0;
|
|
||||||
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
|
|
||||||
IfcSchema::IfcRelVoidsElement* v = *it;
|
|
||||||
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
|
||||||
if ( fes->declaration().is(IfcSchema::IfcOpeningElement::Class()) ) {
|
|
||||||
if (!fes->hasRepresentation()) continue;
|
|
||||||
|
|
||||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
|
||||||
gp_Trsf opening_trsf;
|
|
||||||
if (fes->hasObjectPlacement()) {
|
|
||||||
try {
|
|
||||||
convert(fes->ObjectPlacement(),opening_trsf);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
Logger::Error(e);
|
|
||||||
} catch (...) {
|
|
||||||
Logger::Error("Failed to construct placement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the opening into the coordinate system of the IfcProduct
|
|
||||||
opening_trsf.PreMultiply(entity_trsf.Inverted());
|
|
||||||
|
|
||||||
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
|
|
||||||
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
|
||||||
|
|
||||||
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
|
||||||
convert_shapes(*it2,opening_shapes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int current_size = (const unsigned int) opening_shapes.size();
|
|
||||||
for ( unsigned int i = last_size; i < current_size; ++ i ) {
|
|
||||||
OpenCascadePlacement p((gp_GTrsf)opening_trsf);
|
|
||||||
opening_shapes[i].prepend(&p);
|
|
||||||
}
|
|
||||||
last_size = current_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over the shapes of the IfcProduct
|
|
||||||
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
|
||||||
TopoDS_Shape entity_shape_solid;
|
|
||||||
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it3->Shape(), entity_shape_solid);
|
|
||||||
const OpenCascadePlacement* entity_shape_gtrsf = (OpenCascadePlacement*) it3->Placement();
|
|
||||||
|
|
||||||
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
|
|
||||||
|
|
||||||
// Iterate over the shapes of the IfcOpeningElements
|
|
||||||
for ( IfcGeom::ConversionResults::const_iterator it4 = opening_shapes.begin(); it4 != opening_shapes.end(); ++ it4 ) {
|
|
||||||
TopoDS_Shape opening_shape_solid;
|
|
||||||
const TopoDS_Shape& opening_shape_unlocated = ensure_fit_for_subtraction(*(OpenCascadeShape*) it4->Shape(),opening_shape_solid);
|
|
||||||
const OpenCascadePlacement* opening_shape_gtrsf = (OpenCascadePlacement*)it4->Placement();
|
|
||||||
TopoDS_Shape opening_shape = apply_transformation(opening_shape_unlocated, opening_shape_gtrsf);
|
|
||||||
|
|
||||||
double opening_volume;
|
|
||||||
if (Logger::LOG_WARNING >= Logger::Verbosity()) {
|
|
||||||
opening_volume = shape_volume(opening_shape);
|
|
||||||
if ( opening_volume <= ALMOST_ZERO )
|
|
||||||
Logger::Message(Logger::LOG_WARNING,"Empty opening for:",entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity_shape.ShapeType() == TopAbs_COMPSOLID) {
|
|
||||||
|
|
||||||
// For compound solids process the subtraction for the constituent
|
|
||||||
// solids individually and write the result back as a compound solid.
|
|
||||||
|
|
||||||
TopoDS_CompSolid compound;
|
|
||||||
BRep_Builder builder;
|
|
||||||
builder.MakeCompSolid(compound);
|
|
||||||
|
|
||||||
TopExp_Explorer exp(entity_shape, TopAbs_SOLID);
|
|
||||||
|
|
||||||
for (; exp.More(); exp.Next()) {
|
|
||||||
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
BRepAlgoAPI_Cut brep_cut(exp.Current(), opening_shape);
|
|
||||||
#else
|
|
||||||
BRepAlgoAPI_Cut brep_cut;
|
|
||||||
TopTools_ListOfShape s1s;
|
|
||||||
s1s.Append(exp.Current());
|
|
||||||
TopTools_ListOfShape s2s;
|
|
||||||
s2s.Append(opening_shape);
|
|
||||||
brep_cut.SetFuzzyValue(getValue(GV_PRECISION));
|
|
||||||
brep_cut.SetArguments(s1s);
|
|
||||||
brep_cut.SetTools(s2s);
|
|
||||||
brep_cut.Build();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool added = false;
|
|
||||||
if ( brep_cut.IsDone() ) {
|
|
||||||
TopoDS_Shape brep_cut_result = brep_cut;
|
|
||||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
|
||||||
bool is_valid = analyser.IsValid() != 0;
|
|
||||||
if (is_valid) {
|
|
||||||
TopExp_Explorer exp2(brep_cut_result, TopAbs_SOLID);
|
|
||||||
for (; exp2.More(); exp2.Next()) {
|
|
||||||
builder.Add(compound, exp2.Current());
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!added) {
|
|
||||||
// Add the original in case subtraction fails
|
|
||||||
builder.Add(compound, exp.Current());
|
|
||||||
} else {
|
|
||||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_shape = compound;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_shape);
|
|
||||||
#else
|
|
||||||
BRepAlgoAPI_Cut brep_cut;
|
|
||||||
TopTools_ListOfShape s1s;
|
|
||||||
s1s.Append(entity_shape);
|
|
||||||
TopTools_ListOfShape s2s;
|
|
||||||
s2s.Append(opening_shape);
|
|
||||||
brep_cut.SetFuzzyValue(getValue(GV_PRECISION));
|
|
||||||
brep_cut.SetArguments(s1s);
|
|
||||||
brep_cut.SetTools(s2s);
|
|
||||||
brep_cut.Build();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( brep_cut.IsDone() ) {
|
|
||||||
TopoDS_Shape brep_cut_result = brep_cut;
|
|
||||||
|
|
||||||
ShapeFix_Shape fix(brep_cut_result);
|
|
||||||
try {
|
|
||||||
fix.Perform();
|
|
||||||
brep_cut_result = fix.Shape();
|
|
||||||
} catch (...) {
|
|
||||||
Logger::Error("Shape healing failed on opening subtraction result", entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
|
||||||
bool is_valid = analyser.IsValid() != 0;
|
|
||||||
if ( is_valid ) {
|
|
||||||
entity_shape = brep_cut_result;
|
|
||||||
if (Logger::LOG_WARNING >= Logger::Verbosity()) {
|
|
||||||
const double volume_after_subtraction = shape_volume(entity_shape);
|
|
||||||
double original_shape_volume = shape_volume(entity_shape);
|
|
||||||
if ( ALMOST_THE_SAME(original_shape_volume,volume_after_subtraction) )
|
|
||||||
Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",entity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger::Message(Logger::LOG_ERROR,"Invalid result from subtraction:",entity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), it3->Placement()->clone(), new OpenCascadeShape(entity_shape), &it3->Style()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
|
||||||
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
|
|
||||||
|
|
||||||
// Create a compound of all opening shapes in order to speed up the boolean operations
|
|
||||||
TopoDS_Compound opening_compound;
|
|
||||||
BRep_Builder builder;
|
|
||||||
builder.MakeCompound(opening_compound);
|
|
||||||
|
|
||||||
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
|
|
||||||
IfcSchema::IfcRelVoidsElement* v = *it;
|
|
||||||
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
|
||||||
if ( fes->declaration().is(IfcSchema::IfcOpeningElement::Class()) ) {
|
|
||||||
if (!fes->hasRepresentation()) continue;
|
|
||||||
|
|
||||||
// Convert the IfcRepresentation of the IfcOpeningElement
|
|
||||||
gp_Trsf opening_trsf;
|
|
||||||
if (fes->hasObjectPlacement()) {
|
|
||||||
try {
|
|
||||||
convert(fes->ObjectPlacement(),opening_trsf);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
Logger::Error(e);
|
|
||||||
} catch (...) {
|
|
||||||
Logger::Error("Failed to construct placement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the opening into the coordinate system of the IfcProduct
|
|
||||||
opening_trsf.PreMultiply(entity_trsf.Inverted());
|
|
||||||
|
|
||||||
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
|
|
||||||
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
|
||||||
|
|
||||||
IfcGeom::ConversionResults opening_shapes;
|
|
||||||
|
|
||||||
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
|
||||||
convert_shapes(*it2,opening_shapes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
|
|
||||||
gp_GTrsf gtrsf = opening_shapes[i].Placement();
|
|
||||||
gtrsf.PreMultiply(opening_trsf);
|
|
||||||
TopoDS_Shape opening_shape = apply_transformation(opening_shapes[i].Shape(), gtrsf);
|
|
||||||
builder.Add(opening_compound, opening_shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over the shapes of the IfcProduct
|
|
||||||
for ( IfcGeom::ConversionResults::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
|
||||||
TopoDS_Shape entity_shape_solid;
|
|
||||||
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
|
|
||||||
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
|
|
||||||
if (entity_shape_gtrsf.Form() == gp_Other) {
|
|
||||||
Logger::Message(Logger::LOG_WARNING, "Applying non uniform transformation to:", entity);
|
|
||||||
}
|
|
||||||
TopoDS_Shape entity_shape = apply_transformation(entity_shape_unlocated, entity_shape_gtrsf);
|
|
||||||
|
|
||||||
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_compound);
|
|
||||||
|
|
||||||
bool is_valid = false;
|
|
||||||
if ( brep_cut.IsDone() ) {
|
|
||||||
TopoDS_Shape brep_cut_result = brep_cut;
|
|
||||||
|
|
||||||
BRepCheck_Analyzer analyser(brep_cut_result);
|
|
||||||
is_valid = analyser.IsValid() != 0;
|
|
||||||
if ( is_valid ) {
|
|
||||||
cut_shapes.push_back(IfcGeom::ConversionResult(it3->ItemId(), brep_cut_result, &it3->Style()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !is_valid ) {
|
|
||||||
// Apparently processing the boolean operation failed or resulted in an invalid result
|
|
||||||
// in which case the original shape without the subtractions is returned instead
|
|
||||||
// we try convert the openings in the original way, one by one.
|
|
||||||
Logger::Message(Logger::LOG_WARNING,"Subtracting combined openings compound failed:",entity);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct opening_sorter {
|
struct opening_sorter {
|
||||||
bool operator()(const std::pair<double, TopoDS_Shape>& a, const std::pair<double, TopoDS_Shape>& b) const {
|
bool operator()(const std::pair<double, TopoDS_Shape>& a, const std::pair<double, TopoDS_Shape>& b) const {
|
||||||
@@ -767,8 +514,10 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
||||||
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
|
const IfcGeom::ConversionResults& entity_shapes, const ConversionResultPlacement* entity_place, IfcGeom::ConversionResults& cut_shapes) {
|
||||||
|
|
||||||
|
const gp_Trsf entity_trsf = ((OpenCascadePlacement*)entity_place)->trsf().Trsf();
|
||||||
|
|
||||||
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
|
std::vector< std::pair<double, TopoDS_Shape> > opening_vector;
|
||||||
|
|
||||||
@@ -859,7 +608,6 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& face) {
|
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& face) {
|
||||||
TopoDS_Wire wire = w;
|
TopoDS_Wire wire = w;
|
||||||
@@ -1084,63 +832,6 @@ void IfcGeom::Kernel::apply_tolerance(TopoDS_Shape& s, double t) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfcGeom::Kernel::setValue(GeomValue var, double value) {
|
|
||||||
switch (var) {
|
|
||||||
case GV_DEFLECTION_TOLERANCE:
|
|
||||||
deflection_tolerance = value;
|
|
||||||
break;
|
|
||||||
case GV_WIRE_CREATION_TOLERANCE:
|
|
||||||
wire_creation_tolerance = value;
|
|
||||||
break;
|
|
||||||
case GV_POINT_EQUALITY_TOLERANCE:
|
|
||||||
point_equality_tolerance = value;
|
|
||||||
break;
|
|
||||||
case GV_LENGTH_UNIT:
|
|
||||||
ifc_length_unit = value;
|
|
||||||
break;
|
|
||||||
case GV_PLANEANGLE_UNIT:
|
|
||||||
ifc_planeangle_unit = value;
|
|
||||||
break;
|
|
||||||
case GV_PRECISION:
|
|
||||||
modelling_precision = value;
|
|
||||||
break;
|
|
||||||
case GV_DIMENSIONALITY:
|
|
||||||
dimensionality = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(!"never reach here");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double IfcGeom::Kernel::getValue(GeomValue var) const {
|
|
||||||
switch (var) {
|
|
||||||
case GV_DEFLECTION_TOLERANCE:
|
|
||||||
return deflection_tolerance;
|
|
||||||
case GV_WIRE_CREATION_TOLERANCE:
|
|
||||||
return wire_creation_tolerance;
|
|
||||||
case GV_MINIMAL_FACE_AREA:
|
|
||||||
// Considering a right-angled triangle, this about the smallest
|
|
||||||
// area you can obtain without the vertices being confused.
|
|
||||||
return modelling_precision * modelling_precision / 2.;
|
|
||||||
case GV_POINT_EQUALITY_TOLERANCE:
|
|
||||||
return point_equality_tolerance;
|
|
||||||
case GV_LENGTH_UNIT:
|
|
||||||
return ifc_length_unit;
|
|
||||||
break;
|
|
||||||
case GV_PLANEANGLE_UNIT:
|
|
||||||
return ifc_planeangle_unit;
|
|
||||||
break;
|
|
||||||
case GV_PRECISION:
|
|
||||||
return modelling_precision;
|
|
||||||
break;
|
|
||||||
case GV_DIMENSIONALITY:
|
|
||||||
return dimensionality;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(!"never reach here");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Returns the vertex part of an TopoDS_Edge edge that is not TopoDS_Vertex vertex
|
// Returns the vertex part of an TopoDS_Edge edge that is not TopoDS_Vertex vertex
|
||||||
@@ -1407,422 +1098,6 @@ void IfcGeom::Kernel::sequence_of_point_to_wire(const TColgp_SequenceOfPnt& p, T
|
|||||||
w = builder.Wire();
|
w = builder.Wire();
|
||||||
}
|
}
|
||||||
|
|
||||||
const IfcSchema::IfcMaterial* IfcGeom::Kernel::get_single_material_association(const IfcSchema::IfcProduct* product) {
|
|
||||||
IfcSchema::IfcMaterial* single_material = 0;
|
|
||||||
IfcSchema::IfcRelAssociatesMaterial::list::ptr associated_materials = product->HasAssociations()->as<IfcSchema::IfcRelAssociatesMaterial>();
|
|
||||||
if (associated_materials->size() == 1) {
|
|
||||||
IfcSchema::IfcMaterialSelect* associated_material = (*associated_materials->begin())->RelatingMaterial();
|
|
||||||
single_material = associated_material->as<IfcSchema::IfcMaterial>();
|
|
||||||
|
|
||||||
// NB: Single-layer layersets are also considered, regardless of --enable-layerset-slicing, this
|
|
||||||
// in accordance with other viewers.
|
|
||||||
if (!single_material && associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()) {
|
|
||||||
IfcSchema::IfcMaterialLayerSet* layerset = associated_material->as<IfcSchema::IfcMaterialLayerSetUsage>()->ForLayerSet();
|
|
||||||
if (layerset->MaterialLayers()->size() == 1) {
|
|
||||||
IfcSchema::IfcMaterialLayer* layer = (*layerset->MaterialLayers()->begin());
|
|
||||||
if (layer->hasMaterial()) {
|
|
||||||
single_material = layer->Material();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return single_material;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename PP>
|
|
||||||
IfcGeom::NativeElement<P, PP>* IfcGeom::Kernel::create_brep_for_representation_and_product(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
|
|
||||||
{
|
|
||||||
std::stringstream representation_id_builder;
|
|
||||||
|
|
||||||
representation_id_builder << representation->data().id();
|
|
||||||
|
|
||||||
IfcGeom::Representation::BRep* shape;
|
|
||||||
IfcGeom::ConversionResults shapes, shapes2;
|
|
||||||
|
|
||||||
if ( !convert_shapes(representation, shapes) ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.get(IteratorSettings::APPLY_LAYERSETS)) {
|
|
||||||
TopoDS_Shape merge;
|
|
||||||
if (flatten_shape_list(shapes, merge, false)) {
|
|
||||||
if (count(merge, TopAbs_FACE) > 0) {
|
|
||||||
std::vector<double> thickness;
|
|
||||||
std::vector<Handle_Geom_Surface> layers;
|
|
||||||
std::vector< std::vector<Handle_Geom_Surface> > folded_layers;
|
|
||||||
std::vector<const SurfaceStyle*> styles;
|
|
||||||
if (convert_layerset(product, layers, styles, thickness)) {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (styles.size() > 1) {
|
|
||||||
// If there's only a single layer there is no need to manipulate geometries.
|
|
||||||
bool success = true;
|
|
||||||
if (product->as<IfcSchema::IfcWall>() && fold_layers(product->as<IfcSchema::IfcWall>(), shapes, layers, thickness, folded_layers)) {
|
|
||||||
if (apply_folded_layerset(shapes, folded_layers, styles, shapes2)) {
|
|
||||||
std::swap(shapes, shapes2);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (apply_layerset(shapes, layers, styles, shapes2)) {
|
|
||||||
std::swap(shapes, shapes2);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
Logger::Error("Failed processing layerset");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool material_style_applied = false;
|
|
||||||
|
|
||||||
const IfcSchema::IfcMaterial* single_material = get_single_material_association(product);
|
|
||||||
if (single_material) {
|
|
||||||
const IfcGeom::SurfaceStyle* s = get_style(single_material);
|
|
||||||
for (IfcGeom::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 (IfcGeom::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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
gp_Trsf trsf;
|
|
||||||
try {
|
|
||||||
convert(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(IfcGeom::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();
|
|
||||||
}
|
|
||||||
|
|
||||||
IfcGeom::ConversionResults opened_shapes;
|
|
||||||
bool caught_error = false;
|
|
||||||
try {
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
const bool faster_booleans = settings.get(IteratorSettings::FASTER_BOOLEANS);
|
|
||||||
#else
|
|
||||||
const bool faster_booleans = true;
|
|
||||||
#endif
|
|
||||||
if (faster_booleans) {
|
|
||||||
bool success = convert_openings_fast(product,openings,shapes,trsf,opened_shapes);
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
if (!success) {
|
|
||||||
opened_shapes.clear();
|
|
||||||
convert_openings(product,openings,shapes,trsf,opened_shapes);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)success;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
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 ( IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++ it ) {
|
|
||||||
OpenCascadePlacement p(trsf);
|
|
||||||
it->prepend(&p);
|
|
||||||
}
|
|
||||||
trsf = gp_Trsf();
|
|
||||||
representation_id_builder << "-world-coords";
|
|
||||||
}
|
|
||||||
shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), opened_shapes);
|
|
||||||
} else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) {
|
|
||||||
for ( IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++ it ) {
|
|
||||||
OpenCascadePlacement p(trsf);
|
|
||||||
it->prepend(&p);
|
|
||||||
}
|
|
||||||
trsf = gp_Trsf();
|
|
||||||
representation_id_builder << "-world-coords";
|
|
||||||
shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), shapes);
|
|
||||||
} else {
|
|
||||||
shape = new IfcGeom::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,
|
|
||||||
new OpenCascadePlacement(trsf),
|
|
||||||
boost::shared_ptr<IfcGeom::Representation::BRep>(shape),
|
|
||||||
product
|
|
||||||
);
|
|
||||||
|
|
||||||
if (settings.get(IteratorSettings::VALIDATE_QUANTITIES)) {
|
|
||||||
auto rels = product->IsDefinedBy();
|
|
||||||
for (auto& rel : *rels) {
|
|
||||||
if (rel->as<IfcSchema::IfcRelDefinesByProperties>()) {
|
|
||||||
auto pdef = rel->as<IfcSchema::IfcRelDefinesByProperties>()->RelatingPropertyDefinition();
|
|
||||||
if (pdef->as<IfcSchema::IfcElementQuantity>()) {
|
|
||||||
std::string organization_name;
|
|
||||||
try {
|
|
||||||
// A couple of files are not according to the schema here.
|
|
||||||
organization_name = pdef->as<IfcSchema::IfcElementQuantity>()->OwnerHistory()->OwningApplication()->ApplicationDeveloper()->Name();
|
|
||||||
} catch (...) {}
|
|
||||||
if (organization_name == "IfcOpenShell") {
|
|
||||||
auto qs = pdef->as<IfcSchema::IfcElementQuantity>()->Quantities();
|
|
||||||
for (auto& q : *qs) {
|
|
||||||
if (q->as<IfcSchema::IfcQuantityArea>() && q->Name() == "Total Surface Area") {
|
|
||||||
double a_calc;
|
|
||||||
double a_file = q->as<IfcSchema::IfcQuantityArea>()->AreaValue();
|
|
||||||
if (elem->geometry().calculate_surface_area(a_calc)) {
|
|
||||||
double diff = std::abs(a_calc - a_file);
|
|
||||||
if (diff / std::sqrt(a_file) > getValue(GV_PRECISION)) {
|
|
||||||
Logger::Error("Validation of surface area failed for:", product);
|
|
||||||
} else {
|
|
||||||
Logger::Notice("Validation of surface area succeeded for:", product);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger::Error("Validation of surface area failed for:", product);
|
|
||||||
}
|
|
||||||
} else if (q->as<IfcSchema::IfcQuantityVolume>() && q->Name() == "Volume") {
|
|
||||||
double v_calc;
|
|
||||||
double v_file = q->as<IfcSchema::IfcQuantityVolume>()->VolumeValue();
|
|
||||||
if (elem->geometry().calculate_volume(v_calc)) {
|
|
||||||
double diff = std::abs(v_calc - v_file);
|
|
||||||
if (diff / std::sqrt(v_file) > getValue(GV_PRECISION)) {
|
|
||||||
Logger::Error("Validation of volume failed for:", product);
|
|
||||||
} else {
|
|
||||||
Logger::Notice("Validation of volume succeeded for:", product);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger::Error("Validation of volume failed for:", product);
|
|
||||||
}
|
|
||||||
} else if (q->as<IfcSchema::IfcPhysicalComplexQuantity>() && q->Name() == "Shape Validation Properties") {
|
|
||||||
auto qs2 = q->as<IfcSchema::IfcPhysicalComplexQuantity>()->HasQuantities();
|
|
||||||
bool all_succeeded = qs2->size() > 0;
|
|
||||||
for (auto& q2 : *qs2) {
|
|
||||||
if (q2->as<IfcSchema::IfcQuantityCount>() && q2->Name() == "Surface Genus" && q2->hasDescription()) {
|
|
||||||
int item_id = boost::lexical_cast<int>(q2->Description().substr(1));
|
|
||||||
int genus = q2->as<IfcSchema::IfcQuantityCount>()->CountValue();
|
|
||||||
for (auto& part : elem->geometry()) {
|
|
||||||
if (part.ItemId() == item_id) {
|
|
||||||
if (surface_genus(*(OpenCascadeShape*)part.Shape()) != genus) {
|
|
||||||
all_succeeded = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!all_succeeded) {
|
|
||||||
Logger::Error("Validation of surface genus failed for:", product);
|
|
||||||
} else {
|
|
||||||
Logger::Notice("Validation of surface genus succeeded for:", product);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
IfcSchema::IfcRepresentation* IfcGeom::Kernel::representation_mapped_to(const IfcSchema::IfcRepresentation* representation) {
|
|
||||||
IfcSchema::IfcRepresentation* representation_mapped_to = 0;
|
|
||||||
IfcSchema::IfcRepresentationItem::list::ptr items = representation->Items();
|
|
||||||
if (items->size() == 1) {
|
|
||||||
IfcSchema::IfcRepresentationItem* item = *items->begin();
|
|
||||||
if (item->declaration().is(IfcSchema::IfcMappedItem::Class())) {
|
|
||||||
if (item->StyledByItem()->size() == 0) {
|
|
||||||
IfcSchema::IfcMappedItem* mapped_item = item->as<IfcSchema::IfcMappedItem>();
|
|
||||||
if (is_identity_transform(mapped_item->MappingTarget())) {
|
|
||||||
IfcSchema::IfcRepresentationMap* map = mapped_item->MappingSource();
|
|
||||||
if (is_identity_transform(map->MappingOrigin())) {
|
|
||||||
representation_mapped_to = map->MappedRepresentation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return representation_mapped_to;
|
|
||||||
}
|
|
||||||
|
|
||||||
IfcSchema::IfcProduct::list::ptr IfcGeom::Kernel::products_represented_by(const IfcSchema::IfcRepresentation* representation) {
|
|
||||||
IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list);
|
|
||||||
|
|
||||||
IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation->OfProductRepresentation();
|
|
||||||
|
|
||||||
for (IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it) {
|
|
||||||
// http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm
|
|
||||||
// IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards.
|
|
||||||
// It will be changed into an ABSTRACT supertype in future releases of IFC.
|
|
||||||
|
|
||||||
// IfcProductRepresentation also lacks the INVERSE relation to IfcProduct
|
|
||||||
// Let's find the IfcProducts that reference the IfcProductRepresentation anyway
|
|
||||||
products->push((*it)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>());
|
|
||||||
}
|
|
||||||
|
|
||||||
IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap();
|
|
||||||
if (maps->size() == 1) {
|
|
||||||
IfcSchema::IfcRepresentationMap* map = *maps->begin();
|
|
||||||
if (is_identity_transform(map->MappingOrigin())) {
|
|
||||||
IfcSchema::IfcMappedItem::list::ptr items = map->MapUsage();
|
|
||||||
for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) {
|
|
||||||
IfcSchema::IfcMappedItem* item = *it;
|
|
||||||
if (item->StyledByItem()->size() != 0) continue;
|
|
||||||
|
|
||||||
if (!is_identity_transform(item->MappingTarget())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IfcSchema::IfcRepresentation::list::ptr reps = item->data().getInverse((&IfcSchema::IfcRepresentation::Class()), -1)->as<IfcSchema::IfcRepresentation>();
|
|
||||||
for (IfcSchema::IfcRepresentation::list::it jt = reps->begin(); jt != reps->end(); ++jt) {
|
|
||||||
IfcSchema::IfcRepresentation* rep = *jt;
|
|
||||||
if (rep->Items()->size() != 1) continue;
|
|
||||||
IfcSchema::IfcProductRepresentation::list::ptr prodreps_mapped = rep->OfProductRepresentation();
|
|
||||||
for (IfcSchema::IfcProductRepresentation::list::it kt = prodreps_mapped->begin(); kt != prodreps_mapped->end(); ++kt) {
|
|
||||||
IfcSchema::IfcProduct::list::ptr ps = (*kt)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as<IfcSchema::IfcProduct>();
|
|
||||||
products->push(ps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return products;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename P, typename PP>
|
|
||||||
IfcGeom::NativeElement<P, PP>* IfcGeom::Kernel::create_brep_for_processed_representation(
|
|
||||||
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
|
|
||||||
IfcGeom::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();
|
|
||||||
|
|
||||||
gp_Trsf trsf;
|
|
||||||
try {
|
|
||||||
convert(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,
|
|
||||||
new OpenCascadePlacement(trsf),
|
|
||||||
brep->geometry_pointer(),
|
|
||||||
product
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, float>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<float, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::Kernel::create_brep_for_representation_and_product<double, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
|
||||||
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::Kernel::create_brep_for_processed_representation<float, float>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::Kernel::create_brep_for_processed_representation<float, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
|
|
||||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::Kernel::create_brep_for_processed_representation<double, double>(
|
|
||||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
|
|
||||||
|
|
||||||
std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) {
|
std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUnitAssignment* unit_assignment) {
|
||||||
// Set default units, set length to meters, angles to undefined
|
// Set default units, set length to meters, angles to undefined
|
||||||
setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 1.0);
|
setValue(IfcGeom::Kernel::GV_LENGTH_UNIT, 1.0);
|
||||||
@@ -2951,36 +2226,14 @@ bool IfcGeom::Kernel::project(const Handle_Geom_Surface& srf, const TopoDS_Shape
|
|||||||
return vertex_count > 0;
|
return vertex_count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IfcSchema::IfcRepresentationItem* IfcGeom::Kernel::find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item) {
|
bool IfcGeom::Kernel::is_identity_transform(const IfcUtil::IfcBaseClass* l) {
|
||||||
if (item->StyledByItem()->size()) {
|
const IfcSchema::IfcAxis2Placement2D* ax2d;
|
||||||
return item;
|
const IfcSchema::IfcAxis2Placement3D* ax3d;
|
||||||
}
|
|
||||||
|
|
||||||
while (item->declaration().is(IfcSchema::IfcBooleanClippingResult::Class())) {
|
const IfcSchema::IfcCartesianTransformationOperator2D* op2d;
|
||||||
// All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of
|
const IfcSchema::IfcCartesianTransformationOperator3D* op3d;
|
||||||
// IfcGeometricRepresentationItem
|
const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu;
|
||||||
item = (IfcSchema::IfcGeometricRepresentationItem*) ((IfcSchema::IfcBooleanClippingResult*) item)->FirstOperand();
|
const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu;
|
||||||
if (item->StyledByItem()->size()) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well.
|
|
||||||
// But neither are these very prevalent, nor does the current IfcOpenShell style
|
|
||||||
// mechanism enable to conveniently style subshapes, which would be necessary for
|
|
||||||
// distinctly styled union operands.
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
|
|
||||||
IfcSchema::IfcAxis2Placement2D* ax2d;
|
|
||||||
IfcSchema::IfcAxis2Placement3D* ax3d;
|
|
||||||
|
|
||||||
IfcSchema::IfcCartesianTransformationOperator2D* op2d;
|
|
||||||
IfcSchema::IfcCartesianTransformationOperator3D* op3d;
|
|
||||||
IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu;
|
|
||||||
IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu;
|
|
||||||
|
|
||||||
if((op2dnonu = l->as<IfcSchema::IfcCartesianTransformationOperator2DnonUniform>()) != 0) {
|
if((op2dnonu = l->as<IfcSchema::IfcCartesianTransformationOperator2DnonUniform>()) != 0) {
|
||||||
gp_GTrsf2d gtrsf2d;
|
gp_GTrsf2d gtrsf2d;
|
||||||
@@ -3846,4 +3099,112 @@ IfcGeom::Kernel::faceset_helper::faceset_helper(Kernel* kernel, const IfcSchema:
|
|||||||
if (loops_removed || (non_manifold && l->declaration().is(IfcSchema::IfcClosedShell::Class()))) {
|
if (loops_removed || (non_manifold && l->declaration().is(IfcSchema::IfcClosedShell::Class()))) {
|
||||||
Logger::Warning(boost::lexical_cast<std::string>(loops_removed) + " loops removed and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges for:", l);
|
Logger::Warning(boost::lexical_cast<std::string>(loops_removed) + " loops removed and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges for:", l);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcGeom::Kernel::apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes) {
|
||||||
|
IfcGeom::ConversionResults shapes2;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
TopoDS_Shape merge;
|
||||||
|
if (flatten_shape_list(shapes, merge, false)) {
|
||||||
|
if (count(merge, TopAbs_FACE) > 0) {
|
||||||
|
std::vector<double> thickness;
|
||||||
|
std::vector<Handle_Geom_Surface> layers;
|
||||||
|
std::vector< std::vector<Handle_Geom_Surface> > folded_layers;
|
||||||
|
std::vector<const SurfaceStyle*> styles;
|
||||||
|
if (convert_layerset(product, layers, styles, thickness)) {
|
||||||
|
if (styles.size() > 1) {
|
||||||
|
// If there's only a single layer there is no need to manipulate geometries.
|
||||||
|
success = true;
|
||||||
|
if (product->as<IfcSchema::IfcWall>() && fold_layers(product->as<IfcSchema::IfcWall>(), shapes, layers, thickness, folded_layers)) {
|
||||||
|
if (apply_folded_layerset(shapes, folded_layers, styles, shapes2)) {
|
||||||
|
std::swap(shapes, shapes2);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (apply_layerset(shapes, layers, styles, shapes2)) {
|
||||||
|
std::swap(shapes, shapes2);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
Logger::Error("Failed processing layerset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcGeom::Kernel::validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep) {
|
||||||
|
auto rels = product->IsDefinedBy();
|
||||||
|
for (auto& rel : *rels) {
|
||||||
|
if (rel->as<IfcSchema::IfcRelDefinesByProperties>()) {
|
||||||
|
auto pdef = rel->as<IfcSchema::IfcRelDefinesByProperties>()->RelatingPropertyDefinition();
|
||||||
|
if (pdef->as<IfcSchema::IfcElementQuantity>()) {
|
||||||
|
std::string organization_name;
|
||||||
|
try {
|
||||||
|
// A couple of files are not according to the schema here.
|
||||||
|
organization_name = pdef->as<IfcSchema::IfcElementQuantity>()->OwnerHistory()->OwningApplication()->ApplicationDeveloper()->Name();
|
||||||
|
} catch (...) {}
|
||||||
|
if (organization_name == "IfcOpenShell") {
|
||||||
|
auto qs = pdef->as<IfcSchema::IfcElementQuantity>()->Quantities();
|
||||||
|
for (auto& q : *qs) {
|
||||||
|
if (q->as<IfcSchema::IfcQuantityArea>() && q->Name() == "Total Surface Area") {
|
||||||
|
double a_calc;
|
||||||
|
double a_file = q->as<IfcSchema::IfcQuantityArea>()->AreaValue();
|
||||||
|
if (brep.calculate_surface_area(a_calc)) {
|
||||||
|
double diff = std::abs(a_calc - a_file);
|
||||||
|
if (diff / std::sqrt(a_file) > getValue(GV_PRECISION)) {
|
||||||
|
Logger::Error("Validation of surface area failed for:", product);
|
||||||
|
} else {
|
||||||
|
Logger::Notice("Validation of surface area succeeded for:", product);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::Error("Validation of surface area failed for:", product);
|
||||||
|
}
|
||||||
|
} else if (q->as<IfcSchema::IfcQuantityVolume>() && q->Name() == "Volume") {
|
||||||
|
double v_calc;
|
||||||
|
double v_file = q->as<IfcSchema::IfcQuantityVolume>()->VolumeValue();
|
||||||
|
if (brep.calculate_volume(v_calc)) {
|
||||||
|
double diff = std::abs(v_calc - v_file);
|
||||||
|
if (diff / std::sqrt(v_file) > getValue(GV_PRECISION)) {
|
||||||
|
Logger::Error("Validation of volume failed for:", product);
|
||||||
|
} else {
|
||||||
|
Logger::Notice("Validation of volume succeeded for:", product);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::Error("Validation of volume failed for:", product);
|
||||||
|
}
|
||||||
|
} else if (q->as<IfcSchema::IfcPhysicalComplexQuantity>() && q->Name() == "Shape Validation Properties") {
|
||||||
|
auto qs2 = q->as<IfcSchema::IfcPhysicalComplexQuantity>()->HasQuantities();
|
||||||
|
bool all_succeeded = qs2->size() > 0;
|
||||||
|
for (auto& q2 : *qs2) {
|
||||||
|
if (q2->as<IfcSchema::IfcQuantityCount>() && q2->Name() == "Surface Genus" && q2->hasDescription()) {
|
||||||
|
int item_id = boost::lexical_cast<int>(q2->Description().substr(1));
|
||||||
|
int genus = q2->as<IfcSchema::IfcQuantityCount>()->CountValue();
|
||||||
|
for (auto& part : brep) {
|
||||||
|
if (part.ItemId() == item_id) {
|
||||||
|
if (surface_genus(*(OpenCascadeShape*)part.Shape()) != genus) {
|
||||||
|
all_succeeded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!all_succeeded) {
|
||||||
|
Logger::Error("Validation of surface genus failed for:", product);
|
||||||
|
} else {
|
||||||
|
Logger::Notice("Validation of surface genus succeeded for:", product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -362,10 +362,6 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcAxis2Placement2D* l, gp_Trsf2d
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfcGeom::Kernel::set_conversion_placement_rel_to(const IfcParse::declaration* type) {
|
|
||||||
placement_rel_to = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) {
|
bool IfcGeom::Kernel::convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) {
|
||||||
IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf)
|
IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf)
|
||||||
if ( ! l->declaration().is(IfcSchema::IfcLocalPlacement::Class()) ) {
|
if ( ! l->declaration().is(IfcSchema::IfcLocalPlacement::Class()) ) {
|
||||||
|
|||||||
@@ -1,140 +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 <map>
|
|
||||||
|
|
||||||
#include "IfcGeom.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) {
|
|
||||||
if (colour != 0) {
|
|
||||||
rgb[0] = colour->Red();
|
|
||||||
rgb[1] = colour->Green();
|
|
||||||
rgb[2] = colour->Blue();
|
|
||||||
}
|
|
||||||
return colour != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_colour(IfcSchema::IfcNormalisedRatioMeasure* factor, double* rgb) {
|
|
||||||
if (factor != 0) {
|
|
||||||
const double f = *factor;
|
|
||||||
rgb[0] = rgb[1] = rgb[2] = f;
|
|
||||||
}
|
|
||||||
return factor != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, double* rgb) {
|
|
||||||
if (colour_or_factor == 0) {
|
|
||||||
return false;
|
|
||||||
} else if (colour_or_factor->declaration().is(IfcSchema::IfcColourRgb::Class())) {
|
|
||||||
return process_colour(static_cast<IfcSchema::IfcColourRgb*>(colour_or_factor), rgb);
|
|
||||||
} else if (colour_or_factor->declaration().is(IfcSchema::IfcNormalisedRatioMeasure::Class())) {
|
|
||||||
return process_colour(static_cast<IfcSchema::IfcNormalisedRatioMeasure*>(colour_or_factor), rgb);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Kernel MAKE_TYPE_NAME(Kernel)
|
|
||||||
|
|
||||||
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::internalize_surface_style(const std::pair<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*>& shading_styles) {
|
|
||||||
if (shading_styles.second == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int surface_style_id = shading_styles.first->data().id();
|
|
||||||
std::map<int,SurfaceStyle>::const_iterator it = style_cache.find(surface_style_id);
|
|
||||||
if (it != style_cache.end()) {
|
|
||||||
return &(it->second);
|
|
||||||
}
|
|
||||||
SurfaceStyle surface_style;
|
|
||||||
|
|
||||||
IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as<IfcSchema::IfcSurfaceStyle>();
|
|
||||||
IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as<IfcSchema::IfcSurfaceStyleShading>();
|
|
||||||
|
|
||||||
if (style->hasName()) {
|
|
||||||
surface_style = SurfaceStyle(surface_style_id, style->Name());
|
|
||||||
} else {
|
|
||||||
surface_style = SurfaceStyle(surface_style_id);
|
|
||||||
}
|
|
||||||
double rgb[3];
|
|
||||||
if (process_colour(shading->SurfaceColour(), rgb)) {
|
|
||||||
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
|
||||||
}
|
|
||||||
if (shading_styles.second->declaration().is(IfcSchema::IfcSurfaceStyleRendering::Class())) {
|
|
||||||
IfcSchema::IfcSurfaceStyleRendering* rendering_style = static_cast<IfcSchema::IfcSurfaceStyleRendering*>(shading_styles.second);
|
|
||||||
if (rendering_style->hasDiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) {
|
|
||||||
SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1,1,1));
|
|
||||||
surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2]));
|
|
||||||
}
|
|
||||||
if (rendering_style->hasDiffuseTransmissionColour()) {
|
|
||||||
// Not supported
|
|
||||||
}
|
|
||||||
if (rendering_style->hasReflectionColour()) {
|
|
||||||
// Not supported
|
|
||||||
}
|
|
||||||
if (rendering_style->hasSpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) {
|
|
||||||
surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2]));
|
|
||||||
}
|
|
||||||
if (rendering_style->hasSpecularHighlight()) {
|
|
||||||
IfcSchema::IfcSpecularHighlightSelect* highlight = rendering_style->SpecularHighlight();
|
|
||||||
if (highlight->declaration().is(IfcSchema::IfcSpecularRoughness::Class())) {
|
|
||||||
double roughness = *((IfcSchema::IfcSpecularRoughness*)highlight);
|
|
||||||
if (roughness >= 1e-9) {
|
|
||||||
surface_style.Specularity().reset(1.0 / roughness);
|
|
||||||
}
|
|
||||||
} else if (highlight->declaration().is(IfcSchema::IfcSpecularExponent::Class())) {
|
|
||||||
surface_style.Specularity().reset(*((IfcSchema::IfcSpecularExponent*)highlight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rendering_style->hasTransmissionColour()) {
|
|
||||||
// Not supported
|
|
||||||
}
|
|
||||||
if (rendering_style->hasTransparency()) {
|
|
||||||
const double d = rendering_style->Transparency();
|
|
||||||
surface_style.Transparency().reset(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &(style_cache[surface_style_id] = surface_style);
|
|
||||||
}
|
|
||||||
|
|
||||||
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationItem* item) {
|
|
||||||
return internalize_surface_style(get_surface_style<IfcSchema::IfcSurfaceStyleShading>(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
const IfcGeom::SurfaceStyle* IfcGeom::Kernel::get_style(const IfcSchema::IfcMaterial* material) {
|
|
||||||
IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation();
|
|
||||||
for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) {
|
|
||||||
IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations();
|
|
||||||
IfcSchema::IfcStyledItem::list::ptr styles(new IfcSchema::IfcStyledItem::list);
|
|
||||||
for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) {
|
|
||||||
styles->push((**it).Items()->as<IfcSchema::IfcStyledItem>());
|
|
||||||
}
|
|
||||||
for (IfcSchema::IfcStyledItem::list::it it = styles->begin(); it != styles->end(); ++it) {
|
|
||||||
const std::pair<IfcSchema::IfcSurfaceStyle*, IfcSchema::IfcSurfaceStyleShading*> ss = get_surface_style<IfcSchema::IfcSurfaceStyleShading>(*it);
|
|
||||||
if (ss.second) {
|
|
||||||
return internalize_surface_style(ss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IfcGeom::SurfaceStyle material_style = IfcGeom::SurfaceStyle(material->data().id(), material->Name());
|
|
||||||
return &(style_cache[material->data().id()] = material_style);
|
|
||||||
}
|
|
||||||
@@ -34,6 +34,7 @@ namespace IfcGeom {
|
|||||||
public:
|
public:
|
||||||
virtual void Multiply(const ConversionResultPlacement*) = 0;
|
virtual void Multiply(const ConversionResultPlacement*) = 0;
|
||||||
virtual void PreMultiply(const ConversionResultPlacement*) = 0;
|
virtual void PreMultiply(const ConversionResultPlacement*) = 0;
|
||||||
|
virtual void TranslationPart(double& X, double& Y, double& Z) const = 0;
|
||||||
virtual ConversionResultPlacement* inverted() const = 0;
|
virtual ConversionResultPlacement* inverted() const = 0;
|
||||||
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const = 0;
|
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const = 0;
|
||||||
virtual double Value(int i, int j) const = 0;
|
virtual double Value(int i, int j) const = 0;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace IfcGeom {
|
|||||||
return implementation_->convert(item);
|
return implementation_->convert(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, gp_Trsf& trsf) {
|
virtual bool convert_placement(IfcUtil::IfcBaseClass* item, ConversionResultPlacement*& trsf) {
|
||||||
return implementation_->convert_placement(item, trsf);
|
return implementation_->convert_placement(item, trsf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ namespace IfcGeom {
|
|||||||
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const {
|
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const {
|
||||||
throw std::runtime_error("Not implemented");
|
throw std::runtime_error("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void TranslationPart(double& X, double& Y, double& Z) const {
|
||||||
|
throw std::runtime_error("Not implemented");
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
cgal_placement_t trsf_;
|
cgal_placement_t trsf_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ namespace IfcGeom {
|
|||||||
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
|
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
|
||||||
return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->trsf_));
|
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:
|
private:
|
||||||
gp_GTrsf trsf_;
|
gp_GTrsf trsf_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -512,9 +512,11 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) {
|
|||||||
for (auto jt = insts->begin(); jt != insts->end(); ++jt) {
|
for (auto jt = insts->begin(); jt != insts->end(); ++jt) {
|
||||||
IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *jt;
|
IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *jt;
|
||||||
if (!product->get("ObjectPlacement")->isNull()) {
|
if (!product->get("ObjectPlacement")->isNull()) {
|
||||||
gp_Trsf trsf;
|
IfcGeom::ConversionResultPlacement* trsf;
|
||||||
if (kernel.convert_placement(*product->get("ObjectPlacement"), trsf)) {
|
if (kernel.convert_placement(*product->get("ObjectPlacement"), trsf)) {
|
||||||
setSectionHeight(trsf.TranslationPart().Z() + 1.);
|
double X, Y, Z;
|
||||||
|
trsf->TranslationPart(X, Y, Z);
|
||||||
|
setSectionHeight(Z + 1.);
|
||||||
Logger::Warning("No building storeys encountered, used for reference:", product);
|
Logger::Warning("No building storeys encountered, used for reference:", product);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user