public Geometry BoundaryPolygonSMeshTest(string meshPath, bool alwaysMultiPolygon = true, string extra = "") { string fileName = Path.GetFileName(meshPath); Stopwatch timer; SMeshData mesh; if (Path.GetExtension(meshPath) == ".dfsu") { DfsuFile file = DfsFileFactory.DfsuFileOpen(meshPath); timer = MeshExtensions.StartTimer(); mesh = new SMeshData(file.Projection.WKTString, file.NodeIds, file.X, file.Y, file.Z.ToDoubleArray(), file.Code, file.ElementIds, file.ElementType, file.ElementTable.ToZeroBased()); file.Close(); } else { MeshFile meshFile = MeshFile.ReadMesh(meshPath); timer = MeshExtensions.StartTimer(); mesh = meshFile.ToSMeshData(); } Console.Out.WriteLine("(#nodes,#elmts)=({0},{1}) ({2})", mesh.NumberOfNodes, mesh.NumberOfElements, mesh.NumberOfNodes + mesh.NumberOfElements); timer.ReportAndRestart("Create "); Geometry boundaryGeom = mesh.BuildBoundaryGeometry(alwaysMultiPolygon); timer.ReportAndRestart("Build "); BoundaryPolygonWriter(fileName, "-sbnd" + extra, boundaryGeom, timer); return(boundaryGeom); }
private static void DfsuBuildGeometry(string targetMeshFilename, DfsuBuilder builder) { DfsFactory factory = new DfsFactory(); if (targetMeshFilename.EndsWith(".mesh", StringComparison.OrdinalIgnoreCase)) { MeshFile target = MeshFile.ReadMesh(targetMeshFilename); // Setup header and geometry, copy from source file builder.SetNodes(target.X, target.Y, target.Z.ToFloatArray(), target.Code); builder.SetElements(target.ElementTable); builder.SetProjection(factory.CreateProjection(target.Projection)); builder.SetZUnit(eumUnit.eumUmeter); } else { DfsuFile target = DfsFileFactory.DfsuFileOpen(targetMeshFilename); // Setup header and geometry, copy from source file builder.SetNodes(target.X, target.Y, target.Z, target.Code); builder.SetElements(target.ElementTable); builder.SetProjection(target.Projection); builder.SetZUnit(eumUnit.eumUmeter); target.Close(); } }
public List <SMeshBoundary> BoundaryListSMeshTest(string meshPath) { string fileName = Path.GetFileName(meshPath); Stopwatch timer; SMeshData mesh; if (Path.GetExtension(meshPath) == ".dfsu") { DfsuFile file = DfsFileFactory.DfsuFileOpen(meshPath); timer = MeshExtensions.StartTimer(); mesh = new SMeshData(file.Projection.WKTString, file.NodeIds, file.X, file.Y, file.Z.ToDoubleArray(), file.Code, file.ElementIds, file.ElementType, file.ElementTable.ToZeroBased()); file.Close(); } else { MeshFile meshFile = MeshFile.ReadMesh(meshPath); timer = MeshExtensions.StartTimer(); mesh = meshFile.ToSMeshData(); } Console.Out.WriteLine("(#nodes,#elmts)=({0},{1}) ({2})", mesh.NumberOfNodes, mesh.NumberOfElements, mesh.NumberOfNodes + mesh.NumberOfElements); timer.ReportAndRestart("Create"); List <SMeshBoundary> boundaries = mesh.BuildBoundaryList(); timer.ReportAndRestart("Time "); string gpFileName = UnitTestHelper.TestDataDir + "test_" + fileName + "-bndscode.txt"; GnuPlotWriteBoundaryList(mesh, gpFileName, boundaries); return(boundaries); }
private IMeshDataInfo GetMesh(string dfsufilepath, bool smesh) { IMeshDataInfo mesh; DfsuFile file = DfsFileFactory.DfsuFileOpen(dfsufilepath); if (smesh) { mesh = new SMeshData(file.Projection.WKTString, file.NodeIds, file.X, file.Y, file.Z.ToDoubleArray(), file.Code, file.ElementIds, file.ElementType, file.ElementTable.ToZeroBased()); return(mesh); } else { mesh = new MeshData(file.Projection.WKTString, file.NodeIds, file.X, file.Y, file.Z.ToDoubleArray(), file.Code, file.ElementIds, file.ElementType, file.ElementTable.ToZeroBased()); return(mesh); } }
/// <summary> /// Interpolate values from <paramref name="sourceFilename"/> to mesh /// defined by <paramref name="targetMeshFilename"/>, and store it in /// <paramref name="targetFilename"/> /// </summary> /// <param name="sourceFilename">Source data for interpolation</param> /// <param name="targetMeshFilename">Target mesh to interpolate to. Can be a mesh or dfsu file</param> /// <param name="targetFilename">File to store interpolated data to</param> public static void Interpolate(string sourceFilename, string targetMeshFilename, string targetFilename) { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); DfsuFile sourceDfsu = DfsFileFactory.DfsuFileOpen(sourceFilename); DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); DfsuBuildGeometry(targetMeshFilename, builder); builder.SetTimeInfo(sourceDfsu.StartDateTime, sourceDfsu.TimeStepInSeconds); // Add dynamic items, copying from source foreach (IDfsSimpleDynamicItemInfo itemInfo in sourceDfsu.ItemInfo) { builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } DfsuFile targetDfsu = builder.CreateFile(targetFilename); watch.Stop(); Console.Out.WriteLine("Create File : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); SMeshData sourceMesh = Create(sourceDfsu); SMeshData targetMesh = Create(targetDfsu); sourceMesh.BuildDerivedData(); watch.Stop(); Console.Out.WriteLine("Build mesh : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); MeshInterpolator2D interpolator = new MeshInterpolator2D(sourceMesh, MeshValueType.Elements) { DeleteValue = sourceDfsu.DeleteValueFloat, DeleteValueFloat = sourceDfsu.DeleteValueFloat, //AllowExtrapolation = true, }; interpolator.SetTarget(targetMesh, MeshValueType.Elements); watch.Stop(); Console.Out.WriteLine("Interpolator: " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); // Temporary, interpolated target-data float[] targetData = new float[targetDfsu.NumberOfElements]; // Add data for all item-timesteps, copying from source, interpolating IDfsItemData <float> sourceData; while (null != (sourceData = sourceDfsu.ReadItemTimeStepNext() as IDfsItemData <float>)) { interpolator.InterpolateElmtToTarget(sourceData.Data, targetData); targetDfsu.WriteItemTimeStepNext(sourceData.Time, targetData); } watch.Stop(); Console.Out.WriteLine("Interpolate : " + watch.Elapsed.TotalSeconds); watch.Reset(); sourceDfsu.Close(); targetDfsu.Close(); }
/// <summary> /// Create a difference file between <paramref name="referenceFilename"/> /// and <paramref name="compareFilename"/>, and store it in /// <paramref name="diffFilename"/>. /// The compare-file data is interpolated to the reference-file mesh, if /// meshes does not match. /// </summary> /// <param name="referenceFilename">Reference data for comparison</param> /// <param name="compareFilename">Comparison data</param> /// <param name="diffFilename">File to store difference data to</param> /// <param name="deleteValueDiff">If set to true, comparing delete value to non-delete value will return the non-delete value</param> public static void DfsuDiff(string referenceFilename, string compareFilename, string diffFilename, bool deleteValueDiff = true) { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); // Open reference file and comparison file DfsuFile refdfsu = DfsFileFactory.DfsuFileOpen(referenceFilename); DfsuFile comdfsu = DfsFileFactory.DfsuFileOpen(compareFilename); float refDeleteValueFloat = refdfsu.DeleteValueFloat; float comDeleteValueFloat = comdfsu.DeleteValueFloat; // Create diff file, matching reference file. DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); // Setup header and geometry, copy from source file builder.SetNodes(refdfsu.X, refdfsu.Y, refdfsu.Z, refdfsu.Code); builder.SetElements(refdfsu.ElementTable); builder.SetProjection(refdfsu.Projection); builder.SetZUnit(refdfsu.ZUnit); builder.SetTimeInfo(refdfsu.StartDateTime, refdfsu.TimeStepInSeconds); // Add dynamic items, copying from source foreach (IDfsSimpleDynamicItemInfo itemInfo in refdfsu.ItemInfo) { builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } DfsuFile diffDfsu = builder.CreateFile(diffFilename); watch.Stop(); Console.Out.WriteLine("Create File : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); // Build up mesh structures for interpolation SMeshData refMesh = SCreate(refdfsu); SMeshData comMesh = SCreate(comdfsu); watch.Stop(); Console.Out.WriteLine("Create mesh : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); bool meshEquals = refMesh.EqualsGeometry(comMesh); if (!meshEquals) { comMesh.BuildDerivedData(); } watch.Stop(); Console.Out.WriteLine("Build Deriv : " + watch.Elapsed.TotalSeconds); watch.Reset(); MeshInterpolator2D interpolator = null; float[] targetData = null; // Do not interpolate if meshes equals if (!meshEquals) { watch.Start(); // Build up interpolatin structures interpolator = new MeshInterpolator2D(comMesh, MeshValueType.Elements) { DeleteValue = comdfsu.DeleteValueFloat, DeleteValueFloat = comdfsu.DeleteValueFloat, //AllowExtrapolation = true, }; interpolator.SetTarget(refMesh, MeshValueType.Elements); // Temporary, interpolated compare-data targetData = new float[diffDfsu.NumberOfElements]; watch.Stop(); Console.Out.WriteLine("Interpolator: " + watch.Elapsed.TotalSeconds); watch.Reset(); } watch.Start(); // Loop over all time steps IDfsItemData <float> refData; IDfsItemData <float> comData; while (null != (refData = refdfsu.ReadItemTimeStepNext() as IDfsItemData <float>) && null != (comData = comdfsu.ReadItemTimeStepNext() as IDfsItemData <float>)) { if (interpolator != null) { interpolator.InterpolateElmtToTarget(comData.Data, targetData); } else { targetData = comData.Data; } for (int i = 0; i < targetData.Length; i++) { // ReSharper disable CompareOfFloatsByEqualityOperator if (refData.Data[i] != refDeleteValueFloat && targetData[i] != comDeleteValueFloat) { targetData[i] = refData.Data[i] - targetData[i]; } else if (refData.Data[i] == refDeleteValueFloat && targetData[i] == comDeleteValueFloat) { targetData[i] = refDeleteValueFloat; } else if (deleteValueDiff) { if (refData.Data[i] != refDeleteValueFloat) { targetData[i] = refData.Data[i]; } else // (targetData[i] != comDeleteValueFloat) { targetData[i] = -targetData[i]; } } else { targetData[i] = refDeleteValueFloat; } // ReSharper restore CompareOfFloatsByEqualityOperator } diffDfsu.WriteItemTimeStepNext(refData.Time, targetData); } watch.Stop(); Console.Out.WriteLine("Interpolate : " + watch.Elapsed.TotalSeconds); watch.Reset(); refdfsu.Close(); comdfsu.Close(); diffDfsu.Close(); }
/// <summary> /// Create a difference file between <paramref name="referenceFilename"/> /// and <paramref name="compareFilename"/>, and store it in /// <paramref name="diffFilename"/>. /// The compare-file data is interpolated to the reference-file mesh, if /// meshes does not match. /// </summary> /// <param name="referenceFilename">Reference data for comparison</param> /// <param name="compareFilename">Comparison data</param> /// <param name="diffFilename">File to store difference data to</param> public static void DfsuDiff(string referenceFilename, string compareFilename, string diffFilename) { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); // Open reference file and comparison file DfsuFile refdfsu = DfsFileFactory.DfsuFileOpen(referenceFilename); DfsuFile comdfsu = DfsFileFactory.DfsuFileOpen(compareFilename); float deleteValueFloat = refdfsu.DeleteValueFloat; // Create diff file, matching reference file. DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); // Setup header and geometry, copy from source file builder.SetNodes(refdfsu.X, refdfsu.Y, refdfsu.Z, refdfsu.Code); builder.SetElements(refdfsu.ElementTable); builder.SetProjection(refdfsu.Projection); builder.SetZUnit(refdfsu.ZUnit); builder.SetTimeInfo(refdfsu.StartDateTime, refdfsu.TimeStepInSeconds); // Add dynamic items, copying from source foreach (DfsuDynamicItemInfo itemInfo in refdfsu.ItemInfo) { builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } DfsuFile diffDfsu = builder.CreateFile(diffFilename); watch.Stop(); Console.Out.WriteLine("Create File : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); // Build up mesh structures for interpolation MeshData sourceMesh = Create(refdfsu); MeshData targetMesh = Create(diffDfsu); sourceMesh.BuildDerivedData(); watch.Stop(); Console.Out.WriteLine("Build mesh : " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); // Build up interpolatin structures MeshInterpolator2D interpolator = new MeshInterpolator2D(sourceMesh) { DeleteValue = refdfsu.DeleteValueFloat, DeleteValueFloat = refdfsu.DeleteValueFloat, }; interpolator.SetTarget(targetMesh); watch.Stop(); Console.Out.WriteLine("Interpolator: " + watch.Elapsed.TotalSeconds); watch.Reset(); watch.Start(); // Temporary, interpolated compare-data float[] targetData = new float[diffDfsu.NumberOfElements]; // Loop over all time steps IDfsItemData <float> refData; IDfsItemData <float> comData; while (null != (refData = refdfsu.ReadItemTimeStepNext() as IDfsItemData <float>) && null != (comData = comdfsu.ReadItemTimeStepNext() as IDfsItemData <float>)) { interpolator.InterpolateToTarget(comData.Data, targetData); for (int i = 0; i < targetData.Length; i++) { if (refData.Data[i] != deleteValueFloat && targetData[i] != deleteValueFloat) { targetData[i] = refData.Data[i] - targetData[i]; } else { targetData[i] = deleteValueFloat; } } diffDfsu.WriteItemTimeStepNext(refData.Time, targetData); } watch.Stop(); Console.Out.WriteLine("Interpolate : " + watch.Elapsed.TotalSeconds); watch.Reset(); refdfsu.Close(); comdfsu.Close(); diffDfsu.Close(); }
/// <summary> /// Example of plotting dfsu file data, water levels with a velocity vector overlay. /// </summary> public static void DfsuTest(bool makeBmp) { DHI.Chart.Map.Chart.Init(); // File to load string pathName = Path.Combine(UnitTestHelper.TestDataRoot, @"OresundHD.dfsu"); DfsuFile dfsu = DfsFileFactory.DfsuFileOpen(pathName); // FemVolGridData is data for the water levels, a value in the center of each element, used for coloring FemVolGridData data = new FemVolGridData(); data.CreateNodesAndElements(dfsu.NumberOfNodes, dfsu.NumberOfElements, dfsu.X, dfsu.Y, dfsu.Z, dfsu.ElementTable); // FemVolVectorData is data for the vector overlay FemVolVectorData uvData = new FemVolVectorData(); uvData.CreateNodesAndElements(dfsu.NumberOfNodes, dfsu.NumberOfElements, dfsu.X, dfsu.Y, dfsu.Z, dfsu.ElementTable); uvData.CreateUV(); uvData.CreateStructuredElements(50, 100); // Create chart DHI.Chart.Map.Chart chart = new DHI.Chart.Map.Chart(1024, 1024); // Add overlay that plots the water levels FemVolGridOverlay overlay = new FemVolGridOverlay(); overlay.SetGridData(data); overlay.EnableNiceValue = true; overlay.CreateAutoScaledRainbowPalette(); overlay.EnableIsoline = true; overlay.ColoringType = MapOverlay.EColoringType.ContinuousColoring; overlay.SetFeathering(true, 0.5f); overlay.EnableIsolineLabel = true; overlay.SetLineColor(MapOverlay.ELineType.Isoline, Color.LawnGreen); //overlay.DrawElementNumbers = true; chart.AddOverlay(overlay); // Add overlay that plots the vectors FemVolVectorOverlay uvOverlay = new FemVolVectorOverlay(); uvOverlay.SetVectorData(uvData); uvOverlay.SetScale(VectorOverlay.EScaleType.UserDefinedScale, 2000.0); uvOverlay.EnableAutomaticScaling = false; uvOverlay.VectorStyle = FemVolVectorOverlay.EVectorStyle.StructuredVectors; uvOverlay.LineColor = Color.BlueViolet; uvOverlay.SetLineThickness(VectorOverlay.EVectorType.NormalVector, 0.4f); chart.AddOverlay(uvOverlay); // Select rectangle to plot, by default the full data area MzRectangle wrect = new MzRectangle(); data.GetDataArea(wrect); // Here you may limit the area to be plotted //wrect.X0 = wrect.X0 + 20000; //wrect.Y0 = wrect.Y0 + 20000; //wrect.X1 = wrect.X0 + 30000; //wrect.Y1 = wrect.Y0 + 30000; chart.SetDataArea(wrect); chart.SetView(wrect); string pngFilepath = null; // Loop over the first 4 time steps for (int i = 0; i < 4; i++) { // Set water level data data.SetElementValues(dfsu.ReadItemTimeStep(1, i).Data as float[]); // Set u-v vector data uvData.SetUV(dfsu.ReadItemTimeStep(2, i).Data as float[], dfsu.ReadItemTimeStep(3, i).Data as float[]); // When running with autoscaled palette, an update is required. overlay.UpdatePalette(); // Draw to bitmap Bitmap bmp = chart.DrawBitmap(); // Save bitmap to disc if (makeBmp) { pngFilepath = Path.Combine(UnitTestHelper.TestDataRoot, string.Format(@"test_oresundHD.1.{0}.png", i)); bmp.Save(pngFilepath); } } chart.Dispose(); if (makeBmp && pngFilepath != null) // Show last bitmap saved { System.Diagnostics.Process.Start(pngFilepath); } }
/// <summary> /// Extract sub-area of dfsu (2D) file to a new dfsu file /// </summary> /// <param name="sourceFilename">Name of source file, i.e. OresundHD.dfsu test file</param> /// <param name="outputFilename">Name of output file</param> /// <param name="x1">Lower left x coordinate of sub area</param> /// <param name="y1">Lower left y coordinate of sub area</param> /// <param name="x2">upper right x coordinate of sub area</param> /// <param name="y2">upper right y coordinate of sub area</param> public static void ExtractSubareaDfsu2D(string sourceFilename, string outputFilename, double x1, double y1, double x2, double y2) { DfsuFile dfsu = DfsFileFactory.DfsuFileOpen(sourceFilename); // Node coordinates double[] X = dfsu.X; double[] Y = dfsu.Y; float[] Z = dfsu.Z; int[] Code = dfsu.Code; // Loop over all elements, and all its nodes: If one node is inside // region, element (and nodes) are to be included in new mesh List <int> elmtsIncluded = new List <int>(); bool[] nodesIncluded = new bool[dfsu.NumberOfNodes]; for (int i = 0; i < dfsu.NumberOfElements; i++) { // Nodes of element int[] nodes = dfsu.ElementTable[i]; // Check if one of the nodes of the element is inside region bool elmtIncluded = false; for (int j = 0; j < nodes.Length; j++) { int node = nodes[j] - 1; if (x1 <= X[node] && X[node] <= x2 && y1 <= Y[node] && Y[node] <= y2) { elmtIncluded = true; } } if (elmtIncluded) { // Add element to list of included elements elmtsIncluded.Add(i); // Mark all nodes of element as included for (int j = 0; j < nodes.Length; j++) { int node = nodes[j] - 1; nodesIncluded[node] = true; } } } // array containing numbers of existing nodes in new mesh (indices) int[] renumber = new int[dfsu.NumberOfNodes]; // new mesh nodes List <double> X2 = new List <double>(); List <double> Y2 = new List <double>(); List <float> Z2 = new List <float>(); List <int> Code2 = new List <int>(); List <int> nodeIds = new List <int>(); int i2 = 0; for (int i = 0; i < dfsu.NumberOfNodes; i++) { if (nodesIncluded[i]) { X2.Add(X[i]); Y2.Add(Y[i]); Z2.Add(Z[i]); Code2.Add(Code[i]); nodeIds.Add(dfsu.NodeIds[i]); // Node with index i will get index i2 in new mesh renumber[i] = i2; i2++; } } // New mesh elements List <int[]> elmttable2 = new List <int[]>(); List <int> elmtIds = new List <int>(); for (int i = 0; i < elmtsIncluded.Count; i++) { // Add new element int elmt = elmtsIncluded[i]; int[] nodes = dfsu.ElementTable[elmt]; // newNodes must be renumbered int[] newNodes = new int[nodes.Length]; for (int j = 0; j < nodes.Length; j++) { // Do the renumbering of nodes from existing mesh to new mesh newNodes[j] = renumber[nodes[j] - 1] + 1; } elmttable2.Add(newNodes); elmtIds.Add(dfsu.ElementIds[i]); } // Create 2D dfsu file DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); // Setup header and geometry builder.SetNodes(X2.ToArray(), Y2.ToArray(), Z2.ToArray(), Code2.ToArray()); //builder.SetNodeIds(nodeIds.ToArray()); builder.SetElements(elmttable2.ToArray()); builder.SetElementIds(elmtIds.ToArray()); // retain original element id's builder.SetProjection(dfsu.Projection); builder.SetTimeInfo(dfsu.StartDateTime, dfsu.TimeStepInSeconds); if (dfsu.ZUnit == eumUnit.eumUUnitUndefined) { builder.SetZUnit(eumUnit.eumUmeter); } else { builder.SetZUnit(dfsu.ZUnit); } // Add dynamic items, copying from source for (int i = 0; i < dfsu.ItemInfo.Count; i++) { IDfsSimpleDynamicItemInfo itemInfo = dfsu.ItemInfo[i]; builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } // Create new file DfsuFile dfsuOut = builder.CreateFile(outputFilename); // Add new data float[] data2 = new float[elmtsIncluded.Count]; for (int i = 0; i < dfsu.NumberOfTimeSteps; i++) { for (int j = 0; j < dfsu.ItemInfo.Count; j++) { // Read data from existing dfsu IDfsItemData <float> itemData = (IDfsItemData <float>)dfsu.ReadItemTimeStep(j + 1, i); // Extract value for elements in new mesh for (int k = 0; k < elmtsIncluded.Count; k++) { data2[k] = itemData.Data[elmtsIncluded[k]]; } // write data dfsuOut.WriteItemTimeStepNext(itemData.Time, data2); } } dfsuOut.Close(); dfsu.Close(); }
/// <summary> /// Extract a single layer from a 3D dfsu file, and write it to a 2D dfsu file. /// <para> /// If a layer value does not exist for a certain 2D element, delete value is written /// to the 2D resut file. This is relevant for Sigma-Z type of files. /// </para> /// </summary> /// <param name="filenameDfsu3">Name of 3D dfsu source file</param> /// <param name="filenameDfsu2">Name of 2D dfsu result file</param> /// <param name="layerNumber">Layer to extract. /// <para> /// Positive values count from bottom up i.e. 1 is bottom layer, 2 is second layer from bottom etc. /// </para> /// <para> /// Negative values count from top down, i.e. -1 is toplayer, -2 is second layer from top etc. /// </para> /// </param> public static void ExtractDfsu2DLayerFrom3D(string filenameDfsu3, string filenameDfsu2, int layerNumber) { IDfsuFile dfsu3File = DfsFileFactory.DfsuFileOpen(filenameDfsu3); // Check that dfsu3 file is a 3D dfsu file. switch (dfsu3File.DfsuFileType) { case DfsuFileType.Dfsu2D: case DfsuFileType.DfsuVerticalColumn: case DfsuFileType.DfsuVerticalProfileSigma: case DfsuFileType.DfsuVerticalProfileSigmaZ: throw new InvalidOperationException("Input file is not a 3D dfsu file"); } // Calculate offset from toplayer element. Offset is between 0 (top layer) and // dfsu3File.NumberOfLayers-1 (bottom layer) int topLayerOffset; if (layerNumber > 0 && layerNumber <= dfsu3File.NumberOfLayers) { topLayerOffset = dfsu3File.NumberOfLayers - layerNumber; } else if (layerNumber < 0 && -layerNumber <= dfsu3File.NumberOfLayers) { topLayerOffset = -layerNumber - 1; } else { throw new ArgumentException("Layer number is out of range"); } double[] xv = dfsu3File.X; double[] yv = dfsu3File.Y; float[] zv = dfsu3File.Z; int[] cv = dfsu3File.Code; // -------------------------------------------------- // Create 2D mesh from 3D mesh // List of new 2D nodes int node2DCount = 0; List <double> xv2 = new List <double>(); List <double> yv2 = new List <double>(); List <float> zv2 = new List <float>(); List <int> cv2 = new List <int>(); // Renumbering array, from 3D node numbers to 2D node numbers // i.e. if a 3D element refers to node number k, the 2D element node number is renumber[k] int[] renumber = new int[dfsu3File.NumberOfNodes]; // Coordinates of last created node double xr2 = -1e-10; double yr2 = -1e-10; // Create 2D nodes, by skipping nodes with equal x,y coordinates for (int i = 0; i < dfsu3File.NumberOfNodes; i++) { // If 3D x,y coordinates are equal to the last created 2D node, // map this node to the last created 2D node, otherwise // create new 2D node and map to that one if (xv[i] != xr2 || yv[i] != yr2) { // Create new node node2DCount++; xr2 = xv[i]; yr2 = yv[i]; float zr2 = zv[i]; int cr2 = cv[i]; xv2.Add(xr2); yv2.Add(yr2); zv2.Add(zr2); cv2.Add(cr2); } // Map this 3D node to the last created 2D node. renumber[i] = node2DCount; } // Find indices of top layer elements IList <int> topLayer = dfsu3File.FindTopLayerElements(); // Create element table for 2D dfsu file int[][] elmttable2 = new int[topLayer.Count][]; for (int i = 0; i < topLayer.Count; i++) { // 3D element nodes int[] elmt3 = dfsu3File.ElementTable[topLayer[i]]; // 2D element nodes, only half as big, so copy over the first half int[] elmt2 = new int[elmt3.Length / 2]; for (int j = 0; j < elmt2.Length; j++) { elmt2[j] = renumber[elmt3[j]]; } elmttable2[i] = elmt2; } // -------------------------------------------------- // Create 2D dfsu file DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D); // Setup header and geometry builder.SetNodes(xv2.ToArray(), yv2.ToArray(), zv2.ToArray(), cv2.ToArray()); builder.SetElements(elmttable2); builder.SetProjection(dfsu3File.Projection); builder.SetTimeInfo(dfsu3File.StartDateTime, dfsu3File.TimeStepInSeconds); if (dfsu3File.ZUnit == eumUnit.eumUUnitUndefined) { builder.SetZUnit(eumUnit.eumUmeter); } else { builder.SetZUnit(dfsu3File.ZUnit); } // Add dynamic items, copying from source, though not the first one, if it // contains the z-variation on the nodes for (int i = 0; i < dfsu3File.ItemInfo.Count; i++) { IDfsSimpleDynamicItemInfo itemInfo = dfsu3File.ItemInfo[i]; if (itemInfo.ElementCount == dfsu3File.NumberOfElements) { builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity); } } // Create file DfsuFile dfsu2File = builder.CreateFile(filenameDfsu2); // -------------------------------------------------- // Process data // Check if the layer number exists for 2D element, i.e. if that element // in 2D has that number of columnes in the 3D (relevant for sigma-z files) // If elementExists[i] is false, write delete value to file bool[] elementExists = new bool[topLayer.Count]; int numLayersInColumn = topLayer[0] + 1; elementExists[0] = (numLayersInColumn - topLayerOffset) > 0; for (int i = 1; i < topLayer.Count; i++) { numLayersInColumn = (topLayer[i] - topLayer[i - 1]); elementExists[i] = (numLayersInColumn - topLayerOffset) > 0; } // For performance, use predefined itemdata objects when reading data from dfsu 3D file IDfsItemData <float>[] dfsu3ItemDatas = new IDfsItemData <float> [dfsu3File.ItemInfo.Count]; for (int j = 0; j < dfsu3File.ItemInfo.Count; j++) { dfsu3ItemDatas[j] = (IDfsItemData <float>)dfsu3File.ItemInfo[j].CreateEmptyItemData(); } // Float data to write to dfsu 2D file float[] data2 = new float[dfsu2File.NumberOfElements]; float deleteValueFloat = dfsu2File.DeleteValueFloat; for (int i = 0; i < dfsu3File.NumberOfTimeSteps; i++) { for (int j = 0; j < dfsu3File.ItemInfo.Count; j++) { // Read data from 3D dfsu IDfsItemData <float> data3Item = dfsu3ItemDatas[j]; bool ok = dfsu3File.ReadItemTimeStep(data3Item, i); // 3D data float[] data3 = data3Item.Data; // Skip any items not having size = NumberOfElments (the z-variation on the nodes) if (data3.Length != dfsu3File.NumberOfElements) { continue; } // Loop over all 2D elements for (int k = 0; k < topLayer.Count; k++) { // Extract layer data from 3D column into 2D element value if (elementExists[k]) { data2[k] = data3[topLayer[k] - topLayerOffset]; } else { data2[k] = deleteValueFloat; } } dfsu2File.WriteItemTimeStepNext(data3Item.Time, data2); } } dfsu3File.Close(); dfsu2File.Close(); }