LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
voronoi2d::VoronoiDiagram Class Reference

VoronoiDiagram class definiton. More...

#include "Voronoi.h"

Public Types

using PointPair = std::pair< dcel2d::Point, dcel2d::Point >
 
using MinMaxPointPair = std::pair< PointPair, PointPair >
 

Public Member Functions

 VoronoiDiagram (dcel2d::HalfEdgeList &, dcel2d::VertexList &, dcel2d::FaceList &)
 Constructor. More...
 
 ~VoronoiDiagram ()
 Destructor. More...
 
void buildVoronoiDiagram (const dcel2d::PointList &)
 Given an input set of 2D points construct a 2D voronoi diagram. More...
 
void buildVoronoiDiagramBoost (const dcel2d::PointList &)
 
const dcel2d::FaceListgetFaceList () const
 Recover the list of faces. More...
 
const dcel2d::VertexListgetVertexList () const
 Recover the list of vertices. More...
 
double getVoronoiDiagramArea () const
 recover the area of the convex hull More...
 
const dcel2d::PointListgetConvexHull () const
 recover the point list representing the convex hull More...
 
PointPair getExtremePoints () const
 Given an input Point, find the nearest edge. More...
 
PointPair findNearestEdge (const dcel2d::Point &, double &) const
 Given an input Point, find the nearest edge. More...
 
double findNearestDistance (const dcel2d::Point &) const
 Given an input point, find the distance to the nearest edge/point. More...
 

Private Types

using EventQueue = std::priority_queue< IEvent *, std::vector< IEvent * >, bool(*)(const IEvent *, const IEvent *)>
 
using BoostEdgeToEdgeMap = std::map< const boost::polygon::voronoi_edge< double > *, dcel2d::HalfEdge * >
 Translate boost to dcel. More...
 
using BoostVertexToVertexMap = std::map< const boost::polygon::voronoi_vertex< double > *, dcel2d::Vertex * >
 
using BoostCellToFaceMap = std::map< const boost::polygon::voronoi_cell< double > *, dcel2d::Face * >
 

Private Member Functions

void handleSiteEvents (BeachLine &, EventQueue &, IEvent *)
 There are two types of events in the queue, here we handle site events. More...
 
void handleCircleEvents (BeachLine &, EventQueue &, IEvent *)
 There are two types of events in the queue, here we handle circle events. More...
 
void makeLeftCircleEvent (EventQueue &, BSTNode *, double)
 
void makeRightCircleEvent (EventQueue &, BSTNode *, double)
 
IEventmakeCircleEvent (BSTNode *, BSTNode *, BSTNode *, double)
 There are two types of events in the queue, here we handle circle events. More...
 
bool computeCircleCenter (const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &, double &) const
 
bool computeCircleCenter2 (const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &) const
 
bool computeCircleCenter3 (const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &) const
 
void getConvexHull (const BSTNode *)
 this function recovers the convex hull More...
 
void terminateInfiniteEdges (BeachLine &, double)
 this aims to process remaining elements in the beachline after the event queue has been depleted More...
 
bool isInsideConvexHull (const dcel2d::Vertex &) const
 Is a vertex inside the convex hull - meant to be a fast check. More...
 
bool isOutsideConvexHull (const dcel2d::Vertex &, dcel2d::PointList::const_iterator, dcel2d::Coords &, double &) const
 is vertex outside the convex hull and if so return some useful information More...
 
void findBoundingBox (const dcel2d::VertexList &)
 Find the min/max values in x-y to use as a bounding box. More...
 
void boostTranslation (const dcel2d::PointList &, const boost::polygon::voronoi_edge< double > *, const boost::polygon::voronoi_edge< double > *, BoostEdgeToEdgeMap &, BoostVertexToVertexMap &, BoostCellToFaceMap &)
 
void mergeDegenerateVertices ()
 merge degenerate vertices (found by zero length edges) More...
 
double ComputeFaceArea ()
 Compute the area of the faces. More...
 
double crossProduct (const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &p2) const
 Gets the cross product of line from p0 to p1 and p0 to p2. More...
 
double Area () const
 Computes the area of the enclosed convext hull. More...
 
bool isLeft (const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &pCheck) const
 Determines whether a point is to the left, right or on line specifiec by p0 and p1. More...
 

Private Attributes

dcel2d::HalfEdgeListfHalfEdgeList
 
dcel2d::VertexListfVertexList
 
dcel2d::FaceListfFaceList
 
dcel2d::PointList fPointList
 
SiteEventList fSiteEventList
 
CircleEventList fCircleEventList
 
BSTNodeList fCircleNodeList
 
dcel2d::PointList fConvexHullList
 
dcel2d::Coords fConvexHullCenter
 
double fXMin
 
double fXMax
 
double fYMin
 
double fYMax
 
int fNumBadCircles
 
double fVoronoiDiagramArea
 
EventUtilities fUtilities
 

Detailed Description

VoronoiDiagram class definiton.

Definition at line 30 of file Voronoi.h.

Member Typedef Documentation

using voronoi2d::VoronoiDiagram::BoostCellToFaceMap = std::map<const boost::polygon::voronoi_cell<double>*, dcel2d::Face*>
private

Definition at line 167 of file Voronoi.h.

using voronoi2d::VoronoiDiagram::BoostEdgeToEdgeMap = std::map<const boost::polygon::voronoi_edge<double>*, dcel2d::HalfEdge*>
private

Translate boost to dcel.

Definition at line 164 of file Voronoi.h.

using voronoi2d::VoronoiDiagram::BoostVertexToVertexMap = std::map<const boost::polygon::voronoi_vertex<double>*, dcel2d::Vertex*>
private

Definition at line 166 of file Voronoi.h.

using voronoi2d::VoronoiDiagram::EventQueue = std::priority_queue<IEvent*, std::vector<IEvent*>, bool (*)(const IEvent*, const IEvent*)>
private

Definition at line 93 of file Voronoi.h.

Definition at line 33 of file Voronoi.h.

Definition at line 32 of file Voronoi.h.

Constructor & Destructor Documentation

voronoi2d::VoronoiDiagram::VoronoiDiagram ( dcel2d::HalfEdgeList halfEdgeList,
dcel2d::VertexList vertexList,
dcel2d::FaceList faceList 
)

Constructor.

Parameters
pset

Definition at line 47 of file Voronoi.cxx.

References Area(), fCircleEventList, fCircleNodeList, fConvexHullList, fFaceList, fHalfEdgeList, fPointList, fSiteEventList, fVertexList, and fVoronoiDiagramArea.

50  : fHalfEdgeList(halfEdgeList)
51  , fVertexList(vertexList)
52  , fFaceList(faceList)
53  , fXMin(0.)
54  , fXMax(0.)
55  , fYMin(0.)
56  , fYMax(0.)
58  {
59  fHalfEdgeList.clear();
60  fVertexList.clear();
61  fFaceList.clear();
62  fPointList.clear();
63  fSiteEventList.clear();
64  fCircleEventList.clear();
65  fCircleNodeList.clear();
66  fConvexHullList.clear();
67 
68  // And the area
70  }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
double Area() const
Computes the area of the enclosed convext hull.
Definition: Voronoi.cxx:104
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
BSTNodeList fCircleNodeList
Definition: Voronoi.h:212
CircleEventList fCircleEventList
Definition: Voronoi.h:211
SiteEventList fSiteEventList
Definition: Voronoi.h:210
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
dcel2d::PointList fPointList
Definition: Voronoi.h:209
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
voronoi2d::VoronoiDiagram::~VoronoiDiagram ( )

Destructor.

Definition at line 74 of file Voronoi.cxx.

74 {}

Member Function Documentation

double voronoi2d::VoronoiDiagram::Area ( ) const
private

Computes the area of the enclosed convext hull.

Definition at line 104 of file Voronoi.cxx.

References crossProduct(), and fPointList.

Referenced by VoronoiDiagram().

105  {
106  double area(0.);
107 
108  // Compute the area by taking advantage of
109  // 1) the ability to decompose a convex hull into triangles,
110  // 2) the ability to use the cross product to calculate the area
111  // So, the technique is to pick a point (for technical reasons we use 0,0)
112  // and then sum the signed area of triangles formed from this point to two adjecent
113  // vertices on the convex hull.
114  dcel2d::Point center(0., 0., NULL);
115  dcel2d::Point lastPoint = fPointList.front();
116 
117  for (const auto& point : fPointList) {
118  if (point != lastPoint) area += 0.5 * crossProduct(center, lastPoint, point);
119 
120  lastPoint = point;
121  }
122 
123  return area;
124  }
dcel2d::PointList fPointList
Definition: Voronoi.h:209
double crossProduct(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &p2) const
Gets the cross product of line from p0 to p1 and p0 to p2.
Definition: Voronoi.cxx:89
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
void voronoi2d::VoronoiDiagram::boostTranslation ( const dcel2d::PointList pointList,
const boost::polygon::voronoi_edge< double > *  edge,
const boost::polygon::voronoi_edge< double > *  twin,
BoostEdgeToEdgeMap boostEdgeToEdgeMap,
BoostVertexToVertexMap boostVertexToVertexMap,
BoostCellToFaceMap boostCellToFaceMap 
)
private

Definition at line 355 of file Voronoi.cxx.

References fFaceList, fHalfEdgeList, fVertexList, dcel2d::HalfEdge::setFace(), dcel2d::HalfEdge::setLastHalfEdge(), dcel2d::HalfEdge::setNextHalfEdge(), dcel2d::HalfEdge::setTargetVertex(), and dcel2d::HalfEdge::setTwinHalfEdge().

Referenced by buildVoronoiDiagramBoost().

361  {
362  dcel2d::HalfEdge* halfEdge = NULL;
363  dcel2d::HalfEdge* twinEdge = NULL;
364 
365  if (boostEdgeToEdgeMap.find(edge) != boostEdgeToEdgeMap.end())
366  halfEdge = boostEdgeToEdgeMap.at(edge);
367  else {
368  fHalfEdgeList.emplace_back();
369 
370  halfEdge = &fHalfEdgeList.back();
371 
372  boostEdgeToEdgeMap[edge] = halfEdge;
373  }
374 
375  if (boostEdgeToEdgeMap.find(twin) != boostEdgeToEdgeMap.end())
376  twinEdge = boostEdgeToEdgeMap.at(twin);
377  else {
378  fHalfEdgeList.emplace_back();
379 
380  twinEdge = &fHalfEdgeList.back();
381 
382  boostEdgeToEdgeMap[twin] = twinEdge;
383  }
384 
385  // Do the primary half edge first
386  const boost::polygon::voronoi_vertex<double>* boostVertex = edge->vertex1();
387  dcel2d::Vertex* vertex = NULL;
388 
389  // note we can have a null vertex (infinite edge)
390  if (boostVertex) {
391  if (boostVertexToVertexMap.find(boostVertex) == boostVertexToVertexMap.end()) {
392  dcel2d::Coords coords(boostVertex->y(), boostVertex->x(), 0.);
393 
394  fVertexList.emplace_back(coords, halfEdge);
395 
396  vertex = &fVertexList.back();
397 
398  boostVertexToVertexMap[boostVertex] = vertex;
399  }
400  else
401  vertex = boostVertexToVertexMap.at(boostVertex);
402  }
403 
404  const boost::polygon::voronoi_cell<double>* boostCell = edge->cell();
405  dcel2d::Face* face = NULL;
406 
407  if (boostCellToFaceMap.find(boostCell) == boostCellToFaceMap.end()) {
408  dcel2d::PointList::const_iterator pointItr = pointList.begin();
409  int pointIdx = boostCell->source_index();
410 
411  std::advance(pointItr, pointIdx);
412 
413  const dcel2d::Point& point = *pointItr;
414  dcel2d::Coords coords(std::get<0>(point), std::get<1>(point), 0.);
415 
416  fFaceList.emplace_back(halfEdge, coords, std::get<2>(point));
417 
418  face = &fFaceList.back();
419 
420  boostCellToFaceMap[boostCell] = face;
421  }
422 
423  halfEdge->setTargetVertex(vertex);
424  halfEdge->setFace(face);
425  halfEdge->setTwinHalfEdge(twinEdge);
426 
427  // For the prev/next half edges we can have two cases, so check:
428  if (boostEdgeToEdgeMap.find(edge->next()) != boostEdgeToEdgeMap.end()) {
429  dcel2d::HalfEdge* nextEdge = boostEdgeToEdgeMap.at(edge->next());
430 
431  halfEdge->setNextHalfEdge(nextEdge);
432  nextEdge->setLastHalfEdge(halfEdge);
433  }
434 
435  if (boostEdgeToEdgeMap.find(edge->prev()) != boostEdgeToEdgeMap.end()) {
436  dcel2d::HalfEdge* lastEdge = boostEdgeToEdgeMap.at(edge->prev());
437 
438  halfEdge->setLastHalfEdge(lastEdge);
439  lastEdge->setNextHalfEdge(halfEdge);
440  }
441 
442  return;
443  }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
intermediate_table::const_iterator const_iterator
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
void setLastHalfEdge(HalfEdge *last)
Definition: DCEL.h:158
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:156
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
void setFace(Face *face)
Definition: DCEL.h:155
void setNextHalfEdge(HalfEdge *next)
Definition: DCEL.h:157
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
Eigen::Vector3f Coords
Definition: DCEL.h:44
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:154
vertex reconstruction
void voronoi2d::VoronoiDiagram::buildVoronoiDiagram ( const dcel2d::PointList pointList)

Given an input set of 2D points construct a 2D voronoi diagram.

Parameters
PointListThe input list of 2D points

Definition at line 135 of file Voronoi.cxx.

References voronoi2d::compareSiteEventPtrs(), voronoi2d::BeachLine::countLeaves(), fCircleEventList, fCircleNodeList, fFaceList, fHalfEdgeList, findBoundingBox(), fNumBadCircles, fPointList, fSiteEventList, fVertexList, fXMax, fXMin, fYMax, fYMin, dcel2d::HalfEdge::getFace(), dcel2d::HalfEdge::getLastHalfEdge(), dcel2d::HalfEdge::getNextHalfEdge(), handleCircleEvents(), handleSiteEvents(), terminateInfiniteEdges(), and voronoi2d::BeachLine::traverseBeach().

Referenced by lar_cluster3d::ClusterPathFinder::buildVoronoiDiagram(), and lar_cluster3d::VoronoiPathFinder::buildVoronoiDiagram().

136  {
137  // Insure all the local data structures have been cleared
138  fHalfEdgeList.clear();
139  fVertexList.clear();
140  fFaceList.clear();
141  fPointList.clear();
142  fSiteEventList.clear();
143  fCircleEventList.clear();
144  fCircleNodeList.clear();
145  fNumBadCircles = 0;
146 
147  std::cout << "*********************************************************************************"
148  "*********************************"
149  << std::endl;
150  std::cout << "*********************************************************************************"
151  "*********************************"
152  << std::endl;
153  std::cout << "*********************************************************************************"
154  "*********************************"
155  << std::endl;
156  std::cout << "==> # input points: " << pointList.size() << std::endl;
157 
158  // Define the priority queue to contain our events
159  EventQueue eventQueue(compareSiteEventPtrs);
160 
161  // Now populate the event queue with site events
162  for (const auto& point : pointList) {
163  fSiteEventList.emplace_back(point);
164  IEvent* iEvent = &fSiteEventList.back();
165  eventQueue.push(iEvent);
166  }
167 
168  // Declare the beachline which will contain the BSTNode objects for site events
169  BeachLine beachLine;
170 
171  // Finally, we need a container for our circle event BSTNodes
172  BSTNodeList circleNodeList;
173 
174  // Now process the queue
175  while (!eventQueue.empty()) {
176  IEvent* event = eventQueue.top();
177 
178  eventQueue.pop();
179 
180  // If a site or circle event then handle appropriately
181  if (event->isSite())
182  handleSiteEvents(beachLine, eventQueue, event);
183  else if (event->isValid())
184  handleCircleEvents(beachLine, eventQueue, event);
185  }
186 
187  std::cout << "*******> # input points: " << pointList.size()
188  << ", remaining leaves: " << beachLine.countLeaves() << ", "
189  << beachLine.traverseBeach() << ", # bad circles: " << fNumBadCircles << std::endl;
190  std::cout << " Faces: " << fFaceList.size() << ", Vertices: " << fVertexList.size()
191  << ", # half edges: " << fHalfEdgeList.size() << std::endl;
192 
193  // Get the bounding box
195 
196  std::cout << " Range min/maxes, x: " << fXMin << ", " << fXMax << ", y: " << fYMin
197  << ", " << fYMax << std::endl;
198 
199  // Terminate the infinite edges
200  terminateInfiniteEdges(beachLine, std::get<0>(pointList.front()));
201 
202  // Look for open faces
203  int nOpenFaces(0);
204 
205  std::map<int, int> edgeCountMap;
206  std::map<int, int> openCountMap;
207 
208  for (const auto& face : fFaceList) {
209  int nEdges(1);
210  bool closed(false);
211  const dcel2d::HalfEdge* startEdge = face.getHalfEdge();
212 
213  // Count forwards
214  for (const dcel2d::HalfEdge* halfEdge = startEdge->getNextHalfEdge(); halfEdge && !closed;) {
215  if (halfEdge->getFace() != &face) {
216  std::cout << " ===> halfEdge does not match face: " << halfEdge
217  << ", face: " << halfEdge->getFace() << ", base: " << &face << std::endl;
218  }
219 
220  if (halfEdge == startEdge) {
221  closed = true;
222  break;
223  }
224  nEdges++;
225  halfEdge = halfEdge->getNextHalfEdge();
226  }
227 
228  // Count backwards. Note if face is closed then nothing to do here
229  if (!closed) {
230  for (const dcel2d::HalfEdge* halfEdge = startEdge->getLastHalfEdge();
231  halfEdge && !closed;) {
232  if (halfEdge->getFace() != &face) {
233  std::cout << " ===> halfEdge does not match face: " << halfEdge
234  << ", face: " << halfEdge->getFace() << ", base: " << &face << std::endl;
235  }
236 
237  if (halfEdge == startEdge) {
238  closed = true;
239  break;
240  }
241  nEdges++;
242  halfEdge = halfEdge->getLastHalfEdge();
243  }
244  }
245 
246  if (!closed) {
247  nOpenFaces++;
248  openCountMap[nEdges]++;
249  }
250 
251  edgeCountMap[nEdges]++;
252  }
253 
254  std::cout << "==> Found " << nOpenFaces << " open faces from total of " << fFaceList.size()
255  << std::endl;
256  for (const auto& edgeCount : edgeCountMap)
257  std::cout << " -> all edges, # edges: " << edgeCount.first
258  << ", count: " << edgeCount.second << std::endl;
259  for (const auto& edgeCount : openCountMap)
260  std::cout << " -> open edges, # edges: " << edgeCount.first
261  << ", count: " << edgeCount.second << std::endl;
262  std::cout << "*********************************************************************************"
263  "*********************************"
264  << std::endl;
265  std::cout << "*********************************************************************************"
266  "*********************************"
267  << std::endl;
268  std::cout << "*********************************************************************************"
269  "*********************************"
270  << std::endl;
271 
272  // Clear internal containers that are no longer useful
273  fSiteEventList.clear();
274  fCircleEventList.clear();
275  fCircleNodeList.clear();
276 
277  return;
278  }
HalfEdge * getLastHalfEdge() const
Definition: DCEL.h:152
HalfEdge * getNextHalfEdge() const
Definition: DCEL.h:151
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
Face * getFace() const
Definition: DCEL.h:149
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
std::list< BSTNode > BSTNodeList
Definition: BeachLine.h:118
BSTNodeList fCircleNodeList
Definition: Voronoi.h:212
void handleCircleEvents(BeachLine &, EventQueue &, IEvent *)
There are two types of events in the queue, here we handle circle events.
Definition: Voronoi.cxx:503
CircleEventList fCircleEventList
Definition: Voronoi.h:211
SiteEventList fSiteEventList
Definition: Voronoi.h:210
bool compareSiteEventPtrs(const IEvent *left, const IEvent *right)
Definition: Voronoi.cxx:128
void findBoundingBox(const dcel2d::VertexList &)
Find the min/max values in x-y to use as a bounding box.
Definition: Voronoi.cxx:1408
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
std::priority_queue< IEvent *, std::vector< IEvent * >, bool(*)(const IEvent *, const IEvent *)> EventQueue
Definition: Voronoi.h:93
dcel2d::PointList fPointList
Definition: Voronoi.h:209
void terminateInfiniteEdges(BeachLine &, double)
this aims to process remaining elements in the beachline after the event queue has been depleted ...
Definition: Voronoi.cxx:854
Event finding and building.
void handleSiteEvents(BeachLine &, EventQueue &, IEvent *)
There are two types of events in the queue, here we handle site events.
Definition: Voronoi.cxx:445
void voronoi2d::VoronoiDiagram::buildVoronoiDiagramBoost ( const dcel2d::PointList pointList)

Definition at line 282 of file Voronoi.cxx.

References boostTranslation(), fCircleEventList, fCircleNodeList, fFaceList, fHalfEdgeList, fNumBadCircles, fPointList, fSiteEventList, and fVertexList.

283  {
284  // Insure all the local data structures have been cleared
285  fHalfEdgeList.clear();
286  fVertexList.clear();
287  fFaceList.clear();
288  fPointList.clear();
289  fSiteEventList.clear();
290  fCircleEventList.clear();
291  fCircleNodeList.clear();
292  fNumBadCircles = 0;
293 
294  std::cout << "*********************************************************************************"
295  "*********************************"
296  << std::endl;
297  std::cout << "*********************************************************************************"
298  "*********************************"
299  << std::endl;
300  std::cout << "*********************************************************************************"
301  "*********************************"
302  << std::endl;
303  std::cout << "==> # input points: " << pointList.size() << std::endl;
304 
305  // Construct out voronoi diagram
306  boost::polygon::voronoi_diagram<double> vd;
307  boost::polygon::construct_voronoi(pointList.begin(), pointList.end(), &vd);
308 
309  // Make maps for translating from boost to me (or we can rewrite our code in boost... for now maps)
310  using BoostEdgeToEdgeMap =
311  std::map<const boost::polygon::voronoi_edge<double>*, dcel2d::HalfEdge*>;
312  using BoostVertexToVertexMap =
313  std::map<const boost::polygon::voronoi_vertex<double>*, dcel2d::Vertex*>;
314  using BoostCellToFaceMap = std::map<const boost::polygon::voronoi_cell<double>*, dcel2d::Face*>;
315 
316  BoostEdgeToEdgeMap boostEdgeToEdgeMap;
317  BoostVertexToVertexMap boostVertexToVertexMap;
318  BoostCellToFaceMap boostCellToFaceMap;
319 
320  // Loop over the edges
321  for (const auto& edge : vd.edges()) {
322  const boost::polygon::voronoi_edge<double>* twin = edge.twin();
323 
325  pointList, &edge, twin, boostEdgeToEdgeMap, boostVertexToVertexMap, boostCellToFaceMap);
327  pointList, twin, &edge, boostEdgeToEdgeMap, boostVertexToVertexMap, boostCellToFaceMap);
328  }
329 
330  //std::cout << "==> Found " << nOpenFaces << " open faces from total of " << fFaceList.size() << std::endl;
331  //for(const auto& edgeCount : edgeCountMap) std::cout << " -> all edges, # edges: " << edgeCount.first << ", count: " << edgeCount.second << std::endl;
332  //for(const auto& edgeCount : openCountMap) std::cout << " -> open edges, # edges: " << edgeCount.first << ", count: " << edgeCount.second << std::endl;
333  std::cout << "==> Boost returns " << fHalfEdgeList.size() << " edges, " << fFaceList.size()
334  << " faces, " << fVertexList.size() << " vertices " << std::endl;
335  std::cout << " " << vd.edges().size() << " edges, " << vd.cells().size()
336  << " faces, " << vd.vertices().size() << " vertices" << std::endl;
337  std::cout << "*********************************************************************************"
338  "*********************************"
339  << std::endl;
340  std::cout << "*********************************************************************************"
341  "*********************************"
342  << std::endl;
343  std::cout << "*********************************************************************************"
344  "*********************************"
345  << std::endl;
346 
347  // Clear internal containers that are no longer useful
348  fSiteEventList.clear();
349  fCircleEventList.clear();
350  fCircleNodeList.clear();
351 
352  return;
353  }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
BSTNodeList fCircleNodeList
Definition: Voronoi.h:212
CircleEventList fCircleEventList
Definition: Voronoi.h:211
SiteEventList fSiteEventList
Definition: Voronoi.h:210
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
dcel2d::PointList fPointList
Definition: Voronoi.h:209
void boostTranslation(const dcel2d::PointList &, const boost::polygon::voronoi_edge< double > *, const boost::polygon::voronoi_edge< double > *, BoostEdgeToEdgeMap &, BoostVertexToVertexMap &, BoostCellToFaceMap &)
Definition: Voronoi.cxx:355
std::map< const boost::polygon::voronoi_edge< double > *, dcel2d::HalfEdge * > BoostEdgeToEdgeMap
Translate boost to dcel.
Definition: Voronoi.h:164
std::map< const boost::polygon::voronoi_vertex< double > *, dcel2d::Vertex * > BoostVertexToVertexMap
Definition: Voronoi.h:166
std::map< const boost::polygon::voronoi_cell< double > *, dcel2d::Face * > BoostCellToFaceMap
Definition: Voronoi.h:167
bool voronoi2d::VoronoiDiagram::computeCircleCenter ( const dcel2d::Coords p1,
const dcel2d::Coords p2,
const dcel2d::Coords p3,
dcel2d::Coords center,
double &  radius,
double &  delta 
) const
private

Definition at line 714 of file Voronoi.cxx.

References e, fNumBadCircles, x2, x3, y2, and y3.

Referenced by makeCircleEvent().

720  {
721  // The method is to translate the three points to a system where the first point is at the origin. Then we
722  // are looking for a circle that passes through the origin and the two remaining (translated) points. In
723  // this mode the circle radius is the distance from the origin to the circle center which simplifies the
724  // calculation.
725  double xCoord = p1[0];
726  double yCoord = p1[1];
727 
728  double x2 = p2[0] - xCoord;
729  double y2 = p2[1] - yCoord;
730  double x3 = p3[0] - xCoord;
731  double y3 = p3[1] - yCoord;
732 
733  double det = x2 * y3 - x3 * y2;
734 
735  // Points are colinear so cannot make a circle
736  // Or, if negative then the midpoint is "left" of line between first and third points meaning the
737  // circle curvature is the "wrong" way for making a circle event
738  if (det <= 0.) // std::numeric_limits<double>::epsilon())
739  //if (!(std::abs(det) > 0.)) // std::numeric_limits<double>::epsilon())
740  {
741  if (det > -std::numeric_limits<double>::epsilon())
742  std::cout << " --->Circle failure, det: " << det << ", mid x: " << p2[0]
743  << ", y: " << p2[1] << ", l x: " << p1[0] << ", y: " << p1[1]
744  << ", r x: " << p3[0] << ", y: " << p3[1] << std::endl;
745 
746  return false;
747  }
748 
749  double p2sqr = x2 * x2 + y2 * y2;
750  double p3sqr = x3 * x3 + y3 * y3;
751 
752  double cxpr = 0.5 * (y3 * p2sqr - y2 * p3sqr) / det;
753  double cypr = 0.5 * (x2 * p3sqr - x3 * p2sqr) / det;
754 
755  radius = std::sqrt(cxpr * cxpr + cypr * cypr);
756  center[0] = cxpr + xCoord;
757  center[1] = cypr + yCoord;
758  center[2] = 0.;
759 
760  // So... roundoff error can cause degenerate circles to get missed
761  // We need to attack that problem by calculating the radius all possible
762  // ways and then take the largest...
763  dcel2d::Coords p1Rad = p1 - center;
764  dcel2d::Coords p2Rad = p2 - center;
765  dcel2d::Coords p3Rad = p3 - center;
766 
767  std::vector<float> radSqrVec;
768 
769  radSqrVec.push_back(p1Rad.norm());
770  radSqrVec.push_back(p2Rad.norm());
771  radSqrVec.push_back(p3Rad.norm());
772 
773  double maxRadius = *std::max_element(radSqrVec.begin(), radSqrVec.end());
774 
775  delta = std::max(5.e-7, maxRadius - radius);
776 
777  if (radius > 1000.) {
778  // std::cout << " ***> Radius = " << radius << ", circ x,y: " << center[0] << ", " << center[1] << ", p1: " << xCoord << "," << yCoord << ", p2: " << p2[0] << "," << p2[1] << ", p3: " << p3[0] << "," << p3[1] << ", det: " << det << std::endl;
779  fNumBadCircles++;
780  }
781 
782  return true;
783  }
Float_t x3[n_points_geant4]
Float_t y2[n_points_geant4]
Definition: compare.C:26
Float_t radius
Definition: plot.C:23
Eigen::Vector3f Coords
Definition: DCEL.h:44
Float_t x2[n_points_geant4]
Definition: compare.C:26
Float_t y3[n_points_geant4]
Float_t e
Definition: plot.C:35
bool voronoi2d::VoronoiDiagram::computeCircleCenter2 ( const dcel2d::Coords p1,
const dcel2d::Coords p2,
const dcel2d::Coords p3,
dcel2d::Coords center,
double &  radius 
) const
private

Definition at line 785 of file Voronoi.cxx.

References util::abs().

790  {
791  // Compute the circle center as the intersection of the two perpendicular bisectors of rays between the points
792  double slope12 = (p2[1] - p1[1]) / (p2[0] - p1[0]);
793  double slope32 = (p3[1] - p2[1]) / (p3[0] - p2[0]);
794 
795  if (std::abs(slope12 - slope32) <= std::numeric_limits<double>::epsilon()) {
796  std::cout << " >>>> Matching slopes! points: (" << p1[0] << "," << p1[1] << "), ("
797  << p2[0] << "," << p2[1] << "), (" << p3[0] << "," << p3[1] << ")" << std::endl;
798 
799  return false;
800  }
801 
802  center[0] = (slope12 * slope32 * (p3[1] - p1[1]) + slope12 * (p2[0] + p3[0]) -
803  slope32 * (p1[0] + p2[0])) /
804  (2. * (slope12 - slope32));
805  center[1] = 0.5 * (p1[1] + p2[1]) - (center[0] - 0.5 * (p1[0] + p2[0])) / slope12;
806  center[2] = 0.;
807  radius = std::sqrt(std::pow((p2[0] - center[0]), 2) + std::pow((p2[1] - center[1]), 2));
808 
809  if (radius > 100.) {
810  std::cout << " ***> Rad2 = " << radius << ", circ x,y: " << center[0] << ","
811  << center[1] << ", p1: " << p1[0] << "," << p1[1] << ", p2: " << p2[0] << ","
812  << p2[1] << ", p3: " << p3[0] << ", " << p3[1] << std::endl;
813  }
814 
815  return true;
816  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
Float_t radius
Definition: plot.C:23
bool voronoi2d::VoronoiDiagram::computeCircleCenter3 ( const dcel2d::Coords p1,
const dcel2d::Coords p2,
const dcel2d::Coords p3,
dcel2d::Coords center,
double &  radius 
) const
private

Definition at line 818 of file Voronoi.cxx.

References util::abs().

823  {
824  // Yet another bisector method to calculate the circle center...
825  double temp = p2[0] * p2[0] + p2[1] * p2[1];
826  double p1p2 = (p1[0] * p1[0] + p1[1] * p1[1] - temp) / 2.0;
827  double p2p3 = (temp - p3[0] * p3[0] - p3[1] * p3[1]) / 2.0;
828  double det = (p1[0] - p2[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p2[1]);
829 
830  if (std::abs(det) < 10. * std::numeric_limits<double>::epsilon()) {
831  std::cout << " >>>> Determinant zero! points: (" << p1[0] << "," << p1[1] << "), ("
832  << p2[0] << "," << p2[1] << "), (" << p3[0] << "," << p3[1] << ")" << std::endl;
833 
834  return false;
835  }
836 
837  det = 1. / det;
838 
839  center[0] = (p1p2 * (p2[1] - p3[1]) - p2p3 * (p1[1] - p2[1])) * det;
840  center[1] = (p2p3 * (p1[0] - p2[0]) - p1p2 * (p2[0] - p3[0])) * det;
841  center[2] = 0.;
842 
843  radius = std::sqrt(std::pow((p1[0] - center[0]), 2) + std::pow((p1[1] - center[1]), 2));
844 
845  if (radius > 100.) {
846  std::cout << " ***> Rad3 = " << radius << ", circ x,y: " << center[0] << ","
847  << center[1] << ", p1: " << p1[0] << "," << p1[1] << ", p2: " << p2[0] << ","
848  << p2[1] << ", p3: " << p3[0] << ", " << p3[1] << std::endl;
849  }
850 
851  return true;
852  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
Float_t radius
Definition: plot.C:23
double voronoi2d::VoronoiDiagram::ComputeFaceArea ( )
private

Compute the area of the faces.

Definition at line 1270 of file Voronoi.cxx.

References crossProduct(), e, fFaceList, dcel2d::Vertex::getCoords(), dcel2d::HalfEdge::getNextHalfEdge(), dcel2d::HalfEdge::getTargetVertex(), dcel2d::HalfEdge::getTwinHalfEdge(), art::left(), art::right(), and sum.

Referenced by terminateInfiniteEdges().

1271  {
1272  // Compute the area by taking advantage of
1273  // 1) the ability to decompose a convex hull into triangles,
1274  // 2) the ability to use the cross product to calculate the area
1275  // So the idea is to loop through all the faces and then follow the edges
1276  // around the face to compute the area of the face.
1277  // Note that a special case are the "infinite faces" which lie on the
1278  // convex hull of the event. Skip these for now...
1279 
1280  double totalArea(0.);
1281  int nNonInfiniteFaces(0);
1282  double smallestArea(std::numeric_limits<double>::max());
1283  double largestArea(0.);
1284 
1285  std::vector<std::pair<double, const dcel2d::Face*>> areaFaceVec;
1286 
1287  areaFaceVec.reserve(fFaceList.size());
1288 
1289  for (auto& face : fFaceList) {
1290  // const dcel2d::Coords& faceCoords = face.getCoords();
1291  const dcel2d::HalfEdge* halfEdge = face.getHalfEdge();
1292  double faceArea(0.);
1293  int numEdges(0);
1294  bool doNext = true;
1295 
1296  dcel2d::Coords faceCenter(0., 0., 0.);
1297 
1298  while (doNext) {
1299  if (halfEdge->getTargetVertex()) faceCenter += halfEdge->getTargetVertex()->getCoords();
1300 
1301  numEdges++;
1302 
1303  halfEdge = halfEdge->getNextHalfEdge();
1304 
1305  if (!halfEdge) {
1306  faceArea = std::numeric_limits<double>::max();
1307  doNext = false;
1308  }
1309 
1310  if (halfEdge == face.getHalfEdge()) doNext = false;
1311  }
1312 
1313  faceCenter /= numEdges;
1314 
1315  halfEdge = face.getHalfEdge();
1316  doNext = true;
1317 
1318  while (doNext) {
1319  const dcel2d::HalfEdge* twinEdge = halfEdge->getTwinHalfEdge();
1320 
1321  if (!halfEdge->getTargetVertex() || !twinEdge->getTargetVertex()) {
1322  faceArea = std::numeric_limits<double>::max();
1323  break;
1324  }
1325 
1326  // Recover the two vertex points
1327  const dcel2d::Coords& p1 = halfEdge->getTargetVertex()->getCoords();
1328  const dcel2d::Coords& p2 = twinEdge->getTargetVertex()->getCoords();
1329 
1330  // Define a quick 2D cross product here since it will used quite a bit!
1331  double dp1p0X = p1[0] - faceCenter[0];
1332  double dp1p0Y = p1[1] - faceCenter[1];
1333  double dp2p0X = p2[0] - faceCenter[0];
1334  double dp2p0Y = p2[1] - faceCenter[1];
1335 
1336  //faceArea += dp1p0X * dp2p0Y - dp1p0Y * dp2p0X;
1337  double crossProduct = dp1p0X * dp2p0Y - dp1p0Y * dp2p0X;
1338 
1339  faceArea += crossProduct;
1340 
1341  if (crossProduct < 0.) {
1342  dcel2d::Coords edgeVec = p1 - p2;
1343  std::cout << "--- negative cross: " << crossProduct << ", edgeLen: " << edgeVec.norm()
1344  << ", x/y: " << edgeVec[0] << "/" << edgeVec[1] << std::endl;
1345  }
1346 
1347  // numEdges++;
1348 
1349  halfEdge = halfEdge->getNextHalfEdge();
1350 
1351  if (!halfEdge) {
1352  faceArea = std::numeric_limits<double>::max();
1353  break;
1354  }
1355 
1356  if (halfEdge == face.getHalfEdge()) doNext = false;
1357  }
1358 
1359  areaFaceVec.emplace_back(faceArea, &face);
1360 
1361  if (faceArea < std::numeric_limits<double>::max() && faceArea > 0.) {
1362  nNonInfiniteFaces++;
1363  totalArea += faceArea;
1364  smallestArea = std::min(faceArea, smallestArea);
1365  largestArea = std::max(faceArea, largestArea);
1366  }
1367 
1368  if (faceArea < 1.e-4)
1369  std::cout << "---> face area <= 0: " << faceArea << ", with " << numEdges << " edges"
1370  << std::endl;
1371 
1372  face.setFaceArea(faceArea);
1373  }
1374 
1375  // Calculate a truncated mean...
1376  std::sort(areaFaceVec.begin(), areaFaceVec.end(), [](const auto& left, const auto& right) {
1377  return left.first < right.first;
1378  });
1379 
1380  std::vector<std::pair<double, const dcel2d::Face*>>::iterator firstItr = std::find_if(
1381  areaFaceVec.begin(), areaFaceVec.end(), [](const auto& val) { return val.first > 0.; });
1382  std::vector<std::pair<double, const dcel2d::Face*>>::iterator lastItr =
1383  std::find_if(areaFaceVec.begin(), areaFaceVec.end(), [](const auto& val) {
1384  return !(val.first < std::numeric_limits<double>::max());
1385  });
1386 
1387  size_t nToKeep = 0.8 * std::distance(firstItr, lastItr);
1388 
1389  std::cout << ">>>>> nToKeep: " << nToKeep
1390  << ", last non infinite entry: " << std::distance(areaFaceVec.begin(), lastItr)
1391  << std::endl;
1392 
1393  double totalTruncArea = std::accumulate(
1394  firstItr, firstItr + nToKeep, 0., [](auto sum, const auto& val) { return sum + val.first; });
1395  double aveTruncArea = totalTruncArea / double(nToKeep);
1396 
1397  if (nNonInfiniteFaces > 0)
1398  std::cout << ">>>> Face area for " << nNonInfiniteFaces
1399  << ", ave area: " << totalArea / nNonInfiniteFaces
1400  << ", ave trunc area: " << aveTruncArea << ", ratio: " << totalTruncArea / totalArea
1401  << ", smallest: " << smallestArea << ", largest: " << largestArea << std::endl;
1402  else
1403  std::cout << ">>>>> there are no non infinite faces" << std::endl;
1404 
1405  return totalArea;
1406  }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
HalfEdge * getNextHalfEdge() const
Definition: DCEL.h:151
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:150
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
double crossProduct(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &p2) const
Gets the cross product of line from p0 to p1 and p0 to p2.
Definition: Voronoi.cxx:89
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
Vertex * getTargetVertex() const
Definition: DCEL.h:148
Eigen::Vector3f Coords
Definition: DCEL.h:44
Double_t sum
Definition: plot.C:31
Float_t e
Definition: plot.C:35
const Coords & getCoords() const
Definition: DCEL.h:62
double voronoi2d::VoronoiDiagram::crossProduct ( const dcel2d::Point p0,
const dcel2d::Point p1,
const dcel2d::Point p2 
) const
private

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

Definition at line 89 of file Voronoi.cxx.

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

92  {
93  // Define a quick 2D cross product here since it will used quite a bit!
94  double deltaX = std::get<0>(p1) - std::get<0>(p0);
95  double deltaY = std::get<1>(p1) - std::get<1>(p0);
96  double dCheckX = std::get<0>(p2) - std::get<0>(p0);
97  double dCheckY = std::get<1>(p2) - std::get<1>(p0);
98 
99  return ((deltaX * dCheckY) - (deltaY * dCheckX));
100  }
void voronoi2d::VoronoiDiagram::findBoundingBox ( const dcel2d::VertexList vertexList)
private

Find the min/max values in x-y to use as a bounding box.

Definition at line 1408 of file Voronoi.cxx.

References fXMax, fXMin, fYMax, fYMin, art::left(), and art::right().

Referenced by buildVoronoiDiagram().

1409  {
1410  // Find extremes in x to start
1411  std::pair<dcel2d::VertexList::const_iterator, dcel2d::VertexList::const_iterator> minMaxItrX =
1412  std::minmax_element(
1413  vertexList.begin(), vertexList.end(), [](const auto& left, const auto& right) {
1414  return left.getCoords()[0] < right.getCoords()[0];
1415  });
1416 
1417  fXMin = minMaxItrX.first->getCoords()[0];
1418  fXMax = minMaxItrX.second->getCoords()[0];
1419 
1420  // To get the extremes in y we need to make a pass through the list
1421  std::pair<dcel2d::VertexList::const_iterator, dcel2d::VertexList::const_iterator> minMaxItrY =
1422  std::minmax_element(
1423  vertexList.begin(), vertexList.end(), [](const auto& left, const auto& right) {
1424  return left.getCoords()[1] < right.getCoords()[1];
1425  });
1426 
1427  fYMin = minMaxItrY.first->getCoords()[1];
1428  fYMax = minMaxItrY.second->getCoords()[1];
1429 
1430  return;
1431  }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
double voronoi2d::VoronoiDiagram::findNearestDistance ( const dcel2d::Point point) const

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

Definition at line 1494 of file Voronoi.cxx.

References findNearestEdge().

Referenced by getConvexHull().

1495  {
1496  double closestDistance;
1497 
1498  findNearestEdge(point, closestDistance);
1499 
1500  return closestDistance;
1501  }
PointPair findNearestEdge(const dcel2d::Point &, double &) const
Given an input Point, find the nearest edge.
Definition: Voronoi.cxx:1433
VoronoiDiagram::PointPair voronoi2d::VoronoiDiagram::findNearestEdge ( const dcel2d::Point point,
double &  closestDistance 
) const

Given an input Point, find the nearest edge.

Definition at line 1433 of file Voronoi.cxx.

References fPointList, and isLeft().

Referenced by findNearestDistance(), and getConvexHull().

1435  {
1436  // The idea is to find the nearest edge of the convex hull, defined by
1437  // two adjacent vertices of the hull, to the input point.
1438  // As near as I can tell, the best way to do this is to apply brute force...
1439  // Idea will be to iterate over pairs of points
1440  dcel2d::PointList::const_iterator curPointItr = fPointList.begin();
1441  dcel2d::Point prevPoint = *curPointItr++;
1442  dcel2d::Point curPoint = *curPointItr;
1443 
1444  // Set up the winner
1445  PointPair closestEdge(prevPoint, curPoint);
1446 
1447  closestDistance = std::numeric_limits<double>::max();
1448 
1449  // curPointItr is meant to point to the second point
1450  while (curPointItr != fPointList.end()) {
1451  if (curPoint != prevPoint) {
1452  // Dereference some stuff
1453  double xPrevToPoint = (std::get<0>(point) - std::get<0>(prevPoint));
1454  double yPrevToPoint = (std::get<1>(point) - std::get<1>(prevPoint));
1455  double xPrevToCur = (std::get<0>(curPoint) - std::get<0>(prevPoint));
1456  double yPrevToCur = (std::get<1>(curPoint) - std::get<1>(prevPoint));
1457  double edgeLength = std::sqrt(xPrevToCur * xPrevToCur + yPrevToCur * yPrevToCur);
1458 
1459  // Find projection onto convex hull edge
1460  double projection =
1461  ((xPrevToPoint * xPrevToCur) + (yPrevToPoint * yPrevToCur)) / edgeLength;
1462 
1463  // DOCA point
1464  dcel2d::Point docaPoint(std::get<0>(prevPoint) + projection * xPrevToCur / edgeLength,
1465  std::get<1>(prevPoint) + projection * yPrevToCur / edgeLength,
1466  0);
1467 
1468  if (projection > edgeLength) docaPoint = curPoint;
1469  if (projection < 0) docaPoint = prevPoint;
1470 
1471  double xDocaDist = std::get<0>(point) - std::get<0>(docaPoint);
1472  double yDocaDist = std::get<1>(point) - std::get<1>(docaPoint);
1473  double docaDist = xDocaDist * xDocaDist + yDocaDist * yDocaDist;
1474 
1475  if (docaDist < closestDistance) {
1476  closestEdge = PointPair(prevPoint, curPoint);
1477  closestDistance = docaDist;
1478  }
1479  }
1480 
1481  prevPoint = curPoint;
1482  curPoint = *curPointItr++;
1483  }
1484 
1485  closestDistance = std::sqrt(closestDistance);
1486 
1487  // Convention is convex hull vertices sorted in counter clockwise fashion so if the point
1488  // lays to the left of the nearest edge then it must be an interior point
1489  if (isLeft(closestEdge.first, closestEdge.second, point)) closestDistance = -closestDistance;
1490 
1491  return closestEdge;
1492  }
std::pair< dcel2d::Point, dcel2d::Point > PointPair
Definition: Voronoi.h:32
intermediate_table::const_iterator const_iterator
dcel2d::PointList fPointList
Definition: Voronoi.h:209
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
bool isLeft(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &pCheck) const
Determines whether a point is to the left, right or on line specifiec by p0 and p1.
Definition: Voronoi.cxx:78
const dcel2d::PointList& voronoi2d::VoronoiDiagram::getConvexHull ( ) const
inline

recover the point list representing the convex hull

Definition at line 74 of file Voronoi.h.

References fConvexHullList, findNearestDistance(), findNearestEdge(), and getExtremePoints().

Referenced by terminateInfiniteEdges().

74 { return fConvexHullList; }
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
void voronoi2d::VoronoiDiagram::getConvexHull ( const BSTNode topNode)
private

this function recovers the convex hull

Definition at line 1009 of file Voronoi.cxx.

References util::abs(), fConvexHullCenter, fConvexHullList, lar_cluster3d::ConvexHull::getConvexHull(), voronoi2d::IEvent::getCoords(), voronoi2d::BSTNode::getEvent(), voronoi2d::BSTNode::getFace(), voronoi2d::BSTNode::getLeftChild(), voronoi2d::IEvent::getPoint(), voronoi2d::BSTNode::getPredecessor(), voronoi2d::BSTNode::getRightChild(), art::left(), art::right(), and dcel2d::Face::setOnConvexHull().

1010  {
1011  // Assume the input node is the top of the binary search tree and represents
1012  // the beach line at the end of the sweep algorithm
1013  // The convex hull will then be the leaf elements along the beach line.
1014  // Note that this algorithm will give you the convex hull in a clockwise manner
1015  if (topNode) {
1016  const BSTNode* node = topNode;
1017 
1018  // Initialize the center
1019  fConvexHullCenter = dcel2d::Coords(0., 0., 0.);
1020 
1021  // Run down the left branches to find the right most leaf
1022  // We do it this way to make sure we get a CCW convex hull
1023  while (node->getRightChild())
1024  node = node->getRightChild();
1025 
1026  // Include a check on convexity...
1027  Eigen::Vector3f prevVec(0., 0., 0.);
1028  dcel2d::Coords lastPoint(0., 0., 0.);
1029 
1030  // Now we are going to traverse across the beach line and process the remaining leaves
1031  // This will identify the convex hull
1032  while (node) {
1033  if (!node->getLeftChild() && !node->getRightChild()) {
1034  // Add point to the convex hull list
1035  fConvexHullList.emplace_back(node->getEvent()->getPoint());
1036 
1037  // Mark the face as on the convex hull
1038  node->getFace()->setOnConvexHull();
1039 
1040  dcel2d::Coords nextPoint = node->getEvent()->getCoords();
1041  Eigen::Vector3f curVec = nextPoint - lastPoint;
1042 
1043  curVec.normalize();
1044 
1045  double dotProd = prevVec.dot(curVec);
1046 
1047  std::cout << "--> lastPoint: " << lastPoint[0] << "/" << lastPoint[1]
1048  << ", tan: " << std::atan2(lastPoint[1], lastPoint[0])
1049  << ", curPoint: " << nextPoint[0] << "/" << nextPoint[1]
1050  << ", tan: " << std::atan2(nextPoint[1], nextPoint[0]) << ", dot: " << dotProd
1051  << std::endl;
1052 
1053  prevVec = curVec;
1054  lastPoint = nextPoint;
1055  }
1056 
1057  node = node->getPredecessor();
1058  }
1059 
1060  // Annoyingly, our algorithm does not contain only the convex hull points and so we need to skim out the renegades...
1062 
1063  for (const auto& edgePoint : fConvexHullList)
1064  localList.emplace_back(
1065  std::get<0>(edgePoint), std::get<1>(edgePoint), std::get<2>(edgePoint));
1066 
1067  // Sort the point vec by increasing x, then increase y
1068  localList.sort([](const auto& left, const auto& right) {
1069  return (std::abs(std::get<0>(left) - std::get<0>(right)) >
1070  std::numeric_limits<float>::epsilon()) ?
1071  std::get<0>(left) < std::get<0>(right) :
1072  std::get<1>(left) < std::get<1>(right);
1073  });
1074 
1075  // Why do I need to do this?
1076  lar_cluster3d::ConvexHull convexHull(localList);
1077 
1078  // Clear the convex hull list...
1079  // fConvexHullList.clear();
1080 
1081  std::cout << "~~~>> there are " << convexHull.getConvexHull().size()
1082  << " convex hull points and " << fConvexHullList.size() << " infinite cells"
1083  << std::endl;
1084 
1085  // Now rebuild it
1086  for (const auto& hullPoint : convexHull.getConvexHull()) {
1087  // fConvexHullList.emplace_back(std::get<0>(hullPoint),std::get<1>(hullPoint),std::get<2>(hullPoint));
1088 
1089  std::cout << "~~~ Convex hull Point: " << std::get<0>(hullPoint) << ", "
1090  << std::get<1>(hullPoint) << std::endl;
1091  }
1092  }
1093 
1094  return;
1095  }
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:33
constexpr auto abs(T v)
Returns the absolute value of the argument.
dcel2d::Coords fConvexHullCenter
Definition: Voronoi.h:215
ConvexHull class definiton.
Definition: ConvexHull.h:26
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
Eigen::Vector3f Coords
Definition: DCEL.h:44
VoronoiDiagram::PointPair voronoi2d::VoronoiDiagram::getExtremePoints ( ) const

Given an input Point, find the nearest edge.

Definition at line 1097 of file Voronoi.cxx.

References fConvexHullList.

Referenced by getConvexHull().

1098  {
1099  dcel2d::PointList::const_iterator nextPointItr = fConvexHullList.begin();
1100  dcel2d::PointList::const_iterator firstPointItr = nextPointItr++;
1101 
1102  float maxSeparation(0.);
1103 
1104  PointPair extremePoints(dcel2d::Point(0, 0, NULL), dcel2d::Point(0, 0, NULL));
1105 
1106  while (nextPointItr != fConvexHullList.end()) {
1107  // Get a vector representing the edge from the first to the current next point
1108  dcel2d::Point firstPoint = *firstPointItr++;
1109  dcel2d::Point nextPoint = *nextPointItr;
1110  Eigen::Vector2f firstEdge(std::get<0>(*firstPointItr) - std::get<0>(firstPoint),
1111  std::get<1>(*firstPointItr) - std::get<1>(firstPoint));
1112 
1113  // normalize it
1114  firstEdge.normalize();
1115 
1116  dcel2d::PointList::const_iterator endPointItr = nextPointItr;
1117 
1118  while (++endPointItr != fConvexHullList.end()) {
1119  dcel2d::Point endPoint = *endPointItr;
1120  Eigen::Vector2f nextEdge(std::get<0>(endPoint) - std::get<0>(nextPoint),
1121  std::get<1>(endPoint) - std::get<1>(nextPoint));
1122 
1123  // normalize it
1124  nextEdge.normalize();
1125 
1126  // Have we found the turnaround point?
1127  if (firstEdge.dot(nextEdge) < 0.) {
1128  Eigen::Vector2f separation(std::get<0>(nextPoint) - std::get<0>(firstPoint),
1129  std::get<1>(nextPoint) - std::get<1>(firstPoint));
1130  float separationDistance = separation.norm();
1131 
1132  if (separationDistance > maxSeparation) {
1133  extremePoints.first = firstPoint;
1134  extremePoints.second = nextPoint;
1135  maxSeparation = separationDistance;
1136  }
1137 
1138  // Regardless of thise being the maximum distance we have hit a turnaround point so
1139  // we need to break out of this loop
1140  break;
1141  }
1142 
1143  nextPointItr = endPointItr;
1144  nextPoint = endPoint;
1145  }
1146 
1147  // If we have hit the end of the convex hull without finding a turnaround point then we are not
1148  // going to find one so break out of the main loop
1149  if (endPointItr == fConvexHullList.end()) break;
1150 
1151  // Need to make sure we don't overrun the next point
1152  if (firstPointItr == nextPointItr) nextPointItr++;
1153  }
1154 
1155  return extremePoints;
1156  }
std::pair< dcel2d::Point, dcel2d::Point > PointPair
Definition: Voronoi.h:32
intermediate_table::const_iterator const_iterator
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
const dcel2d::FaceList& voronoi2d::VoronoiDiagram::getFaceList ( ) const
inline

Recover the list of faces.

Definition at line 59 of file Voronoi.h.

References fFaceList.

59 { return fFaceList; }
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
const dcel2d::VertexList& voronoi2d::VoronoiDiagram::getVertexList ( ) const
inline

Recover the list of vertices.

Definition at line 64 of file Voronoi.h.

References fVertexList.

64 { return fVertexList; }
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
double voronoi2d::VoronoiDiagram::getVoronoiDiagramArea ( ) const
inline

recover the area of the convex hull

Definition at line 69 of file Voronoi.h.

References fVoronoiDiagramArea.

69 { return fVoronoiDiagramArea; }
void voronoi2d::VoronoiDiagram::handleCircleEvents ( BeachLine beachLine,
EventQueue eventQueue,
IEvent circleEvent 
)
private

There are two types of events in the queue, here we handle circle events.

Definition at line 503 of file Voronoi.cxx.

References voronoi2d::IEvent::circleCenter(), fHalfEdgeList, fVertexList, voronoi2d::BSTNode::getAssociated(), voronoi2d::IEvent::getBSTNode(), voronoi2d::BSTNode::getFace(), dcel2d::HalfEdge::getFace(), voronoi2d::BSTNode::getHalfEdge(), voronoi2d::BSTNode::getPredecessor(), voronoi2d::BSTNode::getSuccessor(), dcel2d::HalfEdge::getTwinHalfEdge(), makeLeftCircleEvent(), makeRightCircleEvent(), voronoi2d::BeachLine::removeLeaf(), dcel2d::HalfEdge::setFace(), dcel2d::Vertex::setHalfEdge(), voronoi2d::BSTNode::setHalfEdge(), dcel2d::HalfEdge::setLastHalfEdge(), dcel2d::HalfEdge::setNextHalfEdge(), dcel2d::HalfEdge::setTargetVertex(), dcel2d::HalfEdge::setTwinHalfEdge(), and voronoi2d::IEvent::xPos().

Referenced by buildVoronoiDiagram().

506  {
507  BSTNode* circleNode = circleEvent->getBSTNode();
508  BSTNode* arcNode = circleNode->getAssociated();
509 
510  // Recover the half edges for the breakpoints either side of the arc we're removing
511  dcel2d::HalfEdge* leftHalfEdge = arcNode->getPredecessor()->getHalfEdge();
512  dcel2d::HalfEdge* rightHalfEdge = arcNode->getSuccessor()->getHalfEdge();
513 
514  if (leftHalfEdge->getTwinHalfEdge()->getFace() != rightHalfEdge->getFace()) {
515  std::cout << ">>>> Face mismatch in circle handling, left face: " << leftHalfEdge->getFace()
516  << ", left twin: " << leftHalfEdge->getTwinHalfEdge()->getFace()
517  << ", right: " << rightHalfEdge->getFace()
518  << ", right twin: " << rightHalfEdge->getTwinHalfEdge()->getFace()
519  << ", arc face: " << arcNode->getFace() << std::endl;
520  }
521 
522  // Create the new vertex point
523  // Don't forget we need to swap coordinates when returning to the outside world
524  dcel2d::Coords vertexPos(circleEvent->circleCenter());
525 
526  fVertexList.push_back(dcel2d::Vertex(vertexPos, leftHalfEdge->getTwinHalfEdge()));
527 
528  dcel2d::Vertex* vertex = &fVertexList.back();
529 
530  // The edges we obtained "emanate" from the new vertex point,
531  // their twins will point to it
532  leftHalfEdge->getTwinHalfEdge()->setTargetVertex(vertex);
533  rightHalfEdge->getTwinHalfEdge()->setTargetVertex(vertex);
534 
535  // Remove the arc which will return the new breakpoint
536  // NOTE: invalidation of any possible circle events occurs in the call to this routine
537  BSTNode* newBreakPoint = beachLine.removeLeaf(arcNode);
538 
539  // Now create edges associated with the new break point
540  fHalfEdgeList.push_back(dcel2d::HalfEdge());
541 
542  dcel2d::HalfEdge* halfEdgeOne = &fHalfEdgeList.back();
543 
544  fHalfEdgeList.push_back(dcel2d::HalfEdge());
545 
546  dcel2d::HalfEdge* halfEdgeTwo = &fHalfEdgeList.back();
547 
548  // Associate the first edge with the new break point
549  newBreakPoint->setHalfEdge(halfEdgeTwo);
550 
551  // These are twins
552  halfEdgeOne->setTwinHalfEdge(halfEdgeTwo);
553  halfEdgeTwo->setTwinHalfEdge(halfEdgeOne);
554 
555  // The second points to the vertex we just made
556  halfEdgeTwo->setTargetVertex(vertex);
557  vertex->setHalfEdge(halfEdgeOne);
558 
559  // halfEdgeTwo points to the vertex, face to left, so pairs with
560  // the leftHalfEdge (leaving the vertex, face to left)
561  halfEdgeTwo->setNextHalfEdge(leftHalfEdge);
562  leftHalfEdge->setLastHalfEdge(halfEdgeTwo);
563  halfEdgeTwo->setFace(leftHalfEdge->getFace());
564 
565  // halfEdgeOne emanates from the vertex, face to left, so pairs with
566  // the twin of the rightHalfEdge (pointing to vertex, face to left)
567  halfEdgeOne->setLastHalfEdge(rightHalfEdge->getTwinHalfEdge());
568  rightHalfEdge->getTwinHalfEdge()->setNextHalfEdge(halfEdgeOne);
569  halfEdgeOne->setFace(rightHalfEdge->getTwinHalfEdge()->getFace());
570 
571  // Finally, the twin of the leftHalfEdge points to the vertex (face to left)
572  // and will pair with the rightHalfEdge emanating from the vertex
573  // In this case they should already be sharing the same face
574  rightHalfEdge->setLastHalfEdge(leftHalfEdge->getTwinHalfEdge());
575  leftHalfEdge->getTwinHalfEdge()->setNextHalfEdge(rightHalfEdge);
576 
577  // We'll try to make circle events with the remnant arcs so get the pointers now
578  // Note that we want the former left and right arcs to be the middle arcs in this case
579  BSTNode* leftArc = newBreakPoint->getPredecessor();
580  BSTNode* rightArc = newBreakPoint->getSuccessor();
581 
582  // Look for a new circle candidates
583  // In this case, we'd like the right arc to be the middle of the right circle,
584  // the left arc to be the middle of the left circle, hence the logic below
585  makeRightCircleEvent(eventQueue, leftArc, circleEvent->xPos());
586  makeLeftCircleEvent(eventQueue, rightArc, circleEvent->xPos());
587 
588  return;
589  }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
void setHalfEdge(HalfEdge *half)
Definition: DCEL.h:74
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:150
Face * getFace() const
Definition: DCEL.h:149
void makeLeftCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:591
void setLastHalfEdge(HalfEdge *last)
Definition: DCEL.h:158
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:156
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
void makeRightCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:633
void setFace(Face *face)
Definition: DCEL.h:155
void setNextHalfEdge(HalfEdge *next)
Definition: DCEL.h:157
Eigen::Vector3f Coords
Definition: DCEL.h:44
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:154
vertex reconstruction
void voronoi2d::VoronoiDiagram::handleSiteEvents ( BeachLine beachLine,
EventQueue eventQueue,
IEvent siteEvent 
)
private

There are two types of events in the queue, here we handle site events.

Definition at line 445 of file Voronoi.cxx.

References fFaceList, fHalfEdgeList, voronoi2d::IEvent::getCoords(), voronoi2d::BSTNode::getFace(), dcel2d::Face::getHalfEdge(), voronoi2d::IEvent::getPoint(), voronoi2d::BSTNode::getPredecessor(), voronoi2d::BSTNode::getSuccessor(), voronoi2d::BeachLine::insertNewLeaf(), makeLeftCircleEvent(), makeRightCircleEvent(), voronoi2d::BSTNode::setFace(), dcel2d::HalfEdge::setFace(), voronoi2d::BSTNode::setHalfEdge(), dcel2d::Face::setHalfEdge(), dcel2d::HalfEdge::setTwinHalfEdge(), and voronoi2d::IEvent::xPos().

Referenced by buildVoronoiDiagram().

448  {
449  // Insert the new site event into the beach line and recover the leaf for the
450  // new arc in the beach line
451  // NOTE: invalidation of any possible circle events occurs in the call to this routine
452  BSTNode* newLeaf = beachLine.insertNewLeaf(siteEvent);
453 
454  // Create a new vertex for each site event
455  fFaceList.emplace_back(
456  dcel2d::Face(NULL, siteEvent->getCoords(), std::get<2>(siteEvent->getPoint())));
457 
458  dcel2d::Face* face = &fFaceList.back();
459 
460  newLeaf->setFace(face);
461 
462  // If we are the first site added to the BST then we are done
463  if (!(newLeaf->getPredecessor() || newLeaf->getSuccessor())) return;
464 
465  // So, now we deal with creating the edges that will be mapped out by the two breakpoints as they
466  // move with the beachline. Note that this is a single edge pair (edge and its twin) between the
467  // two breakpoints that have been created.
468  fHalfEdgeList.push_back(dcel2d::HalfEdge());
469 
470  dcel2d::HalfEdge* halfEdge = &fHalfEdgeList.back();
471 
472  fHalfEdgeList.push_back(dcel2d::HalfEdge());
473 
474  dcel2d::HalfEdge* halfTwin = &fHalfEdgeList.back();
475 
476  // Each half edge is the twin of the other
477  halfEdge->setTwinHalfEdge(halfTwin);
478  halfTwin->setTwinHalfEdge(halfEdge);
479 
480  // Point the breakpoint to the new edge
481  newLeaf->getPredecessor()->setHalfEdge(halfEdge);
482  newLeaf->getSuccessor()->setHalfEdge(halfTwin);
483 
484  // The second half edge corresponds to our face for the left breakpoint...
485  face->setHalfEdge(halfTwin);
486  halfTwin->setFace(face);
487 
488  // Update for the left leaf
489  BSTNode* leftLeaf = newLeaf->getPredecessor()->getPredecessor();
490 
491  // This needs to be checked since the first face will not have an edge set to it
492  if (!leftLeaf->getFace()->getHalfEdge()) leftLeaf->getFace()->setHalfEdge(halfEdge);
493 
494  halfEdge->setFace(leftLeaf->getFace());
495 
496  // Try to make circle events either side of this leaf
497  makeLeftCircleEvent(eventQueue, newLeaf, siteEvent->xPos());
498  makeRightCircleEvent(eventQueue, newLeaf, siteEvent->xPos());
499 
500  return;
501  }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:207
void makeLeftCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:591
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:156
void makeRightCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:633
void setFace(Face *face)
Definition: DCEL.h:155
void setHalfEdge(HalfEdge *half)
Definition: DCEL.h:108
bool voronoi2d::VoronoiDiagram::isInsideConvexHull ( const dcel2d::Vertex vertex) const
private

Is a vertex inside the convex hull - meant to be a fast check.

Definition at line 1158 of file Voronoi.cxx.

References fConvexHullList, dcel2d::Vertex::getCoords(), and isLeft().

Referenced by terminateInfiniteEdges().

1159  {
1160  bool insideHull(true);
1161  dcel2d::Point vertexPos(vertex.getCoords()[0], vertex.getCoords()[1], NULL);
1162 
1163  // Now check to see if the vertex is inside the convex hull
1165  dcel2d::Point firstPoint = *hullItr++;
1166 
1167  // We assume here the convex hull is stored in a CCW order
1168  while (hullItr != fConvexHullList.end()) {
1169  dcel2d::Point secondPoint = *hullItr++;
1170 
1171  // CCW order means we check to see if this point lies to left of line from first to second point
1172  // in order for the point to be "inside" the convex hull
1173  // Note that we are looking to reject points that are outside...
1174  if (!isLeft(firstPoint, secondPoint, vertexPos)) {
1175  insideHull = false;
1176  break;
1177  }
1178 
1179  firstPoint = secondPoint;
1180  }
1181 
1182  return insideHull;
1183  }
intermediate_table::const_iterator const_iterator
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
const Coords & getCoords() const
Definition: DCEL.h:62
bool isLeft(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &pCheck) const
Determines whether a point is to the left, right or on line specifiec by p0 and p1.
Definition: Voronoi.cxx:78
bool voronoi2d::VoronoiDiagram::isLeft ( const dcel2d::Point p0,
const dcel2d::Point p1,
const dcel2d::Point pCheck 
) const
private

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

Definition at line 78 of file Voronoi.cxx.

References crossProduct().

Referenced by findNearestEdge(), isInsideConvexHull(), and isOutsideConvexHull().

81  {
82  // Use the cross product to determine if the check point lies to the left, on or right
83  // of the line defined by points p0 and p1
84  return crossProduct(p0, p1, pCheck) > 0;
85  }
double crossProduct(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &p2) const
Gets the cross product of line from p0 to p1 and p0 to p2.
Definition: Voronoi.cxx:89
bool voronoi2d::VoronoiDiagram::isOutsideConvexHull ( const dcel2d::Vertex vertex,
dcel2d::PointList::const_iterator  firstHullPointItr,
dcel2d::Coords intersection,
double &  distToConvexHull 
) const
private

is vertex outside the convex hull and if so return some useful information

Definition at line 1185 of file Voronoi.cxx.

References fConvexHullList, dcel2d::Vertex::getCoords(), and isLeft().

1189  {
1190  bool outsideHull(false);
1191  dcel2d::Point vertexPos(vertex.getCoords()[0], vertex.getCoords()[1], NULL);
1192 
1193  distToConvexHull = std::numeric_limits<double>::max();
1194  firstHullPointItr = fConvexHullList.begin();
1195 
1196  // Now check to see if the vertex is inside the convex hull
1197  dcel2d::PointList::const_iterator hullItr = firstHullPointItr;
1198  dcel2d::PointList::const_iterator firstPointItr = hullItr++;
1199 
1200  while (hullItr != fConvexHullList.end()) {
1201  dcel2d::PointList::const_iterator secondPointItr = hullItr++;
1202 
1203  // Dereference some stuff
1204  double xPrevToPoint = (std::get<0>(vertexPos) - std::get<0>(*firstPointItr));
1205  double yPrevToPoint = (std::get<1>(vertexPos) - std::get<1>(*firstPointItr));
1206  double xPrevToCur = (std::get<0>(*secondPointItr) - std::get<0>(*firstPointItr));
1207  double yPrevToCur = (std::get<1>(*secondPointItr) - std::get<1>(*firstPointItr));
1208  double edgeLength = std::sqrt(xPrevToCur * xPrevToCur + yPrevToCur * yPrevToCur);
1209 
1210  // Find projection onto convex hull edge
1211  double projection = ((xPrevToPoint * xPrevToCur) + (yPrevToPoint * yPrevToCur)) / edgeLength;
1212 
1213  // DOCA point
1214  dcel2d::Point docaPoint(std::get<0>(*firstPointItr) + projection * xPrevToCur / edgeLength,
1215  std::get<1>(*firstPointItr) + projection * yPrevToCur / edgeLength,
1216  0);
1217 
1218  if (projection > edgeLength) docaPoint = *secondPointItr;
1219  if (projection < 0) docaPoint = *firstPointItr;
1220 
1221  double xDocaDist = std::get<0>(vertexPos) - std::get<0>(docaPoint);
1222  double yDocaDist = std::get<1>(vertexPos) - std::get<1>(docaPoint);
1223  double docaDist = xDocaDist * xDocaDist + yDocaDist * yDocaDist;
1224 
1225  if (docaDist < distToConvexHull) {
1226  firstHullPointItr = firstPointItr;
1227  intersection = dcel2d::Coords(std::get<0>(docaPoint), std::get<1>(docaPoint), 0.);
1228  distToConvexHull = docaDist;
1229  }
1230 
1231  // Check to see if this point is outside the convex hull
1232  if (isLeft(*firstPointItr, *secondPointItr, vertexPos)) outsideHull = true;
1233 
1234  firstPointItr = secondPointItr;
1235  }
1236 
1237  return outsideHull;
1238  }
intermediate_table::const_iterator const_iterator
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
Eigen::Vector3f Coords
Definition: DCEL.h:44
const Coords & getCoords() const
Definition: DCEL.h:62
bool isLeft(const dcel2d::Point &p0, const dcel2d::Point &p1, const dcel2d::Point &pCheck) const
Determines whether a point is to the left, right or on line specifiec by p0 and p1.
Definition: Voronoi.cxx:78
IEvent * voronoi2d::VoronoiDiagram::makeCircleEvent ( BSTNode arc1,
BSTNode arc2,
BSTNode arc3,
double  beachLinePos 
)
private

There are two types of events in the queue, here we handle circle events.

Definition at line 673 of file Voronoi.cxx.

References computeCircleCenter(), e, fCircleEventList, voronoi2d::IEvent::getCoords(), voronoi2d::BSTNode::getEvent(), and radius.

Referenced by makeLeftCircleEvent(), and makeRightCircleEvent().

677  {
678  // It might be that we don't create a new circle
679  IEvent* circle = 0;
680 
681  // First step is to calculate the center and radius of the circle determined by the three input site events
682  dcel2d::Coords center;
683  double radius;
684  double deltaR;
685 
686  IEvent* p1 = arc1->getEvent();
687  IEvent* p2 = arc2->getEvent();
688  IEvent* p3 = arc3->getEvent();
689 
690  // Compute the center of the circle. Note that this will also automagically check that breakpoints are
691  // converging so that this is a circle we want
693  p1->getCoords(), p2->getCoords(), p3->getCoords(), center, radius, deltaR)) {
694  double circleBottomX = center[0] - radius;
695 
696  // Now check if the bottom of this circle lies below the beach line
697  if (beachLinePos >= circleBottomX - 10. * deltaR) {
698  // Making a circle event!
699  dcel2d::Point circleBottom(circleBottomX, center[1], NULL);
700 
701  fCircleEventList.emplace_back(circleBottom, center);
702 
703  circle = &fCircleEventList.back();
704  }
705  else if (circleBottomX - beachLinePos < 1.e-4)
706  std::cout << "==> Circle close, beachLine: " << beachLinePos
707  << ", circleBottomX: " << circleBottomX << ", deltaR: " << deltaR
708  << ", d: " << circleBottomX - beachLinePos << std::endl;
709  }
710 
711  return circle;
712  }
bool computeCircleCenter(const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &, double &) const
Definition: Voronoi.cxx:714
CircleEventList fCircleEventList
Definition: Voronoi.h:211
Float_t radius
Definition: plot.C:23
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
Eigen::Vector3f Coords
Definition: DCEL.h:44
Float_t e
Definition: plot.C:35
void voronoi2d::VoronoiDiagram::makeLeftCircleEvent ( EventQueue eventQueue,
BSTNode leaf,
double  beachLine 
)
private

Definition at line 591 of file Voronoi.cxx.

References fCircleNodeList, voronoi2d::BSTNode::getAssociated(), voronoi2d::BSTNode::getEvent(), voronoi2d::IEvent::getPoint(), voronoi2d::BSTNode::getPredecessor(), makeCircleEvent(), voronoi2d::BSTNode::setAssociated(), and voronoi2d::IEvent::setInvalid().

Referenced by handleCircleEvents(), and handleSiteEvents().

592  {
593 
594  // Check status of triplet of site events to the left of this new leaf
595  if (leaf->getPredecessor()) {
596  BSTNode* midLeaf = leaf->getPredecessor()->getPredecessor();
597 
598  if (midLeaf && midLeaf->getPredecessor()) {
599  BSTNode* edgeLeaf = midLeaf->getPredecessor()->getPredecessor();
600 
601  // edge leaves must be different
602  if (leaf->getEvent()->getPoint() == edgeLeaf->getEvent()->getPoint()) return;
603 
604  if (edgeLeaf) {
605  IEvent* circleEvent = makeCircleEvent(edgeLeaf, midLeaf, leaf, beachLine);
606 
607  // Did we succeed in making a circle event?
608  if (circleEvent) {
609  // Add to the circle node list
610  fCircleNodeList.emplace_back(circleEvent);
611 
612  BSTNode* circleNode = &fCircleNodeList.back();
613 
614  // If there was an associated circle event to this node, invalidate it
615  if (midLeaf->getAssociated()) {
616  midLeaf->getAssociated()->setAssociated(NULL);
617  midLeaf->getAssociated()->getEvent()->setInvalid();
618  }
619 
620  // Now reset to point at the new one
621  midLeaf->setAssociated(circleNode);
622  circleNode->setAssociated(midLeaf);
623 
624  eventQueue.push(circleEvent);
625  }
626  }
627  }
628  }
629 
630  return;
631  }
BSTNodeList fCircleNodeList
Definition: Voronoi.h:212
IEvent * makeCircleEvent(BSTNode *, BSTNode *, BSTNode *, double)
There are two types of events in the queue, here we handle circle events.
Definition: Voronoi.cxx:673
void voronoi2d::VoronoiDiagram::makeRightCircleEvent ( EventQueue eventQueue,
BSTNode leaf,
double  beachLine 
)
private

Definition at line 633 of file Voronoi.cxx.

References fCircleNodeList, voronoi2d::BSTNode::getAssociated(), voronoi2d::BSTNode::getEvent(), voronoi2d::IEvent::getPoint(), voronoi2d::BSTNode::getSuccessor(), makeCircleEvent(), voronoi2d::BSTNode::setAssociated(), and voronoi2d::IEvent::setInvalid().

Referenced by handleCircleEvents(), and handleSiteEvents().

634  {
635  // Check status of triplet of site events to the left of this new leaf
636  if (leaf->getSuccessor()) {
637  BSTNode* midLeaf = leaf->getSuccessor()->getSuccessor();
638 
639  if (midLeaf && midLeaf->getSuccessor()) {
640  BSTNode* edgeLeaf = midLeaf->getSuccessor()->getSuccessor();
641 
642  if (leaf->getEvent()->getPoint() == edgeLeaf->getEvent()->getPoint()) return;
643 
644  if (edgeLeaf) {
645  IEvent* circleEvent = makeCircleEvent(leaf, midLeaf, edgeLeaf, beachLine);
646 
647  // Did we succeed in making a circle event?
648  if (circleEvent) {
649  // Add to the circle node list
650  fCircleNodeList.emplace_back(circleEvent);
651 
652  BSTNode* circleNode = &fCircleNodeList.back();
653 
654  // If there was an associated circle event to this node, invalidate it
655  if (midLeaf->getAssociated()) {
656  midLeaf->getAssociated()->setAssociated(NULL);
657  midLeaf->getAssociated()->getEvent()->setInvalid();
658  }
659 
660  // Now reset to point at the new one
661  midLeaf->setAssociated(circleNode);
662  circleNode->setAssociated(midLeaf);
663 
664  eventQueue.push(circleEvent);
665  }
666  }
667  }
668  }
669 
670  return;
671  }
BSTNodeList fCircleNodeList
Definition: Voronoi.h:212
IEvent * makeCircleEvent(BSTNode *, BSTNode *, BSTNode *, double)
There are two types of events in the queue, here we handle circle events.
Definition: Voronoi.cxx:673
void voronoi2d::VoronoiDiagram::mergeDegenerateVertices ( )
private

merge degenerate vertices (found by zero length edges)

Definition at line 1240 of file Voronoi.cxx.

References fHalfEdgeList, dcel2d::Vertex::getCoords(), dcel2d::HalfEdge::getTargetVertex(), and dcel2d::HalfEdge::getTwinHalfEdge().

Referenced by terminateInfiniteEdges().

1241  {
1243 
1244  while (edgeItr != fHalfEdgeList.end()) {
1245  dcel2d::HalfEdge* halfEdge = &(*edgeItr);
1246  dcel2d::HalfEdge* twinEdge = halfEdge->getTwinHalfEdge();
1247 
1248  // Make sure we are not looking at an infinite edge
1249  if (halfEdge->getTargetVertex() && twinEdge->getTargetVertex()) {
1250  dcel2d::Coords vtxPosDiff =
1251  halfEdge->getTargetVertex()->getCoords() - twinEdge->getTargetVertex()->getCoords();
1252 
1253  if (vtxPosDiff.norm() < 1.e-3) {
1254  std::cout << "***>> found a degenerate vertex! "
1255  << halfEdge->getTargetVertex()->getCoords()[0] << "/"
1256  << halfEdge->getTargetVertex()->getCoords()[1] << ", d: " << vtxPosDiff.norm()
1257  << std::endl;
1258  edgeItr++;
1259  }
1260  else
1261  edgeItr++;
1262  }
1263  else
1264  edgeItr++;
1265  }
1266 
1267  return;
1268  }
intermediate_table::iterator iterator
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:205
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:150
Vertex * getTargetVertex() const
Definition: DCEL.h:148
Eigen::Vector3f Coords
Definition: DCEL.h:44
const Coords & getCoords() const
Definition: DCEL.h:62
void voronoi2d::VoronoiDiagram::terminateInfiniteEdges ( BeachLine beachLine,
double  beachLinePos 
)
private

this aims to process remaining elements in the beachline after the event queue has been depleted

Definition at line 854 of file Voronoi.cxx.

References voronoi2d::EventUtilities::computeArcVal(), voronoi2d::EventUtilities::computeBreak(), ComputeFaceArea(), fConvexHullList, fUtilities, fVertexList, voronoi2d::BSTNode::getAssociated(), getConvexHull(), voronoi2d::IEvent::getCoords(), dcel2d::Vertex::getCoords(), voronoi2d::BSTNode::getEvent(), voronoi2d::BSTNode::getFace(), dcel2d::HalfEdge::getFace(), voronoi2d::BSTNode::getHalfEdge(), dcel2d::HalfEdge::getLastHalfEdge(), voronoi2d::BSTNode::getLeftChild(), dcel2d::HalfEdge::getNextHalfEdge(), voronoi2d::BSTNode::getPredecessor(), voronoi2d::BSTNode::getRightChild(), voronoi2d::BSTNode::getSuccessor(), dcel2d::HalfEdge::getTargetVertex(), voronoi2d::BeachLine::getTopNode(), dcel2d::HalfEdge::getTwinHalfEdge(), voronoi2d::IEvent::isCircle(), isInsideConvexHull(), voronoi2d::IEvent::isValid(), mergeDegenerateVertices(), dcel2d::HalfEdge::setTargetVertex(), voronoi2d::IEvent::xPos(), and voronoi2d::IEvent::yPos().

Referenced by buildVoronoiDiagram().

855  {
856  // Need to complete processing of the beachline, the remaning leaves represent the site points with "infinite"
857  // edges which we need to terminate at our bounding box.
858  // For now let's just do step one which is to find the convex hull
859  const BSTNode* node = beachLine.getTopNode();
860 
861  // Do the convex hull independently but before terminating edges
862  getConvexHull(node);
863 
864  if (node) {
865  // Run down the left branches to find the left most leaf
866  while (node->getLeftChild())
867  node = node->getLeftChild();
868 
869  // Things to keep track of...
870  int nodeCount(0);
871  int nBadBreaks(0);
872  double lastBreakPoint = std::numeric_limits<double>::lowest();
873 
874  // Now we are going to traverse across the beach line and process the remaining leaves
875  // This will identify the infinite edges and find the convex hull
876  while (node) {
877  std::cout << "-----------------------------------------------------------------------------"
878  "---------------"
879  << std::endl;
880 
881  // Do we have a leaf?
882  if (!node->getLeftChild() && !node->getRightChild()) {
883  std::cout << "node " << nodeCount << " has leaf: " << node
884  << ", face: " << node->getFace()
885  << ", pos: " << node->getEvent()->getCoords()[0] << "/"
886  << node->getEvent()->getCoords()[1] << std::endl;
887  }
888  // Otherwise it is a break point
889  else {
890  RootsPair roots;
891  double breakPoint = fUtilities.computeBreak(beachLinePos,
892  node->getPredecessor()->getEvent(),
893  node->getSuccessor()->getEvent(),
894  roots);
895  double leftArcVal =
896  fUtilities.computeArcVal(beachLinePos, breakPoint, node->getPredecessor()->getEvent());
897  double rightArcVal =
898  fUtilities.computeArcVal(beachLinePos, breakPoint, node->getSuccessor()->getEvent());
899 
900  dcel2d::HalfEdge* halfEdge = node->getHalfEdge();
901  dcel2d::HalfEdge* halfTwin = halfEdge->getTwinHalfEdge();
902  dcel2d::Vertex* vertex = halfEdge->getTargetVertex();
903 
904  std::cout << "node " << nodeCount << " has break: " << breakPoint
905  << ", beachPos: " << beachLinePos << " (last: " << lastBreakPoint
906  << "), leftArcVal: " << leftArcVal << ", rightArcVal: " << rightArcVal
907  << std::endl;
908  if (lastBreakPoint > breakPoint)
909  std::cout << " ***** lastBreakPoint larger than current break point *****"
910  << std::endl;
911  std::cout << " left arc x/y: " << node->getPredecessor()->getEvent()->xPos() << "/"
912  << node->getPredecessor()->getEvent()->yPos()
913  << ", right arc x/y: " << node->getSuccessor()->getEvent()->xPos() << "/"
914  << node->getSuccessor()->getEvent()->yPos() << std::endl;
915  std::cout << " halfEdge: " << halfEdge << ", target vtx: " << vertex
916  << ", face: " << halfEdge->getFace() << ", twin: " << halfTwin
917  << ", twin tgt: " << halfTwin->getTargetVertex()
918  << ", twin face: " << halfTwin->getFace()
919  << ", next: " << halfEdge->getNextHalfEdge()
920  << ", last: " << halfEdge->getLastHalfEdge() << std::endl;
921 
922  const dcel2d::Coords& leftLeafPos = node->getPredecessor()->getEvent()->getCoords();
923  const dcel2d::Coords& rightLeafPos = node->getSuccessor()->getEvent()->getCoords();
924  Eigen::Vector3f lrPosDiff = rightLeafPos - leftLeafPos;
925  Eigen::Vector3f lrPosSum = rightLeafPos + leftLeafPos;
926 
927  lrPosDiff.normalize();
928  lrPosSum *= 0.5;
929 
930  dcel2d::Coords leafPos = node->getSuccessor()->getEvent()->getCoords();
931  dcel2d::Coords leafDir = lrPosDiff;
932 
933  if (vertex) {
934  dcel2d::Coords breakDir(leafDir[1], -leafDir[0], 0.);
935  dcel2d::Coords breakPos = lrPosSum;
936  dcel2d::Coords vertexPos = vertex->getCoords();
937 
938  // Get the arclength from the break position to the intersection of the two lines
939  dcel2d::Coords breakToLeafPos = leafPos - vertexPos;
940  double arcLenToLine = breakToLeafPos.dot(breakDir);
941 
942  // Now get position
943  dcel2d::Coords breakVertexPos = vertexPos + arcLenToLine * breakDir;
944 
945  std::cout << " halfEdge position: " << breakPos[0] << "/" << breakPos[1]
946  << ", vertex: " << vertexPos[0] << "/" << vertexPos[1]
947  << ", end: " << breakVertexPos[0] << "/" << breakVertexPos[1]
948  << ", dir: " << breakDir[0] << "/" << breakDir[1]
949  << ", arclen: " << arcLenToLine << std::endl;
950 
951  // At this point we need to create a vertex and then terminate the half edges here...
952  fVertexList.push_back(dcel2d::Vertex(breakVertexPos, halfEdge));
953 
954  dcel2d::Vertex* breakVertex = &fVertexList.back();
955 
956  halfTwin->setTargetVertex(breakVertex);
957  }
958  else {
959  std::cout << "****** null vertex!!! Skipping to next node... *********" << std::endl;
960  }
961 
962  if (lastBreakPoint > breakPoint) nBadBreaks++;
963 
964  lastBreakPoint = breakPoint;
965  }
966 
967  if (node->getAssociated()) {
968  BSTNode* associated = node->getAssociated();
969  IEvent* iEvent = associated->getEvent();
970 
971  std::cout << " -> associated circle: " << iEvent->isCircle()
972  << ", is valid: " << iEvent->isValid() << std::endl;
973  }
974 
975  node = node->getSuccessor();
976  nodeCount++;
977  }
978 
979  // Now that we have the convex hull, loop over vertices to see if they are inside or outside of the convex hull
980  dcel2d::VertexList::iterator curVertexItr = fVertexList.begin();
981 
982  size_t nVerticesInitial = fVertexList.size();
983 
984  // Loop over all vertices to begin with
985  while (curVertexItr != fVertexList.end()) {
986  // Dereference vertex
987  dcel2d::Vertex& vertex = *curVertexItr;
988 
989  bool outsideHull = !isInsideConvexHull(vertex);
990 
991  // Do we need to drop this vertex?
992  if (outsideHull) { curVertexItr = fVertexList.erase(curVertexItr); }
993  else
994  curVertexItr++;
995  }
996 
998  ComputeFaceArea();
999 
1000  std::cout << "Loop over beachline done, saved " << fConvexHullList.size()
1001  << " arcs, encountered " << nBadBreaks << " bad break points" << std::endl;
1002  std::cout << "-- started with " << nVerticesInitial << " vertices, found "
1003  << fVertexList.size() << " inside convex hull" << std::endl;
1004  }
1005 
1006  return;
1007  }
intermediate_table::iterator iterator
HalfEdge * getLastHalfEdge() const
Definition: DCEL.h:152
HalfEdge * getNextHalfEdge() const
Definition: DCEL.h:151
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:150
Face * getFace() const
Definition: DCEL.h:149
bool isInsideConvexHull(const dcel2d::Vertex &) const
Is a vertex inside the convex hull - meant to be a fast check.
Definition: Voronoi.cxx:1158
double computeArcVal(const double, const double, const IEvent *) const
double ComputeFaceArea()
Compute the area of the faces.
Definition: Voronoi.cxx:1270
EventUtilities fUtilities
Definition: Voronoi.h:224
std::pair< double, double > RootsPair
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:206
void mergeDegenerateVertices()
merge degenerate vertices (found by zero length edges)
Definition: Voronoi.cxx:1240
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:214
double computeBreak(const double, const IEvent *, const IEvent *, RootsPair &) const
const dcel2d::PointList & getConvexHull() const
recover the point list representing the convex hull
Definition: Voronoi.h:74
Vertex * getTargetVertex() const
Definition: DCEL.h:148
Eigen::Vector3f Coords
Definition: DCEL.h:44
const Coords & getCoords() const
Definition: DCEL.h:62
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:154
vertex reconstruction

Member Data Documentation

CircleEventList voronoi2d::VoronoiDiagram::fCircleEventList
private
BSTNodeList voronoi2d::VoronoiDiagram::fCircleNodeList
private
dcel2d::Coords voronoi2d::VoronoiDiagram::fConvexHullCenter
private

Definition at line 215 of file Voronoi.h.

Referenced by getConvexHull().

dcel2d::PointList voronoi2d::VoronoiDiagram::fConvexHullList
private
dcel2d::FaceList& voronoi2d::VoronoiDiagram::fFaceList
private
int voronoi2d::VoronoiDiagram::fNumBadCircles
mutableprivate

Definition at line 221 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), buildVoronoiDiagramBoost(), and computeCircleCenter().

dcel2d::PointList voronoi2d::VoronoiDiagram::fPointList
private
SiteEventList voronoi2d::VoronoiDiagram::fSiteEventList
private

Definition at line 210 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), buildVoronoiDiagramBoost(), and VoronoiDiagram().

EventUtilities voronoi2d::VoronoiDiagram::fUtilities
private

Definition at line 224 of file Voronoi.h.

Referenced by terminateInfiniteEdges().

double voronoi2d::VoronoiDiagram::fVoronoiDiagramArea
private

Definition at line 222 of file Voronoi.h.

Referenced by getVoronoiDiagramArea(), and VoronoiDiagram().

double voronoi2d::VoronoiDiagram::fXMax
private

Definition at line 218 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), and findBoundingBox().

double voronoi2d::VoronoiDiagram::fXMin
private

Definition at line 217 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), and findBoundingBox().

double voronoi2d::VoronoiDiagram::fYMax
private

Definition at line 220 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), and findBoundingBox().

double voronoi2d::VoronoiDiagram::fYMin
private

Definition at line 219 of file Voronoi.h.

Referenced by buildVoronoiDiagram(), and findBoundingBox().


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