Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        private static IEnumerable <Vertex> GetLeftChain(IList <Vertex> sortedVerts, Face face)
        {
            var heHandle   = new int();
            var endOfChain = sortedVerts.Last();

            var startingAtFirstV = _geometry.GetVertexStartingHalfEdges(sortedVerts[0].Handle).ToList();

            if (startingAtFirstV.Count > 1)
            {
                foreach (var heh in startingAtFirstV)
                {
                    var he = heh;
                    if (he.IncidentFace == face.Handle)
                    {
                        heHandle = heh.Handle;
                    }
                }
            }
            else
            {
                heHandle = sortedVerts[0].IncidentHalfEdge;
            }

            do
            {
                var halfEdge = _geometry.GetHalfEdgeByHandle(heHandle);
                yield return(_geometry.GetVertexByHandle(halfEdge.OriginVertex));

                heHandle = halfEdge.NextHalfEdge;
            } while (_geometry.GetHalfEdgeByHandle(heHandle).OriginVertex != endOfChain.Handle);
        }
Exemplo n.º 3
0
        private static void AssignFaceHandle(this Geometry geometry, int heHandle, Face newFace)
        {
            var oldFaceHandle = geometry.GetHalfEdgeByHandle(heHandle).IncidentFace;
            var currentHe     = geometry.GetHalfEdgeByHandle(heHandle);

            do
            {
                currentHe.IncidentFace = newFace.Handle;

                geometry.DictHalfEdges[currentHe.Handle] = currentHe;

                currentHe = geometry.GetHalfEdgeByHandle(currentHe.NextHalfEdge);
            } while (currentHe.Handle != heHandle);

            //Assign newFace to possible holes in the "old" face.
            var oldFace = geometry.GetFaceByHandle(oldFaceHandle);

            if (oldFace.InnerHalfEdges.Count == 0)
            {
                return;
            }

            var inner = new List <int>();

            inner.AddRange(oldFace.InnerHalfEdges);

            foreach (var heh in inner)
            {
                var origin = geometry.GetHalfEdgeByHandle(heh).OriginVertex;

                if (!geometry.IsPointInPolygon(newFace, geometry.GetVertexByHandle(origin)))
                {
                    continue;
                }

                oldFace.InnerHalfEdges.Remove(heh);
                newFace.InnerHalfEdges.Add(heh);

                var curHe = geometry.GetHalfEdgeByHandle(heh);
                do
                {
                    curHe.IncidentFace = newFace.Handle;

                    geometry.DictHalfEdges[curHe.Handle] = curHe;

                    curHe = geometry.GetHalfEdgeByHandle(curHe.NextHalfEdge);
                } while (curHe.Handle != heh);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Returns the half edges from a source collection of half edges - with opposite direction.
        /// </summary>
        /// <param name="geometry"></param>
        /// <param name="originHEdges"></param>
        /// <returns></returns>
        public static IEnumerable <HalfEdge> GetHalfEdgesWChangedWinding(this Geometry geometry, IEnumerable <HalfEdge> originHEdges)
        {
            foreach (var hEdge in originHEdges)
            {
                var he   = hEdge;
                var next = he.PrevHalfEdge;
                var prev = he.NextHalfEdge;

                he.NextHalfEdge = next;
                he.PrevHalfEdge = prev;

                var newOrigin = geometry.GetHalfEdgeByHandle(he.PrevHalfEdge).OriginVertex;
                he.OriginVertex = newOrigin;

                yield return(he);

                var vertToUpdate = geometry.DictVertices[newOrigin];
                vertToUpdate.IncidentHalfEdge    = he.Handle;
                geometry.DictVertices[newOrigin] = vertToUpdate;
            }
        }
Exemplo n.º 5
0
        private static Dictionary <int, Vertex> GetEdgeVertices(Geometry geometry, Dictionary <int, Vertex> faceVertices)
        {
            var allEdges = geometry.GetAllHalfEdges();

            var doneHe = new int[allEdges.Count() + 1];

            var allEdgeVertices = new Dictionary <int, Vertex>();

            foreach (var edge in allEdges)
            {
                if (doneHe[edge.Handle] == edge.TwinHalfEdge)
                {
                    continue;
                }
                var face1 = edge.IncidentFace;
                var twin  = geometry.GetHalfEdgeByHandle(edge.TwinHalfEdge);
                var face2 = twin.IncidentFace;

                var vertex1 = geometry.GetVertexByHandle(edge.OriginVertex);
                var vertex2 = geometry.GetVertexByHandle(twin.OriginVertex);

                var cVertex1 = faceVertices[face1];
                var cVertex2 = faceVertices[face2];

                var temp = new List <Vertex> {
                    vertex1, vertex2, cVertex1, cVertex2
                };

                var finalVertex = new Vertex(edge.Handle, GeometricOperations.GetVerticesMeanPos(temp))
                {
                    IncidentHalfEdge = edge.Handle
                };

                allEdgeVertices.Add(edge.Handle, finalVertex);
                doneHe[edge.TwinHalfEdge] = edge.Handle;
            }
            return(allEdgeVertices);
        }
Exemplo n.º 6
0
        private static Geometry ExtrudeFaceByHandle(Geometry geometry, int faceHandle, float offset, float3 extrusionVector)
        {
            var face = geometry.GetFaceByHandle(faceHandle);

            //get HE of Face
            var start = geometry.GetHalfEdgeByHandle(face.OuterHalfEdge);
            var next  = start;

            var vertexIncHe     = new Dictionary <int, List <HalfEdge> >();
            var allFaceVertices = geometry.GetFaceVertices(faceHandle);

            foreach (var vertex in allFaceVertices)
            {
                vertexIncHe.Add(vertex.Handle, geometry.GetVertexStartingHalfEdges(vertex.Handle).ToList());
            }
            var allH2NEdges = new List <HalfEdge>();

            do
            {
                var nextOriginV = geometry.GetVertexByHandle(next.OriginVertex);
                var newVertex   = new Vertex(geometry.CreateVertHandleId(), nextOriginV.VertData.Pos);

                var twinEdge     = geometry.GetHalfEdgeByHandle(next.TwinHalfEdge);
                var prevEdge     = geometry.GetHalfEdgeByHandle(next.PrevHalfEdge);
                var prevTwinEdge = geometry.GetHalfEdgeByHandle(prevEdge.TwinHalfEdge);

                nextOriginV.VertData.Pos = nextOriginV.VertData.Pos + extrusionVector * offset;

                var h4  = new HalfEdge(geometry.CreateHalfEdgeHandleId());
                var h2n = new HalfEdge(geometry.CreateHalfEdgeHandleId());

                var h1 = new HalfEdge(geometry.CreateHalfEdgeHandleId());

                var currentList = vertexIncHe[nextOriginV.Handle];
                foreach (var halfEdge in currentList)
                {
                    if (halfEdge == next)
                    {
                        continue;
                    }
                    var edge = GeomEditing.UpdateHalfEdgeOrigin(halfEdge, newVertex.Handle);
                    geometry.ReplaceHalfEdge(edge);
                }

                nextOriginV.IncidentHalfEdge = next.Handle;

                h4.OriginVertex  = nextOriginV.Handle;
                h2n.OriginVertex = newVertex.Handle;
                h1.OriginVertex  = newVertex.Handle;

                h4.TwinHalfEdge  = h2n.Handle;
                h2n.TwinHalfEdge = h4.Handle;

                h4.NextHalfEdge = h1.Handle;
                h1.PrevHalfEdge = h4.Handle;

                h1.TwinHalfEdge       = next.TwinHalfEdge;
                twinEdge.TwinHalfEdge = h1.Handle;

                prevTwinEdge.OriginVertex = newVertex.Handle;

                newVertex.IncidentHalfEdge = h2n.Handle;

                geometry.ReplaceHalfEdge(twinEdge);
                geometry.ReplaceHalfEdge(prevTwinEdge);
                geometry.ReplaceVertex(nextOriginV);
                geometry.DictVertices.Add(newVertex.Handle, newVertex);
                geometry.DictHalfEdges.Add(h4.Handle, h4);
                geometry.DictHalfEdges.Add(h1.Handle, h1);
                geometry.DictHalfEdges.Add(h2n.Handle, h2n);

                allH2NEdges.Add(h2n);

                next = geometry.GetHalfEdgeByHandle(next.NextHalfEdge);
            } while (start != next);

            start = geometry.GetHalfEdgeByHandle(face.OuterHalfEdge);
            next  = start;
            do
            {
                var newFace = new Face(geometry.CreateFaceHandleId());

                var twinEdge = geometry.GetHalfEdgeByHandle(next.TwinHalfEdge);

                var h1 = geometry.GetHalfEdgeByHandle(twinEdge.TwinHalfEdge);
                var h2 = allH2NEdges.First(n => n.OriginVertex == twinEdge.OriginVertex);
                var h3 = new HalfEdge(geometry.CreateHalfEdgeHandleId());
                var h4 = geometry.GetHalfEdgeByHandle(h1.PrevHalfEdge);

                //set Face
                h1.IncidentFace = newFace.Handle;
                h2.IncidentFace = newFace.Handle;
                h3.IncidentFace = newFace.Handle;
                h4.IncidentFace = newFace.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;

                h3.TwinHalfEdge       = next.Handle;
                h3.OriginVertex       = geometry.GetHalfEdgeByHandle(next.NextHalfEdge).OriginVertex;
                next.TwinHalfEdge     = h3.Handle;
                newFace.OuterHalfEdge = h1.Handle;

                //write all changes
                geometry.ReplaceHalfEdge(h1);
                geometry.ReplaceHalfEdge(h2);
                geometry.ReplaceHalfEdge(h4);
                geometry.ReplaceHalfEdge(next);

                geometry.DictHalfEdges.Add(h3.Handle, h3);
                geometry.DictFaces.Add(newFace.Handle, newFace);

                newFace.FaceData.FaceNormal = GeometricOperations.CalculateFaceNormal(geometry.GetFaceVertices(newFace.Handle).ToList());

                geometry.ReplaceFace(newFace);

                next = geometry.GetHalfEdgeByHandle(next.NextHalfEdge);
            } while (start != next);

            return(geometry);
        }
Exemplo n.º 7
0
        private static void CreateSidefaces(Geometry geometry)
        {
            var unboundedFace = geometry.GetFaceByHandle(1); //The unbounded face is always added first - therefore it will always have 1 as handle.

            var frontLoopsStartHalfEdges = unboundedFace.InnerHalfEdges.Take(unboundedFace.InnerHalfEdges.Count / 2).ToList();
            var backLoopsStartHalfEdges  = unboundedFace.InnerHalfEdges.Skip(unboundedFace.InnerHalfEdges.Count / 2).ToList();

            for (var i = 0; i < frontLoopsStartHalfEdges.Count; i++)
            {
                var frontEdgeLoop = geometry.GetHalfEdgeLoop(frontLoopsStartHalfEdges[i]).ToList();
                var backEdgeLoop  = geometry.GetHalfEdgeLoopReverse(backLoopsStartHalfEdges[i]).ToList();

                var newHalfEdges = new List <HalfEdge>();

                var newFaces = new List <Face>();

                for (var j = 0; j < frontEdgeLoop.Count; j++)
                {
                    var halfEdgeFront  = frontEdgeLoop[j];
                    var halfEdgeInBack = backEdgeLoop[j];

                    var backOriginVert  = geometry.GetHalfEdgeByHandle(halfEdgeInBack.NextHalfEdge).OriginVertex;
                    var frontOriginVert = geometry.GetHalfEdgeByHandle(halfEdgeFront.NextHalfEdge).OriginVertex;

                    var newFromBack = new HalfEdge(geometry.CreateHalfEdgeHandleId())
                    {
                        OriginVertex = backOriginVert,
                        NextHalfEdge = halfEdgeFront.Handle,
                        PrevHalfEdge = halfEdgeInBack.Handle
                    };

                    var newFace = new Face(geometry.CreateFaceHandleId(), newFromBack.Handle);
                    newFaces.Add(newFace);

                    geometry.DictFaces.Add(newFace.Handle, newFace);

                    newFromBack.IncidentFace = newFace.Handle;

                    var newFromFront = new HalfEdge(geometry.CreateHalfEdgeHandleId())
                    {
                        OriginVertex = frontOriginVert,
                        NextHalfEdge = halfEdgeInBack.Handle,
                        PrevHalfEdge = halfEdgeFront.Handle,
                        IncidentFace = newFace.Handle
                    };

                    halfEdgeFront.IncidentFace = newFace.Handle;
                    halfEdgeFront.NextHalfEdge = newFromFront.Handle;
                    halfEdgeFront.PrevHalfEdge = newFromBack.Handle;

                    halfEdgeInBack.IncidentFace = newFace.Handle;
                    halfEdgeInBack.NextHalfEdge = newFromBack.Handle;
                    halfEdgeInBack.PrevHalfEdge = newFromFront.Handle;

                    geometry.ReplaceHalfEdge(halfEdgeFront);
                    geometry.ReplaceHalfEdge(halfEdgeInBack);

                    newHalfEdges.Add(newFromBack);
                    newHalfEdges.Add(newFromFront);
                }

                for (var j = 0; j < newHalfEdges.Count; j++)
                {
                    var current = newHalfEdges[j];
                    if (j == 0)
                    {
                        current.TwinHalfEdge = newHalfEdges.Last().Handle;
                    }
                    else if (j == newHalfEdges.Count - 1)
                    {
                        current.TwinHalfEdge = newHalfEdges[0].Handle;
                    }
                    else if (j % 2 != 0 && j != newHalfEdges.Count - 1) //odd
                    {
                        current.TwinHalfEdge = newHalfEdges[j + 1].Handle;
                    }
                    else if (j % 2 == 0 && j != 0) //even
                    {
                        current.TwinHalfEdge = newHalfEdges[j - 1].Handle;
                    }
                    newHalfEdges[j] = current;

                    geometry.DictHalfEdges.Add(current.Handle, current);
                }

                foreach (var face in newFaces)
                {
                    geometry.SetFaceNormal(geometry.GetFaceOuterVertices(face.Handle).ToList(), geometry.DictFaces[face.Handle]);
                }
            }

            //Delete unbounded face
            geometry.DictFaces.Remove(unboundedFace.Handle);
        }
Exemplo n.º 8
0
        private static IEnumerable <BoundaryEdge> CreateHalfEdgesForBoundary(PolyBoundary outline)
        {
            var outlineVerts  = OutlineVertices(outline);
            var boundaryEdges = BoundaryEdges(outlineVerts, outline);

            SetPrevAndNextForBoundary(boundaryEdges);

            var halfEdgesToUpdate = new List <HalfEdge>();

            for (var i = boundaryEdges.Count - 1; i > -1; i--)
            {
                var bEdge = boundaryEdges[i];

                if (!bEdge.IsOriginOldVert)
                {
                    continue;                         //A half-edge can only exist if its source vertex is an old one.
                }
                int existingHeHandle;
                if (!IsEdgeExisting(bEdge.HalfEdge, boundaryEdges, out existingHeHandle))
                {
                    continue; //Check the target vertex to identify the existing half edge.
                }
                //If the existing half edge is halfedge.IncidentFace.OuterHalfEdge, replace it.
                var face = _geometry.GetFaceByHandle(bEdge.HalfEdge.IncidentFace);
                if (face.OuterHalfEdge == bEdge.HalfEdge.Handle)
                {
                    face.OuterHalfEdge = existingHeHandle;
                    _geometry.ReplaceFace(face);
                }

                //If the existing half edge is one of the unbounded faces inner half edges, replace it.
                var unboundedFace = _geometry.DictFaces[1];
                for (var k = 0; k < unboundedFace.InnerHalfEdges.Count; k++)
                {
                    var heHandle = unboundedFace.InnerHalfEdges[k];
                    if (heHandle != existingHeHandle)
                    {
                        continue;
                    }
                    var nextHe = _geometry.GetHalfEdgeByHandle(heHandle).NextHalfEdge;

                    unboundedFace.InnerHalfEdges[k] = nextHe;
                    _geometry.DictFaces[1]          = unboundedFace;
                    break;
                }

                var existingHe = _geometry.GetHalfEdgeByHandle(existingHeHandle);

                existingHe.NextHalfEdge = bEdge.HalfEdge.NextHalfEdge;
                existingHe.PrevHalfEdge = bEdge.HalfEdge.PrevHalfEdge;
                existingHe.IncidentFace = bEdge.HalfEdge.IncidentFace;

                halfEdgesToUpdate.Add(existingHe);

                SetPrevAndNextToExistingHalfEdge(bEdge, existingHeHandle, boundaryEdges, halfEdgesToUpdate);

                boundaryEdges.RemoveAt(i);
            }

            if (halfEdgesToUpdate.Count == 0)
            {
                return(boundaryEdges);
            }

            foreach (var he in halfEdgesToUpdate)
            {
                _geometry.ReplaceHalfEdge(he);
            }
            return(boundaryEdges);
        }
Exemplo n.º 9
0
        /// <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 inseted 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 greate 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 sotres 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);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Inserts a new Vertex between two given exsisting 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 Handels
            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 exsisnting 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);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Inserts a pair of HalfEdges between two (non adjacent) vertices of a Face.
        /// </summary>
        /// <param name="geometry">The Geometry to insert a dignonal</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 sucessor 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;
        }
Exemplo n.º 12
0
        /// <summary>
        /// Performs a Catmull-Clark Subdivision-Surface algorithm on a given geometry which is stored as DCEL.
        /// </summary>
        /// <param name="geometry">The geometry to perform the SD on.</param>
        /// <returns>A smoother geometry with </returns>
        public static Geometry CatmullClarkSubdivision(Geometry geometry)
        {
            //initializing
            var newGeometry = geometry.CloneGeometry();

            //computes all Face Vertices and all Edge Vertices
            var allFaceVertices = GetFaceVertices(geometry);
            var allEdgeVertices = GetEdgeVertices(geometry, allFaceVertices);

            //Calculates the new position of existing Vertices
            var allVertices = newGeometry.GetAllVertices().ToList();

            foreach (var vertex in allVertices)
            {
                var outgoingEdges = newGeometry.GetVertexStartingHalfEdges(vertex.Handle).ToList();

                //Get average of all face Points and average of all edge Points
                var faceVertices = new List <Vertex>();
                var edgeVertices = new List <Vertex>();
                foreach (var edge in outgoingEdges)
                {
                    var twin = geometry.GetHalfEdgeByHandle(edge.TwinHalfEdge);

                    if (allFaceVertices.ContainsKey(edge.IncidentFace))
                    {
                        faceVertices.Add(allFaceVertices[edge.IncidentFace]);
                    }
                    else
                    {
                        faceVertices.Add(allFaceVertices[twin.IncidentFace]);
                    }

                    if (allEdgeVertices.ContainsKey(edge.Handle))
                    {
                        edgeVertices.Add(allEdgeVertices[edge.Handle]);
                    }
                    else
                    {
                        edgeVertices.Add(allEdgeVertices[twin.Handle]);
                    }
                }

                var meanEdgeVertexPos = GeometricOperations.GetVerticesMeanPos(edgeVertices);
                var meanFaceVertexPos = GeometricOperations.GetVerticesMeanPos(faceVertices);

                float edgeCount = outgoingEdges.Count;

                var newVertexPos = (meanFaceVertexPos + 2 * meanEdgeVertexPos + (edgeCount - 3) * vertex.VertData.Pos) / edgeCount;
                var newVertex    = new Vertex(vertex.Handle, newVertexPos)
                {
                    IncidentHalfEdge = vertex.IncidentHalfEdge
                };

                newGeometry.ReplaceVertex(newVertex);
            }

            //adds newly calculated Edge Vertices
            var allEdges = geometry.GetAllHalfEdges();
            var doneHe   = new int[allEdges.Count() + 1];

            foreach (var edge in allEdges)
            {
                if (doneHe[edge.Handle] == edge.TwinHalfEdge)
                {
                    continue;
                }
                var vertexOld1 = edge.OriginVertex;

                var twinEdge = geometry.GetHalfEdgeByHandle(edge.TwinHalfEdge);

                var vertexOld2 = twinEdge.OriginVertex;

                //find correct Edge Vertex
                Vertex edgeVertex;
                if (allEdgeVertices.ContainsKey(edge.Handle))
                {
                    edgeVertex = allEdgeVertices[edge.Handle];
                }
                else
                {
                    edgeVertex = allEdgeVertices[twinEdge.Handle];
                }

                newGeometry.InsertVertex(vertexOld1, vertexOld2, edgeVertex.VertData.Pos);
                doneHe[edge.TwinHalfEdge] = edge.Handle;
            }

            newGeometry.SetHighestHandles();
            geometry = newGeometry.CloneGeometry();

            //creates the new quad faces and connects everything
            AddFaceVerticesAndNewFaces(geometry, newGeometry, allFaceVertices);

            return(newGeometry);
        }
Exemplo n.º 13
0
        private static void AddFaceVerticesAndNewFaces(Geometry geometry, Geometry newGeometry, Dictionary <int, Vertex> allFaceVertices)
        {
            var allFaces = geometry.GetAllFaces();

            foreach (var face in allFaces)
            {
                Vertex   faceVertex = new Vertex(newGeometry.CreateVertHandleId(), allFaceVertices[face.Handle].VertData.Pos);
                HalfEdge startEdge  = geometry.GetHalfEdgeByHandle(face.OuterHalfEdge);
                HalfEdge nextEdge   = startEdge;

                //stores Halfedges without Twin
                Dictionary <int, HalfEdge> halfEdges2 = new Dictionary <int, HalfEdge>();
                Dictionary <int, HalfEdge> halfEdges1 = new Dictionary <int, HalfEdge>();

                newGeometry.DictVertices.Add(faceVertex.Handle, faceVertex);
                int i = 0;
                do
                {
                    HalfEdge h1 = new HalfEdge(newGeometry.CreateHalfEdgeHandleId());
                    HalfEdge h2 = new HalfEdge(newGeometry.CreateHalfEdgeHandleId());
                    HalfEdge h3 = newGeometry.GetHalfEdgeByHandle(nextEdge.PrevHalfEdge);
                    HalfEdge h4 = newGeometry.GetHalfEdgeByHandle(nextEdge.Handle);

                    //create new quad face
                    Face newFace;
                    newFace  = i == 0 ? face : new Face(newGeometry.CreateFaceHandleId());
                    nextEdge = geometry.GetHalfEdgeByHandle(nextEdge.NextHalfEdge);

                    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.OriginVertex = nextEdge.OriginVertex;
                    h2.OriginVertex = faceVertex.Handle;

                    h1.IncidentFace = newFace.Handle;
                    h2.IncidentFace = newFace.Handle;
                    h3.IncidentFace = newFace.Handle;
                    h4.IncidentFace = newFace.Handle;

                    faceVertex.IncidentHalfEdge = h2.Handle;
                    newFace.OuterHalfEdge       = h1.Handle;

                    //add and replace changed
                    newGeometry.DictHalfEdges.Add(h1.Handle, h1);
                    newGeometry.DictHalfEdges.Add(h2.Handle, h2);

                    newGeometry.ReplaceHalfEdge(h3);
                    newGeometry.ReplaceHalfEdge(h4);

                    newGeometry.ReplaceVertex(faceVertex);

                    if (i == 0) // the old face becomes the first quad, so no new face to create
                    {
                        newGeometry.ReplaceFace(newFace);
                    }
                    else //create new face
                    {
                        newGeometry.DictFaces.Add(newFace.Handle, newFace);
                    }

                    //Stores Vertices to get the face normal
                    List <Vertex> faceVertices = new List <Vertex>
                    {
                        newGeometry.GetVertexByHandle(h1.OriginVertex),
                        newGeometry.GetVertexByHandle(h2.OriginVertex),
                        newGeometry.GetVertexByHandle(h3.OriginVertex),
                        newGeometry.GetVertexByHandle(h4.OriginVertex)
                    };

                    newGeometry.SetFaceNormal(faceVertices, newFace);

                    halfEdges2.Add(i, h2);
                    halfEdges1.Add(i, h1);

                    //for the second Edge per Face connect the twin
                    if (i > 0)
                    {
                        HalfEdge h1N = halfEdges1[i - 1];
                        h1N.TwinHalfEdge = halfEdges2[i].Handle;

                        HalfEdge h2N = halfEdges2[i];
                        h2N.TwinHalfEdge = h1N.Handle;

                        newGeometry.ReplaceHalfEdge(h1N);
                        newGeometry.ReplaceHalfEdge(h2N);
                    }

                    i++;
                    nextEdge = geometry.GetHalfEdgeByHandle(nextEdge.NextHalfEdge);
                } while (startEdge != nextEdge);

                //set Twin of firsts and lasts of each new Face
                var h2Firts = halfEdges2[0];
                var h1Last  = halfEdges1[i - 1];

                h2Firts.TwinHalfEdge = h1Last.Handle;
                h1Last.TwinHalfEdge  = h2Firts.Handle;

                newGeometry.ReplaceHalfEdge(h2Firts);
                newGeometry.ReplaceHalfEdge(h1Last);
            }
        }
Exemplo n.º 14
0
        /// <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 lastlatitudeVerticesHandles    = new int[horizontalResolution]; //stores last vertices to connect them later with the next latitude 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 ? lastlatitudeVerticesHandles[0] : lastlatitudeVerticesHandles[j + 1];
                        h1.OriginVertex = lastlatitudeVerticesHandles[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(lastlatitudeVerticesHandles[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, lastlatitudeVerticesHandles,
                           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);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Creates and returns a cone with the given dimensions.
        /// </summary>
        /// <param name="baseRadius">The radius of the base circle.</param>
        /// <param name="dimensionY">The height of the cone.</param>
        /// <param name="sliceCount">The horizontal resolution 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 parameters <= 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 north pole
            cone.DictVertices.Add(southPole.Handle, southPole);
            cone.DictVertices.Add(northPole.Handle, northPole);

            //create last 2 triangles
            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);
        }