From 4dccadc2462a56e4d012173c19692a200a74a33c Mon Sep 17 00:00:00 2001 From: "SND\\wo80_cp" Date: Fri, 26 Oct 2012 14:44:56 +0000 Subject: [PATCH] Added edges property to mesh, Added a simple mesh smoother git-svn-id: https://triangle.svn.codeplex.com/svn@70496 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5 --- Triangle.NET/TestApp/FormGenerator.cs | 1 + Triangle.NET/TestApp/FormLog.Designer.cs | 1 + Triangle.NET/TestApp/FormLog.cs | 12 ++ Triangle.NET/TestApp/FormLog.resx | 120 +++++++++++++ Triangle.NET/TestApp/FormMain.cs | 6 +- .../TestApp/Generators/BoxWithHole.cs | 163 ++++++++++++++++++ Triangle.NET/TestApp/Mesh Explorer.csproj | 4 + Triangle.NET/Triangle/Mesh.cs | 19 +- .../Triangle/Smoothing/SimpleSmoother.cs | 98 +++++++++++ Triangle.NET/Triangle/Tools/BoundedVoronoi.cs | 18 +- Triangle.NET/Triangle/Tools/IVoronoi.cs | 4 +- Triangle.NET/Triangle/Tools/Voronoi.cs | 4 +- Triangle.NET/Triangle/Triangle.csproj | 1 + 13 files changed, 439 insertions(+), 12 deletions(-) create mode 100644 Triangle.NET/TestApp/FormLog.resx create mode 100644 Triangle.NET/TestApp/Generators/BoxWithHole.cs create mode 100644 Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs diff --git a/Triangle.NET/TestApp/FormGenerator.cs b/Triangle.NET/TestApp/FormGenerator.cs index 213f9e0..6bd8356 100644 --- a/Triangle.NET/TestApp/FormGenerator.cs +++ b/Triangle.NET/TestApp/FormGenerator.cs @@ -134,6 +134,7 @@ namespace MeshExplorer darkListBox1.Items.Add(new RandomPointsCircle()); darkListBox1.Items.Add(new StarInBox()); darkListBox1.Items.Add(new RingPolygon()); + darkListBox1.Items.Add(new BoxWithHole()); darkListBox1.SelectedIndex = 0; } diff --git a/Triangle.NET/TestApp/FormLog.Designer.cs b/Triangle.NET/TestApp/FormLog.Designer.cs index 0e3347e..f680174 100644 --- a/Triangle.NET/TestApp/FormLog.Designer.cs +++ b/Triangle.NET/TestApp/FormLog.Designer.cs @@ -51,6 +51,7 @@ this.listLog.UseCompatibleStateImageBehavior = false; this.listLog.View = System.Windows.Forms.View.Details; this.listLog.DoubleClick += new System.EventHandler(this.listLog_DoubleClick); + this.listLog.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listLog_KeyDown); // // colMessage // diff --git a/Triangle.NET/TestApp/FormLog.cs b/Triangle.NET/TestApp/FormLog.cs index d54ab91..32df43a 100644 --- a/Triangle.NET/TestApp/FormLog.cs +++ b/Triangle.NET/TestApp/FormLog.cs @@ -74,6 +74,18 @@ namespace MeshExplorer } } + private void listLog_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Delete) + { + if (ModifierKeys == Keys.Control) + { + listLog.Items.Clear(); + SimpleLog.Instance.Clear(); + } + } + } + private void listLog_DoubleClick(object sender, EventArgs e) { StringBuilder sb = new StringBuilder(); diff --git a/Triangle.NET/TestApp/FormLog.resx b/Triangle.NET/TestApp/FormLog.resx new file mode 100644 index 0000000..29dcb1b --- /dev/null +++ b/Triangle.NET/TestApp/FormLog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Triangle.NET/TestApp/FormMain.cs b/Triangle.NET/TestApp/FormMain.cs index 00c6f47..240964c 100644 --- a/Triangle.NET/TestApp/FormMain.cs +++ b/Triangle.NET/TestApp/FormMain.cs @@ -289,7 +289,7 @@ namespace MeshExplorer // Update Statistic view statisticView.HandleMeshChange(mesh); - // TODO: Should the Voronoi diagram automaticaly update? + // TODO: Should the Voronoi diagram automatically update? menuViewVoronoi.Checked = false; // Enable menu items @@ -534,7 +534,7 @@ namespace MeshExplorer statisticView.UpdateStatistic(mesh); - HandleMeshChange(); + HandleMeshUpdate(); } catch (Exception ex) { @@ -650,8 +650,6 @@ namespace MeshExplorer voronoi = new Voronoi(mesh); } - voronoi.Generate(); - renderData.SetVoronoi(voronoi); renderManager.SetData(renderData); diff --git a/Triangle.NET/TestApp/Generators/BoxWithHole.cs b/Triangle.NET/TestApp/Generators/BoxWithHole.cs new file mode 100644 index 0000000..6424e9c --- /dev/null +++ b/Triangle.NET/TestApp/Generators/BoxWithHole.cs @@ -0,0 +1,163 @@ +// ----------------------------------------------------------------------- +// +// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/ +// +// ----------------------------------------------------------------------- + +namespace MeshExplorer.Generators +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using TriangleNet.Geometry; + + /// + /// Generates a star contained in a box. + /// + public class BoxWithHole : IGenerator + { + public string Name + { + get { return "Box with Hole"; } + } + + public string Description + { + get { return ""; } + } + + public int ParameterCount + { + get { return 3; } + } + + public string ParameterDescription(int paramIndex) + { + if (paramIndex == 1) + { + return "Points on box sides:"; + } + + if (paramIndex == 2) + { + return "Points on hole:"; + } + + if (paramIndex == 3) + { + return "Radius:"; + } + + return ""; + } + + public string ParameterDescription(int paramIndex, double paramValue) + { + if (paramIndex == 1) + { + int numPoints = (int)((50.0 - 5.0) / 100.0 * paramValue + 5.0); + + if (numPoints < 5) + { + numPoints = 5; + } + + return numPoints.ToString(); + } + + if (paramIndex == 2) + { + int numPoints = (int)((100.0 - 10.0) / 100.0 * paramValue + 10.0); + numPoints = (numPoints / 5) * 5; + + if (numPoints < 10) + { + numPoints = 10; + } + + return numPoints.ToString(); + } + + if (paramIndex == 3) + { + int radius = (int)((20.0 - 5.0) / 100.0 * paramValue + 5.0); + + return radius.ToString(); + } + + return ""; + } + + public InputGeometry Generate(double param1, double param2, double param3) + { + int numPoints = (int)((100.0 - 10.0) / 100.0 * param2 + 10.0); + + InputGeometry input = new InputGeometry(numPoints + 4); + + double x, y, step = 2 * Math.PI / numPoints; + + double r = (int)((20.0 - 5.0) / 100.0 * param3 + 5.0); + + // Generate circle + for (int i = 0; i < numPoints; i++) + { + x = r * Math.Cos(i * step); + y = r * Math.Sin(i * step); + + input.AddPoint(x, y, 2); + input.AddSegment(i, (i + 1) % numPoints, 2); + } + + numPoints = input.Count; + + int numPointsB = (int)((50.0 - 5.0) / 100.0 * param1 + 5.0); + + // Box sides are 100 units long + step = 100.0 / numPointsB; + + // Left box boundary points + for (int i = 0; i < numPointsB; i++) + { + input.AddPoint(-50, -50 + i * step, 1); + } + + // Top box boundary points + for (int i = 0; i < numPointsB; i++) + { + input.AddPoint(-50 + i * step, 50, 1); + } + + // Right box boundary points + for (int i = 0; i < numPointsB; i++) + { + input.AddPoint(50, 50 - i * step, 1); + } + + // Bottom box boundary points + for (int i = 0; i < numPointsB; i++) + { + input.AddPoint(50 - i * step, -50, 1); + } + + // Add box segments + for (int i = numPoints; i < input.Count - 1; i++) + { + input.AddSegment(i, i + 1, 1); + } + + // Add last segments which closes the box + input.AddSegment(input.Count - 1, numPoints, 1); + + // Add hole + input.AddHole(0, 0); + + return input; + } + + public override string ToString() + { + return this.Name; + } + } +} diff --git a/Triangle.NET/TestApp/Mesh Explorer.csproj b/Triangle.NET/TestApp/Mesh Explorer.csproj index 1645317..3845269 100644 --- a/Triangle.NET/TestApp/Mesh Explorer.csproj +++ b/Triangle.NET/TestApp/Mesh Explorer.csproj @@ -96,6 +96,7 @@ FormMain.cs + @@ -138,6 +139,9 @@ FormGenerator.cs + + FormLog.cs + FormMain.cs diff --git a/Triangle.NET/Triangle/Mesh.cs b/Triangle.NET/Triangle/Mesh.cs index 0d3214b..ad24ec5 100644 --- a/Triangle.NET/Triangle/Mesh.cs +++ b/Triangle.NET/Triangle/Mesh.cs @@ -129,6 +129,21 @@ namespace TriangleNet get { return this.subsegs.Values; } } + /// + /// Gets the mesh edges. + /// + public IEnumerable Edges + { + get + { + EdgeEnumerator e = new EdgeEnumerator(this); + while (e.MoveNext()) + { + yield return e.Current; + } + } + } + /// /// Gets the number of input vertices. /// @@ -457,8 +472,8 @@ namespace TriangleNet { numbering = NodeNumbering.None; - //ISmoother smoother = new CvdSmoother(this); - //smoother.Smooth(); + ISmoother smoother = new SimpleSmoother(this); + smoother.Smooth(); } /// diff --git a/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs new file mode 100644 index 0000000..77e4bdd --- /dev/null +++ b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs @@ -0,0 +1,98 @@ +// ----------------------------------------------------------------------- +// +// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/ +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.Smoothing +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using TriangleNet.Geometry; + using TriangleNet.Tools; + + /// + /// Simple mesh smoother implementation. + /// + public class SimpleSmoother : ISmoother + { + Mesh mesh; + + public SimpleSmoother(Mesh mesh) + { + this.mesh = mesh; + } + + public void Smooth() + { + // Take a few smoothing rounds. + for (int i = 0; i < 5; i++) + { + Step(); + + // Actually, we only want to rebuild, if mesh is no longer + // Delaunay. Flipping edges could be the right choice instead + // of re-triangulating... + var geometry = Rebuild(); + + mesh.SetOption(Options.Quality, false); + mesh.Triangulate(geometry); + } + } + + /// + /// Smooth all free nodes. + /// + private void Step() + { + BoundedVoronoi voronoi = new BoundedVoronoi(this.mesh, false); + + var cells = voronoi.Regions; + + double x, y; + int n; + + foreach (var cell in cells) + { + n = 0; + x = y = 0.0; + foreach (var p in cell.Vertices) + { + n++; + x += p.x; + y += p.y; + } + + cell.Generator.x = x / n; + cell.Generator.y = y / n; + } + } + + /// + /// Rebuild the input geometry. + /// + private InputGeometry Rebuild() + { + InputGeometry geometry = new InputGeometry(mesh.vertices.Count); + + foreach (var vertex in mesh.vertices.Values) + { + geometry.AddPoint(vertex.x, vertex.y, vertex.mark); + } + + foreach (var segment in mesh.subsegs.Values) + { + geometry.AddSegment(segment.P0, segment.P1, segment.Boundary); + } + + foreach (var hole in mesh.holes) + { + geometry.AddHole(hole.x, hole.y); + } + + return geometry; + } + } +} diff --git a/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs b/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs index 3bce64f..5b357e0 100644 --- a/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs +++ b/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs @@ -31,13 +31,27 @@ namespace TriangleNet.Tools Dictionary subsegMap; + bool includeBoundary = true; + /// /// Initializes a new instance of the class. /// /// Mesh instance. public BoundedVoronoi(Mesh mesh) + : this(mesh, true) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Mesh instance. + public BoundedVoronoi(Mesh mesh, bool includeBoundary) { this.mesh = mesh; + this.includeBoundary = includeBoundary; + + Generate(); } /// @@ -59,7 +73,7 @@ namespace TriangleNet.Tools /// /// Computes the bounded voronoi diagram. /// - public void Generate() + private void Generate() { mesh.Renumber(); mesh.MakeVertexMap(); @@ -79,7 +93,7 @@ namespace TriangleNet.Tools { ConstructBvdCell(v); } - else + else if (includeBoundary) { ConstructBoundaryBvdCell(v); } diff --git a/Triangle.NET/Triangle/Tools/IVoronoi.cs b/Triangle.NET/Triangle/Tools/IVoronoi.cs index ca63f50..591efad 100644 --- a/Triangle.NET/Triangle/Tools/IVoronoi.cs +++ b/Triangle.NET/Triangle/Tools/IVoronoi.cs @@ -20,10 +20,8 @@ namespace TriangleNet.Tools Point[] Points { get; } /// - /// Gets the directions for infinite Voronoi edges. + /// Gets the list of Voronoi regions. /// List Regions { get; } - - void Generate(); } } diff --git a/Triangle.NET/Triangle/Tools/Voronoi.cs b/Triangle.NET/Triangle/Tools/Voronoi.cs index 370cd0f..c1e6919 100644 --- a/Triangle.NET/Triangle/Tools/Voronoi.cs +++ b/Triangle.NET/Triangle/Tools/Voronoi.cs @@ -34,6 +34,8 @@ namespace TriangleNet.Tools public Voronoi(Mesh mesh) { this.mesh = mesh; + + Generate(); } /// @@ -63,7 +65,7 @@ namespace TriangleNet.Tools /// triangles, and the Voronoi edges are listed by traversing the Delaunay /// edges. /// - public void Generate() + private void Generate() { mesh.Renumber(); mesh.MakeVertexMap(); diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj index 7b9aad5..35c3610 100644 --- a/Triangle.NET/Triangle/Triangle.csproj +++ b/Triangle.NET/Triangle/Triangle.csproj @@ -81,6 +81,7 @@ +