Example #1
0
// This method splits the current edge, adding a node at the given point.
// The current edge will connect the source node and the newly created node.
// A new edge will connect the new node and the node at the other end of the
// original edge.
//
void HyperEdgeTreeEdge::splitFromNodeAtPoint(HyperEdgeTreeNode *source, 
        const Point& point)
{
    // Make the source the first of the two nodes.
    if (ends.second == source)
    {
        std::swap(ends.second, ends.first);
    }
    COLA_ASSERT(ends.first == source);

    // Remember the other end.
    HyperEdgeTreeNode *target = ends.second;

    // Create a new node for the split point at the given position.
    HyperEdgeTreeNode *split = new HyperEdgeTreeNode();
    split->point = point;

    // Create a new edge between the split point and the other end.
    new HyperEdgeTreeEdge(split, target, conn);
    
    // Disconnect the current edge from the other end and connect it to 
    // the new split point node.
    target->disconnectEdge(this);
    ends.second = split;
    split->edges.push_back(this);
}
Example #2
0
// This method traverses the hyperedge tree removing zero length edges.
//
void HyperEdgeTreeNode::removeZeroLengthEdges(HyperEdgeTreeEdge *ignored)
{
    for (std::list<HyperEdgeTreeEdge *>::iterator curr = edges.begin();
            curr != edges.end(); ++curr)
    {
        HyperEdgeTreeEdge *edge = *curr;
        if (edge != ignored)
        {
            if (edge->zeroLength())
            {
                HyperEdgeTreeNode *other = edge->followFrom(this);
                HyperEdgeTreeNode *target = NULL;
                HyperEdgeTreeNode *source = NULL;
                if (other->junction && ! junction)
                {
                    target = other;
                    source = this;
                }
                else if ( ! other->junction && junction)
                {
                    target = this;
                    source = other;
                }
                else if ( ! other->junction && ! junction)
                {
                    target = this;
                    source = other;
                }

                if (target)
                {
                    edge->disconnectEdge();
                    delete edge;
                    target->spliceEdgesFrom(source);
                    delete source;
                    target->removeZeroLengthEdges(ignored);
                    return;
                }
                // XXX Deal with merging two junctions?
            }

            // Recursive call.
            edge->removeZeroLengthEdges(this);
        }
    }
}
Example #3
0
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 HYPEREDGE_DEBUG
    double minX = LIMIT;
    double minY = LIMIT;
    double maxX = -LIMIT;
    double maxY = -LIMIT;

    VertInf *curr = m_router->vertices.connsBegin();
    while (curr)
    {
        Point p = curr->point;

        reduceRange(p.x);
        reduceRange(p.y);
        
        if (p.x > -LIMIT)
        {
            minX = std::min(minX, p.x);
        }
        if (p.x < LIMIT)
        {
            maxX = std::max(maxX, p.x);
        }
        if (p.y > -LIMIT)
        {
            minY = std::min(minY, p.y);
        }
        if (p.y < LIMIT)
        {
            maxY = std::max(maxY, p.y);
        }
        curr = curr->lstNext;
    }
    minX -= 8;
    minY -= 8;
    maxX += 8;
    maxY += 8;

    FILE *fp = fopen("hyperedge-debug.svg", "w");
    fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
    // width=\"100%%\" height=\"100%%\" 
    fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY);
    fprintf(fp, "<defs>\n");
    fprintf(fp, "<style type=\"text/css\" ><![CDATA[\n");
    fprintf(fp, ".shape { stroke-width: 1px; stroke: black; fill: blue; stroke-opacity: 0.50; fill-opacity: 0.50; }\n");
    fprintf(fp, ".graph { opacity: 0; fill: none; stroke: red; stroke-width: 1px; }\n");
    fprintf(fp, ".forest { fill: none; stroke: purple; stroke-width: 1px; }\n");
    fprintf(fp, ".hyperedge { fill: none; stroke-width: 1px; }\n");
    fprintf(fp, "]]></style>\n");
    fprintf(fp, "</defs>\n");

    fprintf(fp, "<g inkscape:groupmode=\"layer\" "
            "inkscape:label=\"ShapesRect\">\n");
    ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin();
    while (obstacleIt != m_router->m_obstacles.end())
    {
        Obstacle *obstacle = *obstacleIt;
        bool isShape = (NULL != dynamic_cast<ShapeRef *> (obstacle));

        if ( ! isShape )
        {
            // Don't output obstacles here, for now.
            ++obstacleIt;
            continue;
        }

        Box bb = obstacle->routingBox();

        fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" "
                "height=\"%g\" class=\"shape\" />\n",
                obstacle->id(), bb.min.x, bb.min.y, 
                bb.max.x - bb.min.x, bb.max.y - bb.min.y);
        // shapeContainsEndpointVertex(obstacle) ? "style=\"fill: green;\"" : "");
        ++obstacleIt;
    }
    fprintf(fp, "</g>\n");

    fprintf(fp, "<g inkscape:groupmode=\"layer\" "
            "id=\"graph\" style=\"display: none;\" "
            "inkscape:label=\"OrthogVisGraph\">\n");
    EdgeInf *finish = m_router->visOrthogGraph.end();
    for (EdgeInf *t = m_router->visOrthogGraph.begin(); t != finish; t = t->lstNext)
    {
        std::pair<Point, Point> ptpair = t->points();
        Point p1 = ptpair.first;
        Point p2 = ptpair.second;
        
        reduceRange(p1.x);
        reduceRange(p1.y);
        reduceRange(p2.x);
        reduceRange(p2.y);
        
        // std::pair<VertID, VertID> ids = t->ids();
        // (ids.first.isConnPt() || ids.second.isConnPt()) ? "style=\"stroke: green\" " : ""
        fprintf(fp, "<path class=\"graph\" d=\"M %g %g L %g %g\" "
                "%s />\n", p1.x, p1.y, p2.x, p2.y,
                ""
                );
    }
    fprintf(fp, "</g>\n");
#endif
    
    // For each hyperedge...
    const size_t num_hyperedges = count();
    for (size_t i = 0; i < num_hyperedges; ++i)
    {
        // Execute the MTST method to find good junction positions and an
        // initial path.  A hyperedge tree will be build for the new route.
        JunctionHyperEdgeTreeNodeMap hyperEdgeTreeJunctions;
        MinimumTerminalSpanningTree mtst(m_router, 
                m_terminal_vertices_vector[i], &hyperEdgeTreeJunctions);
#ifdef HYPEREDGE_DEBUG
        mtst.setDebuggingOutput(fp, i);
#endif
        // 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();
#ifdef HYPEREDGE_DEBUG
    fprintf(fp, "</svg>\n");
    fclose(fp);
#endif
}
Example #4
0
// This method moves the junction at the given node along any shared paths
// (so long as this action would not create any additional shared paths),
// while also removing and freeing merged edges and nodes in the process.
// It returns the new node where the junction is now located.
//
HyperEdgeTreeNode *HyperEdgeTreeNode::moveJunctionAlongCommonEdge(
        HyperEdgeTreeNode *self)
{
    COLA_ASSERT(self->junction);

    HyperEdgeTreeNode *newSelf = NULL;
    std::vector<HyperEdgeTreeEdge *> commonEdges;
    std::vector<HyperEdgeTreeEdge *> otherEdges;

    // Consider each edge from this node in turn.
    for (std::list<HyperEdgeTreeEdge *>::iterator curr = self->edges.begin();
            curr != self->edges.end(); ++curr)
    {
        HyperEdgeTreeEdge *currEdge = *curr;
        HyperEdgeTreeNode *currNode = currEdge->followFrom(self);
        commonEdges.clear();
        otherEdges.clear();

        if (currNode->junction)
        {
            // Don't shift junctions onto other junctions.
            continue;
        }

        // The current edge is a common edge we are looking to shift along.
        commonEdges.push_back(currEdge);

        // Consider each of the other edges.
        for (std::list<HyperEdgeTreeEdge *>::iterator curr2 = 
                self->edges.begin(); curr2 != self->edges.end(); ++curr2)
        {
            if (curr == curr2)
            {
                // Except the current (curr) one.
                continue;
            }
            
            HyperEdgeTreeEdge *otherEdge = *curr2;
            HyperEdgeTreeNode *otherNode = otherEdge->followFrom(self);
            if (otherNode->point == currNode->point)
            {
                // A common edge can be at the same point, but can't have
                // a junction at it.
                if (otherNode->junction)
                {
                    otherEdges.push_back(otherEdge);
                }
                else
                {
                    commonEdges.push_back(otherEdge);
                }
            }
            else if (pointOnLine(self->point, otherNode->point, 
                    currNode->point))
            {
                // A common edge can be a (longer) collinear line, but we
                // need to split the longer line at the other end of curr.
                otherEdge->splitFromNodeAtPoint(self, currNode->point);
                commonEdges.push_back(otherEdge);
            }
            else
            {
                // If the edge goes in another direction it is not common.
                otherEdges.push_back(otherEdge);
            }
        }

        if ((commonEdges.size() > 1) && (otherEdges.size() <= 1))
        {
            // One of the common nodes becomes the target node, we move 
            // all connections from the other common nodes to this node.
            // We also move the junction there and remove it from the 
            // current node.
            HyperEdgeTreeNode *targetNode = commonEdges[0]->followFrom(self);
            for (size_t i = 1; i < commonEdges.size(); ++i)
            {
                HyperEdgeTreeNode *thisNode = commonEdges[i]->followFrom(self);
                commonEdges[i]->disconnectEdge();
                targetNode->spliceEdgesFrom(thisNode);
                delete thisNode;
                delete commonEdges[i];
            }
            targetNode->junction = self->junction;
            self->junction = NULL;

            if (otherEdges.empty())
            {
                // Nothing else connected to this node, so remove the node
                // and the edge to the target node.
                commonEdges[0]->disconnectEdge();

                delete commonEdges[0];
                delete self;
            }
            else
            {
                // We need to mark commonEdges[0] as being from the connector
                // of the otherEdges[0].
                commonEdges[0]->conn = otherEdges[0]->conn;
            }
            newSelf = targetNode;

            break;
        }
    }

    return newSelf;
}
Example #5
0
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());

    // For each hyperedge...
    const size_t num_hyperedges = count();
    for (size_t i = 0; i < num_hyperedges; ++i)
    {
        // Execute the MTST method to find good junction positions and an
        // initial path.  A hyperedge tree will be build for the new route.
        JunctionHyperEdgeTreeNodeMap hyperEdgeTreeJunctions;
        MinimumTerminalSpanningTree mtst(m_router, m_terminal_vertices_vector[i],
                &hyperEdgeTreeJunctions);
        mtst.execute();

        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)
        {
            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();
}