diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bc965d74c91f46268aface68d889c048d131c769..ff0a84bfd37daca4a39f53c7884d4463e11be6db 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,6 @@ 4.10.2 (Work-in-progress): fixed regression introduced in 4.9 for recombined -meshes with boundary layers; small bug fixes. +meshes with boundary layers; new HealShapes command in .geo files; simplified +calculation of OCC STL bounding boxes; small bug fixes. 4.10.1 (May 1, 2022): small bug fixes. diff --git a/src/geo/GModelIO_OCC.cpp b/src/geo/GModelIO_OCC.cpp index 7fc3bb06974063d89dfd271ec523475c6c5fe2b7..d99b082d20086a7b29491703e587959da4718ffb 100644 --- a/src/geo/GModelIO_OCC.cpp +++ b/src/geo/GModelIO_OCC.cpp @@ -4489,6 +4489,26 @@ bool OCC_Internals::_getBoundingBox(const TopoDS_Shape &shape, double &xmin, std::vector<SVector3> normals; std::vector<int> triangles; _makeSTL(shape, vertices, normals, triangles); + // BRepBndLib can use the STL mesh if available, but unfortunately it + // enlarges the box with the mesh deflection tolerance and the shape + // tolerance, which makes it hard to get the expected minimal box in simple + // cases (e.g. for plane surfaces), and always leads to boxes that are too + // large; so we simply compute the box from the STL vertices. The downside + // of this approach is that the bbox might be *smaller* than the actual box + // for curved shapes, but this is preferable for us as boxes are mostly used + // to find/identify entities + if(vertices.size()) { + SBoundingBox3d bbox; + for(std::size_t i = 0; i < vertices.size(); i++) + bbox += vertices[i]; + xmin = bbox.min().x(); + ymin = bbox.min().y(); + zmin = bbox.min().z(); + xmax = bbox.max().x(); + ymax = bbox.max().y(); + zmax = bbox.max().z(); + return true; + } } Bnd_Box b; try { @@ -4498,8 +4518,6 @@ bool OCC_Internals::_getBoundingBox(const TopoDS_Shape &shape, double &xmin, return false; } b.Get(xmin, ymin, zmin, xmax, ymax, zmax); - if(CTX::instance()->geom.occBoundsUseSTL) - fixSTLBounds(xmin, ymin, zmin, xmax, ymax, zmax); return true; } @@ -5745,28 +5763,6 @@ bool OCC_Internals::makeTorusSTL(double x, double y, double z, double r1, return true; } -void OCC_Internals::fixSTLBounds(double &xmin, double &ymin, double &zmin, - double &xmax, double &ymax, double &zmax) -{ - // When an STL exists, OCC enlarges the bounding box by the allowed linear - // deflection given to BRepMesh_IncrementalMesh. This is "safe", but on simple - // polyhedral geometries (a cube!) it will consistently lead to enlarging the - // bounding box by twice this value in all directions. Since we use bounds() - // mostly for locating entities, it's better to remove the tolerance (with the - // risk that the bbox is a bit too small for curved boundaries - but that's - // fine) - double eps = CTX::instance()->mesh.stlLinearDeflection; - // OCC also enlarges the bounding box by Precision::Confusion(): remove it as - // well - eps += Precision::Confusion(); - xmin += eps; - xmax -= eps; - ymin += eps; - ymax -= eps; - zmin += eps; - zmax -= eps; -} - #endif void GModel::createOCCInternals() diff --git a/src/geo/GModelIO_OCC.h b/src/geo/GModelIO_OCC.h index 71c388ece98fdbe1acf84f9ef927b62f1dc051f5..6e7b9764096845bc4cf47662461124bd7244e972 100644 --- a/src/geo/GModelIO_OCC.h +++ b/src/geo/GModelIO_OCC.h @@ -460,8 +460,6 @@ public: double angle, std::vector<SPoint3> &vertices, std::vector<SVector3> &normals, std::vector<int> &triangles); - void fixSTLBounds(double &xmin, double &ymin, double &zmin, double &xmax, - double &ymax, double &zmax); }; #else diff --git a/src/geo/OCCEdge.cpp b/src/geo/OCCEdge.cpp index b62ca7a8523d93d9e81e6b8375c9f06700e86d33..b08cff67d2266ab7c031fc8e57e662de14468aed 100644 --- a/src/geo/OCCEdge.cpp +++ b/src/geo/OCCEdge.cpp @@ -72,6 +72,21 @@ void OCCEdge::delFace(GFace *f) SBoundingBox3d OCCEdge::bounds(bool fast) { + if(CTX::instance()->geom.occBoundsUseSTL && stl_vertices_xyz.size()) { + // BRepBndLib can use the STL mesh if available, but unfortunately it + // enlarges the box with the mesh deflection tolerance and the shape + // tolerance, which makes it hard to get the expected minimal box in simple + // cases (e.g. for straight lines), and always leads to boxes that are too + // large; so we simply compute the box from the STL vertices. The downside + // of this approach is that the bbox might be *smaller* than the actual box + // for curved shapes, but this is preferable for us as boxes are mostly used + // to find/identify entities + SBoundingBox3d bbox; + for(std::size_t i = 0; i < stl_vertices_xyz.size(); i++) + bbox += stl_vertices_xyz[i]; + return bbox; + } + Bnd_Box b; try { BRepBndLib::Add(_c, b); @@ -81,11 +96,6 @@ SBoundingBox3d OCCEdge::bounds(bool fast) } double xmin, ymin, zmin, xmax, ymax, zmax; b.Get(xmin, ymin, zmin, xmax, ymax, zmax); - - if(CTX::instance()->geom.occBoundsUseSTL) - model()->getOCCInternals()->fixSTLBounds(xmin, ymin, zmin, xmax, ymax, - zmax); - SBoundingBox3d bbox(xmin, ymin, zmin, xmax, ymax, zmax); return bbox; } diff --git a/src/geo/OCCFace.cpp b/src/geo/OCCFace.cpp index 538d8672308b389a18091d9a783c6fc0dc1a2059..ff5654b2d83f5d15fbdb75bd0c7bca18ec531905 100644 --- a/src/geo/OCCFace.cpp +++ b/src/geo/OCCFace.cpp @@ -193,7 +193,23 @@ void OCCFace::_setup() SBoundingBox3d OCCFace::bounds(bool fast) { - if(CTX::instance()->geom.occBoundsUseSTL) buildSTLTriangulation(); + if(CTX::instance()->geom.occBoundsUseSTL) { + buildSTLTriangulation(); + // BRepBndLib can use the STL mesh if available, but unfortunately it + // enlarges the box with the mesh deflection tolerance and the shape + // tolerance, which makes it hard to get the expected minimal box in simple + // cases (e.g. for plane surfaces), and always leads to boxes that are too + // large; so we simply compute the box from the STL vertices. The downside + // of this approach is that the bbox might be *smaller* than the actual box + // for curved shapes, but this is preferable for us as boxes are mostly used + // to find/identify entities + if(stl_vertices_xyz.size()) { + SBoundingBox3d bbox; + for(std::size_t i = 0; i < stl_vertices_xyz.size(); i++) + bbox += stl_vertices_xyz[i]; + return bbox; + } + } Bnd_Box b; try { @@ -204,11 +220,6 @@ SBoundingBox3d OCCFace::bounds(bool fast) } double xmin, ymin, zmin, xmax, ymax, zmax; b.Get(xmin, ymin, zmin, xmax, ymax, zmax); - - if(CTX::instance()->geom.occBoundsUseSTL) - model()->getOCCInternals()->fixSTLBounds(xmin, ymin, zmin, xmax, ymax, - zmax); - SBoundingBox3d bbox(xmin, ymin, zmin, xmax, ymax, zmax); return bbox; } diff --git a/src/geo/OCCRegion.cpp b/src/geo/OCCRegion.cpp index b979d877686ab81d53a5953cc47e0f614733f6c7..3a1b39d37b73905c5459069077f0ad602c7b1278 100644 --- a/src/geo/OCCRegion.cpp +++ b/src/geo/OCCRegion.cpp @@ -97,10 +97,13 @@ void OCCRegion::_setup() SBoundingBox3d OCCRegion::bounds(bool fast) { if(CTX::instance()->geom.occBoundsUseSTL) { - // if a triangulation exist on a shape, OCC will use it to compute more - // accurate bounds std::vector<GFace *> f = faces(); - for(std::size_t i = 0; i < f.size(); i++) f[i]->buildSTLTriangulation(); + SBoundingBox3d bbox; + for(std::size_t i = 0; i < f.size(); i++) { + f[i]->buildSTLTriangulation(); + bbox += f[i]->bounds(); + } + return bbox; } Bnd_Box b; @@ -112,11 +115,6 @@ SBoundingBox3d OCCRegion::bounds(bool fast) } double xmin, ymin, zmin, xmax, ymax, zmax; b.Get(xmin, ymin, zmin, xmax, ymax, zmax); - - if(CTX::instance()->geom.occBoundsUseSTL) - model()->getOCCInternals()->fixSTLBounds(xmin, ymin, zmin, xmax, ymax, - zmax); - SBoundingBox3d bbox(xmin, ymin, zmin, xmax, ymax, zmax); return bbox; }