1 /*
2 * vim: ts=4 sw=4 et tw=0 wm=0
3 *
4 * libavoid - Fast, Incremental, Object-avoiding Line Router
5 *
6 * Copyright (C) 2004-2008 Monash University
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 * See the file LICENSE.LGPL distributed with the library.
13 *
14 * Licensees holding a valid commercial license may use this file in
15 * accordance with the commercial license agreement provided with the
16 * library.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
23 */
26 #include "libavoid/shape.h"
27 #include "libavoid/graph.h" // For alertConns
28 #include "libavoid/vertices.h"
29 #include "libavoid/router.h"
30 #include "libavoid/debug.h"
31 #include "libavoid/assertions.h"
34 namespace Avoid {
37 ShapeRef::ShapeRef(Router *router, Polygon& ply, const unsigned int id)
38 : _router(router)
39 , _poly(ply)
40 , _active(false)
41 , _inMoveList(false)
42 , _firstVert(NULL)
43 , _lastVert(NULL)
44 {
45 _id = router->assignId(id);
47 bool isShape = true;
48 VertID i = VertID(_id, isShape, 0);
50 const bool addToRouterNow = false;
51 VertInf *last = NULL;
52 VertInf *node = NULL;
53 for (size_t pt_i = 0; pt_i < _poly.size(); ++pt_i)
54 {
55 node = new VertInf(_router, i, _poly.ps[pt_i], addToRouterNow);
57 if (!_firstVert)
58 {
59 _firstVert = node;
60 }
61 else
62 {
63 node->shPrev = last;
64 last->shNext = node;
65 //node->lstPrev = last;
66 //last->lstNext = node;
67 }
69 last = node;
70 i++;
71 }
72 _lastVert = node;
74 _lastVert->shNext = _firstVert;
75 _firstVert->shPrev = _lastVert;
76 }
79 ShapeRef::~ShapeRef()
80 {
81 COLA_ASSERT(!_router->shapeInQueuedActionList(this));
83 if (_active)
84 {
85 // Destroying a shape without calling removeShape(), so do it now.
86 _router->removeShape(this);
87 _router->processTransaction();
88 }
90 COLA_ASSERT(_firstVert != NULL);
92 VertInf *it = _firstVert;
93 do
94 {
95 VertInf *tmp = it;
96 it = it->shNext;
98 delete tmp;
99 }
100 while (it != _firstVert);
101 _firstVert = _lastVert = NULL;
102 }
105 void ShapeRef::setNewPoly(const Polygon& poly)
106 {
107 COLA_ASSERT(_firstVert != NULL);
108 COLA_ASSERT(_poly.size() == poly.size());
110 VertInf *curr = _firstVert;
111 for (size_t pt_i = 0; pt_i < _poly.size(); ++pt_i)
112 {
113 COLA_ASSERT(curr->visListSize == 0);
114 COLA_ASSERT(curr->invisListSize == 0);
116 // Reset with the new polygon point.
117 curr->Reset(poly.ps[pt_i]);
118 curr->pathNext = NULL;
120 curr = curr->shNext;
121 }
122 COLA_ASSERT(curr == _firstVert);
124 _poly = poly;
125 }
128 void ShapeRef::makeActive(void)
129 {
130 COLA_ASSERT(!_active);
132 // Add to shapeRefs list.
133 _pos = _router->shapeRefs.insert(_router->shapeRefs.begin(), this);
135 // Add points to vertex list.
136 VertInf *it = _firstVert;
137 do
138 {
139 VertInf *tmp = it;
140 it = it->shNext;
142 _router->vertices.addVertex(tmp);
143 }
144 while (it != _firstVert);
146 _active = true;
147 }
150 void ShapeRef::makeInactive(void)
151 {
152 COLA_ASSERT(_active);
154 // Remove from shapeRefs list.
155 _router->shapeRefs.erase(_pos);
157 // Remove points from vertex list.
158 VertInf *it = _firstVert;
159 do
160 {
161 VertInf *tmp = it;
162 it = it->shNext;
164 _router->vertices.removeVertex(tmp);
165 }
166 while (it != _firstVert);
168 _active = false;
169 }
172 bool ShapeRef::isActive(void) const
173 {
174 return _active;
175 }
178 VertInf *ShapeRef::firstVert(void)
179 {
180 return _firstVert;
181 }
184 VertInf *ShapeRef::lastVert(void)
185 {
186 return _lastVert;
187 }
190 unsigned int ShapeRef::id(void) const
191 {
192 return _id;
193 }
196 const Polygon& ShapeRef::polygon(void) const
197 {
198 return _poly;
199 }
202 Router *ShapeRef::router(void) const
203 {
204 return _router;
205 }
208 void ShapeRef::boundingBox(BBox& bbox)
209 {
210 COLA_ASSERT(!_poly.empty());
212 bbox.a = bbox.b = _poly.ps[0];
213 Point& a = bbox.a;
214 Point& b = bbox.b;
216 for (size_t i = 1; i < _poly.size(); ++i)
217 {
218 const Point& p = _poly.ps[i];
220 a.x = std::min(p.x, a.x);
221 a.y = std::min(p.y, a.y);
222 b.x = std::max(p.x, b.x);
223 b.y = std::max(p.y, b.y);
224 }
225 }
228 void ShapeRef::removeFromGraph(void)
229 {
230 for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
231 {
232 VertInf *tmp = iter;
233 iter = iter->lstNext;
235 // For each vertex.
236 EdgeInfList& visList = tmp->visList;
237 EdgeInfList::const_iterator finish = visList.end();
238 EdgeInfList::const_iterator edge;
239 while ((edge = visList.begin()) != finish)
240 {
241 // Remove each visibility edge
242 (*edge)->alertConns();
243 delete (*edge);
244 }
246 EdgeInfList& invisList = tmp->invisList;
247 finish = invisList.end();
248 while ((edge = invisList.begin()) != finish)
249 {
250 // Remove each invisibility edge
251 delete (*edge);
252 }
254 EdgeInfList& orthogList = tmp->orthogVisList;
255 finish = orthogList.end();
256 while ((edge = orthogList.begin()) != finish)
257 {
258 // Remove each orthogonal visibility edge
259 (*edge)->alertConns();
260 delete (*edge);
261 }
262 }
263 }
266 void ShapeRef::markForMove(void)
267 {
268 if (!_inMoveList)
269 {
270 _inMoveList = true;
271 }
272 else
273 {
274 db_printf("WARNING: two moves queued for same shape prior to rerouting."
275 "\n This is not safe.\n");
276 }
277 }
280 void ShapeRef::clearMoveMark(void)
281 {
282 _inMoveList = false;
283 }
286 VertInf *ShapeRef::getPointVertex(const Point& point)
287 {
288 VertInf *curr = _firstVert;
289 do
290 {
291 if (curr->point == point)
292 {
293 return curr;
294 }
295 curr = curr->shNext;
296 }
297 while (curr != _firstVert);
299 return NULL;
300 }
303 }