Public Types | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
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 &, double &) const
 
bool computeCircleCenter3 (const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &, 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 31 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 151 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 149 of file Voronoi.h.

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

Definition at line 150 of file Voronoi.h.

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

Definition at line 95 of file Voronoi.h.

Definition at line 35 of file Voronoi.h.

Definition at line 34 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 51 of file Voronoi.cxx.

51  :
52  fHalfEdgeList(halfEdgeList),
53  fVertexList(vertexList),
54  fFaceList(faceList),
55  fXMin(0.),
56  fXMax(0.),
57  fYMin(0.),
58  fYMax(0.),
60 {
61  fHalfEdgeList.clear();
62  fVertexList.clear();
63  fFaceList.clear();
64  fPointList.clear();
65  fSiteEventList.clear();
66  fCircleEventList.clear();
67  fCircleNodeList.clear();
68  fConvexHullList.clear();
69 
70  // And the area
72 }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
double Area() const
Computes the area of the enclosed convext hull.
Definition: Voronoi.cxx:104
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:187
BSTNodeList fCircleNodeList
Definition: Voronoi.h:192
CircleEventList fCircleEventList
Definition: Voronoi.h:191
SiteEventList fSiteEventList
Definition: Voronoi.h:190
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:186
dcel2d::PointList fPointList
Definition: Voronoi.h:189
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
voronoi2d::VoronoiDiagram::~VoronoiDiagram ( )

Destructor.

Definition at line 76 of file Voronoi.cxx.

77 {
78 }

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.

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  {
119  if (point != lastPoint) area += 0.5 * crossProduct(center,lastPoint,point);
120 
121  lastPoint = point;
122  }
123 
124  return area;
125 }
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
dcel2d::PointList fPointList
Definition: Voronoi.h:189
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:91
def center(depos, point)
Definition: depos.py:117
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 321 of file Voronoi.cxx.

327 {
328  dcel2d::HalfEdge* halfEdge = NULL;
329  dcel2d::HalfEdge* twinEdge = NULL;
330 
331  if (boostEdgeToEdgeMap.find(edge) != boostEdgeToEdgeMap.end()) halfEdge = boostEdgeToEdgeMap.at(edge);
332  else
333  {
334  fHalfEdgeList.emplace_back();
335 
336  halfEdge = &fHalfEdgeList.back();
337 
338  boostEdgeToEdgeMap[edge] = halfEdge;
339  }
340 
341  if (boostEdgeToEdgeMap.find(twin) != boostEdgeToEdgeMap.end()) twinEdge = boostEdgeToEdgeMap.at(twin);
342  else
343  {
344  fHalfEdgeList.emplace_back();
345 
346  twinEdge = &fHalfEdgeList.back();
347 
348  boostEdgeToEdgeMap[twin] = twinEdge;
349  }
350 
351  // Do the primary half edge first
352  const boost::polygon::voronoi_vertex<double>* boostVertex = edge->vertex1();
353  dcel2d::Vertex* vertex = NULL;
354 
355  // note we can have a null vertex (infinite edge)
356  if (boostVertex)
357  {
358  if (boostVertexToVertexMap.find(boostVertex) == boostVertexToVertexMap.end())
359  {
360  dcel2d::Coords coords(boostVertex->y(),boostVertex->x(),0.);
361 
362  fVertexList.emplace_back(coords, halfEdge);
363 
364  vertex = &fVertexList.back();
365 
366  boostVertexToVertexMap[boostVertex] = vertex;
367  }
368  else vertex = boostVertexToVertexMap.at(boostVertex);
369  }
370 
371  const boost::polygon::voronoi_cell<double>* boostCell = edge->cell();
372  dcel2d::Face* face = NULL;
373 
374  if (boostCellToFaceMap.find(boostCell) == boostCellToFaceMap.end())
375  {
376  dcel2d::PointList::const_iterator pointItr = pointList.begin();
377  int pointIdx = boostCell->source_index();
378 
379  std::advance(pointItr, pointIdx);
380 
381  const dcel2d::Point& point = *pointItr;
382  dcel2d::Coords coords(std::get<0>(point),std::get<1>(point),0.);
383 
384  fFaceList.emplace_back(halfEdge,coords,std::get<2>(point));
385 
386  face = &fFaceList.back();
387 
388  boostCellToFaceMap[boostCell] = face;
389  }
390 
391  halfEdge->setTargetVertex(vertex);
392  halfEdge->setFace(face);
393  halfEdge->setTwinHalfEdge(twinEdge);
394 
395  // For the prev/next half edges we can have two cases, so check:
396  if (boostEdgeToEdgeMap.find(edge->next()) != boostEdgeToEdgeMap.end())
397  {
398  dcel2d::HalfEdge* nextEdge = boostEdgeToEdgeMap.at(edge->next());
399 
400  halfEdge->setNextHalfEdge(nextEdge);
401  nextEdge->setLastHalfEdge(halfEdge);
402  }
403 
404  if (boostEdgeToEdgeMap.find(edge->prev()) != boostEdgeToEdgeMap.end())
405  {
406  dcel2d::HalfEdge* lastEdge = boostEdgeToEdgeMap.at(edge->prev());
407 
408  halfEdge->setLastHalfEdge(lastEdge);
409  lastEdge->setNextHalfEdge(halfEdge);
410  }
411 
412  return;
413 }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
intermediate_table::const_iterator const_iterator
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:187
void setLastHalfEdge(HalfEdge *last)
Definition: DCEL.h:171
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:169
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:186
void setFace(Face *face)
Definition: DCEL.h:168
void setNextHalfEdge(HalfEdge *next)
Definition: DCEL.h:170
Eigen::Vector3f Coords
Definition: DCEL.h:46
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:167
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 133 of file Voronoi.cxx.

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

Definition at line 265 of file Voronoi.cxx.

266 {
267  // Insure all the local data structures have been cleared
268  fHalfEdgeList.clear();
269  fVertexList.clear();
270  fFaceList.clear();
271  fPointList.clear();
272  fSiteEventList.clear();
273  fCircleEventList.clear();
274  fCircleNodeList.clear();
275  fNumBadCircles = 0;
276 
277  std::cout << "******************************************************************************************************************" << std::endl;
278  std::cout << "******************************************************************************************************************" << std::endl;
279  std::cout << "******************************************************************************************************************" << std::endl;
280  std::cout << "==> # input points: " << pointList.size() << std::endl;
281 
282  // Construct out voronoi diagram
283  boost::polygon::voronoi_diagram<double> vd;
284  boost::polygon::construct_voronoi(pointList.begin(),pointList.end(),&vd);
285 
286  // Make maps for translating from boost to me (or we can rewrite our code in boost... for now maps)
287  using BoostEdgeToEdgeMap = std::map<const boost::polygon::voronoi_edge<double>*, dcel2d::HalfEdge*>;
288  using BoostVertexToVertexMap = std::map<const boost::polygon::voronoi_vertex<double>*, dcel2d::Vertex*>;
289  using BoostCellToFaceMap = std::map<const boost::polygon::voronoi_cell<double>*, dcel2d::Face*>;
290 
291  BoostEdgeToEdgeMap boostEdgeToEdgeMap;
292  BoostVertexToVertexMap boostVertexToVertexMap;
293  BoostCellToFaceMap boostCellToFaceMap;
294 
295  // Loop over the edges
296  for(const auto& edge : vd.edges())
297  {
298  const boost::polygon::voronoi_edge<double>* twin = edge.twin();
299 
300  boostTranslation(pointList, &edge, twin, boostEdgeToEdgeMap, boostVertexToVertexMap, boostCellToFaceMap);
301  boostTranslation(pointList, twin, &edge, boostEdgeToEdgeMap, boostVertexToVertexMap, boostCellToFaceMap);
302  }
303 
304  //std::cout << "==> Found " << nOpenFaces << " open faces from total of " << fFaceList.size() << std::endl;
305  //for(const auto& edgeCount : edgeCountMap) std::cout << " -> all edges, # edges: " << edgeCount.first << ", count: " << edgeCount.second << std::endl;
306  //for(const auto& edgeCount : openCountMap) std::cout << " -> open edges, # edges: " << edgeCount.first << ", count: " << edgeCount.second << std::endl;
307  std::cout << "==> Boost returns " << fHalfEdgeList.size() << " edges, " << fFaceList.size() << " faces, " << fVertexList.size() << " vertices " << std::endl;
308  std::cout << " " << vd.edges().size() << " edges, " << vd.cells().size() << " faces, " << vd.vertices().size() << " vertices" << std::endl;
309  std::cout << "******************************************************************************************************************" << std::endl;
310  std::cout << "******************************************************************************************************************" << std::endl;
311  std::cout << "******************************************************************************************************************" << std::endl;
312 
313  // Clear internal containers that are no longer useful
314  fSiteEventList.clear();
315  fCircleEventList.clear();
316  fCircleNodeList.clear();
317 
318  return;
319 }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:187
BSTNodeList fCircleNodeList
Definition: Voronoi.h:192
CircleEventList fCircleEventList
Definition: Voronoi.h:191
SiteEventList fSiteEventList
Definition: Voronoi.h:190
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:186
dcel2d::PointList fPointList
Definition: Voronoi.h:189
void boostTranslation(const dcel2d::PointList &, const boost::polygon::voronoi_edge< double > *, const boost::polygon::voronoi_edge< double > *, BoostEdgeToEdgeMap &, BoostVertexToVertexMap &, BoostCellToFaceMap &)
Definition: Voronoi.cxx:321
std::map< const boost::polygon::voronoi_edge< double > *, dcel2d::HalfEdge * > BoostEdgeToEdgeMap
Translate boost to dcel.
Definition: Voronoi.h:149
std::map< const boost::polygon::voronoi_vertex< double > *, dcel2d::Vertex * > BoostVertexToVertexMap
Definition: Voronoi.h:150
std::map< const boost::polygon::voronoi_cell< double > *, dcel2d::Face * > BoostCellToFaceMap
Definition: Voronoi.h:151
QTextStream & endl(QTextStream &s)
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 690 of file Voronoi.cxx.

696 {
697  // The method is to translate the three points to a system where the first point is at the origin. Then we
698  // are looking for a circle that passes through the origin and the two remaining (translated) points. In
699  // this mode the circle radius is the distance from the origin to the circle center which simplifies the
700  // calculation.
701  double xCoord = p1[0];
702  double yCoord = p1[1];
703 
704  double x2 = p2[0] - xCoord;
705  double y2 = p2[1] - yCoord;
706  double x3 = p3[0] - xCoord;
707  double y3 = p3[1] - yCoord;
708 
709  double det = x2 * y3 - x3 * y2;
710 
711  // Points are colinear so cannot make a circle
712  // Or, if negative then the midpoint is "left" of line between first and third points meaning the
713  // circle curvature is the "wrong" way for making a circle event
714  if (det <= 0.) // std::numeric_limits<double>::epsilon())
715  //if (!(std::abs(det) > 0.)) // std::numeric_limits<double>::epsilon())
716  {
717  if (det > -std::numeric_limits<double>::epsilon())
718  std::cout << " --->Circle failure, det: " << det << ", mid x: " << p2[0] << ", y: " << p2[1]
719  << ", l x: " << p1[0] << ", y: " << p1[1]
720  << ", r x: " << p3[0] << ", y: " << p3[1] << std::endl;
721 
722  return false;
723  }
724 
725  double p2sqr = x2 * x2 + y2 * y2;
726  double p3sqr = x3 * x3 + y3 * y3;
727 
728  double cxpr = 0.5 * (y3 * p2sqr - y2 * p3sqr) / det;
729  double cypr = 0.5 * (x2 * p3sqr - x3 * p2sqr) / det;
730 
731  radius = std::sqrt(cxpr * cxpr + cypr * cypr);
732  center[0] = cxpr + xCoord;
733  center[1] = cypr + yCoord;
734  center[2] = 0.;
735 
736  // So... roundoff error can cause degenerate circles to get missed
737  // We need to attack that problem by calculating the radius all possible
738  // ways and then take the largest...
739  dcel2d::Coords p1Rad = p1 - center;
740  dcel2d::Coords p2Rad = p2 - center;
741  dcel2d::Coords p3Rad = p3 - center;
742 
743  std::vector<float> radSqrVec;
744 
745  radSqrVec.push_back(p1Rad.norm());
746  radSqrVec.push_back(p2Rad.norm());
747  radSqrVec.push_back(p3Rad.norm());
748 
749  double maxRadius = *std::max_element(radSqrVec.begin(),radSqrVec.end());
750 
751  delta = std::max(5.e-7, maxRadius - radius);
752 
753  if (radius > 1000.)
754  {
755 // 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;
756  fNumBadCircles++;
757  }
758 
759  return true;
760 }
const double e
static int max(int a, int b)
def center(depos, point)
Definition: depos.py:117
Eigen::Vector3f Coords
Definition: DCEL.h:46
QTextStream & endl(QTextStream &s)
bool voronoi2d::VoronoiDiagram::computeCircleCenter2 ( const dcel2d::Coords p1,
const dcel2d::Coords p2,
const dcel2d::Coords p3,
dcel2d::Coords center,
double &  radius,
double &  delta 
) const
private

Definition at line 762 of file Voronoi.cxx.

768 {
769  // Compute the circle center as the intersection of the two perpendicular bisectors of rays between the points
770  double slope12 = (p2[1] - p1[1]) / (p2[0] - p1[0]);
771  double slope32 = (p3[1] - p2[1]) / (p3[0] - p2[0]);
772 
773  if (std::abs(slope12 - slope32) <= std::numeric_limits<double>::epsilon())
774  {
775  std::cout << " >>>> Matching slopes! points: (" << p1[0] << "," << p1[1] << "), ("<< p2[0] << "," << p2[1] << "), ("<< p3[0] << "," << p3[1] << ")" << std::endl;
776 
777  return false;
778  }
779 
780  center[0] = (slope12 * slope32 * (p3[1] - p1[1]) + slope12 * (p2[0] + p3[0]) - slope32 * (p1[0] + p2[0])) / (2. * (slope12 - slope32));
781  center[1] = 0.5 * (p1[1] + p2[1]) - (center[0] - 0.5 * (p1[0] + p2[0])) / slope12;
782  center[2] = 0.;
783  radius = std::sqrt(std::pow((p2[0] - center[0]),2) + std::pow((p2[1] - center[1]),2));
784 
785  if (radius > 100.)
786  {
787  std::cout << " ***> Rad2 = " << radius << ", circ x,y: " << center[0] << "," << center[1] << ", p1: " << p1[0] << "," << p1[1] << ", p2: " << p2[0] << "," << p2[1] << ", p3: " << p3[0] << ", " << p3[1] << std::endl;
788  }
789 
790  return true;
791 }
constexpr T pow(T x)
Definition: pow.h:72
T abs(T value)
def center(depos, point)
Definition: depos.py:117
QTextStream & endl(QTextStream &s)
bool voronoi2d::VoronoiDiagram::computeCircleCenter3 ( const dcel2d::Coords p1,
const dcel2d::Coords p2,
const dcel2d::Coords p3,
dcel2d::Coords center,
double &  radius,
double &  delta 
) const
private

Definition at line 793 of file Voronoi.cxx.

799 {
800  // Yet another bisector method to calculate the circle center...
801  double temp = p2[0] * p2[0] + p2[1] * p2[1];
802  double p1p2 = (p1[0] * p1[0] + p1[1] * p1[1] - temp) / 2.0;
803  double p2p3 = (temp - p3[0] * p3[0] - p3[1] * p3[1]) / 2.0;
804  double det = (p1[0] - p2[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p2[1]);
805 
806  if (std::abs(det) < 10. * std::numeric_limits<double>::epsilon())
807  {
808  std::cout << " >>>> Determinant zero! points: (" << p1[0] << "," << p1[1] << "), ("<< p2[0] << "," << p2[1] << "), ("<< p3[0] << "," << p3[1] << ")" << std::endl;
809 
810  return false;
811  }
812 
813  det = 1. / det;
814 
815  center[0] = (p1p2 * (p2[1] - p3[1]) - p2p3 * (p1[1] - p2[1])) * det;
816  center[1] = (p2p3 * (p1[0] - p2[0]) - p1p2 * (p2[0] - p3[0])) * det;
817  center[2] = 0.;
818 
819  radius = std::sqrt(std::pow((p1[0] - center[0]),2) + std::pow((p1[1] - center[1]),2));
820 
821  if (radius > 100.)
822  {
823  std::cout << " ***> Rad3 = " << radius << ", circ x,y: " << center[0] << "," << center[1] << ", p1: " << p1[0] << "," << p1[1] << ", p2: " << p2[0] << "," << p2[1] << ", p3: " << p3[0] << ", " << p3[1] << std::endl;
824  }
825 
826  return true;
827 }
constexpr T pow(T x)
Definition: pow.h:72
T abs(T value)
def center(depos, point)
Definition: depos.py:117
QTextStream & endl(QTextStream &s)
double voronoi2d::VoronoiDiagram::ComputeFaceArea ( )
private

Compute the area of the faces.

Definition at line 1215 of file Voronoi.cxx.

1216 {
1217  // Compute the area by taking advantage of
1218  // 1) the ability to decompose a convex hull into triangles,
1219  // 2) the ability to use the cross product to calculate the area
1220  // So the idea is to loop through all the faces and then follow the edges
1221  // around the face to compute the area of the face.
1222  // Note that a special case are the "infinite faces" which lie on the
1223  // convex hull of the event. Skip these for now...
1224 
1225  double totalArea(0.);
1226  int nNonInfiniteFaces(0);
1227  double smallestArea(std::numeric_limits<double>::max());
1228  double largestArea(0.);
1229 
1230  std::vector<std::pair<double,const dcel2d::Face*>> areaFaceVec;
1231 
1232  areaFaceVec.reserve(fFaceList.size());
1233 
1234  for(auto& face : fFaceList)
1235  {
1236 // const dcel2d::Coords& faceCoords = face.getCoords();
1237  const dcel2d::HalfEdge* halfEdge = face.getHalfEdge();
1238  double faceArea(0.);
1239  int numEdges(0);
1240  bool doNext = true;
1241 
1242  dcel2d::Coords faceCenter(0.,0.,0.);
1243 
1244  while(doNext)
1245  {
1246  if (halfEdge->getTargetVertex())
1247  faceCenter += halfEdge->getTargetVertex()->getCoords();
1248 
1249  numEdges++;
1250 
1251  halfEdge = halfEdge->getNextHalfEdge();
1252 
1253  if (!halfEdge)
1254  {
1255  faceArea = std::numeric_limits<double>::max();
1256  doNext = false;
1257  }
1258 
1259  if (halfEdge == face.getHalfEdge()) doNext = false;
1260  }
1261 
1262  faceCenter /= numEdges;
1263 
1264  halfEdge = face.getHalfEdge();
1265  doNext = true;
1266 
1267  while(doNext)
1268  {
1269  const dcel2d::HalfEdge* twinEdge = halfEdge->getTwinHalfEdge();
1270 
1271  if (!halfEdge->getTargetVertex() || !twinEdge->getTargetVertex())
1272  {
1273  faceArea = std::numeric_limits<double>::max();
1274  break;
1275  }
1276 
1277  // Recover the two vertex points
1278  const dcel2d::Coords& p1 = halfEdge->getTargetVertex()->getCoords();
1279  const dcel2d::Coords& p2 = twinEdge->getTargetVertex()->getCoords();
1280 
1281  // Define a quick 2D cross product here since it will used quite a bit!
1282  double dp1p0X = p1[0] - faceCenter[0];
1283  double dp1p0Y = p1[1] - faceCenter[1];
1284  double dp2p0X = p2[0] - faceCenter[0];
1285  double dp2p0Y = p2[1] - faceCenter[1];
1286 
1287  //faceArea += dp1p0X * dp2p0Y - dp1p0Y * dp2p0X;
1288  double crossProduct = dp1p0X * dp2p0Y - dp1p0Y * dp2p0X;
1289 
1290  faceArea += crossProduct;
1291 
1292  if (crossProduct < 0.)
1293  {
1294  dcel2d::Coords edgeVec = p1 - p2;
1295  std::cout << "--- negative cross: " << crossProduct << ", edgeLen: " << edgeVec.norm() << ", x/y: " << edgeVec[0] << "/" << edgeVec[1] << std::endl;
1296  }
1297 
1298 // numEdges++;
1299 
1300  halfEdge = halfEdge->getNextHalfEdge();
1301 
1302  if (!halfEdge)
1303  {
1304  faceArea = std::numeric_limits<double>::max();
1305  break;
1306  }
1307 
1308  if (halfEdge == face.getHalfEdge()) doNext = false;
1309  }
1310 
1311  areaFaceVec.emplace_back(faceArea,&face);
1312 
1313  if (faceArea < std::numeric_limits<double>::max() && faceArea > 0.)
1314  {
1315  nNonInfiniteFaces++;
1316  totalArea += faceArea;
1317  smallestArea = std::min(faceArea,smallestArea);
1318  largestArea = std::max(faceArea,largestArea);
1319  }
1320 
1321  if (faceArea < 1.e-4) std::cout << "---> face area <= 0: " << faceArea << ", with " << numEdges << " edges" << std::endl;
1322 
1323  face.setFaceArea(faceArea);
1324  }
1325 
1326  // Calculate a truncated mean...
1327  std::sort(areaFaceVec.begin(),areaFaceVec.end(),[](const auto& left, const auto& right){return left.first < right.first;});
1328 
1329  std::vector<std::pair<double,const dcel2d::Face*>>::iterator firstItr = std::find_if(areaFaceVec.begin(),areaFaceVec.end(),[](const auto& val){return val.first > 0.;});
1330  std::vector<std::pair<double,const dcel2d::Face*>>::iterator lastItr = std::find_if(areaFaceVec.begin(),areaFaceVec.end(),[](const auto& val){return !(val.first < std::numeric_limits<double>::max());});
1331 
1332  size_t nToKeep = 0.8 * std::distance(firstItr,lastItr);
1333 
1334  std::cout << ">>>>> nToKeep: " << nToKeep << ", last non infinite entry: " << std::distance(areaFaceVec.begin(),lastItr) << std::endl;
1335 
1336  double totalTruncArea = std::accumulate(firstItr,firstItr+nToKeep,0.,[](auto sum, const auto& val){return sum+val.first;});
1337  double aveTruncArea = totalTruncArea / double(nToKeep);
1338 
1339  if (nNonInfiniteFaces > 0) std::cout << ">>>> Face area for " << nNonInfiniteFaces << ", ave area: " << totalArea / nNonInfiniteFaces << ", ave trunc area: " << aveTruncArea << ", ratio: " << totalTruncArea / totalArea << ", smallest: " << smallestArea << ", largest: " << largestArea << std::endl;
1340  else std::cout << ">>>>> there are no non infinite faces" << std::endl;
1341 
1342  return totalArea;
1343 }
HalfEdge * getNextHalfEdge() const
Definition: DCEL.h:164
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:163
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:187
const double e
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
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:91
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Vertex * getTargetVertex() const
Definition: DCEL.h:161
Eigen::Vector3f Coords
Definition: DCEL.h:46
const Coords & getCoords() const
Definition: DCEL.h:69
QTextStream & endl(QTextStream &s)
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 91 of file Voronoi.cxx.

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 1346 of file Voronoi.cxx.

1347 {
1348  // Find extremes in x to start
1349  std::pair<dcel2d::VertexList::const_iterator,dcel2d::VertexList::const_iterator> minMaxItrX = std::minmax_element(vertexList.begin(),vertexList.end(),[](const auto& left, const auto& right){return left.getCoords()[0] < right.getCoords()[0];});
1350 
1351  fXMin = minMaxItrX.first->getCoords()[0];
1352  fXMax = minMaxItrX.second->getCoords()[0];
1353 
1354  // To get the extremes in y we need to make a pass through the list
1355  std::pair<dcel2d::VertexList::const_iterator,dcel2d::VertexList::const_iterator> minMaxItrY = std::minmax_element(vertexList.begin(),vertexList.end(),[](const auto& left, const auto& right){return left.getCoords()[1] < right.getCoords()[1];});
1356 
1357  fYMin = minMaxItrY.first->getCoords()[1];
1358  fYMax = minMaxItrY.second->getCoords()[1];
1359 
1360  return;
1361 }
double voronoi2d::VoronoiDiagram::findNearestDistance ( const dcel2d::Point point) const

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

Definition at line 1424 of file Voronoi.cxx.

1425 {
1426  double closestDistance;
1427 
1428  findNearestEdge(point,closestDistance);
1429 
1430  return closestDistance;
1431 }
PointPair findNearestEdge(const dcel2d::Point &, double &) const
Given an input Point, find the nearest edge.
Definition: Voronoi.cxx:1363
VoronoiDiagram::PointPair voronoi2d::VoronoiDiagram::findNearestEdge ( const dcel2d::Point point,
double &  closestDistance 
) const

Given an input Point, find the nearest edge.

Definition at line 1363 of file Voronoi.cxx.

1364 {
1365  // The idea is to find the nearest edge of the convex hull, defined by
1366  // two adjacent vertices of the hull, to the input point.
1367  // As near as I can tell, the best way to do this is to apply brute force...
1368  // Idea will be to iterate over pairs of points
1369  dcel2d::PointList::const_iterator curPointItr = fPointList.begin();
1370  dcel2d::Point prevPoint = *curPointItr++;
1371  dcel2d::Point curPoint = *curPointItr;
1372 
1373  // Set up the winner
1374  PointPair closestEdge(prevPoint,curPoint);
1375 
1376  closestDistance = std::numeric_limits<double>::max();
1377 
1378  // curPointItr is meant to point to the second point
1379  while(curPointItr != fPointList.end())
1380  {
1381  if (curPoint != prevPoint)
1382  {
1383  // Dereference some stuff
1384  double xPrevToPoint = (std::get<0>(point) - std::get<0>(prevPoint));
1385  double yPrevToPoint = (std::get<1>(point) - std::get<1>(prevPoint));
1386  double xPrevToCur = (std::get<0>(curPoint) - std::get<0>(prevPoint));
1387  double yPrevToCur = (std::get<1>(curPoint) - std::get<1>(prevPoint));
1388  double edgeLength = std::sqrt(xPrevToCur * xPrevToCur + yPrevToCur * yPrevToCur);
1389 
1390  // Find projection onto convex hull edge
1391  double projection = ((xPrevToPoint * xPrevToCur) + (yPrevToPoint * yPrevToCur)) / edgeLength;
1392 
1393  // DOCA point
1394  dcel2d::Point docaPoint(std::get<0>(prevPoint) + projection * xPrevToCur / edgeLength,
1395  std::get<1>(prevPoint) + projection * yPrevToCur / edgeLength, 0);
1396 
1397  if (projection > edgeLength) docaPoint = curPoint;
1398  if (projection < 0) docaPoint = prevPoint;
1399 
1400  double xDocaDist = std::get<0>(point) - std::get<0>(docaPoint);
1401  double yDocaDist = std::get<1>(point) - std::get<1>(docaPoint);
1402  double docaDist = xDocaDist * xDocaDist + yDocaDist * yDocaDist;
1403 
1404  if (docaDist < closestDistance)
1405  {
1406  closestEdge = PointPair(prevPoint,curPoint);
1407  closestDistance = docaDist;
1408  }
1409  }
1410 
1411  prevPoint = curPoint;
1412  curPoint = *curPointItr++;
1413  }
1414 
1415  closestDistance = std::sqrt(closestDistance);
1416 
1417  // Convention is convex hull vertices sorted in counter clockwise fashion so if the point
1418  // lays to the left of the nearest edge then it must be an interior point
1419  if (isLeft(closestEdge.first,closestEdge.second,point)) closestDistance = -closestDistance;
1420 
1421  return closestEdge;
1422 }
intermediate_table::const_iterator const_iterator
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
static int max(int a, int b)
dcel2d::PointList fPointList
Definition: Voronoi.h:189
std::pair< dcel2d::Point, dcel2d::Point > PointPair
Definition: Voronoi.h:34
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:82
const dcel2d::PointList& voronoi2d::VoronoiDiagram::getConvexHull ( ) const
inline

recover the point list representing the convex hull

Definition at line 76 of file Voronoi.h.

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

this function recovers the convex hull

Definition at line 963 of file Voronoi.cxx.

964 {
965  // Assume the input node is the top of the binary search tree and represents
966  // the beach line at the end of the sweep algorithm
967  // The convex hull will then be the leaf elements along the beach line.
968  // Note that this algorithm will give you the convex hull in a clockwise manner
969  if (topNode)
970  {
971  const BSTNode* node = topNode;
972 
973  // Initialize the center
974  fConvexHullCenter = dcel2d::Coords(0.,0.,0.);
975 
976  // Run down the left branches to find the right most leaf
977  // We do it this way to make sure we get a CCW convex hull
978  while(node->getRightChild()) node = node->getRightChild();
979 
980  // Include a check on convexity...
981  Eigen::Vector3f prevVec(0.,0.,0.);
982  dcel2d::Coords lastPoint(0.,0.,0.);
983 
984  // Now we are going to traverse across the beach line and process the remaining leaves
985  // This will identify the convex hull
986  while(node)
987  {
988  if (!node->getLeftChild() && !node->getRightChild())
989  {
990  // Add point to the convex hull list
991  fConvexHullList.emplace_back(node->getEvent()->getPoint());
992 
993  // Mark the face as on the convex hull
994  node->getFace()->setOnConvexHull();
995 
996  dcel2d::Coords nextPoint = node->getEvent()->getCoords();
997  Eigen::Vector3f curVec = nextPoint - lastPoint;
998 
999  curVec.normalize();
1000 
1001  double dotProd = prevVec.dot(curVec);
1002 
1003  std::cout << "--> lastPoint: " << lastPoint[0] << "/" << lastPoint[1] << ", tan: " << std::atan2(lastPoint[1],lastPoint[0]) << ", curPoint: " << nextPoint[0] << "/" << nextPoint[1] << ", tan: " << std::atan2(nextPoint[1],nextPoint[0]) << ", dot: " << dotProd << std::endl;
1004 
1005  prevVec = curVec;
1006  lastPoint = nextPoint;
1007  }
1008 
1009  node = node->getPredecessor();
1010  }
1011 
1012  // Annoyingly, our algorithm does not contain only the convex hull points and so we need to skim out the renegades...
1014 
1015  for(const auto& edgePoint : fConvexHullList) localList.emplace_back(std::get<0>(edgePoint),std::get<1>(edgePoint),std::get<2>(edgePoint));
1016 
1017  // Sort the point vec by increasing x, then increase y
1018  localList.sort([](const auto& left, const auto& right){return (std::abs(std::get<0>(left) - std::get<0>(right)) > std::numeric_limits<float>::epsilon()) ? std::get<0>(left) < std::get<0>(right) : std::get<1>(left) < std::get<1>(right);});
1019 
1020  // Why do I need to do this?
1021  lar_cluster3d::ConvexHull convexHull(localList);
1022 
1023  // Clear the convex hull list...
1024 // fConvexHullList.clear();
1025 
1026  std::cout << "~~~>> there are " << convexHull.getConvexHull().size() << " convex hull points and " << fConvexHullList.size() << " infinite cells" << std::endl;
1027 
1028  // Now rebuild it
1029  for(const auto& hullPoint : convexHull.getConvexHull())
1030  {
1031 // fConvexHullList.emplace_back(std::get<0>(hullPoint),std::get<1>(hullPoint),std::get<2>(hullPoint));
1032 
1033  std::cout << "~~~ Convex hull Point: " << std::get<0>(hullPoint) << ", " << std::get<1>(hullPoint) << std::endl;
1034  }
1035  }
1036 
1037  return;
1038 }
std::list< Point > PointList
The list of the projected points.
Definition: ConvexHull.h:34
T abs(T value)
dcel2d::Coords fConvexHullCenter
Definition: Voronoi.h:195
ConvexHull class definiton.
Definition: ConvexHull.h:27
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
Eigen::Vector3f Coords
Definition: DCEL.h:46
QTextStream & endl(QTextStream &s)
VoronoiDiagram::PointPair voronoi2d::VoronoiDiagram::getExtremePoints ( ) const

Given an input Point, find the nearest edge.

Definition at line 1040 of file Voronoi.cxx.

1041 {
1042  dcel2d::PointList::const_iterator nextPointItr = fConvexHullList.begin();
1043  dcel2d::PointList::const_iterator firstPointItr = nextPointItr++;
1044 
1045  float maxSeparation(0.);
1046 
1047  PointPair extremePoints(dcel2d::Point(0,0,NULL),dcel2d::Point(0,0,NULL));
1048 
1049  while(nextPointItr != fConvexHullList.end())
1050  {
1051  // Get a vector representing the edge from the first to the current next point
1052  dcel2d::Point firstPoint = *firstPointItr++;
1053  dcel2d::Point nextPoint = *nextPointItr;
1054  Eigen::Vector2f firstEdge(std::get<0>(*firstPointItr) - std::get<0>(firstPoint), std::get<1>(*firstPointItr) - std::get<1>(firstPoint));
1055 
1056  // normalize it
1057  firstEdge.normalize();
1058 
1059  dcel2d::PointList::const_iterator endPointItr = nextPointItr;
1060 
1061  while(++endPointItr != fConvexHullList.end())
1062  {
1063  dcel2d::Point endPoint = *endPointItr;
1064  Eigen::Vector2f nextEdge(std::get<0>(endPoint) - std::get<0>(nextPoint), std::get<1>(endPoint) - std::get<1>(nextPoint));
1065 
1066  // normalize it
1067  nextEdge.normalize();
1068 
1069  // Have we found the turnaround point?
1070  if (firstEdge.dot(nextEdge) < 0.)
1071  {
1072  Eigen::Vector2f separation(std::get<0>(nextPoint) - std::get<0>(firstPoint), std::get<1>(nextPoint) - std::get<1>(firstPoint));
1073  float separationDistance = separation.norm();
1074 
1075  if (separationDistance > maxSeparation)
1076  {
1077  extremePoints.first = firstPoint;
1078  extremePoints.second = nextPoint;
1079  maxSeparation = separationDistance;
1080  }
1081 
1082  // Regardless of thise being the maximum distance we have hit a turnaround point so
1083  // we need to break out of this loop
1084  break;
1085  }
1086 
1087  nextPointItr = endPointItr;
1088  nextPoint = endPoint;
1089  }
1090 
1091  // If we have hit the end of the convex hull without finding a turnaround point then we are not
1092  // going to find one so break out of the main loop
1093  if (endPointItr == fConvexHullList.end()) break;
1094 
1095  // Need to make sure we don't overrun the next point
1096  if (firstPointItr == nextPointItr) nextPointItr++;
1097  }
1098 
1099  return extremePoints;
1100 }
intermediate_table::const_iterator const_iterator
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
std::pair< dcel2d::Point, dcel2d::Point > PointPair
Definition: Voronoi.h:34
const dcel2d::FaceList& voronoi2d::VoronoiDiagram::getFaceList ( ) const
inline

Recover the list of faces.

Definition at line 61 of file Voronoi.h.

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

Recover the list of vertices.

Definition at line 66 of file Voronoi.h.

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

recover the area of the convex hull

Definition at line 71 of file Voronoi.h.

71 {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 472 of file Voronoi.cxx.

475 {
476  BSTNode* circleNode = circleEvent->getBSTNode();
477  BSTNode* arcNode = circleNode->getAssociated();
478 
479  // Recover the half edges for the breakpoints either side of the arc we're removing
480  dcel2d::HalfEdge* leftHalfEdge = arcNode->getPredecessor()->getHalfEdge();
481  dcel2d::HalfEdge* rightHalfEdge = arcNode->getSuccessor()->getHalfEdge();
482 
483  if (leftHalfEdge->getTwinHalfEdge()->getFace() != rightHalfEdge->getFace())
484  {
485  std::cout << ">>>> Face mismatch in circle handling, left face: " << leftHalfEdge->getFace() << ", left twin: " << leftHalfEdge->getTwinHalfEdge()->getFace() << ", right: " << rightHalfEdge->getFace() << ", right twin: " << rightHalfEdge->getTwinHalfEdge()->getFace() << ", arc face: " << arcNode->getFace() << std::endl;
486  }
487 
488  // Create the new vertex point
489  // Don't forget we need to swap coordinates when returning to the outside world
490  dcel2d::Coords vertexPos(circleEvent->circleCenter());
491 
492  fVertexList.push_back(dcel2d::Vertex(vertexPos,leftHalfEdge->getTwinHalfEdge()));
493 
494  dcel2d::Vertex* vertex = &fVertexList.back();
495 
496  // The edges we obtained "emanate" from the new vertex point,
497  // their twins will point to it
498  leftHalfEdge->getTwinHalfEdge()->setTargetVertex(vertex);
499  rightHalfEdge->getTwinHalfEdge()->setTargetVertex(vertex);
500 
501  // Remove the arc which will return the new breakpoint
502  // NOTE: invalidation of any possible circle events occurs in the call to this routine
503  BSTNode* newBreakPoint = beachLine.removeLeaf(arcNode);
504 
505  // Now create edges associated with the new break point
506  fHalfEdgeList.push_back(dcel2d::HalfEdge());
507 
508  dcel2d::HalfEdge* halfEdgeOne = &fHalfEdgeList.back();
509 
510  fHalfEdgeList.push_back(dcel2d::HalfEdge());
511 
512  dcel2d::HalfEdge* halfEdgeTwo = &fHalfEdgeList.back();
513 
514  // Associate the first edge with the new break point
515  newBreakPoint->setHalfEdge(halfEdgeTwo);
516 
517  // These are twins
518  halfEdgeOne->setTwinHalfEdge(halfEdgeTwo);
519  halfEdgeTwo->setTwinHalfEdge(halfEdgeOne);
520 
521  // The second points to the vertex we just made
522  halfEdgeTwo->setTargetVertex(vertex);
523  vertex->setHalfEdge(halfEdgeOne);
524 
525  // halfEdgeTwo points to the vertex, face to left, so pairs with
526  // the leftHalfEdge (leaving the vertex, face to left)
527  halfEdgeTwo->setNextHalfEdge(leftHalfEdge);
528  leftHalfEdge->setLastHalfEdge(halfEdgeTwo);
529  halfEdgeTwo->setFace(leftHalfEdge->getFace());
530 
531  // halfEdgeOne emanates from the vertex, face to left, so pairs with
532  // the twin of the rightHalfEdge (pointing to vertex, face to left)
533  halfEdgeOne->setLastHalfEdge(rightHalfEdge->getTwinHalfEdge());
534  rightHalfEdge->getTwinHalfEdge()->setNextHalfEdge(halfEdgeOne);
535  halfEdgeOne->setFace(rightHalfEdge->getTwinHalfEdge()->getFace());
536 
537  // Finally, the twin of the leftHalfEdge points to the vertex (face to left)
538  // and will pair with the rightHalfEdge emanating from the vertex
539  // In this case they should already be sharing the same face
540  rightHalfEdge->setLastHalfEdge(leftHalfEdge->getTwinHalfEdge());
541  leftHalfEdge->getTwinHalfEdge()->setNextHalfEdge(rightHalfEdge);
542 
543  // We'll try to make circle events with the remnant arcs so get the pointers now
544  // Note that we want the former left and right arcs to be the middle arcs in this case
545  BSTNode* leftArc = newBreakPoint->getPredecessor();
546  BSTNode* rightArc = newBreakPoint->getSuccessor();
547 
548  // Look for a new circle candidates
549  // In this case, we'd like the right arc to be the middle of the right circle,
550  // the left arc to be the middle of the left circle, hence the logic below
551  makeRightCircleEvent(eventQueue, leftArc, circleEvent->xPos());
552  makeLeftCircleEvent(eventQueue, rightArc, circleEvent->xPos());
553 
554  return;
555 }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
void setHalfEdge(HalfEdge *half)
Definition: DCEL.h:81
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:163
Face * getFace() const
Definition: DCEL.h:162
void makeLeftCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:557
void setLastHalfEdge(HalfEdge *last)
Definition: DCEL.h:171
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:169
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:186
void makeRightCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:606
void setFace(Face *face)
Definition: DCEL.h:168
void setNextHalfEdge(HalfEdge *next)
Definition: DCEL.h:170
Eigen::Vector3f Coords
Definition: DCEL.h:46
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:167
QTextStream & endl(QTextStream &s)
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 415 of file Voronoi.cxx.

418 {
419  // Insert the new site event into the beach line and recover the leaf for the
420  // new arc in the beach line
421  // NOTE: invalidation of any possible circle events occurs in the call to this routine
422  BSTNode* newLeaf = beachLine.insertNewLeaf(siteEvent);
423 
424  // Create a new vertex for each site event
425  fFaceList.emplace_back(dcel2d::Face(NULL,siteEvent->getCoords(),std::get<2>(siteEvent->getPoint())));
426 
427  dcel2d::Face* face = &fFaceList.back();
428 
429  newLeaf->setFace(face);
430 
431  // If we are the first site added to the BST then we are done
432  if (!(newLeaf->getPredecessor() || newLeaf->getSuccessor())) return;
433 
434  // So, now we deal with creating the edges that will be mapped out by the two breakpoints as they
435  // move with the beachline. Note that this is a single edge pair (edge and its twin) between the
436  // two breakpoints that have been created.
437  fHalfEdgeList.push_back(dcel2d::HalfEdge());
438 
439  dcel2d::HalfEdge* halfEdge = &fHalfEdgeList.back();
440 
441  fHalfEdgeList.push_back(dcel2d::HalfEdge());
442 
443  dcel2d::HalfEdge* halfTwin = &fHalfEdgeList.back();
444 
445  // Each half edge is the twin of the other
446  halfEdge->setTwinHalfEdge(halfTwin);
447  halfTwin->setTwinHalfEdge(halfEdge);
448 
449  // Point the breakpoint to the new edge
450  newLeaf->getPredecessor()->setHalfEdge(halfEdge);
451  newLeaf->getSuccessor()->setHalfEdge(halfTwin);
452 
453  // The second half edge corresponds to our face for the left breakpoint...
454  face->setHalfEdge(halfTwin);
455  halfTwin->setFace(face);
456 
457  // Update for the left leaf
458  BSTNode* leftLeaf = newLeaf->getPredecessor()->getPredecessor();
459 
460  // This needs to be checked since the first face will not have an edge set to it
461  if (!leftLeaf->getFace()->getHalfEdge()) leftLeaf->getFace()->setHalfEdge(halfEdge);
462 
463  halfEdge->setFace(leftLeaf->getFace());
464 
465  // Try to make circle events either side of this leaf
466  makeLeftCircleEvent( eventQueue, newLeaf, siteEvent->xPos());
467  makeRightCircleEvent(eventQueue, newLeaf, siteEvent->xPos());
468 
469  return;
470 }
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
dcel2d::FaceList & fFaceList
Definition: Voronoi.h:187
void makeLeftCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:557
void setTwinHalfEdge(HalfEdge *twin)
Definition: DCEL.h:169
void makeRightCircleEvent(EventQueue &, BSTNode *, double)
Definition: Voronoi.cxx:606
void setFace(Face *face)
Definition: DCEL.h:168
void setHalfEdge(HalfEdge *half)
Definition: DCEL.h:116
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 1102 of file Voronoi.cxx.

1103 {
1104  bool insideHull(true);
1105  dcel2d::Point vertexPos(vertex.getCoords()[0],vertex.getCoords()[1],NULL);
1106 
1107  // Now check to see if the vertex is inside the convex hull
1109  dcel2d::Point firstPoint = *hullItr++;
1110 
1111  // We assume here the convex hull is stored in a CCW order
1112  while(hullItr != fConvexHullList.end())
1113  {
1114  dcel2d::Point secondPoint = *hullItr++;
1115 
1116  // CCW order means we check to see if this point lies to left of line from first to second point
1117  // in order for the point to be "inside" the convex hull
1118  // Note that we are looking to reject points that are outside...
1119  if (!isLeft(firstPoint,secondPoint,vertexPos))
1120  {
1121  insideHull = false;
1122  break;
1123  }
1124 
1125  firstPoint = secondPoint;
1126  }
1127 
1128  return insideHull;
1129 }
intermediate_table::const_iterator const_iterator
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
const Coords & getCoords() const
Definition: DCEL.h:69
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:82
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 82 of file Voronoi.cxx.

83 {
84  // Use the cross product to determine if the check point lies to the left, on or right
85  // of the line defined by points p0 and p1
86  return crossProduct(p0, p1, pCheck) > 0;
87 }
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:91
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 1131 of file Voronoi.cxx.

1135 {
1136  bool outsideHull(false);
1137  dcel2d::Point vertexPos(vertex.getCoords()[0],vertex.getCoords()[1],NULL);
1138 
1139  distToConvexHull = std::numeric_limits<double>::max();
1140  firstHullPointItr = fConvexHullList.begin();
1141 
1142  // Now check to see if the vertex is inside the convex hull
1143  dcel2d::PointList::const_iterator hullItr = firstHullPointItr;
1144  dcel2d::PointList::const_iterator firstPointItr = hullItr++;
1145 
1146  while(hullItr != fConvexHullList.end())
1147  {
1148  dcel2d::PointList::const_iterator secondPointItr = hullItr++;
1149 
1150  // Dereference some stuff
1151  double xPrevToPoint = (std::get<0>(vertexPos) - std::get<0>(*firstPointItr));
1152  double yPrevToPoint = (std::get<1>(vertexPos) - std::get<1>(*firstPointItr));
1153  double xPrevToCur = (std::get<0>(*secondPointItr) - std::get<0>(*firstPointItr));
1154  double yPrevToCur = (std::get<1>(*secondPointItr) - std::get<1>(*firstPointItr));
1155  double edgeLength = std::sqrt(xPrevToCur * xPrevToCur + yPrevToCur * yPrevToCur);
1156 
1157  // Find projection onto convex hull edge
1158  double projection = ((xPrevToPoint * xPrevToCur) + (yPrevToPoint * yPrevToCur)) / edgeLength;
1159 
1160  // DOCA point
1161  dcel2d::Point docaPoint(std::get<0>(*firstPointItr) + projection * xPrevToCur / edgeLength,
1162  std::get<1>(*firstPointItr) + projection * yPrevToCur / edgeLength, 0);
1163 
1164  if (projection > edgeLength) docaPoint = *secondPointItr;
1165  if (projection < 0) docaPoint = *firstPointItr;
1166 
1167  double xDocaDist = std::get<0>(vertexPos) - std::get<0>(docaPoint);
1168  double yDocaDist = std::get<1>(vertexPos) - std::get<1>(docaPoint);
1169  double docaDist = xDocaDist * xDocaDist + yDocaDist * yDocaDist;
1170 
1171  if (docaDist < distToConvexHull)
1172  {
1173  firstHullPointItr = firstPointItr;
1174  intersection = dcel2d::Coords(std::get<0>(docaPoint),std::get<1>(docaPoint),0.);
1175  distToConvexHull = docaDist;
1176  }
1177 
1178  // Check to see if this point is outside the convex hull
1179  if (isLeft(*firstPointItr,*secondPointItr,vertexPos)) outsideHull = true;
1180 
1181  firstPointItr = secondPointItr;
1182  }
1183 
1184  return outsideHull;
1185 }
intermediate_table::const_iterator const_iterator
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
static int max(int a, int b)
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
Eigen::Vector3f Coords
Definition: DCEL.h:46
const Coords & getCoords() const
Definition: DCEL.h:69
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:82
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 653 of file Voronoi.cxx.

654 {
655  // It might be that we don't create a new circle
656  IEvent* circle = 0;
657 
658  // First step is to calculate the center and radius of the circle determined by the three input site events
660  double radius;
661  double deltaR;
662 
663  IEvent* p1 = arc1->getEvent();
664  IEvent* p2 = arc2->getEvent();
665  IEvent* p3 = arc3->getEvent();
666 
667  // Compute the center of the circle. Note that this will also automagically check that breakpoints are
668  // converging so that this is a circle we want
669  if (computeCircleCenter( p1->getCoords(), p2->getCoords(), p3->getCoords(), center, radius, deltaR))
670  {
671  double circleBottomX = center[0] - radius;
672 
673  // Now check if the bottom of this circle lies below the beach line
674  if (beachLinePos >= circleBottomX - 10. * deltaR)
675  {
676  // Making a circle event!
677  dcel2d::Point circleBottom(circleBottomX, center[1], NULL);
678 
679  fCircleEventList.emplace_back(circleBottom, center);
680 
681  circle = &fCircleEventList.back();
682  }
683  else if (circleBottomX - beachLinePos < 1.e-4)
684  std::cout << "==> Circle close, beachLine: " << beachLinePos << ", circleBottomX: " << circleBottomX << ", deltaR: " << deltaR << ", d: " << circleBottomX - beachLinePos << std::endl;
685  }
686 
687  return circle;
688 }
bool computeCircleCenter(const dcel2d::Coords &, const dcel2d::Coords &, const dcel2d::Coords &, dcel2d::Coords &, double &, double &) const
Definition: Voronoi.cxx:690
const double e
CircleEventList fCircleEventList
Definition: Voronoi.h:191
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
def center(depos, point)
Definition: depos.py:117
Eigen::Vector3f Coords
Definition: DCEL.h:46
QTextStream & endl(QTextStream &s)
void voronoi2d::VoronoiDiagram::makeLeftCircleEvent ( EventQueue eventQueue,
BSTNode leaf,
double  beachLine 
)
private

Definition at line 557 of file Voronoi.cxx.

560 {
561 
562  // Check status of triplet of site events to the left of this new leaf
563  if (leaf->getPredecessor())
564  {
565  BSTNode* midLeaf = leaf->getPredecessor()->getPredecessor();
566 
567  if (midLeaf && midLeaf->getPredecessor())
568  {
569  BSTNode* edgeLeaf = midLeaf->getPredecessor()->getPredecessor();
570 
571  // edge leaves must be different
572  if (leaf->getEvent()->getPoint() == edgeLeaf->getEvent()->getPoint()) return;
573 
574  if (edgeLeaf)
575  {
576  IEvent* circleEvent = makeCircleEvent(edgeLeaf, midLeaf, leaf, beachLine);
577 
578  // Did we succeed in making a circle event?
579  if (circleEvent)
580  {
581  // Add to the circle node list
582  fCircleNodeList.emplace_back(circleEvent);
583 
584  BSTNode* circleNode = &fCircleNodeList.back();
585 
586  // If there was an associated circle event to this node, invalidate it
587  if (midLeaf->getAssociated())
588  {
589  midLeaf->getAssociated()->setAssociated(NULL);
590  midLeaf->getAssociated()->getEvent()->setInvalid();
591  }
592 
593  // Now reset to point at the new one
594  midLeaf->setAssociated(circleNode);
595  circleNode->setAssociated(midLeaf);
596 
597  eventQueue.push(circleEvent);
598  }
599  }
600  }
601  }
602 
603  return;
604 }
BSTNodeList fCircleNodeList
Definition: Voronoi.h:192
IEvent * makeCircleEvent(BSTNode *, BSTNode *, BSTNode *, double)
There are two types of events in the queue, here we handle circle events.
Definition: Voronoi.cxx:653
void voronoi2d::VoronoiDiagram::makeRightCircleEvent ( EventQueue eventQueue,
BSTNode leaf,
double  beachLine 
)
private

Definition at line 606 of file Voronoi.cxx.

609 {
610  // Check status of triplet of site events to the left of this new leaf
611  if (leaf->getSuccessor())
612  {
613  BSTNode* midLeaf = leaf->getSuccessor()->getSuccessor();
614 
615  if (midLeaf && midLeaf->getSuccessor())
616  {
617  BSTNode* edgeLeaf = midLeaf->getSuccessor()->getSuccessor();
618 
619  if (leaf->getEvent()->getPoint() == edgeLeaf->getEvent()->getPoint()) return;
620 
621  if (edgeLeaf)
622  {
623  IEvent* circleEvent = makeCircleEvent(leaf, midLeaf, edgeLeaf, beachLine);
624 
625  // Did we succeed in making a circle event?
626  if (circleEvent)
627  {
628  // Add to the circle node list
629  fCircleNodeList.emplace_back(circleEvent);
630 
631  BSTNode* circleNode = &fCircleNodeList.back();
632 
633  // If there was an associated circle event to this node, invalidate it
634  if (midLeaf->getAssociated())
635  {
636  midLeaf->getAssociated()->setAssociated(NULL);
637  midLeaf->getAssociated()->getEvent()->setInvalid();
638  }
639 
640  // Now reset to point at the new one
641  midLeaf->setAssociated(circleNode);
642  circleNode->setAssociated(midLeaf);
643 
644  eventQueue.push(circleEvent);
645  }
646  }
647  }
648  }
649 
650  return;
651 }
BSTNodeList fCircleNodeList
Definition: Voronoi.h:192
IEvent * makeCircleEvent(BSTNode *, BSTNode *, BSTNode *, double)
There are two types of events in the queue, here we handle circle events.
Definition: Voronoi.cxx:653
void voronoi2d::VoronoiDiagram::mergeDegenerateVertices ( )
private

merge degenerate vertices (found by zero length edges)

Definition at line 1187 of file Voronoi.cxx.

1188 {
1190 
1191  while(edgeItr != fHalfEdgeList.end())
1192  {
1193  dcel2d::HalfEdge* halfEdge = &(*edgeItr);
1194  dcel2d::HalfEdge* twinEdge = halfEdge->getTwinHalfEdge();
1195 
1196  // Make sure we are not looking at an infinite edge
1197  if (halfEdge->getTargetVertex() && twinEdge->getTargetVertex())
1198  {
1199  dcel2d::Coords vtxPosDiff = halfEdge->getTargetVertex()->getCoords() - twinEdge->getTargetVertex()->getCoords();
1200 
1201  if (vtxPosDiff.norm() < 1.e-3)
1202  {
1203  std::cout << "***>> found a degenerate vertex! " << halfEdge->getTargetVertex()->getCoords()[0] << "/" << halfEdge->getTargetVertex()->getCoords()[1] << ", d: " << vtxPosDiff.norm() << std::endl;
1204  edgeItr++;
1205  }
1206  else edgeItr++;
1207  }
1208  else edgeItr++;
1209  }
1210 
1211  return;
1212 }
intermediate_table::iterator iterator
dcel2d::HalfEdgeList & fHalfEdgeList
Definition: Voronoi.h:185
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:163
Vertex * getTargetVertex() const
Definition: DCEL.h:161
Eigen::Vector3f Coords
Definition: DCEL.h:46
const Coords & getCoords() const
Definition: DCEL.h:69
QTextStream & endl(QTextStream &s)
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 829 of file Voronoi.cxx.

830 {
831  // Need to complete processing of the beachline, the remaning leaves represent the site points with "infinite"
832  // edges which we need to terminate at our bounding box.
833  // For now let's just do step one which is to find the convex hull
834  const BSTNode* node = beachLine.getTopNode();
835 
836  // Do the convex hull independently but before terminating edges
837  getConvexHull(node);
838 
839  if (node)
840  {
841  // Run down the left branches to find the left most leaf
842  while(node->getLeftChild()) node = node->getLeftChild();
843 
844  // Things to keep track of...
845  int nodeCount(0);
846  int nBadBreaks(0);
847  double lastBreakPoint = std::numeric_limits<double>::lowest();
848 
849  // Now we are going to traverse across the beach line and process the remaining leaves
850  // This will identify the infinite edges and find the convex hull
851  while(node)
852  {
853  std::cout << "--------------------------------------------------------------------------------------------" << std::endl;
854 
855  // Do we have a leaf?
856  if (!node->getLeftChild() && !node->getRightChild())
857  {
858  std::cout << "node " << nodeCount << " has leaf: " << node << ", face: " << node->getFace() << ", pos: " << node->getEvent()->getCoords()[0] << "/" << node->getEvent()->getCoords()[1] << std::endl;
859  }
860  // Otherwise it is a break point
861  else
862  {
863  RootsPair roots;
864  double breakPoint = fUtilities.computeBreak(beachLinePos, node->getPredecessor()->getEvent(), node->getSuccessor()->getEvent(), roots);
865  double leftArcVal = fUtilities.computeArcVal(beachLinePos, breakPoint, node->getPredecessor()->getEvent());
866  double rightArcVal = fUtilities.computeArcVal(beachLinePos, breakPoint, node->getSuccessor()->getEvent());
867 
868  dcel2d::HalfEdge* halfEdge = node->getHalfEdge();
869  dcel2d::HalfEdge* halfTwin = halfEdge->getTwinHalfEdge();
870  dcel2d::Vertex* vertex = halfEdge->getTargetVertex();
871 
872  std::cout << "node " << nodeCount << " has break: " << breakPoint << ", beachPos: " << beachLinePos << " (last: " << lastBreakPoint << "), leftArcVal: " << leftArcVal << ", rightArcVal: " << rightArcVal << std::endl;
873  if (lastBreakPoint > breakPoint) std::cout << " ***** lastBreakPoint larger than current break point *****" << std::endl;
874  std::cout << " left arc x/y: " << node->getPredecessor()->getEvent()->xPos() << "/" << node->getPredecessor()->getEvent()->yPos() << ", right arc x/y: " << node->getSuccessor()->getEvent()->xPos() << "/" << node->getSuccessor()->getEvent()->yPos() << std::endl;
875  std::cout << " halfEdge: " << halfEdge << ", target vtx: " << vertex << ", face: " << halfEdge->getFace() << ", twin: " << halfTwin << ", twin tgt: " << halfTwin->getTargetVertex() << ", twin face: " << halfTwin->getFace() << ", next: " << halfEdge->getNextHalfEdge() << ", last: " << halfEdge->getLastHalfEdge() << std::endl;
876 
877  const dcel2d::Coords& leftLeafPos = node->getPredecessor()->getEvent()->getCoords();
878  const dcel2d::Coords& rightLeafPos = node->getSuccessor()->getEvent()->getCoords();
879  Eigen::Vector3f lrPosDiff = rightLeafPos - leftLeafPos;
880  Eigen::Vector3f lrPosSum = rightLeafPos + leftLeafPos;
881 
882  lrPosDiff.normalize();
883  lrPosSum *= 0.5;
884 
885  dcel2d::Coords leafPos = node->getSuccessor()->getEvent()->getCoords();
886  dcel2d::Coords leafDir = lrPosDiff;
887 
888  if (vertex)
889  {
890  dcel2d::Coords breakDir(leafDir[1],-leafDir[0],0.);
891  dcel2d::Coords breakPos = lrPosSum;
892  dcel2d::Coords vertexPos = vertex->getCoords();
893 
894  // Get the arclength from the break position to the intersection of the two lines
895  dcel2d::Coords breakToLeafPos = leafPos - vertexPos;
896  double arcLenToLine = breakToLeafPos.dot(breakDir);
897 
898  // Now get position
899  dcel2d::Coords breakVertexPos = vertexPos + arcLenToLine * breakDir;
900 
901  std::cout << " halfEdge position: " << breakPos[0] << "/" << breakPos[1] << ", vertex: " << vertexPos[0] << "/" << vertexPos[1] << ", end: " << breakVertexPos[0] << "/" << breakVertexPos[1] << ", dir: " << breakDir[0] << "/" << breakDir[1] << ", arclen: " << arcLenToLine << std::endl;
902 
903  // At this point we need to create a vertex and then terminate the half edges here...
904  fVertexList.push_back(dcel2d::Vertex(breakVertexPos,halfEdge));
905 
906  dcel2d::Vertex* breakVertex = &fVertexList.back();
907 
908  halfTwin->setTargetVertex(breakVertex);
909  }
910  else
911  {
912  std::cout << "****** null vertex!!! Skipping to next node... *********" << std::endl;
913  }
914 
915  if (lastBreakPoint > breakPoint) nBadBreaks++;
916 
917  lastBreakPoint = breakPoint;
918  }
919 
920  if (node->getAssociated())
921  {
922  BSTNode* associated = node->getAssociated();
923  IEvent* iEvent = associated->getEvent();
924 
925  std::cout << " -> associated circle: " << iEvent->isCircle() << ", is valid: " << iEvent->isValid() << std::endl;
926  }
927 
928  node = node->getSuccessor();
929  nodeCount++;
930  }
931 
932  // Now that we have the convex hull, loop over vertices to see if they are inside or outside of the convex hull
933  dcel2d::VertexList::iterator curVertexItr = fVertexList.begin();
934 
935  size_t nVerticesInitial = fVertexList.size();
936 
937  // Loop over all vertices to begin with
938  while(curVertexItr != fVertexList.end())
939  {
940  // Dereference vertex
941  dcel2d::Vertex& vertex = *curVertexItr;
942 
943  bool outsideHull = !isInsideConvexHull(vertex);
944 
945  // Do we need to drop this vertex?
946  if (outsideHull)
947  {
948  curVertexItr = fVertexList.erase(curVertexItr);
949  }
950  else curVertexItr++;
951  }
952 
954  ComputeFaceArea();
955 
956  std::cout << "Loop over beachline done, saved " << fConvexHullList.size() << " arcs, encountered " << nBadBreaks << " bad break points" << std::endl;
957  std::cout << "-- started with " << nVerticesInitial << " vertices, found " << fVertexList.size() << " inside convex hull" << std::endl;
958  }
959 
960  return;
961 }
intermediate_table::iterator iterator
HalfEdge * getLastHalfEdge() const
Definition: DCEL.h:165
HalfEdge * getNextHalfEdge() const
Definition: DCEL.h:164
HalfEdge * getTwinHalfEdge() const
Definition: DCEL.h:163
Face * getFace() const
Definition: DCEL.h:162
bool isInsideConvexHull(const dcel2d::Vertex &) const
Is a vertex inside the convex hull - meant to be a fast check.
Definition: Voronoi.cxx:1102
double computeArcVal(const double, const double, const IEvent *) const
double ComputeFaceArea()
Compute the area of the faces.
Definition: Voronoi.cxx:1215
EventUtilities fUtilities
Definition: Voronoi.h:204
dcel2d::VertexList & fVertexList
Definition: Voronoi.h:186
void mergeDegenerateVertices()
merge degenerate vertices (found by zero length edges)
Definition: Voronoi.cxx:1187
dcel2d::PointList fConvexHullList
Definition: Voronoi.h:194
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:76
std::pair< double, double > RootsPair
Vertex * getTargetVertex() const
Definition: DCEL.h:161
Eigen::Vector3f Coords
Definition: DCEL.h:46
const Coords & getCoords() const
Definition: DCEL.h:69
void setTargetVertex(Vertex *vertex)
Definition: DCEL.h:167
QTextStream & endl(QTextStream &s)
vertex reconstruction

Member Data Documentation

CircleEventList voronoi2d::VoronoiDiagram::fCircleEventList
private

Definition at line 191 of file Voronoi.h.

BSTNodeList voronoi2d::VoronoiDiagram::fCircleNodeList
private

Definition at line 192 of file Voronoi.h.

dcel2d::Coords voronoi2d::VoronoiDiagram::fConvexHullCenter
private

Definition at line 195 of file Voronoi.h.

dcel2d::PointList voronoi2d::VoronoiDiagram::fConvexHullList
private

Definition at line 194 of file Voronoi.h.

dcel2d::FaceList& voronoi2d::VoronoiDiagram::fFaceList
private

Definition at line 187 of file Voronoi.h.

dcel2d::HalfEdgeList& voronoi2d::VoronoiDiagram::fHalfEdgeList
private

Definition at line 185 of file Voronoi.h.

int voronoi2d::VoronoiDiagram::fNumBadCircles
mutableprivate

Definition at line 201 of file Voronoi.h.

dcel2d::PointList voronoi2d::VoronoiDiagram::fPointList
private

Definition at line 189 of file Voronoi.h.

SiteEventList voronoi2d::VoronoiDiagram::fSiteEventList
private

Definition at line 190 of file Voronoi.h.

EventUtilities voronoi2d::VoronoiDiagram::fUtilities
private

Definition at line 204 of file Voronoi.h.

dcel2d::VertexList& voronoi2d::VoronoiDiagram::fVertexList
private

Definition at line 186 of file Voronoi.h.

double voronoi2d::VoronoiDiagram::fVoronoiDiagramArea
private

Definition at line 202 of file Voronoi.h.

double voronoi2d::VoronoiDiagram::fXMax
private

Definition at line 198 of file Voronoi.h.

double voronoi2d::VoronoiDiagram::fXMin
private

Definition at line 197 of file Voronoi.h.

double voronoi2d::VoronoiDiagram::fYMax
private

Definition at line 200 of file Voronoi.h.

double voronoi2d::VoronoiDiagram::fYMin
private

Definition at line 199 of file Voronoi.h.


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