/// <summary> /// Convert <see cref="MeshUnit"/> into an EUM unit integer /// </summary> public static int ToEum(this MeshUnit meshUnit) { switch (meshUnit) { case MeshUnit.Meter: return(1000); case MeshUnit.Millimeter: return(1002); case MeshUnit.Centimeter: return(1007); case MeshUnit.Kilometer: return(1001); case MeshUnit.Inch: return(1004); case MeshUnit.InchUS: return(1013); case MeshUnit.Feet: return(1003); case MeshUnit.FeetUS: return(1014); case MeshUnit.Yard: return(1006); case MeshUnit.YardUS: return(1015); case MeshUnit.Mile: return(1005); case MeshUnit.MileUS: return(1016); default: throw new ArgumentOutOfRangeException(nameof(meshUnit), meshUnit, null); } }
public MeshDataBase(IList <MeshNode> nodes, IList <MeshElement> elements, string projection, MeshUnit zUnit) { Nodes = nodes; Elements = elements; Projection = projection; ZUnit = zUnit; }
/// <summary> /// Create mesh from arrays. /// <para> /// Note that the <paramref name="connectivity"/> array is using zero-based indices /// (as compared to the <see cref="MeshFile.ElementTable"/>, which is using one-based indices) /// </para> /// </summary> public MeshDataBase(string projection, int[] nodeIds, double[] x, double[] y, double[] z, int[] code, int[] elementIds, int[] elementTypes, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) { Projection = projection; ZUnit = zUnit; Nodes = new List <MeshNode>(nodeIds.Length); Elements = new List <MeshElement>(elementIds.Length); for (int i = 0; i < nodeIds.Length; i++) { var node = new MeshNode() { Index = i, Id = nodeIds[i], X = x[i], Y = y[i], Z = z[i], Code = code[i], }; Nodes.Add(node); } for (int ielmt = 0; ielmt < elementIds.Length; ielmt++) { int[] nodeInElmt = connectivity[ielmt]; int numNodesInElmt = nodeInElmt.Length; var element = new MeshElement() { Index = ielmt, Id = elementIds[ielmt], ElementType = elementTypes[ielmt], Nodes = new List <MeshNode>(numNodesInElmt), }; double xc = 0; double yc = 0; double zc = 0; for (int j = 0; j < numNodesInElmt; j++) { int nodeIndex = nodeInElmt[j]; MeshNode meshNode = Nodes[nodeIndex]; element.Nodes.Add(meshNode); xc += meshNode.X; yc += meshNode.Y; zc += meshNode.Z; } double inumNodesInElmt = 1.0 / numNodesInElmt; element.XCenter = xc * inumNodesInElmt; // / numNodesInElmt; element.YCenter = yc * inumNodesInElmt; // / numNodesInElmt; element.ZCenter = zc * inumNodesInElmt; // / numNodesInElmt; Elements.Add(element); } }
public SMeshDataBase(string projection, int[] nodeIds, double[] x, double[] y, double[] z, int[] code, int[] elementIds, int[] elementType, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) { Projection = projection; ZUnit = zUnit; _nodeIds = nodeIds; _x = x; _y = y; _z = z; _code = code; _elementIds = elementIds; _elementType = elementType; _connectivity = connectivity; }
internal static MeshFile Create(MeshUnit zUnit, string wktString, int[] nodeIds, double[] x, double[] y, double[] z, int[] nodeCode, int[] elmtIds, int[] elmtTypes, int[][] connectivity) { MeshFile res = new MeshFile(); res._zUnit = zUnit; res._wktString = wktString; res._nodeIds = nodeIds; res._x = x; res._y = y; res._z = z; res._code = nodeCode; res._elementIds = elmtIds; res._elementType = elmtTypes; res._connectivity = connectivity; for (int i = 0; i < connectivity.Length; i++) { if (connectivity[i].Length == 4) { res._hasQuads = true; break; } } return(res); }
/// <summary> /// Create mesh from arrays. /// <para> /// Note that the <paramref name="connectivity"/> array is using zero-based indices /// (as compared to the <see cref="MeshFile.ElementTable"/>, which is using one-based indices) /// </para> /// </summary> public MeshData(string projection, int[] nodeIds, double[] x, double[] y, double[] z, int[] code, int[] elementIds, int[] elementTypes, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) : base(projection, nodeIds, x, y, z, code, elementIds, elementTypes, connectivity, zUnit = MeshUnit.Meter) { }
public MeshData(IList <MeshNode> nodes, IList <MeshElement> elements, string projection, MeshUnit zUnit) : base(nodes, elements, projection, zUnit) { }
/// <summary> /// Read .mesh file from reader and load all data. /// <para> /// If an element specifies a node number of zero, that node number is ignored, and /// does not become a part of the mesh data structure. That is the case for e.g. /// mixed triangular/quadrilateral meshes, where all elements specify 4 nodes, /// and triangular elements specifies the last node as zero. /// </para> /// </summary> public void Read(TextReader tr, string filename) { string line; try { char[] separator = new char[] { ' ', '\t' }; // Read header line line = tr.ReadLine(); if (line == null) { throw new IOException("Can not load mesh file. File is empty"); } // Remove any leading spaces if present line = line.Trim(); int noNodes = 0; string proj = null; // First try match the 2012 header line format Match match = _header2012.Match(line); if (match.Success) { // We just ignore the itemType integer, assuming it has the EUM value of eumIBathymetry (100079) int itemType = Int32.Parse(match.Groups[1].Value); int itemUnit = Int32.Parse(match.Groups[2].Value); _zUnit = MeshUnitUtil.FromEum(itemUnit); noNodes = Int32.Parse(match.Groups[3].Value); proj = match.Groups[4].Value; } // If not successfull, try match the 2011 header line format if (proj == null) { match = _header2011.Match(line); if (match.Success) { _zUnit = MeshUnit.Meter; noNodes = Int32.Parse(match.Groups[1].Value); proj = match.Groups[2].Value; } } if (proj == null) { throw new IOException(string.Format("Can not load mesh file (failed reading mesh file header line): {0}", filename)); } _wktString = proj.Trim(); string[] strings; // Allocate memory for nodes _nodeIds = new int[noNodes]; _x = new double[noNodes]; _y = new double[noNodes]; _z = new double[noNodes]; _code = new int[noNodes]; // Read nodes try { for (int i = 0; i < noNodes; i++) { line = tr.ReadLine(); if (line == null) { throw new IOException("Unexpected end of file"); // used as inner exception } line = line.Trim(); strings = line.Split(separator, StringSplitOptions.RemoveEmptyEntries); _nodeIds[i] = int.Parse(strings[0]); _x[i] = double.Parse(strings[1], NumberFormatInfo.InvariantInfo); _y[i] = double.Parse(strings[2], NumberFormatInfo.InvariantInfo); _z[i] = double.Parse(strings[3], NumberFormatInfo.InvariantInfo); _code[i] = int.Parse(strings[4]); } } catch (Exception inner) { throw new Exception(string.Format("Can not load mesh file (failed reading nodes): {0}", filename), inner); } // Reading element header line int noElements; int maxNoNodesPerElement; int elmtCode; line = tr.ReadLine(); if (line == null) { throw new IOException(string.Format("Can not load mesh file (unexpected end of file): {0}", filename)); } line = line.Trim(); strings = line.Split(separator, StringSplitOptions.RemoveEmptyEntries); if (strings.Length != 3) { throw new IOException(string.Format("Can not load mesh file (failed reading element header line): {0}", filename)); } try { noElements = int.Parse(strings[0]); maxNoNodesPerElement = int.Parse(strings[1]); elmtCode = int.Parse(strings[2]); } catch (Exception ex) { throw new Exception(string.Format("Can not load mesh file (failed reading element header line): {0}", filename), ex); } // Element code must be 21 or 25 (21 for triangular meshes, 25 for mixed meshes) if (elmtCode != 21 || elmtCode != 25) { // TODO: Do we care? } // Allocate memory for elements _elementIds = new int[noElements]; _elementType = new int[noElements]; _connectivity = new int[noElements][]; // Temporary (reused) list of nodes in one element List <int> nodesInElement = new List <int>(maxNoNodesPerElement); // Read all elements try { for (int i = 0; i < noElements; i++) { nodesInElement.Clear(); // Read element header line line = tr.ReadLine(); if (line == null) { throw new IOException("Unexpected end of file"); // used as inner exception } line = line.Trim(); strings = line.Split(separator, StringSplitOptions.RemoveEmptyEntries); // Read element id _elementIds[i] = int.Parse(strings[0]); // figure out number of nodes int noNodesInElmt = strings.Length - 1; for (int j = 0; j < noNodesInElmt; j++) { int nodeNumber = int.Parse(strings[j + 1]); // Check that the node number exists if (nodeNumber < 0 || nodeNumber > noNodes) // used as inner exception: { throw new IOException("Node number in element table is negative or larger than number of nodes"); } // It is only a node in the element if the node number is positive if (nodeNumber > 0) { nodesInElement.Add(nodeNumber); } } _connectivity[i] = nodesInElement.ToArray(); // Get element type from number of nodes if (_connectivity[i].Length == 3) { _elementType[i] = 21; } else if (_connectivity[i].Length == 4) { _elementType[i] = 25; _hasQuads = true; } else { _elementType[i] = 0; // TODO: Throw an exception? } } } catch (Exception inner) { throw new Exception(string.Format("Can not load mesh file (failed reading elements): {0}", filename), inner); } } finally { try { tr.Close(); } catch { } } }
/// <summary> /// Create mesh from arrays. /// </summary> public static MeshData CreateMesh(string projection, int[] nodeIds, double[] x, double[] y, double[] z, int[] code, int[] elementIds, int[] elementTypes, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) { MeshData meshData = new MeshData(); meshData.Projection = projection; meshData.ZUnit = zUnit; meshData.Nodes = new List <MeshNode>(nodeIds.Length); meshData.Elements = new List <MeshElement>(elementIds.Length); for (int i = 0; i < nodeIds.Length; i++) { var node = new MeshNode() { Index = i, Id = nodeIds[i], X = x[i], Y = y[i], Z = z[i], Code = code[i], Elements = new List <MeshElement>(), }; meshData.Nodes.Add(node); } for (int ielmt = 0; ielmt < elementIds.Length; ielmt++) { var element = new MeshElement() { Index = ielmt, Id = elementIds[ielmt], ElementType = elementTypes[ielmt], Nodes = new List <MeshNode>(connectivity[ielmt].Length), }; double xc = 0; double yc = 0; double zc = 0; for (int j = 0; j < connectivity[ielmt].Length; j++) { MeshNode meshNode = meshData.Nodes[connectivity[ielmt][j] - 1]; element.Nodes.Add(meshNode); meshNode.Elements.Add(element); xc += meshNode.X; yc += meshNode.Y; zc += meshNode.Z; } element.XCenter = xc / connectivity[ielmt].Length; element.YCenter = yc / connectivity[ielmt].Length; element.ZCenter = zc / connectivity[ielmt].Length; meshData.Elements.Add(element); } return(meshData); }
/// <summary> /// Create mesh from arrays. /// </summary> public static SMeshData CreateMesh(SMeshDataBase database, int[] elementTypes, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) { return(new SMeshData(database.Projection, database.NodeIds, database.X, database.Y, database.Z, database.Code, database.ElementIds, elementTypes, connectivity, zUnit)); }
/// <summary> /// Create mesh from arrays. /// </summary> public static SMeshData CreateMesh( string projection, double[] x, double[] y, double[] z, int[] code, int[][] connectivity, MeshUnit zUnit = MeshUnit.Meter) { return(new SMeshData(projection, null, x, y, z, code, null, null, connectivity, zUnit)); }
/// <summary> /// Set the quantity to use for the mesh Z variable. If not set, /// it will use a Bathymetry item type (eumIBathymetry) /// with meter unit (eumUmeter). /// </summary> public void SetZUnit(MeshUnit zUnit) { _zUnit = zUnit; }
/// <summary> /// Create and return a new <see cref="MeshFile"/> object /// </summary> public MeshFile CreateMesh() { Validate(true); // Creating default eumQuantity in meters _zUnit = MeshUnit.Meter; // Creating default node id's, if empty if (_nodeIds == null) { // Setting node ids 1,2,3,... _nodeIds = new int[_x.Length]; for (int i = 0; i < _x.Length; i++) { _nodeIds[i] = i + 1; } } // Creating default element id's, if empty if (_elementIds == null) { // Setting element ids 1,2,3,... _elementIds = new int[_connectivity.Length]; for (int i = 0; i < _connectivity.Length; i++) { _elementIds[i] = i + 1; } } // Creating additional element information int[] elementType = new int[_connectivity.Length]; int[] nodesPerElmt = new int[_connectivity.Length]; int nodeElmtCount = 0; // total number of nodes listed in the connectivity table for (int i = 0; i < elementType.Length; i++) { int elmtTypeNumber; int[] elmt = _connectivity[i]; switch (elmt.Length) { case 3: elmtTypeNumber = 21; break; case 4: elmtTypeNumber = 25; break; case 6: elmtTypeNumber = 32; break; case 8: elmtTypeNumber = 33; break; default: // this should have been caught in the validate phase, but just in case: throw new Exception("Element with invalid number of nodes encountered"); } elementType[i] = elmtTypeNumber; nodesPerElmt[i] = elmt.Length; nodeElmtCount += elmt.Length; } int[] connectivityArray = new int[nodeElmtCount]; int k = 0; for (int i = 0; i < elementType.Length; i++) { int[] elmt = _connectivity[i]; for (int j = 0; j < elmt.Length; j++) { connectivityArray[k++] = elmt[j]; } } MeshFile res = MeshFile.Create(_zUnit, _projection, _nodeIds, _x, _y, _z, _code, _elementIds, elementType, _connectivity); return(res); }