void removeoverlaps(vpsc::Rectangles &rs, bool bothaxes) {
	double xBorder=0, yBorder=0;
    static const double EXTRA_GAP=1e-5;
	unsigned n=rs.size();
	try {
		// The extra gap avoids numerical imprecision problems
		Rectangle::setXBorder(xBorder+EXTRA_GAP);
		Rectangle::setYBorder(yBorder+EXTRA_GAP);
        vpsc::Variables vs(n);
		unsigned i=0;
		for(Variables::iterator v=vs.begin();v!=vs.end();++v,++i) {
			*v=new Variable(i,0,1);
		}
        vpsc::Constraints cs;
        vpsc::generateXConstraints(rs,vs,cs,bothaxes);
        vpsc::IncSolver vpsc_x(vs,cs);
		vpsc_x.solve();
        vpsc::Rectangles::iterator r=rs.begin();
		for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
			assert((*v)->finalPosition==(*v)->finalPosition);
			(*r)->moveCentreX((*v)->finalPosition);
		}
		assert(r==rs.end());
		for_each(cs.begin(),cs.end(),vpsc::delete_object());
		cs.clear();
        if(bothaxes) {
            // Removing the extra gap here ensures things that were moved to be adjacent to one another above are not considered overlapping
            Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP);
            vpsc::generateYConstraints(rs,vs,cs);
            vpsc::IncSolver vpsc_y(vs,cs);
            vpsc_y.solve();
            r=rs.begin();
            for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
                (*r)->moveCentreY((*v)->finalPosition);
            }
            for_each(cs.begin(),cs.end(),vpsc::delete_object());
            cs.clear();
            Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP);
            vpsc::generateXConstraints(rs,vs,cs,false);
            vpsc::IncSolver vpsc_x2(vs,cs);
            vpsc_x2.solve();
            r=rs.begin();
            for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
                (*r)->moveCentreX((*v)->finalPosition);
            }
            for_each(cs.begin(),cs.end(),vpsc::delete_object());
        }
		for_each(vs.begin(),vs.end(),vpsc::delete_object());
	} catch (char *str) {
		std::cerr<<str<<std::endl;
		for(vpsc::Rectangles::iterator r=rs.begin();r!=rs.end();++r) {
			std::cerr << **r <<std::endl;
		}
	}
    Rectangle::setXBorder(xBorder);
    Rectangle::setYBorder(yBorder);
}
/*
 * Make feasible:
 *   - remove overlaps between rectangular boundaries of nodes/clusters
 *     (respecting structural constraints)
 *   - perform routing (preserve previous topology using rubber banding)
 */
void makeFeasible(vpsc::Rectangles& rs, vector<cola::Edge>& edges,
    std::vector<topology::Edge*>& routes,
    std::vector<topology::Node*>& topologyNodes, double defaultEdgeLength) {
    printf("Removing overlaps...\n");
    removeoverlaps(rs,false);
    printf("done.\n");
    printf("Running libavoid to compute routes...\n");
    clock_t libavoidstarttime=clock();
    // find feasible routes for edges
    Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting);
    // Use rotational sweep for point visibility
    router->UseLeesAlgorithm = true;
    // Don't use invisibility graph.
    router->InvisibilityGrph = false;
    double g=0; // make shape that libavoid sees slightly smaller
    for(unsigned i=0;i<rs.size();++i) {
        vpsc::Rectangle* r=rs[i];
        double x=r->getMinX()+g;
        double X=r->getMaxX()-g;
        double y=r->getMinY()+g;
        double Y=r->getMaxY()-g;
        // Create the ShapeRef:
        Avoid::Polygon shapePoly(4);
        // AntiClockwise!
        shapePoly.ps[0] = Avoid::Point(X,y);
        shapePoly.ps[1] = Avoid::Point(X,Y);
        shapePoly.ps[2] = Avoid::Point(x,Y);
        shapePoly.ps[3] = Avoid::Point(x,y);
        //if(i==4||i==13||i==9) {
            //printf("rect[%d]:{%f,%f,%f,%f}\n",i,x,y,X,Y);
        //}
        unsigned int shapeID = i + 1;
        Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly,
                shapeID);
        // ShapeRef constructor makes a copy of polygon so we can free it:
        //router->addShape(shapeRef); // FIXME
    }
    for(unsigned i=0;i<edges.size();++i) {
        cola::Edge e=edges[i];
        Avoid::ConnRef *connRef;
        unsigned int connID = i + rs.size() + 1;
        Rectangle* r0=rs[e.first], *r1=rs[e.second];
        Avoid::Point srcPt(r0->getCentreX(),r0->getCentreY());
        Avoid::Point dstPt(r1->getCentreX(),r1->getCentreY());
        connRef = new Avoid::ConnRef(router, srcPt, dstPt, connID);
        router->processTransaction();
        const Avoid::Polygon& route = connRef->route();
        vector<topology::EdgePoint*> eps;
        eps.push_back( new topology::EdgePoint( topologyNodes[e.first], 
                    topology::EdgePoint::CENTRE));
        for(size_t j=1;j+1<route.size();j++) {
            const Avoid::Point& p = route.ps[j];
            const unsigned nodeID=p.id-1;
            topology::Node* node=topologyNodes[nodeID];
            topology::EdgePoint::RectIntersect ri;
            switch(p.vn) {
                case 0: ri=topology::EdgePoint::BR; 
                        break;
                case 1: ri=topology::EdgePoint::TR; 
                        break;
                case 2: ri=topology::EdgePoint::TL;
                        break;
                case 3: ri=topology::EdgePoint::BL; 
                        break;
                default: ri=topology::EdgePoint::CENTRE;
            }
            eps.push_back(new topology::EdgePoint(node,ri));
        }
        eps.push_back(new topology::EdgePoint(topologyNodes[e.second],
                    topology::EdgePoint::CENTRE));
        topology::Edge* edgeRoute=new topology::Edge(i,defaultEdgeLength, eps);
        edgeRoute->assertConvexBends();
        routes.push_back(edgeRoute);

    }
    writeFile(topologyNodes,routes,"beautify0.svg");
    assert(topology::assertNoSegmentRectIntersection(topologyNodes,routes));
    double libavoidtime=double(clock()-libavoidstarttime)/double(CLOCKS_PER_SEC);
    cout << "done. Libavoid ran in " << libavoidtime << " seconds" << endl;
    delete router;
}
void ColaTopologyAddon::makeFeasible(bool generateNonOverlapConstraints, 
        vpsc::Rectangles& boundingBoxes, cola::RootCluster* clusterHierarchy)
{
    if (generateNonOverlapConstraints)
    {
        // Set up topologyNodes:
        unsigned nodesTotal = boundingBoxes.size();
        topologyNodes = topology::Nodes(nodesTotal);
        for (unsigned id = 0; id < nodesTotal; ++id)
        {
            topologyNodes[id] = new topology::Node(id, boundingBoxes[id]);
        }
    }
  
    if (clusterHierarchy)
    {
        // create cluster boundaries
        unsigned clusterCount=0;
        for (std::vector<cola::Cluster*>::iterator i = 
                clusterHierarchy->clusters.begin();
                i != clusterHierarchy->clusters.end(); ++i, ++clusterCount)
        {
            (*i)->computeBoundary(boundingBoxes);
            cola::ConvexCluster* c=dynamic_cast<cola::ConvexCluster*>(*i);
            if(c!=NULL) {
                double idealCircumference=2.0*sqrt(M_PI*c->area(boundingBoxes));
                std::vector<topology::EdgePoint*> eps;
                for(unsigned j=0;j<c->hullRIDs.size();++j) {
                    const unsigned id = c->nodes[c->hullRIDs[j]];
                    const unsigned char corner = c->hullCorners[j];
                    COLA_ASSERT(id < topologyNodes.size());
                    //cout << "addToPath(vs[" << id << "],";
                    topology::Node *node= topologyNodes[id];
                    topology::EdgePoint::RectIntersect ri;
                    switch(corner) {
                        case 0: 
                            ri=topology::EdgePoint::BR; 
                            //cout << "EdgePoint::BR);" << endl;
                            break;
                        case 1: 
                            ri=topology::EdgePoint::TR; 
                            //cout << "EdgePoint::TR);" << endl;
                            break;
                        case 2: 
                            ri=topology::EdgePoint::TL;
                            //cout << "EdgePoint::TL);" << endl;
                            break;
                        default:
                            COLA_ASSERT(corner==3);
                            ri=topology::EdgePoint::BL; 
                            //cout << "EdgePoint::BL);" << endl;
                            break;
                    }
                    eps.push_back(new topology::EdgePoint(node,ri));
                }
                eps.push_back(eps[0]);
                //cout << "addToPath(vs[" << eps[0]->node->id << "],(EdgePoint::RectIntersect)"<<eps[0]->rectIntersect<<");" << endl;
                topology::Edge* e = new topology::Edge(clusterCount,idealCircumference, eps);
                topologyRoutes.push_back(e);
            }
        }
    }
}