Esempio n. 1
0
        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);
        }
Esempio n. 2
0
 public ColladaMeshExporter(IRepository repository, MeshFile meshFile, ExportDDSToPngFileDelegate exportDDSToPngFile = null)
 {
     Repository         = repository;
     MeshFile           = meshFile;
     ExportDDSToPngFile = exportDDSToPngFile ?? DefaultExportDDSToPngFileDelegate;
     TNS = TemplateNameSpace;
 }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
 private static void WriteMesh(MeshDef def, string path)
 {
     using (Stream s = File.OpenWrite(path))
     {
         MeshFile.Save(s, def);
     }
 }
Esempio n. 5
0
        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();
            }
        }
Esempio n. 6
0
        public void InterpolateNodeTest()
        {
            string triMesh  = UnitTestHelper.TestDataDir + "odense_rough.mesh";
            string quadMesh = UnitTestHelper.TestDataDir + "odense_rough_quads.mesh";
            // Source mesh
            MeshFile  sourcemeshFile = MeshFile.ReadMesh(triMesh);
            SMeshData sourcemesh     = sourcemeshFile.ToSMeshData();

            sourcemesh.BuildDerivedData();
            // Target mesh
            MeshFile  targetMeshFile = MeshFile.ReadMesh(quadMesh);
            SMeshData targetmesh     = targetMeshFile.ToSMeshData();

            targetmesh.BuildDerivedData();

            MeshInterpolator2D interpolator = new MeshInterpolator2D(sourcemesh, MeshValueType.Nodes);

            interpolator.SetTarget(targetmesh, MeshValueType.Nodes);

            double[] target = new double[targetmesh.NumberOfNodes];
            interpolator.InterpolateNodeToTarget(sourcemesh.Z, target);

            Assert.False(target.Any(vv => vv == interpolator.DeleteValue));

            targetMeshFile.Z = target;
            targetMeshFile.Write(UnitTestHelper.TestDataDir + "test_odense_rough_quads-fromTri.mesh");
        }
Esempio n. 7
0
        public void SMeshDataOdenseQuadsTest()
        {
            string    quadMesh = UnitTestHelper.TestDataDir + "odense_rough_quads.mesh";
            MeshFile  meshFile = MeshFile.ReadMesh(quadMesh);
            SMeshData mesh     = meshFile.ToSMeshData();

            Assert.AreEqual(535, mesh.NumberOfNodes);
            Assert.AreEqual(5, mesh.NodeIds[4]);
            Assert.AreEqual(212827.81746849261, mesh.X[4]);
            Assert.AreEqual(6156804.9152286667, mesh.Y[4]);
            Assert.AreEqual(-0.42102556956959569, mesh.Z[4]);
            Assert.AreEqual(1, mesh.Code[5]);

            Assert.AreEqual(724, mesh.NumberOfElements);
            Assert.AreEqual(5, mesh.ElementIds[4]);
            Assert.AreEqual(3, mesh.ElementTable[4].Length);
            Assert.AreEqual(62, mesh.ElementTable[4][0]); // Remember: Index here is zero based, while mesh file is one-based
            Assert.AreEqual(367, mesh.ElementTable[4][1]);
            Assert.AreEqual(358, mesh.ElementTable[4][2]);

            mesh.BuildNodeElements();
            Assert.AreEqual(4, mesh.NodesElmts[4].Count);
            Assert.AreEqual(33, mesh.NodesElmts[4][0] + 1);
            Assert.AreEqual(36, mesh.NodesElmts[4][1] + 1);
            Assert.AreEqual(43, mesh.NodesElmts[4][2] + 1);
            Assert.AreEqual(58, mesh.NodesElmts[4][3] + 1);

            //mesh.BuildFaces(true, true, false);
            //int reverts = FaceRevert(mesh, mesh.Faces);
            //Console.Out.WriteLine("reverts: " + reverts);
            //mesh.Faces.Sort(FaceSortComparer);
            //List<MeshFace> facesOld = mesh.Faces;

            //mesh.BuildFaces(true, true, true);
            //reverts = FaceRevert(mesh, mesh.Faces);
            //Console.Out.WriteLine("reverts: " + reverts);
            //mesh.Faces.Sort(FaceSortComparer);
            //List<MeshFace> facesNew = mesh.Faces;
            //for (int i = 0; i < facesOld.Count; i++)
            //{
            //  bool ok = FaceEquals(facesOld[i], facesNew[i]);
            //  Assert.IsTrue(ok, "Face " + i);
            //}

            //Assert.AreEqual(1259, mesh.Faces.Count);
            //Assert.AreEqual(1, mesh.Faces[0].FromNode.Id);
            //Assert.AreEqual(42, mesh.Faces[0].ToNode.Id);
            //Assert.AreEqual(1, mesh.Faces[1].FromNode.Id);
            //Assert.AreEqual(251, mesh.Faces[1].ToNode.Id);
            //Assert.AreEqual(1, mesh.Faces[2].FromNode.Id);
            //Assert.AreEqual(309, mesh.Faces[2].ToNode.Id);
            //int ind = mesh.Faces.FindIndex(mf => mf.FromNode.Id == 68);
            //Assert.AreEqual(202, ind);
            //Assert.AreEqual(68, mesh.Faces[ind].FromNode.Id);
            //Assert.AreEqual(43, mesh.Faces[ind].ToNode.Id);
            //Assert.AreEqual(1, mesh.Faces[ind].Code);
            //Assert.AreEqual(366, mesh.Faces[ind].LeftElement.Id);
            //Assert.AreEqual(null, mesh.Faces[ind].RightElement);
        }
        public void NodeInterpolationTest(string meshFileName, CircularValueTypes cvt = CircularValueTypes.Normal)
        {
            // Source mesh
            MeshFile meshFile = MeshFile.ReadMesh(meshFileName);
            MeshData mesh     = meshFile.ToMeshData();

            // Allow for extrapolation on boundary nodes (disable clipping)
            MeshNodeInterpolation interpolation = new MeshNodeInterpolation(mesh)
            {
                AllowExtrapolation = true,
            };

            interpolation.Setup();
            Interpolator nodeInterpolator = interpolation.NodeInterpolator;

            nodeInterpolator.CircularType = cvt;

            // Find reference x and y value as the smallest x and y value
            double xMin = mesh.Nodes.Select(mn => mn.X).Min();
            double xMax = mesh.Nodes.Select(mn => mn.X).Max();
            double yMin = mesh.Nodes.Select(mn => mn.Y).Min();
            double yMax = mesh.Nodes.Select(mn => mn.Y).Max();

            // Function over the (x,y) plane.
            Func <double, double, double> function = ValueFunction(cvt, xMin, yMin, xMax, yMax);

            // Calculate element center values
            double[] elmtVals = new double[mesh.Elements.Count];
            for (int i = 0; i < mesh.Elements.Count; i++)
            {
                MeshElement elmt = mesh.Elements[i];
                elmtVals[i] = function(elmt.XCenter, elmt.YCenter);
            }

            // Write out bounds, to check we got things right
            Console.Out.WriteLine("{0,10} (min,max) = ({1},{2})", cvt, elmtVals.Min(), elmtVals.Max());

            // Interpolate to nodes
            double[] nodeValues = new double[mesh.Nodes.Count];
            nodeInterpolator.Interpolate(elmtVals, nodeValues);

            // Check node values
            for (int i = 0; i < mesh.Nodes.Count; i++)
            {
                MeshNode node        = mesh.Nodes[i];
                double   exactValue  = function(node.X, node.Y);
                double   interpValue = nodeValues[i];
                double   diff        = exactValue - interpValue;
                // It can only extrapolate when there is at least three elements per node.
                // When there is two or less elements, the inverse distance weighting takes over
                // and the results are not correct, so we skip the check here.
                if (node.Elements.Count > 2 && diff > 1e-6)
                {
                    string msg = string.Format("{0,2} {6}: {1}-{2}={3} ({4},{5})", i, exactValue, interpValue, diff, node.X, node.Y, node.Elements.Count);
                    Console.Out.WriteLine(msg);
                    Assert.Fail(msg);
                }
            }
        }
        protected override void ProcessValidation()
        {
            if (string.IsNullOrEmpty(this.MeshFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.MeshFile, ValidationValue.IsError,
                                                        string.Format(CultureInfo.CurrentCulture, AMLResources.Properties.Resources.IsRequired, AMLResources.Properties.Resources.MeshFile));
            }
            else if (!MeshFile.EndsWith(DataStrings.DXSExtension, StringComparison.OrdinalIgnoreCase))
            {
                base.ValidationCollection.AddValidation(DataStrings.MeshFile, ValidationValue.IsWarnState,
                                                        AMLResources.Properties.Resources.MeshFileExtensionValidation);
            }
            if (string.IsNullOrEmpty(this.DiffuseFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.DiffuseFile, ValidationValue.IsError,
                                                        string.Format(CultureInfo.CurrentCulture, AMLResources.Properties.Resources.IsRequired, AMLResources.Properties.Resources.DiffuseFile));
            }
            else if (!FileHelper.IsImageFile(DiffuseFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.DiffuseFile, ValidationValue.IsError,
                                                        AMLResources.Properties.Resources.NotAnImageFile);
            }



            if (string.IsNullOrEmpty(this.GlowFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.GlowFile, ValidationValue.IsError,
                                                        string.Format(CultureInfo.CurrentCulture, AMLResources.Properties.Resources.IsRequired, AMLResources.Properties.Resources.GlowFile));
            }
            else if (!FileHelper.IsImageFile(GlowFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.GlowFile, ValidationValue.IsError,
                                                        AMLResources.Properties.Resources.NotAnImageFile);
            }


            if (string.IsNullOrEmpty(this.SpecularFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.SpecularFile, ValidationValue.IsError,
                                                        string.Format(CultureInfo.CurrentCulture, AMLResources.Properties.Resources.IsRequired, AMLResources.Properties.Resources.SpecularFile));
            }
            else if (!FileHelper.IsImageFile(SpecularFile))
            {
                base.ValidationCollection.AddValidation(DataStrings.SpecularFile, ValidationValue.IsError,
                                                        AMLResources.Properties.Resources.NotAnImageFile);
            }

            if (Scale <= 0)
            {
                base.ValidationCollection.AddValidation(DataStrings.Scale, ValidationValue.IsError,
                                                        AMLResources.Properties.Resources.ScaleValidation);
            }
            if (PushRadius <= 0)
            {
                base.ValidationCollection.AddValidation(DataStrings.PushRadius, ValidationValue.IsWarnState,
                                                        AMLResources.Properties.Resources.PushRadiusValidation);
            }
        }
Esempio n. 10
0
 /// <summary>
 /// Create <see cref="IMeshDataInfo"/>, depending on <paramref name="smesh"/> flag.
 /// </summary>
 public static IMeshDataInfo ToMeshData(this MeshFile file, bool smesh)
 {
     if (smesh)
     {
         return(file.ToSMeshData());
     }
     return(file.ToMeshData());
 }
        public override string ValidateInternally()
        {
            var sb = new StringBuilder();

            if (MeshFile.FindFileExtension(_filePath) is null)
            {
                sb.AppendLine("The used file extension is invalid.");
            }

            return(sb.ToString());
        }
Esempio n. 12
0
        private Model.Ndfbin.NdfBinary ReadTextureBindings(Stream s, MeshFile file)
        {
            var buffer = new byte[file.SubHeader.MeshMaterial.Size];

            s.Seek(file.SubHeader.MeshMaterial.Offset, SeekOrigin.Begin);
            s.Read(buffer, 0, buffer.Length);

            var ndfReader = new NdfbinReader();

            return(ndfReader.Read(buffer));
        }
Esempio n. 13
0
        public MeshFile Read(Stream s)
        {
            var file = new MeshFile();

            file.Header    = ReadHeader(s);
            file.SubHeader = ReadSubHeader(s);

            file.MultiMaterialMeshFiles = ReadMeshDictionary(s, file);

            file.TextureBindings = ReadTextureBindings(s, file);

            return(file);
        }
Esempio n. 14
0
        public void MeshDataOdenseQuadsTest()
        {
            string   quadMesh = UnitTestHelper.TestDataDir + "odense_rough_quads.mesh";
            MeshFile meshFile = MeshFile.ReadMesh(quadMesh);
            MeshData mesh     = meshFile.ToMeshData();

            Assert.AreEqual(535, mesh.Nodes.Count);
            Assert.AreEqual(4, mesh.Nodes[4].Index);
            Assert.AreEqual(5, mesh.Nodes[4].Id);
            Assert.AreEqual(212827.81746849261, mesh.Nodes[4].X);
            Assert.AreEqual(6156804.9152286667, mesh.Nodes[4].Y);
            Assert.AreEqual(-0.42102556956959569, mesh.Nodes[4].Z);
            Assert.AreEqual(1, mesh.Nodes[5].Code);

            Assert.AreEqual(724, mesh.Elements.Count);
            Assert.AreEqual(4, mesh.Elements[4].Index);
            Assert.AreEqual(5, mesh.Elements[4].Id);
            Assert.AreEqual(3, mesh.Elements[4].Nodes.Count);
            Assert.AreEqual(62, mesh.Elements[4].Nodes[0].Index); // Remember: Index here is zero based, while mesh file is one-based
            Assert.AreEqual(367, mesh.Elements[4].Nodes[1].Index);
            Assert.AreEqual(358, mesh.Elements[4].Nodes[2].Index);

            mesh.BuildNodeElements();
            Assert.AreEqual(4, mesh.Nodes[4].Elements.Count);
            Assert.AreEqual(33, mesh.Nodes[4].Elements[0].Id);
            Assert.AreEqual(36, mesh.Nodes[4].Elements[1].Id);
            Assert.AreEqual(43, mesh.Nodes[4].Elements[2].Id);
            Assert.AreEqual(58, mesh.Nodes[4].Elements[3].Id);

            mesh.BuildFaces(true);
            FaceRevert(mesh, mesh.Faces);
            mesh.Faces.Sort(FaceSortComparer);
            Assert.AreEqual(1259, mesh.Faces.Count);
            Assert.AreEqual(1, mesh.Faces[0].FromNode.Id);
            Assert.AreEqual(42, mesh.Faces[0].ToNode.Id);
            Assert.AreEqual(1, mesh.Faces[1].FromNode.Id);
            Assert.AreEqual(251, mesh.Faces[1].ToNode.Id);
            Assert.AreEqual(1, mesh.Faces[2].FromNode.Id);
            Assert.AreEqual(309, mesh.Faces[2].ToNode.Id);
            int ind = mesh.Faces.FindIndex(mf => mf.FromNode.Id == 68);

            Assert.AreEqual(202, ind);
            Assert.AreEqual(68, mesh.Faces[ind].FromNode.Id);
            Assert.AreEqual(43, mesh.Faces[ind].ToNode.Id);
            Assert.AreEqual(1, mesh.Faces[ind].Code);
            Assert.AreEqual(366, mesh.Faces[ind].LeftElement.Id);
            Assert.AreEqual(null, mesh.Faces[ind].RightElement);
        }
Esempio n. 15
0
        private void selectMesh()
        {
            if (dImportDialog.ShowDialog() == DialogResult.OK)
            {
                string     basefile = Path.GetDirectoryName(dImportDialog.FileName);
                string     filename = Path.GetFileName(dImportDialog.FileName);
                FileSystem fs       = new FileSystem();
                fs.addRoot(basefile);

                dAnimations.DropDownItems.Clear();

                ToolStripButton btn = new ToolStripButton("Add animations");
                btn.Click += new EventHandler(btn_Click);
                dAnimations.DropDownItems.Add(btn);

                string extent = Path.GetExtension(filename);
                if (extent == ".act")
                {
                    anim = null;

                    Actor act = ActorFile.Load(fs, filename);
                    def  = act.Mesh;
                    mesh = null;

                    foreach (KeyValuePair <string, Animation> an in act.Animations)
                    {
                        addAnimation(an.Key, an.Value);
                    }
                }
                else
                {
                    def  = MeshFile.Load(fs, filename);
                    anim = null;
                }

                newMesh(fs);
                updatePose();

                dModelActions.Text = filename;

                dMeshInfo.Text = string.Format("{0} points, {1} texcoords {2} tris, {3}/{4} bones", def.points.Count, def.uvs.Count, def.TriCount, def.bones.Count, new List <MeshDef.Bone>(def.RootBones).Count);

                forceRedraw();
            }
        }
Esempio n. 16
0
        public static PartWrapper GetPartFromLif(LifFile lif, int partID, bool loadMeshes)
        {
            var primitiveFolder = lif.GetFolder("Primitives");
            var meshesFolder    = primitiveFolder.GetFolder("LOD0");

            var primitiveEntry = primitiveFolder.GetFile($"{partID}.xml");

            if (primitiveEntry == null)
            {
                throw new FileNotFoundException($"Primitive file not found. ({partID}.xml)");
            }

            var surfaces = new List <PartSurfaceMesh>();

            foreach (var meshEntry in meshesFolder.GetFiles($"{partID}.g*"))
            {
                if (!PartSurfaceMesh.ParseSurfaceID(meshEntry.Name, out int surfID))
                {
                    surfID = surfaces.Count;
                }

                var surfaceInfo = new PartSurfaceMesh(partID, surfID,
                                                      loadMeshes ? MeshFile.Read(meshEntry.GetStream()) : null);
                surfaces.Add(surfaceInfo);
            }

            if (!surfaces.Any())
            {
                throw new FileNotFoundException($"Mesh file not found. ({partID}.g)");
            }

            var primitive = Primitive.Load(primitiveEntry.GetStream());

            primitive.ID = partID;
            return(new PartWrapper(primitive, surfaces)
            {
                PartID = partID
            });
        }
Esempio n. 17
0
        public void MeshBoundaryToFileTest()
        {
            string   triMesh  = UnitTestHelper.TestDataDir + "odense_rough.mesh";
            MeshFile meshFile = MeshFile.ReadMesh(triMesh);
            MeshData mesh     = meshFile.ToMeshData();

            List <MeshBoundary> boundaries = MeshBoundary.BuildBoundaryList(mesh);

            Assert.AreEqual(2, boundaries.Count);
            Assert.AreEqual(1, boundaries[0].Code);
            Assert.AreEqual(2, boundaries[1].Code);

            Assert.AreEqual(2, boundaries[0].Segments.Count);
            Assert.AreEqual(1, boundaries[1].Segments.Count);
            Assert.AreEqual(9, boundaries[1].Segments[0].Count);

            // First node of the first code-1 boundary segment is the last node of the code-2 boundary segment
            Assert.IsTrue(boundaries[0].Segments[0][0].FromNode == boundaries[1].Segments[0].Last().ToNode);
            Assert.IsTrue(boundaries[0].Segments[0].Last().ToNode == boundaries[1].Segments[0][0].FromNode);

            StreamWriter writer = new StreamWriter(UnitTestHelper.TestDataDir + "out_odense_rough-bnd.txt");

            foreach (MeshBoundary meshBoundary in boundaries)
            {
                writer.WriteLine("# " + meshBoundary.Code);
                foreach (List <MeshFace> segment in meshBoundary.Segments)
                {
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1}", segment[0].FromNode.X, segment[0].FromNode.Y));
                    foreach (MeshFace face in segment)
                    {
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1}", face.ToNode.X, face.ToNode.Y));
                    }
                    writer.WriteLine("");
                }
                writer.WriteLine("");
            }
            writer.Close();
        }
Esempio n. 18
0
        public void InterpolateElementValuesToXYExample()
        {
            // Source mesh
            string   triMesh  = UnitTestHelper.TestDataDir + "odense_rough.mesh";
            MeshFile meshFile = MeshFile.ReadMesh(triMesh);
            MeshData mesh     = meshFile.ToMeshData();

            mesh.BuildDerivedData();

            // Element center values - usually read from dfsu file - here
            // we just calculate some arbitrary linear function of (x,y)
            double[] sourceValues = new double[meshFile.NumberOfElements];
            for (int i = 0; i < meshFile.NumberOfElements; i++)
            {
                sourceValues[i] = 2 * mesh.Elements[i].XCenter + mesh.Elements[i].YCenter;
            }

            // Mesh interpolator
            MeshInterpolator2D interpolator = new MeshInterpolator2D(mesh, MeshValueType.Elements);

            // Coordinates to interpolate values to
            interpolator.SetTargetSize(3);
            interpolator.AddTarget(216600, 6159900);
            interpolator.AddTarget(216700, 6159900);
            interpolator.AddTarget(216700, 6160000);

            // Array to interpolate values to
            double[] targetValues = new double[3];

            // Interpolate element values to target values
            interpolator.InterpolateElmtToTarget(sourceValues, targetValues);

            // Test that values are really 2*x+y
            Assert.AreEqual(2 * 216600 + 6159900, targetValues[0], 1e-6);
            Assert.AreEqual(2 * 216700 + 6159900, targetValues[1], 1e-6);
            Assert.AreEqual(2 * 216700 + 6160000, targetValues[2], 1e-6);
        }
Esempio n. 19
0
        public static PartWrapper GetPartFromDirectory(string path, int partID, bool loadMeshes)
        {
            //var primitivesDir = Path.Combine(path, "db\\Primitives");
            //var meshesDir = Path.Combine(path, "db\\Primitives\\LOD0");

            var primitivesDir = path;
            var meshesDir     = Path.Combine(path, "LOD0");

            var primitiveFile = Path.Combine(primitivesDir, $"{partID}.xml");

            if (!File.Exists(primitiveFile))
            {
                throw new FileNotFoundException($"Primitive file not found. ({partID}.xml)");
            }

            var surfaces = new List <PartSurfaceMesh>();

            foreach (string meshPath in Directory.GetFiles(meshesDir, $"{partID}.g*"))
            {
                if (!PartSurfaceMesh.ParseSurfaceID(meshPath, out int surfID))
                {
                    surfID = surfaces.Count;
                }

                surfaces.Add(new PartSurfaceMesh(partID, surfID, loadMeshes ? MeshFile.Read(meshPath) : null));
            }

            if (!surfaces.Any())
            {
                throw new FileNotFoundException($"Mesh file not found. ({partID}.g)");
            }

            return(new PartWrapper(Primitive.Load(primitiveFile), surfaces)
            {
                PartID = partID
            });
        }
Esempio n. 20
0
 public static MeshData Create(MeshFile mesh)
 {
     return(MeshData.CreateMesh(mesh.Projection, mesh.NodeIds, mesh.X, mesh.Y, mesh.Z, mesh.Code, mesh.ElementIds, mesh.ElementType, mesh.ElementTable));
 }
        public void InterpolationTest(string sourceMeshFileName, string targetMeshFileName, CircularValueTypes cvt = CircularValueTypes.Normal)
        {
            // Source mesh
            MeshFile meshFile = MeshFile.ReadMesh(sourceMeshFileName);
            MeshData mesh     = meshFile.ToMeshData();

            mesh.BuildDerivedData();

            // Mesh to interpolate to
            MeshFile targetFile = MeshFile.ReadMesh(targetMeshFileName);
            MeshData targetmesh = targetFile.ToMeshData();

            // Setup interpolator
            MeshInterpolator2D interpolator = new MeshInterpolator2D(mesh)
            {
                CircularType = cvt, AllowExtrapolation = true
            };

            interpolator.SetupNodeInterpolation();
            interpolator.SetTarget(targetmesh);

            // Find reference x and y value as the smallest x and y value
            double xMin = mesh.Nodes.Select(mn => mn.X).Min();
            double xMax = mesh.Nodes.Select(mn => mn.X).Max();
            double yMin = mesh.Nodes.Select(mn => mn.Y).Min();
            double yMax = mesh.Nodes.Select(mn => mn.Y).Max();

            // Function over the (x,y) plane.
            Func <double, double, double> function = ValueFunction(cvt, xMin, yMin, xMax, yMax);

            // Calculate element center values of function
            double[] elmtVals = new double[mesh.Elements.Count];
            for (int i = 0; i < mesh.Elements.Count; i++)
            {
                MeshElement elmt = mesh.Elements[i];
                elmtVals[i] = function(elmt.XCenter, elmt.YCenter);
            }

            // Write out bounds, to check we got things right
            Console.Out.WriteLine("{0,10} (min,max) = ({1},{2})", cvt, elmtVals.Min(), elmtVals.Max());

            // Interpolate to nodes
            double[] targetValues = new double[targetmesh.Elements.Count];
            interpolator.InterpolateToTarget(elmtVals, targetValues);

            // Check node values
            for (int i = 0; i < targetmesh.Elements.Count; i++)
            {
                MeshElement targetElmt  = targetmesh.Elements[i];
                double      exactValue  = function(targetElmt.XCenter, targetElmt.YCenter);
                double      interpValue = targetValues[i];
                double      diff        = exactValue - interpValue;

                // Check if target element has a boundary node.
                // Nodes on the boundary may not have correctly interpolated value due to
                // inverse distance interpolation on the boundary, and hence also interpolation
                // to target element value will not be exact. So only check on those elements that are
                // fully internal (no boundary nodes).
                bool internalElmt = targetElmt.Nodes.Select(node => node.Code).All(code => code == 0);

                if (internalElmt && diff > 1e-6 * Math.Max(Math.Abs(exactValue), 1))
                {
                    string msg = string.Format("{0,2} : {1}-{2}={3} ({4},{5})", i, exactValue, interpValue, diff, targetElmt.XCenter, targetElmt.YCenter);
                    Console.Out.WriteLine(msg);
                    Assert.Fail(msg);
                }
            }
        }
Esempio n. 22
0
        public static void CreateLDDPackages()
        {
            string lddDir        = Environment.ExpandEnvironmentVariables(@"%appdata%\LEGO Company\LEGO Digital Designer\");
            string primitiveDir  = Path.Combine(lddDir, "db\\Primitives");
            string meshDir       = Path.Combine(lddDir, "db\\Primitives\\LOD0");
            string decorationDir = Path.Combine(lddDir, "db\\Decorations");
            var    lddPalette    = PaletteFile.FromLif(Path.Combine(lddDir, "Palettes\\LDD.lif")).Palettes[0];
            var    xmlDecMap     = XDocument.Load(Path.Combine(lddDir, "db\\DecorationMapping.xml"));
            var    decMappings   = new List <LDD.Data.DecorationMapping>();

            foreach (var elem in xmlDecMap.Root.Elements("Mapping"))
            {
                decMappings.Add(XmlHelper.DefaultDeserialize <LDD.Data.DecorationMapping>(elem));
            }

            foreach (var primitivePath in Directory.GetFiles(primitiveDir, "*.xml")
                     .OrderBy(x => int.Parse(Path.GetFileNameWithoutExtension(x))))
            {
                var primitive = Primitive.Load(primitivePath);

                var package = new PartPackage()
                {
                    PartID    = int.Parse(Path.GetFileNameWithoutExtension(primitivePath)),
                    Primitive = primitive
                };
                var myDecorations = decMappings.Where(x => x.DesignID == package.PartID);

                if (myDecorations.Any())
                {
                    package.DecorationMappings.AddRange(
                        myDecorations.Select(x =>
                                             new LDD.Palettes.Decoration(x.SurfaceID, x.DecorationID)));

                    foreach (string decID in package.DecorationMappings.Select(x => x.DecorationID).Distinct())
                    {
                        var imagePath = Directory.EnumerateFiles(decorationDir, decID + ".*").FirstOrDefault();
                        if (string.IsNullOrEmpty(imagePath))
                        {
                            continue;
                        }
                        var img = Image.FromFile(imagePath);
                        package.DecorationImages.Add(new DecorationImage(decID, img));
                    }
                }

                var myElements = lddPalette.Bricks.Where(x => x.DesignID == package.PartID);
                if (myElements.Any())
                {
                    package.Configurations.AddRange(myElements);
                }

                int surfaceId = 0;
                foreach (var meshPath in Directory.GetFiles(meshDir, package.PartID + ".g*").OrderBy(x => x))
                {
                    var mesh = MeshFile.Read(meshPath);
                    package.Meshes.Add(new PartMesh(package.PartID, surfaceId++, mesh));
                }

                string folderName = package.PartID.ToString()[0].ToString().PadRight(package.PartID.ToString().Length, '0');

                package.Save($"LPI TEST\\{folderName}\\{package.PartID}.lpi");

                package.Dispose();
            }
        }
Esempio n. 23
0
 public PartMesh(int partID, int surfaceID, MeshFile mesh)
 {
     PartID    = partID;
     SurfaceID = surfaceID;
     Mesh      = mesh;
 }
Esempio n. 24
0
        private void AddMesh(MeshFile mesh, List <int> boundaryCodesToRemove = null)
        {
            // node numbers in new mesh for each node in provided mesh
            int[] renumberNodes = new int[mesh.NumberOfNodes];

            // Reused variables
            Extent e = new Extent();
            List <QuadSearchTree.Point> points = new List <QuadSearchTree.Point>();

            // Index of first new node
            int newMeshFirstNodeIndex = _x.Count;

            // Add nodes of current mesh to merged mesh, find which nodes should be merged
            for (int i = 0; i < mesh.NumberOfNodes; i++)
            {
                double x    = mesh.X[i];
                double y    = mesh.Y[i];
                double z    = mesh.Z[i];
                int    code = mesh.Code[i];

                bool boundaryNode = code != 0;

                if (boundaryCodesToRemove != null && boundaryCodesToRemove.Contains(code))
                {
                    code = 0;
                }

                // This criteria selects which nodes to try to merge on, i.e.
                // when to try to find a "duplicate" in merged mesh.
                if (TryMergeAllNodes || boundaryNode)
                {
                    // Check if this current node already "exists" in the merged mesh
                    // i.e. if the current node is "close to" a node in the merged mesh.
                    // "Close to" is decided by the NodeTolerance

                    // Find all nodes within NodeTolerance of (x,y) in search tree
                    UpdatePointExtent(e, x, y, NodeTolerance);
                    points.Clear();
                    _nodeSearchTree.Find(e, points);
                    if (points.Count > 0)
                    {
                        // find the point closest to (x,y), and witin NodeTolerance distance
                        QuadSearchTree.Point closest = null;
                        // Distance must be less than NodeTolerance in order to reuse existing node
                        // Comparing on squared distances, to avoid taking a lot of square roots
                        double minDistSq = NodeTolerance * NodeTolerance;
                        foreach (QuadSearchTree.Point point in points)
                        {
                            double dx     = point.X - x;
                            double dy     = point.Y - y;
                            double distSq = dx * dx + dy * dy;
                            if (distSq < minDistSq)
                            {
                                closest   = point;
                                minDistSq = distSq;
                            }
                        }

                        if (closest != null)
                        {
                            // Node already exist at/close to coordinate, use existing node
                            // and disregard the current node, remember node number (1-based)
                            // for renumbering when adding elements from current mesh.
                            renumberNodes[i] = closest.No;
                            // Update boundary code
                            if (_code[closest.No - 1] == 0 && code != 0)
                            {
                                _code[closest.No - 1] = code;
                            }
                            // Store some statistics
                            NodeMergeCount++;
                            // Skip from here, since the current node should not be added
                            // to the merged mesh.
                            continue;
                        }
                    }
                }

                // Add node to merged mesh
                _x.Add(x);
                _y.Add(y);
                _z.Add(z);
                _code.Add(code);

                // Number of node (1-based) in new mesh
                int nodeNum = _x.Count;
                // remember new node number, for renumbering when adding elements from current mesh
                renumberNodes[i] = nodeNum;
            }

            // Add all new nodes to the quad search tree. New nodes are first added to the search tree
            // now, such that the merge routine never merges two nodes from the same mesh.
            for (int i = newMeshFirstNodeIndex; i < _x.Count; i++)
            {
                // Add to search tree
                QuadSearchTree.Point p = new QuadSearchTree.Point()
                {
                    No = i + 1,
                    X  = _x[i],
                    Y  = _y[i],
                };
                _nodeSearchTree.Add(p);
            }

            // Add all elements
            for (int i = 0; i < mesh.NumberOfElements; i++)
            {
                _elementType.Add(mesh.ElementType[i]);
                // Renumber the nodes of each element to the new node numbers
                int[] meshElmt = mesh.ElementTable[i];
                int[] newelmt  = new int[meshElmt.Length];
                for (int j = 0; j < meshElmt.Length; j++)
                {
                    newelmt[j] = renumberNodes[meshElmt[j] - 1];
                }
                _connectivity.Add(newelmt);
            }
        }
Esempio n. 25
0
        /// <summary>
        /// Process the incoming mesh file names
        /// </summary>
        /// <param name="files">List of mesh file names to merge</param>
        /// <param name="fileBoundaryCodesToRemove">List of boundary codes to remove for each mesh. Must match the size of the files argument</param>
        public void Process(List <string> files, List <List <int> > fileBoundaryCodesToRemove = null)
        {
            // Extent of entire domain, all meshes
            Extent extent = new Extent();

            // Load all meshes
            List <MeshFile> meshes = new List <MeshFile>(files.Count);

            for (int i = 0; i < files.Count; i++)
            {
                MeshFile mesh = MeshFile.ReadMesh(files[i]);
                meshes.Add(mesh);
                for (int j = 0; j < mesh.NumberOfNodes; j++)
                {
                    extent.Include(mesh.X[j], mesh.Y[j]);
                }
            }
            // grow it a littl bit, in case of rounding errors
            extent.XMin = extent.XMin - NodeTolerance;
            extent.XMax = extent.XMax + NodeTolerance;
            extent.YMin = extent.YMin - NodeTolerance;
            extent.YMax = extent.YMax + NodeTolerance;

            // Initialize search tree
            _nodeSearchTree = new QuadSearchTree(extent);

            // Create new mesh nodes and elements
            for (int i = 0; i < files.Count; i++)
            {
                int        prevNodeMergeCount    = NodeMergeCount;
                List <int> boundaryCodesToRemove = fileBoundaryCodesToRemove != null ? fileBoundaryCodesToRemove[i] : null;
                AddMesh(meshes[i], boundaryCodesToRemove);
                if (i > 0)
                {
                    Console.Out.WriteLine("Mesh {0}, number of nodes merged in: {1}", i + 1, NodeMergeCount - prevNodeMergeCount);
                }
            }
            Console.Out.WriteLine("Total number of nodes merged in  : {0}", NodeMergeCount);

            RemoveInternalBoundaryCodes(_code, _connectivity);

            // Create new mesh file
            string      projection  = meshes[0].ProjectionString;
            eumQuantity eumQuantity = meshes[0].EumQuantity;

            MeshBuilder builder = new MeshBuilder();

            builder.SetNodes(_x.ToArray(), _y.ToArray(), _z.ToArray(), _code.ToArray());
            builder.SetElements(_connectivity.ToArray());
            builder.SetProjection(projection);
            builder.SetEumQuantity(eumQuantity);

            MeshFile newMesh = builder.CreateMesh();

            MeshValidator meshValidator = new MeshValidator();

            meshValidator.ValidateMesh(newMesh.X, newMesh.Y, newMesh.Code, newMesh.ElementTable);

            foreach (string error in meshValidator.Errors)
            {
                Console.Out.WriteLine(error);
            }

            newMesh.Write(_newMeshFileName);

            //-------------------------------------
            // Do some statistics on the mesh:

            // collect number of face codes for each mesh
            SortedDictionary <int, int[]> bcCodesStats = new SortedDictionary <int, int[]>();
            List <MeshValidator>          validators   = new List <MeshValidator>();

            for (int meshIndex = 0; meshIndex < meshes.Count; meshIndex++)
            {
                MeshFile      meshFile  = meshes[meshIndex];
                MeshValidator validator = new MeshValidator();
                validator.ValidateMesh(meshFile.X, meshFile.Y, meshFile.Code, meshFile.ElementTable);
                validators.Add(validator);
                UpdateStatistics(meshes.Count + 1, meshIndex, bcCodesStats, validator.GetFaceCodeStatistics());
            }
            UpdateStatistics(meshes.Count + 1, meshes.Count, bcCodesStats, meshValidator.GetFaceCodeStatistics());

            Console.Out.Write("---------------------");
            Console.Out.Write(" Statistics of faces ");
            Console.Out.Write("---------------------");
            Console.Out.WriteLine("");
            Console.Out.Write("FaceCode  |");
            for (int i = 0; i < meshes.Count; i++)
            {
                Console.Out.Write(" mesh {0,2}  ", i + 1);
            }
            Console.Out.Write(" |  total | new mesh");
            Console.Out.WriteLine("");

            int[] totals = new int[meshes.Count + 2];
            foreach (KeyValuePair <int, int[]> keyValuePair in bcCodesStats)
            {
                Console.Out.Write("    {0,4}  |", keyValuePair.Key);
                int total = 0;
                for (int index = 0; index < keyValuePair.Value.Length - 1; index++)
                {
                    int meshCodeCount = keyValuePair.Value[index];
                    total         += meshCodeCount;
                    totals[index] += meshCodeCount;
                    Console.Out.Write(" {0,7}  ", meshCodeCount);
                }
                totals[meshes.Count]     += total;
                totals[meshes.Count + 1] += keyValuePair.Value.Last();
                Console.Out.Write(" |{0,7} | ", total);
                Console.Out.Write(" {0,7}  ", keyValuePair.Value.Last());
                Console.Out.WriteLine("");
            }
            Console.Out.Write("   total  |");
            for (int index = 0; index < meshes.Count; index++)
            {
                Console.Out.Write(" {0,7}  ", totals[index]);
            }
            Console.Out.Write(" |{0,7} | ", totals[meshes.Count]);
            Console.Out.Write(" {0,7}  ", totals[meshes.Count + 1]);
            Console.Out.WriteLine("");
            Console.Out.Write("---------------------");
            Console.Out.Write("---------------------");
            Console.Out.Write("---------------------");
            Console.Out.WriteLine("");
        }
Esempio n. 26
0
 public static SMeshData SCreate(MeshFile mesh)
 {
     return(new SMeshData(mesh.Projection, mesh.NodeIds, mesh.X, mesh.Y, mesh.Z, mesh.Code, mesh.ElementIds, mesh.ElementType, mesh.ElementTable.ToZeroBased()));
 }
Esempio n. 27
0
        public MeshEditorViewModel(MeshFile file)
        {
            MeshFile = file;

            EditTextureBindingsCommand = new ActionCommand(EditTextureBindingsExecute);
        }
Esempio n. 28
0
        /// <summary>
        /// Example of how to plot a mesh file. A mesh contains bottom levels in each node.
        /// </summary>
        public static void MeshTest(bool makeBmp)
        {
            DHI.Chart.Map.Chart.Init();

            // Load mesh data
            string   pathName = Path.Combine(UnitTestHelper.TestDataRoot, @"oresund.mesh");
            MeshFile meshFile = MeshFile.ReadMesh(pathName);

            // FemGridData is data for the bottom levels, a value in each element node, used for coloring
            FemGridData data = new FemGridData();

            data.CreateNodesAndElements(meshFile.NumberOfNodes, meshFile.NumberOfElements, meshFile.X, meshFile.Y, meshFile.Z.ToFloatArray(), meshFile.ElementTable);

            // Create chart
            DHI.Chart.Map.Chart chart = new DHI.Chart.Map.Chart();

            // Add overlay that plots the bottom levels
            FemGridOverlay overlay = new FemGridOverlay();

            overlay.SetGridData(data);
            overlay.EnableNiceValue = true;
            overlay.CreateAutoScaledRainbowPalette();
            overlay.EnableIsoline = true;
            overlay.ColoringType  = MapOverlay.EColoringType.ContinuousColoring;
            overlay.SetFeathering(true, 0.5f);
            overlay.EnableIsolineLabel = true;
            chart.AddOverlay(overlay);

            // Grab map projection of meshfile
            MapProjection mapProj = new MapProjection(meshFile.ProjectionString);
            double        lonOrigin, latOrigin, eastOrigin, northOrigin;

            mapProj.GetOrigin(out lonOrigin, out latOrigin);
            mapProj.Geo2Proj(lonOrigin, latOrigin, out eastOrigin, out northOrigin);
            double convergence = mapProj.GetConvergence(lonOrigin, latOrigin);

            // Overlay adding geographical lines
            // Mesh is drawn in map projection coordinates
            GeoGridOverlay ggOverlay = new GeoGridOverlay();

            ggOverlay.ReferenceProjection = meshFile.ProjectionString;
            ggOverlay.DisplayProjection   = meshFile.ProjectionString;
            // Origin for mesh data is the origin of the projection
            ggOverlay.SetGeoOrigin(lonOrigin, latOrigin);
            ggOverlay.SetOrigin(eastOrigin, northOrigin);
            // Mesh overlay draws in map projection coordinates, so north-Y rotation is the convergence (which is zero)
            ggOverlay.SetNYCRotation(convergence);
            ggOverlay.EnableLonLatGrid  = true;
            ggOverlay.EnableMapProjGrid = true;
            // DataValid must be set after changing in GeoGridOverlay
            ggOverlay.DataValid = true;
            chart.AddOverlay(ggOverlay);

            // 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);

            //chart.GetActiveCoordinateSystem().SetDrawAxis(true, true);
            //chart.GetActiveCoordinateSystem().EnableBorder(true);
            //chart.DrawGrid = true;
            //chart.DrawTitle = true;

            // Draw to bitmap
            double ratio = wrect.Width / (double)wrect.Height;
            Bitmap bmp   = new Bitmap(((int)(ratio * 1024)) + 10, 1024);

            chart.Draw(bmp);

            chart.Dispose();

            if (makeBmp)
            {
                string pngFilepath = Path.Combine(UnitTestHelper.TestDataRoot, @"oresundMesh.png");
                bmp.Save(pngFilepath);

                System.Diagnostics.Process.Start(pngFilepath);
            }
        }
Esempio n. 29
0
 public void AddSurfaceMesh(int surfaceID, MeshFile meshFile)
 {
     Surfaces.Add(new PartSurfaceMesh(PartID, surfaceID, meshFile));
 }
Esempio n. 30
0
        public void InterpolateToXYExample(bool nodeInterp)
        {
            // Source mesh
            string    triMesh  = UnitTestHelper.TestDataDir + "small.mesh";
            MeshFile  meshFile = MeshFile.ReadMesh(triMesh);
            SMeshData mesh     = meshFile.ToSMeshData();

            // Build derived data, required for the interpolation routines
            mesh.BuildDerivedData();

            // Create element center Z values array
            double[] elmtZ = new double[meshFile.NumberOfElements];
            Array.Copy(mesh.ElementZCenter, elmtZ, mesh.NumberOfElements);
            // Make a strong peak at element 5 - in the center of the mesh
            elmtZ[4] = -6;

            // Set up so source can be both element values and node values
            MeshValueType sourceType = MeshValueType.Elements | MeshValueType.Nodes;

            // Mesh interpolator
            MeshInterpolator2D interpolator = new MeshInterpolator2D(mesh, sourceType);

            if (nodeInterp)
            {
                // Simpler interpolation type
                interpolator.ElementValueInterpolationType = MeshInterpolator2D.ElmtValueInterpolationType.NodeValues;
            }

            // Interpolate elmtZ to nodeZ
            double[] nodeZInterp = new double[mesh.NumberOfNodes];
            interpolator.SetupElmtToNodeInterpolation();
            interpolator.NodeInterpolator.Interpolate(elmtZ, nodeZInterp);

            // Interpolation of values one-by-one, no storing of interpolation weights
            Assert.AreEqual(-5.999, interpolator.InterpolateElmtToXY(0.7833, 0.531, elmtZ, nodeZInterp), 1e-3);
            Assert.AreEqual(-3.543, interpolator.InterpolateNodeToXY(0.7833, 0.531, nodeZInterp), 1e-3);

            // Add targets, to store interpolation weights
            interpolator.SetTargetSize(mesh.NumberOfElements + 1);
            interpolator.AddTarget(0.7833, 0.531); // Target at (almost) center of element 5
            for (int i = 0; i < mesh.NumberOfElements; i++)
            {
                interpolator.AddTarget(mesh.ElementXCenter[i], mesh.ElementYCenter[i]);
            }

            // Array to interpolate values to
            double[] targetValues = new double[mesh.NumberOfElements + 1];
            // Interpolate to all target points
            interpolator.InterpolateElmtToTarget(elmtZ, targetValues);

            if (!nodeInterp)
            {
                // When element+node values are used, close to peak value of 6
                Assert.AreEqual(-5.999, targetValues[0], 1e-3);
                Assert.AreEqual(-3.8225, targetValues[1], 1e-3);
                for (int i = 0; i < mesh.NumberOfElements; i++)
                {
                    Assert.AreEqual(elmtZ[i], targetValues[i + 1]);
                }
            }
            else // Using only node interpolation, the value is cut off
            {
                Assert.AreEqual(-3.543, targetValues[0], 1e-3);
                Assert.AreEqual(-3.649, targetValues[1], 1e-3);
            }

            // Interpolating in node Z values, matching to box center value of element.
            interpolator.InterpolateNodeToTarget(mesh.Z, targetValues);
            Assert.AreEqual(-4.376, targetValues[0], 1e-3);
            Assert.AreEqual(-4.376, mesh.ElementZCenter[4], 1e-3);
        }