Переход из пространства на плоскость и обратно

Если точки в трёхмерном пространстве лежат на одной плоскости часто имеет смысл перейти из трёхмерного пространства в двумерное и делать дальнейшие манипуляции там. При необходимости можно затем вернуться обратно. Здесь предложены два варианта таких переходов. Первый из них не сохраняет значения углов и расстояний, но является более быстрым и точным ( из трёх координат две остаются неизменными ). Суть его заключается в проекции на одну из шести плоскостей, нормали которых лежат на осях системы координат ( столько же граней в кубе ). Выбирается та плоскость, нормаль которой ближе всего к нормали исходной плоскости.

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 находится здесь.
Описание классаVector3d и функции reper находится здесь.
Описание класса Vector2d находится здесь.
Описание класса Plane3d находится здесь.
Исходники находятся в файле trans.cpp.

Наверх