Нахождение ориентированной ограничивающей рамки выпуклой оболочки в XNA с помощью вращающихся штангенциркулей

Возможно, это скорее математический вопрос, чем вопрос программирования, но я пытался реализовать алгоритм вращающегося суппорта в 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 верхний левый угол. Перевернуть список кажется достаточным. Я также удаляю повторяющуюся точку в конце.

После этого процесса данные становятся:

  • Вектор2 (115, 14)
  • Вектор2 (129, 0)
  • Вектор2 (131, 0)
  • Вектор2 (204, 63)
  • Вектор2 (199, 68)
  • Вектор2 (150, 110)
  • Вектор2 (1, 138)
  • Вектор2 (0, 138)

Этот тест не пройден в первом цикле, когда 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 #и есть пример?

6
задан MattB 20 August 2012 в 17:01
поделиться