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