diff --git a/src/ifcgeom/kernel_agnostic/AbstractKernel.cpp b/src/ifcgeom/kernel_agnostic/AbstractKernel.cpp index a73027edda..62cebcabfb 100644 --- a/src/ifcgeom/kernel_agnostic/AbstractKernel.cpp +++ b/src/ifcgeom/kernel_agnostic/AbstractKernel.cpp @@ -55,6 +55,9 @@ bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonom for (auto& c : collection->children) { convert(c, r); } + for (auto i = s; i < r.size(); ++i) { + r[i].prepend(collection->matrix); + } return r.size() > s; } diff --git a/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp index 15ea102524..f17955d9bf 100644 --- a/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp +++ b/src/ifcgeom/kernels/opencascade/IfcGeomShapes.cpp @@ -2104,18 +2104,37 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result* br, ifcopen TopoDS_Shape a; TopTools_ListOfShape b; + taxonomy::style first_item_style; + for (auto& c : br->children) { + // AbstractKernel::convert(c, results); + // continue; + ifcopenshell::geometry::ConversionResults cr; // @todo half-space detection AbstractKernel::convert(c, cr); if (first && br->operation == taxonomy::boolean_result::SUBTRACTION) { // @todo A will be null on union/intersection, intended? flatten_shape_list(cr, a, false); + first_item_style = ((taxonomy::geom_item*)c)->surface_style; + if (!first_item_style.diffuse && c->kind() == taxonomy::COLLECTION) { + first_item_style = ((taxonomy::geom_item*) ((taxonomy::collection*)c)->children[0])->surface_style; + } } else { for (auto& r : cr) { - auto oshp = (OpenCascadeShape*)r.Shape(); - b.Append(oshp->shape()); - } + auto S = ((OpenCascadeShape*)r.Shape())->shape(); + gp_GTrsf trsf; + convert(&r.Placement(), trsf); + // @todo it really confuses me why I cannot use Moved() here instead + S.Location(S.Location() * trsf.Trsf()); + b.Append(S); + /*results.emplace_back(ConversionResult( + r.ItemId(), + ifcopenshell::geometry::taxonomy::matrix4(), + new OpenCascadeShape(S), + r.Style() + ));*/ + } } first = false; } @@ -2125,11 +2144,21 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result* br, ifcopen return false; } + /* + TopoDS_Compound r; + BRep_Builder B; + B.MakeCompound(r); + B.Add(r, a); + for (auto& bb : b) { + B.Add(r, bb); + } + */ + results.emplace_back(ConversionResult( br->instance->data().id(), br->matrix, new OpenCascadeShape(r), - br->surface_style + br->surface_style.diffuse ? br->surface_style : first_item_style )); return true; } @@ -2261,4 +2290,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face* face, ifcopenshell::g new OpenCascadeShape(shape), face->surface_style )); + + return true; } diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h index f2c564662f..9f49245e58 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h @@ -218,7 +218,9 @@ namespace kernels { public: OpenCascadeKernel() : AbstractKernel("opencascade") - , faceset_helper_(nullptr) {} + , faceset_helper_(nullptr) + // @todo + , precision_(1.e-5) {} OpenCascadeKernel(const OpenCascadeKernel& other) : AbstractKernel("opencascade") { diff --git a/src/ifcgeom/schema/mapping.cpp b/src/ifcgeom/schema/mapping.cpp index d603a9b67d..51a29a32a1 100644 --- a/src/ifcgeom/schema/mapping.cpp +++ b/src/ifcgeom/schema/mapping.cpp @@ -306,9 +306,39 @@ taxonomy::item* mapping::map_impl(const IfcSchema::IfcDirection* inst) { taxonomy::item* mapping::map_impl(const IfcSchema::IfcProduct* inst) { auto openings = find_openings(inst); - auto n = map_to_collection(this, openings); - n->matrix = as(map(inst->ObjectPlacement())); - return n; + // @todo const cast + auto reps = inst->data().file->traverse((IfcSchema::IfcProduct*) inst, 2)->as(); + IfcSchema::IfcRepresentation* body = nullptr; + for (auto& rep : *reps) { + if (rep->RepresentationIdentifier() == "Body") { + body = rep; + } + } + if (!body) { + return nullptr; + } + + auto c = new taxonomy::collection; + c->matrix = as(map(inst->ObjectPlacement())); + + if (openings->size()) { + auto ci = c->matrix.components.inverse(); + + IfcEntityList::ptr operands(new IfcEntityList); + operands->push(body); + operands->push(openings); + auto n = map_to_collection(this, operands); + std::for_each(n->children.begin() + 1, n->children.end(), [&ci](taxonomy::item* i) { + ((taxonomy::geom_item*)i)->matrix.components = ci * ((taxonomy::geom_item*)i)->matrix.components; + }); + n->operation = taxonomy::boolean_result::SUBTRACTION; + // @todo one indirection too many + n->instance = inst; + c->children = { n }; + } else { + c->children = { map(body) }; + } + return c; } taxonomy::item* mapping::map_impl(const IfcSchema::IfcAxis2Placement3D* inst) { @@ -515,7 +545,10 @@ IfcEntityList::ptr mapping::find_openings(const IfcSchema::IfcProduct* product) IfcEntityList::ptr openings(new IfcEntityList); if (product->declaration().is(IfcSchema::IfcElement::Class()) && !product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; - openings = element->HasOpenings()->generalize(); + auto rels = element->HasOpenings(); + for (auto& rel : *rels) { + openings->push(rel->RelatedOpeningElement()); + } } // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? @@ -526,7 +559,10 @@ IfcEntityList::ptr mapping::find_openings(const IfcSchema::IfcProduct* product) IfcSchema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->as()->RelatingObject(); if (rel_obdef->declaration().is(IfcSchema::IfcElement::Class()) && !rel_obdef->declaration().is(IfcSchema::IfcOpeningElement::Class())) { IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)rel_obdef; - openings->push(element->HasOpenings()->generalize()); + auto rels = element->HasOpenings(); + for (auto& rel : *rels) { + openings->push(rel->RelatedOpeningElement()); + } } obdef = rel_obdef; diff --git a/src/ifcgeom/schema_agnostic/Converter.cpp b/src/ifcgeom/schema_agnostic/Converter.cpp index 97a6f41d78..0a72eb7efd 100644 --- a/src/ifcgeom/schema_agnostic/Converter.cpp +++ b/src/ifcgeom/schema_agnostic/Converter.cpp @@ -34,18 +34,24 @@ ifcopenshell::geometry::NativeElement* ifcopenshell::geometry::Converter::create ifcopenshell::geometry::Representation::BRep* shape; ifcopenshell::geometry::ConversionResults shapes; + /* auto rep_item = mapping_->map(representation); // @todo should map() throw an exception instead? if (rep_item == nullptr) { return nullptr; } + */ - // @todo decide how to get placement from product - auto placement = (taxonomy::geom_item*) mapping_->map(product); - if (placement == nullptr) { + // @todo how to combine product_node and rep_item? + auto product_node = (taxonomy::geom_item*) mapping_->map(product); + if (product_node == nullptr) { return nullptr; } - kernel_->convert(rep_item, shapes); + + auto place = taxonomy::matrix4(); + std::swap(place, product_node->matrix); + + kernel_->convert(product_node, shapes); shape = new ifcopenshell::geometry::Representation::BRep(s, representation_id_builder.str(), shapes); @@ -57,7 +63,8 @@ ifcopenshell::geometry::NativeElement* ifcopenshell::geometry::Converter::create guid, // @todo "", - placement->matrix, + place, + // product_node->matrix, boost::shared_ptr(shape), product );