private void CheckOnEdge(Cell cell, int x, int y, HandleEdge workOnEdge) { var neighbours = Neighbour.None; if (x == 0) { neighbours |= Neighbour.Left; } if (x == _map.NumberOfTiles) { neighbours |= Neighbour.Right; } if (y == 0) { neighbours |= Neighbour.Top; } if (y == _map.NumberOfTiles) { neighbours |= Neighbour.Bottom; } if ((neighbours & Neighbour.Left) == Neighbour.Left) { workOnEdge(cell, x, y, -1, 0); } if ((neighbours & Neighbour.Top) == Neighbour.Top) { workOnEdge(cell, x, y, 0, -1); } if ((neighbours & Neighbour.Right) == Neighbour.Right) { workOnEdge(cell, x, y, 1, 0); } if ((neighbours & Neighbour.Bottom) == Neighbour.Bottom) { workOnEdge(cell, x, y, 0, 1); } if ((neighbours & Neighbour.LeftTop) == Neighbour.LeftTop) { workOnEdge(cell, x, y, -1, -1); } if ((neighbours & Neighbour.RightTop) == Neighbour.RightTop) { workOnEdge(cell, x, y, 1, -1); } if ((neighbours & Neighbour.LeftBottom) == Neighbour.LeftBottom) { workOnEdge(cell, x, y, -1, 1); } if ((neighbours & Neighbour.RightBottom) == Neighbour.RightBottom) { workOnEdge(cell, x, y, 1, 1); } }
/// <summary> /// Establishes a connection between two vertices. /// 1) Creates two half-edges /// 2) Fills them with information /// 3) Creates an edge pointer container and adds it to the geo container. /// 4) returns a handle to an edge /// </summary> /// <param name="fromVert">HandleVertex from which vertex</param> /// <param name="toVert">Handlevertex to which vertex</param> /// <returns>Returns a handle to the half-edge that has just been inserted</returns> public HandleHalfEdge CreateConnection(HandleVertex fromVert, HandleVertex toVert) { // Check if the connection does already exist. HandleEdge existingEdge = DoesConnectionExist(fromVert, toVert); if (existingEdge != -1) { return(ReuseExistingConnection(existingEdge, fromVert, toVert)); } else { return(CreateAllNewConnection(fromVert, toVert)); } }
/// <summary> /// For testing only now. /// </summary> /// <param name="existingEdge"></param> /// <param name="fromVert"></param> /// <param name="toVert"></param> /// <returns></returns> private HandleHalfEdge ReuseExistingConnection(HandleEdge existingEdge, HandleVertex fromVert, HandleVertex toVert) { // Check half-edge 1 and 2 if one points to the actual face. This is the one we use for our face then. If no one we build a new connection. HEdgePtrCont hedge1 = _LhedgePtrCont[_LedgePtrCont[existingEdge]._he1]; HEdgePtrCont hedge2 = _LhedgePtrCont[_LedgePtrCont[existingEdge]._he2]; HandleHalfEdge hedgeToUse = new HandleHalfEdge(-1); if (hedge2._f == -1) { // It is hedge 2 that is free. We should use it. hedgeToUse = _LedgePtrCont[existingEdge]._he2; } else if (hedge1._f == -1) { // It is hedge 1 that is free. We should use it. Should never happen. TODO: Exception throw? hedgeToUse = _LedgePtrCont[existingEdge]._he1; } else { // Neither one of the faces of the existing half-edges was free so we build a new edge. return(CreateAllNewConnection(fromVert, toVert)); } // Updating the face pointer. HEdgePtrCont hedge = _LhedgePtrCont[hedgeToUse]; hedge._f = new HandleFace(_LfacePtrCont.Count - 1); _LhedgePtrCont[hedgeToUse] = new HEdgePtrCont() { _f = hedge._f, _he = hedge._he, _nhe = hedge._nhe, _v = hedge._v, _vn = hedge._vn, _vuv = hedge._vuv }; return(hedgeToUse); }
/// <summary> /// This method converts a quad based 'Geometry' object to a triangle based one. /// </summary> private void TriangulateGeometry() { List <HandleFace> LtmpFaces = new List <HandleFace>(); foreach (HandleFace currentFace in _LfaceHndl) { // Pruefe zuerst ob man das face triangulaten sollte oder nicht. if (EnFaceAdjacentHalfEdges(currentFace).Count() == 3) { continue; } // Hole aktuelles face und merke den index. FacePtrCont currentFaceCont = _LfacePtrCont[currentFace]; // Merke erste hedge h0. HandleHalfEdge h0H = currentFaceCont._h; HEdgePtrCont h0Cont = _LhedgePtrCont[h0H]; // Merke ersten vert v0. HandleVertex v0H = _LhedgePtrCont[h0Cont._he]._v; // Merke die letzte hedge im face hl. //HandleHalfEdge hlH = RetLastHalfEdgeInFaceCw(currentFace); var temp = EnFaceAdjacentHalfEdges(currentFace); HandleHalfEdge hlH = temp.ElementAt(temp.Count() - 1); HEdgePtrCont hlCont = _LhedgePtrCont[hlH]; // Lege zwei neue hedges an und fülle sie korrekt. int hedgeCount = _LhedgePtrCont.Count; HandleHalfEdge hedge0H = new HandleHalfEdge() { _DataIndex = hedgeCount }; HandleHalfEdge hedge1H = new HandleHalfEdge() { _DataIndex = hedgeCount + 1 }; HandleEdge edgeHNew = new HandleEdge() { _DataIndex = _LedgeHndl.Count }; EdgePtrCont edgeContNew = new EdgePtrCont() { _he1 = hedge0H, _he2 = hedge1H }; HEdgePtrCont newhedge0 = new HEdgePtrCont() { _nhe = h0H, _v = v0H, _he = hedge1H, _f = currentFace, _vn = hlCont._vn, _vuv = hlCont._vuv }; // Hole h1 und h2 zum Merken. HandleHalfEdge h1H = h0Cont._nhe; HEdgePtrCont h1Cont = _LhedgePtrCont[h1H]; HandleHalfEdge h2H = h1Cont._nhe; HEdgePtrCont h2Cont = _LhedgePtrCont[h2H]; HEdgePtrCont newhedge1 = new HEdgePtrCont() { _nhe = h1Cont._nhe, _v = h1Cont._v, _he = hedge0H, _f = new HandleFace(-1), _vn = h1Cont._vn, _vuv = h1Cont._vuv, }; // Update die jeweiligen next pointer der angrenzenden hedges. h1Cont._nhe = hedge0H; hlCont._nhe = hedge1H; // Lege ein neues face an für das triangle 2. HandleFace f1H = new HandleFace() { _DataIndex = (_LfaceHndl.Count - 1) + LtmpFaces.Count + 1 }; FacePtrCont f1Cont = new FacePtrCont() { _fn = currentFaceCont._fn, _h = hlH }; // Update das neue triangle bezüglich des neuen faces. Dazu erstmal h2 holen noch. newhedge1._f = f1H; h2Cont._f = f1H; hlCont._f = f1H; // Sichere die Änderungen in den listen. _LedgeHndl.Add(edgeHNew); _LedgePtrCont.Add(edgeContNew); _LhedgePtrCont.Add(newhedge0); _LhedgePtrCont.Add(newhedge1); // Speichere das face handle erstmal in tmp faces wegen der iteration. LtmpFaces.Add(f1H); _LfacePtrCont.Add(f1Cont); _LhedgePtrCont[h1H] = new HEdgePtrCont() { _f = h1Cont._f, _he = h1Cont._he, _nhe = h1Cont._nhe, _v = h1Cont._v, _vn = h1Cont._vn, _vuv = h1Cont._vuv }; _LhedgePtrCont[h2H] = new HEdgePtrCont() { _f = h2Cont._f, _he = h2Cont._he, _nhe = h2Cont._nhe, _v = h2Cont._v, _vn = h2Cont._vn, _vuv = h2Cont._vuv }; _LhedgePtrCont[hlH] = new HEdgePtrCont() { _f = hlCont._f, _he = hlCont._he, _nhe = hlCont._nhe, _v = hlCont._v, _vn = hlCont._vn, _vuv = hlCont._vuv }; } foreach (HandleFace handleFace in LtmpFaces) { _LfaceHndl.Add(handleFace); } LtmpFaces.Clear(); }
private void CheckOnEdge(Cell cell, int x, int y, HandleEdge workOnEdge) { var neighbours = Neighbour.None; if (x == 0) neighbours |= Neighbour.Left; if (x == _map.NumberOfTiles) neighbours |= Neighbour.Right; if (y == 0) neighbours |= Neighbour.Top; if (y == _map.NumberOfTiles) neighbours |= Neighbour.Bottom; if ((neighbours & Neighbour.Left) == Neighbour.Left) { workOnEdge(cell, x, y, -1, 0); } if ((neighbours & Neighbour.Top) == Neighbour.Top) { workOnEdge(cell, x, y, 0, -1); } if ((neighbours & Neighbour.Right) == Neighbour.Right) { workOnEdge(cell, x, y, 1, 0); } if ((neighbours & Neighbour.Bottom) == Neighbour.Bottom) { workOnEdge(cell, x, y, 0, 1); } if ((neighbours & Neighbour.LeftTop) == Neighbour.LeftTop) { workOnEdge(cell, x, y, -1, -1); } if ((neighbours & Neighbour.RightTop) == Neighbour.RightTop) { workOnEdge(cell, x, y, 1, -1); } if ((neighbours & Neighbour.LeftBottom) == Neighbour.LeftBottom) { workOnEdge(cell, x, y, -1, 1); } if ((neighbours & Neighbour.RightBottom) == Neighbour.RightBottom) { workOnEdge(cell, x, y, 1, 1); } }