1 /*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2012, 2011, 2010, 2009 University of Chicago
4 Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann
5 Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 (LGPL) as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 The terms of redistributing and/or modifying this software also
12 include exceptions to the LGPL that facilitate static linking.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library; if not, write to Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "echo.h"
25 #include "privateEcho.h"
26
27 void
echoListAdd(echoObject * list,echoObject * child)28 echoListAdd(echoObject *list, echoObject *child) {
29 int idx;
30
31 if (!( list && child &&
32 (echoTypeList == list->type ||
33 echoTypeAABBox == list->type) ))
34 return;
35
36 idx = airArrayLenIncr(LIST(list)->objArr, 1);
37 LIST(list)->obj[idx] = child;
38
39 return;
40 }
41
42 int
_echoPosCompare(double * A,double * B)43 _echoPosCompare(double *A, double *B) {
44
45 return *A < *B ? -1 : (*A > *B ? 1 : 0);
46 }
47
48 /*
49 ******** echoListSplit()
50 **
51 ** returns a echoObjectSplit to point to the same things as pointed
52 ** to by the given echoObjectList
53 */
54 echoObject *
echoListSplit(echoScene * scene,echoObject * list,int axis)55 echoListSplit(echoScene *scene, echoObject *list, int axis) {
56 echoPos_t lo[3], hi[3], loest0[3], hiest0[3],
57 loest1[3], hiest1[3];
58 double *mids;
59 echoObject *o, *split, *list0, *list1;
60 int i, splitIdx, len;
61
62 if (!( echoTypeList == list->type ||
63 echoTypeAABBox == list->type )) {
64 return list;
65 }
66
67 len = LIST(list)->objArr->len;
68 if (len <= ECHO_LEN_SMALL_ENOUGH) {
69 /* there is nothing or only one object */
70 return list;
71 }
72
73 split = echoObjectNew(scene, echoTypeSplit);
74 list0 = echoObjectNew(scene, echoTypeList);
75 list1 = echoObjectNew(scene, echoTypeList);
76 SPLIT(split)->axis = axis;
77 SPLIT(split)->obj0 = list0;
78 SPLIT(split)->obj1 = list1;
79
80 mids = (double *)malloc(2 * len * sizeof(double));
81 for (i=0; i<len; i++) {
82 o = LIST(list)->obj[i];
83 echoBoundsGet(lo, hi, o);
84 mids[0 + 2*i] = (lo[axis] + hi[axis])/2;
85 *((unsigned int *)(mids + 1 + 2*i)) = i;
86 }
87 /* overkill, I know, I know */
88 qsort(mids, len, 2*sizeof(double),
89 (int (*)(const void *, const void *))_echoPosCompare);
90 /*
91 for (i=0; i<len; i++) {
92 printf("%d -> %g\n", i, mids[0 + 2*i]);
93 }
94 */
95
96 splitIdx = len/2;
97 /* printf("splitIdx = %d\n", splitIdx); */
98 ELL_3V_SET(loest0, ECHO_POS_MAX, ECHO_POS_MAX, ECHO_POS_MAX);
99 ELL_3V_SET(loest1, ECHO_POS_MAX, ECHO_POS_MAX, ECHO_POS_MAX);
100 ELL_3V_SET(hiest0, ECHO_POS_MIN, ECHO_POS_MIN, ECHO_POS_MIN);
101 ELL_3V_SET(hiest1, ECHO_POS_MIN, ECHO_POS_MIN, ECHO_POS_MIN);
102 airArrayLenSet(LIST(list0)->objArr, splitIdx);
103 for (i=0; i<splitIdx; i++) {
104 o = LIST(list)->obj[*((unsigned int *)(mids + 1 + 2*i))];
105 LIST(list0)->obj[i] = o;
106 echoBoundsGet(lo, hi, o);
107 /*
108 printf("000 lo = (%g,%g,%g), hi = (%g,%g,%g)\n",
109 lo[0], lo[1], lo[2], hi[0], hi[1], hi[2]);
110 */
111 ELL_3V_MIN(loest0, loest0, lo);
112 ELL_3V_MAX(hiest0, hiest0, hi);
113 }
114 airArrayLenSet(LIST(list1)->objArr, len-splitIdx);
115 for (i=splitIdx; i<len; i++) {
116 o = LIST(list)->obj[*((unsigned int *)(mids + 1 + 2*i))];
117 LIST(list1)->obj[i-splitIdx] = o;
118 echoBoundsGet(lo, hi, o);
119 /*
120 printf("111 lo = (%g,%g,%g), hi = (%g,%g,%g)\n",
121 lo[0], lo[1], lo[2], hi[0], hi[1], hi[2]);
122 */
123 ELL_3V_MIN(loest1, loest1, lo);
124 ELL_3V_MAX(hiest1, hiest1, hi);
125 }
126 /*
127 printf("0: loest = (%g,%g,%g); hiest = (%g,%g,%g)\n",
128 loest0[0], loest0[1], loest0[2],
129 hiest0[0], hiest0[1], hiest0[2]);
130 printf("1: loest = (%g,%g,%g); hiest = (%g,%g,%g)\n",
131 loest1[0], loest1[1], loest1[2],
132 hiest1[0], hiest1[1], hiest1[2]);
133 */
134 ELL_3V_COPY(SPLIT(split)->min0, loest0);
135 ELL_3V_COPY(SPLIT(split)->max0, hiest0);
136 ELL_3V_COPY(SPLIT(split)->min1, loest1);
137 ELL_3V_COPY(SPLIT(split)->max1, hiest1);
138
139 /* we can't delete the list object here, we just gut it so
140 that there's nothing substantial left of it */
141 airArrayLenSet(LIST(list)->objArr, 0);
142 mids = (double *)airFree(mids);
143 return split;
144 }
145
146 echoObject *
echoListSplit3(echoScene * scene,echoObject * list,int depth)147 echoListSplit3(echoScene *scene, echoObject *list, int depth) {
148 echoObject *ret, *tmp0, *tmp1;
149
150 if (!( echoTypeList == list->type ||
151 echoTypeAABBox == list->type ))
152 return NULL;
153
154 if (!depth)
155 return list;
156
157 ret = echoListSplit(scene, list, 0);
158
159 #define DOIT(obj, ax) ((obj) = echoListSplit(scene, (obj), (ax)))
160 #define MORE(obj) echoTypeSplit == (obj)->type
161
162 if (MORE(ret)) {
163 tmp0 = DOIT(SPLIT(ret)->obj0, 1);
164 if (MORE(tmp0)) {
165 tmp1 = DOIT(SPLIT(tmp0)->obj0, 2);
166 if (MORE(tmp1)) {
167 SPLIT(tmp1)->obj0 = echoListSplit3(scene, SPLIT(tmp1)->obj0, depth-1);
168 SPLIT(tmp1)->obj1 = echoListSplit3(scene, SPLIT(tmp1)->obj1, depth-1);
169 }
170 tmp1 = DOIT(SPLIT(tmp0)->obj1, 2);
171 if (MORE(tmp1)) {
172 SPLIT(tmp1)->obj0 = echoListSplit3(scene, SPLIT(tmp1)->obj0, depth-1);
173 SPLIT(tmp1)->obj1 = echoListSplit3(scene, SPLIT(tmp1)->obj1, depth-1);
174 }
175 }
176 tmp0 = DOIT(SPLIT(ret)->obj1, 1);
177 if (MORE(tmp0)) {
178 tmp1 = DOIT(SPLIT(tmp0)->obj0, 2);
179 if (MORE(tmp1)) {
180 SPLIT(tmp1)->obj0 = echoListSplit3(scene, SPLIT(tmp1)->obj0, depth-1);
181 SPLIT(tmp1)->obj1 = echoListSplit3(scene, SPLIT(tmp1)->obj1, depth-1);
182 }
183 tmp1 = DOIT(SPLIT(tmp0)->obj1, 2);
184 if (MORE(tmp1)) {
185 SPLIT(tmp1)->obj0 = echoListSplit3(scene, SPLIT(tmp1)->obj0, depth-1);
186 SPLIT(tmp1)->obj1 = echoListSplit3(scene, SPLIT(tmp1)->obj1, depth-1);
187 }
188 }
189 }
190 return ret;
191 }
192
193