Пример #1
0
        public void TestDprev()
        {
            var triangles = CreateExampleMesh();

            Otri t = default;

            // Start with the top triangle.
            t.tri = triangles[3];

            // Start with edge  5 -> 3.
            t.orient = 2;

            // Make sure we're on the correct edge.
            Assert.AreEqual(5, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);

            t.Dprev();
            Assert.AreEqual(4, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);
            Assert.AreEqual(1, t.tri.ID);

            t.Dprev();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);
            Assert.AreEqual(0, t.tri.ID);

            // Out of mesh.
            t.Dprev();
            Assert.AreEqual(-1, t.tri.ID);
        }
Пример #2
0
        public void TestOnext()
        {
            var triangles = CreateExampleMesh();

            Otri t = default;

            // Start with the bottom right triangle.
            t.tri = triangles[2];

            // Start with edge  1 -> 2.
            t.orient = 0;

            // Make sure we're on the correct edge.
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(2, t.Dest().ID);

            t.Onext();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(4, t.Dest().ID);
            Assert.AreEqual(1, t.tri.ID);

            t.Onext();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);
            Assert.AreEqual(0, t.tri.ID);

            // Out of mesh.
            t.Onext();
            Assert.AreEqual(-1, t.tri.ID);
        }
Пример #3
0
        public void TestRprev()
        {
            var triangles = CreateExampleMesh();

            Otri t = default;

            // Start with the top triangle.
            t.tri = triangles[3];

            // Start with edge  3 -> 4.
            t.orient = 0;

            // Make sure we're on the correct edge.
            Assert.AreEqual(3, t.Org().ID);
            Assert.AreEqual(4, t.Dest().ID);

            t.Rprev();
            Assert.AreEqual(4, t.Org().ID);
            Assert.AreEqual(1, t.Dest().ID);
            Assert.AreEqual(2, t.tri.ID);

            t.Rprev();
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);
            Assert.AreEqual(0, t.tri.ID);

            // Back where we started.
            t.Rprev();
            Assert.AreEqual(3, t.tri.ID);
        }
Пример #4
0
        public void TestRnext()
        {
            var triangles = CreateExampleMesh();

            Otri t = default;

            // Start with the bottom left triangle.
            t.tri = triangles[0];

            // Start with edge  1 -> 3.
            t.orient = 1;

            // Make sure we're on the correct edge.
            Assert.AreEqual(1, t.Org().ID);
            Assert.AreEqual(3, t.Dest().ID);

            t.Rnext();
            Assert.AreEqual(4, t.Org().ID);
            Assert.AreEqual(1, t.Dest().ID);
            Assert.AreEqual(2, t.tri.ID);

            t.Rnext();
            Assert.AreEqual(3, t.Org().ID);
            Assert.AreEqual(4, t.Dest().ID);
            Assert.AreEqual(3, t.tri.ID);

            // Back where we started.
            t.Rnext();
            Assert.AreEqual(0, t.tri.ID);
        }
Пример #5
0
        public void TestDest()
        {
            Otri t = default;

            t.tri = Helper.CreateTriangle(0, vertices[1], vertices[4], vertices[3]);

            t.orient = 0;
            Assert.AreEqual(4, t.Dest().ID);

            t.orient = 1;
            Assert.AreEqual(3, t.Dest().ID);

            t.orient = 2;
            Assert.AreEqual(1, t.Dest().ID);
        }
        /// <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);
        }
Пример #7
0
        /// <summary>
        /// Enumerate all edges of the given mesh.
        /// </summary>
        /// <param name="mesh"></param>
        /// <returns></returns>
        public IEnumerable <Edge> EnumerateEdges(IMesh mesh)
        {
            Otri tri      = default;
            Otri neighbor = default;
            Osub sub      = default;

            Vertex p1, p2;

            foreach (var t in mesh.Triangles)
            {
                tri.tri    = t;
                tri.orient = 0;

                for (int i = 0; i < 3; i++)
                {
                    tri.Sym(ref neighbor);

                    int nid = neighbor.tri.id;

                    if ((tri.tri.id < nid) || (nid == Mesh.DUMMY))
                    {
                        p1 = tri.Org();
                        p2 = tri.Dest();

                        tri.Pivot(ref sub);

                        // Boundary mark of dummysub is 0, so we don't need to worry about that.
                        yield return(new Edge(p1.id, p2.id, sub.seg.boundary));
                    }

                    tri.orient++;
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Compute the Voronoi vertices (the circumcenters of the triangles).
        /// </summary>
        /// <returns>An empty map, which will map all vertices to a list of leaving edges.</returns>
        protected List <HalfEdge>[] ComputeVertices(Mesh mesh, Vertex[] vertices)
        {
            Otri   tri = default(Otri);
            double xi = 0, eta = 0;
            Vertex vertex;
            Point  pt;
            int    id;

            // Maps all vertices to a list of leaving edges.
            var map = new List <HalfEdge> [mesh.triangles.Count];

            // Compue triangle circumcenters
            foreach (var t in mesh.triangles)
            {
                id      = t.id;
                tri.tri = t;

                pt = predicates.FindCircumcenter(tri.Org(), tri.Dest(), tri.Apex(), ref xi, ref eta);

                vertex    = factory.CreateVertex(pt.x, pt.y);
                vertex.id = id;

                vertices[id] = vertex;
                map[id]      = new List <HalfEdge>();
            }

            return(map);
        }
Пример #9
0
        /// <summary>
        /// Virally infect all of the triangles of the convex hull that are not
        /// protected by subsegments. Where there are subsegments, set boundary
        /// markers as appropriate.
        /// </summary>
        private void InfectHull()
        {
            Otri   hulltri = default(Otri);
            Otri   nexttri = default(Otri);
            Otri   starttri = default(Otri);
            Osub   hullsubseg = default(Osub);
            Vertex horg, hdest;

            // Find a triangle handle on the hull.
            hulltri.triangle = Mesh.dummytri;
            hulltri.orient   = 0;
            hulltri.SymSelf();
            // Remember where we started so we know when to stop.
            hulltri.Copy(ref starttri);
            // Go once counterclockwise around the convex hull.
            do
            {
                // Ignore triangles that are already infected.
                if (!hulltri.IsInfected())
                {
                    // Is the triangle protected by a subsegment?
                    hulltri.SegPivot(ref hullsubseg);
                    if (hullsubseg.seg == Mesh.dummysub)
                    {
                        // The triangle is not protected; infect it.
                        if (!hulltri.IsInfected())
                        {
                            hulltri.Infect();
                            viri.Add(hulltri.triangle);
                        }
                    }
                    else
                    {
                        // The triangle is protected; set boundary markers if appropriate.
                        if (hullsubseg.seg.boundary == 0)
                        {
                            hullsubseg.seg.boundary = 1;
                            horg  = hulltri.Org();
                            hdest = hulltri.Dest();
                            if (horg.mark == 0)
                            {
                                horg.mark = 1;
                            }
                            if (hdest.mark == 0)
                            {
                                hdest.mark = 1;
                            }
                        }
                    }
                }
                // To find the next hull edge, go clockwise around the next vertex.
                hulltri.LnextSelf();
                hulltri.Oprev(ref nexttri);
                while (nexttri.triangle != Mesh.dummytri)
                {
                    nexttri.Copy(ref hulltri);
                    hulltri.Oprev(ref nexttri);
                }
            } while (!hulltri.Equal(starttri));
        }
Пример #10
0
 private SweepLine.SplayNode SplayInsert(SweepLine.SplayNode splayroot, Otri newkey, Point searchpoint)
 {
     SweepLine.SplayNode splayNode = new SweepLine.SplayNode();
     this.splaynodes.Add(splayNode);
     newkey.Copy(ref splayNode.keyedge);
     splayNode.keydest = newkey.Dest();
     if (splayroot == null)
     {
         splayNode.lchild = null;
         splayNode.rchild = null;
     }
     else if (!this.RightOfHyperbola(ref splayroot.keyedge, searchpoint))
     {
         splayNode.lchild = splayroot.lchild;
         splayNode.rchild = splayroot;
         splayroot.lchild = null;
     }
     else
     {
         splayNode.lchild = splayroot;
         splayNode.rchild = splayroot.rchild;
         splayroot.rchild = null;
     }
     return(splayNode);
 }
Пример #11
0
        SplayNode SplayInsert(SplayNode splayroot, Otri newkey, Point searchpoint)
        {
            SplayNode newsplaynode;

            newsplaynode = new SplayNode(); //poolalloc(m.splaynodes);
            splaynodes.Add(newsplaynode);
            newkey.Copy(ref newsplaynode.keyedge);
            newsplaynode.keydest = newkey.Dest();
            if (splayroot == null)
            {
                newsplaynode.lchild = null;
                newsplaynode.rchild = null;
            }
            else if (RightOfHyperbola(ref splayroot.keyedge, searchpoint))
            {
                newsplaynode.lchild = splayroot;
                newsplaynode.rchild = splayroot.rchild;
                splayroot.rchild    = null;
            }
            else
            {
                newsplaynode.lchild = splayroot.lchild;
                newsplaynode.rchild = splayroot;
                splayroot.lchild    = null;
            }
            return(newsplaynode);
        }
Пример #12
0
        private bool RightOfHyperbola(ref Otri fronttri, Point newsite)
        {
            Vertex leftvertex, rightvertex;
            double dxa, dya, dxb, dyb;

            leftvertex  = fronttri.Dest();
            rightvertex = fronttri.Apex();
            if ((leftvertex.Y < rightvertex.Y) ||
                ((leftvertex.Y == rightvertex.Y) &&
                 (leftvertex.X < rightvertex.X)))
            {
                if (newsite.X >= rightvertex.X)
                {
                    return(true);
                }
            }
            else
            {
                if (newsite.X <= leftvertex.X)
                {
                    return(false);
                }
            }
            dxa = leftvertex.X - newsite.X;
            dya = leftvertex.Y - newsite.Y;
            dxb = rightvertex.X - newsite.X;
            dyb = rightvertex.Y - newsite.Y;
            return(dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya));
        }
Пример #13
0
        public static void WriteElements(Mesh mesh, string filename)
        {
            Otri otri = new Otri();
            bool flag = mesh.behavior.useRegions;
            int  num  = 0;

            otri.orient = 0;
            using (StreamWriter streamWriter = new StreamWriter(new FileStream(filename, FileMode.Create)))
            {
                streamWriter.WriteLine("{0} 3 {1}", mesh.triangles.Count, (flag ? 1 : 0));
                foreach (Triangle value in mesh.triangles.Values)
                {
                    otri.triangle = value;
                    Vertex vertex  = otri.Org();
                    Vertex vertex1 = otri.Dest();
                    Vertex vertex2 = otri.Apex();
                    streamWriter.Write("{0} {1} {2} {3}", new object[] { num, vertex.id, vertex1.id, vertex2.id });
                    if (flag)
                    {
                        streamWriter.Write(" {0}", otri.triangle.region);
                    }
                    streamWriter.WriteLine();
                    int num1 = num;
                    num      = num1 + 1;
                    value.id = num1;
                }
            }
        }
Пример #14
0
        bool RightOfHyperbola(ref Otri fronttri, Point newsite)
        {
            Vertex leftvertex, rightvertex;
            double dxa, dya, dxb, dyb;

            Statistic.HyperbolaCount++;

            leftvertex  = fronttri.Dest();
            rightvertex = fronttri.Apex();
            if ((leftvertex.y < rightvertex.y) ||
                ((leftvertex.y == rightvertex.y) &&
                 (leftvertex.x < rightvertex.x)))
            {
                if (newsite.x >= rightvertex.x)
                {
                    return(true);
                }
            }
            else
            {
                if (newsite.x <= leftvertex.x)
                {
                    return(false);
                }
            }
            dxa = leftvertex.x - newsite.x;
            dya = leftvertex.y - newsite.y;
            dxb = rightvertex.x - newsite.x;
            dyb = rightvertex.y - newsite.y;
            return(dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya));
        }
Пример #15
0
        /// <summary>
        ///     Find the holes and infect them. Find the area constraints and infect
        ///     them. Infect the convex hull. Spread the infection and kill triangles.
        ///     Spread the area constraints.
        /// </summary>
        public void CarveHoles()
        {
            Otri         searchtri = default(Otri);
            Vertex       searchorg, searchdest;
            LocateResult intersect;

            var dummytri = mesh.dummytri;

            if (!mesh.behavior.Convex)
            {
                // Mark as infected any unprotected triangles on the boundary.
                // This is one way by which concavities are created.
                InfectHull();
            }

            if (!mesh.behavior.NoHoles)
            {
                // Infect each triangle in which a hole lies.
                foreach (var hole in mesh.holes)
                {
                    // Ignore holes that aren't within the bounds of the mesh.
                    if (mesh.bounds.Contains(hole))
                    {
                        // Start searching from some triangle on the outer boundary.
                        searchtri.tri    = dummytri;
                        searchtri.orient = 0;
                        searchtri.Sym();
                        // Ensure that the hole is to the left of this boundary edge;
                        // otherwise, locate() will falsely report that the hole
                        // falls within the starting triangle.
                        searchorg  = searchtri.Org();
                        searchdest = searchtri.Dest();
                        if (RobustPredicates.CounterClockwise(searchorg, searchdest, hole) > 0.0)
                        {
                            // Find a triangle that contains the hole.
                            intersect = mesh.locator.Locate(hole, ref searchtri);
                            if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected()))
                            {
                                // Infect the triangle. This is done by marking the triangle
                                // as infected and including the triangle in the virus pool.
                                searchtri.Infect();
                                viri.Add(searchtri.tri);
                            }
                        }
                    }
                }
            }

            if (viri.Count > 0)
            {
                // Carve the holes and concavities.
                Plague();
            }

            // Free up memory (virus pool should be empty anyway).
            viri.Clear();
        }
Пример #16
0
        /// <summary>
        ///     Scout the first triangle on the path from one endpoint to another, and check
        ///     for completion (reaching the second endpoint), a collinear vertex, or the
        ///     intersection of two segments.
        /// </summary>
        /// <param name="searchtri"></param>
        /// <param name="endpoint2"></param>
        /// <param name="newmark"></param>
        /// <returns>
        ///     Returns true if the entire segment is successfully inserted, and false
        ///     if the job must be finished by ConstrainedEdge().
        /// </returns>
        /// <remarks>
        ///     If the first triangle on the path has the second endpoint as its
        ///     destination or apex, a subsegment is inserted and the job is done.
        ///     If the first triangle on the path has a destination or apex that lies on
        ///     the segment, a subsegment is inserted connecting the first endpoint to
        ///     the collinear vertex, and the search is continued from the collinear
        ///     vertex.
        ///     If the first triangle on the path has a subsegment opposite its origin,
        ///     then there is a segment that intersects the segment being inserted.
        ///     Their intersection vertex is inserted, splitting the subsegment.
        /// </remarks>
        private bool ScoutSegment(ref Otri searchtri, Vertex endpoint2, ushort newmark)
        {
            Otri   crosstri = default(Otri);
            Osub   crosssubseg = default(Osub);
            Vertex leftvertex, rightvertex;
            FindDirectionResult collinear;

            collinear   = FindDirection(ref searchtri, endpoint2);
            rightvertex = searchtri.Dest();
            leftvertex  = searchtri.Apex();
            if (((leftvertex.X == endpoint2.X) && (leftvertex.Y == endpoint2.Y)) ||
                ((rightvertex.X == endpoint2.X) && (rightvertex.Y == endpoint2.Y)))
            {
                // The segment is already an edge in the mesh.
                if ((leftvertex.X == endpoint2.X) && (leftvertex.Y == endpoint2.Y))
                {
                    searchtri.Lprev();
                }
                // Insert a subsegment, if there isn't already one there.
                mesh.InsertSubseg(ref searchtri, newmark);
                return(true);
            }
            if (collinear == FindDirectionResult.Leftcollinear)
            {
                // We've collided with a vertex between the segment's endpoints.
                // Make the collinear vertex be the triangle's origin.
                searchtri.Lprev();
                mesh.InsertSubseg(ref searchtri, newmark);
                // Insert the remainder of the segment.
                return(ScoutSegment(ref searchtri, endpoint2, newmark));
            }
            if (collinear == FindDirectionResult.Rightcollinear)
            {
                // We've collided with a vertex between the segment's endpoints.
                mesh.InsertSubseg(ref searchtri, newmark);
                // Make the collinear vertex be the triangle's origin.
                searchtri.Lnext();
                // Insert the remainder of the segment.
                return(ScoutSegment(ref searchtri, endpoint2, newmark));
            }
            searchtri.Lnext(ref crosstri);
            crosstri.Pivot(ref crosssubseg);
            // Check for a crossing segment.
            if (crosssubseg.seg.hash == Mesh.DUMMY)
            {
                return(false);
            }
            // Insert a vertex at the intersection.
            SegmentIntersection(ref crosstri, ref crosssubseg, endpoint2);
            crosstri.Copy(ref searchtri);
            mesh.InsertSubseg(ref searchtri, newmark);
            // Insert the remainder of the segment.
            return(ScoutSegment(ref searchtri, endpoint2, newmark));
        }
Пример #17
0
        public void TestDissolve()
        {
            // Outer space triangle.
            var dummy = new Triangle()
            {
                id = -1
            };

            var triangles = CreateExampleMesh();

            Otri s = default;
            Otri t = default;

            Otri tmp = default;

            // The bottom left triangle with edge 1 -> 3.
            s.tri    = triangles[0];
            s.orient = 1;

            // The center triangle with edge 3 -> 1.
            t.tri    = triangles[1];
            t.orient = 2;

            // Make sure we're on the correct edges.
            Assert.AreEqual(1, s.Org().ID);
            Assert.AreEqual(3, s.Dest().ID);
            Assert.AreEqual(3, t.Org().ID);
            Assert.AreEqual(1, t.Dest().ID);

            // Check that neighbors are properly set.
            s.Sym(ref tmp);
            Assert.AreEqual(1, tmp.tri.ID);
            t.Sym(ref tmp);
            Assert.AreEqual(0, tmp.tri.ID);

            // Now dissolve the bond from one side.
            s.Dissolve(dummy);

            // Check neighbors.
            s.Sym(ref tmp);
            Assert.AreEqual(-1, tmp.tri.ID);
            t.Sym(ref tmp);
            Assert.AreEqual(0, tmp.tri.ID);

            // And dissolve the bond from the other side.
            t.Dissolve(dummy);

            // Check neighbors.
            s.Sym(ref tmp);
            Assert.AreEqual(-1, tmp.tri.ID);
            t.Sym(ref tmp);
            Assert.AreEqual(-1, tmp.tri.ID);
        }
Пример #18
0
        public static void WriteEdges(Mesh mesh, string filename)
        {
            Otri     otri     = new Otri();
            Otri     otri1    = new Otri();
            Osub     osub     = new Osub();
            Behavior behavior = mesh.behavior;

            using (StreamWriter streamWriter = new StreamWriter(new FileStream(filename, FileMode.Create)))
            {
                streamWriter.WriteLine("{0} {1}", mesh.edges, (behavior.UseBoundaryMarkers ? "1" : "0"));
                long num = (long)0;
                foreach (Triangle value in mesh.triangles.Values)
                {
                    otri.triangle = value;
                    otri.orient   = 0;
                    while (otri.orient < 3)
                    {
                        otri.Sym(ref otri1);
                        if (otri.triangle.id < otri1.triangle.id || otri1.triangle == Mesh.dummytri)
                        {
                            Vertex vertex  = otri.Org();
                            Vertex vertex1 = otri.Dest();
                            if (!behavior.UseBoundaryMarkers)
                            {
                                streamWriter.WriteLine("{0} {1} {2}", num, vertex.id, vertex1.id);
                            }
                            else if (!behavior.useSegments)
                            {
                                StreamWriter streamWriter1 = streamWriter;
                                object[]     objArray      = new object[] { num, vertex.id, vertex1.id, null };
                                objArray[3] = (otri1.triangle == Mesh.dummytri ? "1" : "0");
                                streamWriter1.WriteLine("{0} {1} {2} {3}", objArray);
                            }
                            else
                            {
                                otri.SegPivot(ref osub);
                                if (osub.seg != Mesh.dummysub)
                                {
                                    streamWriter.WriteLine("{0} {1} {2} {3}", new object[] { num, vertex.id, vertex1.id, osub.seg.boundary });
                                }
                                else
                                {
                                    streamWriter.WriteLine("{0} {1} {2} {3}", new object[] { num, vertex.id, vertex1.id, 0 });
                                }
                            }
                            num = num + (long)1;
                        }
                        otri.orient = otri.orient + 1;
                    }
                }
            }
        }
        public void Update(Otri otri)
        {
            if (otri.Triangle == null || otri.Triangle.ID < 0)
            {
                renderer.SelectTriangle(null, null, null);
            }
            else
            {
                renderer.SelectTriangle(otri.Triangle, otri.Org(), otri.Dest());
            }

            this.Render();
        }
Пример #20
0
        private void ComputeCircumCenters()
        {
            Otri   otri = new Otri();
            double num  = 0;
            double num1 = 0;

            foreach (Triangle value in this.mesh.triangles.Values)
            {
                otri.triangle = value;
                Point point = Primitives.FindCircumcenter(otri.Org(), otri.Dest(), otri.Apex(), ref num, ref num1);
                point.id = value.id;
                this.points[value.id] = point;
            }
        }
Пример #21
0
        private void InfectHull()
        {
            Otri otri  = new Otri();
            Otri otri1 = new Otri();
            Otri otri2 = new Otri();
            Osub osub  = new Osub();

            otri.triangle = Mesh.dummytri;
            otri.orient   = 0;
            otri.SymSelf();
            otri.Copy(ref otri2);
            do
            {
                if (!otri.IsInfected())
                {
                    otri.SegPivot(ref osub);
                    if (osub.seg == Mesh.dummysub)
                    {
                        if (!otri.IsInfected())
                        {
                            otri.Infect();
                            this.viri.Add(otri.triangle);
                        }
                    }
                    else if (osub.seg.boundary == 0)
                    {
                        osub.seg.boundary = 1;
                        Vertex vertex  = otri.Org();
                        Vertex vertex1 = otri.Dest();
                        if (vertex.mark == 0)
                        {
                            vertex.mark = 1;
                        }
                        if (vertex1.mark == 0)
                        {
                            vertex1.mark = 1;
                        }
                    }
                }
                otri.LnextSelf();
                otri.Oprev(ref otri1);
                while (otri1.triangle != Mesh.dummytri)
                {
                    otri1.Copy(ref otri);
                    otri.Oprev(ref otri1);
                }
            }while (!otri.Equal(otri2));
        }
        private void ComputeCircumCenters()
        {
            Otri  tri = default(Otri);
            float xi = 0, eta = 0;
            Point pt;

            // Compue triangle circumcenters
            foreach (var item in _TriangleNetMesh.triangles)
            {
                tri.tri = item;

                pt    = predicates.FindCircumcenter(tri.Org(), tri.Dest(), tri.Apex(), ref xi, ref eta);
                pt.id = item.id;

                points[item.id] = pt;
            }
        }
Пример #23
0
        private void ComputeCircumCenters()
        {
            Otri   tri = default(Otri);
            double xi = 0, eta = 0;
            Point  pt;

            // Compue triangle circumcenters
            foreach (var item in mesh.triangles.Values)
            {
                tri.triangle = item;

                pt    = Primitives.FindCircumcenter(tri.Org(), tri.Dest(), tri.Apex(), ref xi, ref eta);
                pt.id = item.id;

                points[item.id] = pt;
            }
        }
Пример #24
0
        public bool CheckDelaunay()
        {
            Otri otri    = new Otri();
            Otri otri1   = new Otri();
            Osub osub    = new Osub();
            bool noExact = Behavior.NoExact;

            Behavior.NoExact = false;
            int num = 0;

            foreach (Triangle value in this.mesh.triangles.Values)
            {
                otri.triangle = value;
                otri.orient   = 0;
                while (otri.orient < 3)
                {
                    Vertex vertex  = otri.Org();
                    Vertex vertex1 = otri.Dest();
                    Vertex vertex2 = otri.Apex();
                    otri.Sym(ref otri1);
                    Vertex vertex3 = otri1.Apex();
                    bool   flag    = (otri1.triangle == Mesh.dummytri || Otri.IsDead(otri1.triangle) || otri.triangle.id >= otri1.triangle.id || !(vertex != this.mesh.infvertex1) || !(vertex != this.mesh.infvertex2) || !(vertex != this.mesh.infvertex3) || !(vertex1 != this.mesh.infvertex1) || !(vertex1 != this.mesh.infvertex2) || !(vertex1 != this.mesh.infvertex3) || !(vertex2 != this.mesh.infvertex1) || !(vertex2 != this.mesh.infvertex2) || !(vertex2 != this.mesh.infvertex3) || !(vertex3 != this.mesh.infvertex1) || !(vertex3 != this.mesh.infvertex2) ? false : vertex3 != this.mesh.infvertex3);
                    if (this.mesh.checksegments & flag)
                    {
                        otri.SegPivot(ref osub);
                        if (osub.seg != Mesh.dummysub)
                        {
                            flag = false;
                        }
                    }
                    if (flag && Primitives.NonRegular(vertex, vertex1, vertex2, vertex3) > 0)
                    {
                        this.logger.Warning(string.Format("Non-regular pair of triangles found (IDs {0}/{1}).", otri.triangle.id, otri1.triangle.id), "Quality.CheckDelaunay()");
                        num++;
                    }
                    otri.orient = otri.orient + 1;
                }
            }
            if (num == 0)
            {
                this.logger.Info("Mesh is Delaunay.");
            }
            Behavior.NoExact = noExact;
            return(num == 0);
        }
Пример #25
0
        private void ComputeCircumCenters()
        {
            Otri   otri = new Otri();
            double num  = 0;
            double num1 = 0;

            foreach (Triangle value in this.mesh.triangles.Values)
            {
                otri.triangle = value;
                Point point = Primitives.FindCircumcenter(otri.Org(), otri.Dest(), otri.Apex(), ref num, ref num1);
                point.id = value.id;
                this.points[value.id] = point;
                this.bounds.Update(point.x, point.y);
            }
            double num2 = Math.Max(this.bounds.Width, this.bounds.Height);

            this.bounds.Scale(num2, num2);
        }
Пример #26
0
        /// <summary>
        /// Write the triangles to an .ele file.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="filename"></param>
        public void WriteElements(Mesh mesh, string filename)
        {
            Otri   tri = default(Otri);
            Vertex p1, p2, p3;
            bool   regions = mesh.behavior.useRegions;

            int j = 0;

            tri.orient = 0;

            using (
#if NETFX_CORE
                var writer = new WinRTLegacy.IO.StreamWriter(filename)
#else
                var writer = new StreamWriter(filename)
#endif
                )
            {
                // Number of triangles, vertices per triangle, attributes per triangle.
                writer.WriteLine("{0} 3 {1}", mesh.triangles.Count, regions ? 1 : 0);

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

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

                    // Triangle number, indices for three vertices.
                    writer.Write("{0} {1} {2} {3}", j, p1.id, p2.id, p3.id);

                    if (regions)
                    {
                        writer.Write(" {0}", tri.tri.label);
                    }

                    writer.WriteLine();

                    // Number elements
                    item.id = j++;
                }
            }
        }
Пример #27
0
        /// <summary>
        /// Enumerate all edges of the given mesh.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="skipSegments"></param>
        /// <returns></returns>
        /// <remarks>
        /// In contrast to <see cref="EnumerateEdges(IMesh)"/> this method will return
        /// objects that include the vertex information (and not only the indices).
        /// </remarks>
        public static IEnumerable <ISegment> EnumerateEdges(IMesh mesh, bool skipSegments = true)
        {
            Otri tri      = default;
            Otri neighbor = default;
            Osub sub      = default;

            Vertex p1, p2;

            bool segments = !skipSegments;

            foreach (var t in mesh.Triangles)
            {
                tri.tri    = t;
                tri.orient = 0;

                for (int i = 0; i < 3; i++)
                {
                    tri.Sym(ref neighbor);

                    int nid = neighbor.tri.id;

                    if ((tri.tri.id < nid) || (nid == Mesh.DUMMY))
                    {
                        p1 = tri.Org();
                        p2 = tri.Dest();

                        tri.Pivot(ref sub);

                        if (sub.seg.hash == Mesh.DUMMY)
                        {
                            yield return(new Segment(p1, p2));
                        }
                        else if (segments)
                        {
                            // Segments might be processed separately, so only
                            // include them if requested.
                            yield return(sub.seg);
                        }
                    }

                    tri.orient++;
                }
            }
        }
Пример #28
0
        public bool MoveNext()
        {
            if (tri.tri == null)
            {
                return(false);
            }

            current = null;

            while (current == null)
            {
                if (tri.orient == 3)
                {
                    if (triangles.MoveNext())
                    {
                        tri.tri    = triangles.Current;
                        tri.orient = 0;
                    }
                    else
                    {
                        // Finally no more triangles
                        return(false);
                    }
                }

                tri.Sym(ref neighbor);

                if ((tri.tri.id < neighbor.tri.id) || (neighbor.tri.id == Mesh.DUMMY))
                {
                    p1 = tri.Org();
                    p2 = tri.Dest();

                    tri.Pivot(ref sub);

                    // Boundary mark of dummysub is 0, so we don't need to worry about that.
                    current = new Edge(p1.id, p2.id, sub.seg.boundary);
                }

                tri.orient++;
            }

            return(true);
        }
Пример #29
0
        public static void WriteOffFile(Mesh mesh, string filename)
        {
            Otri   otri  = new Otri();
            Vertex value = null;
            long   count = (long)mesh.vertices.Count;

            if (mesh.behavior.Jettison)
            {
                count = (long)(mesh.vertices.Count - mesh.undeads);
            }
            int num = 0;

            using (StreamWriter streamWriter = new StreamWriter(new FileStream(filename, FileMode.Create)))
            {
                streamWriter.WriteLine("OFF");
                streamWriter.WriteLine("{0}  {1}  {2}", count, mesh.triangles.Count, mesh.edges);
                foreach (Vertex v in mesh.vertices.Values)
                {
                    if (mesh.behavior.Jettison && v.type == VertexType.UndeadVertex)
                    {
                        continue;
                    }
                    double item = v[0];
                    string str  = item.ToString(FileWriter.nfi);
                    item = v[1];
                    streamWriter.WriteLine(" {0}  {1}  0.0", str, item.ToString(FileWriter.nfi));
                    int num1 = num;
                    num  = num1 + 1;
                    v.id = num1;
                }
                otri.orient = 0;
                foreach (Triangle triangle in mesh.triangles.Values)
                {
                    otri.triangle = triangle;
                    value         = otri.Org();
                    Vertex vertex  = otri.Dest();
                    Vertex vertex1 = otri.Apex();
                    streamWriter.WriteLine(" 3   {0}  {1}  {2}", value.id, vertex.id, vertex1.id);
                }
            }
        }
Пример #30
0
        private void GetAspectHistogram(Mesh mesh)
        {
            int[]    numArray  = new int[16];
            double[] numArray1 = new double[] { 1.5, 2, 2.5, 3, 4, 6, 10, 15, 25, 50, 100, 300, 1000, 10000, 100000, 0 };
            Otri     otri      = new Otri();

            Vertex[] vertexArray = new Vertex[3];
            double[] numArray2   = new double[3];
            double[] numArray3   = new double[3];
            double[] numArray4   = new double[3];
            otri.orient = 0;
            foreach (Triangle value in mesh.triangles.Values)
            {
                otri.triangle  = value;
                vertexArray[0] = otri.Org();
                vertexArray[1] = otri.Dest();
                vertexArray[2] = otri.Apex();
                double num = 0;
                for (int i = 0; i < 3; i++)
                {
                    int num1 = Statistic.plus1Mod3[i];
                    int num2 = Statistic.minus1Mod3[i];
                    numArray2[i] = vertexArray[num1].x - vertexArray[num2].x;
                    numArray3[i] = vertexArray[num1].y - vertexArray[num2].y;
                    numArray4[i] = numArray2[i] * numArray2[i] + numArray3[i] * numArray3[i];
                    if (numArray4[i] > num)
                    {
                        num = numArray4[i];
                    }
                }
                double num3 = Math.Abs((vertexArray[2].x - vertexArray[0].x) * (vertexArray[1].y - vertexArray[0].y) - (vertexArray[1].x - vertexArray[0].x) * (vertexArray[2].y - vertexArray[0].y)) / 2;
                double num4 = num / (num3 * num3 / num);
                int    num5 = 0;
                while (num4 > numArray1[num5] * numArray1[num5] && num5 < 15)
                {
                    num5++;
                }
                numArray[num5] = numArray[num5] + 1;
            }
        }