diff --git a/src/core/SmootherTools.cpp b/src/core/SmootherTools.cpp index dc46199..63ab617 100644 --- a/src/core/SmootherTools.cpp +++ b/src/core/SmootherTools.cpp @@ -565,8 +565,40 @@ Coordinates SmootherTools::collapsePointsOnContour( } if (!validContourIds.empty()) { - for (auto const& interiorId : cG.getInterior()) { - res[interiorId] = coords[*validContourIds.begin()]; + const IdSet interior = cG.getInterior(); + bool collapseToMinExterior = false; + if (interior.size() > 1 && validContourIds.size() == 2) { + const CoordinateId minExt = *validContourIds.begin(); + const CoordinateId maxExt = *validContourIds.rbegin(); + // Preserve the established behavior for a contour run that + // extends toward both anchors: collapse the run as a unit. + for (const auto interiorId : interior) { + if ((coords[interiorId] - coords[maxExt]).norm() + < (coords[interiorId] - coords[minExt]).norm()) { + collapseToMinExterior = true; + break; + } + } + } + + if (collapseToMinExterior) { + const CoordinateId anchor = *validContourIds.begin(); + for (const auto interiorId : interior) { + res[interiorId] = coords[anchor]; + } + } + else { + for (const auto interiorId : interior) { + if (res[interiorId] != coords[interiorId]) { + continue; + } + const IdSet targets = + cG.getClosestVerticesInSet(interiorId, validContourIds); + if (targets.empty()) { + continue; + } + res[interiorId] = coords[*targets.begin()]; + } } } diff --git a/test/app/launcherTest.cpp b/test/app/launcherTest.cpp index 2cf01ab..b7869b8 100644 --- a/test/app/launcherTest.cpp +++ b/test/app/launcherTest.cpp @@ -193,6 +193,15 @@ TEST_F(LauncherTest, launches_conformal_sphere_case) EXPECT_EQ(exitCode, EXIT_SUCCESS); } +TEST_F(LauncherTest, launches_conformal_smallSphere_case) +{ + int ac = 3; + const char* av[] = { NULL, "-i", "testData/cases/smallSphere/smallSphere.conformal.tessellator.json"}; + int exitCode; + EXPECT_NO_THROW(exitCode = launcher(ac, av)); + EXPECT_EQ(exitCode, EXIT_SUCCESS); +} + TEST_F(LauncherTest, launches_conformal_thinCylinder_case) { int ac = 3; diff --git a/test/core/SmootherToolsTest.cpp b/test/core/SmootherToolsTest.cpp index e93a9d0..7edb594 100644 --- a/test/core/SmootherToolsTest.cpp +++ b/test/core/SmootherToolsTest.cpp @@ -299,6 +299,43 @@ class SmootherToolsTest : public ::testing::Test { return res; } + static Mesh buildCollapseEdgeMeshWithInnerDent() + { + // 7-------------6 + // | _-'/| + // | _-' / | + // | _-' / | + // | _-' / | + // 4---3----------5 + // | __-- + // 2-' --__ + // 0----------1 + Mesh res; + res.grid = utils::GridTools::buildCartesianGrid(0.0, 1.0, 2); + res.coordinates = { + Coordinate({0.00, 0.00, 1.00}), // 0 + Coordinate({0.60, 0.00, 1.00}), // 1 + Coordinate({0.00, 0.10, 1.00}), // 2 + Coordinate({0.20, 0.40, 1.00}), // 3 + Coordinate({0.00, 0.40, 1.00}), // 4 + Coordinate({1.00, 0.40, 1.00}), // 5 + Coordinate({1.00, 1.00, 1.00}), // 6 + Coordinate({0.00, 1.00, 1.00}), // 7 + }; + + res.groups.push_back(Group()); + res.groups[0].elements = { + Element({0, 1, 2}, Element::Type::Surface), + Element({1, 3, 2}, Element::Type::Surface), + Element({2, 3, 4}, Element::Type::Surface), + Element({3, 5, 6}, Element::Type::Surface), + Element({3, 6, 4}, Element::Type::Surface), + Element({4, 6, 7}, Element::Type::Surface), + }; + + return res; + } + static Mesh buildElementsToRemesh() { // 4 ---- 5 @@ -649,6 +686,21 @@ TEST_F(SmootherToolsTest, collapse_two_points_in_contour) EXPECT_EQ(collapsed[6], collapsed[7]); } +TEST_F(SmootherToolsTest, collapsePointsInContourWithInnerDent) +{ + Mesh mesh = buildCollapseEdgeMeshWithInnerDent(); + const Elements& elements = mesh.groups[0].elements; + + const Coordinates collapsed = SmootherTools(mesh.grid).collapsePointsOnContour( + elements, mesh.coordinates, alignmentAngle); + + EXPECT_EQ(8, countDifferentCoordinates(mesh.coordinates)); + ASSERT_EQ(6, countDifferentCoordinates(collapsed)); + EXPECT_NE(collapsed[2], collapsed[4]); + EXPECT_EQ(collapsed[2], collapsed[0]); + EXPECT_EQ(collapsed[4], collapsed[7]); +} + /// Build the list of singular Ids corresponding to a corner structure with the following ids /// \verbatim /// 2 ----- 6 diff --git a/testData/cases/smallSphere/smallSphere.conformal.tessellator.json b/testData/cases/smallSphere/smallSphere.conformal.tessellator.json new file mode 100644 index 0000000..0b60d8f --- /dev/null +++ b/testData/cases/smallSphere/smallSphere.conformal.tessellator.json @@ -0,0 +1,17 @@ +{ + "grid": { + "numberOfCells": [5, 5, 5], + "boundingBox": [ + [-3.0, -3.0, -3.0], + [ 2.0, 2.0, 2.0] + ] + }, + "object": {"filename": "smallSphere.stl"}, + "mesher": { + "type": "conformal", + "options": { + "edgePoints": 4, + "forbiddenLength": 0.0 + } + } +} diff --git a/testData/cases/smallSphere/smallSphere.stl b/testData/cases/smallSphere/smallSphere.stl new file mode 100644 index 0000000..0ba95a9 Binary files /dev/null and b/testData/cases/smallSphere/smallSphere.stl differ