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