/// <summary> /// Quick (O(n log n)) and accurate collision detection /// </summary> /// <param name="labels"></param> public static void QuickAccurateCollisionDetectionMethod(List <BaseLabel> labels) { // find minimum / maximum coordinates double minX = double.MaxValue; double maxX = double.MinValue; double minY = double.MaxValue; double maxY = double.MinValue; foreach (BaseLabel l in labels) { var box = new ProperBox(l is PathLabel pl ? new LabelBox(pl.Location.GetBounds()) : l.Box); if (box.Left < minX) { minX = box.Left; } if (box.Right > maxX) { maxX = box.Right; } if (box.Bottom > maxY) { maxY = box.Bottom; } if (box.Top < minY) { minY = box.Top; } } // sort by area (highest priority first, followed by low area to maximize the amount of labels displayed) var sortedLabels = labels.OrderByDescending(label => label.Priority).ThenBy(label => { var box = label is PathLabel pl ? new LabelBox(pl.Location.GetBounds()) : label.Box; return(box.Width * box.Height); }); // make visible if it does not collide with other labels. Uses a quadtree and is therefore fast O(n log n) QuadTreeNode <ProperBox> quadTree = new QuadTreeNode <ProperBox>(minX, maxX, minY, maxY, new LabelBoxContainmentChecker(), 0, 10); foreach (BaseLabel l in sortedLabels) { if (!l.Show) { continue; } var box = new ProperBox(l is PathLabel pl ? new LabelBox(pl.Location.GetBounds()) : l.Box); if (quadTree.CollidesWithAny(box)) { l.Show = false; } else { quadTree.Insert(box); } } }