1 /****************************************************************************
2  * Copyright (C) 2008-2011 by Matteo Franchin                               *
3  *                                                                          *
4  * This file is part of Box.                                                *
5  *                                                                          *
6  *   Box is free software: you can redistribute it and/or modify it         *
7  *   under the terms of the GNU Lesser General Public License as published  *
8  *   by the Free Software Foundation, either version 3 of the License, or   *
9  *   (at your option) any later version.                                    *
10  *                                                                          *
11  *   Box 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 Lesser General Public License for more details.                    *
15  *                                                                          *
16  *   You should have received a copy of the GNU Lesser General Public       *
17  *   License along with Box.  If not, see <http://www.gnu.org/licenses/>.   *
18  ****************************************************************************/
19 
20 
21 #ifndef _BOX_LIBG_TRANSFORM_H
22 #  define _BOX_LIBG_TRANSFORM_H
23 
24 #  include <box/types.h>
25 #  include "graphic.h"
26 
27 /** Flags used to specify which transformations are allowed. */
28 typedef enum {
29   BOXGALLOW_TRANSLATE_X = 0x1,  /**< Allow automatic translation along x */
30   BOXGALLOW_TRANSLATE_Y = 0x2,  /**< Allow automatic translation along y */
31   BOXGALLOW_TRANSLATE   = 0x3,  /**< Allow automatic translation in x, y */
32   BOXGALLOW_ROTATE      = 0x4,  /**< Allow automatic rotation */
33   BOXGALLOW_SCALE       = 0x8,  /**< Allow automatic scaling */
34   BOXGALLOW_ANISOTROPIC = 0x10, /**< Allow different scaling in x and y */
35   BOXGALLOW_INVERT      = 0x20, /**< Allow mirroring the figure */
36   BOXGALLOW_DEFORM      = 0x30, /**< Allow mirroring and anisotropic scaling */
37   BOXGALLOW_ALL         = 0x3f  /**< All flags or-ed together */
38 
39 } BoxGAllow;
40 
41 /** Structure containing a transformation in terms of translation vector,
42  * rotation center and angle and scaling factors. From this structure
43  * a transformation matrix can be obtained.
44  */
45 typedef struct {
46   BoxPoint translation,
47            rotation_center;
48   BoxReal  rotation_angle,
49            rotation_cos,
50            rotation_sin,
51            scale_factor,
52            scaling_angle,
53            scaling_cos,
54            scaling_sin;
55 
56 } BoxGTransform;
57 
58 /** Used by BoxG_Auto_Transform to signal errors. */
59 typedef enum {
60   BOXGAUTOTRANSFORMERR_NO_ERR=0,
61   BOXGAUTOTRANSFORMERR_NOT_ENOUGH_POINTS,
62   BOXGAUTOTRANSFORMERR_ZERO_WEIGHTS,
63   BOXGAUTOTRANSFORMERR_NOT_IMPLEMENTED
64 
65 } BoxGAutoTransformErr;
66 
67 
68 /** Provide a string representation of the given BoxGAutoTransformErr. */
69 const char *BoxGAutoTransformErr_To_String(BoxGAutoTransformErr n);
70 
71 /** From an initial transformation 'transform', 'n' constraints (provided in
72  * 'src', 'dst' and 'weight') and a set of allowed transformations,
73  * 'allowed_transformation', finds the one which best satisfies the
74  * constraints. In particular, the objective is to minimise the function:
75  *
76  *   f(q) = sum_i {weight[i]*(T(q) src[i] - dst[i])^2} / sum_i {weight[i]}
77  *
78  * where T[q] is a transformation parametrized by q, which is a vector made
79  * by all the available degrees of freedom. The objective is then to determine
80  * 'q' and T(q). T(q) is then stored inside 'transform'.
81  */
82 BoxGAutoTransformErr
83 BoxG_Auto_Transform(BoxGTransform *transform,
84                     BoxPoint *src, BoxPoint *dst, BoxReal *weight, int n,
85 		    BoxGAllow allowed_transforms);
86 
87 /** Convert a string to a BoxGAllow value to use with BoxG_Auto_Transform. This
88  * function allows quick specification of the allowed transformations. Allowed
89  * transformations are specified using letters. Each letter corresponds to an
90  * allowed transformation. For example: "rt" means that "r"otations and
91  * "t"ranslations are allowed. The order of letters does not matter, e.g. "rt"
92  * is equivalent to "tr". The following table collects the associations
93  * between letters and transformations:
94  *  "t" -> translation, "r" -> rotation, "s" -> scale,
95  *  "a" -> allows anisotropic scaling, "i" -> allows inversion (mirroring) It
96  * is also possible to use "tx" or "ty" to enable translation only along one of
97  * the axes. It is also possible to give sign "+" and "-". The sign change the
98  * behaviour of the function. "+" means that the following characters should be
99  * used to enable transformations (default), while "-" means that they should
100  * be used to disable transformations. This is handy for concatenated
101  * strings. Example: allowed + "-txr" means that we should do whathever
102  * specified by 'allowed', but we should not translate along-x nor rotate.
103  * There are then a few characters to fine tune the behaviour of the function.
104  * When 'string' starts with a white space " ", the flags are or-ed over the
105  * pre-existing flags in '*allow' (while if the string does not start with a
106  * space the initial value of '*allow' is ignored, i.e. set to zero). Spaces in
107  * the middle of the string are ignored.
108  */
109 BoxTask BoxGAllow_Of_String(BoxGAllow *allow, const char *string);
110 
111 #endif /*_BOX_LIBG_TRANSFORM_H */
112