Exemplo n.º 1
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;
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
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);
        }