gdiam.cpp
Go to the documentation of this file.
1 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
2  * gdiam.C -
3  * Computes diameter, and a tight-fitting bounding box of a
4  * point-set in 3d.
5  *
6  * Copyright 2000 Sariel Har-Peled (ssaarriieell@cs.uiuc.edu)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2,
11  * or (at your option) any later version.
12  *
13  * Code is based on the paper:
14  * A Practical Approach for Computing the Diameter of a
15  * Point-Set (in ACM Sym. on Computation Geometry
16  * SoCG 2001)
17  * Sariel Har-Peled (http://www.uiuc.edu/~sariel)
18  *--------------------------------------------------------------
19  * History
20  * 3/28/01 -
21  * This is a more robust version of the code. It should
22  * handlereally abnoxious inputs well (i.e., points with equal
23  * coordinates, etc.
24 \*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
25 
26 #include "gdiam.h"
27 
28 #include <assert.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 
33 #include <algorithm>
34 #include <vector>
35 
36 #include <memory.h>
37 
38 /*--- Constants ---*/
39 
40 #define HEAP_LIMIT 10000
41 #define HEAP_DELTA 10000
42 #define PI 3.14159265958979323846
43 
44 /*--- Start of Code ---*/
45 
46 typedef long double ldouble;
47 
48 class GFSPPair;
49 
50 /*void computeExtremePairDir( const ArrPoint3d & arr,
51  const Point3d & dir,
52  GPointPair & pp,
53  int start,
54  int end
55  );
56 */
57 
59 {
60 private:
61  GBBox bbox;
62  //int left_ind, p_pnt_right; // range in the array
63  gdiam_point *p_pnt_left, *p_pnt_right;
64  gdiam_real bbox_diam, bbox_diam_proj;
65  GFSPTreeNode *left, *right;
66  gdiam_point_t center;
67 
68 public:
69  void
70  dump() const
71  {
72  printf("dump...\n");
73  //printf( "\tNode: Range: [%d, %d]\n", left_ind, p_pnt_right );
74  }
75 
76  int
77  size() const
78  {
79  return (int)(p_pnt_right - p_pnt_left);
80  }
81 
83  getCenter() const
84  {
85  return (gdiam_point)center;
86  }
87 
88  int
89  nodes_number() const
90  {
91  int sum;
92 
93  if ((left == NULL) && (right == NULL))
94  {
95  return 1;
96  }
97 
98  sum = 1;
99 
100  if (left != NULL)
101  {
102  sum += left->nodes_number();
103  }
104 
105  if (right != NULL)
106  {
107  sum += right->nodes_number();
108  }
109 
110  return sum;
111  }
112 
113  GFSPTreeNode(gdiam_point* _p_pnt_left, gdiam_point* _p_pnt_right)
114  {
115  bbox.init();
116  left = right = NULL;
117  p_pnt_left = _p_pnt_left;
118  p_pnt_right = _p_pnt_right;
119  bbox_diam = bbox_diam_proj = -1;
120  }
121 
122  gdiam_real
123  maxDiam() const
124  {
125  return bbox_diam;
126  }
127 
128  gdiam_real
129  maxDiamProj() const
130  {
131  return bbox_diam_proj;
132  }
133 
134  GFSPTreeNode*
136  {
137  return left;
138  }
139 
140  GFSPTreeNode*
142  {
143  return right;
144  }
145 
146  bool
147  isSplitable() const
148  {
149  return (size() > 1);
150  }
151 
152  const gdiam_point*
154  {
155  return p_pnt_left;
156  }
157 
158  const gdiam_point*
160  {
161  return p_pnt_left + (rand() % (p_pnt_right - p_pnt_left + 1));
162  }
163 
164  const gdiam_point*
166  {
167  return p_pnt_right;
168  }
169 
170 
171  friend class GFSPTree;
172 
173  const GBBox&
174  getBBox() const
175  {
176  return bbox;
177  }
178 };
179 
180 class GFSPTree
181 {
182 private:
183  gdiam_point* arr;
184  GFSPTreeNode* root;
185 
186 public:
187  void
188  init(const gdiam_point* _arr, int size)
189  {
190  arr = (gdiam_point*)malloc(sizeof(gdiam_point) * size);
191  assert(arr != NULL);
192 
193  for (int ind = 0; ind < size; ind++)
194  {
195  arr[ind] = _arr[ind];
196  }
197 
198  root = build_node(arr, arr + size - 1);
199  }
200 
201  static void
203  {
204  if (node == NULL)
205  {
206  return;
207  }
208 
209  terminate(node->left);
210  terminate(node->right);
211 
212  node->left = node->right = NULL;
213 
214  delete node;
215  }
216 
217  void
219  {
220  free(arr);
221  arr = NULL;
222 
223  GFSPTree::terminate(root);
224  root = NULL;
225  }
226 
227  const gdiam_point*
228  getPoints() const
229  {
230  return arr;
231  }
232 
233  int
234  nodes_number() const
235  {
236  return root->nodes_number();
237  }
238 
239  gdiam_real
240  brute_diameter(int a_lo, int a_hi, int b_lo, int b_hi, GPointPair& diam) const
241  {
242  for (int ind = a_lo; ind <= a_hi; ind++)
243  for (int jnd = b_lo; jnd <= b_hi; jnd++)
244  {
245  diam.update_diam(arr[ind], arr[jnd]);
246  }
247 
248  return diam.distance;
249  }
250 
251  gdiam_real
252  brute_diameter(int a_lo, int a_hi, int b_lo, int b_hi, GPointPair& diam, const gdiam_point dir)
253  const
254  {
255  for (int ind = a_lo; ind <= a_hi; ind++)
256  for (int jnd = b_lo; jnd <= b_hi; jnd++)
257  {
258  diam.update_diam(arr[ind], arr[jnd], dir);
259  }
260 
261  return diam.distance;
262  }
263 
264  gdiam_real
266  const gdiam_point* a_hi,
267  const gdiam_point* b_lo,
268  const gdiam_point* b_hi,
269  GPointPair& diam) const
270  {
271  for (const gdiam_point* ind = a_lo; ind <= a_hi; ind++)
272  for (const gdiam_point* jnd = b_lo; jnd <= b_hi; jnd++)
273  {
274  diam.update_diam(*ind, *jnd);
275  }
276 
277  return diam.distance;
278  }
279 
280  gdiam_real
282  const gdiam_point* a_hi,
283  const gdiam_point* b_lo,
284  const gdiam_point* b_hi,
285  GPointPair& diam,
286  const gdiam_point dir) const
287  {
288  for (const gdiam_point* ind = a_lo; ind <= a_hi; ind++)
289  for (const gdiam_point* jnd = b_lo; jnd <= b_hi; jnd++)
290  {
291  diam.update_diam(*ind, *jnd, dir);
292  }
293 
294  return diam.distance;
295  }
296 
298  getPoint(int ind) const
299  {
300  return arr[ind];
301  }
302 
303  GFSPTreeNode*
305  {
306  return root;
307  }
308 
309  GFSPTreeNode*
311  {
312  if (left > right)
313  {
314  printf("what!?\n");
315  fflush(stdout);
316  assert(left <= right);
317  }
318 
319  while ((right > left) && (pnt_isEqual(*right, *left)))
320  {
321  right--;
322  }
323 
324  GFSPTreeNode* node = new GFSPTreeNode(left, right);
325 
326  node->bbox.init();
327 
328  for (const gdiam_point* ind = left; ind <= right; ind++)
329  {
330  node->bbox.bound(*ind);
331  }
332 
333  node->bbox_diam = node->bbox.get_diam();
334 
335  node->bbox.center(node->center);
336 
337  return node;
338  }
339 
340  // return how many elements on left side.
341  int
342  split_array(gdiam_point* left, gdiam_point* right, int dim, const gdiam_real& val)
343  {
344  const gdiam_point* start_left = left;
345 
346  while (left < right)
347  {
348  if ((*left)[dim] < val)
349  {
350  left++;
351  }
352  else if ((*right)[dim] >= val)
353  {
354  right--;
355  }
356  else
357  {
358  gdiam_exchange(*right, *left);
359  }
360  }
361 
362  return left - start_left;
363  }
364 
365  void
367  {
368  int dim, left_size;
369  gdiam_real split_val;
370 
371  if (node->left != NULL)
372  {
373  return;
374  }
375 
376  GBBox& bb(node->bbox);
377 
378  dim = bb.getLongestDim();
379  split_val = (bb.min_coord(dim) + bb.max_coord(dim)) / 2.0;
380 
381  left_size = split_array(node->p_pnt_left, node->p_pnt_right, dim, split_val);
382 
383  if (left_size <= 0.0)
384  {
385  printf("bb: %g %g\n", bb.min_coord(dim), bb.max_coord(dim));
386  printf("left: %p, right: %p\n", node->p_pnt_left, node->p_pnt_right);
387  assert(left_size > 0);
388  }
389 
390  if (left_size >= (node->p_pnt_right - node->p_pnt_left + 1))
391  {
392  printf("left size too large?\n");
393  fflush(stdout);
394  assert(left_size < (node->p_pnt_right - node->p_pnt_left + 1));
395  }
396 
397  node->left = build_node(node->p_pnt_left, node->p_pnt_left + left_size - 1);
398  node->right = build_node(node->p_pnt_left + left_size, node->p_pnt_right);
399  }
400 
401  void findExtremeInProjection(GFSPPair& pair, GPointPair& max_pair_diam);
402 };
403 
404 void
405 bbox_vertex(const GBBox& bb, gdiam_point_t& ver, int vert)
406 {
407  ver[0] = ((vert & 0x1) != 0) ? bb.min_coord(0) : bb.max_coord(0);
408  ver[1] = ((vert & 0x2) != 0) ? bb.min_coord(1) : bb.max_coord(1);
409  ver[2] = ((vert & 0x4) != 0) ? bb.min_coord(2) : bb.max_coord(2);
410 }
411 
413 bbox_proj_dist(const GBBox& bb1, const GBBox& bb2, gdiam_point_cnt proj)
414 {
415  gdiam_point_t a, b;
416  gdiam_real rl;
417 
418  rl = 0;
419 
420  for (int ind = 0; ind < 8; ind++)
421  {
422  bbox_vertex(bb1, a, ind);
423 
424  //printf( "\n\n" );
425  for (int jnd = 0; jnd < 8; jnd++)
426  {
427  bbox_vertex(bb2, b, jnd);
428  //pnt_dump( b );
429  rl = max(rl, pnt_distance(a, b, proj));
430  }
431  }
432 
433  return rl;
434 }
435 
436 class GFSPPair
437 {
438 private:
439  GFSPTreeNode *left, *right;
440  double max_diam;
441 
442 public:
443  void
444  init(GFSPTreeNode* _left, GFSPTreeNode* _right)
445  {
446  left = _left;
447  right = _right;
448 
449  GBBox bb;
450 
451  bb.init(left->getBBox(), right->getBBox());
452  //printf( "\t\tbbox: \n" );
453  //bb.dump();
454  max_diam = bb.get_diam();
455  //printf( "\t\tmax_diam: %g\n", max_diam );
456  }
457 
458  void
459  init(GFSPTreeNode* _left, GFSPTreeNode* _right, gdiam_point proj_dir, gdiam_real dist)
460  {
461  left = _left;
462  right = _right;
463 
464  GBBox bb;
465 
466  bb.init(left->getBBox(), right->getBBox());
467  //printf( "\t\tbbox: \n" );
468  //bb.dump();
469 
470  //max_diam = dist + _left->getBBox().get_diam()
471  // + _right->getBBox().get_diam();
472  max_diam = max(max(bbox_proj_dist(_left->getBBox(), _right->getBBox(), proj_dir),
473  bbox_proj_dist(_left->getBBox(), _left->getBBox(), proj_dir)),
474  bbox_proj_dist(_right->getBBox(), _right->getBBox(), proj_dir));
475 
476  //printf( "diam: %g, smart diam: %g\n",
477  // max_diam,
478  // bbox_proj_dist( _left->getBBox(),
479  // _right->getBBox(),
480  // proj_dir ) );
481 
482  //printf( "dist: %g, %g, %g:\n",
483  // dist, _left->getBBox().get_diam(),
484  // _right->getBBox().get_diam() );
485 
486  //bb.get_diam_proj( proj_dir );
487  //printf( "\t\tmax_diam: %g\n", max_diam );
488  }
489 
490  // error 2r/l - approximate cos of the max possible angle in the pair
491  double
493  {
494  double l, two_r;
495 
496  l = pnt_distance(left->getCenter(), right->getCenter());
497  two_r = max(left->maxDiam(), right->maxDiam());
498 
499  if (l == 0.0)
500  {
501  return 10;
502  }
503 
504  return two_r / l;
505  }
506 
507  GFSPTreeNode*
509  {
510  return left;
511  }
512 
513  GFSPTreeNode*
515  {
516  return right;
517  }
518 
519  void
520  dump() const
521  {
522  printf("[\n");
523  left->dump();
524  right->dump();
525  printf("\tmax_diam; %g\n", max_diam);
526  }
527 
528  bool
529  isBelowThreshold(int threshold) const
530  {
531  if (left->size() > threshold)
532  {
533  return false;
534  }
535 
536  if (right->size() > threshold)
537  {
538  return false;
539  }
540 
541  return true;
542  }
543 
544  double
545  directDiameter(const GFSPTree& tree, GPointPair& diam) const
546  {
547  return tree.brute_diameter(left->ptr_pnt_left(),
548  left->ptr_pnt_right(),
549  right->ptr_pnt_left(),
550  right->ptr_pnt_right(),
551  diam);
552  }
553 
554  double
555  directDiameter(const GFSPTree& tree, GPointPair& diam, const gdiam_point dir) const
556  {
557  return tree.brute_diameter(left->ptr_pnt_left(),
558  left->ptr_pnt_right(),
559  right->ptr_pnt_left(),
560  right->ptr_pnt_right(),
561  diam,
562  dir);
563  }
564 
565  double
566  maxDiam() const
567  {
568  return max_diam;
569  }
570 
571  double
572  minAprxDiam() const
573  {
574  double sub_diam;
575 
576  sub_diam = left->maxDiam() + right->maxDiam();
577 
578  if (sub_diam > (max_diam / 10.0))
579  {
580  return max_diam;
581  }
582 
583  return max_diam - sub_diam / 2.0;
584  }
585 };
586 
587 
588 class g_heap_pairs_p;
589 
590 #define UDM_SIMPLE 1
591 #define UDM_BIG_SAMPLE 2
592 
594 {
595 private:
596  GFSPTree tree;
597  //double diam;
598  GPointPair pair_diam;
599  int points_num;
600  int threshold_brute;
601  int update_diam_mode;
602 
603 public:
604  GTreeDiamAlg(gdiam_point* arr, int size, int mode)
605  {
606  tree.init(arr, size);
607  //diam = 0;
608  pair_diam.init(arr[0]);
609  points_num = size;
610  threshold_brute = 40;
611  update_diam_mode = mode;
612  }
613 
614  void
616  {
617  tree.term();
618  }
619 
620  int
621  size() const
622  {
623  return points_num;
624  }
625 
626  const GPointPair&
627  getDiameter() const
628  {
629  return pair_diam;
630  }
631 
632  int
633  nodes_number() const
634  {
635  return tree.nodes_number();
636  }
637 
638  void addPairHeap(g_heap_pairs_p& heap, GFSPTreeNode* left, GFSPTreeNode* right);
639  void addPairHeap(g_heap_pairs_p& heap,
640  GFSPTreeNode* left,
641  GFSPTreeNode* right,
642  gdiam_point proj,
643  GFSPPair& father);
644  void split_pair(GFSPPair& pair, g_heap_pairs_p& heap, double eps);
645  void split_pair_proj(GFSPPair& pair, g_heap_pairs_p& heap, double eps, gdiam_point proj);
646  void compute_by_heap(double eps);
647  void compute_by_heap_proj(double eps, gdiam_point proj);
648 
649  double
651  {
652  return pair_diam.distance;
653  }
654 };
655 
656 /*--- Heap implementation ---*/
657 
658 typedef int (*ptrCompareFunc)(void* aPtr, void* bPtr);
659 typedef void* voidPtr_t;
660 
661 struct heap_t
662 {
666 };
667 
668 void
669 heap_init(heap_t* pHeap, ptrCompareFunc _pCompFunc)
670 {
671  assert(pHeap != NULL);
672  assert(_pCompFunc != NULL);
673 
674  memset(pHeap, 0, sizeof(heap_t));
675 
676  pHeap->pCompFunc = _pCompFunc;
677  pHeap->max_size = 100;
678  pHeap->pArr = (voidPtr_t*)malloc(sizeof(void*) * pHeap->max_size);
679  assert(pHeap->pArr != NULL);
680  pHeap->curr_size = 0;
681 }
682 
683 static void
684 resize(heap_t* pHeap, int size)
685 {
686  int max_sz;
687  voidPtr_t* pTmp;
688 
689  if (size <= pHeap->max_size)
690  {
691  return;
692  }
693 
694  max_sz = size * 2;
695  pTmp = (voidPtr_t*)malloc(max_sz * sizeof(void*));
696  assert(pTmp != NULL);
697  memset(pTmp, 0, max_sz * sizeof(void*));
698  memcpy(pTmp, pHeap->pArr, pHeap->curr_size * sizeof(void*));
699  free(pHeap->pArr);
700  pHeap->pArr = pTmp;
701 }
702 
703 void
705 {
706  assert(pHeap != NULL);
707 
708  if (pHeap->pArr != NULL)
709  {
710  free(pHeap->pArr);
711  }
712 
713  memset(pHeap, 0, sizeof(heap_t));
714 }
715 
716 void
717 heap_insert(heap_t* pHeap, void* pData)
718 {
719  int ind, father;
720  voidPtr_t pTmp;
721 
722  resize(pHeap, pHeap->curr_size + 1);
723 
724  ind = pHeap->curr_size;
725  pHeap->curr_size++;
726 
727  pHeap->pArr[ind] = pData;
728 
729  while (ind > 0)
730  {
731  father = (ind - 1) / 2;
732 
733  if ((*pHeap->pCompFunc)(pHeap->pArr[ind], pHeap->pArr[father]) <= 0)
734  {
735  break;
736  }
737 
738  pTmp = pHeap->pArr[ind];
739  pHeap->pArr[ind] = pHeap->pArr[father];
740  pHeap->pArr[father] = pTmp;
741 
742  ind = father;
743  }
744 }
745 
746 void*
748 {
749  return pHeap->pArr[0];
750 }
751 
752 void*
754 {
755  void* res;
756  void* pTmp;
757  int ind, left, right, max_ind;
758 
759  if (pHeap->curr_size <= 0)
760  {
761  return NULL;
762  }
763 
764  res = pHeap->pArr[0];
765 
766  //printf( "pHeap->curr_size: %d\n", pHeap->curr_size );
767  //printf( "res= %p\n", res );
768 
769  pHeap->curr_size--;
770  pHeap->pArr[0] = pHeap->pArr[pHeap->curr_size];
771  pHeap->pArr[pHeap->curr_size] = NULL;
772  ind = 0;
773 
774  while (ind < pHeap->curr_size)
775  {
776  left = 2 * ind + 1;
777  right = 2 * ind + 2;
778 
779  if (left >= pHeap->curr_size)
780  {
781  break;
782  }
783 
784  if (right >= pHeap->curr_size)
785  {
786  right = left;
787  }
788 
789  if ((*pHeap->pCompFunc)(pHeap->pArr[left], pHeap->pArr[right]) <= 0)
790  {
791  max_ind = right;
792  }
793  else
794  {
795  max_ind = left;
796  }
797 
798  if ((*pHeap->pCompFunc)(pHeap->pArr[ind], pHeap->pArr[max_ind]) >= 0)
799  {
800  break;
801  }
802 
803  pTmp = pHeap->pArr[ind];
804  pHeap->pArr[ind] = pHeap->pArr[max_ind];
805  pHeap->pArr[max_ind] = pTmp;
806 
807  ind = max_ind;
808  }
809 
810  return res;
811 }
812 
813 bool
815 {
816  assert(pHeap != NULL);
817 
818  return (pHeap->curr_size <= 0);
819 }
820 
821 int
822 compare_pairs(void* _a, void* _b)
823 {
824  const GFSPPair& a(*(GFSPPair*)_a);
825  const GFSPPair& b(*(GFSPPair*)_b);
826 
827  if (a.maxDiam() < b.maxDiam())
828  {
829  return -1;
830  }
831 
832  if (a.maxDiam() > b.maxDiam())
833  {
834  return 1;
835  }
836 
837  return 0;
838 }
839 
841 {
842 private:
843  heap_t heap;
844 
845 public:
847  {
848  heap_init(&heap, compare_pairs);
849  }
850 
852  {
853  while (size() > 0)
854  {
855  pop();
856  }
857 
858  heap_term(&heap);
859  }
860 
861  void
862  push(GFSPPair& pair)
863  {
864  //printf( "pushing: (%p, %p)\n", pair.get_left(),
865  // pair.get_right() );
866  GFSPPair* p_pair = new GFSPPair(pair);
867  heap_insert(&heap, (void*)p_pair);
868  }
869 
870  int
871  size() const
872  {
873  return heap.curr_size;
874  }
875 
876  GFSPPair
877  top()
878  {
879  return *(GFSPPair*)heap_top(&heap);
880  }
881 
882  void
883  pop()
884  {
885  GFSPPair* ptr = (GFSPPair*)heap_delete_max(&heap);
886 
887  delete ptr;
888  }
889 };
890 
891 /* heap.implementation end */
892 
893 
894 void
895 computeExtremePair(const gdiam_point* arr, int size, int dim, GPointPair& pp)
896 {
897  pp.init(arr[0]);
898 
899  for (int ind = 1; ind < size; ind++)
900  {
901  const gdiam_point pnt(arr[ind]);
902 
903  if (pnt[dim] < pp.p[dim])
904  {
905  pp.p = pnt;
906  }
907 
908  if (pnt[dim] > pp.q[dim])
909  {
910  pp.q = pnt;
911  }
912  }
913 
914  pp.distance = pnt_distance(pp.p, pp.q);
915 }
916 
917 void
919 {
920  g_heap_pairs_p heap;
921  int heap_limit, heap_delta;
922 
923  heap_limit = HEAP_LIMIT;
924  heap_delta = HEAP_DELTA;
925 
926  GFSPTreeNode* root = tree.getRoot();
927 
928  computeExtremePair(tree.getPoints(), points_num, root->getBBox().getLongestDim(), pair_diam);
929 
930  GFSPPair root_pair;
931 
932  root_pair.init(root, root);
933 
934  heap.push(root_pair);
935  //queue_a.pushx( root_pair );
936 
937  int count = 0;
938 
939  while (heap.size() > 0)
940  {
941  //printf( "heap.size: %d\n", heap.size() );
942  //printf( "%d: curr_diam: %g\n", count++, pair_diam.distance );
943  GFSPPair pair = heap.top();
944  heap.pop();
945  split_pair(pair, heap, eps);
946 
947  //if ( ( count & 0x3ff ) == 0 ) {
948  // printf( "heap.size: %d\n", heap.size() );
949  //}
950  if ((count & 0x3ff) == 0)
951  {
952  if (((int)heap.size()) > heap_limit)
953  {
954  threshold_brute *= 2;
955  printf("threshold_brute: %d\n", threshold_brute);
956  heap_limit += heap_delta;
957  }
958  }
959 
960  count++;
961  }
962 }
963 
964 void
966 {
967  g_heap_pairs_p heap;
968  int heap_limit, heap_delta;
969  GPointPair pair_diam_x;
970 
971 
972  //pnt_dump( proj );
973  //printf( "length = %g\n", pnt_length( proj ) );
974 
975  heap_limit = HEAP_LIMIT;
976  heap_delta = HEAP_DELTA;
977 
978  GFSPTreeNode* root = tree.getRoot();
979 
980  computeExtremePair(tree.getPoints(), points_num, root->getBBox().getLongestDim(), pair_diam_x);
981  pair_diam.init(pair_diam_x.p, pair_diam_x.q, proj);
982 
983  GFSPPair root_pair;
984 
985  root_pair.init(root, root, proj, 0);
986 
987  //printf( "root pair distance: %g\n", root_pair.maxDiam() );
988  heap.push(root_pair);
989  //queue_a.pushx( root_pair );
990 
991  int count = 0;
992 
993  while (heap.size() > 0)
994  {
995  //printf( "heap.size: %d\n", heap.size() );
996  //printf( "%d: curr_diam: %g\n", count++, pair_diam.distance );
997  GFSPPair pair = heap.top();
998  heap.pop();
999  //printf( "pair distance: %g\n", pair.maxDiam() );
1000  split_pair_proj(pair, heap, eps, proj);
1001 
1002  //if ( ( count & 0x3ff ) == 0 ) {
1003  // printf( "heap.size: %d\n", heap.size() );
1004  //}
1005  if ((count & 0x3ff) == 0)
1006  {
1007  if (((int)heap.size()) > heap_limit)
1008  {
1009  threshold_brute *= 2;
1010  printf("threshold_brute: %d\n", threshold_brute);
1011  heap_limit += heap_delta;
1012  }
1013  }
1014 
1015  count++;
1016  //printf( "Poping!\n" );
1017  }
1018 }
1019 
1020 void
1022 {
1023  if (update_diam_mode == UDM_SIMPLE)
1024  {
1025  const gdiam_point p(*(left->ptr_pnt_left()));
1026  const gdiam_point q(*(right->ptr_pnt_left()));
1027 
1028  pair_diam.update_diam(p, q);
1029  }
1030  else if (update_diam_mode == UDM_BIG_SAMPLE)
1031  {
1032  if ((left->size() < 100) || (right->size() < 100))
1033  {
1034  const gdiam_point p(*(left->ptr_pnt_left()));
1035  const gdiam_point q(*(right->ptr_pnt_left()));
1036 
1037  pair_diam.update_diam(p, q);
1038  }
1039  else
1040  {
1041 #define UMD_SIZE 5
1042  gdiam_point arr_left[UMD_SIZE], arr_right[UMD_SIZE];
1043 
1044  for (int ind = 0; ind < UMD_SIZE; ind++)
1045  {
1046  const gdiam_point p(*(left->ptr_pnt_rand()));
1047  const gdiam_point q(*(right->ptr_pnt_rand()));
1048  arr_left[ind] = p;
1049  arr_right[ind] = q;
1050 
1051  //pair_diam.update_diam( p, q );
1052  }
1053 
1054  for (int ind = 0; ind < UMD_SIZE; ind++)
1055  for (int jnd = 0; jnd < UMD_SIZE; jnd++)
1056  pair_diam.update_diam(arr_left[ind], arr_right[jnd]);
1057  }
1058  }
1059  else
1060  {
1061  assert(false);
1062  }
1063 
1064  //printf( "old_diam; %g\n", diam );
1065  //diam = max( diam, pnt_distance( p, q ) );
1066  //printf( "new_diam; %g\n", diam );
1067 
1068  GFSPPair pair;
1069 
1070  pair.init(left, right);
1071 
1072  if (pair.maxDiam() <= pair_diam.distance)
1073  {
1074  return;
1075  }
1076 
1077  heap.push(pair);
1078 }
1079 
1080 void
1082  GFSPTreeNode* left,
1083  GFSPTreeNode* right,
1084  gdiam_point proj,
1085  GFSPPair& father)
1086 {
1087  const gdiam_point p(*(left->ptr_pnt_left()));
1088  const gdiam_point q(*(right->ptr_pnt_left()));
1089 
1090  //printf( "addPairHeap( ?, %p, %p, ? )\n", left, right );
1091  pair_diam.update_diam(p, q, proj);
1092  //printf( "old_diam; %g\n", diam );
1093  //diam = max( diam, pnt_distance( p, q ) );
1094  //printf( "new_diam; %g\n", diam );
1095 
1096  GFSPPair pair;
1097 
1098  pair.init(left, right, proj, pnt_distance(p, q, proj));
1099 
1100  if (pair.maxDiam() <= pair_diam.distance)
1101  {
1102  return;
1103  }
1104 
1105  //printf( "pair.maxDiam: %g, father.maxDiam: %g\n",
1106  // pair.maxDiam(), father.maxDiam() );
1107  //printf( "pair_diam.distance: %g\n", pair_diam.distance );
1108  //pnt_dump( proj );
1109  heap.push(pair);
1110 }
1111 
1112 void
1114 {
1115  bool f_is_left_splitable, f_is_right_splitable;
1116 
1117  //printf( "pair.maxDiam: %g, limit: %g\n",
1118  // pair.maxDiam(), ((1.0 + eps) * pair_diam.distance ));
1119 
1120  if (pair.maxDiam() <= ((1.0 + eps) * pair_diam.distance))
1121  {
1122  return;
1123  }
1124 
1125  if (pair.isBelowThreshold(threshold_brute))
1126  {
1127  pair.directDiameter(tree, pair_diam, proj);
1128  return;
1129  }
1130 
1131  //printf( "Curr pair: (%p, %p)\n", pair.get_left(), pair.get_right() );
1132  f_is_left_splitable = pair.get_left()->isSplitable();
1133  f_is_right_splitable = pair.get_right()->isSplitable();
1134  assert(f_is_left_splitable || f_is_right_splitable);
1135 
1136  if (f_is_left_splitable)
1137  {
1138  tree.split_node(pair.get_left());
1139  }
1140 
1141  if (f_is_right_splitable)
1142  {
1143  tree.split_node(pair.get_right());
1144  }
1145 
1146  if (f_is_left_splitable && f_is_right_splitable)
1147  {
1148  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right()->get_left(), proj, pair);
1149  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right()->get_right(), proj, pair);
1150 
1151  // to avoid exponential blowup
1152  if (pair.get_left() != pair.get_right())
1153  addPairHeap(
1154  heap, pair.get_left()->get_right(), pair.get_right()->get_left(), proj, pair);
1155 
1156  addPairHeap(heap, pair.get_left()->get_right(), pair.get_right()->get_right(), proj, pair);
1157  return;
1158  }
1159 
1160  if (f_is_left_splitable)
1161  {
1162  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right(), proj, pair);
1163  addPairHeap(heap, pair.get_left()->get_right(), pair.get_right(), proj, pair);
1164  return;
1165  }
1166 
1167  if (f_is_right_splitable)
1168  {
1169  addPairHeap(heap, pair.get_left(), pair.get_right()->get_left(), proj, pair);
1170  addPairHeap(heap, pair.get_left(), pair.get_right()->get_right(), proj, pair);
1171  return;
1172  }
1173 }
1174 
1175 void
1177 {
1178  bool f_is_left_splitable, f_is_right_splitable;
1179 
1180  if (pair.maxDiam() <= ((1.0 + eps) * pair_diam.distance))
1181  {
1182  return;
1183  }
1184 
1185  if (pair.isBelowThreshold(threshold_brute))
1186  {
1187  pair.directDiameter(tree, pair_diam);
1188  return;
1189  }
1190 
1191  f_is_left_splitable = pair.get_left()->isSplitable();
1192  f_is_right_splitable = pair.get_right()->isSplitable();
1193  assert(f_is_left_splitable || f_is_right_splitable);
1194 
1195  if (f_is_left_splitable)
1196  {
1197  tree.split_node(pair.get_left());
1198  }
1199 
1200  if (f_is_right_splitable)
1201  {
1202  tree.split_node(pair.get_right());
1203  }
1204 
1205  if (f_is_left_splitable && f_is_right_splitable)
1206  {
1207  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right()->get_left());
1208  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right()->get_right());
1209 
1210  // to avoid exponential blowup
1211  if (pair.get_left() != pair.get_right())
1212  addPairHeap(heap, pair.get_left()->get_right(), pair.get_right()->get_left());
1213 
1214  addPairHeap(heap, pair.get_left()->get_right(), pair.get_right()->get_right());
1215  return;
1216  }
1217 
1218  if (f_is_left_splitable)
1219  {
1220  addPairHeap(heap, pair.get_left()->get_left(), pair.get_right());
1221  addPairHeap(heap, pair.get_left()->get_right(), pair.get_right());
1222  return;
1223  }
1224 
1225  if (f_is_right_splitable)
1226  {
1227  addPairHeap(heap, pair.get_left(), pair.get_right()->get_left());
1228  addPairHeap(heap, pair.get_left(), pair.get_right()->get_right());
1229  return;
1230  }
1231 }
1232 
1233 GPointPair
1235 {
1236  //gdiam_real diam;
1237  GPointPair pair;
1238 
1239  GTreeDiamAlg* pAlg = new GTreeDiamAlg(start, size, UDM_SIMPLE);
1240  pAlg->compute_by_heap(eps);
1241 
1242  pair = pAlg->getDiameter();
1243 
1244  delete pAlg;
1245 
1246  return pair;
1247 }
1248 
1249 GPointPair
1251 {
1252  //gdiam_real diam;
1253  GPointPair pair;
1254 
1255  GTreeDiamAlg* pAlg = new GTreeDiamAlg(start, size, UDM_BIG_SAMPLE);
1256  pAlg->compute_by_heap(eps);
1257 
1258  pair = pAlg->getDiameter();
1259 
1260  delete pAlg;
1261 
1262  return pair;
1263 }
1264 
1265 gdiam_point*
1266 gdiam_convert(gdiam_real* start, int size)
1267 {
1268  gdiam_point* p_arr;
1269 
1270  assert(start != NULL);
1271  assert(size > 0);
1272 
1273  p_arr = (gdiam_point*)malloc(sizeof(gdiam_point) * size);
1274  assert(p_arr != NULL);
1275 
1276  for (int ind = 0; ind < size; ind++)
1277  {
1278  p_arr[ind] = (gdiam_point) & (start[ind * 3]);
1279  }
1280 
1281  return p_arr;
1282 }
1283 
1284 GPointPair
1286 {
1287  gdiam_point* p_arr;
1288  GPointPair pair;
1289 
1290  p_arr = gdiam_convert(start, size);
1291  pair = gdiam_approx_diam(p_arr, size, eps);
1292  free(p_arr);
1293 
1294  return pair;
1295 }
1296 
1297 GPointPair
1299 {
1300  gdiam_point* p_arr;
1301  GPointPair pair;
1302 
1303  p_arr = gdiam_convert(start, size);
1304  pair = gdiam_approx_diam_UDM(p_arr, size, eps);
1305  free(p_arr);
1306 
1307  return pair;
1308 }
1309 
1310 gdiam_bbox
1311 gdiam_approx_const_mvbb(gdiam_point* start, int size, gdiam_real eps, GBBox* p_ap_bbox)
1312 {
1313  //gdiam_real diam;
1314  GPointPair pair, pair_2;
1315 
1316  GTreeDiamAlg* pAlg = new GTreeDiamAlg(start, size, UDM_SIMPLE);
1317  pAlg->compute_by_heap(eps);
1318 
1319  pair = pAlg->getDiameter();
1320 
1321  /* Comput ethe resulting diameter */
1322  gdiam_point_t dir, dir_2, dir_3;
1323 
1324  dir[0] = pair.p[0] - pair.q[0];
1325  dir[1] = pair.p[1] - pair.q[1];
1326  dir[2] = pair.p[2] - pair.q[2];
1327  pnt_normalize(dir);
1328 
1329  // printf( "Before computing second direction!\n" );
1330  //fflush( stdout );
1331  pAlg->compute_by_heap_proj(eps, dir);
1332  //printf( "second direction computed!\n" );
1333  //fflush( stdout );
1334 
1335  pair_2 = pAlg->getDiameter();
1336  dir_2[0] = pair_2.p[0] - pair_2.q[0];
1337  dir_2[1] = pair_2.p[1] - pair_2.q[1];
1338  dir_2[2] = pair_2.p[2] - pair_2.q[2];
1339 
1340  gdiam_real prd;
1341 
1342  prd = pnt_dot_prod(dir, dir_2);
1343  dir_2[0] = dir_2[0] - prd * dir[0];
1344  dir_2[1] = dir_2[1] - prd * dir[1];
1345  dir_2[2] = dir_2[2] - prd * dir[2];
1346 
1347  pnt_normalize(dir);
1348  pnt_normalize(dir_2);
1349 
1350  pnt_cross_prod(dir, dir_2, dir_3);
1351  pnt_normalize(dir_3);
1352 
1353  gdiam_bbox bbox;
1354  GBBox ap_bbox;
1355 
1356  if ((pnt_length(dir_2) < 1e-6) && (pnt_length(dir_3) < 1e-6))
1357  {
1358  gdiam_generate_orthonormal_base(dir, dir_2, dir_3);
1359  }
1360 
1361  if ((pnt_length(dir) == 0.0) || (pnt_length(dir_2) < 1e-6) || (pnt_length(dir_3) < 1e-6))
1362  {
1363  gdiam_generate_orthonormal_base(dir, dir_2, dir_3);
1364  pnt_dump(dir);
1365  pnt_dump(dir_2);
1366  pnt_dump(dir_3);
1367 
1368  fflush(stdout);
1369  fflush(stderr);
1370  assert(false);
1371  }
1372 
1373  bbox.init(dir, dir_2, dir_3);
1374  ap_bbox.init();
1375 
1376  for (int ind = 0; ind < size; ind++)
1377  {
1378  bbox.bound(start[ind]);
1379  ap_bbox.bound(start[ind]);
1380  }
1381 
1382  //printf( "Axis parallel bounding box:\n" );
1383  //ap_bbox.dump();
1384 
1385  //printf( "Arbitrarily oriented bounding box:\n" );
1386  //bbox.dump();
1387 
1388  delete pAlg;
1389 
1390  if (ap_bbox.volume() < bbox.volume())
1391  {
1392  bbox.init(ap_bbox);
1393  }
1394 
1395  if (p_ap_bbox != NULL)
1396  {
1397  *p_ap_bbox = ap_bbox;
1398  }
1399 
1400  return bbox;
1401 }
1402 
1403 gdiam_bbox
1405 {
1406  gdiam_point* p_arr;
1407  gdiam_bbox gbbox;
1408 
1409  p_arr = gdiam_convert(start, size);
1410  gbbox = gdiam_approx_const_mvbb(p_arr, size, eps, NULL);
1411  free(p_arr);
1412 
1413  return gbbox;
1414 }
1415 
1416 /*-----------------------------------------------------------------------
1417  * Code for computing best bounding box in a given drection
1418 \*-----------------------------------------------------------------------*/
1419 
1420 void
1422 {
1423  assert(pnt_length(in) > 0.0);
1424 
1425  pnt_normalize(in);
1426 
1427  // stupid cases..
1428  if (in[0] == 0.0)
1429  {
1430  if (in[1] == 0.0)
1431  {
1432  pnt_init_normalize(out1, 1, 0, 0);
1433  pnt_init_normalize(out2, 0, 1, 0);
1434  return;
1435  }
1436 
1437  if (in[2] == 0.0)
1438  {
1439  pnt_init_normalize(out1, 1, 0, 0);
1440  pnt_init_normalize(out2, 0, 0, 1);
1441  return;
1442  }
1443 
1444  pnt_init_normalize(out1, 0, -in[2], in[1]);
1445  pnt_init_normalize(out2, 1, 0, 0);
1446  return;
1447  }
1448 
1449  if ((in[1] == 0.0) && (in[2] == 0.0))
1450  {
1451  pnt_init_normalize(out1, 0, 1, 0);
1452  pnt_init_normalize(out2, 0, 0, 1);
1453  return;
1454  }
1455 
1456  if (in[1] == 0.0)
1457  {
1458  pnt_init_normalize(out1, -in[2], 0, in[0]);
1459  pnt_init_normalize(out2, 0, 1, 0);
1460  return;
1461  }
1462 
1463  if (in[2] == 0.0)
1464  {
1465  pnt_init_normalize(out1, -in[1], in[0], 0);
1466  pnt_init_normalize(out2, 0, 0, 1);
1467  return;
1468  }
1469 
1470  // all entries in the vector are not zero.
1471  pnt_init_normalize(out1, -in[1], in[0], 0);
1472  pnt_cross_prod(in, out1, out2);
1473 
1474  pnt_normalize(out2);
1475 }
1476 
1477 class point2d
1478 {
1479 public:
1482 
1483  void
1485  {
1486  src = pnt;
1487  x = pnt_dot_prod(pnt, base_x);
1488  y = pnt_dot_prod(pnt, base_y);
1489  }
1490 
1491  gdiam_real
1492  dist(const point2d& pnt)
1493  {
1494  return sqrt((x - pnt.x) * (x - pnt.x) + (y - pnt.y) * (y - pnt.y));
1495  }
1496 
1497  void
1498  dump() const
1499  {
1500  printf("(%g, %g)\n", x, y);
1501  }
1502 
1503  bool
1504  equal(const point2d& pnt) const
1505  {
1506  return ((x == pnt.x) && (y == pnt.y));
1507  }
1508 
1509  bool
1510  equal_real(const point2d& pnt) const
1511  {
1512  return ((fabs(x - pnt.x) < 1e-8) && (fabs(y - pnt.y) < 1e-8));
1513  }
1514 };
1515 
1517 
1518 class vec_point_2d : public std::vector<point2d_ptr>
1519 {
1520 };
1521 
1522 inline ldouble
1523 Area(const point2d& a, const point2d& b, const point2d& c)
1524 {
1525  double x1, y1, x2, y2, len;
1526 
1527  x1 = b.x - a.x;
1528  y1 = b.y - a.y;
1529 
1530  x2 = c.x - a.x;
1531  y2 = c.y - a.y;
1532 
1533  if ((x1 != 0.0) || (y1 != 0.0))
1534  {
1535  len = sqrt(x1 * x1 + y1 * y1);
1536  x1 /= len;
1537  y1 /= len;
1538  }
1539 
1540  if ((x2 != 0.0) || (y2 != 0.0))
1541  {
1542  len = sqrt(x2 * x2 + y2 * y2);
1543  x2 /= len;
1544  y2 /= len;
1545  }
1546 
1547  ldouble area;
1548 
1549  area = x1 * y2 - x2 * y1;
1550  //area = (ldouble)a.x * (ldouble)b.y - (ldouble)a.y * (ldouble)b.x +
1551  // (ldouble)a.y * (ldouble)c.x - (ldouble)a.x * (ldouble)c.y +
1552  // (ldouble)b.x * (ldouble)c.y - (ldouble)c.x * (ldouble)b.y;
1553 
1554  //printf( "area: %g\n", area );
1555  return area;
1556 }
1557 
1558 inline int
1559 AreaSign(const point2d& a, const point2d& b, const point2d& c)
1560 {
1561  ldouble area;
1562 
1563  area = a.x * b.y - a.y * b.x + a.y * c.x - a.x * c.y + b.x * c.y - c.x * b.y;
1564 
1565  //printf( "area: %g\n", area );
1566  return ((area < (ldouble)0.0) ? -1 : ((area > (ldouble)0.0) ? 1 : 0));
1567 }
1568 
1569 inline bool
1570 Left(const point2d& a, const point2d& b, const point2d& c)
1571 {
1572  return AreaSign(a, b, c) > 0;
1573 }
1574 
1575 inline bool
1576 Left_colinear(const point2d& a, const point2d& b, const point2d& c)
1577 {
1578  return AreaSign(a, b, c) >= 0;
1579 }
1580 
1582 {
1583 public:
1585 
1586  bool
1588  {
1589  int sgn;
1590  gdiam_real len1, len2;
1591 
1592  if (a->equal(*b))
1593  {
1594  return false;
1595  }
1596 
1597  assert(a != NULL);
1598  assert(b != NULL);
1599 
1600  if (a->equal(base))
1601  {
1602  //assert( false );
1603  return true;
1604  }
1605 
1606  if (b->equal(base))
1607  {
1608  // assert( false );
1609  return false;
1610  }
1611 
1612  //printf( "before: %p %p...\n", a, b );
1613  //fflush( stdout );
1614  /*
1615  if ( a->equal( base ) )
1616  return true;
1617  if ( b->equal( base ) )
1618  return false;
1619  */
1620  //printf( "a: (%g, %g)\n", a->x, a->y );
1621  //printf( "b: (%g, %g)\n", b->x, b->y );
1622  //fflush( stdout );
1623 
1624  sgn = AreaSign(base, *a, *b);
1625 
1626  if (sgn != 0)
1627  {
1628  return (sgn > 0);
1629  }
1630 
1631  len1 = base.dist(*a);
1632  len2 = base.dist(*b);
1633 
1634  //printf( "bogi!\n" );
1635  //fflush( stdout );
1636 
1637  return (len1 > len2);
1638  }
1639 };
1640 
1643 {
1644  point2d_ptr min_pnt = in[0];
1645 
1646  index = 0;
1647 
1648  for (int ind = 0; ind < (int)in.size(); ind++)
1649  {
1650  if (in[ind]->y < min_pnt->y)
1651  {
1652  min_pnt = in[ind];
1653  index = ind;
1654  }
1655  else if ((in[ind]->y == min_pnt->y) && (in[ind]->x < min_pnt->x))
1656  {
1657  min_pnt = in[ind];
1658  index = ind;
1659  }
1660  }
1661 
1662  return min_pnt;
1663 }
1664 
1665 void
1667 {
1668  for (int ind = 0; ind < (int)vec.size(); ind++)
1669  {
1670  printf("-- %11d (%-11g, %-11g)\n", ind, vec[ind]->x, vec[ind]->y);
1671  }
1672 
1673  printf("\n\n");
1674 }
1675 
1676 static void
1677 print_pnt(point2d_ptr pnt)
1678 {
1679  printf("(%g, %g)\n", pnt->x, pnt->y);
1680 }
1681 
1682 void
1684 {
1685  ldouble area;
1686 
1687  //dump( ch );
1688  //fflush( stdout );
1689  //fflush( stderr );
1690  for (int ind = 0; ind < (int)(ch.size() - 2); ind++)
1691  assert(Left(*(ch[ind]), *(ch[ind + 1]), *(ch[ind + 2])));
1692 
1693  assert(Left(*(ch[ch.size() - 2]), *(ch[ch.size() - 1]), *(ch[0])));
1694  assert(Left(*(ch[ch.size() - 1]), *(ch[0]), *(ch[1])));
1695 
1696  for (int ind = 0; ind < (int)(in.size() - 2); ind++)
1697  {
1698  for (int jnd = 0; jnd < (int)(ch.size() - 1); jnd++)
1699  {
1700  if (ch[jnd]->equal_real(*(in[ind])))
1701  {
1702  continue;
1703  }
1704 
1705  if (ch[jnd + 1]->equal(*(in[ind])))
1706  {
1707  continue;
1708  }
1709 
1710  if (!Left_colinear(*(ch[jnd]), *(ch[jnd + 1]), *(in[ind])))
1711  {
1712  area = Area(*(ch[jnd]), *(ch[jnd + 1]), *(in[ind]));
1713 
1714  if (fabs(area) < 1e-12)
1715  {
1716  continue;
1717  }
1718 
1719  printf("Failure in progress!\n\n");
1720  print_pnt(ch[jnd]);
1721  print_pnt(ch[jnd + 1]);
1722  print_pnt(in[ind]);
1723 
1724  //dump( ch );
1725  printf("ch[ jnd ]: (%g, %g)\n", ch[jnd]->x, ch[jnd]->y);
1726  printf("ch[ jnd + 1 ]: (%g, %g)\n", ch[jnd + 1]->x, ch[jnd + 1]->y);
1727  printf("ch[ ind ]: (%g, %g)\n", in[ind]->x, in[ind]->y);
1728  printf("Area: %g\n", (double)Area(*(ch[jnd]), *(ch[jnd + 1]), *(in[ind])));
1729  printf("jnd: %d, jnd + 1: %d, ind: %d\n", jnd, jnd + 1, ind);
1730  fflush(stdout);
1731  fflush(stderr);
1732 
1733  assert(Left(*(ch[jnd]), *(ch[jnd + 1]), *(in[ind])));
1734  }
1735  }
1736 
1737  if (ch[0]->equal(*(in[ind])))
1738  {
1739  continue;
1740  }
1741 
1742  if (ch[ch.size() - 1]->equal(*(in[ind])))
1743  {
1744  continue;
1745  }
1746 
1747  assert(Left(*(ch[ch.size() - 1]), *(ch[0]), *(in[ind])));
1748  }
1749 
1750  printf("Convex hull seems to be ok!\n");
1751 }
1752 
1753 static void
1754 remove_duplicate(vec_point_2d& in, point2d_ptr ptr, int start)
1755 {
1756  int dest;
1757 
1758  dest = start;
1759 
1760  while (start < (int)in.size())
1761  {
1762  if (in[start]->equal_real(*ptr))
1763  {
1764  start++;
1765  continue;
1766  }
1767 
1768  in[dest++] = in[start++];
1769  }
1770 
1771  while ((int)in.size() > dest)
1772  {
1773  in.pop_back();
1774  }
1775 }
1776 
1777 static void
1778 remove_consecutive_dup(vec_point_2d& in)
1779 {
1780  int dest, pos;
1781 
1782  if (in.size() < 1)
1783  {
1784  return;
1785  }
1786 
1787  dest = pos = 0;
1788 
1789  // copy first entry
1790  in[dest++] = in[pos++];
1791 
1792  while (pos < ((int)in.size() - 1))
1793  {
1794  if (in[pos - 1]->equal_real(*(in[pos])))
1795  {
1796  pos++;
1797  continue;
1798  }
1799 
1800  in[dest++] = in[pos++];
1801  }
1802 
1803  in[dest++] = in[pos++];
1804 
1805  while ((int)in.size() > dest)
1806  {
1807  in.pop_back();
1808  }
1809 }
1810 
1811 void
1813 {
1814 
1815  CompareByAngle comp;
1816  int ind, position;
1817 
1818  assert(in.size() > 1);
1819 
1820  comp.base = *(get_min_point(in, position));
1821  std::swap(in[0], in[position]);
1822 
1823  remove_duplicate(in, in[0], 1);
1824 
1825  /*
1826  printf( "comp.base: (%g, %g)\n",
1827  comp.base.x,
1828  comp.base.y );
1829  */
1830  for (int ind = 0; ind < (int)in.size(); ind++)
1831  {
1832  assert(in[ind] != NULL);
1833  }
1834 
1835  /*
1836  if ( in.size() == 24 ) {
1837  dump( in );
1838  fflush( stdout );
1839  fflush( stderr );
1840  }*/
1841 
1842  //printf( "sort( %d, %d, comp )\n", 1, in.size() );
1843  sort(in.begin() + 1, in.end(), comp);
1844  remove_consecutive_dup(in);
1845 
1846  //dump( in );
1847  /*
1848  for ( int ind = 0; ind < (int)in.size(); ind++ ) {
1849  double x_delta, y_delta;
1850 
1851  x_delta = in[ ind ]->x - comp.base.x;
1852  y_delta = in[ ind ]->y - comp.base.y;
1853 
1854  printf( "-- %11d (%-11g, %-11g) atan2: %-11g\n",
1855  ind, in[ ind ]->x,
1856  in[ ind ]->y,
1857  atan2( y_delta, x_delta ) );
1858  }*/
1859 
1860  //fflush( stdout );
1861  //printf( "pushing...\n" );
1862  //fflush( stdout );
1863  out.push_back(in[in.size() - 1]);
1864  out.push_back(in[0]);
1865 
1866  // perform the graham scan
1867  ind = 1;
1868  int last;
1869 
1870  while (ind < (int)in.size())
1871  {
1872  if (out[out.size() - 1]->equal_real(*(in[ind])))
1873  {
1874  ind++;
1875  continue;
1876  }
1877 
1878  last = out.size();
1879  assert(last > 1);
1880 
1881  if (Left(*(out[last - 2]), *(out[last - 1]), *(in[ind])))
1882  {
1883  if (!out[last - 1]->equal(*(in[ind])))
1884  {
1885  out.push_back(in[ind]);
1886  }
1887 
1888  ind++;
1889  }
1890  else
1891  {
1892  if (out.size() < 3)
1893  {
1894  dump(out);
1895  printf("Input:\n");
1896  dump(in);
1897  printf("ind: %d\n", ind);
1898  fflush(stdout);
1899  assert(out.size() > 2);
1900  }
1901 
1902  out.pop_back();
1903  }
1904  }
1905 
1906  // we pushed in[ in.size() -1 ] twice in the output
1907  out.pop_back();
1908 
1909  //verify_convex_hull( in, out );
1910 }
1911 
1913 {
1916 
1917  void
1918  get_dir(int ind, gdiam_point_2d out)
1919  {
1920  out[0] = vertices[ind][0] - vertices[(ind + 1) % 4][0];
1921  out[1] = vertices[ind][1] - vertices[(ind + 1) % 4][1];
1922  }
1923 
1924  void
1926  {
1927  printf("--- bbox 2d ----------------------------\n");
1928 
1929  for (int ind = 0; ind < 4; ind++)
1930  printf("%d: (%g, %g)\n", ind, vertices[ind][0], vertices[ind][1]);
1931 
1932  for (int ind = 0; ind < 4; ind++)
1933  {
1934  gdiam_point_2d_t dir;
1935 
1936  get_dir(ind, dir);
1937 
1938  printf("dir %d: (%g, %g)\n", ind, dir[0], dir[1]);
1939  }
1940 
1941  printf("\\----------------------------------\n");
1942  }
1943 };
1944 
1945 #define EPS 1e-6
1946 
1947 inline bool
1949 {
1950  return (((b - EPS) < a) && (a < (b + EPS)));
1951 }
1952 
1954 {
1955 private:
1956  vec_point_2d ch;
1957  gdiam_real* angles;
1958 
1959 public:
1960  void
1962  {
1963  for (int ind = 0; ind < (int)ch.size(); ind++)
1964  {
1965  printf("%d: (%g, %g)\n", ind, ch[ind]->x, ch[ind]->y);
1966  }
1967  }
1968 
1969  void
1971  {
1972  int u2;
1973  double ang;
1974  double x1, y1, x2, y2;
1975 
1976  u2 = (u + 1) % ch.size();
1977 
1978  x1 = ch[u]->x;
1979  y1 = ch[u]->y;
1980  x2 = ch[u2]->x;
1981  y2 = ch[u2]->y;
1982 
1983  ang = atan2(y2 - y1, x2 - x1);
1984 
1985  if (ang < 0)
1986  {
1987  ang += 2.0 * PI;
1988  }
1989 
1990  angles[u] = ang;
1991 
1992  // floating point nonsence. A huck to solve this...
1993  if ((u > 0) && (angles[u] < angles[u - 1]) && eq_real(angles[u], angles[u - 1]))
1994  {
1995  angles[u] = angles[u - 1];
1996  }
1997 
1998  /*
1999  printf( "angles[ %4d ]: %.20f ", u, ang );
2000  if ( u > 0 )
2001  printf( "%2d", (angles[ u ] >= angles[ u - 1 ] ) );
2002  if ( u > 1 ) {
2003  printf( " area: %.20f ", (double)Area( *( ch[ u - 2 ] ),
2004  *( ch[ u - 1 ] ),
2005  *( ch[ u ] ) ) );
2006  }
2007  printf( "\n" );
2008  */
2009  }
2010 
2011  /* Finding the first vertex whose edge is over a given angle */
2012  int
2013  find_vertex(int start_vertex, double trg_angle)
2014  {
2015  double prev_angle, curr_angle;
2016  bool f_found;
2017  int ver, prev_vertex;
2018 
2019  f_found = false;
2020 
2021  prev_vertex = start_vertex - 1;
2022 
2023  if (prev_vertex < 0)
2024  {
2025  prev_vertex = ch.size() - 1;
2026  }
2027 
2028  prev_angle = angles[prev_vertex];
2029  ver = start_vertex;
2030 
2031  while (!f_found)
2032  {
2033  curr_angle = angles[ver];
2034 
2035  if (prev_angle <= curr_angle)
2036  f_found = ((prev_angle < trg_angle) && (trg_angle <= curr_angle));
2037  else
2038  f_found = ((prev_angle < trg_angle) || (trg_angle <= curr_angle));
2039 
2040  if (f_found)
2041  {
2042  break;
2043  }
2044  else
2045  {
2046  prev_angle = curr_angle;
2047  }
2048 
2049  ver = (ver + 1) % ch.size();
2050  }
2051 
2052  return ver;
2053  }
2054 
2055  /* Computing the intersection point of two lines, each given by a
2056  point and slope */
2057  void
2058  compute_crossing(int a_ind,
2059  double a_angle,
2060  int b_ind,
2061  double b_angle,
2062  gdiam_real& x,
2063  gdiam_real& y)
2064  {
2065  double a_slope, b_slope, x_a, x_b, y_a, y_b;
2066 
2067  if (eq_real(a_angle, 0.0) || eq_real(a_angle, PI))
2068  {
2069  x = ch[b_ind]->x;
2070  y = ch[a_ind]->y;
2071  return;
2072  }
2073 
2074  if (eq_real(a_angle, PI / 2.0) || eq_real(a_angle, PI * 1.5))
2075  {
2076  x = ch[a_ind]->x;
2077  y = ch[b_ind]->y;
2078  return;
2079  }
2080 
2081  a_slope = tan(a_angle);
2082  b_slope = tan(b_angle);
2083  x_a = ch[a_ind]->x;
2084  y_a = ch[a_ind]->y;
2085  x_b = ch[b_ind]->x;
2086  y_b = ch[b_ind]->y;
2087 
2088  double a_const, b_const, x_out, y_out;
2089 
2090  // Let see:
2091  // l_a = y = a_slope * x + a_const ->
2092  // y_a = a_slope * x_a + a_const (since (x_a, y_a) in l_a
2093  // a_const = y_a - a_slope * x_a
2094  a_const = y_a - a_slope * x_a;
2095  //printf( "a_const: %g, y_a: %g, a_slope: %g, x_a: %g\n",
2096  // a_const, y_a, a_slope, x_a );
2097 
2098  b_const = y_b - b_slope * x_b;
2099  //printf( "b_const: %g, y_b: %g, b_slope: %g, x_b: %g\n",
2100  // b_const, y_b, b_slope, x_b );
2101 
2102  x_out = -(a_const - b_const) / (a_slope - b_slope);
2103  y_out = a_slope * x_out + a_const;
2104  /*
2105  x = (y_b - y_a + x_a * a_slope - x_b * a_slope)
2106  / (a_slope - b_slope);
2107  y = ((y_a - x_a * a_slope) / a_slope - (y_b - x_b * b_slope)
2108  / b_slope) /
2109  (1.0 / a_slope - 1.0 / b_slope );
2110  printf( "gill: (%g, %g)\nMine: (%g, %g)\n",
2111  x, y, x_out, y_out );
2112  */
2113  //printf( "a_angle: %g, b_angle: %g\n",
2114  // a_angle / PI, b_angle/ PI );
2115  //printf( "a_slope: %g, b_slope: %g\n",
2116  // a_slope, b_slope );
2117  //printf( "on line_b: %g\n",
2118  // b_slope * x_out + b_const - y_out );
2119  x = x_out;
2120  y = y_out;
2121  //printf( "line_a : y = %g * x + %g\n",
2122  // a_slope, a_const );
2123  //printf( "line_b : y = %g * x + %g\n",
2124  // b_slope, b_const );
2125  //printf( "a: (%g, %g)\n"
2126  // "b: (%g, %g)\n",
2127  // x_a, y_a, x_b, y_b );
2128 
2129  //printf( "out: (%g, %g)\n", x, y );
2130  }
2131 
2132  void
2133  get_bbox(int a_ind,
2134  gdiam_real a_angle,
2135  int b_ind,
2136  gdiam_real b_angle,
2137  int c_ind,
2138  gdiam_real c_angle,
2139  int d_ind,
2140  gdiam_real d_angle,
2141  bbox_2d_info& bbox,
2142  gdiam_real& area)
2143  {
2144  /*
2145  printf( "get_bbox: (%d, %g,\n"
2146  "%d, %g\n"
2147  "%d, %g\n"
2148  "%d, %g )\n",
2149  a_ind, a_angle / PI,
2150  b_ind, b_angle / PI,
2151  c_ind, c_angle / PI,
2152  d_ind, d_angle / PI );*/
2153 
2154  compute_crossing(a_ind, a_angle, b_ind, b_angle, bbox.vertices[0][0], bbox.vertices[0][1]);
2155  compute_crossing(b_ind, b_angle, c_ind, c_angle, bbox.vertices[1][0], bbox.vertices[1][1]);
2156  compute_crossing(c_ind, c_angle, d_ind, d_angle, bbox.vertices[2][0], bbox.vertices[2][1]);
2157  compute_crossing(d_ind, d_angle, a_ind, a_angle, bbox.vertices[3][0], bbox.vertices[3][1]);
2158 
2159  area = pnt_distance_2d(bbox.vertices[0], bbox.vertices[1]) *
2160  pnt_distance_2d(bbox.vertices[0], bbox.vertices[3]);
2161  }
2162 
2163  /* Given one angle (bbx direction), find the other three */
2164  void
2165  get_angles(int ind, gdiam_real& angle_1, gdiam_real& angle_2, gdiam_real& angle_3)
2166  {
2167  double angle;
2168 
2169  angle = angles[ind];
2170  angle_1 = angle + PI * 0.5;
2171  //printf( "angle = %g\n", angle / PI );
2172  //printf( "angle1 = %g\n", angle_1 / PI );
2173 
2174  if (angle_1 >= (2.0 * PI))
2175  {
2176  angle_1 -= 2.0 * PI;
2177  }
2178 
2179  //printf( "angle1 = %g\n", angle_1 / PI );
2180 
2181 
2182  angle_2 = angle + PI;
2183 
2184  if (angle_2 >= (2.0 * PI))
2185  {
2186  angle_2 -= 2.0 * PI;
2187  }
2188 
2189  angle_3 = angle + 1.5 * PI;
2190 
2191  if (angle_3 >= (2.0 * PI))
2192  {
2193  angle_3 -= 2.0 * PI;
2194  }
2195  }
2196 
2197  void
2199  {
2200  int u, v, s, t;
2201  gdiam_real ang1, ang2, ang3, tmp_area;
2202  bbox_2d_info tmp_bbox;
2203 
2204  angles = (gdiam_real*)malloc(sizeof(gdiam_real) * (int)ch.size());
2205  assert(angles != NULL);
2206 
2207  /* Pre-computing all edge directions */
2208  for (u = 0; u < (int)ch.size(); u++)
2209  {
2210  compute_edge_dir(u);
2211  }
2212 
2213  /* Initializing the search */
2214  //printf( "_angles[ 0 ]: %g\n", angles[ 0 ] );
2215  get_angles(0, ang1, ang2, ang3);
2216 
2217  //printf( "_angles[ 0 ]: %g\n", angles[ 0 ] );
2218  s = find_vertex(0, ang1);
2219  //printf( "_angles[ 0 ]: %g\n", angles[ 0 ] );
2220  v = find_vertex(s, ang2);
2221  t = find_vertex(v, ang3);
2222 
2223  //printf( "_angles[ 0 ]: %g\n", angles[ 0 ] );
2224  get_bbox(0, angles[0], s, ang1, v, ang2, t, ang3, min_bbox, min_area);
2225  //min_bbox.dump();
2226 
2227  //printf( "min_area: %g\n", min_area );
2228  /* Performing a double rotating calipers */
2229  for (u = 1; u < (int)ch.size(); u++)
2230  {
2231  get_angles(u, ang1, ang2, ang3);
2232  s = find_vertex(s, ang1);
2233  v = find_vertex(v, ang2);
2234  t = find_vertex(t, ang3);
2235  get_bbox(u, angles[u], s, ang1, v, ang2, t, ang3, tmp_bbox, tmp_area);
2236 
2237  //tmp_bbox.dump();
2238  //printf( "tmp_area: %g\n", tmp_area );
2239  if (min_area > tmp_area)
2240  {
2241  min_area = tmp_area;
2242  min_bbox = tmp_bbox;
2243  }
2244  }
2245 
2246  free(angles);
2247  angles = NULL;
2248  }
2249 
2250  void
2251  compute_min_bbox(vec_point_2d& points, bbox_2d_info& min_bbox, gdiam_real& min_area)
2252  {
2253  //printf( "before cunvex hull\n" );
2254  convex_hull(points, ch);
2255  //printf( "cunvex hull done!\n" );
2256  //dump_ch();
2257  compute_min_bbox_inner(min_bbox, min_area);
2258  //min_bbox.dump();
2259  }
2260 };
2261 
2262 void
2263 dump_points(gdiam_point* in_arr, int size)
2264 {
2265  for (int ind = 0; ind < size; ind++)
2266  {
2267  printf("%d: (%g, %g, %g)\n", ind, in_arr[ind][0], in_arr[ind][1], in_arr[ind][2]);
2268  }
2269 }
2270 
2271 #define ZERO_EPS (1e-6)
2272 
2273 static void
2274 construct_base_inner(gdiam_point pnt1, gdiam_point pnt2, gdiam_point pnt3)
2275 {
2276  pnt_normalize(pnt1);
2277  pnt_normalize(pnt2);
2278  pnt_normalize(pnt3);
2279 
2280  if ((pnt_length(pnt1) < ZERO_EPS) && (pnt_length(pnt2) < ZERO_EPS) &&
2281  (pnt_length(pnt3) < ZERO_EPS))
2282  {
2283  assert(false);
2284  }
2285 
2286  if ((pnt_length(pnt1) < ZERO_EPS) && (pnt_length(pnt2) < ZERO_EPS))
2287  {
2288  gdiam_generate_orthonormal_base(pnt3, pnt1, pnt2);
2289  return;
2290  }
2291 
2292  if ((pnt_length(pnt1) < ZERO_EPS) && (pnt_length(pnt3) < ZERO_EPS))
2293  {
2294  gdiam_generate_orthonormal_base(pnt2, pnt1, pnt3);
2295  return;
2296  }
2297 
2298  if ((pnt_length(pnt2) < ZERO_EPS) && (pnt_length(pnt3) < ZERO_EPS))
2299  {
2300  gdiam_generate_orthonormal_base(pnt1, pnt2, pnt3);
2301  return;
2302  }
2303 
2304  if (pnt_length(pnt1) < ZERO_EPS)
2305  {
2306  pnt_cross_prod(pnt2, pnt3, pnt1);
2307  return;
2308  }
2309 
2310  if (pnt_length(pnt2) < ZERO_EPS)
2311  {
2312  pnt_cross_prod(pnt1, pnt3, pnt2);
2313  return;
2314  }
2315 
2316  if (pnt_length(pnt3) < ZERO_EPS)
2317  {
2318  pnt_cross_prod(pnt1, pnt2, pnt3);
2319  return;
2320  }
2321 }
2322 
2323 void
2325 {
2326  construct_base_inner(pnt1, pnt2, pnt3);
2327  pnt_scale_and_add(pnt2, -pnt_dot_prod(pnt1, pnt2), pnt1);
2328  pnt_normalize(pnt2);
2329 
2330  pnt_scale_and_add(pnt3, -pnt_dot_prod(pnt1, pnt3), pnt1);
2331  pnt_scale_and_add(pnt3, -pnt_dot_prod(pnt2, pnt3), pnt2);
2332  pnt_normalize(pnt3);
2333 }
2334 
2336 {
2337 private:
2338  gdiam_point_t base_x, base_y, base_proj;
2339  point2d* arr;
2340  vec_point_2d points, ch;
2341  gdiam_bbox bbox;
2342  gdiam_point* in_arr;
2343  int size;
2344 
2345 public:
2347  {
2348  term();
2349  }
2350 
2351  void
2352  init(gdiam_point dir, gdiam_point* _in_arr, int _size)
2353  {
2354  arr = NULL;
2355 
2356  if (pnt_length(dir) == 0.0)
2357  {
2358  dump_points(_in_arr, _size);
2359  pnt_dump(dir);
2360  fflush(stdout);
2361  fflush(stderr);
2362  assert(pnt_length(dir) > 0.0);
2363  }
2364 
2365  size = _size;
2366  in_arr = _in_arr;
2367  assert(size > 0);
2368 
2369  pnt_copy(base_proj, dir);
2370  gdiam_generate_orthonormal_base(base_proj, base_x, base_y);
2371 
2372  arr = (point2d*)malloc(sizeof(point2d) * size);
2373  assert(arr != 0);
2374 
2375  for (int ind = 0; ind < size; ind++)
2376  {
2377  arr[ind].init(in_arr[ind], base_x, base_y);
2378  points.push_back(&(arr[ind]));
2379  }
2380  }
2381 
2382  void
2384  {
2385  MinAreaRectangle mar;
2386  bbox_2d_info min_bbox;
2387  gdiam_real min_area;
2388  double x1, y1, x2, y2;
2389  gdiam_point_t out_1, out_2;
2390 
2391  mar.compute_min_bbox(points, min_bbox, min_area);
2392 
2393  // We take the resulting min_area rectangle and lift it back to 3d...
2394  x1 = min_bbox.vertices[0][0] - min_bbox.vertices[1][0];
2395  y1 = min_bbox.vertices[0][1] - min_bbox.vertices[1][1];
2396  x2 = min_bbox.vertices[0][0] - min_bbox.vertices[3][0];
2397  y2 = min_bbox.vertices[0][1] - min_bbox.vertices[3][1];
2398 
2399  //printf( "prod: %g\n", x1 * x2 + y1 * y2 );
2400 
2401  double len;
2402 
2403  len = sqrt(x1 * x1 + y1 * y1);
2404 
2405  if (len > 0.0)
2406  {
2407  x1 /= len;
2408  y1 /= len;
2409  }
2410 
2411  len = sqrt(x2 * x2 + y2 * y2);
2412 
2413  if (len > 0.0)
2414  {
2415  x2 /= len;
2416  y2 /= len;
2417  }
2418 
2419  pnt_zero(out_1);
2420  pnt_scale_and_add(out_1, x1, base_x);
2421  pnt_scale_and_add(out_1, y1, base_y);
2422  pnt_normalize(out_1);
2423 
2424  pnt_zero(out_2);
2425  pnt_scale_and_add(out_2, x2, base_x);
2426  pnt_scale_and_add(out_2, y2, base_y);
2427  pnt_normalize(out_2);
2428 
2429  construct_base(base_proj, out_1, out_2);
2430 
2431  if ((!(fabs(pnt_dot_prod(base_proj, out_1)) < 1e-6)) ||
2432  (!(fabs(pnt_dot_prod(base_proj, out_2)) < 1e-6)) ||
2433  (!(fabs(pnt_dot_prod(out_1, out_2)) < 1e-6)))
2434  {
2435  printf("should be all close to zero: %g, %g, %g\n",
2436  pnt_dot_prod(base_proj, out_1),
2437  pnt_dot_prod(base_proj, out_2),
2438  pnt_dot_prod(out_1, out_2));
2439  pnt_dump(base_proj);
2440  pnt_dump(out_1);
2441  pnt_dump(out_2);
2442 
2443 
2444  printf("real points:\n");
2445  dump_points(in_arr, size);
2446 
2447  printf("points on CH:\n");
2448  dump(points);
2449 
2450  printf("BBox:\n");
2451  min_bbox.dump();
2452 
2453  fflush(stdout);
2454  fflush(stderr);
2455  assert(fabs(pnt_dot_prod(base_proj, out_1)) < 1e-6);
2456  assert(fabs(pnt_dot_prod(base_proj, out_2)) < 1e-6);
2457  assert(fabs(pnt_dot_prod(out_1, out_2)) < 1e-6);
2458  }
2459 
2460  bbox.init(base_proj, out_1, out_2);
2461 
2462  for (int ind = 0; ind < size; ind++)
2463  {
2464  bbox.bound(in_arr[ind]);
2465  }
2466  }
2467 
2468  gdiam_bbox&
2470  {
2471  return bbox;
2472  }
2473 
2474  void
2476  {
2477  if (arr != NULL)
2478  {
2479  free(arr);
2480  arr = NULL;
2481  }
2482  }
2483 
2484  void
2486  {
2487  }
2488 };
2489 
2490 gdiam_bbox
2491 gdiam_mvbb_optimize(gdiam_point* start, int size, gdiam_bbox bb_out, int times)
2492 {
2493  gdiam_bbox bb_tmp;
2494 
2495  //printf( "gdiam_mvbb_optimize called\n" );
2496 
2497  for (int ind = 0; ind < times; ind++)
2498  {
2499  ProjPointSet pps;
2500 
2501  if (pnt_length(bb_out.get_dir(ind % 3)) == 0.0)
2502  {
2503  printf("Dumping!\n");
2504  bb_out.dump();
2505  fflush(stdout);
2506  continue;
2507  }
2508 
2509  pps.init(bb_out.get_dir(ind % 3), start, size);
2510 
2511  pps.compute();
2512 
2513  //printf( "Old volume: %g\n", bb_out.volume() );
2514  bb_tmp = pps.get_bbox();
2515  //printf( "New volume: %g\n", bb_tmp.volume() );
2516  //printf( "Old bounding box:\n" );
2517  //bb2.dump();
2518 
2519  if (bb_tmp.volume() < bb_out.volume())
2520  {
2521  bb_out = bb_tmp;
2522  }
2523  }
2524 
2525  return bb_out;
2526 }
2527 
2528 gdiam_bbox
2530 {
2531  gdiam_bbox bb, bb2;
2532 
2533  bb = gdiam_approx_const_mvbb(start, size, 0.0, NULL);
2534  bb2 = gdiam_mvbb_optimize(start, size, bb, 10);
2535 
2536  //bb2.dump();
2537 
2538  return bb2;
2539 }
2540 
2541 static int
2542 gcd2(int a, int b)
2543 {
2544  if (a == 0 || a == b)
2545  {
2546  return b;
2547  }
2548 
2549  if (b == 0)
2550  {
2551  return a;
2552  }
2553 
2554  if (a > b)
2555  {
2556  return gcd2(a % b, b);
2557  }
2558  else
2559  {
2560  return gcd2(a, b % a);
2561  }
2562 }
2563 
2564 static int
2565 gcd3(int a, int b, int c)
2566 {
2567  a = abs(a);
2568  b = abs(b);
2569  c = abs(c);
2570 
2571  if (a == 0)
2572  {
2573  return gcd2(b, c);
2574  }
2575 
2576  if (b == 0)
2577  {
2578  return gcd2(a, c);
2579  }
2580 
2581  if (c == 0)
2582  {
2583  return gcd2(a, b);
2584  }
2585 
2586  return gcd2(a, gcd2(b, c));
2587 }
2588 
2589 static void
2590 try_direction(gdiam_bbox& bb,
2591  gdiam_bbox& bb_out,
2592  gdiam_point* start,
2593  int size,
2594  int x_coef,
2595  int y_coef,
2596  int z_coef)
2597 {
2598  gdiam_bbox bb_new;
2599 
2600  if (gcd3(x_coef, y_coef, z_coef) > 1)
2601  {
2602  return;
2603  }
2604 
2605  if ((x_coef == 0) && (y_coef == 0) && (z_coef == 0))
2606  {
2607  return;
2608  }
2609 
2610  //printf( "trying: (%d, %d, %d)\n",
2611  // x_coef, y_coef, z_coef );
2612  //fflush( stdout );
2613  gdiam_point_t new_dir;
2614  bb.combine(new_dir, x_coef, y_coef, z_coef);
2615 
2616  ProjPointSet pps;
2617 
2618  pps.init(new_dir, start, size);
2619 
2620  pps.compute();
2621 
2622  bb_new = pps.get_bbox();
2623  bb_new = gdiam_mvbb_optimize(start, size, bb_new, 10);
2624 
2625  if (bb_new.volume() < bb_out.volume())
2626  {
2627  bb_out = bb_new;
2628  }
2629 }
2630 
2631 gdiam_bbox
2632 gdiam_approx_mvbb_grid(gdiam_point* start, int size, int grid_size)
2633 {
2634  gdiam_bbox bb, bb_out;
2635 
2636  bb_out = bb = gdiam_approx_const_mvbb(start, size, 0.0, NULL);
2637 
2638  if (bb.volume() == 0)
2639  {
2640  dump_points(start, size);
2641  printf("1zero volume???\n");
2642  bb.dump();
2643  }
2644 
2645  bb_out = bb = gdiam_mvbb_optimize(start, size, bb_out, 10);
2646 
2647  if (bb.volume() == 0)
2648  {
2649  printf("2zero volume???\n");
2650  bb.dump();
2651  }
2652 
2653  //trying: (1, -4, 4)
2654  //try_direction( bb, bb_out, start, size,
2655  // 1, -4, 4 );
2656 
2657  for (int x_coef = -grid_size; x_coef <= grid_size; x_coef++)
2658  for (int y_coef = -grid_size; y_coef <= grid_size; y_coef++)
2659  for (int z_coef = 0; z_coef <= grid_size; z_coef++)
2660  try_direction(bb, bb_out, start, size, x_coef, y_coef, z_coef);
2661 
2662  bb_out = gdiam_mvbb_optimize(start, size, bb_out, 10);
2663 
2664  return bb_out;
2665 }
2666 
2667 static void
2668 register_point(gdiam_point pnt,
2669  gdiam_point* tops,
2670  gdiam_point* bottoms,
2671  int grid_size,
2672  gdiam_bbox& bb)
2673 {
2674  gdiam_point_t pnt_bb, pnt_bottom, pnt_top;
2675  int x_ind, y_ind, position;
2676 
2677  bb.get_normalized_coordinates(pnt, pnt_bb);
2678 
2679  // x_ind
2680  x_ind = (int)(pnt_bb[0] * grid_size);
2681  assert((-1 <= x_ind) && (x_ind <= grid_size));
2682 
2683  if (x_ind < 0)
2684  {
2685  x_ind = 0;
2686  }
2687 
2688  if (x_ind >= grid_size)
2689  {
2690  x_ind = grid_size - 1;
2691  }
2692 
2693  // y_ind
2694  y_ind = (int)(pnt_bb[1] * grid_size);
2695  assert((-1 <= y_ind) && (y_ind <= grid_size));
2696 
2697  if (y_ind < 0)
2698  {
2699  y_ind = 0;
2700  }
2701 
2702  if (y_ind >= grid_size)
2703  {
2704  y_ind = grid_size - 1;
2705  }
2706 
2707  position = x_ind + y_ind * grid_size;
2708 
2709  if (tops[position] == NULL)
2710  {
2711  tops[position] = bottoms[position] = pnt;
2712  return;
2713  }
2714 
2715  bb.get_normalized_coordinates(tops[position], pnt_top);
2716 
2717  if (pnt_top[2] < pnt_bb[2])
2718  {
2719  tops[position] = pnt;
2720  }
2721 
2722  bb.get_normalized_coordinates(bottoms[position], pnt_bottom);
2723 
2724  if (pnt_bottom[2] > pnt_bb[2])
2725  {
2726  bottoms[position] = pnt;
2727  }
2728 }
2729 
2730 // gdiam_convex_sample
2731 
2732 // We are given a point set, and (hopefully) a tight fitting
2733 // bounding box. We compute a smplae of the given size that represents
2734 // the point-set. The only guarenteed is that if we use ample of size m,
2735 // we get an approximation of quality about 1/\sqrt{m}. Note that we pad
2736 // the sample if necessary to get the desired size.
2737 gdiam_point*
2738 gdiam_convex_sample(gdiam_point* start, int size, gdiam_bbox& bb, int sample_size)
2739 {
2740  int grid_size, mem_size, grid_entries;
2741  gdiam_point *bottoms, *tops, *out_arr;
2742  int out_count;
2743 
2744  assert(sample_size > 1);
2745 
2746  // we want the grid to be on the two minor dimensions.
2747  bb.set_third_dim_longest();
2748 
2749  grid_size = (int)sqrt(sample_size / 2);
2750 
2751  grid_entries = grid_size * grid_size;
2752  mem_size = (int)(sizeof(gdiam_point) * grid_size * grid_size);
2753 
2754  bottoms = (gdiam_point*)malloc(mem_size);
2755  tops = (gdiam_point*)malloc(mem_size);
2756  out_arr = (gdiam_point*)malloc(sizeof(gdiam_point) * sample_size);
2757 
2758  assert(bottoms != NULL);
2759  assert(tops != NULL);
2760  assert(out_arr != NULL);
2761 
2762  for (int ind = 0; ind < grid_entries; ind++)
2763  {
2764  tops[ind] = bottoms[ind] = NULL;
2765  }
2766 
2767  // No we stream the points registering them with the relevant
2768  // shaft in the grid.
2769  for (int ind = 0; ind < size; ind++)
2770  register_point(start[ind], tops, bottoms, grid_size, bb);
2771 
2772  out_count = 0;
2773 
2774  for (int ind = 0; ind < grid_entries; ind++)
2775  {
2776  if (tops[ind] == NULL)
2777  {
2778  continue;
2779  }
2780 
2781  out_arr[out_count++] = tops[ind];
2782 
2783  if (tops[ind] != bottoms[ind])
2784  {
2785  out_arr[out_count++] = bottoms[ind];
2786  }
2787  }
2788 
2789  // We dont have neough entries in our sample - lets randomly pick
2790  // points.
2791  while (out_count < sample_size)
2792  {
2793  out_arr[out_count++] = start[rand() % size];
2794  }
2795 
2796  free(tops);
2797  free(bottoms);
2798 
2799  return out_arr;
2800 }
2801 
2802 gdiam_bbox
2803 gdiam_approx_mvbb_grid_sample(gdiam_point* start, int size, int grid_size, int sample_size)
2804 {
2805  gdiam_bbox bb, bb_new;
2806  gdiam_point* sample;
2807 
2808  if (sample_size >= size)
2809  {
2810  return gdiam_approx_mvbb_grid(start, size, grid_size);
2811  }
2812 
2813  //printf( "gdiam_approx_mvbb_grid_sample(...) called\n" );
2814  //fflush( stdout );
2815 
2816  bb = gdiam_approx_const_mvbb(start, size, 0.0, NULL);
2817  //printf( "guess from const approximation:\n" );
2818 
2819  sample = gdiam_convex_sample(start, size, bb, sample_size);
2820 
2821  bb_new = gdiam_approx_mvbb_grid(sample, sample_size, grid_size);
2822 
2823  //printf( "new volume on sample: %g\n",
2824  // bb_new.volume() );
2825  //fflush( stdout );
2826 
2827  for (int ind = 0; ind < size; ind++)
2828  {
2829  bb_new.bound(start[ind]);
2830  }
2831 
2832  //printf( "new volume on resized input: %g\n",
2833  // bb_new.volume() );
2834 
2835  //bb_new = gdiam_mvbb_optimize( start, size, bb_new, 10 );
2836  //printf(s "optimized new volume: %g\n",
2837  // bb_new.volume() );
2838 
2839  return bb_new;
2840 }
2841 
2842 gdiam_bbox
2843 gdiam_approx_mvbb_grid_sample(gdiam_real* start, int size, int grid_size, int sample_size)
2844 {
2845  gdiam_point* p_arr;
2846  gdiam_bbox bb;
2847 
2848  //printf( "gdiam_approx_mvbb_grid_sample( ?, %d, ...)\n", size );
2849  //fflush( stdout );
2850 
2851  p_arr = gdiam_convert(start, size);
2852  bb = gdiam_approx_mvbb_grid_sample(p_arr, size, grid_size, sample_size);
2853  free(p_arr);
2854 
2855  return bb;
2856 }
2857 
2858 /* gdiam.C - End of File ------------------------------------------*/
g_heap_pairs_p::g_heap_pairs_p
g_heap_pairs_p()
Definition: gdiam.cpp:846
GFSPPair::get_left
GFSPTreeNode * get_left()
Definition: gdiam.cpp:508
ptrCompareFunc
int(* ptrCompareFunc)(void *aPtr, void *bPtr)
Definition: gdiam.cpp:658
Area
ldouble Area(const point2d &a, const point2d &b, const point2d &c)
Definition: gdiam.cpp:1523
gdiam_bbox::volume
gdiam_real volume() const
Definition: gdiam.h:552
ProjPointSet::init
void init(gdiam_point dir, gdiam_point *_in_arr, int _size)
Definition: gdiam.cpp:2352
vec_point_2d
Definition: gdiam.cpp:1518
g_heap_pairs_p::top
GFSPPair top()
Definition: gdiam.cpp:877
MinAreaRectangle::compute_crossing
void compute_crossing(int a_ind, double a_angle, int b_ind, double b_angle, gdiam_real &x, gdiam_real &y)
Definition: gdiam.cpp:2058
ZERO_EPS
#define ZERO_EPS
Definition: gdiam.cpp:2271
point2d::y
gdiam_real y
Definition: gdiam.cpp:1480
gdiam_approx_mvbb
gdiam_bbox gdiam_approx_mvbb(gdiam_point *start, int size, gdiam_real eps)
Definition: gdiam.cpp:2529
gdiam_approx_diam_pair
GPointPair gdiam_approx_diam_pair(gdiam_real *start, int size, gdiam_real eps)
Definition: gdiam.cpp:1285
g_heap_pairs_p
Definition: gdiam.cpp:840
point2d::equal
bool equal(const point2d &pnt) const
Definition: gdiam.cpp:1504
ldouble
long double ldouble
Definition: gdiam.cpp:46
Left_colinear
bool Left_colinear(const point2d &a, const point2d &b, const point2d &c)
Definition: gdiam.cpp:1576
pnt_zero
void pnt_zero(gdiam_point dst)
Definition: gdiam.h:97
gdiam_approx_diam_UDM
GPointPair gdiam_approx_diam_UDM(gdiam_point *start, int size, gdiam_real eps)
Definition: gdiam.cpp:1250
CompareByAngle
Definition: gdiam.cpp:1581
gdiam_mvbb_optimize
gdiam_bbox gdiam_mvbb_optimize(gdiam_point *start, int size, gdiam_bbox bb_out, int times)
Definition: gdiam.cpp:2491
GFSPTreeNode::ptr_pnt_rand
const gdiam_point * ptr_pnt_rand()
Definition: gdiam.cpp:159
bbox_2d_info
Definition: gdiam.cpp:1912
gdiam_approx_mvbb_grid
gdiam_bbox gdiam_approx_mvbb_grid(gdiam_point *start, int size, int grid_size)
Definition: gdiam.cpp:2632
GTreeDiamAlg::getDiameter
const GPointPair & getDiameter() const
Definition: gdiam.cpp:627
ProjPointSet::compute
void compute()
Definition: gdiam.cpp:2383
GFSPTree::build_node
GFSPTreeNode * build_node(gdiam_point *left, gdiam_point *right)
Definition: gdiam.cpp:310
GTreeDiamAlg::split_pair
void split_pair(GFSPPair &pair, g_heap_pairs_p &heap, double eps)
Definition: gdiam.cpp:1176
GFSPTree::getPoints
const gdiam_point * getPoints() const
Definition: gdiam.cpp:228
GFSPTree::term
void term()
Definition: gdiam.cpp:218
GPointPair::init
void init(const gdiam_point _p, const gdiam_point _q)
Definition: gdiam.h:202
g_heap_pairs_p::pop
void pop()
Definition: gdiam.cpp:883
index
uint8_t index
Definition: EtherCATFrame.h:59
GFSPTreeNode::getBBox
const GBBox & getBBox() const
Definition: gdiam.cpp:174
GFSPTreeNode::get_right
GFSPTreeNode * get_right()
Definition: gdiam.cpp:141
pnt_distance_2d
gdiam_real pnt_distance_2d(gdiam_point_2d p, gdiam_point_2d q)
Definition: gdiam.h:123
GPointPair::p
gdiam_point p
Definition: gdiam.h:194
GFSPTreeNode::isSplitable
bool isSplitable() const
Definition: gdiam.cpp:147
gdiam_bbox::bound
void bound(const gdiam_point pnt)
Definition: gdiam.h:742
GFSPTreeNode::GFSPTreeNode
GFSPTreeNode(gdiam_point *_p_pnt_left, gdiam_point *_p_pnt_right)
Definition: gdiam.cpp:113
CompareByAngle::base
point2d base
Definition: gdiam.cpp:1584
GTreeDiamAlg::size
int size() const
Definition: gdiam.cpp:621
gdiam_approx_mvbb_grid_sample
gdiam_bbox gdiam_approx_mvbb_grid_sample(gdiam_point *start, int size, int grid_size, int sample_size)
Definition: gdiam.cpp:2803
GFSPTree::init
void init(const gdiam_point *_arr, int size)
Definition: gdiam.cpp:188
heap_is_empty
bool heap_is_empty(heap_t *pHeap)
Definition: gdiam.cpp:814
MinAreaRectangle
Definition: gdiam.cpp:1953
compare_pairs
int compare_pairs(void *_a, void *_b)
Definition: gdiam.cpp:822
verify_convex_hull
void verify_convex_hull(vec_point_2d &in, vec_point_2d &ch)
Definition: gdiam.cpp:1683
gdiam_bbox
Definition: gdiam.h:492
GFSPTreeNode::ptr_pnt_right
const gdiam_point * ptr_pnt_right()
Definition: gdiam.cpp:165
GFSPTreeNode::maxDiamProj
gdiam_real maxDiamProj() const
Definition: gdiam.cpp:129
bbox_proj_dist
gdiam_real bbox_proj_dist(const GBBox &bb1, const GBBox &bb2, gdiam_point_cnt proj)
Definition: gdiam.cpp:413
PI
#define PI
Definition: gdiam.cpp:42
pnt_length
gdiam_real pnt_length(const gdiam_point pnt)
Definition: gdiam.h:68
MinAreaRectangle::compute_edge_dir
void compute_edge_dir(int u)
Definition: gdiam.cpp:1970
GTreeDiamAlg::addPairHeap
void addPairHeap(g_heap_pairs_p &heap, GFSPTreeNode *left, GFSPTreeNode *right)
Definition: gdiam.cpp:1021
gdiam_point
gdiam_real * gdiam_point
Definition: gdiam.h:24
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
point2d::init
void init(gdiam_point pnt, gdiam_point base_x, gdiam_point base_y)
Definition: gdiam.cpp:1484
GFSPTreeNode::size
int size() const
Definition: gdiam.cpp:77
UMD_SIZE
#define UMD_SIZE
GFSPTree::brute_diameter
gdiam_real brute_diameter(int a_lo, int a_hi, int b_lo, int b_hi, GPointPair &diam, const gdiam_point dir) const
Definition: gdiam.cpp:252
MinAreaRectangle::compute_min_bbox
void compute_min_bbox(vec_point_2d &points, bbox_2d_info &min_bbox, gdiam_real &min_area)
Definition: gdiam.cpp:2251
GBBox::center
void center(gdiam_point out) const
Definition: gdiam.h:327
GBBox::max_coord
const gdiam_real & max_coord(int coord) const
Definition: gdiam.h:379
heap_delete_max
void * heap_delete_max(heap_t *pHeap)
Definition: gdiam.cpp:753
gdiam_bbox::dump
void dump() const
Definition: gdiam.h:651
GFSPPair
Definition: gdiam.cpp:436
eq_real
bool eq_real(gdiam_real a, gdiam_real b)
Definition: gdiam.cpp:1948
GFSPTree::findExtremeInProjection
void findExtremeInProjection(GFSPPair &pair, GPointPair &max_pair_diam)
GPointPair::update_diam
void update_diam(const gdiam_point _p, const gdiam_point _q)
Definition: gdiam.h:260
GFSPPair::init
void init(GFSPTreeNode *_left, GFSPTreeNode *_right)
Definition: gdiam.cpp:444
UDM_SIMPLE
#define UDM_SIMPLE
Definition: gdiam.cpp:590
gdiam_convex_sample
gdiam_point * gdiam_convex_sample(gdiam_point *start, int size, gdiam_bbox &bb, int sample_size)
Definition: gdiam.cpp:2738
HEAP_DELTA
#define HEAP_DELTA
Definition: gdiam.cpp:41
construct_base
void construct_base(gdiam_point pnt1, gdiam_point pnt2, gdiam_point pnt3)
Definition: gdiam.cpp:2324
GFSPTree::brute_diameter
gdiam_real brute_diameter(const gdiam_point *a_lo, const gdiam_point *a_hi, const gdiam_point *b_lo, const gdiam_point *b_hi, GPointPair &diam) const
Definition: gdiam.cpp:265
GFSPTreeNode::nodes_number
int nodes_number() const
Definition: gdiam.cpp:89
pnt_copy
void pnt_copy(gdiam_point_t dest, gdiam_point_t src)
Definition: gdiam.h:89
gdiam_real
double gdiam_real
Definition: gdiam.h:20
GFSPPair::init
void init(GFSPTreeNode *_left, GFSPTreeNode *_right, gdiam_point proj_dir, gdiam_real dist)
Definition: gdiam.cpp:459
GFSPPair::directDiameter
double directDiameter(const GFSPTree &tree, GPointPair &diam) const
Definition: gdiam.cpp:545
pnt_dump
void pnt_dump(gdiam_point_cnt pnt)
Definition: gdiam.h:103
bbox_2d_info::area
gdiam_real area
Definition: gdiam.cpp:1915
heap_top
void * heap_top(heap_t *pHeap)
Definition: gdiam.cpp:747
GTreeDiamAlg::split_pair_proj
void split_pair_proj(GFSPPair &pair, g_heap_pairs_p &heap, double eps, gdiam_point proj)
Definition: gdiam.cpp:1113
gdiam_bbox::combine
void combine(gdiam_point out, double a_coef, double b_coef, double c_coef)
Definition: gdiam.h:616
heap_t::pCompFunc
ptrCompareFunc pCompFunc
Definition: gdiam.cpp:665
armarx::armem::client::util::swap
void swap(SubscriptionHandle &first, SubscriptionHandle &second)
Definition: SubscriptionHandle.cpp:66
GBBox::bound
void bound(const gdiam_point pnt)
Definition: gdiam.h:385
GFSPPair::get_right
GFSPTreeNode * get_right()
Definition: gdiam.cpp:514
computeExtremePair
void computeExtremePair(const gdiam_point *arr, int size, int dim, GPointPair &pp)
Definition: gdiam.cpp:895
GFSPPair::dump
void dump() const
Definition: gdiam.cpp:520
GFSPTreeNode::ptr_pnt_left
const gdiam_point * ptr_pnt_left()
Definition: gdiam.cpp:153
GFSPTree::brute_diameter
gdiam_real brute_diameter(const gdiam_point *a_lo, const gdiam_point *a_hi, const gdiam_point *b_lo, const gdiam_point *b_hi, GPointPair &diam, const gdiam_point dir) const
Definition: gdiam.cpp:281
gdiam_convert
gdiam_point * gdiam_convert(gdiam_real *start, int size)
Definition: gdiam.cpp:1266
GFSPTree::split_array
int split_array(gdiam_point *left, gdiam_point *right, int dim, const gdiam_real &val)
Definition: gdiam.cpp:342
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
GTreeDiamAlg::nodes_number
int nodes_number() const
Definition: gdiam.cpp:633
g_heap_pairs_p::size
int size() const
Definition: gdiam.cpp:871
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
GTreeDiamAlg::term
void term()
Definition: gdiam.cpp:615
GFSPPair::maxDiam
double maxDiam() const
Definition: gdiam.cpp:566
GFSPTree::brute_diameter
gdiam_real brute_diameter(int a_lo, int a_hi, int b_lo, int b_hi, GPointPair &diam) const
Definition: gdiam.cpp:240
GTreeDiamAlg::diameter
double diameter()
Definition: gdiam.cpp:650
ProjPointSet::init
void init()
Definition: gdiam.cpp:2485
GBBox::get_diam
gdiam_real get_diam() const
Definition: gdiam.h:431
gdiam_point_2d
gdiam_real * gdiam_point_2d
Definition: gdiam.h:23
bbox_2d_info::dump
void dump()
Definition: gdiam.cpp:1925
GFSPTreeNode::get_left
GFSPTreeNode * get_left()
Definition: gdiam.cpp:135
GTreeDiamAlg::compute_by_heap_proj
void compute_by_heap_proj(double eps, gdiam_point proj)
Definition: gdiam.cpp:965
dump_points
void dump_points(gdiam_point *in_arr, int size)
Definition: gdiam.cpp:2263
GBBox::init
void init(const GBBox &a, const GBBox &b)
Definition: gdiam.h:298
heap_insert
void heap_insert(heap_t *pHeap, void *pData)
Definition: gdiam.cpp:717
GFSPTree::nodes_number
int nodes_number() const
Definition: gdiam.cpp:234
GFSPPair::directDiameter
double directDiameter(const GFSPTree &tree, GPointPair &diam, const gdiam_point dir) const
Definition: gdiam.cpp:555
pnt_distance
gdiam_real pnt_distance(gdiam_point p, gdiam_point q)
Definition: gdiam.h:132
dump
void dump(vec_point_2d &vec)
Definition: gdiam.cpp:1666
point2d::dump
void dump() const
Definition: gdiam.cpp:1498
g_heap_pairs_p::push
void push(GFSPPair &pair)
Definition: gdiam.cpp:862
MinAreaRectangle::get_angles
void get_angles(int ind, gdiam_real &angle_1, gdiam_real &angle_2, gdiam_real &angle_3)
Definition: gdiam.cpp:2165
pnt_cross_prod
void pnt_cross_prod(const gdiam_point a, const gdiam_point b, const gdiam_point out)
Definition: gdiam.h:115
bbox_2d_info::vertices
gdiam_point_2d_t vertices[4]
Definition: gdiam.cpp:1914
GBBox
Definition: gdiam.h:290
gdiam_bbox::get_dir
gdiam_point get_dir(int ind)
Definition: gdiam.h:593
EPS
#define EPS
Definition: gdiam.cpp:1945
GFSPTree::split_node
void split_node(GFSPTreeNode *node)
Definition: gdiam.cpp:366
max
T max(T t1, T t2)
Definition: gdiam.h:51
point2d::equal_real
bool equal_real(const point2d &pnt) const
Definition: gdiam.cpp:1510
gdiam_approx_const_mvbb
gdiam_bbox gdiam_approx_const_mvbb(gdiam_point *start, int size, gdiam_real eps, GBBox *p_ap_bbox)
Definition: gdiam.cpp:1311
GFSPPair::getProjectionError
double getProjectionError() const
Definition: gdiam.cpp:492
GFSPTreeNode::getCenter
gdiam_point getCenter() const
Definition: gdiam.cpp:83
bbox_vertex
void bbox_vertex(const GBBox &bb, gdiam_point_t &ver, int vert)
Definition: gdiam.cpp:405
GBBox::min_coord
const gdiam_real & min_coord(int coord) const
Definition: gdiam.h:373
gdiam_approx_diam_pair_UDM
GPointPair gdiam_approx_diam_pair_UDM(gdiam_real *start, int size, gdiam_real eps)
Definition: gdiam.cpp:1298
GFSPTree
Definition: gdiam.cpp:180
pnt_dot_prod
gdiam_real pnt_dot_prod(gdiam_point_cnt a, gdiam_point_cnt b)
Definition: gdiam.h:109
q
#define q
point2d::src
gdiam_point src
Definition: gdiam.cpp:1481
GBBox::getLongestDim
int getLongestDim() const
Definition: gdiam.h:409
GPointPair::q
gdiam_point q
Definition: gdiam.h:194
GFSPTreeNode::maxDiam
gdiam_real maxDiam() const
Definition: gdiam.cpp:123
pnt_scale_and_add
void pnt_scale_and_add(gdiam_point dest, gdiam_real coef, gdiam_point_cnt vec)
Definition: gdiam.h:183
gdiam_point_cnt
const gdiam_real * gdiam_point_cnt
Definition: gdiam.h:25
get_min_point
point2d_ptr get_min_point(vec_point_2d &in, int &index)
Definition: gdiam.cpp:1642
gdiam_bbox::get_normalized_coordinates
void get_normalized_coordinates(gdiam_point in, gdiam_point out)
Definition: gdiam.h:793
HEAP_LIMIT
#define HEAP_LIMIT
Definition: gdiam.cpp:40
gdiam.h
GPointPair::distance
gdiam_real distance
Definition: gdiam.h:193
gdiam_bbox::set_third_dim_longest
void set_third_dim_longest()
Definition: gdiam.h:564
heap_t::max_size
int max_size
Definition: gdiam.cpp:664
convex_hull
void convex_hull(vec_point_2d &in, vec_point_2d &out)
Definition: gdiam.cpp:1812
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
GTreeDiamAlg
Definition: gdiam.cpp:593
point2d::x
gdiam_real x
Definition: gdiam.cpp:1480
point2d::dist
gdiam_real dist(const point2d &pnt)
Definition: gdiam.cpp:1492
MinAreaRectangle::find_vertex
int find_vertex(int start_vertex, double trg_angle)
Definition: gdiam.cpp:2013
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
heap_t::pArr
voidPtr_t * pArr
Definition: gdiam.cpp:663
point2d
Definition: gdiam.cpp:1477
gdiam_point_2d_t
gdiam_real gdiam_point_2d_t[2]
Definition: gdiam.h:22
pnt_isEqual
bool pnt_isEqual(const gdiam_point p, const gdiam_point q)
Definition: gdiam.h:176
gdiam_generate_orthonormal_base
void gdiam_generate_orthonormal_base(gdiam_point in, gdiam_point out1, gdiam_point out2)
Definition: gdiam.cpp:1421
MinAreaRectangle::dump_ch
void dump_ch()
Definition: gdiam.cpp:1961
gdiam_exchange
void gdiam_exchange(T &a, T &b)
Definition: gdiam.h:59
heap_init
void heap_init(heap_t *pHeap, ptrCompareFunc _pCompFunc)
Definition: gdiam.cpp:669
gdiam_point_t
gdiam_real gdiam_point_t[GDIAM_DIM]
Definition: gdiam.h:21
GFSPPair::minAprxDiam
double minAprxDiam() const
Definition: gdiam.cpp:572
gdiam_approx_diam
GPointPair gdiam_approx_diam(gdiam_point *start, int size, gdiam_real eps)
Definition: gdiam.cpp:1234
GBBox::volume
gdiam_real volume() const
Definition: gdiam.h:336
angle
double angle(const Point &a, const Point &b, const Point &c)
Definition: point.hpp:109
heap_t
Definition: gdiam.cpp:661
ProjPointSet
Definition: gdiam.cpp:2335
GFSPTreeNode::dump
void dump() const
Definition: gdiam.cpp:70
pnt_normalize
void pnt_normalize(gdiam_point pnt)
Definition: gdiam.h:74
GFSPTree::getRoot
GFSPTreeNode * getRoot()
Definition: gdiam.cpp:304
UDM_BIG_SAMPLE
#define UDM_BIG_SAMPLE
Definition: gdiam.cpp:591
CompareByAngle::operator()
bool operator()(const point2d_ptr &a, const point2d_ptr &b)
Definition: gdiam.cpp:1587
GFSPTreeNode
Definition: gdiam.cpp:58
g_heap_pairs_p::~g_heap_pairs_p
~g_heap_pairs_p()
Definition: gdiam.cpp:851
GTreeDiamAlg::GTreeDiamAlg
GTreeDiamAlg(gdiam_point *arr, int size, int mode)
Definition: gdiam.cpp:604
ProjPointSet::get_bbox
gdiam_bbox & get_bbox()
Definition: gdiam.cpp:2469
MinAreaRectangle::compute_min_bbox_inner
void compute_min_bbox_inner(bbox_2d_info &min_bbox, gdiam_real &min_area)
Definition: gdiam.cpp:2198
voidPtr_t
void * voidPtr_t
Definition: gdiam.cpp:659
MinAreaRectangle::get_bbox
void get_bbox(int a_ind, gdiam_real a_angle, int b_ind, gdiam_real b_angle, int c_ind, gdiam_real c_angle, int d_ind, gdiam_real d_angle, bbox_2d_info &bbox, gdiam_real &area)
Definition: gdiam.cpp:2133
Left
bool Left(const point2d &a, const point2d &b, const point2d &c)
Definition: gdiam.cpp:1570
heap_term
void heap_term(heap_t *pHeap)
Definition: gdiam.cpp:704
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
heap_t::curr_size
int curr_size
Definition: gdiam.cpp:664
memory.h
ProjPointSet::term
void term()
Definition: gdiam.cpp:2475
ProjPointSet::~ProjPointSet
~ProjPointSet()
Definition: gdiam.cpp:2346
point2d_ptr
point2d * point2d_ptr
Definition: gdiam.cpp:1516
GFSPTree::getPoint
gdiam_point getPoint(int ind) const
Definition: gdiam.cpp:298
GPointPair
Definition: gdiam.h:190
GFSPPair::isBelowThreshold
bool isBelowThreshold(int threshold) const
Definition: gdiam.cpp:529
AreaSign
int AreaSign(const point2d &a, const point2d &b, const point2d &c)
Definition: gdiam.cpp:1559
pnt_init_normalize
void pnt_init_normalize(gdiam_point pnt, gdiam_real x, gdiam_real y, gdiam_real z)
Definition: gdiam.h:166
bbox_2d_info::get_dir
void get_dir(int ind, gdiam_point_2d out)
Definition: gdiam.cpp:1918
gdiam_bbox::init
void init(const GBBox &bb)
Definition: gdiam.h:682
GFSPTree::terminate
static void terminate(GFSPTreeNode *node)
Definition: gdiam.cpp:202
GTreeDiamAlg::compute_by_heap
void compute_by_heap(double eps)
Definition: gdiam.cpp:918