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);
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);
65 last = node;
66 i++;
67 // Increase total vertices count ++;
68 }
69 _lastVert = node;
71 _lastVert->shNext = _firstVert;
72 _firstVert->shPrev = _lastVert;
74 // Increase total shape count ++;
75 makeActive();
76 }
79 ShapeRef::~ShapeRef()
80 {
81 assert(_firstVert != NULL);
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);
99 makeInactive();
100 }
103 void ShapeRef::setNewPoly(Polygn& poly)
104 {
105 assert(_firstVert != NULL);
106 assert(_poly.pn == poly.pn);
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;
119 curr = curr->shNext;
120 }
121 assert(curr == _firstVert);
123 freePoly(_poly);
124 _poly = copyPoly(poly);
125 }
128 void ShapeRef::makeActive(void)
129 {
130 assert(!_active);
132 // Add to connRefs list.
133 _pos = _router->shapeRefs.insert(_router->shapeRefs.begin(), this);
134 _active = true;
135 }
138 void ShapeRef::makeInactive(void)
139 {
140 assert(_active);
142 // Remove from connRefs list.
143 _router->shapeRefs.erase(_pos);
144 _active = false;
145 }
148 VertInf *ShapeRef::firstVert(void)
149 {
150 return _firstVert;
151 }
154 VertInf *ShapeRef::lastVert(void)
155 {
156 return _lastVert;
157 }
160 unsigned int ShapeRef::id(void)
161 {
162 return _id;
163 }
166 Polygn ShapeRef::poly(void)
167 {
168 return _poly;
169 }
172 Router *ShapeRef::router(void)
173 {
174 return _router;
175 }
178 void ShapeRef::boundingBox(BBox& bbox)
179 {
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 }
195 }
198 void ShapeRef::removeFromGraph(void)
199 {
200 for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
201 {
202 VertInf *tmp = iter;
203 iter = iter->lstNext;
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 }
224 }
227 }