/// <summary>
        /// Check if given triangle is blinded by given segment.
        /// </summary>
        /// <param name="tri">Triangle.</param>
        /// <param name="seg">Segments</param>
        /// <returns>Returns true, if the triangle is blinded.</returns>
        private bool TriangleIsBlinded(ref Otri tri, ref Osub seg)
        {
            Point c, pt;

            Vertex torg  = tri.Org();
            Vertex tdest = tri.Dest();
            Vertex tapex = tri.Apex();

            Vertex sorg  = seg.Org();
            Vertex sdest = seg.Dest();

            c = points[tri.tri.id];

            if (SegmentsIntersect(sorg, sdest, c, torg, out pt, true))
            {
                return(true);
            }

            if (SegmentsIntersect(sorg, sdest, c, tdest, out pt, true))
            {
                return(true);
            }

            if (SegmentsIntersect(sorg, sdest, c, tapex, out pt, true))
            {
                return(true);
            }

            return(false);
        }
Example #2
0
        public int CheckSeg4Encroach(ref Osub testsubseg)
        {
            double num;
            Vertex vertex;
            Otri   otri    = new Otri();
            Osub   osub    = new Osub();
            int    num1    = 0;
            int    num2    = 0;
            Vertex vertex1 = testsubseg.Org();
            Vertex vertex2 = testsubseg.Dest();

            testsubseg.TriPivot(ref otri);
            if (otri.triangle != Mesh.dummytri)
            {
                num2++;
                vertex = otri.Apex();
                num    = (vertex1.x - vertex.x) * (vertex2.x - vertex.x) + (vertex1.y - vertex.y) * (vertex2.y - vertex.y);
                if (num < 0 && (this.behavior.ConformingDelaunay || num * num >= (2 * this.behavior.goodAngle - 1) * (2 * this.behavior.goodAngle - 1) * ((vertex1.x - vertex.x) * (vertex1.x - vertex.x) + (vertex1.y - vertex.y) * (vertex1.y - vertex.y)) * ((vertex2.x - vertex.x) * (vertex2.x - vertex.x) + (vertex2.y - vertex.y) * (vertex2.y - vertex.y))))
                {
                    num1 = 1;
                }
            }
            testsubseg.Sym(ref osub);
            osub.TriPivot(ref otri);
            if (otri.triangle != Mesh.dummytri)
            {
                num2++;
                vertex = otri.Apex();
                num    = (vertex1.x - vertex.x) * (vertex2.x - vertex.x) + (vertex1.y - vertex.y) * (vertex2.y - vertex.y);
                if (num < 0 && (this.behavior.ConformingDelaunay || num * num >= (2 * this.behavior.goodAngle - 1) * (2 * this.behavior.goodAngle - 1) * ((vertex1.x - vertex.x) * (vertex1.x - vertex.x) + (vertex1.y - vertex.y) * (vertex1.y - vertex.y)) * ((vertex2.x - vertex.x) * (vertex2.x - vertex.x) + (vertex2.y - vertex.y) * (vertex2.y - vertex.y))))
                {
                    num1 = num1 + 2;
                }
            }
            if (num1 > 0 && (this.behavior.NoBisect == 0 || this.behavior.NoBisect == 1 && num2 == 2))
            {
                BadSubseg badSubseg = new BadSubseg();
                if (num1 != 1)
                {
                    badSubseg.encsubseg  = osub;
                    badSubseg.subsegorg  = vertex2;
                    badSubseg.subsegdest = vertex1;
                }
                else
                {
                    badSubseg.encsubseg  = testsubseg;
                    badSubseg.subsegorg  = vertex1;
                    badSubseg.subsegdest = vertex2;
                }
                this.badsubsegs.Enqueue(badSubseg);
            }
            return(num1);
        }
        private bool TriangleIsBlinded(ref Otri tri, ref Osub seg)
        {
            Point  point;
            Vertex vertex  = tri.Org();
            Vertex vertex1 = tri.Dest();
            Vertex vertex2 = tri.Apex();
            Vertex vertex3 = seg.Org();
            Vertex vertex4 = seg.Dest();
            Point  point1  = this.points[tri.triangle.id];

            if (this.SegmentsIntersect(vertex3, vertex4, point1, vertex, out point, true))
            {
                return(true);
            }
            if (this.SegmentsIntersect(vertex3, vertex4, point1, vertex1, out point, true))
            {
                return(true);
            }
            if (this.SegmentsIntersect(vertex3, vertex4, point1, vertex2, out point, true))
            {
                return(true);
            }
            return(false);
        }
        private void ConstructBoundaryCell(Vertex vertex)
        {
            VoronoiRegion region = new VoronoiRegion(vertex);

            regions.Add(region);

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Otri f_prev = default(Otri);
            Osub sf     = default(Osub);
            Osub sfn    = default(Osub);

            Vertex torg, tdest, tapex, sorg, sdest;
            Point  cc_f, cc_f_next, p;

            int n = _TriangleNetMesh.triangles.Count;

            // Call P the polygon (cell) in construction
            List <Point> vpoints = new List <Point>();

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            if (f_init.Org() != vertex)
            {
                throw new Exception("ConstructBoundaryCell: inconsistent topology.");
            }
            // Let f be initialized to f_init
            f_init.Copy(ref f);
            // Call f_next the next triangle counterclockwise around x
            f_init.Onext(ref f_next);

            f_init.Oprev(ref f_prev);

            // Is the border to the left?
            if (f_prev.tri.id != TriangleNetMesh.DUMMY)
            {
                // Go clockwise until we reach the border (or the initial triangle)
                while (f_prev.tri.id != TriangleNetMesh.DUMMY && !f_prev.Equals(f_init))
                {
                    f_prev.Copy(ref f);
                    f_prev.Oprev();
                }

                f.Copy(ref f_init);
                f.Onext(ref f_next);
            }

            if (f_prev.tri.id == TriangleNetMesh.DUMMY)
            {
                // For vertices on the domain boundaray, add the vertex. For
                // internal boundaries don't add it.
                p = new Point(vertex.x, vertex.y);

                p.id = n + segIndex++;
                segPoints.Add(p);
                vpoints.Add(p);
            }

            // Add midpoint of start triangles' edge.
            torg  = f.Org();
            tdest = f.Dest();
            p     = new Point((torg.x + tdest.x) / 2, (torg.y + tdest.y) / 2);

            p.id = n + segIndex++;
            segPoints.Add(p);
            vpoints.Add(p);

            // repeat ... until f = f_init
            do
            {
                // Call Lffnext the line going through the circumcenters of f and f_next
                cc_f = points[f.tri.id];

                if (f_next.tri.id == TriangleNetMesh.DUMMY)
                {
                    if (!f.tri.infected)
                    {
                        // Add last circumcenter
                        vpoints.Add(cc_f);
                    }

                    // Add midpoint of last triangles' edge (chances are it has already
                    // been added, so post process cell to remove duplicates???)
                    torg  = f.Org();
                    tapex = f.Apex();
                    p     = new Point((torg.x + tapex.x) / 2, (torg.y + tapex.y) / 2);

                    p.id = n + segIndex++;
                    segPoints.Add(p);
                    vpoints.Add(p);

                    break;
                }

                cc_f_next = points[f_next.tri.id];

                // if f is tagged non-blind then
                if (!f.tri.infected)
                {
                    // Insert the circumcenter of f into P
                    vpoints.Add(cc_f);

                    if (f_next.tri.infected)
                    {
                        // Call S_fnext the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.tri.hash];

                    sorg  = sf.Org();
                    sdest = sf.Dest();

                    // if f_next is tagged non-blind then
                    if (!f_next.tri.infected)
                    {
                        tdest = f.Dest();
                        tapex = f.Apex();

                        // Both circumcenters lie on the blinded side, but we
                        // have to add the intersection with the segment.

                        // Center of f edge dest->apex
                        Point bisec = new Point((tdest.x + tapex.x) / 2, (tdest.y + tapex.y) / 2);

                        // Find intersection of seg with line through f's bisector and circumcenter
                        if (SegmentsIntersect(sorg, sdest, bisec, cc_f, out p, false))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }

                        // Insert point Lf,f_next /\ Sf into P
                        if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // if Sf != Sf_next then
                        if (!sf.Equal(sfn))
                        {
                            // Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
                            if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                        else
                        {
                            // Both circumcenters lie on the blinded side, but we
                            // have to add the intersection with the segment.

                            // Center of f_next edge org->dest
                            Point bisec = new Point((torg.x + tdest.x) / 2, (torg.y + tdest.y) / 2);

                            // Find intersection of seg with line through f_next's bisector and circumcenter
                            if (SegmentsIntersect(sorg, sdest, bisec, cc_f_next, out p, false))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                    }
                }

                // f <- f_next
                f_next.Copy(ref f);

                // Call f_next the next triangle counterclockwise around x
                f_next.Onext();
            }while (!f.Equals(f_init));

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
        private void ConstructCell(Vertex vertex)
        {
            VoronoiRegion region = new VoronoiRegion(vertex);

            regions.Add(region);

            Otri f      = default(Otri);
            Otri f_init = default(Otri);
            Otri f_next = default(Otri);
            Osub sf     = default(Osub);
            Osub sfn    = default(Osub);

            Point cc_f, cc_f_next, p;

            int n = _TriangleNetMesh.triangles.Count;

            // Call P the polygon (cell) in construction
            List <Point> vpoints = new List <Point>();

            // Call f_init a triangle incident to x
            vertex.tri.Copy(ref f_init);

            if (f_init.Org() != vertex)
            {
                throw new Exception("ConstructCell: inconsistent topology.");
            }

            // Let f be initialized to f_init
            f_init.Copy(ref f);
            // Call f_next the next triangle counterclockwise around x
            f_init.Onext(ref f_next);

            // repeat ... until f = f_init
            do
            {
                // Call Lffnext the line going through the circumcenters of f and f_next
                cc_f      = points[f.tri.id];
                cc_f_next = points[f_next.tri.id];

                // if f is tagged non-blind then
                if (!f.tri.infected)
                {
                    // Insert the circumcenter of f into P
                    vpoints.Add(cc_f);

                    if (f_next.tri.infected)
                    {
                        // Call S_fnext the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // Insert point Lf,f_next /\ Sf_next into P
                        if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                }
                else
                {
                    // Call Sf the constrained edge blinding f
                    sf.seg = subsegMap[f.tri.hash];

                    // if f_next is tagged non-blind then
                    if (!f_next.tri.infected)
                    {
                        // Insert point Lf,f_next /\ Sf into P
                        if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
                        {
                            p.id = n + segIndex++;
                            segPoints.Add(p);
                            vpoints.Add(p);
                        }
                    }
                    else
                    {
                        // Call Sf_next the constrained edge blinding f_next
                        sfn.seg = subsegMap[f_next.tri.hash];

                        // if Sf != Sf_next then
                        if (!sf.Equal(sfn))
                        {
                            // Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
                            if (SegmentsIntersect(sf.Org(), sf.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }

                            if (SegmentsIntersect(sfn.Org(), sfn.Dest(), cc_f, cc_f_next, out p, true))
                            {
                                p.id = n + segIndex++;
                                segPoints.Add(p);
                                vpoints.Add(p);
                            }
                        }
                    }
                }

                // f <- f_next
                f_next.Copy(ref f);

                // Call f_next the next triangle counterclockwise around x
                f_next.Onext();
            }while (!f.Equals(f_init));

            // Output: Bounded Voronoi cell of x in counterclockwise order.
            region.Add(vpoints);
        }
Example #6
0
        /// <summary>
        /// Reconstruct a triangulation from its raw data representation.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <remarks>
        /// Reads an .ele file and reconstructs the original mesh.  If the -p switch
        /// is used, this procedure will also read a .poly file and reconstruct the
        /// subsegments of the original mesh.  If the -a switch is used, this
        /// procedure will also read an .area file and set a maximum area constraint
        /// on each triangle.
        ///
        /// Vertices that are not corners of triangles, such as nodes on edges of
        /// subparametric elements, are discarded.
        ///
        /// This routine finds the adjacencies between triangles (and subsegments)
        /// by forming one stack of triangles for each vertex. Each triangle is on
        /// three different stacks simultaneously. Each triangle's subsegment
        /// pointers are used to link the items in each stack. This memory-saving
        /// feature makes the code harder to read. The most important thing to keep
        /// in mind is that each triangle is removed from a stack precisely when
        /// the corresponding pointer is adjusted to refer to a subsegment rather
        /// than the next triangle of the stack.
        /// </remarks>
        public static int Reconstruct(Mesh mesh, InputGeometry input, ITriangle[] triangles)
        {
            int hullsize = 0;

            Otri tri           = default(Otri);
            Otri triangleleft  = default(Otri);
            Otri checktri      = default(Otri);
            Otri checkleft     = default(Otri);
            Otri checkneighbor = default(Otri);
            Osub subseg        = default(Osub);

            List <Otri>[] vertexarray; // Triangle
            Otri          prevlink;    // Triangle
            Otri          nexttri;     // Triangle
            Vertex        tdest, tapex;
            Vertex        checkdest, checkapex;
            Vertex        shorg;
            Vertex        segmentorg, segmentdest;

            int[] corner = new int[3];
            int[] end    = new int[2];
            //bool segmentmarkers = false;
            int  boundmarker;
            int  aroundvertex;
            bool notfound;
            int  i = 0;

            int elements         = triangles == null ? 0 : triangles.Length;
            int numberofsegments = input.segments.Count;

            mesh.inelements = elements;
            mesh.regions.AddRange(input.regions);

            // Create the triangles.
            for (i = 0; i < mesh.inelements; i++)
            {
                mesh.MakeTriangle(ref tri);
                // Mark the triangle as living.
                //tri.triangle.neighbors[0].triangle = tri.triangle;
            }

            if (mesh.behavior.Poly)
            {
                mesh.insegments = numberofsegments;

                // Create the subsegments.
                for (i = 0; i < mesh.insegments; i++)
                {
                    mesh.MakeSegment(ref subseg);
                    // Mark the subsegment as living.
                    //subseg.ss.subsegs[0].ss = subseg.ss;
                }
            }

            // Allocate a temporary array that maps each vertex to some adjacent
            // triangle. I took care to allocate all the permanent memory for
            // triangles and subsegments first.
            vertexarray = new List <Otri> [mesh.vertices.Count];
            // Each vertex is initially unrepresented.
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                Otri tmp = default(Otri);
                tmp.triangle   = Mesh.dummytri;
                vertexarray[i] = new List <Otri>(3);
                vertexarray[i].Add(tmp);
            }

            i = 0;

            // Read the triangles from the .ele file, and link
            // together those that share an edge.
            foreach (var item in mesh.triangles.Values)
            {
                tri.triangle = item;

                corner[0] = triangles[i].P0;
                corner[1] = triangles[i].P1;
                corner[2] = triangles[i].P2;

                // Copy the triangle's three corners.
                for (int j = 0; j < 3; j++)
                {
                    if ((corner[j] < 0) || (corner[j] >= mesh.invertices))
                    {
                        SimpleLog.Instance.Error("Triangle has an invalid vertex index.", "MeshReader.Reconstruct()");
                        throw new Exception("Triangle has an invalid vertex index.");
                    }
                }

                // Read the triangle's attributes.
                tri.triangle.region = triangles[i].Region;

                // TODO: VarArea
                if (mesh.behavior.VarArea)
                {
                    tri.triangle.area = triangles[i].Area;
                }

                // Set the triangle's vertices.
                tri.orient = 0;
                tri.SetOrg(mesh.vertices[corner[0]]);
                tri.SetDest(mesh.vertices[corner[1]]);
                tri.SetApex(mesh.vertices[corner[2]]);

                // Try linking the triangle to others that share these vertices.
                for (tri.orient = 0; tri.orient < 3; tri.orient++)
                {
                    // Take the number for the origin of triangleloop.
                    aroundvertex = corner[tri.orient];
                    int index = vertexarray[aroundvertex].Count - 1;
                    // Look for other triangles having this vertex.
                    nexttri = vertexarray[aroundvertex][index];
                    // Link the current triangle to the next one in the stack.
                    //tri.triangle.neighbors[tri.orient] = nexttri;
                    // Push the current triangle onto the stack.
                    vertexarray[aroundvertex].Add(tri);

                    checktri = nexttri;

                    if (checktri.triangle != Mesh.dummytri)
                    {
                        tdest = tri.Dest();
                        tapex = tri.Apex();

                        // Look for other triangles that share an edge.
                        do
                        {
                            checkdest = checktri.Dest();
                            checkapex = checktri.Apex();

                            if (tapex == checkdest)
                            {
                                // The two triangles share an edge; bond them together.
                                tri.Lprev(ref triangleleft);
                                triangleleft.Bond(ref checktri);
                            }
                            if (tdest == checkapex)
                            {
                                // The two triangles share an edge; bond them together.
                                checktri.Lprev(ref checkleft);
                                tri.Bond(ref checkleft);
                            }
                            // Find the next triangle in the stack.
                            index--;
                            nexttri = vertexarray[aroundvertex][index];

                            checktri = nexttri;
                        } while (checktri.triangle != Mesh.dummytri);
                    }
                }

                i++;
            }

            // Prepare to count the boundary edges.
            hullsize = 0;
            if (mesh.behavior.Poly)
            {
                // Read the segments from the .poly file, and link them
                // to their neighboring triangles.
                boundmarker = 0;
                i           = 0;
                foreach (var item in mesh.subsegs.Values)
                {
                    subseg.seg = item;

                    end[0]      = input.segments[i].P0;
                    end[1]      = input.segments[i].P1;
                    boundmarker = input.segments[i].Boundary;

                    for (int j = 0; j < 2; j++)
                    {
                        if ((end[j] < 0) || (end[j] >= mesh.invertices))
                        {
                            SimpleLog.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
                            throw new Exception("Segment has an invalid vertex index.");
                        }
                    }

                    // set the subsegment's vertices.
                    subseg.orient = 0;
                    segmentorg    = mesh.vertices[end[0]];
                    segmentdest   = mesh.vertices[end[1]];
                    subseg.SetOrg(segmentorg);
                    subseg.SetDest(segmentdest);
                    subseg.SetSegOrg(segmentorg);
                    subseg.SetSegDest(segmentdest);
                    subseg.seg.boundary = boundmarker;
                    // Try linking the subsegment to triangles that share these vertices.
                    for (subseg.orient = 0; subseg.orient < 2; subseg.orient++)
                    {
                        // Take the number for the destination of subsegloop.
                        aroundvertex = end[1 - subseg.orient];
                        int index = vertexarray[aroundvertex].Count - 1;
                        // Look for triangles having this vertex.
                        prevlink = vertexarray[aroundvertex][index];
                        nexttri  = vertexarray[aroundvertex][index];

                        checktri = nexttri;
                        shorg    = subseg.Org();
                        notfound = true;
                        // Look for triangles having this edge.  Note that I'm only
                        // comparing each triangle's destination with the subsegment;
                        // each triangle's apex is handled through a different vertex.
                        // Because each triangle appears on three vertices' lists, each
                        // occurrence of a triangle on a list can (and does) represent
                        // an edge.  In this way, most edges are represented twice, and
                        // every triangle-subsegment bond is represented once.
                        while (notfound && (checktri.triangle != Mesh.dummytri))
                        {
                            checkdest = checktri.Dest();

                            if (shorg == checkdest)
                            {
                                // We have a match. Remove this triangle from the list.
                                //prevlink = vertexarray[aroundvertex][index];
                                vertexarray[aroundvertex].Remove(prevlink);
                                // Bond the subsegment to the triangle.
                                checktri.SegBond(ref subseg);
                                // Check if this is a boundary edge.
                                checktri.Sym(ref checkneighbor);
                                if (checkneighbor.triangle == Mesh.dummytri)
                                {
                                    // The next line doesn't insert a subsegment (because there's
                                    // already one there), but it sets the boundary markers of
                                    // the existing subsegment and its vertices.
                                    mesh.InsertSubseg(ref checktri, 1);
                                    hullsize++;
                                }
                                notfound = false;
                            }
                            index--;
                            // Find the next triangle in the stack.
                            prevlink = vertexarray[aroundvertex][index];
                            nexttri  = vertexarray[aroundvertex][index];

                            checktri = nexttri;
                        }
                    }

                    i++;
                }
            }

            // Mark the remaining edges as not being attached to any subsegment.
            // Also, count the (yet uncounted) boundary edges.
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                // Search the stack of triangles adjacent to a vertex.
                int index = vertexarray[i].Count - 1;
                nexttri  = vertexarray[i][index];
                checktri = nexttri;

                while (checktri.triangle != Mesh.dummytri)
                {
                    // Find the next triangle in the stack before this
                    // information gets overwritten.
                    index--;
                    nexttri = vertexarray[i][index];
                    // No adjacent subsegment.  (This overwrites the stack info.)
                    checktri.SegDissolve();
                    checktri.Sym(ref checkneighbor);
                    if (checkneighbor.triangle == Mesh.dummytri)
                    {
                        mesh.InsertSubseg(ref checktri, 1);
                        hullsize++;
                    }

                    checktri = nexttri;
                }
            }

            return(hullsize);
        }
        /// <summary>
        /// Split all the encroached subsegments.
        /// </summary>
        /// <param name="triflaws">A flag that specifies whether one should take
        /// note of new bad triangles that result from inserting vertices to repair
        /// encroached subsegments.</param>
        /// <remarks>
        /// Each encroached subsegment is repaired by splitting it - inserting a
        /// vertex at or near its midpoint.  Newly inserted vertices may encroach
        /// upon other subsegments; these are also repaired.
        /// </remarks>
        private void SplitEncSegs(bool triflaws)
        {
            Otri               enctri     = default(Otri);
            Otri               testtri    = default(Otri);
            Osub               testsh     = default(Osub);
            Osub               currentenc = default(Osub);
            BadSubseg          seg;
            Vertex             eorg, edest, eapex;
            Vertex             newvertex;
            InsertVertexResult success;
            float              segmentlength, nearestpoweroftwo;
            float              split;
            float              multiplier, divisor;
            bool               acuteorg, acuteorg2, acutedest, acutedest2;

            // Note that steinerleft == -1 if an unlimited number
            // of Steiner points is allowed.
            while (badsubsegs.Count > 0)
            {
                if (mesh.steinerleft == 0)
                {
                    break;
                }

                seg = badsubsegs.Dequeue();

                currentenc = seg.encsubseg;
                eorg       = currentenc.Org();
                edest      = currentenc.Dest();
                // Make sure that this segment is still the same segment it was
                // when it was determined to be encroached.  If the segment was
                // enqueued multiple times (because several newly inserted
                // vertices encroached it), it may have already been split.
                if (!Osub.IsDead(currentenc.seg) && (eorg == seg.subsegorg) && (edest == seg.subsegdest))
                {
                    // To decide where to split a segment, we need to know if the
                    // segment shares an endpoint with an adjacent segment.
                    // The concern is that, if we simply split every encroached
                    // segment in its center, two adjacent segments with a small
                    // angle between them might lead to an infinite loop; each
                    // vertex added to split one segment will encroach upon the
                    // other segment, which must then be split with a vertex that
                    // will encroach upon the first segment, and so on forever.
                    // To avoid this, imagine a set of concentric circles, whose
                    // radii are powers of two, about each segment endpoint.
                    // These concentric circles determine where the segment is
                    // split. (If both endpoints are shared with adjacent
                    // segments, split the segment in the middle, and apply the
                    // concentric circles for later splittings.)

                    // Is the origin shared with another segment?
                    currentenc.TriPivot(ref enctri);
                    enctri.Lnext(ref testtri);
                    testtri.SegPivot(ref testsh);
                    acuteorg = testsh.seg != Mesh.dummysub;
                    // Is the destination shared with another segment?
                    testtri.LnextSelf();
                    testtri.SegPivot(ref testsh);
                    acutedest = testsh.seg != Mesh.dummysub;

                    // If we're using Chew's algorithm (rather than Ruppert's)
                    // to define encroachment, delete free vertices from the
                    // subsegment's diametral circle.
                    if (!behavior.ConformingDelaunay && !acuteorg && !acutedest)
                    {
                        eapex = enctri.Apex();
                        while ((eapex.type == VertexType.FreeVertex) &&
                               ((eorg.x - eapex.x) * (edest.x - eapex.x) +
                                (eorg.y - eapex.y) * (edest.y - eapex.y) < 0.0))
                        {
                            mesh.DeleteVertex(ref testtri);
                            currentenc.TriPivot(ref enctri);
                            eapex = enctri.Apex();
                            enctri.Lprev(ref testtri);
                        }
                    }

                    // Now, check the other side of the segment, if there's a triangle there.
                    enctri.Sym(ref testtri);
                    if (testtri.triangle != Mesh.dummytri)
                    {
                        // Is the destination shared with another segment?
                        testtri.LnextSelf();
                        testtri.SegPivot(ref testsh);
                        acutedest2 = testsh.seg != Mesh.dummysub;
                        acutedest  = acutedest || acutedest2;
                        // Is the origin shared with another segment?
                        testtri.LnextSelf();
                        testtri.SegPivot(ref testsh);
                        acuteorg2 = testsh.seg != Mesh.dummysub;
                        acuteorg  = acuteorg || acuteorg2;

                        // Delete free vertices from the subsegment's diametral circle.
                        if (!behavior.ConformingDelaunay && !acuteorg2 && !acutedest2)
                        {
                            eapex = testtri.Org();
                            while ((eapex.type == VertexType.FreeVertex) &&
                                   ((eorg.x - eapex.x) * (edest.x - eapex.x) +
                                    (eorg.y - eapex.y) * (edest.y - eapex.y) < 0.0))
                            {
                                mesh.DeleteVertex(ref testtri);
                                enctri.Sym(ref testtri);
                                eapex = testtri.Apex();
                                testtri.LprevSelf();
                            }
                        }
                    }

                    // Use the concentric circles if exactly one endpoint is shared
                    // with another adjacent segment.
                    if (acuteorg || acutedest)
                    {
                        segmentlength = UnityEngine.Mathf.Sqrt((edest.x - eorg.x) * (edest.x - eorg.x) +
                                                               (edest.y - eorg.y) * (edest.y - eorg.y));
                        // Find the power of two that most evenly splits the segment.
                        // The worst case is a 2:1 ratio between subsegment lengths.
                        nearestpoweroftwo = 1.0f;
                        while (segmentlength > 3.0f * nearestpoweroftwo)
                        {
                            nearestpoweroftwo *= 2.0f;
                        }
                        while (segmentlength < 1.5f * nearestpoweroftwo)
                        {
                            nearestpoweroftwo *= 0.5f;
                        }
                        // Where do we split the segment?
                        split = nearestpoweroftwo / segmentlength;
                        if (acutedest)
                        {
                            split = 1.0f - split;
                        }
                    }
                    else
                    {
                        // If we're not worried about adjacent segments, split
                        // this segment in the middle.
                        split = 0.5f;
                    }

                    // Create the new vertex (interpolate coordinates).
                    newvertex = new Vertex(
                        eorg.x + split * (edest.x - eorg.x),
                        eorg.y + split * (edest.y - eorg.y),
                        currentenc.Mark(),
                        mesh.nextras);

                    newvertex.type = VertexType.SegmentVertex;

                    newvertex.hash = mesh.hash_vtx++;
                    newvertex.id   = newvertex.hash;

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

                    // Interpolate attributes.
                    for (int i = 0; i < mesh.nextras; i++)
                    {
                        newvertex.attributes[i] = eorg.attributes[i]
                                                  + split * (edest.attributes[i] - eorg.attributes[i]);
                    }

                    if (!Behavior.NoExact)
                    {
                        // Roundoff in the above calculation may yield a 'newvertex'
                        // that is not precisely collinear with 'eorg' and 'edest'.
                        // Improve collinearity by one step of iterative refinement.
                        multiplier = Primitives.CounterClockwise(eorg, edest, newvertex);
                        divisor    = ((eorg.x - edest.x) * (eorg.x - edest.x) +
                                      (eorg.y - edest.y) * (eorg.y - edest.y));
                        if ((multiplier != 0.0) && (divisor != 0.0))
                        {
                            multiplier = multiplier / divisor;
                            // Watch out for NANs.
                            if (!float.IsNaN(multiplier))
                            {
                                newvertex.x += multiplier * (edest.y - eorg.y);
                                newvertex.y += multiplier * (eorg.x - edest.x);
                            }
                        }
                    }

                    // Check whether the new vertex lies on an endpoint.
                    if (((newvertex.x == eorg.x) && (newvertex.y == eorg.y)) ||
                        ((newvertex.x == edest.x) && (newvertex.y == edest.y)))
                    {
                        logger.Error("Ran out of precision: I attempted to split a"
                                     + " segment to a smaller size than can be accommodated by"
                                     + " the finite precision of floating point arithmetic.",
                                     "Quality.SplitEncSegs()");

                        throw new Exception("Ran out of precision");
                    }
                    // Insert the splitting vertex.  This should always succeed.
                    success = mesh.InsertVertex(newvertex, ref enctri, ref currentenc, true, triflaws);
                    if ((success != InsertVertexResult.Successful) && (success != InsertVertexResult.Encroaching))
                    {
                        logger.Error("Failure to split a segment.", "Quality.SplitEncSegs()");
                        throw new Exception("Failure to split a segment.");
                    }
                    if (mesh.steinerleft > 0)
                    {
                        mesh.steinerleft--;
                    }
                    // Check the two new subsegments to see if they're encroached.
                    CheckSeg4Encroach(ref currentenc);
                    currentenc.NextSelf();
                    CheckSeg4Encroach(ref currentenc);
                }

                // Set subsegment's origin to NULL. This makes it possible to detect dead
                // badsubsegs when traversing the list of all badsubsegs.
                seg.subsegorg = null;
            }
        }
        /// <summary>
        /// Check a subsegment to see if it is encroached; add it to the list if it is.
        /// </summary>
        /// <param name="testsubseg">The subsegment to check.</param>
        /// <returns>Returns a nonzero value if the subsegment is encroached.</returns>
        /// <remarks>
        /// A subsegment is encroached if there is a vertex in its diametral lens.
        /// For Ruppert's algorithm (-D switch), the "diametral lens" is the
        /// diametral circle. For Chew's algorithm (default), the diametral lens is
        /// just big enough to enclose two isosceles triangles whose bases are the
        /// subsegment. Each of the two isosceles triangles has two angles equal
        /// to 'b.minangle'.
        ///
        /// Chew's algorithm does not require diametral lenses at all--but they save
        /// time. Any vertex inside a subsegment's diametral lens implies that the
        /// triangle adjoining the subsegment will be too skinny, so it's only a
        /// matter of time before the encroaching vertex is deleted by Chew's
        /// algorithm. It's faster to simply not insert the doomed vertex in the
        /// first place, which is why I use diametral lenses with Chew's algorithm.
        /// </remarks>
        public int CheckSeg4Encroach(ref Osub testsubseg)
        {
            Otri      neighbortri = default(Otri);
            Osub      testsym     = default(Osub);
            BadSubseg encroachedseg;
            float     dotproduct;
            int       encroached;
            int       sides;
            Vertex    eorg, edest, eapex;

            encroached = 0;
            sides      = 0;

            eorg  = testsubseg.Org();
            edest = testsubseg.Dest();
            // Check one neighbor of the subsegment.
            testsubseg.TriPivot(ref neighbortri);
            // Does the neighbor exist, or is this a boundary edge?
            if (neighbortri.triangle != Mesh.dummytri)
            {
                sides++;
                // Find a vertex opposite this subsegment.
                eapex = neighbortri.Apex();
                // Check whether the apex is in the diametral lens of the subsegment
                // (the diametral circle if 'conformdel' is set).  A dot product
                // of two sides of the triangle is used to check whether the angle
                // at the apex is greater than (180 - 2 'minangle') degrees (for
                // lenses; 90 degrees for diametral circles).
                dotproduct = (eorg.x - eapex.x) * (edest.x - eapex.x) +
                             (eorg.y - eapex.y) * (edest.y - eapex.y);
                if (dotproduct < 0.0)
                {
                    if (behavior.ConformingDelaunay ||
                        (dotproduct * dotproduct >=
                         (2.0 * behavior.goodAngle - 1.0) * (2.0 * behavior.goodAngle - 1.0) *
                         ((eorg.x - eapex.x) * (eorg.x - eapex.x) +
                          (eorg.y - eapex.y) * (eorg.y - eapex.y)) *
                         ((edest.x - eapex.x) * (edest.x - eapex.x) +
                          (edest.y - eapex.y) * (edest.y - eapex.y))))
                    {
                        encroached = 1;
                    }
                }
            }
            // Check the other neighbor of the subsegment.
            testsubseg.Sym(ref testsym);
            testsym.TriPivot(ref neighbortri);
            // Does the neighbor exist, or is this a boundary edge?
            if (neighbortri.triangle != Mesh.dummytri)
            {
                sides++;
                // Find the other vertex opposite this subsegment.
                eapex = neighbortri.Apex();
                // Check whether the apex is in the diametral lens of the subsegment
                // (or the diametral circle, if 'conformdel' is set).
                dotproduct = (eorg.x - eapex.x) * (edest.x - eapex.x) +
                             (eorg.y - eapex.y) * (edest.y - eapex.y);
                if (dotproduct < 0.0)
                {
                    if (behavior.ConformingDelaunay ||
                        (dotproduct * dotproduct >=
                         (2.0 * behavior.goodAngle - 1.0) * (2.0 * behavior.goodAngle - 1.0) *
                         ((eorg.x - eapex.x) * (eorg.x - eapex.x) +
                          (eorg.y - eapex.y) * (eorg.y - eapex.y)) *
                         ((edest.x - eapex.x) * (edest.x - eapex.x) +
                          (edest.y - eapex.y) * (edest.y - eapex.y))))
                    {
                        encroached += 2;
                    }
                }
            }

            if (encroached > 0 && (behavior.NoBisect == 0 || ((behavior.NoBisect == 1) && (sides == 2))))
            {
                // Add the subsegment to the list of encroached subsegments.
                // Be sure to get the orientation right.
                encroachedseg = new BadSubseg();
                if (encroached == 1)
                {
                    encroachedseg.encsubseg  = testsubseg;
                    encroachedseg.subsegorg  = eorg;
                    encroachedseg.subsegdest = edest;
                }
                else
                {
                    encroachedseg.encsubseg  = testsym;
                    encroachedseg.subsegorg  = edest;
                    encroachedseg.subsegdest = eorg;
                }

                badsubsegs.Enqueue(encroachedseg);
            }

            return(encroached);
        }
Example #9
0
        private void WriteMesh(TriangleNetMesh triangleNetMesh, bool skip)
        {
            // Mesh may have changed, but we choose to skip
            if (triangles == triangleNetMesh.triangles.Count && skip)
            {
                return;
            }

            // Header line
            stream.WriteLine("#!M{0}", iteration++);

            Vertex p1, p2, p3;

            if (VerticesChanged(triangleNetMesh))
            {
                HashVertices(triangleNetMesh);

                // Number of vertices.
                stream.WriteLine("{0}", triangleNetMesh.vertices.Count);

                foreach (var v in triangleNetMesh.vertices.Values)
                {
                    // Vertex number, x and y coordinates and marker.
                    stream.WriteLine("{0} {1} {2} {3}", v.id, v.x.ToString(nfi), v.y.ToString(nfi), v.label);
                }
            }
            else
            {
                stream.WriteLine("0");
            }

            // Number of segments.
            stream.WriteLine("{0}", triangleNetMesh.subsegs.Count);

            Osub subseg = default(Osub);

            subseg.orient = 0;

            foreach (var item in triangleNetMesh.subsegs.Values)
            {
                if (item.hash <= 0)
                {
                    continue;
                }

                subseg.seg = item;

                p1 = subseg.Org();
                p2 = subseg.Dest();

                // Segment number, indices of its two endpoints, and marker.
                stream.WriteLine("{0} {1} {2} {3}", subseg.seg.hash, p1.id, p2.id, subseg.seg.boundary);
            }

            Otri tri = default(Otri), trisym = default(Otri);

            tri.orient = 0;

            int n1, n2, n3, h1, h2, h3;

            // Number of triangles.
            stream.WriteLine("{0}", triangleNetMesh.triangles.Count);

            foreach (var item in triangleNetMesh.triangles)
            {
                tri.tri = item;

                p1 = tri.Org();
                p2 = tri.Dest();
                p3 = tri.Apex();

                h1 = (p1 == null) ? -1 : p1.id;
                h2 = (p2 == null) ? -1 : p2.id;
                h3 = (p3 == null) ? -1 : p3.id;

                // Triangle number, indices for three vertices.
                stream.Write("{0} {1} {2} {3}", tri.tri.hash, h1, h2, h3);

                tri.orient = 1;
                tri.Sym(ref trisym);
                n1 = trisym.tri.hash;

                tri.orient = 2;
                tri.Sym(ref trisym);
                n2 = trisym.tri.hash;

                tri.orient = 0;
                tri.Sym(ref trisym);
                n3 = trisym.tri.hash;

                // Neighboring triangle numbers.
                stream.WriteLine(" {0} {1} {2}", n1, n2, n3);
            }
        }
Example #10
0
        /// <summary>
        /// Write the segments and holes to a .poly file.
        /// </summary>
        /// <param name="mesh">Data source.</param>
        /// <param name="filename">File name.</param>
        /// <param name="writeNodes">Write nodes into this file.</param>
        /// <remarks>If the nodes should not be written into this file,
        /// make sure a .node file was written before, so that the nodes
        /// are numbered right.</remarks>
        public void WritePoly(Mesh mesh, string filename, bool writeNodes)
        {
            Osub   subseg = default(Osub);
            Vertex pt1, pt2;

            bool useBoundaryMarkers = mesh.behavior.UseBoundaryMarkers;

            using (var writer = new StreamWriter(filename))
            {
                if (writeNodes)
                {
                    // Write nodes to this file.
                    WriteNodes(writer, mesh);
                }
                else
                {
                    // The zero indicates that the vertices are in a separate .node file.
                    // Followed by number of dimensions, number of vertex attributes,
                    // and number of boundary markers (zero or one).
                    writer.WriteLine("0 {0} {1} {2}", mesh.mesh_dim, mesh.nextras,
                                     useBoundaryMarkers ? "1" : "0");
                }

                // Number of segments, number of boundary markers (zero or one).
                writer.WriteLine("{0} {1}", mesh.subsegs.Count,
                                 useBoundaryMarkers ? "1" : "0");

                subseg.orient = 0;

                int j = 0;
                foreach (var item in mesh.subsegs.Values)
                {
                    subseg.seg = item;

                    pt1 = subseg.Org();
                    pt2 = subseg.Dest();

                    // Segment number, indices of its two endpoints, and possibly a marker.
                    if (useBoundaryMarkers)
                    {
                        writer.WriteLine("{0} {1} {2} {3}", j, pt1.id, pt2.id, subseg.seg.boundary);
                    }
                    else
                    {
                        writer.WriteLine("{0} {1} {2}", j, pt1.id, pt2.id);
                    }

                    j++;
                }

                // Holes
                j = 0;
                writer.WriteLine("{0}", mesh.holes.Count);
                foreach (var hole in mesh.holes)
                {
                    writer.WriteLine("{0} {1} {2}", j++, hole.X.ToString(nfi), hole.Y.ToString(nfi));
                }

                // Regions
                if (mesh.regions.Count > 0)
                {
                    j = 0;
                    writer.WriteLine("{0}", mesh.regions.Count);
                    foreach (var region in mesh.regions)
                    {
                        writer.WriteLine("{0} {1} {2} {3}", j, region.point.X.ToString(nfi),
                                         region.point.Y.ToString(nfi), region.id);

                        j++;
                    }
                }
            }
        }
Example #11
0
        private void WriteMesh(Mesh mesh, bool skip)
        {
            Vertex vertex;
            Vertex vertex1;

            if (this.triangles == mesh.triangles.Count & skip)
            {
                return;
            }
            StreamWriter streamWriter = this.stream;
            int          num          = this.iteration;

            this.iteration = num + 1;
            streamWriter.WriteLine("#!M{0}", num);
            if (!this.VerticesChanged(mesh))
            {
                this.stream.WriteLine("0");
            }
            else
            {
                this.HashVertices(mesh);
                this.stream.WriteLine("{0}", mesh.vertices.Count);
                foreach (Vertex value in mesh.vertices.Values)
                {
                    this.stream.WriteLine("{0} {1} {2} {3}", new object[] { value.hash, value.x.ToString(DebugWriter.nfi), value.y.ToString(DebugWriter.nfi), value.mark });
                }
            }
            this.stream.WriteLine("{0}", mesh.subsegs.Count);
            Osub osub = new Osub()
            {
                orient = 0
            };

            foreach (Segment segment in mesh.subsegs.Values)
            {
                if (segment.hash <= 0)
                {
                    continue;
                }
                osub.seg = segment;
                vertex   = osub.Org();
                vertex1  = osub.Dest();
                this.stream.WriteLine("{0} {1} {2} {3}", new object[] { osub.seg.hash, vertex.hash, vertex1.hash, osub.seg.boundary });
            }
            Otri otri  = new Otri();
            Otri otri1 = new Otri();

            otri.orient = 0;
            this.stream.WriteLine("{0}", mesh.triangles.Count);
            foreach (Triangle triangle in mesh.triangles.Values)
            {
                otri.triangle = triangle;
                vertex        = otri.Org();
                vertex1       = otri.Dest();
                Vertex vertex2 = otri.Apex();
                int    num1    = (vertex == null ? -1 : vertex.hash);
                int    num2    = (vertex1 == null ? -1 : vertex1.hash);
                int    num3    = (vertex2 == null ? -1 : vertex2.hash);
                this.stream.Write("{0} {1} {2} {3}", new object[] { otri.triangle.hash, num1, num2, num3 });
                otri.orient = 1;
                otri.Sym(ref otri1);
                int num4 = otri1.triangle.hash;
                otri.orient = 2;
                otri.Sym(ref otri1);
                int num5 = otri1.triangle.hash;
                otri.orient = 0;
                otri.Sym(ref otri1);
                int num6 = otri1.triangle.hash;
                this.stream.WriteLine(" {0} {1} {2}", num4, num5, num6);
            }
        }
Example #12
0
        private void SplitEncSegs(bool triflaws)
        {
            Vertex vertex;
            double num;
            Otri   otri  = new Otri();
            Otri   otri1 = new Otri();
            Osub   osub  = new Osub();
            Osub   osub1 = new Osub();

            while (this.badsubsegs.Count > 0 && this.mesh.steinerleft != 0)
            {
                BadSubseg badSubseg = this.badsubsegs.Dequeue();
                osub1 = badSubseg.encsubseg;
                Vertex vertex1 = osub1.Org();
                Vertex vertex2 = osub1.Dest();
                if (!Osub.IsDead(osub1.seg) && vertex1 == badSubseg.subsegorg && vertex2 == badSubseg.subsegdest)
                {
                    osub1.TriPivot(ref otri);
                    otri.Lnext(ref otri1);
                    otri1.SegPivot(ref osub);
                    bool flag = osub.seg != Mesh.dummysub;
                    otri1.LnextSelf();
                    otri1.SegPivot(ref osub);
                    bool flag1 = osub.seg != Mesh.dummysub;
                    if (!this.behavior.ConformingDelaunay && !flag && !flag1)
                    {
                        vertex = otri.Apex();
                        while (vertex.type == VertexType.FreeVertex && (vertex1.x - vertex.x) * (vertex2.x - vertex.x) + (vertex1.y - vertex.y) * (vertex2.y - vertex.y) < 0)
                        {
                            this.mesh.DeleteVertex(ref otri1);
                            osub1.TriPivot(ref otri);
                            vertex = otri.Apex();
                            otri.Lprev(ref otri1);
                        }
                    }
                    otri.Sym(ref otri1);
                    if (otri1.triangle != Mesh.dummytri)
                    {
                        otri1.LnextSelf();
                        otri1.SegPivot(ref osub);
                        bool flag2 = osub.seg != Mesh.dummysub;
                        flag1 = flag1 | flag2;
                        otri1.LnextSelf();
                        otri1.SegPivot(ref osub);
                        bool flag3 = osub.seg != Mesh.dummysub;
                        flag = flag | flag3;
                        if (!this.behavior.ConformingDelaunay && !flag3 && !flag2)
                        {
                            vertex = otri1.Org();
                            while (vertex.type == VertexType.FreeVertex && (vertex1.x - vertex.x) * (vertex2.x - vertex.x) + (vertex1.y - vertex.y) * (vertex2.y - vertex.y) < 0)
                            {
                                this.mesh.DeleteVertex(ref otri1);
                                otri.Sym(ref otri1);
                                vertex = otri1.Apex();
                                otri1.LprevSelf();
                            }
                        }
                    }
                    if (!(flag | flag1))
                    {
                        num = 0.5;
                    }
                    else
                    {
                        double num1 = Math.Sqrt((vertex2.x - vertex1.x) * (vertex2.x - vertex1.x) + (vertex2.y - vertex1.y) * (vertex2.y - vertex1.y));
                        double num2 = 1;
                        while (num1 > 3 * num2)
                        {
                            num2 = num2 * 2;
                        }
                        while (num1 < 1.5 * num2)
                        {
                            num2 = num2 * 0.5;
                        }
                        num = num2 / num1;
                        if (flag1)
                        {
                            num = 1 - num;
                        }
                    }
                    Vertex vertex3 = new Vertex(vertex1.x + num * (vertex2.x - vertex1.x), vertex1.y + num * (vertex2.y - vertex1.y), osub1.Mark(), this.mesh.nextras)
                    {
                        type = VertexType.SegmentVertex
                    };
                    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);
                    for (int i = 0; i < this.mesh.nextras; i++)
                    {
                        vertex3.attributes[i] = vertex1.attributes[i] + num * (vertex2.attributes[i] - vertex1.attributes[i]);
                    }
                    if (!Behavior.NoExact)
                    {
                        double num3 = Primitives.CounterClockwise(vertex1, vertex2, vertex3);
                        double num4 = (vertex1.x - vertex2.x) * (vertex1.x - vertex2.x) + (vertex1.y - vertex2.y) * (vertex1.y - vertex2.y);
                        if (num3 != 0 && num4 != 0)
                        {
                            num3 = num3 / num4;
                            if (!double.IsNaN(num3))
                            {
                                Vertex vertex4 = vertex3;
                                vertex4.x = vertex4.x + num3 * (vertex2.y - vertex1.y);
                                Vertex vertex5 = vertex3;
                                vertex5.y = vertex5.y + num3 * (vertex1.x - vertex2.x);
                            }
                        }
                    }
                    if (vertex3.x == vertex1.x && vertex3.y == vertex1.y || vertex3.x == vertex2.x && vertex3.y == vertex2.y)
                    {
                        this.logger.Error("Ran out of precision: I attempted to split a segment to a smaller size than can be accommodated by the finite precision of floating point arithmetic.", "Quality.SplitEncSegs()");
                        throw new Exception("Ran out of precision");
                    }
                    InsertVertexResult insertVertexResult = this.mesh.InsertVertex(vertex3, ref otri, ref osub1, true, triflaws);
                    if (insertVertexResult != InsertVertexResult.Successful && insertVertexResult != InsertVertexResult.Encroaching)
                    {
                        this.logger.Error("Failure to split a segment.", "Quality.SplitEncSegs()");
                        throw new Exception("Failure to split a segment.");
                    }
                    if (this.mesh.steinerleft > 0)
                    {
                        Mesh mesh1 = this.mesh;
                        mesh1.steinerleft = mesh1.steinerleft - 1;
                    }
                    this.CheckSeg4Encroach(ref osub1);
                    osub1.NextSelf();
                    this.CheckSeg4Encroach(ref osub1);
                }
                badSubseg.subsegorg = null;
            }
        }
Example #13
0
        public static void WritePoly(Mesh mesh, string filename, bool writeNodes)
        {
            double x;
            Osub   osub = new Osub();
            bool   useBoundaryMarkers = mesh.behavior.UseBoundaryMarkers;

            using (StreamWriter streamWriter = new StreamWriter(new FileStream(filename, FileMode.Create)))
            {
                if (!writeNodes)
                {
                    streamWriter.WriteLine("0 {0} {1} {2}", mesh.mesh_dim, mesh.nextras, (useBoundaryMarkers ? "1" : "0"));
                }
                else
                {
                    FileWriter.WriteNodes(streamWriter, mesh);
                }
                streamWriter.WriteLine("{0} {1}", mesh.subsegs.Count, (useBoundaryMarkers ? "1" : "0"));
                osub.orient = 0;
                int num = 0;
                foreach (Segment value in mesh.subsegs.Values)
                {
                    osub.seg = value;
                    Vertex vertex  = osub.Org();
                    Vertex vertex1 = osub.Dest();
                    if (!useBoundaryMarkers)
                    {
                        streamWriter.WriteLine("{0} {1} {2}", num, vertex.id, vertex1.id);
                    }
                    else
                    {
                        streamWriter.WriteLine("{0} {1} {2} {3}", new object[] { num, vertex.id, vertex1.id, osub.seg.boundary });
                    }
                    num++;
                }
                num = 0;
                streamWriter.WriteLine("{0}", mesh.holes.Count);
                foreach (Point hole in mesh.holes)
                {
                    int num1 = num;
                    num = num1 + 1;
                    object obj = num1;
                    x = hole.X;
                    string str = x.ToString(FileWriter.nfi);
                    x = hole.Y;
                    streamWriter.WriteLine("{0} {1} {2}", obj, str, x.ToString(FileWriter.nfi));
                }
                if (mesh.regions.Count > 0)
                {
                    num = 0;
                    streamWriter.WriteLine("{0}", mesh.regions.Count);
                    foreach (RegionPointer region in mesh.regions)
                    {
                        object[] objArray = new object[] { num, null, null, null };
                        x           = region.point.X;
                        objArray[1] = x.ToString(FileWriter.nfi);
                        x           = region.point.Y;
                        objArray[2] = x.ToString(FileWriter.nfi);
                        objArray[3] = region.id;
                        streamWriter.WriteLine("{0} {1} {2} {3}", objArray);
                        num++;
                    }
                }
            }
        }
Example #14
0
        /// <summary>
        /// Finds the adjacencies between triangles and subsegments.
        /// </summary>
        private static void SetSegments(Mesh mesh, Polygon polygon, List <Otri>[] vertexarray)
        {
            Otri    checktri = default(Otri);
            Otri    nexttri; // Triangle
            TVertex checkdest;
            Otri    checkneighbor = default(Otri);
            Osub    subseg        = default(Osub);
            Otri    prevlink; // Triangle

            TVertex tmp;
            TVertex sorg, sdest;

            bool notfound;

            //bool segmentmarkers = false;
            int boundmarker;
            int aroundvertex;
            int i;

            int hullsize = 0;

            // Prepare to count the boundary edges.
            if (mesh.behavior.Poly)
            {
                // Link the segments to their neighboring triangles.
                boundmarker = 0;
                i           = 0;
                foreach (var item in mesh.subsegs.Values)
                {
                    subseg.seg = item;

                    sorg  = polygon.Segments[i].GetVertex(0);
                    sdest = polygon.Segments[i].GetVertex(1);

                    boundmarker = polygon.Segments[i].Label;

                    if ((sorg.id < 0 || sorg.id >= mesh.invertices) || (sdest.id < 0 || sdest.id >= mesh.invertices))
                    {
                        Log.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
                        throw new Exception("Segment has an invalid vertex index.");
                    }

                    // set the subsegment's vertices.
                    subseg.orient = 0;
                    subseg.SetOrg(sorg);
                    subseg.SetDest(sdest);
                    subseg.SetSegOrg(sorg);
                    subseg.SetSegDest(sdest);
                    subseg.seg.boundary = boundmarker;
                    // Try linking the subsegment to triangles that share these vertices.
                    for (subseg.orient = 0; subseg.orient < 2; subseg.orient++)
                    {
                        // Take the number for the destination of subsegloop.
                        aroundvertex = subseg.orient == 1 ? sorg.id : sdest.id;

                        int index = vertexarray[aroundvertex].Count - 1;

                        // Look for triangles having this vertex.
                        prevlink = vertexarray[aroundvertex][index];
                        nexttri  = vertexarray[aroundvertex][index];

                        checktri = nexttri;
                        tmp      = subseg.Org();
                        notfound = true;
                        // Look for triangles having this edge.  Note that I'm only
                        // comparing each triangle's destination with the subsegment;
                        // each triangle's apex is handled through a different vertex.
                        // Because each triangle appears on three vertices' lists, each
                        // occurrence of a triangle on a list can (and does) represent
                        // an edge.  In this way, most edges are represented twice, and
                        // every triangle-subsegment bond is represented once.
                        while (notfound && (checktri.tri.id != Mesh.DUMMY))
                        {
                            checkdest = checktri.Dest();

                            if (tmp == checkdest)
                            {
                                // We have a match. Remove this triangle from the list.
                                //prevlink = vertexarray[aroundvertex][index];
                                vertexarray[aroundvertex].Remove(prevlink);
                                // Bond the subsegment to the triangle.
                                checktri.SegBond(ref subseg);
                                // Check if this is a boundary edge.
                                checktri.Sym(ref checkneighbor);
                                if (checkneighbor.tri.id == Mesh.DUMMY)
                                {
                                    // The next line doesn't insert a subsegment (because there's
                                    // already one there), but it sets the boundary markers of
                                    // the existing subsegment and its vertices.
                                    mesh.InsertSubseg(ref checktri, 1);
                                    hullsize++;
                                }
                                notfound = false;
                            }
                            index--;
                            // Find the next triangle in the stack.
                            prevlink = vertexarray[aroundvertex][index];
                            nexttri  = vertexarray[aroundvertex][index];

                            checktri = nexttri;
                        }
                    }

                    i++;
                }
            }

            // Mark the remaining edges as not being attached to any subsegment.
            // Also, count the (yet uncounted) boundary edges.
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                // Search the stack of triangles adjacent to a vertex.
                int index = vertexarray[i].Count - 1;
                nexttri  = vertexarray[i][index];
                checktri = nexttri;

                while (checktri.tri.id != Mesh.DUMMY)
                {
                    // Find the next triangle in the stack before this
                    // information gets overwritten.
                    index--;
                    nexttri = vertexarray[i][index];
                    // No adjacent subsegment.  (This overwrites the stack info.)
                    checktri.SegDissolve(mesh.dummysub);
                    checktri.Sym(ref checkneighbor);
                    if (checkneighbor.tri.id == Mesh.DUMMY)
                    {
                        mesh.InsertSubseg(ref checktri, 1);
                        hullsize++;
                    }

                    checktri = nexttri;
                }
            }

            mesh.hullsize = hullsize;
        }
Example #15
0
        public static int Reconstruct(Mesh mesh, InputGeometry input, ITriangle[] triangles)
        {
            Otri item;
            int  num;
            int  num1   = 0;
            Otri region = new Otri();
            Otri otri   = new Otri();
            Otri l      = new Otri();
            Otri otri1  = new Otri();
            Otri otri2  = new Otri();
            Osub osub   = new Osub();

            int[] p0    = new int[3];
            int[] p1    = new int[2];
            int   i     = 0;
            int   num2  = (triangles == null ? 0 : (int)triangles.Length);
            int   count = input.segments.Count;

            mesh.inelements = num2;
            mesh.regions.AddRange(input.regions);
            for (i = 0; i < mesh.inelements; i++)
            {
                mesh.MakeTriangle(ref region);
            }
            if (mesh.behavior.Poly)
            {
                mesh.insegments = count;
                for (i = 0; i < mesh.insegments; i++)
                {
                    mesh.MakeSegment(ref osub);
                }
            }
            List <Otri>[] otris = new List <Otri> [mesh.vertices.Count];
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                Otri otri3 = new Otri()
                {
                    triangle = Mesh.dummytri
                };
                otris[i] = new List <Otri>(3);
                otris[i].Add(otri3);
            }
            i = 0;
            foreach (Triangle value in mesh.triangles.Values)
            {
                region.triangle = value;
                p0[0]           = triangles[i].P0;
                p0[1]           = triangles[i].P1;
                p0[2]           = triangles[i].P2;
                for (int j = 0; j < 3; j++)
                {
                    if (p0[j] < 0 || p0[j] >= mesh.invertices)
                    {
                        SimpleLog.Instance.Error("Triangle has an invalid vertex index.", "MeshReader.Reconstruct()");
                        throw new Exception("Triangle has an invalid vertex index.");
                    }
                }
                region.triangle.region = triangles[i].Region;
                if (mesh.behavior.VarArea)
                {
                    region.triangle.area = triangles[i].Area;
                }
                region.orient = 0;
                region.SetOrg(mesh.vertices[p0[0]]);
                region.SetDest(mesh.vertices[p0[1]]);
                region.SetApex(mesh.vertices[p0[2]]);
                region.orient = 0;
                while (region.orient < 3)
                {
                    num = p0[region.orient];
                    int count1 = otris[num].Count - 1;
                    item = otris[num][count1];
                    otris[num].Add(region);
                    l = item;
                    if (l.triangle != Mesh.dummytri)
                    {
                        Vertex vertex  = region.Dest();
                        Vertex vertex1 = region.Apex();
                        do
                        {
                            Vertex vertex2 = l.Dest();
                            Vertex vertex3 = l.Apex();
                            if (vertex1 == vertex2)
                            {
                                region.Lprev(ref otri);
                                otri.Bond(ref l);
                            }
                            if (vertex == vertex3)
                            {
                                l.Lprev(ref otri1);
                                region.Bond(ref otri1);
                            }
                            count1--;
                            item = otris[num][count1];
                            l    = item;
                        }while (l.triangle != Mesh.dummytri);
                    }
                    region.orient = region.orient + 1;
                }
                i++;
            }
            num1 = 0;
            if (mesh.behavior.Poly)
            {
                int boundary = 0;
                i = 0;
                foreach (Segment segment in mesh.subsegs.Values)
                {
                    osub.seg = segment;
                    p1[0]    = input.segments[i].P0;
                    p1[1]    = input.segments[i].P1;
                    boundary = input.segments[i].Boundary;
                    for (int k = 0; k < 2; k++)
                    {
                        if (p1[k] < 0 || p1[k] >= mesh.invertices)
                        {
                            SimpleLog.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
                            throw new Exception("Segment has an invalid vertex index.");
                        }
                    }
                    osub.orient = 0;
                    Vertex item1 = mesh.vertices[p1[0]];
                    Vertex item2 = mesh.vertices[p1[1]];
                    osub.SetOrg(item1);
                    osub.SetDest(item2);
                    osub.SetSegOrg(item1);
                    osub.SetSegDest(item2);
                    osub.seg.boundary = boundary;
                    osub.orient       = 0;
                    while (osub.orient < 2)
                    {
                        num = p1[1 - osub.orient];
                        int  count2 = otris[num].Count - 1;
                        Otri item3  = otris[num][count2];
                        item = otris[num][count2];
                        l    = item;
                        Vertex vertex4 = osub.Org();
                        bool   flag    = true;
                        while (flag && l.triangle != Mesh.dummytri)
                        {
                            if (vertex4 == l.Dest())
                            {
                                otris[num].Remove(item3);
                                l.SegBond(ref osub);
                                l.Sym(ref otri2);
                                if (otri2.triangle == Mesh.dummytri)
                                {
                                    mesh.InsertSubseg(ref l, 1);
                                    num1++;
                                }
                                flag = false;
                            }
                            count2--;
                            item3 = otris[num][count2];
                            item  = otris[num][count2];
                            l     = item;
                        }
                        osub.orient = osub.orient + 1;
                    }
                    i++;
                }
            }
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                int count3 = otris[i].Count - 1;
                item = otris[i][count3];
                for (l = item; l.triangle != Mesh.dummytri; l = item)
                {
                    count3--;
                    item = otris[i][count3];
                    l.SegDissolve();
                    l.Sym(ref otri2);
                    if (otri2.triangle == Mesh.dummytri)
                    {
                        mesh.InsertSubseg(ref l, 1);
                        num1++;
                    }
                }
            }
            return(num1);
        }