/// <summary> /// Tests if a vertex is a direct neighbour of an other vertex. Only use this method if you know the incident half edges of the vertex. /// </summary> /// <param name="geometry">The geometry the vertex belongs to.</param> /// <param name="p">First vertex</param> /// <param name="q">Secound vertex</param> /// <param name="vertPStartHe">p incident half edge. </param> /// <param name="vertQStartHe">q incident half edge.</param> /// <returns></returns> public static bool IsVertexAdjacentToVertex(this Geometry geometry, int p, int q, HalfEdge vertPStartHe, HalfEdge vertQStartHe) { var nextHeP = geometry.GetHalfEdgeByHandle(vertPStartHe.NextHalfEdge); var nextHeQ = geometry.GetHalfEdgeByHandle(vertQStartHe.NextHalfEdge); return(nextHeP.OriginVertex == q || nextHeQ.OriginVertex == p); }
internal void ReplaceHalfEdge(HalfEdge halfEdge) { var key = halfEdge.Handle; DictHalfEdges[key] = halfEdge; }
/// <summary> /// Insets a Face with a given offset. The new, center Face has the same Handle as the original Face. /// </summary> /// <param name="geometry">The geometry on which to perform a face inset.</param> /// <param name="faceHandle">The Handle of the face, the new one will be inserted to.</param> /// <param name="insetOffset">The offset of the inset in percent. Use values between 0 and 1. A value of 0.5f means 50% of the original face remains.</param> /// <returns>Returns the geometry with edited faces.</returns> public static Geometry InsetFace(this Geometry geometry, int faceHandle, float insetOffset) { if (insetOffset >= 1) { throw new ArgumentException("insetOffset can not be greater or equal to 1."); } if (insetOffset <= 0) { throw new ArgumentException("insetOffset can not be smaller or equal to 0."); } var face = geometry.GetFaceByHandle(faceHandle); var allFaceVertices = geometry.GetFaceVertices(faceHandle).ToList(); var meanPos = GeometricOperations.GetVerticesMeanPos(allFaceVertices); //Dict stores countEdges; [0] = edge1.handle, [1] = edge2twin.handle, [2] = edge3.handle, [3] = vertex.Handle var edgeStorage = new Dictionary <int, int[]>(); var countEdges = 0; var start = geometry.GetHalfEdgeByHandle(face.OuterHalfEdge); var next = start; do { var nextEdge = next.NextHalfEdge; var currentVertex = geometry.GetVertexByHandle(next.OriginVertex); var currentPos = currentVertex.VertData.Pos; var newPos = (currentPos - meanPos) * insetOffset + meanPos; var newVertex = new Vertex(geometry.CreateVertHandleId(), newPos); var nextNext = geometry.GetHalfEdgeByHandle(next.NextHalfEdge); var edge1 = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var edge2Twin = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var edge2 = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var edge3 = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var newFace = new Face(geometry.CreateFaceHandleId()); //store info edgeStorage.Add(countEdges, new[] { edge1.Handle, edge2Twin.Handle, edge3.Handle, newVertex.Handle }); newVertex.IncidentHalfEdge = edge3.Handle; newFace.OuterHalfEdge = edge1.Handle; edge1.OriginVertex = nextNext.OriginVertex; edge3.OriginVertex = newVertex.Handle; edge2Twin.OriginVertex = newVertex.Handle; //twins edge2.TwinHalfEdge = edge2Twin.Handle; edge2Twin.TwinHalfEdge = edge2.Handle; //nexts edge1.NextHalfEdge = edge2.Handle; edge2.NextHalfEdge = edge3.Handle; edge3.NextHalfEdge = next.Handle; next.NextHalfEdge = edge1.Handle; //prevs edge1.PrevHalfEdge = next.Handle; edge2.PrevHalfEdge = edge1.Handle; edge3.PrevHalfEdge = edge2.Handle; next.PrevHalfEdge = edge3.Handle; //face edge1.IncidentFace = newFace.Handle; edge2.IncidentFace = newFace.Handle; edge3.IncidentFace = newFace.Handle; next.IncidentFace = newFace.Handle; edge2Twin.IncidentFace = face.Handle; newFace.FaceData.FaceNormal = face.FaceData.FaceNormal; //write changes geometry.DictVertices.Add(newVertex.Handle, newVertex); geometry.DictFaces.Add(newFace.Handle, newFace); geometry.DictHalfEdges.Add(edge1.Handle, edge1); geometry.DictHalfEdges.Add(edge2Twin.Handle, edge2Twin); geometry.DictHalfEdges.Add(edge2.Handle, edge2); geometry.DictHalfEdges.Add(edge3.Handle, edge3); geometry.ReplaceHalfEdge(next); countEdges++; next = geometry.GetHalfEdgeByHandle(nextEdge); } while (start != next); for (var i = 0; i < countEdges; i++) { var prevFace = i - 1; var nextFace = i + 1; var faceData = edgeStorage[i]; if (i == 0) { prevFace = countEdges - 1; } if (i == countEdges - 1) { nextFace = 0; face.OuterHalfEdge = faceData[1]; geometry.ReplaceFace(face); } var prevFaceData = edgeStorage[prevFace]; var nextFaceData = edgeStorage[nextFace]; var edge2Twin = geometry.GetHalfEdgeByHandle(faceData[1]); var edge3 = geometry.GetHalfEdgeByHandle(faceData[2]); var edge3Twin = geometry.GetHalfEdgeByHandle(prevFaceData[0]); var edge2 = geometry.GetHalfEdgeByHandle(edge2Twin.TwinHalfEdge); edge2Twin.PrevHalfEdge = prevFaceData[1]; edge2Twin.NextHalfEdge = nextFaceData[1]; edge2.OriginVertex = nextFaceData[3]; edge3Twin.TwinHalfEdge = edge3.Handle; edge3.TwinHalfEdge = edge3Twin.Handle; //write geometry.ReplaceHalfEdge(edge2Twin); geometry.ReplaceHalfEdge(edge2); geometry.ReplaceHalfEdge(edge3Twin); geometry.ReplaceHalfEdge(edge3); } return(geometry); }
internal static HalfEdge UpdateHalfEdgeOrigin(HalfEdge edge, int newVHandle) { edge.OriginVertex = newVHandle; return(edge); }
/// <summary> /// Inserts a new Vertex between two given existing Vertices. /// </summary> /// <param name="geometry">The Geometry to insert a Vertex.</param> /// <param name="p">Handle of Vertex one.</param> /// <param name="q">Handle of Vertex two.</param> /// <param name="pos">Position of the new Vertex</param> /// <returns>New Vertex Handle.</returns> public static int InsertVertex(this Geometry geometry, int p, int q, float3 pos) { var adjacentVertices = geometry.GetVertexAdjacentVertices(p).ToList(); for (var i = 0; i < adjacentVertices.Count; i++) { if (adjacentVertices[i].Handle == q) { break; } if (i == adjacentVertices.Count - 1) { throw new ArgumentException("Vertices with Handle q=" + q + " and p=" + p + " are not adjacent!"); } } var newVertex = new Vertex(geometry.CreateVertHandleId(), pos); //add two new Half Edges var newHalfEdge1 = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var newHalfEdge2 = new HalfEdge(geometry.CreateHalfEdgeHandleId()); //set origin to new Vertex newHalfEdge1.OriginVertex = newVertex.Handle; newHalfEdge2.OriginVertex = newVertex.Handle; newVertex.IncidentHalfEdge = newHalfEdge2.Handle; var vertexP = geometry.GetVertexByHandle(p); var vertexQ = geometry.GetVertexByHandle(q); //Find Half Edge between p and q var incomingEdges = geometry.GetVertexStartingHalfEdges(vertexP.Handle); var he1 = new HalfEdge(); var he2 = new HalfEdge(); foreach (var halfEdge in incomingEdges) { var twinEdge = geometry.GetHalfEdgeByHandle(halfEdge.TwinHalfEdge); if (twinEdge.OriginVertex != vertexQ.Handle) { continue; } he1 = halfEdge; he2 = twinEdge; } var next1 = geometry.GetHalfEdgeByHandle(he2.NextHalfEdge); var next2 = geometry.GetHalfEdgeByHandle(he1.NextHalfEdge); //change handles he1.TwinHalfEdge = newHalfEdge1.Handle; newHalfEdge1.TwinHalfEdge = he1.Handle; newHalfEdge1.NextHalfEdge = he2.NextHalfEdge; he2.NextHalfEdge = newHalfEdge1.Handle; newHalfEdge1.PrevHalfEdge = he2.Handle; next1.PrevHalfEdge = newHalfEdge1.Handle; he2.TwinHalfEdge = newHalfEdge2.Handle; newHalfEdge2.TwinHalfEdge = he2.Handle; newHalfEdge2.NextHalfEdge = he1.NextHalfEdge; he1.NextHalfEdge = newHalfEdge2.Handle; newHalfEdge2.PrevHalfEdge = he1.Handle; next2.PrevHalfEdge = newHalfEdge2.Handle; //reconnect faces newHalfEdge1.IncidentFace = he2.IncidentFace; newHalfEdge2.IncidentFace = he1.IncidentFace; //replace existing Edges geometry.ReplaceHalfEdge(he1); geometry.ReplaceHalfEdge(he2); geometry.ReplaceHalfEdge(next1); geometry.ReplaceHalfEdge(next2); //add to dict geometry.DictVertices.Add(newVertex.Handle, newVertex); geometry.DictHalfEdges.Add(newHalfEdge1.Handle, newHalfEdge1); geometry.DictHalfEdges.Add(newHalfEdge2.Handle, newHalfEdge2); return(newVertex.Handle); }
/// <summary> /// Inserts a pair of HalfEdges between two (non adjacent) vertices of a Face. /// </summary> /// <param name="geometry">The Geometry to insert a diagonal.</param> /// <param name="p">First Vertex handle.</param> /// <param name="q">Second Vertex handle.</param> /// <exception cref="Exception"></exception> public static void InsertDiagonal(this Geometry geometry, int p, int q) { var pStartHe = new HalfEdge(); var qStartHe = new HalfEdge(); var face = geometry.GetFaceToInsertDiag(p, q, ref pStartHe, ref qStartHe); if (geometry.IsVertexAdjacentToVertex(p, q, pStartHe, qStartHe)) { throw new ArgumentException("A diagonal can't be inserted between adjacent Vertices!"); } var newFromP = new HalfEdge(geometry.CreateHalfEdgeHandleId()); var newFromQ = new HalfEdge(geometry.CreateHalfEdgeHandleId()); newFromP.OriginVertex = p; newFromP.NextHalfEdge = qStartHe.Handle; newFromP.PrevHalfEdge = pStartHe.PrevHalfEdge; newFromP.IncidentFace = face.Handle; newFromQ.OriginVertex = q; newFromQ.NextHalfEdge = pStartHe.Handle; newFromQ.PrevHalfEdge = qStartHe.PrevHalfEdge; newFromQ.IncidentFace = face.Handle; newFromP.TwinHalfEdge = newFromQ.Handle; newFromQ.TwinHalfEdge = newFromP.Handle; geometry.DictHalfEdges.Add(newFromP.Handle, newFromP); geometry.DictHalfEdges.Add(newFromQ.Handle, newFromQ); //Assign new successor to previous HalfEdges from p and q & assign new predecessor for qStartHe and pStartHe. var prevHeP = geometry.GetHalfEdgeByHandle(pStartHe.PrevHalfEdge); var prevHeQ = geometry.GetHalfEdgeByHandle(qStartHe.PrevHalfEdge); var prevHePUpdate = geometry.DictHalfEdges[prevHeP.Handle]; prevHePUpdate.NextHalfEdge = newFromP.Handle; geometry.DictHalfEdges[prevHeP.Handle] = prevHePUpdate; var prevHeQUpdate = geometry.DictHalfEdges[prevHeQ.Handle]; prevHeQUpdate.NextHalfEdge = newFromQ.Handle; geometry.DictHalfEdges[prevHeQ.Handle] = prevHeQUpdate; var nextHePUpdate = geometry.DictHalfEdges[pStartHe.Handle]; nextHePUpdate.PrevHalfEdge = newFromQ.Handle; geometry.DictHalfEdges[pStartHe.Handle] = nextHePUpdate; var nextHeQUpdate = geometry.DictHalfEdges[qStartHe.Handle]; nextHeQUpdate.PrevHalfEdge = newFromP.Handle; geometry.DictHalfEdges[qStartHe.Handle] = nextHeQUpdate; var holes = geometry.GetHoles(face); if (holes.Count != 0 && IsNewEdgeToHole(holes, p, q, face)) { return; } var newFace = new Face(geometry.CreateFaceHandleId(), newFromQ.Handle); //The face normal of the newFace equals the normal of the original Face because adding a diagonal does not change the face vertices position. var newFaceData = newFace.FaceData; newFaceData.FaceNormal = face.FaceData.FaceNormal; newFace.FaceData = newFaceData; geometry.DictFaces.Add(newFace.Handle, newFace); //Assign the handle of the new Face to its HalfEdges. geometry.AssignFaceHandle(newFace.OuterHalfEdge, newFace); //Set Face.OuterHalfEdge to newFromP - old OuterHalfEdge can be part of new Face now! var currentFace = face; currentFace.OuterHalfEdge = newFromP.Handle; face = currentFace; geometry.DictFaces[face.Handle] = face; }
/// <summary> /// Creates and returns a UV-Sphere as a DCEL with the specified dimensions centered in the worlds coordinate system. /// </summary> /// <param name="radius">Radius of the sphere.</param> /// <param name="horizontalResolution">Lines of latitude, smallest value is 3.</param> /// <param name="verticalResolution">Lines of longitude, smallest value is 3.</param> /// <returns>A UV-Sphere centered in the world coordinate system as a DCEL.</returns> public static Geometry CreateSpehreGeometry(float radius, int horizontalResolution, int verticalResolution) { //check input if (radius <= 0) { throw new ArgumentException("Radius can not be <= 0"); } if (horizontalResolution <= 3) { horizontalResolution = 3; } if (verticalResolution <= 2) { verticalResolution = 2; } var sphere = new Geometry(); var northPole = new Vertex(sphere.CreateVertHandleId(), new float3(0, radius, 0)); var southPole = new Vertex(sphere.CreateVertHandleId(), new float3(0, -radius, 0)); var horizontalAngleStep = System.Math.PI * 2 / horizontalResolution; // s var verrticalAngleStep = System.Math.PI / verticalResolution; // t var currentLatitudeVerticesHandles = new int[horizontalResolution]; var lastLaitudeVerticesHandles = new int[horizontalResolution]; //stores last vertices to connect them later with the next latidute vertices for (var i = 1; i < verticalResolution + 1; i++) { //create all vertices if (i < verticalResolution) { for (var j = 0; j < horizontalResolution; j++) { //create all Vertices of current latitude var xPos = (float)(radius * System.Math.Sin(horizontalAngleStep * j) * System.Math.Sin(verrticalAngleStep * i)); var yPos = (float)(radius * System.Math.Cos(verrticalAngleStep * (i))); var zPos = (float)(radius * System.Math.Cos(horizontalAngleStep * j) * System.Math.Sin(verrticalAngleStep * i)); var circleVertex = new Vertex(sphere.CreateVertHandleId(), new float3(xPos, yPos, zPos)); sphere.DictVertices.Add(circleVertex.Handle, circleVertex); currentLatitudeVerticesHandles[j] = circleVertex.Handle; } } //create faces var topHeHandles = new int[horizontalResolution]; for (var j = 0; j < horizontalResolution; j++) { // bottom triangles of sphere if (i == verticalResolution) { var bottomTriangle = new Face(sphere.CreateFaceHandleId()); var h1 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h2 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h3 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); topHeHandles[j] = h1.Handle; h1.NextHalfEdge = h2.Handle; h2.NextHalfEdge = h3.Handle; h3.NextHalfEdge = h1.Handle; h1.PrevHalfEdge = h3.Handle; h2.PrevHalfEdge = h1.Handle; h3.PrevHalfEdge = h2.Handle; h1.IncidentFace = bottomTriangle.Handle; h2.IncidentFace = bottomTriangle.Handle; h3.IncidentFace = bottomTriangle.Handle; h1.OriginVertex = currentLatitudeVerticesHandles[j]; h2.OriginVertex = j == horizontalResolution - 1 ? currentLatitudeVerticesHandles[0] : currentLatitudeVerticesHandles[j + 1]; h3.OriginVertex = southPole.Handle; bottomTriangle.OuterHalfEdge = h1.Handle; southPole.IncidentHalfEdge = h3.Handle; //write changes sphere.DictHalfEdges.Add(h1.Handle, h1); sphere.DictHalfEdges.Add(h2.Handle, h2); sphere.DictHalfEdges.Add(h3.Handle, h3); sphere.DictFaces.Add(bottomTriangle.Handle, bottomTriangle); } // top triangles of sphere else if (i == 1) { var topTriangle = new Face(sphere.CreateFaceHandleId()); var h1 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h2 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h3 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); topHeHandles[j] = h1.Handle; h1.NextHalfEdge = h2.Handle; h2.NextHalfEdge = h3.Handle; h3.NextHalfEdge = h1.Handle; h1.PrevHalfEdge = h3.Handle; h2.PrevHalfEdge = h1.Handle; h3.PrevHalfEdge = h2.Handle; h1.IncidentFace = topTriangle.Handle; h2.IncidentFace = topTriangle.Handle; h3.IncidentFace = topTriangle.Handle; h1.OriginVertex = j == horizontalResolution - 1 ? currentLatitudeVerticesHandles[0] : currentLatitudeVerticesHandles[j + 1]; h2.OriginVertex = currentLatitudeVerticesHandles[j]; h3.OriginVertex = northPole.Handle; topTriangle.OuterHalfEdge = h1.Handle; var currentVertex = sphere.GetVertexByHandle(currentLatitudeVerticesHandles[j]); currentVertex.IncidentHalfEdge = h2.Handle; northPole.IncidentHalfEdge = h3.Handle; //write changes sphere.DictHalfEdges.Add(h1.Handle, h1); sphere.DictHalfEdges.Add(h2.Handle, h2); sphere.DictHalfEdges.Add(h3.Handle, h3); sphere.DictFaces.Add(topTriangle.Handle, topTriangle); sphere.ReplaceVertex(currentVertex); } // middle quads of sphere else { var quad = new Face(sphere.CreateFaceHandleId()); var h1 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h2 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h3 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); var h4 = new HalfEdge(sphere.CreateHalfEdgeHandleId()); topHeHandles[j] = h1.Handle; h1.NextHalfEdge = h2.Handle; h2.NextHalfEdge = h3.Handle; h3.NextHalfEdge = h4.Handle; h4.NextHalfEdge = h1.Handle; h1.PrevHalfEdge = h4.Handle; h2.PrevHalfEdge = h1.Handle; h3.PrevHalfEdge = h2.Handle; h4.PrevHalfEdge = h3.Handle; h1.IncidentFace = quad.Handle; h2.IncidentFace = quad.Handle; h3.IncidentFace = quad.Handle; h4.IncidentFace = quad.Handle; quad.OuterHalfEdge = h1.Handle; h4.OriginVertex = currentLatitudeVerticesHandles[j]; h3.OriginVertex = j == horizontalResolution - 1 ? currentLatitudeVerticesHandles[0] : currentLatitudeVerticesHandles[j + 1]; h2.OriginVertex = j == horizontalResolution - 1 ? lastLaitudeVerticesHandles[0] : lastLaitudeVerticesHandles[j + 1]; h1.OriginVertex = lastLaitudeVerticesHandles[j]; var currentVertex = sphere.GetVertexByHandle(currentLatitudeVerticesHandles[j]); currentVertex.IncidentHalfEdge = h4.Handle; //write changes sphere.DictFaces.Add(quad.Handle, quad); sphere.DictHalfEdges.Add(h1.Handle, h1); sphere.DictHalfEdges.Add(h2.Handle, h2); sphere.DictHalfEdges.Add(h3.Handle, h3); sphere.DictHalfEdges.Add(h4.Handle, h4); sphere.ReplaceVertex(currentVertex); } } //set twins for (int j = 0; j < horizontalResolution; j++) { //set twins of adjacent triangles bottom if (i == 1) { int nextH1Index; nextH1Index = j == 0 ? horizontalResolution - 1 : j - 1; var h1 = sphere.GetHalfEdgeByHandle(topHeHandles[j]); var h2 = sphere.GetHalfEdgeByHandle(h1.NextHalfEdge); var nextH1 = sphere.GetHalfEdgeByHandle(topHeHandles[nextH1Index]); var nextH3 = sphere.GetHalfEdgeByHandle(nextH1.PrevHalfEdge); nextH3.TwinHalfEdge = h2.Handle; h2.TwinHalfEdge = nextH3.Handle; sphere.ReplaceHalfEdge(nextH3); sphere.ReplaceHalfEdge(h2); } else if (i == verticalResolution) { int nextH1Index; nextH1Index = j == 0 ? horizontalResolution - 1 : j - 1; var h1 = sphere.GetHalfEdgeByHandle(topHeHandles[j]); var h3 = sphere.GetHalfEdgeByHandle(h1.PrevHalfEdge); var nextH1 = sphere.GetHalfEdgeByHandle(topHeHandles[nextH1Index]); var nextH2 = sphere.GetHalfEdgeByHandle(nextH1.NextHalfEdge); nextH2.TwinHalfEdge = h3.Handle; h3.TwinHalfEdge = nextH2.Handle; sphere.ReplaceHalfEdge(nextH2); sphere.ReplaceHalfEdge(h3); } else //set twins of adjacent quads { var h1 = sphere.GetHalfEdgeByHandle(topHeHandles[j]); var h4 = sphere.GetHalfEdgeByHandle(h1.PrevHalfEdge); int nextH1Index; nextH1Index = j == 0 ? horizontalResolution - 1 : j - 1; var nextH1 = sphere.GetHalfEdgeByHandle(topHeHandles[nextH1Index]); var nextH2 = sphere.GetHalfEdgeByHandle(nextH1.NextHalfEdge); nextH2.TwinHalfEdge = h4.Handle; h4.TwinHalfEdge = nextH2.Handle; sphere.ReplaceHalfEdge(nextH2); sphere.ReplaceHalfEdge(h4); } //set twin of face on top if (i > 1) { var h1 = sphere.GetHalfEdgeByHandle(topHeHandles[j]); var lastVertex = sphere.GetVertexByHandle(lastLaitudeVerticesHandles[j]); var topH1 = sphere.GetHalfEdgeByHandle(lastVertex.IncidentHalfEdge); while (true) { if (topH1.TwinHalfEdge == 0) { break; } topH1 = sphere.GetHalfEdgeByHandle(topH1.NextHalfEdge); } topH1.TwinHalfEdge = h1.Handle; h1.TwinHalfEdge = topH1.Handle; sphere.ReplaceHalfEdge(h1); sphere.ReplaceHalfEdge(topH1); } } Array.Copy(currentLatitudeVerticesHandles, lastLaitudeVerticesHandles, currentLatitudeVerticesHandles.Length); } sphere.DictVertices.Add(northPole.Handle, northPole); sphere.DictVertices.Add(southPole.Handle, southPole); //calculate normals var allFaces = sphere.GetAllFaces().ToList(); foreach (var face in allFaces) { sphere.SetFaceNormal(sphere.GetFaceVertices(face.Handle).ToList(), face); } return(sphere); }
/// <summary> /// Creates and returns a Pyramid as a DCEL with the specified dimensions centered in the worlds coordinate system. /// </summary> /// <param name="dimensionX">Width of the Pyramid in X-dimension</param> /// <param name="dimensionY">Height of the Pyramid in Y-dimension.</param> /// <param name="dimensionZ">Depth of the Pyramid in Z-dimension.</param> /// <returns></returns> public static Geometry CreatePyramidGeometry(float dimensionX, float dimensionY, float dimensionZ) { //check input if (dimensionX <= 0 || dimensionY <= 0 || dimensionZ <= 0) { throw new ArgumentException("The dimension values can not be <= 0"); } var xPos = dimensionX / 2.0f; var yPos = dimensionY / 2.0f; var zPos = dimensionZ / 2.0f; var pyramid = new Geometry(); var positions = new float3[5]; //stores all Vertices positions positions[0] = new float3(-xPos, -yPos, -zPos); positions[1] = new float3(xPos, -yPos, -zPos); positions[2] = new float3(xPos, -yPos, zPos); positions[3] = new float3(-xPos, -yPos, zPos); positions[4] = new float3(0, yPos, 0); var baseFace = new Face(6) { OuterHalfEdge = 4 }; //create nad add vertices for (var i = 0; i < 5; i++) { Vertex current = new Vertex(pyramid.CreateVertHandleId(), positions[i]); if (i < 4) { current.IncidentHalfEdge = i * 4 + 1; } if (i == 4) { current.IncidentHalfEdge = 3; } pyramid.DictVertices.Add(current.Handle, current); } //create add Edges and Faces for (var i = 0; i < 4; i++) { var h1 = new HalfEdge(i * 4 + 1); var h2 = new HalfEdge(i * 4 + 2); var h3 = new HalfEdge(i * 4 + 3); var h4 = new HalfEdge(i * 4 + 4); var sideFace = new Face(i + 2) { OuterHalfEdge = h1.Handle }; h1.IncidentFace = sideFace.Handle; h2.IncidentFace = sideFace.Handle; h3.IncidentFace = sideFace.Handle; h4.IncidentFace = baseFace.Handle; h1.NextHalfEdge = h2.Handle; h2.NextHalfEdge = h3.Handle; h3.NextHalfEdge = h1.Handle; h1.PrevHalfEdge = h3.Handle; h2.PrevHalfEdge = h1.Handle; h3.PrevHalfEdge = h2.Handle; h3.OriginVertex = pyramid.DictVertices[5].Handle; h1.TwinHalfEdge = h4.Handle; h4.TwinHalfEdge = h1.Handle; if (i < 3) { h4.PrevHalfEdge = (i + 1) * 4 + 4; h2.TwinHalfEdge = (i + 1) * 4 + 3; h1.OriginVertex = pyramid.DictVertices[i + 1].Handle; h2.OriginVertex = pyramid.DictVertices[i + 2].Handle; h4.OriginVertex = pyramid.DictVertices[i + 2].Handle; } else { h4.PrevHalfEdge = 4; h2.TwinHalfEdge = 3; h1.OriginVertex = pyramid.DictVertices[i + 1].Handle; h2.OriginVertex = pyramid.DictVertices[1].Handle; h4.OriginVertex = pyramid.DictVertices[1].Handle; } if (i > 0) { h3.TwinHalfEdge = (i - 1) * 4 + 2; h4.NextHalfEdge = (i - 1) * 4 + 4; } else { h3.TwinHalfEdge = 3 * 4 + 2; h4.NextHalfEdge = 3 * 4 + 4; } //add pyramid.DictHalfEdges.Add(h1.Handle, h1); pyramid.DictHalfEdges.Add(h2.Handle, h2); pyramid.DictHalfEdges.Add(h3.Handle, h3); pyramid.DictHalfEdges.Add(h4.Handle, h4); pyramid.DictFaces.Add(sideFace.Handle, sideFace); } pyramid.DictFaces.Add(baseFace.Handle, baseFace); pyramid.SetHighestHandles(); var allFaces = pyramid.GetAllFaces().ToList(); foreach (var face in allFaces) { var faceVertices = pyramid.GetFaceVertices(face.Handle).ToList(); pyramid.SetFaceNormal(faceVertices, face); } return(pyramid); }
/// <summary> /// Creates and returns a cone with the given dimensions. /// </summary> /// <param name="baseRadius">The radiaus of the base circle.</param> /// <param name="dimensionY">The height of the cone.</param> /// <param name="sliceCount">The horizontal resulotion of the base circle. Min value is 3. For a basic cone 15.</param> /// <returns></returns> public static Geometry CreateConeGeometry(float baseRadius, float dimensionY, int sliceCount) { //check input if (sliceCount < 3) { sliceCount = 3; } if (baseRadius <= 0 || dimensionY <= 0) { throw new ArgumentException("You can not input paramaters <= 0"); } var cone = new Geometry(); var northPole = new Vertex(cone.CreateVertHandleId(), new float3(0, dimensionY / 2, 0)); var southPole = new Vertex(cone.CreateVertHandleId(), new float3(0, -dimensionY / 2, 0)); var angleStep = System.Math.PI * 2 / sliceCount; var yPos = -dimensionY / 2.0f; int[] firstHandles = null; //stores the handles of the first slice to connect it later with the last slice var lastH3 = new HalfEdge(); var lastH2 = new HalfEdge(); var lastVertex = southPole; for (var i = 1; i < sliceCount + 1; i++) { var x = (float)System.Math.Cos(angleStep * i) * baseRadius; var z = (float)System.Math.Sin(angleStep * i) * baseRadius; var tempVertex = new Vertex(cone.CreateVertHandleId(), new float3(x, yPos, z)); //south to temp var h1 = new HalfEdge(cone.CreateHalfEdgeHandleId()); var h2 = new HalfEdge(cone.CreateHalfEdgeHandleId()); //twin of h1 tempVertex.IncidentHalfEdge = h2.Handle; h1.OriginVertex = southPole.Handle; h2.OriginVertex = tempVertex.Handle; h1.TwinHalfEdge = h2.Handle; h2.TwinHalfEdge = h1.Handle; //temp to north var h3 = new HalfEdge(cone.CreateHalfEdgeHandleId()); var h4 = new HalfEdge(cone.CreateHalfEdgeHandleId()); northPole.IncidentHalfEdge = h3.Handle; southPole.IncidentHalfEdge = h1.Handle; h3.OriginVertex = northPole.Handle; h4.OriginVertex = tempVertex.Handle; h3.TwinHalfEdge = h4.Handle; h4.TwinHalfEdge = h3.Handle; if (lastVertex == southPole) { firstHandles = new[] { tempVertex.Handle, h1.Handle, h4.Handle }; lastH3 = h3; lastH2 = h2; cone.DictVertices.Add(tempVertex.Handle, tempVertex); cone.DictHalfEdges.Add(h1.Handle, h1); cone.DictHalfEdges.Add(h2.Handle, h2); cone.DictHalfEdges.Add(h3.Handle, h3); cone.DictHalfEdges.Add(h4.Handle, h4); lastVertex = tempVertex; continue; } //temp to last var h5 = new HalfEdge(cone.CreateHalfEdgeHandleId()); var h6 = new HalfEdge(cone.CreateHalfEdgeHandleId()); h5.OriginVertex = lastVertex.Handle; h6.OriginVertex = tempVertex.Handle; h5.TwinHalfEdge = h6.Handle; h6.TwinHalfEdge = h5.Handle; //create top triangles south-temp-last var triangle1 = new Face(cone.CreateFaceHandleId()); h5.NextHalfEdge = h4.Handle; triangle1.OuterHalfEdge = h5.Handle; h4.NextHalfEdge = lastH3.Handle; lastH3.NextHalfEdge = h5.Handle; h5.IncidentFace = triangle1.Handle; h4.IncidentFace = triangle1.Handle; lastH3.IncidentFace = triangle1.Handle; h5.PrevHalfEdge = lastH3.Handle; lastH3.PrevHalfEdge = h4.Handle; h4.PrevHalfEdge = h5.Handle; //north-last-temp var triangle2 = new Face(cone.CreateFaceHandleId()); h6.NextHalfEdge = lastH2.Handle; triangle2.OuterHalfEdge = h6.Handle; lastH2.NextHalfEdge = h1.Handle; h1.NextHalfEdge = h6.Handle; h6.IncidentFace = triangle2.Handle; lastH2.IncidentFace = triangle2.Handle; h1.IncidentFace = triangle2.Handle; h6.PrevHalfEdge = h1.Handle; h1.PrevHalfEdge = lastH2.Handle; lastH2.PrevHalfEdge = h6.Handle; //write cone.DictVertices.Add(tempVertex.Handle, tempVertex); cone.DictHalfEdges.Add(h1.Handle, h1); cone.DictHalfEdges.Add(h2.Handle, h2); cone.DictHalfEdges.Add(h3.Handle, h3); cone.DictHalfEdges.Add(h4.Handle, h4); cone.DictHalfEdges.Add(h5.Handle, h5); cone.DictHalfEdges.Add(h6.Handle, h6); cone.ReplaceHalfEdge(lastH2); cone.ReplaceHalfEdge(lastH3); cone.DictFaces.Add(triangle1.Handle, triangle1); cone.DictFaces.Add(triangle2.Handle, triangle2); lastH2 = h2; lastH3 = h3; lastVertex = tempVertex; } //add south and northpole cone.DictVertices.Add(southPole.Handle, southPole); cone.DictVertices.Add(northPole.Handle, northPole); //create last 2 traingles var firstVertex = cone.GetVertexByHandle(firstHandles[0]); var firtstH1 = cone.GetHalfEdgeByHandle(firstHandles[1]); var firstH4 = cone.GetHalfEdgeByHandle(firstHandles[2]); var lastH5 = new HalfEdge(cone.CreateHalfEdgeHandleId()); var lastH6 = new HalfEdge(cone.CreateHalfEdgeHandleId()); lastH5.OriginVertex = lastVertex.Handle; lastH6.OriginVertex = firstVertex.Handle; lastH5.TwinHalfEdge = lastH6.Handle; lastH6.TwinHalfEdge = lastH5.Handle; //create to triangles south-temp-last, north-last-temp var triangleL1 = new Face(cone.CreateFaceHandleId()) { OuterHalfEdge = lastH5.Handle }; lastH5.NextHalfEdge = firstH4.Handle; firstH4.NextHalfEdge = lastH3.Handle; lastH3.NextHalfEdge = lastH5.Handle; lastH5.IncidentFace = triangleL1.Handle; firstH4.IncidentFace = triangleL1.Handle; lastH3.IncidentFace = triangleL1.Handle; lastH5.PrevHalfEdge = lastH3.Handle; lastH3.PrevHalfEdge = firstH4.Handle; firstH4.PrevHalfEdge = lastH5.Handle; var triangleL2 = new Face(cone.CreateFaceHandleId()) { OuterHalfEdge = lastH6.Handle }; lastH6.NextHalfEdge = lastH2.Handle; lastH2.NextHalfEdge = firtstH1.Handle; firtstH1.NextHalfEdge = lastH6.Handle; lastH6.IncidentFace = triangleL2.Handle; lastH2.IncidentFace = triangleL2.Handle; firtstH1.IncidentFace = triangleL2.Handle; lastH6.PrevHalfEdge = firtstH1.Handle; firtstH1.PrevHalfEdge = lastH2.Handle; lastH2.PrevHalfEdge = lastH6.Handle; //write cone.ReplaceHalfEdge(firtstH1); cone.DictHalfEdges.Add(lastH5.Handle, lastH5); cone.DictHalfEdges.Add(lastH6.Handle, lastH6); cone.ReplaceHalfEdge(lastH2); cone.ReplaceHalfEdge(lastH3); cone.ReplaceHalfEdge(firstH4); cone.DictFaces.Add(triangleL1.Handle, triangleL1); cone.DictFaces.Add(triangleL2.Handle, triangleL2); //face normals var allFaces = cone.GetAllFaces().ToList(); foreach (var face in allFaces) { cone.SetFaceNormal(cone.GetFaceVertices(face.Handle).ToList(), face); } return(cone); }