summaryrefslogtreecommitdiffstats
path: root/src/libavoid/connector.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/libavoid/connector.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/libavoid/connector.cpp')
-rw-r--r--src/libavoid/connector.cpp408
1 files changed, 408 insertions, 0 deletions
diff --git a/src/libavoid/connector.cpp b/src/libavoid/connector.cpp
new file mode 100644
index 000000000..cde387c5b
--- /dev/null
+++ b/src/libavoid/connector.cpp
@@ -0,0 +1,408 @@
+/*
+ * 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>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include "libavoid/graph.h"
+#include "libavoid/makepath.h"
+#include "libavoid/visibility.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+
+ConnRefList connRefs;
+
+
+ConnRef::ConnRef(const uint id)
+ : _id(id)
+ , _needs_reroute_flag(true)
+ , _false_path(false)
+ , _active(false)
+ , _route_dist(0)
+ , _srcVert(NULL)
+ , _dstVert(NULL)
+ , _initialised(false)
+ , _callback(NULL)
+ , _connector(NULL)
+{
+ // TODO: Store endpoints and details.
+ _route.pn = 0;
+ _route.ps = NULL;
+}
+
+
+ConnRef::ConnRef(const uint id, const Point& src, const Point& dst)
+ : _id(id)
+ , _needs_reroute_flag(true)
+ , _false_path(false)
+ , _active(false)
+ , _route_dist(0)
+ , _srcVert(NULL)
+ , _dstVert(NULL)
+ , _initialised(false)
+ , _callback(NULL)
+ , _connector(NULL)
+{
+ _route.pn = 0;
+ _route.ps = NULL;
+
+ if (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);
+ makeActive();
+ _initialised = true;
+ }
+}
+
+
+ConnRef::~ConnRef()
+{
+ freeRoute();
+
+ if (_srcVert)
+ {
+ vertices.removeVertex(_srcVert);
+ delete _srcVert;
+ _srcVert = NULL;
+ }
+
+ if (_dstVert)
+ {
+ vertices.removeVertex(_dstVert);
+ delete _dstVert;
+ _dstVert = NULL;
+ }
+
+ if (_active)
+ {
+ makeInactive();
+ }
+}
+
+void ConnRef::updateEndPoint(const uint type, const Point& point)
+{
+ assert((type == (uint) VertID::src) || (type == (uint) VertID::tar));
+ //assert(IncludeEndpoints);
+
+ VertInf *altered = NULL;
+ VertInf *partner = NULL;
+ bool isShape = false;
+
+ if (type == (uint) VertID::src)
+ {
+ if (_srcVert)
+ {
+ _srcVert->Reset(point);
+ }
+ else
+ {
+ _srcVert = new VertInf(VertID(_id, isShape, type), point);
+ vertices.addVertex(_srcVert);
+ }
+
+ altered = _srcVert;
+ partner = _dstVert;
+ }
+ else // if (type == (uint) VertID::dst)
+ {
+ if (_dstVert)
+ {
+ _dstVert->Reset(point);
+ }
+ else
+ {
+ _dstVert = new VertInf(VertID(_id, isShape, type), point);
+ vertices.addVertex(_dstVert);
+ }
+
+ altered = _dstVert;
+ partner = _srcVert;
+ }
+
+ bool knownNew = false;
+ vertexVisibility(altered, partner, knownNew, true);
+}
+
+
+void ConnRef::makeActive(void)
+{
+ assert(!_active);
+
+ // Add to connRefs list.
+ _pos = connRefs.insert(connRefs.begin(), this);
+ _active = true;
+}
+
+
+void ConnRef::makeInactive(void)
+{
+ assert(_active);
+
+ // Remove from connRefs list.
+ connRefs.erase(_pos);
+ _active = false;
+}
+
+
+void ConnRef::freeRoute(void)
+{
+ if (_route.ps)
+ {
+ _route.pn = 0;
+ std::free(_route.ps);
+ _route.ps = NULL;
+ }
+}
+
+
+PolyLine& ConnRef::route(void)
+{
+ return _route;
+}
+
+
+void ConnRef::calcRouteDist(void)
+{
+ _route_dist = 0;
+ for (int i = 1; i < _route.pn; i++)
+ {
+ _route_dist += dist(_route.ps[i], _route.ps[i - 1]);
+ }
+}
+
+
+bool ConnRef::needsReroute(void)
+{
+ return (_false_path || _needs_reroute_flag);
+}
+
+
+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);
+ makeActive();
+ _initialised = true;
+}
+
+
+VertInf *ConnRef::src(void)
+{
+ return _srcVert;
+}
+
+
+VertInf *ConnRef::dst(void)
+{
+ return _dstVert;
+}
+
+
+bool ConnRef::isInitialised(void)
+{
+ return _initialised;
+}
+
+
+void ConnRef::unInitialise(void)
+{
+ vertices.removeVertex(_srcVert);
+ vertices.removeVertex(_dstVert);
+ makeInactive();
+ _initialised = false;
+}
+
+
+void ConnRef::removeFromGraph(void)
+{
+ for (VertInf *iter = _srcVert; iter != NULL; )
+ {
+ VertInf *tmp = iter;
+ iter = (iter == _srcVert) ? _dstVert : NULL;
+
+ // For each vertex.
+ EdgeInfList& visList = tmp->visList;
+ EdgeInfList::iterator finish = visList.end();
+ EdgeInfList::iterator edge;
+ while ((edge = visList.begin()) != finish)
+ {
+ // Remove each visibility edge
+ delete (*edge);
+ }
+
+ EdgeInfList& invisList = tmp->invisList;
+ finish = invisList.end();
+ while ((edge = invisList.begin()) != finish)
+ {
+ // Remove each invisibility edge
+ delete (*edge);
+ }
+ }
+}
+
+
+void ConnRef::setCallback(void (*cb)(void *), void *ptr)
+{
+ _callback = cb;
+ _connector = ptr;
+}
+
+
+void ConnRef::handleInvalid(void)
+{
+ if (_false_path || _needs_reroute_flag) {
+ if (_callback) {
+ _callback(_connector);
+ }
+ }
+}
+
+
+void ConnRef::makePathInvalid(void)
+{
+ _needs_reroute_flag = true;
+}
+
+
+int ConnRef::generatePath(Point p0, Point p1)
+{
+ if (!_false_path && !_needs_reroute_flag) {
+ // This connector is up to date.
+ return (int) false;
+ }
+
+ _false_path = false;
+ _needs_reroute_flag = false;
+
+ VertInf *src = _srcVert;
+ VertInf *tar = _dstVert;
+
+ if (!IncludeEndpoints)
+ {
+ lateSetup(p0, p1);
+
+ // Update as they have just been set by lateSetup.
+ src = _srcVert;
+ tar = _dstVert;
+
+ bool knownNew = true;
+ vertexVisibility(src, tar, knownNew);
+ vertexVisibility(tar, src, knownNew);
+ }
+
+ bool *flag = &(_needs_reroute_flag);
+
+ makePath(this, flag);
+
+ bool result = true;
+
+ int pathlen = 1;
+ for (VertInf *i = tar; i != src; i = i->pathNext)
+ {
+ pathlen++;
+ if (i == NULL)
+ {
+ db_printf("Warning: Path not found...\n");
+ pathlen = 2;
+ tar->pathNext = src;
+ if (InvisibilityGrph)
+ {
+ // TODO: Could we know this edge already?
+ EdgeInf *edge = EdgeInf::existingEdge(src, tar);
+ assert(edge != NULL);
+ edge->addCycleBlocker();
+ }
+ result = false;
+ break;
+ }
+ if (pathlen > 100)
+ {
+ fprintf(stderr, "ERROR: Should never be here...\n");
+ exit(1);
+ }
+ }
+ Point *path = (Point *) malloc(pathlen * sizeof(Point));
+
+ int j = pathlen - 1;
+ for (VertInf *i = tar; i != src; i = i->pathNext)
+ {
+ if (InvisibilityGrph)
+ {
+ // TODO: Again, we could know this edge without searching.
+ EdgeInf *edge = EdgeInf::existingEdge(i, i->pathNext);
+ edge->addConn(flag);
+ }
+ else
+ {
+ _false_path = true;
+ }
+ path[j--] = i->point;
+ }
+ path[0] = src->point;
+
+
+ // Would clear visibility for endpoints here if required.
+
+ PolyLine& output_route = route();
+ output_route.pn = pathlen;
+ output_route.ps = path;
+
+ return (int) result;
+}
+
+
+//============================================================================
+
+
+ // 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();
+ }
+}
+
+
+}
+
+