Code

c0ff2f6e893d83a51d4585d8ad7abc52c0365d25
[inkscape.git] / src / libavoid / shape.cpp
1 /*
2  * vim: ts=4 sw=4 et tw=0 wm=0
3  *
4  * libavoid - Fast, Incremental, Object-avoiding Line Router
5  * Copyright (C) 2004-2006  Michael Wybrow <mjwybrow@users.sourceforge.net>
6  *
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.
11  *
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.
16  *
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
20  * 
21 */
23 #include <cassert>
25 #include "libavoid/shape.h"
26 #include "libavoid/graph.h"  // For alertConns
27 #include "libavoid/vertices.h"
28 #include "libavoid/polyutil.h"
29 #include "libavoid/router.h"
32 namespace Avoid {
35 ShapeRef::ShapeRef(Router *router, unsigned int id, Polygn& ply)
36     : _router(router)
37     , _id(id)
38     , _poly(copyPoly(ply))
39     , _active(false)
40     , _inMoveList(false)
41     , _firstVert(NULL)
42     , _lastVert(NULL)
43 {
44     bool isShape = true;
45     VertID i = VertID(id, isShape, 0);
46     
47     VertInf *last = NULL;
48     VertInf *node = NULL;
49     for (int pt_i = 0; pt_i < _poly.pn; pt_i++)
50     {
51         node = new VertInf(_router, i, _poly.ps[pt_i]);
53         if (!_firstVert)
54         {
55             _firstVert = node;
56         }
57         else
58         {
59             node->shPrev = last;
60             last->shNext = node;
61             //node->lstPrev = last;
62             //last->lstNext = node;
63         }
64         
65         last = node;
66         i++;
67     }
68     _lastVert = node;
69     
70     _lastVert->shNext = _firstVert;
71     _firstVert->shPrev = _lastVert;
72     
73     makeActive();
74 }
77 ShapeRef::~ShapeRef()
78 {
79     assert(_firstVert != NULL);
80     
81     makeInactive();
83     VertInf *it = _firstVert;
84     do
85     {
86         VertInf *tmp = it;
87         it = it->shNext;
89         delete tmp;
90     }
91     while (it != _firstVert);
92     _firstVert = _lastVert = NULL;
94     freePoly(_poly);
95 }
98 void ShapeRef::setNewPoly(Polygn& poly)
99 {
100     assert(_firstVert != NULL);
101     assert(_poly.pn == poly.pn);
102     
103     VertInf *curr = _firstVert;
104     for (int pt_i = 0; pt_i < _poly.pn; pt_i++)
105     {
106         assert(curr->visListSize == 0);
107         assert(curr->invisListSize == 0);
109         // Reset with the new polygon point.
110         curr->Reset(poly.ps[pt_i]);
111         curr->pathNext = NULL;
112         curr->pathDist = 0;
113         
114         curr = curr->shNext;
115     }
116     assert(curr == _firstVert);
117         
118     freePoly(_poly);
119     _poly = copyPoly(poly);
123 void ShapeRef::makeActive(void)
125     assert(!_active);
126     
127     // Add to connRefs list.
128     _pos = _router->shapeRefs.insert(_router->shapeRefs.begin(), this);
130     // Add points to vertex list.
131     VertInf *it = _firstVert;
132     do
133     {
134         VertInf *tmp = it;
135         it = it->shNext;
137         _router->vertices.addVertex(tmp);
138     }
139     while (it != _firstVert);
140     
141     _active = true;
145 void ShapeRef::makeInactive(void)
147     assert(_active);
148     
149     // Remove from connRefs list.
150     _router->shapeRefs.erase(_pos);
152     // Remove points from vertex list.
153     VertInf *it = _firstVert;
154     do
155     {
156         VertInf *tmp = it;
157         it = it->shNext;
159         _router->vertices.removeVertex(tmp);
160     }
161     while (it != _firstVert);
162     
163     _active = false;
165     
167 VertInf *ShapeRef::firstVert(void)
169     return _firstVert;
173 VertInf *ShapeRef::lastVert(void)
175     return _lastVert;
179 unsigned int ShapeRef::id(void)
181     return _id;
185 Polygn ShapeRef::poly(void)
187     return _poly;
191 Router *ShapeRef::router(void)
193     return _router;
197 void ShapeRef::boundingBox(BBox& bbox)
199     assert(_poly.pn > 0);
201     bbox.a = bbox.b = _poly.ps[0];
202     Point& a = bbox.a;
203     Point& b = bbox.b;
205     for (int i = 1; i < _poly.pn; ++i)
206     {
207         const Point& p = _poly.ps[i];
209         a.x = std::min(p.x, a.x);
210         a.y = std::min(p.y, a.y);
211         b.x = std::max(p.x, b.x);
212         b.y = std::max(p.y, b.y);
213     }
217 void ShapeRef::removeFromGraph(void)
219     for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
220     {
221         VertInf *tmp = iter;
222         iter = iter->lstNext;
223         
224         // For each vertex.
225         EdgeInfList& visList = tmp->visList;
226         EdgeInfList::iterator finish = visList.end();
227         EdgeInfList::iterator edge;
228         while ((edge = visList.begin()) != finish)
229         {
230             // Remove each visibility edge
231             (*edge)->alertConns();
232             delete (*edge);
233         }
235         EdgeInfList& invisList = tmp->invisList;
236         finish = invisList.end();
237         while ((edge = invisList.begin()) != finish)
238         {
239             // Remove each invisibility edge
240             delete (*edge);
241         }
242     }
246 void ShapeRef::markForMove(void)
248     if (!_inMoveList)
249     {
250         _inMoveList = true;
251     }
252     else
253     {
254         fprintf(stderr, "WARNING: two moves queued for same shape prior to "
255                 "rerouting.\n         This is not safe.\n");
256     }
260 void ShapeRef::clearMoveMark(void)
262     _inMoveList = false;
266 VertInf *ShapeRef::getPointVertex(const Point& point)
268     VertInf *curr = _firstVert;
269     do
270     {
271         if (curr->point == point)
272         {
273             return curr;
274         }
275         curr = curr->shNext;
276     }
277     while (curr != _firstVert);
279     return NULL;