Пример #1
0
        /// <summary>
        ///     Find the intersection of an existing segment and a segment that is being
        ///     inserted. Insert a vertex at the intersection, splitting an existing subsegment.
        /// </summary>
        /// <param name="splittri"></param>
        /// <param name="splitsubseg"></param>
        /// <param name="endpoint2"></param>
        /// <remarks>
        ///     The segment being inserted connects the apex of splittri to endpoint2.
        ///     splitsubseg is the subsegment being split, and MUST adjoin splittri.
        ///     Hence, endpoints of the subsegment being split are the origin and
        ///     destination of splittri.
        ///     On completion, splittri is a handle having the newly inserted
        ///     intersection point as its origin, and endpoint1 as its destination.
        /// </remarks>
        private void SegmentIntersection(ref Otri splittri, ref Osub splitsubseg, Vertex endpoint2)
        {
            Osub               opposubseg = default(Osub);
            Vertex             endpoint1;
            Vertex             torg, tdest;
            Vertex             leftvertex, rightvertex;
            Vertex             newvertex;
            InsertVertexResult success;

            var dummysub = mesh.dummysub;

            double ex, ey;
            double tx, ty;
            double etx, ety;
            double split, denom;

            // Find the other three segment endpoints.
            endpoint1 = splittri.Apex();
            torg      = splittri.Org();
            tdest     = splittri.Dest();
            // Segment intersection formulae; see the Antonio reference.
            tx    = tdest.X - torg.X;
            ty    = tdest.Y - torg.Y;
            ex    = endpoint2.X - endpoint1.X;
            ey    = endpoint2.Y - endpoint1.Y;
            etx   = torg.X - endpoint2.X;
            ety   = torg.Y - endpoint2.Y;
            denom = ty * ex - tx * ey;
            if (denom == 0.0)
            {
                throw new Exception("Attempt to find intersection of parallel segments.");
            }
            split = (ey * etx - ex * ety) / denom;

            // Create the new vertex.
            newvertex = new Vertex(
                torg.X + split * (tdest.X - torg.X),
                torg.Y + split * (tdest.Y - torg.Y),
                splitsubseg.seg.boundary);

            newvertex.Id = mesh.hash_vtx++;

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

            // Insert the intersection vertex.  This should always succeed.
            success = mesh.InsertVertex(newvertex, ref splittri, ref splitsubseg, false, false);
            if (success != InsertVertexResult.Successful)
            {
                throw new Exception("Failure to split a segment.");
            }
            // Record a triangle whose origin is the new vertex.
            newvertex.tri = splittri;
            if (mesh.steinerleft > 0)
            {
                mesh.steinerleft--;
            }

            // Divide the segment into two, and correct the segment endpoints.
            splitsubseg.Sym();
            splitsubseg.Pivot(ref opposubseg);
            splitsubseg.Dissolve(dummysub);
            opposubseg.Dissolve(dummysub);
            do
            {
                splitsubseg.SetSegOrg(newvertex);
                splitsubseg.Next();
            } while (splitsubseg.seg.hash != Mesh.DUMMY);
            do
            {
                opposubseg.SetSegOrg(newvertex);
                opposubseg.Next();
            } while (opposubseg.seg.hash != Mesh.DUMMY);

            // Inserting the vertex may have caused edge flips.  We wish to rediscover
            // the edge connecting endpoint1 to the new intersection vertex.
            FindDirection(ref splittri, endpoint1);

            rightvertex = splittri.Dest();
            leftvertex  = splittri.Apex();
            if ((leftvertex.X == endpoint1.X) && (leftvertex.Y == endpoint1.Y))
            {
                splittri.Onext();
            }
            else if ((rightvertex.X != endpoint1.X) || (rightvertex.Y != endpoint1.Y))
            {
                throw new Exception("Topological inconsistency after splitting a segment.");
            }
            // 'splittri' should have destination endpoint1.
        }