/// <summary>
        /// Inserts a vertex at the circumcenter of a triangle. Deletes
        /// the newly inserted vertex if it encroaches upon a segment.
        /// </summary>
        /// <param name="badtri"></param>
        private void SplitTriangle(BadTriangle badtri)
        {
            Otri               badotri = default(Otri);
            Vertex             borg, bdest, bapex;
            Point              newloc; // Location of the new vertex
            float              xi = 0, eta = 0;
            InsertVertexResult success;
            bool               errorflag;

            badotri = badtri.poortri;
            borg    = badotri.Org();
            bdest   = badotri.Dest();
            bapex   = badotri.Apex();

            // Make sure that this triangle is still the same triangle it was
            // when it was tested and determined to be of bad quality.
            // Subsequent transformations may have made it a different triangle.
            if (!Otri.IsDead(badotri.tri) && (borg == badtri.org) &&
                (bdest == badtri.dest) && (bapex == badtri.apex))
            {
                errorflag = false;
                // Create a new vertex at the triangle's circumcenter.

                // Using the original (simpler) Steiner point location method
                // for mesh refinement.
                // TODO: NewLocation doesn't work for refinement. Why? Maybe
                // reset VertexType?
                if (behavior.fixedArea || behavior.VarArea)
                {
                    newloc = predicates.FindCircumcenter(borg, bdest, bapex, ref xi, ref eta, behavior.offconstant);
                }
                else
                {
                    newloc = newLocation.FindLocation(borg, bdest, bapex, ref xi, ref eta, true, badotri);
                }

                // Check whether the new vertex lies on a triangle vertex.
                if (((newloc.x == borg.x) && (newloc.y == borg.y)) ||
                    ((newloc.x == bdest.x) && (newloc.y == bdest.y)) ||
                    ((newloc.x == bapex.x) && (newloc.y == bapex.y)))
                {
                    if (Log.Verbose)
                    {
                        logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
                        errorflag = true;
                    }
                }
                else
                {
                    // The new vertex must be in the interior, and therefore is a
                    // free vertex with a marker of zero.
                    Vertex newvertex = new Vertex(newloc.x, newloc.y, 0
#if USE_ATTRIBS
                                                  , mesh.nextras
#endif
                                                  );

                    newvertex.type = VertexType.FreeVertex;

                    // 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.
                    // (If the angle org-apex-dest exceeds 90 degrees, then the
                    // circumcenter lies outside the org-dest edge, and eta is
                    // negative.  Roundoff error might prevent eta from being
                    // negative when it should be, so I test eta against xi.)
                    if (eta < xi)
                    {
                        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);
                    success = _TriangleNetMesh.InsertVertex(newvertex, ref badotri, ref tmp, true, true);

                    if (success == InsertVertexResult.Successful)
                    {
                        newvertex.hash = _TriangleNetMesh.hash_vtx++;
                        newvertex.id   = newvertex.hash;
#if USE_ATTRIBS
                        if (mesh.nextras > 0)
                        {
                            Interpolation.InterpolateAttributes(newvertex, newvertex.tri.tri, mesh.nextras);
                        }
#endif
#if USE_Z
                        Interpolation.InterpolateZ(newvertex, newvertex.tri.tri);
#endif
                        _TriangleNetMesh.vertices.Add(newvertex.hash, newvertex);

                        if (_TriangleNetMesh.steinerleft > 0)
                        {
                            _TriangleNetMesh.steinerleft--;
                        }
                    }
                    else if (success == InsertVertexResult.Encroaching)
                    {
                        // If the newly inserted vertex encroaches upon a subsegment,
                        // delete the new vertex.
                        _TriangleNetMesh.UndoVertex();
                    }
                    else if (success == InsertVertexResult.Violating)
                    {
                        // Failed to insert the new vertex, but some subsegment was
                        // marked as being encroached.
                    }
                    else
                    {   // success == DUPLICATEVERTEX
                        // Couldn't insert the new vertex because a vertex is already there.
                        if (Log.Verbose)
                        {
                            logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
                            errorflag = true;
                        }
                    }
                }
                if (errorflag)
                {
                    logger.Error("The new vertex is at the circumcenter of triangle: This probably "
                                 + "means that I am trying to refine triangles to a smaller size than can be "
                                 + "accommodated by the finite precision of floating point arithmetic.",
                                 "Quality.SplitTriangle()");

                    throw new Exception("The new vertex is at the circumcenter of triangle.");
                }
            }
        }