File indexing completed on 2024-06-16 04:12:13

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_LAZY_FILL_GRAPH_H
0008 #define __KIS_LAZY_FILL_GRAPH_H
0009 
0010 #include <numeric>
0011 #include <boost/limits.hpp>
0012 #include <boost/operators.hpp>
0013 
0014 #include <boost/graph/graph_traits.hpp>
0015 #include <boost/graph/properties.hpp>
0016 #include <boost/iterator/counting_iterator.hpp>
0017 #include <boost/iterator/transform_iterator.hpp>
0018 
0019 #include <KisRegion.h>
0020 
0021 //#define USE_LAZY_FILL_SANITY_CHECKS 1
0022 
0023 #ifdef USE_LAZY_FILL_SANITY_CHECKS
0024 #define LF_SANITY_ASSERT(x) KIS_ASSERT(x)
0025 #define LF_SANITY_ASSERT_RECOVER(x) KIS_ASSERT_RECOVER(x)
0026 #else
0027 #define LF_SANITY_ASSERT(x)
0028 #define LF_SANITY_ASSERT_RECOVER(x) if (0)
0029 #endif /* USE_LAZY_FILL_SANITY_CHECKS */
0030 
0031 
0032 using namespace boost;
0033 
0034 /*
0035 BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<ScribbleMap, vertex_descriptor> )); //read flow-values from vertices
0036 */
0037 
0038 class KisLazyFillGraph;
0039 
0040 //===================
0041 // Index Property Map
0042 //===================
0043 
0044 template <typename Graph,
0045           typename Descriptor,
0046           typename Index>
0047 struct lazy_fill_graph_index_map {
0048 public:
0049     typedef Index value_type;
0050     typedef Index reference_type;
0051     typedef reference_type reference;
0052     typedef Descriptor key_type;
0053     typedef readable_property_map_tag category;
0054 
0055     lazy_fill_graph_index_map() { }
0056 
0057     lazy_fill_graph_index_map(const Graph& graph) :
0058         m_graph(&graph) { }
0059 
0060     value_type operator[](key_type key) const {
0061         value_type index = m_graph->index_of(key);
0062         LF_SANITY_ASSERT(index >= 0);
0063         return index;
0064     }
0065 
0066     friend inline Index
0067     get(const lazy_fill_graph_index_map<Graph, Descriptor, Index>& index_map,
0068         const typename lazy_fill_graph_index_map<Graph, Descriptor, Index>::key_type& key)
0069         {
0070             return (index_map[key]);
0071         }
0072 
0073 protected:
0074     const Graph* m_graph;
0075 };
0076 
0077 //==========================
0078 // Reverse Edge Property Map
0079 //==========================
0080 
0081 template <typename Descriptor>
0082 struct lazy_fill_graph_reverse_edge_map {
0083 public:
0084     typedef Descriptor value_type;
0085     typedef Descriptor reference_type;
0086     typedef reference_type reference;
0087     typedef Descriptor key_type;
0088     typedef readable_property_map_tag category;
0089 
0090     lazy_fill_graph_reverse_edge_map() { }
0091 
0092     value_type operator[](const key_type& key) const {
0093         return (value_type(key.second, key.first));
0094     }
0095 
0096     friend inline Descriptor
0097     get(const lazy_fill_graph_reverse_edge_map<Descriptor>& rev_map,
0098         const typename lazy_fill_graph_reverse_edge_map<Descriptor>::key_type& key)
0099         {
0100             return (rev_map[key]);
0101         }
0102 };
0103 
0104 //=================
0105 // Function Objects
0106 //=================
0107 
0108 namespace kis_detail {
0109 
0110     // vertex_at
0111     template <typename Graph>
0112     struct lazy_fill_graph_vertex_at {
0113 
0114         typedef typename graph_traits<Graph>::vertex_descriptor result_type;
0115 
0116         lazy_fill_graph_vertex_at() : m_graph(0) {}
0117 
0118         lazy_fill_graph_vertex_at(const Graph* graph) :
0119             m_graph(graph) { }
0120 
0121         result_type
0122         operator()
0123         (typename graph_traits<Graph>::vertices_size_type vertex_index) const {
0124             return (vertex(vertex_index, *m_graph));
0125         }
0126 
0127     private:
0128         const Graph* m_graph;
0129     };
0130 
0131     // out_edge_at
0132     template <typename Graph>
0133     struct lazy_fill_graph_out_edge_at {
0134 
0135     private:
0136         typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0137 
0138     public:
0139         typedef typename graph_traits<Graph>::edge_descriptor result_type;
0140 
0141         lazy_fill_graph_out_edge_at() : m_vertex(), m_graph(0) {}
0142 
0143         lazy_fill_graph_out_edge_at(vertex_descriptor source_vertex,
0144                                const Graph* graph) :
0145             m_vertex(source_vertex),
0146             m_graph(graph) { }
0147 
0148         result_type
0149         operator()
0150         (typename graph_traits<Graph>::degree_size_type out_edge_index) const {
0151             return (out_edge_at(m_vertex, out_edge_index, *m_graph));
0152         }
0153 
0154     private:
0155         vertex_descriptor m_vertex;
0156         const Graph* m_graph;
0157     };
0158 
0159     // in_edge_at
0160     template <typename Graph>
0161     struct lazy_fill_graph_in_edge_at {
0162 
0163     private:
0164         typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0165 
0166     public:
0167         typedef typename graph_traits<Graph>::edge_descriptor result_type;
0168 
0169         lazy_fill_graph_in_edge_at() : m_vertex(), m_graph(0) {}
0170 
0171         lazy_fill_graph_in_edge_at(vertex_descriptor target_vertex,
0172                               const Graph* graph) :
0173             m_vertex(target_vertex),
0174             m_graph(graph) { }
0175 
0176         result_type
0177         operator()
0178         (typename graph_traits<Graph>::degree_size_type in_edge_index) const {
0179             return (in_edge_at(m_vertex, in_edge_index, *m_graph));
0180         }
0181 
0182     private:
0183         vertex_descriptor m_vertex;
0184         const Graph* m_graph;
0185     };
0186 
0187     // edge_at
0188     template <typename Graph>
0189     struct lazy_fill_graph_edge_at {
0190 
0191         typedef typename graph_traits<Graph>::edge_descriptor result_type;
0192 
0193         lazy_fill_graph_edge_at() : m_graph(0) {}
0194 
0195         lazy_fill_graph_edge_at(const Graph* graph) :
0196             m_graph(graph) { }
0197 
0198         result_type
0199         operator()
0200         (typename graph_traits<Graph>::edges_size_type edge_index) const {
0201             return (edge_at(edge_index, *m_graph));
0202         }
0203 
0204     private:
0205         const Graph* m_graph;
0206     };
0207 
0208     // adjacent_vertex_at
0209     template <typename Graph>
0210     struct lazy_fill_graph_adjacent_vertex_at {
0211 
0212     public:
0213         typedef typename graph_traits<Graph>::vertex_descriptor result_type;
0214 
0215         lazy_fill_graph_adjacent_vertex_at(result_type source_vertex,
0216                                       const Graph* graph) :
0217             m_vertex(source_vertex),
0218             m_graph(graph) { }
0219 
0220         result_type
0221         operator()
0222         (typename graph_traits<Graph>::degree_size_type adjacent_index) const {
0223             return (target(out_edge_at(m_vertex, adjacent_index, *m_graph), *m_graph));
0224         }
0225 
0226     private:
0227         result_type m_vertex;
0228         const Graph* m_graph;
0229     };
0230 
0231 } // namespace kis_detail
0232 
0233 
0234 class KisLazyFillGraph
0235 {
0236 public:
0237     typedef KisLazyFillGraph type;
0238 
0239 
0240     typedef long VertexIndex;
0241     typedef long EdgeIndex;
0242 
0243     // sizes
0244     typedef VertexIndex vertices_size_type;
0245     typedef EdgeIndex edges_size_type;
0246     typedef EdgeIndex degree_size_type;
0247 
0248     struct VertexDescriptor : public equality_comparable<VertexDescriptor>
0249     {
0250         enum VertexType {
0251             NORMAL = 0,
0252             LABEL_A,
0253             LABEL_B
0254         };
0255 
0256         vertices_size_type x;
0257         vertices_size_type y;
0258         VertexType type;
0259 
0260         VertexDescriptor(vertices_size_type _x, vertices_size_type _y, VertexType _type = NORMAL)
0261             : x(_x), y(_y), type(_type) {}
0262 
0263         // TODO: Extra constructors look unnecessary, ask Dmitry before removing
0264         VertexDescriptor(VertexType _type)
0265             : x(0), y(0), type(_type) {}
0266 
0267         VertexDescriptor()
0268             : x(0), y(0), type(NORMAL) {}
0269 
0270         bool operator ==(const VertexDescriptor &rhs) const {
0271             return rhs.x == x && rhs.y == y && rhs.type == type;
0272         }
0273     };
0274 
0275     // descriptors
0276     typedef VertexDescriptor vertex_descriptor;
0277     typedef std::pair<vertex_descriptor, vertex_descriptor> edge_descriptor;
0278 
0279     friend QDebug operator<<(QDebug dbg, const KisLazyFillGraph::edge_descriptor &e);
0280     friend QDebug operator<<(QDebug dbg, const KisLazyFillGraph::vertex_descriptor &v);
0281 
0282     // vertex_iterator
0283     typedef counting_iterator<vertices_size_type> vertex_index_iterator;
0284     typedef kis_detail::lazy_fill_graph_vertex_at<KisLazyFillGraph> vertex_function;
0285     typedef transform_iterator<vertex_function, vertex_index_iterator> vertex_iterator;
0286 
0287     // edge_iterator
0288     typedef counting_iterator<edges_size_type> edge_index_iterator;
0289     typedef kis_detail::lazy_fill_graph_edge_at<type> edge_function;
0290     typedef transform_iterator<edge_function, edge_index_iterator> edge_iterator;
0291 
0292     // out_edge_iterator
0293     typedef counting_iterator<degree_size_type> degree_iterator;
0294     typedef kis_detail::lazy_fill_graph_out_edge_at<type> out_edge_function;
0295     typedef transform_iterator<out_edge_function, degree_iterator> out_edge_iterator;
0296 
0297     // adjacency_iterator
0298     typedef kis_detail::lazy_fill_graph_adjacent_vertex_at<type> adjacent_vertex_function;
0299     typedef transform_iterator<adjacent_vertex_function, degree_iterator> adjacency_iterator;
0300 
0301     // categories
0302     typedef directed_tag directed_category;
0303     typedef disallow_parallel_edge_tag edge_parallel_category;
0304     struct traversal_category : virtual public incidence_graph_tag,
0305                                 virtual public adjacency_graph_tag,
0306                                 virtual public vertex_list_graph_tag,
0307                                 virtual public edge_list_graph_tag,
0308                                 virtual public adjacency_matrix_tag { };
0309 
0310     static inline vertex_descriptor null_vertex()
0311     {
0312         vertex_descriptor maxed_out_vertex(
0313             std::numeric_limits<vertices_size_type>::max(),
0314             std::numeric_limits<vertices_size_type>::max(),
0315             vertex_descriptor::NORMAL);
0316 
0317         return (maxed_out_vertex);
0318     }
0319 
0320     KisLazyFillGraph() {}
0321 
0322     KisLazyFillGraph(const QRect &mainRect,
0323                      const KisRegion &aLabelRegion,
0324                      const KisRegion &bLabelRegion)
0325         : m_x(mainRect.x()),
0326           m_y(mainRect.y()),
0327           m_width(mainRect.width()),
0328           m_height(mainRect.height())
0329     {
0330         m_mainArea = mainRect;
0331         m_aLabelArea = aLabelRegion.boundingRect();
0332         m_bLabelArea = bLabelRegion.boundingRect();
0333 
0334         m_aLabelRects = aLabelRegion.rects();
0335         m_bLabelRects = bLabelRegion.rects();
0336 
0337         KIS_ASSERT(m_mainArea.contains(m_aLabelArea));
0338         KIS_ASSERT(m_mainArea.contains(m_bLabelArea));
0339 
0340         m_numVertices = m_width * m_height + 2;
0341 
0342         m_edgeBins << EdgeIndexBin(0,                 m_mainArea.adjusted(0, 0, -1, 0), HORIZONTAL);
0343         m_edgeBins << EdgeIndexBin(m_edgeBins.last(), m_mainArea.adjusted(0, 0, -1, 0), HORIZONTAL_REVERSED);
0344 
0345         m_edgeBins << EdgeIndexBin(m_edgeBins.last(), m_mainArea.adjusted(0, 0, 0, -1), VERTICAL);
0346         m_edgeBins << EdgeIndexBin(m_edgeBins.last(), m_mainArea.adjusted(0, 0, 0, -1), VERTICAL_REVERSED);
0347 
0348         Q_FOREACH (const QRect &rc, m_aLabelRects) {
0349             m_edgeBins << EdgeIndexBin(m_edgeBins.last(), rc, LABEL_A);
0350         }
0351 
0352         // out_edge_at relies on the sequential layout of reversed edges of one type
0353         m_aReversedEdgesStart = m_edgeBins.last().last() + 1;
0354 
0355         Q_FOREACH (const QRect &rc, m_aLabelRects) {
0356             m_edgeBins << EdgeIndexBin(m_edgeBins.last(), rc, LABEL_A_REVERSED);
0357         }
0358 
0359         m_numAEdges = m_edgeBins.last().last() + 1 - m_aReversedEdgesStart;
0360 
0361         Q_FOREACH (const QRect &rc, m_bLabelRects) {
0362             m_edgeBins << EdgeIndexBin(m_edgeBins.last(), rc, LABEL_B);
0363         }
0364 
0365         // out_edge_at relies on the sequential layout of reversed edges of one type
0366         m_bReversedEdgesStart = m_edgeBins.last().last() + 1;
0367 
0368         Q_FOREACH (const QRect &rc, m_bLabelRects) {
0369             m_edgeBins << EdgeIndexBin(m_edgeBins.last(), rc, LABEL_B_REVERSED);
0370         }
0371 
0372         m_numBEdges = m_edgeBins.last().last() + 1 - m_bReversedEdgesStart;
0373 
0374         m_numEdges = m_edgeBins.last().last() + 1;
0375     }
0376 
0377     ~KisLazyFillGraph() {
0378 
0379     }
0380 
0381     QSize size() const { return QSize(m_width, m_height); }
0382     QRect rect() const { return QRect(m_x, m_y, m_width, m_height); }
0383 
0384 
0385     vertices_size_type m_x;
0386     vertices_size_type m_y;
0387 
0388     vertices_size_type m_width;
0389     vertices_size_type m_height;
0390 
0391     vertices_size_type m_numVertices;
0392     vertices_size_type m_numEdges;
0393 
0394     vertices_size_type m_aReversedEdgesStart;
0395     vertices_size_type m_bReversedEdgesStart;
0396     vertices_size_type m_numAEdges;
0397     vertices_size_type m_numBEdges;
0398 
0399     enum EdgeIndexBinId {
0400         HORIZONTAL,
0401         HORIZONTAL_REVERSED,
0402         VERTICAL,
0403         VERTICAL_REVERSED,
0404         LABEL_A,
0405         LABEL_A_REVERSED,
0406         LABEL_B,
0407         LABEL_B_REVERSED,
0408     };
0409 
0410     struct EdgeIndexBin {
0411         EdgeIndexBin()
0412             : start(0), stride(0), size(0) {}
0413 
0414         EdgeIndexBin(edges_size_type _start,
0415                      const QRect &_rect,
0416                      EdgeIndexBinId _binId)
0417             : start(_start),
0418               stride(_rect.width()),
0419               size(_rect.width() * _rect.height()),
0420               xOffset(_rect.x()),
0421               yOffset(_rect.y()),
0422               binId(_binId),
0423               isReversed(int(_binId) & 0x1),
0424               rect(_rect) {}
0425 
0426         EdgeIndexBin(const EdgeIndexBin &putAfter,
0427                      const QRect &_rect,
0428                      EdgeIndexBinId _binId)
0429             : start(putAfter.last() + 1),
0430               stride(_rect.width()),
0431               size(_rect.width() * _rect.height()),
0432               xOffset(_rect.x()),
0433               yOffset(_rect.y()),
0434               binId(_binId),
0435               isReversed(int(_binId) & 0x1),
0436               rect(_rect) {}
0437 
0438         edges_size_type last() const {
0439             return start + size - 1;
0440         }
0441 
0442         bool contains(edges_size_type index) const {
0443             index -= start;
0444             return index >= 0 && index < size;
0445         }
0446 
0447         bool contains(const edge_descriptor &edge) const {
0448             return indexOf(edge) >= 0;
0449         }
0450 
0451         edges_size_type indexOf(const edge_descriptor &edge) const {
0452             vertex_descriptor src_vertex = source(edge, *this);
0453             vertex_descriptor dst_vertex = target(edge, *this);
0454 
0455             const bool srcColoredA = src_vertex.type == vertex_descriptor::LABEL_A;
0456             const bool dstColoredA = dst_vertex.type == vertex_descriptor::LABEL_A;
0457             const bool srcColoredB = src_vertex.type == vertex_descriptor::LABEL_B;
0458             const bool dstColoredB = dst_vertex.type == vertex_descriptor::LABEL_B;
0459 
0460             if (srcColoredA || dstColoredA) {
0461                 const bool edgeReversed = srcColoredA;
0462 
0463                 if (isReversed != edgeReversed ||
0464                     (binId != LABEL_A && binId != LABEL_A_REVERSED) ||
0465                     (srcColoredA && (dst_vertex.type != vertex_descriptor::NORMAL)) ||
0466                     (dstColoredA && (src_vertex.type != vertex_descriptor::NORMAL))) {
0467 
0468                     return -1;
0469                 }
0470             } else if (srcColoredB || dstColoredB) {
0471                 const bool edgeReversed = srcColoredB;
0472 
0473                 if (isReversed != edgeReversed ||
0474                     (binId != LABEL_B && binId != LABEL_B_REVERSED) ||
0475                     (srcColoredB && (dst_vertex.type != vertex_descriptor::NORMAL)) ||
0476                     (dstColoredB && (src_vertex.type != vertex_descriptor::NORMAL))) {
0477 
0478                     return -1;
0479                 }
0480             } else {
0481                 const vertices_size_type xDiff = dst_vertex.x - src_vertex.x;
0482                 const vertices_size_type yDiff = dst_vertex.y - src_vertex.y;
0483                 const vertices_size_type xAbsDiff = qAbs(xDiff);
0484                 const vertices_size_type yAbsDiff = qAbs(yDiff);
0485                 const bool edgeReversed = xDiff < 0 || yDiff < 0;
0486 
0487                 if (isReversed != edgeReversed ||
0488                     (xDiff && binId != HORIZONTAL && binId != HORIZONTAL_REVERSED) ||
0489                     (yDiff && binId != VERTICAL && binId != VERTICAL_REVERSED) ||
0490                     xAbsDiff > 1 ||
0491                     yAbsDiff > 1 ||
0492                     xAbsDiff == yAbsDiff) {
0493 
0494                     return -1;
0495                 }
0496             }
0497 
0498             if (isReversed) {
0499                 std::swap(src_vertex, dst_vertex);
0500             }
0501 
0502             // using direct QRect::contains makes the code 30% slower
0503             const int x = src_vertex.x;
0504             const int y = src_vertex.y;
0505             if (x < rect.x() || x > rect.right() ||
0506                 y < rect.y() || y > rect.bottom()) {
0507                 return -1;
0508             }
0509 
0510             edges_size_type internalIndex =
0511                 (src_vertex.x - xOffset) +
0512                 (src_vertex.y - yOffset) * stride;
0513 
0514             LF_SANITY_ASSERT_RECOVER(internalIndex >= 0 && internalIndex < size) {
0515                 return -1;
0516             }
0517 
0518             return internalIndex + start;
0519         }
0520 
0521 
0522         edge_descriptor edgeAt(edges_size_type index) const {
0523             edges_size_type localOffset = index - start;
0524 
0525             if (localOffset < 0 || localOffset >= size) {
0526                 return edge_descriptor();
0527             }
0528 
0529             const edges_size_type x = localOffset % stride + xOffset;
0530             const edges_size_type y = localOffset / stride + yOffset;
0531 
0532             vertex_descriptor src_vertex(x, y, vertex_descriptor::NORMAL);
0533             vertex_descriptor dst_vertex;
0534 
0535             switch (binId) {
0536             case HORIZONTAL:
0537             case HORIZONTAL_REVERSED:
0538                 dst_vertex.x = x + 1;
0539                 dst_vertex.y = y;
0540                 dst_vertex.type = vertex_descriptor::NORMAL;
0541                 break;
0542             case VERTICAL:
0543             case VERTICAL_REVERSED:
0544                 dst_vertex.x = x;
0545                 dst_vertex.y = y + 1;
0546                 dst_vertex.type = vertex_descriptor::NORMAL;
0547                 break;
0548             case LABEL_A:
0549             case LABEL_A_REVERSED:
0550                 dst_vertex.type = vertex_descriptor::LABEL_A;
0551                 break;
0552             case LABEL_B:
0553             case LABEL_B_REVERSED:
0554                 dst_vertex.type = vertex_descriptor::LABEL_B;
0555                 break;
0556             }
0557 
0558             if (isReversed) {
0559                 std::swap(src_vertex, dst_vertex);
0560             }
0561 
0562             return std::make_pair(src_vertex, dst_vertex);
0563         }
0564 
0565         edges_size_type start {0};
0566         edges_size_type stride {0};
0567         edges_size_type size {0};
0568         edges_size_type xOffset {0};
0569         edges_size_type yOffset {0};
0570         EdgeIndexBinId binId {HORIZONTAL};
0571         bool isReversed {false};
0572         QRect rect;
0573     };
0574 
0575     QVector<EdgeIndexBin> m_edgeBins;
0576 
0577     QRect m_aLabelArea;
0578     QRect m_bLabelArea;
0579     QRect m_mainArea;
0580 
0581     QVector<QRect> m_aLabelRects;
0582     QVector<QRect> m_bLabelRects;
0583 
0584 public:
0585 
0586     // Returns the number of vertices in the graph
0587     inline vertices_size_type num_vertices() const {
0588       return (m_numVertices);
0589     }
0590 
0591     // Returns the number of edges in the graph
0592     inline edges_size_type num_edges() const {
0593       return (m_numEdges);
0594     }
0595 
0596     // Returns the index of [vertex] (See also vertex_at)
0597     vertices_size_type index_of(vertex_descriptor vertex) const {
0598         vertices_size_type vertex_index = -1;
0599 
0600         switch (vertex.type) {
0601         case vertex_descriptor::NORMAL:
0602             vertex_index = vertex.x - m_x + (vertex.y - m_y) * m_width;
0603             break;
0604         case vertex_descriptor::LABEL_A:
0605             vertex_index = m_numVertices - 2;
0606             break;
0607         case vertex_descriptor::LABEL_B:
0608             vertex_index = m_numVertices - 1;
0609             break;
0610         }
0611 
0612         return vertex_index;
0613     }
0614 
0615     // Returns the vertex whose index is [vertex_index] (See also
0616     // index_of(vertex_descriptor))
0617     vertex_descriptor vertex_at (vertices_size_type vertex_index) const {
0618         vertex_descriptor vertex;
0619 
0620         if (vertex_index == m_numVertices - 2) {
0621             vertex.type = vertex_descriptor::LABEL_A;
0622         } else if (vertex_index == m_numVertices - 1) {
0623             vertex.type = vertex_descriptor::LABEL_B;
0624         } else if (vertex_index >= 0) {
0625             vertex.x = vertex_index % m_width + m_x;
0626             vertex.y = vertex_index / m_width + m_y;
0627             vertex.type = vertex_descriptor::NORMAL;
0628         }
0629 
0630       return vertex;
0631     }
0632 
0633     // Returns the edge whose index is [edge_index] (See also
0634     // index_of(edge_descriptor)).  NOTE: The index mapping is
0635     // dependent upon dimension wrapping.
0636     edge_descriptor edge_at(edges_size_type edge_index) const {
0637 
0638         int binIndex = 0;
0639 
0640         while (binIndex < m_edgeBins.size() &&
0641                !m_edgeBins[binIndex].contains(edge_index)) {
0642 
0643             binIndex++;
0644         }
0645 
0646         if (binIndex >= m_edgeBins.size()) {
0647             return edge_descriptor();
0648         }
0649 
0650         return m_edgeBins[binIndex].edgeAt(edge_index);
0651     }
0652 
0653     // Returns the index for [edge] (See also edge_at)
0654     edges_size_type index_of(edge_descriptor edge) const {
0655         edges_size_type index = -1;
0656 
0657         auto it = m_edgeBins.constBegin();
0658         for (; it != m_edgeBins.constEnd(); ++it) {
0659 
0660             index = it->indexOf(edge);
0661             if (index >= 0) break;
0662         }
0663 
0664         return index;
0665     }
0666 
0667 private:
0668     static vertices_size_type numVacantEdges(const vertex_descriptor &vertex, const QRect &rc) {
0669         vertices_size_type vacantEdges = 4;
0670 
0671         if (vertex.x == rc.x()) {
0672             vacantEdges--;
0673         }
0674 
0675         if (vertex.y == rc.y()) {
0676             vacantEdges--;
0677         }
0678 
0679         if (vertex.x == rc.right()) {
0680             vacantEdges--;
0681         }
0682 
0683         if (vertex.y == rc.bottom()) {
0684             vacantEdges--;
0685         }
0686 
0687         return vacantEdges;
0688     }
0689 
0690     static inline bool findInRects(const QVector<QRect> &rects, const QPoint &pt) {
0691         bool result = false;
0692 
0693         auto it = rects.constBegin();
0694         for (; it != rects.constEnd(); ++it) {
0695 
0696             if (it->contains(pt)) {
0697                 result = true;
0698                 break;
0699             }
0700         }
0701         return result;
0702     }
0703 public:
0704     // Returns the number of out-edges for [vertex]
0705     degree_size_type out_degree(vertex_descriptor vertex) const {
0706         degree_size_type out_edge_count = 0;
0707         if (index_of(vertex) < 0) return out_edge_count;
0708 
0709         switch (vertex.type) {
0710         case vertex_descriptor::NORMAL: {
0711             out_edge_count = numVacantEdges(vertex, m_mainArea);
0712 
0713             const QPoint pt = QPoint(vertex.x, vertex.y);
0714 
0715             if (m_aLabelArea.contains(pt) && findInRects(m_aLabelRects, pt)) {
0716                 out_edge_count++;
0717             }
0718 
0719             if (m_bLabelArea.contains(pt) && findInRects(m_bLabelRects, pt)) {
0720                 out_edge_count++;
0721             }
0722 
0723             break;
0724         }
0725         case vertex_descriptor::LABEL_A:
0726             out_edge_count = m_numAEdges;
0727             break;
0728         case vertex_descriptor::LABEL_B:
0729             out_edge_count = m_numBEdges;
0730             break;
0731         }
0732 
0733         return (out_edge_count);
0734     }
0735 
0736     // Returns an out-edge for [vertex] by index. Indices are in the
0737     // range [0, out_degree(vertex)).
0738     edge_descriptor out_edge_at (vertex_descriptor vertex,
0739                                  degree_size_type out_edge_index) const {
0740 
0741         const QPoint pt = QPoint(vertex.x, vertex.y);
0742         vertex_descriptor dst_vertex = vertex;
0743 
0744         switch (vertex.type) {
0745         case vertex_descriptor::NORMAL:
0746             if (vertex.x > m_mainArea.x() && !out_edge_index--) {
0747                 dst_vertex.x--;
0748             } else if (vertex.y > m_mainArea.y() && !out_edge_index--) {
0749                 dst_vertex.y--;
0750             } else if (vertex.x < m_mainArea.right() && !out_edge_index--) {
0751                 dst_vertex.x++;
0752             } else if (vertex.y < m_mainArea.bottom() && !out_edge_index--) {
0753                 dst_vertex.y++;
0754             } else if (m_aLabelArea.contains(pt) && findInRects(m_aLabelRects, pt) && !out_edge_index--) {
0755                 dst_vertex = vertex_descriptor(0, 0, vertex_descriptor::LABEL_A);
0756             } else if (m_bLabelArea.contains(pt) && findInRects(m_bLabelRects, pt) && !out_edge_index--) {
0757                 dst_vertex = vertex_descriptor(0, 0, vertex_descriptor::LABEL_B);
0758             } else {
0759                 dbgImage << ppVar(vertex) << ppVar(out_edge_index) << ppVar(out_degree(vertex));
0760                 qFatal("Wrong edge sub-index");
0761             }
0762             break;
0763         case vertex_descriptor::LABEL_A: {
0764             edge_descriptor edge = edge_at(m_aReversedEdgesStart + out_edge_index);
0765             dst_vertex = edge.second;
0766             break;
0767         }
0768         case vertex_descriptor::LABEL_B: {
0769             edge_descriptor edge = edge_at(m_bReversedEdgesStart + out_edge_index);
0770             dst_vertex = edge.second;
0771             break;
0772         }
0773         }
0774 
0775         return std::make_pair(vertex, dst_vertex);
0776     }
0777 
0778 public:
0779 
0780     //================
0781     // VertexListGraph
0782     //================
0783 
0784     friend inline std::pair<typename type::vertex_iterator,
0785                             typename type::vertex_iterator>
0786     vertices(const type& graph) {
0787         typedef typename type::vertex_iterator vertex_iterator;
0788         typedef typename type::vertex_function vertex_function;
0789         typedef typename type::vertex_index_iterator vertex_index_iterator;
0790 
0791         return (std::make_pair
0792                 (vertex_iterator(vertex_index_iterator(0),
0793                                  vertex_function(&graph)),
0794                  vertex_iterator(vertex_index_iterator(graph.num_vertices()),
0795                                  vertex_function(&graph))));
0796     }
0797 
0798     friend inline typename type::vertices_size_type
0799     num_vertices(const type& graph) {
0800         return (graph.num_vertices());
0801     }
0802 
0803     friend inline typename type::vertex_descriptor
0804     vertex(typename type::vertices_size_type vertex_index,
0805            const type& graph) {
0806 
0807         return (graph.vertex_at(vertex_index));
0808     }
0809 
0810     //===============
0811     // IncidenceGraph
0812     //===============
0813 
0814     friend inline std::pair<typename type::out_edge_iterator,
0815                             typename type::out_edge_iterator>
0816     out_edges(typename type::vertex_descriptor vertex,
0817               const type& graph) {
0818         typedef typename type::degree_iterator degree_iterator;
0819         typedef typename type::out_edge_function out_edge_function;
0820         typedef typename type::out_edge_iterator out_edge_iterator;
0821 
0822         return (std::make_pair
0823                 (out_edge_iterator(degree_iterator(0),
0824                                    out_edge_function(vertex, &graph)),
0825                  out_edge_iterator(degree_iterator(graph.out_degree(vertex)),
0826                                    out_edge_function(vertex, &graph))));
0827     }
0828 
0829     friend inline typename type::degree_size_type
0830     out_degree
0831     (typename type::vertex_descriptor vertex,
0832      const type& graph) {
0833         return (graph.out_degree(vertex));
0834     }
0835 
0836     friend inline typename type::edge_descriptor
0837     out_edge_at(typename type::vertex_descriptor vertex,
0838                 typename type::degree_size_type out_edge_index,
0839                 const type& graph) {
0840         return (graph.out_edge_at(vertex, out_edge_index));
0841     }
0842 
0843     //===============
0844     // AdjacencyGraph
0845     //===============
0846 
0847     friend typename std::pair<typename type::adjacency_iterator,
0848                               typename type::adjacency_iterator>
0849     adjacent_vertices (typename type::vertex_descriptor vertex,
0850                        const type& graph) {
0851       typedef typename type::degree_iterator degree_iterator;
0852       typedef typename type::adjacent_vertex_function adjacent_vertex_function;
0853       typedef typename type::adjacency_iterator adjacency_iterator;
0854 
0855       return (std::make_pair
0856               (adjacency_iterator(degree_iterator(0),
0857                                  adjacent_vertex_function(vertex, &graph)),
0858                adjacency_iterator(degree_iterator(graph.out_degree(vertex)),
0859                                  adjacent_vertex_function(vertex, &graph))));
0860     }
0861 
0862     //==================
0863     // Adjacency Matrix
0864     //==================
0865 
0866     friend std::pair<typename type::edge_descriptor, bool>
0867     edge (typename type::vertex_descriptor source_vertex,
0868           typename type::vertex_descriptor destination_vertex,
0869           const type& graph) {
0870 
0871         std::pair<typename type::edge_descriptor, bool> edge_exists =
0872             std::make_pair(std::make_pair(source_vertex, destination_vertex), false);
0873 
0874         const edges_size_type index = graph.index_of(edge_exists.first);
0875 
0876         edge_exists.second = index >= 0;
0877 
0878         return edge_exists;
0879     }
0880 
0881     //==============
0882     // EdgeListGraph
0883     //==============
0884 
0885     friend inline typename type::edges_size_type
0886     num_edges(const type& graph) {
0887       return (graph.num_edges());
0888     }
0889 
0890     friend inline typename type::edge_descriptor
0891     edge_at(typename type::edges_size_type edge_index,
0892             const type& graph) {
0893       return (graph.edge_at(edge_index));
0894     }
0895 
0896     friend inline std::pair<typename type::edge_iterator,
0897                             typename type::edge_iterator>
0898     edges(const type& graph) {
0899       typedef typename type::edge_index_iterator edge_index_iterator;
0900       typedef typename type::edge_function edge_function;
0901       typedef typename type::edge_iterator edge_iterator;
0902 
0903       return (std::make_pair
0904               (edge_iterator(edge_index_iterator(0),
0905                              edge_function(&graph)),
0906                edge_iterator(edge_index_iterator(graph.num_edges()),
0907                              edge_function(&graph))));
0908     }
0909 
0910     //=============================
0911     // Index Property Map Functions
0912     //=============================
0913 
0914     friend inline typename type::vertices_size_type
0915     get(vertex_index_t,
0916         const type& graph,
0917         typename type::vertex_descriptor vertex) {
0918 
0919         type::vertices_size_type index = graph.index_of(vertex);
0920         LF_SANITY_ASSERT(index >= 0);
0921         return index;
0922     }
0923 
0924     friend inline typename type::edges_size_type
0925     get(edge_index_t,
0926         const type& graph,
0927         typename type::edge_descriptor edge) {
0928 
0929         type::edges_size_type index = graph.index_of(edge);
0930         LF_SANITY_ASSERT(index >= 0);
0931         return index;
0932     }
0933 
0934     friend inline lazy_fill_graph_index_map<
0935         type,
0936         typename type::vertex_descriptor,
0937         typename type::vertices_size_type>
0938     get(vertex_index_t, const type& graph) {
0939         return (lazy_fill_graph_index_map<
0940                 type,
0941                 typename type::vertex_descriptor,
0942                 typename type::vertices_size_type>(graph));
0943     }
0944 
0945     friend inline lazy_fill_graph_index_map<
0946         type,
0947         typename type::edge_descriptor,
0948         typename type::edges_size_type>
0949     get(edge_index_t, const type& graph) {
0950         return (lazy_fill_graph_index_map<
0951                 type,
0952                 typename type::edge_descriptor,
0953                 typename type::edges_size_type>(graph));
0954     }
0955 
0956     friend inline lazy_fill_graph_reverse_edge_map<
0957         typename type::edge_descriptor>
0958     get(edge_reverse_t, const type& graph) {
0959         Q_UNUSED(graph);
0960         return (lazy_fill_graph_reverse_edge_map<
0961                 typename type::edge_descriptor>());
0962     }
0963 
0964     template<typename Graph,
0965              typename Descriptor,
0966              typename Index>
0967     friend struct lazy_fill_graph_index_map;
0968 
0969     template<typename Descriptor>
0970     friend struct lazy_fill_graph_reverse_edge_map;
0971 };
0972 
0973 namespace boost {
0974     template <>
0975     struct property_map<KisLazyFillGraph, vertex_index_t> {
0976         typedef lazy_fill_graph_index_map<KisLazyFillGraph,
0977                                           typename graph_traits<KisLazyFillGraph>::vertex_descriptor,
0978                                           typename graph_traits<KisLazyFillGraph>::vertices_size_type> type;
0979         typedef type const_type;
0980     };
0981 
0982     template<>
0983     struct property_map<KisLazyFillGraph, edge_index_t> {
0984         typedef lazy_fill_graph_index_map<KisLazyFillGraph,
0985                                           typename graph_traits<KisLazyFillGraph>::edge_descriptor,
0986                                           typename graph_traits<KisLazyFillGraph>::edges_size_type> type;
0987         typedef type const_type;
0988     };
0989 }
0990 
0991 namespace boost {
0992     template <>
0993     struct property_map<KisLazyFillGraph, edge_reverse_t> {
0994         typedef lazy_fill_graph_reverse_edge_map<typename graph_traits<KisLazyFillGraph>::edge_descriptor> type;
0995         typedef type const_type;
0996     };
0997 }
0998 
0999 QDebug operator<<(QDebug dbg, const KisLazyFillGraph::vertex_descriptor &v) {
1000     const QString type =
1001         v.type == KisLazyFillGraph::vertex_descriptor::NORMAL ? "normal" :
1002         v.type == KisLazyFillGraph::vertex_descriptor::LABEL_A ? "label_A" :
1003         v.type == KisLazyFillGraph::vertex_descriptor::LABEL_B ? "label_B" : "<unknown>";
1004 
1005     dbg.nospace() << "(" << v.x << ", " << v.y << ", " << type << ")";
1006     return dbg.space();
1007 }
1008 
1009 QDebug operator<<(QDebug dbg, const KisLazyFillGraph::edge_descriptor &e) {
1010     KisLazyFillGraph::vertex_descriptor src = e.first;
1011     KisLazyFillGraph::vertex_descriptor dst = e.second;
1012 
1013     dbg.nospace() << "(" << src << " -> " << dst << ")";
1014     return dbg.space();
1015 }
1016 
1017 #endif /* __KIS_LAZY_FILL_GRAPH_H */