LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
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...
 
virtual ~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 25 of file ConvexHull.h.

Member Typedef Documentation

Definition at line 34 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 31 of file ConvexHull.h.

The list of the projected points.

Definition at line 32 of file ConvexHull.h.

Definition at line 33 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 31 of file ConvexHull.cxx.

References Area(), fConvexHull, fConvexHullArea, fPoints, and getConvexHull().

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

Destructor.

Definition at line 45 of file ConvexHull.cxx.

46 {
47 }

Member Function Documentation

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

Computes the area of the enclosed convext hull.

Definition at line 73 of file ConvexHull.cxx.

References crossProduct(), fConvexHull, n, x, and y.

Referenced by ConvexHull(), and getConvexHullArea().

74 {
75  float area(0.);
76 
77  // Compute the area by taking advantage of
78  // 1) the ability to decompose a convex hull into triangles,
79  // 2) the ability to use the cross product to calculate the area
80  // So, the technique is to pick a point which we take as the center of the polygon
81  // and then sum the signed area of triangles formed from this point to two adjecent
82  // vertices on the convex hull.
83  float x = 0.;
84  float y = 0.;
85  float n = float(fConvexHull.size());
86 
87  for(const auto& point : fConvexHull)
88  {
89  x += std::get<0>(point);
90  y += std::get<1>(point);
91  }
92 
93  Point center(x/n,y/n,0);
94 
95  Point lastPoint = fConvexHull.front();
96 
97  for(const auto& point : fConvexHull)
98  {
99  if (point != lastPoint) area += 0.5 * crossProduct(center,lastPoint,point);
100 
101  lastPoint = point;
102  }
103 
104  return area;
105 }
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
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:60
std::tuple< float, float, const reco::ClusterHit3D * > Point
projected x,y position and 3D hit
Definition: ConvexHull.h:31
Char_t n[5]
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 60 of file ConvexHull.cxx.

Referenced by Area(), getConvexHullArea(), and isLeft().

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

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

Definition at line 394 of file ConvexHull.cxx.

References findNearestEdge().

Referenced by getConvexHullArea().

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

Given an input Point, find the nearest edge.

Definition at line 333 of file ConvexHull.cxx.

References fConvexHull, isLeft(), and max.

Referenced by findNearestDistance(), and getConvexHullArea().

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

References fConvexHull, fMinMaxPointPair, and isLeft().

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

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

Definition at line 209 of file ConvexHull.cxx.

References fConvexHull, and fExtremePoints.

Referenced by getMinMaxPointPair().

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

Find the points with the largest angles.

Definition at line 278 of file ConvexHull.cxx.

References fConvexHull, fKinkAngle, fKinkPoints, and fMinEdgeDistance.

Referenced by getMinMaxPointPair().

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

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

Definition at line 61 of file ConvexHull.h.

References fMinMaxPointPair, getExtremePoints(), and getKinkPoints().

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

recover the list of points used to build convex hull

Definition at line 51 of file ConvexHull.h.

References fPoints.

51 {return fPoints;}
const PointList & fPoints
Definition: ConvexHull.h:115
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 51 of file ConvexHull.cxx.

References crossProduct().

Referenced by findNearestEdge(), getConvexHull(), and getConvexHullArea().

52 {
53  // Use the cross product to determine if the check point lies to the left, on or right
54  // of the line defined by points p0 and p1
55  return crossProduct(p0, p1, pCheck) > 0;
56 }
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:60

Member Data Documentation

PointList lar_cluster3d::ConvexHull::fConvexHull
private
float lar_cluster3d::ConvexHull::fConvexHullArea
private

Definition at line 118 of file ConvexHull.h.

Referenced by ConvexHull(), and getConvexHullArea().

PointList lar_cluster3d::ConvexHull::fExtremePoints
private

Definition at line 119 of file ConvexHull.h.

Referenced by getExtremePoints().

float lar_cluster3d::ConvexHull::fKinkAngle
private

Definition at line 112 of file ConvexHull.h.

Referenced by getKinkPoints().

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

Definition at line 120 of file ConvexHull.h.

Referenced by getKinkPoints().

float lar_cluster3d::ConvexHull::fMinEdgeDistance
private

Definition at line 113 of file ConvexHull.h.

Referenced by getKinkPoints().

MinMaxPointPair lar_cluster3d::ConvexHull::fMinMaxPointPair
private

Definition at line 117 of file ConvexHull.h.

Referenced by getConvexHull(), and getMinMaxPointPair().

const PointList& lar_cluster3d::ConvexHull::fPoints
private

Definition at line 115 of file ConvexHull.h.

Referenced by ConvexHull(), and getPointsList().


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