Пересечение прямой и плоскости
Пересечение: Прямая (или отрезок) и плоскость. Плоскость задана тремя точками, прямая (или отрезок) начальной и конечными точками. Очевидно, эта задача, как и многие подобные ей, может быть решена путем составления системы. Хотелось бы предложить более геометричный метод, который гораздо удобней в большинстве случаев.
Будем обозначать 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)