public static string RunSequential(List <IPolygon> polygons) { var pool = new TrianglePool(); var predicates = new RobustPredicates(); var config = new Configuration(); config.Predicates = () => predicates; config.TrianglePool = () => pool.Restart(); var mesher = new GenericMesher(config); var result = new MeshResult(); foreach (var poly in polygons) { var mesh = mesher.Triangulate(poly); ProcessMesh(mesh, result); } pool.Clear(); //Console.WriteLine("Total number of triangles processed: {0}", result.NumberOfTriangles); var sequential = $"Total number of triangles processed: {result.NumberOfTriangles}"; if (result.Invalid > 0) { //Console.WriteLine(" Number of invalid triangulations: {0}", result.Invalid); sequential += $"Number of invalid triangulations: {result.Invalid}"; } return(sequential); }
/// <summary> /// Reads all .poly files from given directory and processes them in parallel. /// </summary> public static bool Run(string dir) { var files = Directory.EnumerateFiles(dir, "*.poly", SearchOption.AllDirectories); var queue = new ConcurrentQueue <string>(files); int concurrencyLevel = Environment.ProcessorCount / 2; var tasks = new Task <MeshResult> [concurrencyLevel]; for (int i = 0; i < concurrencyLevel; i++) { tasks[i] = Task.Run(() => { // Each task has it's own triangle pool and predicates instance. var pool = new TrianglePool(); var predicates = new RobustPredicates(); // The factory methods return the above instances. var config = new Configuration() { Predicates = () => predicates, TrianglePool = () => pool.Restart(), RandomSource = () => Random.Shared }; var mesher = new GenericMesher(config); var result = new MeshResult(); while (queue.Count > 0) { if (queue.TryDequeue(out var file)) { var poly = FileProcessor.Read(file); var mesh = mesher.Triangulate(poly); ProcessMesh(mesh, result); } } pool.Clear(); return(result); }); } Task.WaitAll(tasks); int numberOfTriangles = tasks.Sum(t => t.Result.NumberOfTriangles); int invalid = tasks.Sum(t => t.Result.Invalid); Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles); if (invalid > 0) { Console.WriteLine(" Number of invalid triangulations: {0}", invalid); } return(invalid == 0); }
/// <summary> /// Triangulate a given number of random point sets in parallel. /// </summary> public static bool Run(int n = 1000) { // Use thread-safe random source. var random = Random.Shared; // Generate a random set of sizes. var sizes = Enumerable.Range(0, n).Select(_ => random.Next(500, 5000)); var queue = new ConcurrentQueue <int>(sizes); int concurrencyLevel = Environment.ProcessorCount / 2; var tasks = new Task <MeshResult> [concurrencyLevel]; for (int i = 0; i < concurrencyLevel; i++) { tasks[i] = Task.Run(() => { // Each task has it's own triangle pool and predicates instance. var pool = new TrianglePool(); var predicates = new RobustPredicates(); // The factory methods return the above instances. var config = new Configuration() { Predicates = () => predicates, TrianglePool = () => pool.Restart(), RandomSource = () => Random.Shared }; var triangulator = new Dwyer(); var result = new MeshResult(); var bounds = new Rectangle(0d, 0d, 1000d, 1000d); while (queue.Count > 0) { if (queue.TryDequeue(out int size)) { var points = Generate.RandomPoints(size, bounds); var mesh = triangulator.Triangulate(points, config); ProcessMesh(mesh, result); } } pool.Clear(); return(result); }); } Task.WaitAll(tasks); int numberOfTriangles = tasks.Sum(t => t.Result.NumberOfTriangles); int invalid = tasks.Sum(t => t.Result.Invalid); Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles); if (invalid > 0) { Console.WriteLine(" Number of invalid triangulations: {0}", invalid); } return(invalid == 0); }
public static string RunParallel(List <IPolygon> polygons) { var queue = new ConcurrentQueue <IPolygon>(polygons); int concurrencyLevel = Environment.ProcessorCount; var tasks = new Task <MeshResult> [concurrencyLevel]; for (int i = 0; i < concurrencyLevel; i++) { tasks[i] = Task.Run(() => { // Each task has it's own triangle pool and predicates instance. var pool = new TrianglePool(); var predicates = new RobustPredicates(); var config = new Configuration(); // The factory methods return the above instances. config.Predicates = () => predicates; config.TrianglePool = () => pool.Restart(); IPolygon poly; var mesher = new GenericMesher(config); var result = new MeshResult(); while (queue.Count > 0) { if (queue.TryDequeue(out poly)) { var mesh = mesher.Triangulate(poly); ProcessMesh(mesh, result); } } pool.Clear(); return(result); }); } Task.WaitAll(tasks); int numberOfTriangles = 0; int invalid = 0; for (int i = 0; i < concurrencyLevel; i++) { var result = tasks[i].Result; numberOfTriangles += result.NumberOfTriangles; invalid += result.Invalid; } string parallel = $"Total number of triangles processed: {numberOfTriangles}"; //Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles); if (invalid > 0) { //Console.WriteLine(" Number of invalid triangulations: {0}", invalid); parallel += $"\tNumber of invalid triangulations: {invalid}"; } return(parallel); }
/* loop through each point to add, brute force search through each triangle, if * the point is contained in the triangle's circumcircle remove it. Create a polygon with * each removed triangle's outer edge, and add the triangles made by linking each edge to * the new point */ private void Triangulate() { triangulation.Clear(); trianglePool.Clear(); // first triangle, containing the whole playground superTriangle = trianglePool.Get(); superTriangle.Populate(new Vector2(-halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(0.0f, halfHeight * 3 * scalePlayground)); triangulation.Add(superTriangle); List <Triangle> badTriangles = new List <Triangle>(); List <Edge> polygon = new List <Edge>(); for (int i = 0; i < points.Count; i++) { Vector2 point = points[i].position; badTriangles.Clear(); polygon.Clear(); // check if the triangle contains point in its circumcircle foreach (Triangle triangle in triangulation) { if (triangle.isPointInsideCircumcircle(point)) { badTriangles.Add(triangle); } } // create the outer polygon for (int outer = 0; outer < badTriangles.Count; outer++) { for (int edge = 0; edge < 3; edge++) { bool isShared = false; for (int inner = 0; inner < badTriangles.Count; inner++) { if (inner != outer && !isShared) { for (int badEdge = 0; badEdge < 3; badEdge++) { if (badTriangles[outer].edges[edge].Compare(badTriangles[inner].edges[badEdge])) { isShared = true; } } } } if (!isShared) { polygon.Add(badTriangles[outer].edges[edge]); } } } // remove bad triangles for (int j = 0; j < badTriangles.Count; j++) { trianglePool.Remove(badTriangles[j]); triangulation.Remove(badTriangles[j]); } // create new triangles for (int j = 0; j < polygon.Count; j++) { Triangle thisTriangle = trianglePool.Get(); thisTriangle.Populate(polygon[j].A, polygon[j].B, point); triangulation.Add(thisTriangle); } } }