Пример #1
0
 /**
  * @param LocalMinimumTable $lmtTable
  * @param ScanBeamTreeEntries $sbte
  * @param Polygon $polygon
  * @param int $type
  *
  * @return EdgeTable
  */
 protected function buildLmt(LocalMinimumTable $lmtTable, ScanBeamTreeEntries $sbte, Polygon $polygon, $type)
 {
     /* Create the entire input polygon edge table in one go */
     $edgeTable = new EdgeTable();
     for ($c = 0; $c < $polygon->getNumInnerPoly(); $c++) {
         $innerPolygon = $polygon->getInnerPolygon($c);
         if (isset($this->contributions[$innerPolygon->getId()]) && !$this->contributions[$innerPolygon->getId()]) {
             $this->contributions[$innerPolygon->getId()] = true;
         } else {
             /* Perform contour optimisation */
             $numVertices = 0;
             $eIndex = 0;
             $edgeTable = new EdgeTable();
             for ($i = 0; $i < $innerPolygon->nVertices(); $i++) {
                 if ($this->isOptimal($innerPolygon, $i)) {
                     $x = $innerPolygon->getInnerPolygon(0)->getPoints()[$i]->getX();
                     $y = $innerPolygon->getInnerPolygon(0)->getPoints()[$i]->getY();
                     $edgeTable->addNode($x, $y);
                     /* Perform contour optimisation */
                     self::addToSbtree($sbte, $y);
                     $numVertices++;
                 }
             }
             /* Do the contour forward pass */
             for ($min = 0; $min < $numVertices; $min++) {
                 /* If a forward local minimum */
                 if ($edgeTable->fwdMin($min)) {
                     /* Search for the next local maximum */
                     $numEdges = 1;
                     $max = $this->nextIndex($min, $numVertices);
                     while ($edgeTable->notFMax($max)) {
                         $numEdges++;
                         $max = $this->nextIndex($max, $numVertices);
                     }
                     /* Build the next edge list */
                     $v = $min;
                     $edgeNode = $edgeTable->getNode($eIndex);
                     $edgeNode->addBstate(self::BELOW, BundleState::unbundled());
                     $edgeNode->bundle[self::BELOW][self::CLIP] = 0;
                     $edgeNode->bundle[self::BELOW][self::SUBJ] = 0;
                     for ($i = 0; $i < $numEdges; $i++) {
                         $ei = $edgeTable->getNode($eIndex + $i);
                         $ev = $edgeTable->getNode($v);
                         $ei->setXb($ev->getVertex()->getX());
                         $ei->getBot()->setX($ev->getVertex()->getX());
                         $ei->getBot()->setY($ev->getVertex()->getY());
                         $v = $this->nextIndex($v, $numVertices);
                         $ev = $edgeTable->getNode($v);
                         $ei->getTop()->setX($ev->getVertex()->getX());
                         $ei->getTop()->setY($ev->getVertex()->getY());
                         $ei->setDx(($ev->getVertex()->getX() - $ei->getBot()->getX()) / ($ei->getTop()->getY() - $ei->getBot()->getY()));
                         $ei->setType($type);
                         $ei->outp[self::ABOVE] = null;
                         $ei->outp[self::BELOW] = null;
                         $ei->setNext(null);
                         $ei->setPrev(null);
                         $succ = $numEdges > 1 && $i < $numEdges - 1 ? $edgeTable->getNode($eIndex + $i + 1) : null;
                         $ei->setSucc($succ);
                         //                            $pred = (($numEdges > 1) && ($i > 0))
                         //                                ? $edgeNode->getNode($eIndex + $i - 1)
                         //                                : null;
                         $ei->setNextBound(null);
                         $ei->setBside([self::CLIP => self::LEFT, self::SUBJ => self::LEFT]);
                     }
                     self::insertBound(self::boundList($lmtTable, $edgeTable->getNode($min)->getVertex()->getY()), $edgeNode);
                     $eIndex += $numEdges;
                 }
             }
             /* Do the contour reverse pass */
             for ($min = 0; $min < $numVertices; $min++) {
                 /* If a reverse local minimum... */
                 if ($edgeTable->revMin($min)) {
                     /* Search for the previous local maximum */
                     $numEdges = 1;
                     $max = $this->prevIndex($min, $numVertices);
                     while ($edgeTable->notRMax($max)) {
                         $numEdges++;
                         $max = $this->prevIndex($max, $numVertices);
                     }
                     /* Build the previous edge list */
                     $v = $min;
                     $edgeNode = $edgeTable->getNode($eIndex);
                     $edgeNode->addBstate(self::BELOW, BundleState::unbundled());
                     $edgeNode->bundle[self::BELOW][self::CLIP] = 0;
                     $edgeNode->bundle[self::BELOW][self::SUBJ] = 0;
                     for ($i = 0; $i < $numEdges; $i++) {
                         $ei = $edgeTable->getNode($eIndex + $i);
                         $ev = $edgeTable->getNode($v);
                         $ei->setXb($ev->getVertex()->getX());
                         $ei->getBot()->setX($ev->getVertex()->getX());
                         $ei->getBot()->setY($ev->getVertex()->getY());
                         $v = $this->prevIndex($v, $numVertices);
                         $ev = $edgeTable->getNode($v);
                         $ei->getTop()->setX($ev->getVertex()->getX());
                         $ei->getTop()->setY($ev->getVertex()->getY());
                         $ei->setDx(($ev->getVertex()->getX() - $ei->getBot()->getX()) / ($ei->getTop()->getY() - $ei->getBot()->getY()));
                         $ei->setType($type);
                         $ei->outp[self::ABOVE] = null;
                         $ei->outp[self::BELOW] = null;
                         $ei->setNext(null);
                         $ei->setPrev(null);
                         $succ = $numEdges > 1 && $i < $numEdges - 1 ? $edgeTable->getNode($eIndex + $i + 1) : null;
                         $ei->setSucc($succ);
                         //                            $pred = (($numEdges > 1) && ($i > 0))
                         //                                ? $edgeNode->getNode($eIndex + $i - 1)
                         //                                : null;
                         $ei->setNextBound(null);
                         $ei->setBside([self::CLIP => self::LEFT, self::SUBJ => self::LEFT]);
                     }
                     self::insertBound(self::boundList($lmtTable, $edgeTable->getNode($min)->getVertex()->getY()), $edgeNode);
                     $eIndex += $numEdges;
                 }
             }
         }
     }
     return $edgeTable;
 }