IList <IndexSegment> setupEdges(IList <int> vertxIndices) { IList <IndexSegment> indexList = new List <IndexSegment>(); int boundLinesDictOffset = 0; if (boundaryLinesDict == null) { IEqualityComparer <IndexSegment> segCompare = new SegmentCompare(); boundaryLinesDict = new Dictionary <IndexSegment, int>(segCompare); } else { boundLinesDictOffset = boundaryLinesDict.Count(); } for (int ii = 0; ii < vertxIndices.Count; ++ii) { IndexSegment segm; if (ii == vertxIndices.Count - 1) { segm = new IndexSegment(vertxIndices[ii], vertxIndices[0]); } else { segm = new IndexSegment(vertxIndices[ii], vertxIndices[ii + 1]); } indexList.Add(segm); boundaryLinesDict.Add(segm, ii + boundLinesDictOffset); // boundaryLinesDict is a dictionary for the combined outer and inner boundaries, the values should be sequential } return(indexList); }
/// <summary> /// Find matched line segment in the face boundaries /// </summary> /// <param name="inpSeg">Input line segment as vertex indices</param> /// <returns>Return index of the matched segment</returns> public int FindMatchedIndexSegment(IndexSegment inpSeg) { int idx; if (BoundaryLinesDict.TryGetValue(inpSeg, out idx)) { return(idx); } else { return(-1); } }
void SetupEdges(IList <int> vertxIndices, int idxOffset) { int boundLinesDictOffset = 0; if (BoundaryLinesDict == null) { IEqualityComparer <IndexSegment> segCompare = new SegmentComparer(false /*compareBothDirections*/); BoundaryLinesDict = new Dictionary <IndexSegment, int>(segCompare); } else { boundLinesDictOffset = BoundaryLinesDict.Count(); } int prevIdx = 0; int idx = 0; int vertCount = vertxIndices.Count; foreach (int vIdx in vertxIndices) { IndexSegment segm = null; if (idx > 0) { segm = new IndexSegment(prevIdx, vIdx); OuterAndInnerBoundaries.Add(idx - 1 + idxOffset, segm); BoundaryLinesDict.Add(segm, (idx - 1 + boundLinesDictOffset)); // boundaryLinesDict is a dictionary for the combined outer and inner boundaries, the values should be sequential } if (idx == vertCount - 1) // The last index. Close the loop by connecing it to the first index { segm = new IndexSegment(vIdx, vertxIndices[0]); OuterAndInnerBoundaries.Add((idx + idxOffset), segm); BoundaryLinesDict.Add(segm, (idx + boundLinesDictOffset)); // boundaryLinesDict is a dictionary for the combined outer and inner boundaries, the values should be sequential } prevIdx = vIdx; idx++; } }
/// <summary> /// Go through the input face list that share the same vertex and has the same normal (coplannar). /// </summary> /// <param name="inputFaceList"></param> /// <param name="outputFaceList"></param> /// <returns>True if done successfully</returns> void TryMergeFaces(List <int> inputFaceList, out List <int> outputFaceList) { outputFaceList = new List <int>(); IndexFace firstF = m_FacesCollDict[inputFaceList[0]]; int currProcFace = inputFaceList[0]; inputFaceList.RemoveAt(0); // remove the first face from the list bool merged = false; IEqualityComparer <IndexSegment> segCompare = new SegmentComparer(false /*compareBothDirections*/); IDictionary <IndexSegment, Tuple <int, int> > segmentOfFaceDict = new Dictionary <IndexSegment, Tuple <int, int> >(segCompare); IList <int> discardList = new List <int>(); foreach (int fidx in inputFaceList) { if (!SegmentOfFaceToDict(ref segmentOfFaceDict, fidx)) { discardList.Add(fidx); } } // Remove bad face from the input list, if any if (discardList.Count > 0) { foreach (int fidx in discardList) { inputFaceList.Remove(fidx); } } discardList.Clear(); while (inputFaceList.Count > 0) { IndexFace mergedFace = null; for (int currEdgeIdx = 0; currEdgeIdx < firstF.OuterAndInnerBoundaries.Count; currEdgeIdx++) { IndexSegment currEdge = firstF.OuterAndInnerBoundaries[currEdgeIdx]; IndexSegment reversedEdge = currEdge.Reverse(); IndexFace currFace = null; int currFaceIdx = -1; int idx = -1; Tuple <int, int> pairedFace = null; if (!segmentOfFaceDict.TryGetValue(reversedEdge, out pairedFace)) { if (!segmentOfFaceDict.TryGetValue(currEdge, out pairedFace)) { merged = false; continue; } else { currFaceIdx = pairedFace.Item1; currFace = m_FacesCollDict[currFaceIdx]; // Need to reverse the face boundaries. Remove the entries in the Dict first, reverse the face, and add them back for (int cidx = 0; cidx < currFace.OuterAndInnerBoundaries.Count; ++cidx) { segmentOfFaceDict.Remove(currFace.OuterAndInnerBoundaries[cidx]); } currFace.Reverse(); if (!SegmentOfFaceToDict(ref segmentOfFaceDict, currFaceIdx)) { // Something is wrong with this face (should not be here in the normal circumstance), discard it and continue inputFaceList.Remove(currFaceIdx); merged = false; continue; } if (!segmentOfFaceDict.TryGetValue(reversedEdge, out pairedFace)) { if (!segmentOfFaceDict.TryGetValue(currEdge, out pairedFace)) { // Should not be here. If somehow here, discard the face and continue inputFaceList.Remove(currFaceIdx); merged = false; continue; } } idx = pairedFace.Item2; } } else { currFaceIdx = pairedFace.Item1; currFace = m_FacesCollDict[currFaceIdx]; idx = pairedFace.Item2; } // Now we need to check other edges of this face whether there is other coincide edge (this is in the case of hole(s)) List <int> fFaceIdxList = new List <int>(); List <int> currFaceIdxList = new List <int>(); int ci = -1; foreach (KeyValuePair <int, IndexSegment> idxSeg in currFace.OuterAndInnerBoundaries) { ci++; if (ci == idx) { continue; // skip already known coincide edge } int ffIdx = -1; IndexSegment reL = new IndexSegment(idxSeg.Value.EndPIndex, idxSeg.Value.StartPindex); ffIdx = firstF.FindMatchedIndexSegment(reL); if (ffIdx > 0) { fFaceIdxList.Add(ffIdx); // List of edges to skip when merging currFaceIdxList.Add(ci); // List of edges to skip when merging } } // Now we will remove the paired edges and merge the faces List <IndexSegment> newFaceEdges = new List <IndexSegment>(); for (int ii = 0; ii < currEdgeIdx; ii++) { bool toSkip = false; if (fFaceIdxList.Count > 0) { toSkip = fFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(firstF.OuterAndInnerBoundaries[ii]); // add the previous edges from the firstF faces first. This will skip the currEdge } } // Add the next-in-sequence edges from the second face for (int ii = idx + 1; ii < currFace.OuterAndInnerBoundaries.Count; ii++) { bool toSkip = false; if (currFaceIdxList.Count > 0) { toSkip = currFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(currFace.OuterAndInnerBoundaries[ii]); } } for (int ii = 0; ii < idx; ii++) { bool toSkip = false; if (currFaceIdxList.Count > 0) { toSkip = currFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(currFace.OuterAndInnerBoundaries[ii]); } } for (int ii = currEdgeIdx + 1; ii < firstF.OuterAndInnerBoundaries.Count; ii++) { bool toSkip = false; if (fFaceIdxList.Count > 0) { toSkip = fFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(firstF.OuterAndInnerBoundaries[ii]); } } // Build a new face // Important to note that the list of edges may not be continuous if there is a hole. We need to go through the list here to identify whether there is any such // discontinuity and collect the edges into their respective loops List <List <IndexSegment> > loops = new List <List <IndexSegment> >(); List <IndexSegment> loopEdges = new List <IndexSegment>(); loops.Add(loopEdges); IndexSegment prevSegm = newFaceEdges[0]; foreach (IndexSegment idxSeg in newFaceEdges) { if (prevSegm == idxSeg) { loopEdges.Add(idxSeg); } else { if (idxSeg.StartPindex == prevSegm.EndPIndex) { loopEdges.Add(idxSeg); } else { // Discontinuity detected loopEdges = new List <IndexSegment>(); // start new loop loops.Add(loopEdges); loopEdges.Add(idxSeg); } } prevSegm = idxSeg; } List <List <IndexSegment> > finalLoops = new List <List <IndexSegment> >(); { while (loops.Count > 1) { // There are more than 1 loops, need to consolidate if there are fragments to combine due to their continuity between the fragments int toDelIdx = -1; for (int ii = 1; ii < loops.Count; ii++) { if (loops[0][loops[0].Count - 1].EndPIndex == loops[ii][0].StartPindex) { // found continuity, merge the loops List <IndexSegment> newLoop = new List <IndexSegment>(loops[0]); newLoop.AddRange(loops[ii]); finalLoops.Add(newLoop); toDelIdx = ii; break; } } if (toDelIdx > 0) { loops.RemoveAt(toDelIdx); // !!!! Important to remove the later member first before removing the first one loops.RemoveAt(0); } else { // No continuity found, copy the first loop to the final loop List <IndexSegment> newLoop = new List <IndexSegment>(loops[0]); finalLoops.Add(newLoop); loops.RemoveAt(0); } } if (loops.Count > 0) { // Add remaining list into the final loops finalLoops.AddRange(loops); } } if (finalLoops.Count > 1) { // Find the largest loop and put it in the first position signifying the outer loop and the rest are the inner loops int largestPerimeterIdx = 0; double largestPerimeter = 0.0; for (int i = 0; i < finalLoops.Count; i++) { double loopPerimeter = 0.0; foreach (IndexSegment line in finalLoops[i]) { loopPerimeter += line.Extent(ref m_MeshVertices); } if (loopPerimeter > largestPerimeter) { largestPerimeter = loopPerimeter; largestPerimeterIdx = i; } } // We need to move the largest loop into the head if it is not if (largestPerimeterIdx > 0) { List <IndexSegment> largestLoop = new List <IndexSegment>(finalLoops[largestPerimeterIdx]); finalLoops.RemoveAt(largestPerimeterIdx); finalLoops.Insert(0, largestLoop); } } // Collect the vertices from the list of Edges into list of list of vertices starting with the outer loop (largest loop) following the finalLoop IList <IList <int> > newFaceVertsLoops = new List <IList <int> >(); foreach (List <IndexSegment> loop in finalLoops) { IList <int> newFaceVerts = new List <int>(); foreach (IndexSegment idxSeg in loop) { newFaceVerts.Add(idxSeg.StartPindex); } if (newFaceVerts.Count > 0) { if (newFaceVerts.Count >= 3) { newFaceVertsLoops.Add(newFaceVerts); } else { // Something wrong, a face cannot have less than 3 vertices Debug.WriteLine("Something went wrong when merging faces resulting with a loop that has less than 3 vertices"); } } } mergedFace = new IndexFace(newFaceVertsLoops, ref m_MeshVertices); inputFaceList.Remove(currFaceIdx); // Remove the merged face from segmentOfFaceDict foreach (KeyValuePair <int, IndexSegment> idxSeg in m_FacesCollDict[currFaceIdx].OuterAndInnerBoundaries) { segmentOfFaceDict.Remove(idxSeg.Value); } if (m_FacesCollDict.ContainsKey(currFaceIdx)) { m_FacesCollDict.Remove(currFaceIdx); } merged = true; break; // Once there is an edge merged, create a new face and continue the process of merging } int lastFaceID = faceIdxOffset++; // The new index is always the next one in the collection was inserted based on the seq order if (mergedFace != null) { m_FacesCollDict.Add(lastFaceID, mergedFace); } if (!merged) { // No edge match for this face, add the face into the output face list and move to the next face in the input list outputFaceList.Add(currProcFace); if (inputFaceList.Count > 0) { firstF = m_FacesCollDict[inputFaceList[0]]; // Remove the merged face from segmentOfFaceDict foreach (KeyValuePair <int, IndexSegment> idxSeg in firstF.OuterAndInnerBoundaries) { segmentOfFaceDict.Remove(idxSeg.Value); } currProcFace = inputFaceList[0]; // keep the last processed item inputFaceList.RemoveAt(0); // remove the first face from the list merged = false; // If there is no more face to process, add the merged face into the output list if (inputFaceList.Count == 0) { outputFaceList.Add(currProcFace); } } } else { // If there is no more face to process, add the merged face into the output list if (inputFaceList.Count == 0) { outputFaceList.Add(lastFaceID); } // Remove merged face from the Dict if (m_FacesCollDict.ContainsKey(currProcFace)) { m_FacesCollDict.Remove(currProcFace); } if (inputFaceList.Count > 0) { // use the current face as the next face as a merge candidate firstF = mergedFace; currProcFace = lastFaceID; merged = false; } } } // Finally, there may be multiple faces left because there are multiple disconnected faces at the same normal. Collect them and return if (segmentOfFaceDict.Count > 0) { HashSet <int> indexFaces = new HashSet <int>(); foreach (KeyValuePair <IndexSegment, Tuple <int, int> > segmentFace in segmentOfFaceDict) { indexFaces.Add(segmentFace.Value.Item1); } foreach (int idxFace in indexFaces) { outputFaceList.Add(idxFace); } } }
/// <summary> /// Test whether a line segment coincides with this one (must be exactly the same start - end, or end - start) /// </summary> /// <param name="inputSegment">Line segment to test for coincidence</param> /// <param name="compareBothDirections">Whether to check if the input segment is the reverse of this one</param> /// <returns>True if coincide</returns> public bool Coincide(IndexSegment inputSegment, bool compareBothDirections) { return((StartPindex == inputSegment.StartPindex && EndPIndex == inputSegment.EndPIndex) || (compareBothDirections && (EndPIndex == inputSegment.StartPindex && StartPindex == inputSegment.EndPIndex))); }
/// <summary> /// Test whether a line segment coincides with this one (must be exactly the same start - end, or end - start) /// </summary> /// <param name="inputSegment"></param> /// <returns>True if coincide</returns> public bool coincide(IndexSegment inputSegment) { return((startPindex == inputSegment.startPindex && endPIndex == inputSegment.endPIndex) || (endPIndex == inputSegment.startPindex && startPindex == inputSegment.endPIndex)); }
/// <summary> /// Test whether a line segment coincides with this one (must be exactly the same start - end, or end - start) /// </summary> /// <param name="inputSegment">Line segment to test for coincidence</param> /// <param name="compareBothDirections">Whether to check if the input segment is the reverse of this one</param> /// <returns>True if coincide</returns> public bool coincide(IndexSegment inputSegment, bool compareBothDirections) { return((startPindex == inputSegment.startPindex && endPIndex == inputSegment.endPIndex) || (compareBothDirections && (endPIndex == inputSegment.startPindex && startPindex == inputSegment.endPIndex))); }
/// <summary> /// Go through the input face list that share the same vertex and has the same normal (coplannar). /// </summary> /// <param name="inputFaceList"></param> /// <param name="outputFaceList"></param> /// <returns>True if done successfully</returns> bool TryMergeFaces(List <int> inputFaceList, out List <int> outputFaceList) { outputFaceList = new List <int>(); IndexFace firstF = facesColl[inputFaceList[0]]; //int prevFirstFIdx = 0; HashSet <int> mergedFacesIdxList = new HashSet <int>(); mergedFacesIdxList.Add(inputFaceList[0]); inputFaceList.RemoveAt(0); // remove the first face from the list int currEdgeIdx = 0; bool merged = false; IEqualityComparer <IndexSegment> segCompare = new SegmentCompare(); IDictionary <IndexSegment, Tuple <IndexFace, int, int> > segmentOfFaceDict = new Dictionary <IndexSegment, Tuple <IndexFace, int, int> >(segCompare); IList <int> discardList = new List <int>(); for (int iFace = 0; iFace < inputFaceList.Count; ++iFace) { int fidx = inputFaceList[iFace]; IndexFace IdxFace = facesColl[fidx]; if (!segmentOfFaceToDict(ref segmentOfFaceDict, ref IdxFace, fidx)) { discardList.Add(fidx); } } // Remove bad face from the input list, if any if (discardList.Count > 0) { foreach (int fidx in discardList) { inputFaceList.Remove(fidx); } } discardList.Clear(); while (currEdgeIdx < firstF.outerAndInnerBoundaries.Count && inputFaceList.Count > 0) { IndexSegment currEdge = firstF.outerAndInnerBoundaries[currEdgeIdx]; IndexSegment reversedEdge = currEdge.reverse(); { IndexFace currFace = null; int currFaceIdx = -1; int idx = -1; Tuple <IndexFace, int, int> pairedFace = null; if (!segmentOfFaceDict.TryGetValue(reversedEdge, out pairedFace)) { if (!segmentOfFaceDict.TryGetValue(currEdge, out pairedFace)) { currEdgeIdx++; merged = false; continue; } else { currFace = pairedFace.Item1; currFaceIdx = pairedFace.Item2; // Need to reverse the face boundaries. Remove the entries in the Dict first, reverse the face, and add them back for (int cidx = 0; cidx < currFace.outerAndInnerBoundaries.Count; ++cidx) { segmentOfFaceDict.Remove(currFace.outerAndInnerBoundaries[cidx]); } currFace.Reverse(); if (!segmentOfFaceToDict(ref segmentOfFaceDict, ref currFace, currFaceIdx)) { // Something is wrong with this face (should not be here in the normal circumstance), discard it and continue inputFaceList.Remove(currFaceIdx); currEdgeIdx++; merged = false; continue; } if (!segmentOfFaceDict.TryGetValue(reversedEdge, out pairedFace)) { if (!segmentOfFaceDict.TryGetValue(currEdge, out pairedFace)) { // Should not be here. If somehow here, discard the face and continue inputFaceList.Remove(currFaceIdx); currEdgeIdx++; merged = false; continue; } } idx = pairedFace.Item3; } } else { currFace = pairedFace.Item1; currFaceIdx = pairedFace.Item2; idx = pairedFace.Item3; } // Now we need to check other edges of this face whether there is other coincide edge (this is in the case of hole(s)) List <int> fFaceIdxList = new List <int>(); List <int> currFaceIdxList = new List <int>(); for (int ci = 0; ci < currFace.outerAndInnerBoundaries.Count; ci++) { if (ci == idx) { continue; // skip already known coincide edge } int ffIdx = -1; IndexSegment reL = new IndexSegment(currFace.outerAndInnerBoundaries[ci].endPIndex, currFace.outerAndInnerBoundaries[ci].startPindex); ffIdx = firstF.findMatchedIndexSegment(reL); if (ffIdx > 0) { fFaceIdxList.Add(ffIdx); // List of edges to skip when merging currFaceIdxList.Add(ci); // List of edges to skip when merging } } // Now we will remove the paired edges and merge the faces List <IndexSegment> newFaceEdges = new List <IndexSegment>(); for (int ii = 0; ii < currEdgeIdx; ii++) { bool toSkip = false; if (fFaceIdxList.Count > 0) { toSkip = fFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(firstF.outerAndInnerBoundaries[ii]); // add the previous edges from the firstF faces first. This will skip the currEdge } } // Add the next-in-sequence edges from the second face for (int ii = idx + 1; ii < currFace.outerAndInnerBoundaries.Count; ii++) { bool toSkip = false; if (currFaceIdxList.Count > 0) { toSkip = currFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(currFace.outerAndInnerBoundaries[ii]); } } for (int ii = 0; ii < idx; ii++) { bool toSkip = false; if (currFaceIdxList.Count > 0) { toSkip = currFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(currFace.outerAndInnerBoundaries[ii]); } } for (int ii = currEdgeIdx + 1; ii < firstF.outerAndInnerBoundaries.Count; ii++) { bool toSkip = false; if (fFaceIdxList.Count > 0) { toSkip = fFaceIdxList.Contains(ii); } if (!toSkip) { newFaceEdges.Add(firstF.outerAndInnerBoundaries[ii]); } } // Build a new face // Important to note that the list of edges may not be continuous if there is a hole. We need to go through the list here to identify whether there is any such // discontinuity and collect the edges into their respective loops List <List <IndexSegment> > loops = new List <List <IndexSegment> >(); List <IndexSegment> loopEdges = new List <IndexSegment>(); loops.Add(loopEdges); for (int ii = 0; ii < newFaceEdges.Count; ii++) { if (ii == 0) { loopEdges.Add(newFaceEdges[ii]); } else { if (newFaceEdges[ii].startPindex == newFaceEdges[ii - 1].endPIndex) { loopEdges.Add(newFaceEdges[ii]); } else { // Discontinuity detected loopEdges = new List <IndexSegment>(); // start new loop loops.Add(loopEdges); loopEdges.Add(newFaceEdges[ii]); } } } List <List <IndexSegment> > finalLoops = new List <List <IndexSegment> >(); { while (loops.Count > 1) { // There are more than 1 loops, need to consolidate if there are fragments to combine due to their continuity between the fragments int toDelIdx = -1; for (int ii = 1; ii < loops.Count; ii++) { if (loops[0][loops[0].Count - 1].endPIndex == loops[ii][0].startPindex) { // found continuity, merge the loops List <IndexSegment> newLoop = new List <IndexSegment>(loops[0]); newLoop.AddRange(loops[ii]); finalLoops.Add(newLoop); toDelIdx = ii; break; } } if (toDelIdx > 0) { loops.RemoveAt(toDelIdx); // !!!! Important to remove the later member first before removing the first one loops.RemoveAt(0); } else { // No continuity found, copy the first loop to the final loop List <IndexSegment> newLoop = new List <IndexSegment>(loops[0]); finalLoops.Add(newLoop); loops.RemoveAt(0); } } if (loops.Count > 0) { // Add remaining list into the final loops finalLoops.AddRange(loops); } } if (finalLoops.Count > 1) { // Find the largest loop and put it in the first position signifying the outer loop and the rest are the inner loops int largestPerimeterIdx = 0; double largestPerimeter = 0.0; for (int i = 0; i < finalLoops.Count; i++) { double loopPerimeter = 0.0; foreach (IndexSegment line in finalLoops[i]) { loopPerimeter += line.extent; } if (loopPerimeter > largestPerimeter) { largestPerimeter = loopPerimeter; largestPerimeterIdx = i; } } // We need to move the largest loop into the head if it is not if (largestPerimeterIdx > 0) { List <IndexSegment> largestLoop = new List <IndexSegment>(finalLoops[largestPerimeterIdx]); finalLoops.RemoveAt(largestPerimeterIdx); finalLoops.Insert(0, largestLoop); } } // Collect the vertices from the list of Edges into list of list of vertices starting with the outer loop (largest loop) following the finalLoop IList <IList <int> > newFaceVertsLoops = new List <IList <int> >(); foreach (List <IndexSegment> loop in finalLoops) { IList <int> newFaceVerts = new List <int>(); for (int ii = 0; ii < loop.Count; ii++) { if (ii == 0) { newFaceVerts.Add(loop[ii].startPindex); newFaceVerts.Add(loop[ii].endPIndex); } else if (ii == loop.Count - 1) // Last { // Add nothing as the last segment ends at the first vertex } else { newFaceVerts.Add(loop[ii].endPIndex); } } // close the loop with end point from the starting point (it is important to mark the end of loop and if there is any other vertex follow, they start the inner loop) if (newFaceVerts.Count > 0) { if (newFaceVerts.Count >= 3) { newFaceVertsLoops.Add(newFaceVerts); } else { // Something wrong, a face cannot have less than 3 vertices Debug.WriteLine("Something went wrong when merging faces resulting with a loop that has less than 3 vertices"); } } } firstF = new IndexFace(newFaceVertsLoops); currEdgeIdx = 0; reversedEdge = new IndexSegment(firstF.outerAndInnerBoundaries[currEdgeIdx].endPIndex, firstF.outerAndInnerBoundaries[currEdgeIdx].startPindex); mergedFacesIdxList.Add(currFaceIdx); inputFaceList.Remove(currFaceIdx); // Remove the merged face from segmentOfFaceDict IList <IndexSegment> rem = facesColl[currFaceIdx].outerAndInnerBoundaries; for (int cidx = 0; cidx < rem.Count; ++cidx) { segmentOfFaceDict.Remove(rem[cidx]); } merged = true; } if (!merged) { currEdgeIdx++; } if (merged || currEdgeIdx == firstF.outerAndInnerBoundaries.Count) { int lastFaceID = facesColl.Count; // The new index is always the next one in the collection was inserted based on the seq order facesColl.Add(lastFaceID, firstF); //prevFirstFIdx = lastFaceID; // If there is no more face to process, add the merged face into the output list if (inputFaceList.Count == 0) { outputFaceList.Add(lastFaceID); } // Now loop through all the dictionary of the sortedVert and replace all merged face indexes with the new one foreach (KeyValuePair <int, HashSet <int> > v in sortedFVert) { HashSet <int> fIndexes = v.Value; bool replaced = false; foreach (int Idx in mergedFacesIdxList) { replaced |= fIndexes.Remove(Idx); _mergedFaceList.Remove(Idx); // Remove the idx face also from _mergeFaceList as some faces might be left unmerged in the previous step(s) } if (replaced) { fIndexes.Add(lastFaceID); // replace the merged face indexes with the new merged face index } } if (inputFaceList.Count > 0) { firstF = facesColl[inputFaceList[0]]; mergedFacesIdxList.Clear(); mergedFacesIdxList.Add(inputFaceList[0]); // Remove the merged face from segmentOfFaceDict IList <IndexSegment> rem = firstF.outerAndInnerBoundaries; for (int cidx = 0; cidx < rem.Count; ++cidx) { segmentOfFaceDict.Remove(rem[cidx]); } inputFaceList.RemoveAt(0); // remove the first face from the list currEdgeIdx = 0; merged = false; // If there is still more face to process, add the merged face into the list to be processed futher // Add new face to segmentOfFaceDict IndexFace newFace = facesColl[lastFaceID]; if (segmentOfFaceToDict(ref segmentOfFaceDict, ref newFace, lastFaceID)) { inputFaceList.Add(lastFaceID); } } } } return(merged); }