LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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...
 
 ~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 26 of file ConvexHull.h.

Member Typedef Documentation

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

The list of the projected points.

Definition at line 33 of file ConvexHull.h.

Definition at line 34 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.

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

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

Destructor.

Definition at line 46 of file ConvexHull.cxx.

46 {}

Member Function Documentation

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

Computes the area of the enclosed convext hull.

Definition at line 72 of file ConvexHull.cxx.

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

Referenced by ConvexHull(), and getConvexHullArea().

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

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

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

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

Definition at line 389 of file ConvexHull.cxx.

References findNearestEdge().

Referenced by getConvexHullArea().

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

Given an input Point, find the nearest edge.

Definition at line 329 of file ConvexHull.cxx.

References fConvexHull, and isLeft().

Referenced by findNearestDistance(), and getConvexHullArea().

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

References fConvexHull, fMinMaxPointPair, and isLeft().

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

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

Definition at line 206 of file ConvexHull.cxx.

References fConvexHull, and fExtremePoints.

Referenced by getMinMaxPointPair().

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

Find the points with the largest angles.

Definition at line 274 of file ConvexHull.cxx.

References fConvexHull, fKinkAngle, fKinkPoints, and fMinEdgeDistance.

Referenced by getMinMaxPointPair().

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

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

62 { 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 52 of file ConvexHull.h.

References fPoints.

52 { 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 50 of file ConvexHull.cxx.

References crossProduct().

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

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

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: