void UMLGraph::undoGenMergers() { SListConstIterator<edge> it; for(it = m_mergeEdges.begin(); it.valid(); ++it) { edge eMerge = *it; node u = eMerge->source(); const DPolyline &common = bends(eMerge); adjEntry adj, adjSucc; for(adj = u->firstAdj(); adj != nullptr; adj = adjSucc) { adjSucc = adj->succ(); edge e = adj->theEdge(); if(e->target() != u) continue; DPolyline &dpl = bends(e); dpl.pushBack(DPoint(x(u),y(u))); ListConstIterator<DPoint> itDp; for(itDp = common.begin(); itDp.valid(); ++itDp) dpl.pushBack(*itDp); m_pG->moveTarget(e,eMerge->target()); } m_pG->delNode(u); } m_mergeEdges.clear(); }
int LayoutStatistics::numberOfBends( const GraphAttributes &ga, int *pMinBendsPerEdge, int *pMaxBendsPerEdge, double *pAvgBendsPerEdge, double *pStdDeviation, bool considerSelfLoops) { const Graph &G = ga.constGraph(); int m = G.numberOfEdges(); int totalBends = 0, minBends = numeric_limits<int>::max(), maxBends = 0; EdgeArray<int> bends(G); int nSelfLoops = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) { nSelfLoops++; continue; } const DPolyline &dpl = ga.bends(e); bends[e] = max(0, dpl.size() - 2); totalBends += bends[e]; minBends = min(minBends, bends[e]); maxBends = max(maxBends, bends[e]); } m -= nSelfLoops; double avgBends = double(totalBends) / m; if(pAvgBendsPerEdge) *pAvgBendsPerEdge = avgBends; if(pMinBendsPerEdge) *pMinBendsPerEdge = minBends; if(pMaxBendsPerEdge) *pMaxBendsPerEdge = maxBends; if(pStdDeviation) { double sum = 0; for(edge e : G.edges) { if(!considerSelfLoops && e->isSelfLoop()) continue; double d = bends[e] - avgBends; sum += d*d; } *pStdDeviation = sqrt(sum / m); } return totalBends; }
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); }