void BinaryHeap<T>::heapifyDown(int nodeIndex) { int leftChildIndex = getLeftChildIndex(nodeIndex); int rightChildIndex = getRightChildIndex(nodeIndex); T leftChildElem, rightChildElem, currentNodeElem; while(leftChildIndex != -1) { if(rightChildIndex == -1) { rightChildIndex = leftChildIndex; } leftChildElem = heap[leftChildIndex]->payload; rightChildElem = heap[rightChildIndex]->payload; currentNodeElem = heap[nodeIndex]->payload; int higherPriorityChildIndex = compare(leftChildElem, rightChildElem) ? leftChildIndex : rightChildIndex; T higherPriorityChildElem = compare(leftChildElem, rightChildElem) ? leftChildElem : rightChildElem; if(compare(higherPriorityChildElem, currentNodeElem)) { swap(higherPriorityChildIndex, nodeIndex); nodeIndex = higherPriorityChildIndex; } else break; leftChildIndex = getLeftChildIndex(nodeIndex); rightChildIndex = getRightChildIndex(nodeIndex); } }
void StatusStructure::move(size_t from, size_t to) { if (to >= m_tree.size()) { return; } // Movement must be recursive and breath-first instead of depth-first (otherwise we would overwrite elements before they are moved) std::queue<std::pair<size_t, size_t>> moveQueue; moveQueue.push(std::make_pair(from, to)); while (!moveQueue.empty()) { from = moveQueue.front().first; to = moveQueue.front().second; moveQueue.pop(); auto toMoveFrag = getAt(from); insertAt(to, toMoveFrag); if (toMoveFrag != nullptr) { // move the children of the moved element insertAt(from, nullptr); // clear the element moveQueue.push(std::make_pair(getLeftChildIndex(from), getLeftChildIndex(to))); // move left children moveQueue.push(std::make_pair(getRightChildIndex(from), getRightChildIndex(to))); // move right children } } }
void StatusStructure::remove(const LineSegmentPtr& fragment) { bool valid; size_t index = indexOf(fragment, valid); if (!valid) { return; } m_index_map.erase(fragment); if (leftChild(index) == nullptr) { move(getRightChildIndex(index), index); return; } else if (rightChild(index) == nullptr) { move(getLeftChildIndex(index), index); return; } // get direct left neighbour of index (most right child in left subtree) size_t directLeftNeighbourIndex = getLeftChildIndex(index); while (rightChild(directLeftNeighbourIndex) != nullptr) { directLeftNeighbourIndex = getRightChildIndex(directLeftNeighbourIndex); } insertAt(index, getAt(directLeftNeighbourIndex)); move(getLeftChildIndex(directLeftNeighbourIndex), directLeftNeighbourIndex); }
size_t StatusStructure::getClosestTo(const Point& point, float& outDist) const { size_t index = 0; auto currentFrag = getAt(index); if (currentFrag == nullptr) { return index; } float dist = getPositionOnScanLine(currentFrag, point); size_t closestIndex = index; outDist = dist; for (;;) { if (dist > 0 && leftChild(index) != nullptr) { index = getLeftChildIndex(index); } else if (dist < 0 && rightChild(index) != nullptr) { index = getRightChildIndex(index); } else { break; } currentFrag = getAt(index); dist = getPositionOnScanLine(currentFrag, point); if (std::fabs(outDist) > std::fabs(dist)) { closestIndex = index; outDist = dist; } } return closestIndex; }
void StatusStructure::insert(LineSegmentPtr fragment, const Point& scanLinePosition) { size_t currentIndex = 0; auto currentFrag = getAt(currentIndex); while (currentFrag != nullptr) { if (currentFrag == fragment) { return; } if (isALeftOfBOnScanLine(*fragment, *currentFrag, scanLinePosition)) { currentIndex = getLeftChildIndex(currentIndex); } else { currentIndex = getRightChildIndex(currentIndex); } currentFrag = getAt(currentIndex); } insertAt(currentIndex, fragment); }
size_t StatusStructure::getLeftNeighbourIndex(size_t index) const { size_t currentIndex = index; if (leftChild(currentIndex) != nullptr) { // if there is a left sub tree find the most right leaf in that tree currentIndex = getLeftChildIndex(currentIndex); while (rightChild(currentIndex) != nullptr) { currentIndex = getRightChildIndex(currentIndex); } return currentIndex; } // the root element can't be the right child of another element if (currentIndex == 0) { return index; } if (!isLeftChild(currentIndex)) { // current element is the right child of its parent... hence the parent is the left neighbour return getParentIndex(currentIndex); } // current element is the left child of its parent... traverse upwards to the first node that is not a left child or the root node while (currentIndex > 0 && isLeftChild(currentIndex)) { currentIndex = getParentIndex(currentIndex); } if (currentIndex == 0) { return index; } // the fragment at currentIndex is right of its parent and the fragment that // we started with is the most left child of this fragment... hence the parent is // the direct left neighbour currentIndex = getParentIndex(currentIndex); return currentIndex; }
size_t StatusStructure::getRightNeighbourIndex(size_t index) const { size_t currentIndex = index; if (rightChild(currentIndex) != nullptr) { // if there is a right sub tree find the most left leaf in that tree currentIndex = getRightChildIndex(currentIndex); while (leftChild(currentIndex) != nullptr) { currentIndex = getLeftChildIndex(currentIndex); } return currentIndex; } // the root element can't be the left child of another element if (currentIndex == 0) { return index; } if (isLeftChild(currentIndex)) { // current element is the left child of its parent... hence the parent is the right neighbour return getParentIndex(currentIndex); } // current element is the right child of its parent... traverse upwards to the first node that is not a right child or the root node while (currentIndex > 0 && !isLeftChild(currentIndex)) { currentIndex = getParentIndex(currentIndex); } if (currentIndex == 0) { return index; } currentIndex = getParentIndex(currentIndex); return currentIndex; }
LineSegmentPtr StatusStructure::rightChild(size_t index) const { return getAt(getRightChildIndex(index)); }