diff --git a/src/Triangle/Geometry/ExtensionMethods.cs b/src/Triangle/Geometry/ExtensionMethods.cs index fae7666..1874068 100644 --- a/src/Triangle/Geometry/ExtensionMethods.cs +++ b/src/Triangle/Geometry/ExtensionMethods.cs @@ -1,7 +1,7 @@  namespace TriangleNet.Geometry { - using System; + using System.Threading; using TriangleNet.Meshing; /// @@ -34,9 +34,10 @@ public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options /// /// Polygon instance. /// Quality options. - public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality) + /// A token that receives a cancellation notification when requested. + public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality, CancellationToken cancellationToken = default) { - return (new GenericMesher()).Triangulate(polygon, null, quality); + return (new GenericMesher()).Triangulate(polygon, null, quality, cancellationToken); } /// @@ -45,9 +46,10 @@ public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality) /// Polygon instance. /// Constraint options. /// Quality options. - public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality) + /// A token that receives a cancellation notification when requested. + public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality, CancellationToken cancellationToken = default) { - return (new GenericMesher()).Triangulate(polygon, options, quality); + return (new GenericMesher()).Triangulate(polygon, options, quality, cancellationToken); } /// diff --git a/src/Triangle/Mesh.cs b/src/Triangle/Mesh.cs index 0c0be46..eb012ea 100644 --- a/src/Triangle/Mesh.cs +++ b/src/Triangle/Mesh.cs @@ -9,6 +9,7 @@ namespace TriangleNet { using System; using System.Collections.Generic; + using System.Threading; using TriangleNet.Geometry; using TriangleNet.Meshing; using TriangleNet.Meshing.Data; @@ -224,7 +225,8 @@ public Mesh(Configuration config, IList points) /// /// The quality constraints. /// A value indicating, whether the refined mesh should be Conforming Delaunay. - public void Refine(QualityOptions quality, bool delaunay = false) + /// A token that receives a cancellation notification when requested. + public void Refine(QualityOptions quality, bool delaunay = false, CancellationToken cancellationToken = default) { invertices = vertices.Count; @@ -241,7 +243,7 @@ public void Refine(QualityOptions quality, bool delaunay = false) } // Enforce angle and area constraints. - qualityMesher.Apply(quality, delaunay); + qualityMesher.Apply(quality, delaunay, cancellationToken); } /// diff --git a/src/Triangle/Meshing/GenericMesher.cs b/src/Triangle/Meshing/GenericMesher.cs index d46080c..83cd60e 100644 --- a/src/Triangle/Meshing/GenericMesher.cs +++ b/src/Triangle/Meshing/GenericMesher.cs @@ -8,6 +8,7 @@ namespace TriangleNet.Meshing { using System; using System.Collections.Generic; + using System.Threading; using TriangleNet.Geometry; using TriangleNet.IO; using TriangleNet.Meshing.Algorithm; @@ -96,10 +97,11 @@ public IMesh Triangulate(IPolygon polygon, ConstraintOptions options) /// /// The input polygon. /// The . + /// A token that receives a cancellation notification when requested. /// The mesh. - public IMesh Triangulate(IPolygon polygon, QualityOptions quality) + public IMesh Triangulate(IPolygon polygon, QualityOptions quality, CancellationToken cancellationToken = default) { - return Triangulate(polygon, null, quality); + return Triangulate(polygon, null, quality, cancellationToken); } /// @@ -108,8 +110,9 @@ public IMesh Triangulate(IPolygon polygon, QualityOptions quality) /// The input polygon. /// The . /// The . + /// A token that receives a cancellation notification when requested. /// The mesh. - public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality) + public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality, CancellationToken cancellationToken = default) { var mesh = (Mesh)triangulator.Triangulate(polygon.Points, config); @@ -122,7 +125,7 @@ public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOpt cmesher.Apply(polygon, options); // Refine mesh. - qmesher.Apply(quality); + qmesher.Apply(quality, options?.ConformingDelaunay ?? false, cancellationToken); return mesh; } diff --git a/src/Triangle/Meshing/IMesh.cs b/src/Triangle/Meshing/IMesh.cs index b1be86b..20d579a 100644 --- a/src/Triangle/Meshing/IMesh.cs +++ b/src/Triangle/Meshing/IMesh.cs @@ -2,6 +2,7 @@ namespace TriangleNet.Meshing { using System.Collections.Generic; + using System.Threading; using TriangleNet.Topology; using TriangleNet.Geometry; @@ -49,9 +50,8 @@ public interface IMesh /// Refine the mesh. /// /// The quality constraints. - /// - /// A value indicating, whether the refined mesh should be Conforming Delaunay. - /// - void Refine(QualityOptions quality, bool delaunay); + /// A value indicating, whether the refined mesh should be Conforming Delaunay. + /// A token that receives a cancellation notification when requested. + void Refine(QualityOptions quality, bool delaunay, CancellationToken cancellationToken = default); } } diff --git a/src/Triangle/Meshing/QualityMesher.cs b/src/Triangle/Meshing/QualityMesher.cs index dfa19ec..7a97565 100644 --- a/src/Triangle/Meshing/QualityMesher.cs +++ b/src/Triangle/Meshing/QualityMesher.cs @@ -9,6 +9,7 @@ namespace TriangleNet.Meshing { using System; using System.Collections.Generic; + using System.Threading; using TriangleNet.Geometry; using TriangleNet.Meshing.Data; using TriangleNet.Topology; @@ -55,7 +56,8 @@ public QualityMesher(Mesh mesh, Configuration config) /// /// The quality constraints. /// A value indicating, whether the refined mesh should be Conforming Delaunay. - public void Apply(QualityOptions quality, bool delaunay = false) + /// A token that receives a cancellation notification when requested. + public void Apply(QualityOptions quality, bool delaunay = false, CancellationToken cancellationToken = default) { // Copy quality options if (quality != null) @@ -98,7 +100,7 @@ public void Apply(QualityOptions quality, bool delaunay = false) if (behavior.Quality && mesh.triangles.Count > 0) { // Enforce angle and area constraints. - EnforceQuality(); + EnforceQuality(cancellationToken); } } @@ -841,7 +843,7 @@ private void SplitTriangle(BadTriangle badtri) /// /// Remove all the encroached subsegments and bad triangles from the triangulation. /// - private void EnforceQuality() + private void EnforceQuality(CancellationToken cancellationToken) { BadTriangle badtri; @@ -864,6 +866,9 @@ private void EnforceQuality() mesh.checkquality = true; while ((queue.Count > 0) && (mesh.steinerleft != 0)) { + // throw an OperationCanceledException if cancellation is requested + cancellationToken.ThrowIfCancellationRequested(); + // Fix one bad triangle by inserting a vertex at its circumcenter. badtri = queue.Dequeue(); SplitTriangle(badtri); diff --git a/src/Triangle/Smoothing/SimpleSmoother.cs b/src/Triangle/Smoothing/SimpleSmoother.cs index a0f6fc2..30e4b05 100644 --- a/src/Triangle/Smoothing/SimpleSmoother.cs +++ b/src/Triangle/Smoothing/SimpleSmoother.cs @@ -5,6 +5,7 @@ // ----------------------------------------------------------------------- using System; +using System.Threading; namespace TriangleNet.Smoothing { @@ -77,11 +78,12 @@ public SimpleSmoother(IVoronoiFactory factory, Configuration config) /// the previous and the current solutions. If their relative difference /// is not greater than the tolerance, the current solution is /// considered good enough already. + /// A token that receives a cancellation notification when requested. /// The number of actual iterations performed. It is 0 if a /// non-positive limit is passed. Otherwise, it is always a value /// between 1 and the limit (inclusive). /// - public int Smooth(IMesh mesh, int limit = 10, double tol = .01) + public int Smooth(IMesh mesh, int limit = 10, double tol = .01, CancellationToken cancellationToken = default) { if (limit <= 0) return 0; @@ -106,6 +108,9 @@ public int Smooth(IMesh mesh, int limit = 10, double tol = .01) int i = 0; while (i < limit && Math.Abs(currMax - prevMax) > tol * currMax) { + // throw an OperationCanceledException if cancellation is requested + cancellationToken.ThrowIfCancellationRequested(); + prevMax = currMax; currMax = Step(smoothedMesh, factory, predicates);