From 14ee9120bd10f7e813d9160520df0b7883ad5b6f Mon Sep 17 00:00:00 2001 From: "SND\\wo80_cp" Date: Sun, 27 Sep 2015 20:19:51 +0000 Subject: [PATCH] Changed IPolygon interface; Fix #10971 git-svn-id: https://triangle.svn.codeplex.com/svn@77342 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5 --- Triangle.NET/Triangle/Geometry/Contour.cs | 88 ++++++++++----- Triangle.NET/Triangle/Geometry/IPolygon.cs | 57 +++++++--- Triangle.NET/Triangle/Geometry/Polygon.cs | 101 +++++++++++++----- Triangle.NET/Triangle/Mesh.cs | 9 ++ .../Triangle/Meshing/QualityMesher.cs | 70 ++++++++++-- .../Triangle/Smoothing/SimpleSmoother.cs | 6 +- 6 files changed, 250 insertions(+), 81 deletions(-) diff --git a/Triangle.NET/Triangle/Geometry/Contour.cs b/Triangle.NET/Triangle/Geometry/Contour.cs index 7ddb23d..fe7e35c 100644 --- a/Triangle.NET/Triangle/Geometry/Contour.cs +++ b/Triangle.NET/Triangle/Geometry/Contour.cs @@ -8,33 +8,72 @@ namespace TriangleNet.Geometry { using System; using System.Collections.Generic; - + public class Contour { int marker; + bool convex; + + /// + /// Gets or sets the list of points making up the contour. + /// public List Points { get; set; } /// /// Initializes a new instance of the class. /// - public Contour(IEnumerable points, int marker) + /// The points that make up the contour. + public Contour(IEnumerable points) + : this(points, 0, false) { - this.Points = new List(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) + /// + /// Initializes a new instance of the class. + /// + /// The points that make up the contour. + /// Contour marker. + public Contour(IEnumerable points, int marker) + : this(points, marker, false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The points that make up the contour. + /// Contour marker. + /// The hole is convex. + public Contour(IEnumerable points, int marker, bool convex) + { + AddPoints(points); + + this.marker = marker; + this.convex = convex; + } + + public List GetSegments() + { + var segments = new List(); + + 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; + } + + public Point FindInteriorPoint() { if (convex) { @@ -58,24 +97,17 @@ namespace TriangleNet.Geometry return FindPointInPolygon(this.Points); } - public List GetSegments() + private void AddPoints(IEnumerable points) { - var segments = new List(); + this.Points = new List(points); - var p = this.Points; + int count = Points.Count - 1; - int count = p.Count - 1; - - for (int i = 0; i < count; i++) + // Check if first vertex equals last vertex. + if (Points[0] == Points[count]) { - // Add segments to polygon. - segments.Add(new Segment(p[i], p[i + 1], marker)); + Points.RemoveAt(count); } - - // Close the contour. - segments.Add(new Segment(p[count], p[0], marker)); - - return segments; } private static Point FindPointInPolygon(List contour) diff --git a/Triangle.NET/Triangle/Geometry/IPolygon.cs b/Triangle.NET/Triangle/Geometry/IPolygon.cs index 19475db..e420586 100644 --- a/Triangle.NET/Triangle/Geometry/IPolygon.cs +++ b/Triangle.NET/Triangle/Geometry/IPolygon.cs @@ -6,8 +6,8 @@ namespace TriangleNet.Geometry { + using System; using System.Collections.Generic; - using TriangleNet.Topology; /// /// Polygon interface. @@ -44,21 +44,10 @@ namespace TriangleNet.Geometry /// bool HasSegmentMarkers { get; set; } - /// - /// Adds a contour to the polygon. - /// - /// Points making up the contour. - /// Contour marker. - /// Treat contour as a hole (interior boundary). - /// The hole is convex. + [Obsolete("Use polygon.Add(contour) method instead.")] void AddContour(IEnumerable points, int marker, bool hole, bool convex); - /// - /// Adds a contour to the polygon. - /// - /// Points making up the contour. - /// Contour marker. - /// Point inside the contour, making it a hole. + [Obsolete("Use polygon.Add(contour) method instead.")] void AddContour(IEnumerable points, int marker, Point hole); /// @@ -66,5 +55,45 @@ namespace TriangleNet.Geometry /// /// Rectangle defining an axis-aligned bounding box. Rectangle Bounds(); + + /// + /// Add a vertex to the polygon. + /// + /// The vertex to insert. + void Add(Vertex vertex); + + /// + /// Add a segment to the polygon. + /// + /// The segment to insert. + void Add(ISegment segment); + + /// + /// Add a segment to the polygon. + /// + /// The segment to insert. + /// If true, both endpoints will be added to the points list. + void Add(ISegment segment, bool insert); + + /// + /// Add a segment to the polygon. + /// + /// The segment to insert. + /// The index of the segment endpoint to add to the points list (must be 0 or 1). + void Add(ISegment segment, int index); + + /// + /// Add a contour to the polygon. + /// + /// The contour to insert. + /// Treat contour as a hole. + void Add(Contour contour, bool hole = false); + + /// + /// Add a contour to the polygon. + /// + /// The contour to insert. + /// Point inside the contour, making it a hole. + void Add(Contour contour, Point hole); } } diff --git a/Triangle.NET/Triangle/Geometry/Polygon.cs b/Triangle.NET/Triangle/Geometry/Polygon.cs index 3c2f955..82447ab 100644 --- a/Triangle.NET/Triangle/Geometry/Polygon.cs +++ b/Triangle.NET/Triangle/Geometry/Polygon.cs @@ -8,7 +8,6 @@ namespace TriangleNet.Geometry { using System; using System.Collections.Generic; - using TriangleNet.Topology; /// /// A polygon represented as a planar straight line graph. @@ -21,37 +20,37 @@ namespace TriangleNet.Geometry List segments; - /// + /// public List Points { get { return points; } } - /// + /// public List Holes { get { return holes; } } - /// + /// public List Regions { get { return regions; } } - /// + /// public List Segments { get { return segments; } } - /// + /// public bool HasPointMarkers { get; set; } - /// + /// public bool HasSegmentMarkers { get; set; } - /// + /// public int Count { get { return points.Count; } @@ -91,35 +90,20 @@ namespace TriangleNet.Geometry HasSegmentMarkers = markers; } - /// + [Obsolete("Use polygon.Add(contour) method instead.")] public void AddContour(IEnumerable points, int marker = 0, bool hole = false, bool convex = false) { - var c = new Contour(points, marker); - - this.points.AddRange(c.Points); - - this.segments.AddRange(c.GetSegments()); - - if (hole) - { - this.holes.Add(c.FindInteriorPoint(convex)); - } + this.Add(new Contour(points, marker, convex), hole); } - /// + [Obsolete("Use polygon.Add(contour) method instead.")] public void AddContour(IEnumerable points, int marker, Point hole) { - var c = new Contour(points, marker); - - this.points.AddRange(c.Points); - - this.segments.AddRange(c.GetSegments()); - - this.holes.Add(hole); + this.Add(new Contour(points, marker), hole); } - /// + /// public Rectangle Bounds() { var bounds = new Rectangle(); @@ -131,6 +115,7 @@ namespace TriangleNet.Geometry /// /// Add a vertex to the polygon. /// + /// The vertex to insert. public void Add(Vertex vertex) { this.points.Add(vertex); @@ -139,9 +124,69 @@ namespace TriangleNet.Geometry /// /// Add a segment to the polygon. /// + /// The segment to insert. public void Add(ISegment segment) { this.segments.Add(segment); } + + /// + /// Add a segment to the polygon. + /// + /// The segment to insert. + /// If true, both endpoints will be added to the points list. + public void Add(ISegment segment, bool insert) + { + this.segments.Add(segment); + + if (insert) + { + this.points.Add(segment.GetVertex(0)); + this.points.Add(segment.GetVertex(1)); + } + } + + /// + /// Add a segment to the polygon. + /// + /// The segment to insert. + /// The index of the segment endpoint to add to the points list (must be 0 or 1). + public void Add(ISegment segment, int index) + { + this.segments.Add(segment); + + this.points.Add(segment.GetVertex(index)); + } + + /// + /// Add a contour to the polygon. + /// + /// The contour to insert. + /// Treat contour as a hole. + public void Add(Contour contour, bool hole = false) + { + if (hole) + { + this.Add(contour, contour.FindInteriorPoint()); + } + else + { + this.points.AddRange(contour.Points); + this.segments.AddRange(contour.GetSegments()); + } + } + + /// + /// Add a contour to the polygon. + /// + /// The contour to insert. + /// Point inside the contour, making it a hole. + public void Add(Contour contour, Point hole) + { + this.points.AddRange(contour.Points); + this.segments.AddRange(contour.GetSegments()); + + this.holes.Add(hole); + } } } diff --git a/Triangle.NET/Triangle/Mesh.cs b/Triangle.NET/Triangle/Mesh.cs index 39a359b..8b1b46e 100644 --- a/Triangle.NET/Triangle/Mesh.cs +++ b/Triangle.NET/Triangle/Mesh.cs @@ -884,6 +884,15 @@ namespace TriangleNet // The insertion is successful by default, unless an encroached // subsegment is found. success = InsertVertexResult.Successful; + + if (newvertex.tri.tri != null) + { + // Store the coordinates of the triangle that contains newvertex. + newvertex.tri.SetOrg(rightvertex); + newvertex.tri.SetDest(leftvertex); + newvertex.tri.SetApex(botvertex); + } + // Circle around the newly inserted vertex, checking each edge opposite it // for the Delaunay property. Non-Delaunay edges are flipped. 'horiz' is // always the edge being checked. 'first' marks where to stop circling. diff --git a/Triangle.NET/Triangle/Meshing/QualityMesher.cs b/Triangle.NET/Triangle/Meshing/QualityMesher.cs index d566463..4cb967b 100644 --- a/Triangle.NET/Triangle/Meshing/QualityMesher.cs +++ b/Triangle.NET/Triangle/Meshing/QualityMesher.cs @@ -30,6 +30,10 @@ namespace TriangleNet.Meshing ILog logger; + // Stores the vertices of the triangle that contains newvertex + // in SplitTriangle method. + Triangle newvertex_tri; + public QualityMesher(Mesh mesh, IPredicates predicates) { logger = Log.Instance; @@ -43,6 +47,8 @@ namespace TriangleNet.Meshing this.behavior = mesh.behavior; newLocation = new NewLocation(mesh, predicates); + + newvertex_tri = new Triangle(); } /// @@ -683,6 +689,54 @@ namespace TriangleNet.Meshing } } + /// + /// Linear interpolation of vertex attributes. + /// + /// + private void InterpolateAttribs(Vertex newvertex) + { + Vertex org = newvertex_tri.vertices[0]; + Vertex dest = newvertex_tri.vertices[1]; + Vertex apex = newvertex_tri.vertices[2]; + + double xdo, ydo, xao, yao; + double denominator; + double dx, dy; + double xi, eta; + + int nextras = mesh.nextras; + + // Compute the circumcenter of the triangle. + xdo = dest.x - org.x; + ydo = dest.y - org.y; + xao = apex.x - org.x; + yao = apex.y - org.y; + + denominator = 0.5 / (xdo * yao - xao * ydo); + + //dx = (yao * dodist - ydo * aodist) * denominator; + //dy = (xdo * aodist - xao * dodist) * denominator; + + dx = newvertex.x - org.x; + dy = newvertex.y - org.y; + + // To interpolate vertex attributes for the new vertex inserted at + // the circumcenter, define a coordinate system with a xi-axis, + // directed from the triangle's origin to its destination, and + // an eta-axis, directed from its origin to its apex. + // Calculate the xi and eta coordinates of the circumcenter. + xi = (yao * dx - xao * dy) * (2.0 * denominator); + eta = (xdo * dy - ydo * dx) * (2.0 * denominator); + + for (int i = 0; i < nextras; i++) + { + // Interpolate the vertex attributes. + newvertex.attributes[i] = org.attributes[i] + + xi * (dest.attributes[i] - org.attributes[i]) + + eta * (apex.attributes[i] - org.attributes[i]); + } + } + /// /// Inserts a vertex at the circumcenter of a triangle. Deletes /// the newly inserted vertex if it encroaches upon a segment. @@ -742,14 +796,6 @@ namespace TriangleNet.Meshing Vertex newvertex = new Vertex(newloc.x, newloc.y, 0, mesh.nextras); newvertex.type = VertexType.FreeVertex; - for (int i = 0; i < mesh.nextras; i++) - { - // Interpolate the vertex attributes at the circumcenter. - newvertex.attributes[i] = borg.attributes[i] - + xi * (bdest.attributes[i] - borg.attributes[i]) - + eta * (bapex.attributes[i] - borg.attributes[i]); - } - // Ensure that the handle 'badotri' does not represent the longest // edge of the triangle. This ensures that the circumcenter must // fall to the left of this edge, so point location will work. @@ -762,6 +808,9 @@ namespace TriangleNet.Meshing badotri.Lprev(); } + // Assign triangle for attributes interpolation. + newvertex.tri.tri = newvertex_tri; + // Insert the circumcenter, searching from the edge of the triangle, // and maintain the Delaunay property of the triangulation. Osub tmp = default(Osub); @@ -772,6 +821,11 @@ namespace TriangleNet.Meshing newvertex.hash = mesh.hash_vtx++; newvertex.id = newvertex.hash; + if (mesh.nextras > 0) + { + InterpolateAttribs(newvertex); + } + mesh.vertices.Add(newvertex.hash, newvertex); if (mesh.steinerleft > 0) diff --git a/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs index c47f4c5..67a4e9c 100644 --- a/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs +++ b/Triangle.NET/Triangle/Smoothing/SimpleSmoother.cs @@ -110,10 +110,10 @@ namespace TriangleNet.Smoothing p = edge.Origin; q = edge.Twin.Origin; - ai = p.X * q.Y - q.X * p.Y; + ai = p.x * q.y - q.x * p.y; atmp += ai; - xtmp += (q.X + p.X) * ai; - ytmp += (q.Y + p.Y) * ai; + xtmp += (q.x + p.x) * ai; + ytmp += (q.y + p.y) * ai; edge = edge.Next;