void CreateLocalTriangulationsBoundary(List <Tuple <Edge, TriangleBranch> > boundary, TriangleBranch previousBranch, Edge vertice, Vertex point) { if (vertice.MirrorOut != null) { VertexCircleRelation relation = vertice.MirrorOut.NextIn.EndVertex. IsRelativeToCircle(vertice.EndVertex, point, vertice.StartVertex); if (relation == VertexCircleRelation.Outside || relation == VertexCircleRelation.Cocircular) { boundary.Add(new Tuple <Edge, TriangleBranch>(vertice, previousBranch)); } else { var branch = new TriangleBranch(vertice.MirrorOut.IncludingTriangle, previousBranch); CreateLocalTriangulationsBoundary(boundary, branch, vertice.MirrorOut.NextIn, point); CreateLocalTriangulationsBoundary(boundary, branch, vertice.MirrorOut.NextIn.NextIn, point); _triangles.Remove(vertice.MirrorOut.IncludingTriangle); } } else { boundary.Add(new Tuple <Edge, TriangleBranch>(vertice, previousBranch)); } }
Tuple <Edge, Edge> AddSlice(Tuple <Edge, TriangleBranch> bound, Vertex point) { Edge vertice = bound.Item1; TriangleBranch branch = bound.Item2; var slice = new Triangle(vertice, point, 0, true); do { int j = 0; while (j < branch.Node.VerticesIncluded.Count) { Vertex pointToInclude = branch.Node.VerticesIncluded[j]; VertexVectorOrientation o1 = pointToInclude.IsRelativeToLine(vertice.NextIn), o2 = pointToInclude.IsRelativeToLine(vertice.NextIn.NextIn); if ((o2 == VertexVectorOrientation.ToTheLeftOf || o2 == VertexVectorOrientation.Colinear) && o1 == VertexVectorOrientation.ToTheLeftOf) { slice.VerticesIncluded.Add(pointToInclude); branch.Node.VerticesIncluded.Remove(pointToInclude); } else { j++; } } branch = branch.PreviousNode; }while (branch != null); _triangles.Add(slice); if (vertice.StartVertex == _m && vertice.EndVertex == _k) { _rightExtremeTriangle = slice; } return(new Tuple <Edge, Edge>(slice.Edges[2], slice.Edges[1])); }
void Triangulate() { #region Local Fields Edge firstVertice, secondVertice = null; TriangleBranch containingTriangleRoot = new TriangleBranch(), mirrorContainingTriangleRoot = new TriangleBranch(); var boundary = new List <Tuple <Edge, TriangleBranch> >(); Tuple <Edge, Edge> adjacentVertices = null; #endregion // End of Local Fields #region Rearrange data (I) _points.Sort(_yComparer); double xmin = _points.Min(p => p.X), xmax = _points.Max(p => p.X), ymin = _points[0].Y, ymax = _points[_points.Count - 1].Y, xo = (xmax + xmin) / 2D, yo = (ymax + ymin) / 2D, xdis = Math.Floor(xo), ydis = Math.Floor(yo); foreach (Vertex point in _points) { point.X -= xdis; point.Y -= ydis; } xmin -= xdis; ymin -= ydis; xo -= xdis; yo -= ydis; #endregion // End of Rearrange data (I) #region Create container triangle double radious = (RadiousIncreaseByPercent + 1) * Math.Sqrt(Math.Pow(xo - xmin, 2) + Math.Pow(yo - ymin, 2)), diam = 2 * radious, height = radious * Math.Sqrt(3); _k = new Vertex(xo, yo + diam, 0); _l = new Vertex(xo - height, yo - radious, 0); _m = new Vertex(xo + height, yo - radious, 0); _triangles.Add(new Triangle(_k, _l, _m, new List <Vertex>(_points))); _rightExtremeTriangle = _triangles[0]; #endregion // End of Create container triangle #region Construct the mesh of points foreach (Vertex point in _points) { Triangle containingTriangle = TriangleIncluding(point); containingTriangle.VerticesIncluded.Remove(point); containingTriangleRoot.Node = containingTriangle; containingTriangleRoot.PreviousNode = null; int i, j = i = 0; bool found = false; do { if (containingTriangle.Edges[i].EndVertex == _k) { found = true; } else { i++; } }while (!found); found = false; do { if (point.IsRelativeToLine(containingTriangle.Edges[j]) == VertexVectorOrientation.Colinear) { found = true; } else { j++; } }while (!found && j < 3); if (found) { for (int k = i; k < i + 3; k++) { if (k == j) { if (containingTriangle.Edges[j].MirrorOut != null) { firstVertice = containingTriangle.Edges[j].MirrorOut; CreateLocalTriangulationsBoundary(boundary, containingTriangleRoot, firstVertice.NextIn, point); mirrorContainingTriangleRoot.Node = firstVertice.IncludingTriangle; mirrorContainingTriangleRoot.PreviousNode = null; CreateLocalTriangulationsBoundary(boundary, mirrorContainingTriangleRoot, firstVertice.NextIn.NextIn, point); _triangles.Remove(firstVertice.IncludingTriangle); } else { boundary.Add(new Tuple <Edge, TriangleBranch>(containingTriangle.Edges[j], containingTriangleRoot)); } } else { CreateLocalTriangulationsBoundary(boundary, containingTriangleRoot, containingTriangle.Edges[k % 3], point); } } } else { for (j = i; j < i + 3; j++) { CreateLocalTriangulationsBoundary(boundary, containingTriangleRoot, containingTriangle.Edges[j % 3], point); } } _triangles.Remove(containingTriangle); Tuple <Edge, Edge> previousAdjacentVertices = AddSlice(boundary[0], point); firstVertice = previousAdjacentVertices.Item1; for (i = 1; i < boundary.Count; i++) { adjacentVertices = AddSlice(boundary[i], point); adjacentVertices.Item1.ConnectWithMirror(previousAdjacentVertices.Item2); previousAdjacentVertices = adjacentVertices; } adjacentVertices.Item2.ConnectWithMirror(firstVertice); boundary.Clear(); } #endregion // End of Construct the mesh of points #region Envelope in closed curved boundary EdgesRing closedBoundary = GetTriangulationsClosedBoundary(); closedBoundary.CurvePath(); closedBoundary.Triangulate(_triangles); #endregion // End of Envelope in closed curved boundary #region Apply edge constrains if (!(_constrains == null || _constrains.Count == 0)) { foreach (Tuple <Vertex, Vertex> constrain in _constrains) { if (!_points.Contains(constrain.Item1, _pComparer) || !_points.Contains(constrain.Item2, _pComparer)) { continue; } List <Tuple <EdgesPath, EdgesPath> > sequencesPairs = GetSequences(constrain.Item1, constrain.Item2); if (sequencesPairs == null) { continue; } foreach (Tuple <EdgesPath, EdgesPath> pair in sequencesPairs) { firstVertice = null; if (pair.Item1.Path.Count > 0) { firstVertice = pair.Item1.Triangulate(_triangles); } if (pair.Item2.Path.Count > 0) { secondVertice = pair.Item2.Triangulate(_triangles); } if (firstVertice != null && secondVertice != null) { firstVertice.ConnectWithMirror(secondVertice); } } } } #endregion // End of Apply edge constrains #region Rearrange data (II) foreach (Vertex point in _points) { point.X += xdis; point.Y += ydis; } #endregion // End of Rearrange data (II) }