Ejemplo n.º 1
0
 public void Insert(HalfEdge lb, HalfEdge newHe)
 {
     newHe.EdgeListLeft = lb;
     newHe.EdgeListRight = lb.EdgeListRight;
     lb.EdgeListRight.EdgeListLeft = newHe;
     lb.EdgeListRight = newHe;
 }
Ejemplo n.º 2
0
        protected void AddVertex(Face face, Vertex vertex)
        {
            base.AddVertex(vertex);
            Faces.Remove(face);

            HalfEdge h1 = face.HalfEdge;
            HalfEdge h2 = h1.Next;
            HalfEdge h3 = h2.Next;

            HalfEdge h4 = new HalfEdge(h1.Origin);
            HalfEdge h5 = new HalfEdge(h2.Origin);
            HalfEdge h6 = new HalfEdge(h3.Origin);
            HalfEdge h7 = new HalfEdge(vertex);
            HalfEdge h8 = new HalfEdge(vertex);
            HalfEdge h9 = new HalfEdge(vertex);
            HalfEdges.AddRange(new List<HalfEdge> {h4, h5, h6, h7, h8, h9});

            h4.Twin = h7;
            h7.Twin = h4;
            h5.Twin = h8;
            h8.Twin = h5;
            h6.Twin = h9;
            h9.Twin = h6;

            // Set all next
            h1.Next = h5;
            h5.Prev = h1;
            h5.Next = h7;
            h7.Prev = h5;
            h7.Next = h1;
            h1.Prev = h7;

            h2.Next = h6;
            h6.Prev = h2;
            h6.Next = h8;
            h8.Prev = h6;
            h8.Next = h2;
            h2.Prev = h8;

            h3.Next = h4;
            h4.Prev = h3;
            h4.Next = h9;
            h9.Prev = h4;
            h9.Next = h3;
            h3.Prev = h9;

            Triangle t1 = new Triangle(h1);
            Triangle t2 = new Triangle(h2);
            Triangle t3 = new Triangle(h3);

            Faces.Add(t1);
            Faces.Add(t2);
            Faces.Add(t3);

            Tree.Add(vertex, t1, t2, t3);

            LogEntry logEntry = new LogEntry("Adding edges.", this);
            logEntry.Objects.Add(vertex);
            Log.Add(logEntry);
        }
Ejemplo n.º 3
0
		internal static void ELinsert(HalfEdge lb, HalfEdge New)
		{
			New.Left = lb;
			New.Right = lb.Right;
			lb.Right.Left = New;
			lb.Right = New;
		}
Ejemplo n.º 4
0
 public EdgeList( SiteList siteList) {
     _siteList = siteList;
     LeftEnd = new HalfEdge(null, Side.Left);
     RightEnd = new HalfEdge(null, Side.Left);
     LeftEnd.Right = RightEnd;
     RightEnd.Left = LeftEnd;
 }
Ejemplo n.º 5
0
        public HalfEdge(Vertex v)
        {
            _origin = new Vertex(v.X, v.Y);

            Twin = null;
            Next = null;
            Prev = null;
        }
Ejemplo n.º 6
0
		/// <summary>
		/// Half edge create
		/// </summary>
		internal static HalfEdge HEcreate(Edge e, int pm)
		{
			HalfEdge answer = new HalfEdge();//** Memory.getfree(hfl);
			answer.Edge = e;
			answer.ELpm = pm;
			answer.PQnext = null;
			answer.Vertex = null;
			answer.RefCount = 0;

			return answer;
		}
Ejemplo n.º 7
0
 public void Delete(HalfEdge he)
 {
     if (he.Vertex != null) {
         HalfEdge last = _hash[Bucket(he)];
         while (last.PriorityQueueNext != he) {
             last = last.PriorityQueueNext;
         }
         last.PriorityQueueNext = he.PriorityQueueNext;
         _count--;
         he.Vertex = null;
     }
 }
Ejemplo n.º 8
0
 public void Insert(HalfEdge he, Site v, float offset)
 {
     he.Vertex = v;
     he.YStar = v.Coord.Y + offset;
     var last = _hash[Bucket(he)];
     HalfEdge next;
     while ((next = last.PriorityQueueNext) != null && (he.YStar > next.YStar || he.YStar == next.YStar && v.Coord.X > next.Vertex.Coord.X)) {
         last = next;
     }
     he.PriorityQueueNext = last.PriorityQueueNext;
     last.PriorityQueueNext = he;
     _count++;
 }
Ejemplo n.º 9
0
 public EdgeList(int sqrtNSites)
 {
     HashSize = 2*sqrtNSites;
     Hash = new HalfEdge[HashSize];
     LeftEnd = HalfEdge.Create(null, LR.Left);
     RightEnd = HalfEdge.Create(null, LR.Left);
     LeftEnd.EdgeListLeft = null;
     LeftEnd.EdgeListRight = RightEnd;
     RightEnd.EdgeListLeft = LeftEnd;
     RightEnd.EdgeListRight = null;
     Hash[0] = LeftEnd;
     Hash[HashSize - 1] = RightEnd;
 }
Ejemplo n.º 10
0
		public static void PQdelete(HalfEdge he)
		{
			HalfEdge last;
			if (he.Vertex != null)
			{
				last = PQhash[PQbucket(he)];
				while (last.PQnext != he)
				{
					last = last.PQnext;
				}
				last.PQnext = he.PQnext;
				PQcount--;
				VoronoiGeometry.deref(he.Vertex);
				he.Vertex = null;
			}
		}
Ejemplo n.º 11
0
        /// <summary>
        /// Inserts an edge not already present into the graph.
        /// </summary>
        /// <param name="orig">the edge origin location</param>
        /// <param name="dest">the edge destination location</param>
        /// <param name="eAdj">an existing edge with same orig (if any)</param>
        /// <returns>the created edge</returns>
        private HalfEdge Insert(Coordinate orig, Coordinate dest, HalfEdge eAdj)
        {
            // edge does not exist, so create it and insert in graph
            HalfEdge e = Create(orig, dest);
            if (eAdj != null)
                eAdj.Insert(e);
            else vertexMap.Add(orig, e);

            HalfEdge eAdjDest;
            bool eAdjDestFound = vertexMap.TryGetValue(dest, out eAdjDest);
            HalfEdge sym = e.Sym;
            if (eAdjDestFound)
                eAdjDest.Insert(sym);
            else vertexMap.Add(dest, sym);
            return e;
        }
Ejemplo n.º 12
0
 public int Bucket(HalfEdge he)
 {
     int bucket;
     if (he.YStar < Geometry.Bounds.Top) bucket = 0;
     else if (he.YStar >= Geometry.Bounds.Bottom) bucket = _hashSize - 1;
     else bucket = (int) ((he.YStar - Geometry.Bounds.Top)/Geometry.DeltaY*_hashSize);
     if (bucket < 0) {
         bucket = 0;
     }
     if (bucket >= _hashSize) {
         bucket = _hashSize - 1;
     }
     if (bucket < _min) {
         _min = bucket;
     }
     return bucket;
 }
Ejemplo n.º 13
0
		public static int PQbucket(HalfEdge he)
		{
			int bucket;

			if (he.ystar < VoronoiMain.ymin) bucket = 0;
			else if (he.ystar >= VoronoiMain.ymax) bucket = PQhashsize - 1;
			else bucket = (int)((he.ystar - VoronoiMain.ymin) / VoronoiGeometry.deltay * PQhashsize);

			if (bucket < 0)
				bucket = 0;

			if (bucket >= PQhashsize)
				bucket = PQhashsize - 1;
			if (bucket < PQmin)
				PQmin = bucket;

			return bucket;
		}
Ejemplo n.º 14
0
		public static void PQinsert(HalfEdge he, Site v, double offset)
		{
			he.Vertex = v;
			VoronoiGeometry.Ref(v);
			he.ystar = v.Coord.Y + offset;
			HalfEdge last = PQhash[PQbucket(he)];

			HalfEdge next;
			while ((next = last.PQnext) != null &&
				(he.ystar > next.ystar || he.ystar == next.ystar && v.Coord.X > next.Vertex.Coord.X))
			{
				last = next;
			}

			he.PQnext = last.PQnext;
			last.PQnext = he;
			PQcount++;
		}
Ejemplo n.º 15
0
		internal static Site intersect(HalfEdge el1, HalfEdge el2)
		{
			Edge e1 = el1.Edge;
			Edge e2 = el2.Edge;
			Edge e;
			HalfEdge el;

			if (e1 == null || e2 == null)
				return null;
			if (e1.reg[1] == e2.reg[1])
				return null;

			double d = e1.a * e2.b - e1.b * e2.a;
			if (-1E-10 < d && d < 1E-10)
				return null;

			double xint = (e1.c * e2.b - e2.c * e1.b) / d;
			double yint = (e2.c * e1.a - e1.c * e2.a) / d;

			if (e1.reg[1].Coord.Y < e2.reg[1].Coord.Y ||
				e1.reg[1].Coord.Y == e2.reg[1].Coord.Y &&
				e1.reg[1].Coord.X < e2.reg[1].Coord.X)
			{
				el = el1;
				e = e1;
			}
			else
			{
				el = el2;
				e = e2;
			}

			bool right_of_site = xint >= e.reg[1].Coord.X;
			if (right_of_site && el.ELpm == EndPoint.Left ||
				!right_of_site && el.ELpm == EndPoint.Right)
				return null;

			Site v = new Site(); //** Memory.getfree(
			v.refCount = 0;
			v.Coord = new Point(xint, yint);

			return v;
		}
Ejemplo n.º 16
0
		public static void ELinitialize()
		{
			ELhashsize = 2 * VoronoiGeometry.sqrt_nsites;
			ELhash = new HalfEdge[ELhashsize];
			for (int i = 0; i < ELhashsize; i++)
			{
				ELhash[i] = null;
			}

			ELleftend = HEcreate(null, 0);
			ELrightend = HEcreate(null, 0);

			ELleftend.Left = null;
			ELleftend.Right = ELrightend;
			ELrightend.Left = ELleftend;
			ELrightend.Right = null;

			ELhash[0] = ELleftend;
			ELhash[ELhashsize - 1] = ELrightend;
		}
Ejemplo n.º 17
0
        ushort[] FindOutlines(Vector2[] vertices, ushort[] triangles)
        {
            var halfEdges = new HashSet<HalfEdge> ();
            for (var i = 0; i < triangles.Length; i+=3) {
                for (var j = 0; j < 3; j++) {
                    var t0 = triangles[j + i];
                    var t1 = triangles[(j + 1) % 3 + i];
                    var h = new HalfEdge(t0, t1);
                    halfEdges.Add(h);
                }
            }
            var outlines = new Dictionary<ushort, HalfEdge> ();
            var t = (ushort)0;
            foreach (var h0 in halfEdges) {
                var h1 = h0.Opposite();
                if (!halfEdges.Contains(h1))
                    outlines.Add(t = h0.t0, h0);
            }

            var result = new List<ushort> (outlines.Count * 2);
            while (outlines.Count > 0 && outlines.ContainsKey(t)) {
                var h = outlines[t];
                outlines.Remove(t);
                result.Add(h.t0);
                t = h.t1;
            }

            var k = 0;
            while (k < result.Count) {
                var t0 = result[k];
                var t1 = result[(k + 1) % outlines.Count];
                var d = vertices[t0] - vertices[t1];
                if (d.sqrMagnitude < (degenerationDistance * degenerationDistance))
                    result.RemoveAt(k);
                else
                    k++;
            }

            return result.ToArray ();
        }
Ejemplo n.º 18
0
        private void Flip(HalfEdge h)
        {
            HalfEdge h1 = h;
            HalfEdge h2 = h1.Next;
            HalfEdge h3 = h2.Next;
            HalfEdge h4 = h.Twin;
            HalfEdge h5 = h4.Next;
            HalfEdge h6 = h5.Next;

            if (h1.Face == null || h4.Face == null)
                return;

            LogEntry logEntry = new LogEntry("Flipping edge", this);
            logEntry.Objects.Add(new Edge(h.Origin, h.Next.Origin));
            Log.Add(logEntry);

            // Remove old faces
            Faces.Remove(h.Face);
            Faces.Remove(h.Twin.Face);

            h1.Next = h6;
            h6.Prev = h1;
            h6.Next = h2;
            h2.Prev = h6;
            h2.Next = h1;
            h1.Prev = h2;
            h1.Origin = h3.Origin;

            h4.Next = h3;
            h3.Prev = h4;
            h3.Next = h5;
            h5.Prev = h3;
            h5.Next = h4;
            h4.Prev = h5;
            h4.Origin = h6.Origin;

            Faces.Add(new Triangle(h1));
            Faces.Add(new Triangle(h1.Twin));
        }
Ejemplo n.º 19
0
 internal static Site Intersect(HalfEdge el1, HalfEdge el2)
 {
     var e1 = el1.Edge;
     var e2 = el2.Edge;
     if ((e1 == null) || e2 == null) {
         return null;
     }
     if (e1.Sites[LR.Right] == e2.Sites[LR.Right]) {
         return null;
     }
     var d = (e1.A*e2.B) - (e1.B*e2.A);
     if ((-1.0e-10 < d) && (d < 1.0e-10)) {
         return null;
     }
     var xint = (e1.C*e2.B - e2.C*e1.B)/d;
     var yint = (e2.C*e1.A - e1.C*e2.A)/d;
     HalfEdge el;
     Edge e;
     if ((e1.Sites[LR.Right].Coord.Y < e2.Sites[LR.Right].Coord.Y) ||
         (e1.Sites[LR.Right].Coord.Y == e2.Sites[LR.Right].Coord.Y &&
          e1.Sites[LR.Right].Coord.X < e2.Sites[LR.Right].Coord.X)) {
         el = el1;
         e = e1;
     } else {
         el = el2;
         e = e2;
     }
     var rightOfSite = (xint >= e.Sites[LR.Right].Coord.X);
     if ((rightOfSite && (el.LeftRight == LR.Left)) ||
         (!rightOfSite && (el.LeftRight == LR.Right))) {
         return null;
     }
     var v = new Site();
     v.Coord = new Vector2(xint, yint);
     return v;
 }
Ejemplo n.º 20
0
        public Triangle(HalfEdge halfEdge)
            : base(halfEdge)
        {
            Vertex v1 = HalfEdge.Origin;
            Vertex v2 = HalfEdge.Next.Origin;
            Vertex v3 = HalfEdge.Next.Next.Origin;
            Vertex v4 = HalfEdge.Next.Next.Next.Origin;

            if (v1 == v2 || v2 == v3 || v1 == v3)
                throw new IncorrectTriangleException("Triangle does not has a correct 3 vertex loop.");

            if (v1 != v4)
                throw new IncorrectTriangleException("Triangle does not has a correct 3 vertex loop.");

            // Fix halfedges to this face
            halfEdge.Face = this;
            halfEdge.Next.Face = this;
            halfEdge.Next.Next.Face = this;

            // Add vertices to the array
            Vertices.Add(v1);
            Vertices.Add(v2);
            Vertices.Add(v3);
        }
Ejemplo n.º 21
0
            public void Deleted(HalfEdge e)
            {
                Edges--;

                Assert.IsTrue(e.Primary);
            }
Ejemplo n.º 22
0
        private void Populate(UnityEngine.Mesh mesh)
        {
            edges = new Dictionary<long, HalfEdge>(mesh.triangles.Length);
            faces = new HashSet<Face>();
            vertexFaces = new Face[mesh.vertexCount];
            vertices = new Vector3[mesh.vertexCount];
            normals = new Vector3[mesh.vertexCount];
            uvs = new Vector2[mesh.vertexCount];

            verticesDelta = new HashSet<int>();

            Array.Copy(mesh.vertices, vertices, mesh.vertexCount);
            Array.Copy(mesh.normals, normals, mesh.vertexCount);
            Array.Copy(mesh.uv, uvs, mesh.vertexCount);

            var tris = mesh.triangles;

            for (int i = 0; i < tris.Length; i+=3)
            {
                var edge0 = HashEdge(tris[i],   tris[i + 1]);
                var edge1 = HashEdge(tris[i+1], tris[i + 2]);
                var edge2 = HashEdge(tris[i+2], tris[i]);

                var face = new Face(tris[i], tris[i+1], tris[i+2]);

                var he0 = new HalfEdge { face = face, point = tris[i]   };
                var he1 = new HalfEdge { face = face, point = tris[i+1] };
                var he2 = new HalfEdge { face = face, point = tris[i+2] };

                vertexFaces[tris[i]] = face;
                vertexFaces[tris[i+1]] = face;
                vertexFaces[tris[i+2]] = face;

                try
                {
                    he0.nextEdge = he1;
                    he1.nextEdge = he2;
                    he2.nextEdge = he0;

                    edges.Add(edge0, he0);
                    edges.Add(edge1, he1);
                    edges.Add(edge2, he2);

                    faces.Add(face);
                }
                catch{}
            //                catch (Exception ex)
            //                {
            //                    MeshUtils.Log("Duplicated face detected.");
            //                }
            }

            foreach (var halfEdge in edges.Values)
            {
                var p0 = halfEdge.point;
                var p1 = halfEdge.nextEdge.point;

                if (halfEdge.oppositeEdge == null)
                {
                    var oppositeEdgeHash = HashEdge(p1, p0);
                    HalfEdge oppositeHalfEdge;

                    if (edges.TryGetValue(oppositeEdgeHash, out oppositeHalfEdge))
                    {
                        halfEdge.oppositeEdge = oppositeHalfEdge;
                        oppositeHalfEdge.oppositeEdge = halfEdge;
                    }
                }
            }
        }
Ejemplo n.º 23
0
 /// <summary>
 /// Tries to find an already existing halfedge for the given vertices
 /// </summary>
 /// <param name="origin"></param>
 /// <param name="target"></param>
 /// <param name="result">The matching halfedge, or null</param>
 /// <returns>true on success, false on failure</returns>
 public bool TryGetHalfEdgeBetweenVertices(Vertex origin, Vertex target, out HalfEdge result)
 {
     return(HalfEdgeQuery.TryGetHalfEdge(origin, target, out result));
 }
 void Mesh.IChangeListener.Deleted(HalfEdge e)
 {
 }
Ejemplo n.º 25
0
 /// <summary>
 /// 右ハーフエッジについて(相互)接続します
 /// </summary>
 /// <param name="right"></param>
 internal void ConnectRight(HalfEdge right)
 {
     this.Right     = right;
     right.HostEdge = this;
 }
    //Alternative 1. Triangulate with some algorithm - then flip edges until we have a delaunay triangulation
    public static List <Triangle> TriangulateByFlippingEdges(List <Vector3> sites)
    {
        //Step 1. Triangulate the points with some algorithm
        //Vector3 to vertex
        List <Vertex> vertices = new List <Vertex>();

        for (int i = 0; i < sites.Count; i++)
        {
            vertices.Add(new Vertex(sites[i]));
        }

        //Triangulate the convex hull of the sites
        List <Triangle> triangles = IncrementalTriangulationAlgorithm.TriangulatePoints(vertices);
        //List<Triangle> triangles = TriangulatePoints.IncrementalTriangulation(vertices);

        //List triangles = TriangulatePoints.TriangleSplitting(vertices);

        //Step 2. Change the structure from triangle to half-edge to make it faster to flip edges
        List <HalfEdge> halfEdges = TransformFromTriangleToHalfEdge(triangles);
        // // List<HalfEdge> halfEdges = TransformRepresentation.TransformFromTriangleToHalfEdge(triangles);

        //Step 3. Flip edges until we have a delaunay triangulation
        int safety = 0;

        int flippedEdges = 0;

        while (true)
        {
            safety += 1;

            if (safety > 100000)
            {
                Debug.Log("Stuck in endless loop");

                break;
            }

            bool hasFlippedEdge = false;

            //Search through all edges to see if we can flip an edge
            for (int i = 0; i < halfEdges.Count; i++)
            {
                HalfEdge thisEdge = halfEdges[i];

                //Is this edge sharing an edge, otherwise its a border, and then we cant flip the edge
                if (thisEdge.oppositeEdge == null)
                {
                    continue;
                }

                //The vertices belonging to the two triangles, c-a are the edge vertices, b belongs to this triangle
                Vertex a = thisEdge.v;
                Vertex b = thisEdge.nextEdge.v;
                Vertex c = thisEdge.prevEdge.v;
                Vertex d = thisEdge.oppositeEdge.nextEdge.v;

                Vector2 aPos = a.GetPos2D_XZ();
                Vector2 bPos = b.GetPos2D_XZ();
                Vector2 cPos = c.GetPos2D_XZ();
                Vector2 dPos = d.GetPos2D_XZ();

                //Use the circle test to test if we need to flip this edge
                if (Geometry.IsPointInsideOutsideOrOnCircle(aPos, bPos, cPos, dPos) < 0f)
                {
                    //Are these the two triangles that share this edge forming a convex quadrilateral?
                    //Otherwise the edge cant be flipped
                    if (Geometry.IsQuadrilateralConvex(aPos, bPos, cPos, dPos))
                    {
                        //If the new triangle after a flip is not better, then dont flip
                        //This will also stop the algoritm from ending up in an endless loop
                        if (Geometry.IsPointInsideOutsideOrOnCircle(bPos, cPos, dPos, aPos) < 0f)
                        {
                            continue;
                        }

                        //Flip the edge
                        flippedEdges += 1;

                        hasFlippedEdge = true;

                        FlipEdge(thisEdge);
                    }
                }
            }

            //We have searched through all edges and havent found an edge to flip, so we have a Delaunay triangulation!
            if (!hasFlippedEdge)
            {
                //Debug.Log("Found a delaunay triangulation");

                break;
            }
        }

        //Debug.Log("Flipped edges: " + flippedEdges);

        //Dont have to convert from half edge to triangle because the algorithm will modify the objects, which belongs to the
        //original triangles, so the triangles have the data we need

        return(triangles);
    }
Ejemplo n.º 27
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        ///  <summary>	Updates the Trapezoid which an endpoint of the edge is located in. </summary>
        ///
        ///  <remarks>	Note - we presume the caller is modifying trapezoids intersected by the side from
        ///             left to right.  The lNeighborTop and lNeighborBottom are the top and bottom
        ///             trapezoids created by the edge splitting in the trapezoid to our left.  This is
        ///             so we can merge one of our upper or lower traps with the one on the left. Generally
        ///                 we can't merge right traps into left ones because the right trapezoids haven't been
        ///                 created yet.
        ///
        ///                 Darrell Plank, 2/12/2018. </remarks>
        ///
        ///  <param name="oldTrap">	The trapNode which contains the left endpoint. </param>
        ///  <param name="edge">	    The edge whose left endpoint is in the trapezoid. </param>
        /// <param name="lNeighborTop"> The left neighbor's top trapezoid </param>
        /// <param name="lNeighborBottom"> The left neighbor's bottom trapezoid </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        public PlacementNode  UpdateEndTrapezoid(Trapezoid oldTrap, HalfEdge edge, ref Trapezoid lNeighborTop, ref Trapezoid lNeighborBottom)
        {
            (var belowFace, var aboveFace) = GetFaces(edge);

            // The edge splits some portion of our trapezoid vertically.  Determine the extent of that
            // region and which vertices bound it.
            var trapLeft  = oldTrap.LeftVtx.X;
            var trapRight = oldTrap.RightVtx.X;
            var edgeLeft  = edge.InitVertex.X;
            var edgeRight = edge.NextVertex.X;

            // "meets" in this context means the side shares a previously established vertex.
            // "exceeds" means "goes past" which means it splits through
            // the side of the trap.  If neither of these is true, it ends in the proper
            // interior of the trapezoid.

            // We can use equality here since these will be coming from a shared vertex
            // ReSharper disable CompareOfFloatsByEqualityOperator
            var meetsLeft  = trapLeft == edgeLeft;
            var meetsRight = trapRight == edgeRight;
            // ReSharper restore CompareOfFloatsByEqualityOperator
            //
            var exceedsLeft   = trapLeft > edgeLeft;
            var exceedsRight  = trapRight < edgeRight;
            var interiorLeft  = trapLeft < edgeLeft;
            var interiorRight = trapRight > edgeRight;

            var midRightVtx = meetsRight || exceedsRight ? oldTrap.RightVtx : edge.NextVertex;
            var midLeftVtx  = meetsLeft || exceedsLeft ? oldTrap.LeftVtx : edge.InitVertex;

            // The newly created traps to be inserted into the map
            Trapezoid above, below, left, right;

            // Create left trapezoid if necessary
            if (interiorLeft)
            {
                left = new Trapezoid
                {
                    RightVtx       = midLeftVtx,
                    LeftVtx        = oldTrap.LeftVtx,
                    LeftTop        = oldTrap.LeftTop,
                    LeftBottom     = oldTrap.LeftBottom,
                    BottomEdge     = oldTrap.BottomEdge,
                    TopEdge        = oldTrap.TopEdge,
                    ContainingFace = oldTrap.ContainingFace
                };
                oldTrap.LeftBottom?.LinkTo(oldTrap, left, true);
                oldTrap.LeftTop?.LinkTo(oldTrap, left, true);
            }
            else
            {
                left = null;
            }

            // Create right trapezoid if necessary
            if (interiorRight)
            {
                right = new Trapezoid
                {
                    RightVtx       = oldTrap.RightVtx,
                    LeftVtx        = midRightVtx,
                    RightBottom    = oldTrap.RightBottom,
                    LeftBottom     = oldTrap.LeftBottom,
                    BottomEdge     = oldTrap.BottomEdge,
                    TopEdge        = oldTrap.TopEdge,
                    ContainingFace = oldTrap.ContainingFace
                };
                oldTrap.RightBottom?.LinkTo(oldTrap, right, false);
                oldTrap.RightTop?.LinkTo(oldTrap, right, false);
            }
            else
            {
                right = null;
            }

            TrapNode aboveNode = null, belowNode = null;

            // Create top/bottom trapezoids (which is always necessary)
            if (exceedsLeft)
            {
                // These assumptions need to be met when merging below.  This should all compile out
                // in the release build.
                Debug.Assert(oldTrap.LeftTop == null ^ oldTrap.LeftBottom == null);
                Debug.Assert(lNeighborBottom != null && lNeighborTop != null);

                if (oldTrap.LeftBottom == null)
                {
                    // Old trap's left side comes up from vertex below and we're cutting it off so merge top traps
                    above          = lNeighborTop;
                    above.RightVtx = midRightVtx;
                    aboveNode      = above.Node;

                    // Create new bottom trap
                    below = new Trapezoid
                    {
                        RightVtx       = midRightVtx,
                        LeftVtx        = midLeftVtx,
                        LeftTop        = lNeighborBottom,
                        TopEdge        = edge,
                        BottomEdge     = oldTrap.BottomEdge,
                        ContainingFace = belowFace
                    };
                    lNeighborBottom.RightTop = below;
                }
                else
                {
                    // Merge bottom traps
                    below          = lNeighborBottom;
                    below.RightVtx = midRightVtx;
                    belowNode      = below.Node;

                    // Create new top trap
                    above = new Trapezoid
                    {
                        RightVtx       = midRightVtx,
                        LeftVtx        = midLeftVtx,
                        LeftBottom     = lNeighborTop,
                        BottomEdge     = edge,
                        TopEdge        = oldTrap.TopEdge,
                        ContainingFace = aboveFace
                    };
                    lNeighborTop.RightBottom = above;
                }
            }
            else if (meetsLeft)
            {
                var leftOfTopTrap    = oldTrap.LeftTop;
                var leftOfBottomTrap = oldTrap.LeftBottom;

                above = new Trapezoid
                {
                    RightVtx       = midRightVtx,
                    LeftVtx        = midLeftVtx,
                    LeftTop        = leftOfTopTrap,
                    TopEdge        = oldTrap.TopEdge,
                    BottomEdge     = edge,
                    ContainingFace = aboveFace
                };

                below = new Trapezoid
                {
                    RightVtx       = midRightVtx,
                    LeftVtx        = midLeftVtx,
                    LeftBottom     = leftOfBottomTrap,
                    BottomEdge     = oldTrap.BottomEdge,
                    TopEdge        = edge,
                    ContainingFace = belowFace
                };

                oldTrap.LeftTop?.LinkTo(oldTrap, above, true);
                oldTrap.LeftBottom?.LinkTo(oldTrap, below, true);
            }
            else
            {
                // Interior on left - i.e., we created a left trapezoid within the old trapezoid
                above = new Trapezoid
                {
                    RightVtx       = midRightVtx,
                    LeftVtx        = midLeftVtx,
                    LeftTop        = left,
                    TopEdge        = oldTrap.TopEdge,
                    BottomEdge     = edge,
                    ContainingFace = aboveFace
                };

                below = new Trapezoid
                {
                    RightVtx       = midRightVtx,
                    LeftVtx        = midLeftVtx,
                    LeftBottom     = left,
                    BottomEdge     = oldTrap.BottomEdge,
                    TopEdge        = edge,
                    ContainingFace = belowFace
                };
                // ReSharper disable once PossibleNullReferenceException
                left.RightTop    = above;
                left.RightBottom = below;
            }

            if (meetsRight)
            {
                above.RightTop    = oldTrap.RightTop;
                above.RightBottom = null;
                below.RightTop    = null;
                below.RightBottom = oldTrap.RightBottom;
                oldTrap.RightTop?.LinkTo(oldTrap, above, false);
                oldTrap.RightBottom?.LinkTo(oldTrap, below, false);
            }
            else if (interiorRight)
            {
                above.RightTop    = right;
                above.RightBottom = null;
                below.RightTop    = null;
                below.RightBottom = right;
                right.LeftTop     = above;
                right.LeftBottom  = below;
            }
            // If exceedRight then we'll be backpatched in the next trap to the right.

            if (aboveNode == null)
            {
                aboveNode = new TrapNode(above);
            }

            if (belowNode == null)
            {
                belowNode = new TrapNode(below);
            }

            lNeighborTop    = above;
            lNeighborBottom = below;

            // Okay - finally done with the map.  Now to deal with the tree.
            // We always have the edge split to concern ourselves with
            PlacementNode repl = new YNode(edge.InitVertex.Position, edge.NextVertex.Position, aboveNode, belowNode);

            // Do we split off a right trap?
            if (interiorRight)
            {
                repl = new XNode(repl, new TrapNode(right), right.LeftVtx);
                //repl = new XNode(repl, new TrapNode(right), midRight);
            }

            // How about splitting off a left trap?
            if (interiorLeft)
            {
                repl = new XNode(new TrapNode(left), repl, left.RightVtx);
                //repl = new XNode(new TrapNode(left), repl, midLeft);
            }

            return(repl);
        }
Ejemplo n.º 28
0
            public void Added(HalfEdge e)
            {
                Edges++;

                Assert.IsTrue(e.Primary);
            }
Ejemplo n.º 29
0
 public static void Insert(HalfEdge lb, HalfEdge he) {
     he.Left = lb;
     he.Right = lb.Right;
     lb.Right.Left = he;
     lb.Right = he;
 }
Ejemplo n.º 30
0
 public override HalfEdge <T> CreateHalfEdge(Vertex <T> vertex, HalfEdge <T> opposite, Face <T> face, HalfEdge <T> nextEdge)
 {
     return(new PrevEdgeHalfEdge <T>(vertex, opposite, face, nextEdge));
 }
Ejemplo n.º 31
0
        public static DcelMesh ToDCEL(Mesh mesh)
        {
            var dcel = new DcelMesh();

            var vertices = new HVertex[mesh.vertices.Count];
            var faces    = new Face[mesh.triangles.Count];

            dcel.HalfEdges.Capacity = 2 * mesh.NumberOfEdges;

            mesh.Renumber();

            HVertex vertex;

            foreach (var v in mesh.vertices.Values)
            {
                vertex       = new HVertex(v.x, v.y);
                vertex.id    = v.id;
                vertex.label = v.label;

                vertices[v.id] = vertex;
            }

            // Maps a triangle to its 3 edges (used to set next pointers).
            var map = new List <HalfEdge> [mesh.triangles.Count];

            Face face;

            foreach (var t in mesh.triangles)
            {
                face    = new Face(null);
                face.id = t.id;

                faces[t.id] = face;

                map[t.id] = new List <HalfEdge>(3);
            }

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

            TriangleNet.Geometry.Vertex org, dest;

            int id, nid, count = mesh.triangles.Count;

            HalfEdge edge, twin, next;

            var edges = dcel.HalfEdges;

            // Count half-edges (edge ids).
            int k = 0;

            // Maps a vertex to its leaving boundary edge.
            var boundary = new Dictionary <int, HalfEdge>();

            foreach (var t in mesh.triangles)
            {
                id = t.id;

                tri.tri = t;

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

                    nid = neighbor.tri.id;

                    if (id < nid || nid < 0)
                    {
                        face = faces[id];

                        // Get the endpoints of the current triangle edge.
                        org  = tri.Org();
                        dest = tri.Dest();

                        // Create half-edges.
                        edge = new HalfEdge(vertices[org.id], face);
                        twin = new HalfEdge(vertices[dest.id], nid < 0 ? Face.Empty : faces[nid]);

                        map[id].Add(edge);

                        if (nid >= 0)
                        {
                            map[nid].Add(twin);
                        }
                        else
                        {
                            boundary.Add(dest.id, twin);
                        }

                        // Set leaving edges.
                        edge.origin.leaving = edge;
                        twin.origin.leaving = twin;

                        // Set twin edges.
                        edge.twin = twin;
                        twin.twin = edge;

                        edge.id = k++;
                        twin.id = k++;

                        edges.Add(edge);
                        edges.Add(twin);
                    }
                }
            }

            // Set next pointers for each triangle face.
            foreach (var t in map)
            {
                edge = t[0];
                next = t[1];

                if (edge.twin.origin.id == next.origin.id)
                {
                    edge.next = next;
                    next.next = t[2];
                    t[2].next = edge;
                }
                else
                {
                    edge.next = t[2];
                    next.next = edge;
                    t[2].next = next;
                }
            }

            // Resolve boundary edges.
            foreach (var e in boundary.Values)
            {
                e.next = boundary[e.twin.origin.id];
            }

            dcel.Vertices.AddRange(vertices);
            dcel.Faces.AddRange(faces);

            return(dcel);
        }
Ejemplo n.º 32
0
        private void DrawHeEdges(DrawPen borderPen, DrawPen edgePen, double edgeThreshold, HeModel model)
        {
            bool drawBorder = !borderPen.IsNullPen;
            bool drawEdge   = !edgePen.IsNullPen;

            if (!drawBorder && !drawEdge)
            {
                return;
            }

            DisableLight();

            GL.LineWidth(1.0f);

            Color4 color     = borderPen.Color4();
            Color4 edgeColor = edgePen.Color4();

            Vector3d shift = GetShiftForOutLine();

            Vector3d p0;
            Vector3d p1;

            for (int i = 0; i < model.FaceStore.Count; i++)
            {
                HeFace f = model.FaceStore[i];

                HalfEdge head = f.Head;

                HalfEdge c = head;

                HalfEdge pair;

                p0 = model.VertexStore.Ref(c.Vertex).vector *DC.WorldScale + shift;

                for (; ;)
                {
                    bool drawAsEdge = false;

                    pair = c.Pair;

                    if (drawEdge)
                    {
                        if (pair == null)
                        {
                            drawAsEdge = true;
                        }
                        else
                        {
                            if (edgeThreshold != 0)
                            {
                                double s = CadMath.InnerProduct(model.NormalStore[c.Normal], model.NormalStore[pair.Normal]);

                                if (Math.Abs(s) <= edgeThreshold)
                                {
                                    drawAsEdge = true;
                                }
                            }
                        }
                    }

                    p1 = model.VertexStore.Ref(c.Next.Vertex).vector *DC.WorldScale + shift;

                    if (drawAsEdge)
                    {
                        GL.Color4(edgeColor);
                        GL.Begin(PrimitiveType.Lines);
                        GL.Vertex3(p0);
                        GL.Vertex3(p1);
                        GL.End();
                    }
                    else
                    {
                        if (drawBorder)
                        {
                            GL.Color4(color);
                            GL.Begin(PrimitiveType.Lines);
                            GL.Vertex3(p0);
                            GL.Vertex3(p1);
                            GL.End();
                        }
                    }

                    p0 = p1;

                    c = c.Next;

                    if (c == head)
                    {
                        break;
                    }
                }
            }
        }
Ejemplo n.º 33
0
 /// <summary>
 /// Le suivant de l'opposé
 /// </summary>
 /// <param name="dart">Brin actuel</param>
 /// <returns>Retourne le brin du point suivant</returns>
 public HalfEdge NextDartOnPoint(HalfEdge dart)
 {
     return(dart.Opposite.Next);
 }
Ejemplo n.º 34
0
 // Relie de points pour former une arête
 private void LinkTwoDegeneratedDarts(HalfEdge dart1, HalfEdge dart2)
 {
     dart1.SetHalfEdge(dart2, dart2, dart2);
     dart2.SetHalfEdge(dart1, dart1, dart1);
 }
Ejemplo n.º 35
0
 public Site RightRegion(HalfEdge he) {
     if (he.Edge == null) {
         return _siteList.BottomSite;
     }
     return he.Side == Side.Left ? he.Edge.Region[Side.Right] : he.Edge.Region[Side.Left];
 }
Ejemplo n.º 36
0
 public void SplitMidpointEnd(HalfEdge e, Vertex mid)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 37
0
 protected override void ChangeBoundaryToInternalHook(HalfEdge edge)
 {
     _boundaryEdges.Remove(edge);
 }
Ejemplo n.º 38
0
        internal static bool TrySplitFace(this Kernel kernel, HalfEdge start, HalfEdge end, out (Face, Face) parts)
        {
            parts = (null, null);
            // TODO: Error checks

            // get edges for face of both halfedges
            var edges = new EdgeIterator(start).ToArray();

            // can't split triangles
            if (edges.Length <= 3)
            {
                return(false);
            }

            // get the index of the end edge inside the edges array
            var endIndex = Array.IndexOf(edges, end);

            // create the new ending halfedge for the start half
            var newEnd = new HalfEdge
            {
                Face     = start.Face,
                Next     = start,
                Previous = edges[endIndex - 1],
                Origin   = end.Origin
            };

            // create the new Face for the end half
            var newFace = new Face {
                Start = end
            };
            // create a new starting edge for the end half
            var newStart = new HalfEdge
            {
                Face     = newFace,
                Next     = end,
                Previous = edges.Last(),
                Origin   = start.Origin,
                Pair     = newEnd
            };

            // pair up the new end
            newEnd.Pair = newStart;

            // establish circular link for first face
            var firstFaceEdges = edges.Take(endIndex).ToList();

            firstFaceEdges.Add(newEnd);
            EdgeLinker.LinkOrderedEdgeCollection(firstFaceEdges);

            // hacky re-assignment
            newEnd.Face.Start = newEnd.Next;

            // establish circular link for second face
            var secondFaceEdges = edges.Skip(endIndex).ToList();

            secondFaceEdges.Insert(0, newStart);
            EdgeLinker.LinkOrderedEdgeCollection(secondFaceEdges);
            secondFaceEdges.ForEach(e => e.Face = newFace);

            // Add new edges to kernel
            kernel.Add(newEnd);
            kernel.Add(newStart);

            // add new face
            kernel.Insert(newFace);

            // prepare output
            parts = (start.Face, newFace);
            return(true);
        }
 void Mesh.IChangeListener.Added(HalfEdge e)
 {
 }
Ejemplo n.º 40
0
 private void Process(HalfEdge e)
 {
     HalfEdge eNode = e.PrevNode();
     // if edge is in a ring, just process this edge
     if (eNode == null)
         eNode = e;
     StackEdges(eNode);
     // extract lines from node edges in stack
     BuildLines();
 }
 void Mesh.IChangeListener.SplitMidpointBegin(HalfEdge e, Vertex mid)
 {
 }
Ejemplo n.º 42
0
        private void BuildRing(HalfEdge eStartRing)
        {
            CoordinateList line = new CoordinateList();
            HalfEdge e = eStartRing;

            Coordinate orig = e.Orig;
            line.Add(orig.Clone(), false);
            // scan along the path until a node is found (if one exists)
            while (e.Sym.Degree() == 2)
            {
                HalfEdge eNext = e.Next;
                // check if edges form a ring - if so, we're done
                if (eNext == eStartRing)
                    break;

                // add point to line, and move to next edge
                orig = eNext.Orig;
                line.Add(orig.Clone(), false);
                e = eNext;
            }
            // add final node
            Coordinate dest = e.Dest;
            line.Add(dest.Clone(), false);

            // store the scanned line
            AddLine(line);
        }
Ejemplo n.º 43
0
 /// <summary>
 /// Inserts a <see cref="HalfEdge"/> instance into the kernel.
 /// For this to work the halfedge needs linking information present on its
 /// <see cref="HalfEdge.Next"/> and <see cref="HalfEdge.Previous" /> properties.
 /// If no linking information is present for the <see cref="HalfEdge.Pair"/>, a new pair edge
 /// will be created and inserted as a naked edge
 /// </summary>
 /// <param name="edge"></param>
 /// <returns>true on success, false on failure</returns>
 public bool Insert(HalfEdge edge)
 {
     return(_halfEdges.Insert(edge));
 }
Ejemplo n.º 44
0
 /// <summary>
 /// 左ハーフエッジについて(相互)接続します
 /// </summary>
 /// <param name="left"></param>
 internal void ConnectLeft(HalfEdge left)
 {
     this.Left     = left;
     left.HostEdge = this;
 }
Ejemplo n.º 45
0
        /// <summary>
        /// Adds a new face to the kernel
        /// </summary>
        /// <param name="positions"></param>
        public bool AddFace(IEnumerable <Vec3d> positions)
        {
            // No bad faces please :(
            if (positions.Count() < 3)
            {
                return(false);
            }

            // convert positions to vertices inside the mesh
            var vertices = VertexQuery.GetVerticesForPositions(_vertices, positions);

            // if the positions had stacked vertices, we might not be able to continue
            if (vertices.Count() < 3)
            {
                // iterate over position vertices
                foreach (var vertex in vertices)
                {
                    // if the vertex was old, it will have an outgoing
                    if (vertex.Outgoing != null)
                    {
                        continue;
                    }

                    // if it was new we need to remove it to restore state
                    Remove(vertex);
                }

                return(false);
            }

            var edges = new List <HalfEdge>();

            // iterate over all positions
            foreach (var vertex in vertices)
            {
                // create a new halfedge originating from the current vertex and linked to the new face
                var halfEdge = new HalfEdge
                {
                    Origin = vertex,
                };

                // test if the vertex already has an outgoing edge assigned
                if (vertex.Outgoing is null)
                {
                    vertex.Outgoing = halfEdge;
                }

                edges.Add(halfEdge);
            }

            // Insert a face from the edges
            Insert(edges);

            // iterate over all edges and insert them
            foreach (var edge in edges)
            {
                // TODO: Maybe we should NOT skip linking checks here
                _halfEdges.Add(edge);
            }

            // test if first face
            if (this.FaceCount == 1)
            {
                var outerRing = new EdgeIterator(
                    _halfEdges[0])
                                .Select(h => h.Pair)
                                .Reverse()
                                .ToList();

                // establish circular link between outside half-edges
                EdgeLinker.LinkOrderedEdgeCollection(outerRing);
            }

            // TODO: Should be method of edgelinker instead
            // Make sure edge pairs either have a starting face or the ghost face
            // Iterators are lazy, calling `Count()` will execute the select body
            _ = edges.Where(e => e.Pair.Face == null).Select(e => e.Pair.Face = Kernel.Outside).Count();

            return(true);

            // TODO: Make sure outer halfEdges are linked,too
            // TODO: Right now only inner halfEdges are linked circularly
            // TODO: This leads to crashes on faces with too many naked edges when creating vertexringiterators
            // TODO: For this we will need a 'ghost' face that encompasses all the space outside of the mesh faces
            // TODO: CLosed meshes will have an empty ghost face
        }
Ejemplo n.º 46
0
        public void TestHasPrevious_HasNoPrevious()
        {
            HalfEdge edge = Auxilaries.RandomHalfEdge();

            Assert.IsFalse(edge.HasPrevious);
        }
Ejemplo n.º 47
0
        public float GetNearestEdge(Ray ray, out HalfEdge minEdge, bool excludeBackSidePolygons)
        {
            var localOrigin = Transform.InverseTransformPoint(ray.origin);
            var localDir = Transform.InverseTransformDirection(ray.direction);
            var localRay = new Ray(localOrigin, localDir);

            var minDistance = float.MaxValue;
            minEdge = null;

            foreach (var edge in edges.Values)
            {
                var p0 = vertices[edge.point];
                var p1 = vertices[edge.nextEdge.point];

                var squaredDist = MeshUtils.SegmentSegmentDistance2(p0, p1, localRay.origin, localRay.origin + localRay.direction*10000.0f);

                if (squaredDist < minDistance)
                {
                    if (excludeBackSidePolygons)
                    {
                        var p2 = vertices[edge.nextEdge.nextEdge.point];

                        if (!Utils.Plane.GetSide(p0, p1, p2, localRay.origin))
                        {
                            continue;
                        }
                    }

                    minDistance = squaredDist;
                    minEdge = edge;
                }
            }

            return minDistance;
        }
Ejemplo n.º 48
0
        public void TestHasNext_HasNoNext()
        {
            HalfEdge edge = Auxilaries.RandomHalfEdge();

            Assert.IsFalse(edge.HasNext);
        }
Ejemplo n.º 49
0
 public BreakpointNode(Site leftSite, Site rightSite, HalfEdge halfEdge, bool isLeftBreakpoint)
 {
     LeftSite = leftSite;
     RightSite = rightSite;
     HalfEdge = halfEdge;
     IsLeftBreakpoint = isLeftBreakpoint;
 }
Ejemplo n.º 50
0
        public void TestHasDestination_HasNoDestination()
        {
            HalfEdge edge = Auxilaries.RandomHalfEdge();

            Assert.IsFalse(edge.HasDestination);
        }
Ejemplo n.º 51
0
        public void TestHasIncidentFace_HasNoIncidentFace()
        {
            HalfEdge edge = Auxilaries.RandomHalfEdge();

            Assert.IsFalse(edge.HasDestination);
        }
Ejemplo n.º 52
0
    //From triangle where each triangle has one vertex to half edge
    public static List <HalfEdge> TransformFromTriangleToHalfEdge(List <Triangle> triangles)
    {
        //Make sure the triangles have the same orientation
        MeshOperations.OrientTrianglesClockwise(triangles);

        //First create a list with all possible half-edges
        List <HalfEdge> halfEdges = new List <HalfEdge>(triangles.Count * 3);

        for (int i = 0; i < triangles.Count; i++)
        {
            Triangle t = triangles[i];

            HalfEdge he1 = new HalfEdge(t.v1);
            HalfEdge he2 = new HalfEdge(t.v2);
            HalfEdge he3 = new HalfEdge(t.v3);

            he1.nextEdge = he2;
            he2.nextEdge = he3;
            he3.nextEdge = he1;

            he1.prevEdge = he3;
            he2.prevEdge = he1;
            he3.prevEdge = he2;

            //The vertex needs to know of an edge going from it
            he1.v.halfEdge = he2;
            he2.v.halfEdge = he3;
            he3.v.halfEdge = he1;

            //The face the half-edge is connected to
            t.halfEdge = he1;

            he1.t = t;
            he2.t = t;
            he3.t = t;

            //Add the half-edges to the list
            halfEdges.Add(he1);
            halfEdges.Add(he2);
            halfEdges.Add(he3);
        }

        //Find the half-edges going in the opposite direction
        for (int i = 0; i < halfEdges.Count; i++)
        {
            HalfEdge he = halfEdges[i];

            Vertex goingToVertex   = he.v;
            Vertex goingFromVertex = he.prevEdge.v;

            for (int j = 0; j < halfEdges.Count; j++)
            {
                //Dont compare with itself
                if (i == j)
                {
                    continue;
                }

                HalfEdge heOpposite = halfEdges[j];

                //Is this edge going between the vertices in the opposite direction
                if (goingFromVertex.position == heOpposite.v.position && goingToVertex.position == heOpposite.prevEdge.v.position)
                {
                    he.oppositeEdge = heOpposite;

                    break;
                }
            }
        }


        return(halfEdges);
    }
Ejemplo n.º 53
0
 public static void Delete(HalfEdge he) {
     he.Left.Right = he.Right;
     he.Right.Left = he.Left;
     he.Edge = null;
 }
Ejemplo n.º 54
0
 protected override void AddBoundaryEdgeHook(HalfEdge edge)
 {
     _boundaryEdges.Add(edge);
 }
 public Triangle(HalfEdge halfEdge)
 {
     this.halfEdge = halfEdge;
 }
    //Flip an edge
    private static void FlipEdge(HalfEdge one)
    {
        //The data we need
        //This edge's triangle
        HalfEdge two   = one.nextEdge;
        HalfEdge three = one.prevEdge;
        //The opposite edge's triangle
        HalfEdge four = one.oppositeEdge;
        HalfEdge five = one.oppositeEdge.nextEdge;
        HalfEdge six  = one.oppositeEdge.prevEdge;
        //The vertices
        Vertex a = one.v;
        Vertex b = one.nextEdge.v;
        Vertex c = one.prevEdge.v;
        Vertex d = one.oppositeEdge.nextEdge.v;



        //Flip

        //Change vertex
        a.halfEdge = one.nextEdge;
        c.halfEdge = one.oppositeEdge.nextEdge;

        //Change half-edge
        //Half-edge - half-edge connections
        one.nextEdge = three;
        one.prevEdge = five;

        two.nextEdge = four;
        two.prevEdge = six;

        three.nextEdge = five;
        three.prevEdge = one;

        four.nextEdge = six;
        four.prevEdge = two;

        five.nextEdge = one;
        five.prevEdge = three;

        six.nextEdge = two;
        six.prevEdge = four;

        //Half-edge - vertex connection
        one.v   = b;
        two.v   = b;
        three.v = c;
        four.v  = d;
        five.v  = d;
        six.v   = a;

        //Half-edge - triangle connection
        Triangle t1 = one.t;
        Triangle t2 = four.t;

        one.t   = t1;
        three.t = t1;
        five.t  = t1;

        two.t  = t2;
        four.t = t2;
        six.t  = t2;

        //Opposite-edges are not changing!

        //Triangle connection
        t1.v1 = b;
        t1.v2 = c;
        t1.v3 = d;

        t2.v1 = b;
        t2.v2 = d;
        t2.v3 = a;

        t1.halfEdge = three;
        t2.halfEdge = four;
    }
Ejemplo n.º 57
0
        /// <summary>
        /// Builds a line starting from the given edge.
        /// The start edge origin is a node (valence = 1 or >= 3), 
        /// unless it is part of a pure ring.
        /// </summary>
        /// <remarks>
        /// A pure ring has no other incident lines.
        /// In this case the start edge may occur anywhere on the ring.
        /// </remarks>
        /// <remarks>
        /// The line is built up to the next node encountered,
        /// or until the start edge is re-encountered
        /// (which happens if the edges form a ring).
        /// </remarks>
        /// <param name="eStart"></param>
        private void BuildLine(HalfEdge eStart)
        {
            CoordinateList line = new CoordinateList();
            DissolveHalfEdge e = (DissolveHalfEdge)eStart;
            _ringStartEdge = null;

            MarkHalfEdge.MarkBoth(e);
            Coordinate orig = e.Orig;
            line.Add(orig.Clone(), false);
            // scan along the path until a node is found (if one exists)
            while (e.Sym.Degree() == 2)
            {
                UpdateRingStartEdge(e);
                DissolveHalfEdge eNext = (DissolveHalfEdge)e.Next;
                // check if edges form a ring - if so, we're done
                if (eNext == eStart)
                {
                    BuildRing(_ringStartEdge);
                    return;
                }
                // add point to line, and move to next edge
                orig = eNext.Orig;
                line.Add(orig.Clone(), false);
                e = eNext;
                MarkHalfEdge.MarkBoth(e);
            }
            // add final node
            Coordinate dest = e.Dest;
            line.Add(dest.Clone(), false);

            // queue up the final node edges
            StackEdges(e.Sym);
            // store the scanned line
            AddLine(line);
        }
Ejemplo n.º 58
0
        public void TestEquals_NotEqualsDifferentIncidentFaces()
        {
            Vertex a = Auxilaries.RandomVertex();
            Vertex b = Auxilaries.RandomVertex();
            Vertex c = Auxilaries.RandomVertex();

            HalfEdge abOther = new HalfEdge(a);
            HalfEdge abThis  = new HalfEdge(a);
            HalfEdge ac      = new HalfEdge(a);

            HalfEdge ba = new HalfEdge(b);
            HalfEdge bc = new HalfEdge(b);

            HalfEdge ca = new HalfEdge(c);
            HalfEdge cb = new HalfEdge(c);

            Vector3 normal = Auxilaries.RandomNormal();

            Face thisFace = new Face(0, normal);

            thisFace.AddOuterComponent(abThis);
            thisFace.AddOuterComponent(bc);
            thisFace.AddOuterComponent(ca);

            Face otherFace = new Face(1, normal);

            otherFace.AddOuterComponent(abOther);

            abThis.IncidentFace  = thisFace;
            abOther.IncidentFace = otherFace;

            abThis.Twin  = ba;
            abOther.Twin = ba;
            ac.Twin      = ca;

            ba.Twin = abThis;
            bc.Twin = bc;

            ca.Twin = ac;
            cb.Twin = bc;

            abThis.Next  = bc;
            abOther.Next = bc;
            ac.Next      = cb;

            ba.Next = ac;
            bc.Next = ca;

            ca.Next = abThis;
            cb.Next = ba;

            abThis.Previous  = ca;
            abOther.Previous = ca;
            ac.Previous      = ba;

            ba.Previous = cb;
            bc.Previous = abThis;

            ca.Previous = bc;
            cb.Previous = ac;

            Assert.AreNotEqual(abThis.GetHashCode(), abOther.GetHashCode());

            Assert.IsFalse(abThis.Equals(abOther));
            Assert.IsFalse(abOther.Equals(abThis));
        }
Ejemplo n.º 59
0
 /// <summary>
 /// Adds edges around this node to the stack.
 /// </summary>
 /// <param name="node"></param>
 private void StackEdges(HalfEdge node)
 {
     HalfEdge e = node;
     do
     {
         if (!MarkHalfEdge.IsMarked(e))
             _nodeEdgeStack.Push(e);
         e = e.ONext;
     } while (e != node);
 }
Ejemplo n.º 60
0
        public void TestHasTwin_HasNoTwin()
        {
            HalfEdge edge = Auxilaries.RandomHalfEdge();

            Assert.IsFalse(edge.HasTwin);
        }