BeachLine.cxx
Go to the documentation of this file.
1 /**
2  * @file BeachLine.cxx
3  *
4  * @brief Producer module to create 3D clusters from input hits
5  *
6  */
7 
8 // Framework Includes
9 
11 
12 // std includes
13 #include <iostream>
14 #include <limits>
15 #include <string>
16 
17 //------------------------------------------------------------------------------------------------------------------------------------------
18 // implementation follows
19 
20 namespace voronoi2d {
21 
23 {
24  m_depth = 0;
25  m_event = event;
26  m_parent = parent;
27  m_leftChild = leftChild;
28  m_rightChild = rightChild;
29  m_predecessor = NULL;
30  m_successor = NULL;
31  m_associated = NULL;
32 
33  m_event->setBSTNode(this);
34 
35  // Reset depth
36  setDepth();
37 }
38 
40 {
42  {
43  int maxDepth = std::max(m_leftChild->getDepth(),m_rightChild->getDepth());
44 
45  m_depth = maxDepth + 1;
46  }
47  else m_depth = 0;
48 
49  // If we change depth at this level then need to ripple it up through the tree
50  if (m_parent) m_parent->setDepth();
51 
52  return;
53 }
54 
56 {
57  // Find the insertion point for the new event
58  BSTNode* node = findBestLeaf(event, m_root);
59 
60  // Insert it
61  node = insertNewLeaf(event, node);
62 
63  // Now rebalance starting at this node
64  rebalance(node);
65 
66  // Check beach line integrity
67 // checkBeachLine(event->xPos() - 0.000001);
68 
69  return node;
70 }
71 
73 {
74  // Assumption: a leaf will have NULL child pointers so the idea is to
75  // follow the left or right child pointers until we get to a leaf
76  BSTNode* node = topNode;
77 
78  // A leaf is found when the node has no children
79  if (node && node->getLeftChild() && node->getRightChild())
80  {
81  // This node represents a breakpoint between two arcs and we can
82  // recover these immediately by getting the predecessor and successor leafs
83  BSTNode* rightLeaf = node->getSuccessor();
84  BSTNode* leftLeaf = node->getPredecessor();
85 
86  // Which path do we follow down the tree?
87  if (m_utilities.newSiteToLeft(event, leftLeaf->getEvent(), rightLeaf->getEvent()))
88  node = findBestLeaf(event, node->getLeftChild());
89  else
90  node = findBestLeaf(event, node->getRightChild());
91  }
92 
93  return node;
94 }
95 
97 {
98  // The idea of this function is to insert a new Site Event into the beach line
99  // where it is assumed that the input node is the matched arc into which we
100  // insert the new site event.
101  // The function then returns the new leaf created which represents the new arc
102 
103  // Have we found a null pointer?
104  if (node == NULL)
105  {
106  m_nodeVec.push_back(BSTNode(event));
107  node = &m_nodeVec.back();
108  return node;
109  }
110 
111  // Check if a circle event had been definied for the node we are splitting,
112  // if so then we need to invalidate that circle event
113  if (node->getAssociated())
114  {
115  node->getAssociated()->getEvent()->setInvalid();
116  node->getAssociated()->setAssociated(NULL);
117  node->setAssociated(NULL);
118  }
119 
120  // Right now assume that the input node is the leaf at which we want to insert the new data
121  // For the beachline, this means we are inserting a new arc into the beachline by dividing the
122  // current arc. So we are going to replace the input leaf with a subtree having three leaves
123  // (two breakpoints)...
124  // Start by creating a node for the new arc
125  m_nodeVec.push_back(BSTNode(event)); // This will be the new site point
126 
127  BSTNode* newLeaf = &m_nodeVec.back();
128 
129  m_nodeVec.push_back(BSTNode(*node)); // This will be the new left leaf (the original arc)
130 
131  BSTNode* leftLeaf = &m_nodeVec.back();
132 
133  m_nodeVec.push_back(BSTNode(event)); // This will be the breakpoint between the left and new leaves
134 
135  BSTNode* breakNode = &m_nodeVec.back();
136 
137  m_nodeVec.push_back(BSTNode(event)); // Finally, this is the breakpoint between new and right leaves
138 
139  BSTNode* topNode = &m_nodeVec.back();
140 
141  // Set this to be the king of the local world
142  topNode->setParent(node->getParent());
143 
144  // Make sure the parent points to this new node
145  if (node->getParent())
146  {
147  if (node->getParent()->getLeftChild() == node) node->getParent()->setLeftChild(topNode);
148  else node->getParent()->setRightChild(topNode);
149  }
150  // But if there is no parent then the topnode is the new root
151  else m_root = topNode;
152 
153  // Set our children
154  topNode->setLeftChild(breakNode);
155  topNode->setRightChild(node);
156 
157  // Original node is now child of the top node
158  node->setParent(topNode);
159 
160  // If there was an associated circle event to this node, invalidate it
161  if (node->getAssociated())
162  {
163  node->getAssociated()->setAssociated(NULL);
164  node->getAssociated()->getEvent()->setInvalid();
165  node->setAssociated(NULL);
166  leftLeaf->setAssociated(NULL);
167  }
168 
169  // Now set the parent and children of the left breakpoint node
170  breakNode->setParent(topNode);
171  breakNode->setLeftChild(leftLeaf);
172  breakNode->setRightChild(newLeaf);
173 
174  // Finally set the leaves parents
175  leftLeaf->setParent(breakNode);
176  newLeaf->setParent(breakNode);
177 
178  // Now we wire up traversal chain, going left to right
179  leftLeaf->setPredecessor(node->getPredecessor());
180  leftLeaf->setSuccessor(breakNode);
181 
182  if (node->getPredecessor()) node->getPredecessor()->setSuccessor(leftLeaf);
183 
184  breakNode->setPredecessor(leftLeaf);
185  breakNode->setSuccessor(newLeaf);
186 
187  newLeaf->setPredecessor(breakNode);
188  newLeaf->setSuccessor(topNode);
189 
190  topNode->setPredecessor(newLeaf);
191  topNode->setSuccessor(node);
192  node->setPredecessor(topNode);
193 
194  // Finally, reset the depths
195  // By definition the break node will have depth of 1
196  breakNode->setDepth();
197 
198  // Check the beachline integrity
199  checkBeachLine(newLeaf->getEvent()->xPos()-0.00000001);
200 
201  return newLeaf;
202 }
203 
205 {
206  // The input node is assumed to be a leaf (arc) and is the disappearing arc
207  // between a leaf (arc) to the left and one to the right. There are breakpoints
208  // between the arcs.
209  // One of the intervening breakpoints is the parent of the leaf to remove
210  BSTNode* nodeParent = node->getParent();
211 
212  // parent of the parent
213  BSTNode* grandParent = nodeParent->getParent();
214 
215  // Parent is either left or right child, node is left or right child.... my brain is dizzy
216  BSTNode* sibling = nodeParent->getRightChild();
217 
218  if (node == sibling) sibling = nodeParent->getLeftChild();
219 
220  if (nodeParent == grandParent->getLeftChild()) grandParent->setLeftChild(sibling);
221  else grandParent->setRightChild(sibling);
222 
223  sibling->setParent(grandParent);
224 
225  // Now we need to deal with the predecessor/successor chain.
226  // This should be straightforward, we are removing the middle arc and the immediate parent
227  // breakpoint with the grandparent becoming the new breakpoint. It should be that we simply
228  // set the left arc's successor, the right arc's predecessor and make sure the grandparent points
229  // to the right objects.
230  // Also note that if here there MUST be a left and right arc
231  BSTNode* arcLeft = node->getPredecessor()->getPredecessor();
232  BSTNode* arcRight = node->getSuccessor()->getSuccessor();
233 
234  // Note as well that any circle events for those arcs are now invalid
235  if (arcLeft->getAssociated())
236  {
237  arcLeft->getAssociated()->getEvent()->setInvalid();
238  arcLeft->getAssociated()->setAssociated(NULL);
239  arcLeft->setAssociated(NULL);
240  }
241 
242  if (arcRight->getAssociated())
243  {
244  arcRight->getAssociated()->getEvent()->setInvalid();
245  arcRight->getAssociated()->setAssociated(NULL);
246  arcRight->setAssociated(NULL);
247  }
248 
249  // Basically, we need to connect the left and right arcs to their common break point
250  // What breakpoint that is will be determined by weather the arc we are removing is a
251  // left or right child
252  if (node == nodeParent->getLeftChild())
253  {
254  // In this case, the right arc's predecessor becomes the node's predecessor
255  // The left arc is all set
256  arcRight->setPredecessor(node->getPredecessor());
257  node->getPredecessor()->setSuccessor(arcRight);
258  }
259  else
260  {
261  // Here the left arc's successor is what needs to be changed
262  arcLeft->setSuccessor(node->getSuccessor());
263  node->getSuccessor()->setPredecessor(arcLeft);
264  }
265 
266  // zap the pointers for the removed nodes
267  node->setParent(NULL);
268  nodeParent->setLeftChild(NULL);
269  nodeParent->setRightChild(NULL);
270  nodeParent->setParent(NULL);
271  nodeParent->setSuccessor(NULL);
272  nodeParent->setPredecessor(NULL);
273  node->setSuccessor(NULL);
274  node->setPredecessor(NULL);
275  node->setHalfEdge(NULL);
276  node->setFace(NULL);
277 
278  // Reset the depth
279  grandParent->setDepth();
280 
281  // Check beach line integrity
282 // checkBeachLine(node->getAssociated()->getEvent()->xPos()-0.000001);
283 
284  // Rebalance
285  rebalance(grandParent);
286 
287  // Check beach line integrity
288  checkBeachLine(node->getAssociated()->getEvent()->xPos()-0.00000001);
289 
290  // Return the new breakpoint
291  return arcLeft->getSuccessor();
292 }
293 
295 {
296  int nodeCount(0);
297 
298  countNodes(m_root, nodeCount);
299 
300  return nodeCount;
301 }
302 
304 {
305  int leafCount(0);
306 
307  countLeaves(m_root, leafCount);
308 
309  return leafCount;
310 }
311 
312 void BeachLine::countNodes(const BSTNode* node, int& nodeCount) const
313 {
314  if (node)
315  {
316  if (node->getLeftChild()) countNodes(node->getLeftChild(), nodeCount);
317  if (node->getRightChild()) countNodes(node->getRightChild(), nodeCount);
318 
319  if ((node->getLeftChild() != NULL) != (node->getRightChild() != NULL))
320  {
321  std::cout << "****** Tree has one branch but not the other! *******" << std::endl;
322  }
323 
324  nodeCount++;
325  }
326 
327  return;
328 }
329 
330 void BeachLine::countLeaves(const BSTNode* node, int& leafCount) const
331 {
332  // If not a leaf then still have children to search
333  if (node->getLeftChild() && node->getRightChild())
334  {
335  countLeaves(node->getLeftChild(), leafCount);
336  countLeaves(node->getRightChild(), leafCount);
337  }
338  else leafCount += 1;
339 
340  return;
341 }
342 
344 {
345  int leafCount(0);
346 
347  // Starting with the root, dive down until we find a leaf
348  BSTNode* node = m_root;
349 
350  // Basically, follow the left branch down until we have no more children
351  while(node->getLeftChild()) node = node->getLeftChild();
352 
353  // Note that construction we should be a leaf, now we traverse across
354  // the beach line in both directions to get the leaf count
355  if (node)
356  {
357  leafCount += traverseBeachLeft(node->getPredecessor());
358  leafCount += traverseBeachRight(node->getSuccessor());
359 
360  // just to be sure...
361  if (!node->getLeftChild() && !node->getRightChild()) leafCount++;
362  }
363 
364  return leafCount;
365 }
366 
367 void BeachLine::checkBeachLine(double beachLine) const
368 {
369  // Starting with the root, dive down until we find the leftmost leaf
370  BSTNode* node = m_root;
371 
372  if (!node) return;
373 
374  // Basically, follow the left branch down until we have no more children
375  while(node->getLeftChild()) node = node->getLeftChild();
376 
377  // Keep track of breakpoints
378  double lastBreakPointY = -std::numeric_limits<double>::max();
379  int nBadCompares(0);
380  int nNodes(0);
381  int nBreakPoints(0);
382  int nLeaves(0);
383  BSTNode* lastBreakPoint(NULL);
384 
385  const double tolerance(1.e-5);
386 
387  // This is the start of the beach line, we now traverse across and and check status
388  // of each breakpoint's position
389  while(node->getSuccessor())
390  {
391  // Is this a breakpoint?
392  if (node->getLeftChild() && node->getRightChild())
393  {
394  RootsPair roots;
395  double breakPoint = m_utilities.computeBreak(beachLine, node->getPredecessor()->getEvent(), node->getSuccessor()->getEvent(), roots);
396 
397  if (breakPoint + tolerance < lastBreakPointY)
398  {
399  std::cout << " #####>> Beach line check gets bad breakpoint, last: " << lastBreakPointY << ", new: " << breakPoint << ", roots: " << roots.first << "/" << roots.second << std::endl;
400  std::cout << " Current left arc x,y: " << node->getPredecessor()->getEvent()->xPos() << ", " << node->getPredecessor()->getEvent()->yPos() << ", right arc x,y: " << node->getSuccessor()->getEvent()->xPos() << ", " << node->getSuccessor()->getEvent()->yPos() << ", beachLine: " << beachLine;
401  if (node->getPredecessor()->getAssociated()) std::cout << ", left: " << node->getPredecessor()->getAssociated()->getEvent()->isValid();
402  if (node->getSuccessor()->getAssociated()) std::cout << ", right: " << node->getSuccessor()->getAssociated()->getEvent()->isValid();
403  std::cout << std::endl;
404  if (lastBreakPoint)
405  {
406  std::cout << " Previous left arc x,y: " << lastBreakPoint->getPredecessor()->getEvent()->xPos() << ", " << lastBreakPoint->getPredecessor()->getEvent()->yPos() << ", right arc x,y: " << lastBreakPoint->getSuccessor()->getEvent()->xPos() << ", " << lastBreakPoint->getSuccessor()->getEvent()->yPos();
407  if (lastBreakPoint->getPredecessor()->getAssociated()) std::cout << ", left: " << lastBreakPoint->getPredecessor()->getAssociated()->getEvent()->isValid();
408  if (lastBreakPoint->getSuccessor()->getAssociated()) std::cout << ", right: " << lastBreakPoint->getSuccessor()->getAssociated()->getEvent()->isValid();
409  std::cout << std::endl;
410  }
411  nBadCompares++;
412  }
413 
414  lastBreakPointY = breakPoint;
415  lastBreakPoint = node;
416  nBreakPoints++;
417  }
418  else
419  {
420  // Confirm that the next leaf in the beachline is the next according to the tree
421  if (node->getSuccessor())
422  {
423  BSTNode* temp = node;
424  while(temp->getParent() && temp != temp->getParent()->getLeftChild()) temp = temp->getParent();
425  if (temp->getParent()) temp = temp->getParent()->getRightChild();
426  while(temp->getLeftChild()) temp = temp->getLeftChild();
427 
428  if (node->getSuccessor()->getSuccessor() != temp || node != temp->getPredecessor()->getPredecessor())
429  {
430  std::cout << " --> Successor tree/beach mismatch, leaf # " << nLeaves << ", node: " << node << ", " << node->getEvent()->xPos() << "/" << node->getEvent()->yPos() << ", s: " << node->getSuccessor() << ", ss: " << node->getSuccessor()->getSuccessor() << std::endl;
431  std::cout << " temp: " << temp << ", " << temp->getEvent()->xPos() << "/" << temp->getEvent()->yPos() << ", p: " << temp->getPredecessor() << ", pp: " << temp->getPredecessor()->getPredecessor() << std::endl;
432  }
433  }
434 
435  if (node->getPredecessor())
436  {
437  BSTNode* temp = node;
438  while(temp->getParent() && temp != temp->getParent()->getRightChild()) temp = temp->getParent();
439  if (temp->getParent()) temp = temp->getParent()->getLeftChild();
440  while(temp->getRightChild()) temp = temp->getRightChild();
441 
442  if (node->getPredecessor()->getPredecessor() != temp || node != temp->getSuccessor()->getSuccessor())
443  {
444  std::cout << " --> Predecessor tree/beach mismatch, leaf # " << nLeaves << ", node: " << node << ", " << node->getEvent()->xPos() << "/" << node->getEvent()->yPos() << ", p: " << node->getPredecessor() << ", pp: " << node->getPredecessor()->getPredecessor() << std::endl;
445  std::cout << " temp: " << temp << ", " << temp->getEvent()->xPos() << "/" << temp->getEvent()->yPos() << ", s: " << temp->getSuccessor() << ", ss: " << temp->getSuccessor()->getSuccessor() << std::endl;
446  }
447  }
448 
449  nLeaves++;
450  }
451 
452  nNodes++;
453 
454  node = node->getSuccessor();
455  }
456 
457  if (nBadCompares > 0) std::cout << "=======>> Beach line check resulted in " << nBadCompares << " bad compares of " << nBreakPoints << " break points checked, with " << nLeaves << " leaves" << std::endl;
458 
459 // std::cout << "-------------------------------------------------------------------------------------------------------" << std::endl;
460 
461  return;
462 }
463 
465 {
466  int leafCount(0);
467 
468  if (node)
469  {
470  // Keep traversing
471  if (node->getPredecessor()) leafCount += traverseBeachLeft(node->getPredecessor());
472 
473  // Are we also a leaf?
474  if (!node->getLeftChild() && !node->getRightChild()) leafCount++;
475  }
476 
477  return leafCount;
478 }
479 
481 {
482  int leafCount(0);
483 
484  if (node)
485  {
486  // Keep traversing
487  if (node->getSuccessor()) leafCount += traverseBeachRight(node->getSuccessor());
488 
489  // Are we also a leaf?
490  if (!node->getLeftChild() && !node->getRightChild()) leafCount++;
491  }
492 
493  return leafCount;
494 }
495 
496 int BeachLine::getTreeDepth(const BSTNode* node) const
497 {
498  int depth(0);
499 
500  // Node exists and its not a leaf
501  if (node && node->getLeftChild() && node->getRightChild())
502  {
503  depth = std::max(getTreeDepth(node->getLeftChild()),getTreeDepth(node->getRightChild()));
504 
505  depth++;
506  }
507  else if (node && (node->getLeftChild() || node->getRightChild()))
508  {
509  std::cout << "****** Found a node which only one child: " << node << ", L/R: " << node->getLeftChild() << "/" << node->getRightChild() << std::endl;
510  }
511 
512  return depth;
513 }
514 
516 {
517  // The idea is to rebalance starting with the current node and the walking back up the branch
518  // until we reach the ultimate parent.
519  // First, if at internal node then check depth down either branch
520  if (node->getLeftChild() && node->getRightChild())
521  {
522  int depthLeft = getTreeDepth(node->getLeftChild());
523  int depthRight = getTreeDepth(node->getRightChild());
524 
525  if (depthLeft != node->getLeftChild()->getDepth() || depthRight != node->getRightChild()->getDepth())
526  {
527  std::cout << " --> node depth: " << getTreeDepth(node) << ", left/right: " << depthLeft << "/" << node->getLeftChild()->getDepth() << ", " << depthRight << "/" << node->getRightChild()->getDepth() << ", parent/depth " << node->getParent() << "/" << getTreeDepth(node->getParent()) << std::endl;
528  }
529 
530  // If left branch is longer then we rotate with the left child
531  if (depthLeft - depthRight > 2) node = rotateWithLeftChild(node);
532  else if (depthRight - depthLeft > 2) node = rotateWithRightChild(node);
533  }
534 
535  // Ok now rebalance the parent unless we are the root
536  if (node->getParent()) rebalance(node->getParent());
537  // In which case update the internal root node pointer
538  else m_root = node;
539 
540  return;
541 }
542 
544 {
545  // Here we rebalance by rotating the root node with its left child
546  BSTNode* newTopNode = node->getLeftChild();
547  BSTNode* parent = node->getParent();
548 
549  // Check if there is a parent and if so make sure it points at the new node
550  if (parent)
551  {
552  if (parent->getLeftChild() == node) parent->setLeftChild(newTopNode);
553  else parent->setRightChild(newTopNode);
554  }
555  // if no parent this the new root
556  else m_root = newTopNode;
557 
558  // Swap parents (for the root node the parent is null)
559  newTopNode->setParent(parent);
560  node->setParent(newTopNode);
561 
562  // Reset the children
563  BSTNode* childToSwitch = newTopNode->getRightChild();
564 
565  childToSwitch->setParent(node);
566  node->setLeftChild(childToSwitch);
567  newTopNode->setRightChild(node);
568 
569  // Reset node depth
570  node->getLeftChild()->setDepth();
571 
572  return newTopNode;
573 }
574 
576 {
577  // Here we rebalance by rotating the root node with its left child
578  BSTNode* newTopNode = node->getRightChild();
579  BSTNode* parent = node->getParent();
580 
581  // Check if there is a parent and if so make sure it points at the new node
582  if (parent)
583  {
584  if (parent->getLeftChild() == node) parent->setLeftChild(newTopNode);
585  else parent->setRightChild(newTopNode);
586  }
587  // if no parent this the new root
588  else m_root = newTopNode;
589 
590  // Swap parents (for the root node the parent is null)
591  newTopNode->setParent(parent);
592  node->setParent(newTopNode);
593 
594  // Reset the children
595  BSTNode* childToSwitch = newTopNode->getLeftChild();
596 
597  childToSwitch->setParent(node);
598  node->setRightChild(childToSwitch);
599  newTopNode->setLeftChild(node);
600 
601  // Reset node depths
602  node->getRightChild()->setDepth();
603 
604  return newTopNode;
605 }
606 
607 
608 } // namespace lar_cluster3d
void checkBeachLine(double) const
Definition: BeachLine.cxx:367
BSTNode * rotateWithLeftChild(BSTNode *)
Definition: BeachLine.cxx:543
IEvent * m_event
Definition: BeachLine.h:106
void setRightChild(BSTNode *node)
Definition: BeachLine.h:88
void setSuccessor(BSTNode *node)
Definition: BeachLine.h:90
BSTNode * m_associated
Definition: BeachLine.h:112
BSTNode class definiton specifically for use in constructing Voronoi diagrams. We are trying to follo...
Definition: BeachLine.h:32
void setDepth(int depth)
Definition: BeachLine.h:96
auto const tolerance
void rebalance(BSTNode *)
Tree balancing functions.
Definition: BeachLine.cxx:515
BSTNode * getParent() const
Definition: BeachLine.h:73
int getTreeDepth(const BSTNode *) const
This recovers the depth of longest branch in the tree below input node.
Definition: BeachLine.cxx:496
Represents the beachline implemented as a self balancing binary search tree.
BSTNode * findBestLeaf(const IEvent *event) const
Definition: BeachLine.h:132
BSTNode * getAssociated() const
Definition: BeachLine.h:78
int countLeaves() const
Definition: BeachLine.cxx:303
BSTNode * m_successor
Definition: BeachLine.h:111
const double e
BSTNode * insertNewLeaf(IEvent *)
Definition: BeachLine.cxx:55
BSTNode * m_predecessor
Definition: BeachLine.h:110
void setLeftChild(BSTNode *node)
Definition: BeachLine.h:87
virtual double yPos() const =0
void setParent(BSTNode *node)
Allow setting of the points.
Definition: BeachLine.h:86
BSTNode * getRightChild() const
Definition: BeachLine.h:75
BSTNode * m_parent
Definition: BeachLine.h:107
virtual void setBSTNode(BSTNode *)=0
static int max(int a, int b)
int traverseBeachLeft(BSTNode *) const
Definition: BeachLine.cxx:464
BSTNode * removeLeaf(BSTNode *)
Definition: BeachLine.cxx:204
void setAssociated(BSTNode *node)
Definition: BeachLine.h:91
virtual bool isValid() const =0
BSTNode()
Constructor.
Definition: BeachLine.h:38
int traverseBeachRight(BSTNode *) const
Definition: BeachLine.cxx:480
virtual double xPos() const =0
int getDepth() const
recover the data members
Definition: BeachLine.h:71
int traverseBeach() const
Definition: BeachLine.cxx:343
int countNodes() const
Definition: BeachLine.cxx:294
BSTNode * getPredecessor() const
Definition: BeachLine.h:76
BSTNode * rotateWithRightChild(BSTNode *)
Definition: BeachLine.cxx:575
BSTNode * m_leftChild
Definition: BeachLine.h:108
std::pair< double, double > RootsPair
void setFace(dcel2d::Face *face)
Definition: BeachLine.h:94
void setPredecessor(BSTNode *node)
Definition: BeachLine.h:89
virtual void setInvalid() const =0
Interface for configuring the particular algorithm tool.
IEvent * getEvent() const
Definition: BeachLine.h:72
def parent(G, child, parent_type)
Definition: graph.py:67
BSTNode * getSuccessor() const
Definition: BeachLine.h:77
BSTNode * m_rightChild
Definition: BeachLine.h:109
BSTNode * getLeftChild() const
Definition: BeachLine.h:74
QTextStream & endl(QTextStream &s)
Event finding and building.
void setHalfEdge(dcel2d::HalfEdge *half)
Definition: BeachLine.h:93