<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 <NAME>, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#ifndef APPLESEED_FOUNDATION_MATH_TRANSFORM_H
#define APPLESEED_FOUNDATION_MATH_TRANSFORM_H

// appleseed.foundation headers.
#include "foundation/math/aabb.h"
#include "foundation/math/matrix.h"
#include "foundation/math/quaternion.h"
#include "foundation/math/ray.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"

// Standard headers.
#include <cassert>

namespace foundation
{

//
// The Transform class represents a 3D affine transformation, and allows
// transformation of points, vectors, normals, rays and bounding boxes
// from parent space to local space (as defined by the transform) and
// from local space to parent space.
//
// Note: normals and ray directions are not required to be unit-length,
// and are never normalized after transformation.
//

template <typename T>
class Transform
{
  public:
    // Matrix and transform types.
    typedef Matrix<T, 4, 4> MatrixType;
    typedef Transform<T> TransformType;

    // Constructors.
    Transform();                                // leave the transformation uninitialized
    explicit Transform(
        const MatrixType& local_to_parent);
    Transform(
        const MatrixType& local_to_parent,
        const MatrixType& parent_to_local);     // must be equal to inverse(local_to_parent)

    // Return the identity transform.
    static Transform identity();

    // Retrieve the transformation matrices.
    const MatrixType& get_local_to_parent() const;
    const MatrixType& get_parent_to_local() const;

    // Compose two transformations.
    TransformType operator*(const TransformType& rhs) const;

    // Transform a 3D point.
    template <typename U> Vector<U, 3> point_to_local(const Vector<U, 3>& p) const;
    template <typename U> Vector<U, 3> point_to_parent(const Vector<U, 3>& p) const;

    // Transform a 3D vector.
    template <typename U> Vector<U, 3> vector_to_local(const Vector<U, 3>& v) const;
    template <typename U> Vector<U, 3> vector_to_parent(const Vector<U, 3>& v) const;

    // Transform a 3D normal.
    template <typename U> Vector<U, 3> normal_to_local(const Vector<U, 3>& n) const;
    template <typename U> Vector<U, 3> normal_to_parent(const Vector<U, 3>& n) const;

    // Transform a 3D ray.
    template <typename U> Ray<U, 3> to_local(const Ray<U, 3>& r) const;
    template <typename U> Ray<U, 3> to_parent(const Ray<U, 3>& r) const;

    // Transform a 3D axis-aligned bounding box.
    // If the bounding box is invalid, it is returned unmodified.
    template <typename U> AABB<U, 3> to_local(const AABB<U, 3>& b) const;
    template <typename U> AABB<U, 3> to_parent(const AABB<U, 3>& b) const;

  private:
    MatrixType  m_local_to_parent;
    MatrixType  m_parent_to_local;
};

// Exact inequality and equality tests.
template <typename T> bool operator!=(const Transform<T>& lhs, const Transform<T>& rhs);
template <typename T> bool operator==(const Transform<T>& lhs, const Transform<T>& rhs);

// Approximate equality tests.
template <typename T> bool feq(const Transform<T>& lhs, const Transform<T>& rhs);
template <typename T> bool feq(const Transform<T>& lhs, const Transform<T>& rhs, const T eps);


//
// Specializations for single and double precision transformations.
//

typedef Transform<float>  Transformf;
typedef Transform<double> Transformd;


//
// The TransformInterpolator class allows to interpolate between two
// rigid transformations (combinations of rotations and translations).
//

template <typename T>
class TransformInterpolator
{
  public:
    // Matrix and transform types.
    typedef Matrix<T, 4, 4> MatrixType;
    typedef Transform<T> TransformType;

    // Constructors.
    TransformInterpolator();                    // leave the interpolator uninitialized
    TransformInterpolator(
        const TransformType& from,
        const TransformType& to);

    // Set the initial and final transformations.
    void set_transforms(
        const TransformType& from,
        const TransformType& to);

    TransformType evaluate(const T t) const;

  private:
    Vector<T, 3>  m_t0, m_t1;
    Quaternion<T> m_q0, m_q1;
};


//
// Specializations for single and double precision transformation interpolators.
//

typedef TransformInterpolator<float>  TransformInterpolatorf;
typedef TransformInterpolator<double> TransformInterpolatord;


//
// Transform class implementation.
//

template <typename T>
inline Transform<T>::Transform()
{
}

template <typename T>
inline Transform<T>::Transform(const MatrixType& local_to_parent)
  : m_local_to_parent(local_to_parent)
  , m_parent_to_local(inverse(local_to_parent))
{
}

template <typename T>
inline Transform<T>::Transform(
    const MatrixType& local_to_parent,
    const MatrixType& parent_to_local)
  : m_local_to_parent(local_to_parent)
  , m_parent_to_local(parent_to_local)
{
    assert(feq(m_parent_to_local, inverse(m_local_to_parent), make_eps<T>(1.0e-6f, 1.0e-9)));
}

template <typename T>
inline Transform<T> Transform<T>::identity()
{
    return Transform(MatrixType::identity());
}

template <typename T>
inline const Matrix<T, 4, 4>& Transform<T>::get_local_to_parent() const
{
    return m_local_to_parent;
}

template <typename T>
inline const Matrix<T, 4, 4>& Transform<T>::get_parent_to_local() const
{
    return m_parent_to_local;
}

template <typename T>
inline Transform<T> Transform<T>::operator*(const TransformType& rhs) const
{
    return Transform<T>(
        rhs.m_local_to_parent * m_local_to_parent,
        m_parent_to_local * rhs.m_parent_to_local);
}

template <typename T>
template <typename U>
inline Vector<U, 3> Transform<T>::point_to_local(const Vector<U, 3>& p) const<commit_msg>replaced a numerically unstable assertion by a more robust variant.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 <NAME>, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#ifndef APPLESEED_FOUNDATION_MATH_TRANSFORM_H
#define APPLESEED_FOUNDATION_MATH_TRANSFORM_H

// appleseed.foundation headers.
#include "foundation/math/aabb.h"
#include "foundation/math/matrix.h"
#include "foundation/math/quaternion.h"
#include "foundation/math/ray.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"

// Standard headers.
#include <cassert>

namespace foundation
{

//
// The Transform class represents a 3D affine transformation, and allows
// transformation of points, vectors, normals, rays and bounding boxes
// from parent space to local space (as defined by the transform) and
// from local space to parent space.
//
// Note: normals and ray directions are not required to be unit-length,
// and are never normalized after transformation.
//

template <typename T>
class Transform
{
  public:
    // Matrix and transform types.
    typedef Matrix<T, 4, 4> MatrixType;
    typedef Transform<T> TransformType;

    // Constructors.
    Transform();                                // leave the transformation uninitialized
    explicit Transform(
        const MatrixType& local_to_parent);
    Transform(
        const MatrixType& local_to_parent,
        const MatrixType& parent_to_local);     // must be equal to inverse(local_to_parent)

    // Return the identity transform.
    static Transform identity();

    // Retrieve the transformation matrices.
    const MatrixType& get_local_to_parent() const;
    const MatrixType& get_parent_to_local() const;

    // Compose two transformations.
    TransformType operator*(const TransformType& rhs) const;

    // Transform a 3D point.
    template <typename U> Vector<U, 3> point_to_local(const Vector<U, 3>& p) const;
    template <typename U> Vector<U, 3> point_to_parent(const Vector<U, 3>& p) const;

    // Transform a 3D vector.
    template <typename U> Vector<U, 3> vector_to_local(const Vector<U, 3>& v) const;
    template <typename U> Vector<U, 3> vector_to_parent(const Vector<U, 3>& v) const;

    // Transform a 3D normal.
    template <typename U> Vector<U, 3> normal_to_local(const Vector<U, 3>& n) const;
    template <typename U> Vector<U, 3> normal_to_parent(const Vector<U, 3>& n) const;

    // Transform a 3D ray.
    template <typename U> Ray<U, 3> to_local(const Ray<U, 3>& r) const;
    template <typename U> Ray<U, 3> to_parent(const Ray<U, 3>& r) const;

    // Transform a 3D axis-aligned bounding box.
    // If the bounding box is invalid, it is returned unmodified.
    template <typename U> AABB<U, 3> to_local(const AABB<U, 3>& b) const;
    template <typename U> AABB<U, 3> to_parent(const AABB<U, 3>& b) const;

  private:
    MatrixType  m_local_to_parent;
    MatrixType  m_parent_to_local;
};

// Exact inequality and equality tests.
template <typename T> bool operator!=(const Transform<T>& lhs, const Transform<T>& rhs);
template <typename T> bool operator==(const Transform<T>& lhs, const Transform<T>& rhs);

// Approximate equality tests.
template <typename T> bool feq(const Transform<T>& lhs, const Transform<T>& rhs);
template <typename T> bool feq(const Transform<T>& lhs, const Transform<T>& rhs, const T eps);


//
// Specializations for single and double precision transformations.
//

typedef Transform<float>  Transformf;
typedef Transform<double> Transformd;


//
// The TransformInterpolator class allows to interpolate between two
// rigid transformations (combinations of rotations and translations).
//

template <typename T>
class TransformInterpolator
{
  public:
    // Matrix and transform types.
    typedef Matrix<T, 4, 4> MatrixType;
    typedef Transform<T> TransformType;

    // Constructors.
    TransformInterpolator();                    // leave the interpolator uninitialized
    TransformInterpolator(
        const TransformType& from,
        const TransformType& to);

    // Set the initial and final transformations.
    void set_transforms(
        const TransformType& from,
        const TransformType& to);

    TransformType evaluate(const T t) const;

  private:
    Vector<T, 3>  m_t0, m_t1;
    Quaternion<T> m_q0, m_q1;
};


//
// Specializations for single and double precision transformation interpolators.
//

typedef TransformInterpolator<float>  TransformInterpolatorf;
typedef TransformInterpolator<double> TransformInterpolatord;


//
// Transform class implementation.
//

template <typename T>
inline Transform<T>::Transform()
{
}

template <typename T>
inline Transform<T>::Transform(const MatrixType& local_to_parent)
  : m_local_to_parent(local_to_parent)
  , m_parent_to_local(inverse(local_to_parent))
{
}

template <typename T>
inline Transform<T>::Transform(
    const MatrixType& local_to_parent,
    const MatrixType& parent_to_local)
  : m_local_to_parent(local_to_parent)
  , m_parent_to_local(parent_to_local)
{
    assert(feq(m_local_to_parent * m_parent_to_local, MatrixType::identity(), make_eps<T>(1.0e-6f, 1.0e-9)));
}

template <typename T>
inline Transform<T> Transform<T>::identity()
{
    return Transform(MatrixType::identity());
}

template <typename T>
inline const Matrix<T, 4, 4>& Transform<T>::get_local_to_parent() const
{
    return m_local_to_parent;
}

template <typename T>
inline const Matrix<T, 4, 4>& Transform<T>::get_parent_to_local() const
{
    return m_parent_to_local;
}

template <typename T>
inline Transform<T> Transform<T>::operator*(const TransformType& rhs) const
{
    return Transform<T>(
        rhs.m_local_to_parent * m_local_to_parent,
        m_parent_to_local * rhs.m_parent_to_local);
}

template <typename T>
template <typename U>
inline Vector<U, 3> Transform<T>::point_to_local(const Vector<U, 3>& p) const
{'fraction_non_alphanumeric': 0.10014245014245014, 'fraction_numerical': 0.007834757834757835, 'mean_word_length': 3.9808442710180914, 'pattern_counts': {'":': 0, '<': 165, '<?xml version=': 0, '>': 165, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6189933', 'n_tokens_mistral': 4412, 'n_tokens_neox': 4085, 'n_words': 1451}