Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/CheckLargeResultsSets.cs
===================================================================
diff -u -r6404 -r7045
--- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/CheckLargeResultsSets.cs (.../CheckLargeResultsSets.cs) (revision 6404)
+++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/CheckLargeResultsSets.cs (.../CheckLargeResultsSets.cs) (revision 7045)
@@ -121,7 +121,7 @@
{
Assert.Multiple(() =>
{
- Assert.That(designResult.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.204).Within(tolerance));
+ Assert.That(designResult.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.203).Within(tolerance));
Assert.That(designResult.ScenarioName, Is.EqualTo("4"));
Assert.That(designResult.StabilityDesignResults.UpliftSituation.Pl3HeadAdjusted, Is.EqualTo(-0.52).Within(tol2Digits));
});
Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs
===================================================================
diff -u -r6677 -r7045
--- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 6677)
+++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 7045)
@@ -42,8 +42,8 @@
[TestCase("DWP_7", "SegDWP_7",9, 65, 57, 37, 1.264)]
[TestCase("DWP_8", "SegDWP_8",27, 117, 91, 46, 1.020)]
[TestCase("DWP_16", "SegDWP_16",26, 99, 74, 39, 0.713)]
- [TestCase("DWP_17", "SegDWP_17",19, 82, 64, 32, 1.256)]
- [TestCase("DWP_20", "SegDWP_20",24, 102, 79, 46, 1.523)]
+ [TestCase("DWP_17", "SegDWP_17",18, 81, 64, 33, 1.256)]
+ [TestCase("DWP_20", "SegDWP_20",25, 104, 80, 46, 1.523)]
public void TestGeometryAndResultForIssueWithDwpsFromTutorial(string location, string segment, int surfaceCount, int curveCount, int pointCount, int surfaceLinePointCount, double safetyFactor)
{
const string calcDir = "TestGeometryAndResultForIssueWithDwpsFromTutorial";
Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs
===================================================================
diff -u -r7044 -r7045
--- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs (.../GeometrySurface.cs) (revision 7044)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs (.../GeometrySurface.cs) (revision 7045)
@@ -178,14 +178,20 @@
const double stopCriteriumOffset = 1e-8;
double offset = initialOffset;
Point2D point = null;
- var geometryPointString = DetermineTopGeometrySurface();
+ GeometryPointString geometryPointString = DetermineTopGeometrySurface();
geometryPointString.SortPointsByXAscending();
while (point == null && offset > stopCriteriumOffset)
{
// Just keep looking by halving the offset until found.
point = FindValidTestPoint(geometryPointString, offset);
offset /= 2.0;
}
+
+ // if no valid point is found (this can happen in case of very thin layer), try using the centroid of the outer loop
+ if (point == null && InnerLoops.Count == 0)
+ {
+ point = Routines2D.ComputeCentroid(geometryPointString.Points);
+ }
return point;
}
Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/Routines2DTests.cs
===================================================================
diff -u
--- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/Routines2DTests.cs (revision 0)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/Routines2DTests.cs (revision 7045)
@@ -0,0 +1,69 @@
+// Copyright (C) Stichting Deltares 2025. All rights reserved.
+//
+// This file is part of the Dam Engine.
+//
+// The Dam Engine is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+// All names, logos, and references to "Deltares" are registered trademarks of
+// Stichting Deltares and remain full property of Stichting Deltares at all times.
+// All rights reserved.
+
+using System.Collections.Generic;
+using Deltares.DamEngine.Data.Geometry;
+using NUnit.Framework;
+
+namespace Deltares.DamEngine.Data.Tests.Geometry;
+
+[TestFixture]
+public class Routines2DTests
+{
+ [Test]
+ public void GivenTriangle_WhenDeterminingTheCentroid_ThenReturnMediansIntersection()
+ {
+ var polygon = new List
+ {
+ new Point2D(-5, -1),
+ new Point2D(3, -1),
+ new Point2D(-1, 5)
+ };
+
+ Point2D centroid = Routines2D.ComputeCentroid(polygon);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(centroid.X, Is.EqualTo(-1));
+ Assert.That(centroid.Z, Is.EqualTo(1));
+ });
+ }
+
+ [Test]
+ public void GivenRectangle_WhenDeterminingTheCentroid_ThenReturnCenter()
+ {
+ var polygon = new List
+ {
+ new Point2D(-5, -1),
+ new Point2D(3, -1),
+ new Point2D(3, 6),
+ new Point2D(-5, 6)
+ };
+
+ Point2D centroid = Routines2D.ComputeCentroid(polygon);
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(centroid.X, Is.EqualTo(-1));
+ Assert.That(centroid.Z, Is.EqualTo(2.5));
+ });
+ }
+}
\ No newline at end of file
Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs
===================================================================
diff -u -r6404 -r7045
--- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs (.../Routines2D.cs) (revision 6404)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/Routines2D.cs (.../Routines2D.cs) (revision 7045)
@@ -294,7 +294,7 @@
al3 = al3 - (2.0 * Math.PI);
}
- if (((Math.PI - al3) < epsilon) || ((Math.PI + al3) < epsilon))
+ if ((Math.PI - al3 < epsilon) || (Math.PI + al3 < epsilon))
{
UndoAddIfNeeded(polygon, pointAdded);
return PointInPolygon.OnPolygonEdge;
@@ -307,7 +307,7 @@
index++;
}
- if ((som > (1.9 * Math.PI)) || (som < (-1.9 * Math.PI)))
+ if ((som > 1.9 * Math.PI) || (som < -1.9 * Math.PI))
{
result = PointInPolygon.InsidePolygon;
}
@@ -359,7 +359,7 @@
if (lD > lAbcEps)
{
double lU = (-lB + Math.Sqrt(lD)) / (2 * lA);
- if ((lU >= -lAbcEps) && (lU <= (1.0 + lAbcEps)))
+ if ((lU >= -lAbcEps) && (lU <= 1.0 + lAbcEps))
{
result.Add(new Point2D
{
@@ -370,7 +370,7 @@
lU = (-lB - Math.Sqrt(lD)) / (2 * lA);
- if ((lU >= -lAbcEps) && (lU <= (1.0 + lAbcEps)))
+ if ((lU >= -lAbcEps) && (lU <= 1.0 + lAbcEps))
{
result.Add(new Point2D
{
@@ -381,7 +381,7 @@
}
else if (Math.Abs(lD) <= lAbcEps)
{
- double lU = (-lB) / (2 * lA);
+ double lU = -lB / (2 * lA);
if ((lU >= -lAbcEps) && (lU <= 1.0 + lAbcEps))
{
result.Add(new Point2D
@@ -444,7 +444,7 @@
///
public static bool AreEqual(double x1, double x2, double tolerance)
{
- return (Math.Abs(x1 - x2) < tolerance);
+ return Math.Abs(x1 - x2) < tolerance;
}
///
@@ -512,7 +512,7 @@
/// true when points coincide
public static bool DetermineIfPointsCoincide(double point1X, double point1Z, double point2X, double point2Z, double tolerance)
{
- if ((Math.Abs(point1X - point2X)) < tolerance && Math.Abs(point1Z - point2Z) < tolerance)
+ if (Math.Abs(point1X - point2X) < tolerance && Math.Abs(point1Z - point2Z) < tolerance)
{
return true;
}
@@ -558,6 +558,32 @@
new Point2D(lineEndX, lineEndY)));
}
+ public static Point2D ComputeCentroid(List polygon)
+ {
+ double accumulatedArea = 0;
+ double centerX = 0;
+ double centerY = 0;
+
+ int count = polygon.Count;
+
+ for (var i = 0; i < count; i++)
+ {
+ Point2D current = polygon[i];
+ Point2D next = polygon[(i + 1) % count];
+
+ double cross = current.X * next.Z - next.X * current.Z;
+ accumulatedArea += cross;
+ centerX += (current.X + next.X) * cross;
+ centerY += (current.Z + next.Z) * cross;
+ }
+
+ accumulatedArea *= 0.5f;
+ centerX /= 6 * accumulatedArea;
+ centerY /= 6 * accumulatedArea;
+
+ return new Point2D(centerX, centerY);
+ }
+
private static void UndoAddIfNeeded(GeometryLoop polygon, bool needed)
{
if (needed)