// container = cube, 8 vertices, 6 faces of 4 vertices each void buildContainer() { float[][] tmpv = new float[][] { new float[] { S, S, S }, new float[] { -S, S, S }, new float[] { -S, S, -S }, new float[] { S, S, -S }, new float[] { S, -S, S }, new float[] { -S, -S, S }, new float[] { -S, -S, -S }, new float[] { S, -S, -S } }; containerVertices = tmpv; // vertices need to be in a consistent order (clockwise, or counterclockwise around the face) int[][] tmpf = new int[][] { new int[] { 0, 1, 2, 3 }, new int[] { 1, 0, 4, 5 }, new int[] { 0, 3, 7, 4 }, new int[] { 2, 1, 5, 6 }, new int[] { 5, 4, 7, 6 }, new int[] { 3, 2, 6, 7 } }; containerFaces = tmpf; container = new HE_Mesh(); container.buildMesh(containerVertices, containerFaces); //container.roundEdges(100); //container.roundCorners(40); }
/// <summary> /// Compute the level-sets for a mesh given a specified valueKey for the mesh vertex dictionary. /// </summary> /// <param name="valueKey">Key of the value to be computed per vertex.</param> /// <param name="levels">List of level values to be computed.</param> /// <param name="mesh">The mesh to compute the level-sets in.</param> /// <param name="levelSets">Resulting level sets.</param> public static void ComputeLevels(string valueKey, List <double> levels, HE_Mesh mesh, out List <List <Line> > levelSets) { List <List <Line> > resultLines = new List <List <Line> >(); for (int i = 0; i < levels.Count; i++) { resultLines.Add(new List <Line>()); } int iter = 0; foreach (HE_Face face in mesh.Faces) { int count = 0; foreach (double level in levels) { Line l = new Line(); if (GetFaceLevel(valueKey, level, face, out l)) { resultLines[count].Add(l); } count++; } iter++; } levelSets = resultLines; }
/// <summary> /// Compute the gradient on a given mesh given some per-vertex values /// </summary> /// <param name="valueKey">Key of the values in the vertex.UserData dictionary</param> /// <param name="mesh">Mesh to compute the gradient.</param> /// <returns>A list containing all the gradient vectors per-face.</returns> public static List <Vector3d> ComputeGradientField(string valueKey, HE_Mesh mesh) { List <Vector3d> gradientField = new List <Vector3d>(); mesh.Faces.ForEach(face => gradientField.Add(ComputeFaceGradient(valueKey, face))); return(gradientField); }
void OnPostRender() { List <HE_Mesh> meshes = voronoiTest.meshes; List <PVector> centers = voronoiTest.centers; CreateGLMaterial(); glMaterial.SetPass(0); GL.PushMatrix(); Matrix4x4 mtx = voronoiTest.transform.localToWorldMatrix; //draw ////////////////////////// GL.Begin(GL.LINES); for (int i = 0; i < meshes.Count; i++) { PVector center = (PVector)centers [i]; HE_Mesh mesh = (HE_Mesh)meshes [i]; Color color = Color.Lerp(Color.red, Color.blue, (float)i / (float)meshes.Count); //mesh.drawEdges(); int edgeNum = mesh.edges.Count; for (int j = 0; j < edgeNum; j++) { HE_Edge e = mesh.edges [j]; GL.Color(color); Vector3 pos0 = mtx.MultiplyPoint3x4(e.halfEdge.vert.pos + center.pos * 0.2f); Vector3 pos1 = mtx.MultiplyPoint3x4(e.halfEdge.pair.vert.pos + center.pos * 0.2f); //Debug.DrawLine (p0 + center.pos * 0.2f, p1 + center.pos * 0.2f, Color.red); GL.Vertex(pos0); GL.Vertex(pos1); } } /* * for(int i=0; i < voronoiCells.Length; i++) * { * int edgeNum = voronoiCells[i].edges.Count; * * for(int j = 0; j < edgeNum; j++){ * HE_Edge e = voronoiCells[i].edges[j]; * Color color = Color.Lerp(Color.red, Color.blue, (float)j / (float)edgeNum); * //Debug.DrawLine(e.halfEdge.vert.pos, e.halfEdge.pair.vert.pos, color); * * GL.Color(color); * Vector3 pos0 = mtx.MultiplyPoint3x4(e.halfEdge.vert.pos); * Vector3 pos1 = mtx.MultiplyPoint3x4(e.halfEdge.pair.vert.pos); * GL.Vertex(pos0); * GL.Vertex(pos1); * } * } */ GL.End(); GL.PopMatrix(); }
// get clone public HE_Mesh get() { HE_Mesh result = new HE_Mesh(); reindex(); for (int i = 0; i < vertices.Count; i++) { result.vertices.Add((vertices [i]).getClone()); } for (int i = 0; i < faces.Count; i++) { result.faces.Add(new HE_Face()); } for (int i = 0; i < halfEdges.Count; i++) { result.halfEdges.Add(new HE_HalfEdge()); } for (int i = 0; i < edges.Count; i++) { result.edges.Add(new HE_Edge()); } // for (int i = 0; i < vertices.Count; i++) { HE_Vertex sv = vertices [i]; HE_Vertex tv = result.vertices [i]; tv.halfEdge = result.halfEdges [sv.halfEdge.id]; } for (int i = 0; i < faces.Count; i++) { HE_Face sf = faces [i]; HE_Face tf = result.faces [i]; tf.id = i; tf.halfEdge = result.halfEdges [sf.halfEdge.id]; } for (int i = 0; i < edges.Count; i++) { HE_Edge se = edges [i]; HE_Edge te = result.edges [i]; te.halfEdge = result.halfEdges [se.halfEdge.id]; te.id = i; } for (int i = 0; i < halfEdges.Count; i++) { HE_HalfEdge she = halfEdges [i]; HE_HalfEdge the = result.halfEdges [i]; the.pair = result.halfEdges [she.pair.id]; the.next = result.halfEdges [she.next.id]; the.prev = result.halfEdges [she.prev.id]; the.vert = result.vertices [she.vert.id]; the.face = result.faces [she.face.id]; the.edge = result.edges [she.edge.id]; the.id = i; } return(result); }
void buildMesh() { HE_Mesh mesh = new HE_Mesh(); mesh = container.get(); meshes.Add(mesh); centers.Add(new PVector()); }
HE_Mesh getDual() { HE_Mesh result = new HE_Mesh(); reindex(); for (int i = 0; i < faces.Count; i++) { HE_Face f = faces [i]; HE_HalfEdge he = f.halfEdge; PVector faceCenter = new PVector(); int n = 0; do { faceCenter.add(he.vert); he = he.next; n++; } while(he != f.halfEdge); faceCenter.div(n); result.vertices.Add(new HE_Vertex(faceCenter.x, faceCenter.y, faceCenter.z, i)); } //for(int i=0;i<vertices.Count;i++){ //HE_Vertex v=getVertex(i); foreach (HE_Vertex v in vertices) { HE_HalfEdge he = v.halfEdge; HE_Face f = he.face; List <HE_HalfEdge> faceHalfEdges = new List <HE_HalfEdge> (); HE_Face nf = new HE_Face(); result.faces.Add(nf); do { HE_HalfEdge hen = new HE_HalfEdge(); faceHalfEdges.Add(hen); hen.face = nf; hen.vert = result.vertices [f.id]; if (hen.vert.halfEdge == null) { hen.vert.halfEdge = hen; } if (nf.halfEdge == null) { nf.halfEdge = hen; } he = he.pair.next; f = he.face; } while(he != v.halfEdge); cycleHalfEdges(faceHalfEdges, false); result.halfEdges.AddRange(faceHalfEdges); } result.pairHalfEdges(result.halfEdges); result.createEdges(result.halfEdges, result.edges); result.reindex(); return(result); }
/// <summary> /// Computes the total area of the mesh /// </summary> /// <returns>The mesh area.</returns> public static double TotalArea(HE_Mesh Mesh) { double sum = 0.0; foreach (HE_Face f in Mesh.Faces) { sum += Area(f); } return(sum); }
/// <summary> /// Calculates the mean edge length of the mesh /// </summary> /// <returns>The mean edge length of the mesh</returns> public static double MeanEdgeLength(HE_Mesh Mesh) { double sum = 0.0; foreach (HE_Edge e in Mesh.Edges) { sum += Length(e); } return(sum / Mesh.Edges.Count); }
/// <summary> /// Compute the total angle defect of the mesh. /// </summary> /// <param name="Mesh">Mesh to compute angle defect.</param> /// <returns>Returns the total angle defect as a scalar value.</returns> public static double TotalAngleDefect(HE_Mesh Mesh) { double totalDefect = 0.0; foreach (HE_Vertex v in Mesh.Vertices) { totalDefect += AngleDefect(v); } return(totalDefect); }
// container = cube, 8 vertices, 6 faces of 4 vertices each void buildContainer() { containerVertices = new float[][] { new float[] { S, 0, S }, new float[] { -S, 0, S }, new float[] { -S, 0, -S }, new float[] { S, 0, -S } }; // vertices need to be in a consistent order (clockwise, or counterclockwise around the face) containerFaces = new int[][] { new int[] { 0, 1, 2, 3 } }; container = new HE_Mesh(); container.buildMesh(containerVertices, containerFaces); }
/// <summary> /// Computes a geodesic on a mesh given a starting point and an initial direction. /// Returns true if successfull and false if something went wrong. /// </summary> public static bool StartDir(HE_MeshPoint meshPoint, Vector3d vector, HE_Mesh mesh, int maxIter, out List <Point3d> geodesic) { // Get initial face on the mesh HE_Face initialFace = mesh.Faces[meshPoint.FaceIndex]; // Start iteration // Create variables for current iteration step HE_Face thisFace = initialFace; Point3d thisPoint = new Point3d(); Vector3d thisDirection = vector; int iter = 0; List <Point3d> geodPoints = new List <Point3d>(); do { Ray ray = new Ray(thisPoint, thisDirection); // Find intersection between ray and boundary AR_Lib.Intersect3D.RayFacePerimeter(ray, thisFace, out Point3d nextPoint, out HE_HalfEdge halfEdge); // Intersection method should check for correct direction using sign of dot product // Add point to pointlist geodPoints.Add(nextPoint); // Walk to next face HE_Face nextFace = halfEdge.Twin.Face; // Flip vector to next face Vector3d perpVector = Vector3d.CrossProduct(thisDirection, HE_MeshGeometry.FaceNormal(thisFace)); Vector3d nextVector = Vector3d.CrossProduct(HE_MeshGeometry.FaceNormal(nextFace), perpVector); // Assign iteration variables to current thisPoint = nextPoint; thisFace = nextFace; thisDirection = nextVector; // Increase counter iter++; } while (iter < maxIter); // Assign outputs geodesic = geodPoints; return(true); }
public override void mousePressed() { PVector O = new PVector(random(-S, S), random(-S, S), random(-S, S)); Plane P = new Plane(O, new PVector(random(-1, 1), random(-1, 1), random(-1, 1))); List <HE_Mesh> newMeshes = new List <HE_Mesh> (); List <PVector> newCenters = new List <PVector> (); for (int i = 0; i < meshes.Count; i++) { HE_Mesh mesh = (HE_Mesh)meshes [i]; HE_Mesh mesh2 = mesh.get(); mesh.cutMesh(P, new PVector()); mesh2.cutMesh(P, new PVector(2 * O.x, 2 * O.y, 2 * O.z)); newMeshes.Add(mesh); newMeshes.Add(mesh2); PVector center = new PVector(); for (int j = 0; j < mesh.vertices.Count; j++) { HE_Vertex v = (HE_Vertex)mesh.vertices [j]; center.add(v); } center.div(mesh.vertices.Count); newCenters.Add(center); center = new PVector(); for (int j = 0; j < mesh2.vertices.Count; j++) { HE_Vertex v = (HE_Vertex)mesh2.vertices [j]; center.add(v); } center.div(mesh2.vertices.Count); newCenters.Add(center); } meshes = newMeshes; centers = newCenters; // drawMesh(); }
public static void TestHalfEdgeMesh(string path) { Console.WriteLine("---- TestHalfEdgeMesh() called ----"); OFFMeshData data; OFFResult result = OFFReader.ReadMeshFromFile(path, out data); Debug.WriteLine("OFFReader result: " + result + "\n"); HE_Mesh mesh = new HE_Mesh(data.vertices, data.faces); Debug.WriteLine(mesh); HE_MeshTopology top = new HE_MeshTopology(mesh); top.computeVertexAdjacency(); top.computeFaceAdjacency(); top.computeEdgeAdjacency(); //Debug.WriteLine(top.TopologyDictToString(top.FaceVertex)); Debug.WriteLine("isMesh? triangular: " + mesh.isTriangularMesh() + " quad: " + mesh.isQuadMesh() + " ngon: " + mesh.isNgonMesh()); OFFResult result2 = OFFWritter.WriteMeshToFile(mesh, "/Users/alan/Desktop/AR_GeometryLibrary/AR_TerminalApp/meshes/cubeOut.off"); Debug.WriteLine(result.ToString()); mesh.Faces[0].HalfEdge.Vertex.UserValues.Add("set1", 3); mesh.Faces[0].HalfEdge.Next.Vertex.UserValues.Add("set1", 4); mesh.Faces[0].HalfEdge.Next.Next.Vertex.UserValues.Add("set1", 3); Line levelLine; AR_Lib.Curve.LevelSets.getFaceLevel("set1", 3.5, mesh.Faces[0], out levelLine); Console.WriteLine("---- TestHalfEdgeMesh() ended ----"); }
/// <summary> /// Write a Half-Edge mesh to a .OFF file /// </summary> /// <param name="mesh">Half-edge mesh to export</param> /// <param name="filePath">Path to save the file to</param> /// <returns></returns> public static OFFResult WriteMeshToFile(HE_Mesh mesh, string filePath) { string[] offLines = new string[mesh.Vertices.Count + mesh.Faces.Count + 2]; string offHead = "OFF"; offLines[0] = offHead; string offCount = mesh.Vertices.Count + " " + mesh.Faces.Count + " 0"; offLines[1] = offCount; int count = 2; foreach (HE_Vertex vertex in mesh.Vertices) { string vText = vertex.X + " " + vertex.Y + " " + vertex.Z; offLines[count] = vText; count++; } foreach (HE_Face face in mesh.Faces) { if (!face.isBoundaryLoop()) { List <HE_Vertex> vertices = face.adjacentVertices(); string faceString = vertices.Count.ToString(); foreach (HE_Vertex v in face.adjacentVertices()) { faceString = faceString + " " + v.Index; } offLines[count] = faceString; count++; } } System.IO.File.WriteAllLines(filePath, offLines); return(OFFResult.OK); }
void drawMesh() { List <Triangle3D> triangles3D = new List <Triangle3D> (); for (int i = 0; i < meshes.Count; i++) { PVector center = (PVector)centers [i]; HE_Mesh mesh = (HE_Mesh)meshes [i]; /* * //mesh.drawEdges(); * foreach (HE_Edge e in mesh.edges) { * Vector3 p0 = e.halfEdge.vert.pos; * Vector3 p1 = e.halfEdge.pair.vert.pos; * Debug.DrawLine (p0 + center.pos * 0.2f, p1 + center.pos * 0.2f, Color.red); * } */ Triangle3D tri = mesh.draw(); triangles3D.Add(tri); } List <Vector3> vertices = new List <Vector3> (); List <int> triangles = new List <int> (); List <Vector2> uvs = new List <Vector2> (); int indexCount = 0; for (int i = 0; i < triangles3D.Count; i++) { Triangle3D tri = triangles3D [i]; PVector center = (PVector)centers [i]; for (int n = 0; n < tri.vertices.Count; n++) { HE_Vertex hV = tri.vertices [n]; vertices.Add(hV.pos + center.pos * 0.2f); triangles.Add(indexCount); uvs.Add(Vector2.zero); indexCount++; } } if (generateMesh == null) { generateMesh = new Mesh(); generateMesh.name = "generateMesh"; } generateMesh.Clear(false); generateMesh.vertices = vertices.ToArray(); generateMesh.triangles = triangles.ToArray(); generateMesh.uv = uvs.ToArray(); //generateMesh.SetIndices(triangles.ToArray(), MeshTopology.Triangles, 0); generateMesh.RecalculateNormals(); meshFilter.mesh = generateMesh; //Material tempmaterial = new Material(lineshader); //renderer.material = tempmaterial; }