private double?GetDataValue(int itemNum, int timeIdx) { if (_dfs2File.ItemInfo[itemNum].DataType == DfsSimpleType.Float) { var datastruct = (IDfsItemData <float>)_dfs2File.ReadItemTimeStep(itemNum + 1, timeIdx); // ReSharper disable CompareOfFloatsByEqualityOperator if (datastruct.Data[0] != _deleteValueFloat) // ReSharper restore CompareOfFloatsByEqualityOperator { return(Convert.ToDouble(datastruct.Data[0])); } } else if (_dfs2File.ItemInfo[itemNum].DataType == DfsSimpleType.Double) { var datastruct = (IDfsItemData <double>)_dfs2File.ReadItemTimeStep(itemNum + 1, timeIdx); // ReSharper disable CompareOfFloatsByEqualityOperator if (datastruct.Data[0] != _deleteValueDouble) // ReSharper restore CompareOfFloatsByEqualityOperator { return(datastruct.Data[0]); } } // if values are not real, return null. return(null); }
static void Main(string[] args) { string filename = @"..\..\TestData\OresundHD.dfs2"; // Load the file Dfs2File dfs2File = DfsFileFactory.Dfs2FileOpen(filename); // Print out some info on the spatial axis IDfsAxisEqD2 axis = (IDfsAxisEqD2)dfs2File.SpatialAxis; Console.Out.WriteLine("Size of grid : {0} x {1}", axis.XCount, axis.YCount); Console.Out.WriteLine("Projection : " + dfs2File.FileInfo.Projection.WKTString); // Print out some info of the first item IDfsSimpleDynamicItemInfo dynamicItemInfo = dfs2File.ItemInfo[0]; Console.Out.WriteLine("Item 1 name : " + dynamicItemInfo.Name); Console.Out.WriteLine("Item 1 datatype : " + dynamicItemInfo.DataType); // This iterates through the first 5 time steps and print out the value in the grid // at index (3,4) for the first item for (int i = 0; i < 5; i++) { IDfsItemData2D <float> data2D = (IDfsItemData2D <float>)dfs2File.ReadItemTimeStep(1, i); float value = data2D[3, 4]; Console.Out.WriteLine("Value in time step {0} = {1}", i, value); } }
/// <summary> /// Example of how to get from a geographical coordinate to an (j,k) index /// in the 2D grid. It also shows how to get the closest cell value and how /// to perform bilinear interpolation. /// <para> /// The method assumes that the OresundHD.dfs2 test file is the input file. /// </para> /// </summary> /// <param name="filename">Path and name of OresundHD.dfs2 test file</param> public static void GetjkIndexForGeoCoordinate(string filename) { Dfs2File file = DfsFileFactory.Dfs2FileOpen(filename); // The spatial axis is a EqD2 axis IDfsAxisEqD2 axis = (IDfsAxisEqD2)file.SpatialAxis; // Data for first time step IDfsItemData2D <float> data = (IDfsItemData2D <float>)file.ReadItemTimeStep(1, 0); // Get the projection and create a cartography object IDfsProjection projection = file.FileInfo.Projection; DHI.Projections.Cartography cart = new DHI.Projections.Cartography(projection.WKTString, projection.Longitude, projection.Latitude, projection.Orientation); // Coordinates just south of Amager double lon = 12.59; double lat = 55.54; // Get the (x,y) grid coordinates double x; double y; cart.Geo2Xy(lon, lat, out x, out y); Console.Out.WriteLine("Grid coordinates (x,y) = ({0:0.000},{1:0.000})", x, y); Console.Out.WriteLine("Relative grid coordinates (x,y) = ({0:0.000},{1:0.000})", x / axis.Dx, y / axis.Dy); // Calculate the cell indices of the lon-lat coordinate. // The cell extents from its center and +/- 1/2 dx and dy // in each direction int j = (int)(x / axis.Dx + 0.5); // 30 int k = (int)(y / axis.Dy + 0.5); // 27 Console.Out.WriteLine("Value in cell ({0},{1}) = {2}", j, k, data[j, k]); // If you want to interpolate between the values, calculate // the (j,k) indices of lower left corner and do bilinear interpolation. // This procedure does not take delete values into account!!! j = (int)(x / axis.Dx); // 30 k = (int)(y / axis.Dy); // 26 double xFrac = (x % axis.Dx) / axis.Dx; // fraction of j+1 value double yFrac = (y % axis.Dy) / axis.Dy; // fraction of k+1 value double vk = (1 - xFrac) * data[j, k] + xFrac * data[j + 1, k]; double vkp1 = (1 - xFrac) * data[j, k + 1] + xFrac * data[j + 1, k + 1]; double v = (1 - yFrac) * vk + yFrac * vkp1; Console.Out.WriteLine("Interpolated value = {0}", v); file.Close(); }
/// <summary> /// Introductory example of how to load a dfs2 file. /// <para> /// The method assumes that the OresundHD.dfs2 test file /// is the input file. /// </para> /// </summary> /// <param name="filename">path and name of OresundHD.dfs2 test file</param> public static void ReadingDfs2File(string filename) { // Open the file as a dfs2 file Dfs2File dfs2File = DfsFileFactory.Dfs2FileOpen(filename); // Spatial axis for this file is a 2D equidistant axis IDfsAxisEqD2 axisEqD2 = ((IDfsAxisEqD2)dfs2File.SpatialAxis); double dx = axisEqD2.Dx; // 900 double dy = axisEqD2.Dy; // 900 // Header information is contained in the IDfsFileInfo IDfsFileInfo fileInfo = dfs2File.FileInfo; int steps = fileInfo.TimeAxis.NumberOfTimeSteps; // 13 string projectionString = fileInfo.Projection.WKTString; // "UTM-33" // Information on each of the dynamic items, here the first one IDfsSimpleDynamicItemInfo dynamicItemInfo = dfs2File.ItemInfo[0]; string nameOfFirstDynamicItem = dynamicItemInfo.Name; // "H Water Depth m" DfsSimpleType typeOfFirstDynamicItem = dynamicItemInfo.DataType; // Float // Read data of first item, third time step (items start by 1, timesteps by 0), // assuming data is of type float. IDfsItemData2D <float> data2D = (IDfsItemData2D <float>)dfs2File.ReadItemTimeStep(1, 2); // Get the value at (i,j) = (3,4) of the item and timestep float value = data2D[3, 4]; // 11.3634329 // This iterates through all the timesteps and items in the file // For performance reasons it is important to iterate over time steps // first and items second. for (int i = 0; i < steps; i++) { for (int j = 1; j <= dfs2File.ItemInfo.Count; j++) { data2D = (IDfsItemData2D <float>)dfs2File.ReadItemTimeStep(j, i); value = data2D[3, 4]; } } }
/// <summary> /// Create dfsu and mesh file from dfs2 file. /// <para> /// Note 1: Boundary code is set to land value at /// all boundaries of mesh and dfsu file. /// These must be updated to something "better" /// if to use as input in another simulation. /// </para> /// <para> /// Note 2: P and Q values are not rotated with the /// grid, but should be so, if used in the /// projected coordinate system. It must take /// the 327 degrees rotation into account. /// </para> /// </summary> /// <param name="dfs2Filename">Name of input dfs2 file, e.g. the OresundHD.dfs2</param> /// <param name="meshFilename">Name of output mesh file</param> /// <param name="dfsuFilename">Name of output dfsu file</param> public static void CreateDfsuFromDfs2(string dfs2Filename, string meshFilename, string dfsuFilename) { // Open file Dfs2File dfs2 = DfsFileFactory.Dfs2FileOpen(dfs2Filename); // Read bathymetry from first static item IDfsStaticItem bathymetryItem = dfs2.ReadStaticItemNext(); float[] bathymetry = (float[])bathymetryItem.Data; // Extract spatial axis IDfsAxisEqD2 spatialAxis = (IDfsAxisEqD2)dfs2.SpatialAxis; // Some convenience variables double dx = spatialAxis.Dx; double dy = spatialAxis.Dy; double x0 = spatialAxis.X0; double y0 = spatialAxis.Y0; int xCount = spatialAxis.XCount; int yCount = spatialAxis.YCount; // First custom block (index 0) contains the M21_MISC values, // where the 4th (index 3) is the land value float landValue = (float)dfs2.FileInfo.CustomBlocks[0][3]; //----------------------------------------- // Find out which elements in the dfs2 grid that is not a land value // and include all those elements and their surrounding nodes in mesh // Arrays indicating if element and node in grid is used or not in mesh bool[,] elmts = new bool[xCount, yCount]; int[,] nodes = new int[xCount + 1, yCount + 1]; // Loop over all elements in 2D grid for (int l = 0; l < yCount; l++) { for (int k = 0; k < xCount; k++) { // If bathymetry is not land value, use element. if (bathymetry[k + l * xCount] != landValue) { // element [l,k] is used, and also the 4 nodes around it elmts[k, l] = true; nodes[k, l] = 1; nodes[k + 1, l] = 1; nodes[k, l + 1] = 1; nodes[k + 1, l + 1] = 1; } } } //----------------------------------------- // Create new mest nodes // Cartography object can convert grid (x,y) to projection (east,north) IDfsProjection proj = dfs2.FileInfo.Projection; DHI.Projections.Cartography cart = new DHI.Projections.Cartography(proj.WKTString, proj.Longitude, proj.Latitude, proj.Orientation); // New mesh nodes List <double> X = new List <double>(); List <double> Y = new List <double>(); List <float> Zf = new List <float>(); // float values for dfsu file List <double> Zd = new List <double>(); // double values for mesh file List <int> Code = new List <int>(); // Loop over all nodes int nodesCount = 0; for (int l = 0; l < yCount + 1; l++) { for (int k = 0; k < xCount + 1; k++) { // Check if node is included in mesh if (nodes[k, l] > 0) { // Convert from mesh (x,y) to projection (east,north) double east, north; cart.Xy2Proj((k - 0.5) * dx + x0, (l - 0.5) * dy + y0, out east, out north); // Average Z on node from neighbouring grid cell values, cell value is used // unless they are outside grid or has land values double z = 0; int zCount = 0; if (k > 0 && l > 0 && bathymetry[k - 1 + (l - 1) * xCount] != landValue) { zCount++; z += bathymetry[k - 1 + (l - 1) * xCount]; } if (k < xCount && l > 0 && bathymetry[k + (l - 1) * xCount] != landValue) { zCount++; z += bathymetry[k + (l - 1) * xCount]; } if (k > 0 && l < yCount && bathymetry[k - 1 + (l) * xCount] != landValue) { zCount++; z += bathymetry[k - 1 + (l) * xCount]; } if (k < xCount && l < yCount && bathymetry[k + (l) * xCount] != landValue) { zCount++; z += bathymetry[k + (l) * xCount]; } if (zCount > 0) { z /= zCount; } else { z = landValue; } // Store new node number and add node nodesCount++; nodes[k, l] = nodesCount; // this is the node number to use in the element table X.Add(east); Y.Add(north); Zf.Add((float)z); Zd.Add(z); Code.Add(zCount == 4 ? 0 : 1); // Land boundary if zCount < 4 } } } // New mesh elements List <int[]> elmttable2 = new List <int[]>(); for (int l = 0; l < yCount; l++) { for (int k = 0; k < xCount; k++) { // Check if element is included in mesh if (elmts[k, l]) { // For this element, add the four surrounding nodes, // counter-clockwise order int[] newNodes = new int[4]; newNodes[0] = nodes[k, l]; newNodes[1] = nodes[k + 1, l]; newNodes[2] = nodes[k + 1, l + 1]; newNodes[3] = nodes[k, l + 1]; elmttable2.Add(newNodes); } } } //----------------------------------------- // Create mesh { // Create 2D dfsu file MeshBuilder builder = new MeshBuilder(); // Setup header and geometry builder.SetNodes(X.ToArray(), Y.ToArray(), Zd.ToArray(), Code.ToArray()); builder.SetElements(elmttable2.ToArray()); builder.SetProjection(dfs2.FileInfo.Projection); // Create new file MeshFile mesh = builder.CreateMesh(); mesh.Write(meshFilename); } //----------------------------------------- // Create dfsu file { // dfs2 time axis IDfsEqCalendarAxis timeAxis = (IDfsEqCalendarAxis)dfs2.FileInfo.TimeAxis; // Create 2D dfsu file DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); // Setup header and geometry builder.SetNodes(X.ToArray(), Y.ToArray(), Zf.ToArray(), Code.ToArray()); builder.SetElements(elmttable2.ToArray()); builder.SetProjection(dfs2.FileInfo.Projection); builder.SetTimeInfo(timeAxis.StartDateTime, timeAxis.TimeStepInSeconds()); builder.SetZUnit(eumUnit.eumUmeter); // Add dynamic items, copying from dfs2 file for (int i = 0; i < dfs2.ItemInfo.Count; i++) { IDfsSimpleDynamicItemInfo itemInfo = dfs2.ItemInfo[i]; builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } // Create new file DfsuFile dfsu = builder.CreateFile(dfsuFilename); // Add dfs2 data to dfsu file float[] dfsuData = new float[dfsu.NumberOfElements]; for (int i = 0; i < dfs2.FileInfo.TimeAxis.NumberOfTimeSteps; i++) { for (int j = 0; j < dfs2.ItemInfo.Count; j++) { // Read dfs2 grid data IDfsItemData2D <float> itemData = (IDfsItemData2D <float>)dfs2.ReadItemTimeStep(j + 1, i); // Extract 2D grid data to dfsu data array int lk = 0; for (int l = 0; l < yCount; l++) { for (int k = 0; k < xCount; k++) { if (elmts[k, l]) { dfsuData[lk++] = itemData[k, l]; } } } // write data dfsu.WriteItemTimeStepNext(itemData.Time, dfsuData); } } dfsu.Close(); } dfs2.Close(); }