diff options
Diffstat (limited to 'src/libdepixelize')
| -rw-r--r-- | src/libdepixelize/kopftracer2011.cpp | 415 | ||||
| -rw-r--r-- | src/libdepixelize/kopftracer2011.h | 26 | ||||
| -rw-r--r-- | src/libdepixelize/priv/homogeneoussplines.h | 21 | ||||
| -rw-r--r-- | src/libdepixelize/priv/pixelgraph.h | 80 | ||||
| -rw-r--r-- | src/libdepixelize/priv/simplifiedvoronoi.h | 271 |
5 files changed, 655 insertions, 158 deletions
diff --git a/src/libdepixelize/kopftracer2011.cpp b/src/libdepixelize/kopftracer2011.cpp index ab31d05c3..e2f387c86 100644 --- a/src/libdepixelize/kopftracer2011.cpp +++ b/src/libdepixelize/kopftracer2011.cpp @@ -31,7 +31,6 @@ #include <glibmm/threads.h> #endif -#include <utility> #include <algorithm> #include "kopftracer2011.h" #include "priv/colorspace.h" @@ -40,6 +39,11 @@ #include "priv/splines-kopf2011.h" #include "priv/iterator.h" +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 +#include <glibmm/datetime.h> +#include <iostream> +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + namespace Tracer { namespace Heuristics { @@ -86,7 +90,95 @@ Splines Kopf2011::to_voronoi(const std::string &filename, Splines Kopf2011::to_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf, const Options &options) { +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + SimplifiedVoronoi<Precision, false> voronoi + = _voronoi<Precision, false>(buf, options); + + Glib::DateTime profiling_info[2]; + profiling_info[0] = Glib::DateTime::create_now_utc(); + + Splines ret(voronoi); + + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Splines construction time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + + return ret; +#else // LIBDEPIXELIZE_PROFILE_KOPF2011 return Splines(_voronoi<Precision, false>(buf, options)); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 +} + +Splines Kopf2011::to_grouped_voronoi(const std::string &filename, + const Options &options) +{ + return to_grouped_voronoi(Gdk::Pixbuf::create_from_file(filename), options); +} + +Splines Kopf2011::to_grouped_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf, + const Options &options) +{ +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + SimplifiedVoronoi<Precision, false> voronoi + = _voronoi<Precision, false>(buf, options); + + Glib::DateTime profiling_info[2]; + profiling_info[0] = Glib::DateTime::create_now_utc(); + + HomogeneousSplines<Precision> splines(voronoi); + +#else // LIBDEPIXELIZE_PROFILE_KOPF2011 + HomogeneousSplines<Precision> splines(_voronoi<Precision, false> + (buf, options)); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name() + << ">(Tracer::SimplifiedVoronoi<" << typeid(Precision).name() + << ",false>) construction time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + + for ( HomogeneousSplines<Precision>::iterator it = splines.begin(), + end = splines.end() ; it != end ; ++it ) { + for ( HomogeneousSplines<Precision>::Polygon::points_iter + it2 = it->vertices.begin(), end2 = it->vertices.end() + ; it2 != end2 ; ++it2 ) { + it2->smooth = false; + } + for ( HomogeneousSplines<Precision>::Polygon::holes_iter + it2 = it->holes.begin(), end2 = it->holes.end() + ; it2 != end2 ; ++it2 ) { + for ( HomogeneousSplines<Precision>::Polygon::points_iter + it3 = it2->begin(), end3 = it2->end() + ; it3 != end3 ; ++it3 ) { + it3->smooth = false; + } + } + } + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Kopf2011::to_grouped_voronoi internal work time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + profiling_info[0] = Glib::DateTime::create_now_utc(); + + Splines ret(splines, false, options.nthreads); + + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Splines construction time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + + return ret; +#else // LIBDEPIXELIZE_PROFILE_KOPF2011 + return Splines(splines, false, options.nthreads); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 } Splines Kopf2011::to_splines(const std::string &filename, @@ -98,9 +190,36 @@ Splines Kopf2011::to_splines(const std::string &filename, Splines Kopf2011::to_splines(const Glib::RefPtr<Gdk::Pixbuf const> &buf, const Options &options) { +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + SimplifiedVoronoi<Precision, true> voronoi + = _voronoi<Precision, true>(buf, options); + + Glib::DateTime profiling_info[2]; + profiling_info[0] = Glib::DateTime::create_now_utc(); + + HomogeneousSplines<Precision> splines(voronoi); + + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name() + << "> construction time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + + profiling_info[0] = Glib::DateTime::create_now_utc(); + + Splines ret(splines, options.optimize, options.nthreads); + + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Splines construction time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; + + return ret; +#else // LIBDEPIXELIZE_PROFILE_KOPF2011 HomogeneousSplines<Precision> splines(_voronoi<Precision, true> (buf, options)); return Splines(splines, options.optimize, options.nthreads); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 } template<class T, bool adjust_splines> @@ -108,47 +227,131 @@ SimplifiedVoronoi<T, adjust_splines> Kopf2011::_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf, const Options &options) { +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + Glib::DateTime profiling_info[2]; + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + PixelGraph graph(buf); - /*if ( !graph.width() || !graph.height() ) - return;*/ +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::PixelGraph creation time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + + // gdk-pixbuf2 already checks if image size is meaningful, but asserts state + // preconditions and will be useful if gdk-pixbuf is replaced later + assert(graph.width() > 0); + assert(graph.height() > 0); #ifndef NDEBUG graph.checkConsistency(); #endif +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + // This step could be part of the initialization of PixelGraph // and decrease the necessary number of passes graph.connectAllNeighbors(); +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::PixelGraph::connectAllNeighbors() time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + #ifndef NDEBUG graph.checkConsistency(); #endif +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + // This step can't be part of PixelGraph initilization without adding some // cache misses due to random access patterns that might be injected _disconnect_neighbors_with_dissimilar_colors(graph); +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Kopf2011::" + "_disconnect_neighbors_with_dissimilar_colors(Tracer::PixelGraph) time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + #ifndef NDEBUG graph.checkConsistency(); #endif - // This and below steps must be executed in separate. - // Otherwise, there will be colateral effects due to misassumption about the - // data being read. - _remove_crossing_edges_safe(graph); +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + + { + // edges_safe and edges_unsafe must be executed in separate. + // Otherwise, there will be colateral effects due to misassumption about + // the data being read. + PixelGraph::EdgePairContainer edges = graph.crossingEdges(); + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::PixelGraph::crossingEdges() time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + + _remove_crossing_edges_safe(edges); + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_safe" + "(Tracer::PixelGraph) time: " + << profiling_info[1].difference(profiling_info[0]) + << std::endl; +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 #ifndef NDEBUG - graph.checkConsistency(); + graph.checkConsistency(); #endif - _remove_crossing_edges_unsafe(graph, options); +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[0] = Glib::DateTime::create_now_utc(); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 + + _remove_crossing_edges_unsafe(graph, edges, options); + } + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_unsafe" + "(Tracer::PixelGraph) time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 #ifndef NDEBUG graph.checkConsistency(); #endif + assert(graph.crossingEdges().size() == 0); + +#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011 + profiling_info[0] = Glib::DateTime::create_now_utc(); + + SimplifiedVoronoi<T, adjust_splines> ret(graph); + + profiling_info[1] = Glib::DateTime::create_now_utc(); + std::cerr << "Tracer::SimplifiedVoronoi<" << typeid(T).name() << ',' + << (adjust_splines ? "true" : "false") + << ">(Tracer::PixelGraph) construction time: " + << profiling_info[1].difference(profiling_info[0]) << std::endl; + + return ret; +#else // LIBDEPIXELIZE_PROFILE_KOPF2011 return SimplifiedVoronoi<T, adjust_splines>(graph); +#endif // LIBDEPIXELIZE_PROFILE_KOPF2011 } // TODO: move this function (plus connectAllNeighbors) to PixelGraph constructor @@ -192,123 +395,115 @@ Kopf2011::_disconnect_neighbors_with_dissimilar_colors(PixelGraph &graph) * * In this case the two diagonal connections can be safely removed without * affecting the final result. - * - * \TODO: It should remember/cache who are the unsafe crossing edges? */ -inline void Kopf2011::_remove_crossing_edges_safe(PixelGraph &graph) +template<class T> +void Kopf2011::_remove_crossing_edges_safe(T &container) { - if ( graph.width() < 2 || graph.height() < 2 ) - return; - - PixelGraph::iterator it = graph.begin(); - for ( int i = 0 ; i != graph.height() - 1 ; ++i, ++it ) { - for ( int j = 0 ; j != graph.width() - 1 ; ++j, ++it ) { - // this <-> right - if ( !it->adj.right ) - continue; - - // this <-> down - if ( !it->adj.bottom ) - continue; - - PixelGraph::iterator down_right = it + graph.width() + 1; - - // down_right <-> right - if ( !down_right->adj.top ) - continue; + for ( typename T::reverse_iterator it = container.rbegin(), + end = container.rend() ; it != end ; ) { + /* A | B + --+-- + C | D */ + PixelGraph::iterator a = it->first.first; + PixelGraph::iterator b = it->second.first; + PixelGraph::iterator c = it->second.second; + PixelGraph::iterator d = it->first.second; + + if ( !a->adj.right || !a->adj.bottom || !b->adj.bottom + || !c->adj.right ) { + ++it; + continue; + } - // down_right <-> down - if ( !down_right->adj.left ) - continue; + // main diagonal + a->adj.bottomright = 0; + d->adj.topleft = 0; - // main diagonal - // this <-> down_right - it->adj.bottomright = 0; - down_right->adj.topleft = 0; + // secondary diagonal + b->adj.bottomleft = 0; + c->adj.topright = 0; - // secondary diagonal - // right <-> down - (it + 1)->adj.bottomleft = 0; - (it + graph.width())->adj.topright = 0; - } + // base iterator is always past one + typename T::iterator current = --(it.base()); + ++it; + container.erase(current); } } /** * This method removes crossing edges using the heuristics. */ -inline -void Kopf2011::_remove_crossing_edges_unsafe(PixelGraph &graph, +template<class T> +void Kopf2011::_remove_crossing_edges_unsafe(PixelGraph &graph, T &edges, const Options &options) { - if ( graph.width() < 2 || graph.height() < 2 ) - return; - - // Iterate over the graph, 2x2 blocks at time - PixelGraph::iterator it = graph.begin(); - for (int i = 0 ; i != graph.height() - 1 ; ++i, ++it ) { - for ( int j = 0 ; j != graph.width() - 1 ; ++j, ++it ) { - using std::pair; - using std::make_pair; - - typedef pair<PixelGraph::iterator, PixelGraph::iterator> Edge; - typedef pair<Edge, int> EdgeWeight; - - EdgeWeight diagonals[2] = { - make_pair(make_pair(it, graph.nodeBottomRight(it)), 0), - make_pair(make_pair(graph.nodeRight(it), graph.nodeBottom(it)), - 0) - }; - - // Check if there are crossing edges - if ( !diagonals[0].first.first->adj.bottomright - || !diagonals[1].first.first->adj.bottomleft ) { - continue; - } - - // Compute weights - for ( int i = 0 ; i != 2 ; ++i ) { - // Curves and islands heuristics - PixelGraph::const_iterator a = diagonals[i].first.first; - PixelGraph::const_iterator b = diagonals[i].first.second; - - diagonals[i].second += Heuristics::curves(graph, a, b) - * options.curvesMultiplier; - - diagonals[i].second += Heuristics::islands(a, b) - * options.islandsWeight; - } - - { - // Sparse pixels heuristic - Heuristics::SparsePixels sparse_pixels; - - for ( int i = 0 ; i != 2 ; ++i ) - sparse_pixels.diagonals[i] = diagonals[i]; - - sparse_pixels(graph, options.sparsePixelsRadius); - - for ( int i = 0 ; i != 2 ; ++i ) { - diagonals[i].second += sparse_pixels.diagonals[i].second - * options.sparsePixelsMultiplier; - } - } + std::vector< std::pair<int, int> > weights(edges.size(), + std::make_pair(0, 0)); + + // Compute weights + for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) { + /* A | B + --+-- + C | D */ + PixelGraph::iterator a = edges[i].first.first; + PixelGraph::iterator b = edges[i].second.first; + PixelGraph::iterator c = edges[i].second.second; + PixelGraph::iterator d = edges[i].first.second; + + // Curves heuristic + weights[i].first += Heuristics::curves(graph, a, d) + * options.curvesMultiplier; + weights[i].second += Heuristics::curves(graph, b, c) + * options.curvesMultiplier; + + // Islands heuristic + weights[i].first += Heuristics::islands(a, d) * options.islandsWeight; + weights[i].second += Heuristics::islands(b, c) * options.islandsWeight; + + // Sparse pixels heuristic + using Heuristics::SparsePixels; + SparsePixels sparse_pixels; + + sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].first + = edges[i].first; + sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].first + = edges[i].second; + + sparse_pixels(graph, options.sparsePixelsRadius); + + weights[i].first + += sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].second + * options.sparsePixelsMultiplier; + weights[i].second + += sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].second + * options.sparsePixelsMultiplier; + } - // Remove edges with lower weight - if ( diagonals[0].second > diagonals[1].second ) { - diagonals[1].first.first->adj.bottomleft = 0; - diagonals[1].first.second->adj.topright = 0; - } else if ( diagonals[0].second < diagonals[1].second ) { - diagonals[0].first.first->adj.bottomright = 0; - diagonals[0].first.second->adj.topleft = 0; - } else { - diagonals[0].first.first->adj.bottomright = 0; - diagonals[0].first.second->adj.topleft = 0; - diagonals[1].first.first->adj.bottomleft = 0; - diagonals[1].first.second->adj.topright = 0; - } + // Remove edges with lower weight + for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) { + /* A | B + --+-- + C | D */ + PixelGraph::iterator a = edges[i].first.first; + PixelGraph::iterator b = edges[i].second.first; + PixelGraph::iterator c = edges[i].second.second; + PixelGraph::iterator d = edges[i].first.second; + + if ( weights[i].first > weights[i].second ) { + b->adj.bottomleft = 0; + c->adj.topright = 0; + } else if ( weights[i].first < weights[i].second ) { + a->adj.bottomright = 0; + d->adj.topleft = 0; + } else { + a->adj.bottomright = 0; + b->adj.bottomleft = 0; + c->adj.topright = 0; + d->adj.topleft = 0; } } + + edges.clear(); } inline int Heuristics::curves(const PixelGraph &graph, diff --git a/src/libdepixelize/kopftracer2011.h b/src/libdepixelize/kopftracer2011.h index c224abe9a..598f6c79c 100644 --- a/src/libdepixelize/kopftracer2011.h +++ b/src/libdepixelize/kopftracer2011.h @@ -88,6 +88,23 @@ public: /** * # Exceptions * + * \p options.optimize and options.nthreads will be ignored + * + * Glib::FileError + * Gdk::PixbufError + */ + static Splines to_grouped_voronoi(const std::string &filename, + const Options &options = Options()); + + /* + * \p options.optimize and options.nthreads will be ignored + */ + static Splines to_grouped_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf, + const Options &options = Options()); + + /** + * # Exceptions + * * Glib::FileError * Gdk::PixbufError */ @@ -106,8 +123,13 @@ private: const Options &options); static void _disconnect_neighbors_with_dissimilar_colors(PixelGraph &graph); - static void _remove_crossing_edges_safe(PixelGraph &graph); - static void _remove_crossing_edges_unsafe(PixelGraph &graph, + + // here, T/template is only used as an easy way to not expose internal + // symbols + template<class T> + static void _remove_crossing_edges_safe(T &container); + template<class T> + static void _remove_crossing_edges_unsafe(PixelGraph &graph, T &edges, const Options &options); }; diff --git a/src/libdepixelize/priv/homogeneoussplines.h b/src/libdepixelize/priv/homogeneoussplines.h index 57c77a163..6c4894dd8 100644 --- a/src/libdepixelize/priv/homogeneoussplines.h +++ b/src/libdepixelize/priv/homogeneoussplines.h @@ -38,6 +38,12 @@ class HomogeneousSplines public: struct Polygon { + typedef std::vector< Point<T> > Points; + typedef typename Points::iterator points_iter; + typedef typename Points::const_iterator const_points_iter; + typedef typename std::vector<Points>::iterator holes_iter; + typedef typename std::vector<Points>::const_iterator const_holes_iter; + Polygon() {} Polygon(const guint8 (&rgba)[4]) { @@ -59,7 +65,8 @@ public: typedef typename std::vector<Polygon>::const_iterator const_iterator; typedef typename std::vector<Polygon>::size_type size_type; - HomogeneousSplines(const SimplifiedVoronoi<T> &voronoi); + template<bool adjust_splines> + HomogeneousSplines(const SimplifiedVoronoi<T, adjust_splines> &voronoi); // Iterators iterator begin() @@ -98,12 +105,7 @@ public: } private: - typedef typename SimplifiedVoronoi<T>::Cell Cell; typedef std::vector< Point<T> > Points; - - typedef typename SimplifiedVoronoi<T>::iterator voronoi_iter; - typedef typename SimplifiedVoronoi<T>::const_iterator voronoi_citer; - typedef typename Points::iterator points_iter; typedef typename Points::const_iterator points_citer; typedef typename Points::reverse_iterator points_riter; @@ -171,7 +173,9 @@ private: }; template<class T> -HomogeneousSplines<T>::HomogeneousSplines(const SimplifiedVoronoi<T> &voronoi) : +template<bool adjust_splines> +HomogeneousSplines<T>::HomogeneousSplines(const SimplifiedVoronoi<T, + adjust_splines> &voronoi) : _width(voronoi.width()), _height(voronoi.height()) { @@ -179,6 +183,9 @@ HomogeneousSplines<T>::HomogeneousSplines(const SimplifiedVoronoi<T> &voronoi) : // return; using colorspace::same_color; + typedef typename SimplifiedVoronoi<T, adjust_splines>::const_iterator + voronoi_citer; + // Identify visible edges (group polygons with the same color) for ( voronoi_citer cell_it = voronoi.begin(), cell_end = voronoi.end() ; cell_it != cell_end ; ++cell_it ) { diff --git a/src/libdepixelize/priv/pixelgraph.h b/src/libdepixelize/priv/pixelgraph.h index 9e8c2124a..112242647 100644 --- a/src/libdepixelize/priv/pixelgraph.h +++ b/src/libdepixelize/priv/pixelgraph.h @@ -28,6 +28,7 @@ #include <gdkmm/pixbuf.h> #include <vector> #include <cassert> +#include <utility> namespace Tracer { @@ -76,6 +77,10 @@ public: typedef std::vector<Node>::reverse_iterator reverse_iterator; typedef std::vector<Node>::const_reverse_iterator const_reverse_iterator; + typedef std::pair<iterator, iterator> Edge; + typedef std::pair<Edge, Edge> EdgePair; + typedef std::vector<EdgePair> EdgePairContainer; + class ColumnView { public: @@ -162,6 +167,7 @@ public: // Algorithms void connectAllNeighbors(); + EdgePairContainer crossingEdges(); int toX(const_iterator n) const { @@ -389,14 +395,23 @@ inline void PixelGraph::connectAllNeighbors() // ...then the "top" nodes... if ( _width > 2 ) { Node *it = &_nodes[1]; - for ( int i = 1 ; i != _width - 1 ; ++i ) { - it->adj.right = 1; - it->adj.bottomright = 1; - it->adj.bottom = 1; - it->adj.bottomleft = 1; - it->adj.left = 1; + if ( _height > 1 ) { + for ( int i = 1 ; i != _width - 1 ; ++i ) { + it->adj.right = 1; + it->adj.bottomright = 1; + it->adj.bottom = 1; + it->adj.bottomleft = 1; + it->adj.left = 1; - ++it; + ++it; + } + } else { + for ( int i = 1 ; i != _width - 1 ; ++i ) { + it->adj.right = 1; + it->adj.left = 1; + + ++it; + } } } @@ -417,14 +432,23 @@ inline void PixelGraph::connectAllNeighbors() // ...then the "left" nodes... if ( _height > 2 ) { iterator it = nodeBottom(begin()); // [0][1] - for ( int i = 1 ; i != _height - 1 ; ++i ) { - it->adj.top = 1; - it->adj.topright = 1; - it->adj.right = 1; - it->adj.bottomright = 1; - it->adj.bottom = 1; + if ( _width > 1 ) { + for ( int i = 1 ; i != _height - 1 ; ++i ) { + it->adj.top = 1; + it->adj.topright = 1; + it->adj.right = 1; + it->adj.bottomright = 1; + it->adj.bottom = 1; - it = nodeBottom(it); + it = nodeBottom(it); + } + } else { + for ( int i = 1 ; i != _height - 1 ; ++i ) { + it->adj.top = 1; + it->adj.bottom = 1; + + it = nodeBottom(it); + } } } @@ -482,6 +506,34 @@ inline void PixelGraph::connectAllNeighbors() } } +PixelGraph::EdgePairContainer PixelGraph::crossingEdges() +{ + EdgePairContainer ret; + + if ( width() < 2 || height() < 2 ) + return ret; + + // Iterate over the graph, 2x2 blocks at time + PixelGraph::iterator it = begin(); + for (int i = 0 ; i != height() - 1 ; ++i, ++it ) { + for ( int j = 0 ; j != width() - 1 ; ++j, ++it ) { + EdgePair diagonals( + Edge(it, nodeBottomRight(it)), + Edge(nodeRight(it), nodeBottom(it))); + + // Check if there are crossing edges + if ( !diagonals.first.first->adj.bottomright + || !diagonals.second.first->adj.bottomleft ) { + continue; + } + + ret.push_back(diagonals); + } + } + + return ret; +} + inline PixelGraph::Node &PixelGraph::ColumnView::operator[](int line) { return _nodes[line * _width + _column]; diff --git a/src/libdepixelize/priv/simplifiedvoronoi.h b/src/libdepixelize/priv/simplifiedvoronoi.h index 8a25bc626..84feab08d 100644 --- a/src/libdepixelize/priv/simplifiedvoronoi.h +++ b/src/libdepixelize/priv/simplifiedvoronoi.h @@ -296,21 +296,40 @@ SimplifiedVoronoi<T, adjust_splines> PixelGraph::const_iterator graph_it = graph.begin() + 1; Cell *cells_it = &_cells.front() + 1; - for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) { - for ( int j = 0 ; j != 4 ; ++j ) - cells_it->rgba[j] = graph_it->rgba[j]; + if ( _height > 1 ) { + for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) { + for ( int j = 0 ; j != 4 ; ++j ) + cells_it->rgba[j] = graph_it->rgba[j]; - // Top-left - cells_it->vertices.push_back(Point<T>(i, 0, false)); + // Top-left + cells_it->vertices.push_back(Point<T>(i, 0, false)); - // Top-right - cells_it->vertices.push_back(Point<T>(i + 1, 0, false)); + // Top-right + cells_it->vertices.push_back(Point<T>(i + 1, 0, false)); - // Bottom-right - _complexBottomRight(graph, graph_it, cells_it, i, 0); + // Bottom-right + _complexBottomRight(graph, graph_it, cells_it, i, 0); - // Bottom-left - _complexBottomLeft(graph, graph_it, cells_it, i, 0); + // Bottom-left + _complexBottomLeft(graph, graph_it, cells_it, i, 0); + } + } else { + for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) { + for ( int j = 0 ; j != 4 ; ++j ) + cells_it->rgba[j] = graph_it->rgba[j]; + + // Top-left + cells_it->vertices.push_back(Point<T>(i, 0, false)); + + // Top-right + cells_it->vertices.push_back(Point<T>(i + 1, 0, false)); + + // Bottom-right + cells_it->vertices.push_back(Point<T>(i + 1, 1, false)); + + // Bottom-left + cells_it->vertices.push_back(Point<T>(i, 1, false)); + } } } @@ -344,24 +363,46 @@ SimplifiedVoronoi<T, adjust_splines> PixelGraph::const_iterator graph_it = graph.begin() + _width; Cell *cells_it = &_cells.front() + _width; - for ( int i = 1 ; i != _height - 1 ; ++i) { - for ( int j = 0 ; j != 4 ; ++j ) - cells_it->rgba[j] = graph_it->rgba[j]; + if ( _width > 1 ) { + for ( int i = 1 ; i != _height - 1 ; ++i) { + for ( int j = 0 ; j != 4 ; ++j ) + cells_it->rgba[j] = graph_it->rgba[j]; - // Top-left - cells_it->vertices.push_back(Point<T>(0, i, false)); + // Top-left + cells_it->vertices.push_back(Point<T>(0, i, false)); - // Top-right - _complexTopRight(graph, graph_it, cells_it, 0, i); + // Top-right + _complexTopRight(graph, graph_it, cells_it, 0, i); - // Bottom-right - _complexBottomRight(graph, graph_it, cells_it, 0, i); + // Bottom-right + _complexBottomRight(graph, graph_it, cells_it, 0, i); - // Bottom-left - cells_it->vertices.push_back(Point<T>(0, i + 1, false)); + // Bottom-left + cells_it->vertices.push_back(Point<T>(0, i + 1, false)); - graph_it += _width; - cells_it += _width; + graph_it += _width; + cells_it += _width; + } + } else { + for ( int i = 1 ; i != _height - 1 ; ++i) { + for ( int j = 0 ; j != 4 ; ++j ) + cells_it->rgba[j] = graph_it->rgba[j]; + + // Top-left + cells_it->vertices.push_back(Point<T>(0, i, false)); + + // Top-right + cells_it->vertices.push_back(Point<T>(1, i, false)); + + // Bottom-right + cells_it->vertices.push_back(Point<T>(1, i, false)); + + // Bottom-left + cells_it->vertices.push_back(Point<T>(0, i + 1, false)); + + graph_it += _width; + cells_it += _width; + } } } @@ -890,7 +931,11 @@ SimplifiedVoronoi<T, adjust_splines> } if ( !smooth[0] && adjust_splines ) { - cells_it->vertices.push_back(vertices[0].invisible()); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE + cells_it->vertices.push_back(vertices[0].invisible()); +#else + cells_it->vertices.push_back(vertices[0]); +#endif { Point<T> another = vertices[0]; transform(another, @@ -899,7 +944,11 @@ SimplifiedVoronoi<T, adjust_splines> // y - ( 0.5625 - ( topright(a_it) + topleft(b_it) ) * 0.1875 )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertices[0]; @@ -910,7 +959,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( 0.1875 - ( topright(a_it) + topleft(b_it) ) * 0.0625) ); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertices[0]; @@ -920,7 +973,11 @@ SimplifiedVoronoi<T, adjust_splines> // y 0.0625 + ( bottomright(b_it) - topright(d_it) ) * 0.0625); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { transform(vertices[0], @@ -932,7 +989,9 @@ SimplifiedVoronoi<T, adjust_splines> + ( topright(d_it) - topright(a_it) - topleft(b_it) - bottomright(b_it) ) * 0.03125 )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertices[0].visible = false; +#endif } } @@ -950,7 +1009,11 @@ SimplifiedVoronoi<T, adjust_splines> 0.0625 + ( bottomleft(a_it) - bottomleft(d_it) - topleft(c_it) - bottomright(c_it) ) * 0.03125); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertices[1]; @@ -960,7 +1023,11 @@ SimplifiedVoronoi<T, adjust_splines> // y 0.1875 - ( bottomright(c_it) + bottomleft(d_it) ) * 0.0625); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertices[1]; @@ -973,7 +1040,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( bottomleft(a_it) - topleft(c_it) ) * 0.0625 )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertices[1]; @@ -985,9 +1056,15 @@ SimplifiedVoronoi<T, adjust_splines> - ( 0.1875 - ( bottomleft(a_it) - topleft(c_it) ) * 0.1875 )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertices[1].visible = false; +#endif } cells_it->vertices.push_back(vertices[1]); @@ -1029,13 +1106,21 @@ SimplifiedVoronoi<T, adjust_splines> - ( ( bottomright(c_it) + topleft(c_it) ) * 0.03125 ); transform(another, - amount, amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * bottomright(c_it); transform(another, amount, 0.25 - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1043,16 +1128,26 @@ SimplifiedVoronoi<T, adjust_splines> transform(another, - ( 0.25 - amount ), - amount); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.1875 * topleft(c_it); transform(another, - ( 0.75 - amount ), - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } else if ( twin_is_contour ) { T amount = 0.125 - ( ( bottomleft(d_it) + topright(d_it) ) @@ -1076,7 +1171,11 @@ SimplifiedVoronoi<T, adjust_splines> - amount * ( topleft(c_it) + topright(d_it) - bottomleft(a_it) - bottomright(b_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1087,7 +1186,11 @@ SimplifiedVoronoi<T, adjust_splines> // y - amount * ( topright(d_it) - bottomright(b_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1099,7 +1202,11 @@ SimplifiedVoronoi<T, adjust_splines> - amount * ( topleft(c_it) - bottomleft(a_it) )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1110,9 +1217,15 @@ SimplifiedVoronoi<T, adjust_splines> // y - amount * ( topleft(c_it) - bottomleft(a_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } else { // {this, right} is the pair with the angle @@ -1146,13 +1259,21 @@ SimplifiedVoronoi<T, adjust_splines> if ( !vertex.smooth ) { if ( another_is_contour ) { +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(vertex.invisible()); +#else + cells_it->vertices.push_back(vertex); +#endif { Point<T> another = vertex; T amount = 0.1875 * topleft(b_it); transform(another, - amount, - ( 0.75 - amount )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1160,20 +1281,30 @@ SimplifiedVoronoi<T, adjust_splines> transform(another, - amount, - ( 0.25 - amount )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * bottomright(b_it); transform(another, 0.25 - amount, amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { T amount = 0.125 - (bottomright(b_it) + topleft(b_it)) * 0.03125; transform(vertex, amount, - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } else if ( twin_is_contour ) { T amount = 0.125 @@ -1187,7 +1318,11 @@ SimplifiedVoronoi<T, adjust_splines> // I REALLY NEED lambdas to improve this code without // creating yet another interface that takes a million // of function parameters and keep code locality +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(vertex.invisible()); +#else + cells_it->vertices.push_back(vertex); +#endif { Point<T> another = vertex; T amount = 0.1875; @@ -1197,7 +1332,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( 0.75 - ( topleft(b_it) + topright(a_it) ) * amount )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1209,7 +1348,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( topleft(b_it) + topright(a_it) ) * amount )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1219,7 +1362,11 @@ SimplifiedVoronoi<T, adjust_splines> // y 0.25 - amount * ( bottomleft(d_it) + bottomright(c_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { transform(vertex, @@ -1230,7 +1377,9 @@ SimplifiedVoronoi<T, adjust_splines> ( topleft(b_it) - bottomleft(d_it) + topright(a_it) - bottomright(c_it) ) * 0.03125); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } } else { @@ -1273,28 +1422,46 @@ SimplifiedVoronoi<T, adjust_splines> - ( topleft(c_it) + bottomright(c_it) ) * 0.03125; transform(another, - amount, amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * bottomright(c_it); transform(another, amount, 0.25 - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * topleft(c_it); transform(another, - ( 0.25 - amount ), - amount); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.1875 * topleft(c_it); transform(another, - ( 0.75 - amount ), - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } else { special = true; } @@ -1308,7 +1475,11 @@ SimplifiedVoronoi<T, adjust_splines> } if ( special ) { +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(vertex.invisible()); +#else + cells_it->vertices.push_back(vertex); +#endif { Point<T> another = vertex; T amount = 0.1875; @@ -1318,7 +1489,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( 0.75 - ( topleft(b_it) + topright(a_it) ) * amount )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1330,7 +1505,11 @@ SimplifiedVoronoi<T, adjust_splines> - ( topleft(b_it) + topright(a_it) ) * amount )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1340,7 +1519,11 @@ SimplifiedVoronoi<T, adjust_splines> // y 0.25 - amount * ( bottomleft(d_it) + bottomright(c_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { transform(vertex, @@ -1351,7 +1534,9 @@ SimplifiedVoronoi<T, adjust_splines> ( topleft(b_it) - bottomleft(d_it) + topright(a_it) - bottomright(c_it) ) * 0.03125); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } } else if ( right(c_it) && adjust_splines ) { @@ -1372,31 +1557,49 @@ SimplifiedVoronoi<T, adjust_splines> if ( !vertex.smooth ) { if ( similar_neighbor_is_contour ) { +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(vertex.invisible()); +#else + cells_it->vertices.push_back(vertex); +#endif { Point<T> another = vertex; T amount = 0.1875 * topleft(b_it); transform(another, - amount, - ( 0.75 - amount )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * topleft(b_it); transform(another, - amount, - ( 0.25 - amount )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; T amount = 0.0625 * bottomright(b_it); transform(another, 0.25 - amount, amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { T amount = 0.125 - 0.03125 * (topleft(b_it) + bottomright(b_it)); transform(vertex, amount, - amount); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } else { special = true; @@ -1422,7 +1625,11 @@ SimplifiedVoronoi<T, adjust_splines> - amount * ( topleft(c_it) + topright(d_it) - bottomleft(a_it) - bottomright(b_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1433,7 +1640,11 @@ SimplifiedVoronoi<T, adjust_splines> // y - amount * ( topright(d_it) - bottomright(b_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1445,7 +1656,11 @@ SimplifiedVoronoi<T, adjust_splines> - amount * ( topleft(c_it) - bottomleft(a_it) )); another.smooth = true; +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE + cells_it->vertices.push_back(another.invisible()); +#else cells_it->vertices.push_back(another); +#endif } { Point<T> another = vertex; @@ -1456,9 +1671,15 @@ SimplifiedVoronoi<T, adjust_splines> // y - amount * ( topleft(c_it) - bottomleft(a_it) )); +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE cells_it->vertices.push_back(another.invisible()); +#else + cells_it->vertices.push_back(another); +#endif } +#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE vertex.visible = false; +#endif } } else { // there is a 4-color pattern, where the current node |
