我有一个矩形数组。其中一些可能会相交,组成一对:
虽然其他的可能会相交,形成一个链:
当然,其中一些可能是单独的。
我想要形成一个列表,其中包括所有的链、对和单个矩形。例如,如果我们有一个看起来像这样的矩形数组:
我想获取以下列表:
{ { A, B, C, D, E },
{ F },
{ G },
{ H, J },
{ K, L },
{ M, N, O } }
其中A、B、C、D、E等均为相应的矩形。
到目前为止,我尝试使用以下代码生成所有可能的排列:
var rectangles = new Rectangle[] { ..., ..., ... }; // my rectangles
var rectanglePermutations = new IEnumerable<IEnumerable<Rectangle>>();
// make all permutations with 2, 3, 4 (and so on) elements
for (var i = 2; i < rectangles.Length; i++)
{
rectanglePermutations.AddRange(GetPermutations(rectangles, i));
}
IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> items, int count)
{
var i = 0;
foreach (var item in items)
{
if (count == 1)
{
yield return new T[] { item };
}
else
{
foreach (var result in GetPermutations(items.Skip(i + 1), count - 1))
{
yield return new T[] { item }.Concat(result);
}
}
i++;
}
}
然后我试图找出每个可枚举对象中的所有矩形是否可以形成链:
var result = new List<List<Rectangle>>();
foreach (var permutations in rectanglePermutations)
{
var chain = new List<Rectangle>(permutations);
var canFormNewRectangles = true;
do
{
var newlyFormedRectanglesCount = 0;
// get all possible pairs
var pairs = GetPermutations(chain.Distinct(), 2);
chain.Clear();
foreach (var pair in pairs)
{
// if rectangles in pair intersect
var union = Rectangle.Union(pair.First(), pair.Last());
if (union.Width * union.Height > 0)
{
// replace them with a new rectangle
chain.Add(new Rectangle(pair.Min(r => r.Left), pair.Min(r => r.Top), pair.Max(r => r.Right) - pair.Min(r => r.Left), pair.Min(r => r.Top) - pair.Max(r => r.Bottom)));
newlyFormedRectanglesCount++;
}
}
// if we can't make any more new rectangles
if (newlyFormedRectanglesCount == 0)
{
canFormNewRectangles = false;
}
}
while (canFormNewRectangles);
// if all rectangles made a single chain
if (chain.Count == 1)
{
result.Add(permutation.ToList());
}
}
// add single rectangles to result that are not used in any chains
var usedRectangles = chains.SelectMany(chain => chain).Distinct();
result.AddRange(rectangles.Except(usedRectangles).ToList());
问题在于上面的代码是无效和缓慢的。例如,如果我们有一个由5个矩形组成的链、一个由3个矩形组成的链和2个单独的矩形(总共10个),我们将从第一部分代码得到1013个可能的排列,从第二部分代码至少得到11160次迭代(实际上,对于给定的示例,我们将得到两倍的结果)。使用这种方法来找到仅2个合适的组合是低效的。我相信有更好的方法,需要一些帮助。
Rectangle.IntersectsWith
返回真(true)形成图中的一条边。然后检测链是连通组件标记的特殊情况。不确定为什么要使用Rectangle.Union
来检测重叠。 - WyckRectangle.Union
返回一个包含两个源矩形的单个矩形。我不明白这与矩形重叠或创建“链”有什么关系。你能否通过编辑问题(而不是在评论中)澄清你想做什么? - Rufus L