From 6aa06511900f68b8d99f7f98b22d46bed1d4ff7d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 4 Mar 2021 14:39:32 +0100 Subject: [PATCH] #1153 support IfcAnnotation with Box as drawing view --- src/serializers/SvgSerializer.cpp | 116 ++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index c0ab3fc7c2..c9f9f6fe94 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -335,6 +335,8 @@ namespace { return boost::none; } + typedef std::pair, std::array> box_t; + boost::optional edge_from_compound(TopoDS_Shape& compound) { TopoDS_Iterator it(compound); if (it.More()) { @@ -353,6 +355,69 @@ namespace { } return boost::none; } + + class almost { + private: + double v_, eps_; + public: + almost(double v, double eps = 1.e-7) + : v_(v) + , eps_(eps) + {} + + bool operator==(double other) const { + return std::fabs(other - v_) < eps_; + } + + bool operator!=(double other) const { + return !(*this == other); + } + }; + + boost::optional box_from_compound(TopoDS_Shape& compound) { + TopExp_Explorer exp(compound, TopAbs_SHELL); + TopoDS_Shell shell; + if (exp.More()) { + shell = TopoDS::Shell(exp.Current()); + exp.Next(); + if (exp.More()) { + return boost::none; + } + } + else { + return boost::none; + } + + if (IfcGeom::Kernel::count(shell, TopAbs_FACE) != 6) { + return boost::none; + } + + TopoDS_Iterator it(shell); + for (; it.More(); it.Next()) { + const auto& face = TopoDS::Face(it.Value()); + auto surf = BRep_Tool::Surface(face); + if (surf->DynamicType() != STANDARD_TYPE(Geom_Plane)) { + return boost::none; + } + auto pln = Handle(Geom_Plane)::DownCast(surf); + auto dz = std::abs(pln->Position().Direction().Z()); + if (almost(0.) != dz && almost(1.) != dz) { + return boost::none; + } + auto dy = std::abs(pln->Position().Direction().Y()); + if (almost(0.) != dy && almost(1.) != dy) { + return boost::none; + } + } + + Bnd_Box b; + BRepBndLib::Add(compound, b, false); + + double x0, y0, z0, x1, y1, z1; + b.Get(x0, y0, z0, x1, y1, z1); + + return box_t{ {{x0, y0, z0}}, {{x1, y1, z1}} }; + } } void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { @@ -375,6 +440,7 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { auto compound_unmirrored = make_transform_global.Shape(); auto e = edge_from_compound(compound_unmirrored); + boost::optional pln; if (e) { TopoDS_Edge global_edge = TopoDS::Edge(e->Moved(trsf)); double u0, u1; @@ -384,30 +450,36 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { gp_Vec V; crv->D1((u0 + u1) / 2., P, V); auto N = V.Crossed(gp::DZ()); - gp_Pln pln(gp_Ax3(P, N, V)); - - // Move pln to have projection of origin at plane center. - // This is necessary to have Poly and BRep HLR at the same position - // (Poly) is wrong otherwise. - Extrema_ExtPElS ext; - ext.Perform(gp::Origin(), pln, 1.e-5); - pln.SetLocation(ext.Point(1).Value()); - - if (!deferred_section_data_) { - deferred_section_data_.emplace(); - } - std::string name = brep_obj->name(); - if (name.empty()) { - name = boost::lexical_cast(brep_obj->id()); - } - if (is_section) { - deferred_section_data_->push_back(vertical_section{ pln , "Section " + name, false }); - } - if (is_elevation) { - deferred_section_data_->push_back(vertical_section{ pln , "Elevation " + name, true }); - } + pln = gp_Pln(gp_Ax3(P, N, V)); } } + else if (box_from_compound(compound_local)) { + pln = gp_Pln().Transformed(trsf); + } + + if (pln) { + // Move pln to have projection of origin at plane center. + // This is necessary to have Poly and BRep HLR at the same position + // (Poly) is wrong otherwise. + Extrema_ExtPElS ext; + ext.Perform(gp::Origin(), *pln, 1.e-5); + pln->SetLocation(ext.Point(1).Value()); + + if (!deferred_section_data_) { + deferred_section_data_.emplace(); + } + std::string name = brep_obj->name(); + if (name.empty()) { + name = boost::lexical_cast(brep_obj->id()); + } + if (is_section) { + deferred_section_data_->push_back(vertical_section{ *pln , "Section " + name, false }); + } + if (is_elevation) { + deferred_section_data_->push_back(vertical_section{ *pln , "Elevation " + name, true }); + } + } + return; }