source: trunk/MagicSoft/Simulation/Detector/Camera/moments.cxx@ 5987

Last change on this file since 5987 was 308, checked in by harald, 25 years ago
This the starting point for CVS controlled further developments of the camera program. The program was originally written by Jose Carlos. But here you can find a "rootified" version to the program. This means that there is no hbook stuff in it now. Also the output of the program changed to the MagicRawDataFormat. The "rootification" was done by Dirk Petry and Harald Kornmayer. In the following you can see the README file of that version: ================================================== Fri Oct 22 1999 D.P. The MAGIC Monte Carlo System Camera Simulation Programme --------------------------- 1) Description This version is the result of the fusion of H.K.'s root_camera which is described below (section 2) and another version by D.P. which had a few additional useful features. The version compiles under Linux with ROOT 2.22 installed (variable ROOTSYS has to be set). Compile as before simply using "make" in the root_camera directory. All features of H.K.'s root_camera were retained. Additional features of this version are: a) HBOOK is no longer used and all references are removed. b) Instead of HBOOK, the user is given now the possibility of having Diagnostic data in ROOT format as a complement to the ROOT Raw data. This data is written to the file which is determined by the new input parameter "diag_file" in the camera parameter file. All source code file belonging to this part have filenames starting with "MDiag". The user can read the output file using the following commands in an interactive ROOT session: root [0] .L MDiag.so root [1] new TFile("diag.root"); root [2] new TTreeViewer("T"); This brings up a viewer from which all variables of the TTree can be accessed and histogrammed. This example assumes that you have named the file "diag.root", that you are using ROOT version 2.22 or later and that you have the shared object library "MDiag.so" which is produced by the Makefile along with the executable "camera". ! The contents of the so-called diag file is not yet fixed. ! At the moment it is what J.C.G. used to put into the HBOOK ! ntuple. In future versions the moments calculation can be ! removed and the parameter list be modified correspondingly. c) Now concatenated reflector files can be read. This is useful if you have run the reflector with different parameters but you want to continue the analysis with all reflector data going into ONE ROOT outputfile. The previous camera version contained a bug which made reading of two or more concatenated reflector files impossible. d) The reflector output format was changed. It is now version 0.4 . The change solely consists in a shortening of the flag definition in the file include-MC/MCCphoton.hxx ! IF YOU WANT TO READ REFLECTOR FORMAT 0.3, you can easily ! do so by recompiling camera with the previous version of ! include-MC/MCCphoton.hxx. The change was necessary for saving space and better debugging. From now on, this format can be frozen. ! For producing reflector output in the new format, you ! of course have to recompile your reflector with the ! new include-MC/MCCphoton.hxx . e) A first version of the pixelization with the larger outer pixels is implemented. THIS IS NOT YET FULLY TESTED, but first rough tests show that it works at least to a good approximation. The present version implements the camera outline with 18 "gap-pixels" and 595 pixels in total as shown in http://sarastro.ifae.es/internal/home/hardware/camera/numbering.ps This change involved (i) The file pixels.dat is no longer needed. Instead the coordinates are generated by the program itself (takes maybe 1 second). In the file pixel-coords.txt in the same directory as this README, you find a list of the coordinates generated by this new routine. It has the format number i j x y size-factor where i and j are J.C.G.'s so called biaxis hexagonal coordinates (for internal use) and x and y are the coordinates of the pixel centers in the standard camera coordinate system in units of centimeters. The value of "size-factor" determines the linear size of the pixel relative to the central pixels. (ii) The magic.def file has two additional parameters which give the number of central pixels and the number of gap pixels (iii) In camera.h and camera.cxx several changes were necessary, among them the introduction of several new functions The newly suggested outline with asymmetric Winston cones will be implemented in a later version. f) phe files can no longer be read since this contradicts our philosophy that the analysis should be done with other programs like e.g. EVITA and not with "camera" itself. This possibility was removed. g) ROOT is no longer invoked with an interactive interface. In this way, camera can better be run as a batch program and it uses less memory. h) small changes concerning the variable "t_chan" were necessary in order to avoid segmentation faults: The variable is used as an index and it went sometimes outside the limits when camera was reading proton data. This is because the reflector files don't contain the photons in a chronological order and also the timespread can be considerably longer that the foreseen digitisation timespan. Please see the source code of camera.cxx round about line 1090. j) several unused variables were removed, a few warning messages occur when you compile camera.cxx but these can be ignored at the moment. In general the program is of course not finished. It still needs debugging, proper trigger simulation, simulation of the asymmetric version of the outer pixels, proper NSB simulation, adaption of the diag "ntuple" contents to our need and others small improvements. In the directory rfl-files there is now a file in reflector format 0.4 containing a single event produced by the starfiled adder. It has a duration of 30 ns and represents the region around the Crab Nebula. Using the enclosed input parameter file, camera should process this file without problems. 2) The README for the previous version of root_camera README for a preliminary version of the root_camera program. root_camera is based on the program "camera"of Jose Carlos Gonzalez. It was changed in the way that only the pixelisation and the distibution of the phe to the FADCs works in a first version. Using the #undef command most possibilities of the orignal program are switched of. The new parts are signed by - ROOT or __ROOT__ nearly all important codelines for ROOT output are enclosed in structures like #ifdef __ROOT__ code #endif __ROOT__ In same case the new lines are signed by a comment with the word ROOT in it. For timing of the pulse some variable names are changed. (t0, t1, t --> t_ini, t_fin, t_1st, t_chan,...) Look also for this changes. For the new root-file is also a change in readparm-files - __DETAIL_TRIGGER__ This is for the implementation of the current work on trigger studies. Because the class MTrigger is not well documented it isn´t a part of this tar file. Only a dummy File exists. With all files in the archive, the root_camera program should run. A reflector file is in the directory rfl-files ================================================== From now on, use CVS for development!!!!
File size: 18.4 KB
Line 
1//=//////////////////////////////////////////////////////////////////////
2//=
3//= moments
4//=
5//= @file moments.cxx
6//= @desc Calculation of image parameters
7//= @author J C Gonzalez
8//= @email gonzalez@mppmu.mpg.de
9//= @date Thu May 7 16:24:22 1998
10//=
11//=----------------------------------------------------------------------
12//=
13//= Created: Thu May 7 16:24:22 1998
14//= Author: Jose Carlos Gonzalez
15//= Purpose: Program for reflector simulation
16//= Notes: See files README for details
17//=
18//=----------------------------------------------------------------------
19//=
20//= $RCSfile: moments.cxx,v $
21//= $Revision: 1.1.1.1 $
22//= $Author: harald $
23//= $Date: 1999-11-05 11:59:33 $
24//=
25//=//////////////////////////////////////////////////////////////////////
26
27// @T \newpage
28
29//!@section Source code of |moments.cxx|.
30
31/*!@{
32
33 This section describes briefly the source code for the file
34 |moments.cxx|. All the defines it uses are located in the file
35 |moments.h|.
36
37 @"*/
38
39//!@subsection Includes and Global variables definition.
40
41/*!@"
42
43 All the defines are located in the file |moments.h|.
44
45 @"*/
46
47//!@{
48
49#include "moments.h"
50
51//!@}
52
53//!@subsection Definition of global variables.
54
55//!@{
56
57static int npix; //@< number of pixels
58static float *q; //@< charges in the pixels
59static float xm, ym; //@< centroid (used in moments and lenwid)
60
61//@: structure with information about the image
62static Moments_Info m;
63
64//@: structure with information about islands
65static Islands_Info is;
66
67//@: structure with information about lenwid
68static LenWid_Info lw;
69
70//!@}
71
72//!@subsection The function |moments()|.
73
74//!-----------------------------------------------------------
75// @name moments
76//
77// @desc calculate moments on the image
78//
79// @var n Number of pixels
80// @var *image Vector of ph.e.s in pixels
81// @var **pix Array with information about the pixels
82// @var plateScale Plate scale for the CT in use
83// @var flag 1: initialize; other: normal
84//
85// @return Pointer to structure Moments_Info
86//
87// @date Mon Sep 14 15:22:44 MET DST 1998
88//------------------------------------------------------------
89// @function
90
91//!@{
92Moments_Info *
93moments( int n, float *image, float **pix,
94 float plateScale, int flag )
95{
96 register int i, k;
97
98 float x, y;
99 float x2m, xym, y2m;
100 float x3m, x2ym, xy2m, y3m;
101 float zz, zd, zu, zv;
102 float ax, ay, unitx, unity, sigmaax;
103 float sx2, sxy, sy2;
104 float sx3, sx2y, sxy2, sy3;
105
106 if ( flag == 1 ) {
107 q = new float[n];
108 is.fi = new float[n];
109 is.vislands = new float[n];
110 is.islands = new int[n];
111 is.isl = new int[n];
112 for (i=1; i<n; ++i) {
113 q[i] = is.fi[i] = is.vislands[i] = 0.0;
114 is.islands[i] = is.isl[i] = 0;
115 }
116 return &m;
117 } else {
118 memcpy( q, image, sizeof(float) * n );
119 /*
120 for (i=1; i<n; ++i)
121 cout << q[i] << '\n';
122 cout << endl << flush;
123 */
124 }
125
126 // save number of pixels
127 npix = n;
128
129 // calculate sum of values
130 xm = ym = 0.0;
131 x2m = xym = y2m = 0.0;
132 x3m = x2ym = xy2m = y3m = 0.0;
133 m.charge = 0.0;
134
135 for (i=0; i<npix; ++i)
136 if ( q[i] > 0.0 ) {
137 x = pix[i][0];
138 y = pix[i][1];
139 xm += x * q[i];
140 ym += y * q[i];
141 x2m += x * x * q[i];
142 xym += x * y * q[i];
143 y2m += y * y * q[i];
144 x3m += x * x * x * q[i];
145 x2ym += x * x * y * q[i];
146 xy2m += x * y * y * q[i];
147 y3m += y * y * y * q[i];
148 m.charge += q[i];
149 }
150
151 xm *= plateScale;
152 ym *= plateScale;
153 x2m *= plateScale * plateScale;
154 xym *= plateScale * plateScale;
155 y2m *= plateScale * plateScale;
156 x3m *= plateScale * plateScale * plateScale;
157 x2ym *= plateScale * plateScale * plateScale;
158 xy2m *= plateScale * plateScale * plateScale;
159 y3m *= plateScale * plateScale * plateScale;
160
161 //++++++++++++++++++++++++++++++++++++++++++++++++++
162 // extremes and charges
163 //--------------------------------------------------
164
165 for (i=0; i<10; ++i)
166 m.maxs[i] = 0.0;
167
168 for (i=0; i<npix; ++i) {
169 if ( q[i] > m.maxs[0] ) {
170 for (k=9; k>0; --k)
171 m.maxs[k] = m.maxs[k-1];
172 for (k=9; k>0; --k)
173 m.nmaxs[k] = m.nmaxs[k-1];
174 m.maxs[0] = q[i];
175 m.nmaxs[0] = i;
176 }
177 }
178
179 // calculates weighted position of the maximum (6 pixels)
180
181 m.xmax = m.ymax = m.smax = 0.0;
182
183 for (i=0; i<6; ++i) {
184 m.xmax += pix[m.nmaxs[i]][0] * q[m.nmaxs[i]];
185 m.ymax += pix[m.nmaxs[i]][1] * q[m.nmaxs[i]];
186 m.smax += q[m.nmaxs[i]];
187 }
188
189 if (m.smax==0.) m.smax=1.;
190 if (m.charge==0.) m.charge=1.;
191
192 m.xmax = m.xmax * plateScale / m.smax;
193 m.ymax = m.ymax * plateScale / m.smax;
194
195 // calculate concentrations with 2,3,4...10 pixels
196
197 m.conc[0] = q[ m.nmaxs[0] ] + q[ m.nmaxs[1] ];
198
199 for (i=2; i<10; ++i)
200 m.conc[i-1] = m.conc[i-2] + q[ m.nmaxs[i] ];
201
202 for (i=0; i<9; ++i)
203 m.conc[i] /= m.charge;
204
205 //++++++++++++++++++++++++++++++++++++++++++++++++++
206 // 1st moments
207 //--------------------------------------------------
208
209 xm /= m.charge;
210 ym /= m.charge;
211
212 m.m1x = xm;
213 m.m1y = ym;
214
215 //++++++++++++++++++++++++++++++++++++++++++++++++++
216 // 2nd moments
217 //--------------------------------------------------
218
219 x2m /= m.charge;
220 xym /= m.charge;
221 y2m /= m.charge;
222
223 // around the origin
224 m.m2xx = x2m;
225 m.m2xy = xym;
226 m.m2yy = y2m;
227
228 // around the mean
229 sx2 = x2m - SQR(xm);
230 sxy = xym - xm * ym;
231 sy2 = y2m - SQR(ym);
232
233 m.m2cxx = sx2;
234 m.m2cxy = sxy;
235 m.m2cyy = sy2;
236
237 //++++++++++++++++++++++++++++++++++++++++++++++++++
238 // 3rd moments
239 //--------------------------------------------------
240
241 x3m /= m.charge;
242 x2ym /= m.charge;
243 xy2m /= m.charge;
244 y3m /= m.charge;
245
246 // around the origin
247 m.m3xxx = x3m;
248 m.m3xxy = x2ym;
249 m.m3xyy = xy2m;
250 m.m3yyy = y3m;
251
252 // around the mean
253 sx3 = x3m - 3 * x2m * xm + 2 * xm * xm * xm;
254 sx2y = x2ym - 2 * xym * xm + 2 * xm * xm * ym - x2m * ym;
255 sxy2 = xy2m - 2 * xym * ym + 2 * xm * ym * ym - y2m * xm;
256 sy3 = y3m - 3 * y2m * ym + 2 * ym * ym * ym;
257
258 m.m3cxxx = x3m;
259 m.m3cxxy = x2ym;
260 m.m3cxyy = xy2m;
261 m.m3cyyy = y3m;
262
263 //++++++++++++++++++++++++++++++++++++++++++++++++++
264 // hillas' parameters
265 //--------------------------------------------------
266
267 zd = sy2 - sx2;
268 zz = sqrt( SQR(zd) + 4.*SQR( sxy ));;
269 if ( (zz < 1.e-6) || (sxy == 0.) ) {
270 m.dist = -1.;
271 return &m;
272 }
273 zu = 1.0 + zd / zz;
274 zv = 2.0 - zu;
275
276 /*
277 a = (zd + zz) / (2 * sxy);
278 b = ym - a * xm;
279
280 m.length = sqrt( fabs( sx2 + 2 * a * sxy + a * a * sy2 ) / (1+a*a) );
281 m.width = sqrt( fabs( sx2 - 2 * a * sxy + a * a * sy2 ) / (1+a*a) );
282 m.dist = sqrt( SQR(xm) + SQR(ym) );
283 m.xdist = sqrt( SQR( m.xmax ) + SQR( m.ymax ) );
284 m.azw = sqrt( fabs( SQR(xm)* y2m - 2.* xm * ym * xym + x2m*SQR(ym) ) );
285 m.miss = fabs( b / sqrt(1+a*a) );
286 m.alpha = DEG( asin( m.miss / m.dist ) );
287 */
288
289 m.length = sqrt( fabs(sx2 + sy2 + zz) / 2. );
290 m.width = sqrt( fabs(sx2 + sy2 - zz) / 2. );
291 m.dist = sqrt( SQR(xm) + SQR(ym) );
292 m.xdist = sqrt( SQR(m.xmax) + SQR(m.ymax) );
293 m.azw = sqrt( fabs( SQR(xm)*y2m - 2.*xm*ym*xym + x2m*SQR(ym) ) ) / m.dist;
294 m.miss = sqrt( fabs( (SQR(xm)*zu + SQR(ym)*zv)/2. - (2.*sxy*xm*ym/zz) ) );
295 m.alpha = DEG( asin( m.miss/m.dist ) );
296
297
298 /*
299 length = sqrt( fabs(sx2 + sy2 + zz) /2. );
300 width = sqrt( fabs(sx2 + sy2 - zz) / 2. );
301 dist = sqrt( SQR(xm) + SQR(ym) );
302 xdist = sqrt( SQR(m.xmax) + SQR(m.ymax) );
303 azw = sqrt( fabs( SQR(xm)*y2m - 2.*xm*ym*xym + x2m*SQR(ym) ) );
304 miss = sqrt( fabs( (SQR(xm)*zu + SQR(ym)*zv)/2. - (2.*sxy*xm*ym/zz) ) );
305 alpha = DEG( asin(miss/dist) );
306 */
307
308 //++++++++++++++++++++++++++++++++++++++++++++++++++
309 // asymetry
310 //--------------------------------------------------
311
312 unitx = sqrt(0.5*zv);
313 unity = SGN( sxy )*sqrt(0.5*zu);
314
315 if ( m.xdist > 0.0 ) {
316
317 m.phi = acos((unitx*m.xmax + unity*m.ymax )/m.xdist);
318
319 sigmaax = sx3*CUB(cos(m.phi)) + 3.0*sx2y*SQR(cos(m.phi))*sin(m.phi) +
320 3.0*sxy2*cos(m.phi)*SQR(sin(m.phi)) + sy3*CUB(sin(m.phi));
321 sigmaax = pow(fabs(sigmaax),0.3333333)*SGN(sigmaax);
322
323 ax = sigmaax*unitx;
324 ay = sigmaax*unity;
325 m.asymx = (ax*m.xmax + ay*m.ymax)/(m.xdist*m.length*cos(m.phi));
326 m.asymy = 0.0;
327
328 } else {
329
330 m.phi=-1000.0;
331 m.asymx = -1000.0;
332 m.asymy = -1000.0;
333
334 }
335
336 /*
337 cout
338 << "length "<< length << endl
339 << "width "<< width << endl
340 << "dist "<< dist << endl
341 << "xdist "<< xdist << endl
342 << "azw "<< azw << endl
343 << "miss "<< miss << endl
344 << "alpha "<< alpha << endl << flush;
345 */
346
347 return &m;
348}
349//!@}
350
351// @T \newpage
352
353//!@subsection The function |islands()|.
354
355//!-----------------------------------------------------------
356// @name islands
357//
358// @desc implementation of the "islands" algorithm
359//
360// @var n Number of pixels
361// @var f Vector with the image (ph.e.s in pixels)
362// @var **pixneig Array with indices of neighbour pixels
363// @var *npixneig Vector with number of neighbours per pixel
364// @var cleanning TRUE: remove spurious islands
365// @var ipixcut Islands number cut
366//
367// @return Pointer to structure Islands_Info
368//
369// @date Mon Sep 14 15:22:44 MET DST 1998
370//------------------------------------------------------------
371// @function
372
373//!@{
374Islands_Info *
375islands( int n, float *f, int **pixneig, int *npixneig,
376 int cleanning, int ipixcut)
377{
378 register int i;
379 int j, k;
380 int haschanged;
381
382 is.numisl = 0;
383
384 memcpy( is.fi, f, sizeof(float) * n );
385
386 // be aware: here we use the side effect of ++
387 // there are two possibilities of using the operator ++:
388 // 1) a = ++i => is.first increments i, then evaluates expresion
389 // 2) a = i++ => is.first evaluates expresion, then increments i
390 // we INTENTIONALLY use the second form
391
392 // algorithm to isolate/detect is.islands
393 j=1;
394 for (i=0; i<n; ++i)
395 if ( is.fi[i]>0.0 ) {
396 is.isl[i] = j;
397 ++j;
398 } else {
399 is.isl[i] = 0;
400 }
401
402 haschanged = TRUE;
403 while ( haschanged ) {
404 haschanged = FALSE;
405 for (i=0; i<n; ++i)
406 if ( is.isl[i] > 0 )
407 for (j=0; (j<npixneig[i]) && (pixneig[i][j]>-1); ++j)
408 if ( (k=is.isl[pixneig[i][j]]) > 0 )
409 if ( is.isl[i] > is.isl[k] ) {
410 is.isl[i] = is.isl[k];
411 haschanged=TRUE;
412 }
413 }
414
415 // count is.islands
416
417 for (i=0;i<n;++i)
418 is.islands[i] = 0;
419
420 for (i=0;i<n;++i)
421 is.vislands[i] = 0.0;
422
423 for (i=0;i<n;++i)
424 if (is.isl[i]>0) {
425 is.islands[is.isl[i]]++;
426 is.vislands[is.isl[i]] += is.fi[i];
427 }
428
429 for (i=0,j=0,is.numisl=0; i<n; ++i) {
430
431 if (is.islands[i]>0) {
432 j++;
433 //cout << '#' << j << ':' << is.islands[i] << " q=" << is.vislands[i]
434 // << endl;
435
436 if (is.islands[i] > ipixcut)
437 is.numisl++;
438 }
439
440 }
441
442 cout << j << '[' << is.numisl << "] is.islands\n" << flush;
443
444 if ( cleanning ) {
445
446 // cleanning image: pixcut = 3 (any is.island with <= 3 pixels is removed
447 for (i=0;i<n;++i)
448 if (is.islands[is.isl[i]] <= ipixcut)
449 f[i] = 0.0;
450 }
451
452 return &is;
453}
454//!@}
455
456
457//!@subsection The function |lenwid()|.
458
459//!-----------------------------------------------------------
460// @name lenwid
461//
462// @desc calculation of extended length and width params.
463//
464// @var n Number of pixels
465// @var *image Vector of ph.e.s in pixels
466// @var **pix Array with information about the pixels
467// @var plateScale Plate scale for the CT in use
468// @var flag 1: initialize; other: normal
469//
470// @return Pointer to structure LenWid_Info
471//
472// @date Mon Sep 14 15:22:44 MET DST 1998
473//------------------------------------------------------------
474// @function
475
476//!@{
477LenWid_Info *
478lenwid( int n, float *image, float **pix,
479 float plateScale,
480 float max_distance)
481{
482 register int i, j, k;
483 float chi, phi;
484 float cp, sp;
485 float px1[2], px2[2], py1[2], py2[2];
486 float x1, x2, y1, y2;
487 int sign_of_semiplane;
488 float a, b, c;
489 float dist_to_axis;
490 float x, y;
491 float wsum[4];
492 float sum[4];
493 float weight;
494 float alpha;
495 float radius, radius2;
496
497 // calculate the radius of a circle with the same area of a pixel
498
499 radius2 = max_distance*max_distance*cos(DEG30)*3.0 / M_PI;
500 radius = sqrt(radius2);
501
502 /* @comment
503 We have now an image in the camera. In this image we have
504 defined two axes, Xe and Ye. Given the definition of alpha,
505 we define phi, which is the angle of the rotation that should
506 be applied to the original axis X and Y to get, together with
507 a translation to the point (xm, ym), the new axes Xe and Ye.
508 @endcomment */
509
510 chi = atan2(ym,xm);
511 phi = m.alpha + chi;
512
513 /* If the angle is phi, the rotation will be:
514 * / cos(phi) sin(phi)\
515 * R(phi) = | |
516 * \-sin(phi) cos(phi)/
517 */
518
519 cp=cos(phi);
520 sp=sin(phi);
521
522 /* The reference points for each axis will be px1,px2 and py1,py2
523 We obtain these points by rotation and translation of the
524 points [+-1000,0] and [0,+-1000] */
525
526 /* Note! The rotation has to be R(-phi) */
527
528 px1[0] = cp*1000 + xm;
529 px1[1] = sp*1000 + ym;
530
531 px2[0] = -cp*1000 + xm;
532 px2[1] = -sp*1000 + ym;
533
534 py1[0] = -sp*1000 + xm;
535 py1[1] = cp*1000 + ym;
536
537 py2[0] = sp*1000 + xm;
538 py2[1] = -cp*1000 + ym;
539
540 /* Now we have finally two points for each of the axes.
541 We can now do, for each axis, and for each semi-plane
542 it defines, the loop over the pixels */
543
544 // Note that the possible values for sign_of_semiplane in the
545 // next loops are precisely -1 and +1
546
547 for (i=0; i<4; ++i) {
548 wsum[i] = sum[i] = 0.;
549 }
550
551 // first with the X, then with the Y
552
553 for (k=1; k<=2; ++k) {
554
555 if ( k == 1) {
556 x1 = px1[0];
557 y1 = px1[1];
558 x2 = px2[0];
559 y2 = px2[1];
560 } else {
561 x1 = py1[0];
562 y1 = py1[1];
563 x2 = py2[0];
564 y2 = py2[1];
565 }
566
567 for ( sign_of_semiplane = -1;
568 sign_of_semiplane < 2;
569 sign_of_semiplane += 2 ) {
570
571 // loop on pixels
572 for ( i=0; i<n; ++i ) {
573
574 // let's calculate the distance between the point and the axis
575
576 x = pix[i][0];
577 y = pix[i][1];
578
579 a = (y2 - y1);
580 b = (x1 - x2);
581 c = (x1 * (y1-y2) + y1 * (x2 - x1));
582
583 dist_to_axis = (a*x + b*y + c) / sqrt(a*a+b*b);
584
585 // we have THREE cases:
586
587 // (A)
588
589 // if distance to the axis if larger than pixel diameter,
590 // AND
591 // the semiplane is the WRONG one -> forget that pixel
592
593 if ( (fabs(dist_to_axis) > max_distance) &&
594 (SGN(dist_to_axis) != sign_of_semiplane) )
595 continue;
596
597 // (B)
598
599 // if distance to the axis if larger than pixel diameter,
600 // AND
601 // the semiplane is the GOOD one -> add this pixel
602
603 if ( (fabs(dist_to_axis) > max_distance) &&
604 (SGN(dist_to_axis) == sign_of_semiplane) ) {
605
606 // here the sum
607
608 weight = image[i];
609 j = k+sign_of_semiplane;
610 wsum[j] += weight * dist_to_axis * dist_to_axis;
611 sum[j] += weight;
612
613 continue;
614 }
615
616 // (C)
617 // if we reach this point, that means that the center
618 // of our pixel is too close to the axis, and we have
619 // to feed it into the routine to check if the pixel
620 // crosses the axis
621
622 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
623 // simplified algorithm
624 // assume the pixels are circular, and takes
625 // the fraction of the surface lying on the semiplane
626 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
627
628 // alpha
629 alpha = 2*asin(sqrt(2*(radius-dist_to_axis)*radius -
630 radius2) / radius);
631
632 // here the sum
633 // the fraction is the fraction of the area inside the semiplane
634 weight = image[i] * ( (alpha * radius2 / 2.0) / (M_PI * radius2));
635 j = k+sign_of_semiplane;
636 wsum[j] += weight * dist_to_axis * dist_to_axis;
637 sum[j] += weight;
638
639 } // foreach pixel pixels
640
641 } // foreach semiplane
642
643 } // foreach axis
644
645 lw.length1 = (sum[0] > 0.) ? sqrt(wsum[0] / sum[0]) : -1;
646 lw.width1 = (sum[1] > 0.) ? sqrt(wsum[1] / sum[1]) : -1;
647 lw.length2 = (sum[2] > 0.) ? sqrt(wsum[2] / sum[2]) : -1;
648 lw.width2 = (sum[3] > 0.) ? sqrt(wsum[3] / sum[3]) : -1;
649
650 lw.length1 *= plateScale;
651 lw.width1 *= plateScale;
652 lw.length2 *= plateScale;
653 lw.width2 *= plateScale;
654
655 return &lw;
656}
657//!@}
658
659
660//!@subsection Auxiliary functions.
661
662//!-----------------------------------------------------------
663// @name crosspt
664//
665// @desc calculate cross point of segments AB and CD
666//
667// @var ax Coor. X of point A
668// @var ay Coor. Y of point A
669// @var bx Coor. X of point A
670// @var by Coor. Y of point A
671// @var cx Coor. X of point A
672// @var cy Coor. Y of point A
673// @var dx Coor. X of point A
674// @var dy Coor. Y of point A
675// @var *pcrossx Coor. X of cross point
676// @var *pcrossy Coor. Y of cross point
677//
678// @date Mon Mar 8 13:35:54 MET 1999
679//------------------------------------------------------------
680// @function
681
682//!@{
683void
684crosspt( float ax, float ay,
685 float bx, float by,
686 float cx, float cy,
687 float dx, float dy,
688 float * pcrossx, float * pcrossy)
689{
690 float w, r;
691
692 // the points A and B, and C and D define two segments (AB and CD)
693 // the coordinates of these points are
694 // A(ax,ay), B(bx,by), C(cx,cy), D(dx,dy)
695
696 w=(bx-ax)*(dy-cy)-(by-ay)*(dx-cx);
697 r=(ay-cy)*(dx-cx)-(ax-cx)*(dy-cy);
698
699 *pcrossx = ax + r*(bx-ax)/w;
700 *pcrossy = ay + r*(by-ay)/w;
701
702}
703//!@}
704
705//=------------------------------------------------------------
706//!@subsection Log of this file.
707
708//!@{
709//
710// $Log: not supported by cvs2svn $
711// Revision 1.2 1999/10/22 15:01:29 petry
712// version sent to H.K. and N.M. on Fri Oct 22 1999
713//
714// Revision 1.1.1.1 1999/10/21 16:35:10 petry
715// first synthesised version
716//
717// Revision 1.1 1999/03/08 10:04:06 gonzalez
718// *** empty log message ***
719//
720// Revision 1.4 1999/03/02 09:56:14 gonzalez
721// *** empty log message ***
722//
723// Revision 1.5 1999/03/15 14:59:10 gonzalez
724// camera-1_1
725//
726//!@}
727
728//=EOF
Note: See TracBrowser for help on using the repository browser.