Как проверить положения прямоугольника в повторяющейся 4-ролльной компоновке с пространственными ограничениями на основе ⇐ C#

Место общения программистов C#
Anonymous
Как проверить положения прямоугольника в повторяющейся 4-ролльной компоновке с пространственными ограничениями на основе

Сообщение Anonymous »

Я работаю со списком прямоугольников и должен проверить, находится ли каждый из них в правильном положении на основе фиксированной шаблона и набора геометрических ограничений. 4-role pattern based on their index:
0 → Top Left

1 → Bottom Left

2 → Top Right

3 → Bottom Right
4 → Top Left

5 → Bottom Left

6 → Top Right

7 → Внизу справа

...
Каждая группа состоит из 4 прямоугольников с последовательными показателями, начиная с кратных 4 (то есть, индексы 0–3, 4–7, 8–11 и т. Д.).
Роли, назначенные индексом % 4, повторяйте в каждой группе. Несмотря на то, что сама роль определяется исключительно по индексу, фактическая позиция прямоугольника, как ожидается, будет визуально соответствовать этой роли (например, прямоугольный прямолинейный взгляд на верхнюю левую в своей группе). < /P>
Последняя группа может содержать менее 4 прямоугольников, если длина списка не делится на 4. Это не рассматривается по ошибке, пока все еще не будет осмотрительно. Это исключение относится только к окончательной группе на основе длины списка ввода. < /P>
шаблон повторяется каждые 4 элемента. Однако прямоугольники в сборе ввода уже могут быть неправильно расположены. Верхний левый прямоугольник помещается там, где должен быть прямоугольный прямоугольник). < /P>
Допустимый диапазон движения каждого прямоугольника определяется не только путем предотвращения прямого перекрытия с соседями, но также и дополнительным правилом:
не должно пересекать линии расширенной оси (x-ax-ax ax ax ax ax. < /P>
horizontal mails): < /p>
horizontal mails). Горизонтально, пока он не пересекает вертикальные граничные линии своих горизонтальных соседей: < /p>
Слева: она не должна пересекать вертикальную линию, простирающуюся от правого края левого соседа. < /p>
Право: не должна пересекать версическую линию, выходящую от левого края правого соседа. (Ось Y):
прямоугольник может двигаться вертикально только до тех пор, пока он не пересекает горизонтальные граничные линии своей вертикальной пары (верхняя /нижняя пара): < /p>
Движение вниз: она не должна пересекать горизонтальную линию, расширяющуюся от верхней части нижней пары. его верхняя пара. < /p>
Другими словами, прямоугольник никогда не должен пересекать воображаемые границы, выравниваемые осью, даже если сами прямоугольники не касаются физически. Ограничение: не может пересечь горизонтальную ось, простирающуюся от края пары.
прямоугольники могут варьироваться по размеру, они не обязаны быть равномерными. Это учитывается в логике: все валидация положения основана на краях и ограничениях, выравниваемых осью (не фиксированными измерениями). Прямоугольник считается недействительным, только если он пересекает расширенные граничные линии соседа, независимо от его размера. < /P>
Я пишу приведенный ниже код. В настоящее время моя функция идентифицирует, когда два прямоугольника нарушают ограничение оси (например, один перекрывает другой вдоль x или y). Но в таких случаях он помечает оба прямоугольника - тот, который остался в правильном положении, и тот, который фактически перемещался в пространство другого. < /P>
Однако это поведение не идеально. Я хотел бы просто пометить прямоугольник, который вторгся в зону оси другого. < /P>

Код: Выделить всё

public List GetInvalidRectIndexes(List rects)
{
List invalidIndexes = new List();

for (int i = 0; i < rects.Count; i++)
{
if (!IsValidPosition(i, rects))
invalidIndexes.Add(i);
}

return invalidIndexes;
}

private bool IsValidPosition(int index, List rects)
{
var rect = rects[index];
int role = index % 4;

var pos = GetEdges(rect);

RectModel leftNeighbor = (index - 2 >= 0) ? rects[index - 2] : null;
RectModel rightNeighbor = (index + 2 < rects.Count) ? rects[index + 2] : null;

int pairIndex = (role == 0 || role == 2) ? index + 1 : index - 1;
RectModel pair = (pairIndex >= 0 && pairIndex < rects.Count) ? rects[pairIndex] : null;

// X constraint
if (leftNeighbor != null)
{
var left = GetEdges(leftNeighbor);
if (pos.Left < left.Right)
return false;
}

if (rightNeighbor != null)
{
var right = GetEdges(rightNeighbor);
if (pos.Right > right.Left)
return false;
}

// Y constraint
if (pair != null)
{
var pairPos = GetEdges(pair);

if (role == 0 || role == 2) // Top*
{
if (pos.Bottom > pairPos.Top)
return false;
}
else if (role == 1 || role == 3) // Bottom*
{
if (pos.Top < pairPos.Bottom)
return false;
}
}

return true;
}

private class Edges
{
public double Left, Right, Top, Bottom;
}

private Edges GetEdges(RectModel rect)
{
var x = rect.X;
var y = rect.Y;
var w = rect.Width;
var h = rect.Height;

return new Edges
{
Left = x,
Right = x + w,
Top = y,
Bottom = y + h
};
}

private List _rectangles = new();
public List Rectangles
{
get => _rectangles;
set { _rectangles = value; }
}

public class RectModel : ViewModelBase
{
private double _x, _y, _width, _height;
private SolidColorBrush _color;
private int _index;

public int Index
{
get => _index;
set { _index = value; OnPropertyChanged(nameof(X)); }
}

public double X
{
get => _x;
set { _x = value; OnPropertyChanged(nameof(X)); }
}

public double Y
{
get => _y;
set { _y = value; OnPropertyChanged(nameof(Y)); }
}

public double Width
{
get => _width;
set { _width = value; OnPropertyChanged(nameof(Width)); }
}

public double Height
{
get => _height;
set { _height = value; OnPropertyChanged(nameof(Height)); }
}

public SolidColorBrush Color
{
get => _color;
set { _color = value; OnPropertyChanged(nameof(Color)); }
}
}

var invalidIndices = GetInvalidRectIndexes(Rectangles);

for (int i = 0; i < Rectangles.Count; i++)
{
Rectangles[i].Color = invalidIndices.Contains(i) ? Brushes.Red : Brushes.Green;
}
< /code>
Вот 2 тестовых входа для метода.
Этот первый - пример, показывающий, как входные прямоугольники выглядят, когда они правильно расположены. Это просто ссылка на понимание того, каким будет компоновка, когда все прямоугольники находятся в их допустимых позициях.  < /P>
var validRectangles = new List
{
new RectModel { X = 80, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 80, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 250, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 250, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 460, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 460, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 640, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 640, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 830, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 830, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1000, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1000, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 1220, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1220, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1380, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1380, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 1580, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1580, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1730, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1730, Y = 720, Width = 130, Height = 150 }
};
Визуально о допустимых прямоугольниках:

, на основе Logic, с приведенным ниже примером. 11 < /p>
Причины: < /p>
Индекс 2 скрещивается влево над осью правого края своего левого соседа (то есть, он нарушает вертикальную границу левого соседа). < /P>
Индексы 1 и 14 заменяются - их позиции - это то, где, как следует, то, где, как следует, то, где, то есть, то, где, то, что нужно, то есть, что нужно, то вершина ». BE, и наоборот). < /p>
Индекс 6 пересекается вправо над осью левого края своего правого соседа (то есть, он нарушает левую вертикальную границу правого соседа). < /p>
Индексы 15 и 11 разбиваются, нарушая ожидаемый циклический порядок.var testRectangles = new List
{
new RectModel { X = 80, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1380, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 100, Y = 55, Width = 130, Height = 150 },
new RectModel { X = 250, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 460, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 460, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 740, Y = 475, Width = 130, Height = 150 },
new RectModel { X = 640, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 830, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 830, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1000, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1380, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 1220, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1220, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 80, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1000, Y = 720, Width = 130, Height = 150 },

new RectModel { X = 1580, Y = 275, Width = 130, Height = 150 },
new RectModel { X = 1580, Y = 720, Width = 130, Height = 150 },
new RectModel { X = 1730, Y = 275, Width = 130, Height = 150 }
};
< /code>
Визуально с неверными прямыми:

Как я могу улучшить логику, чтобы отметить только то, что прямое, что например, что -то, если это то, что правильно, - это то, что правильно, - это то, что правильно, - это то, что правильно, - это то, что правильно, - это то, что правильно, и то, что она нарушает? B пересекается в область A, только B должен быть помечен, а не оба. макет - а затем только отмечает неправильный? Благодарность.

Подробнее здесь: https://stackoverflow.com/questions/796 ... axis-based

Вернуться в «C#»