convexHull.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <cassert>
27 #include <iostream>
28 #include <memory>
29 #include <vector>
30 
31 #include "point.hpp"
32 
33 template <class T>
35 {
36 public:
37  struct Face;
38  struct HalfEdge;
39  using FacePtr = std::shared_ptr<Face>;
40  using HalfEdgePtr = std::shared_ptr<HalfEdge>;
41 
42  struct HalfEdge
43  {
44  const T* origin;
49  };
50 
51  struct Face
52  {
53  Face() : outerComponent(NULL), lastVisitedBy(NULL), toDelete(false)
54  {
55  }
56 
57  HalfEdgePtr outerComponent; //The face lies on the left of the edge
58  std::vector<HalfEdgePtr> innerComponents;
59  std::vector<const T*> visiblePoints;
60  const T* lastVisitedBy;
61  bool toDelete;
62  };
63 
64  // ~DoublyLinkedEdgeList() {
65  // for(HalfEdgePtr e : mHalfEdges) {
66  // delete e;
67  // }
68  // for(FacePtr f : mFaces) {
69  // delete f;
70  // }
71  // }
72 
73  std::vector<FacePtr>
75  {
76  return mFaces;
77  }
78 
79  /*
80  * Check if the face f is visible from point p
81  */
82  static bool
83  visible(const FacePtr& f, const T& p)
84  {
85  HalfEdgePtr a = f->outerComponent;
86  HalfEdgePtr b = a->next;
87  HalfEdgePtr c = b->next;
88 
89  T x = sub(*b->origin, *a->origin);
90  T y = sub(*c->origin, *a->origin);
91  T n = cross(x, y);
92 
93  //The triangle is only visible if the product of the
94  //normal and P - A is positive, i.e. smaller than 90 degs.
95  return dot(n, sub(p, *(a->origin))) >= 0;
96  }
97 
98  /*
99  * (Positive) distance from a point to a face
100  */
101  static double
102  distance(const FacePtr& f, const T& p)
103  {
104  auto e = f->outerComponent;
105  const T* a = e->origin;
106  const T* b = e->next->origin;
107  const T* c = e->next->next->origin;
108 
109  return distanceToTriangle(*a, *b, *c, p);
110  }
111 
112  /*
113  * Add a CCW triangular face, where e is the base and p the
114  * opposite point.
115  */
116  FacePtr
117  addFace(HalfEdgePtr e, const T* p)
118  {
119  FacePtr f(new Face());
120  f->outerComponent = e;
121  HalfEdgePtr ep(new HalfEdge());
122  HalfEdgePtr pe(new HalfEdge());
123  ep->origin = e->twin->origin;
124  pe->origin = p;
125  ep->incidentFace = pe->incidentFace = e->incidentFace = f;
126  e->next = ep;
127  ep->next = pe;
128  pe->next = e;
129  e->prev = pe;
130  pe->prev = ep;
131  ep->prev = e;
132 
133  //Note that here we don't use the `twin->origin` tests
134  assert(e->prev->next == e);
135  assert(e->next->prev == e);
136  assert(e->twin->twin == e);
137  assert(e->prev->incidentFace == e->incidentFace);
138  assert(e->next->incidentFace == e->incidentFace);
139 
140  assert(ep->prev->next == ep);
141  assert(ep->next->prev == ep);
142  assert(ep->prev->incidentFace == ep->incidentFace);
143  assert(ep->next->incidentFace == ep->incidentFace);
144 
145  assert(pe->prev->next == pe);
146  assert(pe->next->prev == pe);
147  assert(pe->prev->incidentFace == pe->incidentFace);
148  assert(pe->next->incidentFace == pe->incidentFace);
149 
150  assert(f->outerComponent->incidentFace == f);
151  mFaces.push_back(f);
152  return f;
153  }
154 
155  double
157  {
158  return m_area;
159  }
160 
161  void
163  {
164  double area = 0.0;
165 
166  //Heron's formula
167  for (const auto& f : mFaces)
168  {
169  HalfEdgePtr e = f->outerComponent;
170  const T* x = e->origin;
171  const T* y = e->next->origin;
172  const T* z = e->next->next->origin;
173 
174  double a = norm(sub(*y, *x));
175  double b = norm(sub(*z, *x));
176  double c = norm(sub(*y, *z));
177  double p = (a + b + c) / 2;
178 
179  area += sqrt(abs(p * (p - a) * (p - b) * (p - c)));
180  }
181 
182  m_area = area;
183  }
184 
185  double
187  {
188  return m_volume;
189  }
190 
191  void
193  {
194  double volume = 0.0;
195  //Use the origin as the center of the volume calculation
196  //TODO make this more robust (centroid?)
197  T center(0, 0, 0);
198 
199  for (const auto& f : mFaces)
200  {
201  HalfEdgePtr e = f->outerComponent;
202  const T* x = e->origin;
203  const T* y = e->next->origin;
204  const T* z = e->next->next->origin;
205 
206  double a = norm(sub(*y, *x));
207  double b = norm(sub(*z, *x));
208  double c = norm(sub(*y, *z));
209  double p = (a + b + c) / 2;
210 
211  double area = sqrt(abs(p * (p - a) * (p - b) * (p - c)));
212  double height = distance(f, center);
213  volume += area * height / 3.0;
214  }
215 
216  m_volume = volume;
217  }
218 
219  /*
220  * Assume the first three vertices are already in CCW fashion
221  * when looking at the base from the bottom, i.e. the border
222  * of the base is a->b->c->a.
223  */
224  void
225  addTetrahedron(const T& a, const T& b, const T& c, const T& d)
226  {
227  //This code is going to be sooo buggy.....
228 
229  //Create the base
230  FacePtr base(new Face());
231  HalfEdgePtr ab(new HalfEdge()); //Base edge from a and twin
232  HalfEdgePtr ba(new HalfEdge());
233  ab->twin = ba;
234  ba->twin = ab;
235  ab->origin = &a;
236  ba->origin = &b;
237  ab->incidentFace = base;
238  mHalfEdges.push_back(ab);
239  mHalfEdges.push_back(ba);
240 
241  HalfEdgePtr bc(new HalfEdge()); //Base edge from b and twin
242  HalfEdgePtr cb(new HalfEdge());
243  bc->twin = cb;
244  cb->twin = bc;
245  bc->origin = &b;
246  cb->origin = &c;
247  bc->incidentFace = base;
248  mHalfEdges.push_back(bc);
249  mHalfEdges.push_back(cb);
250 
251  HalfEdgePtr ca(new HalfEdge()); //Base edge from c and twin
252  HalfEdgePtr ac(new HalfEdge());
253  ca->twin = ac;
254  ac->twin = ca;
255  ca->origin = &c;
256  ac->origin = &a;
257  ca->incidentFace = base;
258  mHalfEdges.push_back(ca);
259  mHalfEdges.push_back(ac);
260 
261  base->outerComponent = ab;
262 
263  //Link the edges
264  ab->next = bc;
265  bc->next = ca;
266  ca->next = ab;
267  ab->prev = ca;
268  bc->prev = ab;
269  ca->prev = bc;
270 
271  mFaces.push_back(base);
272 
273  assert(!DoublyLinkedEdgeList<T>::visible(base, d));
274 
275  //Create the edges from the point
276  HalfEdgePtr bd(new HalfEdge());
277  HalfEdgePtr db(new HalfEdge());
278  bd->twin = db;
279  db->twin = bd;
280  bd->origin = &b;
281  db->origin = &d;
282  mHalfEdges.push_back(bd);
283  mHalfEdges.push_back(db);
284 
285  HalfEdgePtr da(new HalfEdge());
286  HalfEdgePtr ad(new HalfEdge());
287  da->twin = ad;
288  ad->twin = da;
289  da->origin = &d;
290  ad->origin = &a;
291  mHalfEdges.push_back(da);
292  mHalfEdges.push_back(ad);
293 
294  HalfEdgePtr dc(new HalfEdge());
295  HalfEdgePtr cd(new HalfEdge());
296  dc->twin = cd;
297  cd->twin = dc;
298  dc->origin = &d;
299  cd->origin = &c;
300  mHalfEdges.push_back(dc);
301  mHalfEdges.push_back(cd);
302 
303  //Now the other faces
304  FacePtr bad(new Face());
305  ba->incidentFace = db->incidentFace = ad->incidentFace = bad;
306  ba->next = ad;
307  ad->next = db;
308  db->next = ba;
309  ba->prev = db;
310  db->prev = ad;
311  ad->prev = ba;
312  bad->outerComponent = ba;
313  mFaces.push_back(bad);
314 
315  FacePtr acd(new Face());
316  ac->incidentFace = cd->incidentFace = da->incidentFace = acd;
317  ac->next = cd;
318  cd->next = da;
319  da->next = ac;
320  ac->prev = da;
321  da->prev = cd;
322  cd->prev = ac;
323  acd->outerComponent = ac;
324  mFaces.push_back(acd);
325 
326  FacePtr cbd(new Face());
327  cb->incidentFace = bd->incidentFace = dc->incidentFace = cbd;
328  cb->next = bd;
329  bd->next = dc;
330  dc->next = cb;
331  cb->prev = dc;
332  dc->prev = bd;
333  bd->prev = cb;
334  cbd->outerComponent = cb;
335  mFaces.push_back(cbd);
336 
337  //Now try to make sense of this mess
338  for (FacePtr f : mFaces)
339  {
340  assert(f->outerComponent->incidentFace == f);
341  }
342 
343  for (HalfEdgePtr e : mHalfEdges)
344  {
345  assert(e->prev->next == e);
346  assert(e->next->prev == e);
347  assert(e->twin->twin == e);
348  assert(e->twin->next->origin == e->origin);
349  assert(e->prev->twin->origin == e->origin);
350  assert(e->prev->incidentFace == e->incidentFace);
351  assert(e->next->incidentFace == e->incidentFace);
352  }
353  }
354 
355  void
357  {
358  mFaces.erase(remove_if(mFaces.begin(), mFaces.end(), [](FacePtr f) { return f->toDelete; }),
359  mFaces.end());
360  }
361 
362 private:
363  std::vector<HalfEdgePtr> mHalfEdges;
364  std::vector<FacePtr> mFaces;
365 
366  double m_volume;
367  double m_area;
368 };
369 
370 /*
371  * Weird pre-C++11 deficiency,
372  * you have to use ::type because we cannot use
373  * `using ConvexHull = DoublyLinkedEdgeList<T>`
374  */
375 template <typename T>
377 {
379 };
380 
381 namespace Convex
382 {
383  template <class Point>
384  std::vector<const Point*>
385  extremePoints(const std::vector<Point>& points)
386  {
387  std::vector<const Point*> tetraPoints;
388  const Point *a, *b, *c, *d;
389  double dmax, dcur;
390  dmax = dcur = 0.0;
391  const Point* tmp[6] = {&points[0],
392  &points[0], //x min, max
393  &points[0],
394  &points[0], //y min, max
395  &points[0],
396  &points[0]}; //z min, max
397 
398  for (unsigned int p = 0; p < points.size(); p++)
399  {
400  if (points.at(p)[0] < (*tmp[0])[0])
401  {
402  tmp[0] = &points.at(p);
403  }
404 
405  if (points.at(p)[0] > (*tmp[1])[0])
406  {
407  tmp[1] = &points.at(p);
408  }
409 
410  if (points.at(p)[1] < (*tmp[2])[1])
411  {
412  tmp[2] = &points.at(p);
413  }
414 
415  if (points.at(p)[1] > (*tmp[3])[1])
416  {
417  tmp[3] = &points.at(p);
418  }
419 
420  if (points.at(p)[2] < (*tmp[4])[2])
421  {
422  tmp[4] = &points.at(p);
423  }
424 
425  if (points.at(p)[2] > (*tmp[5])[2])
426  {
427  tmp[5] = &points.at(p);
428  }
429  }
430 
431  //Find the two most distant points
432  for (int i = 0; i < 6; i++)
433  {
434  for (int j = i + 1; j < 6; j++)
435  {
436  dcur = distance(*tmp[i], *tmp[j]);
437 
438  if (dmax < dcur)
439  {
440  dmax = dcur;
441  a = tmp[i];
442  b = tmp[j];
443  }
444  }
445  }
446 
447  //Find the most distant point to the line
448  dmax = 0.0;
449 
450  for (int i = 0; i < 6; i++)
451  {
452  dcur = distanceToLine(*a, *b, *tmp[i]);
453 
454  if (dmax < dcur)
455  {
456  dmax = dcur;
457  c = tmp[i];
458  }
459  }
460 
461  //Find the most distant point to the plane (from the whole point list)
462  dmax = 0.0;
463 
464  for (unsigned int i = 0; i < points.size(); i++)
465  {
466  dcur = distanceToTriangle(*a, *b, *c, points.at(i));
467 
468  if (dmax < dcur)
469  {
470  dmax = dcur;
471  d = &points.at(i);
472  }
473  }
474 
475  if (inFront(*a, *b, *c, *d))
476  {
477  tetraPoints.push_back(b);
478  tetraPoints.push_back(a);
479  }
480  else
481  {
482  tetraPoints.push_back(a);
483  tetraPoints.push_back(b);
484  }
485 
486  tetraPoints.push_back(c);
487  tetraPoints.push_back(d);
488 
489  return tetraPoints;
490  }
491 
492  /*
493  * Implementation based on the QuickHull algorithm. The idea is to assign to each face of
494  * the CH the points from which it is visible. If this list is non-empty, this face should
495  * not be on the CH, and has to be processed. The faces are put on a stack. For each face on
496  * the stack, a cone is built from the furthest point and its horizon edges. The points
497  * visible from the old faces are reassigned to the new faces.
498  */
499  template <class Point>
500  typename ConvexHull<Point>::type
501  convexHull(const std::vector<Point>& points)
502  {
503  std::cout << "CH -----------------------------------------------------------------"
504  << std::endl;
505  const double eps = 0.001;
506 
507  //Try to find four non-coplanar points
508  auto tetraPoints = extremePoints<Point>(points);
509 
510  assert(tetraPoints.size() == 4);
511 
512  typename ConvexHull<Point>::type CH;
513 
514  CH.addTetrahedron(*tetraPoints[0], *tetraPoints[1], *tetraPoints[2], *tetraPoints[3]);
515 
516  auto facesStack = CH.faces();
517  assert(facesStack.size() == 4);
518 
519  //Assign points to the face that is closest
520  for (unsigned int p = 0; p < points.size(); p++)
521  {
522  bool visible = false;
524  typename ConvexHull<Point>::type::FacePtr closestFace = NULL;
525 
526  //Find closest face
527  for (const auto& f : facesStack)
528  {
529  double distance = ConvexHull<Point>::type::distance(f, points.at(p));
530 
531  if (ConvexHull<Point>::type::visible(f, points.at(p)) && distance > eps)
532  {
533  if (distance < d)
534  {
535  d = distance;
536  visible = true;
537  closestFace = f;
538  }
539  }
540  }
541 
542  if (visible)
543  {
544  closestFace->visiblePoints.push_back(&(points.at(p)));
545  }
546  }
547 
548  //Process the stack of facets
549  while (!facesStack.empty())
550  {
551  auto currentFace = facesStack.back();
552  facesStack.pop_back();
553 
554  if (currentFace->visiblePoints.size() == 0)
555  {
556  continue;
557  }
558 
559  //std::cout << *currentFace->outerComponent->origin << "\n" << std::endl;
560  //std::cout << *currentFace->outerComponent->next->origin << "\n" << std::endl;
561  //std::cout << *currentFace->outerComponent->next->next->origin << "\n" << std::endl;
562 
563  //Find point farthest away
564  const Point* point = NULL;
566 
567  for (const Point* p : currentFace->visiblePoints)
568  {
569  double distance = ConvexHull<Point>::type::distance(currentFace, *p);
570 
571  if (distance >= d)
572  {
573  d = distance;
574  point = p;
575  }
576  }
577 
578  //Find the horizon as seen from that point
579  typename ConvexHull<Point>::type::HalfEdgePtr horizonStart = NULL;
580  //First find all visible faces
581  std::vector<typename ConvexHull<Point>::type::FacePtr> visibleFaces;
582  std::vector<typename ConvexHull<Point>::type::FacePtr> toVisit;
583  currentFace->lastVisitedBy = point;
584  visibleFaces.push_back(currentFace);
585  toVisit.push_back(currentFace);
586 
587  //Spread from the current face to the adjacent ones until no new
588  //face can be added
589  while (!toVisit.empty())
590  {
591  currentFace = toVisit.back();
592  toVisit.pop_back();
593  auto e = currentFace->outerComponent;
594 
595  //Go through the adjacent faces
596  do
597  {
598  auto adjFace = e->twin->incidentFace;
599 
600  if (adjFace->lastVisitedBy != point &&
601  ConvexHull<Point>::type::visible(adjFace, *point))
602  {
603  adjFace->lastVisitedBy = point;
604  visibleFaces.push_back(adjFace);
605  toVisit.push_back(adjFace);
606  }
607 
608  //If the adjacent face is not visible, this edge lies on the horizon
609  //TODO pull into the othe if-branch
610  if (horizonStart == NULL && !ConvexHull<Point>::type::visible(adjFace, *point))
611  {
612  horizonStart = e;
613  }
614 
615  e = e->next;
616  } while (e != currentFace->outerComponent);
617  }
618 
619  assert(horizonStart != NULL);
620 
621  //Mark visible faces for deletion later on
622  for (auto v : visibleFaces)
623  {
624  v->toDelete = true;
625  }
626 
627  //The horizon should be convex when 2D-projected from the point
628  std::vector<typename ConvexHull<Point>::type::HalfEdgePtr> horizon;
629  auto currentHorizon = horizonStart;
630 
631  //Build the horizon step by step until the loop is closed
632  do
633  {
634  horizon.push_back(currentHorizon);
635  //Find adjacent edge that is on the horizon
636  auto nextEdge = currentHorizon->next;
637 
638  while (ConvexHull<Point>::type::visible(nextEdge->twin->incidentFace, *point))
639  {
640  nextEdge = nextEdge->twin->next;
641  }
642 
643  currentHorizon = nextEdge;
644  } while (currentHorizon != horizonStart);
645 
646 
647  //Now iterate over the horizon and build the new faces
648  //Save the last one so that we can go around the horizon
649  std::vector<typename ConvexHull<Point>::type::FacePtr> newFaces;
650  auto prev = horizon.back();
651  newFaces.push_back(CH.addFace(prev, point));
652 
653  for (auto e : horizon)
654  {
655  if (e != horizon.back())
656  {
657  //For each one create the new triangular facet to the point
658  auto f = CH.addFace(e, point);
659  newFaces.push_back(f);
660 
661  //Assume you are going in CCW order?
662  assert(prev->twin->origin == e->origin);
663 
664  //Link to the prev face
665  prev->next->twin = e->prev;
666  e->prev->twin = prev->next;
667 
668  prev = e;
669  assert(e->prev->twin->twin == e->prev);
670  assert(e->prev->twin->origin == e->origin);
671  }
672  else
673  {
674  //Went through the whole horizon, join the start and the end,
675  //but don't create a new face
676  prev->next->twin = e->prev;
677  e->prev->twin = prev->next;
678 
679  assert(e->prev->twin->twin == e->prev);
680  assert(e->prev->twin->origin == e->origin);
681  }
682  }
683 
684  int visiblePoints = 0;
685  int assignedPoints = 0;
686 
687  //Also reassign the points of the old visible faces to the new faces
688  for (auto& v : visibleFaces)
689  {
690  for (auto& p : v->visiblePoints)
691  {
692  visiblePoints++;
693  bool visible = false;
695  typename ConvexHull<Point>::type::FacePtr closestFace = NULL;
696 
697  //Find closest face
698  for (auto& f : newFaces)
699  {
701 
702  if (ConvexHull<Point>::type::visible(f, *p) && distance > eps)
703  {
704  if (distance < d)
705  {
706  d = distance;
707  visible = true;
708  closestFace = f;
709  }
710  }
711  }
712 
713  if (visible)
714  {
715  closestFace->visiblePoints.push_back(p);
716  assignedPoints++;
717  }
718  }
719 
720  v->visiblePoints.clear();
721  }
722 
723  //Push the new faces into the faces stack
724  for (auto& f : newFaces)
725  {
726  if (!f->visiblePoints.empty())
727  {
728  facesStack.push_back(f);
729  }
730  }
731 
732  //Remember to delete the old visible faces (which are no longer in the CH)
733  }
734 
735  CH.cleanup();
736 
737  CH.calculateArea();
738  CH.calculateVolume();
739 
740  return CH;
741  }
742 } // namespace Convex
DoublyLinkedEdgeList::calculateVolume
void calculateVolume()
Definition: convexHull.hpp:192
DoublyLinkedEdgeList
Definition: convexHull.hpp:34
DoublyLinkedEdgeList::Face
Definition: convexHull.hpp:51
DoublyLinkedEdgeList::HalfEdge::twin
HalfEdgePtr twin
Definition: convexHull.hpp:45
distanceToLine
double distanceToLine(const Point &x, const Point &y, const Point &p)
Definition: point.hpp:125
DoublyLinkedEdgeList::addFace
FacePtr addFace(HalfEdgePtr e, const T *p)
Definition: convexHull.hpp:117
DoublyLinkedEdgeList::addTetrahedron
void addTetrahedron(const T &a, const T &b, const T &c, const T &d)
Definition: convexHull.hpp:225
DoublyLinkedEdgeList::HalfEdge::prev
HalfEdgePtr prev
Definition: convexHull.hpp:48
Convex
Definition: convexHull.hpp:381
DoublyLinkedEdgeList::Face::toDelete
bool toDelete
Definition: convexHull.hpp:61
DoublyLinkedEdgeList::distance
static double distance(const FacePtr &f, const T &p)
Definition: convexHull.hpp:102
DoublyLinkedEdgeList::HalfEdgePtr
std::shared_ptr< HalfEdge > HalfEdgePtr
Definition: convexHull.hpp:40
Convex::convexHull
ConvexHull< Point >::type convexHull(const std::vector< Point > &points)
Definition: convexHull.hpp:501
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
DoublyLinkedEdgeList::Face::Face
Face()
Definition: convexHull.hpp:53
DoublyLinkedEdgeList::HalfEdge::next
HalfEdgePtr next
Definition: convexHull.hpp:47
DoublyLinkedEdgeList::HalfEdge::origin
const T * origin
Definition: convexHull.hpp:44
distanceToTriangle
double distanceToTriangle(const Point &x, const Point &y, const Point &z, const Point &p)
Definition: point.hpp:146
DoublyLinkedEdgeList::area
double area()
Definition: convexHull.hpp:156
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
DoublyLinkedEdgeList::calculateArea
void calculateArea()
Definition: convexHull.hpp:162
DoublyLinkedEdgeList::Face::outerComponent
HalfEdgePtr outerComponent
Definition: convexHull.hpp:57
inFront
bool inFront(const Point &p1, const Point &p2, const Point &p3, const Point &p4)
Definition: point.hpp:84
DoublyLinkedEdgeList::FacePtr
std::shared_ptr< Face > FacePtr
Definition: convexHull.hpp:39
Point
Definition: PointCloud.h:21
cross
Point cross(const Point &x, const Point &y)
Definition: point.hpp:35
max
T max(T t1, T t2)
Definition: gdiam.h:51
DoublyLinkedEdgeList::HalfEdge
Definition: convexHull.hpp:42
DoublyLinkedEdgeList::faces
std::vector< FacePtr > faces()
Definition: convexHull.hpp:74
DoublyLinkedEdgeList::Face::innerComponents
std::vector< HalfEdgePtr > innerComponents
Definition: convexHull.hpp:58
DoublyLinkedEdgeList::visible
static bool visible(const FacePtr &f, const T &p)
Definition: convexHull.hpp:83
Convex::extremePoints
std::vector< const Point * > extremePoints(const std::vector< Point > &points)
Definition: convexHull.hpp:385
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
ConvexHull
Definition: convexHull.hpp:376
sub
Point sub(const Point &x, const Point &y)
Definition: point.hpp:46
dot
double dot(const Point &x, const Point &y)
Definition: point.hpp:57
DoublyLinkedEdgeList::HalfEdge::incidentFace
FacePtr incidentFace
Definition: convexHull.hpp:46
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:95
DoublyLinkedEdgeList::Face::visiblePoints
std::vector< const T * > visiblePoints
Definition: convexHull.hpp:59
T
float T
Definition: UnscentedKalmanFilterTest.cpp:38
min
T min(T t1, T t2)
Definition: gdiam.h:44
point.hpp
DoublyLinkedEdgeList::volume
double volume()
Definition: convexHull.hpp:186
DoublyLinkedEdgeList::cleanup
void cleanup()
Definition: convexHull.hpp:356
DoublyLinkedEdgeList::Face::lastVisitedBy
const T * lastVisitedBy
Definition: convexHull.hpp:60
norm
double norm(const Point &a)
Definition: point.hpp:102