index c4dc8961f5fb714c9ff032ff20141a3e949a13b9..6570962a9f13beaf768dc1af62b32047a186094c 100644 (file)
--- a/src/libavoid/router.cpp
+++ b/src/libavoid/router.cpp
#include "libavoid/connector.h"
#include "libavoid/polyutil.h"
#include "libavoid/debug.h"
#include "libavoid/connector.h"
#include "libavoid/polyutil.h"
#include "libavoid/debug.h"
+#include "libavoid/region.h"
#include "math.h"
//#define ORTHOGONAL_ROUTING
#include "math.h"
//#define ORTHOGONAL_ROUTING
namespace Avoid {
namespace Avoid {
+static const unsigned int infoAdd = 1;
+static const unsigned int infoDel = 2;
+static const unsigned int infoMov = 3;
+
+
+class MoveInfo {
+ public:
+ MoveInfo(ShapeRef *s, Polygn *p, bool fM)
+ : shape(s)
+ , newPoly(copyPoly(*p))
+ , firstMove(fM)
+ { }
+ ~MoveInfo()
+ {
+ freePoly(newPoly);
+ }
+ ShapeRef *shape;
+ Polygn newPoly;
+ bool firstMove;
+};
+
+
+
Router::Router()
: PartialTime(false)
Router::Router()
: PartialTime(false)
+ , segmt_penalty(0)
+ , angle_penalty(0)
+ , crossing_penalty(200)
// Algorithm options:
, UseAStarSearch(true)
, IgnoreRegions(true)
// Algorithm options:
, UseAStarSearch(true)
, IgnoreRegions(true)
, IncludeEndpoints(true)
, UseLeesAlgorithm(false)
, InvisibilityGrph(true)
, IncludeEndpoints(true)
, UseLeesAlgorithm(false)
, InvisibilityGrph(true)
- , ConsolidateMoves(false)
+ , ConsolidateMoves(true)
, PartialFeedback(false)
// Instrumentation:
, st_checked_edges(0)
, PartialFeedback(false)
// Instrumentation:
, st_checked_edges(0)
void Router::moveShape(ShapeRef *shape, Polygn *newPoly, const bool first_move)
{
void Router::moveShape(ShapeRef *shape, Polygn *newPoly, const bool first_move)
{
- unsigned int pid = shape->id();
- bool notPartialTime = !(PartialFeedback && PartialTime);
+ // Sanely cope with the case where the user requests moving the same
+ // shape multiple times before rerouting connectors.
+ bool alreadyThere = false;
+ unsigned int id = shape->id();
+ MoveInfoList::iterator finish = moveList.end();
+ for (MoveInfoList::iterator it = moveList.begin(); it != finish; ++it)
+ {
+ if ((*it)->shape->id() == id)
+ {
+ fprintf(stderr,
+ "warning: multiple moves requested for shape %d.\n",
+ (int) id);
+ // Just update the MoveInfo with the second polygon, but
+ // leave the firstMove setting alone.
+ (*it)->newPoly = copyPoly(*newPoly);
+ alreadyThere = true;
+ }
+ }
- // o Remove entries related to this shape's vertices
- shape->removeFromGraph();
-
- if (SelectiveReroute && (notPartialTime || first_move))
+ if (!alreadyThere)
{
{
- markConnectors(shape);
+ MoveInfo *moveInfo = new MoveInfo(shape, newPoly, first_move);
+ moveList.push_back(moveInfo);
}
}
- adjustContainsWithDel(pid);
-
+ if (!ConsolidateMoves)
+ {
+ processMoves();
+ }
+}
+
+
+void Router::processMoves(void)
+{
+ if (moveList.empty())
+ {
+ return;
+ }
+
+ MoveInfoList::iterator curr;
+ MoveInfoList::iterator finish = moveList.end();
+ for (curr = moveList.begin(); curr != finish; ++curr)
+ {
+ MoveInfo *moveInf = *curr;
+ ShapeRef *shape = moveInf->shape;
+ Polygn *newPoly = &(moveInf->newPoly);
+ bool first_move = moveInf->firstMove;
+
+ unsigned int pid = shape->id();
+ bool notPartialTime = !(PartialFeedback && PartialTime);
+
+ // o Remove entries related to this shape's vertices
+ shape->removeFromGraph();
+
+ if (SelectiveReroute && (notPartialTime || first_move))
+ {
+ markConnectors(shape);
+ }
+
+ adjustContainsWithDel(pid);
+
#ifdef ORTHOGONAL_ROUTING
#ifdef ORTHOGONAL_ROUTING
- Region::removeShape(shape);
+ Region::removeShape(shape);
#endif
#endif
- shape->setNewPoly(*newPoly);
+ shape->setNewPoly(*newPoly);
+
+ adjustContainsWithAdd(*newPoly, pid);
- adjustContainsWithAdd(*newPoly, pid);
+ // Ignore this shape for visibility.
+ // XXX: We don't really need to do this if we're not using Partial
+ // Feedback. Without this the blocked edges still route
+ // around the shape until it leaves the connector.
+ shape->makeInactive();
+
+ }
- // o Check all edges that were blocked by this shape.
if (InvisibilityGrph)
{
if (InvisibilityGrph)
{
- checkAllBlockedEdges(pid);
+ for (curr = moveList.begin(); curr != finish; ++curr)
+ {
+ MoveInfo *moveInf = *curr;
+ ShapeRef *shape = moveInf->shape;
+ unsigned int pid = shape->id();
+
+ // o Check all edges that were blocked by this shape.
+ checkAllBlockedEdges(pid);
+ }
}
else
{
}
else
{
@@ -150,31 +240,46 @@ void Router::moveShape(ShapeRef *shape, Polygn *newPoly, const bool first_move)
checkAllMissingEdges();
}
checkAllMissingEdges();
}
+ while ( ! moveList.empty() )
+ {
+ MoveInfo *moveInf = moveList.front();
+ ShapeRef *shape = moveInf->shape;
+ Polygn *newPoly = &(moveInf->newPoly);
+
+ unsigned int pid = shape->id();
+ bool notPartialTime = !(PartialFeedback && PartialTime);
+
+ // Restore this shape for visibility.
+ shape->makeActive();
+
#ifdef ORTHOGONAL_ROUTING
#ifdef ORTHOGONAL_ROUTING
- Region::addShape(shape);
+ Region::addShape(shape);
#endif
#endif
- // o Check all visibility edges to see if this one shape
- // blocks them.
- if (notPartialTime)
- {
- newBlockingShape(newPoly, pid);
- }
+ // o Check all visibility edges to see if this one shape
+ // blocks them.
+ if (notPartialTime)
+ {
+ newBlockingShape(newPoly, pid);
+ }
- // o Calculate visibility for the new vertices.
- if (UseLeesAlgorithm)
- {
- shapeVisSweep(shape);
- }
- else
- {
- shapeVis(shape);
+ // o Calculate visibility for the new vertices.
+ if (UseLeesAlgorithm)
+ {
+ shapeVisSweep(shape);
+ }
+ else
+ {
+ shapeVis(shape);
+ }
+
+ moveList.pop_front();
+ delete moveInf;
}
callbackAllInvalidConnectors();
}
}
callbackAllInvalidConnectors();
}
-
//----------------------------------------------------------------------------
// XXX: attachedShapes and attachedConns both need to be rewritten
//----------------------------------------------------------------------------
// XXX: attachedShapes and attachedConns both need to be rewritten
for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
if ((type & runningTo) && ((*i)->_dstId == shapeId)) {
for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
if ((type & runningTo) && ((*i)->_dstId == shapeId)) {
- conns.push_back((*i)->_srcId);
+ conns.push_back((*i)->_id);
}
else if ((type & runningFrom) && ((*i)->_srcId == shapeId)) {
}
else if ((type & runningFrom) && ((*i)->_srcId == shapeId)) {
- conns.push_back((*i)->_dstId);
+ conns.push_back((*i)->_id);
}
}
}
}
}
}
if (tmp->getDist() != 0)
{
if (tmp->getDist() != 0)
{
- pair<VertID, VertID> ids(tmp->ids());
+ std::pair<VertID, VertID> ids(tmp->ids());
VertID eID1 = ids.first;
VertID eID2 = ids.second;
VertID eID1 = ids.first;
VertID eID2 = ids.second;
- pair<Point, Point> points(tmp->points());
+ std::pair<Point, Point> points(tmp->points());
Point e1 = points.first;
Point e2 = points.second;
bool blocked = false;
Point e1 = points.first;
Point e2 = points.second;
bool blocked = false;
// Ignore uninitialised connectors.
continue;
}
// Ignore uninitialised connectors.
continue;
}
+ else if (conn->_needs_reroute_flag)
+ {
+ // Already marked, so skip.
+ continue;
+ }
Point start = conn->_route.ps[0];
Point end = conn->_route.ps[conn->_route.pn - 1];
Point start = conn->_route.ps[0];
Point end = conn->_route.ps[conn->_route.pn - 1];
else
{
// Need to do rotation
else
{
// Need to do rotation
- Point n_p2 = { p2.x - p1.x, p2.y - p1.y };
- Point n_start = { start.x - p1.x, start.y - p1.y };
- Point n_end = { end.x - p1.x, end.y - p1.y };
+ Point n_p2(p2.x - p1.x, p2.y - p1.y);
+ Point n_start(start.x - p1.x, start.y - p1.y);
+ Point n_end(end.x - p1.x, end.y - p1.y);
//printf("n_p2: (%.1f, %.1f)\n", n_p2.x, n_p2.y);
//printf("n_start: (%.1f, %.1f)\n", n_start.x, n_start.y);
//printf("n_end: (%.1f, %.1f)\n", n_end.x, n_end.y);
//printf("n_p2: (%.1f, %.1f)\n", n_p2.x, n_p2.y);
//printf("n_start: (%.1f, %.1f)\n", n_start.x, n_start.y);
//printf("n_end: (%.1f, %.1f)\n", n_end.x, n_end.y);
double theta = 0 - atan2(n_p2.y, n_p2.x);
//printf("theta = %.2f\n", theta * (180 / PI));
double theta = 0 - atan2(n_p2.y, n_p2.x);
//printf("theta = %.2f\n", theta * (180 / PI));
- Point r_p1 = {0, 0};
+ Point r_p1(0, 0);
Point r_p2 = n_p2;
start = n_start;
end = n_end;
Point r_p2 = n_p2;
start = n_start;
end = n_end;