%PDF- %PDF-
Direktori : /www/varak.net/nextcloud.varak.net/apps/photos/vendor/hexogen/kdtree/src/ |
Current File : //www/varak.net/nextcloud.varak.net/apps/photos/vendor/hexogen/kdtree/src/FSTreePersister.php |
<?php namespace Hexogen\KDTree; use Hexogen\KDTree\Interfaces\ItemInterface; use Hexogen\KDTree\Interfaces\KDTreeInterface; use Hexogen\KDTree\Interfaces\NodeInterface; use Hexogen\KDTree\Interfaces\TreePersisterInterface; class FSTreePersister implements TreePersisterInterface { /** * @var string path to the file */ private $path; /** * @var resource file handler */ private $handler; /** * @var int */ private $dimensions; /** * @var int */ private $nodeMemorySize; public function __construct(string $path) { $this->path = $path; } /** * @api * @param KDTreeInterface $tree * @param string $identifier that identifies persisted tree(may be a filename, database name etc.) * @return mixed */ public function convert(KDTreeInterface $tree, string $identifier) { $this->initTree($identifier); $this->dimensions = $tree->getDimensionCount(); $this->calculateNodeSize(); $this->specifyNumberOfDimensions(); $this->specifyNumberOfItems($tree); $upperBound = $tree->getMaxBoundary(); $this->writeCoordinate($upperBound); $lowerBound = $tree->getMinBoundary(); $this->writeCoordinate($lowerBound); $root = $tree->getRoot(); if ($root) { $this->writeNode($root); } fclose($this->handler); } /** * @param NodeInterface $node */ private function writeNode(NodeInterface $node) { $position = ftell($this->handler); $item = $node->getItem(); $this->writeItemId($item); $dataChunk = pack('V', 0); // left position currently unknown so it equal 0/null fwrite($this->handler, $dataChunk); $rightNode = $node->getRight(); $rightPosition = 0; if ($rightNode) { $rightPosition = $position + $this->nodeMemorySize; } $dataChunk = pack('V', $rightPosition); fwrite($this->handler, $dataChunk); $this->saveItemCoordinate($item); if ($rightNode) { $this->writeNode($rightNode); } $leftNode = $node->getLeft(); if ($leftNode == null) { return; } $this->persistLeftLink($position); $this->writeNode($leftNode); } /** * @param array $coordinate */ private function writeCoordinate(array $coordinate) { $dataChunk = pack('d'.$this->dimensions, ...$coordinate); fwrite($this->handler, $dataChunk); } /** * @param string $identifier */ private function initTree(string $identifier) { $this->handler = fopen($this->path . '/' . $identifier, 'wb'); } /** * Calculate memory size in file needed for single node */ private function calculateNodeSize() { $this->nodeMemorySize = 3 * FSKDTree::INT_LENGTH + $this->dimensions * FSKDTree::FLOAT_LENGTH; } /** * Specify number of dimensions according to file format */ private function specifyNumberOfDimensions() { $dataChunk = pack('V', $this->dimensions); fwrite($this->handler, $dataChunk); } /** * @param KDTreeInterface $tree */ private function specifyNumberOfItems(KDTreeInterface $tree) { $itemCount = $tree->getItemCount(); $dataChunk = pack('V', $itemCount); fwrite($this->handler, $dataChunk); } /** * @param $item */ private function saveItemCoordinate(ItemInterface $item) { $coordinate = []; for ($i = 0; $i < $this->dimensions; $i++) { $coordinate[] = $item->getNthDimension($i); } $this->writeCoordinate($coordinate); } /** * Persist current position before writing left node * @param int $position */ private function persistLeftLink(int $position) { $leftPosition = ftell($this->handler); fseek($this->handler, $position + FSKDTree::INT_LENGTH); $dataChunk = pack('V', $leftPosition); fwrite($this->handler, $dataChunk); fseek($this->handler, $leftPosition); } /** * @param $item */ private function writeItemId(ItemInterface $item) { $itemId = $item->getId(); $dataChunk = pack('V', $itemId); fwrite($this->handler, $dataChunk); } }