1 /*
2 *
3 * str2.c
4 *
5 * Utilities for dealing with strings of 2D points (Edgels or VEC2's)
6 */
7 #include <tina/sys.h>
8 #include <tina/sysfuncs.h>
9 #include <tina/math.h>
10 #include <tina/mathfuncs.h>
11 #include <tina/vision.h>
12 #include <tina/visionfuncs.h>
13
14 /*
15 Return centroid of points on 2D string.
16 */
17 Vec2 str2_centroid(Tstring * str)
18 {
19 Vec2 sum = vec2_zero(), p;
20 List *ptr;
21 int n = 0;
22 if (str == NULL)
23 return (sum);
24 for (ptr = str->start; ; ptr=ptr->next)
25 {
26 DD_GET_POS2(ptr, p);
27 sum = vec2_sum(sum, p);
28 n++;
29 if(ptr == str->end)
30 break;
31 }
32 return (vec2_times(1.0 / n, sum));
33 }
34
35 /*
36 Translate a 2d string by vector v.
37 */
38 void str2_translate(Tstring * str, Vec2 v)
39 {
40 List *ptr;
41
42 if (str == NULL)
43 return;
44 for (ptr = str->start; ; ptr = ptr->next)
45 {
46 Vec2 p;
47
48 DD_GET_POS2(ptr, p);
49 p = vec2_sum(p, v);
50 DD_SET_POS2(ptr, p);
51 if (ptr == str->end)
52 break;
53 }
54 }
55
56 /*
57 Rotate, translate, and scale a 2d string about centre c.
58 x->t+c+sr(x-c).
59 */
60 void str2_rts(Tstring * str, Vec2 c, Mat2 r, Vec2 t, double s)
61 {
62 List *ptr;
63
64 if (str == NULL)
65 return;
66 for (ptr = str->start; ; ptr = ptr->next)
67 {
68 Vec2 p;
69
70 DD_GET_POS2(ptr, p);
71 p = vec2_diff(p, c);
72 p = vec2_times(s, p);
73 p = mat2_vprod(r, p);
74 p = vec2_sum3(c, t, p);
75 DD_SET_POS2(ptr, p);
76 if (ptr == str->end)
77 break;
78 }
79 }
80
81 /*
82 Return area enclosed by 2D string (0 for type STRING).
83 */
84 double str2_area(Tstring * str) /* Newcode */
85 {
86 List *ptr;
87 double a = 0.0;
88 if (str == NULL)
89 return(0.0);
90 if (str->type == STRING)
91 {
92 error("str2_area: passed open contour", non_fatal);
93 return (0.0);
94 }
95 for (ptr = str->start; ; ptr = ptr->next)
96 {
97 Vec2 p1, p2;
98 DD_GET_POS2(ptr, p1);
99 DD_GET_POS2(ptr->next, p2);
100 a += vec2_cross(p1, p2);
101 if (ptr == str->end)
102 break;
103 }
104 a *= 0.5;
105 return (a);
106 }
107
108 /*
109 Find major and minor axes (a, b) and angle of principle direction
110 theta of 2D-string.
111 */
112 void str2_eigen(Tstring * str, double *a, double *b, double *theta)
113 {
114 List *ptr;
115 Mat2 m = mat2_zero();
116 Vec2 c = str2_centroid(str);
117 if (str == NULL)
118 return;
119 for (ptr = str->start; ; ptr = ptr->next)
120 {
121 Vec2 p;
122 DD_GET_POS2(ptr, p);
123 p = vec2_diff(p, c);
124 m = mat2_sum(m, mat2_tensor(p, p));
125 if (ptr == str->end)
126 break;
127 }
128 mat2_sym_eigen(m, theta, a, b);
129 }
130
131 /*
132 Return angle of major axis of 2D string.
133 */
134 double str2_orientation(Tstring * str)
135 {
136 double a, b, theta;
137 str2_eigen(str, &a, &b, &theta);
138 return (theta);
139 }
140
141 /*
142 Allocates Vec2 at same position as Edgel or Vec2 pointer.
143 */
144 static Vec2 *make_vec2_from_edge(void *e, int *type)
145 {
146 Vec2 v;
147
148 GET_POS2(e, *type, v);
149 *type = VEC2;
150 return (vec2_make(v));
151 }
152
153 /*
154 Return copy of 2D string (with Vec2 entries).
155 */
156 Tstring *str2_copy(Tstring * str)
157 {
158 return(str_copy(str, (void *(*) ()) vec2_copy, NULL));
159 }
160
161 /*
162 Return total arc (chord) length of Ddstring, running from
163 start past nextoend.
164 */
165 double dd2_arc_length(List *start, List *nextoend)
166 {
167 List *ptr;
168 double s;
169 if (start == NULL || nextoend == NULL || nextoend->next == NULL)
170 return (0.0);
171 for (s = 0.0, ptr = start;; ptr = ptr->next)
172 {
173 Vec2 p1, p2;
174 DD_GET_POS2(ptr, p1);
175 DD_GET_POS2(ptr->next, p2);
176 s += vec2_dist(p1, p2);
177 if (ptr == nextoend)
178 break;
179 }
180 return (s);
181 }
182
183 /*
184 Return total arc (chord) length of 2D string.
185 */
186 double str2_arc_length(Tstring * str)
187 {
188 if (str == NULL || str->count < 2)
189 return (0.0);
190 switch(str->type)
191 {
192 case LOOP:
193 return(dd2_arc_length(str->start, str->end));
194 case STRING:
195 return(dd2_arc_length(str->start, str->end->last));
196 default:
197 return(-1.0);
198 }
199 }
200
201 /*
202 Return total absolute angle turned through by 2D List,
203 summing angles at nextostart up to nextoend.
204 */
205 double dd2_ang_length(List *nextostart, List *nextoend)
206 {
207 List *ptr;
208 double s;
209 if (nextostart == NULL || nextoend == NULL)
210 return (0.0);
211 for (s = 0.0, ptr = nextostart;; ptr = ptr->next)
212 {
213 Vec2 p1, p2, p3;
214 DD_GET_POS2(ptr->last, p1);
215 DD_GET_POS2(ptr, p2);
216 DD_GET_POS2(ptr->next, p3);
217 s += fabs(vec2_angle(vec2_diff(p3, p2), vec2_diff(p2, p1)));
218 if (ptr == nextoend)
219 break;
220 }
221 return (s);
222 }
223
224 /*
225 Return total absolute angle turned through by 2D string.
226 */
227 double str2_ang_length(Tstring * str)
228 {
229 if (str == NULL ||
230 (str->type == LOOP && str->count < 2) ||
231 (str->type == STRING && str->count < 3))
232 return (0.0);
233 switch(str->type)
234 {
235 case LOOP:
236 return(dd2_ang_length(str->start, str->end));
237 case STRING:
238 return(dd2_ang_length(str->start->next, str->end->last));
239 default:
240 return(-1.0);
241 }
242 }
243
244 /*
245 Put n equally spaced points from 2D string in Vec2 array
246 p[0],i...,p[n-1]. (Note points are always on string, to get
247 interpolated points see str2_get_interp_vec2_knots below)
248 */
249 void str2_get_vec2_knots(Tstring * str, int n, Vec2 * p)
250 {
251 List *ptr;
252 int i, j;
253 double s, ds;
254
255 s = str->count;
256 switch (str->type)
257 {
258 case STRING:
259 ds = (s-1) / (n - 1);
260 break;
261 case LOOP:
262 ds = s / (n-1);
263 break;
264 default:
265 return;
266 }
267 for (i = 0, j = 0, ptr = str->start; j < n; i++, ptr = ptr->next)
268 {
269 if (i >= j * ds || (str->type == STRING && ptr == str->end))
270 {
271 DD_GET_POS2(ptr, p[j]);
272 j++;
273 }
274 }
275 }
276
277 /*
278 Get point given arc-length along 2D string.
279 */
280 Vec2 str2_point(Tstring *str, double t)
281 {
282 List *ptr, *end;
283 double s;
284 if(str == NULL)
285 return(vec2_zero());
286 if(str->count == 1 || t <= 0)
287 {
288 Vec2 p;
289 DD_GET_POS2(str->start, p);
290 return(p);
291 }
292 switch(str->type)
293 {
294 case LOOP:
295 end = str->start;
296 break;
297 case STRING:
298 end = str->end;
299 break;
300 }
301 for(s = 0, ptr = str->start; ; ptr = ptr->next)
302 {
303 Vec2 p1, p2;
304 double ds;
305 DD_GET_POS2(ptr, p1);
306 DD_GET_POS2(ptr->next, p2);
307 ds = vec2_dist(p1, p2);
308 if(ds != 0.0 && s+ds >= t)
309 return(vec2_interp((t-s) / ds, p1, p2));
310 s += ds;
311 if(ptr->next == end)
312 return(p2);
313 }
314 }
315
316 /*
317 Put n equally spaced points interpolated from 2D string
318 in Vec2 array p[0],i...,p[n-1].
319 */
320 void str2_get_interp_vec2_knots(Tstring * str, int n, Vec2 * p)
321 {
322 double s;
323 int i, m;
324 if(str == NULL)
325 return;
326 switch(str->type)
327 {
328 case STRING:
329 m = n-1;
330 break;
331 case LOOP:
332 m = n;
333 break;
334 default:
335 return;
336 }
337 /* get str length */
338 s = str2_arc_length(str);
339 for(i = 0; i < n; i++)
340 {
341 double t = (i*s)/m;
342 p[i] = str2_point(str, t);
343 }
344 }
345
346 /*
347 Return an 8-neighbour connected string linearly interpolating str.
348 */
349 Tstring *str2_fill(Tstring *str)
350 {
351 double s = str2_arc_length(str);
352 return (str2_of_curve2(str2_point, str, 0, s, (void *) NULL));
353 }
354
355 /*
356 Free a 2D string.
357 */
358 void str2_free(Tstring *str)
359 {
360 str_free(str, rfree);
361 }
362
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.