Определение расстояния от точки внутри ячейки до границы этой ячейки — при перемещении по вектору

#generics #math #trigonometry

#общие сведения #математика #тригонометрия

Вопрос:

Я пытаюсь вычислить, как долго мой объект будет перемещаться в пределах данной ячейки, прежде чем он переместится в другую ячейку.

Это то, что действительно важно для меня, но также мне нужно знать, какова точка пересечения (но было бы тривиально, если бы я знал расстояние от начальной точки).

Некоторые из моих правил игры :

  • Каждая ячейка может иметь разную стоимость перемещения
  • Стоимость перемещения точно такая же по всей ячейке
  • Я перемещаю объект из точки A в точку B по прямой
  • Я знаю начальное местоположение объекта и его направление (как вектор)
  • ячейки имеют границы на строках, которые являются полными целыми числами в сети чисел.

Что мне нужно в конце :

  • где именно у единицы закончатся точки перемещения, если она продолжит движение в указанном направлении.

Итак, для каждой ячейки мне нужно вычислить :

  • расстояние от точки внутри ячейки до границы этой ячейки — при движении вдоль вектора направления.

Я думаю, что пропустил какой-то урок тригонометрии, или я слишком сонный, но я не смог бы найти ни простого решения этой проблемы, ни быстрого и грязного обходного пути.

введите описание изображения здесь

Комментарии:

1. Формула расстояния равна C в квадрате = A в квадрате B в квадрате. Другими словами, найдите изменение в X, возведите его в квадрат, найдите изменение в Y, возведите его в квадрат, сложите квадраты вместе и извлеките квадратный корень.

Ответ №1:

Я создал некоторую функцию, которая делает то, что мне нужно. Я не уверен, будет ли оно полностью надежным (я особенно боюсь некоторого округления с плавающей запятой, которое приведет к размещению точки, которая находится на границе, — на неправильной стороне этой границы и приведет к расстоянию 0). Он также много печатает и назначает много, но я планирую сократить его, улучшить и обновить этот ответ в будущем. Я хотел поделиться тем, что сработало достаточно хорошо — на случай, если у кого-то возникнет подобная проблема / или если я не буду обновлять ее в ближайшее время.

 Vector2D cellCross(Vector2D startPoint, Vector2D direction)
{
    printf("start point [x:%f|y:%f]n",startPoint.x,startPoint.y);
    printf("direction [x:%f|y:%f]n",direction.x,direction.y);
    if (!direction.isNormalized())
    {
        printf("in cellCross() : direction vector must be normalized!n");
        throw "bad arg";
    }

    //cell center is like Vector2D(x,y) from my image
    Vector2D cellCenter (floor(startPoint.x) 0.5 , floor(startPoint.y) 0.5);
    printf("cell center [x:%f|y:%f]n",cellCenter.x,cellCenter.y);
    //relative point is like Vector2D(m,n) from my image
    Vector2D relativePoint ( startPoint.x-cellCenter.x , startPoint.y-cellCenter.y );
    printf("relative point [x:%f|y:%f]n",relativePoint.x,relativePoint.y);
    Vector2D targetCorner;
    if (direction.x>0)
        targetCorner.x=0.5;
    else
        targetCorner.x=-0.5;
    if (direction.y>0)
        targetCorner.y=0.5;
    else
        targetCorner.y=-0.5;
    printf("target corner [x:%f|y:%f]n",targetCorner.x,targetCorner.y);

    double x_diff = targetCorner.x - relativePoint.x;
    double y_diff = targetCorner.y - relativePoint.y;
    printf("x_diff : %fn",x_diff);
    printf("y_diff : %fn",y_diff);

    Vector2D crossPoint;

    if (fabs(x_diff*direction.x) > fabs(y_diff*direction.y))
    { // we will cross at (targetCorner.x,[unknown]y)
        crossPoint.x = targetCorner.x;
        crossPoint.y = relativePoint.y   (direction.y * (x_diff/direction.x) );
    }
    else
    { // we will cross at ([unknown]x,targetCorner.y)
        crossPoint.y = targetCorner.y;
        crossPoint.x = relativePoint.x   (direction.x * (y_diff/direction.y) );
    }
    crossPoint.x =cellCenter.x;
    crossPoint.y =cellCenter.y;
    printf("cross point [x:%f|y:%f]n",crossPoint.x,crossPoint.y);
    printf("distance : %fn",startPoint.distanceTo(crossPoint) );
    return crossPoint;
}
 

Чтобы представить один пример — для :

 Vector2D startPoint (2.0,0.5);
Vector2D direction = Vector2D(10,-30).normalized();
Vector2D endingPoint = cellCross(startPoint,direction);
 

он напечатал :

 start point [x:2.000000|y:0.500000]
direction [x:0.316228|y:-0.948683]
cell center [x:2.500000|y:0.500000]
relative point [x:-0.500000|y:0.000000]
target corner [x:0.500000|y:-0.500000]
x_diff : 1.000000
y_diff : -0.500000
cross point [x:2.166667|y:0.000000]
distance : 0.527046
 

что выглядит примерно как правильный результат для меня и моего калькулятора.

Тогда я мог бы просто умножить расстояние от результата функции на стоимость перемещения для этой плитки и повторить вычисление для следующей плитки, пока мое устройство не перейдет к отрицательному количеству точек перемещения. Быстрая коррекция путем перемещения его по last_tile_movement_cost * movement_points в том же направлении должна поместить его прямо туда, где он должен был приземлиться.