/// <summary>
/// Возвращает 2 точки пересечения луча с параллепипедом Extents3d или пустой список если если пересечений нет
/// </summary>
/// <param name="rayPt"></param>
/// <param name="rayVector"></param>
/// <param name="extents"></param>
/// <returns></returns>
private static List<Point3d> CalcRayExtendsIntersection
(Point3d rayPt, Vector3d rayVector, Extents3d extents)
{
List<Point3d> pts = new List<Point3d>();
//Проверить на пересечение со всеми 6 гранями
//Каждая из 6 плоскостей граней параллельна двум осям системы координат,
//поэтому пересечение находится подстановкой максимальных и минимальных координат extents
//в каноническое уравнение прямой - http://mathprofi.ru/uravnenija_pryamoi_v_prostranstve.html
//После нахождения точки пересечения с плоскостью, определить попадает ли она в габариты соответствующей грани
double minX = extents.MinPoint.X;
double minY = extents.MinPoint.Y;
double minZ = extents.MinPoint.Z;
double maxX = extents.MaxPoint.X;
double maxY = extents.MaxPoint.Y;
double maxZ = extents.MaxPoint.Z;
if(rayVector.X!=0)
{
double x = minX;
double n = ((x - rayPt.X) / rayVector.X);
double y = n * rayVector.Y + rayPt.Y;
double z = n * rayVector.Z + rayPt.Z;
if (y >= minY && y <= maxY && z >= minZ && z <= maxZ)//Здесь можно использовать какой-нибудь допуск
{
pts.Add(new Point3d(x, y, z));
}
x = maxX;
n = ((x - rayPt.X) / rayVector.X);
y = n * rayVector.Y + rayPt.Y;
z = n * rayVector.Z + rayPt.Z;
if (y >= minY && y <= maxY && z >= minZ && z <= maxZ)
{
pts.Add(new Point3d(x, y, z));
if (pts.Count > 1) return pts;
}
}
if (rayVector.Y != 0)
{
double y = minY;
double n = ((y - rayPt.Y) / rayVector.Y);
double x = n * rayVector.X + rayPt.X;
double z = n * rayVector.Z + rayPt.Z;
if (x >= minX && x <= maxX && z >= minZ && z <= maxZ)
{
pts.Add(new Point3d(x, y, z));
if (pts.Count > 1) return pts;
}
y = maxY;
n = ((y - rayPt.Y) / rayVector.Y);
x = n * rayVector.X + rayPt.X;
z = n * rayVector.Z + rayPt.Z;
if (x >= minX && x <= maxX && z >= minZ && z <= maxZ)
{
pts.Add(new Point3d(x, y, z));
if (pts.Count > 1) return pts;
}
}
if (rayVector.Z != 0)
{
double z = minZ;
double n = ((z - rayPt.Z) / rayVector.Z);
double x = n * rayVector.X + rayPt.X;
double y = n * rayVector.Y + rayPt.Y;
if (x >= minX && x <= maxX && y >= minY && y <= maxY)
{
pts.Add(new Point3d(x, y, z));
if (pts.Count > 1) return pts;
}
z = maxZ;
n = ((z - rayPt.Z) / rayVector.Z);
x = n * rayVector.X + rayPt.X;
y = n * rayVector.Y + rayPt.Y;
if (x >= minX && x <= maxX && y >= minY && y <= maxY)
{
pts.Add(new Point3d(x, y, z));
if (pts.Count > 1) return pts;
}
}
return pts;
}