// Retrieve all coincident entries by their position, also searches in neighbor cells so the results are exhaustive // NOTE: Neighbor cells are consulted only if within _epsilon threshold public void FindAllIncludeNeighborCells(ref float3 _position, List <keyValue_t> _result, float _epsilon) { int minCellX, minCellY, minCellZ; float3 posMin = _position - _epsilon * float3.One; GetCellIndices(ref posMin, out minCellX, out minCellY, out minCellZ); int maxCellX, maxCellY, maxCellZ; float3 posMax = _position + _epsilon * float3.One; GetCellIndices(ref posMax, out maxCellX, out maxCellY, out maxCellZ); for (int Z = minCellZ; Z <= maxCellZ; Z++) { for (int Y = minCellY; Y <= maxCellY; Y++) { for (int X = minCellX; X <= maxCellX; X++) { uint hash = ComputeHash(X, Y, Z); keyValue_t current = m_table[hash]; while (current != null) { if (Compare(ref current.position, ref _position, _epsilon)) { _result.Add(current); // Another match! } current = current.next; } } } } }
// Clears the entire table public void Clear() { Array.Clear(m_table, 0, m_table.Length); if (m_maxEntries > 0) { for (int nodeIndex = 0; nodeIndex < m_maxEntries - 1; nodeIndex++) { m_nodesPool[nodeIndex].next = m_nodesPool[nodeIndex + 1]; m_nodesPool[nodeIndex].hash = ~0U; } m_nodesPool[m_maxEntries - 1].next = null; } m_freeNode = m_nodesPool[0]; // All free! m_entriesCount = 0; }
// Retrieve all coincident entries by their position public void FindAll(ref float3 _position, List <keyValue_t> _result, float _epsilon) { uint hash = ComputeHash(ref _position); keyValue_t current = m_table[hash]; while (current != null) { if (Compare(ref current.position, ref _position, _epsilon)) { _result.Add(current); // Another match! } current = current.next; } }
// Update the entry's position public bool Update(keyValue_t _entry, float3 _newPosition) { _entry.position = _newPosition; uint newHash = ComputeHash(ref _newPosition); if (newHash == _entry.hash) { return(true); // No change in hash... } // We must first retrieve the existing entry in the linked list of entries sharing that hash keyValue_t previous = null; keyValue_t current = m_table[_entry.hash]; while (current != null) { if (current != _entry) { previous = current; current = current.next; continue; } // Found it! // Link over that node to remove it from this hash's list of entries if (previous != null) { previous.next = current.next; } else { m_table[_entry.hash] = current.next; } // Update its hash _entry.hash = newHash; // Re-link it to its new position in the table _entry.next = m_table[newHash]; m_table[newHash] = _entry; return(true); } return(false); // Not found... }
keyValue_t Alloc() { if (m_freeNode == null) { throw new Exception("Table is full! Consider increasing _maxEntries!"); } keyValue_t node = m_freeNode; m_freeNode = node.next; node.next = null; node.hash = ~0U; m_entriesCount++; return(node); }
void FindAllValuePointersInCell(int _cellX, int _cellY, int _cellZ, List <keyValue_t> _values) { uint hash = ComputeHash(_cellX, _cellY, _cellZ); keyValue_t current = m_table[hash]; while (current != null) { int entryCellX, entryCellY, entryCellZ; GetCellIndices(ref current.position, out entryCellX, out entryCellY, out entryCellZ); if (entryCellX == _cellX && entryCellY == _cellY && entryCellZ == _cellZ) { _values.Add(current); } current = current.next; } }
// Fills a list with all the values stored in a given cell public keyValue_t FindFirstValueInCell(int _cellX, int _cellY, int _cellZ) { uint hash = ComputeHash(_cellX, _cellY, _cellZ); keyValue_t current = m_table[hash]; while (current != null) { int entryCellX, entryCellY, entryCellZ; GetCellIndices(ref current.position, out entryCellX, out entryCellY, out entryCellZ); if (entryCellX == _cellX && entryCellY == _cellY && entryCellZ == _cellZ) { return(current); } current = current.next; } return(null); }
// Retrieve the first entry by its position public keyValue_t Find(ref float3 _position, float _epsilon) { uint hash = ComputeHash(ref _position); keyValue_t current = m_table[hash]; while (current != null) { if (Compare(ref current.position, ref _position, _epsilon)) { return(current); // Found it! } current = current.next; } return(null); // Not found... }
// Adds a new entry to the table // Returns the handle to the added entry public keyValue_t Add(float3 _position, T _value) { uint hash = ComputeHash(ref _position); keyValue_t firstEntry = m_table[hash]; keyValue_t newEntry = Alloc(); if (newEntry != null) { newEntry.next = firstEntry; newEntry.hash = hash; newEntry.position = _position; newEntry.value = _value; m_table[hash] = newEntry; // We're the new first entry } return(newEntry); }
// Removes an entry from the table public bool Remove(keyValue_t _entry) { keyValue_t previous = null; keyValue_t current = m_table[_entry.hash]; while (current != null) { if (current != _entry) { previous = current; current = current.next; continue; } // Found it! // Link over that node if (previous != null) { previous.next = current.next; } else { m_table[_entry.hash] = current.next; } // Add the node back to the free list current.next = m_freeNode; m_freeNode = current; m_entriesCount--; return(true); } return(false); // Not found... }