6 * $Date: 2012-07-16 15:34:43 +0200 (Mo, 16. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of class UniformGrid
12 * \author Rene Weiskircher
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/internal/energybased/UniformGrid.h>
47 const double UniformGrid::m_epsilon
= 0.000001;
48 const double UniformGrid::m_edgeMultiplier
= 1.0;
50 // int UniformGrid::constructorcounter = 0;
52 void UniformGrid::ModifiedBresenham(
55 SList
<IPoint
> &crossedCells
) const{
62 //------------------------------------------------------------------------
63 // INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT AFFECTED BY THE
64 // SLOPE OR DIRECTION OF THE LINE
65 //------------------------------------------------------------------------
66 int dX
= abs(Bx
-Ax
); // store the change in X and Y of the line endpoints
69 //------------------------------------------------------------------------
70 // DETERMINE "DIRECTIONS" TO INCREMENT X AND Y (REGARDLESS OF DECISION)
71 //------------------------------------------------------------------------
72 int Xincr
, Yincr
,Xoffset
,Yoffset
;
73 if (Ax
> Bx
) { Xincr
=-1; Xoffset
= -1;} else { Xincr
=1; Xoffset
= 0;} // which direction in X?
74 if (Ay
> By
) { Yincr
=-1; Yoffset
= -1;} else { Yincr
=1; Yoffset
= 0;} // which direction in Y?
75 // the offsets are necessary because we always want the cell left and below
76 // the point were bresenham wants to draw it
78 //------------------------------------------------------------------------
79 // DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS INCREMENTS BY 1 (OR -1) )
80 // AND INITIATE APPROPRIATE LINE DRAWING ROUTINE (BASED ON FIRST OCTANT
81 // ALWAYS). THE X AND Y'S MAY BE FLIPPED IF Y IS THE INDEPENDENT VARIABLE.
82 //------------------------------------------------------------------------
83 if (dX
>= dY
) // if X is the independent variable
85 int dPr
= dY
<<1; // amount to increment decision if right is chosen (always)
86 int dPru
= dPr
- (dX
<<1); // amount to increment decision if up is chosen
87 int P
= dPr
- dX
; // decision variable start value
88 int secondY
= Ay
+Yincr
; //Y-coordinate of secondary point
89 int testval
= P
; //if P is equal to testval, the the next point is drawn exactly
90 // on the segment. If P is smaller than testval, it is below the
94 for (; dX
>=0; dX
--) // process each point in the line one at a time (just use dX)
96 crossedCells
.pushBack(IPoint(Ax
+Xoffset
,Ay
+Yoffset
));//add the primary cell
97 crossedCells
.pushBack(IPoint(Ax
+Xoffset
,secondY
+Yoffset
));//add the secondary cell
98 if (P
> 0) // is the pixel going right AND up?
100 Ax
+=Xincr
; // increment independent variable
101 Ay
+=Yincr
; // increment dependent variable
102 P
+=dPru
; // increment decision (for up)
104 else // is the pixel just going right?
106 Ax
+=Xincr
; // increment independent variable
107 P
+=dPr
; // increment decision (for right)
109 if(P
- testval
< 0) //primary cell above the line
111 else secondY
= Ay
+Yincr
;//primary cell below the line
114 else // if Y is the independent variable
116 int dPr
= dX
<<1; // amount to increment decision if right is chosen (always)
117 int dPru
= dPr
- (dY
<<1); // amount to increment decision if up is chosen
118 int P
= dPr
- dY
; // decision variable start value
119 int testval
= P
; // substracting this from P tells us if the cell is drawn left or
120 // right from the actual segment
121 int secondX
= Ax
+Xincr
; //X-Coordinate of secondary cell
123 for (; dY
>=0; dY
--) // process each point in the line one at a time (just use dY)
125 crossedCells
.pushBack(IPoint(Ax
+Xoffset
,Ay
+Yoffset
));// add the primary cell
126 crossedCells
.pushBack(IPoint(secondX
+Xoffset
,Ay
+Yoffset
));// add the secondary cell
127 if (P
> 0) // is the pixel going up AND right?
129 Ax
+=Xincr
; // increment dependent variable
130 Ay
+=Yincr
; // increment independent variable
131 P
+=dPru
; // increment decision (for up)
133 else // is the pixel just going up?
135 Ay
+=Yincr
; // increment independent variable
136 P
+=dPr
; // increment decision (for right)
138 if(P
- testval
< 0) //primary cell left of the line
140 else secondX
= Ax
+Xincr
;//primary cell right of the line
146 void UniformGrid::DoubleModifiedBresenham(
149 SList
<IPoint
> &crossedCells
) const{
150 crossedCells
.clear();
151 //------------------------------------------------------------------------
152 // INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT AFFECTED BY THE
153 // SLOPE OR DIRECTION OF THE LINE
154 //------------------------------------------------------------------------
155 double dX
= fabs(p2
.m_x
-p1
.m_x
); // store the change in X and Y of the line endpoints
156 double dY
= fabs(p1
.m_y
-p2
.m_y
);
159 //------------------------------------------------------------------------
160 // DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS INCREMENTS BY 1 (OR -1) )
161 // AND INITIATE APPROPRIATE LINE DRAWING ROUTINE (BASED ON FIRST OCTANT
162 // ALWAYS). THE X AND Y'S MAY BE FLIPPED IF Y IS THE INDEPENDENT VARIABLE.
163 //------------------------------------------------------------------------
164 if (dX
>= dY
) // if X is the independent variable
167 if(p1
.m_x
> p2
.m_x
) {
175 //Now we determine the coordinates of the start cell
177 IPoint
start(computeGridPoint(left
));
179 crossedCells
.pushBack(start
);
182 IPoint
end(computeGridPoint(right
));
183 //Since computeGridPoint rounds down, this gives us the point p1 and
184 //below each of the points. This is the address of the cell that contains
187 //if(left.m_y > right.m_y) Yincr = -1;
188 double slope
= (right
.m_y
-left
.m_y
)/(right
.m_x
-left
.m_x
);
189 double c
= left
.m_y
-slope
*left
.m_x
;
190 OGDF_ASSERT(fabs(slope
*right
.m_x
+c
- right
.m_y
) < m_epsilon
);
191 int endX
= end
.m_x
+1;
192 double dYincr
= slope
* m_CellSize
;
193 double OldYPos
= slope
*start
.m_x
*m_CellSize
+c
;
194 int oldY
= (int)floor(OldYPos
/m_CellSize
);
195 for(int i
= start
.m_x
; i
<= endX
; i
++) {
196 crossedCells
.pushBack(IPoint(i
,oldY
));
197 double newY
= OldYPos
+ dYincr
;
198 OGDF_ASSERT(newY
- ((i
+1)*m_CellSize
*slope
+c
) < m_epsilon
)
199 int newCellY
= (int)floor(newY
/m_CellSize
);
200 if(newCellY
!= oldY
) {
202 crossedCells
.pushBack(IPoint(i
,oldY
));
207 else // if Y is the independent variable
210 if(p1
.m_y
> p2
.m_y
) {
218 IPoint
start(computeGridPoint(bottom
));
219 IPoint
end(computeGridPoint(top
));
221 //if(bottom.m_x > top.m_x) Xincr = -1;
222 double slope
= (top
.m_x
-bottom
.m_x
)/(top
.m_y
-bottom
.m_y
);
223 double c
= bottom
.m_x
-slope
*bottom
.m_y
;
224 OGDF_ASSERT(fabs(slope
*top
.m_y
+c
- top
.m_x
) < m_epsilon
);
225 int endY
= end
.m_y
+1;
226 double dXincr
= slope
* m_CellSize
;
227 double OldXPos
= slope
*start
.m_y
*m_CellSize
+c
;
228 int oldX
= (int)floor(OldXPos
/m_CellSize
);
229 for(int i
= start
.m_y
; i
<= endY
; i
++) {
230 crossedCells
.pushBack(IPoint(oldX
,i
));
231 double newX
= OldXPos
+ dXincr
;
232 OGDF_ASSERT(newX
- ((i
+1)*m_CellSize
*slope
+c
) < m_epsilon
)
233 int newCellX
= (int)floor(newX
/m_CellSize
);
234 if(newCellX
!= oldX
) {
236 crossedCells
.pushBack(IPoint(oldX
,i
));
243 //constructor for computing the grid and the crossings from scratch for the
245 UniformGrid::UniformGrid(const GraphAttributes
&AG
) :
247 m_graph(AG
.constGraph()),
248 m_crossings(m_graph
),
253 //cout<<"New grid \n";
254 node v
= m_graph
.firstNode();
255 DPoint
pos(m_layout
.x(v
),m_layout
.y(v
));
258 m_maxEdgesPerCell
= 0;
261 IntersectionRectangle ir
;
262 computeGridGeometry(v
,pos
,ir
);
263 double maxLength
= max(ir
.height(),ir
.width());
264 m_CellSize
= maxLength
/(m_edgeMultiplier
*(m_graph
).numberOfEdges());
267 computeCrossings(L
,v
,pos
);
269 m_time
= usedTime(m_time
);
273 //constructor for computing the grid and the crossings from scratch for
274 //the given layout where node v is moved to newPos
275 UniformGrid::UniformGrid(
276 const GraphAttributes
&AG
,
278 const DPoint
& newPos
)
281 m_graph(AG
.constGraph()),
282 m_crossings(m_graph
),
289 m_maxEdgesPerCell
= 0;
292 IntersectionRectangle ir
;
293 computeGridGeometry(v
,newPos
,ir
);
294 double maxLength
= max(ir
.height(),ir
.width());
295 m_CellSize
= maxLength
/(m_edgeMultiplier
*(m_graph
).numberOfEdges());
298 computeCrossings(L
,v
,newPos
);
300 m_time
= usedTime(m_time
);
304 //constructor for computing an updated grid for a given grid where one
305 //vertex is moved to a new position
306 UniformGrid::UniformGrid(
307 const UniformGrid
&ug
,
309 const DPoint
& newPos
) :
310 m_layout(ug
.m_layout
),
313 m_crossings(ug
.m_crossings
),
315 m_CellSize(ug
.m_CellSize
),
316 m_crossNum(ug
.m_crossNum
)
318 //constructorcounter++;
321 m_maxEdgesPerCell
= 0;
323 IntersectionRectangle ir
;
324 computeGridGeometry(v
,newPos
,ir
);
325 double l
= max(ir
.width(),ir
.height());
326 l
/=(m_graph
.numberOfEdges()*m_edgeMultiplier
);
327 OGDF_ASSERT(l
> 0.5*m_CellSize
&& l
< 2.0*m_CellSize
);
329 //compute the list of edge incident to v
331 m_graph
.adjEdges(v
,incident
);
332 //set the crossings of all these edges to zero, update the global crossing
333 //number, remove them from their cells. Note that we cannot insert the edge
334 //with its new position into the grid in the same loop because we may get
335 //crossings with other edges incident to v
336 ListIterator
<edge
> it1
;
337 for(it1
= incident
.begin(); it1
.valid(); ++it1
) {
339 //we clear the list of crossings of e and delete e from the
340 //crossings lists of all the edges it crosses
341 List
<edge
>& c
= m_crossings
[e
];
343 edge crossed
= c
.popFrontRet();
344 List
<edge
>& cl
= m_crossings
[crossed
];
345 ListIterator
<edge
> it2
= cl
.begin();
346 while(*it2
!= e
) ++it2
;
350 List
<IPoint
>& cells
= m_cells
[e
];
351 //delete e from all its cells
352 while(!cells
.empty()) {
353 IPoint p
= cells
.popFrontRet();
354 List
<edge
>& eList
= m_grid(p
.m_x
,p
.m_y
);
355 ListIterator
<edge
> it2
= eList
.begin();
356 while(*it2
!= e
) ++it2
;
359 }// at this point, all the data structures look as if the edges in the
360 //list incident where not present. Now we reinsert the edges into the
361 //grid with their new positions and update the crossings
362 computeCrossings(incident
,v
,newPos
);
364 m_time
= usedTime(m_time
);
369 void UniformGrid::computeGridGeometry(
371 const DPoint
& newPos
,
372 IntersectionRectangle
& ir
) const
374 //first we compute the resolution and size of the grid
375 double MinX
= DBL_MAX
, MinY
= DBL_MAX
, MaxX
=DBL_MIN
, MaxY
= DBL_MIN
;
376 //find lower left and upper right vertex
378 forall_nodes(v
,m_graph
) {
379 double x
= 0.0, y
= 0.0;
380 if(v
!= moved
) {// v is the node that was moved
384 else {// v is not the moved node
388 if(x
< MinX
) MinX
= x
;
389 if(x
> MaxX
) MaxX
= x
;
390 if(y
< MinY
) MinY
= y
;
391 if(y
> MaxY
) MaxY
= y
;
393 ir
= IntersectionRectangle(MinX
,MinY
,MaxX
,MaxY
);
397 void UniformGrid::computeCrossings(
398 const List
<edge
>& toInsert
,
400 const DPoint
& newPos
)
402 //now we compute all the remaining data of the class in one loop
403 //going through all edges and storing them in the grid.
404 ListConstIterator
<edge
> it
;
405 for(it
= toInsert
.begin(); it
.valid(); ++it
) {
407 SList
<IPoint
> crossedCells
;
409 const node
& s
= e
->source();
410 if(s
!= moved
) sPos
= DPoint(m_layout
.x(s
),m_layout
.y(s
));
412 const node
& t
= e
->target();
413 if(t
!= moved
) tPos
= DPoint(m_layout
.x(t
),m_layout
.y(t
));
415 DoubleModifiedBresenham(sPos
,tPos
,crossedCells
);
416 SListConstIterator
<IPoint
> it1
;
417 for(it1
= crossedCells
.begin(); it1
.valid(); ++it1
) {
418 const IPoint
& p
= *it1
;
419 (m_cells
[e
]).pushBack(p
);
420 List
<edge
>& edgeList
= m_grid(p
.m_x
,p
.m_y
);
421 if(!edgeList
.empty()) { //there are already edges in that list
422 ListConstIterator
<edge
> it2
;
423 OGDF_ASSERT(!edgeList
.empty());
424 for(it2
= edgeList
.begin(); it2
.valid(); ++it2
) {
425 if(crossingTest(e
,*it2
,moved
,newPos
,p
)) { //two edges cross in p
427 m_crossings
[e
].pushBack(*it2
);
428 m_crossings
[*it2
].pushBack(e
);
432 //now we insert the new edge into the list and store the position
433 //returned by pushBack in the corresponding list of m_storedIn
434 edgeList
.pushBack(e
);
436 if(m_maxEdgesPerCell
< edgeList
.size())
437 m_maxEdgesPerCell
= edgeList
.size();
444 forall_edges(e
,m_graph
) SumCros
+= m_crossings
[e
].size();
445 OGDF_ASSERT((SumCros
>> 1) == m_crossNum
);
450 //returns true if both edges are not adjacent and cross inside the given cell
451 bool UniformGrid::crossingTest(
455 const DPoint
& newPos
,
458 bool crosses
= false;
459 node s1
= e1
->source(), t1
= e1
->target();
460 node s2
= e2
->source(), t2
= e2
->target();
461 if(s1
!= s2
&& s1
!= t2
&& t1
!= s2
&& t1
!= t2
) {//not adjacent
462 double xLeft
= cell
.m_x
*m_CellSize
;
463 double xRight
= (cell
.m_x
+1)*m_CellSize
;
464 double xBottom
= cell
.m_y
*m_CellSize
;
465 double xTop
= (cell
.m_y
+1)*m_CellSize
;
466 DPoint ps1
,pt1
,ps2
,pt2
;
467 if(s1
!= moved
) ps1
= DPoint(m_layout
.x(s1
),m_layout
.y(s1
));
469 if(t1
!= moved
) pt1
= DPoint(m_layout
.x(t1
),m_layout
.y(t1
));
471 if(s2
!= moved
) ps2
= DPoint(m_layout
.x(s2
),m_layout
.y(s2
));
473 if(t2
!= moved
) pt2
= DPoint(m_layout
.x(t2
),m_layout
.y(t2
));
475 DLine
l1(ps1
,pt1
),l2(ps2
,pt2
);
480 if(l1
.intersection(l2
,crossPoint
)) {
481 if(crossPoint
.m_x
>= xLeft
&& crossPoint
.m_x
< xRight
&&
482 crossPoint
.m_y
>= xBottom
&& crossPoint
.m_y
< xTop
) {
492 void UniformGrid::markCells(SList
<IPoint
> &result
, Array2D
<bool> &cells
) const {
493 while(!result
.empty()) {
494 IPoint p
= result
.popFrontRet();
495 if(cells
.low1() <= p
.m_x
&& cells
.high1() >= p
.m_x
496 && cells
.low2() <= p
.m_y
&& cells
.high2() >= p
.m_y
)
497 cells(p
.m_x
,p
.m_y
) = true;
502 void UniformGrid::checkBresenham(DPoint p1
, DPoint p2
) const
505 DPoint
bottomleft(min(p1
.m_x
,p2
.m_x
),min(p1
.m_y
,p2
.m_y
));
506 DPoint
topright(max(max(p1
.m_x
,p2
.m_x
),bottomleft
.m_x
+1.0),
507 max(max(p1
.m_y
,p2
.m_y
),bottomleft
.m_y
+1.0));
508 IPoint
ibl(computeGridPoint(bottomleft
));
509 IPoint
itr(computeGridPoint(topright
));
510 Array2D
<bool> cells(ibl
.m_x
,itr
.m_x
+1,ibl
.m_y
,itr
.m_y
+1,false);
511 SList
<IPoint
> result
;
512 DoubleModifiedBresenham(p1
,p2
,result
);
513 cout
<< "\nList computed by Bresenham:\n";
515 for(SListIterator
<IPoint
> it
= result
.begin(); it
.valid(); ++it
) {
516 cout
<< computeRealPoint(*it
) << " ";
519 markCells(result
,cells
);
520 cout
<< "\nCrossed cells:\n";
521 if(p1
.m_x
== p2
.m_x
) { //vertical segment
522 int cellXcoord
= (int)floor(p1
.m_x
/m_CellSize
);
523 double b
= floor(min(p1
.m_y
,p2
.m_y
)/m_CellSize
);
524 double t
= ceil(max(p1
.m_y
,p2
.m_y
)/m_CellSize
);
525 OGDF_ASSERT(isInt(b
) && isInt(t
));
527 for(int i
= int(b
); i
< intT
; i
++) {
529 IPoint
p(cellXcoord
,i
);
530 cout
<< computeRealPoint(p
) << " ";
531 if(!cells(p
.m_x
,p
.m_y
)) {
532 cout
<< "\nCell " << computeRealPoint(p
) << " is not marked!";
538 if(p1
.m_y
== p2
.m_y
) { //horizontal segment
539 double tmp
= floor(p1
.m_y
/m_CellSize
);
541 int cellYcoord
= (int)tmp
;
542 double l
= floor(min(p1
.m_x
,p2
.m_x
)/m_CellSize
);
543 double r
= ceil(max(p1
.m_x
,p2
.m_x
)/m_CellSize
);
544 assert(isInt(l
) && isInt(r
));
546 for(int i
= int(l
); i
< intR
; i
++) {
548 IPoint
p(i
,cellYcoord
);
549 cout
<< computeRealPoint(p
) << " ";
550 if(!cells(p
.m_x
,p
.m_y
)) {
551 cout
<< "\nCell " << computeRealPoint(p
) << " is not marked!";
557 for(int i
= cells
.low1(); i
<= cells
.high1(); i
++) {
558 for(int j
= cells
.low2(); j
<= cells
.high2(); j
++) {
560 if(crossesCell(p1
,p2
,p
)) {
562 cout
<< computeRealPoint(p
) << " ";
563 if(!cells(p
.m_x
,p
.m_y
)) {
564 cout
<< "\n Cell " << computeRealPoint(p
) << " is not marked!";
573 if(crossed
< max(fabs(p1
.m_x
-p2
.m_x
)/m_CellSize
,fabs(p1
.m_y
-p2
.m_y
)/m_CellSize
)) {
574 cout
<< "\nNot enough crossed cells for " << p1
<< " " << p2
<< "\n";
582 void UniformGrid::checkBresenham(IPoint p1
, IPoint p2
) const
585 int left
= min(p1
.m_x
,p2
.m_x
)-1;
586 int right
= max(max(p1
.m_x
,p2
.m_x
),left
+1);
587 int bottom
= min(p1
.m_y
,p2
.m_y
)-1;
588 int top
= max(max(p1
.m_y
,p2
.m_y
),bottom
+1);
589 Array2D
<bool> cells(left
,right
,bottom
,top
,false);
590 SList
<IPoint
> result
;
591 ModifiedBresenham(p1
,p2
,result
);
592 cout
<< "\nList computed by Bresenham:\n" << result
;
593 markCells(result
,cells
);
594 cout
<< "\nCrossed cells:\n";
595 if(p1
.m_x
== p2
.m_x
) { //vertical segment
596 for(int i
= min(p1
.m_y
,p2
.m_y
); i
< max(p1
.m_y
,p2
.m_y
); i
++) {
600 if(!cells(p
.m_x
,p
.m_y
)) {
601 cout
<< "\nCell " << p
<< " is not marked!";
607 if(p1
.m_y
== p2
.m_y
) { //horizontal segment
608 for(int i
= min(p1
.m_x
,p2
.m_x
); i
< max(p1
.m_x
,p2
.m_x
); i
++) {
612 if(!cells(i
,p1
.m_y
)) {
613 cout
<< "\nCell " << p
<<" is not marked!";
619 for(int i
= cells
.low1(); i
<= cells
.high1(); i
++) {
620 for(int j
= cells
.low2(); j
<= cells
.high2(); j
++) {
622 if(crossesCell(p1
,p2
,p
)) {
625 if(!cells(p
.m_x
,p
.m_y
)) {
626 cout
<< "\n Cell " << p
<< " is not marked!";
635 if(crossed
< max(abs(p1
.m_x
-p2
.m_x
),abs(p1
.m_y
-p2
.m_y
))) {
636 cout
<< "\nNot enough crossed cells for " << p1
<< " " << p2
<< "\n";
644 //the upper and left boundary does not belong to a cell
645 bool UniformGrid::crossesCell(
648 const IPoint
&CellAdr
) const
650 bool crosses
= false;
651 if(A
.m_x
== B
.m_x
) {//line segment is vertical
652 if(A
.m_x
>= CellAdr
.m_x
&& A
.m_x
< CellAdr
.m_x
+1) {
653 if(intervalIntersect(A
.m_y
,B
.m_y
,CellAdr
.m_y
,CellAdr
.m_y
+1))
657 else {//line segment not vertical
658 if(A
.m_x
> B
.m_x
) swap(A
,B
);
659 double m
= double(B
.m_y
-A
.m_y
)/double(B
.m_x
-A
.m_x
);
660 double c
= A
.m_y
-A
.m_x
*m
;
661 double y1
= m
*CellAdr
.m_x
+ c
;
662 double y2
= m
*(CellAdr
.m_x
+1)+c
;
663 crosses
= intervalIntersect(A
.m_x
,B
.m_x
,CellAdr
.m_x
,CellAdr
.m_x
+1);
664 crosses
= crosses
&& intervalIntersect(y1
,y2
,CellAdr
.m_y
,CellAdr
.m_y
+1);
670 //the upper and left boundary does not belong to a cell
671 bool UniformGrid::crossesCell(
674 const IPoint
&CellAdr
) const
676 bool crosses
= false;
677 double xLowCell
= CellAdr
.m_x
* m_CellSize
;
678 double xHighCell
= xLowCell
+ m_CellSize
;
679 double yLowCell
= CellAdr
.m_y
* m_CellSize
;
680 double yHighCell
= yLowCell
+ m_CellSize
;
681 if(A
.m_x
== B
.m_x
) {//line segment is vertical
682 if(A
.m_x
>= xLowCell
&& A
.m_x
< xHighCell
) {
683 if(intervalIntersect(A
.m_y
,B
.m_y
,yLowCell
,yHighCell
))
687 else {//line segment not vertical
688 if(A
.m_x
> B
.m_x
) swap(A
,B
);
689 double m
= (B
.m_y
-A
.m_y
)/(B
.m_x
-A
.m_x
);
690 double c
= A
.m_y
-A
.m_x
*m
;
691 double y1
= m
* xLowCell
+ c
;
692 double y2
= m
* xHighCell
+ c
;
693 crosses
= intervalIntersect(A
.m_x
,B
.m_x
,xLowCell
,xHighCell
);
694 crosses
= crosses
&& intervalIntersect(min(A
.m_y
,B
.m_y
),max(A
.m_y
,B
.m_y
),
696 crosses
= crosses
&& intervalIntersect(y1
,y2
,yLowCell
,yHighCell
);
702 bool UniformGrid::intervalIntersect(
708 double epsilon
= 0.000001;
709 bool intersect
= true;
710 if(min(a1
,a2
)+epsilon
>= max(cell1
,cell2
) || min(cell1
,cell2
)+epsilon
>= max(a1
,a2
)) intersect
= false;
715 ostream
&operator<<(ostream
&out
, const UniformGrid
&ug
)
717 out
<< "\nGrid Size: " << ug
.m_CellSize
;
718 out
<< "\nEpsilon: " << ug
.m_epsilon
;
719 out
<< "\nEdge Multiplier: " << ug
.m_edgeMultiplier
;
720 out
<< "\nCrossing number: " << ug
.m_crossNum
;
722 out
<< "\nCrossing tests: " << ug
.m_crossingTests
;
723 out
<< "\nMax edges per cell: " << ug
.m_maxEdgesPerCell
;
724 out
<< "\nConstruction time: " << ug
.m_time
;
725 IntersectionRectangle ir
;
726 node v
= ug
.m_graph
.firstNode();
727 ug
.computeGridGeometry(v
,DPoint(ug
.m_layout
.x(v
),ug
.m_layout
.y(v
)),ir
);
728 double l
= max(ir
.width(),ir
.height());
729 cout
<< "\nPreferred Cell Size: " << l
/(ug
.m_graph
.numberOfEdges()*ug
.m_edgeMultiplier
);