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);
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 }
65 last = node;
66 i++;
67 }
68 _lastVert = node;
70 _lastVert->shNext = _firstVert;
71 _firstVert->shPrev = _lastVert;
73 makeActive();
74 }
77 ShapeRef::~ShapeRef()
78 {
79 assert(_firstVert != NULL);
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);
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;
114 curr = curr->shNext;
115 }
116 assert(curr == _firstVert);
118 freePoly(_poly);
119 _poly = copyPoly(poly);
120 }
123 void ShapeRef::makeActive(void)
124 {
125 assert(!_active);
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);
141 _active = true;
142 }
145 void ShapeRef::makeInactive(void)
146 {
147 assert(_active);
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);
163 _active = false;
164 }
167 VertInf *ShapeRef::firstVert(void)
168 {
169 return _firstVert;
170 }
173 VertInf *ShapeRef::lastVert(void)
174 {
175 return _lastVert;
176 }
179 unsigned int ShapeRef::id(void)
180 {
181 return _id;
182 }
185 Polygn ShapeRef::poly(void)
186 {
187 return _poly;
188 }
191 Router *ShapeRef::router(void)
192 {
193 return _router;
194 }
197 void ShapeRef::boundingBox(BBox& bbox)
198 {
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 }
214 }
217 void ShapeRef::removeFromGraph(void)
218 {
219 for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
220 {
221 VertInf *tmp = iter;
222 iter = iter->lstNext;
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 }
243 }
246 void ShapeRef::markForMove(void)
247 {
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 }
257 }
260 void ShapeRef::clearMoveMark(void)
261 {
262 _inMoveList = false;
263 }
266 VertInf *ShapeRef::getPointVertex(const Point& point)
267 {
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;
280 }
283 }