Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Extrudes a given Face by a given offset along its normal vector.
        /// </summary>
        /// <param name="geometry">The geometry.</param>
        /// <param name="faceHandle">The handle of the face to extrude.</param>
        /// <param name="offset">How far the face should get extruded.</param>
        /// <returns></returns>
        public static Geometry ExtrudeFace(this Geometry geometry, int faceHandle, float offset)
        {
            var face = geometry.GetFaceByHandle(faceHandle);

            return(ExtrudeFaceByHandle(geometry, faceHandle, offset, face.FaceData.FaceNormal));
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
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);
        }