Esempio n. 1
0
 /// <summary>
 /// Constructs a quad rule factory using the given subdivision
 /// strategy.
 /// </summary>
 /// <param name="subdivisionStrategy">
 /// <see cref="SubdivisionStrategy"/>
 /// </param>
 /// <param name="leafDivisions">
 /// The additional number of subdivisions for the quadrature rule to be
 /// used in cut leaves (see <see cref="SubdivisionNode.IsCut"/>).
 /// </param>
 public CutCellQuadRuleFactory(ISubdivisionStrategy subdivisionStrategy, int leafDivisions)
 {
     SubdivisionStrategy = subdivisionStrategy;
     if (leafDivisions >= 0)
     {
         cutNodeRule = RefElement.GetBruteForceQuadRule(leafDivisions, 1);
     }
 }
        public ITreeMap <FileTreeItem> CreateTreeMap(Rect rectangle, ITree <FileTreeItem> tree, ISubdivisionStrategy subdivisionStrategy, CancellationToken cancellationToken = default)
        {
            if (tree.Root == null)
            {
                return(new FileTreeMap());
            }

            var fileTree = (FileTree)tree;

            directoryAge        = fileTree.NewestFileTimestamp - fileTree.OldestFileTimestamp;
            newestFileTimestamp = fileTree.NewestFileTimestamp;

            var autoResetEvent = new AutoResetEvent(false);
            var tasks          = new List <Task <IEnumerable <FileTreeItemRectangle> > >();
            var map            = new FileTreeMap();
            var queue          = new Queue <FileTreeItemRectangle>();

            queue.Enqueue(new FileTreeItemRectangle(tree.Root, rectangle));

            while (queue.Count > 0)
            {
                while (queue.TryDequeue(out var itemRectangle))
                {
                    map.Add(CreateMapItem(itemRectangle));
                    tasks.Add(Task.Run(() => { return(Subdivide(itemRectangle, subdivisionStrategy)); }));
                }

                Task.WhenAll(tasks).ContinueWith(task =>
                {
                    task.Result.ToList().ForEach(group => group.ToList().ForEach(r => queue.Enqueue(r)));
                    autoResetEvent.Set();
                });

                tasks.Clear();
                autoResetEvent.WaitOne();
            }

            return(map);
        }
        private IEnumerable <FileTreeItemRectangle> Subdivide(FileTreeItemRectangle itemRectangle, ISubdivisionStrategy strategy)
        {
            const int MIN_AREA = 64 * 64;

            if (itemRectangle.RectangleToSubdivide.Width < 4 ||
                itemRectangle.RectangleToSubdivide.Height < 4)
            {
                return(Enumerable.Empty <FileTreeItemRectangle>());
            }

            var rectangleArea = itemRectangle.RectangleToSubdivide.Width * itemRectangle.RectangleToSubdivide.Height;

            var totalSize       = itemRectangle.TreeItem.Items.Sum(i => i.Size);
            var conversionRatio = rectangleArea / totalSize;

            var itemsWithSize = itemRectangle.TreeItem.Items.Where(i => i.Size > 0).OrderByDescending(i => i.Size).ToList();

            if (!itemsWithSize.Any())
            {
                return(Enumerable.Empty <FileTreeItemRectangle>());
            }

            var subrectangleAreas = itemsWithSize.Select(i => new FileTreeItemArea {
                Item = i, Area = i.Size * conversionRatio
            }).ToList();

            // Удаляем самые маленькие прямоугольники и перераспределяем их площадь по остальным прямоугольникам.
            while (subrectangleAreas.Min(sa => sa.Area) < MIN_AREA && subrectangleAreas.Count > 1)
            {
                var last = subrectangleAreas.Last();
                subrectangleAreas.Remove(last);
                var areaToRedistribute = last.Area / subrectangleAreas.Count;
                foreach (var sub in subrectangleAreas)
                {
                    sub.Area += areaToRedistribute;
                }
            }

            var rectangles = strategy.Subdivide(itemRectangle.RectangleToSubdivide, subrectangleAreas.Select(a => a.Area));

            rectangles = DownsizeRectangles(rectangles);
            var pairs = subrectangleAreas.Zip(rectangles, (item, rectangle) => new FileTreeItemRectangle(item.Item !, rectangle));

            return(pairs);
        }