/* * @param target1 the first of two possible target segments for the transfer * @param target2 the second of two possible target segments for the * transfer * @param ignore the constraint which, in being satisfied, caused this * transfer and which should therefore not be transfered. */ transferStraightConstraintChoose(Segment* target1, Segment* target2, StraightConstraint* ignore) : ignore(ignore) { vpsc::Dim dim = ignore->scanDim; double min1=min(target1->start->pos(vpsc::conjugate(dim)),target1->end->pos(vpsc::conjugate(dim))); double max1=max(target1->start->pos(vpsc::conjugate(dim)),target1->end->pos(vpsc::conjugate(dim))); double min2=min(target2->start->pos(vpsc::conjugate(dim)),target2->end->pos(vpsc::conjugate(dim))); double max2=max(target2->start->pos(vpsc::conjugate(dim)),target2->end->pos(vpsc::conjugate(dim))); if(min1<max2) { COLA_ASSERT(max1==min2); lSeg = target1; rSeg = target2; lMin = min1; mid = max1; rMax = max2; } else { COLA_ASSERT(max2==min1); lSeg = target2; rSeg = target1; lMin = min2; mid = max2; rMax = max1; } }
static double hRule8(vpsc::Dim dim, const EdgePoint* u, const EdgePoint* v, const EdgePoint* w, const EdgePoint* a, const EdgePoint* b, const EdgePoint* c) { double dxuv, dyuv, dxuv2, dyuv2; double luv=dim==vpsc::HORIZONTAL? len(u,v,dxuv,dyuv,dxuv2,dyuv2): len(u,v,dyuv,dxuv,dyuv2,dxuv2); COLA_ASSERT(luv!=0); double dxvw, dyvw, dxvw2, dyvw2; double lvw=dim==vpsc::HORIZONTAL? len(v,w,dxvw,dyvw,dxvw2,dyvw2): len(v,w,dyvw,dxvw,dyvw2,dxvw2); COLA_ASSERT(lvw!=0); double dxab, dyab, dxab2, dyab2; double lab=dim==vpsc::HORIZONTAL? len(a,b,dxab,dyab,dxab2,dyab2): len(a,b,dyab,dxab,dyab2,dxab2); COLA_ASSERT(lab!=0); double dxbc, dybc, dxbc2, dybc2; double lbc=dim==vpsc::HORIZONTAL? len(b,c,dxbc,dybc,dxbc2,dybc2): len(b,c,dybc,dxbc,dybc2,dxbc2); COLA_ASSERT(lbc!=0); return (dxuv/luv - dxvw/lvw) * (dxab/lab - dxbc/lbc); }
// Returns the rotationalAngle, between 0 and 360, of this point from (0,0). // double rotationalAngle(const Point& p) { if (p.y == 0) { return ((p.x < 0) ? 180 : 0); } else if (p.x == 0) { return ((p.y < 0) ? 270 : 90); } double ang = atan(p.y / p.x); ang = (ang * 180) / M_PI; if (p.x < 0) { ang += 180; } else if (p.y < 0) { ang += 360; } COLA_ASSERT(ang >= 0); COLA_ASSERT(ang <= 360); return ang; }
Obstacle::~Obstacle() { COLA_ASSERT(!m_router->objectIsInQueuedActionList(this)); if (m_active) { makeInactive(); m_router->processTransaction(); } COLA_ASSERT(m_first_vert != NULL); VertInf *it = m_first_vert; do { VertInf *tmp = it; it = it->shNext; delete tmp; } while (it != m_first_vert); m_first_vert = m_last_vert = NULL; // Free and clear any connection pins. while (!m_connection_pins.empty()) { delete *(m_connection_pins.begin()); } }
void Obstacle::setNewPoly(const Polygon& poly) { COLA_ASSERT(m_first_vert != NULL); COLA_ASSERT(m_polygon.size() == poly.size()); m_polygon = poly; Polygon routingPoly = routingPolygon(); VertInf *curr = m_first_vert; for (size_t pt_i = 0; pt_i < routingPoly.size(); ++pt_i) { COLA_ASSERT(curr->visListSize == 0); COLA_ASSERT(curr->invisListSize == 0); // Reset with the new polygon point. curr->Reset(routingPoly.ps[pt_i]); curr->pathNext = NULL; curr = curr->shNext; } COLA_ASSERT(curr == m_first_vert); // It may be that the polygon for the obstacle has been updated after // creating the shape. These events may have been combined for a single // transaction, so update pin positions. for (ShapeConnectionPinSet::iterator curr = m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr) { ShapeConnectionPin *pin = *curr; pin->updatePosition(m_polygon); } }
void floyd_warshall( unsigned const n, T** D, vector<Edge> const & es, valarray<T> const * eweights) { COLA_ASSERT(!eweights||eweights->size()==es.size()); for(unsigned i=0;i<n;i++) { for(unsigned j=0;j<n;j++) { if(i==j) D[i][j]=0; else D[i][j]=numeric_limits<T>::max(); } } for(unsigned i=0;i<es.size();i++) { unsigned u=es[i].first, v=es[i].second; COLA_ASSERT(u<n&&v<n); D[u][v]=D[v][u]=eweights?(*eweights)[i]:1; } for(unsigned k=0; k<n; k++) { for(unsigned i=0; i<n; i++) { for(unsigned j=0; j<n; j++) { D[i][j]=min(D[i][j],D[i][k]+D[k][j]); } } } }
ReferencingPolygon::ReferencingPolygon(const Polygon& poly, const Router *router) : PolygonInterface(), _id(poly._id), psRef(poly.size()), psPoints(poly.size()) { COLA_ASSERT(router != NULL); for (size_t i = 0; i < poly.size(); ++i) { if (poly.ps[i].id == 0) { // Can't be referenced, so just make a copy of the point. psRef[i] = std::make_pair((Polygon *) NULL, kUnassignedVertexNumber); psPoints[i] = poly.ps[i]; } else { const Polygon *polyPtr = NULL; for (ObstacleList::const_iterator sh = router->m_obstacles.begin(); sh != router->m_obstacles.end(); ++sh) { if ((*sh)->id() == poly.ps[i].id) { const Polygon& poly = (*sh)->polygon(); polyPtr = &poly; break; } } COLA_ASSERT(polyPtr != NULL); psRef[i] = std::make_pair(polyPtr, poly.ps[i].vn); } } }
void VertInfList::addVertex(VertInf *vert) { checkVertInfListConditions(); COLA_ASSERT(vert->lstPrev == NULL); COLA_ASSERT(vert->lstNext == NULL); if (vert->id.isConnPt()) { // A Connector vertex if (_firstConnVert) { // Join with previous front vert->lstNext = _firstConnVert; _firstConnVert->lstPrev = vert; // Make front _firstConnVert = vert; } else { // Make front and back _firstConnVert = vert; _lastConnVert = vert; // Link to front of shapes list vert->lstNext = _firstShapeVert; } _connVertices++; } else // if (vert->id.shape > 0) { // A Shape vertex if (_lastShapeVert) { // Join with previous back vert->lstPrev = _lastShapeVert; _lastShapeVert->lstNext = vert; // Make back _lastShapeVert = vert; } else { // Make first and last _firstShapeVert = vert; _lastShapeVert = vert; // Join with conns list if (_lastConnVert) { COLA_ASSERT(_lastConnVert->lstNext == NULL); _lastConnVert->lstNext = vert; } } _shapeVertices++; } checkVertInfListConditions(); }
Polygon Obstacle::routingPolygon(void) const { COLA_ASSERT(!m_polygon.empty()); COLA_ASSERT(m_router); double bufferSpace = m_router->routingParameter(shapeBufferDistance); return m_polygon.offsetPolygon(bufferSpace); }
// Creates the connection between a connector and a shape/junction. void ConnEnd::connect(ConnRef *conn) { COLA_ASSERT(isPinConnection()); COLA_ASSERT(m_anchor_obj); COLA_ASSERT(m_conn_ref == NULL); m_anchor_obj->addFollowingConnEnd(this); m_conn_ref = conn; }
void HyperedgeTreeNode::validateHyperedge(const HyperedgeTreeEdge *ignored, const size_t dist) const { size_t newDist = dist; #ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG if (junction) { if (newDist == 0) { fprintf(stderr,"\nHyperedge topology:\n"); } else { ++newDist; } for (size_t d = 0; d < newDist; ++d) { fprintf(stderr," "); } fprintf(stderr, "j(%d)\n", junction->id()); ++newDist; } else if (edges.size() == 1) { ++newDist; for (size_t d = 0; d < newDist; ++d) { fprintf(stderr, " "); } fprintf(stderr, "t()\n"); ++newDist; } #endif for (std::list<HyperedgeTreeEdge *>::const_iterator curr = edges.begin(); curr != edges.end(); ++curr) { HyperedgeTreeEdge *edge = *curr; std::pair<ConnEnd, ConnEnd> connEnds = edge->conn->endpointConnEnds(); if (junction) { COLA_ASSERT((connEnds.first.junction() == junction) || (connEnds.second.junction() == junction)); COLA_ASSERT(connEnds.first.junction() != connEnds.second.junction()); } else if (edges.size() == 1) { COLA_ASSERT(!connEnds.first.junction() || !connEnds.second.junction()); } if (edge != ignored) { edge->validateHyperedge(this, newDist); } } }
// This method disconnects the hyperedge tree edge nodes that it's attached to. // void HyperEdgeTreeEdge::disconnectEdge(void) { COLA_ASSERT(ends.first != NULL); COLA_ASSERT(ends.second != NULL); ends.first->disconnectEdge(this); ends.second->disconnectEdge(this); ends.first = NULL; ends.second = NULL; }
void dijkstra( unsigned const s, unsigned const n, T* d, vector<Edge> const & es, valarray<T> const * eweights) { COLA_ASSERT(!eweights||es.size()==eweights->size()); COLA_ASSERT(s<n); vector<Node<T> > vs(n); dijkstra_init(vs,es,eweights); dijkstra(s,vs,d); }
// Populate the deleted-object vectors with all the connectors and junctions // that form the registered hyperedges. Then return the set of all these // connectors so they can be ignored for individual rerouting. ConnRefSet HyperedgeRerouter::calcHyperedgeConnectors(void) { COLA_ASSERT(m_router != NULL); ConnRefSet allRegisteredHyperedgeConns; // Clear the deleted-object vectors. We populate them here if necessary. m_deleted_junctions_vector.clear(); m_deleted_junctions_vector.resize(count()); m_deleted_connectors_vector.clear(); m_deleted_connectors_vector.resize(count()); m_terminal_vertices_vector.clear(); m_terminal_vertices_vector.resize(count()); m_added_vertices.clear(); // Populate the deleted-object vectors. const size_t num_hyperedges = count(); for (size_t i = 0; i < num_hyperedges; ++i) { if (m_root_junction_vector[i]) { // Follow objects attached to junction to find the hyperedge. findAttachedObjects(i, m_root_junction_vector[i], NULL, allRegisteredHyperedgeConns); continue; } // Alternatively, we have a set of ConnEnds, so store the // corresponding terminals std::pair<bool, VertInf *> maybeNewVertex; for (ConnEndList::const_iterator it = m_terminals_vector[i].begin(); it != m_terminals_vector[i].end(); ++it) { maybeNewVertex = it->getHyperedgeVertex(m_router); COLA_ASSERT(maybeNewVertex.second != NULL); m_terminal_vertices_vector[i].insert(maybeNewVertex.second); if (maybeNewVertex.first) { // This is a newly created vertex. Remember it so we can // free it and it's visibility edges later. m_added_vertices.push_back(maybeNewVertex.second); } } } // Return these connectors that don't require rerouting. return allRegisteredHyperedgeConns; }
static double hRule4(vpsc::Dim dim, const EdgePoint* a, const EdgePoint* b, const EdgePoint* c, const EdgePoint* d) { double dxab, dyab, dxab2, dyab2; double lab=dim==vpsc::HORIZONTAL? len(a,b,dxab,dyab,dxab2,dyab2): len(a,b,dyab,dxab,dyab2,dxab2); COLA_ASSERT(lab!=0); double dxcd, dycd, dxcd2, dycd2; double lcd=dim==vpsc::HORIZONTAL? len(c,d,dxcd,dycd,dxcd2,dycd2): len(c,d,dycd,dxcd,dycd2,dxcd2); COLA_ASSERT(lcd!=0); return -dxab*dxcd/(lab*lcd); }
ConnEnd::ConnEnd(ShapeRef *shapeRef, const unsigned int connectionPinClassID) : m_type(ConnEndShapePin), m_point(Point(0,0)), m_directions(ConnDirAll), m_connection_pin_class_id(connectionPinClassID), m_anchor_obj(shapeRef), m_conn_ref(NULL), m_active_pin(NULL) { COLA_ASSERT(m_anchor_obj != NULL); COLA_ASSERT(m_connection_pin_class_id > 0); m_point = m_anchor_obj->position(); COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET); }
static double gRule2(vpsc::Dim dim, const EdgePoint* a, const EdgePoint* b, const EdgePoint* c) { double dxab, dyab, dxab2, dyab2; double lab=dim==vpsc::HORIZONTAL? len(a,b,dxab,dyab,dxab2,dyab2): len(a,b,dyab,dxab,dyab2,dxab2); COLA_ASSERT(lab!=0); double dxbc, dybc, dxbc2, dybc2; double lbc=dim==vpsc::HORIZONTAL? len(b,c,dxbc,dybc,dxbc2,dybc2): len(b,c,dybc,dxbc,dybc2,dxbc2); COLA_ASSERT(lbc!=0); return dxab/lab - dxbc/lbc; }
double GradientProjection::computeSteepestDescentVector( valarray<double> const &b, valarray<double> const &x, valarray<double> &g) const { // find steepest descent direction // g = 2 ( b - A x ) // where: A = denseQ + sparseQ // g = 2 ( b - denseQ x) - 2 sparseQ x // // except the 2s don't matter because we compute // the optimal stepsize anyway COLA_ASSERT(x.size()==b.size() && b.size()==g.size()); g = b; for (unsigned i=0; i<denseSize; i++) { for (unsigned j=0; j<denseSize; j++) { g[i] -= (*denseQ)[i*denseSize+j]*x[j]; } } // sparse part: if(sparseQ) { valarray<double> r(x.size()); sparseQ->rightMultiply(x,r); g-=r; } return computeStepSize(g,g); }
bool zagzig(const EdgePoint* a, const Segment* s) { COLA_UNUSED(a); if(s!=nullptr) { COLA_ASSERT(!sameCorner(a,s->start)); } return false; }
bool sameCorner(const EdgePoint* a, const EdgePoint* b) { COLA_UNUSED(a); COLA_UNUSED(b); COLA_ASSERT( !(a->node->id==b->node->id &&a->rectIntersect==b->rectIntersect)); return false; }
ShapeConnectionPin::ShapeConnectionPin(JunctionRef *junction, const unsigned int classId, const ConnDirFlags visDirs) : m_shape(NULL), m_junction(junction), m_class_id(classId), m_x_portion_offset(0.0), m_y_portion_offset(0.0), m_inside_offset(0.0), m_visibility_directions(visDirs), m_exclusive(true), m_connection_cost(0.0), m_vertex(NULL) { COLA_ASSERT(m_junction != NULL); m_router = m_junction->router(); m_junction->addConnectionPin(this); // Create a visibility vertex for this ShapeConnectionPin. VertID id(m_junction->id(), kShapeConnectionPin, VertID::PROP_ConnPoint | VertID::PROP_ConnectionPin); m_vertex = new VertInf(m_router, id, m_junction->position()); m_vertex->visDirections = visDirs; if (m_router->_polyLineRouting) { vertexVisibility(m_vertex, NULL, true, true); } }
void Obstacle::makeInactive(void) { COLA_ASSERT(m_active); // Remove from shapeRefs list. m_router->m_obstacles.erase(m_router_obstacles_pos); // Remove points from vertex list. VertInf *it = m_first_vert; do { VertInf *tmp = it; it = it->shNext; m_router->vertices.removeVertex(tmp); } while (it != m_first_vert); m_active = false; // Turn attached ConnEnds into manual points. bool deletedShape = true; while (!m_following_conns.empty()) { ConnEnd *connEnd = *(m_following_conns.begin()); connEnd->disconnect(deletedShape); } }
void VertInf::removeFromGraph(const bool isConnVert) { if (isConnVert) { COLA_ASSERT(id.isConnPt()); } // For each vertex. EdgeInfList::const_iterator finish = visList.end(); EdgeInfList::const_iterator edge; while ((edge = visList.begin()) != finish) { // Remove each visibility edge (*edge)->alertConns(); delete (*edge); } finish = orthogVisList.end(); while ((edge = orthogVisList.begin()) != finish) { // Remove each orthogonal visibility edge. (*edge)->alertConns(); delete (*edge); } finish = invisList.end(); while ((edge = invisList.begin()) != finish) { // Remove each invisibility edge delete (*edge); } }
ConnRefList HyperedgeRerouter::deletedConnectorList( size_t index) const { COLA_ASSERT(index <= count()); return m_deleted_connectors_vector[index]; }
JunctionRefList HyperedgeRerouter::deletedJunctionList( size_t index) const { COLA_ASSERT(index <= count()); return m_deleted_junctions_vector[index]; }
bool zigzag(const EdgePoint* a, const Segment* s) { COLA_UNUSED(a); if(s!=NULL) { COLA_ASSERT(!sameCorner(a,s->end)); } return false; }
void ColaTopologyAddon::handleResizes(const cola::Resizes& resizeList, unsigned n, std::valarray<double>& X, std::valarray<double>& Y, cola::CompoundConstraints& ccs, vpsc::Rectangles& boundingBoxes, cola::RootCluster* clusterHierarchy) { FILE_LOG(cola::logDEBUG) << "ColaTopologyAddon::handleResizes()..."; if(topologyNodes.empty()) { COLA_ASSERT(topologyRoutes.empty()); return; } // all shapes to be resized are wrapped in a ResizeInfo and // placed in a lookup table, resizes, indexed by id ResizeMap resizes; for(cola::Resizes::const_iterator r=resizeList.begin();r!=resizeList.end();++r) { topology::ResizeInfo ri(topologyNodes[r->getID()],r->getTarget()); resizes.insert(std::make_pair(r->getID(),ri)); } vpsc::Variables xvs, yvs; vpsc::Constraints xcs, ycs; cola::setupVarsAndConstraints(n, ccs, vpsc::HORIZONTAL, boundingBoxes, clusterHierarchy, xvs, xcs, X); cola::setupVarsAndConstraints(n, ccs, vpsc::VERTICAL, boundingBoxes, clusterHierarchy, yvs, ycs, Y); topology::applyResizes(topologyNodes, topologyRoutes, clusterHierarchy, resizes, xvs, xcs, yvs, ycs); for_each(xvs.begin(), xvs.end(), delete_object()); for_each(yvs.begin(), yvs.end(), delete_object()); for_each(xcs.begin(), xcs.end(), delete_object()); for_each(ycs.begin(), ycs.end(), delete_object()); FILE_LOG(cola::logDEBUG) << "ColaTopologyAddon::handleResizes()... done."; }
// Follow connected junctions and connectors from the given junction to // determine the hyperedge topology, saving objects to the deleted-objects // vectors as we go. bool HyperedgeRerouter::findAttachedObjects(size_t index, JunctionRef *junction, ConnRef *ignore, ConnRefSet& hyperedgeConns) { bool validHyperedge = false; m_deleted_junctions_vector[index].push_back(junction); ConnRefList connectors = junction->attachedConnectors(); if (connectors.size() > 2) { // A valid hyperedge must have at least one junction with three // connectors attached, i.e., more than two endpoints. validHyperedge |= true; } for (ConnRefList::iterator curr = connectors.begin(); curr != connectors.end(); ++curr) { if (*curr == ignore) { continue; } COLA_ASSERT(*curr != NULL); validHyperedge |= findAttachedObjects(index, (*curr), junction, hyperedgeConns); } return validHyperedge; }
// This method traverses the hyperedge tree and creates connectors for each // segment bridging junction and/or terminals. It also sets the // appropriate ConnEnds for each connector. // void HyperEdgeTreeNode::addConns(HyperEdgeTreeEdge *ignored, Router *router, ConnRefList& oldConns, ConnRef *conn) { // If no connector is set, then we must be starting off at a junction. COLA_ASSERT(conn || junction); for (std::list<HyperEdgeTreeEdge *>::iterator curr = edges.begin(); curr != edges.end(); ++curr) { if (*curr != ignored) { // If we're not at a junction, then use the connector value being // passed in to the method. if (junction) { // If we're at a junction, then we are effectively starting // our traversal along a connector, so create this new connector // and set it's start ConnEnd to be this junction. conn = new ConnRef(router); router->removeObjectFromQueuedActions(conn); conn->makeActive(); conn->m_initialised = true; ConnEnd connend(junction); conn->updateEndPoint(VertID::src, connend); } // Set the connector for this edge. (*curr)->conn = conn; // Continue recursive traversal. (*curr)->addConns(this, router, oldConns); } } }
// 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); }