FindCircumcenter() public static method

Find the circumcenter of a triangle.
The result is returned both in terms of x-y coordinates and xi-eta (barycentric) coordinates. The xi-eta coordinate system is defined in terms of the triangle: the origin of the triangle is the origin of the coordinate system; the destination of the triangle is one unit along the xi axis; and the apex of the triangle is one unit along the eta axis. This procedure also returns the square of the length of the triangle's shortest edge.
public static FindCircumcenter ( System.Point torg, System.Point tdest, System.Point tapex, double &xi, double &eta ) : System.Point
torg System.Point Triangle point.
tdest System.Point Triangle point.
tapex System.Point Triangle point.
xi double Relative coordinate of new location.
eta double Relative coordinate of new location.
return System.Point
Ejemplo n.º 1
0
        /// <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.triangle) && (borg == badtri.triangorg) &&
                (bdest == badtri.triangdest) && (bapex == badtri.triangapex))
            {
                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 = Primitives.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 (Behavior.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, 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.
                    // (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.LprevSelf();
                    }

                    // Insert the circumcenter, searching from the edge of the triangle,
                    // and maintain the Delaunay property of the triangulation.
                    Osub tmp = default(Osub);
                    success = mesh.InsertVertex(newvertex, ref badotri, ref tmp, true, true);

                    if (success == InsertVertexResult.Successful)
                    {
                        newvertex.hash = mesh.hash_vtx++;
                        newvertex.id   = newvertex.hash;

                        mesh.vertices.Add(newvertex.hash, newvertex);

                        if (mesh.steinerleft > 0)
                        {
                            mesh.steinerleft--;
                        }
                    }
                    else if (success == InsertVertexResult.Encroaching)
                    {
                        // If the newly inserted vertex encroaches upon a subsegment,
                        // delete the new vertex.
                        mesh.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 (Behavior.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.");
                }
            }
        }
Ejemplo n.º 2
0
        private void SplitTriangle(BadTriangle badtri)
        {
            Point  point;
            Otri   otri = new Otri();
            double num  = 0;
            double num1 = 0;

            otri = badtri.poortri;
            Vertex vertex  = otri.Org();
            Vertex vertex1 = otri.Dest();
            Vertex vertex2 = otri.Apex();

            if (!Otri.IsDead(otri.triangle) && vertex == badtri.triangorg && vertex1 == badtri.triangdest && vertex2 == badtri.triangapex)
            {
                bool flag = false;
                point = (this.behavior.fixedArea || this.behavior.VarArea ? Primitives.FindCircumcenter(vertex, vertex1, vertex2, ref num, ref num1, this.behavior.offconstant) : this.newLocation.FindLocation(vertex, vertex1, vertex2, ref num, ref num1, true, otri));
                if ((point.x != vertex.x || point.y != vertex.y) && (point.x != vertex1.x || point.y != vertex1.y) && (point.x != vertex2.x || point.y != vertex2.y))
                {
                    Vertex vertex3 = new Vertex(point.x, point.y, 0, this.mesh.nextras)
                    {
                        type = VertexType.FreeVertex
                    };
                    for (int i = 0; i < this.mesh.nextras; i++)
                    {
                        vertex3.attributes[i] = vertex.attributes[i] + num * (vertex1.attributes[i] - vertex.attributes[i]) + num1 * (vertex2.attributes[i] - vertex.attributes[i]);
                    }
                    if (num1 < num)
                    {
                        otri.LprevSelf();
                    }
                    Osub osub = new Osub();
                    InsertVertexResult insertVertexResult = this.mesh.InsertVertex(vertex3, ref otri, ref osub, true, true);
                    if (insertVertexResult == InsertVertexResult.Successful)
                    {
                        Mesh mesh    = this.mesh;
                        int  hashVtx = mesh.hash_vtx;
                        mesh.hash_vtx = hashVtx + 1;
                        vertex3.hash  = hashVtx;
                        vertex3.id    = vertex3.hash;
                        this.mesh.vertices.Add(vertex3.hash, vertex3);
                        if (this.mesh.steinerleft > 0)
                        {
                            Mesh mesh1 = this.mesh;
                            mesh1.steinerleft = mesh1.steinerleft - 1;
                        }
                    }
                    else if (insertVertexResult == InsertVertexResult.Encroaching)
                    {
                        this.mesh.UndoVertex();
                    }
                    else if (insertVertexResult != InsertVertexResult.Violating && Behavior.Verbose)
                    {
                        this.logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
                        flag = true;
                    }
                }
                else if (Behavior.Verbose)
                {
                    this.logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()");
                    flag = true;
                }
                if (flag)
                {
                    this.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.");
                }
            }
        }