Code

Fixed crash when draw height was zero.
[inkscape.git] / src / libavoid / connector.cpp
index 4d582174157f679df1eab4bd5ab8d2a51ebda74e..3526b3f1594b3b37e8ca52c53416ffe706d104dd 100644 (file)
@@ -2,7 +2,7 @@
  * vim: ts=4 sw=4 et tw=0 wm=0
  *
  * libavoid - Fast, Incremental, Object-avoiding Line Router
- * Copyright (C) 2004-2005  Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2004-2006  Michael Wybrow <mjwybrow@users.sourceforge.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * 
 */
 
-#include "libavoid/connector.h"
 #include "libavoid/graph.h"
+#include "libavoid/connector.h"
 #include "libavoid/makepath.h"
 #include "libavoid/visibility.h"
 #include "libavoid/debug.h"
+#include "libavoid/router.h"
 
 
 namespace Avoid {
 
     
-ConnRefList connRefs;
-
-
-ConnRef::ConnRef(const unsigned int id)
-    : _id(id)
+ConnRef::ConnRef(Router *router, const unsigned int id)
+    : _router(router)
+    , _id(id)
+    , _type(ConnType_PolyLine)
     , _srcId(0)
     , _dstId(0)
     , _needs_reroute_flag(true)
@@ -46,6 +46,7 @@ ConnRef::ConnRef(const unsigned int id)
     , _initialised(false)
     , _callback(NULL)
     , _connector(NULL)
+    , _hateCrossings(false)
 {
     // TODO: Store endpoints and details.
     _route.pn = 0;
@@ -53,8 +54,11 @@ ConnRef::ConnRef(const unsigned int id)
 }
 
 
-ConnRef::ConnRef(const unsigned int id, const Point& src, const Point& dst)
-    : _id(id)
+ConnRef::ConnRef(Router *router, const unsigned int id,
+        const Point& src, const Point& dst)
+    : _router(router)
+    , _id(id)
+    , _type(ConnType_PolyLine)
     , _srcId(0)
     , _dstId(0)
     , _needs_reroute_flag(true)
@@ -66,17 +70,18 @@ ConnRef::ConnRef(const unsigned int id, const Point& src, const Point& dst)
     , _initialised(false)
     , _callback(NULL)
     , _connector(NULL)
+    , _hateCrossings(false)
 {
     _route.pn = 0;
     _route.ps = NULL;
 
-    if (IncludeEndpoints)
+    if (_router->IncludeEndpoints)
     {
         bool isShape = false;
-        _srcVert = new VertInf(VertID(id, isShape, 1), src);
-        _dstVert = new VertInf(VertID(id, isShape, 2), dst);
-        vertices.addVertex(_srcVert);
-        vertices.addVertex(_dstVert);
+        _srcVert = new VertInf(_router, VertID(id, isShape, 1), src);
+        _dstVert = new VertInf(_router, VertID(id, isShape, 2), dst);
+        _router->vertices.addVertex(_srcVert);
+        _router->vertices.addVertex(_dstVert);
         makeActive();
         _initialised = true;
     }
@@ -89,14 +94,14 @@ ConnRef::~ConnRef()
 
     if (_srcVert)
     {
-        vertices.removeVertex(_srcVert);
+        _router->vertices.removeVertex(_srcVert);
         delete _srcVert;
         _srcVert = NULL;
     }
 
     if (_dstVert)
     {
-        vertices.removeVertex(_dstVert);
+        _router->vertices.removeVertex(_dstVert);
         delete _dstVert;
         _dstVert = NULL;
     }
@@ -107,11 +112,20 @@ ConnRef::~ConnRef()
     }
 }
 
+
+void ConnRef::setType(unsigned int type)
+{
+    _type = type;
+}
+
+
 void ConnRef::updateEndPoint(const unsigned int type, const Point& point)
 {
     assert((type == (unsigned int) VertID::src) ||
            (type == (unsigned int) VertID::tar));
-    //assert(IncludeEndpoints);
+    
+    // XXX: This was commented out.  Is there a case where it isn't true? 
+    assert(_router->IncludeEndpoints);
 
     if (!_initialised)
     {
@@ -131,8 +145,8 @@ void ConnRef::updateEndPoint(const unsigned int type, const Point& point)
         }
         else
         {
-            _srcVert = new VertInf(VertID(_id, isShape, type), point);
-            vertices.addVertex(_srcVert);
+            _srcVert = new VertInf(_router, VertID(_id, isShape, type), point);
+            _router->vertices.addVertex(_srcVert);
         }
         
         altered = _srcVert;
@@ -146,15 +160,18 @@ void ConnRef::updateEndPoint(const unsigned int type, const Point& point)
         }
         else
         {
-            _dstVert = new VertInf(VertID(_id, isShape, type), point);
-            vertices.addVertex(_dstVert);
+            _dstVert = new VertInf(_router, VertID(_id, isShape, type), point);
+            _router->vertices.addVertex(_dstVert);
         }
         
         altered = _dstVert;
         partner = _srcVert;
     }
-
-    bool knownNew = false;
+    
+    // XXX: Seems to be faster to just remove the edges and recreate
+    bool isConn = true;
+    altered->removeFromGraph(isConn);
+    bool knownNew = true;
     vertexVisibility(altered, partner, knownNew, true);
 }
 
@@ -172,12 +189,24 @@ void ConnRef::setEndPointId(const unsigned int type, const unsigned int id)
 }
 
 
+unsigned int ConnRef::getSrcShapeId(void)
+{
+    return _srcId;
+}
+
+
+unsigned int ConnRef::getDstShapeId(void)
+{
+    return _dstId;
+}
+
+
 void ConnRef::makeActive(void)
 {
     assert(!_active);
     
     // Add to connRefs list.
-    _pos = connRefs.insert(connRefs.begin(), this);
+    _pos = _router->connRefs.insert(_router->connRefs.begin(), this);
     _active = true;
 }
 
@@ -187,7 +216,7 @@ void ConnRef::makeInactive(void)
     assert(_active);
     
     // Remove from connRefs list.
-    connRefs.erase(_pos);
+    _router->connRefs.erase(_pos);
     _active = false;
 }
 
@@ -225,30 +254,26 @@ bool ConnRef::needsReroute(void)
 }
 
 
-void ConnRef::moveRoute(const int& diff_x, const int& diff_y)
-{
-    for (int i = 0; i < _route.pn; i++)
-    {
-        _route.ps[i].x += diff_x;
-        _route.ps[i].y += diff_y;
-    }
-}
-
-
 void ConnRef::lateSetup(const Point& src, const Point& dst)
 {
     assert(!_initialised);
 
     bool isShape = false;
-    _srcVert = new VertInf(VertID(_id, isShape, 1), src);
-    _dstVert = new VertInf(VertID(_id, isShape, 2), dst);
-    vertices.addVertex(_srcVert);
-    vertices.addVertex(_dstVert);
+    _srcVert = new VertInf(_router, VertID(_id, isShape, 1), src);
+    _dstVert = new VertInf(_router, VertID(_id, isShape, 2), dst);
+    _router->vertices.addVertex(_srcVert);
+    _router->vertices.addVertex(_dstVert);
     makeActive();
     _initialised = true;
 }
 
 
+unsigned int ConnRef::id(void)
+{
+    return _id;
+}
+
+
 VertInf *ConnRef::src(void)
 {
     return _srcVert;
@@ -269,8 +294,8 @@ bool ConnRef::isInitialised(void)
 
 void ConnRef::unInitialise(void)
 {
-    vertices.removeVertex(_srcVert);
-    vertices.removeVertex(_dstVert);
+    _router->vertices.removeVertex(_srcVert);
+    _router->vertices.removeVertex(_dstVert);
     makeInactive();
     _initialised = false;
 }
@@ -327,6 +352,12 @@ void ConnRef::makePathInvalid(void)
 }
 
 
+Router *ConnRef::router(void)
+{
+    return _router;
+}
+
+
 int ConnRef::generatePath(Point p0, Point p1)
 {
     if (!_false_path && !_needs_reroute_flag) {
@@ -340,7 +371,7 @@ int ConnRef::generatePath(Point p0, Point p1)
     VertInf *src = _srcVert;
     VertInf *tar = _dstVert;
 
-    if (!IncludeEndpoints)
+    if ( !(_router->IncludeEndpoints) )
     {
         lateSetup(p0, p1);
         
@@ -349,8 +380,9 @@ int ConnRef::generatePath(Point p0, Point p1)
         tar = _dstVert;
    
         bool knownNew = true;
-        vertexVisibility(src, tar, knownNew);
-        vertexVisibility(tar, src, knownNew);
+        bool genContains = true;
+        vertexVisibility(src, tar, knownNew, genContains);
+        vertexVisibility(tar, src, knownNew, genContains);
     }
 
     bool *flag = &(_needs_reroute_flag);
@@ -368,7 +400,7 @@ int ConnRef::generatePath(Point p0, Point p1)
             db_printf("Warning: Path not found...\n");
             pathlen = 2;
             tar->pathNext = src;
-            if (InvisibilityGrph)
+            if (_router->InvisibilityGrph)
             {
                 // TODO:  Could we know this edge already?
                 EdgeInf *edge = EdgeInf::existingEdge(src, tar);
@@ -389,7 +421,7 @@ int ConnRef::generatePath(Point p0, Point p1)
     int j = pathlen - 1;
     for (VertInf *i = tar; i != src; i = i->pathNext)
     {
-        if (InvisibilityGrph)
+        if (_router->InvisibilityGrph)
         {
             // TODO: Again, we could know this edge without searching.
             EdgeInf *edge = EdgeInf::existingEdge(i, i->pathNext);
@@ -399,7 +431,9 @@ int ConnRef::generatePath(Point p0, Point p1)
         {
             _false_path = true;
         }
-        path[j--] = i->point;
+        path[j] = i->point;
+        path[j].id = i->id.objID;
+        j--;
     }
     path[0] = src->point;
 
@@ -409,75 +443,30 @@ int ConnRef::generatePath(Point p0, Point p1)
     PolyLine& output_route = route();
     output_route.pn = pathlen;
     output_route.ps = path;
+    if ( !(_router->IncludeEndpoints) )
+    {
+        assert(_initialised);
+        unInitialise();
+    }
    
     return (int) result;
 }
 
 
-//============================================================================
-
-const unsigned int ConnRef::runningTo = 1;
-const unsigned int ConnRef::runningFrom = 2;
-const unsigned int ConnRef::runningToAndFrom =
-        ConnRef::runningTo | ConnRef::runningFrom;
-
-// XXX: attachedShapes and attachedConns both need to be rewritten
-//      for constant time lookup of attached objects once this info
-//      is stored better within libavoid.
-
-
-    // Returns a list of connector Ids of all the connectors of type
-    // 'type' attached to the shape with the ID 'shapeId'.
-void attachedConns(IntList &conns, const unsigned int shapeId,
-        const unsigned int type)
+void ConnRef::setHateCrossings(bool value)
 {
-    ConnRefList::iterator fin = connRefs.end();
-    for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
-        if ((type & ConnRef::runningTo) && ((*i)->_dstId == shapeId)) {
-            conns.push_back((*i)->_srcId);
-        }
-        else if ((type & ConnRef::runningFrom) && ((*i)->_srcId == shapeId)) {
-            conns.push_back((*i)->_dstId);
-        }
-    }
+    _hateCrossings = value;
 }
 
 
-    // Returns a list of shape Ids of all the shapes attached to the
-    // shape with the ID 'shapeId' with connection type 'type'.
-void attachedShapes(IntList &shapes, const unsigned int shapeId,
-        const unsigned int type)
+bool ConnRef::doesHateCrossings(void)
 {
-    ConnRefList::iterator fin = connRefs.end();
-    for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
-        if ((type & ConnRef::runningTo) && ((*i)->_dstId == shapeId)) {
-            if ((*i)->_srcId != 0)
-            {
-                // Only if there is a shape attached to the other end.
-                shapes.push_back((*i)->_srcId);
-            }
-        }
-        else if ((type & ConnRef::runningFrom) && ((*i)->_srcId == shapeId)) {
-            if ((*i)->_dstId != 0)
-            {
-                // Only if there is a shape attached to the other end.
-                shapes.push_back((*i)->_dstId);
-            }
-        }
-    }
+    return _hateCrossings;
 }
 
 
-    // It's intended this function is called after shape movement has 
-    // happened to alert connectors that they need to be rerouted.
-void callbackAllInvalidConnectors(void)
-{
-    ConnRefList::iterator fin = connRefs.end();
-    for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
-        (*i)->handleInvalid();
-    }
-}
-
+//============================================================================
 
 }