Пересечение прямой и плоскости
Пересечение: Прямая (или отрезок) и плоскость. Плоскость задана тремя точками, прямая (или отрезок) начальной и конечными точками. Очевидно, эта задача, как и многие подобные ей, может быть решена путем составления системы. Хотелось бы предложить более геометричный метод, который гораздо удобней в большинстве случаев.
Будем обозначать A,B,C - точки плоскости, X,Y - точки прямой(концы отрезка), DotProduct - скалярное произведение, VectorProduct - векторное произведение. O - искомое множество точек пересечения
N = VectorProduct ( B - A, C - A )
N = N / | N | - нормаль к плоскости // в принципе это можно и не делать
V = A - X
// расстояние до плоскости по нормали
d = DotProduct ( N, V )
W = Y - X
// приближение к плоскости по нормали при прохождении отрезка
e = DotProduct ( N, W )
if( e!=0 )
O = X + W * d/e; // одна точка
else if( d==0)
O =X + W * (anything) // прямая принадлежит плоскости
else
O = empty; // прямая параллельна плоскости
-----------------------------------------------------------------------
Было запрограммированно в Делфи следующим образом:
type xyz = record x,y,z : real; end; var NotIntersectPlaneLine:boolean; Function CreateVector(A,B:xyz):xyz; //Функция создает вектор из двух точек A,B. //АВ = (В.х-А.х,В.y-А.y,В.z-А.z) begin CreateVector.x := B.x-A.x; CreateVector.y := B.y-A.y; CreateVector.z := B.z-A.z; end; Function VectorProduct(A,B:xyz):xyz; //Векторное произведение begin VP.x := A.y*B.z-B.y*A.z; VP.y := A.z*B.x-B.z*A.x; VP.z := A.x*B.y-B.x*A.y; end; Function DotProduct(A,B:xyz):real; //Скалярное произведение begin SP := A.x*B.x + A.y*B.y + A.z*B.z; end; Procedure Normalize(var A:xyz); //Привести длину вектора к единице var R,mlr:real; begin mlr := sqrt(sqr(A.x)+sqr(A.y)+sqr(A.z)); A.x := A.x/mlr; A.y := A.y/mlr; A.z := A.z/mlr; end; Function PlaneIntersectLine(A,B,C,X,Y:xyz):xyz; //Итак на входе у нас три точки плоскости A,B,C и две точки прямой X,Y var N,V,W : xyz; e,d : real; begin NotIntersectPlaneLine := true; N := VectorProduct(CreateVector(A,B),CreateVector(A,C)); Normalize(N); V := CreateVector(X,A); // расстояние до плоскости по нормали d := DotProduct(N,V); W := CreateVector(X,Y); // приближение к плоскости по нормали при прохождении отрезка e := DotProduct(N,W); if e<>0 then // одна точка, //в любом другом случае(принадлежит, или параллельна плоскости) //флаг сигнализирующий что единственная точка не найдена будет правдой begin PlaneIntersectLine.x := X.x + W.x*d/e; PlaneIntersectLine.y := X.y + W.y*d/e; PlaneIntersectLine.z := X.z + W.z*d/e; NotIntersectPlaneLine := false; end; end;
Проект делфи как пример, где указываются точки плоскости и прямой можно скачать по этому адресу
http://www.gamedev.ru/download/?id=7125
8 апреля 2008 (Обновление: 11 мар 2024)