/// <summary> /// Combine coplanar triangles from the faceted body if they share the edge. From this process, polygonal faces (with or without holes) will be created /// </summary> public void SimplifyAndMergeFaces() { int noTriangle = _geom.TriangleCount; int noVertices = _geom.VertexCount; IEqualityComparer <XYZ> normalComparer = new vectorCompare(); Dictionary <XYZ, List <int> > faceSortedByNormal = new Dictionary <XYZ, List <int> >(normalComparer); for (int ef = 0; ef < noTriangle; ++ef) { TriangleInShellComponent f = _geom.GetTriangle(ef); IList <int> vertIndex = new List <int>(); vertIndex.Add(f.VertexIndex0); vertIndex.Add(f.VertexIndex1); vertIndex.Add(f.VertexIndex2); IndexFace intF = new IndexFace(vertIndex); facesColl.Add(ef, intF); // Keep faces in a dictionary and assigns ID List <int> fIDList; if (!faceSortedByNormal.TryGetValue(intF.normal, out fIDList)) { fIDList = new List <int>(); fIDList.Add(ef); faceSortedByNormal.Add(intF.normal, fIDList); } else { if (!fIDList.Contains(ef)) { fIDList.Add(ef); } } } foreach (KeyValuePair <XYZ, List <int> > fListDict in faceSortedByNormal) { List <int> mergedFaceList = null; if (fListDict.Value.Count > 1) { TryMergeFaces(fListDict.Value, out mergedFaceList); if (mergedFaceList != null && mergedFaceList.Count > 0) { // insert only new face indexes as the mergedlist from different vertices can be duplicated foreach (int fIdx in mergedFaceList) { if (!_mergedFaceList.Contains(fIdx)) { _mergedFaceList.Add(fIdx); } } } } else if (!_mergedFaceList.Contains(fListDict.Value[0])) { _mergedFaceList.Add(fListDict.Value[0]); // No pair face, add it into the mergedList } } }
/// <summary> /// Combine coplanar triangles from the faceted body if they share the edge. From this process, polygonal faces (with or without holes) will be created /// </summary> public void SimplifyAndMergeFaces() { int eulerBefore = CalculateEulerCharacteristic(); int noTriangle = (IsMesh) ? _meshGeom.NumTriangles : _geom.TriangleCount; int noVertices = (IsMesh) ? _meshGeom.Vertices.Count : _geom.VertexCount; IEqualityComparer <XYZ> normalComparer = new vectorCompare(); Dictionary <XYZ, List <int> > faceSortedByNormal = new Dictionary <XYZ, List <int> >(normalComparer); for (int ef = 0; ef < noTriangle; ++ef) { IList <int> vertIndex = new List <int>(); if (IsMesh) { MeshTriangle f = _meshGeom.get_Triangle(ef); vertIndex.Add((int)f.get_Index(0)); vertIndex.Add((int)f.get_Index(1)); vertIndex.Add((int)f.get_Index(2)); } else { TriangleInShellComponent f = _geom.GetTriangle(ef); vertIndex.Add(f.VertexIndex0); vertIndex.Add(f.VertexIndex1); vertIndex.Add(f.VertexIndex2); } IndexFace intF = new IndexFace(vertIndex); facesColl.Add(ef, intF); // Keep faces in a dictionary and assigns ID List <int> fIDList; if (!faceSortedByNormal.TryGetValue(intF.normal, out fIDList)) { fIDList = new List <int>(); fIDList.Add(ef); faceSortedByNormal.Add(intF.normal, fIDList); } else { if (!fIDList.Contains(ef)) { fIDList.Add(ef); } } } foreach (KeyValuePair <XYZ, List <int> > fListDict in faceSortedByNormal) { List <int> mergedFaceList = null; if (fListDict.Value.Count > 1) { TryMergeFaces(fListDict.Value, out mergedFaceList); if (mergedFaceList != null && mergedFaceList.Count > 0) { // insert only new face indexes as the mergedlist from different vertices can be duplicated foreach (int fIdx in mergedFaceList) { if (!_mergedFaceList.Contains(fIdx)) { _mergedFaceList.Add(fIdx); } } } } else if (!_mergedFaceList.Contains(fListDict.Value[0])) { _mergedFaceList.Add(fListDict.Value[0]); // No pair face, add it into the mergedList } } int eulerAfter = CalculateEulerCharacteristic(); if (eulerBefore != eulerAfter) { throw new InvalidOperationException(); // Coplanar merge broke the mesh in some way, so we need to fall back to exporting a triangular mesh } }
/// <summary> /// Combine coplanar triangles from the faceted body if they share the edge. From this process, polygonal faces (with or without holes) will be created /// </summary> public void SimplifyAndMergeFaces() { int noTriangle = _geom.TriangleCount; int noVertices = _geom.VertexCount; for (int ef = 0; ef < noTriangle; ++ef) { TriangleInShellComponent f = _geom.GetTriangle(ef); IList <int> vertIndex = new List <int>(); vertIndex.Add(f.VertexIndex0); vertIndex.Add(f.VertexIndex1); vertIndex.Add(f.VertexIndex2); IndexFace intF = new IndexFace(vertIndex); facesColl.Add(ef, intF); // Keep faces in a dictionary and assigns ID SortVertAndFaces(f.VertexIndex0, ef); SortVertAndFaces(f.VertexIndex1, ef); SortVertAndFaces(f.VertexIndex2, ef); } // After the above, we have a sorted polyhedron vertices that contains hashset of faces it belongs to // Loop through the dictionary to merge faces that have the same normal (on the same plane) foreach (KeyValuePair <int, HashSet <int> > dictItem in sortedFVert) { IEqualityComparer <XYZ> normalComparer = new vectorCompare(); Dictionary <XYZ, List <int> > faceSortedByNormal = new Dictionary <XYZ, List <int> >(normalComparer); List <int> fIDList; foreach (int fID in dictItem.Value) { IndexFace f = facesColl[fID]; if (!faceSortedByNormal.TryGetValue(f.normal, out fIDList)) { fIDList = new List <int>(); fIDList.Add(fID); faceSortedByNormal.Add(f.normal, fIDList); } else { if (!fIDList.Contains(fID)) { fIDList.Add(fID); } } } foreach (KeyValuePair <XYZ, List <int> > fListDict in faceSortedByNormal) { List <int> mergedFaceList = null; if (fListDict.Value.Count > 1) { TryMergeFaces(fListDict.Value, out mergedFaceList); if (mergedFaceList != null && mergedFaceList.Count > 0) { // insert only new face indexes as the mergedlist from different vertices can be duplicated foreach (int fIdx in mergedFaceList) { if (!_mergedFaceList.Contains(fIdx)) { _mergedFaceList.Add(fIdx); } } } } else if (!_mergedFaceList.Contains(fListDict.Value[0])) { _mergedFaceList.Add(fListDict.Value[0]); // No pair face, add it into the mergedList } } } }