Пересечение луча и квадрата / прямоугольника в 3D - PullRequest
3 голосов
/ 11 января 2012

Hei.Создаем игру и ищем пересечение лучей на квадрат или прямоугольник только в трехмерном пространстве.Ищите в Интернете и нашли много решений, но ничего, что я не могу понять, есть сценарий пересечения линии и отрезка линии в 2D, но я не могу понять, нужно ли сделать его 3D.Неважно, с какой стороны он пересекает квадрат или прямоугольник, но он должен быть в состоянии извлечь вектор точки пересечения, чтобы позже можно было проверить его на расстояние до точки, если это произошло до или после других пересечений на том же пересечении лучей.

Будем весьма благодарны за любые примеры на python или других похожих языках сценариев.

Редактировать : Не знаю, нужно ли изменять 2D, чтобы показать пример, но сделал новый и опубликовал оба.

//this is the exaple it test a ray onto a plane then look to se if that point is in the rectangle and saves it to test for distanse later
list Faces; //triangle faces
list Points; //

vector FindPoint(){
    //calcute the point of intersection onto the plane and returns it
    //if it can intersect
    //else return ZERO_VECTOR
}

integer point-in-quadrilateral(){
    //return 1 if the point is in the rectangular on the plane
    //else return 0
}

default{

    state_entry(){
        integer n = (Faces != []); //return number of elements
        integer x = 0;
        while(x < n){
            vector intersection = FindPoint( FromList(Faces, x) ); //take     out a element and runs it trough the function
            if(intersection != ZERO_VECTOR){
                integer test = point-in-quadrilateral( FromList(Faces,     x) ); //find out if the point is in rectangular
                if(test == 1){ //if so
                    Points += intersection; //save the point
                }
            }
            ++x;
        }

        float first; //the distanse to the box intersection
        integer l = (Points != []);
        integer d;
        while(d < l){
            if(Dist( FromList(Points, d) ) < first) //if the new distanse     is less then first
                return 0; //then end script
            ++d;
        }
    }

}


//this is the 2D version
vector lineIntersection(vector one, vector two, vector three, vector four){
float bx = two.x - one.x;
float by = two.y - one.y;
float dx = four.x - three.x;
float dy = four.y - three.y; 
float b_dot_d_perp = bx*dy - by*dx;
if(b_dot_d_perp == 0.0) {
    return ZERO_VECTOR;
}
float cx = three.x-one.x; 
float cy = three.y-one.y;
float t = (cx*dy - cy*dx) / b_dot_d_perp; 
if(LineSeg){ //if true tests for line segment
    if((t < 0.0) || (t > 1.0)){
        return ZERO_VECTOR;
    }
    float u = (cx * by - cy * bx) / b_dot_d_perp;
    if((u < 0.0) || (u > 1.0)) {
        return ZERO_VECTOR;
    }
}

return <one.x+t*bx, one.y+t*by, 0.0>; 

}

Ответы [ 3 ]

8 голосов
/ 14 января 2012

Решение очень легко, когда вы определяете луч с точкой (= вектор) и вектором направления, а также прямоугольник с точкой (= вектор) и двумя векторами, представляющими стороны.

Предположим, чтоЛуч определяется как R0 + t * D, где R0 является источником луча, D является единичным вектором, представляющим его направление, а t является его длиной.

Прямоугольник может быть представлен с помощьюугловая точка P0 и два вектора S1 и S2, которые должны представлять стороны (их длина равна длине сторон).Вам понадобится еще один вектор N, нормальный к его поверхности, который равен единичному вектору вдоль перекрестного произведения S1 и S2.

Теперь предположим, что луч пересекает прямоугольник в P.Тогда направление луча D должно составлять ненулевой угол с нормалью N.Это можно проверить, проверив D.N < 0.

Чтобы найти точку пересечения, предположим, что P = R0 + a * D (точка должна быть на луче).Вам нужно найти значение a сейчас.Найдите вектор P0P.Это должно быть перпендикулярно N, что означает P0P.N = 0, которое уменьшается до a = ((P0 - R0).N) / (D.N).

Теперь вам нужно проверить, находится ли точка внутри прямоугольника или нет.Для этого возьмите проекцию Q1 из P0P вдоль S1 и Q2 из P0P вдоль S2.Тогда условие для находящейся внутри точки равно 0 <= length(Q1) <= length(S1) и 0 <= length(Q2) <= length(S2).

. Этот метод подходит для любого типа параллелограммов, а не только для прямоугольников.

3 голосов
/ 11 января 2012

Создайте векторное уравнение для линии в R3, затем найдите пересечение этой линии в плоскости прямоугольника, с которым вы тестируете его.После этого достаточно просто проверить, находится ли эта точка решения в границах.

параметр t решения можно найти с помощью:

t = (a * (x0 - rx) + b * (y0 - ry) + c * (x0 - rz)) / (a * vx + b * vy + c * vz)

где:

a(x - x0) + b(y - y0) + c(z - z0) = 0

- это уравнение плоскости, на которой лежит ваш прямоугольник

, а:

<x, y, z> = <rx + vx * t, ry + vy * t, rz + vz * t>

- векторное уравнение рассматриваемой линии.

noteчто:

<rx, ry, rz>

является начальной точкой векторного уравнения, а

<vx, vy, vz>

является вектором направления указанного выше уравнения

После этого включается параметрт в вашем векторном уравнении даст вам точку для проверки расстояния.

enter image description here

1 голос
/ 11 января 2012

Вы не говорите, выровнен ли квадрат / прямоугольник в 3D с осями координат или нет. Предполагая, что трехмерный прямоугольник R ориентирован произвольно в пространстве, вот один из методов. Сначала пересмотрите ваш луч r с плоскостью, содержащей R . Это может быть достигнуто, требуя масштабный коэффициент s для умножения r и размещения его на плоскости R , а также решение для s . Это дает вам точку p на плоскости. Теперь спроецируйте плоскость и R и p на одну из координат самолеты { xy , yz , zx }. Вам нужно только избегать проецирования перпендикуляра к вектору нормали к плоскости, что всегда возможно. А затем решите четырехточечную задачу в плоскости проекции.

Перед началом проверьте, лежит ли сегмент вашей линии в трехмерной плоскости R , и, если это так, обработайте это отдельно.

...