Panda3D
pfmFile.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pfmFile.I
10  * @author drose
11  * @date 2010-12-23
12  */
13 
14 /**
15  *
16  */
17 INLINE bool PfmFile::
18 is_valid() const {
19  return _num_channels != 0 && (_x_size * _y_size * _num_channels <= (int)_table.size());
20 }
21 
22 /**
23  * The "scale" is reported in the pfm header and is probably meaningless.
24  */
25 INLINE PN_float32 PfmFile::
26 get_scale() const {
27  return _scale;
28 }
29 
30 /**
31  * The "scale" is reported in the pfm header and is probably meaningless.
32  */
33 INLINE void PfmFile::
34 set_scale(PN_float32 scale) {
35  _scale = scale;
36 }
37 
38 /**
39  * Returns true if there is a valid point at x, y. This always returns true
40  * unless a "no data" value has been set, in which case it returns false if
41  * the point at x, y is the "no data" value.
42  */
43 INLINE bool PfmFile::
44 has_point(int x, int y) const {
45  return _has_point(this, x, y);
46 }
47 
48 /**
49  * Returns the cth channel of the point value at the indicated point.
50  */
51 INLINE PN_float32 PfmFile::
52 get_channel(int x, int y, int c) const {
53  nassertr(x >= 0 && x < _x_size &&
54  y >= 0 && y < _y_size &&
55  c >= 0 && c < _num_channels, 0.0f);
56  return _table[(y * _x_size + x) * _num_channels + c];
57 }
58 
59 /**
60  * Replaces the cth channel of the point value at the indicated point.
61  */
62 INLINE void PfmFile::
63 set_channel(int x, int y, int c, PN_float32 value) {
64  nassertv(x >= 0 && x < _x_size &&
65  y >= 0 && y < _y_size &&
66  c >= 0 && c < _num_channels);
67  _table[(y * _x_size + x) * _num_channels + c] = value;
68 }
69 
70 /**
71  * Returns the 1-component point value at the indicated point.
72  */
73 INLINE PN_float32 PfmFile::
74 get_point1(int x, int y) const {
75  nassertr(x >= 0 && x < _x_size &&
76  y >= 0 && y < _y_size, 0.0);
77  return _table[(y * _x_size + x) * _num_channels];
78 }
79 
80 /**
81  * Replaces the 1-component point value at the indicated point.
82  */
83 INLINE void PfmFile::
84 set_point1(int x, int y, PN_float32 point) {
85  //nassertv(!cnan(point));
86  nassertv(x >= 0 && x < _x_size &&
87  y >= 0 && y < _y_size);
88  _table[(y * _x_size + x) * _num_channels] = point;
89 }
90 
91 /**
92  * Returns the 2-component point value at the indicated point. In a 1-channel
93  * image, the channel value is in the x component.
94  */
95 INLINE const LPoint2f &PfmFile::
96 get_point2(int x, int y) const {
97  nassertr(x >= 0 && x < _x_size &&
98  y >= 0 && y < _y_size, LPoint2f::zero());
99  return *(LPoint2f *)&_table[(y * _x_size + x) * _num_channels];
100 }
101 
102 /**
103  * Replaces the 2-component point value at the indicated point. In a
104  * 1-channel image, the channel value is in the x component.
105  */
106 INLINE void PfmFile::
107 set_point2(int x, int y, const LVecBase2f &point) {
108  //nassertv(!point.is_nan());
109  nassertv(x >= 0 && x < _x_size &&
110  y >= 0 && y < _y_size);
111  switch (_num_channels) {
112  case 1:
113  _table[(y * _x_size + x)] = point[0];
114  break;
115 
116  case 2:
117  *(LPoint2f *)&_table[(y * _x_size + x) * _num_channels] = point;
118  break;
119 
120  case 3:
121  (*(LPoint3f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], 0.0);
122  break;
123 
124  case 4:
125  (*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], 0.0, 0.0);
126  break;
127  }
128 }
129 
130 /**
131  * Replaces the 2-component point value at the indicated point. In a
132  * 1-channel image, the channel value is in the x component.
133  */
134 INLINE void PfmFile::
135 set_point2(int x, int y, const LVecBase2d &point) {
136  set_point2(x, y, LCAST(PN_float32, point));
137 }
138 
139 /**
140  * Returns a modifiable 2-component point value at the indicated point.
141  */
142 INLINE LPoint2f &PfmFile::
143 modify_point2(int x, int y) {
144 #ifndef NDEBUG
145  static LPoint2f dummy_value = LPoint2f::zero();
146  nassertr(x >= 0 && x < _x_size &&
147  y >= 0 && y < _y_size, dummy_value);
148 #endif
149 
150  return *(LPoint2f *)&_table[(y * _x_size + x) * _num_channels];
151 }
152 
153 /**
154  * Returns the 3-component point value at the indicated point. In a 1-channel
155  * image, the channel value is in the x component.
156  */
157 INLINE const LPoint3f &PfmFile::
158 get_point(int x, int y) const {
159  return get_point3(x, y);
160 }
161 
162 /**
163  * Replaces the 3-component point value at the indicated point. In a
164  * 1-channel image, the channel value is in the x component.
165  */
166 INLINE void PfmFile::
167 set_point(int x, int y, const LVecBase3f &point) {
168  set_point3(x, y, point);
169 }
170 
171 /**
172  * Replaces the 3-component point value at the indicated point. In a
173  * 1-channel image, the channel value is in the x component.
174  */
175 INLINE void PfmFile::
176 set_point(int x, int y, const LVecBase3d &point) {
177  set_point3(x, y, point);
178 }
179 
180 /**
181  * Returns a modifiable 3-component point value at the indicated point.
182  */
183 INLINE LPoint3f &PfmFile::
184 modify_point(int x, int y) {
185  return modify_point3(x, y);
186 }
187 
188 /**
189  * Returns the 3-component point value at the indicated point. In a 1-channel
190  * image, the channel value is in the x component.
191  */
192 INLINE const LPoint3f &PfmFile::
193 get_point3(int x, int y) const {
194  nassertr(x >= 0 && x < _x_size &&
195  y >= 0 && y < _y_size, LPoint3f::zero());
196  return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
197 }
198 
199 /**
200  * Replaces the 3-component point value at the indicated point. In a
201  * 1-channel image, the channel value is in the x component.
202  */
203 INLINE void PfmFile::
204 set_point3(int x, int y, const LVecBase3f &point) {
205  //nassertv(!point.is_nan());
206  nassertv(x >= 0 && x < _x_size &&
207  y >= 0 && y < _y_size);
208  switch (_num_channels) {
209  case 1:
210  _table[(y * _x_size + x)] = point[0];
211  break;
212 
213  case 2:
214  (*(LPoint2f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1]);
215  break;
216 
217  case 3:
218  *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels] = point;
219  break;
220 
221  case 4:
222  (*(LPoint4f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], 0.0f, 0.0f);
223  break;
224  }
225 }
226 
227 /**
228  * Replaces the 3-component point value at the indicated point. In a
229  * 1-channel image, the channel value is in the x component.
230  */
231 INLINE void PfmFile::
232 set_point3(int x, int y, const LVecBase3d &point) {
233  set_point3(x, y, LCAST(PN_float32, point));
234 }
235 
236 /**
237  * Returns a modifiable 3-component point value at the indicated point.
238  */
239 INLINE LPoint3f &PfmFile::
240 modify_point3(int x, int y) {
241 #ifndef NDEBUG
242  static LPoint3f dummy_value = LPoint3f::zero();
243  nassertr(x >= 0 && x < _x_size &&
244  y >= 0 && y < _y_size, dummy_value);
245 #endif
246 
247  return *(LPoint3f *)&_table[(y * _x_size + x) * _num_channels];
248 }
249 
250 /**
251  * Returns the 4-component point value at the indicated point. In a 1-channel
252  * image, the channel value is in the x component.
253  */
254 INLINE const LPoint4f &PfmFile::
255 get_point4(int x, int y) const {
256  nassertr(x >= 0 && x < _x_size &&
257  y >= 0 && y < _y_size, LPoint4f::zero());
258  return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
259 }
260 
261 /**
262  * Replaces the 4-component point value at the indicated point. In a
263  * 1-channel image, the channel value is in the x component.
264  */
265 INLINE void PfmFile::
266 set_point4(int x, int y, const LVecBase4f &point) {
267  //nassertv(!point.is_nan());
268  nassertv(x >= 0 && x < _x_size &&
269  y >= 0 && y < _y_size);
270  switch (_num_channels) {
271  case 1:
272  _table[(y * _x_size + x)] = point[0];
273  break;
274 
275  case 2:
276  (*(LPoint2f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1]);
277  break;
278 
279  case 3:
280  (*(LPoint3f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], point[2]);
281  break;
282 
283  case 4:
284  *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels] = point;
285  break;
286  }
287 }
288 
289 /**
290  * Replaces the 4-component point value at the indicated point. In a
291  * 1-channel image, the channel value is in the x component.
292  */
293 INLINE void PfmFile::
294 set_point4(int x, int y, const LVecBase4d &point) {
295  set_point4(x, y, LCAST(PN_float32, point));
296 }
297 
298 /**
299  * Returns a modifiable 4-component point value at the indicated point.
300  */
301 INLINE LPoint4f &PfmFile::
302 modify_point4(int x, int y) {
303 #ifndef NDEBUG
304  static LPoint4f dummy_value = LPoint4f::zero();
305  nassertr(x >= 0 && x < _x_size &&
306  y >= 0 && y < _y_size, dummy_value);
307 #endif
308 
309  return *(LPoint4f *)&_table[(y * _x_size + x) * _num_channels];
310 }
311 
312 /**
313  * Fills the table with all of the same value.
314  */
315 INLINE void PfmFile::
316 fill(PN_float32 value) {
317  fill(LPoint4f(value, 0.0f, 0.0f, 0.0f));
318 }
319 
320 /**
321  * Fills the table with all of the same value.
322  */
323 INLINE void PfmFile::
324 fill(const LPoint2f &value) {
325  fill(LPoint4f(value[0], value[1], 0.0f, 0.0f));
326 }
327 
328 /**
329  * Fills the table with all of the same value.
330  */
331 INLINE void PfmFile::
332 fill(const LPoint3f &value) {
333  fill(LPoint4f(value[0], value[1], value[2], 0.0f));
334 }
335 
336 /**
337  * Computes the minimum range of x and y across the PFM file that include all
338  * points. If there are no points with no_data_value in the grid--that is,
339  * all points are included--then this will return (0, get_x_size(), 0,
340  * get_y_size()).
341  */
342 INLINE bool PfmFile::
343 calc_autocrop(LVecBase4f &range) const {
344  int x_begin, x_end, y_begin, y_end;
345  bool result = calc_autocrop(x_begin, x_end, y_begin, y_end);
346  range.set(x_begin, x_end, y_begin, y_end);
347  return result;
348 }
349 
350 /**
351  * Computes the minimum range of x and y across the PFM file that include all
352  * points. If there are no points with no_data_value in the grid--that is,
353  * all points are included--then this will return (0, get_x_size(), 0,
354  * get_y_size()).
355  */
356 INLINE bool PfmFile::
357 calc_autocrop(LVecBase4d &range) const {
358  int x_begin, x_end, y_begin, y_end;
359  bool result = calc_autocrop(x_begin, x_end, y_begin, y_end);
360  range.set(x_begin, x_end, y_begin, y_end);
361  return result;
362 }
363 
364 /**
365  * Sets the zero_special flag. When this flag is true, values of (0, 0, 0) in
366  * the pfm file are treated as a special case, and are not processed.
367  *
368  * This is a special case of set_no_data_value().
369  */
370 INLINE void PfmFile::
371 set_zero_special(bool zero_special) {
372  if (zero_special) {
373  set_no_data_value(LPoint4f::zero());
374  } else {
376  }
377 }
378 
379 /**
380  * Sets the no_data_chan4 flag. When this flag is true, and the pfm file has
381  * 4 channels, then a negative value in the fourth channel indicates no data.
382  * When it is false, all points are valid.
383  *
384  * This is a special case of set_no_data_value().
385  */
386 INLINE void PfmFile::
387 set_no_data_chan4(bool chan4) {
388  if (chan4 && _num_channels == 4) {
389  _has_no_data_value = true;
390  _has_no_data_threshold = false;
391  _no_data_value.set(0.0, 0.0, 0.0, -1.0);
392  _has_point = has_point_chan4;
393  } else {
395  }
396 }
397 
398 /**
399  * Sets the special value that means "no data" when it appears in the pfm
400  * file.
401  */
402 INLINE void PfmFile::
403 set_no_data_value(const LPoint4d &no_data_value) {
404  set_no_data_value(LCAST(PN_float32, no_data_value));
405 }
406 
407 /**
408  * Sets the special threshold value. Points that are below this value in all
409  * components are considered "no value".
410  */
411 INLINE void PfmFile::
412 set_no_data_threshold(const LPoint4d &no_data_threshold) {
413  set_no_data_threshold(LCAST(PN_float32, no_data_threshold));
414 }
415 
416 /**
417  * Removes the special value that means "no data" when it appears in the pfm
418  * file. All points will thus be considered valid.
419  */
420 INLINE void PfmFile::
422  _has_no_data_value = false;
423  _has_no_data_threshold = false;
424  _no_data_value = LPoint4f::zero();
425  _has_point = has_point_noop;
426 }
427 
428 /**
429  * Returns whether a "no data" value has been established by
430  * set_no_data_value().
431  */
432 INLINE bool PfmFile::
434  return _has_no_data_value;
435 }
436 
437 /**
438  * Returns whether a "no data" threshold value has been established by
439  * set_no_data_threshold().
440  */
441 INLINE bool PfmFile::
443  return _has_no_data_threshold;
444 }
445 
446 /**
447  * If has_no_data_value() returns true, this returns the particular "no data"
448  * value.
449  */
450 INLINE const LPoint4f &PfmFile::
452  nassertr(_has_no_data_value, LPoint4f::zero());
453  return _no_data_value;
454 }
455 
456 /**
457  * Applies the indicated transform matrix to all points in-place.
458  */
459 INLINE void PfmFile::
460 xform(const LMatrix4d &transform) {
461  xform(LCAST(PN_float32, transform));
462 }
463 
464 /**
465  * Computes the minmax bounding volume of the points in 3-D space, assuming
466  * the points represent a mostly-planar surface.
467  *
468  * This algorithm works by sampling the (square) sample_radius pixels at the
469  * four point_dist corners around the center (cx - pd, cx + pd) and so on, to
470  * approximate the plane of the surface. Then all of the points are projected
471  * into that plane and the bounding volume of the entire mesh within that
472  * plane is determined. If points_only is true, the bounding volume of only
473  * those four points is determined.
474  *
475  * center, point_dist and sample_radius are in UV space, i.e. in the range
476  * 0..1.
477  */
478 INLINE PT(BoundingHexahedron) PfmFile::
479 compute_planar_bounds(const LPoint2d &center, PN_float32 point_dist, PN_float32 sample_radius, bool points_only) const {
480  return compute_planar_bounds(LCAST(PN_float32, center), point_dist, sample_radius, points_only);
481 }
482 
483 /**
484  * Assuming the image was constructed with a gamma curve of from_gamma in the
485  * RGB channels, converts it to an image with a gamma curve of to_gamma in the
486  * RGB channels. Does not affect the alpha channel.
487  */
488 INLINE void PfmFile::
489 gamma_correct(float from_gamma, float to_gamma) {
490  apply_exponent(from_gamma / to_gamma);
491 }
492 
493 /**
494  * Assuming the image was constructed with a gamma curve of from_gamma in the
495  * alpha channel, converts it to an image with a gamma curve of to_gamma in
496  * the alpha channel. Does not affect the RGB channels.
497  */
498 INLINE void PfmFile::
499 gamma_correct_alpha(float from_gamma, float to_gamma) {
500  apply_exponent(1.0, from_gamma / to_gamma);
501 }
502 
503 /**
504  * Adjusts each channel of the image by raising the corresponding component
505  * value to the indicated exponent, such that L' = L ^ exponent.
506  */
507 INLINE void PfmFile::
508 apply_exponent(float gray_exponent) {
509  apply_exponent(gray_exponent, gray_exponent, gray_exponent, 1.0);
510 }
511 
512 /**
513  * Adjusts each channel of the image by raising the corresponding component
514  * value to the indicated exponent, such that L' = L ^ exponent.
515  */
516 INLINE void PfmFile::
517 apply_exponent(float gray_exponent, float alpha_exponent) {
518  apply_exponent(gray_exponent, gray_exponent, gray_exponent, alpha_exponent);
519 }
520 
521 /**
522  * Adjusts each channel of the image by raising the corresponding component
523  * value to the indicated exponent, such that L' = L ^ exponent. For a
524  * grayscale image, the blue_exponent value is used for the grayscale value,
525  * and red_exponent and green_exponent are unused.
526  */
527 INLINE void PfmFile::
528 apply_exponent(float c0_exponent, float c1_exponent, float c2_exponent) {
529  apply_exponent(c0_exponent, c1_exponent, c2_exponent, 1.0);
530 }
531 
532 /**
533  * This is a very low-level function that returns a read-only reference to the
534  * internal table of floating-point numbers. Use this method at your own
535  * risk.
536  */
537 INLINE const vector_float &PfmFile::
538 get_table() const {
539  return _table;
540 }
541 
542 /**
543  * This is a very low-level function that completely exchanges the PfmFile's
544  * internal table of floating-point numbers with whatever you supply. The
545  * provided table must have an appropriate size. Use this method at your own
546  * risk.
547  */
548 void PfmFile::
549 swap_table(vector_float &table) {
550  _table.swap(table);
551 }
552 
553 /**
554  * Computes xmin, ymin, xmax, and ymax, based on the input parameters for
555  * copy_sub_image() and related methods.
556  */
557 INLINE void PfmFile::
558 setup_sub_image(const PfmFile &copy, int &xto, int &yto,
559  int &xfrom, int &yfrom, int &x_size, int &y_size,
560  int &xmin, int &ymin, int &xmax, int &ymax) {
561  if (x_size < 0) {
562  x_size = copy.get_x_size() - xfrom;
563  }
564  if (y_size < 0) {
565  y_size = copy.get_y_size() - yfrom;
566  }
567 
568  if (xfrom < 0) {
569  xto += -xfrom;
570  x_size -= -xfrom;
571  xfrom = 0;
572  }
573  if (yfrom < 0) {
574  yto += -yfrom;
575  y_size -= -yfrom;
576  yfrom = 0;
577  }
578 
579  if (xto < 0) {
580  xfrom += -xto;
581  x_size -= -xto;
582  xto = 0;
583  }
584  if (yto < 0) {
585  yfrom += -yto;
586  y_size -= -yto;
587  yto = 0;
588  }
589 
590  x_size = std::min(x_size, copy.get_x_size() - xfrom);
591  y_size = std::min(y_size, copy.get_y_size() - yfrom);
592 
593  xmin = xto;
594  ymin = yto;
595 
596  xmax = std::min(xmin + x_size, get_x_size());
597  ymax = std::min(ymin + y_size, get_y_size());
598 }
void apply_exponent(float gray_exponent)
Adjusts each channel of the image by raising the corresponding component value to the indicated expon...
Definition: pfmFile.I:508
bool has_point(int x, int y) const
Returns true if there is a valid point at x, y.
Definition: pfmFile.I:44
void set_point4(int x, int y, const LVecBase4f &point)
Replaces the 4-component point value at the indicated point.
Definition: pfmFile.I:266
const LPoint3f & get_point(int x, int y) const
Returns the 3-component point value at the indicated point.
Definition: pfmFile.I:158
void set_no_data_chan4(bool chan4)
Sets the no_data_chan4 flag.
Definition: pfmFile.I:387
void set_point2(int x, int y, const LVecBase2f &point)
Replaces the 2-component point value at the indicated point.
Definition: pfmFile.I:107
const LPoint4f & get_point4(int x, int y) const
Returns the 4-component point value at the indicated point.
Definition: pfmFile.I:255
void set_point3(int x, int y, const LVecBase3f &point)
Replaces the 3-component point value at the indicated point.
Definition: pfmFile.I:204
int get_y_size() const
Returns the number of pixels in the Y direction.
int get_x_size() const
Returns the number of pixels in the X direction.
const LPoint3f & get_point3(int x, int y) const
Returns the 3-component point value at the indicated point.
Definition: pfmFile.I:193
const LPoint2f & get_point2(int x, int y) const
Returns the 2-component point value at the indicated point.
Definition: pfmFile.I:96
void swap_table(vector_float &table)
This is a very low-level function that completely exchanges the PfmFile's internal table of floating-...
Definition: pfmFile.I:549
LPoint4f & modify_point4(int x, int y)
Returns a modifiable 4-component point value at the indicated point.
Definition: pfmFile.I:302
PN_float32 get_point1(int x, int y) const
Returns the 1-component point value at the indicated point.
Definition: pfmFile.I:74
void set_point1(int x, int y, PN_float32 point)
Replaces the 1-component point value at the indicated point.
Definition: pfmFile.I:84
LPoint3f & modify_point3(int x, int y)
Returns a modifiable 3-component point value at the indicated point.
Definition: pfmFile.I:240
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
Definition: pfmFile.h:31
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
Definition: pfmFile.I:52
const vector_float & get_table() const
This is a very low-level function that returns a read-only reference to the internal table of floatin...
Definition: pfmFile.I:538
bool has_no_data_value() const
Returns whether a "no data" value has been established by set_no_data_value().
Definition: pfmFile.I:433
void fill(PN_float32 value)
Fills the table with all of the same value.
Definition: pfmFile.I:316
void set_point(int x, int y, const LVecBase3f &point)
Replaces the 3-component point value at the indicated point.
Definition: pfmFile.I:167
void set_channel(int x, int y, int c, PN_float32 value)
Replaces the cth channel of the point value at the indicated point.
Definition: pfmFile.I:63
bool has_no_data_threshold() const
Returns whether a "no data" threshold value has been established by set_no_data_threshold().
Definition: pfmFile.I:442
PT(BoundingHexahedron) PfmFile
Computes the minmax bounding volume of the points in 3-D space, assuming the points represent a mostl...
Definition: pfmFile.I:478
void xform(const LMatrix4f &transform)
Applies the indicated transform matrix to all points in-place.
Definition: pfmFile.cxx:1222
LPoint3f & modify_point(int x, int y)
Returns a modifiable 3-component point value at the indicated point.
Definition: pfmFile.I:184
void set_zero_special(bool zero_special)
Sets the zero_special flag.
Definition: pfmFile.I:371
void clear_no_data_value()
Removes the special value that means "no data" when it appears in the pfm file.
Definition: pfmFile.I:421
void set_no_data_threshold(const LPoint4f &no_data_value)
Sets the special threshold value.
Definition: pfmFile.cxx:925
LPoint2f & modify_point2(int x, int y)
Returns a modifiable 2-component point value at the indicated point.
Definition: pfmFile.I:143
bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const
Computes the minimum range of x and y across the PFM file that include all points.
Definition: pfmFile.cxx:775
set_scale
The "scale" is reported in the pfm header and is probably meaningless.
Definition: pfmFile.h:57
void gamma_correct_alpha(float from_gamma, float to_gamma)
Assuming the image was constructed with a gamma curve of from_gamma in the alpha channel,...
Definition: pfmFile.I:499
This defines a bounding convex hexahedron.
const LPoint4f & get_no_data_value() const
If has_no_data_value() returns true, this returns the particular "no data" value.
Definition: pfmFile.I:451
void set_no_data_value(const LPoint4f &no_data_value)
Sets the special value that means "no data" when it appears in the pfm file.
Definition: pfmFile.cxx:895