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 */