public ActionResult GetCustomMesh() { IneqMeshViewModel ineqMeshViewModel = (IneqMeshViewModel)Session["IneqMeshViewModel"]; IneqMesh ineqMesh = null; if (ineqMeshViewModel == null) { return(Content(null)); } if (!String.IsNullOrEmpty(ineqMeshViewModel.PLY)) { return(Content(ineqMeshViewModel.PLY)); } ineqMesh = ineqMeshViewModel.IneqMesh; ineqMesh.Create(); if (ineqMeshViewModel.Quality) { CheckQuality(ineqMesh); } if (ineqMeshViewModel.CurvatureQuality) { CheckCurvatureQuality(ineqMesh); } string ply = GetPLY(ineqMesh); ineqMeshViewModel.PLY = ply; return(Content(ply)); }
public ActionResult GetMesh(string Mesh = "") { IneqMesh ineqMesh = null; string path = null; MeshSamples samples = new MeshSamples(); string FileName = Mesh + ".ply"; path = System.IO.Path.Combine(Server.MapPath("~/Samples"), FileName); if (System.IO.File.Exists(path)) { return(File(path, "application/octet-stream")); } ineqMesh = samples[Mesh]; ineqMesh.Create(); CheckQuality(ineqMesh); ineqMesh.DeleteLonelyPoints(); string ply = GetPLY(ineqMesh); System.IO.File.WriteAllText(path, ply); return(File(path, "application/octet-stream")); }
private string GetPLY(IneqMesh ineqMesh) { StringBuilder sbPoints = new StringBuilder(); StringBuilder sbTriangles = new StringBuilder(); int pointsCount = 0; var boundaryTriangles = ineqMesh.Tetrahedrons.SelectMany(t => t.Triangles().Where(tr => /*tr.BoundaryCount == 1 &&*/ tr.P1.Tetrahedrons.Intersect(tr.P2.Tetrahedrons).Intersect(tr.P3.Tetrahedrons).Count() == 1)) //.Where(t => t.Quality > 0.25d) .ToArray(); for (int ineqNumber = 0; ineqNumber < ineqMesh.IneqTree.ExpressionList.Count + 3; ineqNumber++) { var triangles = boundaryTriangles.Where(t => t.CommonBoundaryFlag == ineqNumber).ToArray(); var points = triangles.SelectMany(t => t).Distinct().Select((p, i) => new { Point = p, index = i }).ToDictionary(pi => pi.Point, pi => pi.index); foreach (var p in points.OrderBy(p => p.Value)) { sbPoints.Append(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} {1} {2} {3} 255 {4}", p.Key.X, p.Key.Y, p.Key.Z, colors[ineqNumber % colors.Length], System.Environment.NewLine)); } foreach (var t in triangles) { sbTriangles.Append(String.Format(System.Globalization.CultureInfo.InvariantCulture, "3 {0} {1} {2} {3}", points[t.P1] + pointsCount, points[t.P2] + pointsCount, points[t.P3] + pointsCount, System.Environment.NewLine)); } pointsCount += points.Count; } return(String.Format(plyFormat, pointsCount, boundaryTriangles.Length, sbPoints, sbTriangles)); }
private void CheckBoundaryQuality(IneqMesh ineqMesh) { if (ineqMesh == null) { return; } int c = 0; Dictionary <int, int> counts = new Dictionary <int, int>(); do { c = ineqMesh.CheckBoundaryQuality(minQuality, false); if (!counts.Keys.Contains(c)) { counts[c] = 1; } else { counts[c]++; } }while (c != 0 && counts[c] < 3); //if (c != 0) //{ // c = ineqMesh.CheckBoundaryQuality(minQuality, true); //} ineqMesh.DeleteLonelyPoints(); ineqMesh.Jiggle(3); return; }
public ActionResult GetCustomMeshImproveQuality(bool boundary) { IneqMeshViewModel ineqMeshViewModel = (IneqMeshViewModel)Session["IneqMeshViewModel"]; IneqMesh ineqMesh = null; if (ineqMeshViewModel == null || ineqMeshViewModel.IneqMesh == null || ineqMeshViewModel.IneqMesh.Tetrahedrons.Count == 0) { return(Content(null)); } ineqMesh = ineqMeshViewModel.IneqMesh; if (boundary) { CheckBoundaryQuality(ineqMesh); } else { CheckQuality(ineqMesh); } string ply = GetPLY(ineqMesh); ineqMeshViewModel.PLY = ply; return(Content(ply)); }
public void SetIneqMesh() { IneqMesh = new IneqMesh { X0 = X0, Y0 = Y0, Z0 = Z0, X1 = X1, Y1 = Y1, Z1 = Z1, D = Math.Max(Math.Max(X1 - X0, Y1 - Y0), Z1 - Z0) / MaxDivisionCount, Boxed = true, IneqTree = IneqTreeParser.FromFormula(Formula) }; }
public ActionResult GetCustomMeshJiggle() { IneqMeshViewModel ineqMeshViewModel = (IneqMeshViewModel)Session["IneqMeshViewModel"]; IneqMesh ineqMesh = null; if (ineqMeshViewModel == null || ineqMeshViewModel.IneqMesh == null || ineqMeshViewModel.IneqMesh.Tetrahedrons.Count == 0) { return(Content(null)); } ineqMesh = ineqMeshViewModel.IneqMesh; ineqMesh.Jiggle(3); ineqMesh.DeleteLonelyPoints(); string ply = GetPLY(ineqMesh); ineqMeshViewModel.PLY = ply; return(Content(ply)); }
public MeshSamples() { samples["Half ball and balls"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ( ((IneqTree)((x, y, z) => x * x + y * y + z * z - 1)) & ( (IneqTree)((x, y, z) => - x) | ((x, y, z) => - y )) & ((x, y, z) => - z ) | ((x, y, z) => x * x + y * y + z * z - 0.25) | ((x, y, z) => x * x + y * y + (z + 0.5) * (z + 0.5) - 0.15) ) }; samples["Cylinders, ball, planes"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ( ((IneqTree) ((IneqTree)((x, y, z) => x * x + y * y + z * z - 1) & ((x, y, z) => x - 0.25) & ((x, y, z) => y - 0.25)) | ((x, y, z) => y * y + z * z - 0.2) | ((x, y, z) => x * x + z * z - 0.2) ) & ((x, y, z) => Math.Abs(x) - 1.0) & ((x, y, z) => Math.Abs(y) - 1.0) ) }; samples["4-Ball, cylinder, ball, planes"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ( ((IneqTree) ((x, y, z) => x * x * x * x + y * y * y * y + z * z * z * z - 1) & ((x, y, z) => x - y - z - 0.2d) ) | ((x, y, z) => x * x + y * y + z * z - 0.2) ) & ((x, y, z) => - x * x - y * y + 0.1) & ((x, y, z) => - z - 0.5) }; samples["Cylinders"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = true, IneqTree = ( (IneqTree) ((x, y, z) => y * y + z * z - 0.15) | ((x, y, z) => x * x + z * z - 0.15) | ((x, y, z) => x * x + y * y - 0.15) ) & ( (IneqTree) ((x, y, z) => - x * x - y * y + 0.05) & ((x, y, z) => - x * x - z * z + 0.05) & ((x, y, z) => - z * z - y * y + 0.05) ) & ((x, y, z) => x) }; samples["Sin 1"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ((IneqTree)((x, y, z) => Math.Cos(5 * x) + Math.Cos(5 * y) + Math.Cos(5 * z) - 0.5) & ((x, y, z) => x * x + y * y + z * z - 1) & ((x, y, z) => x - 0.1)) }; samples["Sin 2"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.05d, Boxed = false, IneqTree = ( (IneqTree) ((x, y, z) => x * x + y * y + z * z - ((Math.Cos(9 * x) + Math.Cos(9 * y) + Math.Cos(9 * z)) / 6.0 + 0.6)) | ((x, y, z) => x * x + y * y + z * z - ((Math.Sin(9 * x) + Math.Sin(9 * y) + Math.Sin(9 * z)) / 6.0 + 0.6)) ) & (IneqTree)((x, y, z) => x - 0.1) }; samples["Balls"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -0.25, X1 = 1.0, Y1 = 1.0, Z1 = 0.25, D = 0.075d, Boxed = false, IneqTree = (IneqTreeBalls(8, 0.5d, 0.267d)) & ((x, y, z) => z - 0.1) }; samples["Planes"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -0.25, X1 = 1.0, Y1 = 1.0, Z1 = 0.25, D = 0.075d, Boxed = false, IneqTree = IneqTreePlanes(12) & ((x, y, z) => Math.Abs(z) - 0.25) & ((x, y, z) => - x * x - y * y + 0.1) }; samples["Anuloid, balls"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -0.35, X1 = 1.0, Y1 = 1.0, Z1 = 0.35, D = 0.075d, Boxed = false, IneqTree = (IneqTree) ((x, y, z) => Math.Pow(Math.Sqrt(x * x + y * y) - 0.70, 2) + z * z - 0.0315) | (IneqTreeBalls(6, 0.7d, Math.Sqrt(0.1d))) }; samples["Many cylinders"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -0.25, X1 = 1.0, Y1 = 1.0, Z1 = 0.25, D = 0.075d, Boxed = false, IneqTree = (IneqTreeCylinders(8, 0.5d, 0.253d)) & ((x, y, z) => Math.Abs(z) - 0.25) }; samples["Cone"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = 0, X1 = 1.0, Y1 = 1.0, Z1 = 2.5, D = 0.1d, Boxed = false, IneqTree = ( (IneqTree) ((x, y, z) => x * x + y * y - z * z / 4) ) & (IneqTree)((x, y, z) => - z + 0.4) & (IneqTree)((x, y, z) => x * x + y * y + (z * z) / 2 - 2.25) }; samples["Cone 1"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.055d, Boxed = true, IneqTree = ( (IneqTree) ((x, y, z) => (x - 0.12) * (x - 0.12) + (y + 0.171) * (y + 0.171) - (z - 0.037) * (z - 0.037) / 4) ) & (IneqTree)((x, y, z) => z - 0.037) & (IneqTree)((x, y, z) => (x - 0.12) * (x - 0.12) + (y + 0.171) * (y + 0.171) - 0.15f) }; samples["Ball minus cylinders"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ((IneqTree) ((x, y, z) => x * x + y * y + z * z - 1) & ((x, y, z) => - x * x - y * y - z * z + 25.0 / 64.0)) & ((x, y, z) => - (x + 16.0 / 25.0) * (x + 16.0 / 25.0) - (y - 16.0 / 25.0) * (y - 16.0 / 25.0) + 0.25) & ((x, y, z) => - (y + 16.0 / 25.0) * (y + 16.0 / 25.0) - (z + 16.0 / 25.0) * (z + 16.0 / 25.0) + 0.25) & ((x, y, z) => - (z - 16.0 / 25.0) * (z - 16.0 / 25.0) - (x - 16.0 / 25.0) * (x - 16.0 / 25.0) + 0.25) }; samples["Ball in ball"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = (((IneqTree) ((x, y, z) => x * x + y * y + z * z - 1) & ((x, y, z) => - x * x - y * y + 0.15) & ((x, y, z) => - (x - 1) * (x - 1) - z * z + 0.25))) | ((IneqTree)((x, y, z) => x * x + y * y + z * z - 0.7)) }; samples["Anuloids"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.075d, Boxed = false, IneqTree = (IneqTree) ((x, y, z) => (x * x + y * y) * Math.Pow(1 - 0.70 / Math.Sqrt(x * x + y * y), 2) + z * z - 0.0315) | ((x, y, z) => (x * x + z * z) * Math.Pow(1 - 0.70 / Math.Sqrt(x * x + z * z), 2) + y * y - 0.0315) | ((x, y, z) => (z * z + y * y) * Math.Pow(1 - 0.70 / Math.Sqrt(z * z + y * y), 2) + x * x - 0.0315) }; samples["Anuloids1"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.05d, Boxed = false, IneqTree = IneqTreeAnuloids(6, -0.7d, 0.7d, 0.2d, 0.2d, 0.7d, 0.3d) & ((x, y, z) => Math.Abs(z) - 0.8) }; samples["Anuloids2"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.045d, Boxed = false, IneqTree = IneqTreeAnuloids1(8, 0.7d, 0.2d, 0.1d) | IneqTreeAnuloid(0, 0, 0, 0.15d, 0.7d, 0, 0, 1) }; samples["Anuloids3"] = new IneqMesh { X0 = -1.4, Y0 = -1.4, Z0 = -1.0, X1 = 1.4, Y1 = 1.4, Z1 = 1.0, D = 0.065d, Boxed = false, IneqTree = IneqTreeAnuloids1(16, 0.7d, 0.4d, 0.2d) //| IneqTreeAnuloid(0, 0, 0, 0.15d, 0.7d, 0, 0, 1) }; samples["AntiAnuloids"] = new IneqMesh { X0 = -1.4, Y0 = -1.4, Z0 = -1.0, X1 = 1.4, Y1 = 1.4, Z1 = 1.0, D = 0.065d, Boxed = false, IneqTree = IneqTreeAntiAnuloids(16, 0.7d, 0.4d, 0.1d) & IneqTreeAnuloid(0, 0, 0, 0.4d, 0.7d, 0, 0, 1, false) }; samples["Many cylinders 1"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -0.6, X1 = 1.0, Y1 = 1.0, Z1 = 0.6, D = 0.075d, Boxed = false, IneqTree = ((IneqTreeCylinders1(6, 0.2d, 0.2d) & ((x, y, z) => x * x + y * y + z * z - 1))/* | ((x, y, z) => x * x + y * y + 800 * z * z * z * z * z * z * z * z - 0.25d)*/ ) }; samples["Viviani"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = (IneqTree)((x, y, z) => x * x + y * y + z * z - 1) & ((x, y, z) => (x - 0.5) * (x - 0.5) + y * y - 0.25) }; samples["Sharp cone"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1, X1 = 1.0, Y1 = 1.0, Z1 = 1.2, D = 0.075d, Boxed = false, IneqTree = IneqTreePlanes1(6) & //((x, y, z) => z - 1) & ((x, y, z) => - z) /*& * ((x, y, z) => -x * x - y * y + 0.1)*/ }; samples["Balls in 4-ball"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ( ( (IneqTree)((x, y, z) => x * x * x * x + y * y * y * y + z * z * z * z - 1) & ((x, y, z) => - x * x - y * y + 0.37) & ((x, y, z) => x + y + z - 0.4) ) | ((x, y, z) => (x - 0.35) * (x - 0.35) + y * y + z * z - 0.30) | ((x, y, z) => (x + 0.35) * (x + 0.35) + y * y + z * z - 0.30) ) & ((x, y, z) => y - 0.7) }; samples["Ball in box"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.1d, Boxed = false, IneqTree = ( ( (IneqTree)((x, y, z) => Math.Abs(x) - 0.6) & ((x, y, z) => Math.Abs(y) - 0.6) & ((x, y, z) => Math.Abs(z) - 0.6) ) | ((x, y, z) => x * x + y * y + z * z - 0.5) ) }; samples["SnowWoman"] = new IneqMesh { X0 = -0.6, Y0 = -1.0, Z0 = -0.6, X1 = 0.6, Y1 = 1.0, Z1 = 0.6, D = 0.06, Boxed = false, IneqTree = ( ((IneqTree)((x, y, z) => (y - 0.5) * (y - 0.5) + x * x + z * z - 0.29) | ((x, y, z) => (y - 0) * (y - 0) + x * x + z * z - 0.2) | ((x, y, z) => (y - 0) * (y - 0) + (x + 0.4) * (x + 0.4) + (z - 0.2) * (z - 0.2) - 0.05) | ((x, y, z) => (y - 0) * (y - 0) + (x + 0.4) * (x + 0.4) + (z + 0.2) * (z + 0.2) - 0.05) | ((x, y, z) => (y + 0.5) * (y + 0.5) + x * x + z * z - 0.15) | ((x, y, z) => 2 * (y + 0.5) * (y + 0.5) + (x + 0.4) * (x + 0.4) + 2 * z * z - 0.01) | ((x, y, z) => (x * x + z * z - 0.08))) & ((x, y, z) => (Math.Abs(y) - 1.0)) ) }; samples["Cuted cylinders"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.05d, Boxed = true, IneqTree = ( ( (IneqTree)((x, y, z) => x * x + y * y - 0.25) | ((x, y, z) => x * x + z * z - 0.25) | ((x, y, z) => z * z + y * y - 0.25) ) & (IneqTree)((x, y, z) => Math.Pow(Math.Abs(x), 0.5) + Math.Pow(Math.Abs(y), 0.5) + Math.Pow(Math.Abs(z), 0.5) - 1.89) ) }; samples["Ball"] = new IneqMesh { X0 = -1.0, Y0 = -1.0, Z0 = -1.0, X1 = 1.0, Y1 = 1.0, Z1 = 1.0, D = 0.15d, Boxed = false, IneqTree = ((IneqTree)((x, y, z) => x * x + y * y + z * z - 1)) }; samples["Tetra cylinder"] = new IneqMesh { X0 = -0.75, Y0 = -0.75, Z0 = -0.75, X1 = 2.25, Y1 = 2.25, Z1 = 2.25, D = 0.1d, Boxed = false, IneqTree = IneqTreeBall(0, 0, 0, 0.55) | IneqTreeBall(1.5, 0, 0, 0.55) | IneqTreeBall(0.75, 1.5 * Math.Sin(2 * Math.PI / 3), 0, 0.55) | IneqTreeBall(2.25 / 3, 1.5 * Math.Sin(2 * Math.PI / 3) / 3, Math.Sqrt(2.25 - Math.Pow(2 * 1.5 * Math.Sin(2 * Math.PI / 3) / 3, 2)), 0.55) | IneqTreeCylinder(0, 0, 0, 1.5, 0, 0, 0.2, 1.5) | IneqTreeCylinder(0, 0, 0, 0.75, 1.5 * Math.Sin(2 * Math.PI / 3), 0, 0.2, 1.5) | IneqTreeCylinder(0, 0, 0, 2.25 / 3, 1.5 * Math.Sin(2 * Math.PI / 3) / 3, Math.Sqrt(2.25 - Math.Pow(2 * 1.5 * Math.Sin(2 * Math.PI / 3) / 3, 2)), 0.2, 1.5) | IneqTreeCylinder(1.5, 0, 0, 0.75, 1.5 * Math.Sin(2 * Math.PI / 3), 0, 0.2, 1.5) | IneqTreeCylinder(1.5, 0, 0, 2.25 / 3, 1.5 * Math.Sin(2 * Math.PI / 3) / 3, Math.Sqrt(2.25 - Math.Pow(2 * 1.5 * Math.Sin(2 * Math.PI / 3) / 3, 2)), 0.2, 1.5) | IneqTreeCylinder(0.75, 1.5 * Math.Sin(2 * Math.PI / 3), 0, 2.25 / 3, 1.5 * Math.Sin(2 * Math.PI / 3) / 3, Math.Sqrt(2.25 - Math.Pow(2 * 1.5 * Math.Sin(2 * Math.PI / 3) / 3, 2)), 0.2, 1.5) }; //samples["* Bear"] = new Func<IneqMesh>(() => Bear()); //samples["* Muse"] = new Func<IneqMesh>(() => Muse()); //samples["* Bunny"] = new Func<IneqMesh>(() => Bunny()); //samples["* BunnyHead"] = new Func<IneqMesh>(() => BunnyHead()); //samples["* BunnyMuse"] = new Func<IneqMesh>(() => BunnyMuse()); //samples["* Head"] = new Func<IneqMesh>(() => Head()); //samples["* Head1"] = new Func<IneqMesh>(() => Head1()); //samples["* Moai"] = new Func<IneqMesh>(() => Moai()); //samples["* Moai1"] = new Func<IneqMesh>(() => Moai1()); //samples["** Tooth"] = new Func<IneqMesh>(() => Tooth()); //samples["** Skull and brain"] = new Func<IneqMesh>(() => Skull4()); //samples["** Skull part"] = new Func<IneqMesh>(() => Skull(1)); }
private void CheckCurvatureQuality(IneqMesh ineqMesh) { List <Triangle> refList = new List <Triangle>(); var edges = ineqMesh.Edges .Where(e => e.P1.Boundary.Cast <bool>().Select((b, i) => new { b = b, i = i }).Where(bi => bi.b && e.P2.Boundary[bi.i]).Count() == 2) .Select(e => { var cf = e.P1.Boundary.Cast <bool>().Select((b, i) => new { b = b, i = i }).Where(bi => bi.b && e.P2.Boundary[bi.i]).ToArray(); return(new { bf1 = cf[0].i, bf2 = cf[1].i, p = e.Average(), e = e, length = e.P1.Distance(e.P2) }); }).ToArray(); foreach (var ee in edges) { if (!ee.e.Valid) { continue; } Point origp = new Point(ee.p.X, ee.p.Y, ee.p.Z); ineqMesh.ProjectToEdge(ee.p, ee.bf1, ee.bf2, false); double dist = origp.Distance(ee.p); if (dist >= ee.length / 25.0d) { var e = ee.e; var trians = e .P1.Tetrahedrons.Intersect(e.P2.Tetrahedrons) .SelectMany(tt => tt.Triangles()) .Where(tr => tr.Contains(e.P1) && tr.Contains(e.P2)) .GroupBy(tr => tr) .Where(gr => gr.Count() == 1) .Select(gr => gr.Single()); refList.AddRange(trians); } } var centerPoints = ineqMesh.Tetrahedrons.SelectMany(t => t.Triangles() .Where(tr => tr.BoundaryCount == 1 && tr.P1.Tetrahedrons.Intersect(tr.P2.Tetrahedrons).Intersect(tr.P3.Tetrahedrons).Count() == 1)) .Select(tr => new { bf = tr.CommonBoundaryFlag.Value, p = tr.Average(), tr = tr, maxLength = Math.Max(Math.Max(tr.P1.Distance(tr.P2), tr.P1.Distance(tr.P3)), tr.P2.Distance(tr.P3)) }); foreach (var cp in centerPoints) { Point origp = new Point(cp.p.X, cp.p.Y, cp.p.Z); ineqMesh.ProjectToSurface(cp.p, 100, cp.bf, false); double dist = origp.Distance(cp.p); if (dist >= cp.maxLength / 25.0d) { refList.Add(cp.tr); } } ineqMesh.RefineBoundaryTriangles(refList); ineqMesh.Jiggle(3); }