int main(void) {
    Router *router = new Router(OrthogonalRouting);
    router->setRoutingPenalty((PenaltyType)0, 50);
    router->setRoutingPenalty((PenaltyType)1, 0);
    router->setRoutingPenalty((PenaltyType)2, 0);
    router->setRoutingPenalty((PenaltyType)3, 4000);
    router->setRoutingPenalty((PenaltyType)4, 105);
    router->setOrthogonalNudgeDistance(25);
    Rectangle rect478845150(Point(50695, 51070), Point(50705, 51080));
    JunctionRef *junctionRef478845150 = new JunctionRef(router, 
		    Point(50700, 51075), 478845150);
    
    Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
    new ShapeRef(router, rect92712048, 92712048);
    Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
    new ShapeRef(router, rect23127921, 23127921);
    Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
    new ShapeRef(router, rect159957148, 159957148);
    Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
    new ShapeRef(router, rect1350214, 1350214);
    Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
    new ShapeRef(router, rect247197258, 247197258);
    Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
    new ShapeRef(router, rect281096654, 281096654);
    ConnEnd srcPt342420237(Point(50425, 50800), 15);
    ConnEnd dstPt342420237(Point(50710, 50450), 4);
    new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
    ConnEnd srcPt352019675(Point(50990, 50500), 8);
    ConnEnd dstPt352019675(junctionRef478845150);
    //ConnEnd dstPt352019675(Point(50700, 51075), 15);
    new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
    ConnEnd srcPt42699400(junctionRef478845150);
    //ConnEnd srcPt42699400(Point(50700, 51075), 15);
    ConnEnd dstPt42699400(Point(50615, 51075), 8);
    new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
    ConnEnd srcPt94712625(Point(50710, 50550), 4);
    ConnEnd dstPt94712625(junctionRef478845150);
    //ConnEnd dstPt94712625(Point(50700, 51075), 15);
    new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
    
    ConnEnd srcPt92802970(Point(50990, 50450), 8);
    ConnEnd dstPt92802970(Point(51275, 50485), 1);
    ConnRef *conn = new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
    std::vector<Point> checkpoints;
    checkpoints.push_back(Point(50000, 50000));
    checkpoints.push_back(Point(50200, 50000));
    checkpoints.push_back(Point(50200, 50200));
    conn->setRoutingCheckpoints(checkpoints);
    
    ConnEnd srcPt716502036(Point(50710, 50500), 4);
    ConnEnd dstPt716502036(Point(51800, 50925), 15);
    new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
    router->processTransaction();
    router->outputInstanceToSVG("test-checkpoints01-1");
    router->moveJunction(junctionRef478845150, 585, 0);
    router->processTransaction();
    router->outputInstanceToSVG("test-checkpoints01-2");
    delete router;
    return 0;
};
Beispiel #2
0
void RoutingAdapter::addEdges(const EdgesById &edges, const EdgeConnDirsById *connDirs) {
    // We take advantage of the ordered nature of the maps.
    auto it = edges.begin();
    if (connDirs != nullptr) {
        auto jt = connDirs->begin();
        // Before falling off the end of either map...
        while (it != edges.end() && jt != connDirs->end()) {
            auto p = *it;
            auto q = *jt;
            // Record the Edge in the local lookup.
            this->edges.insert(p);
            // Get the two IDs.
            id_type i = p.first,
                    j = q.first;
            // Advance the connDirs iterator iff its ID lags the edges ID.
            if (i > j) ++jt;
            // In all other cases we are able to test whether the current Edge's ID
            // is in the connDirs map.
            else {
                // Allocate a ConnRef and add it to the router.
                ConnRef *cr = new ConnRef(&router);
                // Store it in the lookup map by Edge ID.
                edgeIdToConnRef.insert({i, cr});
                // Get the ConnEnds.
                ConnEndPair ends;
                if (i==j) {
                    // If the two IDs are equal then this Edge has special connDirs.
                    auto cd = q.second;
                    ends = p.second->makeLibavoidConnEnds(cd.first, cd.second);
                } else {
                    // Otherwise it does not.
                    ends = p.second->makeLibavoidConnEnds();
                }
                // Set the ends in the ConnRef.
                cr->setEndpoints(ends.first, ends.second);
                ++it;
            }
        }
    }
    // In case we fell off the end of the connDirs map first, then all remaining edges
    // take the default of ConnDirAll.
    while (it != edges.end()) {
        auto p = *it;
        // Record the Edge in the local lookup.
        this->edges.insert(p);
        // Allocate a ConnRef and add it to the router.
        ConnRef *cr = new ConnRef(&router);
        // Store it in the lookup map by Edge ID.
        edgeIdToConnRef.insert({p.first, cr});
        // Get the ConnEnds.
        ConnEndPair ends = p.second->makeLibavoidConnEnds();
        // Set the ends in the ConnRef.
        cr->setEndpoints(ends.first, ends.second);
        ++it;
    }
}
Beispiel #3
0
void buildConnectorRouteCheckpointCache(Router *router)
{
    for (ConnRefList::const_iterator curr = router->connRefs.begin(); 
            curr != router->connRefs.end(); ++curr) 
    {
        ConnRef *conn = *curr;
        if (conn->routingType() != ConnType_Orthogonal)
        {
            continue;
        }

        PolyLine& displayRoute = conn->displayRoute();
        std::vector<Point> checkpoints = conn->routingCheckpoints();
       
        // Initialise checkpoint vector and set to false.  There will be
        // one entry for each *segment* in the path, and the value indicates
        // whether the segment is affected by a checkpoint.
        displayRoute.segmentHasCheckpoint = 
                std::vector<bool>(displayRoute.size() - 1, false);
        size_t nCheckpoints = displayRoute.segmentHasCheckpoint.size();

        for (size_t cpi = 0; cpi < checkpoints.size(); ++cpi)
        {
            for (size_t ind = 0; ind < displayRoute.size(); ++ind)
            {
                if (displayRoute.ps[ind].equals(checkpoints[cpi]))
                {
                    // The checkpoint is at a bendpoint, so mark the edge
                    // before and after and being affected by checkpoints.
                    if (ind > 0)
                    {
                        displayRoute.segmentHasCheckpoint[ind - 1] = true;
                    }

                    if (ind < nCheckpoints)
                    {
                        displayRoute.segmentHasCheckpoint[ind] = true;
                    }
                }
                else if ((ind > 0) && pointOnLine(displayRoute.ps[ind - 1], 
                         displayRoute.ps[ind], checkpoints[cpi]) )
                {
                    // If the checkpoint is on a segment, only that segment is
                    // affected.
                    displayRoute.segmentHasCheckpoint[ind - 1] = true;
                }
            }
        }
    }
}
Beispiel #4
0
void buildConnectorRouteCheckpointCache(Router *router)
{
    for (ConnRefList::const_iterator curr = router->connRefs.begin();
            curr != router->connRefs.end(); ++curr)
    {
        ConnRef *conn = *curr;
        if (conn->routingType() != ConnType_Orthogonal)
        {
            continue;
        }

        PolyLine& displayRoute = conn->displayRoute();
        std::vector<Checkpoint> checkpoints = conn->routingCheckpoints();

        // Initialise checkpoint vector and set to false.  There will be
        // one entry for each *segment* in the path, and the value indicates
        // whether the segment is affected by a checkpoint.
        displayRoute.checkpointsOnRoute =
            std::vector<std::pair<size_t, Point> >();

        for (size_t ind = 0; ind < displayRoute.size(); ++ind)
        {
            if (ind > 0)
            {
                for (size_t cpi = 0; cpi < checkpoints.size(); ++cpi)
                {
                    if (pointOnLine(displayRoute.ps[ind - 1],
                                    displayRoute.ps[ind], checkpoints[cpi].point) )
                    {
                        // The checkpoint is on a segment.
                        displayRoute.checkpointsOnRoute.push_back(
                            std::make_pair((ind * 2) - 1,
                                           checkpoints[cpi].point));
                    }
                }
            }

            for (size_t cpi = 0; cpi < checkpoints.size(); ++cpi)
            {
                if (displayRoute.ps[ind].equals(checkpoints[cpi].point))
                {
                    // The checkpoint is at a bendpoint.
                    displayRoute.checkpointsOnRoute.push_back(
                        std::make_pair(ind * 2, checkpoints[cpi].point));
                }
            }
        }
    }
}
Beispiel #5
0
void clearConnectorRouteCheckpointCache(Router *router)
{
    for (ConnRefList::const_iterator curr = router->connRefs.begin();
            curr != router->connRefs.end(); ++curr)
    {
        ConnRef *conn = *curr;
        if (conn->routingType() != ConnType_Orthogonal)
        {
            continue;
        }

        // Clear the cache.
        PolyLine& displayRoute = conn->displayRoute();
        displayRoute.checkpointsOnRoute.clear();
    }
}
Beispiel #6
0
CardinalDir LeaflessOrthoRouter::departureDir(const Edge_SP &e, const Node_SP &u) const {
    ConnRef *cr = m_ra.edgeIdToConnRef.at(e->id());
    PolyLine poly = cr->displayRoute();
    vector<Point> pts = poly.ps;
    Point p0, p1;
    if (u->id() == e->getSourceEnd()->id()) {
        // Node u is the source end of Edge e.
        // So we want the first two points in the route, in order.
        p0 = pts[0];
        p1 = pts[1];
    } else {
        // Node u is the target end of Edge e.
        // So we want the last two points in the route, in reverse order.
        size_t L = pts.size();
        p0 = pts[L-1];
        p1 = pts[L-2];
    }
    return Compass::cardinalDirection(p0, p1);
}
int main(void) {
    Router *router = new Router(OrthogonalRouting);
    router->setRoutingParameter((RoutingParameter)0, 10);
    router->setRoutingParameter((RoutingParameter)1, 0);
    router->setRoutingParameter((RoutingParameter)2, 1000);
    router->setRoutingParameter((RoutingParameter)3, 4000);
    router->setRoutingParameter((RoutingParameter)4, 0);
    router->setRoutingParameter((RoutingParameter)5, 100);
    router->setRoutingParameter((RoutingParameter)6, 1);
    router->setRoutingParameter((RoutingParameter)7, 10);
    router->setRoutingParameter(reverseDirectionPenalty, 500);
    router->setRoutingOption((RoutingOption)0, false);
    router->setRoutingOption((RoutingOption)1, true);
    router->setRoutingOption((RoutingOption)2, false);
    router->setRoutingOption((RoutingOption)3, false);
    router->setRoutingOption((RoutingOption)4, true);
    router->setRoutingOption((RoutingOption)5, true);
    Polygon polygon;
    ConnRef *connRef = NULL;
    ConnEnd srcPt;
    ConnEnd dstPt;
    PolyLine newRoute;
    // shapeRef1
    polygon = Polygon(4);
    polygon.ps[0] = Point(0, 0);
    polygon.ps[1] = Point(0, 0);
    polygon.ps[2] = Point(0, 0);
    polygon.ps[3] = Point(0, 0);
    new ShapeRef(router, polygon, 1);

    // shapeRef2
    polygon = Polygon(4);
    polygon.ps[0] = Point(0, 0);
    polygon.ps[1] = Point(0, 0);
    polygon.ps[2] = Point(0, 0);
    polygon.ps[3] = Point(0, 0);
    new ShapeRef(router, polygon, 2);

    // shapeRef3
    polygon = Polygon(4);
    polygon.ps[0] = Point(0, 0);
    polygon.ps[1] = Point(0, 0);
    polygon.ps[2] = Point(0, 0);
    polygon.ps[3] = Point(0, 0);
    new ShapeRef(router, polygon, 3);

    // shapeRef4
    polygon = Polygon(4);
    polygon.ps[0] = Point(0, 0);
    polygon.ps[1] = Point(0, 0);
    polygon.ps[2] = Point(0, 0);
    polygon.ps[3] = Point(0, 0);
    new ShapeRef(router, polygon, 4);

    // shapeRef5
    polygon = Polygon(4);
    polygon.ps[0] = Point(501, 345);
    polygon.ps[1] = Point(501, 404);
    polygon.ps[2] = Point(421, 404);
    polygon.ps[3] = Point(421, 345);
    ShapeRef *shapeRef5 = new ShapeRef(router, polygon, 5);
    new ShapeConnectionPin(shapeRef5, 5, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef5, 6, 0, 0.79096, true, 0, (ConnDirFlags) 4);
    new ShapeConnectionPin(shapeRef5, 7, 0, 0.514124, true, 0, (ConnDirFlags) 4);

    // shapeRef6
    polygon = Polygon(4);
    polygon.ps[0] = Point(94, 251.5);
    polygon.ps[1] = Point(94, 315.5);
    polygon.ps[2] = Point(12, 315.5);
    polygon.ps[3] = Point(12, 251.5);
    ShapeRef *shapeRef6 = new ShapeRef(router, polygon, 6);
    new ShapeConnectionPin(shapeRef6, 8, 1, 0.640625, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef6, 9, 0, 0.640625, true, 0, (ConnDirFlags) 4);

    // shapeRef7
    polygon = Polygon(4);
    polygon.ps[0] = Point(634.366, 262);
    polygon.ps[1] = Point(634.366, 305);
    polygon.ps[2] = Point(416.366, 305);
    polygon.ps[3] = Point(416.366, 262);
    ShapeRef *shapeRef7 = new ShapeRef(router, polygon, 7);
    new ShapeConnectionPin(shapeRef7, 10, 1, 0.709302, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef7, 11, 0, 0.709302, true, 0, (ConnDirFlags) 4);

    // shapeRef8
    polygon = Polygon(4);
    polygon.ps[0] = Point(324, 147.167);
    polygon.ps[1] = Point(324, 206.167);
    polygon.ps[2] = Point(236, 206.167);
    polygon.ps[3] = Point(236, 147.167);
    ShapeRef *shapeRef8 = new ShapeRef(router, polygon, 8);
    new ShapeConnectionPin(shapeRef8, 12, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef8, 13, 0, 0.79096, true, 0, (ConnDirFlags) 4);
    new ShapeConnectionPin(shapeRef8, 14, 0, 0.514124, true, 0, (ConnDirFlags) 4);

    // shapeRef9
    polygon = Polygon(4);
    polygon.ps[0] = Point(816, 353.167);
    polygon.ps[1] = Point(816, 412.167);
    polygon.ps[2] = Point(735, 412.167);
    polygon.ps[3] = Point(735, 353.167);
    ShapeRef *shapeRef9 = new ShapeRef(router, polygon, 9);
    new ShapeConnectionPin(shapeRef9, 15, 1, 0.514124, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef9, 16, 1, 0.79096, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef9, 17, 0, 0.79096, true, 0, (ConnDirFlags) 4);
    new ShapeConnectionPin(shapeRef9, 18, 0, 0.514124, true, 0, (ConnDirFlags) 4);

    // shapeRef10
    polygon = Polygon(4);
    polygon.ps[0] = Point(981, 263.833);
    polygon.ps[1] = Point(981, 321.833);
    polygon.ps[2] = Point(828, 321.833);
    polygon.ps[3] = Point(828, 263.833);
    ShapeRef *shapeRef10 = new ShapeRef(router, polygon, 10);
    new ShapeConnectionPin(shapeRef10, 19, 0, 0.655172, true, 0, (ConnDirFlags) 4);

    // shapeRef11
    polygon = Polygon(4);
    polygon.ps[0] = Point(1011.49, 361.833);
    polygon.ps[1] = Point(1011.49, 419.833);
    polygon.ps[2] = Point(834.489, 419.833);
    polygon.ps[3] = Point(834.489, 361.833);
    ShapeRef *shapeRef11 = new ShapeRef(router, polygon, 11);
    new ShapeConnectionPin(shapeRef11, 20, 0, 0.655172, true, 0, (ConnDirFlags) 4);

    // shapeRef12
    polygon = Polygon(4);
    polygon.ps[0] = Point(511, 155.333);
    polygon.ps[1] = Point(511, 214.333);
    polygon.ps[2] = Point(422, 214.333);
    polygon.ps[3] = Point(422, 155.333);
    ShapeRef *shapeRef12 = new ShapeRef(router, polygon, 12);
    new ShapeConnectionPin(shapeRef12, 21, 1, 0.514124, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef12, 22, 1, 0.79096, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef12, 23, 0, 0.79096, true, 0, (ConnDirFlags) 4);
    new ShapeConnectionPin(shapeRef12, 24, 0, 0.514124, true, 0, (ConnDirFlags) 4);

    // shapeRef13
    polygon = Polygon(4);
    polygon.ps[0] = Point(690, 66);
    polygon.ps[1] = Point(690, 124);
    polygon.ps[2] = Point(523, 124);
    polygon.ps[3] = Point(523, 66);
    ShapeRef *shapeRef13 = new ShapeRef(router, polygon, 13);
    new ShapeConnectionPin(shapeRef13, 25, 0, 0.655172, true, 0, (ConnDirFlags) 4);

    // shapeRef14
    polygon = Polygon(4);
    polygon.ps[0] = Point(720.212, 164);
    polygon.ps[1] = Point(720.212, 222);
    polygon.ps[2] = Point(529.212, 222);
    polygon.ps[3] = Point(529.212, 164);
    ShapeRef *shapeRef14 = new ShapeRef(router, polygon, 14);
    new ShapeConnectionPin(shapeRef14, 26, 0, 0.655172, true, 0, (ConnDirFlags) 4);

    // shapeRef15
    polygon = Polygon(4);
    polygon.ps[0] = Point(217, 336.833);
    polygon.ps[1] = Point(217, 395.833);
    polygon.ps[2] = Point(98, 395.833);
    polygon.ps[3] = Point(98, 336.833);
    ShapeRef *shapeRef15 = new ShapeRef(router, polygon, 15);
    new ShapeConnectionPin(shapeRef15, 27, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef15, 28, 0, 0.652542, true, 0, (ConnDirFlags) 4);

    // shapeRef16
    polygon = Polygon(4);
    polygon.ps[0] = Point(413, 147.167);
    polygon.ps[1] = Point(413, 206.167);
    polygon.ps[2] = Point(336, 206.167);
    polygon.ps[3] = Point(336, 147.167);
    ShapeRef *shapeRef16 = new ShapeRef(router, polygon, 16);
    new ShapeConnectionPin(shapeRef16, 29, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef16, 30, 0, 0.652542, true, 0, (ConnDirFlags) 4);

    // shapeRef17
    polygon = Polygon(4);
    polygon.ps[0] = Point(306, 336.833);
    polygon.ps[1] = Point(306, 395.833);
    polygon.ps[2] = Point(229, 395.833);
    polygon.ps[3] = Point(229, 336.833);
    ShapeRef *shapeRef17 = new ShapeRef(router, polygon, 17);
    new ShapeConnectionPin(shapeRef17, 31, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef17, 32, 0, 0.652542, true, 0, (ConnDirFlags) 4);

    // shapeRef18
    polygon = Polygon(4);
    polygon.ps[0] = Point(175, 139);
    polygon.ps[1] = Point(175, 198);
    polygon.ps[2] = Point(98, 198);
    polygon.ps[3] = Point(98, 139);
    ShapeRef *shapeRef18 = new ShapeRef(router, polygon, 18);
    new ShapeConnectionPin(shapeRef18, 33, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef18, 34, 0, 0.652542, true, 0, (ConnDirFlags) 4);

    // shapeRef19
    polygon = Polygon(4);
    polygon.ps[0] = Point(409, 399.333);
    polygon.ps[1] = Point(409, 458.333);
    polygon.ps[2] = Point(298, 458.333);
    polygon.ps[3] = Point(298, 399.333);
    ShapeRef *shapeRef19 = new ShapeRef(router, polygon, 19);
    new ShapeConnectionPin(shapeRef19, 35, 1, 0.652542, true, 0, (ConnDirFlags) 8);

    // shapeRef20
    polygon = Polygon(4);
    polygon.ps[0] = Point(224, 40);
    polygon.ps[1] = Point(224, 99);
    polygon.ps[2] = Point(106, 99);
    polygon.ps[3] = Point(106, 40);
    ShapeRef *shapeRef20 = new ShapeRef(router, polygon, 20);
    new ShapeConnectionPin(shapeRef20, 36, 1, 0.652542, true, 0, (ConnDirFlags) 8);

    // shapeRef21
    polygon = Polygon(4);
    polygon.ps[0] = Point(604, 345);
    polygon.ps[1] = Point(604, 404);
    polygon.ps[2] = Point(513, 404);
    polygon.ps[3] = Point(513, 345);
    ShapeRef *shapeRef21 = new ShapeRef(router, polygon, 21);
    new ShapeConnectionPin(shapeRef21, 37, 1, 0.652542, true, 0, (ConnDirFlags) 8);
    new ShapeConnectionPin(shapeRef21, 38, 0, 0.652542, true, 0, (ConnDirFlags) 4);

    // connRef1
    connRef = new ConnRef(router, 1);
    srcPt = ConnEnd(shapeRef5, 5);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef21, 38);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef2
    connRef = new ConnRef(router, 2);
    srcPt = ConnEnd(shapeRef6, 8);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef18, 34);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef3
    connRef = new ConnRef(router, 3);
    srcPt = ConnEnd(shapeRef6, 8);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef15, 28);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef4
    connRef = new ConnRef(router, 4);
    srcPt = ConnEnd(shapeRef6, 8);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef12, 23);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef5
    connRef = new ConnRef(router, 5);
    srcPt = ConnEnd(shapeRef6, 8);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef7, 11);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef6
    connRef = new ConnRef(router, 6);
    srcPt = ConnEnd(shapeRef7, 10);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef9, 17);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);
    ConnRef *connector6 = connRef;

    // connRef7
    connRef = new ConnRef(router, 7);
    srcPt = ConnEnd(shapeRef8, 12);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef16, 30);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef8
    connRef = new ConnRef(router, 8);
    srcPt = ConnEnd(shapeRef9, 15);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef10, 19);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef9
    connRef = new ConnRef(router, 9);
    srcPt = ConnEnd(shapeRef9, 16);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef11, 20);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef10
    connRef = new ConnRef(router, 10);
    srcPt = ConnEnd(shapeRef12, 21);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef13, 25);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef11
    connRef = new ConnRef(router, 11);
    srcPt = ConnEnd(shapeRef12, 22);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef14, 26);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef12
    connRef = new ConnRef(router, 12);
    srcPt = ConnEnd(shapeRef15, 27);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef17, 32);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef13
    connRef = new ConnRef(router, 13);
    srcPt = ConnEnd(shapeRef16, 29);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef12, 24);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef14
    connRef = new ConnRef(router, 14);
    srcPt = ConnEnd(shapeRef17, 31);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef5, 7);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef15
    connRef = new ConnRef(router, 15);
    srcPt = ConnEnd(shapeRef18, 33);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef8, 14);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef16
    connRef = new ConnRef(router, 16);
    srcPt = ConnEnd(shapeRef19, 35);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef5, 7);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef17
    connRef = new ConnRef(router, 17);
    srcPt = ConnEnd(shapeRef20, 36);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef8, 14);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    // connRef18
    connRef = new ConnRef(router, 18);
    srcPt = ConnEnd(shapeRef21, 37);
    connRef->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef9, 18);
    connRef->setDestEndpoint(dstPt);
    connRef->setRoutingType((ConnType)2);

    router->processTransaction();
    // Test that connector 6 has three segments and doesnt loop right
    // around the shapes on the right due to the crossing penalty.
    bool suceeds = (connector6->displayRoute().size() == 4);

    //router->outputDiagram("output/forwardFlowingConnectors01");
    delete router;
    return (suceeds ? 0 : 1);
};
Beispiel #8
0
void LeaflessOrthoRouter::route(Logger *logger) {

    // Set up for logging.
    unsigned ln = logger != nullptr ? logger->nextLoggingIndex : 0;
    std::function<void(unsigned)> log = [ln, this, logger](unsigned n)->void{
        if (logger!=nullptr) {
            std::string fn = string_format("%02d_%02d_routing_attempt", ln, n);
            std::string path = logger->writeFullPathForFilename(fn);
            this->m_ra.router.outputInstanceToSVG(path);
        }
    };

    /*
     * We may need to route multiple times to ensure that at least two sides of each node are being used,
     * but in theory we should never have to route more than 4n+1 times.
     *
     *  Proof: We always begin with an initial routing. We want to show it could be necessary to re-route
     *  at most 4n times.
     *
     *  In order to see this, we first argue that the worst-case-scenario for any single node is that it
     *  require four routings. Consider then some node u all of whose edges have been routed to one side, s0. We
     *  then pick some edge e0 incident to u, say that it may not connect to side s0, and we re-route for the first time.
     *
     *  While unlikely, it could be that, for whatever reason, now all edges incident to node u are routed to some other side,
     *  s1. We then pick some edge e1 (could be the same or different from e0), forbid it from connecting to
     *  side s1, and re-route for a second time.
     *
     *  Again, for whatever reason, all edges could now connect to one
     *  of the two remaining sides, s2. Continuing in this way, we could be led to re-route a third and a fourth time. But
     *  prior to the fourth re-routing it would be the case that for each side si of node u, there was
     *  some edge ei incident to u that had been forbidden from connecting on side si. Therefore on the fourth
     *  re-routing it would be impossible for all edges to connect on any single side of u.
     *
     *  So much for the case of a single node. However, in again a highly unlikely worst-case-scenario, it could be
     *  that during the first five routings no other node besides u was a pseudoleaf (had all edges routed to one side),
     *  but after the fifth some other node became a pseudoleaf. In this way we could be led to do four re-routings
     *  for each node in the graph. QED
     *
     * In practice, it would probably be very rare for more that two routings to ever be necessary. For this
     * requires the odd circumstance, considered in the proof, that forbidding one edge from connecting on a
     * given side somehow results in /all/ edges incident at that node migrating to some other, single side.
     *
     * In order that our theory be tested, we use an infinite loop with counter and assertion, instead
     * of a mere for-loop which would fail silently.
     */
    size_t numRoutings = 0;
    size_t maxRoutings = 4*m_n + 1;
    while (true) {
        m_ra.router.processTransaction();
        log(++numRoutings);
        // As explained in the comments above, at most five routings should ever be needed.
        COLA_ASSERT(numRoutings <= maxRoutings);
        // For testing purposes, we may want to record the results of
        // each routing attempt.
        if (recordEachAttempt) {
            m_ra.recordRoutes(true);
            routingAttemptTglf.push_back(m_graph->writeTglf());
        }
        // Are there any nodes having all of their edges routed
        // out of just one side? This is what we want to prevent.
        // Such nodes would become leaves in a planarisation, so we
        // call them "pseudoleaves".
        Nodes pseudoLeaves;
        // For each such Node (if any), there is a sole direction in which
        // all connectors depart. We keep track of those directions as we work.
        vector<CardinalDir> soleDepartureDirecs;
        // Check each Node in the Graph:
        for (auto p : m_graph->getNodeLookup()) {
            Node_SP &u = p.second;
            const EdgesById edgeLookup = u->getEdgeLookup();
            // Sanity check, that Node u is not an actual leaf:
            COLA_ASSERT(edgeLookup.size() > 1);
            // Determine the departure direction from Node u for its first Edge.
            auto edge_it = edgeLookup.cbegin();
            CardinalDir d0 = departureDir((*edge_it).second, u);
            // If two or more directions have been used, some edge must depart
            // in a different direction than this one. (For if all the rest equal
            // this first one, then all are the same.)
            bool isPseudoLeaf = true;
            for (auto jt = ++edge_it; jt != edgeLookup.cend(); ++jt) {
                CardinalDir d1 = departureDir((*jt).second, u);
                if (d1 != d0) {
                    isPseudoLeaf = false;
                    break;
                }
            }
            if (isPseudoLeaf) {
                pseudoLeaves.push_back(u);
                soleDepartureDirecs.push_back(d0);
            }
        }
        // Are there any pseudoleaves?
        if (pseudoLeaves.empty()) {
            // If there are none, then we're done routing, and can break out of the outer while loop.
            break;
        } else {
            // But if there are still pseudoleaves, then we need to work on them.
            for (size_t i = 0; i < pseudoLeaves.size(); ++i) {
                // Get the Node and the direction in which all connectors currently depart from it.
                Node_SP u = pseudoLeaves[i];
                CardinalDir d0 = soleDepartureDirecs[i];
                // Now among all Edges incident at this Node we must select one that is still
                // allowed to depart in at least two directions (hence at least one different
                // from d0), and remove direction d0 from its list of allowed directions.
                //
                // If possible, we would like to choose such an Edge e such that if v is the Node
                // at the other end, then the predominant cardinal direction from Node u to Node v
                // be different than d0; for such would seem a suitable Edge to depart in a different
                // direction. However, such an Edge may not exist. In that case, we will just take
                // any one.
                Edge_SP candidate;
                for (auto p : u->getEdgeLookup()) {
                    Edge_SP &e = p.second;
                    // If this Edge is only allowed the one direction, then skip it.
                    if (isSoleDirec(m_allowedConnDirs.at(e->id()).at(u->id()))) continue;
                    // Otherwise mark it as the candidate.
                    candidate = e;
                    // Determine the predominant cardinal direction from Node u to the Node v at
                    // the opposite end of Edge e.
                    Node_SP v = e->getOtherEnd(*u);
                    CardinalDir d1 = Compass::cardinalDirection(u, v);
                    // If this is different from direction d0, then we're happy to accept this candidate.
                    if (d1 != d0) break;
                }
                // Start with the directions allowed last time:
                ConnDirFlags available = m_allowedConnDirs.at(candidate->id()).at(u->id());
                // XOR with the connection flag corresponding to cardinal direction d0,
                // so that this direction is no longer allowed.
                available ^= Compass::libavoidConnDirs.at(d0);
                // Record the new value.
                m_allowedConnDirs[candidate->id()][u->id()] = available;
                // Set a new ConnEnd.
                Point p = u->getCentre();
                ConnEnd end(p, available);
                ConnRef *cr = m_ra.edgeIdToConnRef.at(candidate->id());
                if (u->id() == candidate->getSourceEnd()->id()) {
                    cr->setSourceEndpoint(end);
                } else {
                    cr->setDestEndpoint(end);
                }
            }
        }
    }
    // Finally, the routing is done and we can set the connector routes in the Edge objects.
    m_ra.recordRoutes(true);
}
int main(void) {
    Router *router = new Router(OrthogonalRouting);
    router->setRoutingParameter((RoutingParameter)0, 2);
    router->setRoutingParameter((RoutingParameter)1, 0);
    router->setRoutingParameter((RoutingParameter)2, 0);
    router->setRoutingParameter((RoutingParameter)3, 4000);
    router->setRoutingParameter((RoutingParameter)4, 9000);
    router->setRoutingParameter((RoutingParameter)5, 0);
    router->setRoutingParameter((RoutingParameter)6, 0);
    router->setRoutingParameter((RoutingParameter)7, 16);
    router->setRoutingParameter((RoutingParameter)8, 0);
    router->setRoutingOption((RoutingOption)0, false);
    router->setRoutingOption((RoutingOption)1, true);
    router->setRoutingOption((RoutingOption)2, false);
    router->setRoutingOption((RoutingOption)3, false);
    router->setRoutingOption((RoutingOption)4, true);
    router->setRoutingOption((RoutingOption)5, false);
    router->setRoutingOption((RoutingOption)6, true);
    Polygon polygon;
    ConnEnd srcPt;
    ConnEnd dstPt;
    ConnEnd heConnPt;
    PolyLine newRoute;
    ShapeConnectionPin *connPin = NULL;

    // shapeRef1
    polygon = Polygon(4);
    polygon.ps[0] = Point(450, 330);
    polygon.ps[1] = Point(490, 330);
    polygon.ps[2] = Point(490, 450);
    polygon.ps[3] = Point(450, 450);
    ShapeRef *shapeRef1 = new ShapeRef(router, polygon, 1);
    connPin = new ShapeConnectionPin(shapeRef1, 1, 0, 0.333333, true, 10, (ConnDirFlags) 0);
    connPin->setExclusive(false);
    connPin = new ShapeConnectionPin(shapeRef1, 2, 0, 0.666667, true, 10, (ConnDirFlags) 0);
    connPin->setExclusive(false);
    connPin = new ShapeConnectionPin(shapeRef1, 3, 1, 0.5, true, 10, (ConnDirFlags) 0);
    connPin->setExclusive(false);
    connPin = new ShapeConnectionPin(shapeRef1, 4, 0.5, 0, true, 10, (ConnDirFlags) 0);
    connPin->setExclusive(false);

    // shapeRef8
    polygon = Polygon(4);
    polygon.ps[0] = Point(502, 237.5);
    polygon.ps[1] = Point(502, 262.5);
    polygon.ps[2] = Point(438, 262.5);
    polygon.ps[3] = Point(438, 237.5);
    ShapeRef *shapeRef8 = new ShapeRef(router, polygon, 8);
    connPin = new ShapeConnectionPin(shapeRef8, 1, 0, 0.5, true, 1, (ConnDirFlags) 0);
    connPin = new ShapeConnectionPin(shapeRef8, 2, 1, 0.5, true, 1, (ConnDirFlags) 0);
    connPin = new ShapeConnectionPin(shapeRef8, 3, 0.5, 1, true, 1, (ConnDirFlags) 0);
    connPin = new ShapeConnectionPin(shapeRef8, 4, 0.5, 0, true, 1, (ConnDirFlags) 0);

    JunctionRef *junctionRef6 = new JunctionRef(router, Point(470, 300), 6);
    /*
    // This may be useful if junction pins are modified.
    connPin = new ShapeConnectionPin(junctionRef6, 2147483646, (ConnDirFlags) 15);
    */

    // connRef9
    ConnRef *connRef9 = new ConnRef(router, 9);
    srcPt = ConnEnd(junctionRef6);
    connRef9->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef8, 3);
    connRef9->setDestEndpoint(dstPt);
    connRef9->setRoutingType((ConnType)2);

#if 1
    // connRef10 - WITH BUG
    ConnRef *connRef10 = new ConnRef(router, 10);
    srcPt = ConnEnd(junctionRef6);
    connRef10->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(shapeRef1, 4);
    connRef10->setDestEndpoint(dstPt);
    connRef10->setRoutingType((ConnType)2);
#else
    // connRef10 - WITHOUT BUG
    ConnRef *connRef10 = new ConnRef(router, 10);
    srcPt = ConnEnd(shapeRef1, 4);
    connRef10->setSourceEndpoint(srcPt);
    dstPt = ConnEnd(junctionRef6);
    connRef10->setDestEndpoint(dstPt);
    connRef10->setRoutingType((ConnType)2);
#endif

    //    router->deleteConnector(connRef5);
    router->processTransaction();

    ConnRef *mergedConn = junctionRef6->removeJunctionAndMergeConnectors();
    router->processTransaction();
    router->outputDiagram("output/removeJunctions01");

    std::pair<ConnEnd, ConnEnd> ends = mergedConn->endpointConnEnds();

    // Expected result: output images should be virtually identical.
    // Result: An endpoint seems to be disconnected from shapeRef8.
    bool isConnected = (ends.first.shape() == shapeRef8) || (ends.second.shape() == shapeRef8);

    delete router;
    return isConnected ? 0 : 1;
};