diff --git a/Triangle.NET/MeshRenderer.Core/ColorManager.cs b/Triangle.NET/MeshRenderer.Core/ColorManager.cs index f2c1577..412c76e 100644 --- a/Triangle.NET/MeshRenderer.Core/ColorManager.cs +++ b/Triangle.NET/MeshRenderer.Core/ColorManager.cs @@ -6,6 +6,14 @@ namespace MeshRenderer.Core { public class ColorManager { + // Change or add as many colors as you like... + private static Color[] regionColors = { + Color.FromArgb(20, 0, 255, 0), + Color.FromArgb(20, 255, 255, 0), + Color.FromArgb(20, 255, 0, 0), + Color.FromArgb(20, 0, 0, 255) + }; + /// /// Gets a color scheme with black background. /// @@ -50,6 +58,70 @@ namespace MeshRenderer.Core internal Pen segment; internal Pen voronoiLine; + internal SolidBrush[] regions; + internal Dictionary regionMap; + + #region Public methods + + /// + /// Setup a region map. + /// + /// Mesh partition (size = number of triangles in mesh) + /// Number of partitions / regions. + public void MakeRegionMap(int[] partition, int size) + { + if (regions == null || regions.Length != size) + { + int n = regionColors.Length; + + regions = new SolidBrush[size]; + + for (int j = 0; j < size; j++) + { + regions[j] = new SolidBrush(regionColors[j % n]); + } + } + + if (regionMap == null) + { + regionMap = new Dictionary(size); + } + else + { + regionMap.Clear(); + } + + int k = 0; + for (int i = 0; i < partition.Length; i++) + { + if (!regionMap.ContainsKey(partition[i])) + { + regionMap.Add(partition[i], k++); + } + } + } + + /// + /// Get the color defined for given region. + /// + public Brush GetRegionBrush(int region) + { + if (regionMap == null) + { + return triangle; + } + + int k; + if (regionMap.TryGetValue(region, out k)) + { + return regions[k]; + } + + return triangle; + } + + #endregion + #region Public properties public Color Background diff --git a/Triangle.NET/MeshRenderer.Core/GDI/MeshRenderer.cs b/Triangle.NET/MeshRenderer.Core/GDI/MeshRenderer.cs index 68ec82a..a196a0e 100644 --- a/Triangle.NET/MeshRenderer.Core/GDI/MeshRenderer.cs +++ b/Triangle.NET/MeshRenderer.Core/GDI/MeshRenderer.cs @@ -28,9 +28,10 @@ namespace MeshRenderer.Core.GDI /// /// Initializes a new instance of the class. /// - public MeshRenderer(RenderData data) + public MeshRenderer(RenderData data, ColorManager renderColors) { this.data = data; + this.renderColors = renderColors; int featureCount = data.Points.Length; @@ -44,23 +45,36 @@ namespace MeshRenderer.Core.GDI } this.ignoreBounds = featureCount < 1000; + + if (data.Triangles != null && data.NumberOfRegions > 0) + { + renderColors.MakeRegionMap(data.TrianglePartition, data.NumberOfRegions); + } } /// /// Renders the mesh. /// - public void Render(Graphics g, Zoom zoom, ColorManager renderColors) + public void Render(Graphics g, Zoom zoom) + { + Render(g, zoom, false); + } + + /// + /// Renders the mesh. + /// + public void Render(Graphics g, Zoom zoom, bool fillTriangles) { - this.renderColors = renderColors; this.zoom = zoom; - if (data.MeshEdges != null) + if (data.MeshEdges != null && !fillTriangles) { this.RenderEdges(g); } - else if (data.Triangles != null) + + if (fillTriangles && data.Triangles != null) { - this.RenderTriangles(g); + this.RenderTriangles(g, fillTriangles && (data.NumberOfRegions > 0)); } if (data.Segments != null) @@ -77,9 +91,8 @@ namespace MeshRenderer.Core.GDI /// /// Renders only the mesh edges (no points or segments). /// - public void RenderMesh(Graphics g, Zoom zoom, ColorManager renderColors) + public void RenderMesh(Graphics g, Zoom zoom) { - this.renderColors = renderColors; this.zoom = zoom; if (data.MeshEdges != null) @@ -88,16 +101,15 @@ namespace MeshRenderer.Core.GDI } else if (data.Triangles != null) { - this.RenderTriangles(g); + this.RenderTriangles(g, false); } } /// /// Renders only points and segments (no mesh triangles). /// - public void RenderGeometry(Graphics g, Zoom zoom, ColorManager renderColors) + public void RenderGeometry(Graphics g, Zoom zoom) { - this.renderColors = renderColors; this.zoom = zoom; if (data.Segments != null) @@ -142,11 +154,11 @@ namespace MeshRenderer.Core.GDI } } - private void RenderTriangles(Graphics g) + private void RenderTriangles(Graphics g, bool fillTriangles) { int n = data.Triangles.Length / 3; uint k0, k1, k2; - PointF p0, p1, p2; + PointF[] tri = new PointF[3]; float[] pts = data.Points; // Draw triangles @@ -161,13 +173,16 @@ namespace MeshRenderer.Core.GDI zoom.ViewportContains(pts[k1], pts[k1 + 1]) || zoom.ViewportContains(pts[k2], pts[k2 + 1]))) { - p0 = zoom.WorldToScreen(pts[k0], pts[k0 + 1]); - p1 = zoom.WorldToScreen(pts[k1], pts[k1 + 1]); - p2 = zoom.WorldToScreen(pts[k2], pts[k2 + 1]); + tri[0] = zoom.WorldToScreen(pts[k0], pts[k0 + 1]); + tri[1] = zoom.WorldToScreen(pts[k1], pts[k1 + 1]); + tri[2] = zoom.WorldToScreen(pts[k2], pts[k2 + 1]); - g.DrawLine(renderColors.Line, p0, p1); - g.DrawLine(renderColors.Line, p1, p2); - g.DrawLine(renderColors.Line, p2, p0); + g.DrawPolygon(renderColors.Line, tri); + + if (fillTriangles) + { + g.FillPolygon(renderColors.GetRegionBrush(data.TrianglePartition[i]), tri); + } } } } diff --git a/Triangle.NET/MeshRenderer.Core/GDI/RenderControl.cs b/Triangle.NET/MeshRenderer.Core/GDI/RenderControl.cs index 9c22657..bf64193 100644 --- a/Triangle.NET/MeshRenderer.Core/GDI/RenderControl.cs +++ b/Triangle.NET/MeshRenderer.Core/GDI/RenderControl.cs @@ -33,6 +33,7 @@ namespace MeshRenderer.Core.GDI bool initialized = false; bool showVoronoi = false; + bool showRegions = true; string coordinate = String.Empty; @@ -71,6 +72,32 @@ namespace MeshRenderer.Core.GDI }; } + public bool ShowVoronoi + { + get { return showVoronoi; } + set + { + if (showVoronoi != value) + { + this.Render(); + } + showVoronoi = value; + } + } + + public bool ShowRegions + { + get { return showRegions; } + set + { + if (showRegions != value) + { + this.Render(); + } + showRegions = value; + } + } + /// /// Initialize the graphics buffer (should be called in the forms load event). /// @@ -91,7 +118,7 @@ namespace MeshRenderer.Core.GDI { this.data = data; - meshRenderer = new MeshRenderer(data); + meshRenderer = new MeshRenderer(data, renderColors); this.showVoronoi = data.VoronoiPoints != null; @@ -181,13 +208,13 @@ namespace MeshRenderer.Core.GDI if (voronoiRenderer != null && this.showVoronoi) { - meshRenderer.RenderMesh(g, zoom, renderColors); + meshRenderer.RenderMesh(g, zoom); voronoiRenderer.Render(g, zoom, renderColors); - meshRenderer.RenderGeometry(g, zoom, renderColors); + meshRenderer.RenderGeometry(g, zoom); } else if (meshRenderer != null) { - meshRenderer.Render(g, zoom, renderColors); + meshRenderer.Render(g, zoom, showRegions); } this.Invalidate(); diff --git a/Triangle.NET/MeshRenderer.Core/IMeshRenderer.cs b/Triangle.NET/MeshRenderer.Core/IMeshRenderer.cs index ce7030b..bc32f56 100644 --- a/Triangle.NET/MeshRenderer.Core/IMeshRenderer.cs +++ b/Triangle.NET/MeshRenderer.Core/IMeshRenderer.cs @@ -13,6 +13,9 @@ namespace MeshRenderer.Core /// public interface IMeshRenderer { + bool ShowVoronoi { get; set; } + bool ShowRegions { get; set; } + void Zoom(float x, float y, int delta); void HandleResize(); diff --git a/Triangle.NET/MeshRenderer.Core/RenderData.cs b/Triangle.NET/MeshRenderer.Core/RenderData.cs index 953476a..7fc60fb 100644 --- a/Triangle.NET/MeshRenderer.Core/RenderData.cs +++ b/Triangle.NET/MeshRenderer.Core/RenderData.cs @@ -7,7 +7,6 @@ namespace MeshRenderer.Core { using System.Collections.Generic; - using System.Linq; using TriangleNet; using TriangleNet.Geometry; using TriangleNet.Tools; @@ -23,7 +22,9 @@ namespace MeshRenderer.Core public uint[] MeshEdges; public float[] VoronoiPoints; public uint[] VoronoiEdges; + public int[] TrianglePartition; + public int NumberOfRegions; public int NumberOfInputPoints; public BoundingBox Bounds; @@ -42,6 +43,7 @@ namespace MeshRenderer.Core int n = data.Count; int i = 0; + this.NumberOfRegions = data.Regions.Count; this.NumberOfInputPoints = n; // Copy points @@ -124,6 +126,14 @@ namespace MeshRenderer.Core } this.MeshEdges = edges.ToArray(); + + if (this.NumberOfRegions > 0) + { + this.TrianglePartition = new int[mesh.Triangles.Count]; + } + + i = 0; + // Copy Triangles var triangles = new List(3 * mesh.Triangles.Count); foreach (var tri in mesh.Triangles) @@ -131,6 +141,11 @@ namespace MeshRenderer.Core triangles.Add((uint)tri.P0); triangles.Add((uint)tri.P1); triangles.Add((uint)tri.P2); + + if (this.NumberOfRegions > 0) + { + this.TrianglePartition[i++] = tri.Region; + } } this.Triangles = triangles.ToArray(); diff --git a/Triangle.NET/MeshRenderer.Core/RenderManager.cs b/Triangle.NET/MeshRenderer.Core/RenderManager.cs index 7bbf7e2..8727a3a 100644 --- a/Triangle.NET/MeshRenderer.Core/RenderManager.cs +++ b/Triangle.NET/MeshRenderer.Core/RenderManager.cs @@ -31,6 +31,18 @@ namespace MeshRenderer.Core } } + public bool ShowVoronoi + { + get { return renderer.ShowVoronoi; } + set { renderer.ShowVoronoi = value; } + } + + public bool ShowRegions + { + get { return renderer.ShowRegions; } + set { renderer.ShowRegions = value; } + } + public void Initialize() { renderer.Initialize(); diff --git a/Triangle.NET/TestApp/IO/RasterImage.cs b/Triangle.NET/TestApp/IO/RasterImage.cs index 9da32e5..bb51b5e 100644 --- a/Triangle.NET/TestApp/IO/RasterImage.cs +++ b/Triangle.NET/TestApp/IO/RasterImage.cs @@ -84,8 +84,8 @@ namespace MeshExplorer.IO g.SmoothingMode = SmoothingMode.HighQuality; - MeshRenderer meshRenderer = new MeshRenderer(data); - meshRenderer.Render(g, zoom, colors); + MeshRenderer meshRenderer = new MeshRenderer(data, colors); + meshRenderer.Render(g, zoom); g.Dispose(); } diff --git a/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs index 585f33d..1a19466 100644 --- a/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs +++ b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs @@ -95,6 +95,11 @@ namespace TriangleNet.Smoothing geometry.AddHole(hole.x, hole.y); } + foreach (var region in mesh.regions) + { + geometry.AddRegion(region.point.x, region.point.y, region.id); + } + return geometry; } }