Code

Fundamentally reworked version of the 3D box tool (among many other things, this...
[inkscape.git] / src / axis-manip.h
1 /*
2  * Generic auxiliary routines for 3D axes
3  *
4  * Authors:
5  *   Maximilian Albert <Anhalter42@gmx.de>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #ifndef SEEN_AXIS_MANIP_H
13 #define SEEN_AXIS_MANIP_H
15 #include <gtk/gtk.h>
16 #include "libnr/nr-point.h"
18 namespace Proj {
20 enum VPState {
21     FINITE = 0,
22     INFINITE
23 };
25 // The X-/Y-/Z-axis corresponds to the first/second/third digit
26 // in binary representation, respectively.
27 enum Axis {
28     X = 0,
29     Y = 1,
30     Z = 2,
31     W = 3,
32     NONE
33 };
35 extern Axis axes[4];
37 inline gchar * string_from_axis (Proj::Axis axis) {
38     switch (axis) {
39     case X:
40         return "X";
41         break;
42     case Y:
43         return "Y";
44         break;
45     case Z:
46         return "Z";
47         break;
48     case W:
49         return "W";
50         break;
51     case NONE:
52         return "NONE";
53         break;
54     }
55     return "";
56 }
58 } // namespace Proj
60 namespace Box3D {
62 const double epsilon = 1e-6;
64 // The X-/Y-/Z-axis corresponds to the first/second/third digit
65 // in binary representation, respectively.
66 enum Axis {
67     X = 1,
68     Y = 2,
69     Z = 4,
70     XY = 3,
71     XZ = 5,
72     YZ = 6,
73     XYZ = 7,
74     NONE = 0
75 };
77 // We use the fourth bit in binary representation
78 // to indicate whether a face is front or rear.
79 enum FrontOrRear { // find a better name
80     FRONT = 0,
81     REAR = 8
82 };
84 // converts X, Y, Z respectively to 0, 1, 2 (for use as array indices, e.g)
85 inline int axis_to_int(Box3D::Axis axis) {
86     switch (axis) {
87     case Box3D::X:
88         return 0;
89         break;
90     case Box3D::Y:
91         return 1;
92         break;
93     case Box3D::Z:
94         return 2;
95         break;
96     case Box3D::NONE:
97         return -1;
98         break;
99     default:
100         g_assert_not_reached();
101     }
104 inline Proj::Axis toProj(Box3D::Axis axis) {
105     switch (axis) {
106     case Box3D::X:
107         return Proj::X;
108     case Box3D::Y:
109         return Proj::Y;
110     case Box3D::Z:
111         return Proj::Z;
112     case Box3D::NONE:
113         return Proj::NONE;
114     default:
115         g_assert_not_reached();
116     }
119 extern Axis axes[3];
120 extern Axis planes[3];
121 extern FrontOrRear face_positions [2];
123 } // namespace Box3D
125 namespace Proj {
127 inline Box3D::Axis toAffine(Proj::Axis axis) {
128     switch (axis) {
129     case Proj::X:
130         return Box3D::X;
131     case Proj::Y:
132         return Box3D::Y;
133     case Proj::Z:
134         return Box3D::Z;
135     case Proj::NONE:
136         return Box3D::NONE;
137     default:
138         g_assert_not_reached();
139     }
142 } // namespace Proj
144 namespace Box3D {
146 // Given a bit sequence that unambiguously specifies the face of a 3D box,
147 // return a number between 0 and 5 corresponding to that particular face
148 // (which is normally used to index an array). Return -1 if the bit sequence
149 // does not specify a face. A face can either be given by its plane (e.g, XY)
150 // or by the axis that is orthogonal to it (e.g., Z).
151 /***
152 inline gint face_to_int (guint face_id) {
153     switch (face_id) {
154       case 1:  return 0;
155       case 2:  return 2;
156       case 4:  return 4;
157       case 3:  return 4;
158       case 5:  return 2;
159       case 6:  return 0;
161       case 9:  return 1;
162       case 10: return 3;
163       case 12: return 5;
164       case 11: return 5;
165       case 13: return 3;
166       case 14: return 1;
168     default: return -1;
169     }
171 ***/
173 /***
174 inline gint int_to_face (guint id) {
175     switch (id) {
176       case 0: return  6;
177       case 1: return 14;
178       case 2: return  5;
179       case 3: return 13;
180       case 4: return  3;
181       case 5: return 11;
183     default: return -1;
184     }
186 ***/
188 /* 
189  * New version:
190  * Identify the axes X, Y, Z with the numbers 0, 1, 2.
191  * A box's face is identified by the axis perpendicular to it.
192  * For a rear face, add 3.
193  */
194 // Given a bit sequence that unambiguously specifies the face of a 3D box,
195 // return a number between 0 and 5 corresponding to that particular face
196 // (which is normally used to index an array). Return -1 if the bit sequence
197 // does not specify a face. A face can either be given by its plane (e.g, XY)
198 // or by the axis that is orthogonal to it (e.g., Z).
199 inline gint face_to_int (guint face_id) {
200     switch (face_id) {
201       case 1:  return 0;
202       case 2:  return 1;
203       case 4:  return 2;
204       case 3:  return 2;
205       case 5:  return 1;
206       case 6:  return 0;
208       case 9:  return 3;
209       case 10: return 4;
210       case 12: return 5;
211       case 11: return 5;
212       case 13: return 4;
213       case 14: return 3;
215     default: return -1;
216     }
219 inline gint int_to_face (guint id) {
220     switch (id) {
221     case 0: return Box3D::YZ ^ Box3D::FRONT;
222     case 1: return Box3D::XZ ^ Box3D::FRONT;
223     case 2: return Box3D::XY ^ Box3D::FRONT;
224     case 3: return Box3D::YZ ^ Box3D::REAR;
225     case 4: return Box3D::XZ ^ Box3D::REAR;
226     case 5: return Box3D::XY ^ Box3D::REAR;
227     }
228     return Box3D::NONE; // should not be reached
231 inline bool is_face_id (guint face_id) {
232     return !((face_id & 0x7) == 0x7);
235 /**
236 inline gint opposite_face (guint face_id) {
237     return face_id + (((face_id % 2) == 0) ? 1 : -1);
239 **/
241 inline guint number_of_axis_directions (Box3D::Axis axis) {
242     guint num = 0;
243     if (axis & Box3D::X) num++;
244     if (axis & Box3D::Y) num++;
245     if (axis & Box3D::Z) num++;
247     return num;
250 inline bool is_plane (Box3D::Axis plane) {
251     return (number_of_axis_directions (plane) == 2);
254 inline bool is_single_axis_direction (Box3D::Axis dir) {
255     // tests whether dir is nonzero and a power of 2
256     return (!(dir & (dir - 1)) && dir);
259 /***
260 // Warning: We don't check that axis really unambiguously specifies a plane.
261 //          Make sure this is the case when calling this function.
262 inline gint face_containing_corner (Box3D::Axis axis, guint corner) {
263     if (!is_single_axis_direction (axis)) {
264         axis = (Box3D::Axis) (axis ^ Box3D::XYZ);
265     }
266     return face_to_int (axis ^ ((corner & axis) ? Box3D::REAR : Box3D::FRONT));
268 ***/
270 /**
271  * Given two axis directions out of {X, Y, Z} or the corresponding plane, return the remaining one
272  * We don't check if 'plane' really specifies a plane (i.e., if it consists of precisely two directions).
273  */
274 inline Box3D::Axis third_axis_direction (Box3D::Axis dir1, Box3D::Axis dir2) {
275     return (Box3D::Axis) ((dir1 + dir2) ^ 0x7);
277 inline Box3D::Axis third_axis_direction (Box3D::Axis plane) {
278     return (Box3D::Axis) (plane ^ 0x7);
281 /* returns the first/second axis direction occuring in the (possibly compound) expression 'dirs' */
282 inline Box3D::Axis extract_first_axis_direction (Box3D::Axis dirs) {
283     if (dirs & Box3D::X) return Box3D::X;
284     if (dirs & Box3D::Y) return Box3D::Y;
285     if (dirs & Box3D::Z) return Box3D::Z;
286     return Box3D::NONE;
288 inline Box3D::Axis extract_second_axis_direction (Box3D::Axis dirs) {
289     return extract_first_axis_direction ((Box3D::Axis) (dirs ^ extract_first_axis_direction(dirs)));
292 inline Box3D::Axis orth_plane_or_axis (Box3D::Axis axis) {
293     return (Box3D::Axis) (Box3D::XYZ ^ axis);
296 /* returns an axis direction perpendicular to the ones occuring in the (possibly compound) expression 'dirs' */
297 inline Box3D::Axis get_perpendicular_axis_direction (Box3D::Axis dirs) {
298     if (!(dirs & Box3D::X)) return Box3D::X;
299     if (!(dirs & Box3D::Y)) return Box3D::Y;
300     if (!(dirs & Box3D::Z)) return Box3D::Z;
301     return Box3D::NONE;
304 inline gchar * string_from_axes (Box3D::Axis axes) {
305     GString *pstring = g_string_new("");
306     if (axes & Box3D::X) g_string_append_printf (pstring, "X");
307     if (axes & Box3D::Y) g_string_append_printf (pstring, "Y");
308     if (axes & Box3D::Z) g_string_append_printf (pstring, "Z");
309     return pstring->str;
312 std::pair <Axis, Axis> get_remaining_axes (Axis axis);
314 } // namespace Box3D
316 #endif /* !SEEN_AXIS_MANIP_H */
318 /*
319   Local Variables:
320   mode:c++
321   c-file-style:"stroustrup"
322   c-file-offsets:((innamespace . 0)(inline-open . 0))
323   indent-tabs-mode:nil
324   fill-column:99
325   End:
326 */
327 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :