1 /** \file
2  * \brief Declaration of classes InOutPoint and IOPoints which
3  * implement the management of in-/out-points
4  *
5  * \author Carsten Gutwenger
6  *
7  * \par License:
8  * This file is part of the Open Graph Drawing Framework (OGDF).
9  *
10  * \par
11  * Copyright (C)<br>
12  * See README.md in the OGDF root directory for details.
13  *
14  * \par
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * Version 2 or 3 as published by the Free Software Foundation;
18  * see the file LICENSE.txt included in the packaging of this file
19  * for details.
20  *
21  * \par
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * \par
28  * You should have received a copy of the GNU General Public
29  * License along with this program; if not, see
30  * http://www.gnu.org/copyleft/gpl.html
31  */
32 
33 #pragma once
34 
35 #include <ogdf/planarity/PlanRep.h>
36 
37 
38 namespace ogdf {
39 
40 
41 //! Representation of an in- or outpoint
42 struct InOutPoint
43 {
44 	int  m_dx, m_dy;
45 	adjEntry m_adj;
46 
InOutPointInOutPoint47 	InOutPoint() {
48 		m_dx = m_dy = 0; m_adj = nullptr;
49 	}
InOutPointInOutPoint50 	explicit InOutPoint(adjEntry adj) {
51 		m_adj = adj; m_dx = m_dy = 0;
52 	}
53 };
54 
55 
56 //! Representation of in- and outpoint lists
57 class IOPoints {
58 public:
IOPoints()59 	IOPoints() { }
IOPoints(const Graph & G)60 	explicit IOPoints(const Graph &G) : m_depth(G,0), m_height(G,0), m_in(G), m_out(G),
61 		m_mark(G,false), m_pointOf(G,nullptr)  { }
62 
~IOPoints()63 	~IOPoints () { }
64 
65 
66 	// length of in- or outpoint list
out(node v)67 	int out(node v) const {
68 		return m_out[v].size();
69 	}
in(node v)70 	int in(node v) const {
71 		return m_in[v].size();
72 	}
73 
74 	// getting a const-reference to in- or outpoint list
inpoints(node v)75 	const List<InOutPoint> &inpoints(node v) const {
76 		return m_in [v];
77 	}
inpoints(node v)78 	List<InOutPoint> &inpoints(node v) {
79 		return m_in [v];
80 	}
81 
outpoints(node v)82 	const List<InOutPoint> &outpoints(node v) const {
83 		return m_out [v];
84 	}
outpoints(node v)85 	List<InOutPoint> &outpoints(node v) {
86 		return m_out [v];
87 	}
88 
89 	// getting the in-/outpoint belonging to an adjacency entry
pointOf(adjEntry adj)90 	const InOutPoint *pointOf(adjEntry adj) const {
91 		return m_pointOf[adj];
92 	}
93 
94 	// marking adjacency entries
marked(adjEntry adj)95 	bool marked(adjEntry adj) const {
96 		return m_mark[adj];
97 	}
98 
marked(node v)99 	bool marked(node v) {
100 		return v->outdeg() == 1 && marked(v->firstAdj());
101 	}
102 
103 	// finding outpoints belonging to non-marked edges
firstRealOut(node v)104 	ListConstIterator<InOutPoint> firstRealOut(node v) const {
105 		return searchRealForward(m_out[v].begin());
106 	}
107 
lastRealOut(node v)108 	ListConstIterator<InOutPoint> lastRealOut(node v) const {
109 		return searchRealBackward(m_out[v].rbegin());
110 	}
111 
nextRealOut(ListConstIterator<InOutPoint> it)112 	ListConstIterator<InOutPoint> nextRealOut(ListConstIterator<InOutPoint> it) const {
113 		return searchRealForward(it.succ());
114 	}
115 
prevRealOut(ListConstIterator<InOutPoint> it)116 	ListConstIterator<InOutPoint> prevRealOut(ListConstIterator<InOutPoint> it) const {
117 		return searchRealBackward(it.pred());
118 	}
119 
120 	// building in-/outpoint lists
appendInpoint(adjEntry adj)121 	void appendInpoint(adjEntry adj) {
122 		node v = adj->theNode();
123 		m_pointOf[adj] = &(*m_in[v].pushBack(InOutPoint(adj)));
124 	}
appendOutpoint(adjEntry adj)125 	void appendOutpoint(adjEntry adj) {
126 		node v = adj->theNode();
127 		m_pointOf[adj] = &(*m_out[v].pushBack(InOutPoint(adj)));
128 	}
pushInpoint(adjEntry adj)129 	void pushInpoint(adjEntry adj) {
130 		node v = adj->theNode();
131 		m_pointOf[adj] = &(*m_in[v].pushFront(InOutPoint(adj)));
132 	}
133 
134 	// setting relative coordinates
setOutCoord(ListIterator<InOutPoint> it,int dx,int dy)135 	void setOutCoord (ListIterator<InOutPoint> it, int dx, int dy) {
136 		(*it).m_dx = dx;
137 		(*it).m_dy = dy;
138 	}
setInCoord(ListIterator<InOutPoint> it,int dx,int dy)139 	void setInCoord (ListIterator<InOutPoint> it, int dx, int dy) {
140 		(*it).m_dx = dx;
141 		(*it).m_dy = dy;
142 	}
143 
setOutDx(ListIterator<InOutPoint> it,int dx)144 	void setOutDx(ListIterator<InOutPoint> it, int dx) {
145 		(*it).m_dx = dx;
146 	}
147 
148 	void restoreDeg1Nodes(PlanRep &PG, ArrayBuffer<PlanRep::Deg1RestoreInfo> &S);
149 
changeEdge(node v,adjEntry adj_new)150 	void changeEdge(node v, adjEntry adj_new) {
151 		m_out[v].popBack();
152 		appendInpoint(adj_new);
153 	}
154 
155 	// belongs v to a chain (= at most to non-marked incoming edges
isChain(node v)156 	bool isChain(node v) const {
157 		int i = 0;
158 		for(const InOutPoint &iop : m_in[v])
159 			if (!marked(iop.m_adj)) ++i;
160 		return i <= 2;
161 	}
162 
163 	// width of the left-/right side of an in-/outpoint list
outLeft(node v)164 	int outLeft(node v) const {
165 		return (m_out[v].empty()) ? 0 : (-m_out[v].front().m_dx);
166 	}
167 
outRight(node v)168 	int outRight(node v) const {
169 		return (m_out[v].empty()) ? 0 : (m_out[v].back().m_dx);
170 	}
171 
inLeft(node v)172 	int inLeft(node v) const {
173 		return (m_in[v].empty()) ? 0 : (-m_in[v].front().m_dx);
174 	}
175 
inRight(node v)176 	int inRight(node v) const {
177 		return (m_in[v].empty()) ? 0 : (m_in[v].back().m_dx);
178 	}
179 
maxLeft(node v)180 	int maxLeft(node v) const {
181 		return max(inLeft(v), outLeft(v));
182 	}
183 
maxRight(node v)184 	int maxRight(node v) const {
185 		return max(inRight(v), outRight(v));
186 	}
187 
maxPlusLeft(node v)188 	int maxPlusLeft(node v) const {
189 		return (in(v) >= 3) ?
190 			max(inLeft(v)+1, outLeft(v)) : maxLeft(v);
191 	}
192 
maxPlusRight(node v)193 	int maxPlusRight(node v) const {
194 		return (in(v) >= 3) ?
195 			max(inRight(v)+1, outRight(v)) : maxRight(v);
196 	}
197 
198 	InOutPoint middleNeighbor(node z1) const;
199 
200 	void numDeg1(node v, int &xl, int &xr,
201 		bool doubleCount) const;
202 
203 	adjEntry switchBeginIn(node v);
204 	adjEntry switchEndIn  (node v);
205 
206 	void switchBeginOut(node v);
207 	void switchEndOut  (node v);
208 
209 
210 	NodeArray<int> m_depth, m_height;
211 
212 
213 private:
214 	NodeArray<List<InOutPoint> > m_in, m_out;
215 	AdjEntryArray<bool> m_mark;
216 	AdjEntryArray<InOutPoint *> m_pointOf;
217 
218 	ListConstIterator<InOutPoint> searchRealForward (ListConstIterator<InOutPoint> it) const;
219 	ListConstIterator<InOutPoint> searchRealBackward(ListConstIterator<InOutPoint> it) const;
220 };
221 
222 }
223