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 #2
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);
}