mirror of https://github.com/KLayout/klayout.git
2575 lines
58 KiB
C++
2575 lines
58 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#ifndef HDR_dbTrans
|
|
#define HDR_dbTrans
|
|
|
|
#include "dbCommon.h"
|
|
|
|
#include "dbPoint.h"
|
|
#include "dbVector.h"
|
|
#include "dbMatrix.h"
|
|
#include "tlString.h"
|
|
#include "tlAssert.h"
|
|
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <math.h>
|
|
|
|
namespace tl {
|
|
class Extractor;
|
|
}
|
|
|
|
namespace db {
|
|
|
|
template <class I, class F, class R = double> class complex_trans;
|
|
template <class C> class simple_trans;
|
|
template <class C> class disp_trans;
|
|
template <class C> class fixpoint_trans;
|
|
|
|
/**
|
|
* @brief Provide the default predicates and properties for transformations for the coordinate type C
|
|
*/
|
|
|
|
template <class C>
|
|
struct default_trans
|
|
{
|
|
typedef C coord_type;
|
|
typedef C target_coord_type;
|
|
typedef vector<C> displacement_type;
|
|
|
|
/**
|
|
* @brief Mirror predicate
|
|
*
|
|
* If this predicate is true, the transformation will first mirror the coordinates
|
|
* at the x-axis before applying transformations.
|
|
*/
|
|
bool is_mirror () const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief This transformation is always unity
|
|
*/
|
|
bool is_unity () const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Orthogonal predicate
|
|
*
|
|
* This predicate tells if the transformation is orthogonal, i.e. does only provide rotations by
|
|
* multiple of 90 degree.
|
|
*/
|
|
bool is_ortho () const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Magnification predicate
|
|
*
|
|
* This predicate tells if the transformation is magnifying
|
|
*/
|
|
bool is_mag () const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief The default rotation code
|
|
*/
|
|
int rot () const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief The default rotation code
|
|
*/
|
|
fixpoint_trans<C> fp_trans () const
|
|
{
|
|
return fixpoint_trans<C> (0);
|
|
}
|
|
|
|
/**
|
|
* @brief The default displacement
|
|
*/
|
|
displacement_type disp () const
|
|
{
|
|
return displacement_type ();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief A dummy unit transformation
|
|
*
|
|
* This transformation is supplied in order to allow generic transformation
|
|
* parameters being passed a "dummy" transformation.
|
|
* Even though this transformation does not require a coordinate type, it is provided
|
|
* to fulfil the contract.
|
|
*/
|
|
|
|
template <class C>
|
|
struct unit_trans
|
|
: public default_trans<C>
|
|
{
|
|
typedef C coord_type;
|
|
typedef C target_coord_type;
|
|
typedef typename coord_traits<C>::distance_type distance_type;
|
|
typedef vector<C> displacement_type;
|
|
typedef unit_trans inverse_trans;
|
|
|
|
/**
|
|
* @brief The default constructor (unity transformation)
|
|
*/
|
|
unit_trans ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Copy ctor (which basically does nothing)
|
|
*/
|
|
template <class D>
|
|
explicit unit_trans (const unit_trans<D> &)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: does nothing
|
|
*/
|
|
explicit unit_trans (const simple_trans<C> &)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: does nothing
|
|
*/
|
|
explicit unit_trans (const disp_trans<C> &)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: does nothing
|
|
*/
|
|
template <class R>
|
|
explicit unit_trans (const complex_trans<C, C, R> &)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief (dummy) equality
|
|
*/
|
|
bool operator== (unit_trans /*b*/) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief (dummy) fuzzy equality
|
|
*/
|
|
bool equal (unit_trans /*b*/) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief A (fuzzy) inequality test
|
|
*/
|
|
bool not_equal (const unit_trans &t) const
|
|
{
|
|
return ! equal (t);
|
|
}
|
|
|
|
/**
|
|
* @brief (dummy) inequality
|
|
*/
|
|
bool operator!= (unit_trans /*b*/) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief (dummy) comparison
|
|
*/
|
|
bool operator< (unit_trans /*b*/) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief (dummy) fuzzy less comparison
|
|
*/
|
|
bool less (unit_trans /*b*/) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Assignment (which basically does nothing)
|
|
*/
|
|
unit_trans &operator= (const unit_trans &)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*/
|
|
unit_trans inverted () const
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief In-place inversion
|
|
*/
|
|
unit_trans invert ()
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*/
|
|
point<C> operator() (const point<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*/
|
|
vector<C> operator() (const vector<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point (non-operator version)
|
|
*/
|
|
point<C> trans (const point<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector (non-operator version)
|
|
*/
|
|
vector<C> trans (const vector<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Transform a distance
|
|
*/
|
|
distance_type ctrans (distance_type d) const
|
|
{
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
return std::string ("");
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 2d matrix
|
|
*/
|
|
Matrix2d to_matrix2d () const
|
|
{
|
|
return Matrix2d (1.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 3d matrix
|
|
*/
|
|
Matrix3d to_matrix3d () const
|
|
{
|
|
return Matrix3d (1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief Dummy Multiplication (concatenation) of unit transformations
|
|
*/
|
|
template <class C>
|
|
inline unit_trans<C>
|
|
operator* (const unit_trans<C> & /*t1*/, const unit_trans<C> & /*t2*/)
|
|
{
|
|
return unit_trans<C>();
|
|
}
|
|
|
|
/**
|
|
* @brief A fixpoint transformation
|
|
*
|
|
* The fixpoint transformation applies a rotation and/or mirroring operation.
|
|
* Even though this transformation does not require a coordinate type, it is provided
|
|
* to fulfil the contract.
|
|
*/
|
|
|
|
template <class C>
|
|
class fixpoint_trans
|
|
: public default_trans<C>
|
|
{
|
|
public:
|
|
typedef C coord_type;
|
|
typedef C target_coord_type;
|
|
typedef typename coord_traits<C>::distance_type distance_type;
|
|
typedef vector<C> displacement_type;
|
|
typedef fixpoint_trans inverse_trans;
|
|
|
|
/**
|
|
* @brief The default constructor (unity transformation)
|
|
*/
|
|
fixpoint_trans ()
|
|
: m_f (0)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true, if the transformation is unity
|
|
*/
|
|
bool is_unity () const
|
|
{
|
|
return m_f == 0;
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using angle and mirror flag
|
|
*
|
|
* The sequence of operations is: mirroring at x axis,
|
|
* rotation, application of displacement.
|
|
*
|
|
* @param rot The rotation in units of 90 degree
|
|
* @param mirrx True, if mirrored at x axis
|
|
*/
|
|
fixpoint_trans (int rot, bool mirrx)
|
|
: m_f ((rot & 3) + (mirrx ? 4 : 0))
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The copy constructor
|
|
*
|
|
* @param d The source from which to copy
|
|
*/
|
|
template <class D>
|
|
explicit fixpoint_trans (const fixpoint_trans<D> &d)
|
|
: m_f (d.rot ())
|
|
{ }
|
|
|
|
/**
|
|
* @brief The standard constructor using a code rather than angle and mirror and no displacement
|
|
*
|
|
* @param f The rotation/mirror code (r0 .. m135 constants)
|
|
*/
|
|
explicit fixpoint_trans (int f)
|
|
: m_f (f)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The rotation/mirror codes
|
|
*/
|
|
static const int r0 = 0; // No rotation
|
|
static const int r90 = 1; // Rotation by 90 degree counterclockwise
|
|
static const int r180 = 2; // Rotation by 180 degree counterclockwise
|
|
static const int r270 = 3; // Rotation by 270 degree counterclockwise
|
|
static const int m0 = 4; // Mirroring at x-axis
|
|
static const int m45 = 5; // Mirroring at 45-degree axis
|
|
static const int m90 = 6; // Mirroring at y-axis
|
|
static const int m135 = 7; // Mirroring at 135-degree axis
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*
|
|
* Returns the inverted transformation
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
fixpoint_trans<C> inverted () const
|
|
{
|
|
fixpoint_trans t (*this);
|
|
t.invert ();
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief In-place inversion
|
|
*
|
|
* Inverts the transformation and replaces *this by the
|
|
* inverted one.
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
fixpoint_trans<C> invert ()
|
|
{
|
|
if (m_f < 4) {
|
|
m_f = (4 - m_f) & 3;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 2d matrix
|
|
*/
|
|
Matrix2d to_matrix2d () const
|
|
{
|
|
vector<C> tx = operator () (vector<C> (1, 0));
|
|
vector<C> ty = operator () (vector<C> (0, 1));
|
|
return Matrix2d (tx.x (), ty.x (), tx.y (), ty.y ());
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 3d matrix
|
|
*/
|
|
Matrix3d to_matrix3d () const
|
|
{
|
|
return Matrix3d (to_matrix2d ());
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
point<C> operator() (const point<C> &p) const
|
|
{
|
|
switch (m_f) {
|
|
default:
|
|
return point<C> (p.x (), p.y ());
|
|
case 1:
|
|
return point<C> (-p.y (), p.x ());
|
|
case 2:
|
|
return point<C> (-p.x (), -p.y ());
|
|
case 3:
|
|
return point<C> (p.y (), -p.x ());
|
|
case 4:
|
|
return point<C> (p.x (), -p.y ());
|
|
case 5:
|
|
return point<C> (p.y (), p.x ());
|
|
case 6:
|
|
return point<C> (-p.x (), p.y ());
|
|
case 7:
|
|
return point<C> (-p.y (), -p.x ());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point (non-operator version)
|
|
*/
|
|
point<C> trans (const point<C> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*
|
|
* The operator() method transforms the given vector.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
vector<C> operator() (const vector<C> &p) const
|
|
{
|
|
switch (m_f) {
|
|
default:
|
|
return vector<C> (p.x (), p.y ());
|
|
case 1:
|
|
return vector<C> (-p.y (), p.x ());
|
|
case 2:
|
|
return vector<C> (-p.x (), -p.y ());
|
|
case 3:
|
|
return vector<C> (p.y (), -p.x ());
|
|
case 4:
|
|
return vector<C> (p.x (), -p.y ());
|
|
case 5:
|
|
return vector<C> (p.y (), p.x ());
|
|
case 6:
|
|
return vector<C> (-p.x (), p.y ());
|
|
case 7:
|
|
return vector<C> (-p.y (), -p.x ());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector (non-operator version)
|
|
*/
|
|
vector<C> trans (const vector<C> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief Transform a fixpoint transformation
|
|
*/
|
|
fixpoint_trans ftrans (fixpoint_trans t) const
|
|
{
|
|
fixpoint_trans tt (*this);
|
|
tt *= t;
|
|
return tt;
|
|
}
|
|
|
|
/**
|
|
* @brief Extract the fixpoint transformation part (this is identical to *this in this case)
|
|
*/
|
|
const fixpoint_trans &fp_trans () const
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Transform a distance
|
|
*/
|
|
distance_type ctrans (distance_type d) const
|
|
{
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* The *= operator modifies the transformation by
|
|
* replacing *this with *this * t (t is applied before *this).
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The modified transformation
|
|
*/
|
|
fixpoint_trans &operator*= (const fixpoint_trans &t)
|
|
{
|
|
m_f = ((m_f + (1 - ((m_f & 4) >> 1)) * t.m_f) & 3) + ((m_f ^ t.m_f) & 4);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief A sorting criterion
|
|
*/
|
|
bool operator< (const fixpoint_trans &t) const
|
|
{
|
|
return m_f < t.m_f;
|
|
}
|
|
|
|
/**
|
|
* @brief A (dummy) fuzzy less criterion
|
|
*/
|
|
bool less (const fixpoint_trans &t) const
|
|
{
|
|
return m_f < t.m_f;
|
|
}
|
|
|
|
/**
|
|
* @brief Equality test
|
|
*/
|
|
bool operator== (const fixpoint_trans &t) const
|
|
{
|
|
return m_f == t.m_f;
|
|
}
|
|
|
|
/**
|
|
* @brief Inequality test
|
|
*/
|
|
bool operator!= (const fixpoint_trans &t) const
|
|
{
|
|
return !operator== (t);
|
|
}
|
|
|
|
/**
|
|
* @brief A (dummy) fuzzy equality test
|
|
*/
|
|
bool equal (const fixpoint_trans &t) const
|
|
{
|
|
return m_f == t.m_f;
|
|
}
|
|
|
|
/**
|
|
* @brief A (dummy) fuzzy inequality test
|
|
*/
|
|
bool not_equal (const fixpoint_trans &t) const
|
|
{
|
|
return ! equal (t);
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
const char *ms [] = { "r0", "r90", "r180", "r270",
|
|
"m0", "m45", "m90", "m135" };
|
|
|
|
return std::string ((m_f < 0 || m_f >= 8) ? "*" : ms [m_f]);
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the rotation/mirror code
|
|
*/
|
|
int rot () const
|
|
{
|
|
return m_f;
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the angle (in units of 90 degree)
|
|
*/
|
|
int angle () const
|
|
{
|
|
return m_f & 3;
|
|
}
|
|
|
|
/**
|
|
* @brief Mirror flag.
|
|
*
|
|
* The result of this operation is true, if the transformation is
|
|
* mirroring, i.e. det(M) == -1.
|
|
*/
|
|
bool is_mirror () const
|
|
{
|
|
return m_f >= 4;
|
|
}
|
|
|
|
private:
|
|
int m_f;
|
|
};
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* t = t1 * t2 is the resulting transformation that is effectively
|
|
* applied if first t2 and then t1 is applied.
|
|
*
|
|
* @param t1 The transformation to apply last
|
|
* @param t2 The transformation to apply first
|
|
* @return t1 * t2
|
|
*/
|
|
template <class C>
|
|
inline fixpoint_trans<C>
|
|
operator* (const fixpoint_trans<C> &t1, const fixpoint_trans<C> &t2)
|
|
{
|
|
fixpoint_trans<C> t (t1);
|
|
t *= t2;
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief Output stream insertion operator
|
|
*/
|
|
template <class C>
|
|
inline std::ostream &
|
|
operator<< (std::ostream &os, const fixpoint_trans<C> &t)
|
|
{
|
|
return (os << t.to_string ());
|
|
}
|
|
|
|
/**
|
|
* @brief A displacement transformation
|
|
*
|
|
* The displacement transformation applies a displacement vector, but no rotation.
|
|
*/
|
|
|
|
template <class C>
|
|
class disp_trans
|
|
: public default_trans<C>
|
|
{
|
|
public:
|
|
typedef C coord_type;
|
|
typedef C target_coord_type;
|
|
typedef typename coord_traits<C>::distance_type distance_type;
|
|
typedef vector<C> displacement_type;
|
|
typedef disp_trans<C> inverse_trans;
|
|
|
|
/**
|
|
* @brief The default constructor (unity transformation)
|
|
*/
|
|
disp_trans ()
|
|
: m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The "conversion" from the unit transformation to a displacement
|
|
*/
|
|
explicit disp_trans (unit_trans<C>)
|
|
: m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The copy constructor that converts also
|
|
*
|
|
* The copy constructor allows to convert between different
|
|
* coordinate types, if possible.
|
|
*
|
|
* @param d The source from which to copy
|
|
*/
|
|
template <class D>
|
|
explicit disp_trans (const disp_trans<D> &d)
|
|
: m_u (d.disp ())
|
|
{ }
|
|
|
|
/**
|
|
* @brief The standard constructor using a displacement only (as vector)
|
|
*
|
|
* @param u The displacement
|
|
*/
|
|
explicit disp_trans (const displacement_type &u)
|
|
: m_u (u.x (), u.y ())
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: extracts the displacement part of a complex transformation
|
|
*/
|
|
explicit disp_trans (const simple_trans<C> &st)
|
|
: m_u (st.disp ())
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: extracts the displacement part of a complex transformation
|
|
*/
|
|
template <class R>
|
|
explicit disp_trans (const complex_trans<C, C, R> &ct)
|
|
: m_u (ct.disp ())
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true, if the transformation is unity
|
|
*/
|
|
bool is_unity () const
|
|
{
|
|
return m_u.equal (displacement_type ());
|
|
}
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*
|
|
* Returns the inverted transformation
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
disp_trans<C> inverted () const
|
|
{
|
|
disp_trans<C> t (*this);
|
|
t.invert ();
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief In-place inversion
|
|
*
|
|
* Inverts the transformation and replaces *this by the
|
|
* inverted one.
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
disp_trans<C> invert ()
|
|
{
|
|
m_u = -m_u;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 2d matrix
|
|
*/
|
|
Matrix2d to_matrix2d () const
|
|
{
|
|
return Matrix2d (1.0, 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 3d matrix
|
|
*/
|
|
Matrix3d to_matrix3d () const
|
|
{
|
|
return Matrix3d (1.0, 0.0, 0.0, 1.0, m_u.x (), m_u.y (), 0.0, 0.0);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a distance
|
|
*
|
|
* The ctrans method transforms the given distance.
|
|
* e = t(d). For the displacement transformations, there
|
|
* is no magnification and no modification of the distance
|
|
* therefore.
|
|
*
|
|
* @param d The distance to transform
|
|
* @return The transformed distance
|
|
*/
|
|
distance_type ctrans (distance_type d) const
|
|
{
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
point<C> operator() (const point<C> &p) const
|
|
{
|
|
return point<C> (p) + m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point (non-operator version)
|
|
*/
|
|
point<C> trans (const point<C> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*
|
|
* The operator() method transforms the given vector.
|
|
* q = t(p)
|
|
*
|
|
* @param p The vector to transform
|
|
* @return The transformed vector
|
|
*/
|
|
vector<C> operator() (const vector<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector (non-operator version)
|
|
*/
|
|
vector<C> trans (const vector<C> &p) const
|
|
{
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* The *= operator modifies the transformation by
|
|
* replacing *this with *this * t (t is applied before *this).
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The modified transformation
|
|
*/
|
|
disp_trans<C> &operator*= (const disp_trans<C> &t)
|
|
{
|
|
m_u += t.m_u;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief A sorting criterion
|
|
*/
|
|
bool operator< (const disp_trans<C> &t) const
|
|
{
|
|
return m_u < t.m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy sorting criterion
|
|
*/
|
|
bool less (const disp_trans<C> &t) const
|
|
{
|
|
return m_u.less (t.m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief Equality test
|
|
*/
|
|
bool operator== (const disp_trans<C> &t) const
|
|
{
|
|
return m_u == t.m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief Inequality test
|
|
*/
|
|
bool operator!= (const disp_trans<C> &t) const
|
|
{
|
|
return !operator== (t);
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy equality test
|
|
*/
|
|
bool equal (const disp_trans<C> &t) const
|
|
{
|
|
return m_u.equal (t.m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy inequality test
|
|
*/
|
|
bool not_equal (const disp_trans<C> &t) const
|
|
{
|
|
return ! equal (t);
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
return m_u.to_string ();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the displacement
|
|
*/
|
|
const displacement_type &disp () const
|
|
{
|
|
return m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the displacement
|
|
*/
|
|
void disp (const displacement_type &u)
|
|
{
|
|
m_u = u;
|
|
}
|
|
|
|
/**
|
|
* @brief Mirror predicate
|
|
*/
|
|
bool is_mirror () const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief Extract the fixpoint transformation part (this is a r0 contribution in this case)
|
|
*/
|
|
fixpoint_trans<C> fp_trans () const
|
|
{
|
|
return fixpoint_trans<C> ();
|
|
}
|
|
|
|
private:
|
|
displacement_type m_u;
|
|
};
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* t = t1 * t2 is the resulting transformation that is effectively
|
|
* applied if first t2 and then t1 is applied.
|
|
*
|
|
* @param t1 The transformation to apply last
|
|
* @param t2 The transformation to apply first
|
|
* @return t1 * t2
|
|
*/
|
|
template <class C>
|
|
inline disp_trans<C>
|
|
operator* (const disp_trans<C> &t1, const disp_trans<C> &t2)
|
|
{
|
|
disp_trans<C> t (t1);
|
|
t *= t2;
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief Output stream insertion operator
|
|
*/
|
|
template <class C>
|
|
inline std::ostream &
|
|
operator<< (std::ostream &os, const disp_trans<C> &t)
|
|
{
|
|
return (os << t.to_string ());
|
|
}
|
|
|
|
/**
|
|
* @brief A simple transformation
|
|
*
|
|
* The simple transformation applies a displacement vector
|
|
* and a simple fixpoint transformation.
|
|
*/
|
|
|
|
template <class C>
|
|
class simple_trans
|
|
: public fixpoint_trans<C>
|
|
{
|
|
public:
|
|
typedef C coord_type;
|
|
typedef C target_coord_type;
|
|
typedef typename coord_traits<C>::distance_type distance_type;
|
|
typedef vector<C> displacement_type;
|
|
typedef simple_trans<C> inverse_trans;
|
|
|
|
/**
|
|
* @brief The default constructor (unity transformation)
|
|
*/
|
|
simple_trans ()
|
|
: fixpoint_trans<C> (0), m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a fixpoint transformation
|
|
*/
|
|
explicit simple_trans (fixpoint_trans<C> f)
|
|
: fixpoint_trans<C> (f), m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a unit transformation
|
|
*/
|
|
explicit simple_trans (unit_trans<C>)
|
|
: fixpoint_trans<C> (0), m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a displacement transformation
|
|
*/
|
|
explicit simple_trans (const disp_trans<C> &d)
|
|
: fixpoint_trans<C> (0), m_u (d.disp ())
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The copy constructor
|
|
*
|
|
* @param d The source from which to copy
|
|
*/
|
|
simple_trans (const simple_trans<C> &d)
|
|
: fixpoint_trans<C> (d.rot ()), m_u (d.disp ())
|
|
{ }
|
|
|
|
/**
|
|
* @brief The copy constructor that converts to a different coordinate type also
|
|
*
|
|
* The copy constructor allows to convert between different
|
|
* coordinate types, if possible.
|
|
*
|
|
* @param d The source from which to copy
|
|
*/
|
|
template <class D>
|
|
explicit simple_trans (const simple_trans<D> &d)
|
|
: fixpoint_trans<C> (d.rot ()), m_u (d.disp ())
|
|
{ }
|
|
|
|
/**
|
|
* @brief The standard constructor using angle and mirror flag
|
|
*
|
|
* The sequence of operations is: mirroring at x axis,
|
|
* rotation, application of displacement.
|
|
*
|
|
* @param rot The rotation in units of 90 degree
|
|
* @param mirrx True, if mirrored at x axis
|
|
* @param u The displacement
|
|
*/
|
|
simple_trans (int rot, bool mirrx, const vector<C> &u)
|
|
: fixpoint_trans<C> (rot, mirrx), m_u (u)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor for a displacement-only transformation
|
|
*
|
|
* @param u The displacement
|
|
*/
|
|
explicit simple_trans (const vector<C> &u)
|
|
: fixpoint_trans<C> (), m_u (u)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using a code rather than angle and mirror
|
|
*
|
|
* @param f The rotation/mirror code (r0 .. m135 constants)
|
|
* @param u The displacement
|
|
*/
|
|
simple_trans (int f, const vector<C> &u)
|
|
: fixpoint_trans<C> (f), m_u (u)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Downcast: extracts the simple transformation part of a complex transformation
|
|
*/
|
|
template <class R>
|
|
explicit simple_trans (const complex_trans<C, C, R> &ct)
|
|
: fixpoint_trans<C> (ct.fp_trans ()), m_u (ct.disp ())
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using a code rather than angle and mirror and no displacement
|
|
*
|
|
* @param f The rotation/mirror code (r0 .. m135 constants)
|
|
*/
|
|
explicit simple_trans (int f)
|
|
: fixpoint_trans<C> (f), m_u ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*
|
|
* Returns the inverted transformation
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
simple_trans<C> inverted () const
|
|
{
|
|
simple_trans<C> t (*this);
|
|
t.invert ();
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief In-place inversion
|
|
*
|
|
* Inverts the transformation and replaces *this by the
|
|
* inverted one.
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
simple_trans<C> invert ()
|
|
{
|
|
fixpoint_trans<C>::invert ();
|
|
vector<C> u = m_u;
|
|
m_u = -operator() (u);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true, if the transformation is unity
|
|
*/
|
|
bool is_unity () const
|
|
{
|
|
return m_u.equal (displacement_type ()) && fixpoint_trans<C>::is_unity ();
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a distance
|
|
*
|
|
* The ctrans method transforms the given distance.
|
|
* e = t(d). For the simple transformations, there
|
|
* is no magnification and no modification of the distance
|
|
* therefore.
|
|
*
|
|
* @param d The distance to transform
|
|
* @return The transformed distance
|
|
*/
|
|
distance_type ctrans (distance_type d) const
|
|
{
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
point<C> operator() (const point<C> &p) const
|
|
{
|
|
return point<C> (fixpoint_trans<C>::operator() (p)) + m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point (non-operator version)
|
|
*/
|
|
point<C> trans (const point<C> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*
|
|
* The operator() method transforms the given vector.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed vector
|
|
*/
|
|
vector<C> operator() (const vector<C> &p) const
|
|
{
|
|
return vector<C> (fixpoint_trans<C>::operator() (p));
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector (non-operator version)
|
|
*/
|
|
vector<C> trans (const vector<C> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief Transform a fixpoint transformation
|
|
*/
|
|
fixpoint_trans<C> ftrans (fixpoint_trans<C> t) const
|
|
{
|
|
return fixpoint_trans<C>::ftrans (t);
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 2d matrix
|
|
*/
|
|
Matrix2d to_matrix2d () const
|
|
{
|
|
return fp_trans ().to_matrix2d ();
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 3d matrix
|
|
*/
|
|
Matrix3d to_matrix3d () const
|
|
{
|
|
return Matrix3d (1.0, 0.0, 0.0, 1.0, m_u.x (), m_u.y (), 0.0, 0.0) * fp_trans ().to_matrix3d ();
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* The *= operator modifies the transformation by
|
|
* replacing *this with *this * t (t is applied before *this).
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The modified transformation
|
|
*/
|
|
simple_trans<C> &operator*= (const simple_trans<C> &t)
|
|
{
|
|
m_u += operator() (t.m_u);
|
|
fixpoint_trans<C>::operator*= (t);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief A method version of operator*, mainly for automation purposes
|
|
*/
|
|
simple_trans<C> concat (const simple_trans<C> &t) const
|
|
{
|
|
simple_trans<C> r (*this);
|
|
r *= t;
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* @brief A sorting criterion
|
|
*/
|
|
bool operator< (const simple_trans<C> &t) const
|
|
{
|
|
return fixpoint_trans<C>::operator< (t) || (fixpoint_trans<C>::operator== (t) && m_u < t.m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy sorting criterion
|
|
*/
|
|
bool less (const simple_trans<C> &t) const
|
|
{
|
|
return fixpoint_trans<C>::operator< (t) || (fixpoint_trans<C>::operator== (t) && m_u.less (t.m_u));
|
|
}
|
|
|
|
/**
|
|
* @brief Equality test
|
|
*/
|
|
bool operator== (const simple_trans<C> &t) const
|
|
{
|
|
return fixpoint_trans<C>::operator== (t) && m_u == t.m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief Inequality test
|
|
*/
|
|
bool operator!= (const simple_trans<C> &t) const
|
|
{
|
|
return !operator== (t);
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy equality test
|
|
*/
|
|
bool equal (const simple_trans<C> &t) const
|
|
{
|
|
return fixpoint_trans<C>::operator== (t) && m_u.equal (t.m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief A fuzzy inequality test
|
|
*/
|
|
bool not_equal (const simple_trans<C> &t) const
|
|
{
|
|
return ! equal (t);
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
std::string s1 = fixpoint_trans<C>::to_string ();
|
|
std::string s2 = m_u.to_string ();
|
|
if (! s1.empty () && ! s2.empty ()) {
|
|
return s1 + " " + s2;
|
|
} else {
|
|
return s1 + s2;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the displacement
|
|
*/
|
|
const displacement_type &disp () const
|
|
{
|
|
return m_u;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the displacement
|
|
*/
|
|
void disp (const displacement_type &u)
|
|
{
|
|
m_u = u;
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the fp_trans
|
|
*/
|
|
const fixpoint_trans<C> &fp_trans () const
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
displacement_type m_u;
|
|
};
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* t = t1 * t2 is the resulting transformation that is effectively
|
|
* applied if first t2 and then t1 is applied.
|
|
*
|
|
* @param t1 The transformation to apply last
|
|
* @param t2 The transformation to apply first
|
|
* @return t1 * t2
|
|
*/
|
|
template <class C>
|
|
inline simple_trans<C>
|
|
operator* (const simple_trans<C> &t1, const simple_trans<C> &t2)
|
|
{
|
|
simple_trans<C> t (t1);
|
|
t *= t2;
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief Output stream insertion operator
|
|
*/
|
|
template <class C>
|
|
inline std::ostream &
|
|
operator<< (std::ostream &os, const simple_trans<C> &t)
|
|
{
|
|
return (os << t.to_string ());
|
|
}
|
|
|
|
/**
|
|
* @brief A complex transformation
|
|
*
|
|
* A complex transformation provides magnification, mirroring at the x-axis, rotation by an arbitary
|
|
* angle and a displacement. The template parameters for this transformation are
|
|
* I (the input coordinate type), F (the output coordinate type) and R (the representation
|
|
* type used internally for representing the floating-point members).
|
|
*/
|
|
template <class I, class F, class R>
|
|
class complex_trans
|
|
{
|
|
public:
|
|
typedef I coord_type;
|
|
typedef F target_coord_type;
|
|
typedef typename coord_traits<I>::distance_type distance_type;
|
|
typedef typename coord_traits<F>::distance_type target_distance_type;
|
|
typedef vector<F> displacement_type;
|
|
typedef complex_trans<F, I, R> inverse_trans;
|
|
typedef epsilon_f<R> eps_f;
|
|
|
|
/**
|
|
* @brief The default constructor (unity transformation)
|
|
*/
|
|
complex_trans ()
|
|
: m_sin (0.0), m_cos (1.0), m_mag (1.0)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a unit transformation
|
|
*/
|
|
explicit complex_trans (unit_trans<I> /*f*/)
|
|
: m_sin (0.0), m_cos (1.0), m_mag (1.0)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a fixpoint transformation code
|
|
*/
|
|
explicit complex_trans (int fc)
|
|
{
|
|
db::fixpoint_trans<R> f (fc);
|
|
db::point<R> t (1.0, 0.0);
|
|
t = f (t);
|
|
m_cos = t.x ();
|
|
m_sin = t.y ();
|
|
m_mag = f.is_mirror () ? -1.0 : 1.0;
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a fixpoint transformation
|
|
*/
|
|
explicit complex_trans (fixpoint_trans<I> f)
|
|
{
|
|
db::point<R> t (1.0, 0.0);
|
|
t = fixpoint_trans<R> (f) (t);
|
|
m_cos = t.x ();
|
|
m_sin = t.y ();
|
|
m_mag = f.is_mirror () ? -1.0 : 1.0;
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a displacement transformation
|
|
*/
|
|
explicit complex_trans (const disp_trans<I> &d)
|
|
: m_u (d.disp ()), m_sin (0.0), m_cos (1.0), m_mag (1.0)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion constructor from a simple transformation
|
|
*/
|
|
explicit complex_trans (const simple_trans<I> &s)
|
|
: m_u (s.disp ())
|
|
{
|
|
db::point<R> t (1.0, 0.0);
|
|
t = fixpoint_trans<R> (s.fp_trans ()) (t);
|
|
m_cos = t.x ();
|
|
m_sin = t.y ();
|
|
m_mag = s.is_mirror () ? -1.0 : 1.0;
|
|
}
|
|
|
|
/**
|
|
* @brief Migration constructor from a simple transformation to a complex transformation
|
|
*
|
|
* This constructor is supposed to support migration from a simple to a complex transformation
|
|
* in an incremental fashion. Basically that means, that everything that is missing in the
|
|
* simple transformation is added by additional parameters.
|
|
* Specifically this added information is the magnification and the incremental rotation angle
|
|
* to fill up the 90 degree multiples of the simple transformation to the desired rotation.
|
|
* To save a trigonometric function computation, the added angle is given as the cosine of the
|
|
* angle (a value from 1.0 representing 0 degree to 0.0 representing 90 degree).
|
|
*
|
|
* @param s The simple transformation to derive this transformation from
|
|
* @param acos The cosine of the additional rotation angle
|
|
* @param mag The magnification
|
|
*/
|
|
complex_trans (const simple_trans<I> &s, double acos, double mag)
|
|
: m_u (s.disp ())
|
|
{
|
|
db::point<R> t (1.0, 0.0);
|
|
t = fixpoint_trans<R> (s.fp_trans ()) (t);
|
|
double asin = sqrt (1.0 - acos * acos); // we may to this since we know that the angle is between 0 and 90 degree
|
|
m_cos = t.x () * acos - t.y () * asin;
|
|
m_sin = t.x () * asin + t.y () * acos;
|
|
m_mag = s.is_mirror () ? -mag : mag;
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using a Matrix2d and a displacement
|
|
*
|
|
* @param m The matrix to take the rotation part of the transformation from
|
|
* @param u The displacement
|
|
*
|
|
* The matrix must not contain shear components.
|
|
*/
|
|
complex_trans (double mag, double rot, bool mirrx, const displacement_type &u)
|
|
: m_u (u)
|
|
{
|
|
tl_assert (mag > 0.0);
|
|
m_mag = mirrx ? -mag : mag;
|
|
rot *= M_PI / 180.0;
|
|
m_sin = sin (rot);
|
|
m_cos = cos (rot);
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using a Matrix3d object
|
|
*
|
|
* @param m The matrix to take the transformation from
|
|
*
|
|
* The matrix must not represent perspective distortion nor shear.
|
|
*/
|
|
explicit complex_trans (const Matrix3d &m)
|
|
: m_u (m.disp ())
|
|
{
|
|
tl_assert (! m.has_shear ());
|
|
tl_assert (! m.has_perspective ());
|
|
std::pair<double, double> mag = m.mag ();
|
|
tl_assert (fabs (mag.first - mag.second) < 1e-10);
|
|
double rot = m.angle () * M_PI / 180.0;
|
|
m_mag = m.is_mirror () ? -mag.first : mag.first;
|
|
m_sin = sin (rot);
|
|
m_cos = cos (rot);
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using a Matrix2d object
|
|
*
|
|
* The sequence of operations is: magnification, mirroring at x axis,
|
|
* rotation, application of displacement.
|
|
*
|
|
* @param mag The magnification
|
|
* @param rot The rotation angle in units of degree
|
|
* @param mirrx True, if mirrored at x axis
|
|
* @param u The displacement
|
|
*/
|
|
complex_trans (const Matrix2d &m, const vector<I> &u)
|
|
: m_u (u)
|
|
{
|
|
tl_assert (! m.has_shear ());
|
|
std::pair<double, double> mag = m.mag ();
|
|
tl_assert (fabs (mag.first - mag.second) < 1e-10);
|
|
double rot = m.angle () * M_PI / 180.0;
|
|
m_mag = m.is_mirror () ? -mag.first : mag.first;
|
|
m_sin = sin (rot);
|
|
m_cos = cos (rot);
|
|
}
|
|
|
|
/**
|
|
* @brief The standard constructor using magnification only
|
|
*
|
|
* @param mag The magnification
|
|
*/
|
|
explicit complex_trans (double mag)
|
|
{
|
|
tl_assert (mag > 0.0);
|
|
m_mag = mag;
|
|
m_sin = 0.0;
|
|
m_cos = 1.0;
|
|
}
|
|
|
|
/**
|
|
* @brief The copy constructor that converts also
|
|
*
|
|
* The copy constructor allows to convert between different
|
|
* coordinate types, if possible.
|
|
*
|
|
* @param d The source from which to copy
|
|
*/
|
|
template <class II, class FF, class RR>
|
|
explicit complex_trans (const complex_trans<II, FF, RR> &d)
|
|
: m_u (d.m_u), m_sin (d.m_sin), m_cos (d.m_cos), m_mag (d.m_mag)
|
|
{ }
|
|
|
|
/**
|
|
* @brief The standard constructor using a displacement only
|
|
*
|
|
* @param u The displacement
|
|
*/
|
|
explicit complex_trans (const displacement_type &u)
|
|
: m_u (u), m_sin (0.0), m_cos (1.0), m_mag (1.0)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*
|
|
* Returns the inverted transformation. NOTE: in-place inversion is not supported since
|
|
* for transformations where F != I, the inverse transformation is of a different type.
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
inverse_trans inverted () const
|
|
{
|
|
complex_trans<R, R, R> inv;
|
|
|
|
inv.m_mag = 1.0 / m_mag;
|
|
inv.m_sin = -m_sin * (m_mag < 0.0 ? -1.0 : 1.0);
|
|
inv.m_cos = m_cos;
|
|
inv.m_u = inv.operator () (-m_u);
|
|
|
|
return inverse_trans (inv);
|
|
}
|
|
|
|
/**
|
|
* @brief In-place inversion
|
|
*
|
|
* Note that in general, in-place inversion may not be type-consistent if the input and output types
|
|
* are different. The inversion is not a true inversion in the sense of inv(T) * T == 1 because of
|
|
* potential rounding effects.
|
|
*/
|
|
complex_trans &invert ()
|
|
{
|
|
complex_trans<R, R, R> inv;
|
|
|
|
inv.m_mag = 1.0 / m_mag;
|
|
inv.m_sin = -m_sin * (m_mag < 0.0 ? -1.0 : 1.0);
|
|
inv.m_cos = m_cos;
|
|
inv.m_u = inv.operator () (-m_u);
|
|
|
|
*this = complex_trans (inv);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a distance
|
|
*
|
|
* The ctrans method transforms the given distance.
|
|
*
|
|
* @param d The distance to transform
|
|
* @return The transformed distance
|
|
*/
|
|
target_distance_type ctrans (distance_type d) const
|
|
{
|
|
return coord_traits<F>::rounded_distance (d * fabs (m_mag));
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 2d matrix
|
|
*/
|
|
Matrix2d to_matrix2d () const
|
|
{
|
|
return Matrix2d (m_cos * fabs (m_mag), -m_sin * m_mag, m_sin * fabs (m_mag), m_cos * m_mag);
|
|
}
|
|
|
|
/**
|
|
* @brief Conversion to a 3d matrix
|
|
*/
|
|
Matrix3d to_matrix3d () const
|
|
{
|
|
return Matrix3d (m_cos * fabs (m_mag), -m_sin * m_mag, m_sin * fabs (m_mag), m_cos * m_mag, m_u.x (), m_u.y (), 0.0, 0.0);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
point<F> operator() (const point<I> &p) const
|
|
{
|
|
db::point<R> mp (m_cos * p.x () * fabs (m_mag) - m_sin * p.y () * m_mag,
|
|
m_sin * p.x () * fabs (m_mag) + m_cos * p.y () * m_mag);
|
|
return point<F> (mp + m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point (non-operator version)
|
|
*/
|
|
point<F> trans (const point<I> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*
|
|
* The operator() method transforms the given vector.
|
|
* q = t(p)
|
|
*
|
|
* @param p The vector to transform
|
|
* @return The transformed vector
|
|
*/
|
|
vector<F> operator() (const vector<I> &p) const
|
|
{
|
|
db::vector<R> mp (m_cos * p.x () * fabs (m_mag) - m_sin * p.y () * m_mag,
|
|
m_sin * p.x () * fabs (m_mag) + m_cos * p.y () * m_mag);
|
|
return db::vector<F> (mp);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector (non-operator version)
|
|
*/
|
|
vector<F> trans (const vector<I> &p) const
|
|
{
|
|
return operator() (p);
|
|
}
|
|
|
|
/**
|
|
* @brief Test, whether this is a unit transformation
|
|
*/
|
|
bool is_unity () const
|
|
{
|
|
if (fabs (m_mag - 1.0) > eps_f ()) {
|
|
return false;
|
|
}
|
|
if (fabs (m_sin) > eps_f ()) {
|
|
return false;
|
|
}
|
|
if (fabs (m_cos - 1.0) > eps_f ()) {
|
|
return false;
|
|
}
|
|
return fabs (m_u.x ()) <= db::epsilon_f<F> () &&
|
|
fabs (m_u.y ()) <= db::epsilon_f<F> ();
|
|
}
|
|
|
|
/**
|
|
* @brief Test, if the transformation is an orthogonal transformation
|
|
*
|
|
* If the rotation is by a multiple of 90 degree, this method will return true.
|
|
*/
|
|
bool is_ortho () const
|
|
{
|
|
return fabs (m_sin * m_cos) <= eps_f ();
|
|
}
|
|
|
|
/**
|
|
* @brief Return the respective rotation code if possible
|
|
*
|
|
* If this transformation is orthogonal (is_ortho () == true), then this method
|
|
* will return the corresponding fixpoint transformation, not taking into account
|
|
* magnification and displacement. If the transformation is not orthogonal, the result
|
|
* reflects the quadrant the rotation goes into with the guarantee to reproduce the
|
|
* correct quadrant in the exact case.
|
|
*/
|
|
int rot () const
|
|
{
|
|
return fp_trans ().rot ();
|
|
}
|
|
|
|
/**
|
|
* @brief Return the respective fixpoint trans if possible
|
|
*
|
|
* If this transformation is orthogonal (is_ortho () == true), then this method
|
|
* will return the corresponding fixpoint transformation, not taking into account
|
|
* magnification and displacement. If the transformation is not orthogonal, the result
|
|
* reflects the quadrant the rotation goes into with the guarantee to reproduce the
|
|
* correct quadrant in the exact case.
|
|
*/
|
|
fixpoint_trans<I> fp_trans () const
|
|
{
|
|
int c;
|
|
if (m_cos > eps_f () && m_sin >= -eps_f ()) {
|
|
c = 0 /*r0*/;
|
|
} else if (m_cos <= eps_f () && m_sin > eps_f ()) {
|
|
c = 1 /*r90*/;
|
|
} else if (m_cos < -eps_f () && m_sin <= eps_f ()) {
|
|
c = 2 /*r180*/;
|
|
} else {
|
|
c = 3 /*r270*/;
|
|
}
|
|
return fixpoint_trans<I> (c + (m_mag < 0.0 ? 4 : 0));
|
|
}
|
|
|
|
/**
|
|
* @brief Read accessor for the angle
|
|
*
|
|
* To check, if the transformation represents a rotation by a angle that
|
|
* is a multiple of 90 degree, use is_ortho.
|
|
*
|
|
* @return The rotation angle this transformation provides in degree units (0..360 deg).
|
|
*/
|
|
double angle () const
|
|
{
|
|
double a = atan2 (m_sin, m_cos) * (180.0 / M_PI);
|
|
if (a < -eps_f ()) {
|
|
a += 360.0;
|
|
} else if (a <= eps_f ()) {
|
|
a = 0.0;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
/**
|
|
* @brief Write accessor for the angle
|
|
*/
|
|
void angle (double rot)
|
|
{
|
|
rot *= M_PI / 180.0;
|
|
m_sin = sin (rot);
|
|
m_cos = cos (rot);
|
|
}
|
|
|
|
/**
|
|
* @brief Read accessor to the cosine part of the transformation matrix
|
|
*/
|
|
double mcos () const
|
|
{
|
|
return m_cos;
|
|
}
|
|
|
|
/**
|
|
* @brief Read accessor to the sine part of the transformation matrix
|
|
*/
|
|
double msin () const
|
|
{
|
|
return m_sin;
|
|
}
|
|
|
|
/**
|
|
* @brief Read accessor to the magnification
|
|
*/
|
|
double mag () const
|
|
{
|
|
return fabs (m_mag);
|
|
}
|
|
|
|
/**
|
|
* @brief Test, if the transformation is a magnifying one
|
|
*
|
|
* This is the recommended test for checking if the transformation represents
|
|
* a magnification.
|
|
*/
|
|
bool is_mag () const
|
|
{
|
|
return fabs (fabs (m_mag) - 1.0) > eps_f ();
|
|
}
|
|
|
|
/**
|
|
* @brief Write accessor to the magnification
|
|
*/
|
|
void mag (double m)
|
|
{
|
|
tl_assert (m > 0.0);
|
|
m_mag = m_mag < 0.0 ? -m : m;
|
|
}
|
|
|
|
/**
|
|
* @brief Test, if the transformation is mirroring
|
|
*/
|
|
bool is_mirror () const
|
|
{
|
|
return m_mag < 0.0;
|
|
}
|
|
|
|
/**
|
|
* @brief Write accessor to the mirror flag
|
|
*/
|
|
void mirror (bool m)
|
|
{
|
|
m_mag = m ? -fabs (m_mag) : fabs (m_mag);
|
|
}
|
|
|
|
/**
|
|
* @brief Read accessor to the displacement
|
|
*/
|
|
displacement_type disp () const
|
|
{
|
|
return displacement_type (m_u);
|
|
}
|
|
|
|
/**
|
|
* @brief Write accessor to the displacement
|
|
*/
|
|
void disp (const displacement_type &u)
|
|
{
|
|
m_u = vector<R> (u);
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations - in-place version
|
|
*
|
|
* The *= operator modifies the transformation by
|
|
* replacing *this with *this * t (t is applied before *this).
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The modified transformation
|
|
*/
|
|
complex_trans &operator*= (const complex_trans &t)
|
|
{
|
|
*this = concat_same (t);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* The * operator returns a transformation which is identical to the
|
|
* *this * t (t is applied before *this).
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The concatenated transformation
|
|
*/
|
|
template <class II>
|
|
complex_trans<II, F, R> concat (const complex_trans<II, I, R> &t) const
|
|
{
|
|
complex_trans<II, F, R> res;
|
|
|
|
double s1 = m_mag < 0.0 ? -1.0 : 1.0;
|
|
|
|
db::vector<R> tu (m_cos * t.m_u.x () * fabs (m_mag) - m_sin * t.m_u.y () * m_mag,
|
|
m_sin * t.m_u.x () * fabs (m_mag) + m_cos * t.m_u.y () * m_mag);
|
|
res.m_u = m_u + tu;
|
|
|
|
res.m_mag = m_mag * t.m_mag;
|
|
res.m_cos = m_cos * t.m_cos - s1 * m_sin * t.m_sin;
|
|
res.m_sin = m_sin * t.m_cos + s1 * m_cos * t.m_sin;
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations of the same type
|
|
*
|
|
* The * operator returns a transformation which is identical to the
|
|
* *this * t (t is applied before *this).
|
|
*
|
|
* The concatenation of two identical transformations is not strictly type-safe since
|
|
* formally, the output type of the second transformation needs to be compatible with
|
|
* the input type of the first. But transformation arithmetics is easier to do with
|
|
* this definition.
|
|
*
|
|
* @param t The transformation to apply before
|
|
* @return The concatenated transformation
|
|
*/
|
|
complex_trans concat_same (const complex_trans &t) const
|
|
{
|
|
// The concatenation is done with double as the intermediate type to avoid
|
|
// rounding issues as far as possible.
|
|
return complex_trans<double, F, R> (*this).concat (complex_trans<I, double, R>(t));
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the transformation in a different coordinate system
|
|
*
|
|
* Given a transformation which turns the current coordinate system into a new one,
|
|
* this method will compute the transformation as it would look like in the new
|
|
* coordinate system.
|
|
*
|
|
* The mathematical definition is this:
|
|
*
|
|
* T = this
|
|
* U = transformation into the new system
|
|
*
|
|
* T' = U * T * inverse(U)
|
|
*
|
|
* @param u The transformation into the new system
|
|
* @return The transformation in the new system
|
|
*/
|
|
template <class U>
|
|
complex_trans transform_into (const U &uin) const
|
|
{
|
|
// Note: preserving type consistency is a bit tedious here. We assume we can simply
|
|
// return the same type as *this. Ideally *this would be of type (C,C). U would be
|
|
// of type (C,F). Then the output would be (F,F).
|
|
complex_trans u (uin);
|
|
complex_trans uinv (u);
|
|
uinv.invert ();
|
|
return u.concat_same (*this).concat_same (uinv);
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieve the residual part of the angle
|
|
*
|
|
* The residual part is the cosine of the angle difference to the
|
|
* lower next multiple of 90 degree. I.e. the residual part of 135 degree
|
|
* would be cos(45 deg).
|
|
*/
|
|
double rcos () const
|
|
{
|
|
if (m_cos > eps_f () && m_sin >= -eps_f ()) {
|
|
return m_cos;
|
|
} else if (m_cos <= eps_f () && m_sin > eps_f ()) {
|
|
return m_sin;
|
|
} else if (m_cos < -eps_f () && m_sin <= eps_f ()) {
|
|
return -m_cos;
|
|
} else {
|
|
return -m_sin;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief A sorting criterion
|
|
*/
|
|
bool operator< (const complex_trans &t) const
|
|
{
|
|
if (m_u != t.m_u) {
|
|
return m_u < t.m_u;
|
|
}
|
|
if (fabs (m_sin - t.m_sin) > eps_f ()) {
|
|
return m_sin < t.m_sin;
|
|
}
|
|
if (fabs (m_cos - t.m_cos) > eps_f ()) {
|
|
return m_cos < t.m_cos;
|
|
}
|
|
if (fabs (m_mag - t.m_mag) > eps_f ()) {
|
|
return m_mag < t.m_mag;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief A (fuzzy) sorting criterion
|
|
*/
|
|
bool less (const complex_trans &t) const
|
|
{
|
|
if (! m_u.equal (t.m_u)) {
|
|
return m_u.less (t.m_u);
|
|
}
|
|
if (fabs (m_sin - t.m_sin) > eps_f ()) {
|
|
return m_sin < t.m_sin;
|
|
}
|
|
if (fabs (m_cos - t.m_cos) > eps_f ()) {
|
|
return m_cos < t.m_cos;
|
|
}
|
|
if (fabs (m_mag - t.m_mag) > eps_f ()) {
|
|
return m_mag < t.m_mag;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief Equality test
|
|
*/
|
|
bool operator== (const complex_trans &t) const
|
|
{
|
|
return m_u == t.m_u &&
|
|
fabs (m_sin - t.m_sin) <= eps_f () &&
|
|
fabs (m_cos - t.m_cos) <= eps_f () &&
|
|
fabs (m_mag - t.m_mag) <= eps_f ();
|
|
}
|
|
|
|
/**
|
|
* @brief Inequality test
|
|
*/
|
|
bool operator!= (const complex_trans &t) const
|
|
{
|
|
return !operator== (t);
|
|
}
|
|
|
|
/**
|
|
* @brief A (fuzzy) equality test
|
|
*/
|
|
bool equal (const complex_trans &t) const
|
|
{
|
|
return m_u.equal (t.m_u) &&
|
|
fabs (m_sin - t.m_sin) <= eps_f () &&
|
|
fabs (m_cos - t.m_cos) <= eps_f () &&
|
|
fabs (m_mag - t.m_mag) <= eps_f ();
|
|
}
|
|
|
|
/**
|
|
* @brief A (fuzzy) inequality test
|
|
*/
|
|
bool not_equal (const complex_trans &t) const
|
|
{
|
|
return ! equal (t);
|
|
}
|
|
|
|
/**
|
|
* @brief Default string conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
return to_string (false);
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*
|
|
* The lazy and micron flags allow to customize the output somewhat.
|
|
* When lazy is set to true, output that is not required (i.e. magnification when 1)
|
|
* is dropped. If dbu is set, the coordinates are multiplied with this factor to render micron units.
|
|
*/
|
|
std::string to_string (bool lazy, double dbu = 0.0) const
|
|
{
|
|
std::string s;
|
|
if (is_mirror ()) {
|
|
s += "m";
|
|
s += tl::to_string (angle () * 0.5);
|
|
} else {
|
|
s += "r";
|
|
s += tl::to_string (angle ());
|
|
}
|
|
if (! lazy || is_mag ()) {
|
|
s += tl::sprintf (" *%.9g", mag ());
|
|
}
|
|
s += " ";
|
|
s += m_u.to_string (dbu);
|
|
return s;
|
|
}
|
|
|
|
private:
|
|
template <class FF, class II, class RR> friend class complex_trans;
|
|
|
|
vector<R> m_u;
|
|
R m_sin, m_cos;
|
|
R m_mag;
|
|
};
|
|
|
|
/**
|
|
* @brief Multiplication (concatenation) of transformations
|
|
*
|
|
* t = t1 * t2 is the resulting transformation that is effectively
|
|
* applied if first t2 and then t1 is applied.
|
|
*
|
|
* @param t1 The transformation to apply last
|
|
* @param t2 The transformation to apply first
|
|
* @return t1 * t2
|
|
*/
|
|
template <class II, class I, class F, class R>
|
|
inline complex_trans<II, F, R>
|
|
operator* (const complex_trans<I, F, R> &t1, const complex_trans<II, I, R> &t2)
|
|
{
|
|
return t1.concat (t2);
|
|
}
|
|
|
|
/**
|
|
* @brief Scaling of a complex transformation with a scalar
|
|
*
|
|
* The resulting complex transformation will reflex the original one plus
|
|
* an additional magnification given by the factor m.
|
|
*
|
|
* @param t The original transformation
|
|
* @param m The additional magnification
|
|
* @return t1 * m
|
|
*/
|
|
template <class I, class F, class R>
|
|
inline complex_trans<I, F, R>
|
|
operator* (const complex_trans<I, F, R> &t1, double m)
|
|
{
|
|
complex_trans<I, F, R> t (t1);
|
|
t.mag (t.mag () * m);
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* @brief Output stream insertion operator
|
|
*/
|
|
template <class I, class F, class R>
|
|
inline std::ostream &
|
|
operator<< (std::ostream &os, const complex_trans<I, F, R> &t)
|
|
{
|
|
return (os << t.to_string ());
|
|
}
|
|
|
|
/**
|
|
* @brief A combined transformation
|
|
*
|
|
* A combined transformation is the combination of two
|
|
* transformations T1 and T2 (T=T1*T2). Although the multiplication
|
|
* of two transformations may render the same result, but
|
|
* usually is more efficient. To combine two different
|
|
* transformations however, the combined_trans template
|
|
* is better suited.
|
|
*/
|
|
|
|
template <class T1, class T2>
|
|
struct combined_trans
|
|
{
|
|
typedef typename T2::coord_type coord_type;
|
|
typedef typename T1::target_coord_type target_coord_type;
|
|
typedef combined_trans<typename T2::inverse_trans, typename T1::inverse_trans> inverse_trans;
|
|
|
|
/**
|
|
* @brief Default constructor
|
|
*
|
|
* Creates a unity transformation
|
|
*/
|
|
combined_trans ()
|
|
: t1 (), t2 ()
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Standard constructor
|
|
*
|
|
* Takes two transformations and combines both.
|
|
*/
|
|
combined_trans (const T1 &_t1, const T2 &_t2)
|
|
: t1 (_t1), t2 (_t2)
|
|
{
|
|
// .. nothing else ..
|
|
}
|
|
|
|
/**
|
|
* @brief Inversion
|
|
*
|
|
* Inverts the transformation and returns the inverted
|
|
* transformation which swaps T1 and T2 in the type definition.
|
|
*
|
|
* @return The inverted transformation
|
|
*/
|
|
inverse_trans inverted () const
|
|
{
|
|
return inverse_trans (t2.inverted (), t1.inverted ());
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a point
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
template <class C>
|
|
point<target_coord_type> operator() (const point<C> &p) const
|
|
{
|
|
typedef typename T2::target_coord_type intern_coord_type;
|
|
point<intern_coord_type> q = t2.operator() (p);
|
|
return t1.operator() (q);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a vector
|
|
*
|
|
* The operator() method transforms the given point.
|
|
* q = t(p)
|
|
*
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
template <class C>
|
|
vector<target_coord_type> operator() (const vector<C> &p) const
|
|
{
|
|
typedef typename T2::target_coord_type intern_coord_type;
|
|
vector<intern_coord_type> q = t2.operator() (p);
|
|
return t1.operator() (q);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a distance
|
|
*
|
|
* The ctrans method transforms the given distance.
|
|
* s = t(d)
|
|
*
|
|
* @param d The distance to transform
|
|
* @return The transformed distance
|
|
*/
|
|
template <class C>
|
|
target_coord_type ctrans (C p) const
|
|
{
|
|
typedef typename T2::target_coord_type intern_coord_type;
|
|
intern_coord_type q = t2.ctrans (p);
|
|
return t1.ctrans (q);
|
|
}
|
|
|
|
/**
|
|
* @brief The transformation of a fixpoint transformation
|
|
*
|
|
* The ftrans method transforms the given fixpoint transformation.
|
|
* f = t(f)
|
|
*
|
|
* @param f The fixpoint transformation to transform
|
|
* @return The transformed fixpoint transformation
|
|
*/
|
|
template <class D>
|
|
fixpoint_trans<D> ftrans (fixpoint_trans<D> f) const
|
|
{
|
|
return t1 (t2 (f));
|
|
}
|
|
|
|
/**
|
|
* @brief A sorting criterion
|
|
*/
|
|
bool operator< (const combined_trans<T1, T2> &t) const
|
|
{
|
|
return t1 < t.t1 || (t1 == t.t1 && t2 < t.t2);
|
|
}
|
|
|
|
/**
|
|
* @brief Equality test
|
|
*/
|
|
bool operator== (const combined_trans<T1, T2> &t) const
|
|
{
|
|
return t1 == t.t1 && t2 == t.t2;
|
|
}
|
|
|
|
/**
|
|
* @brief Inequality test
|
|
*/
|
|
bool operator!= (const combined_trans<T1, T2> &t) const
|
|
{
|
|
return !operator== (t);
|
|
}
|
|
|
|
/**
|
|
* @brief String conversion
|
|
*/
|
|
std::string to_string () const
|
|
{
|
|
std::string s1 = t1.to_string ();
|
|
std::string s2 = t2.to_string ();
|
|
if (! s1.empty () && ! s2.empty ()) {
|
|
return s1 + " " + s2;
|
|
} else {
|
|
return s1 + s2;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the first part of the combined transformation
|
|
*/
|
|
const T1 &first () const
|
|
{
|
|
return t1;
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the second part of the combined transformation
|
|
*/
|
|
const T2 &second () const
|
|
{
|
|
return t2;
|
|
}
|
|
|
|
T1 t1;
|
|
T2 t2;
|
|
};
|
|
|
|
/**
|
|
* @brief Output stream insertion operator
|
|
*/
|
|
template <class T1, class T2>
|
|
inline std::ostream &
|
|
operator<< (std::ostream &os, const combined_trans<T1, T2> &t)
|
|
{
|
|
return (os << t.to_string ());
|
|
}
|
|
|
|
/**
|
|
* @brief The standard unit transformation
|
|
*/
|
|
typedef unit_trans<db::Coord> UnitTrans;
|
|
|
|
/**
|
|
* @brief The standard unit transformation for double coordinates
|
|
*/
|
|
typedef unit_trans<db::DCoord> DUnitTrans;
|
|
|
|
/**
|
|
* @brief The standard fixpoint transformation
|
|
*/
|
|
typedef fixpoint_trans<db::Coord> FTrans;
|
|
|
|
/**
|
|
* @brief The standard fixpoint transformation for double types
|
|
*/
|
|
typedef fixpoint_trans<db::DCoord> DFTrans;
|
|
|
|
/**
|
|
* @brief The standard displacement transformation
|
|
*/
|
|
typedef disp_trans<db::Coord> Disp;
|
|
|
|
/**
|
|
* @brief The double coordinate displacement transformation
|
|
*/
|
|
typedef disp_trans<db::DCoord> DDisp;
|
|
|
|
/**
|
|
* @brief The standard transformation
|
|
*/
|
|
typedef simple_trans<db::Coord> Trans;
|
|
|
|
/**
|
|
* @brief The double coordinate transformation
|
|
*/
|
|
typedef simple_trans<db::DCoord> DTrans;
|
|
|
|
/**
|
|
* @brief The standard complex transformation that converts integer to integer coordinates
|
|
*/
|
|
typedef complex_trans<db::Coord, db::Coord> ICplxTrans;
|
|
|
|
/**
|
|
* @brief The standard complex transformation
|
|
*/
|
|
typedef complex_trans<db::Coord, db::DCoord> CplxTrans;
|
|
|
|
/**
|
|
* @brief Specialization: concatenation of CplxTrans
|
|
*
|
|
* The combination of two of these objects is basically not allowed, since the
|
|
* output and input types in not compatible. For sake of similicity however, we
|
|
* allow this now.
|
|
*/
|
|
inline CplxTrans operator* (const CplxTrans &a, const CplxTrans &b)
|
|
{
|
|
return a.concat_same (b);
|
|
}
|
|
|
|
/**
|
|
* @brief The inverse of the standard complex transformation
|
|
*/
|
|
typedef complex_trans<db::DCoord, db::Coord> VCplxTrans;
|
|
|
|
/**
|
|
* @brief Specialization: concatenation of VCplxTrans
|
|
*
|
|
* The combination of two of these objects is basically not allowed, since the
|
|
* output and input types in not compatible. For sake of similicity however, we
|
|
* allow this now.
|
|
*/
|
|
inline VCplxTrans operator* (const VCplxTrans &a, const VCplxTrans &b)
|
|
{
|
|
return a.concat_same (b);
|
|
}
|
|
|
|
/**
|
|
* @brief The double coordinate complex transformation
|
|
*/
|
|
typedef complex_trans<db::DCoord, db::DCoord> DCplxTrans;
|
|
|
|
/**
|
|
* @brief Transformation operator
|
|
*
|
|
* Transforms the point with the given transformation
|
|
* (q = T * p).
|
|
*
|
|
* @param t The transformation to apply
|
|
* @param p The point to transform
|
|
* @return The transformed point
|
|
*/
|
|
template <class C, class Tr>
|
|
inline point<typename Tr::target_coord_type>
|
|
operator* (const Tr &t, const point<C> &p)
|
|
{
|
|
return t.operator() (point<typename Tr::coord_type> (p));
|
|
}
|
|
|
|
/**
|
|
* @brief Transformation operator
|
|
*
|
|
* Transforms the vector with the given transformation
|
|
* (q = T * p).
|
|
*
|
|
* @param t The transformation to apply
|
|
* @param p The vector to transform
|
|
* @return The transformed vector
|
|
*/
|
|
template <class C, class Tr>
|
|
inline vector<typename Tr::target_coord_type>
|
|
operator* (const Tr &t, const vector<C> &p)
|
|
{
|
|
return t.operator() (vector<typename Tr::coord_type> (p));
|
|
}
|
|
|
|
/**
|
|
* @brief Fuzzy compare function for transformation objects
|
|
*/
|
|
template <class T>
|
|
class trans_less_func
|
|
{
|
|
public:
|
|
bool operator() (const T &a, const T &b) const
|
|
{
|
|
return a.less (b);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief Fuzzy compare function for transformation objects
|
|
*/
|
|
template <class T>
|
|
class trans_equal_func
|
|
{
|
|
public:
|
|
bool operator() (const T &a, const T &b) const
|
|
{
|
|
return a.equal (b);
|
|
}
|
|
};
|
|
|
|
} // namespace db
|
|
|
|
/**
|
|
* @brief Special extractors for the transformations
|
|
*/
|
|
|
|
namespace tl
|
|
{
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::UnitTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::DUnitTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::FTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::DFTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::Trans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::DTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::Disp &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::DDisp &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::CplxTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::VCplxTrans &t);
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::DCplxTrans &t);
|
|
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::UnitTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::DUnitTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::FTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::DFTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::Trans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::DTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::Disp &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::DDisp &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::CplxTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::VCplxTrans &t);
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::DCplxTrans &t);
|
|
|
|
} // namespace tl
|
|
|
|
#endif
|
|
|
|
|