Если точки в трёхмерном пространстве лежат на одной плоскости часто имеет смысл перейти из трёхмерного пространства в двумерное и делать дальнейшие манипуляции там. При необходимости можно затем вернуться обратно. Здесь предложены два варианта таких переходов. Первый из них не сохраняет значения углов и расстояний, но является более быстрым и точным ( из трёх координат две остаются неизменными ). Суть его заключается в проекции на одну из шести плоскостей, нормали которых лежат на осях системы координат ( столько же граней в кубе ). Выбирается та плоскость, нормаль которой ближе всего к нормали исходной плоскости.
typedef Vector2d (* Func3to2) ( const Vector3d & );
Func3to2 getTrans ( const Vector3d & norm );
inline Vector2d trans ( const Vector3d & from, const Vector3d & norm )
{
return getTrans ( norm ) ( from );
}
ArrRef<Vector2d> trans ( CArrRef<Vector3d> from, const Vector3d & norm, ArrRef<Vector2d> to );
class Func2to3
{
Vector3d c; // коэффициенты преобразования
Vector3d (* func) ( const Vector3d &, const Vector2d & );
public:
explicit Func2to3 ( const Plane3d & );
Vector3d operator () ( const Vector2d & v ) const { return func ( c, v ); }
};
inline Vector3d trans ( const Vector2d & from, const Plane3d & plane )
{
return Func2to3 ( plane ) ( from );
}
ArrRef<Vector3d> trans ( CArrRef<Vector2d> from, const Plane3d & plane, ArrRef<Vector3d> to );
Второй способ сохраняет значения углов и расстояний. Для нормали плоскости находятся два вектора таких, чтобы тройка образовала ортогональный базис, а затем для заданных точек определяюся двумерные координаты, как скалярные произведения на найденные вектора.
class OrthoFunc3to2
{
Vector3d vx, vy;
public:
explicit OrthoFunc3to2 ( const Vector3d & norm ) { reper ( norm, vx, vy ); }
Vector2d operator () ( const Vector3d & v ) const { return Vector2d ( vx*v, vy*v ); }
};
inline Vector2d ortho_trans ( const Vector3d & from, const Vector3d & norm )
{
return OrthoFunc3to2 ( norm ) ( from );
}
ArrRef<Vector2d> ortho_trans ( CArrRef<Vector3d> from, const Vector3d & norm, ArrRef<Vector2d> to );
// Функции ортогонального преобразования двухмерных векторов в трёхмерные
class OrthoFunc2to3
{
Vector3d vx, vy, vz;
public:
explicit OrthoFunc2to3 ( const Plane3d & plane ) : vz ( - plane.dist * plane.norm )
{
reper ( plane.norm, vx, vy );
}
Vector3d operator () ( const Vector2d & v ) const { return vx * v.x + vy * v.y + vz; }
};
inline Vector3d ortho_trans ( const Vector2d & from, const Plane3d & plane )
{
return OrthoFunc2to3 ( plane ) ( from );
}
ArrRef<Vector3d> ortho_trans ( CArrRef<Vector2d> from, const Plane3d & plane, ArrRef<Vector3d> to );
Описание шаблонов классов ArrRef и CArrRef находится здесь.
|