1 // Copyright 2002, 2004, 2007 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * trans_multi.h: Represent multiple transformations, affecting different
26 #ifndef __trans_multi_h__
27 #define __trans_multi_h__
29 #include "trans_abstract.h"
30 #include "trans_single.h"
32 struct trans_multi
: public trans_abstract
{
34 std::vector
<trans_single
> trans_stack
;
36 unsigned int current_element
;
40 trans_multi() : trans_stack() {
45 trans_multi
&operator=(const trans_multi
&tm
) {
46 this->trans_abstract::operator=(*((trans_abstract
*) &tm
));
48 trans_stack
= tm
.trans_stack
;
49 full_support
= tm
.full_support
;
50 current_element
= tm
.current_element
;
55 trans_multi(const trans_multi
&tm
) : trans_stack() {
59 trans_single
get_element(unsigned int index
) {
60 assert (index
< trans_stack
.size());
62 return trans_stack
[index
];
65 trans_single
get_current_element() {
66 return get_element(current_element
);
69 void set_element(unsigned int index
, trans_single t
) {
70 assert (index
< trans_stack
.size());
72 trans_stack
[index
] = t
;
75 void set_current_element(trans_single t
) {
76 set_element(current_element
, t
);
80 assert (trans_stack
.size() > 0);
82 if (++current_element
== trans_stack
.size())
83 trans_stack
.push_back(trans_stack
.back());
86 unsigned int get_current_index() const {
87 return current_element
;
90 void set_current_index(unsigned int i
) {
91 assert (i
< trans_stack
.size());
96 unsigned int stack_depth() {
97 return trans_stack
.size();
100 int supported(int i
, int j
) {
101 if (full_support
|| current_element
== 0)
107 void use_full_support() {
111 void use_restricted_support() {
115 int is_nontrivial() {
119 void begin_calculate_scaled_region(unsigned int i_max
, unsigned int j_max
, point offset
) {
123 void begin_calculate_unscaled_region(unsigned int i_max
, unsigned int j_max
, point offset
) {
127 void end_calculate_region() {
131 point
get_query_point(int i
, int j
) {
132 return point::undefined();
136 * Returns non-zero if the transformation might be non-Euclidean.
138 int is_projective() const {
139 return trans_stack
.front().is_projective();
143 * Projective/Euclidean transformations
145 struct point
pe(struct point p
) const {
146 return trans_stack
.front().pe(p
);
150 * Inverse transformations
152 struct point
pei(struct point p
) const {
153 return trans_stack
.front().pei(p
);
158 * Calculate projective transformation parameters from a euclidean
162 for (unsigned int t
= 0; t
< trans_stack
.size(); t
++)
163 trans_stack
[t
].eu_to_gpt();
167 * Calculate euclidean identity transform for a given image.
169 static struct trans_multi
eu_identity(const image
*i
= NULL
, ale_pos scale_factor
= 1) {
170 struct trans_multi r
;
171 r
.input_width
= i
? i
->width() : 2;
172 r
.input_height
= i
? i
->height() : 2;
173 r
.scale_factor
= scale_factor
;
174 r
.trans_stack
.push_back(trans_single::eu_identity(i
, scale_factor
));
175 r
.current_element
= 0;
180 * Calculate projective identity transform for a given image.
182 static trans_multi
gpt_identity(const image
*i
, ale_pos scale_factor
) {
183 struct trans_multi r
= eu_identity(i
, scale_factor
);
189 * Modify a euclidean transform in the indicated manner.
191 void eu_modify(int i1
, ale_pos diff
) {
192 trans_stack
[current_element
].eu_modify(i1
, diff
);
196 * Rotate about a given point in the original reference frame.
198 void eu_rotate_about_scaled(point center
, ale_pos diff
) {
199 trans_stack
[current_element
].eu_rotate_about_scaled(center
, diff
);
203 * Modify all euclidean parameters at once.
205 void eu_set(ale_pos eu
[3]) {
206 trans_stack
[current_element
].eu_set(eu
);
210 * Get the specified euclidean parameter
212 ale_pos
eu_get(int param
) const {
213 return trans_stack
[current_element
].eu_get(param
);
217 * Modify a projective transform in the indicated manner.
219 void gpt_modify(int i1
, int i2
, ale_pos diff
) {
220 trans_stack
[current_element
].gpt_modify(i1
, i2
, diff
);
224 * Modify a projective transform according to the group operation.
226 void gr_modify(int i1
, int i2
, ale_pos diff
) {
227 trans_stack
[current_element
].gr_modify(i1
, i2
, diff
);
231 * Modify all projective parameters at once.
233 void gpt_set(point x
[4]) {
234 trans_stack
[current_element
].gpt_set(x
);
237 void gpt_set(point x1
, point x2
, point x3
, point x4
) {
238 trans_stack
[current_element
].gpt_set(x1
, x2
, x3
, x4
);
241 void snap(ale_pos interval
) {
242 trans_stack
[current_element
].snap(interval
);
246 * Get the specified projective parameter
248 point
gpt_get(int point
) const {
249 return trans_stack
[current_element
].gpt_get(point
);
253 * Get the specified projective parameter
255 ale_pos
gpt_get(int point
, int dim
) {
256 return trans_stack
[current_element
].gpt_get(point
, dim
);
260 * Translate by a given amount
262 void translate(point p
) {
263 trans_stack
[current_element
].translate(p
);
267 * Rotate by a given amount about a given point.
269 void rotate(point p
, ale_pos degrees
) {
270 trans_stack
[current_element
].rotate(p
, degrees
);
274 for (unsigned int t
= 0; t
< trans_stack
.size(); t
++)
275 trans_stack
[t
].reset_memos();
279 * Rescale a transform with a given factor.
281 void specific_rescale(ale_pos factor
) {
283 if (trans_stack
.size() > 1) {
286 * Rescale region map.
289 #warning d2::trans_multi::specific_rescale() does no region map rescaling.
292 for (unsigned int t
= 0; t
< trans_stack
.size(); t
++)
293 trans_stack
[t
].rescale(factor
);
297 * Set the dimensions of the image.
299 void specific_set_dimensions(const image
*im
) {
300 for (unsigned int t
= 0; t
< trans_stack
.size(); t
++)
301 trans_stack
[t
].set_dimensions(im
);
305 * Modify all projective parameters at once. Accommodate bugs in the
306 * version 0 transformation file handler (ALE versions 0.4.0p1 and
307 * earlier). This code is only called when using a transformation data
308 * file created with an old version of ALE.
310 void gpt_v0_set(point x
[4]) {
311 trans_stack
[current_element
].gpt_v0_set(x
);
315 * Modify all euclidean parameters at once. Accommodate bugs in the
316 * version 0 transformation file handler (ALE versions 0.4.0p1 and
317 * earlier). This code is only called when using a transformation data
318 * file created with an old version of ALE.
320 void eu_v0_set(ale_pos eu
[3]) {
321 trans_stack
[current_element
].eu_v0_set(eu
);
324 void debug_output() {
325 for (unsigned int t
= 0; t
< trans_stack
.size(); t
++)
326 trans_stack
[t
].debug_output();