Возможно, это скорее математический вопрос, чем вопрос программирования, но я пытался реализовать алгоритм вращающегося суппорта в XNA.
Я вывел выпуклую оболочку из своего набора точек, используя монотонную цепочку, как описано в Википедии.
Теперь я пытаюсь смоделировать свой алгоритм поиска OBB после найденного здесь: http://www.cs.purdue.edu/research/technical_reports/1983/TR%2083-463.pdf
Однако я не понимаю, что должны возвращать методы DOTPR и CROSSPR, упомянутые на последней странице.
Я понимаю, как получить скалярное произведение двух точек и перекрестное произведение двух точек, но кажется, что эти функции должны возвращать точечные и перекрестные произведения двух ребер/отрезков прямой. Мои познания в математике, по общему признанию, ограничены, но это мое лучшее предположение о том, что ищет алгоритм
public static float PolygonCross(List polygon, int indexA, int indexB)
{
var segmentA1 = NextVertice(indexA, polygon) - polygon[indexA];
var segmentB1 = NextVertice(indexB, polygon) - polygon[indexB];
float crossProduct1 = CrossProduct(segmentA1, segmentB1);
return crossProduct1;
}
public static float CrossProduct(Vector2 v1, Vector2 v2)
{
return (v1.X * v2.Y - v1.Y * v2.X);
}
public static float PolygonDot(List polygon, int indexA, int indexB)
{
var segmentA1 = NextVertice(indexA, polygon) - polygon[indexA];
var segmentB1 = NextVertice(indexB, polygon) - polygon[indexB];
float dotProduct = Vector2.Dot(segmentA1, segmentB1);
return dotProduct;
}
. Однако когда я использую эти методы, как указано в этой части кода...
while (PolygonDot(polygon, i, j) > 0)
{
j = NextIndex(j, polygon);
}
if (i == 0)
{
k = j;
}
while (PolygonCross(polygon, i, k) > 0)
{
k = NextIndex(k, polygon);
}
if (i == 0)
{
m = k;
}
while (PolygonDot(polygon, i, m) < 0)
{
m = NextIndex(m, polygon);
}
... он возвращает тот же индекс для j, k, когда я даю ему тестовый набор точек:
List polygon = new List()
{
new Vector2(0, 138),
new Vector2(1, 138),
new Vector2(150, 110),
new Vector2(199, 68),
new Vector2(204, 63),
new Vector2(131, 0),
new Vector2(129, 0),
new Vector2(115, 14),
new Vector2(0, 138),
};
Обратите внимание, что я вызываю polygon.Reverse, чтобы разместить эти точки в порядке счетчика -по часовой стрелке, как указано в техническом документе от perdue.edu.Мой алгоритм нахождения выпуклой -оболочки множества точек генерирует список точек в обратном -порядке по часовой стрелке, но делает это в предположении, что y 0, потому что при рисовании на экране 0,0 верхний левый угол. Перевернуть список кажется достаточным. Я также удаляю повторяющуюся точку в конце.
После этого процесса данные становятся:
Этот тест не пройден в первом цикле, когда i равно 0 и j равно 3. Он обнаруживает, что перекрестное произведение -строки (115,14 )на (204,63 )и строки От (204,63 )до (199,68 )равно 0. Затем обнаруживается, что скалярное произведение тех же строк также равно 0, поэтому j и k имеют один и тот же индекс.
Напротив, при наличии этого тестового набора: http://www.wolframalpha.com/input/?i=polygon+%282%2C1%29%2C%281%2C2%29%2C%281%2C3%29%2C%282%2C4%29%2C%284%2C4%29%2C%285%2C3%29%2C%283%2C1%29
Мой код успешно возвращает этот OBB: http://www.wolframalpha.com/input/?i=polygon+%282.5%2C0.5%29%2C%280.5%2C2.5%29%2C%283%2C5%29%2C%285%2C3%29
Я прочитал алгоритм C++, найденный на http://www.geometrictools.com/LibMathematics/Containment/Wm5ContMinBox2.cpp. но я слишком туп, чтобы следовать ему полностью. Он также сильно отличается от другого, подробно описанного в статье выше.
Кто-нибудь знает, какой шаг я пропускаю или вижу ошибку в моем коде для нахождения точечного произведения и перекрестного произведения двух отрезков? Кто-нибудь успешно реализовал этот код раньше на C #и есть пример?