2
2
* vim: ts=4 sw=4 et tw=0 wm=0
4
4
* libavoid - Fast, Incremental, Object-avoiding Line Router
5
* Copyright (C) 2004-2006 Michael Wybrow <mjwybrow@users.sourceforge.net>
6
* Copyright (C) 2004-2009 Monash University
7
8
* This library is free software; you can redistribute it and/or
8
9
* modify it under the terms of the GNU Lesser General Public
9
10
* License as published by the Free Software Foundation; either
10
11
* version 2.1 of the License, or (at your option) any later version.
12
* See the file LICENSE.LGPL distributed with the library.
14
* Licensees holding a valid commercial license may use this file in
15
* accordance with the commercial license agreement provided with the
12
18
* This library is distributed in the hope that it will be useful,
13
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22
* Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
23
28
#include "libavoid/debug.h"
24
29
#include "libavoid/graph.h"
25
30
#include "libavoid/connector.h"
26
31
#include "libavoid/geometry.h"
27
#include "libavoid/polyutil.h"
28
32
#include "libavoid/timer.h"
29
33
#include "libavoid/vertices.h"
30
34
#include "libavoid/router.h"
35
#include "libavoid/assertions.h"
39
EdgeInf::EdgeInf(VertInf *v1, VertInf *v2)
43
EdgeInf::EdgeInf(VertInf *v1, VertInf *v2, const bool orthogonal)
50
_orthogonal(orthogonal),
50
55
// Not passed NULL values.
56
COLA_ASSERT(v1 && v2);
53
58
// We are in the same instance
54
assert(_v1->_router == _v2->_router);
59
COLA_ASSERT(_v1->_router == _v2->_router);
55
60
_router = _v1->_router;
75
// Gives an order value between 0 and 3 for the point c, given the last
76
// segment was from a to b. Returns the following value:
77
// 0 : Point c is directly backwards from point b.
78
// 1 : Point c is a left-hand 90 degree turn.
79
// 2 : Point c is a right-hand 90 degree turn.
80
// 3 : Point c is straight ahead (collinear).
82
static inline int orthogTurnOrder(const Point& a, const Point& b,
85
// We should only be calling this with orthogonal points,
86
COLA_ASSERT((c.x == b.x) || (c.y == b.y));
87
COLA_ASSERT((a.x == b.x) || (a.y == b.y));
89
int direction = vecDir(a, b, c);
93
// Counterclockwise := left
96
else if (direction < 0)
104
if ( ((a.y < b.y) && (c.y < b.y)) ||
105
((a.y > b.y) && (c.y > b.y)) )
113
if ( ((a.x < b.x) && (c.x < b.x)) ||
114
((a.x > b.x) && (c.x > b.x)) )
126
// Returns a less than operation for a set exploration order for orthogonal
127
// searching. Forward, then left, then right. Or if there is no previous
128
// point, then the order is north, east, south, then west.
129
// Note: This method assumes the two Edges that share a common point.
130
bool EdgeInf::rotationLessThan(const VertInf *lastV, const EdgeInf *rhs) const
132
if ((_v1 == rhs->_v1) && (_v2 == rhs->_v2))
134
// Effectively the same visibility edge, so they are equal.
137
VertInf *lhsV = NULL, *rhsV = NULL, *commonV = NULL;
139
// Determine common Point and the comparison point on the left- and
140
// the right-hand-side.
147
else if (_v1 == rhs->_v2)
153
else if (_v2 == rhs->_v1)
159
else if (_v2 == rhs->_v2)
166
const Point& lhsPt = lhsV->point;
167
const Point& rhsPt = rhsV->point;
168
const Point& commonPt = commonV->point;
170
// If no lastPt, use one directly to the left;
171
Point lastPt = (lastV) ? lastV->point : Point(commonPt.x - 10, commonPt.y);
173
int lhsVal = orthogTurnOrder(lastPt, commonPt, lhsPt);
174
int rhsVal = orthogTurnOrder(lastPt, commonPt, rhsPt);
176
return lhsVal < rhsVal;
70
180
void EdgeInf::makeActive(void)
72
assert(_added == false);
182
COLA_ASSERT(_added == false);
76
_router->visGraph.addEdge(this);
77
_pos1 = _v1->visList.insert(_v1->visList.begin(), this);
79
_pos2 = _v2->visList.insert(_v2->visList.begin(), this);
186
COLA_ASSERT(_visible);
187
_router->visOrthogGraph.addEdge(this);
188
_pos1 = _v1->orthogVisList.insert(_v1->orthogVisList.begin(), this);
189
_v1->orthogVisListSize++;
190
_pos2 = _v2->orthogVisList.insert(_v2->orthogVisList.begin(), this);
191
_v2->orthogVisListSize++;
82
else // if (invisible)
84
_router->invisGraph.addEdge(this);
85
_pos1 = _v1->invisList.insert(_v1->invisList.begin(), this);
87
_pos2 = _v2->invisList.insert(_v2->invisList.begin(), this);
197
_router->visGraph.addEdge(this);
198
_pos1 = _v1->visList.insert(_v1->visList.begin(), this);
200
_pos2 = _v2->visList.insert(_v2->visList.begin(), this);
203
else // if (invisible)
205
_router->invisGraph.addEdge(this);
206
_pos1 = _v1->invisList.insert(_v1->invisList.begin(), this);
207
_v1->invisListSize++;
208
_pos2 = _v2->invisList.insert(_v2->invisList.begin(), this);
209
_v2->invisListSize++;
94
216
void EdgeInf::makeInactive(void)
96
assert(_added == true);
218
COLA_ASSERT(_added == true);
100
_router->visGraph.removeEdge(this);
101
_v1->visList.erase(_pos1);
103
_v2->visList.erase(_pos2);
222
COLA_ASSERT(_visible);
223
_router->visOrthogGraph.removeEdge(this);
224
_v1->orthogVisList.erase(_pos1);
225
_v1->orthogVisListSize--;
226
_v2->orthogVisList.erase(_pos2);
227
_v2->orthogVisListSize--;
106
else // if (invisible)
108
_router->invisGraph.removeEdge(this);
109
_v1->invisList.erase(_pos1);
110
_v1->invisListSize--;
111
_v2->invisList.erase(_pos2);
112
_v2->invisListSize--;
233
_router->visGraph.removeEdge(this);
234
_v1->visList.erase(_pos1);
236
_v2->visList.erase(_pos2);
239
else // if (invisible)
241
_router->invisGraph.removeEdge(this);
242
_v1->invisList.erase(_pos1);
243
_v1->invisListSize--;
244
_v2->invisList.erase(_pos2);
245
_v2->invisListSize--;
318
466
VertInf *last = _router->vertices.end();
467
unsigned int lastId = 0;
468
bool seenIntersectionAtEndpoint = false;
319
469
for (VertInf *k = _router->vertices.shapesBegin(); k != last; )
321
471
VertID kID = k->id;
322
if ((ss.find(kID.objID) != ss.end()))
472
if (k->id == dummyOrthogID)
324
unsigned int shapeID = kID.objID;
325
db_printf("Endpoint is inside shape %u so ignore shape edges.\n",
327
// One of the endpoints is inside this shape so ignore it.
328
while ((k != last) && (k->id.objID == shapeID))
330
// And skip the other vertices from this shape.
474
// Don't include orthogonal dummy vertices.
478
if (kID.objID != lastId)
480
if ((ss.find(kID.objID) != ss.end()))
482
unsigned int shapeID = kID.objID;
483
db_printf("Endpoint is inside shape %u so ignore shape "
484
"edges.\n", kID.objID);
485
// One of the endpoints is inside this shape so ignore it.
486
while ((k != last) && (k->id.objID == shapeID))
488
// And skip the other vertices from this shape.
493
seenIntersectionAtEndpoint = false;
335
496
Point& kPoint = k->point;
336
497
Point& kPrevPoint = k->shPrev->point;
338
if (segmentIntersect(pti, ptj, kPrevPoint, kPoint))
498
if (segmentShapeIntersect(pti, ptj, kPrevPoint, kPoint,
499
seenIntersectionAtEndpoint))
341
502
return kID.objID;
373
542
EdgeInf *EdgeInf::checkEdgeVisibility(VertInf *i, VertInf *j, bool knownNew)
544
// This is for polyline routing, so check we're not
545
// considering orthogonal vertices.
546
COLA_ASSERT(i->id != dummyOrthogID);
547
COLA_ASSERT(j->id != dummyOrthogID);
375
549
Router *router = i->_router;
376
550
EdgeInf *edge = NULL;
380
assert(existingEdge(i, j) == NULL);
554
COLA_ASSERT(existingEdge(i, j) == NULL);
381
555
edge = new EdgeInf(i, j);
576
// XXX: This function is ineffecient, and shouldn't even really be
402
578
EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
404
580
VertInf *selected = NULL;
406
if (i->visListSize <= j->visListSize)
582
// Look through poly-line visibility edges.
583
selected = (i->visListSize <= j->visListSize) ? i : j;
415
584
EdgeInfList& visList = selected->visList;
416
EdgeInfList::iterator finish = visList.end();
417
for (EdgeInfList::iterator edge = visList.begin(); edge != finish;
585
EdgeInfList::const_iterator finish = visList.end();
586
for (EdgeInfList::const_iterator edge = visList.begin(); edge != finish;
420
589
if ((*edge)->isBetween(i, j))
426
if (i->invisListSize <= j->invisListSize)
595
// Look through orthogonal visbility edges.
596
selected = (i->orthogVisListSize <= j->orthogVisListSize) ? i : j;
597
EdgeInfList& orthogVisList = selected->orthogVisList;
598
finish = orthogVisList.end();
599
for (EdgeInfList::const_iterator edge = orthogVisList.begin();
600
edge != finish; ++edge)
602
if ((*edge)->isBetween(i, j))
608
// Look through poly-line invisbility edges.
609
selected = (i->invisListSize <= j->invisListSize) ? i : j;
435
610
EdgeInfList& invisList = selected->invisList;
436
611
finish = invisList.end();
437
for (EdgeInfList::iterator edge = invisList.begin(); edge != finish;
612
for (EdgeInfList::const_iterator edge = invisList.begin(); edge != finish;
440
615
if ((*edge)->isBetween(i, j))