Seg3D  2.4
Seg3D is a free volume segmentation and processing tool developed by the NIH Center for Integrative Biomedical Computing at the University of Utah Scientific Computing and Imaging (SCI) Institute.
the_utils.hxx
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2016 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27  */
28 
29 // File : the_utils.hxx
30 // Author : Pavel A. Koshevoy
31 // Created : 2006/04/15 11:25:00
32 // Copyright : (C) 2004-2008 University of Utah
33 // Description : utility functions for working with arrays,
34 // lists, numbers, angles, etc...
35 
36 #ifndef THE_UTILS_HXX_
37 #define THE_UTILS_HXX_
38 
39 // system includes:
40 #ifndef _USE_MATH_DEFINES
41 #define _USE_MATH_DEFINES
42 #endif
43 
44 #ifndef NOMINMAX
45 #define NOMINMAX
46 #endif
47 
48 #include <list>
49 #include <stack>
50 #include <vector>
51 #include <algorithm>
52 #include <stdlib.h>
53 #include <math.h>
54 #include <assert.h>
55 #include <fstream>
56 #include <stdio.h>
57 
58 #include <Core/ITKCommon/the_dynamic_array.hxx>
59 
60 
61 //----------------------------------------------------------------
62 // array2d
63 //
64 #define array2d( T ) std::vector<std::vector<T> >
65 
66 //----------------------------------------------------------------
67 // array3d
68 //
69 #define array3d( T ) std::vector<std::vector<std::vector<T> > >
70 
71 //----------------------------------------------------------------
72 // TWO_PI
73 //
74 static const double TWO_PI = 2.0 * M_PI;
75 
76 
77 //----------------------------------------------------------------
78 // clamp_angle
79 //
80 inline double
81 clamp_angle(const double & absolute_angle)
82 {
83  double a = fmod(absolute_angle + TWO_PI, TWO_PI);
84  assert(a >= 0.0 && a < TWO_PI);
85  return a;
86 }
87 
88 //----------------------------------------------------------------
89 // calc_angle
90 //
91 inline double
92 calc_angle(const double & x,
93  const double & y,
94  const double & reference_angle = 0.0)
95 {
96  return clamp_angle(fmod(atan2(y, x) + TWO_PI, TWO_PI) -
97  fmod(reference_angle, TWO_PI));
98 }
99 
100 //----------------------------------------------------------------
101 // sleep_msec
102 //
103 extern void sleep_msec(size_t msec);
104 
105 //----------------------------------------------------------------
106 // drand
107 //
108 inline static double drand()
109 { return double(rand()) / double(RAND_MAX); }
110 
111 //----------------------------------------------------------------
112 // integer_power
113 //
114 template <typename scalar_t>
115 inline scalar_t
116 integer_power(scalar_t x, size_t p)
117 {
118  scalar_t result = scalar_t(1);
119  while (p != 0u)
120  {
121  if (p & 1) result *= x;
122  x *= x;
123  p >>= 1;
124  }
125 
126  return result;
127 }
128 
129 //----------------------------------------------------------------
130 // closest_power_of_two_larger_than_given
131 //
132 template <typename scalar_t>
133 inline scalar_t
134 closest_power_of_two_larger_than_given(const scalar_t & given)
135 {
136  size_t n = sizeof(given) * 8;
137  scalar_t closest = scalar_t(1);
138  for (size_t i = 0;
139  (i < n) && (closest < given);
140  i++, closest *= scalar_t(2)) {}
141 
142  return closest;
143 }
144 
145 
146 //----------------------------------------------------------------
147 // divide
148 //
149 template <typename data_t>
150 data_t
151 divide(const data_t & numerator, const data_t & denominator)
152 {
153  static data_t zero = data_t(0);
154  return (denominator != zero) ? (numerator / denominator) : zero;
155 }
156 
157 //----------------------------------------------------------------
158 // clear_stack
159 //
160 template <typename data_t>
161 void
162 clear_stack(std::stack<data_t> & s)
163 {
164  while (!s.empty())
165  {
166  s.pop();
167  }
168 }
169 
170 //----------------------------------------------------------------
171 // resize
172 //
173 template <class data_t>
174 void
175 resize(array2d(data_t) & array,
176  const size_t & rows,
177  const size_t & cols)
178 {
179  array.resize(rows);
180  for (size_t j = 0; j < rows; j++)
181  {
182  array[j].resize(cols);
183  }
184 }
185 
186 //----------------------------------------------------------------
187 // assign
188 //
189 template <class data_t>
190 void
191 assign(array2d(data_t) & array,
192  const size_t & rows,
193  const size_t & cols,
194  const data_t & value)
195 {
196  array.resize(rows);
197  for (size_t j = 0; j < rows; j++)
198  {
199  array[j].assign(cols, value);
200  }
201 }
202 
203 //----------------------------------------------------------------
204 // resize
205 //
206 template <class data_t>
207 void
208 resize(array3d(data_t) & array,
209  const size_t & slices,
210  const size_t & rows,
211  const size_t & cols)
212 {
213  array.resize(slices);
214  for (size_t i = 0; i < slices; i++)
215  {
216  array[i].resize(rows);
217  for (size_t j = 0; j < rows; j++)
218  {
219  array[i][j].resize(cols);
220  }
221  }
222 }
223 
224 
225 //----------------------------------------------------------------
226 // push_back_unique
227 //
228 template <class container_t, typename data_t>
229 void
230 push_back_unique(container_t & container,
231  const data_t & data)
232 {
233  typename container_t::const_iterator where =
234  std::find(container.begin(), container.end(), data);
235  if (where != container.end()) return;
236 
237  container.push_back(data);
238 }
239 
240 //----------------------------------------------------------------
241 // push_front_unique
242 //
243 template <class container_t, typename data_t>
244 void
245 push_front_unique(container_t & container,
246  const data_t & data)
247 {
248  typename container_t::const_iterator where =
249  std::find(container.begin(), container.end(), data);
250  if (where != container.end()) return;
251 
252  container.push_front(data);
253 }
254 
255 //----------------------------------------------------------------
256 // remove_head
257 //
258 template <typename data_t>
259 data_t
260 remove_head(std::list<data_t> & container)
261 {
262  data_t head = container.front();
263  container.pop_front();
264  return head;
265 }
266 
267 //----------------------------------------------------------------
268 // remove_tail
269 //
270 template <typename data_t>
271 data_t
272 remove_tail(std::list<data_t> & container)
273 {
274  data_t tail = container.back();
275  container.pop_back();
276  return tail;
277 }
278 
279 //----------------------------------------------------------------
280 // remove_head
281 //
282 template <typename data_t>
283 data_t
284 remove_head(std::vector<data_t> & container)
285 {
286  data_t head = container.front();
287  container.erase(container.begin());
288  return head;
289 }
290 
291 //----------------------------------------------------------------
292 // remove_tail
293 //
294 template <typename data_t>
295 data_t
296 remove_tail(std::vector<data_t> & container)
297 {
298  data_t tail = container.back();
299  container.pop_back();
300  return tail;
301 }
302 
303 //----------------------------------------------------------------
304 // is_size_two_or_larger
305 //
306 template <typename container_t>
307 inline bool
308 is_size_two_or_larger(const container_t & c)
309 {
310  typename container_t::const_iterator i = c.begin();
311  typename container_t::const_iterator e = c.end();
312  return (i != e) && (++i != e);
313 }
314 
315 //----------------------------------------------------------------
316 // is_size_three_or_larger
317 //
318 template <typename container_t>
319 inline bool
320 is_size_three_or_larger(const container_t & c)
321 {
322  typename container_t::const_iterator i = c.begin();
323  typename container_t::const_iterator e = c.end();
324  return (i != e) && (++i != e) && (++i != e);
325 }
326 
327 //----------------------------------------------------------------
328 // is_size_one
329 //
330 template <typename container_t>
331 inline bool
332 is_size_one(const container_t & c)
333 {
334  typename container_t::const_iterator i = c.begin();
335  typename container_t::const_iterator e = c.end();
336  return (i != e) && (++i == e);
337 }
338 
339 
340 //----------------------------------------------------------------
341 // replace
342 //
343 template <class container_t, typename data_t>
344 bool
345 replace(container_t & container, const data_t & a, const data_t & b)
346 {
347  typename container_t::iterator end = container.end();
348  typename container_t::iterator i = std::find(container.begin(), end, a);
349  if (i == end) return false;
350 
351  *i = b;
352  return true;
353 }
354 
355 
356 //----------------------------------------------------------------
357 // iterator_at_index
358 //
359 template <typename data_t>
360 typename std::list<data_t>::const_iterator
361 iterator_at_index(const std::list<data_t> & container,
362  const size_t & index)
363 {
364  typename std::list<data_t>::const_iterator iter = container.begin();
365  for (size_t i = 0; i < index && iter != container.end(); i++, ++iter) ;
366  return iter;
367 }
368 
369 //----------------------------------------------------------------
370 // iterator_at_index
371 //
372 template <typename data_t>
373 typename std::list<data_t>::iterator
374 iterator_at_index(std::list<data_t> & container,
375  const size_t & index)
376 {
377  typename std::list<data_t>::iterator iter = container.begin();
378  for (size_t i = 0; i < index && iter != container.end(); i++, ++iter) ;
379  return iter;
380 }
381 
382 //----------------------------------------------------------------
383 // index_of
384 //
385 template <typename data_t>
386 size_t
387 index_of(const std::list<data_t> & container, const data_t & data)
388 {
389  typename std::list<data_t>::const_iterator iter = container.begin();
390  for (size_t i = 0; iter != container.end(); i++, ++iter)
391  {
392  if (data == *iter) return i;
393  }
394 
395  return ~0;
396 }
397 
398 //----------------------------------------------------------------
399 // has
400 //
401 template <typename data_t>
402 bool
403 has(const std::list<data_t> & container, const data_t & data)
404 {
405  typename std::list<data_t>::const_iterator iter =
406  std::find(container.begin(), container.end(), data);
407 
408  return iter != container.end();
409 }
410 
411 //----------------------------------------------------------------
412 // expand
413 //
414 template <class container_t>
415 container_t &
416 expand(container_t & a,
417  const container_t & b,
418  const bool unique = false)
419 {
420  for (typename container_t::const_iterator i = b.begin(); i != b.end(); ++i)
421  {
422  if (unique)
423  {
424  push_back_unique(a, *i);
425  }
426  else
427  {
428  a.push_back(*i);
429  }
430  }
431 
432  return a;
433 }
434 
435 //----------------------------------------------------------------
436 // next
437 //
438 template <class iterator_t>
439 iterator_t
440 next(const iterator_t & curr)
441 {
442  iterator_t tmp(curr);
443  return ++tmp;
444 }
445 
446 //----------------------------------------------------------------
447 // prev
448 //
449 template <class iterator_t>
450 iterator_t
451 prev(const iterator_t & curr)
452 {
453  iterator_t tmp(curr);
454  return --tmp;
455 }
456 
457 
458 //----------------------------------------------------------------
459 // dump
460 //
461 template <typename stream_t, typename data_t>
462 stream_t &
463 dump(stream_t & so, const std::list<data_t> & c)
464 {
465  for (typename std::list<data_t>::const_iterator
466  i = c.begin(); i != c.end(); ++i)
467  {
468  so << *i << ' ';
469  }
470 
471  return so;
472 }
473 
474 
475 //----------------------------------------------------------------
476 // operator <<
477 //
478 template <typename stream_t, typename data_t>
479 std::ostream &
480 operator << (stream_t & so, const std::list<data_t> & c)
481 {
482  return dump<stream_t, data_t>(so, c);
483 }
484 
485 
486 // TODO: review and delete
487 //----------------------------------------------------------------
488 // operator +
489 //
490 // Construct an on-the-fly linked list containing two elements:
491 //
492 //
493 //template <typename T>
494 //inline std::list<T>
495 //operator + (const T & a, const T & b)
496 //{
497 // std::list<T> ab;
498 // ab.push_back(a);
499 // ab.push_back(b);
500 // return ab;
501 //}
502 //
503 //
504 //----------------------------------------------------------------
505 // operator +
506 //
507 // Construct an on-the-fly linked list containing list a with item b appended:
508 //
509 //template <typename T>
510 //inline std::list<T>
511 //operator + (const std::list<T> & a, const T & b)
512 //{
513 // std::list<T> ab(a);
514 // ab.push_back(b);
515 // return ab;
516 //}
517 //
518 
519 //----------------------------------------------------------------
520 // inserter_t
521 //
522 template <class container_t, typename data_t>
524 {
525 public:
526  inserter_t(container_t & container,
527  const typename container_t::iterator & iter,
528  const bool & expand):
529  container_(container),
530  iter_(iter),
531  expand_(expand)
532  {}
533 
534  inline inserter_t<container_t, data_t> & operator << (const data_t & data)
535  {
536  if (iter_ == container_.end())
537  {
538  if (expand_)
539  {
540  iter_ = container_.insert(iter_, data);
541  }
542  else
543  {
544  assert(0);
545  }
546  }
547  else
548  {
549  *iter_ = data;
550  ++iter_;
551  }
552 
553  return *this;
554  }
555 
556 private:
557  // reference to the container:
558  container_t & container_;
559 
560  // current index into the container:
561  typename container_t::iterator iter_;
562 
563  // a flag indicating whether the container should be expanded to
564  // accomodate the insertions:
565  bool expand_;
566 };
567 
568 //----------------------------------------------------------------
569 // operator <<
570 //
571 template <typename data_t>
573 operator << (std::vector<data_t> & container, const data_t & data)
574 {
576  inserter(container, container.begin(), false);
577  return inserter << data;
578 }
579 
580 //----------------------------------------------------------------
581 // operator <<
582 //
583 template <typename data_t>
585 operator << (std::list<data_t> & container, const data_t & data)
586 {
588  inserter(container, container.begin(), true);
589  return inserter << data;
590 }
591 
592 
593 //----------------------------------------------------------------
594 // calc_euclidian_distance_sqrd
595 //
596 template <size_t dimensions, typename data_t>
597 data_t
598 calc_euclidian_distance_sqrd(const std::vector<data_t> & a,
599  const std::vector<data_t> & b)
600 {
601  data_t distance_sqrd = data_t(0);
602  for (size_t i = 0; i < dimensions; i++)
603  {
604  data_t d = a[i] - b[i];
605  distance_sqrd += d * d;
606  }
607 
608  return distance_sqrd;
609 }
610 
611 //----------------------------------------------------------------
612 // calc_euclidian_distance
613 //
614 template <size_t dimensions, typename data_t>
615 data_t
616 calc_euclidian_distance(const std::vector<data_t> & a,
617  const std::vector<data_t> & b)
618 {
619  data_t dist_sqrd = calc_euclidian_distance_sqrd<dimensions, data_t>(a, b);
620  double dist = sqrt(double(dist_sqrd));
621  return data_t(dist);
622 }
623 
624 //----------------------------------------------------------------
625 // calc_frobenius_norm_sqrd
626 //
627 template <typename data_t>
628 data_t
629 calc_frobenius_norm_sqrd(const std::vector<data_t> & vec)
630 {
631  data_t L2_norm_sqrd = data_t(0);
632 
633  const size_t len = vec.size();
634  for (size_t i = 0; i < len; i++)
635  {
636  L2_norm_sqrd += vec[i] * vec[i];
637  }
638 
639  return L2_norm_sqrd;
640 }
641 
642 //----------------------------------------------------------------
643 // calc_frobenius_norm
644 //
645 template <typename data_t>
646 data_t
647 calc_frobenius_norm(const std::vector<data_t> & vec)
648 {
649  data_t norm_sqrd = calc_frobenius_norm_sqrd<data_t>(vec);
650  double norm = sqrt(double(norm_sqrd));
651  return data_t(norm);
652 }
653 
654 //----------------------------------------------------------------
655 // normalize
656 //
657 template <typename data_t>
658 void
659 normalize(std::vector<data_t> & vec)
660 {
661  data_t norm = calc_frobenius_norm<data_t>(vec);
662 
663  const size_t len = vec.size();
664  for (size_t i = 0; i < len; i++)
665  {
666  vec[i] /= norm;
667  }
668 }
669 
670 
671 //----------------------------------------------------------------
672 // the_sign
673 //
674 template <class T>
675 inline T
676 the_sign(const T & a)
677 {
678  if (a < 0) return -1;
679  if (a > 0) return 1;
680  return 0;
681 }
682 
683 
684 //----------------------------------------------------------------
685 // copy_a_to_b
686 //
687 // list -> array:
688 //
689 template <class T>
690 void
691 copy_a_to_b(const std::list<T> & container_a,
692  std::vector<T> & container_b)
693 {
694  container_b.assign(container_a.begin(), container_a.end());
695 }
696 
697 //----------------------------------------------------------------
698 // copy_a_to_b
699 //
700 // list -> array:
701 //
702 template <class T>
703 void
704 copy_a_to_b(const std::list<T> & container_a,
705  the_dynamic_array_t<T> & container_b)
706 {
707  container_b.resize(container_a.size());
708 
709  const size_t size = container_a.size();
710  typename std::list<T>::const_iterator iter = container_a.begin();
711  for (size_t i = 0; i < size; i++, ++iter)
712  {
713  container_b[i] = *iter;
714  }
715 }
716 
717 //----------------------------------------------------------------
718 // copy_a_to_b
719 //
720 // dynamic_array -> array
721 //
722 template <class T>
723 void
724 copy_a_to_b(const the_dynamic_array_t<T> & container_a,
725  std::vector<T> & container_b)
726 {
727  container_b.resize(container_a.size());
728 
729  const size_t & size = container_a.size();
730  for (size_t i = 0; i < size; i++)
731  {
732  container_b[i] = container_a[i];
733  }
734 }
735 
736 
737 //----------------------------------------------------------------
738 // the_lock_t
739 //
740 template <typename T>
742 {
743 public:
744  the_lock_t(T * lock, bool lock_immediately = true):
745  lock_(lock),
746  armed_(false)
747  { if (lock_immediately) arm(); }
748 
749  the_lock_t(T & lock, bool lock_immediately = true):
750  lock_(&lock),
751  armed_(false)
752  { if (lock_immediately) arm(); }
753 
754  ~the_lock_t()
755  { disarm(); }
756 
757  inline void arm()
758  {
759  if (!armed_ && lock_ != NULL)
760  {
761  lock_->lock();
762  armed_ = true;
763  }
764  }
765 
766  inline void disarm()
767  {
768  if (armed_ && lock_ != NULL)
769  {
770  lock_->unlock();
771  armed_ = false;
772  }
773  }
774 
775 private:
776  the_lock_t();
777  the_lock_t(const the_lock_t &);
778  the_lock_t & operator = (const the_lock_t &);
779 
780  T * lock_;
781  bool armed_;
782 };
783 
784 //----------------------------------------------------------------
785 // the_unlock_t
786 //
787 template <typename T>
789 {
790 public:
791  the_unlock_t(T * lock):
792  lock_(lock)
793  {
794  if (lock_ != NULL)
795  {
796  assert(lock_->try_lock() == false);
797  }
798  }
799 
800  the_unlock_t(T & lock):
801  lock_(&lock)
802  {
803  if (lock_ != NULL)
804  {
805  assert(lock_->try_lock() == false);
806  }
807  }
808 
809  ~the_unlock_t()
810  {
811  if (lock_ != NULL)
812  {
813  lock_->unlock();
814  }
815  }
816 
817 private:
818  the_unlock_t();
819  the_unlock_t(const the_unlock_t &);
820  the_unlock_t & operator = (const the_unlock_t &);
821 
822  T * lock_;
823 };
824 
825 //----------------------------------------------------------------
826 // the_scoped_variable_t
827 //
828 template <typename T>
830 {
831 public:
832  the_scoped_variable_t(T & variable,
833  const T & in_scope_value,
834  const T & out_of_scope_value):
835  var_(variable),
836  in_(in_scope_value),
837  out_(out_of_scope_value)
838  {
839  var_ = in_;
840  }
841 
843  {
844  var_ = out_;
845  }
846 
847 private:
849  the_scoped_variable_t & operator = (const the_scoped_variable_t &);
850 
851  T & var_;
852  const T in_;
853  const T out_;
854 };
855 
856 //----------------------------------------------------------------
857 // the_scoped_increment_t
858 //
859 template <typename T>
861 {
862 public:
863  the_scoped_increment_t(T & variable):
864  var_(variable)
865  {
866  var_++;
867  }
868 
870  {
871  var_--;
872  }
873 
874 private:
876  the_scoped_increment_t & operator = (const the_scoped_increment_t &);
877 
878  T & var_;
879 };
880 
881 //----------------------------------------------------------------
882 // THROW_ARG2_IF_FALSE
883 //
884 #ifndef THROW_ARG2_IF_FALSE
885 #define THROW_ARG2_IF_FALSE(predicate, arg2) \
886 if (predicate) {} else throw arg2
887 #endif
888 
889 //----------------------------------------------------------------
890 // restore_console_stdio
891 //
892 // Reopen stdin, stdout, stderr on windows, no-op everywhere else
893 //
894 extern bool
895 restore_console_stdio();
896 
897 
898 //----------------------------------------------------------------
899 // off_t
900 //
901 #ifdef _WIN32
902 #define off_t __int64
903 #endif
904 
905 namespace the
906 {
907  extern int open_utf8(const char * filename_utf8,
908  int oflag,
909  int pmode);
910 
911  extern void open_utf8(std::fstream & fstream_to_open,
912  const char * filename_utf8,
913  std::ios_base::openmode mode);
914 
915  extern FILE * fopen_utf8(const char * filename_utf8,
916  const char * mode);
917 
918  extern int rename_utf8(const char * old_utf8, const char * new_utf8);
919  extern int remove_utf8(const char * filename_utf8);
920 
921  extern int rmdir_utf8(const char * path_utf8);
922  extern int mkdir_utf8(const char * path_utf8);
923 
924  extern int fseek64(FILE * file, off_t offset, int whence);
925  extern off_t ftell64(const FILE * file);
926 
927  inline static bool
928  close_enough(const float & ref,
929  const float & given,
930  const float tolerance = 1e-6f)
931  {
932  float err = fabsf(given - ref);
933  return err < tolerance;
934  }
935 
936  inline static bool
937  close_enough(const double & ref,
938  const double & given,
939  const double tolerance = 1e-6)
940  {
941  double err = fabs(given - ref);
942  return err < tolerance;
943  }
944 }
945 
946 
947 #endif // THE_UTILS_HXX_
Definition: the_utils.hxx:741
Definition: the_utils.hxx:788
Definition: the_utils.hxx:860
Definition: the_dynamic_array.hxx:45
Definition: the_utils.hxx:829
Definition: the_utils.hxx:523
Definition: the_utils.cxx:107