Как я могу определить, полностью ли один прямоугольник содержится в другом?
у меня есть теоретическая сетка перекрывающихся прямоугольников, которые могут выглядеть примерно так:
но все, с чем я должен работать, это коллекция объектов Rectangle:
var shapes = new List<Rectangle>();
shapes.Add(new Rectangle(10, 10, 580, 380));
shapes.Add(new Rectangle(15, 20, 555, 100));
shapes.Add(new Rectangle(35, 50, 40, 75));
// ...
то, что я хотел бы сделать, это построить DOM-подобную структуру, где каждый прямоугольник имеет свойство ChildRectangles, которое содержит прямоугольники, содержащиеся в нем на сетке.
конечный результат должен позволить мне преобразовать такую структуру в XML, что-то вроде:
<grid>
<shape rectangle="10, 10, 580, 380">
<shape rectangle="5, 10, 555, 100">
<shape rectangle="20, 30, 40, 75"/>
</shape>
</shape>
<shape rectangle="etc..."/>
</grid>
но в основном это DOM-подобная структура в памяти, которую я хочу, выходной XML-это просто пример того, как я могу использовать такую структуру.
бит, на котором я застрял, - это как эффективно определить, какие прямоугольники принадлежат к которым.
Примечание никакие прямоугольники частично не содержатся внутри другого, они всегда полностью внутри другого.
редактировать обычно сотни прямоугольников, должен ли я просто перебирать каждый прямоугольник, чтобы увидеть, содержится ли он в другом?
редактировать кто-то предложил содержит (не мой лучший момент, пропуская это!), но я не уверен, как лучше выстроить дом. Например, возьмите внука первого прямоугольника, родитель действительно содержит внука, но он не должен быть прямым ребенком, он должен быть ребенком первого ребенка родителя.
5 ответов
Как указывает @BeemerGuy,Rect.Contains
скажет вам, содержит ли один прямоугольник другой. Построение иерархии немного сложнее...
есть решение O(N^2), в котором для каждого прямоугольника вы просматриваете список других прямоугольников, чтобы увидеть, подходит ли он внутрь. "Владелец" каждого прямоугольника-это самый маленький прямоугольник, который его содержит. Псевдокод:
foreach (rect in rectangles)
{
owner = null
foreach (possible_owner in rectangles)
{
if (possible_owner != rect)
{
if (possible_owner.contains(rect))
{
if (owner === null || owner.Contains(possible_owner))
{
owner = possible_owner;
}
}
}
}
// at this point you can record that `owner` contains `rect`
}
это не очень эффективно, но это может быть "достаточно быстро" для ваших целей. Я уверен Я видел решение O(n log n) (в конце концов, это просто операция сортировки), но оно было несколько сложнее.
использовать Contains()
на Rectangle
.
Rectangle rect1, rect2;
// initialize them
if(rect1.Continas(rect2))
{
// do...
}
обновление:
Для дальнейшего использования...
Интересно добавить, что Rectangle
также IntersectsWith(Rectangle rect)
если вы хотите проверить, частично ли прямоугольник сталкивается с другим прямоугольником.
решение среднего случая O (N log n):
подумайте о своем наборе прямоугольников как о дереве, где родительские узлы "содержат" дочерние узлы-то же самое, что и структура DOM. Вы будете строить дерево по прямоугольнику за раз.
сделайте фиктивный узел, который будет служить корнем вашего дерева. Затем для каждого из ваших прямоугольников ("current_rect") начните с дочерних элементов корня и работайте вниз, пока не найдете, куда он идет:
parent_node = root_node
sibling_nodes = [children of parent_node]
for this_node in sibling_nodes:
if current_rect contains this_node:
move this_node: make it a child of current_rect instead of parent_node
elseif this_node contains current_rect:
parent_node = this_node
sibling_nodes = [children of parent_node]
restart the "for" loop using new set of sibling_nodes
make current_rect a child of parent_node
в "содержит" relation спрашивает, содержит ли один прямоугольник другой. "Родитель", "ребенок" и "брат" относятся к древовидной структуре.
редактировать: Исправлена ошибка, которая пропустит перемещение некоторых узлов в current_rect.
убедитесь, что каждая точка в прямоугольнике находится в пределах других прямоугольников. В .NET класс Rectangle имеет a .Содержит(точечный) метод. Или вы можете проверить координаты угловой точки againt целевой прямой кишки .Влево. ,Право. ,Верх и. Свойства дна.
псевдо код:
for i = 0 to rectangles.length - 2
for j = i + 1 to rectangles.length - 1
if rectangles[i].Contains(rectangles[j])
//code here
}}}