void HyperedgeRerouter::performRerouting(void) { COLA_ASSERT(m_router != NULL); m_new_junctions_vector.clear(); m_new_junctions_vector.resize(count()); m_new_connectors_vector.clear(); m_new_connectors_vector.resize(count()); #ifdef DEBUGHANDLER if (m_router->debugHandler()) { std::vector<Box> obstacleBoxes; ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin(); while (obstacleIt != m_router->m_obstacles.end()) { Obstacle *obstacle = *obstacleIt; JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle); if (junction && ! junction->positionFixed()) { // Junctions that are free to move are not treated as obstacles. ++obstacleIt; continue; } Box bbox = obstacle->routingBox(); obstacleBoxes.push_back(bbox); ++obstacleIt; } m_router->debugHandler()->updateObstacleBoxes(obstacleBoxes); } #endif // For each hyperedge... const size_t num_hyperedges = count(); for (size_t i = 0; i < num_hyperedges; ++i) { if (m_terminal_vertices_vector[i].empty()) { // Invalid hyperedge, ignore. continue; } // Execute the MTST method to find good junction positions and an // initial path. A hyperedge tree will be built for the new route. JunctionHyperedgeTreeNodeMap hyperedgeTreeJunctions; MinimumTerminalSpanningTree mtst(m_router, m_terminal_vertices_vector[i], &hyperedgeTreeJunctions); // The older MTST construction method (faster, worse results). //mtst.constructSequential(); // The preferred MTST construction method. // Slightly slower, better quality results. mtst.constructInterleaved(); HyperedgeTreeNode *treeRoot = mtst.rootJunction(); COLA_ASSERT(treeRoot); // Fill in connector information and join them to junctions of endpoints // of original connectors. treeRoot->addConns(NULL, m_router, m_deleted_connectors_vector[i], NULL); // Output the list of new junctions and connectors from hyperedge tree. treeRoot->listJunctionsAndConnectors(NULL, m_new_junctions_vector[i], m_new_connectors_vector[i]); // Write paths from the hyperedge tree back into individual // connector routes. for (size_t pass = 0; pass < 2; ++pass) { treeRoot->writeEdgesToConns(NULL, pass); } // Tell the router that we are deleting the objects used for the // previous path for the hyperedge. for (ConnRefList::iterator curr = m_deleted_connectors_vector[i].begin(); curr != m_deleted_connectors_vector[i].end(); ++curr) { // Clear visibility assigned for connection pins. (*curr)->assignConnectionPinVisibility(false); m_router->deleteConnector(*curr); } for (JunctionRefList::iterator curr = m_deleted_junctions_vector[i].begin(); curr != m_deleted_junctions_vector[i].end(); ++curr) { m_router->deleteJunction(*curr); } } // Clear the input to this class, so that new objects can be registered // for rerouting for the next time that transaction that is processed. m_terminals_vector.clear(); m_root_junction_vector.clear(); // Free temporarily added vertices. for (VertexList::iterator curr = m_added_vertices.begin(); curr != m_added_vertices.end(); ++curr) { (*curr)->removeFromGraph(); m_router->vertices.removeVertex(*curr); delete *curr; } m_added_vertices.clear(); }
// This method traverses the hyperedge tree and writes each of the paths // back to the individual connectors as routes. // void HyperedgeTreeEdge::writeEdgesToConns(HyperedgeTreeNode *ignored, size_t pass) { COLA_ASSERT(ignored != NULL); COLA_ASSERT(ends.first != NULL); COLA_ASSERT(ends.second != NULL); HyperedgeTreeNode *prevNode = (ignored == ends.first) ? ends.first : ends.second; HyperedgeTreeNode *nextNode = (ignored == ends.first) ? ends.second : ends.first; if (pass == 0) { conn->m_display_route.clear(); } else if (pass == 1) { if (conn->m_display_route.empty()) { //printf("[%u] - %g %g\n", conn->id(), prevNode->point.x, prevNode->point.y); conn->m_display_route.ps.push_back(prevNode->point); } //printf("[%u] + %g %g\n", conn->id(), nextNode->point.x, nextNode->point.y); conn->m_display_route.ps.push_back(nextNode->point); size_t nextNodeEdges = nextNode->edges.size(); if (nextNodeEdges != 2) { // We have finished writing a connector. If the node has just // two edges then it is an intermediate node on a connector. bool shouldReverse = false; if (nextNodeEdges == 1) { // This connector led to a terminal. if (nextNode->isConnectorSource) { shouldReverse = true; } if (nextNode->isPinDummyEndpoint) { // If may be that the hyperedge has an extra segment or // two leading to the centre dummy pin used for connection // pin routing. If so, remove these points from the // resulting route. conn->m_display_route.ps.pop_back(); if (prevNode->point == nextNode->point) { // Duplicated dummy point. Remove second one. conn->m_display_route.ps.pop_back(); } } } else // if (nextNodeEdges > 2) { // This connector was between two junctions. COLA_ASSERT(conn->m_dst_connend); JunctionRef *correctEndJunction = conn->m_dst_connend->junction(); if (nextNode->junction != correctEndJunction) { shouldReverse = true; } } if (shouldReverse == true) { // Reverse the written connector route. std::reverse(conn->m_display_route.ps.begin(), conn->m_display_route.ps.end()); } } #ifdef DEBUGHANDLER if (conn->router()->debugHandler()) { conn->router()->debugHandler()->updateConnectorRoute( conn, -1, -1); } #endif } nextNode->writeEdgesToConns(this, pass); }