FORS Pipeline Reference Manual  4.12.5
fors_pattern.c
1 /* $Id: fors_pattern.c,v 1.4 2010-09-14 07:49:30 cizzo Exp $
2  *
3  * This file is part of the FORS Library
4  * Copyright (C) 2002-2010 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author: cizzo $
23  * $Date: 2010-09-14 07:49:30 $
24  * $Revision: 1.4 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <fors_pattern.h>
33 
34 #include <fors_double.h>
35 #include <fors_utils.h>
36 
37 #include <cpl.h>
38 
39 #include <math.h>
40 
42 {
43  double ratsq; /* (rmin/Rmax)^2 */
44  double dratsq; /* error */
45 
46  double theta; /* angle min - angle max in [0; 2pi[ */
47  double dtheta; /* error */
48  const fors_point *ref, *min, *max;
49  /* Reference, nearest, farest points used to build this pattern */
50 };
51 
52 #undef cleanup
53 #define cleanup
54 
69 fors_pattern *fors_pattern_new(const fors_point *ref,
70  const fors_point *p1,
71  const fors_point *p2,
72  double sigma)
73 {
74  fors_pattern *p = cpl_malloc(sizeof(*p));
75 
76  assure( ref != NULL, return p, NULL );
77  assure( p1 != NULL, return p, NULL );
78  assure( p2 != NULL, return p, NULL );
79  assure( sigma >= 0, return p, NULL );
80 
81  p->ref = ref;
82  {
83  double r1 = fors_point_distsq(ref, p1);
84  double r2 = fors_point_distsq(ref, p2);
85  double dr1 = sqrt(8*sigma*sigma*r1);
86  double dr2 = sqrt(8*sigma*sigma*r2);
87 
88  double dt1, dt2;
89  double t1 = double_atan2(ref->y - p1->y, sqrt(2)*sigma,
90  ref->x - p1->x, sqrt(2)*sigma,
91  &dt1);
92 
93  double t2 = double_atan2(ref->y - p2->y, sqrt(2)*sigma,
94  ref->x - p2->x, sqrt(2)*sigma,
95  &dt2);
96 
97  if (r1 < r2) {
98  p->ratsq = double_divide(r1, dr1,
99  r2, dr2,
100  &p->dratsq);
101 
102  p->theta = double_subtract(t1, dt1,
103  t2, dt2,
104  &p->dtheta);
105  p->min = p1;
106  p->max = p2;
107  }
108  else {
109  p->ratsq = double_divide(r2, dr2,
110  r1, dr1,
111  &p->dratsq);
112  p->theta = double_subtract(t2, dt2,
113  t1, dt1,
114  &p->dtheta);
115  p->min = p2;
116  p->max = p1;
117  }
118 
119  while (p->theta < 0 ) p->theta += 2*M_PI; /* Error does not change */
120  while (p->theta >= 2*M_PI) p->theta -= 2*M_PI;
121  }
122 
123  return p;
124 }
125 
126 #undef cleanup
127 #define cleanup
128 
137 fors_pattern_list *
138 fors_pattern_new_from_points(fors_point_list *points,
139  double tolerance,
140  double sigma)
141 {
142  fors_pattern_list *patterns = fors_pattern_list_new();
143  double tol_sq = tolerance * tolerance;
144  fors_point *ref, *p1, *p2;
145 
146  assure( points != NULL, return NULL, NULL );
147 
148  for (ref = fors_point_list_first(points);
149  ref != NULL;
150  ref = fors_point_list_next(points)) {
151 
152  for (fors_point_list_first_pair(points, &p1, &p2);
153  p1 != NULL;
154  fors_point_list_next_pair(points, &p1, &p2)) {
155 
156  if (fors_point_distsq(ref, p1) > tol_sq &&
157  fors_point_distsq(ref, p2) > tol_sq &&
158  fors_point_distsq(p1 , p2) > tol_sq) {
159 
160  fors_pattern_list_insert(patterns,
161  fors_pattern_new(
162  ref, p1, p2, sigma));
163  }
164  }
165  }
166 
167  cpl_msg_debug(cpl_func,
168  "Created %d pattern(s)", fors_pattern_list_size(patterns));
169 
170  return patterns;
171 }
172 
173 #undef cleanup
174 #define cleanup
175 
180 #if 0 /* check before enabling! */
181 static fors_pattern *
182 fors_pattern_duplicate(const fors_pattern *p)
183 {
184  fors_pattern *d = NULL;
185 
186  assure( p != NULL, return NULL, NULL );
187 
188  d = cpl_malloc(sizeof(*d));
189 
190  d->ratsq = p->ratsq;
191  d->theta = p->theta;
192 
193  return d;
194 }
195 #endif
196 
201 void fors_pattern_delete(fors_pattern **p)
202 {
203  if (p && *p) {
204  cpl_free(*p); *p = NULL;
205  }
206  return;
207 }
208 
214 const fors_point *
215 fors_pattern_get_ref(const fors_pattern *p)
216 {
217  assure( p != NULL, return NULL, NULL );
218 
219  return p->ref;
220 }
221 
230 void fors_pattern_error(const fors_pattern *p,
231  double *dr2,
232  double *dtheta)
233 {
234  assure( p != NULL, return, NULL );
235  assure( dr2 != NULL, return, NULL );
236  assure( dtheta != NULL, return, NULL );
237 
238  *dr2 = p->dratsq;
239  *dtheta = p->dtheta / (2*M_PI);
240 
241  return;
242 }
243 
244 
253 double fors_pattern_distsq(const fors_pattern *p,
254  const fors_pattern *q)
255 {
256  assure( p != NULL, return -1, NULL );
257  assure( q != NULL, return -1, NULL );
258 
259  double dtheta = fors_angle_diff(&p->theta, &q->theta); /* in [0;pi] */
260 
261  /* Return distance in normalized parameter space [0;1[ x [0;1[.
262  This is to give equal weight to differences in radii
263  and differences in theta.
264  */
265  return
266  (p->ratsq - q->ratsq) * (p->ratsq - q->ratsq) / (1.0 * 1.0) +
267  (dtheta * dtheta) / (M_PI*M_PI);
268 }
269 
276 double fors_pattern_dist_per_error(const fors_pattern *p,
277  const fors_pattern *q)
278 {
279  double dtheta = fors_angle_diff(&p->theta, &q->theta);
280 
281  double p_error_r;
282  double p_error_t;
283 
284  fors_pattern_error(p,
285  &p_error_r,
286  &p_error_t);
287 
288  double q_error_r;
289  double q_error_t;
290 
291  fors_pattern_error(q,
292  &q_error_r,
293  &q_error_t);
294 
295  /* variance of difference */
296  double rr = p_error_r*p_error_r + q_error_r*q_error_r;
297  double tt = p_error_t*p_error_t + q_error_t*q_error_t;
298 
299  return sqrt(
300  (p->ratsq - q->ratsq) * (p->ratsq - q->ratsq) / ((1.0*1.0) * rr) +
301  (dtheta * dtheta) / ((M_PI*M_PI) * tt)
302  );
303 }
304 
305 
306 
307 
312 void fors_pattern_print(const fors_pattern *p)
313 {
314  if (p == NULL) {
315  cpl_msg_info(cpl_func, "NULL pattern");
316  }
317  else {
318  cpl_msg_info(cpl_func, "Rmin^2/Rmax^2 = %f ; theta = %f",
319  p->ratsq, p->theta);
320  }
321  return;
322 }
323 
331 double fors_pattern_get_scale(const fors_pattern *p,
332  const fors_pattern *q)
333 {
334  assure( p != NULL, return 0, NULL );
335  assure( q != NULL, return 0, NULL );
336 
337  double s1 = sqrt(fors_point_distsq(p->ref, p->max));
338  double s2 = sqrt(fors_point_distsq(q->ref, q->max));
339 
340  return (s2 == 0) ? 0 : s1/s2;
341 }
342 
350 double fors_pattern_get_angle(const fors_pattern *p,
351  const fors_pattern *q)
352 {
353  assure( p != NULL, return -1, NULL );
354  assure( q != NULL, return -1, NULL );
355 
356  double t1 = atan2(p->ref->y - p->max->y,
357  p->ref->x - p->max->x);
358  double t2 = atan2(q->ref->y - q->max->y,
359  q->ref->x - q->max->x);
360 
361  double t = t1 - t2;
362 
363  while (t >= 2*M_PI) t -= 2*M_PI;
364  while (t < 0 ) t += 2*M_PI;
365 
366  return t;
367 }
368 
369 
370 #define LIST_DEFINE
371 #undef LIST_ELEM
372 #define LIST_ELEM fors_pattern
373 #include <list.h>
374 
double fors_angle_diff(const double *a1, const double *a2)
Difference between angles.
Definition: fors_utils.c:636
#define assure(EXPR)
Definition: list.c:101
double fors_point_distsq(const fors_point *p, const fors_point *q)
Metric.
Definition: fors_point.c:103