2
* vim: ts=4 sw=4 et tw=0 wm=0
4
* libavoid - Fast, Incremental, Object-avoiding Line Router
5
* Copyright (C) 2004-2005 Michael Wybrow <mjwybrow@users.sourceforge.net>
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* 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
23
#include "libavoid/debug.h"
24
#include "libavoid/graph.h"
25
#include "libavoid/connector.h"
26
#include "libavoid/polyutil.h"
27
#include "libavoid/timer.h"
34
static int st_checked_edges = 0;
40
EdgeInf::EdgeInf(VertInf *v1, VertInf *v2)
63
void EdgeInf::makeActive(void)
65
assert(_added == false);
69
visGraph.addEdge(this);
70
_pos1 = _v1->visList.insert(_v1->visList.begin(), this);
72
_pos2 = _v2->visList.insert(_v2->visList.begin(), this);
75
else // if (invisible)
77
invisGraph.addEdge(this);
78
_pos1 = _v1->invisList.insert(_v1->invisList.begin(), this);
80
_pos2 = _v2->invisList.insert(_v2->invisList.begin(), this);
87
void EdgeInf::makeInactive(void)
89
assert(_added == true);
93
visGraph.removeEdge(this);
94
_v1->visList.erase(_pos1);
96
_v2->visList.erase(_pos2);
99
else // if (invisible)
101
invisGraph.removeEdge(this);
102
_v1->invisList.erase(_pos1);
103
_v1->invisListSize--;
104
_v2->invisList.erase(_pos2);
105
_v2->invisListSize--;
113
double EdgeInf::getDist(void)
119
void EdgeInf::setDist(double dist)
123
if (_added && !_visible)
137
void EdgeInf::alertConns(void)
139
for (FlagList::iterator i = _conns.begin(); i != _conns.end(); ++i)
147
void EdgeInf::addConn(bool *flag)
149
_conns.push_back(flag);
153
void EdgeInf::addCycleBlocker(void)
155
// Needs to be in invisibility graph.
160
void EdgeInf::addBlocker(int b)
162
assert(InvisibilityGrph);
164
if (_added && _visible)
175
_blockers.push_back(b);
179
bool EdgeInf::hasBlocker(int b)
181
assert(InvisibilityGrph);
183
ShapeList::iterator finish = _blockers.end();
184
for (ShapeList::iterator it = _blockers.begin(); it != finish; ++it)
200
pair<VertID, VertID> EdgeInf::ids(void)
202
return std::make_pair(_v1->id, _v2->id);
206
pair<Point, Point> EdgeInf::points(void)
208
return std::make_pair(_v1->point, _v2->point);
212
void EdgeInf::db_print(void)
222
void EdgeInf::checkVis(void)
224
if (_added && !_visible)
226
db_printf("\tChecking visibility for existing invisibility edge..."
230
else if (_added && _visible)
232
db_printf("\tChecking visibility for existing visibility edge..."
243
const VertID& iID = i->id;
244
const VertID& jID = j->id;
245
const Point& iPoint = i->point;
246
const Point& jPoint = j->point;
252
cone1 = inValidRegion(i->shPrev->point, iPoint, i->shNext->point,
257
ShapeSet& ss = contains[iID];
259
if ((jID.isShape) && (ss.find(jID.objID) != ss.end()))
261
db_printf("1: Edge of bounding shape\n");
262
// Don't even check this edge, it should be zero,
263
// since a point in a shape can't see it's corners
270
// If outside the first cone, don't even bother checking.
273
cone2 = inValidRegion(j->shPrev->point, jPoint, j->shNext->point,
278
ShapeSet& ss = contains[jID];
280
if ((iID.isShape) && (ss.find(iID.objID) != ss.end()))
282
db_printf("2: Edge of bounding shape\n");
283
// Don't even check this edge, it should be zero,
284
// since a point in a shape can't see it's corners
290
if (cone1 && cone2 && ((blocker = firstBlocker()) == 0))
293
// if i and j see each other, add edge
294
db_printf("\tSetting visibility edge... \n\t\t");
297
double d = dist(iPoint, jPoint);
302
else if (InvisibilityGrph)
305
db_printf("%d, %d, %d\n", cone1, cone2, blocker);
306
db_printf("\t(%d, %d)--(%d, %d)\n", (int) iInfo.point.x,
307
(int) iInfo.point.y, (int) jInfo.point.x,
308
(int) jInfo.point.y);
311
// if i and j can't see each other, add blank edge
312
db_printf("\tSetting invisibility edge... \n\t\t");
319
int EdgeInf::firstBlocker(void)
321
ShapeSet ss = ShapeSet();
323
Point& pti = _v1->point;
324
Point& ptj = _v2->point;
325
VertID& iID = _v1->id;
326
VertID& jID = _v2->id;
330
ss.insert(contains[iID].begin(), contains[iID].end());
334
ss.insert(contains[jID].begin(), contains[jID].end());
337
VertInf *last = vertices.end();
338
for (VertInf *k = vertices.shapesBegin(); k != last; )
341
if ((ss.find(kID.objID) != ss.end()))
343
uint shapeID = kID.objID;
344
db_printf("Endpoint is inside shape %u so ignore shape edges.\n",
346
// One of the endpoints is inside this shape so ignore it.
347
while ((k != last) && (k->id.objID == shapeID))
349
// And skip the other vertices from this shape.
354
Point& kPoint = k->point;
355
Point& kPrevPoint = k->shPrev->point;
357
if (segmentIntersect(pti, ptj, kPrevPoint, kPoint))
369
bool EdgeInf::isBetween(VertInf *i, VertInf *j)
371
if ( ((i == _v1) && (j == _v2)) ||
372
((i == _v2) && (j == _v1)) )
380
VertInf *EdgeInf::otherVert(VertInf *vert)
382
assert((vert == _v1) || (vert == _v2));
392
EdgeInf *EdgeInf::checkEdgeVisibility(VertInf *i, VertInf *j, bool knownNew)
394
EdgeInf *edge = NULL;
398
assert(existingEdge(i, j) == NULL);
399
edge = new EdgeInf(i, j);
403
edge = existingEdge(i, j);
406
edge = new EdgeInf(i, j);
410
if (!(edge->_added) && !InvisibilityGrph)
420
EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
422
VertInf *selected = NULL;
424
if (i->visListSize <= j->visListSize)
433
EdgeInfList& visList = selected->visList;
434
EdgeInfList::iterator finish = visList.end();
435
for (EdgeInfList::iterator edge = visList.begin(); edge != finish;
438
if ((*edge)->isBetween(i, j))
444
if (i->invisListSize <= j->invisListSize)
453
EdgeInfList& invisList = selected->invisList;
454
finish = invisList.end();
455
for (EdgeInfList::iterator edge = invisList.begin(); edge != finish;
458
if ((*edge)->isBetween(i, j))
468
//===========================================================================
479
void EdgeList::addEdge(EdgeInf *edge)
481
if (_firstEdge == NULL)
483
assert(_lastEdge == NULL);
488
edge->lstPrev = NULL;
489
edge->lstNext = NULL;
493
assert(_lastEdge != NULL);
495
_lastEdge->lstNext = edge;
496
edge->lstPrev = _lastEdge;
500
edge->lstNext = NULL;
506
void EdgeList::removeEdge(EdgeInf *edge)
510
edge->lstPrev->lstNext = edge->lstNext;
514
edge->lstNext->lstPrev = edge->lstPrev;
516
if (edge == _lastEdge)
518
_lastEdge = edge->lstPrev;
519
if (edge == _firstEdge)
524
else if (edge == _firstEdge)
526
_firstEdge = edge->lstNext;
530
edge->lstPrev = NULL;
531
edge->lstNext = NULL;
537
EdgeInf *EdgeList::begin(void)
543
EdgeInf *EdgeList::end(void)
549
// General visibility graph utility functions
552
void newBlockingShape(Polygn *poly, int pid)
554
// o Check all visibility edges to see if this one shape
556
EdgeInf *finish = visGraph.end();
557
for (EdgeInf *iter = visGraph.begin(); iter != finish ; )
560
iter = iter->lstNext;
562
if (tmp->getDist() != 0)
564
pair<VertID, VertID> ids(tmp->ids());
565
VertID eID1 = ids.first;
566
VertID eID2 = ids.second;
567
pair<Point, Point> points(tmp->points());
568
Point e1 = points.first;
569
Point e2 = points.second;
570
bool blocked = false;
572
bool ep_in_poly1 = !(eID1.isShape) ? inPoly(*poly, e1) : false;
573
bool ep_in_poly2 = !(eID2.isShape) ? inPoly(*poly, e2) : false;
574
if (ep_in_poly1 || ep_in_poly2)
576
// Don't check edges that have a connector endpoint
577
// and are inside the shape being added.
581
for (int pt_i = 0; pt_i < poly->pn; pt_i++)
583
int pt_n = (pt_i == (poly->pn - 1)) ? 0 : pt_i + 1;
584
if (segmentIntersect(e1, e2, poly->ps[pt_i], poly->ps[pt_n]))
592
db_printf("\tRemoving newly blocked edge (by shape %3d)"
596
if (InvisibilityGrph)
598
tmp->addBlocker(pid);
610
void checkAllBlockedEdges(int pid)
612
assert(InvisibilityGrph);
614
for (EdgeInf *iter = invisGraph.begin(); iter != invisGraph.end() ; )
617
iter = iter->lstNext;
619
if (tmp->hasBlocker(pid))
627
void checkAllMissingEdges(void)
629
assert(!InvisibilityGrph);
631
VertInf *first = NULL;
633
if (IncludeEndpoints)
635
first = vertices.connsBegin();
639
first = vertices.shapesBegin();
642
VertInf *pend = vertices.end();
643
for (VertInf *i = first; i != pend; i = i->lstNext)
647
// Check remaining, earlier vertices
648
for (VertInf *j = first ; j != i; j = j->lstNext)
651
if (!(iID.isShape) && (iID.objID != jID.objID))
653
// Don't keep visibility between edges of different conns
657
// See if the edge is already there?
658
bool found = (EdgeInf::existingEdge(i, j) != NULL);
662
// Didn't already exist, check.
663
bool knownNew = true;
664
EdgeInf::checkEdgeVisibility(i, j, knownNew);
671
void generateContains(VertInf *pt)
673
contains[pt->id].clear();
675
ShapeRefList::iterator finish = shapeRefs.end();
676
for (ShapeRefList::iterator i = shapeRefs.begin(); i != finish; ++i)
678
Polygn poly = copyPoly(*i);
679
if (inPoly(poly, pt->point))
681
contains[pt->id].insert((*i)->id());
688
void adjustContainsWithAdd(const Polygn& poly, const int p_shape)
690
for (VertInf *k = vertices.connsBegin(); k != vertices.shapesBegin();
693
if (inPoly(poly, k->point))
695
contains[k->id].insert(p_shape);
701
void adjustContainsWithDel(const int p_shape)
703
for (VertInf *k = vertices.connsBegin(); k != vertices.shapesBegin();
706
contains[k->id].erase(p_shape);
711
// Maybe this one should be in with the connector stuff, but it may later
712
// need to operate on a particular section of the visibility graph so it
713
// may have to stay here.
715
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
716
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
718
#ifdef SELECTIVE_DEBUG
719
static double AngleAFromThreeSides(const double a, const double b,
722
// returns angle A, the angle opposite from side a, in radians
723
return acos((pow(b, 2) + pow(c, 2) - pow(a, 2)) / (2 * b * c));
727
void markConnectors(ShapeRef *shape)
729
assert(SelectiveReroute);
731
ConnRefList::iterator end = connRefs.end();
732
for (ConnRefList::iterator it = connRefs.begin(); it != end; ++it)
734
ConnRef *conn = (*it);
736
if (conn->_route.pn == 0)
738
// Ignore uninitialised connectors.
742
Point start = conn->_route.ps[0];
743
Point end = conn->_route.ps[conn->_route.pn - 1];
745
double conndist = conn->_route_dist;
750
VertInf *beginV = shape->firstVert();
751
VertInf *endV = shape->lastVert()->lstNext;
752
for (VertInf *i = beginV; i != endV; i = i->lstNext)
754
const Point& p1 = i->point;
755
const Point& p2 = i->shNext->point;
775
min = MIN(p1.x, p2.x);
776
max = MAX(p1.x, p2.x);
778
else if (p1.x == p2.x)
780
// Other Standard case
787
min = MIN(p1.y, p2.y);
788
max = MAX(p1.y, p2.y);
792
// Need to do rotation
793
Point n_p2 = { p2.x - p1.x, p2.y - p1.y };
794
Point n_start = { start.x - p1.x, start.y - p1.y };
795
Point n_end = { end.x - p1.x, end.y - p1.y };
796
//printf("n_p2: (%.1f, %.1f)\n", n_p2.x, n_p2.y);
797
//printf("n_start: (%.1f, %.1f)\n", n_start.x, n_start.y);
798
//printf("n_end: (%.1f, %.1f)\n", n_end.x, n_end.y);
800
double theta = 0 - atan2(n_p2.y, n_p2.x);
801
//printf("theta = %.2f\n", theta * (180 / PI));
808
double cosv = cos(theta);
809
double sinv = sin(theta);
811
r_p2.x = cosv * n_p2.x - sinv * n_p2.y;
812
r_p2.y = cosv * n_p2.y + sinv * n_p2.x;
813
start.x = cosv * n_start.x - sinv * n_start.y;
814
start.y = cosv * n_start.y + sinv * n_start.x;
815
end.x = cosv * n_end.x - sinv * n_end.y;
816
end.y = cosv * n_end.y + sinv * n_end.x;
817
//printf("r_p2: (%.1f, %.1f)\n", r_p2.x, r_p2.y);
818
//printf("r_start: (%.1f, %.1f)\n", start.x, start.y);
819
//printf("r_end: (%.1f, %.1f)\n", end.x, end.y);
821
if (((int) r_p2.y) != 0)
823
printf("r_p2.y: %f != 0\n", r_p2.y);
826
// This might be slightly off.
835
min = MIN(r_p1.x, r_p2.x);
836
max = MAX(r_p1.x, r_p2.x);
843
db_printf("WARNING: (b + d) == 0\n");
847
if ((b == 0) && (d == 0))
849
db_printf("WARNING: b == d == 0\n");
850
if (((a < min) && (c < min)) ||
851
((a > max) && (c > max)))
853
// It's going to get adjusted.
863
x = ((b*c) + (a*d)) / (b + d);
866
//printf("%.1f, %.1f, %.1f, %.1f\n", a, b, c, d);
867
//printf("x = %.1f\n", x);
869
// XXX: Use MAX and MIN
870
x = (x < min) ? min : x;
871
x = (x > max) ? max : x;
873
//printf("x = %.1f\n", x);
886
//printf("(%.1f, %.1f)\n", xp.x, xp.y);
888
e1 = dist(start, xp);
893
//printf("is %.1f < %.1f\n", estdist, conndist);
894
if (estdist < conndist)
896
#ifdef SELECTIVE_DEBUG
897
//double angle = AngleAFromThreeSides(dist(start, end),
899
printf("[%3d] - Possible better path found (%.1f < %.1f)\n",
900
conn->_id, estdist, conndist);
902
conn->_needs_reroute_flag = true;
914
fprintf(fp, "\nVisibility Graph info:\n");
915
fprintf(fp, "----------------------\n");
920
int st_endpoints = 0;
921
int st_valid_shape_visedges = 0;
922
int st_valid_endpt_visedges = 0;
923
int st_invalid_visedges = 0;
924
VertInf *finish = vertices.end();
925
for (VertInf *t = vertices.connsBegin(); t != finish; t = t->lstNext)
929
if ((pID.isShape) && (pID.objID != currshape))
931
currshape = pID.objID;
940
// The shape 0 ones are temporary and not considered.
944
for (EdgeInf *t = visGraph.begin(); t != visGraph.end();
947
std::pair<VertID, VertID> idpair = t->ids();
949
if (!(idpair.first.isShape) || !(idpair.second.isShape))
951
st_valid_endpt_visedges++;
955
st_valid_shape_visedges++;
958
for (EdgeInf *t = invisGraph.begin(); t != invisGraph.end();
961
st_invalid_visedges++;
963
fprintf(fp, "Number of shapes: %d\n", st_shapes);
964
fprintf(fp, "Number of vertices: %d (%d real, %d endpoints)\n",
965
st_vertices + st_endpoints, st_vertices, st_endpoints);
966
fprintf(fp, "Number of vis_edges: %d (%d valid [%d normal, %d endpt], "
967
"%d invalid)\n", st_valid_shape_visedges + st_invalid_visedges +
968
st_valid_endpt_visedges, st_valid_shape_visedges +
969
st_valid_endpt_visedges, st_valid_shape_visedges,
970
st_valid_endpt_visedges, st_invalid_visedges);
971
fprintf(fp, "----------------------\n");
972
fprintf(fp, "checkVisEdge tally: %d\n", st_checked_edges);
973
fprintf(fp, "----------------------\n");
975
fprintf(fp, "ADDS: "); timers.Print(tmAdd);
976
fprintf(fp, "DELS: "); timers.Print(tmDel);
977
fprintf(fp, "MOVS: "); timers.Print(tmMov);
978
fprintf(fp, "***S: "); timers.Print(tmSev);
979
fprintf(fp, "PTHS: "); timers.Print(tmPth);