1 /**********
2 *
3 * This file is part of the TINA Open Source Image Analysis Environment
4 * henceforth known as TINA
5 *
6 * TINA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation.
9 *
10 * TINA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with TINA; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 **********
20 *
21 * Program : TINA
22 * File : $Source: /home/tina/cvs/tina-libs/tina/geometry/geomCurve_circprox.c,v $
23 * Date : $Date: 2003/09/09 16:02:21 $
24 * Version : $Revision: 1.2 $
25 * CVS Id : $Id: geomCurve_circprox.c,v 1.2 2003/09/09 16:02:21 ipoole Exp $
26 *
27 * Author : Legacy TINA
28 *
29 * Notes :
30 *
31 * fitting a string of 2D pos data with circles the circles are
32 * represented using the conic data structure
33 *
34 *********
35 */
36
37 #include "geomCurve_circprox.h"
38
39 #if HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include <math.h>
44 #include <tina/sys/sysDef.h>
45 #include <tina/sys/sysPro.h>
46 #include <tina/math/mathDef.h>
47 #include <tina/math/mathPro.h>
48 #include <tina/geometry/geomDef.h>
49 #include <tina/geometry/geom_CurveDef.h>
50 #include <tina/geometry/geomLine_linearprox.h>
51 #include <tina/geometry/geomCurve_conicprox.h>
52 #include <tina/geometry/geomCurve_conic.h>
53 #include <tina/geometry/geomCurve_conic_5pt.h>
54
55
56 static int init_sample = 12; /* static data! */
57
58 /* grow the original circle "conic" along the implicit string between
59 * start and end from original p1 and p2 starting and
60 *
61 * ending points (these positions are updated) */
62 Conic *conic_circ_grow(Conic * conic, List * start, List * end, List ** p1, List ** p2, double lo_th, double hi_th, int max_div)
63 {
64 Bool updated;
65 List *m1 = *p1;
66 List *m2 = *p2;
67
68 do
69 {
70 Bool string_grown;
71
72 /** grow start and end along conic **/
73 string_grown = conic_grow_string(conic, start, end, &m1, &m2,
74 lo_th, hi_th, max_div);
75
76 if (string_grown) /** fit a new circ and see if still good **/
77 {
78 Conic *new_conic = ddstr_conic_circ_3pt(m1, m2);
79
80 if (new_conic != NULL &&
81 conic_check(new_conic, m1, m2, lo_th, hi_th, max_div))
82 {
83 updated = true;
84 conic_free(conic);
85 conic = new_conic;
86 } else
87 {
88 updated = false;
89 if (new_conic != NULL)
90 conic_free(new_conic);
91 }
92 } else
93 updated = false;
94 } while (updated);
95
96 *p1 = m1;
97 *p2 = m2;
98
99 return (conic);
100 }
101
102 /* perform a recursive approximation between start and end use the
103 * conic version of a circle as primitive failing to fit a circle use
104 * straight line approximation */
105 static List *conic_circ_prox(List * start, List * end, int sample, double lo_th, double hi_th, int max_div)
106 {
107 List *p1;
108 List *p2;
109 List *m1;
110 List *m2;
111 List *list1 = NULL;
112 List *list2 = NULL;
113 Conic *conic = NULL;
114 double lo_sqth = lo_th * lo_th;
115 double hi_sqth = hi_th * hi_th;
116 int i, maxcount = 0;
117
118 if (start == NULL || end == NULL || start == end)
119 return (NULL);
120
121 p1 = start;
122 p2 = ddstr_nth_point(start, end, 2 * sample + 1);
123 if (p2 == NULL)
124 p2 = end;
125
126 while (1)
127 {
128 conic = ddstr_conic_circ_3pt(p1, p2);
129 if (conic != NULL &&
130 conic_check(conic, p1, p2, lo_sqth, hi_sqth, max_div))
131 {
132 int count = conic_count(conic, start, end, sample / 2, lo_sqth);
133
134 if (count > maxcount)
135 {
136 maxcount = count;
137 m1 = p1;
138 m2 = p2;
139 }
140 }
141 conic_free(conic);
142 conic = NULL;
143
144 if (p2 == end)
145 break;
146
147 for (i = 0; i < sample; ++i)
148 {
149 p1 = p1->next;
150 p2 = p2->next;
151 if (p2 == end)
152 break;
153 }
154 }
155
156 if (maxcount >= 5)
157 {
158 conic = ddstr_conic_circ_3pt(m1, m2);
159 conic = conic_circ_grow(conic, start, end, &m1, &m2,
160 lo_sqth, hi_sqth, max_div);
161 }
162 if (conic == NULL) /* failed */
163 {
164 sample = (int)(sample*0.75); /* increase sample frequency */
165 if (sample > 1)
166 return (conic_circ_prox(start, end, sample, lo_th, hi_th, max_div));
167 return (linear_prox(start, end, (float)lo_th, init_sample));
168 }
169 if (m1 != start)
170 list1 = conic_circ_prox(start, m1, sample, lo_th, hi_th, max_div);
171 if (m2 != end)
172 list2 = conic_circ_prox(m2, end, sample, lo_th, hi_th, max_div);
173
174 return (dd_append(list1, dd_append(dd_link_alloc((void *) conic, CONIC2), list2)));
175 }
176
177 /* approximate given string by circular sections represented as conics
178 * straight lines are used for sections that can not be fit as a circle
179 * return a new string of conics and straight line sections */
180 Tstring *conic_circ_string(Tstring * string, int init_smpl, double lo_th, double hi_th, int max_div)
181 {
182 List *conic_list;
183
184 if (string == NULL)
185 return (NULL);
186
187 init_sample = init_smpl;
188
189 conic_list = conic_circ_prox(string->start, string->end, init_sample,
190 lo_th, hi_th, max_div);
191
192 if (conic_list == NULL)
193 return (NULL);
194
195 return (str_make(STRING, conic_list, dd_get_end(conic_list)));
196 }
197
198 List *conic_circ_strings(List * strings, int init_smpl, double lo_th, double hi_th, int max_div)
199 {
200 List *sptr;
201 List *splist = NULL;
202
203 for (sptr = strings; sptr != NULL; sptr = sptr->next)
204 {
205 Tstring *string = (Tstring *) sptr->to;
206
207 string = conic_circ_string(string, init_smpl, lo_th, hi_th, max_div);
208 splist = ref_addtostart(splist, (void *) string, STRING);
209 }
210 return (splist);
211 }
212
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.