d2::align: Change allocation and deallocation of LOD structures so that 0-level certa...
[Ale.git] / d2 / trans_multi.h
blob25598ce3cb538d7ab397859b1dc1d532b19d4733
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
23 * regions of a scene.
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 {
33 private:
34 std::vector<trans_single> trans_stack;
35 int full_support;
36 unsigned int current_element;
38 public:
40 trans_multi() : trans_stack() {
41 full_support = 0;
42 current_element = 0;
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;
52 return *this;
55 trans_multi(const trans_multi &tm) : trans_stack() {
56 operator=(tm);
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);
79 void push_element() {
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());
93 current_element = i;
96 unsigned int stack_depth() {
97 return trans_stack.size();
100 int supported(int i, int j) {
101 if (full_support || current_element == 0)
102 return 1;
104 return 0;
107 void use_full_support() {
108 full_support = 1;
111 void use_restricted_support() {
112 full_support = 0;
115 int is_nontrivial() {
116 return 0;
119 void begin_calculate_scaled_region(unsigned int i_max, unsigned int j_max, point offset) {
120 assert(0);
123 void begin_calculate_unscaled_region(unsigned int i_max, unsigned int j_max, point offset) {
124 assert(0);
127 void end_calculate_region() {
128 assert(0);
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
159 * transformation.
161 void eu_to_gpt() {
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;
176 return r;
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);
184 r.eu_to_gpt();
185 return r;
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);
273 void reset_memos() {
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();
330 #endif