// faster version of computePolylineClear // clears the list of bend points of all edges in the edge path // in the copy corresponding to eOrig! void Layout::computePolylineClear(PlanRep &PG, edge eOrig, DPolyline &dpl) { dpl.clear(); const List<edge> &edgePath = PG.chain(eOrig); // The corresponding edge path in the copy must contain at least 1 edge! OGDF_ASSERT(edgePath.size() >= 1); // iterate over all edges in the corresponding edge path in the copy bool firstTime = true; for (edge e : edgePath) { node v = e->source(); // append point of source node of e ... if (!firstTime) dpl.pushBack(DPoint(m_x[v], m_y[v])); else firstTime = false; // ... and polyline of e dpl.conc(m_bends[e]); } node w = edgePath.back()->target(); if (PG.typeOf(w) == Graph::NodeType::generalizationExpander) dpl.pushBack(DPoint(m_x[w], m_y[w])); }
void SubgraphPlanarizer::CrossingStructure::init(PlanRep &PG, int weightedCrossingNumber) { m_weightedCrossingNumber = weightedCrossingNumber; m_crossings.init(PG.original()); m_numCrossings = 0; NodeArray<int> index(PG,-1); node v; forall_nodes(v,PG) if(PG.isDummy(v)) index[v] = m_numCrossings++; edge ePG; forall_edges(ePG,PG) { if(PG.original(ePG->source()) != 0) { edge e = PG.original(ePG); ListConstIterator<edge> it = PG.chain(e).begin(); for(++it; it.valid(); ++it) { //cout << index[(*it)->source()] << " "; m_crossings[e].pushBack(index[(*it)->source()]); } } } }
void AbacusOptimalCrossingMinimizer::KuratowskiConstraint::addAccordingCrossing( const Subproblem* S, const PlanRep& I, edge e, int eid, List<CrossingInfo*>& L) { const List<edge>& le = I.chain(e); OGDF_ASSERT( le.size() == 2 ); OGDF_ASSERT( le.front()->target() == le.back()->source() ); node n = le.front()->target(); edge c, te; forall_adj_edges(te, n) { c = I.original(te); if(c != e) break; }
DPoint Layout::computeBoundingBox(PlanRep &PG) const { double maxWidth = 0; double maxHeight = 0; // check rightmost and uppermost extension of all (original) nodes for(int i = PG.startNode(); i < PG.stopNode(); ++i) { node vG = PG.v(i); double maxX = x(PG.copy(vG)) + PG.widthOrig(vG)/2; if (maxX > maxWidth ) maxWidth = maxX; double maxY = y(PG.copy(vG)) + PG.heightOrig(vG)/2; if (maxY > maxHeight) maxHeight = maxY; // check polylines of all (original) edges for(adjEntry adj : vG->adjEntries) { if ((adj->index() & 1) == 0) continue; edge eG = adj->theEdge(); const List<edge> &path = PG.chain(eG); for(edge e : path) { // we have to check (only) all interior points, i.e., we can // omitt the first and last point since it lies in the box of // the source or target node. // This version checks also the first for simplicity of the loop. node v = e->source(); if (x(v) > maxWidth ) maxWidth = x(v); if (y(v) > maxHeight) maxHeight = y(v); const DPolyline &dpl = bends(e); for(const DPoint &dp : dpl) { if (dp.m_x > maxWidth ) maxWidth = dp.m_x; if (dp.m_y > maxHeight) maxHeight = dp.m_y; } } } } return DPoint(maxWidth,maxHeight); }
//--------------------------------------------------------- // actual call (called by all variations of call) // crossing of generalizations is forbidden if forbidCrossingGens = true // edge costs are obeyed if costOrig != 0 // Module::ReturnType FixedEmbeddingInserter::doCall( PlanRep &PG, const List<edge> &origEdges, bool forbidCrossingGens, const EdgeArray<int> *costOrig, const EdgeArray<bool> *forbiddenEdgeOrig, const EdgeArray<unsigned int> *edgeSubGraph) { double T; usedTime(T); ReturnType retValue = retFeasible; m_runsPostprocessing = 0; PG.embed(); OGDF_ASSERT(PG.representsCombEmbedding() == true); if (origEdges.size() == 0) return retOptimal; // nothing to do // initialization CombinatorialEmbedding E(PG); // embedding of PG m_dual.clear(); m_primalAdj.init(m_dual); m_nodeOf.init(E); // construct dual graph m_primalIsGen.init(m_dual,false); OGDF_ASSERT(forbidCrossingGens == false || forbiddenEdgeOrig == 0); if(forbidCrossingGens) constructDualForbidCrossingGens((const PlanRepUML&)PG,E); else constructDual(PG,E,forbiddenEdgeOrig); // m_delFaces and m_newFaces are used by removeEdge() // if we can't allocate memory for them, we throw an exception if (removeReinsert() != rrNone) { m_delFaces = new FaceSetSimple(E); if (m_delFaces == 0) OGDF_THROW(InsufficientMemoryException); m_newFaces = new FaceSetPure(E); if (m_newFaces == 0) { delete m_delFaces; OGDF_THROW(InsufficientMemoryException); } // no postprocessing -> no removeEdge() } else { m_delFaces = 0; m_newFaces = 0; } SListPure<edge> currentOrigEdges; if(removeReinsert() == rrIncremental) { edge e; forall_edges(e,PG) currentOrigEdges.pushBack(PG.original(e)); } // insertion of edges ListConstIterator<edge> it; for(it = origEdges.begin(); it.valid(); ++it) { edge eOrig = *it; int eSubGraph = 0; // edgeSubGraph-data of eOrig if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig]; SList<adjEntry> crossed; if(costOrig != 0) { findShortestPath(PG, E, *costOrig, PG.copy(eOrig->source()),PG.copy(eOrig->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association, crossed, edgeSubGraph, eSubGraph); } else { findShortestPath(E, PG.copy(eOrig->source()),PG.copy(eOrig->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association, crossed); } insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig); if(removeReinsert() == rrIncremental) { currentOrigEdges.pushBack(eOrig); bool improved; do { ++m_runsPostprocessing; improved = false; SListConstIterator<edge> itRR; for(itRR = currentOrigEdges.begin(); itRR.valid(); ++itRR) { edge eOrigRR = *itRR; int pathLength; if(costOrig != 0) pathLength = costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph); else pathLength = PG.chain(eOrigRR).size() - 1; if (pathLength == 0) continue; // cannot improve removeEdge(PG,E,eOrigRR,forbidCrossingGens,forbiddenEdgeOrig); // try to find a better insertion path SList<adjEntry> crossed; if(costOrig != 0) { int eSubGraph = 0; // edgeSubGraph-data of eOrig if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrigRR]; findShortestPath(PG, E, *costOrig, PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association, crossed, edgeSubGraph, eSubGraph); } else { findShortestPath(E, PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association, crossed); } // re-insert edge (insertion path cannot be longer) insertEdge(PG,E,eOrigRR,crossed,forbidCrossingGens,forbiddenEdgeOrig); int newPathLength = (costOrig != 0) ? costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrigRR).size() - 1); OGDF_ASSERT(newPathLength <= pathLength); if(newPathLength < pathLength) improved = true; } } while (improved); } } const Graph &G = PG.original(); if(removeReinsert() != rrIncremental) { // postprocessing (remove-reinsert heuristc) SListPure<edge> rrEdges; switch(removeReinsert()) { case rrAll: case rrMostCrossed: { const List<node> &origInCC = PG.nodesInCC(); ListConstIterator<node> itV; for(itV = origInCC.begin(); itV.valid(); ++itV) { node vG = *itV; adjEntry adj; forall_adj(adj,vG) { if ((adj->index() & 1) == 0) continue; edge eG = adj->theEdge(); rrEdges.pushBack(eG); } } } break; case rrInserted: for(ListConstIterator<edge> it = origEdges.begin(); it.valid(); ++it) rrEdges.pushBack(*it); break; case rrNone: case rrIncremental: break; } // marks the end of the interval of rrEdges over which we iterate // initially set to invalid iterator which means all edges SListConstIterator<edge> itStop; bool improved; do { // abort postprocessing if time limit reached if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) { retValue = retTimeoutFeasible; break; } ++m_runsPostprocessing; improved = false; if(removeReinsert() == rrMostCrossed) { FEICrossingsBucket bucket(&PG); rrEdges.bucketSort(bucket); const int num = int(0.01 * percentMostCrossed() * G.numberOfEdges()); itStop = rrEdges.get(num); } SListConstIterator<edge> it; for(it = rrEdges.begin(); it != itStop; ++it) { edge eOrig = *it; // remove only if crossings on edge; // in especially: forbidden edges are never handled by postprocessing // since there are no crossings on such edges int pathLength; if(costOrig != 0) pathLength = costCrossed(eOrig,PG,*costOrig,edgeSubGraph); else pathLength = PG.chain(eOrig).size() - 1; if (pathLength == 0) continue; // cannot improve removeEdge(PG,E,eOrig,forbidCrossingGens,forbiddenEdgeOrig); // try to find a better insertion path SList<adjEntry> crossed; if(costOrig != 0) { int eSubGraph = 0; // edgeSubGraph-data of eOrig if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig]; findShortestPath(PG, E, *costOrig, PG.copy(eOrig->source()),PG.copy(eOrig->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association, crossed, edgeSubGraph, eSubGraph); } else { findShortestPath(E, PG.copy(eOrig->source()),PG.copy(eOrig->target()), forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association, crossed); } // re-insert edge (insertion path cannot be longer) insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig); int newPathLength = (costOrig != 0) ? costCrossed(eOrig,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrig).size() - 1); OGDF_ASSERT(newPathLength <= pathLength); if(newPathLength < pathLength) improved = true; } } while(improved); // iterate as long as we improve }
int getBucket(const edge &e) { return -m_pPG->chain(e).size(); }