1 /** \file
2 * \brief Implementation of class UniformGrid
3 *
4 * \author Rene Weiskircher
5 *
6 * \par License:
7 * This file is part of the Open Graph Drawing Framework (OGDF).
8 *
9 * \par
10 * Copyright (C)<br>
11 * See README.md in the OGDF root directory for details.
12 *
13 * \par
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * Version 2 or 3 as published by the Free Software Foundation;
17 * see the file LICENSE.txt included in the packaging of this file
18 * for details.
19 *
20 * \par
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * \par
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, see
29 * http://www.gnu.org/copyleft/gpl.html
30 */
31
32 #include <ogdf/energybased/davidson_harel/UniformGrid.h>
33
34 namespace ogdf {
35 namespace davidson_harel {
36
37 const double UniformGrid::m_epsilon = 0.000001;
38 const double UniformGrid::m_edgeMultiplier = 1.0;
39
40 #if 0
41 int UniformGrid::constructorcounter = 0;
42 #endif
43
ModifiedBresenham(const IPoint & p1,const IPoint & p2,SList<IPoint> & crossedCells) const44 void UniformGrid::ModifiedBresenham(
45 const IPoint &p1,
46 const IPoint &p2,
47 SList<IPoint> &crossedCells) const
48 {
49 crossedCells.clear();
50
51 int Ax = p1.m_x;
52 int Ay = p1.m_y;
53 int Bx = p2.m_x;
54 int By = p2.m_y;
55 // INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT AFFECTED BY THE
56 // SLOPE OR DIRECTION OF THE LINE
57 int dX = abs(Bx-Ax); // store the change in X and Y of the line endpoints
58 int dY = abs(By-Ay);
59
60 // DETERMINE "DIRECTIONS" TO INCREMENT X AND Y (REGARDLESS OF DECISION)
61 int Xincr, Yincr,Xoffset,Yoffset;
62 if (Ax > Bx) { Xincr=-1; Xoffset = -1;} else { Xincr=1; Xoffset = 0;} // which direction in X?
63 if (Ay > By) { Yincr=-1; Yoffset = -1;} else { Yincr=1; Yoffset = 0;} // which direction in Y?
64 // the offsets are necessary because we always want the cell left and below
65 // the point were bresenham wants to draw it
66
67 // DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS INCREMENTS BY 1 (OR -1) )
68 // AND INITIATE APPROPRIATE LINE DRAWING ROUTINE (BASED ON FIRST OCTANT
69 // ALWAYS). THE X AND Y'S MAY BE FLIPPED IF Y IS THE INDEPENDENT VARIABLE.
70 if (dX >= dY) // if X is the independent variable
71 {
72 int dPr = dY<<1; // amount to increment decision if right is chosen (always)
73 int dPru = dPr - (dX<<1); // amount to increment decision if up is chosen
74 int P = dPr - dX; // decision variable start value
75 int secondY = Ay+Yincr; //Y-coordinate of secondary point
76 int testval = P; //if P is equal to testval, the the next point is drawn exactly on the segment. If P is smaller than testval, it is below the segment
77
78 for (; dX>=0; dX--) // process each point in the line one at a time (just use dX)
79 {
80 crossedCells.pushBack(IPoint(Ax+Xoffset,Ay+Yoffset));//add the primary cell
81 crossedCells.pushBack(IPoint(Ax+Xoffset,secondY+Yoffset));//add the secondary cell
82 if (P > 0) // is the pixel going right AND up?
83 {
84 Ax+=Xincr; // increment independent variable
85 Ay+=Yincr; // increment dependent variable
86 P+=dPru; // increment decision (for up)
87 }
88 else // is the pixel just going right?
89 {
90 Ax+=Xincr; // increment independent variable
91 P+=dPr; // increment decision (for right)
92 }
93 if(P - testval < 0) //primary cell above the line
94 secondY = Ay-Yincr;
95 else secondY = Ay+Yincr;//primary cell below the line
96 }
97 }
98 else // if Y is the independent variable
99 {
100 int dPr = dX<<1; // amount to increment decision if right is chosen (always)
101 int dPru = dPr - (dY<<1); // amount to increment decision if up is chosen
102 int P = dPr - dY; // decision variable start value
103 int testval = P; // substracting this from P tells us if the cell is drawn left or
104 // right from the actual segment
105 int secondX = Ax+Xincr; //X-Coordinate of secondary cell
106
107 for (; dY>=0; dY--) // process each point in the line one at a time (just use dY)
108 {
109 crossedCells.pushBack(IPoint(Ax+Xoffset,Ay+Yoffset));// add the primary cell
110 crossedCells.pushBack(IPoint(secondX+Xoffset,Ay+Yoffset));// add the secondary cell
111 if (P > 0) // is the pixel going up AND right?
112 {
113 Ax+=Xincr; // increment dependent variable
114 Ay+=Yincr; // increment independent variable
115 P+=dPru; // increment decision (for up)
116 }
117 else // is the pixel just going up?
118 {
119 Ay+=Yincr; // increment independent variable
120 P+=dPr; // increment decision (for right)
121 }
122 if(P - testval < 0) //primary cell left of the line
123 secondX = Ax-Xincr;
124 else secondX = Ax+Xincr;//primary cell right of the line
125 }
126 }
127 }
128
DoubleModifiedBresenham(const DPoint & p1,const DPoint & p2,SList<IPoint> & crossedCells) const129 void UniformGrid::DoubleModifiedBresenham(
130 const DPoint &p1,
131 const DPoint &p2,
132 SList<IPoint> &crossedCells) const
133 {
134 crossedCells.clear();
135 // INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT AFFECTED BY THE
136 // SLOPE OR DIRECTION OF THE LINE
137 double dX = fabs(p2.m_x-p1.m_x); // store the change in X and Y of the line endpoints
138 double dY = fabs(p1.m_y-p2.m_y);
139
140
141 // DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS INCREMENTS BY 1 (OR -1) )
142 // AND INITIATE APPROPRIATE LINE DRAWING ROUTINE (BASED ON FIRST OCTANT
143 // ALWAYS). THE X AND Y'S MAY BE FLIPPED IF Y IS THE INDEPENDENT VARIABLE.
144 if (dX >= dY) // if X is the independent variable
145 {
146 DPoint left,right;
147 if(p1.m_x > p2.m_x) {
148 left = p2;
149 right = p1;
150 }
151 else {
152 left = p1;
153 right= p2;
154 }
155 //Now we determine the coordinates of the start cell
156 //and the end cell
157 IPoint start(computeGridPoint(left));
158 if(p1 == p2) {
159 crossedCells.pushBack(start);
160 return;
161 }
162 IPoint end(computeGridPoint(right));
163 //Since computeGridPoint rounds down, this gives us the point p1 and
164 //below each of the points. This is the address of the cell that contains
165 //the point
166 #if 0
167 int Yincr = 1;
168 if(left.m_y > right.m_y) Yincr = -1;
169 #endif
170 double slope = (right.m_y-left.m_y)/(right.m_x-left.m_x);
171 double c = left.m_y-slope*left.m_x;
172 OGDF_ASSERT(fabs(slope*right.m_x+c - right.m_y) < m_epsilon);
173 int endX = end.m_x+1;
174 double dYincr = slope * m_CellSize;
175 double OldYPos = slope*start.m_x*m_CellSize+c;
176 int oldY = (int)floor(OldYPos/m_CellSize);
177 for(int i = start.m_x; i <= endX; i++) {
178 crossedCells.pushBack(IPoint(i,oldY));
179 double newY = OldYPos + dYincr;
180 OGDF_ASSERT(newY - ((i+1)*m_CellSize*slope+c) < m_epsilon);
181 int newCellY = (int)floor(newY/m_CellSize);
182 if(newCellY != oldY) {
183 oldY = newCellY;
184 crossedCells.pushBack(IPoint(i,oldY));
185 }
186 OldYPos = newY;
187 }
188 }
189 else // if Y is the independent variable
190 {
191 DPoint bottom,top;
192 if(p1.m_y > p2.m_y) {
193 bottom = p2;
194 top = p1;
195 }
196 else {
197 bottom = p1;
198 top = p2;
199 }
200 IPoint start(computeGridPoint(bottom));
201 IPoint end(computeGridPoint(top));
202 #if 0
203 int Xincr = 1;
204 if(bottom.m_x > top.m_x) Xincr = -1;
205 #endif
206 double slope = (top.m_x-bottom.m_x)/(top.m_y-bottom.m_y);
207 double c = bottom.m_x-slope*bottom.m_y;
208 OGDF_ASSERT(fabs(slope*top.m_y+c - top.m_x) < m_epsilon);
209 int endY = end.m_y+1;
210 double dXincr = slope * m_CellSize;
211 double OldXPos = slope*start.m_y*m_CellSize+c;
212 int oldX = (int)floor(OldXPos/m_CellSize);
213 for(int i = start.m_y; i <= endY; i++) {
214 crossedCells.pushBack(IPoint(oldX,i));
215 double newX = OldXPos + dXincr;
216 OGDF_ASSERT(newX - ((i+1)*m_CellSize*slope+c) < m_epsilon);
217 int newCellX = (int)floor(newX/m_CellSize);
218 if(newCellX != oldX) {
219 oldX = newCellX;
220 crossedCells.pushBack(IPoint(oldX,i));
221 }
222 OldXPos = newX;
223 }
224 }
225 }
226
227 //constructor for computing the grid and the crossings from scratch for the
228 //layout given by AG
UniformGrid(const GraphAttributes & AG)229 UniformGrid::UniformGrid(const GraphAttributes &AG) :
230 m_layout(AG),
231 m_graph(AG.constGraph()),
232 m_crossings(m_graph),
233 m_cells(m_graph),
234 m_CellSize(0.0),
235 m_crossNum(0)
236 {
237 #if 0
238 std::cout<<"New grid \n";
239 #endif
240 node v = m_graph.firstNode();
241 DPoint pos(m_layout.x(v),m_layout.y(v));
242 #ifdef OGDF_DEBUG
243 m_crossingTests = 0;
244 m_maxEdgesPerCell = 0;
245 usedTime(m_time);
246 #endif
247 DIntersectableRect ir;
248 computeGridGeometry(v,pos,ir);
249 double maxLength = max(ir.height(),ir.width());
250 m_CellSize = maxLength/(m_edgeMultiplier*(m_graph).numberOfEdges());
251 List<edge> list;
252 m_graph.allEdges(list);
253 computeCrossings(list, v, pos);
254 #ifdef OGDF_DEBUG
255 m_time = usedTime(m_time);
256 #endif
257 }
258
259 //constructor for computing the grid and the crossings from scratch for
260 //the given layout where node v is moved to newPos
UniformGrid(const GraphAttributes & AG,const node v,const DPoint & newPos)261 UniformGrid::UniformGrid(
262 const GraphAttributes &AG,
263 const node v,
264 const DPoint& newPos)
265 :
266 m_layout(AG),
267 m_graph(AG.constGraph()),
268 m_crossings(m_graph),
269 m_cells(m_graph),
270 m_CellSize(0.0),
271 m_crossNum(0)
272 {
273 #ifdef OGDF_DEBUG
274 m_crossingTests = 0;
275 m_maxEdgesPerCell = 0;
276 usedTime(m_time);
277 #endif
278 DIntersectableRect ir;
279 computeGridGeometry(v,newPos,ir);
280 double maxLength = max(ir.height(),ir.width());
281 m_CellSize = maxLength/(m_edgeMultiplier*(m_graph).numberOfEdges());
282 List<edge> list;
283 m_graph.allEdges(list);
284 computeCrossings(list, v, newPos);
285 #ifdef OGDF_DEBUG
286 m_time = usedTime(m_time);
287 #endif
288 }
289
290 //constructor for computing an updated grid for a given grid where one
291 //vertex is moved to a new position
UniformGrid(const UniformGrid & ug,const node v,const DPoint & newPos)292 UniformGrid::UniformGrid(
293 const UniformGrid &ug,
294 const node v,
295 const DPoint& newPos) :
296 m_layout(ug.m_layout),
297 m_graph(ug.m_graph),
298 m_grid(ug.m_grid),
299 m_crossings(ug.m_crossings),
300 m_cells(ug.m_cells),
301 m_CellSize(ug.m_CellSize),
302 m_crossNum(ug.m_crossNum)
303 {
304 //constructorcounter++;
305 #ifdef OGDF_DEBUG
306 m_crossingTests = 0;
307 m_maxEdgesPerCell = 0;
308 usedTime(m_time);
309 DIntersectableRect ir;
310 computeGridGeometry(v,newPos,ir);
311 double size = max(ir.width(),ir.height());
312 size /= m_graph.numberOfEdges() * m_edgeMultiplier;
313 OGDF_ASSERT(size > 0.5*m_CellSize);
314 OGDF_ASSERT(size < 2.0*m_CellSize);
315 #endif
316 //compute the list of edge incident to v
317 List<edge> incident;
318 v->adjEdges(incident);
319 //set the crossings of all these edges to zero, update the global crossing
320 //number, remove them from their cells. Note that we cannot insert the edge
321 //with its new position into the grid in the same loop because we may get
322 //crossings with other edges incident to v
323 for(edge e : incident) {
324 //we clear the list of crossings of e and delete e from the
325 //crossings lists of all the edges it crosses
326 List<edge>& c = m_crossings[e];
327 while(!c.empty()) {
328 edge crossed = c.popFrontRet();
329 List<edge>& cl = m_crossings[crossed];
330 ListIterator<edge> it2 = cl.begin();
331 while(*it2 != e) ++it2;
332 cl.del(it2);
333 m_crossNum--;
334 }
335 List<IPoint>& cells = m_cells[e];
336 //delete e from all its cells
337 while(!cells.empty()) {
338 IPoint p = cells.popFrontRet();
339 List<edge>& eList = m_grid(p.m_x,p.m_y);
340 ListIterator<edge> it2 = eList.begin();
341 while(*it2 != e) ++it2;
342 eList.del(it2);
343 }
344 }
345 // at this point, all the data structures look as if the edges in the
346 //list incident where not present. Now we reinsert the edges into the
347 //grid with their new positions and update the crossings
348 computeCrossings(incident,v,newPos);
349 #ifdef OGDF_DEBUG
350 m_time = usedTime(m_time);
351 #endif
352 }
353
354
computeGridGeometry(const node moved,const DPoint & newPos,DIntersectableRect & ir) const355 void UniformGrid::computeGridGeometry(
356 const node moved,
357 const DPoint& newPos,
358 DIntersectableRect& ir) const
359 {
360 //first we compute the resolution and size of the grid
361 double
362 minX = std::numeric_limits<double>::max(),
363 minY = std::numeric_limits<double>::max(),
364 maxX = std::numeric_limits<double>::lowest(),
365 maxY = std::numeric_limits<double>::lowest();
366
367 //find lower left and upper right vertex
368 for(node v : m_graph.nodes) {
369 double x, y;
370 if(v != moved) {// v is the node that was moved
371 x = m_layout.x(v);
372 y = m_layout.y(v);
373 }
374 else {// v is not the moved node
375 x = newPos.m_x;
376 y = newPos.m_y;
377 }
378 if(x < minX) minX = x;
379 if(x > maxX) maxX = x;
380 if(y < minY) minY = y;
381 if(y > maxY) maxY = y;
382 }
383 ir = DIntersectableRect(minX,minY,maxX,maxY);
384 }
385
386
computeCrossings(const List<edge> & toInsert,const node moved,const DPoint & newPos)387 void UniformGrid::computeCrossings(
388 const List<edge>& toInsert,
389 const node moved,
390 const DPoint& newPos)
391 {
392 //now we compute all the remaining data of the class in one loop
393 //going through all edges and storing them in the grid.
394 for (edge e : toInsert)
395 {
396 SList<IPoint> crossedCells;
397 DPoint sPos, tPos;
398 const node& s = e->source();
399 if (s != moved) sPos = m_layout.point(s);
400 else sPos = newPos;
401 const node& t = e->target();
402 if (t != moved) tPos = m_layout.point(t);
403 else tPos = newPos;
404 DoubleModifiedBresenham(sPos, tPos, crossedCells);
405 for (const IPoint &p : crossedCells) {
406 m_cells[e].pushBack(p);
407 List<edge>& edgeList = m_grid(p.m_x, p.m_y);
408 if (!edgeList.empty()) { //there are already edges in that list
409 OGDF_ASSERT(!edgeList.empty());
410 for (edge e2 : edgeList) {
411 if (crossingTest(e, e2, moved, newPos, p)) { //two edges cross in p
412 ++m_crossNum;
413 m_crossings[e].pushBack(e2);
414 m_crossings[e2].pushBack(e);
415 }
416 }
417 }
418 //now we insert the new edge into the list and store the position
419 //returned by pushBack in the corresponding list of m_storedIn
420 edgeList.pushBack(e);
421 #ifdef OGDF_DEBUG
422 if (m_maxEdgesPerCell < edgeList.size())
423 m_maxEdgesPerCell = edgeList.size();
424 #endif
425 }
426 }
427 #ifdef OGDF_DEBUG
428 int sumCros = 0;
429 for (edge e : m_graph.edges)
430 sumCros += m_crossings[e].size();
431 OGDF_ASSERT((sumCros >> 1) == m_crossNum);
432 #endif
433 }
434
435
436 //returns true if both edges are not adjacent and cross inside the given cell
crossingTest(const edge e1,const edge e2,const node moved,const DPoint & newPos,const IPoint & cell)437 bool UniformGrid::crossingTest(
438 const edge e1,
439 const edge e2,
440 const node moved,
441 const DPoint& newPos,
442 const IPoint& cell)
443 {
444 bool crosses = false;
445 node s1 = e1->source(), t1 = e1->target();
446 node s2 = e2->source(), t2 = e2->target();
447 if(s1 != s2 && s1 != t2 && t1 != s2 && t1 != t2) {//not adjacent
448 double xLeft = cell.m_x*m_CellSize;
449 double xRight = (cell.m_x+1)*m_CellSize;
450 double xBottom = cell.m_y*m_CellSize;
451 double xTop = (cell.m_y+1)*m_CellSize;
452 DPoint ps1,pt1,ps2,pt2;
453 if(s1 != moved) ps1 = m_layout.point(s1);
454 else ps1 = newPos;
455 if(t1 != moved) pt1 = m_layout.point(t1);
456 else pt1 = newPos;
457 if(s2 != moved) ps2 = m_layout.point(s2);
458 else ps2 = newPos;
459 if(t2 != moved) pt2 = m_layout.point(t2);
460 else pt2 = newPos;
461 DSegment l1(ps1,pt1),l2(ps2,pt2);
462 DPoint crossPoint;
463 #ifdef OGDF_DEBUG
464 m_crossingTests++;
465 #endif
466 // TODO: What to do when IntersectionType::Overlapping is returned?
467 if (l1.intersection(l2,crossPoint) == IntersectionType::SinglePoint
468 && crossPoint.m_x >= xLeft
469 && crossPoint.m_x < xRight
470 && crossPoint.m_y >= xBottom
471 && crossPoint.m_y < xTop) {
472 crosses = true;
473 }
474 }
475 return crosses;
476 }
477
478 #ifdef OGDF_DEBUG
479
markCells(SList<IPoint> & result,Array2D<bool> & cells) const480 void UniformGrid::markCells(SList<IPoint> &result, Array2D<bool> &cells) const {
481 while (!result.empty()) {
482 IPoint p = result.popFrontRet();
483 if (cells.low1() <= p.m_x && cells.high1() >= p.m_x
484 && cells.low2() <= p.m_y && cells.high2() >= p.m_y)
485 cells(p.m_x,p.m_y) = true;
486 }
487 }
488
489
checkBresenham(DPoint p1,DPoint p2) const490 void UniformGrid::checkBresenham(DPoint p1, DPoint p2) const
491 {
492 int crossed = 0;
493 DPoint bottomleft(min(p1.m_x,p2.m_x),min(p1.m_y,p2.m_y));
494 DPoint topright(max(max(p1.m_x,p2.m_x),bottomleft.m_x+1.0),
495 max(max(p1.m_y,p2.m_y),bottomleft.m_y+1.0));
496 IPoint ibl(computeGridPoint(bottomleft));
497 IPoint itr(computeGridPoint(topright));
498 Array2D<bool> cells(ibl.m_x,itr.m_x+1,ibl.m_y,itr.m_y+1,false);
499 SList<IPoint> result;
500 DoubleModifiedBresenham(p1,p2,result);
501 std::cout << "\nList computed by Bresenham:\n";
502
503 for(const IPoint &p : result) {
504 std::cout << computeRealPoint(p) << " ";
505 }
506
507 markCells(result,cells);
508 std::cout << "\nCrossed cells:\n";
509 if(p1.m_x == p2.m_x) { //vertical segment
510 int cellXcoord = (int)floor(p1.m_x/m_CellSize);
511 double b = floor(min(p1.m_y,p2.m_y)/m_CellSize);
512 double t = ceil(max(p1.m_y,p2.m_y)/m_CellSize);
513 OGDF_ASSERT(isInt(b));
514 OGDF_ASSERT(isInt(t));
515 int intT = (int)t;
516 for(int i = int(b); i < intT; i++) {
517 crossed++;
518 IPoint p(cellXcoord,i);
519 std::cout << computeRealPoint(p) << " ";
520 if(!cells(p.m_x,p.m_y)) {
521 std::cout << "\nCell " << computeRealPoint(p) << " is not marked!";
522 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
523 }
524 }
525 }
526 else {
527 if(p1.m_y == p2.m_y) { //horizontal segment
528 double tmp = floor(p1.m_y/m_CellSize);
529 OGDF_ASSERT(isInt(tmp));
530 int cellYcoord = (int)tmp;
531 double left = floor(min(p1.m_x,p2.m_x)/m_CellSize);
532 double right = ceil(max(p1.m_x,p2.m_x)/m_CellSize);
533 OGDF_ASSERT(isInt(left));
534 OGDF_ASSERT(isInt(right));
535 int intR = int(right);
536 for(int i = int(left); i < intR; i++) {
537 crossed++;
538 IPoint p(i,cellYcoord);
539 std::cout << computeRealPoint(p) << " ";
540 if(!cells(p.m_x,p.m_y)) {
541 std::cout << "\nCell " << computeRealPoint(p) << " is not marked!";
542 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
543 }
544 }
545 }
546 else {
547 for(int i = cells.low1(); i <= cells.high1(); i++) {
548 for(int j = cells.low2(); j <= cells.high2(); j++) {
549 IPoint p(i,j);
550 if(crossesCell(p1,p2,p)) {
551 crossed++;
552 std::cout << computeRealPoint(p) << " ";
553 if(!cells(p.m_x,p.m_y)) {
554 std::cout << "\n Cell " << computeRealPoint(p) << " is not marked!";
555 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
556 }
557 }
558 }
559 }
560
561 }
562 }
563 if(crossed < max(fabs(p1.m_x-p2.m_x)/m_CellSize,fabs(p1.m_y-p2.m_y)/m_CellSize)) {
564 std::cout << "\nNot enough crossed cells for " << p1 << " " << p2 << "\n";
565 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
566 }
567 std::cout << "\n";
568
569 }
570
571
checkBresenham(IPoint p1,IPoint p2) const572 void UniformGrid::checkBresenham(IPoint p1, IPoint p2) const
573 {
574 int crossed = 0;
575 int left = min(p1.m_x,p2.m_x)-1;
576 int right = max(max(p1.m_x,p2.m_x),left+1);
577 int bottom = min(p1.m_y,p2.m_y)-1;
578 int top = max(max(p1.m_y,p2.m_y),bottom+1);
579 Array2D<bool> cells(left,right,bottom,top,false);
580 SList<IPoint> result;
581 ModifiedBresenham(p1,p2,result);
582 std::cout << "\nList computed by Bresenham:\n" << result;
583 markCells(result,cells);
584 std::cout << "\nCrossed cells:\n";
585 if(p1.m_x == p2.m_x) { //vertical segment
586 for(int i = min(p1.m_y,p2.m_y); i < max(p1.m_y,p2.m_y); i++) {
587 crossed++;
588 IPoint p(p1.m_x,i);
589 std::cout << p << " ";
590 if(!cells(p.m_x,p.m_y)) {
591 std::cout << "\nCell " << p << " is not marked!";
592 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
593 }
594 }
595 }
596 else {
597 if(p1.m_y == p2.m_y) { //horizontal segment
598 for(int i = min(p1.m_x,p2.m_x); i < max(p1.m_x,p2.m_x); i++) {
599 crossed++;
600 IPoint p(i,p1.m_y);
601 std::cout << p << " ";
602 if(!cells(i,p1.m_y)) {
603 std::cout << "\nCell " << p <<" is not marked!";
604 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
605 }
606 }
607 }
608 else {
609 for(int i = cells.low1(); i <= cells.high1(); i++) {
610 for(int j = cells.low2(); j <= cells.high2(); j++) {
611 IPoint p(i,j);
612 if(crossesCell(p1,p2,p)) {
613 crossed++;
614 std::cout << p << " ";
615 if(!cells(p.m_x,p.m_y)) {
616 std::cout << "\n Cell " << p << " is not marked!";
617 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
618 }
619 }
620 }
621 }
622
623 }
624 }
625 if(crossed < max(abs(p1.m_x-p2.m_x),abs(p1.m_y-p2.m_y))) {
626 std::cout << "\nNot enough crossed cells for " << p1 << " " << p2 << "\n";
627 OGDF_THROW_PARAM(AlgorithmFailureException, AlgorithmFailureCode::Unknown);
628 }
629 std::cout << "\n";
630
631 }
632
633
634 //the upper and left boundary does not belong to a cell
crossesCell(IPoint A,IPoint B,const IPoint & CellAdr) const635 bool UniformGrid::crossesCell(
636 IPoint A,
637 IPoint B,
638 const IPoint &CellAdr) const
639 {
640 return crossesCell(A, B,
641 CellAdr.m_x, CellAdr.m_x + 1,
642 CellAdr.m_y, CellAdr.m_y + 1,
643 CellAdr);
644 }
645
646 //the upper and left boundary does not belong to a cell
crossesCell(DPoint A,DPoint B,const IPoint & CellAdr) const647 bool UniformGrid::crossesCell(
648 DPoint A,
649 DPoint B,
650 const IPoint &CellAdr) const
651 {
652 double xLowCell = CellAdr.m_x * m_CellSize;
653 double yLowCell = CellAdr.m_y * m_CellSize;
654 return crossesCell(A, B,
655 xLowCell, xLowCell + m_CellSize,
656 yLowCell, yLowCell + m_CellSize,
657 CellAdr);
658 }
659
660
intervalIntersect(double a1,double a2,double cell1,double cell2) const661 bool UniformGrid::intervalIntersect(
662 double a1,
663 double a2,
664 double cell1,
665 double cell2) const
666 {
667 double epsilon = 0.000001;
668 bool intersect = true;
669 if(min(a1,a2)+epsilon >= max(cell1,cell2) || min(cell1,cell2)+epsilon >= max(a1,a2)) intersect = false;
670 return intersect;
671 }
672
673
operator <<(std::ostream & out,const UniformGrid & ug)674 std::ostream &operator<<(std::ostream &out, const UniformGrid &ug)
675 {
676 out << "\nGrid Size: " << ug.m_CellSize;
677 out << "\nEpsilon: " << ug.m_epsilon;
678 out << "\nEdge Multiplier: " << ug.m_edgeMultiplier;
679 out << "\nCrossing number: " << ug.m_crossNum;
680 #ifdef OGDF_DEBUG
681 out << "\nCrossing tests: " << ug.m_crossingTests;
682 out << "\nMax edges per cell: " << ug.m_maxEdgesPerCell;
683 out << "\nConstruction time: " << ug.m_time;
684 DIntersectableRect ir;
685 node v = ug.m_graph.firstNode();
686 ug.computeGridGeometry(v,ug.m_layout.point(v),ir);
687 double size = max(ir.width(),ir.height());
688 std::cout << "\nPreferred Cell Size: " << size / (ug.m_graph.numberOfEdges()*ug.m_edgeMultiplier);
689 #endif
690 return out;
691 }
692 #endif
693
694 }}
695