public SubMeshes Process() { // Create a stack with an initial capacity matching Sqrt(#elmts), which will approximately match for // a square mesh with quads. _stack = new Stack <int>((int)System.Math.Sqrt(_meshData.NumberOfElements)); SubMeshes subMeshes = new SubMeshes(); subMeshes.SubMeshInfos = new List <SubMeshInfo>(); int subMeshId = 0; ElmtSubMesh = new int[_meshData.NumberOfElements]; for (int i = 0; i < _meshData.NumberOfElements; i++) { if (ElmtSubMesh[i] == 0) { subMeshId++; int subMeshElmtCount = BFSVisit(i, subMeshId); subMeshes.SubMeshInfos.Add(new SubMeshInfo() { SubMeshId = subMeshId, NumberOfElments = subMeshElmtCount }); } } subMeshes.ElmtSubMesh = ElmtSubMesh; return(subMeshes); }
/// <summary> /// Find connected sub meshes. /// </summary> public static SubMeshes FindConnectedSubMeshes(this CMeshData meshData) { // We need faces information for each element. meshData.BuildFaces(true); BFSSubMesher subMesher = new BFSSubMesher(meshData); SubMeshes subMeshes = subMesher.Process(); // Sort such that the sub mesh with most element is first in the list subMeshes.SubMeshInfos.Sort((smi1, smi2) => - smi1.NumberOfElments.CompareTo(smi2.NumberOfElments)); return(subMeshes); }
/// <summary> /// Build boundary polygon. Returns either a <see cref="Polygon"/> or <see cref="MultiPolygon"/> /// depending on whether the mesh is fully connected or consist of independent parts. /// <para> /// To always return a <see cref="MultiPolygon"/>, set the <paramref name="alwaysMultiPolygon"/> to true. /// </para> /// </summary> private static Geometry BuildBoundaryGeometry(CMeshData mesh, List <CMeshFace> boundaryFaces, bool alwaysMultiPolygon) { // There will be one polygon for each connected sub mesh, in case there is more than one. //System.Diagnostics.Stopwatch timer = MeshExtensions.StartTimer(); // Find all connected sub meshes. SubMeshes subMeshes = mesh.FindConnectedSubMeshes(); //timer.ReportAndRestart("FindConnectedSubMeshes " + subMeshes.NumberOfSubMeshes); BoundarySegmentsBuilder bsb = new BoundarySegmentsBuilder(mesh); if (subMeshes.NumberOfSubMeshes == 1) { Polygon boundaryPoly = BuildSubMeshBoundaryGeometry(mesh, bsb, boundaryFaces); if (!alwaysMultiPolygon) { return(boundaryPoly); } MultiPolygon multiPolygon = new MultiPolygon(new Polygon[] { boundaryPoly }); return(multiPolygon); } else // More than one sub-mesh - make a Polygon for each sub mesh { // Find boundary faces for each sub mesh List <List <CMeshFace> > subMeshesBoundaryFaces = new List <List <CMeshFace> >(subMeshes.NumberOfSubMeshes); for (int i = 0; i < subMeshes.NumberOfSubMeshes; i++) { subMeshesBoundaryFaces.Add(new List <CMeshFace>()); } for (int i = 0; i < boundaryFaces.Count; i++) { CMeshFace bcFace = boundaryFaces[i]; int subMeshId = subMeshes.ElmtSubMesh[bcFace.LeftElement.Index]; // subMeshId's starts from 1 subMeshesBoundaryFaces[subMeshId - 1].Add(bcFace); } // Make boundary polygon for each sub mesh - ordered as in SubMeshInfos to get largest parts first List <Polygon> polygons = new List <Polygon>(subMeshes.NumberOfSubMeshes); foreach (SubMeshInfo subMeshInfo in subMeshes.SubMeshInfos) { List <CMeshFace> subMeshBoundaryFaces = subMeshesBoundaryFaces[subMeshInfo.SubMeshId - 1]; Polygon subMeshBoundaryPoly = BuildSubMeshBoundaryGeometry(mesh, bsb, subMeshBoundaryFaces); polygons.Add(subMeshBoundaryPoly); } MultiPolygon multiPoly = new MultiPolygon(polygons.ToArray()); return(multiPoly); } }