mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 11:24:19 +00:00
Introduce AbstractKernel
This commit is contained in:
@@ -427,7 +427,8 @@ IF(MSVC)
|
||||
ENDIF()
|
||||
# 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))
|
||||
add_definitions(-permissive-)
|
||||
# @todo currently fails
|
||||
# add_definitions(-permissive-)
|
||||
endif()
|
||||
# Link against the static VC runtime
|
||||
# TODO Make this configurable
|
||||
|
||||
@@ -182,6 +182,7 @@ int main(int argc, char** argv)
|
||||
exclusion_traverse_filter exclude_traverse_filter;
|
||||
std::string filter_filename;
|
||||
std::string default_material_filename;
|
||||
std::string geometry_kernel;
|
||||
|
||||
po::options_description ifc_options("IFC options");
|
||||
ifc_options.add_options()
|
||||
@@ -190,6 +191,8 @@ int main(int argc, char** argv)
|
||||
|
||||
po::options_description geom_options("Geometry options");
|
||||
geom_options.add_options()
|
||||
("kernel", po::value<std::string>(&geometry_kernel)->default_value("opencascade"),
|
||||
"Geometry kernel to use (opencascade or cgal).")
|
||||
("plan",
|
||||
"Specifies whether to include curves in the output result. Typically "
|
||||
"these are representations of type Plan or Axis. Excluded by default.")
|
||||
@@ -652,7 +655,7 @@ int main(int argc, char** argv)
|
||||
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()) {
|
||||
/// @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.
|
||||
|
||||
@@ -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 "../../ifcgeom/schema_agnostic/IteratorImplementation.h"
|
||||
|
||||
namespace IfcGeom {
|
||||
template class MAKE_TYPE_NAME(IteratorImplementation_)<float, float>;
|
||||
|
||||
@@ -73,9 +73,9 @@
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
|
||||
#include "../../ifcparse/macros.h"
|
||||
#include "../../ifcparse/IfcFile.h"
|
||||
|
||||
#include "../../ifcgeom/kernels/opencascade/IfcGeom.h"
|
||||
#include "../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||
#include "../../ifcgeom/schema_agnostic/IfcGeomMaterial.h"
|
||||
#include "../../ifcgeom/schema_agnostic/IfcGeomIteratorSettings.h"
|
||||
@@ -84,7 +84,11 @@
|
||||
#include "../../ifcgeom/schema_agnostic/IfcGeomFilter.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
|
||||
#ifdef min
|
||||
@@ -103,7 +107,7 @@ namespace IfcGeom {
|
||||
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(Kernel)* kernel;
|
||||
MAKE_TYPE_NAME(AbstractKernel)* kernel;
|
||||
IteratorSettings settings;
|
||||
|
||||
IfcParse::IfcFile* ifc_file;
|
||||
@@ -265,11 +269,11 @@ namespace IfcGeom {
|
||||
IfcSchema::IfcProduct* product = *iter;
|
||||
if (product->hasObjectPlacement()) {
|
||||
// Use a fresh trsf every time in order to prevent the result to be concatenated
|
||||
gp_Trsf trsf;
|
||||
ConversionResultPlacement* trsf;
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
success = kernel->convert(product->ObjectPlacement(), trsf);
|
||||
success = kernel->convert_placement(product->ObjectPlacement(), trsf);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
} catch (...) {
|
||||
@@ -280,13 +284,14 @@ namespace IfcGeom {
|
||||
continue;
|
||||
}
|
||||
|
||||
const gp_XYZ& pos = trsf.TranslationPart();
|
||||
bounds_min_.SetX(std::min(bounds_min_.X(), pos.X()));
|
||||
bounds_min_.SetY(std::min(bounds_min_.Y(), pos.Y()));
|
||||
bounds_min_.SetZ(std::min(bounds_min_.Z(), pos.Z()));
|
||||
bounds_max_.SetX(std::max(bounds_max_.X(), pos.X()));
|
||||
bounds_max_.SetY(std::max(bounds_max_.Y(), pos.Y()));
|
||||
bounds_max_.SetZ(std::max(bounds_max_.Z(), pos.Z()));
|
||||
double X, Y, Z;
|
||||
trsf->TranslationPart(X, Y, Z);
|
||||
bounds_min_.SetX(std::min(bounds_min_.X(), X));
|
||||
bounds_min_.SetY(std::min(bounds_min_.Y(), Y));
|
||||
bounds_min_.SetZ(std::min(bounds_min_.Z(), Z));
|
||||
bounds_max_.SetX(std::max(bounds_max_.X(), X));
|
||||
bounds_max_.SetY(std::max(bounds_max_.Y(), Y));
|
||||
bounds_max_.SetZ(std::max(bounds_max_.Z(), Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,13 +316,6 @@ namespace IfcGeom {
|
||||
private:
|
||||
// Move to the next IfcRepresentation
|
||||
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();
|
||||
++ representation_iterator;
|
||||
++ done;
|
||||
@@ -554,7 +552,7 @@ namespace IfcGeom {
|
||||
}
|
||||
|
||||
const Element<P, PP>* get_object(int id) {
|
||||
gp_Trsf trsf;
|
||||
ConversionResultPlacement* trsf;
|
||||
int parent_id = -1;
|
||||
std::string instance_type, product_name, product_guid;
|
||||
IfcSchema::IfcProduct* ifc_product = 0;
|
||||
@@ -584,7 +582,7 @@ namespace IfcGeom {
|
||||
}
|
||||
|
||||
try {
|
||||
kernel->convert(ifc_product->ObjectPlacement(), trsf);
|
||||
kernel->convert_placement(ifc_product->ObjectPlacement(), trsf);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::Error(e);
|
||||
} catch (...) {
|
||||
@@ -605,7 +603,7 @@ namespace IfcGeom {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -685,7 +683,7 @@ namespace IfcGeom {
|
||||
, filters_(filters)
|
||||
, 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);
|
||||
_initialize();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ void MAKE_INIT_FN(KernelImplementation_cgal_)(IfcGeom::impl::KernelFactoryImplem
|
||||
|
||||
#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()");
|
||||
return false;
|
||||
/*
|
||||
@@ -80,154 +80,15 @@ bool IfcGeom::CgalKernel::is_identity_transform(IfcUtil::IfcBaseClass* l) {
|
||||
*/
|
||||
}
|
||||
|
||||
template <typename P, typename PP>
|
||||
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_representation_and_product(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product)
|
||||
{
|
||||
IfcGeom::Representation::BRep* shape;
|
||||
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
|
||||
);
|
||||
bool IfcGeom::CgalKernel::apply_layerset(const IfcSchema::IfcProduct* product, IfcGeom::ConversionResults& shapes) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
template <typename P, typename PP>
|
||||
IfcGeom::NativeElement<P, PP>* IfcGeom::CgalKernel::create_brep_for_processed_representation(
|
||||
const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product,
|
||||
IfcGeom::NativeElement<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
|
||||
);
|
||||
bool IfcGeom::CgalKernel::validate_quantities(const IfcSchema::IfcProduct* product, const IfcGeom::Representation::BRep& brep) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, float>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<float, double>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_representation_and_product<double, double>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product);
|
||||
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<float, float>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, float>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, float>* brep);
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<float, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<float, double>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<float, double>* brep);
|
||||
template IFC_GEOM_API IfcGeom::NativeElement<double, double>* IfcGeom::CgalKernel::create_brep_for_processed_representation<double, double>(
|
||||
const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, IfcGeom::NativeElement<double, double>* brep);
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
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) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
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 "../../../ifcgeom/kernel_agnostic/AbstractKernel.h"
|
||||
|
||||
#include "../../../ifcgeom/schema_agnostic/Kernel.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/cgal/CgalConversionResult.h"
|
||||
@@ -55,10 +58,11 @@ namespace IfcGeom {
|
||||
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:
|
||||
|
||||
MAKE_TYPE_NAME(CgalKernel)() : Kernel("cgal") {}
|
||||
MAKE_TYPE_NAME(CgalKernel)()
|
||||
: MAKE_TYPE_NAME(AbstractKernel)("cgal") {}
|
||||
|
||||
#ifndef NO_CACHE
|
||||
CgalCache cache;
|
||||
@@ -72,9 +76,6 @@ namespace IfcGeom {
|
||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, cgal_curve_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);
|
||||
|
||||
void purge_cache() {
|
||||
@@ -86,16 +87,10 @@ namespace IfcGeom {
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual bool is_identity_transform(IfcUtil::IfcBaseClass*);
|
||||
|
||||
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>*);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
#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/IfcBaseClass.h"
|
||||
|
||||
#include "../../../ifcgeom/kernel_agnostic/AbstractKernel.h"
|
||||
|
||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomElement.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/IfcGeomRepresentation.h"
|
||||
#include "../../../ifcgeom/schema_agnostic/ConversionResult.h"
|
||||
@@ -108,7 +110,7 @@ public:
|
||||
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:
|
||||
|
||||
/*
|
||||
@@ -203,46 +205,23 @@ private:
|
||||
double epsilon() const {
|
||||
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
|
||||
MAKE_TYPE_NAME(Cache) cache;
|
||||
#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_;
|
||||
|
||||
public:
|
||||
MAKE_TYPE_NAME(Kernel)()
|
||||
: IfcGeom::Kernel("opencascade", 0)
|
||||
, 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)
|
||||
: IfcGeom::MAKE_TYPE_NAME(AbstractKernel)("opencascade")
|
||||
, 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;
|
||||
}
|
||||
|
||||
@@ -267,8 +246,7 @@ public:
|
||||
bool convert_wire(const IfcUtil::IfcBaseClass* L, TopoDS_Wire& result);
|
||||
bool convert_curve(const IfcUtil::IfcBaseClass* L, Handle(Geom_Curve)& 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_fast(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);
|
||||
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>&);
|
||||
@@ -302,8 +280,6 @@ public:
|
||||
|
||||
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_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid);
|
||||
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_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&);
|
||||
|
||||
|
||||
std::pair<std::string, double> initializeUnits(IfcSchema::IfcUnitAssignment*);
|
||||
|
||||
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>*);
|
||||
|
||||
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() {
|
||||
void purge_cache() {
|
||||
// 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
|
||||
// are read later on when serializing Collada files.
|
||||
#ifndef NO_CACHE
|
||||
cache = MAKE_TYPE_NAME(Cache)();
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_conversion_placement_rel_to(const IfcParse::declaration* type);
|
||||
}
|
||||
|
||||
#include "IfcRegisterGeomHeader.h"
|
||||
|
||||
virtual void setValue(GeomValue var, double value);
|
||||
virtual double getValue(GeomValue var) const;
|
||||
|
||||
virtual IfcGeom::NativeElement<double>* convert(
|
||||
const IteratorSettings& settings, IfcUtil::IfcBaseClass* representation,
|
||||
IfcUtil::IfcBaseClass* product)
|
||||
@@ -433,12 +343,15 @@ public:
|
||||
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>()) {
|
||||
return convert(item->as<IfcSchema::IfcObjectPlacement>(), trsf);
|
||||
} else {
|
||||
return false;
|
||||
gp_Trsf occt_trsf;
|
||||
if (convert(item->as<IfcSchema::IfcObjectPlacement>(), occt_trsf)) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
struct opening_sorter {
|
||||
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,
|
||||
const IfcGeom::ConversionResults& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::ConversionResults& cut_shapes) {
|
||||
bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
||||
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;
|
||||
|
||||
@@ -859,7 +608,6 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& w, TopoDS_Face& face) {
|
||||
TopoDS_Wire wire = w;
|
||||
@@ -1084,63 +832,6 @@ void IfcGeom::Kernel::apply_tolerance(TopoDS_Shape& s, double t) {
|
||||
#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 {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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) {
|
||||
// Set default units, set length to meters, angles to undefined
|
||||
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;
|
||||
}
|
||||
|
||||
const IfcSchema::IfcRepresentationItem* IfcGeom::Kernel::find_item_carrying_style(const IfcSchema::IfcRepresentationItem* item) {
|
||||
if (item->StyledByItem()->size()) {
|
||||
return item;
|
||||
}
|
||||
bool IfcGeom::Kernel::is_identity_transform(const IfcUtil::IfcBaseClass* l) {
|
||||
const IfcSchema::IfcAxis2Placement2D* ax2d;
|
||||
const IfcSchema::IfcAxis2Placement3D* ax3d;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
const IfcSchema::IfcCartesianTransformationOperator2D* op2d;
|
||||
const IfcSchema::IfcCartesianTransformationOperator3D* op3d;
|
||||
const IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu;
|
||||
const IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu;
|
||||
|
||||
if((op2dnonu = l->as<IfcSchema::IfcCartesianTransformationOperator2DnonUniform>()) != 0) {
|
||||
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()))) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
IN_CACHE(IfcObjectPlacement,l,gp_Trsf,trsf)
|
||||
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:
|
||||
virtual void Multiply(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* multiplied(const ConversionResultPlacement*) const = 0;
|
||||
virtual double Value(int i, int j) const = 0;
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace IfcGeom {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ namespace IfcGeom {
|
||||
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement*) const {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
|
||||
virtual void TranslationPart(double& X, double& Y, double& Z) const {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
private:
|
||||
cgal_placement_t trsf_;
|
||||
};
|
||||
|
||||
@@ -69,6 +69,12 @@ namespace IfcGeom {
|
||||
virtual ConversionResultPlacement* multiplied(const ConversionResultPlacement* other) const {
|
||||
return new OpenCascadePlacement(trsf_.Multiplied(((OpenCascadePlacement*)other)->trsf_));
|
||||
}
|
||||
|
||||
virtual void TranslationPart(double& X, double& Y, double& Z) const {
|
||||
X = trsf_.TranslationPart().X();
|
||||
Y = trsf_.TranslationPart().Y();
|
||||
Z = trsf_.TranslationPart().Z();
|
||||
}
|
||||
private:
|
||||
gp_GTrsf trsf_;
|
||||
};
|
||||
|
||||
@@ -512,9 +512,11 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) {
|
||||
for (auto jt = insts->begin(); jt != insts->end(); ++jt) {
|
||||
IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *jt;
|
||||
if (!product->get("ObjectPlacement")->isNull()) {
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::ConversionResultPlacement* 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);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user