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