/// <summary> /// Create DFS2 file with iterpolated values from the 3x3 quadrangles, /// with various delete values applied in each time step. /// </summary> public void DeleteValueVisualDfs2DoTest() { string meshFileName = UnitTestHelper.TestDataDir + "small.mesh"; MeshFile file = MeshFile.ReadMesh(meshFileName); _meshVisual = file.ToSMeshData(); DfsFactory factory = new DfsFactory(); Dfs2Builder dfs2Builder = new Dfs2Builder(); dfs2Builder.SetDataType(0); dfs2Builder.SetTemporalAxis(factory.CreateTemporalEqTimeAxis(eumUnit.eumUsec, 0, 1)); dfs2Builder.SetSpatialAxis(factory.CreateAxisEqD2(eumUnit.eumUmeter, 80, 0, 0.01, 80, 0, 0.01)); dfs2Builder.SetGeographicalProjection(factory.CreateProjectionUndefined()); dfs2Builder.AddDynamicItem("DeleteValueSmooth", eumQuantity.UnDefined, DfsSimpleType.Float, DataValueType.Instantaneous); dfs2Builder.AddDynamicItem("DeleteValueBox", eumQuantity.UnDefined, DfsSimpleType.Float, DataValueType.Instantaneous); dfs2Builder.DeleteValueFloat = (float)d; dfs2Builder.CreateFile(UnitTestHelper.TestDataDir + "test_InterpTri.dfs2"); Dfs2File dfs2File = dfs2Builder.GetFile(); // Calculate interpolation weights MeshWeights[][] weights = new MeshWeights[80][]; for (int j = 0; j < 80; j++) { double y = 0.2 + 0.01 * j + 0.005; weights[j] = new MeshWeights[80]; for (int i = 0; i < 80; i++) { double x = 0.4 + 0.01 * i + 0.005; weights[j][i].QuadWeights = InterpQuadrangle.UndefinedWeights(); weights[j][i].TriWeights = InterpTriangle.UndefinedWeights(); for (int ielmt = 0; ielmt < _meshVisual.NumberOfElements; ielmt++) { var elmtNodes = _meshVisual.ElementTable[ielmt]; if (elmtNodes.Length == 4) { double x0 = _meshVisual.X[elmtNodes[0]]; double x1 = _meshVisual.X[elmtNodes[1]]; double x2 = _meshVisual.X[elmtNodes[2]]; double x3 = _meshVisual.X[elmtNodes[3]]; double y0 = _meshVisual.Y[elmtNodes[0]]; double y1 = _meshVisual.Y[elmtNodes[1]]; double y2 = _meshVisual.Y[elmtNodes[2]]; double y3 = _meshVisual.Y[elmtNodes[3]]; if (MeshExtensions.IsPointInsideQuadrangle(x, y, x0, y0, x1, y1, x2, y2, x3, y3)) { weights[j][i].ElmtIndex = ielmt; weights[j][i].QuadWeights = InterpQuadrangle.InterpolationWeights(x, y, x0, y0, x1, y1, x2, y2, x3, y3); } } else { double x0 = _meshVisual.X[elmtNodes[0]]; double x1 = _meshVisual.X[elmtNodes[1]]; double x2 = _meshVisual.X[elmtNodes[2]]; double y0 = _meshVisual.Y[elmtNodes[0]]; double y1 = _meshVisual.Y[elmtNodes[1]]; double y2 = _meshVisual.Y[elmtNodes[2]]; if (MeshExtensions.IsPointInsideTriangle(x, y, x0, y0, x1, y1, x2, y2)) { weights[j][i].ElmtIndex = ielmt; weights[j][i].TriWeights = InterpTriangle.InterpolationWeights(x, y, x0, y0, x1, y1, x2, y2); } } } } } // Original center quadrangle values double z4 = _meshVisual.Z[3]; double z6 = _meshVisual.Z[5]; double z8 = _meshVisual.Z[7]; float[] data = new float[80 * 80]; VisualDfs2Data(weights, data, z4, z6, z8, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, z6, z8, false); dfs2File.WriteItemTimeStepNext(0, data); // One delete value VisualDfs2Data(weights, data, d, z6, z8, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, d, z6, z8, false); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, d, z8, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, d, z8, false); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, z6, d, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, z6, d, false); dfs2File.WriteItemTimeStepNext(0, data); // Two adjacent delete values VisualDfs2Data(weights, data, d, d, z8, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, d, d, z8, false); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, d, d, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, z4, d, d, false); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, d, z6, d, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, d, z6, d, false); dfs2File.WriteItemTimeStepNext(0, data); // All delete values VisualDfs2Data(weights, data, d, d, d, true); dfs2File.WriteItemTimeStepNext(0, data); VisualDfs2Data(weights, data, d, d, d, false); dfs2File.WriteItemTimeStepNext(0, data); dfs2File.Close(); }
/// <summary> /// Calculate interpolation weights for the point (x,y) inside the element"/> /// <para> /// The weights returned can be used to calculate a value v at the point (x,y) using the /// <code>GetValue</code> methods /// </para> /// <para> /// if the point (x,y) is not inside the element, results are undefined. /// </para> /// </summary> /// <returns>Interpolation weights</returns> public static Weights InterpolationWeights(double x, double y, int element, SMeshData smesh) { Weights weights = new Weights(); // Setting "out-of-bounds" index weights.Element1Index = -1; bool found = false; weights.Element1Index = element; // Check which face the point belongs to, and which "side" of the face bool isQuad = smesh.IsQuadrilateral(element); int numFaces = isQuad ? 4 : 3; for (int j = 0; j < numFaces; j++) { SMeshFace elementFace = smesh.Faces[smesh.ElementsFaces[element][j]]; // From the element (x,y), looking towards the face, // figure out wich node is right and which is left. int rightNode, leftNode; if (elementFace.LeftElement == element) { rightNode = elementFace.FromNode; leftNode = elementFace.ToNode; } else { rightNode = elementFace.ToNode; leftNode = elementFace.FromNode; } double elementXCenter = smesh.ElementXCenter[element]; double elementYCenter = smesh.ElementYCenter[element]; double rightNodeX = smesh.X[rightNode]; double rightNodeY = smesh.Y[rightNode]; double leftNodeX = smesh.X[leftNode]; double leftNodeY = smesh.Y[leftNode]; // Find also the element on the other side of the face double otherElementX, otherElementY; int otherElement = elementFace.OtherElement(element); if (otherElement >= 0) { otherElementX = smesh.ElementXCenter[otherElement]; otherElementY = smesh.ElementYCenter[otherElement]; weights.Element2Index = otherElement; } else { // No other element - boundary face, use center of face. otherElementX = 0.5 * (rightNodeX + leftNodeX); otherElementY = 0.5 * (rightNodeY + leftNodeY); // Use "itself" as element-2 weights.Element2Index = element; } // Check if point is on the right side of the line between element and other-element if (MeshExtensions.IsPointInsideLines(x, y, elementXCenter, elementYCenter, rightNodeX, rightNodeY, otherElementX, otherElementY)) { (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights( x, y, elementXCenter, elementYCenter, rightNodeX, rightNodeY, otherElementX, otherElementY); weights.NodeIndex = rightNode; weights.Element1Weight = w1; weights.NodeWeight = w2; weights.Element2Weight = w3; found = true; break; } // Check if point is on the left side of the line between element and other-element if (MeshExtensions.IsPointInsideLines(x, y, elementXCenter, elementYCenter, otherElementX, otherElementY, leftNodeX, leftNodeY)) { (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights( x, y, elementXCenter, elementYCenter, otherElementX, otherElementY, leftNodeX, leftNodeY); weights.NodeIndex = leftNode; weights.Element1Weight = w1; weights.Element2Weight = w2; weights.NodeWeight = w3; found = true; break; } } if (!found) // Should never happen, but just in case { weights.Element1Weight = 1; weights.Element2Weight = 0; weights.NodeWeight = 0; weights.Element2Index = element; weights.NodeIndex = smesh.ElementTable[element][0]; } return(weights); }
public static bool SplitMeshData(SMeshData meshData, List <SMeshData> subMeshDataList) { const int VLIMIT = 60000; int icount = meshData.indices.Length; int vcount = meshData.vertices.Length; subMeshDataList.Clear(); int minv = 0; int maxv = 0; int iOffset = 0; for (int i = 0; i < icount; i += 3) { int idx0 = meshData.indices[i]; int idx1 = meshData.indices[i + 1]; int idx2 = meshData.indices[i + 2]; int minIndex = minv; int maxIndex = maxv; maxIndex = System.Math.Max(maxIndex, idx0); maxIndex = System.Math.Max(maxIndex, idx1); maxIndex = System.Math.Max(maxIndex, idx2); if ((maxIndex - minIndex) >= VLIMIT) //split { SMeshData subMeshData = new SMeshData(); int cvcount = maxv - minv + 1; int cicount = i - iOffset; subMeshData.vertices = new Vector3[cvcount]; subMeshData.indices = new int[cicount]; System.Array.Copy(meshData.vertices, minv, subMeshData.vertices, 0, cvcount); System.Array.Copy(meshData.indices, iOffset, subMeshData.indices, 0, cicount); for (int t = 0; t < cicount; ++t) { subMeshData.indices[t] -= minv; } subMeshDataList.Add(subMeshData); //recalculate iOffset = i; minv = minv + cvcount; maxv = minv; continue; } maxv = maxIndex; if (i + 3 >= icount && maxv - minv > 0) //last { SMeshData subMeshData = new SMeshData(); int cvcount = maxv - minv + 1; int cicount = i + 3 - iOffset; subMeshData.vertices = new Vector3[cvcount]; subMeshData.indices = new int[cicount]; System.Array.Copy(meshData.vertices, minv, subMeshData.vertices, 0, cvcount); System.Array.Copy(meshData.indices, iOffset, subMeshData.indices, 0, cicount); for (int t = 0; t < cicount; ++t) { subMeshData.indices[t] -= minv; } subMeshDataList.Add(subMeshData); iOffset = i; } } return(true); }