/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup freestyle * \brief Chaining iterators */ #include "../python/Director.h" #include "ChainingIterators.h" #include "../system/TimeStamp.h" namespace Freestyle { ViewEdge *AdjacencyIterator::operator*() { return (*_internalIterator).first; } bool AdjacencyIterator::isIncoming() const { return (*_internalIterator).second; } int AdjacencyIterator::increment() { ++_internalIterator; while (!_internalIterator.isEnd() && !isValid((*_internalIterator).first)) { ++_internalIterator; } return 0; } bool AdjacencyIterator::isValid(ViewEdge *edge) { if (_restrictToSelection) { if (edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp()) { return false; } } if (_restrictToUnvisited) { if (edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp()) { return false; } } return true; } int ChainingIterator::init() { return Director_BPy_ChainingIterator_init(this); } int ChainingIterator::traverse(const AdjacencyIterator &it) { return Director_BPy_ChainingIterator_traverse(this, const_cast(it)); } int ChainingIterator::increment() { _increment = true; ViewVertex *vertex = getVertex(); if (!vertex) { _edge = nullptr; return 0; } AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); if (it.isEnd()) { _edge = nullptr; return 0; } if (traverse(it) < 0) { return -1; } _edge = result; if (_edge == nullptr) { return 0; } if (_edge->A() == vertex) { _orientation = true; } else { _orientation = false; } return 0; } int ChainingIterator::decrement() { _increment = false; ViewVertex *vertex = getVertex(); if (!vertex) { _edge = nullptr; return 0; } AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); if (it.isEnd()) { _edge = nullptr; return 0; } if (traverse(it) < 0) { return -1; } _edge = result; if (_edge == nullptr) { return 0; } if (_edge->B() == vertex) { _orientation = true; } else { _orientation = false; } return 0; } // // ChainSilhouetteIterators // /////////////////////////////////////////////////////////// int ChainSilhouetteIterator::traverse(const AdjacencyIterator &ait) { AdjacencyIterator it(ait); ViewVertex *nextVertex = getVertex(); // we can't get a NULL nextVertex here, it was intercepted before if (nextVertex->getNature() & Nature::T_VERTEX) { TVertex *tvertex = (TVertex *)nextVertex; ViewEdge *mate = (tvertex)->mate(getCurrentEdge()); while (!it.isEnd()) { ViewEdge *ve = *it; if (ve == mate) { result = ve; return 0; } ++it; } result = nullptr; return 0; } if (nextVertex->getNature() & Nature::NON_T_VERTEX) { // soc NonTVertex *nontvertex = (NonTVertex*)nextVertex; ViewEdge *newEdge(nullptr); // we'll try to chain the edges by keeping the same nature... // the preseance order is : SILHOUETTE, BORDER, CREASE, MATERIAL_BOUNDARY, EDGE_MARK, // SUGGESTIVE, VALLEY, RIDGE Nature::EdgeNature natures[8] = { Nature::SILHOUETTE, Nature::BORDER, Nature::CREASE, Nature::MATERIAL_BOUNDARY, Nature::EDGE_MARK, Nature::SUGGESTIVE_CONTOUR, Nature::VALLEY, Nature::RIDGE, }; int numNatures = ARRAY_SIZE(natures); for (int i = 0; i < numNatures; ++i) { if (getCurrentEdge()->getNature() & natures[i]) { int n = 0; while (!it.isEnd()) { ViewEdge *ve = *it; if (ve->getNature() & natures[i]) { ++n; newEdge = ve; } ++it; } if (n == 1) { result = newEdge; } else { result = nullptr; } return 0; } } } result = nullptr; return 0; } int ChainPredicateIterator::traverse(const AdjacencyIterator &ait) { if (!_unary_predicate || !_binary_predicate) { return -1; } AdjacencyIterator it(ait); // Iterates over next edges to see if one of them respects the predicate: while (!it.isEnd()) { ViewEdge *ve = *it; if (_unary_predicate->operator()(*ve) < 0) { return -1; } if (_unary_predicate->result) { if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0) { return -1; } if (_binary_predicate->result) { result = ve; return 0; } } ++it; } result = nullptr; return 0; } } /* namespace Freestyle */