summaryrefslogtreecommitdiffstats
path: root/src/libavoid/graph.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libavoid/graph.cpp387
1 files changed, 218 insertions, 169 deletions
diff --git a/src/libavoid/graph.cpp b/src/libavoid/graph.cpp
index 5b617f123..280a347fa 100644
--- a/src/libavoid/graph.cpp
+++ b/src/libavoid/graph.cpp
@@ -3,7 +3,7 @@
*
* libavoid - Fast, Incremental, Object-avoiding Line Router
*
- * Copyright (C) 2004-2009 Monash University
+ * Copyright (C) 2004-2011 Monash University
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
- * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Author(s): Michael Wybrow
*/
@@ -43,29 +43,31 @@ namespace Avoid {
EdgeInf::EdgeInf(VertInf *v1, VertInf *v2, const bool orthogonal)
: lstPrev(NULL),
lstNext(NULL),
- _blocker(0),
- _router(NULL),
- _added(false),
- _visible(false),
- _orthogonal(orthogonal),
- _v1(v1),
- _v2(v2),
- _dist(-1)
+ m_router(NULL),
+ m_blocker(0),
+ m_added(false),
+ m_visible(false),
+ m_orthogonal(orthogonal),
+ m_isHyperedgeSegment(false),
+ m_disabled(false),
+ m_vert1(v1),
+ m_vert2(v2),
+ m_dist(-1)
{
// Not passed NULL values.
COLA_ASSERT(v1 && v2);
// We are in the same instance
- COLA_ASSERT(_v1->_router == _v2->_router);
- _router = _v1->_router;
+ COLA_ASSERT(m_vert1->_router == m_vert2->_router);
+ m_router = m_vert1->_router;
- _conns.clear();
+ m_conns.clear();
}
EdgeInf::~EdgeInf()
{
- if (_added)
+ if (m_added)
{
makeInactive();
}
@@ -78,13 +80,16 @@ EdgeInf::~EdgeInf()
// 1 : Point c is a left-hand 90 degree turn.
// 2 : Point c is a right-hand 90 degree turn.
// 3 : Point c is straight ahead (collinear).
+// 4 : Point c is not orthogonally positioned.
//
static inline int orthogTurnOrder(const Point& a, const Point& b,
const Point& c)
{
- // We should only be calling this with orthogonal points,
- COLA_ASSERT((c.x == b.x) || (c.y == b.y));
- COLA_ASSERT((a.x == b.x) || (a.y == b.y));
+ if ( ((c.x != b.x) && (c.y != b.y)) || ((a.x != b.x) && (a.y != b.y)) )
+ {
+ // Not orthogonally positioned.
+ return 4;
+ }
int direction = vecDir(a, b, c);
@@ -129,9 +134,7 @@ static inline int orthogTurnOrder(const Point& a, const Point& b,
// Note: This method assumes the two Edges that share a common point.
bool EdgeInf::rotationLessThan(const VertInf *lastV, const EdgeInf *rhs) const
{
- assert(_v1 == rhs->_v1 || _v1 == rhs->_v2 || _v2 == rhs->_v1 || _v2 == rhs->_v2 );
-
- if ((_v1 == rhs->_v1) && (_v2 == rhs->_v2))
+ if ((m_vert1 == rhs->m_vert1) && (m_vert2 == rhs->m_vert2))
{
// Effectively the same visibility edge, so they are equal.
return false;
@@ -140,29 +143,29 @@ bool EdgeInf::rotationLessThan(const VertInf *lastV, const EdgeInf *rhs) const
// Determine common Point and the comparison point on the left- and
// the right-hand-side.
- if (_v1 == rhs->_v1)
+ if (m_vert1 == rhs->m_vert1)
{
- commonV = _v1;
- lhsV = _v2;
- rhsV = rhs->_v2;
+ commonV = m_vert1;
+ lhsV = m_vert2;
+ rhsV = rhs->m_vert2;
}
- else if (_v1 == rhs->_v2)
+ else if (m_vert1 == rhs->m_vert2)
{
- commonV = _v1;
- lhsV = _v2;
- rhsV = rhs->_v1;
+ commonV = m_vert1;
+ lhsV = m_vert2;
+ rhsV = rhs->m_vert1;
}
- else if (_v2 == rhs->_v1)
+ else if (m_vert2 == rhs->m_vert1)
{
- commonV = _v2;
- lhsV = _v1;
- rhsV = rhs->_v2;
+ commonV = m_vert2;
+ lhsV = m_vert1;
+ rhsV = rhs->m_vert2;
}
- else if (_v2 == rhs->_v2)
+ else if (m_vert2 == rhs->m_vert2)
{
- commonV = _v2;
- lhsV = _v1;
- rhsV = rhs->_v1;
+ commonV = m_vert2;
+ lhsV = m_vert1;
+ rhsV = rhs->m_vert1;
}
const Point& lhsPt = lhsV->point;
@@ -181,75 +184,75 @@ bool EdgeInf::rotationLessThan(const VertInf *lastV, const EdgeInf *rhs) const
void EdgeInf::makeActive(void)
{
- COLA_ASSERT(_added == false);
+ COLA_ASSERT(m_added == false);
- if (_orthogonal)
+ if (m_orthogonal)
{
- COLA_ASSERT(_visible);
- _router->visOrthogGraph.addEdge(this);
- _pos1 = _v1->orthogVisList.insert(_v1->orthogVisList.begin(), this);
- _v1->orthogVisListSize++;
- _pos2 = _v2->orthogVisList.insert(_v2->orthogVisList.begin(), this);
- _v2->orthogVisListSize++;
+ COLA_ASSERT(m_visible);
+ m_router->visOrthogGraph.addEdge(this);
+ m_pos1 = m_vert1->orthogVisList.insert(m_vert1->orthogVisList.begin(), this);
+ m_vert1->orthogVisListSize++;
+ m_pos2 = m_vert2->orthogVisList.insert(m_vert2->orthogVisList.begin(), this);
+ m_vert2->orthogVisListSize++;
}
else
{
- if (_visible)
+ if (m_visible)
{
- _router->visGraph.addEdge(this);
- _pos1 = _v1->visList.insert(_v1->visList.begin(), this);
- _v1->visListSize++;
- _pos2 = _v2->visList.insert(_v2->visList.begin(), this);
- _v2->visListSize++;
+ m_router->visGraph.addEdge(this);
+ m_pos1 = m_vert1->visList.insert(m_vert1->visList.begin(), this);
+ m_vert1->visListSize++;
+ m_pos2 = m_vert2->visList.insert(m_vert2->visList.begin(), this);
+ m_vert2->visListSize++;
}
else // if (invisible)
{
- _router->invisGraph.addEdge(this);
- _pos1 = _v1->invisList.insert(_v1->invisList.begin(), this);
- _v1->invisListSize++;
- _pos2 = _v2->invisList.insert(_v2->invisList.begin(), this);
- _v2->invisListSize++;
+ m_router->invisGraph.addEdge(this);
+ m_pos1 = m_vert1->invisList.insert(m_vert1->invisList.begin(), this);
+ m_vert1->invisListSize++;
+ m_pos2 = m_vert2->invisList.insert(m_vert2->invisList.begin(), this);
+ m_vert2->invisListSize++;
}
}
- _added = true;
+ m_added = true;
}
void EdgeInf::makeInactive(void)
{
- COLA_ASSERT(_added == true);
+ COLA_ASSERT(m_added == true);
- if (_orthogonal)
+ if (m_orthogonal)
{
- COLA_ASSERT(_visible);
- _router->visOrthogGraph.removeEdge(this);
- _v1->orthogVisList.erase(_pos1);
- _v1->orthogVisListSize--;
- _v2->orthogVisList.erase(_pos2);
- _v2->orthogVisListSize--;
+ COLA_ASSERT(m_visible);
+ m_router->visOrthogGraph.removeEdge(this);
+ m_vert1->orthogVisList.erase(m_pos1);
+ m_vert1->orthogVisListSize--;
+ m_vert2->orthogVisList.erase(m_pos2);
+ m_vert2->orthogVisListSize--;
}
else
{
- if (_visible)
+ if (m_visible)
{
- _router->visGraph.removeEdge(this);
- _v1->visList.erase(_pos1);
- _v1->visListSize--;
- _v2->visList.erase(_pos2);
- _v2->visListSize--;
+ m_router->visGraph.removeEdge(this);
+ m_vert1->visList.erase(m_pos1);
+ m_vert1->visListSize--;
+ m_vert2->visList.erase(m_pos2);
+ m_vert2->visListSize--;
}
else // if (invisible)
{
- _router->invisGraph.removeEdge(this);
- _v1->invisList.erase(_pos1);
- _v1->invisListSize--;
- _v2->invisList.erase(_pos2);
- _v2->invisListSize--;
+ m_router->invisGraph.removeEdge(this);
+ m_vert1->invisList.erase(m_pos1);
+ m_vert1->invisListSize--;
+ m_vert2->invisList.erase(m_pos2);
+ m_vert2->invisListSize--;
}
}
- _blocker = 0;
- _conns.clear();
- _added = false;
+ m_blocker = 0;
+ m_conns.clear();
+ m_added = false;
}
@@ -257,41 +260,75 @@ void EdgeInf::setDist(double dist)
{
//COLA_ASSERT(dist != 0);
- if (_added && !_visible)
+ if (m_added && !m_visible)
{
makeInactive();
- COLA_ASSERT(!_added);
+ COLA_ASSERT(!m_added);
}
- if (!_added)
+ if (!m_added)
{
- _visible = true;
+ m_visible = true;
makeActive();
}
- _dist = dist;
- _blocker = 0;
+ m_dist = dist;
+ m_blocker = 0;
+}
+
+
+void EdgeInf::setMtstDist(const double joinCost)
+{
+ m_mtst_dist = joinCost;
}
+double EdgeInf::mtstDist(void) const
+{
+ return m_mtst_dist;
+}
+
+bool EdgeInf::isHyperedgeSegment(void) const
+{
+ return m_isHyperedgeSegment;
+}
+
+bool EdgeInf::isDisabled(void) const
+{
+ return m_disabled;
+}
+
+void EdgeInf::setDisabled(const bool disabled)
+{
+ m_disabled = disabled;
+}
+
+void EdgeInf::setHyperedgeSegment(const bool hyperedge)
+{
+ m_isHyperedgeSegment = hyperedge;
+}
bool EdgeInf::added(void)
{
- return _added;
+ return m_added;
}
+int EdgeInf::blocker(void) const
+{
+ return m_blocker;
+}
void EdgeInf::alertConns(void)
{
- FlagList::iterator finish = _conns.end();
- for (FlagList::iterator i = _conns.begin(); i != finish; ++i)
+ FlagList::iterator finish = m_conns.end();
+ for (FlagList::iterator i = m_conns.begin(); i != finish; ++i)
{
*(*i) = true;
}
- _conns.clear();
+ m_conns.clear();
}
void EdgeInf::addConn(bool *flag)
{
- _conns.push_back(flag);
+ m_conns.push_back(flag);
}
@@ -304,54 +341,54 @@ void EdgeInf::addCycleBlocker(void)
void EdgeInf::addBlocker(int b)
{
- COLA_ASSERT(_router->InvisibilityGrph);
+ COLA_ASSERT(m_router->InvisibilityGrph);
- if (_added && _visible)
+ if (m_added && m_visible)
{
makeInactive();
- COLA_ASSERT(!_added);
+ COLA_ASSERT(!m_added);
}
- if (!_added)
+ if (!m_added)
{
- _visible = false;
+ m_visible = false;
makeActive();
}
- _dist = 0;
- _blocker = b;
+ m_dist = 0;
+ m_blocker = b;
}
-pair<VertID, VertID> EdgeInf::ids(void)
+pair<VertID, VertID> EdgeInf::ids(void) const
{
- return std::make_pair(_v1->id, _v2->id);
+ return std::make_pair(m_vert1->id, m_vert2->id);
}
-pair<Point, Point> EdgeInf::points(void)
+pair<Point, Point> EdgeInf::points(void) const
{
- return std::make_pair(_v1->point, _v2->point);
+ return std::make_pair(m_vert1->point, m_vert2->point);
}
void EdgeInf::db_print(void)
{
db_printf("Edge(");
- _v1->id.db_print();
+ m_vert1->id.db_print();
db_printf(",");
- _v2->id.db_print();
+ m_vert2->id.db_print();
db_printf(")\n");
}
void EdgeInf::checkVis(void)
{
- if (_added && !_visible)
+ if (m_added && !m_visible)
{
db_printf("\tChecking visibility for existing invisibility edge..."
"\n\t\t");
db_print();
}
- else if (_added && _visible)
+ else if (m_added && m_visible)
{
db_printf("\tChecking visibility for existing visibility edge..."
"\n\t\t");
@@ -362,28 +399,28 @@ void EdgeInf::checkVis(void)
bool cone1 = true;
bool cone2 = true;
- VertInf *i = _v1;
- VertInf *j = _v2;
+ VertInf *i = m_vert1;
+ VertInf *j = m_vert2;
const VertID& iID = i->id;
const VertID& jID = j->id;
const Point& iPoint = i->point;
const Point& jPoint = j->point;
- _router->st_checked_edges++;
+ m_router->st_checked_edges++;
- if (iID.isShape)
+ if (!(iID.isConnPt()))
{
- cone1 = inValidRegion(_router->IgnoreRegions, i->shPrev->point,
+ cone1 = inValidRegion(m_router->IgnoreRegions, i->shPrev->point,
iPoint, i->shNext->point, jPoint);
}
- else if (_router->IgnoreRegions == false)
+ else if (m_router->IgnoreRegions == false)
{
// If Ignoring regions then this case is already caught by
// the invalid regions, so only check it when not ignoring
// regions.
- ShapeSet& ss = _router->contains[iID];
+ ShapeSet& ss = m_router->contains[iID];
- if ((jID.isShape) && (ss.find(jID.objID) != ss.end()))
+ if (!(jID.isConnPt()) && (ss.find(jID.objID) != ss.end()))
{
db_printf("1: Edge of bounding shape\n");
// Don't even check this edge, it should be zero,
@@ -395,19 +432,19 @@ void EdgeInf::checkVis(void)
if (cone1)
{
// If outside the first cone, don't even bother checking.
- if (jID.isShape)
+ if (!(jID.isConnPt()))
{
- cone2 = inValidRegion(_router->IgnoreRegions, j->shPrev->point,
+ cone2 = inValidRegion(m_router->IgnoreRegions, j->shPrev->point,
jPoint, j->shNext->point, iPoint);
}
- else if (_router->IgnoreRegions == false)
+ else if (m_router->IgnoreRegions == false)
{
// If Ignoring regions then this case is already caught by
// the invalid regions, so only check it when not ignoring
// regions.
- ShapeSet& ss = _router->contains[jID];
+ ShapeSet& ss = m_router->contains[jID];
- if ((iID.isShape) && (ss.find(iID.objID) != ss.end()))
+ if (!(iID.isConnPt()) && (ss.find(iID.objID) != ss.end()))
{
db_printf("2: Edge of bounding shape\n");
// Don't even check this edge, it should be zero,
@@ -429,7 +466,7 @@ void EdgeInf::checkVis(void)
setDist(d);
}
- else if (_router->InvisibilityGrph)
+ else if (m_router->InvisibilityGrph)
{
#if 0
db_printf("%d, %d, %d\n", cone1, cone2, blocker);
@@ -450,25 +487,25 @@ int EdgeInf::firstBlocker(void)
{
ShapeSet ss = ShapeSet();
- Point& pti = _v1->point;
- Point& ptj = _v2->point;
- VertID& iID = _v1->id;
- VertID& jID = _v2->id;
+ Point& pti = m_vert1->point;
+ Point& ptj = m_vert2->point;
+ VertID& iID = m_vert1->id;
+ VertID& jID = m_vert2->id;
- ContainsMap &contains = _router->contains;
- if (!(iID.isShape))
+ ContainsMap &contains = m_router->contains;
+ if (iID.isConnPt())
{
ss.insert(contains[iID].begin(), contains[iID].end());
}
- if (!(jID.isShape))
+ if (jID.isConnPt())
{
ss.insert(contains[jID].begin(), contains[jID].end());
}
- VertInf *last = _router->vertices.end();
+ VertInf *last = m_router->vertices.end();
unsigned int lastId = 0;
bool seenIntersectionAtEndpoint = false;
- for (VertInf *k = _router->vertices.shapesBegin(); k != last; )
+ for (VertInf *k = m_router->vertices.shapesBegin(); k != last; )
{
VertID kID = k->id;
if (k->id == dummyOrthogID)
@@ -512,8 +549,8 @@ int EdgeInf::firstBlocker(void)
bool EdgeInf::isBetween(VertInf *i, VertInf *j)
{
- if ( ((i == _v1) && (j == _v2)) ||
- ((i == _v2) && (j == _v1)) )
+ if ( ((i == m_vert1) && (j == m_vert2)) ||
+ ((i == m_vert2) && (j == m_vert1)) )
{
return true;
}
@@ -524,20 +561,25 @@ bool EdgeInf::isBetween(VertInf *i, VertInf *j)
// Returns true if this edge is a vertical or horizontal line segment.
bool EdgeInf::isOrthogonal(void) const
{
- return ((_v1->point.x == _v2->point.x) ||
- (_v1->point.y == _v2->point.y));
+ return ((m_vert1->point.x == m_vert2->point.x) ||
+ (m_vert1->point.y == m_vert2->point.y));
}
-VertInf *EdgeInf::otherVert(VertInf *vert)
+bool EdgeInf::isDummyConnection(void) const
{
- COLA_ASSERT((vert == _v1) || (vert == _v2));
+ // This is a dummy edge from a shape centre to
+ // a set of its ShapeConnectionPins.
+ return ((m_vert1->id.isConnectionPin() && m_vert2->id.isConnPt()) ||
+ (m_vert2->id.isConnectionPin() && m_vert1->id.isConnPt()));
+}
- if (vert == _v1)
- {
- return _v2;
- }
- return _v1;
+
+VertInf *EdgeInf::otherVert(const VertInf *vert) const
+{
+ COLA_ASSERT((vert == m_vert1) || (vert == m_vert2));
+
+ return (vert == m_vert1) ? m_vert2 : m_vert1;
}
@@ -565,7 +607,7 @@ EdgeInf *EdgeInf::checkEdgeVisibility(VertInf *i, VertInf *j, bool knownNew)
}
}
edge->checkVis();
- if (!(edge->_added) && !(router->InvisibilityGrph))
+ if (!(edge->m_added) && !(router->InvisibilityGrph))
{
delete edge;
edge = NULL;
@@ -575,7 +617,7 @@ EdgeInf *EdgeInf::checkEdgeVisibility(VertInf *i, VertInf *j, bool knownNew)
}
- // XXX: This function is ineffecient, and shouldn't even really be
+ // XXX: This function is inefficient, and shouldn't even really be
// required.
EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
{
@@ -594,7 +636,7 @@ EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
}
}
- // Look through orthogonal visbility edges.
+ // Look through orthogonal visibility edges.
selected = (i->orthogVisListSize <= j->orthogVisListSize) ? i : j;
EdgeInfList& orthogVisList = selected->orthogVisList;
finish = orthogVisList.end();
@@ -607,7 +649,7 @@ EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
}
}
- // Look through poly-line invisbility edges.
+ // Look through poly-line invisibility edges.
selected = (i->invisListSize <= j->invisListSize) ? i : j;
EdgeInfList& invisList = selected->invisList;
finish = invisList.end();
@@ -628,10 +670,10 @@ EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
EdgeList::EdgeList(bool orthogonal)
- : _orthogonal(orthogonal),
- _firstEdge(NULL),
- _lastEdge(NULL),
- _count(0)
+ : m_orthogonal(orthogonal),
+ m_first_edge(NULL),
+ m_last_edge(NULL),
+ m_count(0)
{
}
@@ -644,47 +686,54 @@ EdgeList::~EdgeList()
void EdgeList::clear(void)
{
- while (_firstEdge)
+ while (m_first_edge)
{
- delete _firstEdge;
+ // The Edge destructor results in EdgeList:::removeEdge() being called
+ // for this edge and m_first_edge being updated to the subsequent edge
+ // in the EdgeList.
+ delete m_first_edge;
}
- COLA_ASSERT(_count == 0);
- _lastEdge = NULL;
+ COLA_ASSERT(m_count == 0);
+ m_last_edge = NULL;
}
int EdgeList::size(void) const
{
- return _count;
+ return m_count;
}
void EdgeList::addEdge(EdgeInf *edge)
{
- COLA_ASSERT(!_orthogonal || edge->isOrthogonal());
+ // Dummy connections for ShapeConnectionPins won't be orthogonal,
+ // even in the orthogonal visibility graph.
+ COLA_UNUSED(m_orthogonal);
+ COLA_ASSERT(!m_orthogonal || edge->isOrthogonal() ||
+ edge->isDummyConnection());
- if (_firstEdge == NULL)
+ if (m_first_edge == NULL)
{
- COLA_ASSERT(_lastEdge == NULL);
+ COLA_ASSERT(m_last_edge == NULL);
- _lastEdge = edge;
- _firstEdge = edge;
+ m_last_edge = edge;
+ m_first_edge = edge;
edge->lstPrev = NULL;
edge->lstNext = NULL;
}
else
{
- COLA_ASSERT(_lastEdge != NULL);
+ COLA_ASSERT(m_last_edge != NULL);
- _lastEdge->lstNext = edge;
- edge->lstPrev = _lastEdge;
+ m_last_edge->lstNext = edge;
+ edge->lstPrev = m_last_edge;
- _lastEdge = edge;
+ m_last_edge = edge;
edge->lstNext = NULL;
}
- _count++;
+ m_count++;
}
@@ -698,30 +747,30 @@ void EdgeList::removeEdge(EdgeInf *edge)
{
edge->lstNext->lstPrev = edge->lstPrev;
}
- if (edge == _lastEdge)
+ if (edge == m_last_edge)
{
- _lastEdge = edge->lstPrev;
- if (edge == _firstEdge)
+ m_last_edge = edge->lstPrev;
+ if (edge == m_first_edge)
{
- _firstEdge = NULL;
+ m_first_edge = NULL;
}
}
- else if (edge == _firstEdge)
+ else if (edge == m_first_edge)
{
- _firstEdge = edge->lstNext;
+ m_first_edge = edge->lstNext;
}
edge->lstPrev = NULL;
edge->lstNext = NULL;
- _count--;
+ m_count--;
}
EdgeInf *EdgeList::begin(void)
{
- return _firstEdge;
+ return m_first_edge;
}