| 84 | } |
| 85 | |
| 86 | bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, ConversionResults& results) { |
| 87 | return handle_occt_exception([&]() -> bool { |
| 88 | bool valid_result = false; |
| 89 | bool first = true; |
| 90 | const double tol = settings_.get<settings::Precision>().get(); |
| 91 | |
| 92 | TopoDS_Shape a; |
| 93 | TopTools_ListOfShape b; |
| 94 | |
| 95 | taxonomy::style::ptr first_item_style; |
| 96 | |
| 97 | for (auto& c : br->children) { |
| 98 | IfcGeom::ConversionResults cr; |
| 99 | AbstractKernel::convert(c, cr); |
| 100 | if (first && br->operation == taxonomy::boolean_result::SUBTRACTION) { |
| 101 | // @todo A will be null on union/intersection, intended? |
| 102 | IfcGeom::util::flatten_shape_list(cr, a, false, true, settings_.get<settings::Precision>().get()); |
| 103 | first_item_style = c->surface_style; |
| 104 | if (!first_item_style && c->kind() == taxonomy::COLLECTION) { |
| 105 | // @todo recursively right? |
| 106 | first_item_style = taxonomy::cast<taxonomy::geom_item>(taxonomy::cast<taxonomy::collection>(c)->children[0])->surface_style; |
| 107 | } |
| 108 | |
| 109 | if (settings_.get<settings::DisableBooleanResult>().get()) { |
| 110 | results.emplace_back(IfcGeom::ConversionResult( |
| 111 | br->instance->as<IfcUtil::IfcBaseEntity>()->id(), |
| 112 | br->matrix, |
| 113 | new OpenCascadeShape(a), |
| 114 | br->surface_style ? br->surface_style : first_item_style |
| 115 | )); |
| 116 | return true; |
| 117 | } |
| 118 | |
| 119 | const double first_operand_volume = util::shape_volume(a); |
| 120 | if (first_operand_volume <= ALMOST_ZERO) { |
| 121 | Logger::Message(Logger::LOG_WARNING, "Empty solid for:", c->instance); |
| 122 | } |
| 123 | } else { |
| 124 | |
| 125 | for (auto& r : cr) { |
| 126 | auto S = std::static_pointer_cast<OpenCascadeShape>(r.Shape())->shape(); |
| 127 | if (S.IsNull()) { |
| 128 | Logger::Error("Null operand"); |
| 129 | continue; |
| 130 | } |
| 131 | gp_GTrsf trsf; |
| 132 | convert(r.Placement(), trsf); |
| 133 | // @todo it really confuses me why I cannot use Moved() here instead |
| 134 | S.Location(S.Location() * trsf.Trsf()); |
| 135 | |
| 136 | if (is_unbounded_halfspace(S)) { |
| 137 | double d; |
| 138 | TopoDS_Shape result; |
| 139 | util::fit_halfspace(a, S, result, d, tol * 1e3); |
| 140 | // #2665 we also set a precision-independent threshold, because in the boolean op routine |
| 141 | // the working fuzziness might still be increased. |
| 142 | if (d < tol * 20. || d < 0.00002) { |
| 143 | Logger::Message(Logger::LOG_WARNING, "Halfspace subtraction yields unchanged volume:", c->instance); |
nothing calls this directly
no test coverage detected