6 * $Date: 2012-07-06 11:39:38 +0200 (Fr, 06. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of Mixed-Model crossings beautifiers.
12 * \author Carsten Gutwenger
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
43 #include <ogdf/planarlayout/MMCBDoubleGrid.h>
44 #include <ogdf/planarlayout/MMCBLocalStretch.h>
50 //------------------------------------------------------------------
52 //------------------------------------------------------------------
54 void MMCBBase::insertBend(GridLayout
&gl
, edge e
, node v
, int x
, int y
)
56 if (v
== e
->target()) {
57 gl
.bends(e
).pushBack(IPoint(x
,y
));
59 gl
.bends(e
).pushFront(IPoint(x
,y
));
64 void MMCBBase::copyOn(int old_a
[] , int new_a
[])
66 for (int i
= 0; i
< 3; ++i
)
71 int MMCBBase::workOn(GridLayout
&gl
, node v
)
80 edge e
= adj
->theEdge();
82 IPolyline
&ip
= gl
.bends(e
);
83 int xc
= gl
.x(v
), yc
= gl
.y(v
);
84 int xxc
= gl
.x(v
), yyc
= gl
.y(v
);
87 if (ip
.size() < (1+add_l
) ) {
88 if (v
== e
->target()) {
89 xc
= gl
.x(e
->source());
90 yc
= gl
.y(e
->source());
92 xc
= gl
.x(e
->target());
93 yc
= gl
.y(e
->target());
97 if (v
== e
->target()) {
98 p
= *ip
.get(ip
.size()-add_l
-1);
100 p
= *ip
.get(1+add_l
-1);
106 } while((xc
== xxc
) && (yc
== yyc
));
110 else if (xc
== gl
.x(v
))
117 else if (yc
== gl
.y(v
))
128 for (int i
= 0; i
< 4 ; i
++)
131 ev
[i
][2] = 4 + ev
[i
][1] + 2;
133 } else if (ev
[i
][0] == 0) {
141 ev
[i
][2] = -ev
[i
][1]+2;
149 for (int i
= 0; (i
< 8) && (k
>= 0) ; i
++)
151 for (int j
= 0; j
< 4; j
++)
154 copyOn(ev
[j
],ew
[4-k
]);
162 //so now in ew the edges are in an order against the clock starting at position 0,1
164 int crossingCase
= 0;
166 ea
= ew
[2][2] - ew
[0][2];
169 eb
= ew
[3][2] - ew
[1][2];
173 // first case: there is an edge with angle of pi/2
174 // in this case i'm going to, well, cut this edge
179 // -- *ooooooo^ ==> -- / Ooo
186 if (ew
[2][2] - ew
[0][2] > 4) {
193 if (ew
[3][2] - ew
[1][2] > 4) {
201 // second case: both angles are 3pi/4, in this case
202 // i'm going to take both of them back with a row
213 } else if (ea
== 3) {
215 if (ew
[1][2]-ew
[0][2] >= 3) {
216 if (ew
[1][2]-ew
[0][2] == 3)
221 else if (ew
[2][2]-ew
[1][2] >= 3) {
223 if (ew
[2][2]-ew
[1][2] == 3)
227 } else if (ew
[3][2]-ew
[2][2] >= 3) {
229 if (ew
[3][2]-ew
[2][2] == 3)
235 if (ew
[3][2]-ew
[0][2] == 3)
241 // third case: one of the angles is 3pi/4 and the other one is pi
246 // --------*o------- ==> ---------X--------
253 if (ew
[1][2]-ew
[0][2] == 2) {
261 } else if (eb
== 3) {
262 if (ew
[2][2]-ew
[1][2] == 2) {
272 copyOn(ew
[(0+lw_add
) %4],ev
[0]);
273 copyOn(ew
[(1+lw_add
) %4],ev
[1]);
274 copyOn(ew
[(2+lw_add
) %4],ev
[2]);
275 copyOn(ew
[(3+lw_add
) %4],ev
[3]);
277 edge e0
= Lw
[(0+lw_add
) %4];
278 edge e1
= Lw
[(1+lw_add
) %4];
279 edge e2
= Lw
[(2+lw_add
) %4];
280 edge e3
= Lw
[(3+lw_add
) %4];
287 if ((ev
[0][0]*ev
[0][1] == 0) || (gl
.bends(e3
).size() > 0)) {
288 insertBend(gl
,e3
,v
,gl
.x(v
)-ev
[1][0],gl
.y(v
)-ev
[1][1]);
290 insertBend(gl
,e0
,v
,gl
.x(v
)+ev
[3][0],gl
.y(v
)+ev
[3][1]);
291 insertBend(gl
,e2
,v
,gl
.x(v
)-ev
[3][0],gl
.y(v
)-ev
[3][1]);
292 insertBend(gl
,e1
,v
,gl
.x(v
)+ev
[0][0]+ev
[3][0],gl
.y(v
)+ev
[0][1]+ev
[3][1]);
297 if (ev
[0][0]*ev
[0][1] != 0) {
298 insertBend(gl
,e0
,v
,gl
.x(v
)-ev
[2][0],gl
.y(v
)-ev
[2][1]);
299 insertBend(gl
,e1
,v
,gl
.x(v
)-ev
[3][0],gl
.y(v
)-ev
[3][1]);
301 gl
.x(v
) = gl
.x(v
)+ev
[2][0]-ev
[1][0];
302 gl
.y(v
) = gl
.y(v
)+ev
[2][1]-ev
[1][1];
303 if (ev
[2][0]-ev
[1][0] == 0) {
312 insertBend(gl
,e1
,v
,gl
.x(v
)-ev
[3][0],gl
.y(v
)-ev
[3][1]);
313 insertBend(gl
,e2
,v
,gl
.x(v
)-ev
[0][0],gl
.y(v
)-ev
[0][0]);
317 if (ev
[0][0]*ev
[0][1] == 0) {
320 int x_plus
= (ev
[0][0]+ev
[2][0]);
321 int y_plus
= (ev
[0][1]+ev
[2][1]);
322 insertBend(gl
,e0
,v
,old_x
+2*ev
[0][0],old_y
+2*ev
[0][1]);
323 insertBend(gl
,e2
,v
,old_x
+2*ev
[2][0],old_y
+2*ev
[2][1]);
324 insertBend(gl
,e1
,v
,old_x
,old_y
);
325 insertBend(gl
,e3
,v
,old_x
,old_y
);
326 gl
.x(v
) = old_x
+x_plus
;
327 gl
.y(v
) = old_y
+y_plus
;
333 gl
.x(v
) = gl
.x(v
)+ev
[1][0];
334 gl
.y(v
) = gl
.y(v
)+ev
[1][1];
335 insertBend(gl
,e3
,v
,old_x
,old_y
);
336 insertBend(gl
,e1
,v
,gl
.x(v
)+ev
[1][0],gl
.y(v
)+ev
[1][1]);
357 //------------------------------------------------------------------
359 //------------------------------------------------------------------
361 void MMCBDoubleGrid::doCall(const PlanRep
&PG
, GridLayout
&gl
, const List
<node
> &L
)
365 ListIterator
<IPoint
> it
;
366 for(it
= gl
.bends(e
).begin(); it
.valid(); ++it
) {
379 ListConstIterator
<node
> itV
;
380 for(itV
= L
.begin(); itV
.valid(); ++itV
)
385 //------------------------------------------------------------------
387 //------------------------------------------------------------------
389 void MMCBLocalStretch::doCall(const PlanRep
&PG
, GridLayout
&gl
, const List
<node
> &L
)
391 int max_x
= 0, max_y
= 0;
395 ListIterator
<IPoint
> it
;
396 for(it
= gl
.bends(e
).begin(); it
.valid(); ++it
) {
398 if (p
.m_x
> max_x
) max_x
= p
.m_x
;
399 if (p
.m_y
> max_y
) max_y
= p
.m_y
;
407 if (gl
.x(v
) > max_x
) max_x
= gl
.x(v
);
408 if (gl
.y(v
) > max_y
) max_y
= gl
.y(v
);
413 Array
<int> change_x(0,max_x
,1);
414 Array
<int> change_y(0,max_y
,1);
419 ListConstIterator
<node
> itV
;
420 for(itV
= L
.begin(); itV
.valid(); ++itV
) {
422 int val
= workOn(gl
,v
);
425 change_x
[(gl
.x(v
)+1)/2] = 0;
427 change_y
[(gl
.y(v
)+1)/2] = 0;
432 for (int i
= 1; i
<= max_x
; i
++) {
433 change_x
[i
] = change_x
[i
] + change_x
[i
-1];
436 for (int i
= 1; i
<= max_y
; i
++) {
437 change_y
[i
] = change_y
[i
] + change_y
[i
-1];
441 ListIterator
<IPoint
> it
;
442 for(it
= gl
.bends(e
).begin(); it
.valid(); ++it
) {
444 p
.m_x
= p
.m_x
- change_x
[(p
.m_x
+1)/2];
445 p
.m_y
= p
.m_y
- change_y
[(p
.m_y
+1)/2];
450 gl
.x(v
)=gl
.x(v
)-change_x
[(gl
.x(v
)+1)/2];
451 gl
.y(v
)=gl
.y(v
)-change_y
[(gl
.y(v
)+1)/2];
456 } // end namespace ogdf