Code

Various snapping cleanups and bug fixes.
[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     , _firstVert(NULL)
41     , _lastVert(NULL)
42 {
43     bool isShape = true;
44     VertID i = VertID(id, isShape, 0);
45     
46     VertInf *last = NULL;
47     VertInf *node = NULL;
48     for (int pt_i = 0; pt_i < _poly.pn; pt_i++)
49     {
50         node = new VertInf(_router, i, _poly.ps[pt_i]);
52         if (!_firstVert)
53         {
54             _firstVert = node;
55         }
56         else
57         {
58             node->shPrev = last;
59             last->shNext = node;
60             //node->lstPrev = last;
61             //last->lstNext = node;
62         }
63         _router->vertices.addVertex(node);
64         
65         last = node;
66         i++;
67         // Increase total vertices count ++;
68     }
69     _lastVert = node;
70     
71     _lastVert->shNext = _firstVert;
72     _firstVert->shPrev = _lastVert;
73     
74     // Increase total shape count ++;
75     makeActive();
76 }
79 ShapeRef::~ShapeRef()
80 {
81     assert(_firstVert != NULL);
82     
83     VertInf *it = _firstVert;
84     do
85     {
86         VertInf *tmp = it;
87         it = it->shNext;
89         // XXX: This could possibly be done less
90         //      safely but faster, all at once.
91         _router->vertices.removeVertex(tmp);
92         delete tmp;
93     }
94     while (it != _firstVert);
95     _firstVert = _lastVert = NULL;
97     freePoly(_poly);
98     
99     makeInactive();
103 void ShapeRef::setNewPoly(Polygn& poly)
105     assert(_firstVert != NULL);
106     assert(_poly.pn == poly.pn);
107     
108     VertInf *curr = _firstVert;
109     for (int pt_i = 0; pt_i < _poly.pn; pt_i++)
110     {
111         assert(curr->visListSize == 0);
112         assert(curr->invisListSize == 0);
114         // Reset with the new polygon point.
115         curr->Reset(poly.ps[pt_i]);
116         curr->pathNext = NULL;
117         curr->pathDist = 0;
118         
119         curr = curr->shNext;
120     }
121     assert(curr == _firstVert);
122         
123     freePoly(_poly);
124     _poly = copyPoly(poly);
128 void ShapeRef::makeActive(void)
130     assert(!_active);
131     
132     // Add to connRefs list.
133     _pos = _router->shapeRefs.insert(_router->shapeRefs.begin(), this);
134     _active = true;
138 void ShapeRef::makeInactive(void)
140     assert(_active);
141     
142     // Remove from connRefs list.
143     _router->shapeRefs.erase(_pos);
144     _active = false;
146     
148 VertInf *ShapeRef::firstVert(void)
150     return _firstVert;
154 VertInf *ShapeRef::lastVert(void)
156     return _lastVert;
160 unsigned int ShapeRef::id(void)
162     return _id;
166 Polygn ShapeRef::poly(void)
168     return _poly;
172 Router *ShapeRef::router(void)
174     return _router;
178 void ShapeRef::boundingBox(BBox& bbox)
180     assert(_poly.pn > 0);
182     bbox.a = bbox.b = _poly.ps[0];
183     Point& a = bbox.a;
184     Point& b = bbox.b;
186     for (int i = 1; i < _poly.pn; ++i)
187     {
188         const Point& p = _poly.ps[i];
190         a.x = (p.x < a.x) ? p.x : a.x;
191         a.y = (p.y < a.y) ? p.y : a.y;
192         b.x = (p.x > b.x) ? p.x : b.x;
193         b.y = (p.y > b.y) ? p.y : b.y;
194     }
198 void ShapeRef::removeFromGraph(void)
200     for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
201     {
202         VertInf *tmp = iter;
203         iter = iter->lstNext;
204         
205         // For each vertex.
206         EdgeInfList& visList = tmp->visList;
207         EdgeInfList::iterator finish = visList.end();
208         EdgeInfList::iterator edge;
209         while ((edge = visList.begin()) != finish)
210         {
211             // Remove each visibility edge
212             (*edge)->alertConns();
213             delete (*edge);
214         }
216         EdgeInfList& invisList = tmp->invisList;
217         finish = invisList.end();
218         while ((edge = invisList.begin()) != finish)
219         {
220             // Remove each invisibility edge
221             delete (*edge);
222         }
223     }