3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
18 #ifndef LEMON_PLANARITY_H
19 #define LEMON_PLANARITY_H
21 /// \ingroup graph_prop
23 /// \brief Planarity checking, embedding
28 #include <lemon/dfs.h>
29 #include <lemon/radix_sort.h>
30 #include <lemon/maps.h>
31 #include <lemon/path.h>
36 namespace _planarity_bits {
38 template <typename UGraph>
39 struct PlanarityVisitor : DfsVisitor<UGraph> {
41 typedef typename UGraph::Node Node;
42 typedef typename UGraph::Edge Edge;
44 typedef typename UGraph::template NodeMap<Edge> PredMap;
46 typedef typename UGraph::template UEdgeMap<bool> TreeMap;
48 typedef typename UGraph::template NodeMap<int> OrderMap;
49 typedef std::vector<Node> OrderList;
51 typedef typename UGraph::template NodeMap<int> LowMap;
52 typedef typename UGraph::template NodeMap<int> AncestorMap;
54 PlanarityVisitor(const UGraph& ugraph,
55 PredMap& pred_map, TreeMap& tree_map,
56 OrderMap& order_map, OrderList& order_list,
57 AncestorMap& ancestor_map, LowMap& low_map)
58 : _ugraph(ugraph), _pred_map(pred_map), _tree_map(tree_map),
59 _order_map(order_map), _order_list(order_list),
60 _ancestor_map(ancestor_map), _low_map(low_map) {}
62 void reach(const Node& node) {
63 _order_map[node] = _order_list.size();
64 _low_map[node] = _order_list.size();
65 _ancestor_map[node] = _order_list.size();
66 _order_list.push_back(node);
69 void discover(const Edge& edge) {
70 Node source = _ugraph.source(edge);
71 Node target = _ugraph.target(edge);
73 _tree_map[edge] = true;
74 _pred_map[target] = edge;
77 void examine(const Edge& edge) {
78 Node source = _ugraph.source(edge);
79 Node target = _ugraph.target(edge);
81 if (_order_map[target] < _order_map[source] && !_tree_map[edge]) {
82 if (_low_map[source] > _order_map[target]) {
83 _low_map[source] = _order_map[target];
85 if (_ancestor_map[source] > _order_map[target]) {
86 _ancestor_map[source] = _order_map[target];
91 void backtrack(const Edge& edge) {
92 Node source = _ugraph.source(edge);
93 Node target = _ugraph.target(edge);
95 if (_low_map[source] > _low_map[target]) {
96 _low_map[source] = _low_map[target];
100 const UGraph& _ugraph;
103 OrderMap& _order_map;
104 OrderList& _order_list;
105 AncestorMap& _ancestor_map;
109 template <typename UGraph, bool embedding = true>
110 struct NodeDataNode {
113 typename UGraph::Edge first;
117 template <typename UGraph>
118 struct NodeDataNode<UGraph, false> {
123 template <typename UGraph>
124 struct ChildListNode {
125 typedef typename UGraph::Node Node;
130 template <typename UGraph>
131 struct EdgeListNode {
132 typename UGraph::Edge prev, next;
137 /// \ingroup graph_prop
139 /// \brief Planarity checking of an undirected simple graph
141 /// This class implements the Boyer-Myrvold algorithm for planar
142 /// checking of an undirected graph. This class is a simplified
143 /// version of the PlanarEmbedding algorithm class, and it does
144 /// provide neither embedding nor kuratowski subdivisons.
145 template <typename UGraph>
146 class PlanarityChecking {
149 UGRAPH_TYPEDEFS(typename UGraph)
151 const UGraph& _ugraph;
155 typedef typename UGraph::template NodeMap<Edge> PredMap;
157 typedef typename UGraph::template UEdgeMap<bool> TreeMap;
159 typedef typename UGraph::template NodeMap<int> OrderMap;
160 typedef std::vector<Node> OrderList;
162 typedef typename UGraph::template NodeMap<int> LowMap;
163 typedef typename UGraph::template NodeMap<int> AncestorMap;
165 typedef _planarity_bits::NodeDataNode<UGraph> NodeDataNode;
166 typedef std::vector<NodeDataNode> NodeData;
168 typedef _planarity_bits::ChildListNode<UGraph> ChildListNode;
169 typedef typename UGraph::template NodeMap<ChildListNode> ChildLists;
171 typedef typename UGraph::template NodeMap<std::list<int> > MergeRoots;
173 typedef typename UGraph::template NodeMap<bool> EmbedEdge;
177 /// \brief Constructor
179 /// \warining The graph should be simple, i.e. parallel and loop edge
181 PlanarityChecking(const UGraph& ugraph) : _ugraph(ugraph) {}
183 /// \brief Runs the algorithm.
185 /// Runs the algorithm.
186 /// \return %True when the graph is planar.
188 typedef _planarity_bits::PlanarityVisitor<UGraph> Visitor;
190 PredMap pred_map(_ugraph, INVALID);
191 TreeMap tree_map(_ugraph, false);
193 OrderMap order_map(_ugraph, -1);
194 OrderList order_list;
196 AncestorMap ancestor_map(_ugraph, -1);
197 LowMap low_map(_ugraph, -1);
199 Visitor visitor(_ugraph, pred_map, tree_map,
200 order_map, order_list, ancestor_map, low_map);
201 DfsVisit<UGraph, Visitor> visit(_ugraph, visitor);
204 ChildLists child_lists(_ugraph);
205 createChildLists(tree_map, order_map, low_map, child_lists);
207 NodeData node_data(2 * order_list.size());
209 EmbedEdge embed_edge(_ugraph, false);
211 MergeRoots merge_roots(_ugraph);
213 for (int i = order_list.size() - 1; i >= 0; --i) {
215 Node node = order_list[i];
218 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
219 Node target = _ugraph.target(e);
221 if (order_map[source] < order_map[target] && tree_map[e]) {
222 initFace(target, node_data, order_map, order_list);
226 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
227 Node target = _ugraph.target(e);
229 if (order_map[source] < order_map[target] && !tree_map[e]) {
230 embed_edge[target] = true;
231 walkUp(target, source, i, pred_map, low_map,
232 order_map, order_list, node_data, merge_roots);
236 for (typename MergeRoots::Value::iterator it =
237 merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
239 walkDown(rn, i, node_data, order_list, child_lists,
240 ancestor_map, low_map, embed_edge, merge_roots);
242 merge_roots[node].clear();
244 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
245 Node target = _ugraph.target(e);
247 if (order_map[source] < order_map[target] && !tree_map[e]) {
248 if (embed_edge[target]) {
260 void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
261 const LowMap& low_map, ChildLists& child_lists) {
263 for (NodeIt n(_ugraph); n != INVALID; ++n) {
266 std::vector<Node> targets;
267 for (OutEdgeIt e(_ugraph, n); e != INVALID; ++e) {
268 Node target = _ugraph.target(e);
270 if (order_map[source] < order_map[target] && tree_map[e]) {
271 targets.push_back(target);
275 if (targets.size() == 0) {
276 child_lists[source].first = INVALID;
277 } else if (targets.size() == 1) {
278 child_lists[source].first = targets[0];
279 child_lists[targets[0]].prev = INVALID;
280 child_lists[targets[0]].next = INVALID;
282 radixSort(targets.begin(), targets.end(), mapFunctor(low_map));
283 for (int i = 1; i < int(targets.size()); ++i) {
284 child_lists[targets[i]].prev = targets[i - 1];
285 child_lists[targets[i - 1]].next = targets[i];
287 child_lists[targets.back()].next = INVALID;
288 child_lists[targets.front()].prev = INVALID;
289 child_lists[source].first = targets.front();
294 void walkUp(const Node& node, Node root, int rorder,
295 const PredMap& pred_map, const LowMap& low_map,
296 const OrderMap& order_map, const OrderList& order_list,
297 NodeData& node_data, MergeRoots& merge_roots) {
302 na = nb = order_map[node];
303 da = true; db = false;
307 if (node_data[na].visited == rorder) break;
308 if (node_data[nb].visited == rorder) break;
310 node_data[na].visited = rorder;
311 node_data[nb].visited = rorder;
315 if (na >= int(order_list.size())) {
317 } else if (nb >= int(order_list.size())) {
324 nn = da ? node_data[na].prev : node_data[na].next;
325 da = node_data[nn].prev != na;
328 nn = db ? node_data[nb].prev : node_data[nb].next;
329 db = node_data[nn].prev != nb;
334 Node rep = order_list[rn - order_list.size()];
335 Node parent = _ugraph.source(pred_map[rep]);
337 if (low_map[rep] < rorder) {
338 merge_roots[parent].push_back(rn);
340 merge_roots[parent].push_front(rn);
343 if (parent != root) {
344 na = nb = order_map[parent];
345 da = true; db = false;
353 void walkDown(int rn, int rorder, NodeData& node_data,
354 OrderList& order_list, ChildLists& child_lists,
355 AncestorMap& ancestor_map, LowMap& low_map,
356 EmbedEdge& embed_edge, MergeRoots& merge_roots) {
358 std::vector<std::pair<int, bool> > merge_stack;
360 for (int di = 0; di < 2; ++di) {
363 int n = rd ? node_data[rn].next : node_data[rn].prev;
367 Node node = order_list[n];
369 if (embed_edge[node]) {
371 // Merging components on the critical path
372 while (!merge_stack.empty()) {
375 int cn = merge_stack.back().first;
376 bool cd = merge_stack.back().second;
377 merge_stack.pop_back();
379 // Parent of component
380 int dn = merge_stack.back().first;
381 bool dd = merge_stack.back().second;
382 merge_stack.pop_back();
384 Node parent = order_list[dn];
386 // Erasing from merge_roots
387 merge_roots[parent].pop_front();
389 Node child = order_list[cn - order_list.size()];
391 // Erasing from child_lists
392 if (child_lists[child].prev != INVALID) {
393 child_lists[child_lists[child].prev].next =
394 child_lists[child].next;
396 child_lists[parent].first = child_lists[child].next;
399 if (child_lists[child].next != INVALID) {
400 child_lists[child_lists[child].next].prev =
401 child_lists[child].prev;
404 // Merging external faces
407 cn = cd ? node_data[cn].prev : node_data[cn].next;
408 cd = node_data[cn].next == en;
412 if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
413 if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
417 bool d = pn == node_data[n].prev;
419 if (node_data[n].prev == node_data[n].next &&
420 node_data[n].inverted) {
424 // Embedding edge into external face
425 if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
426 if (d) node_data[n].prev = rn; else node_data[n].next = rn;
429 embed_edge[order_list[n]] = false;
432 if (!merge_roots[node].empty()) {
434 bool d = pn == node_data[n].prev;
436 merge_stack.push_back(std::make_pair(n, d));
438 int rn = merge_roots[node].front();
440 int xn = node_data[rn].next;
441 Node xnode = order_list[xn];
443 int yn = node_data[rn].prev;
444 Node ynode = order_list[yn];
447 if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
449 } else if (!external(ynode, rorder, child_lists,
450 ancestor_map, low_map)) {
452 } else if (pertinent(xnode, embed_edge, merge_roots)) {
458 merge_stack.push_back(std::make_pair(rn, rd));
463 } else if (!external(node, rorder, child_lists,
464 ancestor_map, low_map)) {
465 int nn = (node_data[n].next != pn ?
466 node_data[n].next : node_data[n].prev);
468 bool nd = n == node_data[nn].prev;
470 if (nd) node_data[nn].prev = pn;
471 else node_data[nn].next = pn;
473 if (n == node_data[pn].prev) node_data[pn].prev = nn;
474 else node_data[pn].next = nn;
476 node_data[nn].inverted =
477 (node_data[nn].prev == node_data[nn].next && nd != rd);
485 if (!merge_stack.empty() || n == rn) {
491 void initFace(const Node& node, NodeData& node_data,
492 const OrderMap& order_map, const OrderList& order_list) {
493 int n = order_map[node];
494 int rn = n + order_list.size();
496 node_data[n].next = node_data[n].prev = rn;
497 node_data[rn].next = node_data[rn].prev = n;
499 node_data[n].visited = order_list.size();
500 node_data[rn].visited = order_list.size();
504 bool external(const Node& node, int rorder,
505 ChildLists& child_lists, AncestorMap& ancestor_map,
507 Node child = child_lists[node].first;
509 if (child != INVALID) {
510 if (low_map[child] < rorder) return true;
513 if (ancestor_map[node] < rorder) return true;
518 bool pertinent(const Node& node, const EmbedEdge& embed_edge,
519 const MergeRoots& merge_roots) {
520 return !merge_roots[node].empty() || embed_edge[node];
525 /// \ingroup graph_prop
527 /// \brief Planar embedding of an undirected simple graph
529 /// This class implements the Boyer-Myrvold algorithm for planar
530 /// embedding of an undirected graph. The planar embeding is an
531 /// ordering of the outgoing edges in each node, which is a possible
532 /// configuration to draw the graph in the plane. If there is not
533 /// such ordering then the graph contains a \f$ K_5 \f$ (full graph
534 /// with 5 nodes) or an \f$ K_{3,3} \f$ (complete bipartite graph on
535 /// 3 ANode and 3 BNode) subdivision.
537 /// The current implementation calculates an embedding or an
538 /// Kuratowski subdivision if the graph is not planar. The running
539 /// time of the algorithm is \f$ O(n) \f$.
540 template <typename UGraph>
541 class PlanarEmbedding {
544 UGRAPH_TYPEDEFS(typename UGraph)
546 const UGraph& _ugraph;
547 typename UGraph::template EdgeMap<Edge> _embedding;
549 typename UGraph::template UEdgeMap<bool> _kuratowski;
553 typedef typename UGraph::template NodeMap<Edge> PredMap;
555 typedef typename UGraph::template UEdgeMap<bool> TreeMap;
557 typedef typename UGraph::template NodeMap<int> OrderMap;
558 typedef std::vector<Node> OrderList;
560 typedef typename UGraph::template NodeMap<int> LowMap;
561 typedef typename UGraph::template NodeMap<int> AncestorMap;
563 typedef _planarity_bits::NodeDataNode<UGraph> NodeDataNode;
564 typedef std::vector<NodeDataNode> NodeData;
566 typedef _planarity_bits::ChildListNode<UGraph> ChildListNode;
567 typedef typename UGraph::template NodeMap<ChildListNode> ChildLists;
569 typedef typename UGraph::template NodeMap<std::list<int> > MergeRoots;
571 typedef typename UGraph::template NodeMap<Edge> EmbedEdge;
573 typedef _planarity_bits::EdgeListNode<UGraph> EdgeListNode;
574 typedef typename UGraph::template EdgeMap<EdgeListNode> EdgeLists;
576 typedef typename UGraph::template NodeMap<bool> FlipMap;
578 typedef typename UGraph::template NodeMap<int> TypeMap;
580 enum IsolatorNodeType {
583 ROOT = 10, PERTINENT = 11,
589 /// \brief Constructor
591 /// \warining The graph should be simple, i.e. parallel and loop edge
593 PlanarEmbedding(const UGraph& ugraph)
594 : _ugraph(ugraph), _embedding(_ugraph), _kuratowski(ugraph, false) {}
596 /// \brief Runs the algorithm.
598 /// Runs the algorithm.
599 /// \param kuratowski If the parameter is false, then the
600 /// algorithm does not calculate the isolate Kuratowski
602 ///\return %True when the graph is planar.
603 bool run(bool kuratowski = true) {
604 typedef _planarity_bits::PlanarityVisitor<UGraph> Visitor;
606 PredMap pred_map(_ugraph, INVALID);
607 TreeMap tree_map(_ugraph, false);
609 OrderMap order_map(_ugraph, -1);
610 OrderList order_list;
612 AncestorMap ancestor_map(_ugraph, -1);
613 LowMap low_map(_ugraph, -1);
615 Visitor visitor(_ugraph, pred_map, tree_map,
616 order_map, order_list, ancestor_map, low_map);
617 DfsVisit<UGraph, Visitor> visit(_ugraph, visitor);
620 ChildLists child_lists(_ugraph);
621 createChildLists(tree_map, order_map, low_map, child_lists);
623 NodeData node_data(2 * order_list.size());
625 EmbedEdge embed_edge(_ugraph, INVALID);
627 MergeRoots merge_roots(_ugraph);
629 EdgeLists edge_lists(_ugraph);
631 FlipMap flip_map(_ugraph, false);
633 for (int i = order_list.size() - 1; i >= 0; --i) {
635 Node node = order_list[i];
637 node_data[i].first = INVALID;
640 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
641 Node target = _ugraph.target(e);
643 if (order_map[source] < order_map[target] && tree_map[e]) {
644 initFace(target, edge_lists, node_data,
645 pred_map, order_map, order_list);
649 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
650 Node target = _ugraph.target(e);
652 if (order_map[source] < order_map[target] && !tree_map[e]) {
653 embed_edge[target] = e;
654 walkUp(target, source, i, pred_map, low_map,
655 order_map, order_list, node_data, merge_roots);
659 for (typename MergeRoots::Value::iterator it =
660 merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
662 walkDown(rn, i, node_data, edge_lists, flip_map, order_list,
663 child_lists, ancestor_map, low_map, embed_edge, merge_roots);
665 merge_roots[node].clear();
667 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
668 Node target = _ugraph.target(e);
670 if (order_map[source] < order_map[target] && !tree_map[e]) {
671 if (embed_edge[target] != INVALID) {
673 isolateKuratowski(e, node_data, edge_lists, flip_map,
674 order_map, order_list, pred_map, child_lists,
675 ancestor_map, low_map,
676 embed_edge, merge_roots);
684 for (int i = 0; i < int(order_list.size()); ++i) {
686 mergeRemainingFaces(order_list[i], node_data, order_list, order_map,
687 child_lists, edge_lists);
688 storeEmbedding(order_list[i], node_data, order_map, pred_map,
689 edge_lists, flip_map);
695 /// \brief Gives back the successor of an edge
697 /// Gives back the successor of an edge. This function makes
698 /// possible to query the cyclic order of the outgoing edges from
700 Edge next(const Edge& edge) const {
701 return _embedding[edge];
704 /// \brief Gives back true when the undirected edge is in the
705 /// kuratowski subdivision
707 /// Gives back true when the undirected edge is in the kuratowski
709 bool kuratowski(const UEdge& uedge) {
710 return _kuratowski[uedge];
715 void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
716 const LowMap& low_map, ChildLists& child_lists) {
718 for (NodeIt n(_ugraph); n != INVALID; ++n) {
721 std::vector<Node> targets;
722 for (OutEdgeIt e(_ugraph, n); e != INVALID; ++e) {
723 Node target = _ugraph.target(e);
725 if (order_map[source] < order_map[target] && tree_map[e]) {
726 targets.push_back(target);
730 if (targets.size() == 0) {
731 child_lists[source].first = INVALID;
732 } else if (targets.size() == 1) {
733 child_lists[source].first = targets[0];
734 child_lists[targets[0]].prev = INVALID;
735 child_lists[targets[0]].next = INVALID;
737 radixSort(targets.begin(), targets.end(), mapFunctor(low_map));
738 for (int i = 1; i < int(targets.size()); ++i) {
739 child_lists[targets[i]].prev = targets[i - 1];
740 child_lists[targets[i - 1]].next = targets[i];
742 child_lists[targets.back()].next = INVALID;
743 child_lists[targets.front()].prev = INVALID;
744 child_lists[source].first = targets.front();
749 void walkUp(const Node& node, Node root, int rorder,
750 const PredMap& pred_map, const LowMap& low_map,
751 const OrderMap& order_map, const OrderList& order_list,
752 NodeData& node_data, MergeRoots& merge_roots) {
757 na = nb = order_map[node];
758 da = true; db = false;
762 if (node_data[na].visited == rorder) break;
763 if (node_data[nb].visited == rorder) break;
765 node_data[na].visited = rorder;
766 node_data[nb].visited = rorder;
770 if (na >= int(order_list.size())) {
772 } else if (nb >= int(order_list.size())) {
779 nn = da ? node_data[na].prev : node_data[na].next;
780 da = node_data[nn].prev != na;
783 nn = db ? node_data[nb].prev : node_data[nb].next;
784 db = node_data[nn].prev != nb;
789 Node rep = order_list[rn - order_list.size()];
790 Node parent = _ugraph.source(pred_map[rep]);
792 if (low_map[rep] < rorder) {
793 merge_roots[parent].push_back(rn);
795 merge_roots[parent].push_front(rn);
798 if (parent != root) {
799 na = nb = order_map[parent];
800 da = true; db = false;
808 void walkDown(int rn, int rorder, NodeData& node_data,
809 EdgeLists& edge_lists, FlipMap& flip_map,
810 OrderList& order_list, ChildLists& child_lists,
811 AncestorMap& ancestor_map, LowMap& low_map,
812 EmbedEdge& embed_edge, MergeRoots& merge_roots) {
814 std::vector<std::pair<int, bool> > merge_stack;
816 for (int di = 0; di < 2; ++di) {
819 int n = rd ? node_data[rn].next : node_data[rn].prev;
823 Node node = order_list[n];
825 if (embed_edge[node] != INVALID) {
827 // Merging components on the critical path
828 while (!merge_stack.empty()) {
831 int cn = merge_stack.back().first;
832 bool cd = merge_stack.back().second;
833 merge_stack.pop_back();
835 // Parent of component
836 int dn = merge_stack.back().first;
837 bool dd = merge_stack.back().second;
838 merge_stack.pop_back();
840 Node parent = order_list[dn];
842 // Erasing from merge_roots
843 merge_roots[parent].pop_front();
845 Node child = order_list[cn - order_list.size()];
847 // Erasing from child_lists
848 if (child_lists[child].prev != INVALID) {
849 child_lists[child_lists[child].prev].next =
850 child_lists[child].next;
852 child_lists[parent].first = child_lists[child].next;
855 if (child_lists[child].next != INVALID) {
856 child_lists[child_lists[child].next].prev =
857 child_lists[child].prev;
860 // Merging edges + flipping
861 Edge de = node_data[dn].first;
862 Edge ce = node_data[cn].first;
864 flip_map[order_list[cn - order_list.size()]] = cd != dd;
866 std::swap(edge_lists[ce].prev, edge_lists[ce].next);
867 ce = edge_lists[ce].prev;
868 std::swap(edge_lists[ce].prev, edge_lists[ce].next);
872 Edge dne = edge_lists[de].next;
873 Edge cne = edge_lists[ce].next;
875 edge_lists[de].next = cne;
876 edge_lists[ce].next = dne;
878 edge_lists[dne].prev = ce;
879 edge_lists[cne].prev = de;
883 node_data[dn].first = ce;
886 // Merging external faces
889 cn = cd ? node_data[cn].prev : node_data[cn].next;
890 cd = node_data[cn].next == en;
892 if (node_data[cn].prev == node_data[cn].next &&
893 node_data[cn].inverted) {
898 if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
899 if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
903 bool d = pn == node_data[n].prev;
905 if (node_data[n].prev == node_data[n].next &&
906 node_data[n].inverted) {
912 Edge edge = embed_edge[node];
913 Edge re = node_data[rn].first;
915 edge_lists[edge_lists[re].next].prev = edge;
916 edge_lists[edge].next = edge_lists[re].next;
917 edge_lists[edge].prev = re;
918 edge_lists[re].next = edge;
921 node_data[rn].first = edge;
924 Edge rev = _ugraph.oppositeEdge(edge);
925 Edge e = node_data[n].first;
927 edge_lists[edge_lists[e].next].prev = rev;
928 edge_lists[rev].next = edge_lists[e].next;
929 edge_lists[rev].prev = e;
930 edge_lists[e].next = rev;
933 node_data[n].first = rev;
938 // Embedding edge into external face
939 if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
940 if (d) node_data[n].prev = rn; else node_data[n].next = rn;
943 embed_edge[order_list[n]] = INVALID;
946 if (!merge_roots[node].empty()) {
948 bool d = pn == node_data[n].prev;
949 if (node_data[n].prev == node_data[n].next &&
950 node_data[n].inverted) {
954 merge_stack.push_back(std::make_pair(n, d));
956 int rn = merge_roots[node].front();
958 int xn = node_data[rn].next;
959 Node xnode = order_list[xn];
961 int yn = node_data[rn].prev;
962 Node ynode = order_list[yn];
965 if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
967 } else if (!external(ynode, rorder, child_lists,
968 ancestor_map, low_map)) {
970 } else if (pertinent(xnode, embed_edge, merge_roots)) {
976 merge_stack.push_back(std::make_pair(rn, rd));
981 } else if (!external(node, rorder, child_lists,
982 ancestor_map, low_map)) {
983 int nn = (node_data[n].next != pn ?
984 node_data[n].next : node_data[n].prev);
986 bool nd = n == node_data[nn].prev;
988 if (nd) node_data[nn].prev = pn;
989 else node_data[nn].next = pn;
991 if (n == node_data[pn].prev) node_data[pn].prev = nn;
992 else node_data[pn].next = nn;
994 node_data[nn].inverted =
995 (node_data[nn].prev == node_data[nn].next && nd != rd);
1003 if (!merge_stack.empty() || n == rn) {
1009 void initFace(const Node& node, EdgeLists& edge_lists,
1010 NodeData& node_data, const PredMap& pred_map,
1011 const OrderMap& order_map, const OrderList& order_list) {
1012 int n = order_map[node];
1013 int rn = n + order_list.size();
1015 node_data[n].next = node_data[n].prev = rn;
1016 node_data[rn].next = node_data[rn].prev = n;
1018 node_data[n].visited = order_list.size();
1019 node_data[rn].visited = order_list.size();
1021 node_data[n].inverted = false;
1022 node_data[rn].inverted = false;
1024 Edge edge = pred_map[node];
1025 Edge rev = _ugraph.oppositeEdge(edge);
1027 node_data[rn].first = edge;
1028 node_data[n].first = rev;
1030 edge_lists[edge].prev = edge;
1031 edge_lists[edge].next = edge;
1033 edge_lists[rev].prev = rev;
1034 edge_lists[rev].next = rev;
1038 void mergeRemainingFaces(const Node& node, NodeData& node_data,
1039 OrderList& order_list, OrderMap& order_map,
1040 ChildLists& child_lists, EdgeLists& edge_lists) {
1041 while (child_lists[node].first != INVALID) {
1042 int dd = order_map[node];
1043 Node child = child_lists[node].first;
1044 int cd = order_map[child] + order_list.size();
1045 child_lists[node].first = child_lists[child].next;
1047 Edge de = node_data[dd].first;
1048 Edge ce = node_data[cd].first;
1050 if (de != INVALID) {
1051 Edge dne = edge_lists[de].next;
1052 Edge cne = edge_lists[ce].next;
1054 edge_lists[de].next = cne;
1055 edge_lists[ce].next = dne;
1057 edge_lists[dne].prev = ce;
1058 edge_lists[cne].prev = de;
1061 node_data[dd].first = ce;
1066 void storeEmbedding(const Node& node, NodeData& node_data,
1067 OrderMap& order_map, PredMap& pred_map,
1068 EdgeLists& edge_lists, FlipMap& flip_map) {
1070 if (node_data[order_map[node]].first == INVALID) return;
1072 if (pred_map[node] != INVALID) {
1073 Node source = _ugraph.source(pred_map[node]);
1074 flip_map[node] = flip_map[node] != flip_map[source];
1077 Edge first = node_data[order_map[node]].first;
1080 Edge edge = flip_map[node] ?
1081 edge_lists[prev].prev : edge_lists[prev].next;
1083 _embedding[prev] = edge;
1085 while (edge != first) {
1086 Edge next = edge_lists[edge].prev == prev ?
1087 edge_lists[edge].next : edge_lists[edge].prev;
1088 prev = edge; edge = next;
1089 _embedding[prev] = edge;
1094 bool external(const Node& node, int rorder,
1095 ChildLists& child_lists, AncestorMap& ancestor_map,
1097 Node child = child_lists[node].first;
1099 if (child != INVALID) {
1100 if (low_map[child] < rorder) return true;
1103 if (ancestor_map[node] < rorder) return true;
1108 bool pertinent(const Node& node, const EmbedEdge& embed_edge,
1109 const MergeRoots& merge_roots) {
1110 return !merge_roots[node].empty() || embed_edge[node] != INVALID;
1113 int lowPoint(const Node& node, OrderMap& order_map, ChildLists& child_lists,
1114 AncestorMap& ancestor_map, LowMap& low_map) {
1117 Node child = child_lists[node].first;
1119 if (child != INVALID) {
1120 low_point = low_map[child];
1122 low_point = order_map[node];
1125 if (low_point > ancestor_map[node]) {
1126 low_point = ancestor_map[node];
1132 int findComponentRoot(Node root, Node node, ChildLists& child_lists,
1133 OrderMap& order_map, OrderList& order_list) {
1135 int order = order_map[root];
1136 int norder = order_map[node];
1138 Node child = child_lists[root].first;
1139 while (child != INVALID) {
1140 int corder = order_map[child];
1141 if (corder > order && corder < norder) {
1144 child = child_lists[child].next;
1146 return order + order_list.size();
1149 Node findPertinent(Node node, OrderMap& order_map, NodeData& node_data,
1150 EmbedEdge& embed_edge, MergeRoots& merge_roots) {
1151 Node wnode =_ugraph.target(node_data[order_map[node]].first);
1152 while (!pertinent(wnode, embed_edge, merge_roots)) {
1153 wnode = _ugraph.target(node_data[order_map[wnode]].first);
1159 Node findExternal(Node node, int rorder, OrderMap& order_map,
1160 ChildLists& child_lists, AncestorMap& ancestor_map,
1161 LowMap& low_map, NodeData& node_data) {
1162 Node wnode =_ugraph.target(node_data[order_map[node]].first);
1163 while (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
1164 wnode = _ugraph.target(node_data[order_map[wnode]].first);
1169 void markCommonPath(Node node, int rorder, Node& wnode, Node& znode,
1170 OrderList& order_list, OrderMap& order_map,
1171 NodeData& node_data, EdgeLists& edge_lists,
1172 EmbedEdge& embed_edge, MergeRoots& merge_roots,
1173 ChildLists& child_lists, AncestorMap& ancestor_map,
1177 Node pred = INVALID;
1181 bool pert = pertinent(cnode, embed_edge, merge_roots);
1182 bool ext = external(cnode, rorder, child_lists, ancestor_map, low_map);
1185 if (!merge_roots[cnode].empty()) {
1186 int cn = merge_roots[cnode].back();
1188 if (low_map[order_list[cn - order_list.size()]] < rorder) {
1189 Edge edge = node_data[cn].first;
1190 _kuratowski.set(edge, true);
1193 cnode = _ugraph.target(edge);
1198 wnode = znode = cnode;
1204 while (!external(cnode, rorder, child_lists, ancestor_map, low_map)) {
1205 Edge edge = node_data[order_map[cnode]].first;
1207 if (_ugraph.target(edge) == pred) {
1208 edge = edge_lists[edge].next;
1210 _kuratowski.set(edge, true);
1212 Node next = _ugraph.target(edge);
1213 pred = cnode; cnode = next;
1222 while (!pertinent(cnode, embed_edge, merge_roots)) {
1223 Edge edge = node_data[order_map[cnode]].first;
1225 if (_ugraph.target(edge) == pred) {
1226 edge = edge_lists[edge].next;
1228 _kuratowski.set(edge, true);
1230 Node next = _ugraph.target(edge);
1231 pred = cnode; cnode = next;
1238 Edge edge = node_data[order_map[cnode]].first;
1240 if (_ugraph.target(edge) == pred) {
1241 edge = edge_lists[edge].next;
1243 _kuratowski.set(edge, true);
1245 Node next = _ugraph.target(edge);
1246 pred = cnode; cnode = next;
1253 void orientComponent(Node root, int rn, OrderMap& order_map,
1254 PredMap& pred_map, NodeData& node_data,
1255 EdgeLists& edge_lists, FlipMap& flip_map,
1256 TypeMap& type_map) {
1257 node_data[order_map[root]].first = node_data[rn].first;
1260 std::vector<Node> st, qu;
1263 while (!st.empty()) {
1264 Node node = st.back();
1268 Edge edge = node_data[order_map[node]].first;
1270 if (type_map[_ugraph.target(edge)] == 0) {
1271 st.push_back(_ugraph.target(edge));
1272 type_map[_ugraph.target(edge)] = 1;
1275 Edge last = edge, pred = edge;
1276 edge = edge_lists[edge].next;
1277 while (edge != last) {
1279 if (type_map[_ugraph.target(edge)] == 0) {
1280 st.push_back(_ugraph.target(edge));
1281 type_map[_ugraph.target(edge)] = 1;
1284 Edge next = edge_lists[edge].next != pred ?
1285 edge_lists[edge].next : edge_lists[edge].prev;
1286 pred = edge; edge = next;
1292 flip_map[root] = false;
1294 for (int i = 1; i < int(qu.size()); ++i) {
1298 while (type_map[node] != 2) {
1301 node = _ugraph.source(pred_map[node]);
1304 bool flip = flip_map[node];
1306 while (!st.empty()) {
1310 flip_map[node] = flip != flip_map[node];
1311 flip = flip_map[node];
1314 Edge edge = node_data[order_map[node]].first;
1315 std::swap(edge_lists[edge].prev, edge_lists[edge].next);
1316 edge = edge_lists[edge].prev;
1317 std::swap(edge_lists[edge].prev, edge_lists[edge].next);
1318 node_data[order_map[node]].first = edge;
1323 for (int i = 0; i < int(qu.size()); ++i) {
1325 Edge edge = node_data[order_map[qu[i]]].first;
1326 Edge last = edge, pred = edge;
1328 edge = edge_lists[edge].next;
1329 while (edge != last) {
1331 if (edge_lists[edge].next == pred) {
1332 std::swap(edge_lists[edge].next, edge_lists[edge].prev);
1334 pred = edge; edge = edge_lists[edge].next;
1340 void setFaceFlags(Node root, Node wnode, Node ynode, Node xnode,
1341 OrderMap& order_map, NodeData& node_data,
1342 TypeMap& type_map) {
1343 Node node = _ugraph.target(node_data[order_map[root]].first);
1345 while (node != ynode) {
1346 type_map[node] = HIGHY;
1347 node = _ugraph.target(node_data[order_map[node]].first);
1350 while (node != wnode) {
1351 type_map[node] = LOWY;
1352 node = _ugraph.target(node_data[order_map[node]].first);
1355 node = _ugraph.target(node_data[order_map[wnode]].first);
1357 while (node != xnode) {
1358 type_map[node] = LOWX;
1359 node = _ugraph.target(node_data[order_map[node]].first);
1361 type_map[node] = LOWX;
1363 node = _ugraph.target(node_data[order_map[xnode]].first);
1364 while (node != root) {
1365 type_map[node] = HIGHX;
1366 node = _ugraph.target(node_data[order_map[node]].first);
1369 type_map[wnode] = PERTINENT;
1370 type_map[root] = ROOT;
1373 void findInternalPath(std::vector<Edge>& ipath,
1374 Node wnode, Node root, TypeMap& type_map,
1375 OrderMap& order_map, NodeData& node_data,
1376 EdgeLists& edge_lists) {
1377 std::vector<Edge> st;
1381 while (node != root) {
1382 Edge edge = edge_lists[node_data[order_map[node]].first].next;
1384 node = _ugraph.target(edge);
1388 Edge edge = st.back();
1389 if (type_map[_ugraph.target(edge)] == LOWX ||
1390 type_map[_ugraph.target(edge)] == HIGHX) {
1393 if (type_map[_ugraph.target(edge)] == 2) {
1394 type_map[_ugraph.target(edge)] = 3;
1396 edge = edge_lists[_ugraph.oppositeEdge(edge)].next;
1400 edge = edge_lists[edge].next;
1402 while (_ugraph.oppositeEdge(edge) == st.back()) {
1405 edge = edge_lists[edge].next;
1411 for (int i = 0; i < int(st.size()); ++i) {
1412 if (type_map[_ugraph.target(st[i])] != LOWY &&
1413 type_map[_ugraph.target(st[i])] != HIGHY) {
1414 for (; i < int(st.size()); ++i) {
1415 ipath.push_back(st[i]);
1421 void setInternalFlags(std::vector<Edge>& ipath, TypeMap& type_map) {
1422 for (int i = 1; i < int(ipath.size()); ++i) {
1423 type_map[_ugraph.source(ipath[i])] = INTERNAL;
1427 void findPilePath(std::vector<Edge>& ppath,
1428 Node root, TypeMap& type_map, OrderMap& order_map,
1429 NodeData& node_data, EdgeLists& edge_lists) {
1430 std::vector<Edge> st;
1432 st.push_back(_ugraph.oppositeEdge(node_data[order_map[root]].first));
1433 st.push_back(node_data[order_map[root]].first);
1435 while (st.size() > 1) {
1436 Edge edge = st.back();
1437 if (type_map[_ugraph.target(edge)] == INTERNAL) {
1440 if (type_map[_ugraph.target(edge)] == 3) {
1441 type_map[_ugraph.target(edge)] = 4;
1443 edge = edge_lists[_ugraph.oppositeEdge(edge)].next;
1447 edge = edge_lists[edge].next;
1449 while (!st.empty() && _ugraph.oppositeEdge(edge) == st.back()) {
1452 edge = edge_lists[edge].next;
1458 for (int i = 1; i < int(st.size()); ++i) {
1459 ppath.push_back(st[i]);
1464 int markExternalPath(Node node, OrderMap& order_map,
1465 ChildLists& child_lists, PredMap& pred_map,
1466 AncestorMap& ancestor_map, LowMap& low_map) {
1467 int lp = lowPoint(node, order_map, child_lists,
1468 ancestor_map, low_map);
1470 if (ancestor_map[node] != lp) {
1471 node = child_lists[node].first;
1472 _kuratowski[pred_map[node]] = true;
1474 while (ancestor_map[node] != lp) {
1475 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
1476 Node tnode = _ugraph.target(e);
1477 if (order_map[tnode] > order_map[node] && low_map[tnode] == lp) {
1479 _kuratowski[e] = true;
1486 for (OutEdgeIt e(_ugraph, node); e != INVALID; ++e) {
1487 if (order_map[_ugraph.target(e)] == lp) {
1488 _kuratowski[e] = true;
1496 void markPertinentPath(Node node, OrderMap& order_map,
1497 NodeData& node_data, EdgeLists& edge_lists,
1498 EmbedEdge& embed_edge, MergeRoots& merge_roots) {
1499 while (embed_edge[node] == INVALID) {
1500 int n = merge_roots[node].front();
1501 Edge edge = node_data[n].first;
1503 _kuratowski.set(edge, true);
1506 node = _ugraph.target(edge);
1507 while (!pertinent(node, embed_edge, merge_roots)) {
1508 edge = node_data[order_map[node]].first;
1509 if (_ugraph.target(edge) == pred) {
1510 edge = edge_lists[edge].next;
1512 _kuratowski.set(edge, true);
1514 node = _ugraph.target(edge);
1517 _kuratowski.set(embed_edge[node], true);
1520 void markPredPath(Node node, Node snode, PredMap& pred_map) {
1521 while (node != snode) {
1522 _kuratowski.set(pred_map[node], true);
1523 node = _ugraph.source(pred_map[node]);
1527 void markFacePath(Node ynode, Node xnode,
1528 OrderMap& order_map, NodeData& node_data) {
1529 Edge edge = node_data[order_map[ynode]].first;
1530 Node node = _ugraph.target(edge);
1531 _kuratowski.set(edge, true);
1533 while (node != xnode) {
1534 edge = node_data[order_map[node]].first;
1535 _kuratowski.set(edge, true);
1536 node = _ugraph.target(edge);
1540 void markInternalPath(std::vector<Edge>& path) {
1541 for (int i = 0; i < int(path.size()); ++i) {
1542 _kuratowski.set(path[i], true);
1546 void markPilePath(std::vector<Edge>& path) {
1547 for (int i = 0; i < int(path.size()); ++i) {
1548 _kuratowski.set(path[i], true);
1552 void isolateKuratowski(Edge edge, NodeData& node_data,
1553 EdgeLists& edge_lists, FlipMap& flip_map,
1554 OrderMap& order_map, OrderList& order_list,
1555 PredMap& pred_map, ChildLists& child_lists,
1556 AncestorMap& ancestor_map, LowMap& low_map,
1557 EmbedEdge& embed_edge, MergeRoots& merge_roots) {
1559 Node root = _ugraph.source(edge);
1560 Node enode = _ugraph.target(edge);
1562 int rorder = order_map[root];
1564 TypeMap type_map(_ugraph, 0);
1566 int rn = findComponentRoot(root, enode, child_lists,
1567 order_map, order_list);
1569 Node xnode = order_list[node_data[rn].next];
1570 Node ynode = order_list[node_data[rn].prev];
1574 while (!merge_roots[xnode].empty() || !merge_roots[ynode].empty()) {
1576 if (!merge_roots[xnode].empty()) {
1578 rn = merge_roots[xnode].front();
1581 rn = merge_roots[ynode].front();
1584 xnode = order_list[node_data[rn].next];
1585 ynode = order_list[node_data[rn].prev];
1588 if (root != _ugraph.source(edge)) {
1589 orientComponent(root, rn, order_map, pred_map,
1590 node_data, edge_lists, flip_map, type_map);
1591 markFacePath(root, root, order_map, node_data);
1592 int xlp = markExternalPath(xnode, order_map, child_lists,
1593 pred_map, ancestor_map, low_map);
1594 int ylp = markExternalPath(ynode, order_map, child_lists,
1595 pred_map, ancestor_map, low_map);
1596 markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
1597 Node lwnode = findPertinent(ynode, order_map, node_data,
1598 embed_edge, merge_roots);
1600 markPertinentPath(lwnode, order_map, node_data, edge_lists,
1601 embed_edge, merge_roots);
1607 orientComponent(root, rn, order_map, pred_map,
1608 node_data, edge_lists, flip_map, type_map);
1610 Node wnode = findPertinent(ynode, order_map, node_data,
1611 embed_edge, merge_roots);
1612 setFaceFlags(root, wnode, ynode, xnode, order_map, node_data, type_map);
1616 if (!merge_roots[wnode].empty()) {
1617 int cn = merge_roots[wnode].back();
1618 Node rep = order_list[cn - order_list.size()];
1619 if (low_map[rep] < rorder) {
1620 markFacePath(root, root, order_map, node_data);
1621 int xlp = markExternalPath(xnode, order_map, child_lists,
1622 pred_map, ancestor_map, low_map);
1623 int ylp = markExternalPath(ynode, order_map, child_lists,
1624 pred_map, ancestor_map, low_map);
1626 Node lwnode, lznode;
1627 markCommonPath(wnode, rorder, lwnode, lznode, order_list,
1628 order_map, node_data, edge_lists, embed_edge,
1629 merge_roots, child_lists, ancestor_map, low_map);
1631 markPertinentPath(lwnode, order_map, node_data, edge_lists,
1632 embed_edge, merge_roots);
1633 int zlp = markExternalPath(lznode, order_map, child_lists,
1634 pred_map, ancestor_map, low_map);
1636 int minlp = xlp < ylp ? xlp : ylp;
1637 if (zlp < minlp) minlp = zlp;
1639 int maxlp = xlp > ylp ? xlp : ylp;
1640 if (zlp > maxlp) maxlp = zlp;
1642 markPredPath(order_list[maxlp], order_list[minlp], pred_map);
1648 Node pxnode, pynode;
1649 std::vector<Edge> ipath;
1650 findInternalPath(ipath, wnode, root, type_map, order_map,
1651 node_data, edge_lists);
1652 setInternalFlags(ipath, type_map);
1653 pynode = _ugraph.source(ipath.front());
1654 pxnode = _ugraph.target(ipath.back());
1656 wnode = findPertinent(pynode, order_map, node_data,
1657 embed_edge, merge_roots);
1661 if (type_map[_ugraph.source(ipath.front())] == HIGHY) {
1662 if (type_map[_ugraph.target(ipath.back())] == HIGHX) {
1663 markFacePath(xnode, pxnode, order_map, node_data);
1665 markFacePath(root, xnode, order_map, node_data);
1666 markPertinentPath(wnode, order_map, node_data, edge_lists,
1667 embed_edge, merge_roots);
1668 markInternalPath(ipath);
1669 int xlp = markExternalPath(xnode, order_map, child_lists,
1670 pred_map, ancestor_map, low_map);
1671 int ylp = markExternalPath(ynode, order_map, child_lists,
1672 pred_map, ancestor_map, low_map);
1673 markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
1677 if (type_map[_ugraph.target(ipath.back())] == HIGHX) {
1678 markFacePath(ynode, root, order_map, node_data);
1679 markPertinentPath(wnode, order_map, node_data, edge_lists,
1680 embed_edge, merge_roots);
1681 markInternalPath(ipath);
1682 int xlp = markExternalPath(xnode, order_map, child_lists,
1683 pred_map, ancestor_map, low_map);
1684 int ylp = markExternalPath(ynode, order_map, child_lists,
1685 pred_map, ancestor_map, low_map);
1686 markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
1691 std::vector<Edge> ppath;
1692 findPilePath(ppath, root, type_map, order_map, node_data, edge_lists);
1695 if (!ppath.empty()) {
1696 markFacePath(ynode, xnode, order_map, node_data);
1697 markPertinentPath(wnode, order_map, node_data, edge_lists,
1698 embed_edge, merge_roots);
1699 markPilePath(ppath);
1700 markInternalPath(ipath);
1701 int xlp = markExternalPath(xnode, order_map, child_lists,
1702 pred_map, ancestor_map, low_map);
1703 int ylp = markExternalPath(ynode, order_map, child_lists,
1704 pred_map, ancestor_map, low_map);
1705 markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
1712 if (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
1713 Node znode = findExternal(pynode, rorder, order_map,
1714 child_lists, ancestor_map,
1715 low_map, node_data);
1717 if (type_map[znode] == LOWY) {
1718 markFacePath(root, xnode, order_map, node_data);
1719 markPertinentPath(wnode, order_map, node_data, edge_lists,
1720 embed_edge, merge_roots);
1721 markInternalPath(ipath);
1722 int xlp = markExternalPath(xnode, order_map, child_lists,
1723 pred_map, ancestor_map, low_map);
1724 int zlp = markExternalPath(znode, order_map, child_lists,
1725 pred_map, ancestor_map, low_map);
1726 markPredPath(root, order_list[xlp < zlp ? xlp : zlp], pred_map);
1728 markFacePath(ynode, root, order_map, node_data);
1729 markPertinentPath(wnode, order_map, node_data, edge_lists,
1730 embed_edge, merge_roots);
1731 markInternalPath(ipath);
1732 int ylp = markExternalPath(ynode, order_map, child_lists,
1733 pred_map, ancestor_map, low_map);
1734 int zlp = markExternalPath(znode, order_map, child_lists,
1735 pred_map, ancestor_map, low_map);
1736 markPredPath(root, order_list[ylp < zlp ? ylp : zlp], pred_map);
1741 int xlp = markExternalPath(xnode, order_map, child_lists,
1742 pred_map, ancestor_map, low_map);
1743 int ylp = markExternalPath(ynode, order_map, child_lists,
1744 pred_map, ancestor_map, low_map);
1745 int wlp = markExternalPath(wnode, order_map, child_lists,
1746 pred_map, ancestor_map, low_map);
1748 if (wlp > xlp && wlp > ylp) {
1749 markFacePath(root, root, order_map, node_data);
1750 markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
1754 markInternalPath(ipath);
1755 markPertinentPath(wnode, order_map, node_data, edge_lists,
1756 embed_edge, merge_roots);
1758 if (xlp > ylp && xlp > wlp) {
1759 markFacePath(root, pynode, order_map, node_data);
1760 markFacePath(wnode, xnode, order_map, node_data);
1761 markPredPath(root, order_list[ylp < wlp ? ylp : wlp], pred_map);
1765 if (ylp > xlp && ylp > wlp) {
1766 markFacePath(pxnode, root, order_map, node_data);
1767 markFacePath(ynode, wnode, order_map, node_data);
1768 markPredPath(root, order_list[xlp < wlp ? xlp : wlp], pred_map);
1772 if (pynode != ynode) {
1773 markFacePath(pxnode, wnode, order_map, node_data);
1775 int minlp = xlp < ylp ? xlp : ylp;
1776 if (wlp < minlp) minlp = wlp;
1778 int maxlp = xlp > ylp ? xlp : ylp;
1779 if (wlp > maxlp) maxlp = wlp;
1781 markPredPath(order_list[maxlp], order_list[minlp], pred_map);
1785 if (pxnode != xnode) {
1786 markFacePath(wnode, pynode, order_map, node_data);
1788 int minlp = xlp < ylp ? xlp : ylp;
1789 if (wlp < minlp) minlp = wlp;
1791 int maxlp = xlp > ylp ? xlp : ylp;
1792 if (wlp > maxlp) maxlp = wlp;
1794 markPredPath(order_list[maxlp], order_list[minlp], pred_map);
1798 markFacePath(root, root, order_map, node_data);
1799 int minlp = xlp < ylp ? xlp : ylp;
1800 if (wlp < minlp) minlp = wlp;
1801 markPredPath(root, order_list[minlp], pred_map);