00001
00002
00003
00004
00005 #include <stdio.h>
00006 #include <string.h>
00007 #include <math.h>
00008 #include "mb_types.h"
00009
00010
00011 #define ASSERT(x)
00012
00013
00014 #define MUL(a, b) ((a) * (b))
00015 #define ADD(a, b) ((a) + (b))
00016 #define DIV(a, b) ((a) / (b))
00017 #define SUB(a, b) ((a) - (b))
00018
00019 static void mul_matrix(co_aix *m1, co_aix *m2, co_aix *dst) {
00020 dst[0] = ADD(MUL(m1[0], m2[0]), MUL(m1[1], m2[3]));
00021 dst[1] = ADD(MUL(m1[0], m2[1]), MUL(m1[1], m2[4]));
00022 dst[2] = ADD(ADD(MUL(m1[0], m2[2]), MUL(m1[1], m2[5])), m1[2]);
00023 dst[3] = ADD(MUL(m1[3], m2[0]), MUL(m1[4], m2[3]));
00024 dst[4] = ADD(MUL(m1[3], m2[1]), MUL(m1[4], m2[4]));
00025 dst[5] = ADD(ADD(MUL(m1[3], m2[2]), MUL(m1[4], m2[5])), m1[5]);
00026 }
00027
00028
00029
00030
00031
00032
00033 static void compute_transform_function(coord_t *visit) {
00034 if(visit->parent)
00035 mul_matrix(visit->parent->aggr_matrix,
00036 visit->matrix, visit->aggr_matrix);
00037 else
00038 memcpy(visit->aggr_matrix, visit->matrix, sizeof(visit->matrix));
00039 }
00040
00041 void compute_aggr_of_coord(coord_t *coord) {
00042 compute_transform_function(coord);
00043 }
00044
00045
00046
00047
00048
00049
00050 void update_aggr_matrix(coord_t *start) {
00051 coord_t *visit, *child, *next;
00052
00053 compute_transform_function(start);
00054
00055 visit = start;
00056 while(visit) {
00057 child = STAILQ_HEAD(visit->children);
00058 while(child) {
00059 compute_transform_function(child);
00060 child = STAILQ_NEXT(coord_t, sibling, child);
00061 }
00062
00063 if(STAILQ_HEAD(visit->children))
00064 visit = STAILQ_HEAD(visit->children);
00065 else if(STAILQ_NEXT(coord_t, sibling, visit))
00066 visit = STAILQ_NEXT(coord_t, sibling, visit);
00067 else {
00068 next = NULL;
00069 while(visit->parent && visit->parent != start) {
00070 visit = visit->parent;
00071 if(STAILQ_NEXT(coord_t, sibling, visit)) {
00072 next = STAILQ_NEXT(coord_t, sibling, visit);
00073 break;
00074 }
00075 }
00076 visit = next;
00077 }
00078 }
00079 }
00080
00081
00082
00083
00084
00085
00086 void coord_init(coord_t *co, coord_t *parent) {
00087 memset(co, 0, sizeof(coord_t));
00088 if(parent) {
00089
00090 co->parent = parent;
00091 STAILQ_INS_TAIL(parent->children, coord_t, sibling, co);
00092 }
00093 co->matrix[0] = 1;
00094 co->matrix[4] = 1;
00095 co->aggr_matrix[0] = 1;
00096 co->aggr_matrix[4] = 1;
00097 co->cur_area = &co->areas[0];
00098 co->last_area = &co->areas[1];
00099 }
00100
00101 void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) {
00102 co_aix nx, ny;
00103
00104 nx = ADD(ADD(MUL(co->aggr_matrix[0], *x),
00105 MUL(co->aggr_matrix[1], *y)),
00106 co->aggr_matrix[2]);
00107 ny = ADD(ADD(MUL(co->aggr_matrix[3], *x),
00108 MUL(co->aggr_matrix[4], *y)),
00109 co->aggr_matrix[5]);
00110 *x = nx;
00111 *y = ny;
00112 }
00113
00114 co_aix coord_trans_size(coord_t *co, co_aix sz) {
00115 co_aix x, y;
00116
00117 x = MUL(co->aggr_matrix[0], sz);
00118 y = MUL(co->aggr_matrix[3], sz);
00119
00120 return sqrt(x * x + y * y);
00121 }
00122
00123
00124
00125
00126
00127
00128 coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) {
00129 coord_t *next = NULL;
00130
00131 ASSERT(last != NULL);
00132
00133 if((!(last->flags & COF_SKIP_TRIVAL)) &&
00134 STAILQ_HEAD(last->children)) {
00135 next = STAILQ_HEAD(last->children);
00136 if(!(next->flags & COF_SKIP_TRIVAL))
00137 return next;
00138 } else {
00139 next = last;
00140 }
00141
00142 do {
00143 next->flags &= ~COF_SKIP_TRIVAL;
00144 while(next != root && STAILQ_NEXT(coord_t, sibling, next) == NULL)
00145 next = next->parent;
00146 if(next == root)
00147 return NULL;
00148 next = STAILQ_NEXT(coord_t, sibling, next);
00149 } while(next->flags & COF_SKIP_TRIVAL);
00150
00151 return next;
00152 }
00153
00154 coord_t *postorder_coord_subtree(coord_t *root, coord_t *last) {
00155 coord_t *next;
00156
00157 if(root == last)
00158 return NULL;
00159
00160 if(last == NULL) {
00161
00162 next = root;
00163 while(STAILQ_HEAD(next->children))
00164 next = STAILQ_HEAD(next->children);
00165 return next;
00166 }
00167
00168 next = last;
00169 if(STAILQ_NEXT(coord_t, sibling, next) == NULL)
00170 return next->parent;
00171
00172
00173 next = STAILQ_NEXT(coord_t, sibling, next);
00174 while(STAILQ_HEAD(next->children))
00175 next = STAILQ_HEAD(next->children);
00176
00177 return next;
00178 }
00179
00180 #ifdef UNITTEST
00181
00182 #include <CUnit/Basic.h>
00183
00184 void test_update_aggr_matrix(void) {
00185 coord_t elms[6];
00186 co_aix x, y;
00187
00188 coord_init(elms, NULL);
00189 coord_init(elms + 1, elms);
00190 coord_init(elms + 2, elms);
00191 coord_init(elms + 3, elms + 1);
00192 coord_init(elms + 4, elms + 1);
00193 coord_init(elms + 5, elms + 2);
00194
00195
00196
00197
00198
00199 elms[0].matrix[0] = 2;
00200 elms[0].matrix[1] = -1;
00201
00202
00203
00204
00205
00206 elms[1].matrix[1] = 3;
00207 elms[1].matrix[3] = 5;
00208
00209 update_aggr_matrix(elms);
00210
00211
00212
00213
00214
00215 CU_ASSERT(elms[3].aggr_matrix[0] == -3);
00216 CU_ASSERT(elms[3].aggr_matrix[1] == 5);
00217 CU_ASSERT(elms[3].aggr_matrix[2] == 0);
00218 CU_ASSERT(elms[3].aggr_matrix[3] == 5);
00219 CU_ASSERT(elms[3].aggr_matrix[4] == 1);
00220 CU_ASSERT(elms[3].aggr_matrix[5] == 0);
00221
00222 CU_ASSERT(elms[4].aggr_matrix[0] == -3);
00223 CU_ASSERT(elms[4].aggr_matrix[1] == 5);
00224 CU_ASSERT(elms[4].aggr_matrix[2] == 0);
00225 CU_ASSERT(elms[4].aggr_matrix[3] == 5);
00226 CU_ASSERT(elms[4].aggr_matrix[4] == 1);
00227 CU_ASSERT(elms[4].aggr_matrix[5] == 0);
00228
00229 CU_ASSERT(elms[5].aggr_matrix[0] == 2);
00230 CU_ASSERT(elms[5].aggr_matrix[1] == -1);
00231 CU_ASSERT(elms[5].aggr_matrix[2] == 0);
00232 CU_ASSERT(elms[5].aggr_matrix[3] == 0);
00233 CU_ASSERT(elms[5].aggr_matrix[4] == 1);
00234 CU_ASSERT(elms[5].aggr_matrix[5] == 0);
00235
00236 x = 50;
00237 y = 99;
00238 coord_trans_pos(elms + 5, &x, &y);
00239 CU_ASSERT(x == 1);
00240 CU_ASSERT(y == 99);
00241 }
00242
00243 void test_preorder_coord_subtree(void) {
00244 coord_t elms[6];
00245 coord_t *last;
00246
00247 coord_init(elms, NULL);
00248 coord_init(elms + 1, elms);
00249 coord_init(elms + 2, elms);
00250 coord_init(elms + 3, elms + 1);
00251 coord_init(elms + 4, elms + 1);
00252 coord_init(elms + 5, elms + 2);
00253
00254 last = elms;
00255 last = preorder_coord_subtree(elms, last);
00256 CU_ASSERT(last == elms + 1);
00257 last = preorder_coord_subtree(elms, last);
00258 CU_ASSERT(last == elms + 3);
00259 last = preorder_coord_subtree(elms, last);
00260 CU_ASSERT(last == elms + 4);
00261 last = preorder_coord_subtree(elms, last);
00262 CU_ASSERT(last == elms + 2);
00263 last = preorder_coord_subtree(elms, last);
00264 CU_ASSERT(last == elms + 5);
00265 last = preorder_coord_subtree(elms, last);
00266 CU_ASSERT(last == NULL);
00267 }
00268
00269 CU_pSuite get_coord_suite(void) {
00270 CU_pSuite suite;
00271
00272 suite = CU_add_suite("Suite_coord", NULL, NULL);
00273 CU_ADD_TEST(suite, test_update_aggr_matrix);
00274 CU_ADD_TEST(suite, test_preorder_coord_subtree);
00275
00276 return suite;
00277 }
00278
00279 #endif