Make fixed vertex ids work (changed IPolygon interface)
git-svn-id: https://triangle.svn.codeplex.com/svn@77167 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
@@ -54,15 +55,19 @@ namespace MeshExplorer.Generators
|
||||
double ro, r = 10;
|
||||
double step = 2 * Math.PI / m;
|
||||
|
||||
var inner = new List<Vertex>(m);
|
||||
|
||||
// Inner ring
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
input.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
|
||||
input.Add(new Edge(i, (i + 1) % m, 1));
|
||||
inner.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
|
||||
}
|
||||
|
||||
input.AddContour(inner, 1);
|
||||
|
||||
r = 1.5 * r;
|
||||
|
||||
var outer = new List<Vertex>(n);
|
||||
|
||||
step = 2 * Math.PI / n;
|
||||
double offset = step / 2;
|
||||
@@ -77,10 +82,11 @@ namespace MeshExplorer.Generators
|
||||
ro = r + r * Util.Random.NextDouble() * (param1 / 100);
|
||||
}
|
||||
|
||||
input.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
|
||||
input.Add(new Edge(m + i, m + ((i + 1) % n), 2));
|
||||
outer.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
|
||||
}
|
||||
|
||||
input.AddContour(outer, 2);
|
||||
|
||||
input.Holes.Add(new Point(0, 0));
|
||||
|
||||
return input;
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace MeshExplorer.Generators
|
||||
{
|
||||
int numRays = GetParamValueInt(0, param0);
|
||||
|
||||
var input = new Polygon(numRays + 4);
|
||||
var g = new Polygon(numRays + 4);
|
||||
|
||||
input.Add(new Vertex(0, 0)); // Center
|
||||
g.Add(new Vertex(0, 0)); // Center
|
||||
|
||||
double x, y, r, e, step = 2 * Math.PI / numRays;
|
||||
|
||||
@@ -42,22 +42,22 @@ namespace MeshExplorer.Generators
|
||||
x = r * Math.Cos(i * step + e);
|
||||
y = r * Math.Sin(i * step + e);
|
||||
|
||||
input.Add(new Vertex(x, y, 2));
|
||||
input.Add(new Edge(0, i + 1, 2));
|
||||
g.Add(new Vertex(x, y, 2));
|
||||
g.Add(new Segment(g.Points[0], g.Points[i + 1], 2));
|
||||
}
|
||||
|
||||
input.Add(new Vertex(-1, -1, 1)); // Box
|
||||
input.Add(new Vertex(1, -1, 1));
|
||||
input.Add(new Vertex(1, 1, 1));
|
||||
input.Add(new Vertex(-1, 1, 1));
|
||||
g.Add(new Vertex(-1, -1, 1)); // Box
|
||||
g.Add(new Vertex(1, -1, 1));
|
||||
g.Add(new Vertex(1, 1, 1));
|
||||
g.Add(new Vertex(-1, 1, 1));
|
||||
|
||||
numRays = input.Count;
|
||||
input.Add(new Edge(numRays - 1, numRays - 2, 1));
|
||||
input.Add(new Edge(numRays - 2, numRays - 3, 1));
|
||||
input.Add(new Edge(numRays - 3, numRays - 4, 1));
|
||||
input.Add(new Edge(numRays - 4, numRays - 1, 1));
|
||||
numRays = g.Count;
|
||||
g.Add(new Segment(g.Points[numRays - 1], g.Points[numRays - 2], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 2], g.Points[numRays - 3], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 3], g.Points[numRays - 4], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 4], g.Points[numRays - 1], 1));
|
||||
|
||||
return input;
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace MeshExplorer.IO.Formats
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, StreamWriter stream)
|
||||
public void Write(IMesh mesh, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -226,7 +226,7 @@ namespace MeshExplorer.IO.Formats
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, StreamWriter stream)
|
||||
public void Write(IPolygon polygon, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -315,6 +315,9 @@ namespace MeshExplorer.IO.Formats
|
||||
|
||||
int p0, p1;
|
||||
|
||||
throw new NotImplementedException();
|
||||
// TODO: Fix JSON format
|
||||
|
||||
for (int i = 0; i < n; i += 2)
|
||||
{
|
||||
mark = 0;
|
||||
@@ -332,7 +335,7 @@ namespace MeshExplorer.IO.Formats
|
||||
throw new Exception("JSON format error (segment index).");
|
||||
}
|
||||
|
||||
geometry.Add(new Edge(p0, p1, mark));
|
||||
//geometry.Add(new Edge(p0, p1, mark));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,7 +500,7 @@ namespace MeshExplorer.IO.Formats
|
||||
writer.Write("]");
|
||||
}
|
||||
|
||||
private void WriteSegments(IEnumerable<Segment> data, StreamWriter writer, int ns)
|
||||
private void WriteSegments(IEnumerable<SubSegment> data, StreamWriter writer, int ns)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace MeshExplorer.IO.Formats
|
||||
format.Write(polygon, filename);
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, StreamWriter stream)
|
||||
public void Write(IPolygon polygon, Stream stream)
|
||||
{
|
||||
format.Write(polygon, stream);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace MeshExplorer.IO.Formats
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, StreamWriter stream)
|
||||
public void Write(IMesh mesh, Stream stream)
|
||||
{
|
||||
format.Write(mesh, stream);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace TriangleNet.Rendering
|
||||
}
|
||||
}
|
||||
|
||||
internal void Dispose(Dictionary<int, Brush> brushes)
|
||||
internal void Dispose(Dictionary<int, SolidBrush> brushes)
|
||||
{
|
||||
foreach (var brush in brushes.Values)
|
||||
{
|
||||
@@ -153,9 +153,9 @@ namespace TriangleNet.Rendering
|
||||
}
|
||||
}
|
||||
|
||||
internal Dictionary<int, Brush> GetBrushDictionary()
|
||||
internal Dictionary<int, SolidBrush> GetBrushDictionary()
|
||||
{
|
||||
var brushes = new Dictionary<int, Brush>();
|
||||
var brushes = new Dictionary<int, SolidBrush>();
|
||||
|
||||
foreach (var item in ColorDictionary)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,12 @@ namespace TriangleNet.Rendering.GDI
|
||||
|
||||
if (filled)
|
||||
{
|
||||
g.FillPolygon(brushes[partition[i]], tri);
|
||||
var b = brushes[partition[i]];
|
||||
|
||||
if (b.Color.A > 0)
|
||||
{
|
||||
g.FillPolygon(b, tri);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -80,6 +80,14 @@ namespace TriangleNet.Rendering
|
||||
// Always clear voronoi layer.
|
||||
RenderLayers[4].Reset(true);
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Ensure linear numbering of polygon vertices.
|
||||
foreach (var p in data.Points)
|
||||
{
|
||||
p.ID = i++;
|
||||
}
|
||||
|
||||
this.bounds = RenderLayers[2].SetPoints(data);
|
||||
this.zoom.Initialize(bounds);
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Contour.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Geometry
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class Contour
|
||||
{
|
||||
int marker;
|
||||
|
||||
public List<Vertex> Points { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Contour" /> class.
|
||||
/// </summary>
|
||||
public Contour(IEnumerable<Vertex> points, int marker)
|
||||
{
|
||||
this.Points = new List<Vertex>(points);
|
||||
|
||||
int count = Points.Count;
|
||||
|
||||
// Check if first vertex equals last vertex.
|
||||
if (Points[0] == Points[count - 1])
|
||||
{
|
||||
count--;
|
||||
Points.RemoveAt(count);
|
||||
}
|
||||
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
public Point FindInteriorPoint(bool convex)
|
||||
{
|
||||
if (convex)
|
||||
{
|
||||
int count = this.Points.Count;
|
||||
|
||||
var centroid = new Point(0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
centroid.x += this.Points[i].x;
|
||||
centroid.y += this.Points[i].y;
|
||||
}
|
||||
|
||||
// If the hole is convex, use its centroid.
|
||||
centroid.x /= count;
|
||||
centroid.y /= count;
|
||||
|
||||
return centroid;
|
||||
}
|
||||
|
||||
return FindPointInPolygon(this.Points);
|
||||
}
|
||||
|
||||
public List<ISegment> GetSegments()
|
||||
{
|
||||
var segments = new List<ISegment>();
|
||||
|
||||
var p = this.Points;
|
||||
|
||||
int count = p.Count - 1;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Add segments to polygon.
|
||||
segments.Add(new Segment(p[i], p[i + 1], marker));
|
||||
}
|
||||
|
||||
// Close the contour.
|
||||
segments.Add(new Segment(p[count], p[0], marker));
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
private static Point FindPointInPolygon(List<Vertex> contour)
|
||||
{
|
||||
var bounds = new Rectangle();
|
||||
bounds.Expand(contour);
|
||||
|
||||
int length = contour.Count;
|
||||
int limit = 8;
|
||||
|
||||
var test = new Point();
|
||||
|
||||
Point a, b; // Current edge.
|
||||
double cx, cy; // Center of current edge.
|
||||
double dx, dy; // Direction perpendicular to edge.
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
a = contour[i];
|
||||
b = contour[(i + 1) % length];
|
||||
|
||||
cx = (a.x + b.x) / 2;
|
||||
cy = (a.y + b.y) / 2;
|
||||
|
||||
dx = (b.y - a.y) / 1.374;
|
||||
dy = (a.x - b.x) / 1.374;
|
||||
|
||||
for (int j = 1; j <= limit; j++)
|
||||
{
|
||||
// Search to the right of the segment.
|
||||
test.x = cx + dx / j;
|
||||
test.y = cy + dy / j;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
return test;
|
||||
}
|
||||
|
||||
// Search on the other side of the segment.
|
||||
test.x = cx - dx / j;
|
||||
test.y = cy - dy / j;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
return test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the given point is inside the polygon, or false if it is not.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <param name="poly">The polygon (list of contour points).</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// WARNING: If the point is exactly on the edge of the polygon, then the function
|
||||
/// may return true or false.
|
||||
///
|
||||
/// See http://alienryderflex.com/polygon/
|
||||
/// </remarks>
|
||||
private static bool IsPointInPolygon(Point point, List<Vertex> poly)
|
||||
{
|
||||
bool inside = false;
|
||||
|
||||
double x = point.x;
|
||||
double y = point.y;
|
||||
|
||||
int count = poly.Count;
|
||||
|
||||
for (int i = 0, j = count - 1; i < count; i++)
|
||||
{
|
||||
if (((poly[i].y < y && poly[j].y >= y) || (poly[j].y < y && poly[i].y >= y))
|
||||
&& (poly[i].x <= x || poly[j].x <= x))
|
||||
{
|
||||
inside ^= (poly[i].x + (y - poly[i].y) / (poly[j].y - poly[i].y) * (poly[j].x - poly[i].x) < x);
|
||||
}
|
||||
|
||||
j = i;
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IEdge.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Geometry
|
||||
{
|
||||
public interface IEdge
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IPolygon.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Geometry
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
@@ -17,7 +22,7 @@ namespace TriangleNet.Geometry
|
||||
/// <summary>
|
||||
/// Gets the segments of the polygon.
|
||||
/// </summary>
|
||||
List<IEdge> Segments { get; }
|
||||
List<ISegment> Segments { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of points defining the holes of the polygon.
|
||||
@@ -30,12 +35,12 @@ namespace TriangleNet.Geometry
|
||||
List<RegionPointer> Regions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value indicating wether the vertices have marks or not.
|
||||
/// Gets or sets a value indicating whether the vertices have marks or not.
|
||||
/// </summary>
|
||||
bool HasPointMarkers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value indicating wether the segments have marks or not.
|
||||
/// Gets or sets a value indicating whether the segments have marks or not.
|
||||
/// </summary>
|
||||
bool HasSegmentMarkers { get; set; }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Segment.cs" company="">
|
||||
// <copyright file="ISegment.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Polygon.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Geometry
|
||||
{
|
||||
using System;
|
||||
@@ -14,7 +19,7 @@ namespace TriangleNet.Geometry
|
||||
List<Point> holes;
|
||||
List<RegionPointer> regions;
|
||||
|
||||
List<IEdge> segments;
|
||||
List<ISegment> segments;
|
||||
|
||||
/// <inherit />
|
||||
public List<Vertex> Points
|
||||
@@ -35,7 +40,7 @@ namespace TriangleNet.Geometry
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public List<IEdge> Segments
|
||||
public List<ISegment> Segments
|
||||
{
|
||||
get { return segments; }
|
||||
}
|
||||
@@ -80,7 +85,7 @@ namespace TriangleNet.Geometry
|
||||
holes = new List<Point>();
|
||||
regions = new List<RegionPointer>();
|
||||
|
||||
segments = new List<IEdge>();
|
||||
segments = new List<ISegment>();
|
||||
|
||||
HasPointMarkers = markers;
|
||||
HasSegmentMarkers = markers;
|
||||
@@ -90,76 +95,27 @@ namespace TriangleNet.Geometry
|
||||
public void AddContour(IEnumerable<Vertex> points, int marker = 0,
|
||||
bool hole = false, bool convex = false)
|
||||
{
|
||||
// Copy input to list.
|
||||
var contour = new List<Vertex>(points);
|
||||
var c = new Contour(points, marker);
|
||||
|
||||
int offset = this.points.Count;
|
||||
int count = contour.Count;
|
||||
this.points.AddRange(c.Points);
|
||||
|
||||
// Check if first vertex equals last vertex.
|
||||
if (contour[0] == contour[count - 1])
|
||||
{
|
||||
count--;
|
||||
contour.RemoveAt(count);
|
||||
}
|
||||
|
||||
// Add points to polygon.
|
||||
this.points.AddRange(contour);
|
||||
|
||||
var centroid = new Point(0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
centroid.x += contour[i].x;
|
||||
centroid.y += contour[i].y;
|
||||
|
||||
// Add segments to polygon.
|
||||
this.segments.Add(new Edge(offset + i, offset + ((i + 1) % count), marker));
|
||||
}
|
||||
this.segments.AddRange(c.GetSegments());
|
||||
|
||||
if (hole)
|
||||
{
|
||||
if (convex)
|
||||
{
|
||||
// If the hole is convex, use its centroid.
|
||||
centroid.x /= count;
|
||||
centroid.y /= count;
|
||||
|
||||
this.holes.Add(centroid);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.holes.Add(FindPointInPolygon(contour));
|
||||
}
|
||||
this.holes.Add(c.FindInteriorPoint(convex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inherit />
|
||||
public void AddContour(IEnumerable<Vertex> points, int marker, Point hole)
|
||||
{
|
||||
// Copy input to list.
|
||||
var contour = new List<Vertex>(points);
|
||||
var c = new Contour(points, marker);
|
||||
|
||||
int offset = this.points.Count;
|
||||
int count = contour.Count;
|
||||
this.points.AddRange(c.Points);
|
||||
|
||||
// Check if first vertex equals last vertex.
|
||||
if (contour[0] == contour[count - 1])
|
||||
{
|
||||
count--;
|
||||
contour.RemoveAt(count);
|
||||
}
|
||||
this.segments.AddRange(c.GetSegments());
|
||||
|
||||
// Add points to polygon.
|
||||
this.points.AddRange(contour);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Add segments to polygon.
|
||||
this.segments.Add(new Edge(offset + i, offset + ((i + 1) % count), marker));
|
||||
}
|
||||
|
||||
// TODO: check if hole is actually inside contour?
|
||||
this.holes.Add(hole);
|
||||
}
|
||||
|
||||
@@ -180,109 +136,12 @@ namespace TriangleNet.Geometry
|
||||
this.points.Add(vertex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a vertex to the polygon.
|
||||
/// </summary>
|
||||
public void Add(Vertex vertex, double[] attributes)
|
||||
{
|
||||
// TODO: check attibutes
|
||||
|
||||
vertex.attributes = attributes;
|
||||
|
||||
this.points.Add(vertex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a segment to the polygon.
|
||||
/// </summary>
|
||||
public void Add(Edge edge)
|
||||
public void Add(ISegment segment)
|
||||
{
|
||||
this.segments.Add(edge);
|
||||
}
|
||||
|
||||
private Point FindPointInPolygon(List<Vertex> contour)
|
||||
{
|
||||
var bounds = new Rectangle();
|
||||
bounds.Expand(contour);
|
||||
|
||||
int length = contour.Count;
|
||||
int limit = 8;
|
||||
|
||||
var test = new Point();
|
||||
|
||||
Point a, b; // Current edge.
|
||||
double cx, cy; // Center of current edge.
|
||||
double dx, dy; // Direction perpendicular to edge.
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
a = contour[i];
|
||||
b = contour[(i + 1) % length];
|
||||
|
||||
cx = (a.x + b.x) / 2;
|
||||
cy = (a.y + b.y) / 2;
|
||||
|
||||
dx = (b.y - a.y) / 1.374;
|
||||
dy = (a.x - b.x) / 1.374;
|
||||
|
||||
for (int j = 1; j <= limit; j++)
|
||||
{
|
||||
// Search to the right of the segment.
|
||||
test.x = cx + dx / j;
|
||||
test.y = cy + dy / j;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
return test;
|
||||
}
|
||||
|
||||
// Search on the other side of the segment.
|
||||
test.x = cx - dx / j;
|
||||
test.y = cy - dy / j;
|
||||
|
||||
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
|
||||
{
|
||||
return test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the given point is inside the polygon, or false if it is not.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to check.</param>
|
||||
/// <param name="poly">The polygon (list of contour points).</param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// WARNING: If the point is exactly on the edge of the polygon, then the function
|
||||
/// may return true or false.
|
||||
///
|
||||
/// See http://alienryderflex.com/polygon/
|
||||
/// </remarks>
|
||||
private bool IsPointInPolygon(Point point, List<Vertex> poly)
|
||||
{
|
||||
bool inside = false;
|
||||
|
||||
double x = point.x;
|
||||
double y = point.y;
|
||||
|
||||
int count = poly.Count;
|
||||
|
||||
for (int i = 0, j = count - 1; i < count; i++)
|
||||
{
|
||||
if (((poly[i].y < y && poly[j].y >= y) || (poly[j].y < y && poly[i].y >= y))
|
||||
&& (poly[i].x <= x || poly[j].x <= x))
|
||||
{
|
||||
inside ^= (poly[i].x + (y - poly[i].y) / (poly[j].y - poly[i].y) * (poly[j].x - poly[i].x) < x);
|
||||
}
|
||||
|
||||
j = i;
|
||||
}
|
||||
|
||||
return inside;
|
||||
this.segments.Add(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Segment.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Geometry
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a straight line segment in 2D space.
|
||||
/// </summary>
|
||||
public class Segment : ISegment
|
||||
{
|
||||
Vertex v0;
|
||||
Vertex v1;
|
||||
|
||||
int boundary;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Segment" /> class.
|
||||
/// </summary>
|
||||
public Segment(Vertex v0, Vertex v1)
|
||||
: this (v0, v1, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Segment" /> class.
|
||||
/// </summary>
|
||||
public Segment(Vertex v0, Vertex v1, int boundary)
|
||||
{
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
|
||||
this.boundary = boundary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specified segment endpoint.
|
||||
/// </summary>
|
||||
/// <param name="index">The endpoint index (0 or 1).</param>
|
||||
/// <returns></returns>
|
||||
public Vertex GetVertex(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return v0;
|
||||
}
|
||||
|
||||
if (index == 1)
|
||||
{
|
||||
return v1;
|
||||
}
|
||||
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WARNING: not implemented.
|
||||
/// </summary>
|
||||
public ITriangle GetTriangle(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first endpoints index.
|
||||
/// </summary>
|
||||
public int P0
|
||||
{
|
||||
get { return v0.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the second endpoints index.
|
||||
/// </summary>
|
||||
public int P1
|
||||
{
|
||||
get { return v1.id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the segments boundary mark.
|
||||
/// </summary>
|
||||
public int Boundary
|
||||
{
|
||||
get { return boundary; }
|
||||
set { boundary = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,10 @@ namespace TriangleNet.IO
|
||||
void Write(IMesh mesh, string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Save a mesh to a <see cref="StreamWriter" />.
|
||||
/// Save a mesh to a <see cref="Stream" />.
|
||||
/// </summary>
|
||||
/// <param name="mesh">An instance of the <see cref="IMesh" /> interface.</param>
|
||||
/// <param name="stream">The stream to save to.</param>
|
||||
void Write(IMesh mesh, StreamWriter stream);
|
||||
void Write(IMesh mesh, Stream stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ namespace TriangleNet.IO
|
||||
void Write(IPolygon polygon, string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Save a polygon geometry to a <see cref="StreamWriter" />.
|
||||
/// Save a polygon geometry to a <see cref="Stream" />.
|
||||
/// </summary>
|
||||
/// <param name="polygon">An instance of the <see cref="IPolygon" /> class.</param>
|
||||
/// <param name="stream">The stream to save to.</param>
|
||||
void Write(IPolygon polygon, StreamWriter stream);
|
||||
void Write(IPolygon polygon, Stream stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace TriangleNet.IO
|
||||
TriangleWriter.WriteElements((Mesh)mesh, Path.ChangeExtension(filename, ".ele"));
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, StreamWriter stream)
|
||||
public void Write(IMesh mesh, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace TriangleNet.IO
|
||||
TriangleWriter.WritePoly(polygon, filename);
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, StreamWriter stream)
|
||||
public void Write(IPolygon polygon, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -59,29 +59,36 @@ namespace TriangleNet.IO
|
||||
/// <param name="line">The current line.</param>
|
||||
/// <param name="attributes">Number of point attributes</param>
|
||||
/// <param name="marks">Number of point markers (0 or 1)</param>
|
||||
static void ReadVertex(Polygon data, int index, string[] line, int attributes, int marks)
|
||||
static void ReadVertex(List<Vertex> data, int index, string[] line, int attributes, int marks)
|
||||
{
|
||||
double x = double.Parse(line[1], nfi);
|
||||
double y = double.Parse(line[2], nfi);
|
||||
int mark = 0;
|
||||
double[] attribs = attributes == 0 ? null : new double[attributes];
|
||||
|
||||
// Read the vertex attributes.
|
||||
for (int j = 0; j < attributes; j++)
|
||||
{
|
||||
if (line.Length > 3 + j)
|
||||
{
|
||||
attribs[j] = double.Parse(line[3 + j], nfi);
|
||||
}
|
||||
}
|
||||
var v = new Vertex(x, y);
|
||||
|
||||
// Read a vertex marker.
|
||||
if (marks > 0 && line.Length > 3 + attributes)
|
||||
{
|
||||
mark = int.Parse(line[3 + attributes]);
|
||||
v.Boundary = int.Parse(line[3 + attributes]);
|
||||
}
|
||||
|
||||
data.Add(new Vertex(x, y, mark), attribs);
|
||||
if (attributes > 0)
|
||||
{
|
||||
var attribs = new double[attributes];
|
||||
|
||||
// Read the vertex attributes.
|
||||
for (int j = 0; j < attributes; j++)
|
||||
{
|
||||
if (line.Length > 3 + j)
|
||||
{
|
||||
attribs[j] = double.Parse(line[3 + j], nfi);
|
||||
}
|
||||
}
|
||||
|
||||
v.attributes = attribs;
|
||||
}
|
||||
|
||||
data.Add(v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -219,7 +226,7 @@ namespace TriangleNet.IO
|
||||
startIndex = int.Parse(line[0], nfi);
|
||||
}
|
||||
|
||||
ReadVertex(data, i, line, attributes, nodemarkers);
|
||||
ReadVertex(data.Points, i, line, attributes, nodemarkers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,19 +333,21 @@ namespace TriangleNet.IO
|
||||
startIndex = int.Parse(line[0], nfi);
|
||||
}
|
||||
|
||||
ReadVertex(data, i, line, attributes, nodemarkers);
|
||||
ReadVertex(data.Points, i, line, attributes, nodemarkers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the .poly file claims there are zero vertices, that means that
|
||||
// the vertices should be read from a separate .node file.
|
||||
string nodefile = Path.ChangeExtension(polyfilename, ".node");
|
||||
data = ReadNodeFile(nodefile);
|
||||
data = ReadNodeFile(Path.ChangeExtension(polyfilename, ".node"));
|
||||
|
||||
invertices = data.Points.Count;
|
||||
}
|
||||
|
||||
if (data.Points == null)
|
||||
var points = data.Points;
|
||||
|
||||
if (points.Count == 0)
|
||||
{
|
||||
throw new Exception("No nodes available.");
|
||||
}
|
||||
@@ -401,7 +410,7 @@ namespace TriangleNet.IO
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Add(new Edge(end1, end2, mark));
|
||||
data.Add(new Segment(points[end1], points[end2], mark));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -202,17 +202,22 @@ namespace TriangleNet.IO
|
||||
// Number of segments, number of boundary markers (zero or one).
|
||||
writer.WriteLine("{0} {1}", polygon.Segments.Count, hasMarkers ? "1" : "0");
|
||||
|
||||
Vertex p, q;
|
||||
|
||||
int j = 0;
|
||||
foreach (var seg in polygon.Segments)
|
||||
{
|
||||
p = seg.GetVertex(0);
|
||||
q = seg.GetVertex(1);
|
||||
|
||||
// Segment number, indices of its two endpoints, and possibly a marker.
|
||||
if (hasMarkers)
|
||||
{
|
||||
writer.WriteLine("{0} {1} {2} {3}", j, seg.P0, seg.P1, seg.Boundary);
|
||||
writer.WriteLine("{0} {1} {2} {3}", j, p.ID, q.ID, seg.Boundary);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine("{0} {1} {2}", j, seg.P0, seg.P1);
|
||||
writer.WriteLine("{0} {1} {2}", j, p.ID, q.ID);
|
||||
}
|
||||
|
||||
j++;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace TriangleNet
|
||||
|
||||
// Using hashsets for memory management should quite fast.
|
||||
internal Dictionary<int, Triangle> triangles;
|
||||
internal Dictionary<int, Segment> subsegs;
|
||||
internal Dictionary<int, SubSegment> subsegs;
|
||||
internal Dictionary<int, Vertex> vertices;
|
||||
|
||||
// Hash seeds (should belong to mesh instance)
|
||||
@@ -111,7 +111,7 @@ namespace TriangleNet
|
||||
/// <summary>
|
||||
/// Gets the mesh segments.
|
||||
/// </summary>
|
||||
public ICollection<Segment> Segments
|
||||
public ICollection<SubSegment> Segments
|
||||
{
|
||||
get { return this.subsegs.Values; }
|
||||
}
|
||||
@@ -183,11 +183,11 @@ namespace TriangleNet
|
||||
// triangle side or subsegment end that isn't attached to a real
|
||||
// subsegment.
|
||||
|
||||
internal Segment dummysub;
|
||||
internal SubSegment dummysub;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
dummysub = new Segment();
|
||||
dummysub = new SubSegment();
|
||||
dummysub.hash = DUMMY;
|
||||
|
||||
// Initialize the two adjoining subsegments to be the omnipresent
|
||||
@@ -231,7 +231,7 @@ namespace TriangleNet
|
||||
|
||||
vertices = new Dictionary<int, Vertex>();
|
||||
triangles = new Dictionary<int, Triangle>();
|
||||
subsegs = new Dictionary<int, Segment>();
|
||||
subsegs = new Dictionary<int, SubSegment>();
|
||||
|
||||
flipstack = new Stack<Otri>();
|
||||
|
||||
@@ -287,13 +287,13 @@ namespace TriangleNet
|
||||
}
|
||||
else if (num == NodeNumbering.CuthillMcKee)
|
||||
{
|
||||
CuthillMcKee rcm = new CuthillMcKee();
|
||||
int[] perm_inv = rcm.Renumber(this);
|
||||
var rcm = new CuthillMcKee();
|
||||
var iperm = rcm.Renumber(this);
|
||||
|
||||
// Permute the node indices.
|
||||
foreach (var node in this.vertices.Values)
|
||||
{
|
||||
node.id = perm_inv[node.id];
|
||||
node.id = iperm[node.id];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,7 +689,7 @@ namespace TriangleNet
|
||||
/// <param name="newsubseg">Reference to the new subseg.</param>
|
||||
internal void MakeSegment(ref Osub newsubseg)
|
||||
{
|
||||
Segment seg = new Segment();
|
||||
var seg = new SubSegment();
|
||||
|
||||
seg.hash = this.hash_seg++;
|
||||
|
||||
@@ -1924,7 +1924,7 @@ namespace TriangleNet
|
||||
/// Deallocate space for a subsegment, marking it dead.
|
||||
/// </summary>
|
||||
/// <param name="dyingsubseg"></param>
|
||||
internal void SubsegDealloc(Segment dyingsubseg)
|
||||
internal void SubsegDealloc(SubSegment dyingsubseg)
|
||||
{
|
||||
// Mark the subsegment as dead. This makes it possible to detect dead
|
||||
// subsegments when traversing the list of all subsegments.
|
||||
|
||||
@@ -169,9 +169,10 @@ namespace TriangleNet.Meshing
|
||||
/// </summary>
|
||||
public void FormSkeleton(IPolygon input)
|
||||
{
|
||||
Vertex endpoint1, endpoint2;
|
||||
int end1, end2;
|
||||
int boundmarker;
|
||||
// The segment endpoints.
|
||||
Vertex p, q;
|
||||
|
||||
int label;
|
||||
|
||||
mesh.insegments = 0;
|
||||
|
||||
@@ -191,51 +192,31 @@ namespace TriangleNet.Meshing
|
||||
mesh.MakeVertexMap();
|
||||
}
|
||||
|
||||
boundmarker = 0;
|
||||
label = 0;
|
||||
|
||||
// Read and insert the segments.
|
||||
foreach (var seg in input.Segments)
|
||||
{
|
||||
mesh.insegments++;
|
||||
|
||||
end1 = seg.P0;
|
||||
end2 = seg.P1;
|
||||
boundmarker = seg.Boundary;
|
||||
label = seg.Boundary;
|
||||
|
||||
if ((end1 < 0) || (end1 >= mesh.invertices))
|
||||
// TODO: wrap segment dictionary access in try / catch?
|
||||
|
||||
p = seg.GetVertex(0);
|
||||
q = seg.GetVertex(1);
|
||||
|
||||
if ((p.x == q.x) && (p.y == q.y))
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning("Invalid first endpoint of segment.", "Mesh.FormSkeleton().1");
|
||||
}
|
||||
}
|
||||
else if ((end2 < 0) || (end2 >= mesh.invertices))
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning("Invalid second endpoint of segment.", "Mesh.FormSkeleton().2");
|
||||
logger.Warning("Endpoints of segment (IDs " + p.id + "/" + q.id + ") are coincident.",
|
||||
"Mesh.FormSkeleton()");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Is using the vertex ID reliable???
|
||||
// It should be. The ID gets appropriately set in TransferNodes().
|
||||
|
||||
// Find the vertices numbered 'end1' and 'end2'.
|
||||
endpoint1 = mesh.vertices[end1];
|
||||
endpoint2 = mesh.vertices[end2];
|
||||
if ((endpoint1.x == endpoint2.x) && (endpoint1.y == endpoint2.y))
|
||||
{
|
||||
if (Log.Verbose)
|
||||
{
|
||||
logger.Warning("Endpoints of segment (IDs " + end1 + "/" + end2 + ") are coincident.",
|
||||
"Mesh.FormSkeleton()");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertSegment(endpoint1, endpoint2, boundmarker);
|
||||
}
|
||||
InsertSegment(p, q, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,10 +213,12 @@ namespace TriangleNet.Meshing
|
||||
Otri checkneighbor = default(Otri);
|
||||
Osub subseg = default(Osub);
|
||||
Otri prevlink; // Triangle
|
||||
TVertex shorg;
|
||||
TVertex segmentorg, segmentdest;
|
||||
int[] end = new int[2];
|
||||
|
||||
TVertex tmp;
|
||||
TVertex sorg, sdest;
|
||||
|
||||
bool notfound;
|
||||
|
||||
//bool segmentmarkers = false;
|
||||
int boundmarker;
|
||||
int aroundvertex;
|
||||
@@ -234,40 +236,38 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
subseg.seg = item;
|
||||
|
||||
end[0] = polygon.Segments[i].P0;
|
||||
end[1] = polygon.Segments[i].P1;
|
||||
sorg = polygon.Segments[i].GetVertex(0);
|
||||
sdest = polygon.Segments[i].GetVertex(1);
|
||||
|
||||
boundmarker = polygon.Segments[i].Boundary;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
if ((sorg.id < 0 || sorg.id >= mesh.invertices) || (sdest.id < 0 || sdest.id >= mesh.invertices))
|
||||
{
|
||||
if ((end[j] < 0) || (end[j] >= mesh.invertices))
|
||||
{
|
||||
Log.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
|
||||
throw new Exception("Segment has an invalid vertex index.");
|
||||
}
|
||||
Log.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
|
||||
throw new Exception("Segment has an invalid vertex index.");
|
||||
}
|
||||
|
||||
// set the subsegment's vertices.
|
||||
subseg.orient = 0;
|
||||
segmentorg = mesh.vertices[end[0]];
|
||||
segmentdest = mesh.vertices[end[1]];
|
||||
subseg.SetOrg(segmentorg);
|
||||
subseg.SetDest(segmentdest);
|
||||
subseg.SetSegOrg(segmentorg);
|
||||
subseg.SetSegDest(segmentdest);
|
||||
subseg.SetOrg(sorg);
|
||||
subseg.SetDest(sdest);
|
||||
subseg.SetSegOrg(sorg);
|
||||
subseg.SetSegDest(sdest);
|
||||
subseg.seg.boundary = boundmarker;
|
||||
// Try linking the subsegment to triangles that share these vertices.
|
||||
for (subseg.orient = 0; subseg.orient < 2; subseg.orient++)
|
||||
{
|
||||
// Take the number for the destination of subsegloop.
|
||||
aroundvertex = end[1 - subseg.orient];
|
||||
aroundvertex = subseg.orient == 1 ? sorg.id : sdest.id;
|
||||
|
||||
int index = vertexarray[aroundvertex].Count - 1;
|
||||
|
||||
// Look for triangles having this vertex.
|
||||
prevlink = vertexarray[aroundvertex][index];
|
||||
nexttri = vertexarray[aroundvertex][index];
|
||||
|
||||
checktri = nexttri;
|
||||
shorg = subseg.Org();
|
||||
tmp = subseg.Org();
|
||||
notfound = true;
|
||||
// Look for triangles having this edge. Note that I'm only
|
||||
// comparing each triangle's destination with the subsegment;
|
||||
@@ -280,7 +280,7 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
checkdest = checktri.Dest();
|
||||
|
||||
if (shorg == checkdest)
|
||||
if (tmp == checkdest)
|
||||
{
|
||||
// We have a match. Remove this triangle from the list.
|
||||
//prevlink = vertexarray[aroundvertex][index];
|
||||
|
||||
@@ -100,10 +100,10 @@ namespace TriangleNet.Meshing
|
||||
left = bounds.Left;
|
||||
bottom = bounds.Bottom;
|
||||
|
||||
int i, j, k, l, n;
|
||||
int i, j, k, l, n = 0;
|
||||
|
||||
// Add vertices.
|
||||
var points = polygon.Points;
|
||||
var points = new Vertex[(nx + 1) * (ny + 1)];
|
||||
|
||||
for (i = 0; i <= nx; i++)
|
||||
{
|
||||
@@ -113,10 +113,12 @@ namespace TriangleNet.Meshing
|
||||
{
|
||||
y = bottom + j * dy;
|
||||
|
||||
points.Add(new Vertex(x, y));
|
||||
points[n++] = new Vertex(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
polygon.Points.AddRange(points);
|
||||
|
||||
n = 0;
|
||||
|
||||
// Set vertex hash and id.
|
||||
@@ -130,22 +132,44 @@ namespace TriangleNet.Meshing
|
||||
|
||||
segments.Capacity = 2 * (nx + ny);
|
||||
|
||||
Vertex a, b;
|
||||
|
||||
for (j = 0; j < ny; j++)
|
||||
{
|
||||
// Left
|
||||
segments.Add(new Edge(j, j + 1));
|
||||
a = points[j];
|
||||
b = points[j + 1];
|
||||
|
||||
segments.Add(new Segment(a, b, 1));
|
||||
|
||||
a.Boundary = b.Boundary = 1;
|
||||
|
||||
// Right
|
||||
segments.Add(new Edge(nx * (ny + 1) + j, nx * (ny + 1) + (j + 1)));
|
||||
a = points[nx * (ny + 1) + j];
|
||||
b = points[nx * (ny + 1) + (j + 1)];
|
||||
|
||||
segments.Add(new Segment(a, b, 1));
|
||||
|
||||
a.Boundary = b.Boundary = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < nx; i++)
|
||||
{
|
||||
// Bottom
|
||||
segments.Add(new Edge(i * (ny + 1), (i + 1) * (ny + 1)));
|
||||
a = points[i * (ny + 1)];
|
||||
b = points[(i + 1) * (ny + 1)];
|
||||
|
||||
segments.Add(new Segment(a, b, 1));
|
||||
|
||||
a.Boundary = b.Boundary = 1;
|
||||
|
||||
// Top
|
||||
segments.Add(new Edge(i * (ny + 1) + nx, (i + 1) * (ny + 1) + nx));
|
||||
a = points[i * (ny + 1) + nx];
|
||||
b = points[(i + 1) * (ny + 1) + nx];
|
||||
|
||||
segments.Add(new Segment(a, b, 1));
|
||||
|
||||
a.Boundary = b.Boundary = 1;
|
||||
}
|
||||
|
||||
// Add triangles.
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace TriangleNet.Meshing
|
||||
/// <summary>
|
||||
/// Gets the segments (constraint edges) of the mesh.
|
||||
/// </summary>
|
||||
ICollection<Segment> Segments { get; }
|
||||
ICollection<SubSegment> Segments { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the triangles of the mesh.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
namespace TriangleNet.Tools
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
public static class PolygonValidator
|
||||
@@ -18,23 +19,37 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
var logger = Log.Instance;
|
||||
|
||||
var points = poly.Points;
|
||||
|
||||
int horrors = 0;
|
||||
|
||||
int i = 0;
|
||||
int count = poly.Points.Count;
|
||||
int count = points.Count;
|
||||
|
||||
foreach (var p in poly.Points)
|
||||
if (count < 3)
|
||||
{
|
||||
logger.Warning("Polygon must have at least 3 vertices.", "PolygonValidator.IsConsistent()");
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
if (p == null)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Point {0} is null.", i), "PolygonValidator.IsConsistent()");
|
||||
}
|
||||
else if (double.IsNaN(p.x + p.y) || double.IsInfinity(p.x + p.y))
|
||||
else if (double.IsNaN(p.x) || double.IsNaN(p.y))
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Point {0} has invalid coordinates.", i), "PolygonValidator.IsConsistent()");
|
||||
}
|
||||
else if (double.IsInfinity(p.x) || double.IsInfinity(p.y))
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Point {0} has invalid coordinates.", i), "PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -46,27 +61,33 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} is null.", i), "PolygonValidator.IsConsistent()");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seg.P0 < 0 || seg.P0 >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid startpoint.", i),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
if (seg.P1 < 0 || seg.P1 >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid endpoint.", i),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
// Always abort if a NULL-segment is found.
|
||||
return false;
|
||||
}
|
||||
|
||||
var p = seg.GetVertex(0);
|
||||
var q = seg.GetVertex(1);
|
||||
|
||||
if ((p.x == q.x) && (p.y == q.y))
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Endpoints of segment {0} are coincident (IDs {1} / {2}).", i, p.id, q.id),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (points[0].ID == points[1].ID)
|
||||
{
|
||||
horrors += CheckVertexIDs(poly, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
horrors += CheckDuplicateIDs(poly);
|
||||
}
|
||||
|
||||
return horrors == 0;
|
||||
}
|
||||
|
||||
@@ -116,8 +137,8 @@ namespace TriangleNet.Tools
|
||||
q0 = p0;
|
||||
q1 = p1;
|
||||
|
||||
p0 = (seg.P0 >= 0 && seg.P0 < count) ? poly.Points[seg.P0] : null;
|
||||
p1 = (seg.P1 >= 0 && seg.P1 < count) ? poly.Points[seg.P1] : null;
|
||||
p0 = seg.GetVertex(0);
|
||||
p1 = seg.GetVertex(1);
|
||||
|
||||
if (q0 != null && q1 != null)
|
||||
{
|
||||
@@ -160,5 +181,57 @@ namespace TriangleNet.Tools
|
||||
// Calculate the Z coordinate of the cross product.
|
||||
return (a.X - b.X) * (c.Y - b.Y) - (a.Y - b.Y) * (c.X - b.X);
|
||||
}
|
||||
|
||||
private static int CheckVertexIDs(IPolygon poly, int count)
|
||||
{
|
||||
var logger = Log.Instance;
|
||||
|
||||
int horrors = 0;
|
||||
|
||||
int i = 0;
|
||||
|
||||
Vertex p, q;
|
||||
|
||||
foreach (var seg in poly.Segments)
|
||||
{
|
||||
p = seg.GetVertex(0);
|
||||
q = seg.GetVertex(1);
|
||||
|
||||
if (p.ID < 0 || p.ID >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid startpoint.", i),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
if (q.ID < 0 || q.ID >= count)
|
||||
{
|
||||
horrors++;
|
||||
logger.Warning(String.Format("Segment {0} has invalid endpoint.", i),
|
||||
"PolygonValidator.IsConsistent()");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return horrors;
|
||||
}
|
||||
|
||||
private static int CheckDuplicateIDs(IPolygon poly)
|
||||
{
|
||||
var ids = new HashSet<int>();
|
||||
|
||||
// Check for duplicate ids.
|
||||
foreach (var p in poly.Points)
|
||||
{
|
||||
if (!ids.Add(p.ID))
|
||||
{
|
||||
Log.Instance.Warning("Found duplicate vertex ids.", "PolygonValidator.IsConsistent()");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace TriangleNet.Topology
|
||||
/// </remarks>
|
||||
public struct Osub
|
||||
{
|
||||
internal Segment seg;
|
||||
internal SubSegment seg;
|
||||
internal int orient; // Ranges from 0 to 1.
|
||||
|
||||
public Segment Segment
|
||||
public SubSegment Segment
|
||||
{
|
||||
get { return seg; }
|
||||
}
|
||||
@@ -213,7 +213,7 @@ namespace TriangleNet.Topology
|
||||
/// </summary>
|
||||
/// <remarks>Note that the other subsegment will still think it's
|
||||
/// connected to this subsegment.</remarks>
|
||||
internal void Dissolve(Segment dummy)
|
||||
internal void Dissolve(SubSegment dummy)
|
||||
{
|
||||
seg.subsegs[orient].seg = dummy;
|
||||
}
|
||||
@@ -237,7 +237,7 @@ namespace TriangleNet.Topology
|
||||
/// <summary>
|
||||
/// Check a subsegment's deallocation.
|
||||
/// </summary>
|
||||
internal static bool IsDead(Segment sub)
|
||||
internal static bool IsDead(SubSegment sub)
|
||||
{
|
||||
return sub.subsegs[0].seg == null;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ namespace TriangleNet.Topology
|
||||
/// <summary>
|
||||
/// Set a subsegment's deallocation.
|
||||
/// </summary>
|
||||
internal static void Kill(Segment sub)
|
||||
internal static void Kill(SubSegment sub)
|
||||
{
|
||||
sub.subsegs[0].seg = null;
|
||||
sub.subsegs[1].seg = null;
|
||||
|
||||
@@ -454,7 +454,7 @@ namespace TriangleNet.Topology
|
||||
/// <summary>
|
||||
/// Dissolve a bond (from the triangle side).
|
||||
/// </summary>
|
||||
internal void SegDissolve(Segment dummy)
|
||||
internal void SegDissolve(SubSegment dummy)
|
||||
{
|
||||
tri.subsegs[orient].seg = dummy;
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ namespace TriangleNet.Topology
|
||||
/// <summary>
|
||||
/// The subsegment data structure.
|
||||
/// </summary>
|
||||
public class Segment : ISegment
|
||||
public class SubSegment : ISegment
|
||||
{
|
||||
// Hash for dictionary. Will be set by mesh instance.
|
||||
internal int hash;
|
||||
@@ -23,7 +23,7 @@ namespace TriangleNet.Topology
|
||||
internal Otri[] triangles;
|
||||
internal int boundary;
|
||||
|
||||
public Segment()
|
||||
public SubSegment()
|
||||
{
|
||||
// Four NULL vertices.
|
||||
vertices = new Vertex[4];
|
||||
@@ -38,15 +38,31 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Geometry\Contour.cs" />
|
||||
<Compile Include="Geometry\Edge.cs" />
|
||||
<Compile Include="Geometry\ExtensionMethods.cs" />
|
||||
<Compile Include="Geometry\IEdge.cs" />
|
||||
<Compile Include="Geometry\IPolygon.cs" />
|
||||
<Compile Include="Geometry\ExtensionMethods.cs" />
|
||||
<Compile Include="Geometry\ISegment.cs" />
|
||||
<Compile Include="Geometry\ITriangle.cs" />
|
||||
<Compile Include="Geometry\Point.cs" />
|
||||
<Compile Include="Geometry\Polygon.cs" />
|
||||
<Compile Include="Geometry\Rectangle.cs" />
|
||||
<Compile Include="Geometry\RegionPointer.cs" />
|
||||
<Compile Include="Geometry\Segment.cs" />
|
||||
<Compile Include="Geometry\Vertex.cs" />
|
||||
<Compile Include="IO\DebugWriter.cs" />
|
||||
<Compile Include="IO\FileProcessor.cs" />
|
||||
<Compile Include="IO\IFileFormat.cs" />
|
||||
<Compile Include="IO\IMeshFormat.cs" />
|
||||
<Compile Include="IO\InputTriangle.cs" />
|
||||
<Compile Include="IO\IPolygonFormat.cs" />
|
||||
<Compile Include="IO\TriangleFormat.cs" />
|
||||
<Compile Include="IO\TriangleReader.cs" />
|
||||
<Compile Include="IO\TriangleWriter.cs" />
|
||||
<Compile Include="Meshing\ConstraintMesher.cs" />
|
||||
<Compile Include="Meshing\ConstraintOptions.cs" />
|
||||
<Compile Include="Meshing\Converter.cs" />
|
||||
<Compile Include="Meshing\GenericMesher.cs" />
|
||||
@@ -54,69 +70,54 @@
|
||||
<Compile Include="Meshing\IMesh.cs" />
|
||||
<Compile Include="Meshing\IQualityMesher.cs" />
|
||||
<Compile Include="Meshing\ITriangulator.cs" />
|
||||
<Compile Include="Meshing\Data\BadTriQueue.cs" />
|
||||
<Compile Include="Behavior.cs" />
|
||||
<Compile Include="Meshing\ConstraintMesher.cs" />
|
||||
<Compile Include="Meshing\QualityOptions.cs" />
|
||||
<Compile Include="Meshing\QualityMesher.cs" />
|
||||
<Compile Include="Meshing\Algorithm\Dwyer.cs" />
|
||||
<Compile Include="Meshing\Algorithm\Incremental.cs" />
|
||||
<Compile Include="Meshing\Algorithm\SweepLine.cs" />
|
||||
<Compile Include="Meshing\Data\BadSubseg.cs" />
|
||||
<Compile Include="Meshing\Data\BadTriangle.cs" />
|
||||
<Compile Include="Meshing\Data\BadTriQueue.cs" />
|
||||
<Compile Include="Meshing\Iterators\EdgeIterator.cs" />
|
||||
<Compile Include="Meshing\Iterators\RegionIterator.cs" />
|
||||
<Compile Include="Tools\AdjacencyMatrix.cs" />
|
||||
<Compile Include="Tools\CuthillMcKee.cs" />
|
||||
<Compile Include="Tools\IntersectionHelper.cs" />
|
||||
<Compile Include="Tools\PointSorter.cs" />
|
||||
<Compile Include="Tools\PolygonValidator.cs" />
|
||||
<Compile Include="Topology\DCEL\DcelMesh.cs" />
|
||||
<Compile Include="Tools\QualityMeasure.cs" />
|
||||
<Compile Include="Tools\TriangleQuadTree.cs" />
|
||||
<Compile Include="Tools\Statistic.cs" />
|
||||
<Compile Include="Topology\Osub.cs" />
|
||||
<Compile Include="Topology\Otri.cs" />
|
||||
<Compile Include="Topology\Segment.cs" />
|
||||
<Compile Include="Topology\SubSegment.cs" />
|
||||
<Compile Include="Topology\Triangle.cs" />
|
||||
<Compile Include="Geometry\Vertex.cs" />
|
||||
<Compile Include="Meshing\Algorithm\Dwyer.cs" />
|
||||
<Compile Include="Geometry\Rectangle.cs" />
|
||||
<Compile Include="Geometry\Edge.cs" />
|
||||
<Compile Include="Meshing\Iterators\EdgeIterator.cs" />
|
||||
<Compile Include="Geometry\ITriangle.cs" />
|
||||
<Compile Include="Geometry\Point.cs" />
|
||||
<Compile Include="Geometry\RegionPointer.cs" />
|
||||
<Compile Include="Geometry\ISegment.cs" />
|
||||
<Compile Include="IO\DebugWriter.cs" />
|
||||
<Compile Include="IO\TriangleWriter.cs" />
|
||||
<Compile Include="IO\IPolygonFormat.cs" />
|
||||
<Compile Include="IO\IMeshFormat.cs" />
|
||||
<Compile Include="IO\InputTriangle.cs" />
|
||||
<Compile Include="IO\TriangleReader.cs" />
|
||||
<Compile Include="IO\TriangleFormat.cs" />
|
||||
<Compile Include="Logging\ILog.cs" />
|
||||
<Compile Include="Logging\ILogItem.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="Logging\LogItem.cs" />
|
||||
<Compile Include="Meshing\QualityOptions.cs" />
|
||||
<Compile Include="MeshValidator.cs" />
|
||||
<Compile Include="NewLocation.cs" />
|
||||
<Compile Include="Meshing\QualityMesher.cs" />
|
||||
<Compile Include="Enums.cs" />
|
||||
<Compile Include="Meshing\Algorithm\Incremental.cs" />
|
||||
<Compile Include="Mesh.cs" />
|
||||
<Compile Include="RobustPredicates.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Sampler.cs" />
|
||||
<Compile Include="Smoothing\ISmoother.cs" />
|
||||
<Compile Include="Smoothing\SimpleSmoother.cs" />
|
||||
<Compile Include="Tools\AdjacencyMatrix.cs" />
|
||||
<Compile Include="Tools\PointSorter.cs" />
|
||||
<Compile Include="Voronoi\Legacy\BoundedVoronoiLegacy.cs" />
|
||||
<Compile Include="Tools\CuthillMcKee.cs" />
|
||||
<Compile Include="Voronoi\Legacy\IVoronoi.cs" />
|
||||
<Compile Include="Tools\TriangleQuadTree.cs" />
|
||||
<Compile Include="Tools\QualityMeasure.cs" />
|
||||
<Compile Include="Meshing\Iterators\RegionIterator.cs" />
|
||||
<Compile Include="Tools\Statistic.cs" />
|
||||
<Compile Include="Meshing\Algorithm\SweepLine.cs" />
|
||||
<Compile Include="Voronoi\Legacy\SimpleVoronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\VoronoiRegion.cs" />
|
||||
<Compile Include="TriangleLocator.cs" />
|
||||
<Compile Include="Voronoi\BoundedVoronoi.cs" />
|
||||
<Compile Include="Topology\DCEL\DcelMesh.cs" />
|
||||
<Compile Include="Topology\DCEL\Face.cs" />
|
||||
<Compile Include="Topology\DCEL\HalfEdge.cs" />
|
||||
<Compile Include="Topology\DCEL\Vertex.cs" />
|
||||
<Compile Include="Smoothing\ISmoother.cs" />
|
||||
<Compile Include="Smoothing\SimpleSmoother.cs" />
|
||||
<Compile Include="Voronoi\BoundedVoronoi.cs" />
|
||||
<Compile Include="Voronoi\StandardVoronoi.cs" />
|
||||
<Compile Include="Voronoi\VoronoiBase.cs" />
|
||||
<Compile Include="Voronoi\Legacy\BoundedVoronoiLegacy.cs" />
|
||||
<Compile Include="Voronoi\Legacy\IVoronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\SimpleVoronoi.cs" />
|
||||
<Compile Include="Voronoi\Legacy\VoronoiRegion.cs" />
|
||||
<Compile Include="Logging\ILog.cs" />
|
||||
<Compile Include="Logging\ILogItem.cs" />
|
||||
<Compile Include="Logging\LogItem.cs" />
|
||||
<Compile Include="Behavior.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="Enums.cs" />
|
||||
<Compile Include="Mesh.cs" />
|
||||
<Compile Include="MeshValidator.cs" />
|
||||
<Compile Include="NewLocation.cs" />
|
||||
<Compile Include="RobustPredicates.cs" />
|
||||
<Compile Include="Sampler.cs" />
|
||||
<Compile Include="TriangleLocator.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace TriangleNet.Voronoi.Legacy
|
||||
List<Point> segPoints;
|
||||
int segIndex;
|
||||
|
||||
Dictionary<int, Segment> subsegMap;
|
||||
Dictionary<int, SubSegment> subsegMap;
|
||||
|
||||
bool includeBoundary = true;
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace TriangleNet.Voronoi.Legacy
|
||||
int blinded = 0;
|
||||
|
||||
Stack<Triangle> triangles;
|
||||
subsegMap = new Dictionary<int, Segment>();
|
||||
subsegMap = new Dictionary<int, SubSegment>();
|
||||
|
||||
Otri f = default(Otri);
|
||||
Otri f0 = default(Otri);
|
||||
|
||||
Reference in New Issue
Block a user