Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
hyperedge.cpp
Go to the documentation of this file.
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) 2011-2014 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
23*/
24
25#include "libavoid/hyperedge.h"
27#include "libavoid/mtst.h"
28#include "libavoid/junction.h"
29#include "libavoid/connector.h"
30#include "libavoid/vertices.h"
31#include "libavoid/connend.h"
32#include "libavoid/shape.h"
33#include "libavoid/router.h"
34#include "libavoid/assertions.h"
36#include "libavoid/debug.h"
37
38
39namespace Avoid {
40
42 : m_router(nullptr)
43{
44}
45
47{
48 m_router = router;
49}
50
52 ConnEndList terminals)
53{
54 m_terminals_vector.push_back(terminals);
55 m_root_junction_vector.push_back(nullptr);
56
57 return m_terminals_vector.size() - 1;
58}
59
61 JunctionRef *junction)
62{
64 m_root_junction_vector.push_back(junction);
65
66 return m_terminals_vector.size() - 1;
67}
68
69size_t HyperedgeRerouter::count(void) const
70{
71 return m_terminals_vector.size();
72}
73
88
89
91{
92 if (count() == 0)
93 {
94 return;
95 }
96
97 fprintf(fp, " HyperedgeRerouter *hyperedgeRerouter = router->hyperedgeRerouter();\n");
98 const size_t num_hyperedges = count();
99 for (size_t i = 0; i < num_hyperedges; ++i)
100 {
102 {
103 fprintf(fp, " hyperedgeRerouter->registerHyperedgeForRerouting(junctionRef%u);\n",
104 m_root_junction_vector[i]->id());
105 }
106 else
107 {
108 fprintf(fp, " ConnEndList heConnList%u;\n", (unsigned int) i);
109 for (ConnEndList::const_iterator it = m_terminals_vector[i].begin();
110 it != m_terminals_vector[i].end(); ++it)
111 {
112 (*it).outputCode(fp, "heEnd");
113 fprintf(fp, " heConnList%u.push_back(heEndPt);\n",
114 (unsigned int) i);
115 }
116 fprintf(fp, " hyperedgeRerouter->registerHyperedgeForRerouting(heConnList%u);\n",
117 (unsigned int) i);
118
119 }
120 }
121 fprintf(fp, "\n");
122}
123
124
125// Follow connected junctions and connectors from the given connector to
126// determine the hyperedge topology, saving objects to the deleted-objects
127// vectors as we go.
129 ConnRef *connector, JunctionRef *ignore, ConnRefSet& hyperedgeConns)
130{
131 bool validHyperedge = false;
132
133 connector->assignConnectionPinVisibility(true);
134
135 m_deleted_connectors_vector[index].push_back(connector);
136 hyperedgeConns.insert(connector);
137
138 std::pair<Obstacle *, Obstacle *> anchors = connector->endpointAnchors();
139 JunctionRef *jFirst = dynamic_cast<JunctionRef *> (anchors.first);
140 JunctionRef *jSecond = dynamic_cast<JunctionRef *> (anchors.second);
141
142 if (jFirst)
143 {
144 // If attached to a junction and not one we've explored, then continue.
145 if (jFirst != ignore)
146 {
147 validHyperedge |= findAttachedObjects(index, jFirst, connector, hyperedgeConns);
148 }
149 }
150 else
151 {
152 // If its an endpoint, then record the vertex for this endpoint.
153 COLA_ASSERT(connector->m_src_vert);
154 m_terminal_vertices_vector[index].insert(connector->m_src_vert);
155 }
156
157 if (jSecond)
158 {
159 // If attached to a junction and not one we've explored, then continue.
160 if (jSecond != ignore)
161 {
162 validHyperedge |= findAttachedObjects(index, jSecond, connector, hyperedgeConns);
163 }
164 }
165 else
166 {
167 // If its an endpoint, then record the vertex for this endpoint.
168 COLA_ASSERT(connector->m_dst_vert);
169 m_terminal_vertices_vector[index].insert(connector->m_dst_vert);
170 }
171 return validHyperedge;
172}
173
174
175// Follow connected junctions and connectors from the given junction to
176// determine the hyperedge topology, saving objects to the deleted-objects
177// vectors as we go.
179 JunctionRef *junction, ConnRef *ignore, ConnRefSet& hyperedgeConns)
180{
181 bool validHyperedge = false;
182
183 m_deleted_junctions_vector[index].push_back(junction);
184
185 ConnRefList connectors = junction->attachedConnectors();
186
187 if (connectors.size() > 2)
188 {
189 // A valid hyperedge must have at least one junction with three
190 // connectors attached, i.e., more than two endpoints.
191 validHyperedge |= true;
192 }
193
194 for (ConnRefList::iterator curr = connectors.begin();
195 curr != connectors.end(); ++curr)
196 {
197 if (*curr == ignore)
198 {
199 continue;
200 }
201
202 COLA_ASSERT(*curr != nullptr);
203 validHyperedge |= findAttachedObjects(index, (*curr), junction, hyperedgeConns);
204 }
205 return validHyperedge;
206}
207
208
209// Populate the deleted-object vectors with all the connectors and junctions
210// that form the registered hyperedges. Then return the set of all these
211// connectors so they can be ignored for individual rerouting.
213{
214 COLA_ASSERT(m_router != nullptr);
215
216 ConnRefSet allRegisteredHyperedgeConns;
217
218 // Clear the deleted-object vectors. We populate them here if necessary.
223
226 m_added_vertices.clear();
227
228 // Populate the deleted-object vectors.
229 const size_t num_hyperedges = count();
230 for (size_t i = 0; i < num_hyperedges; ++i)
231 {
233 {
234 // Follow objects attached to junction to find the hyperedge.
235 bool valid = findAttachedObjects(i, m_root_junction_vector[i], nullptr,
236 allRegisteredHyperedgeConns);
237 if (!valid)
238 {
239 err_printf("Warning: Hyperedge %d registered with "
240 "HyperedgeRerouter is invalid and will be "
241 "ignored.\n", (int) i);
242 // Hyperedge is invalid. Clear the terminals and other info
243 // so it will be ignored, and rerouted as a normal set of
244 // connectors.
245 m_terminals_vector[i].clear();
249 }
250 continue;
251 }
252
253 // Alternatively, we have a set of ConnEnds, so store the
254 // corresponding terminals
255 std::pair<bool, VertInf *> maybeNewVertex;
256 for (ConnEndList::const_iterator it = m_terminals_vector[i].begin();
257 it != m_terminals_vector[i].end(); ++it)
258 {
259 maybeNewVertex = it->getHyperedgeVertex(m_router);
260 COLA_ASSERT(maybeNewVertex.second != nullptr);
261 m_terminal_vertices_vector[i].insert(maybeNewVertex.second);
262
263 if (maybeNewVertex.first)
264 {
265 // This is a newly created vertex. Remember it so we can
266 // free it and it's visibility edges later.
267 m_added_vertices.push_back(maybeNewVertex.second);
268 }
269 }
270 }
271
272 // Return these connectors that don't require rerouting.
273 return allRegisteredHyperedgeConns;
274}
275
276
278{
279 COLA_ASSERT(m_router != nullptr);
280
285
286#ifdef DEBUGHANDLER
287 if (m_router->debugHandler())
288 {
289 std::vector<Box> obstacleBoxes;
290 ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin();
291 while (obstacleIt != m_router->m_obstacles.end())
292 {
293 Obstacle *obstacle = *obstacleIt;
294 JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
295 if (junction && ! junction->positionFixed())
296 {
297 // Junctions that are free to move are not treated as obstacles.
298 ++obstacleIt;
299 continue;
300 }
301 Box bbox = obstacle->routingBox();
302 obstacleBoxes.push_back(bbox);
303 ++obstacleIt;
304 }
305 m_router->debugHandler()->updateObstacleBoxes(obstacleBoxes);
306 }
307#endif
308
309 // For each hyperedge...
310 const size_t num_hyperedges = count();
311 for (size_t i = 0; i < num_hyperedges; ++i)
312 {
313 if (m_terminal_vertices_vector[i].empty())
314 {
315 // Invalid hyperedge, ignore.
316 continue;
317 }
318
319 // Execute the MTST method to find good junction positions and an
320 // initial path. A hyperedge tree will be built for the new route.
321 JunctionHyperedgeTreeNodeMap hyperedgeTreeJunctions;
323 m_terminal_vertices_vector[i], &hyperedgeTreeJunctions);
324
325 // The older MTST construction method (faster, worse results).
326 //mtst.constructSequential();
327
328 // The preferred MTST construction method.
329 // Slightly slower, better quality results.
331
332 HyperedgeTreeNode *treeRoot = mtst.rootJunction();
333 COLA_ASSERT(treeRoot);
334
335 // Fill in connector information and join them to junctions of endpoints
336 // of original connectors.
337 treeRoot->addConns(nullptr, m_router,
338 m_deleted_connectors_vector[i], nullptr);
339
340 // Output the list of new junctions and connectors from hyperedge tree.
343
344 // Write paths from the hyperedge tree back into individual
345 // connector routes.
346 for (size_t pass = 0; pass < 2; ++pass)
347 {
348 treeRoot->writeEdgesToConns(nullptr, pass);
349 }
350
351 // Tell the router that we are deleting the objects used for the
352 // previous path for the hyperedge.
353 for (ConnRefList::iterator curr =
355 curr != m_deleted_connectors_vector[i].end(); ++curr)
356 {
357 // Clear visibility assigned for connection pins.
358 (*curr)->assignConnectionPinVisibility(false);
359
361 }
362 for (JunctionRefList::iterator curr =
364 curr != m_deleted_junctions_vector[i].end(); ++curr)
365 {
366 m_router->deleteJunction(*curr);
367 }
368 }
369
370 // Clear the input to this class, so that new objects can be registered
371 // for rerouting for the next time that transaction that is processed.
372 m_terminals_vector.clear();
374
375 // Free temporarily added vertices.
376 for (VertexList::iterator curr = m_added_vertices.begin();
377 curr != m_added_vertices.end(); ++curr)
378 {
379 (*curr)->removeFromGraph();
381 delete *curr;
382 }
383 m_added_vertices.clear();
384}
385
386
387}
388
A bounding box, represented by the top-left and bottom-right corners.
Definition geomtypes.h:134
The ConnRef class represents a connector object.
Definition connector.h:132
VertInf * m_dst_vert
Definition connector.h:459
VertInf * m_src_vert
Definition connector.h:458
std::pair< Obstacle *, Obstacle * > endpointAnchors(void) const
std::pair< bool, bool > assignConnectionPinVisibility(const bool connect)
virtual void updateObstacleBoxes(std::vector< Avoid::Box > obstacles)
JunctionRefVector m_root_junction_vector
Definition hyperedge.h:211
ConnEndListVector m_terminals_vector
Definition hyperedge.h:210
ConnRefSet calcHyperedgeConnectors(void)
JunctionRefListVector m_new_junctions_vector
Definition hyperedge.h:212
VertexSetVector m_terminal_vertices_vector
Definition hyperedge.h:216
VertexList m_added_vertices
Definition hyperedge.h:217
HyperedgeNewAndDeletedObjectLists newAndDeletedObjectLists(size_t index) const
Returns a HyperedgeNewAndDeletedObjectLists detailing the lists of junctions and connectors created a...
Definition hyperedge.cpp:74
ConnRefListVector m_new_connectors_vector
Definition hyperedge.h:214
size_t count(void) const
Definition hyperedge.cpp:69
bool findAttachedObjects(size_t index, ConnRef *connector, JunctionRef *ignore, ConnRefSet &hyperedgeConns)
ConnRefListVector m_deleted_connectors_vector
Definition hyperedge.h:215
HyperedgeRerouter()
Constructor for hyperedge rerouter object.
Definition hyperedge.cpp:41
void setRouter(Router *router)
Definition hyperedge.cpp:46
void outputInstanceToSVG(FILE *fp)
Definition hyperedge.cpp:90
JunctionRefListVector m_deleted_junctions_vector
Definition hyperedge.h:213
size_t registerHyperedgeForRerouting(ConnEndList terminals)
Registers a hyperedge to be fully rerouted the next time the router processes a transaction.
Definition hyperedge.cpp:51
The JunctionRef class represents a fixed or free-floating point that connectors can be attached to.
Definition junction.h:58
bool positionFixed(void) const
Returns whether this junction has a fixed position (that can't be moved by the Router during routing)...
Definition junction.cpp:90
HyperedgeTreeNode * rootJunction(void) const
Definition mtst.cpp:98
Box routingBox(void) const
Definition obstacle.cpp:267
ConnRefList attachedConnectors(void) const
Definition obstacle.cpp:340
The Router class represents a libavoid router instance.
Definition router.h:386
ObstacleList m_obstacles
Definition router.h:401
VertInfList vertices
Definition router.h:408
void deleteConnector(ConnRef *connector)
Remove a connector from the router scene.
Definition router.cpp:312
DebugHandler * debugHandler(void) const
Definition router.cpp:153
void deleteJunction(JunctionRef *junction)
Remove a junction from the router scene.
Definition router.cpp:685
VertInf * removeVertex(VertInf *vert)
Definition vertices.cpp:557
Contains the interface for the ConnRef class.
Contains the interface for the ConnEnd class.
Css & result
Contains the interface for the HyperedgeRerouter class.
Contains the interface for the JunctionRef class.
libavoid: Object-avoiding orthogonal and polyline connector routing library.
std::list< ConnEnd > ConnEndList
A list of ConnEnd objects.
Definition hyperedge.h:47
std::set< ConnRef * > ConnRefSet
Definition hyperedge.h:56
std::list< ConnRef * > ConnRefList
A list of ConnRef objects.
Definition connector.h:48
void err_printf(const char *fmt,...)
Definition debug.h:78
std::map< JunctionRef *, HyperedgeTreeNode * > JunctionHyperedgeTreeNodeMap
Contains the interface for the Router class.
Contains the interface for the ShapeRef class.
The HyperedgeNewAndDeletedObjectLists class stores lists of objects created and deleted during hypere...
Definition hyperedge.h:80
JunctionRefList newJunctionList
A list of newly created junctions.
Definition hyperedge.h:82
void writeEdgesToConns(HyperedgeTreeEdge *ignored, size_t pass)
void listJunctionsAndConnectors(HyperedgeTreeEdge *ignored, JunctionRefList &junctions, ConnRefList &connectors)
void addConns(HyperedgeTreeEdge *ignored, Router *router, ConnRefList &oldConns, ConnRef *conn)
int index