public static TetgenMesh ToTetgenMesh(this Mesh m) { Mesh M = m.DuplicateMesh(); M.Faces.ConvertQuadsToTriangles(); M.UnifyNormals(); TetgenMesh tm = new TetgenMesh(); tm.Vertices = new double[M.Vertices.Count * 3]; tm.FaceIndices = new int[M.Faces.Count * 3]; tm.FaceSizes = new int[M.Faces.Count]; for (int i = 0; i < M.Vertices.Count; ++i) { tm.Vertices[i * 3] = M.Vertices[i].X; tm.Vertices[i * 3 + 1] = M.Vertices[i].Y; tm.Vertices[i * 3 + 2] = M.Vertices[i].Z; } for (int i = 0; i < M.Faces.Count; ++i) { tm.FaceSizes[i] = 3; tm.FaceIndices[i * 3] = M.Faces[i].A; tm.FaceIndices[i * 3 + 1] = M.Faces[i].B; tm.FaceIndices[i * 3 + 2] = M.Faces[i].C; } return(tm); }
public static TetgenMesh ToTetgenMesh(this Mesh m) { Mesh M = m.DuplicateMesh(); //M.Faces.ConvertQuadsToTriangles(); M.UnifyNormals(); TetgenMesh tm = new TetgenMesh(); tm.Vertices = new double[M.Vertices.Count * 3]; var FaceIndexCount = 0; tm.FaceSizes = new int[M.Faces.Count]; for (int i = 0; i < M.Faces.Count; ++i) { int fsize = M.Faces[i].IsQuad ? 4 : 3; FaceIndexCount += fsize; tm.FaceSizes[i] = fsize; } tm.FaceIndices = new int[FaceIndexCount]; for (int i = 0; i < M.Vertices.Count; ++i) { tm.Vertices[i * 3] = M.Vertices[i].X; tm.Vertices[i * 3 + 1] = M.Vertices[i].Y; tm.Vertices[i * 3 + 2] = M.Vertices[i].Z; } int fi = 0; for (int i = 0; i < M.Faces.Count; ++i) { tm.FaceIndices[fi] = M.Faces[i].A; fi++; tm.FaceIndices[fi] = M.Faces[i].B; fi++; tm.FaceIndices[fi] = M.Faces[i].C; fi++; if (M.Faces[i].IsQuad) { tm.FaceIndices[fi] = M.Faces[i].D; fi++; } } return(tm); }
public static List <Point3d> ToPointList(this TetgenMesh tm) { List <Point3d> points = new List <Point3d>(); for (int i = 0; i < tm.Vertices.Length; i += 3) { points.Add(new Point3d( tm.Vertices[i], tm.Vertices[i + 1], tm.Vertices[i + 2] )); } return(points); }
public static Mesh[] TetraToRhinoMesh(this TetgenMesh tm) { List <Point3d> points = new List <Point3d>(); for (int i = 0; i < tm.Vertices.Length; i += 3) { points.Add(new Point3d( tm.Vertices[i], tm.Vertices[i + 1], tm.Vertices[i + 2] )); } Mesh[] tetra = new Mesh[tm.TetraIndices.Length / 4]; for (int i = 0; i < tetra.Length; ++i) { int ivert = i * 4; Mesh t = new Mesh(); t.Vertices.Add(points[tm.TetraIndices[ivert]]); t.Vertices.Add(points[tm.TetraIndices[ivert + 1]]); t.Vertices.Add(points[tm.TetraIndices[ivert + 2]]); t.Vertices.Add(points[tm.TetraIndices[ivert + 3]]); t.Faces.AddFace(0, 1, 2); t.Faces.AddFace(1, 2, 3); t.Faces.AddFace(2, 3, 0); t.Faces.AddFace(3, 0, 1); t.FaceNormals.ComputeFaceNormals(); t.Normals.ComputeNormals(); t.UnifyNormals(); tetra[i] = t; } return(tetra); }
public static Mesh ToRhinoMesh(this TetgenMesh tm) { Mesh m = new Mesh(); for (int i = 0; i < tm.Vertices.Length; i += 3) { m.Vertices.Add( tm.Vertices[i], tm.Vertices[i + 1], tm.Vertices[i + 2] ); } for (int i = 0; i < tm.FaceIndices.Length; i += 3) { m.Faces.AddFace( tm.FaceIndices[i], tm.FaceIndices[i + 1], tm.FaceIndices[i + 2] ); } m.Vertices.CullUnused(); m.FaceNormals.ComputeFaceNormals(); m.Normals.ComputeNormals(); m.UnifyNormals(); if (m.SolidOrientation() <= 0) { m.Flip(true, true, true); } return(m); }
protected override void SolveInstance(IGH_DataAccess DA) { List <Mesh> meshes = new List <Mesh>(); if (!DA.GetDataList("Mesh", meshes)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No input mesh specified."); return; } int flags = 1; DA.GetData("Flags", ref flags); double minratio = 2.0; DA.GetData("MinRatio", ref minratio); if (minratio <= 1.0) { minratio = 1.1; } double maxvolume = 2.0; DA.GetData("MaxVolume", ref maxvolume); int steiner = 0; DA.GetData("Steiner", ref steiner); int coarsen = 0; DA.GetData("Coarsen", ref coarsen); DataTree <int> indices = new DataTree <int>(); DataTree <GH_Mesh> meshes_out = new DataTree <GH_Mesh>(); DataTree <GH_Point> points_out = new DataTree <GH_Point>(); var face_indices = new DataTree <int>(); var verts_indices = new DataTree <int>(); int N, index = 0; GH_Path path; for (int i = 0; i < meshes.Count; ++i) { if (maxvolume > 0) { var vmp = VolumeMassProperties.Compute(meshes[i]); maxvolume = Math.Max(maxvolume, vmp.Volume / 100000); // Safety so as not to end up with too many elements... } TetgenSharp.TetgenBehaviour b = new TetgenSharp.TetgenBehaviour(); b.quality = 1; b.plc = 1; b.minratio = minratio; b.coarsen = coarsen; b.maxvolume = maxvolume; b.supsteiner_level = steiner; TetgenMesh tin = TetgenRC.ExtensionMethods.ToTetgenMesh(meshes[i]); TetgenSharp.TetgenMesh tm = TetgenSharp.TetRhino.Tetrahedralize(tin, b); //path = new GH_Path(i); if (tm == null) { this.Message = "Failed."; return; } switch (flags) { case (0): meshes_out.AddRange(TetgenRC.ExtensionMethods.TetraToRhinoMesh(tm).Select(x => new GH_Mesh(x)), new GH_Path(i, 0)); break; case (1): meshes_out.Add(new GH_Mesh(TetgenRC.ExtensionMethods.ToRhinoMesh(tm)), new GH_Path(i, 0)); break; case (2): N = tm.TetraIndices.Length / 4; for (int j = 0; j < N; ++j) { path = new GH_Path(i, j); index = j * 4; indices.Add(tm.TetraIndices[index], path); indices.Add(tm.TetraIndices[index + 1], path); indices.Add(tm.TetraIndices[index + 2], path); indices.Add(tm.TetraIndices[index + 3], path); } N = tm.FaceSizes.Length; int fi = 0; for (int j = 0; j < N; ++j) { var fpath = new GH_Path(i, j); for (int k = 0; k < tm.FaceSizes[j]; ++k) { face_indices.Add(tm.FaceIndices[fi], fpath); fi++; } } points_out.AddRange(TetgenRC.ExtensionMethods.ToPointList(tm).Select(x => new GH_Point(x)), new GH_Path(i, 0)); break; case (3): N = tm.EdgeIndices.Length / 2; for (int j = 0; j < N; ++j) { path = new GH_Path(i, j); index = j * 2; indices.Add(tm.EdgeIndices[index], path); indices.Add(tm.EdgeIndices[index + 1], path); } points_out.AddRange(TetgenRC.ExtensionMethods.ToPointList(tm).Select(x => new GH_Point(x)), new GH_Path(i, 0)); break; default: break; } } DA.SetDataTree(MeshOutIndex, meshes_out); DA.SetDataTree(IndicesOutIndex, indices); DA.SetDataTree(PointsOutIndex, points_out); DA.SetDataTree(FacesOutIndex, face_indices); }
protected override void SolveInstance(IGH_DataAccess DA) { List <Mesh> meshes = new List <Mesh>(); if (!DA.GetDataList("Mesh", meshes)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No input mesh specified."); return; } int flags = 1; DA.GetData("Flags", ref flags); double minratio = 2.0; DA.GetData("MinRatio", ref minratio); if (minratio <= 1.0) { minratio = 1.1; } TetgenSharp.TetgenBehaviour b = new TetgenSharp.TetgenBehaviour(); b.quality = 1; b.plc = 1; b.minratio = minratio; b.coarsen = 1; DataTree <int> indices = new DataTree <int>(); DataTree <GH_Mesh> meshes_out = new DataTree <GH_Mesh>(); DataTree <GH_Point> points_out = new DataTree <GH_Point>(); int N, index = 0; GH_Path path; for (int i = 0; i < meshes.Count; ++i) { TetgenMesh tin = TetgenRC.ExtensionMethods.ToTetgenMesh(meshes[i]); TetgenSharp.TetgenMesh tm = TetgenSharp.TetRhino.Tetrahedralize(tin, b); //path = new GH_Path(i); switch (flags) { case (0): meshes_out.AddRange(TetgenRC.ExtensionMethods.TetraToRhinoMesh(tm).Select(x => new GH_Mesh(x)), new GH_Path(i, 0)); break; case (1): meshes_out.Add(new GH_Mesh(TetgenRC.ExtensionMethods.ToRhinoMesh(tm)), new GH_Path(i, 0)); break; case (2): N = tm.TetraIndices.Length / 4; for (int j = 0; j < N; ++j) { path = new GH_Path(i, j); index = j * 4; indices.Add(tm.TetraIndices[index], path); indices.Add(tm.TetraIndices[index + 1], path); indices.Add(tm.TetraIndices[index + 2], path); indices.Add(tm.TetraIndices[index + 3], path); } points_out.AddRange(TetgenRC.ExtensionMethods.ToPointList(tm).Select(x => new GH_Point(x)), new GH_Path(i, 0)); break; case (3): N = tm.EdgeIndices.Length / 2; for (int j = 0; j < N; ++j) { path = new GH_Path(i, j); index = j * 2; indices.Add(tm.EdgeIndices[index], path); indices.Add(tm.EdgeIndices[index + 1], path); } points_out.AddRange(TetgenRC.ExtensionMethods.ToPointList(tm).Select(x => new GH_Point(x)), new GH_Path(i, 0)); break; default: break; } } DA.SetDataTree(MeshOutIndex, meshes_out); DA.SetDataTree(IndicesOutIndex, indices); DA.SetDataTree(PointsOutIndex, points_out); }
protected override void SolveInstance(IGH_DataAccess DA) { Mesh mesh = new Mesh(); if (!DA.GetData("Mesh", ref mesh)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No input mesh specified."); return; } int flags = 1; DA.GetData("Flags", ref flags); double minratio = 2.0; DA.GetData("MinRatio", ref minratio); if (minratio <= 1.0) { minratio = 1.1; } TetgenSharp.TetgenBehaviour b = new TetgenSharp.TetgenBehaviour(); b.quality = 1; b.plc = 1; b.minratio = minratio; b.coarsen = 1; TetgenMesh tin = TetgenRC.ExtensionMethods.ToTetgenMesh(mesh); TetgenSharp.TetgenMesh tm = TetgenSharp.TetRhino.Tetrahedralize(tin, b); DataTree <int> indices; int N, index = 0; GH_Path path; switch (flags) { case (0): DA.SetDataList("Mesh", TetgenRC.ExtensionMethods.TetraToRhinoMesh(tm).Select(x => new GH_Mesh(x))); break; case (1): DA.SetDataList("Mesh", new GH_Mesh[] { new GH_Mesh(TetgenRC.ExtensionMethods.ToRhinoMesh(tm)) }); break; case (2): indices = new DataTree <int>(); N = tm.TetraIndices.Length / 4; DA.SetData("Length", N); //Ajout BH for (int i = 0; i < N; ++i) { path = new GH_Path(i); index = i * 4; indices.Add(tm.TetraIndices[index], path); indices.Add(tm.TetraIndices[index + 1], path); indices.Add(tm.TetraIndices[index + 2], path); indices.Add(tm.TetraIndices[index + 3], path); } DA.SetDataTree(1, indices); DA.SetDataList("Points", TetgenRC.ExtensionMethods.ToPointList(tm)); break; case (3): indices = new DataTree <int>(); N = tm.EdgeIndices.Length / 2; for (int i = 0; i < N; ++i) { path = new GH_Path(i); index = i * 2; indices.Add(tm.EdgeIndices[index], path); indices.Add(tm.EdgeIndices[index + 1], path); } DA.SetDataTree(1, indices); DA.SetDataList("Points", TetgenRC.ExtensionMethods.ToPointList(tm)); break; default: break; } }