Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
lar_cluster3d::ConvexHull Class Reference

ConvexHull class definiton. More...

#include <ConvexHull.h>

Public Types

using Point = std::tuple< float, float, const reco::ClusterHit3D * >
 projected x,y position and 3D hit More...
 
using PointList = std::list< Point >
 The list of the projected points. More...
 
using PointPair = std::pair< Point, Point >
 
using MinMaxPointPair = std::pair< PointPair, PointPair >
 

Public Member Functions

 ConvexHull (const PointList &, float=0.85, float=0.35)
 Constructor. More...
 
 ~ConvexHull ()
 Destructor. More...
 
const PointListgetPointsList ()
 recover the list of points used to build convex hull More...
 
const PointListgetConvexHull () const
 recover the list of convex hull vertices More...
 
const MinMaxPointPairgetMinMaxPointPair () const
 find the ends of the convex hull (along its x axis) More...
 
const PointListgetExtremePoints ()
 Find the two points on the hull which are furthest apart. More...
 
const reco::ConvexHullKinkTupleListgetKinkPoints ()
 Find the points with the largest angles. More...
 
float getConvexHullArea () const
 recover the area of the convex hull More...
 
PointPair findNearestEdge (const Point &, float &) const
 Given an input Point, find the nearest edge. More...
 
float findNearestDistance (const Point &) const
 Given an input point, find the distance to the nearest edge/point. More...
 

Private Member Functions

void getConvexHull (const PointList &)
 Given an input set of 2D points build a convex hull around them. More...
 
float crossProduct (const Point &p0, const Point &p1, const Point &p2) const
 Gets the cross product of line from p0 to p1 and p0 to p2. More...
 
float Area () const
 Computes the area of the enclosed convext hull. More...
 
bool isLeft (const Point &p0, const Point &p1, const Point &pCheck) const
 Determines whether a point is to the left, right or on line specifiec by p0 and p1. More...
 

Private Attributes

float fKinkAngle
 
float fMinEdgeDistance
 
const PointListfPoints
 
PointList fConvexHull
 
MinMaxPointPair fMinMaxPointPair
 
float fConvexHullArea
 
PointList fExtremePoints
 
reco::ConvexHullKinkTupleList fKinkPoints
 

Detailed Description

ConvexHull class definiton.

Definition at line 27 of file ConvexHull.h.

Member Typedef Documentation

Definition at line 36 of file ConvexHull.h.

using lar_cluster3d::ConvexHull::Point = std::tuple<float,float,const reco::ClusterHit3D*>

projected x,y position and 3D hit

Definition at line 33 of file ConvexHull.h.

The list of the projected points.

Definition at line 34 of file ConvexHull.h.

Definition at line 35 of file ConvexHull.h.

Constructor & Destructor Documentation

lar_cluster3d::ConvexHull::ConvexHull ( const PointList pointListIn,
float  kinkAngle = 0.85,
float  minEdgeDistance = 0.35 
)

Constructor.

Parameters
pset

Definition at line 29 of file ConvexHull.cxx.

29  :
30  fKinkAngle(kinkAngle), fMinEdgeDistance(minEdgeDistance), fPoints(pointListIn), fConvexHullArea(0.)
31 {
32  fConvexHull.clear();
33 
34  // Build out the convex hull around the input points
36 
37  // And the area
39 }
float Area() const
Computes the area of the enclosed convext hull.
Definition: ConvexHull.cxx:71
const PointList & getConvexHull() const
recover the list of convex hull vertices
Definition: ConvexHull.h:58
const PointList & fPoints
Definition: ConvexHull.h:117
lar_cluster3d::ConvexHull::~ConvexHull ( )

Destructor.

Definition at line 43 of file ConvexHull.cxx.

44 {
45 }

Member Function Documentation

float lar_cluster3d::ConvexHull::Area ( ) const
private

Computes the area of the enclosed convext hull.

Definition at line 71 of file ConvexHull.cxx.

72 {
73  float area(0.);
74 
75  // Compute the area by taking advantage of
76  // 1) the ability to decompose a convex hull into triangles,
77  // 2) the ability to use the cross product to calculate the area
78  // So, the technique is to pick a point which we take as the center of the polygon
79  // and then sum the signed area of triangles formed from this point to two adjecent
80  // vertices on the convex hull.
81  float x = 0.;
82  float y = 0.;
83  float n = float(fConvexHull.size());
84 
85  for(const auto& point : fConvexHull)
86  {
87  x += std::get<0>(point);
88  y += std::get<1>(point);
89  }
90 
91  Point center(x/n,y/n,0);
92 
93  Point lastPoint = fConvexHull.front();
94 
95  for(const auto& point : fConvexHull)
96  {
97  if (point != lastPoint) area += 0.5 * crossProduct(center,lastPoint,point);
98 
99  lastPoint = point;
100  }
101 
102  return area;
103 }
float crossProduct(const Point &p0, const Point &p1, const Point &p2) const
Gets the cross product of line from p0 to p1 and p0 to p2.
Definition: ConvexHull.cxx:58
std::void_t< T > n
def center(depos, point)
Definition: depos.py:117
list x
Definition: train.py:276
float lar_cluster3d::ConvexHull::crossProduct ( const Point p0,
const Point p1,
const Point p2 
) const
private

Gets the cross product of line from p0 to p1 and p0 to p2.

Definition at line 58 of file ConvexHull.cxx.

59 {
60  // Define a quick 2D cross product here since it will used quite a bit!
61  float deltaX = std::get<0>(p1) - std::get<0>(p0);
62  float deltaY = std::get<1>(p1) - std::get<1>(p0);
63  float dCheckX = std::get<0>(p2) - std::get<0>(p0);
64  float dCheckY = std::get<1>(p2) - std::get<1>(p0);
65 
66  return ((deltaX * dCheckY) - (deltaY * dCheckX));
67 }
float lar_cluster3d::ConvexHull::findNearestDistance ( const Point point) const

Given an input point, find the distance to the nearest edge/point.

Definition at line 392 of file ConvexHull.cxx.

393 {
394  float closestDistance;
395 
396  findNearestEdge(point,closestDistance);
397 
398  return closestDistance;
399 }
PointPair findNearestEdge(const Point &, float &) const
Given an input Point, find the nearest edge.
Definition: ConvexHull.cxx:331
ConvexHull::PointPair lar_cluster3d::ConvexHull::findNearestEdge ( const Point point,
float &  closestDistance 
) const

Given an input Point, find the nearest edge.

Definition at line 331 of file ConvexHull.cxx.

332 {
333  // The idea is to find the nearest edge of the convex hull, defined by
334  // two adjacent vertices of the hull, to the input point.
335  // As near as I can tell, the best way to do this is to apply brute force...
336  // Idea will be to iterate over pairs of points
337  PointList::const_iterator curPointItr = fConvexHull.begin();
338  Point prevPoint = *curPointItr++;
339  Point curPoint = *curPointItr;
340 
341  // Set up the winner
342  PointPair closestEdge(prevPoint,curPoint);
343 
344  closestDistance = std::numeric_limits<float>::max();
345 
346  // curPointItr is meant to point to the second point
347  while(curPointItr != fConvexHull.end())
348  {
349  if (curPoint != prevPoint)
350  {
351  // Dereference some stuff
352  float xPrevToPoint = (std::get<0>(point) - std::get<0>(prevPoint));
353  float yPrevToPoint = (std::get<1>(point) - std::get<1>(prevPoint));
354  float xPrevToCur = (std::get<0>(curPoint) - std::get<0>(prevPoint));
355  float yPrevToCur = (std::get<1>(curPoint) - std::get<1>(prevPoint));
356  float edgeLength = std::sqrt(xPrevToCur * xPrevToCur + yPrevToCur * yPrevToCur);
357 
358  // Find projection onto convex hull edge
359  float projection = ((xPrevToPoint * xPrevToCur) + (yPrevToPoint * yPrevToCur)) / edgeLength;
360 
361  // DOCA point
362  Point docaPoint(std::get<0>(prevPoint) + projection * xPrevToCur / edgeLength,
363  std::get<1>(prevPoint) + projection * yPrevToCur / edgeLength, 0);
364 
365  if (projection > edgeLength) docaPoint = curPoint;
366  if (projection < 0) docaPoint = prevPoint;
367 
368  float xDocaDist = std::get<0>(point) - std::get<0>(docaPoint);
369  float yDocaDist = std::get<1>(point) - std::get<1>(docaPoint);
370  float docaDist = xDocaDist * xDocaDist + yDocaDist * yDocaDist;
371 
372  if (docaDist < closestDistance)
373  {
374  closestEdge = PointPair(prevPoint,curPoint);
375  closestDistance = docaDist;
376  }
377  }
378 
379  prevPoint = curPoint;
380  curPoint = *curPointItr++;
381  }
382 
383  closestDistance = std::sqrt(closestDistance);
384 
385  // Convention is convex hull vertices sorted in counter clockwise fashion so if the point
386  // lays to the left of the nearest edge then it must be an interior point
387  if (isLeft(closestEdge.first,closestEdge.second,point)) closestDistance = -closestDistance;
388 
389  return closestEdge;
390 }
std::pair< Point, Point > PointPair
Definition: ConvexHull.h:35
intermediate_table::const_iterator const_iterator
static int max(int a, int b)
bool isLeft(const Point &p0, const Point &p1, const Point &pCheck) const
Determines whether a point is to the left, right or on line specifiec by p0 and p1.
Definition: ConvexHull.cxx:49
const PointList& lar_cluster3d::ConvexHull::getConvexHull ( ) const
inline

recover the list of convex hull vertices

Definition at line 58 of file ConvexHull.h.

58 {return fConvexHull;}
void lar_cluster3d::ConvexHull::getConvexHull ( const PointList pointList)
private

Given an input set of 2D points build a convex hull around them.

Parameters
PointListThe input list of 2D points to build hull around

Definition at line 107 of file ConvexHull.cxx.

108 {
109  // Start by identifying the min/max points
110  Point pMinMin = pointList.front();
111 
112  // Find the point with maximum y sharing the same x value...
113  PointList::const_iterator pMinMaxItr = std::find_if(pointList.begin(),pointList.end(),[pMinMin](const auto& elem){return std::get<0>(elem) != std::get<0>(pMinMin);});
114 
115  Point pMinMax = *(--pMinMaxItr); // This could be / probably is the same point
116 
117  fMinMaxPointPair.first.first = pMinMin;
118  fMinMaxPointPair.first.second = pMinMax;
119 
120  Point pMaxMax = pointList.back(); // get the last point
121 
122  // Find the point with minimum y sharing the same x value...
123  PointList::const_reverse_iterator pMaxMinItr = std::find_if(pointList.rbegin(),pointList.rend(),[pMaxMax](const auto& elem){return std::get<0>(elem) != std::get<0>(pMaxMax);});
124 
125  Point pMaxMin = *(--pMaxMinItr); // This could be / probably is the same point
126 
127  fMinMaxPointPair.second.first = pMaxMin;
128  fMinMaxPointPair.second.second = pMaxMax;
129 
130  // Get the lower convex hull
131  PointList lowerHullList;
132 
133  lowerHullList.push_back(pMinMin);
134 
135  // loop over points in the set
136  for(auto curPoint : pointList)
137  {
138  // First check that we even want to consider this point
139  if (isLeft(pMinMin,pMaxMin,curPoint)) continue;
140 
141  // In words: treat "lowerHullVec" as a stack. If there is only one entry then
142  // push the current point onto the stack. If more than one entry then check if
143  // the current point is to the left of the line from the last two points in the
144  // stack. If it is then add the current point to the stack, if it is not then
145  // pop the last point off the stack and try again.
146  while(lowerHullList.size() > 1)
147  {
148  Point lastPoint = lowerHullList.back();
149 
150  lowerHullList.pop_back();
151 
152  Point nextToLastPoint = lowerHullList.back();
153 
154  if (isLeft(nextToLastPoint,lastPoint,curPoint))
155  {
156  lowerHullList.push_back(lastPoint);
157  break;
158  }
159  }
160 
161  lowerHullList.push_back(curPoint);
162  }
163 
164  // Now get the upper hull
165  PointList upperHullList;
166 
167  upperHullList.push_back(pMaxMax);
168 
169  for(auto curPoint : boost::adaptors::reverse(pointList))
170  {
171  // First check that we even want to consider this point
172  // Remember that we are going "backwards" so still want
173  // curPoint to lie to the "left"
174  if (isLeft(pMaxMax,pMinMax,curPoint)) continue;
175 
176  // Replicate the above but going the other direction...
177  while(upperHullList.size() > 1)
178  {
179  Point lastPoint = upperHullList.back();
180 
181  upperHullList.pop_back();
182 
183  Point nextToLastPoint = upperHullList.back();
184 
185  if (isLeft(nextToLastPoint,lastPoint,curPoint))
186  {
187  upperHullList.push_back(lastPoint);
188  break;
189  }
190  }
191 
192  upperHullList.push_back(curPoint);
193  }
194 
195  // Now we merge the two lists into the output list
196  std::copy(lowerHullList.begin(),lowerHullList.end(),std::back_inserter(fConvexHull));
197 
198  if (pMaxMin == pMaxMax) upperHullList.pop_front();
199 
200  std::copy(upperHullList.begin(),upperHullList.end(),std::back_inserter(fConvexHull));
201 
202  if (pMinMin != pMinMax) fConvexHull.push_back(pMinMin);
203 
204  return;
205 }
MinMaxPointPair fMinMaxPointPair
Definition: ConvexHull.h:119
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:34
intermediate_table::const_iterator const_iterator
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
bool isLeft(const Point &p0, const Point &p1, const Point &pCheck) const
Determines whether a point is to the left, right or on line specifiec by p0 and p1.
Definition: ConvexHull.cxx:49
T copy(T const &v)
float lar_cluster3d::ConvexHull::getConvexHullArea ( ) const
inline

recover the area of the convex hull

Definition at line 78 of file ConvexHull.h.

78 {return fConvexHullArea;}
const ConvexHull::PointList & lar_cluster3d::ConvexHull::getExtremePoints ( )

Find the two points on the hull which are furthest apart.

Definition at line 207 of file ConvexHull.cxx.

208 {
209  PointList::const_iterator nextPointItr = fConvexHull.begin();
210  PointList::const_iterator firstPointItr = nextPointItr++;
211 
212  float maxSeparation(0.);
213 
214  // Make sure the current list has been cleared
215  fExtremePoints.clear();
216 
217  // For finding the two farthest points
218  PointPair extremePoints(Point(0,0,NULL),Point(0,0,NULL));
219 
220  while(nextPointItr != fConvexHull.end())
221  {
222  // Get a vector representing the edge from the first to the current next point
223  Point firstPoint = *firstPointItr++;
224  Point nextPoint = *nextPointItr;
225  Eigen::Vector2f firstEdge(std::get<0>(*firstPointItr) - std::get<0>(firstPoint), std::get<1>(*firstPointItr) - std::get<1>(firstPoint));
226 
227  // normalize it
228  firstEdge.normalize();
229 
230  PointList::const_iterator endPointItr = nextPointItr;
231 
232  while(++endPointItr != fConvexHull.end())
233  {
234  Point endPoint = *endPointItr;
235  Eigen::Vector2f nextEdge(std::get<0>(endPoint) - std::get<0>(nextPoint), std::get<1>(endPoint) - std::get<1>(nextPoint));
236 
237  // normalize it
238  nextEdge.normalize();
239 
240  // Have we found the turnaround point?
241  if (firstEdge.dot(nextEdge) < 0.)
242  {
243  Eigen::Vector2f separation(std::get<0>(nextPoint) - std::get<0>(firstPoint), std::get<1>(nextPoint) - std::get<1>(firstPoint));
244  float separationDistance = separation.norm();
245 
246  if (separationDistance > maxSeparation)
247  {
248  extremePoints.first = firstPoint;
249  extremePoints.second = nextPoint;
250  maxSeparation = separationDistance;
251  }
252 
253  // Regardless of thise being the maximum distance we have hit a turnaround point so
254  // we need to break out of this loop
255  break;
256  }
257 
258  nextPointItr = endPointItr;
259  nextPoint = endPoint;
260  }
261 
262  // If we have hit the end of the convex hull without finding a turnaround point then we are not
263  // going to find one so break out of the main loop
264  if (endPointItr == fConvexHull.end()) break;
265 
266  // Need to make sure we don't overrun the next point
267  if (firstPointItr == nextPointItr) nextPointItr++;
268  }
269 
270  fExtremePoints.push_back(extremePoints.first);
271  fExtremePoints.push_back(extremePoints.second);
272 
273  return fExtremePoints;
274 }
std::pair< Point, Point > PointPair
Definition: ConvexHull.h:35
intermediate_table::const_iterator const_iterator
std::tuple< float, float, const reco::ClusterHit3D * > Point
projected x,y position and 3D hit
Definition: ConvexHull.h:33
const reco::ConvexHullKinkTupleList & lar_cluster3d::ConvexHull::getKinkPoints ( )

Find the points with the largest angles.

Definition at line 276 of file ConvexHull.cxx.

277 {
278  // Goal here is to isolate the points where we see a large deviation in the contour defined by the
279  // convex hull. The complications are numerous, chief is that some deviations can be artificially
280  // "rounded" by a series of very small steps around a large corner. So we need to protect against that.
281 
282  // Make sure the current list has been cleared
283  fKinkPoints.clear();
284 
285  // Need a mininum number of points/edges
286  if (fConvexHull.size() > 3)
287  {
288  // Idea will be to traverse the convex hull and keep track of all points where there is a
289  // "kink" which will be defined as a "large" angle between adjacent edges.
290  // Recall that construxtion of the convex hull results in the same point at the start and
291  // end of the list
292  // Getting the initial point requires some contortions because the convex hull point list will
293  // contain the same point at both ends of the list (why?)
294  PointList::iterator pointItr = fConvexHull.begin();
295 
296  // Advance to the second to last element
297  std::advance(pointItr, fConvexHull.size() - 2);
298 
299  Point lastPoint = *pointItr++;
300 
301  // Reset pointer to the first element
302  pointItr = fConvexHull.begin();
303 
304  Point curPoint = *pointItr++;
305  Eigen::Vector2f lastEdge(std::get<0>(curPoint) - std::get<0>(lastPoint), std::get<1>(curPoint) - std::get<1>(lastPoint));
306 
307  lastEdge.normalize();
308 
309  while(pointItr != fConvexHull.end())
310  {
311  Point& nextPoint = *pointItr++;
312 
313  Eigen::Vector2f nextEdge(std::get<0>(nextPoint) - std::get<0>(curPoint), std::get<1>(nextPoint) - std::get<1>(curPoint));
314 
315  if (nextEdge.norm() > fMinEdgeDistance)
316  {
317  nextEdge.normalize();
318 
319  if (lastEdge.dot(nextEdge) < fKinkAngle) fKinkPoints.emplace_back(curPoint,lastEdge,nextEdge);
320 
321  lastEdge = nextEdge;
322  }
323 
324  curPoint = nextPoint;
325  }
326  }
327 
328  return fKinkPoints;
329 }
intermediate_table::iterator iterator
reco::ConvexHullKinkTupleList fKinkPoints
Definition: ConvexHull.h:122
const MinMaxPointPair& lar_cluster3d::ConvexHull::getMinMaxPointPair ( ) const
inline

find the ends of the convex hull (along its x axis)

Definition at line 63 of file ConvexHull.h.

63 {return fMinMaxPointPair;}
MinMaxPointPair fMinMaxPointPair
Definition: ConvexHull.h:119
const PointList& lar_cluster3d::ConvexHull::getPointsList ( )
inline

recover the list of points used to build convex hull

Definition at line 53 of file ConvexHull.h.

53 {return fPoints;}
const PointList & fPoints
Definition: ConvexHull.h:117
bool lar_cluster3d::ConvexHull::isLeft ( const Point p0,
const Point p1,
const Point pCheck 
) const
private

Determines whether a point is to the left, right or on line specifiec by p0 and p1.

Definition at line 49 of file ConvexHull.cxx.

50 {
51  // Use the cross product to determine if the check point lies to the left, on or right
52  // of the line defined by points p0 and p1
53  return crossProduct(p0, p1, pCheck) > 0;
54 }
float crossProduct(const Point &p0, const Point &p1, const Point &p2) const
Gets the cross product of line from p0 to p1 and p0 to p2.
Definition: ConvexHull.cxx:58

Member Data Documentation

PointList lar_cluster3d::ConvexHull::fConvexHull
private

Definition at line 118 of file ConvexHull.h.

float lar_cluster3d::ConvexHull::fConvexHullArea
private

Definition at line 120 of file ConvexHull.h.

PointList lar_cluster3d::ConvexHull::fExtremePoints
private

Definition at line 121 of file ConvexHull.h.

float lar_cluster3d::ConvexHull::fKinkAngle
private

Definition at line 114 of file ConvexHull.h.

reco::ConvexHullKinkTupleList lar_cluster3d::ConvexHull::fKinkPoints
private

Definition at line 122 of file ConvexHull.h.

float lar_cluster3d::ConvexHull::fMinEdgeDistance
private

Definition at line 115 of file ConvexHull.h.

MinMaxPointPair lar_cluster3d::ConvexHull::fMinMaxPointPair
private

Definition at line 119 of file ConvexHull.h.

const PointList& lar_cluster3d::ConvexHull::fPoints
private

Definition at line 117 of file ConvexHull.h.


The documentation for this class was generated from the following files: