changeset 846 | a7a406fdb006 |
parent 835 | eb9587f09b42 |
child 852 | d50d89b86870 |
3:fa4945e50886 | 4:4b245f3c8b79 |
---|---|
38 //! \brief A structure for representing directed paths in a graph. |
38 //! \brief A structure for representing directed paths in a graph. |
39 //! |
39 //! |
40 //! A structure for representing directed path in a graph. |
40 //! A structure for representing directed path in a graph. |
41 //! \param Graph The graph type in which the path is. |
41 //! \param Graph The graph type in which the path is. |
42 //! \param DM DebugMode, defaults to DefaultDebugMode. |
42 //! \param DM DebugMode, defaults to DefaultDebugMode. |
43 //! |
43 //! |
44 //! In a sense, the path can be treated as a graph, for is has \c NodeIt |
44 //! In a sense, the path can be treated as a graph, for is has \c NodeIt |
45 //! and \c EdgeIt with the same usage. These types converts to the \c Node |
45 //! and \c EdgeIt with the same usage. These types converts to the \c Node |
46 //! and \c Edge of the original graph. |
46 //! and \c Edge of the original graph. |
47 //! |
47 //! |
48 //! \todo Thoroughfully check all the range and consistency tests. |
48 //! \todo Thoroughfully check all the range and consistency tests. |
49 template<typename Graph> |
49 template<typename Graph> |
50 class DirPath { |
50 class DirPath { |
51 public: |
51 public: |
52 /// Edge type of the underlying graph. |
52 /// Edge type of the underlying graph. |
53 typedef typename Graph::Edge GraphEdge; |
53 typedef typename Graph::Edge GraphEdge; |
54 /// Node type of the underlying graph. |
54 /// Node type of the underlying graph. |
55 typedef typename Graph::Node GraphNode; |
55 typedef typename Graph::Node GraphNode; |
56 class NodeIt; |
56 class NodeIt; |
57 class EdgeIt; |
57 class EdgeIt; |
58 |
58 |
152 |
152 |
153 /* Iterator classes */ |
153 /* Iterator classes */ |
154 |
154 |
155 /** |
155 /** |
156 * \brief Iterator class to iterate on the edges of the paths |
156 * \brief Iterator class to iterate on the edges of the paths |
157 * |
157 * |
158 * \ingroup paths |
158 * \ingroup paths |
159 * This class is used to iterate on the edges of the paths |
159 * This class is used to iterate on the edges of the paths |
160 * |
160 * |
161 * Of course it converts to Graph::Edge |
161 * Of course it converts to Graph::Edge |
162 * |
162 * |
163 * \todo Its interface differs from the standard edge iterator. |
163 * \todo Its interface differs from the standard edge iterator. |
164 * Yes, it shouldn't. |
164 * Yes, it shouldn't. |
165 */ |
165 */ |
166 class EdgeIt { |
166 class EdgeIt { |
167 friend class DirPath; |
167 friend class DirPath; |
201 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } |
201 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } |
202 }; |
202 }; |
203 |
203 |
204 /** |
204 /** |
205 * \brief Iterator class to iterate on the nodes of the paths |
205 * \brief Iterator class to iterate on the nodes of the paths |
206 * |
206 * |
207 * \ingroup paths |
207 * \ingroup paths |
208 * This class is used to iterate on the nodes of the paths |
208 * This class is used to iterate on the nodes of the paths |
209 * |
209 * |
210 * Of course it converts to Graph::Node |
210 * Of course it converts to Graph::Node |
211 * |
211 * |
212 * \todo Its interface differs from the standard node iterator. |
212 * \todo Its interface differs from the standard node iterator. |
213 * Yes, it shouldn't. |
213 * Yes, it shouldn't. |
214 */ |
214 */ |
215 class NodeIt { |
215 class NodeIt { |
216 friend class DirPath; |
216 friend class DirPath; |
250 |
250 |
251 private: |
251 private: |
252 void validate() { if( size_t(idx) > p->length() ) idx=-1; } |
252 void validate() { if( size_t(idx) > p->length() ) idx=-1; } |
253 }; |
253 }; |
254 |
254 |
255 friend class Builder; |
255 friend class Builder; |
256 |
256 |
257 /** |
257 /** |
258 * \brief Class to build paths |
258 * \brief Class to build paths |
259 * |
259 * |
260 * \ingroup paths |
260 * \ingroup paths |
261 * This class is used to fill a path with edges. |
261 * This class is used to fill a path with edges. |
262 * |
262 * |
263 * You can push new edges to the front and to the back of the path in |
263 * You can push new edges to the front and to the back of the path in |
264 * arbitrary order then you should commit these changes to the graph. |
264 * arbitrary order then you should commit these changes to the graph. |
278 ///\param _P the path you want to fill in. |
278 ///\param _P the path you want to fill in. |
279 /// |
279 /// |
280 Builder(DirPath &_P) : P(_P) {} |
280 Builder(DirPath &_P) : P(_P) {} |
281 |
281 |
282 /// Sets the starting node of the path. |
282 /// Sets the starting node of the path. |
283 |
283 |
284 /// Sets the starting node of the path. Edge added to the path |
284 /// Sets the starting node of the path. Edge added to the path |
285 /// afterwards have to be incident to this node. |
285 /// afterwards have to be incident to this node. |
286 /// It should be called iff the path is empty and before any call to |
286 /// It should be called iff the path is empty and before any call to |
287 /// \ref pushFront() or \ref pushBack() |
287 /// \ref pushFront() or \ref pushBack() |
288 void setStartNode(const GraphNode &) {} |
288 void setStartNode(const GraphNode &) {} |
303 back.push_back(e); |
303 back.push_back(e); |
304 } |
304 } |
305 |
305 |
306 ///Commit the changes to the path. |
306 ///Commit the changes to the path. |
307 void commit() { |
307 void commit() { |
308 if( !(front.empty() && back.empty()) ) { |
308 if( !front.empty() || !back.empty() ) { |
309 Container tmp; |
309 Container tmp; |
310 tmp.reserve(front.size()+back.size()+P.length()); |
310 tmp.reserve(front.size()+back.size()+P.length()); |
311 tmp.insert(tmp.end(), front.rbegin(), front.rend()); |
311 tmp.insert(tmp.end(), front.rbegin(), front.rend()); |
312 tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); |
312 tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); |
313 tmp.insert(tmp.end(), back.begin(), back.end()); |
313 tmp.insert(tmp.end(), back.begin(), back.end()); |
315 front.clear(); |
315 front.clear(); |
316 back.clear(); |
316 back.clear(); |
317 } |
317 } |
318 } |
318 } |
319 |
319 |
320 // FIXME: Hmm, pontosan hogy is kene ezt csinalni? |
|
321 // Hogy kenyelmes egy ilyet hasznalni? |
|
322 |
|
323 ///Reserve storage for the builder in advance. |
320 ///Reserve storage for the builder in advance. |
324 |
321 |
325 ///If you know an reasonable upper bound of the number of the edges |
322 ///If you know a reasonable upper bound of the number of the edges |
326 ///to add, using this function you can speed up the building. |
323 ///to add to the front, using this function you can speed up the building. |
327 void reserve(size_t r) { |
324 |
328 front.reserve(r); |
325 void reserveFront(size_t r) {front.reserve(r);} |
329 back.reserve(r); |
326 |
330 } |
327 ///Reserve storage for the builder in advance. |
331 |
328 |
332 void reserveFront(size_t r) {} |
329 ///If you know a reasonable upper bound of the number of the edges |
333 void reserveBack(size_t r) {} |
330 ///to add to the back, using this function you can speed up the building. |
331 |
|
332 void reserveBack(size_t r) {back.reserve(r);} |
|
334 |
333 |
335 private: |
334 private: |
336 bool empty() { |
335 bool empty() { |
337 return front.empty() && back.empty() && P.empty(); |
336 return front.empty() && back.empty() && P.empty(); |
338 } |
337 } |
380 //! a path in a \e directed graph but the edges should not be directed |
379 //! a path in a \e directed graph but the edges should not be directed |
381 //! forward. |
380 //! forward. |
382 //! |
381 //! |
383 //! \param Graph The graph type in which the path is. |
382 //! \param Graph The graph type in which the path is. |
384 //! \param DM DebugMode, defaults to DefaultDebugMode. |
383 //! \param DM DebugMode, defaults to DefaultDebugMode. |
385 //! |
384 //! |
386 //! In a sense, the path can be treated as a graph, for is has \c NodeIt |
385 //! In a sense, the path can be treated as a graph, for is has \c NodeIt |
387 //! and \c EdgeIt with the same usage. These types converts to the \c Node |
386 //! and \c EdgeIt with the same usage. These types converts to the \c Node |
388 //! and \c Edge of the original graph. |
387 //! and \c Edge of the original graph. |
389 //! |
388 //! |
390 //! \todo Thoroughfully check all the range and consistency tests. |
389 //! \todo Thoroughfully check all the range and consistency tests. |
493 |
492 |
494 |
493 |
495 |
494 |
496 /** |
495 /** |
497 * \brief Iterator class to iterate on the edges of the paths |
496 * \brief Iterator class to iterate on the edges of the paths |
498 * |
497 * |
499 * \ingroup paths |
498 * \ingroup paths |
500 * This class is used to iterate on the edges of the paths |
499 * This class is used to iterate on the edges of the paths |
501 * |
500 * |
502 * Of course it converts to Graph::Edge |
501 * Of course it converts to Graph::Edge |
503 * |
502 * |
504 * \todo Its interface differs from the standard edge iterator. |
503 * \todo Its interface differs from the standard edge iterator. |
505 * Yes, it shouldn't. |
504 * Yes, it shouldn't. |
506 */ |
505 */ |
507 class EdgeIt { |
506 class EdgeIt { |
508 friend class UndirPath; |
507 friend class UndirPath; |
541 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } |
540 void validate() { if( size_t(idx) >= p->length() ) idx=-1; } |
542 }; |
541 }; |
543 |
542 |
544 /** |
543 /** |
545 * \brief Iterator class to iterate on the nodes of the paths |
544 * \brief Iterator class to iterate on the nodes of the paths |
546 * |
545 * |
547 * \ingroup paths |
546 * \ingroup paths |
548 * This class is used to iterate on the nodes of the paths |
547 * This class is used to iterate on the nodes of the paths |
549 * |
548 * |
550 * Of course it converts to Graph::Node |
549 * Of course it converts to Graph::Node |
551 * |
550 * |
552 * \todo Its interface differs from the standard node iterator. |
551 * \todo Its interface differs from the standard node iterator. |
553 * Yes, it shouldn't. |
552 * Yes, it shouldn't. |
554 */ |
553 */ |
555 class NodeIt { |
554 class NodeIt { |
556 friend class UndirPath; |
555 friend class UndirPath; |
590 |
589 |
591 private: |
590 private: |
592 void validate() { if( size_t(idx) > p->length() ) idx=-1; } |
591 void validate() { if( size_t(idx) > p->length() ) idx=-1; } |
593 }; |
592 }; |
594 |
593 |
595 friend class Builder; |
594 friend class Builder; |
596 |
595 |
597 /** |
596 /** |
598 * \brief Class to build paths |
597 * \brief Class to build paths |
599 * |
598 * |
600 * \ingroup paths |
599 * \ingroup paths |
601 * This class is used to fill a path with edges. |
600 * This class is used to fill a path with edges. |
602 * |
601 * |
603 * You can push new edges to the front and to the back of the path in |
602 * You can push new edges to the front and to the back of the path in |
604 * arbitrary order then you should commit these changes to the graph. |
603 * arbitrary order then you should commit these changes to the graph. |
618 ///\param _P the path you want to fill in. |
617 ///\param _P the path you want to fill in. |
619 /// |
618 /// |
620 Builder(UndirPath &_P) : P(_P) {} |
619 Builder(UndirPath &_P) : P(_P) {} |
621 |
620 |
622 /// Sets the starting node of the path. |
621 /// Sets the starting node of the path. |
623 |
622 |
624 /// Sets the starting node of the path. Edge added to the path |
623 /// Sets the starting node of the path. Edge added to the path |
625 /// afterwards have to be incident to this node. |
624 /// afterwards have to be incident to this node. |
626 /// It should be called iff the path is empty and before any call to |
625 /// It should be called iff the path is empty and before any call to |
627 /// \ref pushFront() or \ref pushBack() |
626 /// \ref pushFront() or \ref pushBack() |
628 void setStartNode(const GraphNode &) {} |
627 void setStartNode(const GraphNode &) {} |
655 front.clear(); |
654 front.clear(); |
656 back.clear(); |
655 back.clear(); |
657 } |
656 } |
658 } |
657 } |
659 |
658 |
660 // FIXME: Hmm, pontosan hogy is kene ezt csinalni? |
|
661 // Hogy kenyelmes egy ilyet hasznalni? |
|
662 |
659 |
663 ///Reserve storage for the builder in advance. |
660 ///Reserve storage for the builder in advance. |
664 |
661 |
665 ///If you know an reasonable upper bound of the number of the edges |
662 ///If you know a reasonable upper bound of the number of the edges |
666 ///to add, using this function you can speed up the building. |
663 ///to add to the front, using this function you can speed up the building. |
667 void reserve(size_t r) { |
664 |
668 front.reserve(r); |
665 void reserveFront(size_t r) {front.reserve(r);} |
669 back.reserve(r); |
666 |
670 } |
667 ///Reserve storage for the builder in advance. |
671 |
668 |
672 void reserveFront(size_t r) {} |
669 ///If you know a reasonable upper bound of the number of the edges |
673 void reserveBack(size_t r) {} |
670 ///to add to the back, using this function you can speed up the building. |
671 |
|
672 void reserveBack(size_t r) {back.reserve(r);} |
|
674 |
673 |
675 private: |
674 private: |
676 bool empty() { |
675 bool empty() { |
677 return front.empty() && back.empty() && P.empty(); |
676 return front.empty() && back.empty() && P.empty(); |
678 } |
677 } |
701 }; |
700 }; |
702 |
701 |
703 }; |
702 }; |
704 |
703 |
705 |
704 |
706 |
|
707 |
|
708 |
|
709 |
|
710 |
|
711 |
|
712 |
|
713 |
|
714 /**********************************************************************/ |
|
715 |
|
716 |
|
717 /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata |
|
718 elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */ |
|
719 |
|
720 template<typename Graph> |
|
721 class DynamicPath { |
|
722 |
|
723 public: |
|
724 typedef typename Graph::Edge GraphEdge; |
|
725 typedef typename Graph::Node GraphNode; |
|
726 class NodeIt; |
|
727 class EdgeIt; |
|
728 |
|
729 protected: |
|
730 Graph& G; |
|
731 // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el |
|
732 // iranyitasat: |
|
733 GraphNode _first, _last; |
|
734 typedef std::deque<GraphEdge> Container; |
|
735 Container edges; |
|
736 |
|
737 public: |
|
738 |
|
739 DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {} |
|
740 |
|
741 /// Subpath defined by two nodes. |
|
742 /// Nodes may be in reversed order, then |
|
743 /// we contstruct the reversed path. |
|
744 DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b); |
|
745 /// Subpath defined by two edges. Contains edges in [a,b) |
|
746 /// It is an error if the two edges are not in order! |
|
747 DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b); |
|
748 |
|
749 size_t length() const { return edges.size(); } |
|
750 GraphNode tail() const { return _first; } |
|
751 GraphNode head() const { return _last; } |
|
752 |
|
753 NodeIt& first(NodeIt &n) const { return nth(n, 0); } |
|
754 EdgeIt& first(EdgeIt &e) const { return nth(e, 0); } |
|
755 template<typename It> |
|
756 It first() const { |
|
757 It e; |
|
758 first(e); |
|
759 return e; |
|
760 } |
|
761 |
|
762 NodeIt& nth(NodeIt &, size_t) const; |
|
763 EdgeIt& nth(EdgeIt &, size_t) const; |
|
764 template<typename It> |
|
765 It nth(size_t n) const { |
|
766 It e; |
|
767 nth(e, n); |
|
768 return e; |
|
769 } |
|
770 |
|
771 bool valid(const NodeIt &n) const { return n.idx <= length(); } |
|
772 bool valid(const EdgeIt &e) const { return e.it < edges.end(); } |
|
773 |
|
774 bool isForward(const EdgeIt &e) const { return e.forw; } |
|
775 |
|
776 /// index of a node on the path. Returns length+2 for the invalid NodeIt |
|
777 int index(const NodeIt &n) const { return n.idx; } |
|
778 /// index of an edge on the path. Returns length+1 for the invalid EdgeIt |
|
779 int index(const EdgeIt &e) const { return e.it - edges.begin(); } |
|
780 |
|
781 EdgeIt& next(EdgeIt &e) const; |
|
782 NodeIt& next(NodeIt &n) const; |
|
783 template <typename It> |
|
784 It getNext(It it) const { |
|
785 It tmp(it); return next(tmp); |
|
786 } |
|
787 |
|
788 // A path is constructed using the following four functions. |
|
789 // They return false if the requested operation is inconsistent |
|
790 // with the path constructed so far. |
|
791 // If your path has only one edge you MUST set either "from" or "to"! |
|
792 // So you probably SHOULD call it in any case to be safe (and check the |
|
793 // returned value to check if your path is consistent with your idea). |
|
794 bool pushFront(const GraphEdge &e); |
|
795 bool pushBack(const GraphEdge &e); |
|
796 bool setFrom(const GraphNode &n); |
|
797 bool setTo(const GraphNode &n); |
|
798 |
|
799 // WARNING: these two functions return the head/tail of an edge with |
|
800 // respect to the direction of the path! |
|
801 // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if |
|
802 // P.forward(e) is true (or the edge is a loop)! |
|
803 NodeIt head(const EdgeIt& e) const; |
|
804 NodeIt tail(const EdgeIt& e) const; |
|
805 |
|
806 // FIXME: ezeknek valami jobb nev kellene!!! |
|
807 GraphEdge graphEdge(const EdgeIt& e) const; |
|
808 GraphNode graphNode(const NodeIt& n) const; |
|
809 |
|
810 |
|
811 /*** Iterator classes ***/ |
|
812 class EdgeIt { |
|
813 friend class DynamicPath; |
|
814 |
|
815 typename Container::const_iterator it; |
|
816 bool forw; |
|
817 public: |
|
818 // FIXME: jarna neki ilyen is... |
|
819 // EdgeIt(Invalid); |
|
820 |
|
821 bool forward() const { return forw; } |
|
822 |
|
823 bool operator==(const EdgeIt& e) const { return it==e.it; } |
|
824 bool operator!=(const EdgeIt& e) const { return it!=e.it; } |
|
825 bool operator<(const EdgeIt& e) const { return it<e.it; } |
|
826 }; |
|
827 |
|
828 class NodeIt { |
|
829 friend class DynamicPath; |
|
830 |
|
831 size_t idx; |
|
832 bool tail; // Is this node the tail of the edge with same idx? |
|
833 |
|
834 public: |
|
835 // FIXME: jarna neki ilyen is... |
|
836 // NodeIt(Invalid); |
|
837 |
|
838 bool operator==(const NodeIt& n) const { return idx==n.idx; } |
|
839 bool operator!=(const NodeIt& n) const { return idx!=n.idx; } |
|
840 bool operator<(const NodeIt& n) const { return idx<n.idx; } |
|
841 }; |
|
842 |
|
843 private: |
|
844 bool edgeIncident(const GraphEdge &e, const GraphNode &a, |
|
845 GraphNode &b); |
|
846 bool connectTwoEdges(const GraphEdge &e, const GraphEdge &f); |
|
847 }; |
|
848 |
|
849 template<typename Gr> |
|
850 typename DynamicPath<Gr>::EdgeIt& |
|
851 DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const { |
|
852 if( e.it == edges.end() ) |
|
853 return e; |
|
854 |
|
855 GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) ); |
|
856 ++e.it; |
|
857 |
|
858 // Invalid edgeit is always forward :) |
|
859 if( e.it == edges.end() ) { |
|
860 e.forw = true; |
|
861 return e; |
|
862 } |
|
863 |
|
864 e.forw = ( G.tail(*e.it) == common_node ); |
|
865 return e; |
|
866 } |
|
867 |
|
868 template<typename Gr> |
|
869 typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const { |
|
870 if( n.idx >= length() ) { |
|
871 // FIXME: invalid |
|
872 n.idx = length()+1; |
|
873 return n; |
|
874 } |
|
875 |
|
876 |
|
877 GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) : |
|
878 G.tail(edges[n.idx]) ); |
|
879 ++n.idx; |
|
880 if( n.idx < length() ) { |
|
881 n.tail = ( next_node == G.tail(edges[n.idx]) ); |
|
882 } |
|
883 else { |
|
884 n.tail = true; |
|
885 } |
|
886 |
|
887 return n; |
|
888 } |
|
889 |
|
890 template<typename Gr> |
|
891 bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a, |
|
892 GraphNode &b) { |
|
893 if( G.tail(e) == a ) { |
|
894 b=G.head(e); |
|
895 return true; |
|
896 } |
|
897 if( G.head(e) == a ) { |
|
898 b=G.tail(e); |
|
899 return true; |
|
900 } |
|
901 return false; |
|
902 } |
|
903 |
|
904 template<typename Gr> |
|
905 bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e, |
|
906 const GraphEdge &f) { |
|
907 if( edgeIncident(f, G.tail(e), _last) ) { |
|
908 _first = G.head(e); |
|
909 return true; |
|
910 } |
|
911 if( edgeIncident(f, G.head(e), _last) ) { |
|
912 _first = G.tail(e); |
|
913 return true; |
|
914 } |
|
915 return false; |
|
916 } |
|
917 |
|
918 template<typename Gr> |
|
919 bool DynamicPath<Gr>::pushFront(const GraphEdge &e) { |
|
920 if( G.valid(_first) ) { |
|
921 if( edgeIncident(e, _first, _first) ) { |
|
922 edges.push_front(e); |
|
923 return true; |
|
924 } |
|
925 else |
|
926 return false; |
|
927 } |
|
928 else if( length() < 1 || connectTwoEdges(e, edges[0]) ) { |
|
929 edges.push_front(e); |
|
930 return true; |
|
931 } |
|
932 else |
|
933 return false; |
|
934 } |
|
935 |
|
936 template<typename Gr> |
|
937 bool DynamicPath<Gr>::pushBack(const GraphEdge &e) { |
|
938 if( G.valid(_last) ) { |
|
939 if( edgeIncident(e, _last, _last) ) { |
|
940 edges.push_back(e); |
|
941 return true; |
|
942 } |
|
943 else |
|
944 return false; |
|
945 } |
|
946 else if( length() < 1 || connectTwoEdges(edges[0], e) ) { |
|
947 edges.push_back(e); |
|
948 return true; |
|
949 } |
|
950 else |
|
951 return false; |
|
952 } |
|
953 |
|
954 |
|
955 template<typename Gr> |
|
956 bool DynamicPath<Gr>::setFrom(const GraphNode &n) { |
|
957 if( G.valid(_first) ) { |
|
958 return _first == n; |
|
959 } |
|
960 else { |
|
961 if( length() > 0) { |
|
962 if( edgeIncident(edges[0], n, _last) ) { |
|
963 _first = n; |
|
964 return true; |
|
965 } |
|
966 else return false; |
|
967 } |
|
968 else { |
|
969 _first = _last = n; |
|
970 return true; |
|
971 } |
|
972 } |
|
973 } |
|
974 |
|
975 template<typename Gr> |
|
976 bool DynamicPath<Gr>::setTo(const GraphNode &n) { |
|
977 if( G.valid(_last) ) { |
|
978 return _last == n; |
|
979 } |
|
980 else { |
|
981 if( length() > 0) { |
|
982 if( edgeIncident(edges[0], n, _first) ) { |
|
983 _last = n; |
|
984 return true; |
|
985 } |
|
986 else return false; |
|
987 } |
|
988 else { |
|
989 _first = _last = n; |
|
990 return true; |
|
991 } |
|
992 } |
|
993 } |
|
994 |
|
995 |
|
996 template<typename Gr> |
|
997 typename DynamicPath<Gr>::NodeIt |
|
998 DynamicPath<Gr>::tail(const EdgeIt& e) const { |
|
999 NodeIt n; |
|
1000 |
|
1001 if( e.it == edges.end() ) { |
|
1002 // FIXME: invalid-> invalid |
|
1003 n.idx = length() + 1; |
|
1004 n.tail = true; |
|
1005 return n; |
|
1006 } |
|
1007 |
|
1008 n.idx = e.it-edges.begin(); |
|
1009 n.tail = e.forw; |
|
1010 return n; |
|
1011 } |
|
1012 |
|
1013 template<typename Gr> |
|
1014 typename DynamicPath<Gr>::NodeIt |
|
1015 DynamicPath<Gr>::head(const EdgeIt& e) const { |
|
1016 if( e.it == edges.end()-1 ) { |
|
1017 return _last; |
|
1018 } |
|
1019 |
|
1020 EdgeIt next_edge = e; |
|
1021 next(next_edge); |
|
1022 return tail(next_edge); |
|
1023 } |
|
1024 |
|
1025 template<typename Gr> |
|
1026 typename DynamicPath<Gr>::GraphEdge |
|
1027 DynamicPath<Gr>::graphEdge(const EdgeIt& e) const { |
|
1028 if( e.it != edges.end() ) { |
|
1029 return *e.it; |
|
1030 } |
|
1031 else { |
|
1032 return INVALID; |
|
1033 } |
|
1034 } |
|
1035 |
|
1036 template<typename Gr> |
|
1037 typename DynamicPath<Gr>::GraphNode |
|
1038 DynamicPath<Gr>::graphNode(const NodeIt& n) const { |
|
1039 if( n.idx < length() ) { |
|
1040 return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]); |
|
1041 } |
|
1042 else if( n.idx == length() ) { |
|
1043 return _last; |
|
1044 } |
|
1045 else { |
|
1046 return INVALID; |
|
1047 } |
|
1048 } |
|
1049 |
|
1050 template<typename Gr> |
|
1051 typename DynamicPath<Gr>::EdgeIt& |
|
1052 DynamicPath<Gr>::nth(EdgeIt &e, size_t k) const { |
|
1053 if( k>=length() ) { |
|
1054 // FIXME: invalid EdgeIt |
|
1055 e.it = edges.end(); |
|
1056 e.forw = true; |
|
1057 return e; |
|
1058 } |
|
1059 |
|
1060 e.it = edges.begin()+k; |
|
1061 if(k==0) { |
|
1062 e.forw = ( G.tail(*e.it) == _first ); |
|
1063 } |
|
1064 else { |
|
1065 e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) || |
|
1066 G.tail(*e.it) == G.head(edges[k-1]) ); |
|
1067 } |
|
1068 return e; |
|
1069 } |
|
1070 |
|
1071 template<typename Gr> |
|
1072 typename DynamicPath<Gr>::NodeIt& |
|
1073 DynamicPath<Gr>::nth(NodeIt &n, size_t k) const { |
|
1074 if( k>length() ) { |
|
1075 // FIXME: invalid NodeIt |
|
1076 n.idx = length()+1; |
|
1077 n.tail = true; |
|
1078 return n; |
|
1079 } |
|
1080 if( k==length() ) { |
|
1081 n.idx = length(); |
|
1082 n.tail = true; |
|
1083 return n; |
|
1084 } |
|
1085 n = tail(nth<EdgeIt>(k)); |
|
1086 return n; |
|
1087 } |
|
1088 |
|
1089 // Reszut konstruktorok: |
|
1090 |
|
1091 |
|
1092 template<typename Gr> |
|
1093 DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a, |
|
1094 const EdgeIt &b) : |
|
1095 G(P.G), edges(a.it, b.it) // WARNING: if b.it < a.it this will blow up! |
|
1096 { |
|
1097 if( G.valid(P._first) && a.it < P.edges.end() ) { |
|
1098 _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) ); |
|
1099 if( b.it < P.edges.end() ) { |
|
1100 _last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) ); |
|
1101 } |
|
1102 else { |
|
1103 _last = P._last; |
|
1104 } |
|
1105 } |
|
1106 } |
|
1107 |
|
1108 template<typename Gr> |
|
1109 DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const NodeIt &a, |
|
1110 const NodeIt &b) : G(P.G) |
|
1111 { |
|
1112 if( !P.valid(a) || !P.valid(b) ) |
|
1113 return; |
|
1114 |
|
1115 int ai = a.idx, bi = b.idx; |
|
1116 if( bi<ai ) |
|
1117 std::swap(ai,bi); |
|
1118 |
|
1119 edges.resize(bi-ai); |
|
1120 copy(P.edges.begin()+ai, P.edges.begin()+bi, edges.begin()); |
|
1121 |
|
1122 _first = P.graphNode(a); |
|
1123 _last = P.graphNode(b); |
|
1124 } |
|
1125 |
|
1126 ///@} |
705 ///@} |
1127 |
706 |
1128 } // namespace hugo |
707 } // namespace hugo |
1129 |
708 |
1130 #endif // HUGO_PATH_H |
709 #endif // HUGO_PATH_H |