/// <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); }