summaryrefslogtreecommitdiffstats
path: root/kig/misc/kigtransform.h
blob: 252a0f7281f7bfd6c8e4175d641f191fab9ed3a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/**
 This file is part of Kig, a KDE program for Interactive Geometry...
 Copyright (C) 2002  Maurizio Paolini <paolini@dmf.unicatt.it>
 Copyright (C) 2003  Dominique Devriese <devriese@kde.org>

 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 Street, Fifth Floor, Boston, MA  02110-1301
 USA
**/

#ifndef KIG_MISC_KIGTRANSFORM_H
#define KIG_MISC_KIGTRANSFORM_H

#include "coordinate.h"
#include <vector>

class LineData;

/**
 * Class representing a transformation.  More specifically, this class
 * represents a pretty generic 2-dimensional transformation. Various
 * common transformations can be used.  Construct a Transformation by
 * using one of its static members, and use it either with its
 * Transformation::apply method, or the ObjectImp::transform method.
 */
class Transformation
{
  double mdata[3][3];
  bool mIsHomothety;
  bool mIsAffine;
  Transformation();
public:
  ~Transformation();
  Transformation( double data[3][3], bool ishomothety );

  /**
   * Apply this Tranformation.  Apply this transformation to the
   * Coordinate c.  Can return an invalid Coordinate.
   * apply0 assumes that c indicates a point at infinity, having
   * [0, c.x, c.y] as homogeneous coordinates
   */
  const Coordinate apply( const double x0, const double x1, const double x2 ) const;
  const Coordinate apply( const Coordinate& c ) const;
  const Coordinate apply0( const Coordinate& c ) const;

  /**
   * Returns whether this is a homothetic (affine) transformation.
   */
  bool isHomothetic() const;
  bool isAffine() const;
  double getProjectiveIndicator( const Coordinate& c ) const;
  double getAffineDeterminant() const;
  double getRotationAngle() const;
  const Coordinate apply2by2only( const Coordinate& c ) const;
  /**
   * \ifnot creating-python-scripting-doc
   * a homothetic transformation maintains the ratio's of lengths.
   * This means that every length is multiplied by a fixed number when
   * it is projected...  This function does that calculation for
   * you..
   * \endif
   */
  double apply( double length ) const;
  double data( int r, int c ) const;
  /**
   * The inverse Transformation.  Returns the inverse Transformation
   * of this Transformation.
   */
  const Transformation inverse( bool& valid ) const;

  /**
   * Identity.  Returns the Identity Transformation, i.e. a
   * Transformation that doesn't do anything.
   */
  static const Transformation identity();
  /**
   * Scaling over Point.  Returns a Transformation that scales points
   * by a certain factor with relation to a center point.
   */
  static const Transformation scalingOverPoint( double factor, const Coordinate& center = Coordinate() );
  /**
   * Scaling over Line.  Returns a Transformation that scales points
   * by a certain factor with relation to a line.  Note: This is not a
   * homothetic transformation.
   */
  static const Transformation scalingOverLine( double factor, const LineData& l );
  /**
   * Translation.  Returns a Translation by a vector c.
   */
  static const Transformation translation( const Coordinate& c );
  /**
   * Rotation.  Returns a Rotation by a certain angle, around a
   * certain center.
   */
  static const Transformation rotation( double angle, const Coordinate& center = Coordinate() );
  /**
   * Point Reflection.  Returns a reflection over a point
   * \note This equals scaling( -1, c );
   */
  static const Transformation pointReflection( const Coordinate& c );
  /**
   * Line Reflection.  Returns a reflection over a line
   * \note This equals scaling( -1, l );
   */
  static const Transformation lineReflection( const LineData& l );
  /**
   * Harmonic Homology. Returns a Transformation that transforms points in
   * such a way that it appears to cast a shadow, given a certain
   * light source (center), and a line (axis) indicating a plane.
   */
  static const Transformation harmonicHomology( const Coordinate& center,
                                          const LineData& axis );
  /**
   * Affinity given the image of 3 points. Returns the unique
   * affinity that transforms 3 given points into 3 given points.
   */
  static const Transformation affinityGI3P(
                const std::vector<Coordinate>& FromPoints,
                const std::vector<Coordinate>& ToPoints,
                bool& valid );
  /**
   * Projectivity given the image of 4 points. Returns the unique
   * projectivity that transforms 4 given points into 4 given points.
   */
  static const Transformation projectivityGI4P(
                const std::vector<Coordinate>& FromPoints,
                const std::vector<Coordinate>& ToPoints,
                bool& valid );
  /**
   * Cast Shadow.  Returns a Transformation that transforms points in
   * such a way that it appears to cast a shadow, given a certain
   * light source, and a line indicating a plane.
   */
  static const Transformation castShadow( const Coordinate& ls,
                                          const LineData& d );
  /**
   * Projective Rotation.  This is really only a test example of a
   * projective non-affine transformation...
   */
  static const Transformation projectiveRotation( double alpha,
                                                  const Coordinate& d,
                                                  const Coordinate& t );

  /**
   * Similitude.  Sequence of a rotation and a scaling with relation
   * to a certain center.
   */
  static const Transformation similitude(
    const Coordinate& center, double theta, double factor );

  /**
   * Sequence.  This creates a Transformation that executes first
   * transformation b, and then a.
   */
  friend const Transformation operator*( const Transformation& a, const Transformation& b );

  /**
   * Equality.  Tests two Transformation's for equality.
   */
  friend bool operator==( const Transformation& lhs, const Transformation& rhs );
};

const Transformation operator*( const Transformation&, const Transformation& );
bool operator==( const Transformation& lhs, const Transformation& rhs );

// enum tWantArgsResult { tComplete, tNotComplete, tNotGood };

// Transformation getProjectiveTransformation(
//   int transformationsnum, Object *mtransformations[],
//   bool& valid );

// tWantArgsResult WantTransformation ( Objects::const_iterator& i,
//          const Objects& os );

// QString getTransformMessage ( const Objects& os, const Object *o );

// bool isHomoteticTransformation ( double transformation[3][3] );

#endif // KIG_MISC_KIGTRANSFORM_H