From efd9d1260d8164a20821cf8645f78e3d57dac9ee Mon Sep 17 00:00:00 2001 From: "SND\\wo80_cp" Date: Thu, 9 Jul 2015 17:20:03 +0000 Subject: [PATCH] Add a simple polygon validator. git-svn-id: https://triangle.svn.codeplex.com/svn@77032 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5 --- .../Triangle/Tools/PolygonValidator.cs | 164 ++++++++++++++++++ Triangle.NET/Triangle/Triangle.csproj | 1 + 2 files changed, 165 insertions(+) create mode 100644 Triangle.NET/Triangle/Tools/PolygonValidator.cs diff --git a/Triangle.NET/Triangle/Tools/PolygonValidator.cs b/Triangle.NET/Triangle/Tools/PolygonValidator.cs new file mode 100644 index 0000000..da1da08 --- /dev/null +++ b/Triangle.NET/Triangle/Tools/PolygonValidator.cs @@ -0,0 +1,164 @@ +// ----------------------------------------------------------------------- +// +// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/ +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.Tools +{ + using System; + using TriangleNet.Geometry; + + public static class PolygonValidator + { + /// + /// Test the polygon for consistency. + /// + public static bool IsConsistent(IPolygon poly) + { + var logger = Log.Instance; + + int horrors = 0; + + int i = 0; + int count = poly.Points.Count; + + foreach (var p in poly.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)) + { + horrors++; + logger.Warning(String.Format("Point {0} has invalid coordinates.", i), "PolygonValidator.IsConsistent()"); + } + i++; + } + + i = 0; + + foreach (var seg in poly.Segments) + { + if (seg == null) + { + 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()"); + } + } + + i++; + } + + return horrors == 0; + } + + /// + /// Test the polygon for duplicate vertices. + /// + public static bool HasDuplicateVertices(IPolygon poly) + { + var logger = Log.Instance; + + int horrors = 0; + + var points = poly.Points.ToArray(); + + (new PointSorter()).Sort(points); + + for (int i = 1; i < points.Length; i++) + { + if (points[i - 1] == points[i]) + { + horrors++; + logger.Warning(String.Format("Found duplicate point {0}.", points[i]), + "PolygonValidator.HasDuplicateVertices()"); + } + } + + return horrors == 0; + } + + /// + /// Test the polygon for 360 degree angles. + /// + public static bool HasBadAngles(IPolygon poly) + { + var logger = Log.Instance; + + int horrors = 0; + int i = 0; + + Point p0 = null, p1 = null; + Point q0, q1; + + int count = poly.Points.Count; + + foreach (var seg in poly.Segments) + { + 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; + + if (q0 != null && q1 != null) + { + // The two segments are connected. + if (p0 == q1 && p1 != null) + { + if (IsBadAngle(q0, p0, p1)) + { + horrors++; + logger.Warning(String.Format("Bad segment angle found at index {0}.", i), + "PolygonValidator.HasBadAngles()"); + } + } + } + + i++; + } + + return horrors == 0; + } + + private static bool IsBadAngle(Point a, Point b, Point c, double eps = 0.0) + { + double x = DotProduct(a, b, c); + double y = CrossProductLength(a, b, c); + + return Math.Abs(Math.Atan2(y, x)) <= eps; + } + + // Returns the dot product . + private static double DotProduct(Point a, Point b, Point c) + { + // Calculate the dot product. + return (a.X - b.X) * (c.X - b.X) + (a.Y - b.Y) * (c.Y - b.Y); + } + + // Returns the length of cross product AB x BC. + private static double CrossProductLength(Point a, Point b, Point c) + { + // 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); + } + } +} diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj index a5c1417..7dd5d81 100644 --- a/Triangle.NET/Triangle/Triangle.csproj +++ b/Triangle.NET/Triangle/Triangle.csproj @@ -60,6 +60,7 @@ +