~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Tina4/src/vision/curve2/con_test.c

Version: ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /**@(#)
  2 **/
  3 #include <math.h>
  4 #include <tina/sys.h>
  5 #include <tina/sysfuncs.h>
  6 #include <tina/math.h>
  7 #include <tina/mathfuncs.h>
  8 #include <tina/vision.h>
  9 #include <tina/visionfuncs.h>
 10 #ifdef _PCC
 11 #include <memory.h>
 12 #endif
 13 
 14 double  conic_chi2(Vec2 p, Conic * conic, Conic_stat * stats)
 15 {
 16     double  px = vec2_x(p);
 17     double  py = vec2_y(p);
 18     double  z, h[5], uh[5];
 19     double  sum;
 20     int     i, j;
 21 
 22     if (conic == NULL || stats == NULL)
 23         return (0.0);
 24 
 25     z = conic_eval(conic, p);
 26     h[0] = px * px - py * py;
 27     h[1] = 2.0 * px * py;
 28     h[2] = 2.0 * px;
 29     h[3] = 2.0 * py;
 30     h[4] = 1.0;
 31 
 32     for (i = 0; i < 5; i++)
 33     {
 34         sum = 0.0;
 35         for (j = 0; j < i; j++)
 36             sum += stats->u[j][i] * h[j];
 37         sum += h[i];
 38         uh[i] = sum;
 39     }
 40 
 41     sum = 0.0;
 42     for (i = 0; i < 5; i++)
 43         sum += uh[i] * stats->d[i] * uh[i];
 44 
 45     return (chisq(z * z / sum, 1));
 46 }
 47 
 48 static double neglength(void *geom, int type)
 49 {
 50     switch (type)
 51     {
 52         case CONIC2:
 53         return (-conic_approx_length((Conic *) geom, 2));
 54     default:
 55         return (0.0);
 56     }
 57 }
 58 
 59 #if 0
 60 static double closeness(void *geom, int type, Conic * conic1)
 61 {
 62     Vec2    p1 = {Vec2_id};
 63     Vec2    p2 = {Vec2_id};
 64     Vec2    q1 = {Vec2_id};
 65     Vec2    q2 = {Vec2_id};
 66     double  d11, d12, d21, d22;
 67 
 68     p1 = conic_point(conic1, conic1->t1);
 69     p2 = conic_point(conic1, conic1->t2);
 70 
 71     switch (type)
 72     {
 73     case CONIC2:
 74         {
 75             Conic  *conic = (Conic *) geom;
 76 
 77             q1 = conic_point(conic, conic->t1);
 78             q2 = conic_point(conic, conic->t2);
 79             break;
 80         }
 81     case LINE2:
 82         {
 83             Line2  *line = (Line2 *) geom;
 84 
 85             q1 = line->p1;
 86             q2 = line->p2;
 87             break;
 88         }
 89     default:
 90         return (1e10);
 91     }
 92 
 93     d11 = vec2_dist(p1, q1);
 94     d12 = vec2_dist(p1, q2);
 95     d21 = vec2_dist(p2, q1);
 96     d22 = vec2_dist(p2, q2);
 97     return (MIN4(d11, d12, d21, d22));
 98 }
 99 
100 #endif
101 
102 static Conic *conic_of_line(Line2 * line)
103 {
104     Tstring *str = (Tstring *) prop_get(line->props, STRING);
105     Vec2    p1 = {Vec2_id};
106     Vec2    p2 = {Vec2_id};
107     Vec2    p3 = {Vec2_id};
108 
109     if (str->count < 3)
110         return (NULL);
111 
112     DD_GET_POS2(str->start, p1);
113     DD_GET_POS2(str_mid_point(str), p2);
114     DD_GET_POS2(str->end, p3);
115 
116     return (conic_circ_3pt(p1, p2, p3));
117 }
118 
119 Bool    conic_param_between(double t, double t1, double t2)
120 /* always in range 0 to 2PI */
121 /* t2 always > t1  and t1 is less than 2 PI */
122 {
123     if (t < t1)
124         t += TWOPI;
125 
126     return ((t < t2) ? true : false);
127 }
128 
129 #define MAXRATIO(a, b) MAX((a)/(b), (b)/(a))
130 
131 /* check if a pair of conics are compatible for combination */
132 static Bool conics_compatible(Conic * conic1, Conic * conic2, double low_conf, double hi_conf)
133 {
134     Vec2    p1 = {Vec2_id};
135     Vec2    g1 = {Vec2_id};
136     Vec2    e1 = {Vec2_id};
137     Vec2    p2 = {Vec2_id};
138     Vec2    g2 = {Vec2_id};
139     Vec2    e2 = {Vec2_id};
140     Vec2    e11 = {Vec2_id};
141     Vec2    e12 = {Vec2_id};
142     Vec2    e21 = {Vec2_id};
143     Vec2    e22 = {Vec2_id};
144     Conic_stat *stats1;
145     Conic_stat *stats2;
146     double  chi1, chi2;
147     double  d11, d12, d21, d22;
148     double  len1, len2;
149     double  rad1, rad2;
150     double  t, min_dist;
151 
152     if (conic1 == NULL || conic2 == NULL || conic1->type != conic2->type)
153     {
154 /* this is a sign of corrupted data so watch out!
155    NAT 31/12/99 */
156         if (conic1->type != conic2->type) 
157             error("incompatable structures in conics_compatible()",warning);
158         return (false);
159     }
160 
161     /** conic mid points **/
162     p1 = conic_point(conic1, 0.5 * (conic1->t1 + conic1->t2));
163     p2 = conic_point(conic2, 0.5 * (conic2->t1 + conic2->t2));
164 
165     stats1 = (Conic_stat *) prop_get(conic1->props, STATS);
166     stats2 = (Conic_stat *) prop_get(conic2->props, STATS);
167 
168     chi1 = conic_chi2(p1, conic2, stats2);
169     chi2 = conic_chi2(p2, conic1, stats1);
170 
171     /* test for evidence of continuation from chi test */
172     if (stats2 != NULL && stats1 != NULL)
173     {
174         if (chi1 < low_conf && chi2 < low_conf)
175             return (false);
176     } else if (stats2 != NULL)
177     {
178         if (chi1 < low_conf)
179             return (false);
180     } else if (stats1 != NULL)
181     {
182         if (chi2 < low_conf)
183             return (false);
184     }
185     /* get end points */
186     e11 = conic_point(conic1, conic1->t1);
187     e12 = conic_point(conic1, conic1->t2);
188     e21 = conic_point(conic2, conic2->t1);
189     e22 = conic_point(conic2, conic2->t2);
190 
191     /* check the conics do not overlap */
192 
193     t = conic_param(conic2, e11);
194     if (conic_param_between(t, conic2->t1, conic2->t2))
195         return (false);
196 
197     t = conic_param(conic2, e12);
198     if (conic_param_between(t, conic2->t1, conic2->t2))
199         return (false);
200 
201     t = conic_param(conic1, e21);
202     if (conic_param_between(t, conic1->t1, conic1->t2))
203         return (false);
204 
205     t = conic_param(conic1, e21);
206     if (conic_param_between(t, conic1->t1, conic1->t2))
207         return (false);
208 
209     /* distances between end points */
210     d11 = vec2_dist(e11, e21);
211     d12 = vec2_dist(e11, e22);
212     d21 = vec2_dist(e12, e21);
213     d22 = vec2_dist(e12, e22);
214     min_dist = MIN4(d11, d12, d21, d22);
215 
216     /* if very close end points  then TRUE */
217     if (min_dist < 10)
218         return (true);
219 
220     if (min_dist == d11)
221     {
222         e1 = e11;
223         e2 = e21;
224     } else if (min_dist == d12)
225     {
226         e1 = e11;
227         e2 = e22;
228     } else if (min_dist == d21)
229     {
230         e1 = e12;
231         e2 = e21;
232     } else
233     {
234         e1 = e12;
235         e2 = e22;
236     }
237 
238     len1 = conic_approx_length(conic1, 5);
239     len2 = conic_approx_length(conic2, 5);
240 
241     /* if either of the lines is short then FALSE */
242     if (len1 < 20 || len2 < 20)
243         return (false);
244 
245     /* if the gap is shorter than both of the lines then TRUE */
246     if (min_dist > len1 || min_dist > len2)
247         return (false);
248 
249     g1 = vec2_unit(conic_grad(conic1, e1));
250     g2 = vec2_unit(conic_grad(conic2, e2));
251 
252     /* if ends are co-tangental then TRUE */
253     if (fabs(vec2_dot(g1, g2)) > 0.9)
254     {
255         Vec2    t = {Vec2_id};
256 
257         t = vec2_unit(vec2_diff(e2, e1));
258         if (fabs(vec2_dot(g1, t)) < 0.15 && fabs(vec2_dot(g2, t)) < 0.15)
259             return (true);
260     }
261     rad1 = MAX(conic1->alpha, conic1->beta);
262     rad2 = MAX(conic2->alpha, conic2->beta);
263 
264     /** gross test for closeness **/
265     if (vec2_dist(p2, conic1->center) > 3.0 * rad1 &&
266         vec2_dist(p1, conic2->center) > 3.0 * rad2)
267         return (false);
268 
269     if (chi1 > hi_conf || chi2 > hi_conf)
270         return (true);
271 
272     /** gradients and concavity sign at test point match approximately **/
273     g1 = vec2_unit(conic_grad(conic1, p2));
274     g2 = vec2_unit(conic_grad(conic2, p2));
275     if (vec2_dot(g1, g2) > 0.95)
276         return (true);
277     g1 = vec2_unit(conic_grad(conic1, p1));
278     g2 = vec2_unit(conic_grad(conic2, p1));
279     if (vec2_dot(g1, g2) > 0.95)
280         return (true);
281 
282     return (false);
283 }
284 
285 static Bool conic_and_geom_compatible(Conic * conic1, void *geom, int type, double low_conf, double hi_conf)
286 {
287     switch (type)
288     {
289         case CONIC2:
290         return (conics_compatible(conic1, (Conic *) geom, low_conf, hi_conf));
291     case LINE2:
292         {
293             Conic  *conic2 = conic_of_line((Line2 *) geom);
294             Bool    result;
295 
296             if (conic2 == NULL)
297                 return (false);
298             result = conics_compatible(conic1, conic2, low_conf, hi_conf);
299             conic_free(conic2);
300             return (result);
301         }
302     default:
303         return (false);
304     }
305 }
306 
307 static Conic *conic_join_strings(Tstring * str1, Tstring * str2, double lo_th, double hi_th, int max_div)
308 {
309     Tstring *str;
310     Conic  *conic;
311     List   *strings;
312 
313     str = es_combine(str1, str2);
314     conic = (Conic *) conic_ellipse_fit(str->start, str->end, 0.2);
315     if (conic == NULL)
316     {
317         str_rm(str, (void (*) ()) NULL);
318         return (NULL);
319     }
320     conic->props = proplist_add(conic->props, (void *) str, STRING, str_rm_only_str);
321 
322     strings = list_of(STRING, str1, STRING, str2, NULL);
323     if (!conic_check_list(conic, strings, lo_th, hi_th, max_div))
324     {
325         conic_free(conic);
326         list_rm_links(strings);
327         return (NULL);
328     }
329     list_rm_links(strings);
330     return (conic);
331 }
332 
333 static Conic *conic_join_list(List * list, double lo_th, double hi_th, int max_div)
334 {
335     Tstring *str;
336     Conic  *conic;
337 
338     list = list_copy(list, (void *(*) ()) NULL, NULL);
339     list = es_list_order(list);
340     str = es_list_cat(list);    /* total string */
341 
342     conic = (Conic *) conic_ellipse_fit(str->start, str->end, 0.2);
343     if (conic == NULL)
344     {
345         str_rm(str, (void (*) ()) NULL);
346         list_rm_links(list);
347         return (NULL);
348     }
349     conic->props = proplist_add(conic->props, (void *) str, STRING, str_rm_only_str);
350 
351     if (!conic_check_list(conic, list, lo_th, hi_th, max_div))
352     {
353         conic_free(conic);
354         list_rm_links(list);
355         return (NULL);
356     }
357     list_rm_links(list);
358     return (conic);
359 }
360 
361 static Conic *conic_join_array(Tstring * str, int *t_array, Tstring ** s_array, int n, double lo_th, double hi_th, int max_div)
362 {
363     List   *list = NULL;
364     Conic  *conic;
365     int     i;
366 
367     for (i = 0; i < n; ++i)
368         if (t_array[i])
369             list = ref_addtostart(list, (void *) s_array[i], STRING);
370 
371     if (list == NULL)
372         return (NULL);
373 
374     list = ref_addtostart(list, (void *) str, STRING);
375     list = es_list_order(list);
376     str = es_list_cat(list);    /* total string */
377 
378     conic = (Conic *) conic_ellipse_fit(str->start, str->end, 0.2);
379     if (conic == NULL)
380     {
381         list_rm_links(list);
382         str_rm(str, (void (*) ()) NULL);
383         return (NULL);
384     }
385     conic->props = proplist_add(conic->props, (void *) str, STRING, str_rm_only_str);
386 
387     if (!conic_check_list(conic, list, lo_th, hi_th, max_div))
388     {
389         conic_free(conic);
390         list_rm_links(list);
391         return (NULL);
392     }
393     list_rm_links(list);
394     return (conic);
395 }
396 
397 static int rec_max_div;
398 static double rec_lo_thres, rec_hi_thres, max;
399 static Conic *best_conic=NULL;
400 
401 static int *b_array=NULL;
402 static int *t_array=NULL;
403 static Tstring **s_array=NULL;
404 static Tstring *rec_str=NULL;
405 static int rec_n;
406 
407 static void conic_rec_choose(int i, double val)
408 {
409     if (i == rec_n)
410     {
411         Conic  *conic;
412 
413         if (val < max)
414             return;
415         conic = conic_join_array(rec_str, t_array, s_array, rec_n,
416                              rec_lo_thres, rec_hi_thres, rec_max_div);
417         if (conic == NULL)
418             return;
419         conic_free(best_conic);
420         best_conic = conic;
421         (void) memcpy((char *) b_array, (char *) t_array, rec_n * sizeof(int));
422         max = val;
423         return;
424     }
425     t_array[i] = 1;
426     conic_rec_choose(i + 1, val + s_array[i]->count);
427     t_array[i] = 0;
428     conic_rec_choose(i + 1, val);
429 }
430 
431 static Conic *best_from_list(Conic * conic, List * list, List ** con_list, double lo_thres, double hi_thres, int max_div)
432 {
433     Conic  *new_con;
434     List   *ptr;
435     List   *slist;
436     int     i;
437 
438     if (conic == NULL || list == NULL)
439         return (NULL);
440 
441     slist = reclist_list_update(list, geom_prop_update_get, (int) NULL, (void *) STRING);
442     slist = ref_addtostart(slist, (void *) prop_get(conic->props, STRING), STRING);
443     new_con = conic_join_list(slist, lo_thres, hi_thres, max_div);
444     list_rm_links(slist);
445 
446     if (new_con != NULL)
447     {
448         /* the whole list is consistent */
449         *con_list = list_copy(list, (void *(*) ()) NULL, NULL);
450         return (new_con);
451     }
452     best_conic = NULL;
453     rec_lo_thres = lo_thres;
454     rec_hi_thres = hi_thres;
455     rec_max_div = max_div;
456     rec_str = (Tstring *) prop_get(conic->props, STRING);
457     rec_n = list_length(list);
458     t_array = ivector_alloc(0, rec_n);
459     b_array = ivector_alloc(0, rec_n);
460     s_array = (Tstring **) pvector_alloc(0, rec_n);
461 
462     for (i = 0, ptr = list; ptr != NULL; i++, ptr = ptr->next)
463     {
464         t_array[i] = b_array[i] = 0;
465         s_array[i] = (Tstring *) geom_prop_get(ptr->to, ptr->type, STRING);
466     }
467 #ifdef _ICC
468     {
469         double  zero = 0.0;
470 
471         conic_rec_choose(0, zero);
472     }
473 #else
474     conic_rec_choose(0, 0.0);
475 #endif
476 
477     *con_list = NULL;
478     for (i = 0, ptr = list; ptr != NULL; i++, ptr = ptr->next)
479         if (b_array[i])
480             *con_list = ref_addtostart(*con_list, (void *) ptr->to, ptr->type);
481 
482     ivector_free( t_array, 0);
483     ivector_free( b_array, 0);
484     pvector_free( s_array, 0);
485 
486     return (best_conic);
487 }
488 
489 static double str_tres;
490 
491 void   *conic_pos_thres(void *pos, int type, Conic * conic)
492 {
493     Vec2    p = {Vec2_id};
494     double  t;
495 
496     GET_POS2(pos, type, p);
497     t = conic_param(conic, p);
498     t = vec2_sqrdist(p, conic_point(conic, t));
499     if (t > str_tres)
500         return (NULL);
501     return (pos);
502 }
503 
504 Tstring *conic_threshold_string(Conic * conic, Tstring * string, double thres)
505 {
506     str_tres = thres;
507     return (reclist_string_copy(string, conic_pos_thres, (int) NULL, (void *) conic));
508 }
509 
510 Vec2    geom2_mid_point(void *geom, int type)
511 {
512     switch (type)
513     {
514         case POINT2:
515         return (((Point2 *) geom)->p);
516     case LINE2:
517         {
518             Vec2    p1 = {Vec2_id};
519             Vec2    p2 = {Vec2_id};
520 
521             p1 = ((Line2 *) geom)->p1;
522             p2 = ((Line2 *) geom)->p2;
523 
524             return (vec2_times(0.5, vec2_sum(p1, p2)));
525         }
526     case CONIC2:
527         {
528             double  t1 = ((Conic *) geom)->t1;
529             double  t2 = ((Conic *) geom)->t2;
530 
531             return (conic_point((Conic *) geom, (t1 + t2) * 0.5));
532         }
533     default:
534         return (vec2_zero());   /* could be MAXFLOAT */
535     }
536 }
537 
538 Vec2    geom2_p1(void *geom, int type)
539 {
540     switch (type)
541     {
542         case POINT2:
543         return (((Point2 *) geom)->p);
544     case LINE2:
545         return (((Line2 *) geom)->p1);
546     case CONIC2:
547         return (conic_point((Conic *) geom, ((Conic *) geom)->t1));
548     default:
549         return (vec2_zero());   /* could be MAXFLOAT */
550     }
551 }
552 
553 Vec2    geom2_p2(void *geom, int type)
554 {
555     switch (type)
556     {
557         case POINT2:
558         return (((Point2 *) geom)->p);
559     case LINE2:
560         return (((Line2 *) geom)->p2);
561     case CONIC2:
562         return (conic_point((Conic *) geom, ((Conic *) geom)->t2));
563     default:
564         return (vec2_zero());   /* could be MAXFLOAT */
565     }
566 }
567 
568 static void geom2_mid_add_to_index(void *geom, int type, Windex * index)
569 {
570     Ipos    pos = {Ipos_id};
571 
572     pos = wx_get_index(index, geom2_mid_point(geom, type));
573     wx_add_entry(index, geom, type, ipos_y(pos), ipos_x(pos));
574 }
575 
576 static void geom2_mid_rm_from_index(void *geom, int type, Windex * index)
577 {
578     Ipos    pos = {Ipos_id};
579 
580     pos = wx_get_index(index, geom2_mid_point(geom, type));
581     wx_rm_entry(index, geom, ipos_y(pos), ipos_x(pos));
582 }
583 
584 /* ARGSUSED quieten lint */
585 static void vec2_inc_region(Vec2 p, int type, Imregion * roi)
586 {
587     int     x, y;
588 
589     x = (int)floor(vec2_x(p));
590     y = (int)floor(vec2_y(p));
591 
592     if (roi->lx == LARGEST_INT)
593     {
594         roi->lx = roi->ux = x;
595         roi->ly = roi->uy = y;
596         return;
597     }
598     if (x < roi->lx)
599         roi->lx = x;
600     if (y < roi->ly)
601         roi->ly = y;
602     if (x > roi->ux)
603         roi->ux = x;
604     if (y > roi->uy)
605         roi->uy = y;
606 }
607 
608 
609 static void geom_inc_region(void *geom, int type, Imregion * roi)
610 {
611     vec2_inc_region(geom2_mid_point(geom, type), VEC2, roi);
612     vec2_inc_region(geom2_p1(geom, type), VEC2, roi);
613     vec2_inc_region(geom2_p2(geom, type), VEC2, roi);
614 }
615 
616 Windex *geom_mid_point_index_build(List * geom, Imregion * region)
617 {
618     Windex *index;
619     int     m, n;
620 
621     if (region == NULL)
622     {
623         region = roi_alloc(LARGEST_INT, LARGEST_INT, LARGEST_INT, LARGEST_INT);
624         reclist_list_apply(geom, geom_inc_region, (int) NULL, (void *) region);
625         region->lx -= 20;
626         region->ly -= 20;
627         region->ux += 20;
628         region->uy += 20;
629     }
630     m = (region->uy - region->ly) / 20 + 1;
631     n = (region->ux - region->lx) / 20 + 1;
632     index = wx_alloc(region, m, n, GEOMETRY_2);
633     reclist_list_apply(geom, geom2_mid_add_to_index, (int) NULL, (void *) index);
634     return (index);
635 }
636 
637 List   *geom_from_index(Conic * conic, Conic_stat * stats, Windex * index, char **mask, Ipos p, double conf)
638 {
639     int     i, ii, j, jj;
640     Vec2    v = {Vec2_id};
641     Vec2    v1 = {Vec2_id};
642     Vec2    v2 = {Vec2_id};
643     List   *list = NULL;
644     double  t;
645 
646     i = ipos_y(p);
647     j = ipos_x(p);
648 
649     if (wx_in_index(index, i, j) == false || mask[i][j])
650         return (NULL);
651 
652     mask[i][j] = 1;
653 
654     v = wx_get_mid_pos2(index, p);
655     t = conic_param(conic, v);
656     if (t < conic->t1)
657     {
658         if (t + TWOPI < conic->t2)
659             return (NULL);
660     } else if (t < conic->t2)
661         return (NULL);
662 
663     v1 = wx_get_pos2(index, p);
664     v2 = wx_get_pos2(index, ipos(j + 1, i + 1));
665 
666     if (conic_chi2(v, conic, stats) < conf &&
667         conic_chi2(v1, conic, stats) < conf &&
668         conic_chi2(v2, conic, stats) < conf &&
669         conic_chi2(wx_get_pos2(index, ipos(j, i + 1)), conic, stats) < conf &&
670         conic_chi2(wx_get_pos2(index, ipos(j + 1, i)), conic, stats) < conf)
671     {
672         v = conic_point(conic, t);      /* closest point on conic */
673 
674         /* does the conic NOT pass through this grid point */
675         if (!BETWEEN(vec2_x(v), vec2_x(v1), vec2_x(v2)) ||
676             !BETWEEN(vec2_y(v), vec2_y(v1), vec2_y(v2)))
677             return (NULL);
678     }
679     list = list_copy((List *) wx_get(index, i, j), (void *(*) ()) NULL, NULL);
680 
681     for (ii = -1; ii <= 1; ++ii)
682         for (jj = -1; jj <= 1; ++jj)
683             if (ii != 0 || jj != 0)
684             {
685                 List   *sub;
686 
687                 p = ipos(j + jj, i + ii);
688                 sub = geom_from_index(conic, stats, index, mask, p, conf);
689                 list = list_append(sub, list);
690             }
691     return (list);
692 }
693 
694 static Bool conic_below_thres(Conic * c, double ang_th, double len_th)
695 
696 /* angle threshold in radians */
697 /* angle threshold in radians */
698 {
699     if (c == NULL)
700         return (true);
701 
702     if (c->t2 - c->t1 > ang_th)
703         return (false);
704 
705     if (conic_approx_length(c, 10) > len_th)
706         return (false);
707 
708     return (true);
709 }
710 
711 List   *conic_join(List * geom, Imregion * roi, double conf, double lo_thres, double hi_thres, int max_div)
712 {
713     List   *newgeom;
714     List   *ptr1;
715     Windex *index;
716     char  **mask;
717     int     m, n;
718     int     i, j;
719 
720     if (geom == NULL)
721         return (NULL);
722 
723     /** flatten input list, then sort by approx length **/
724     newgeom = reclist_list_flat(geom, (void *(*) ()) NULL, (int) NULL, NULL);
725     newgeom = sort_list(newgeom, neglength, NULL);
726 
727     index = geom_mid_point_index_build(newgeom, roi);
728     m = index->m;
729     n = index->n;
730     mask = carray_alloc(0, 0, m, n);
731 
732     ptr1 = newgeom;
733     while (ptr1 != NULL)
734     {
735         Conic  *conic;
736         Conic  *new_conic;
737         Conic_stat *stats;
738         List   *ptr2;
739         List   *test_geom;
740         Tstring *str1, *str2;
741         Bool    changed = false;
742         Vec2    v = {Vec2_id};
743         Ipos    p = {Ipos_id};
744 
745         if (ptr1->type != CONIC2 || conic_below_thres((Conic *) ptr1->to, 0.5, 20.0))
746         {
747             ptr1 = ptr1->next;
748             continue;
749         }
750         conic = (Conic *) ptr1->to;
751 
752         stats = (Conic_stat *) prop_get(conic->props, STATS);
753         if (stats == NULL)
754         {
755             ptr1 = ptr1->next;
756             continue;
757         }
758         for (i = 0; i < m; ++i)
759             for (j = 0; j < n; ++j)
760                 mask[i][j] = 0;
761 
762         v = conic_point(conic, PI + (conic->t1 + conic->t2) * 0.5);
763         p = wx_get_index(index, v);
764         test_geom = geom_from_index(conic, stats, index, mask, p, conf);
765         v = conic_point(conic, conic->t1 - 0.1);
766         p = wx_get_index(index, v);
767         ptr2 = geom_from_index(conic, stats, index, mask, p, conf);
768         test_geom = list_append(ptr2, test_geom);
769         v = conic_point(conic, conic->t2 + 0.1);
770         p = wx_get_index(index, v);
771         ptr2 = geom_from_index(conic, stats, index, mask, p, conf);
772         test_geom = list_append(ptr2, test_geom);
773 
774         do
775         {
776             List   *compat = NULL;
777             List   *chosen = NULL;
778 
779             str1 = (Tstring *) prop_get(conic->props, STRING);
780 
781             /** find candidates for joining **/
782             for (ptr2 = test_geom; ptr2 != NULL; ptr2 = ptr2->next)
783             {
784                 if (ptr1->to == ptr2->to)       /* the same conic */
785                     continue;
786 
787                 if (conic_and_geom_compatible(conic, ptr2->to, ptr2->type, conf, 0.1))
788                 {
789                     str2 = (Tstring *) geom_prop_get(ptr2->to, ptr2->type, STRING);
790                     new_conic = conic_join_strings(str1, str2, lo_thres, hi_thres, max_div);
791                     if (new_conic == NULL)
792                         continue;
793 
794                     conic_free(new_conic);
795                     compat = ref_addtostart((List *) compat, (void *) ptr2->to, ptr2->type);
796                 }
797             }
798 
799             new_conic = best_from_list(conic, compat, &chosen, lo_thres, hi_thres, max_div);
800             list_rm_links(compat);
801 
802             if (new_conic != NULL)      /** new fit suceeded **/
803             {
804                 changed = true;
805                 for (ptr2 = chosen; ptr2 != NULL; ptr2 = ptr2->next)
806                 {
807                     test_geom = list_rm_ref(test_geom, ptr2->to, (void (*) ()) NULL);
808                     geom2_mid_rm_from_index(ptr2->to, ptr2->type, index);
809                     newgeom = list_rm_ref(newgeom, ptr2->to, (void (*) ()) geom_free);
810                 }
811                 list_rm_links(chosen);
812 
813                 str2 = (Tstring *) prop_get(new_conic->props, STRING);
814                 str2 = conic_threshold_string(new_conic, str2, lo_thres);
815                 (void) prop_set(new_conic->props, (void *) str2, STRING, true);
816 
817                 conic_free(conic);
818 
819                 geom2_mid_rm_from_index(ptr1->to, ptr1->type, index);
820                 ptr1->to = conic = new_conic;
821                 geom2_mid_add_to_index(ptr1->to, ptr1->type, index);
822             }
823         } while (new_conic != NULL);
824         list_rm_links(test_geom);
825         if (changed == false)
826             ptr1 = ptr1->next;
827     }
828     (void) reclist_list_free(geom, (void (*) ()) NULL, (int) NULL, NULL);
829     wx_free(index, list_rm_links);
830 
831     return (newgeom);
832 }
833 
834 List   *conic_compatible(Conic * conic, List * geom, double lo_thres, double hi_thres, int max_div)
835 {
836     Conic  *new_conic;
837     List   *ptr;
838     List   *candidates = NULL;
839     Tstring *str1, *str2;
840 
841     geom = reclist_list_flat(geom, (void *(*) ()) NULL, (int) NULL, NULL);
842     str1 = (Tstring *) prop_get(conic->props, STRING);
843 
844     /** find candidates for joining **/
845     for (ptr = geom; ptr != NULL; ptr = ptr->next)
846     {
847         if (conic == ptr->to)   /* the same conic */
848             continue;
849 
850         if (conic_and_geom_compatible(conic, ptr->to, ptr->type, 0.01, 0.1))
851         {
852             str2 = (Tstring *) geom_prop_get(ptr->to, ptr->type, STRING);
853             new_conic = conic_join_strings(str1, str2, lo_thres, hi_thres, max_div);
854             if (new_conic == NULL)
855                 continue;
856             conic_free(new_conic);
857             candidates = ref_addtostart((List *) candidates, (void *) ptr->to, ptr->type);
858         }
859     }
860     list_rm_links(geom);
861     return (candidates);
862 }
863 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.