Пример #1
0
 /// <summary>
 /// Returns a list of arrays of 3 vertices, each representing a triangle in the mesh.
 /// Faces are taken from the first FaceSet in the mesh with the given flags,
 /// using None by default for the highest detail mesh. If not found, the first FaceSet is used.
 /// </summary>
 public List <FLVER.Vertex[]> GetFaces(FaceSet.FSFlags fsFlags = FaceSet.FSFlags.None)
 {
     if (FaceSets.Count == 0)
     {
         return(new List <FLVER.Vertex[]>());
     }
     else
     {
         FaceSet    faceSet  = FaceSets.Find(fs => fs.Flags == fsFlags) ?? FaceSets[0];
         List <int> indices  = faceSet.Triangulate(Vertices.Count < ushort.MaxValue);
         var        vertices = new List <FLVER.Vertex[]>(indices.Count);
         for (int i = 0; i < indices.Count - 2; i += 3)
         {
             int vi1 = indices[i];
             int vi2 = indices[i + 1];
             int vi3 = indices[i + 2];
             vertices.Add(new FLVER.Vertex[] { Vertices[vi1], Vertices[vi2], Vertices[vi3] });
         }
         return(vertices);
     }
 }
Пример #2
0
        /// <summary>
        /// Reduce an instance of Set Cover using safe reduction rules
        /// </summary>
        /// <param name="U">The universe</param>
        /// <param name="F">The familiy of sets</param>
        /// <returns>
        /// (U, F, delta), where U and F are "irreducible" and
        /// delta is the number of sets that must be included
        /// </returns>
        private static Tuple <HashSet <int>, Dictionary <int, HashSet <int> >, List <int> > Reduce(HashSet <int> U, Dictionary <int, HashSet <int> > F)
        {
            // EdgeSets : Edges -> 2^Faces
            var EdgeSets = new Dictionary <int, HashSet <int> >();

            // deep copy
            foreach (var edge in F.Keys)
            {
                foreach (var face in F[edge])
                {
                    if (EdgeSets.ContainsKey(edge))
                    {
                        EdgeSets[edge].Add(face);
                    }
                    else
                    {
                        EdgeSets.Add(edge, new HashSet <int> {
                            face
                        });
                    }
                }
            }

            // FaceSets : Faces -> 2^Edges
            var FaceSets = new Dictionary <int, HashSet <int> >();

            foreach (var edge in EdgeSets.Keys)
            {
                foreach (var face in EdgeSets[edge])
                {
                    if (FaceSets.ContainsKey(face))
                    {
                        FaceSets[face].Add(edge);
                    }
                    else
                    {
                        FaceSets.Add(face, new HashSet <int> {
                            edge
                        });
                    }
                }
            }

            // main reduction loop
            // whether the solution changed at all
            var reduced = false;

            // whether the solution changed this iteration
            var changed = true;
            var delta   = new List <int>();

            do
            {
                changed = false;
                // last face was removed
                if (FaceSets.Count() == 0)
                {
                    return(Tuple.Create(new HashSet <int>(), new Dictionary <int, HashSet <int> >(), delta));
                }

                // remove duplicates
                var noDups = RemoveDuplicates(EdgeSets);
                if (noDups.Item1)
                {
                    reduced  = true;
                    changed  = true;
                    EdgeSets = noDups.Item2;

                    FaceSets = new Dictionary <int, HashSet <int> >();
                    foreach (var key in EdgeSets.Keys)
                    {
                        foreach (var edge in EdgeSets[key])
                        {
                            if (FaceSets.ContainsKey(edge))
                            {
                                FaceSets[edge].Add(key);
                            }
                            else
                            {
                                FaceSets.Add(edge, new HashSet <int> {
                                    key
                                });
                            }
                        }
                    }

                    continue;
                }

                //remove isolated faces
                var isolated =
                    from set in FaceSets
                    where (set.Value.Count == 1)
                    select set.Key;

                if (isolated.Count() > 0)
                {
                    reduced = true;
                    changed = true;

                    // collect all faces of sets which include the isolated faces
                    var coveredFaces  = new HashSet <int>();
                    var coveredEdges  = new HashSet <int>();
                    var selectedEdges = new HashSet <int>();
                    foreach (var face in isolated)
                    {
                        // only one set that includes the face
                        var edge = FaceSets[face].ElementAt(0);
                        selectedEdges.Add(edge);

                        foreach (var f in EdgeSets[edge])
                        {
                            coveredFaces.Add(f);
                        }

                        coveredEdges.Add(edge);
                    }
                    delta.AddRange(selectedEdges);

                    // build new FaceSets
                    var newFaceSets = new Dictionary <int, HashSet <int> >();
                    foreach (var pair in FaceSets)
                    {
                        if (!coveredFaces.Contains(pair.Key))
                        {
                            newFaceSets.Add(pair.Key, pair.Value);
                        }
                    }
                    FaceSets = newFaceSets;

                    // build new EdgeSets
                    var newEdgeSets = new Dictionary <int, HashSet <int> >();
                    foreach (var pair in EdgeSets)
                    {
                        if (!coveredEdges.Contains(pair.Key))
                        {
                            var faces = pair.Value;
                            faces.ExceptWith(coveredFaces);
                            newEdgeSets.Add(pair.Key, faces);
                        }
                    }

                    // remove empty sets
                    EdgeSets = new Dictionary <int, HashSet <int> >();
                    foreach (var pair in newEdgeSets)
                    {
                        if (pair.Value.Count > 0)
                        {
                            EdgeSets.Add(pair.Key, pair.Value);
                        }
                    }

                    continue;
                }


                // find the first completely included subsets and remove it
                for (int i = 0; i < EdgeSets.Count && !changed; i++)
                {
                    var edge = EdgeSets.ElementAt(i).Key;
                    var A    = EdgeSets.ElementAt(i).Value;
                    for (int j = 0; j < EdgeSets.Count; j++)
                    {
                        if (i == j)
                        {
                            continue;
                        }
                        bool complete = true;
                        var  B        = EdgeSets.ElementAt(j).Value;
                        foreach (var x in A)
                        {
                            if (!B.Contains(x))
                            {
                                complete = false;
                            }
                        }
                        if (complete)
                        {
                            foreach (var face in A)
                            {
                                // face no longer occurs in Vis(edge)
                                FaceSets[face].Remove(edge);
                            }

                            // remove empty sets
                            var newFaceSets = new Dictionary <int, HashSet <int> >();
                            foreach (var pair in FaceSets)
                            {
                                if (pair.Value.Count > 0)
                                {
                                    newFaceSets.Add(pair.Key, pair.Value);
                                }
                            }
                            FaceSets = newFaceSets;

                            EdgeSets.Remove(edge);

                            reduced = true;
                            changed = true;
                            break;
                        }
                    }
                }

                if (changed)
                {
                    continue;
                }

                // remove the first face which is present in every set
                var redundant     = false;
                var redundantFace = 0;

                foreach (var face in FaceSets.Keys)
                {
                    if (FaceSets[face].Count == EdgeSets.Keys.Count)
                    {
                        // no isolated faces
                        redundant     = true;
                        redundantFace = face;
                        break;
                    }
                }

                if (redundant)
                {
                    reduced = true;
                    changed = true;

                    FaceSets.Remove(redundantFace);
                    foreach (var pair in EdgeSets)
                    {
                        pair.Value.Remove(redundantFace);
                    }
                }
            } while (changed);


            // recover the instance
            if (reduced)
            {
                var new_U = new HashSet <int>();
                foreach (var face in FaceSets.Keys)
                {
                    new_U.Add(face);
                }

                return(Tuple.Create(new_U, FaceSets, delta));
            }
            else
            {
                return(Tuple.Create(U, F, delta));
            }
        }