Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

CompactionConstraintGraph.h
Go to the documentation of this file.
1 
35 #pragma once
36 
37 
38 #include <ogdf/basic/Graph.h>
39 #include <ogdf/basic/GraphList.h>
40 #include <ogdf/basic/List.h>
41 #include <ogdf/basic/SList.h>
42 #include <ogdf/basic/basic.h>
43 #include <ogdf/basic/comparer.h>
44 #include <ogdf/basic/exceptions.h>
45 #include <ogdf/basic/tuples.h>
50 #include <ogdf/planarity/PlanRep.h>
51 
52 #include <algorithm>
53 #include <iostream>
54 #include <string>
55 
56 namespace ogdf {
57 
60 public:
63 
65  bool verticalGen(edge e) const { return m_verticalGen[e]; }
66 
69  bool verticalArc(edge e) const { return m_verticalArc[e]; }
70 
72 
74  void align(bool b) { m_align = b; }
75 
78  bool alignmentArc(edge e) const { return m_alignmentArc[e]; }
79 
81 
82 protected:
84  CompactionConstraintGraphBase(const OrthoRep& OR, const PlanRep& PG, OrthoDir arcDir,
85  int costGen = 1, int costAssoc = 1, bool align = false);
86 
87  int m_edgeCost[2];
88 
89  //test fuer vorkomp. der Generalisierungen
92 
95 
97 
98 private:
99  //set special costs for node to merger generalizations
100  bool m_align;
101 
102  void insertPathVertices(const PlanRep& PG);
103  void dfsInsertPathVertex(node v, node pathVertex, NodeArray<bool>& visited,
104  const NodeArray<node>& genOpposite);
105 
106  void insertBasicArcs(const PlanRep& PG);
107 };
108 
119 template<class ATYPE>
121 public:
123  CompactionConstraintGraph(const OrthoRep& OR, const PlanRep& PG, OrthoDir arcDir, ATYPE sep,
124  int costGen = 1, int costAssoc = 1, bool align = false)
125  : CompactionConstraintGraphBase(OR, PG, arcDir, costGen, costAssoc, align) {
126  OGDF_ASSERT(&(const Graph&)PG == &(const Graph&)OR);
127 
128  m_length.init((Graph&)*this, sep);
129  m_extraOfs.init((Graph&)*this, 0);
130  m_extraRep.init((Graph&)*this, nullptr);
131 
132  m_sep = sep;
133 
134  m_centerPriority = true; //should centering of single edges have prio. to gen. length
135  m_genToMedian = true; //should outgoing merger gen. be drawn to merger median
136 
137  initializeCosts();
138  }
139 
142  ATYPE length(edge e) const { return m_length[e]; }
143 
145  ATYPE extraOfs(node v) const { return m_extraOfs[v]; }
146 
148  bool centerPriority() { return m_centerPriority; }
149 
151  void centerPriority(bool b) { m_centerPriority = b; }
152 
155  ATYPE computeTotalCosts(const NodeArray<ATYPE>& pos) const;
156 
161  void insertVertexSizeArcs(const PlanRep& PG, const NodeArray<ATYPE>& sizeOrig,
162  const RoutingChannel<ATYPE>& rc);
163 
169  void insertVertexSizeArcs(const PlanRep& PG, const NodeArray<ATYPE>& sizeOrig,
170  const MinimumEdgeDistances<ATYPE>& minDist);
171 
175  void insertVisibilityArcs(const PlanRep& PG,
176  const NodeArray<ATYPE>& posDir,
177  const NodeArray<ATYPE>& posOppDir
178  );
179 
180  void insertVisibilityArcs(const PlanRep& PG, const NodeArray<ATYPE>& posDir,
181  const NodeArray<ATYPE>& posOrthDir, const MinimumEdgeDistances<ATYPE>& minDist);
182 
184  void setMinimumSeparation(const PlanRep& PG, const NodeArray<int>& coord,
185  const MinimumEdgeDistances<ATYPE>& minDist);
186 
191  bool isFeasible(const NodeArray<ATYPE>& pos);
192 
194  ATYPE separation() const { return m_sep; }
195 
197  bool areMulti(edge e1, edge e2) const;
198 
199 private:
201  struct Interval {
202  Interval(node v, ATYPE low, ATYPE high) {
203  m_low = low;
204  m_high = high;
205  m_pathNode = v;
206  }
207 
208  ATYPE m_low, m_high;
210 
212  friend std::ostream& operator<<(std::ostream& os, const Interval& interval) {
213  os << "[" << interval.m_low << "," << interval.m_high << ";" << interval.m_pathNode
214  << "]";
215  return os;
216  }
217  };
218 
224  public:
225  SegmentComparer(const NodeArray<ATYPE>& segPos, const NodeArray<int>& secSort) {
226  m_pPos = &segPos;
227  m_pSec = &secSort;
228  }
229 
230  int compare(const node& x, const node& y) const {
231  ATYPE d = (*m_pPos)[x] - (*m_pPos)[y];
232  if (d < 0) {
233  return -1;
234  } else if (d > 0) {
235  return 1;
236  } else {
237  return (*m_pSec)[x] - (*m_pSec)[y];
238  }
239  }
240 
242  private:
245  };
246 
247  virtual string getLengthString(edge e) const override { return to_string(m_length[e]); }
248 
249  void setBasicArcsZeroLength(const PlanRep& PG);
250  void resetGenMergerLengths(const PlanRep& PG, adjEntry adjFirst);
251  void setBoundaryCosts(adjEntry cornerDir, adjEntry cornerOppDir);
252 
253  bool checkSweepLine(const List<Interval>& sweepLine) const;
254 
255  ATYPE m_sep;
256 
258 
260 
263 
264  // we make vertex size arcs more expensive than basic arcs in order
265  // to get small cages
266  // should be replaced by option/value dependent on e.g. degree
272  //this does not work if generalization costs are set very small by the user
273  //because there must be a minimum cost for centering
275 
276  //factor of costs relative to generalization
277  static const int c_vertexArcFactor;
278  static const int c_bungeeFactor;
279  static const int c_doubleBendFactor;
280  static const int c_MedianFactor;
281 
283 
284 protected:
286  void setExtra(node v, node rep, ATYPE ofs) {
287  m_extraNode[v] = true;
288  m_extraRep[v] = rep;
289  m_extraOfs[v] = ofs;
290  }
291 
293  // we make vertex size arcs more expensive than basic arcs in order
294  // to get small cages; not necessary if cage size fixed in improvement
295  // cost should be dependend on degree
296  // Z.B. DURCH OPTION ODER WERT; DER VON DER ZAHL ADJAZENTER KANTEN ABHAENGIG IST
297  // should be derived by number of edges times something
298  int costGen = m_edgeCost[static_cast<int>(Graph::EdgeType::generalization)];
299 
300  m_vertexArcCost = c_vertexArcFactor * costGen; //spaeter aus Kompaktierungsmodul uebergeben
301  if (m_centerPriority) {
302  m_bungeeCost = c_bungeeFactor * costGen + 1; //-1;//for distance to middle position,
303  } else {
304  m_bungeeCost = c_bungeeFactor * 4 + 1; //-1;//for distance to middle position,
305  }
306  //addition value should be < gen cost!!!
309  }
310 };
311 
312 //initialization of static members
313 template<class ATYPE>
315 template<class ATYPE>
317 template<class ATYPE>
319  20; //double bends cost mxxx*vertexArcCost
320 //factor *VertexArcCost, costs for pulling generalization to median position at merger
321 template<class ATYPE>
322 const int CompactionConstraintGraph<ATYPE>::c_MedianFactor = 10 * c_doubleBendFactor;
323 
324 // allow 0-length for sides of generalization merger cages
325 template<class ATYPE>
327  adjEntry adj = adjFirst;
328  int faceSize = 0;
329 
330  do {
331  if ((m_pOR->direction(adj) == m_arcDir || m_pOR->direction(adj) == m_oppArcDir)
332  && (PG.typeOf(adj->theNode()) == Graph::NodeType::dummy
333  || PG.typeOf(adj->twinNode()) == Graph::NodeType::dummy)) {
334  m_length[m_edgeToBasicArc[adj]] = 0;
335  }
336 
337  adj = adj->faceCycleSucc();
338  faceSize++;
339  } while (adj != adjFirst);
340 
341  //generalization position section
342  //pull upper generalization to median of merger cage's incoming lower generalizations
343 
344  if (m_genToMedian
345  && (m_pOR->direction(adjFirst) == m_arcDir || m_pOR->direction(adjFirst) == m_oppArcDir)) {
346  int numIncoming = faceSize - 3;
347  int median = (numIncoming / 2) + 1;
348 
349  // if (numIncoming == 2) ... just the middle position
350  node upper = m_pathNode[adjFirst->theNode()];
351  if (PG.typeOf(adjFirst->theNode()) != Graph::NodeType::generalizationMerger) {
353  }
354 
355  node vMin;
356  if (m_pOR->direction(adjFirst) == m_arcDir) {
357  vMin = adjFirst->faceCyclePred()->theNode();
358  } else {
359  vMin = adjFirst->faceCycleSucc()->theNode();
360  }
361 
362  adj = adjFirst->faceCycleSucc(); // target right or left boundary, depending on drawing direction
363  for (int i = 0; i < median; i++) {
364  adj = adj->faceCycleSucc();
365  }
366 
367  node lower = m_pathNode[adj->theNode()];
368  node vCenter = newNode();
369  setExtra(vCenter, vMin, 0);
370 
371  // it seems we dont need the helper, as only source-adjEntries lying on
372  // the outer face are considered later, but keep it in mind
373 #if 0
374  edge helper = newEdge(m_pathNode[vMin], vCenter);
375  m_length[helper] = 0;
376  m_cost[helper] = 0;
377  m_type[helper] = ConstraintEdgeType::ReducibleArc;
378 #endif
379 
380  edge e1 = newEdge(vCenter, upper);
381  m_length[e1] = 0;
382  m_cost[e1] = m_MedianArcCost;
383  m_type[e1] = ConstraintEdgeType::MedianArc;
384 
385  edge e2 = newEdge(vCenter, lower);
386  m_length[e2] = 0;
387  m_cost[e2] = m_MedianArcCost;
388  m_type[e2] = ConstraintEdgeType::MedianArc;
389  }
390 }
391 
392 // set cost of edges on the cage boundary to 0
393 template<class ATYPE>
395 #if 0
396  adjEntry adj;
397  for (adj = cornerDir; m_pOR->direction(adj) == m_arcDir; adj = adj->faceCycleSucc())
398  m_cost[m_edgeToBasicArc[adj]] = 0;
399  for (adj = cornerOppDir; m_pOR->direction(adj) == m_oppArcDir; adj = adj->faceCycleSucc())
400  m_cost[m_edgeToBasicArc[adj]] = 0;
401 #endif
402  //test for multi separation
403  adjEntry adj;
404  for (adj = cornerDir; m_pOR->direction(adj) == m_arcDir; adj = adj->faceCycleSucc()) {
405  m_cost[m_edgeToBasicArc[adj]] = 0;
406 
407  if (m_pathNode[adj->twin()->cyclicSucc()->theNode()]
408  && (m_pOR->direction(adj->faceCycleSucc()) == m_arcDir)) {
409  m_originalEdge[m_pathNode[adj->twin()->cyclicSucc()->theNode()]] =
410  m_pPR->original(adj->twin()->cyclicSucc()->theEdge());
411  }
412  }
413  for (adj = cornerOppDir; m_pOR->direction(adj) == m_oppArcDir; adj = adj->faceCycleSucc()) {
414  m_cost[m_edgeToBasicArc[adj]] = 0;
415 
416  if (m_pathNode[adj->twin()->cyclicSucc()->theNode()]) {
417  m_originalEdge[m_pathNode[adj->twin()->cyclicSucc()->theNode()]] =
418  m_pPR->original(adj->twin()->cyclicSucc()->theEdge());
419  }
420  }
421 }
422 
423 //
424 // insert arcs required for respecting vertex sizes, sizes of routing channels
425 // and position of attached generalizations
426 // vertices are represented by variable cages
427 template<class ATYPE>
429  const NodeArray<ATYPE>& sizeOrig, const RoutingChannel<ATYPE>& rc) {
430  // segments in constraint graph are sides sMin and sMax; other two side
431  // are sides in which adjacency entries run in direction m_arcDir and
432  // m_oppArcDir
433  OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
434  OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
435 
436  const ATYPE overhang = rc.overhang();
437 
438  for (node v : PG.nodes) {
439  if (PG.expandAdj(v) == nullptr) {
440  continue;
441  }
442 
444  resetGenMergerLengths(PG, PG.expandAdj(v));
445 
446  } else // high/low-degree expander
447  {
448  ATYPE size = sizeOrig[v];
449 
450  const OrthoRep::VertexInfoUML& vi = *m_pOR->cageInfo(v);
451 
452  // determine routing channels rcMin and rcMax
453  ATYPE rcMin = overhang + rc(v, dirMin);
454  ATYPE rcMax = overhang + rc(v, dirMax);
455 
456  adjEntry cornerDir = vi.m_corner[static_cast<int>(m_arcDir)];
457  adjEntry cornerOppDir = vi.m_corner[static_cast<int>(m_oppArcDir)];
458  adjEntry cornerMin = vi.m_corner[static_cast<int>(dirMin)];
459  adjEntry cornerMax = vi.m_corner[static_cast<int>(dirMax)];
460 
461  // set cost of edges on the cage boundary to 0
462  setBoundaryCosts(cornerDir, cornerOppDir);
463 
464  const OrthoRep::SideInfoUML& sDir = vi.m_side[static_cast<int>(m_arcDir)];
465  const OrthoRep::SideInfoUML& sOppDir = vi.m_side[static_cast<int>(m_oppArcDir)];
466 
467  // correct lengths of edges within cage adjacent to corners
468  if (sDir.totalAttached() > 0) {
469  m_length[m_edgeToBasicArc[cornerDir]] = rcMin;
470  m_length[m_edgeToBasicArc[cornerMax->faceCyclePred()]] = rcMax;
471  } else {
472  // if no edges are attached at this side we need no constraint
473  m_length[m_edgeToBasicArc[cornerDir]] = 0;
474  delEdge(m_edgeToBasicArc[cornerDir]);
475  }
476 
477  if (sOppDir.totalAttached() > 0) {
478  m_length[m_edgeToBasicArc[cornerOppDir]] = rcMax;
479  m_length[m_edgeToBasicArc[cornerMin->faceCyclePred()]] = rcMin;
480  } else {
481  // if no edges are attached at this side we need no constraint
482  m_length[m_edgeToBasicArc[cornerOppDir]] = 0;
483  delEdge(m_edgeToBasicArc[cornerOppDir]);
484  }
485 
486 
487  // insert arcs for respecting vertex size / position of generalizations
488  node vMin = m_pathNode[cornerDir->theNode()];
489  node vMax = m_pathNode[cornerOppDir->theNode()];
490 
491  // any attached generalizations ?
492  if (sDir.m_adjGen == nullptr && sOppDir.m_adjGen == nullptr) {
493  // no, only one arc for vertex size + routing channels
494  edge e = newEdge(vMin, vMax);
495  m_length[e] = rcMin + size + rcMax - 2 * overhang;
496  m_cost[e] = 2 * m_vertexArcCost;
498 
499  } else {
500  // yes, then two arcs for each side with an attached generalization
501  ATYPE minHalf = size / 2;
502  ATYPE maxHalf = size - minHalf;
503  ATYPE lenMin = rcMin + minHalf - overhang;
504  ATYPE lenMax = maxHalf + rcMax - overhang;
505 
506  if (sDir.m_adjGen != nullptr) {
507  node vCenter = m_pathNode[sDir.m_adjGen->theNode()];
508  edge e1 = newEdge(vMin, vCenter);
509  m_length[e1] = lenMin;
510  m_cost[e1] = m_vertexArcCost;
512  edge e2 = newEdge(vCenter, vMax);
513  m_length[e2] = lenMax;
514  m_cost[e2] = m_vertexArcCost;
516  }
517 
518  if (sOppDir.m_adjGen != nullptr) {
519  node vCenter = m_pathNode[sOppDir.m_adjGen->theNode()];
520  edge e1 = newEdge(vMin, vCenter);
521  m_length[e1] = lenMin;
522  m_cost[e1] = m_vertexArcCost;
524  edge e2 = newEdge(vCenter, vMax);
525  m_length[e2] = lenMax;
526  m_cost[e2] = m_vertexArcCost;
528  }
529  }
530  }
531  }
532 }
533 
534 template<class ATYPE>
536  for (edge e : PG.edges) {
537  edge arc = m_edgeToBasicArc[e];
538  if (arc == nullptr) {
539  continue;
540  }
541 
542  node v = e->source();
543  node w = e->target();
544  if (((PG.typeOf(v) == Graph::NodeType::dummy) && (PG.typeOf(w) == Graph::NodeType::dummy)
545  && (v->degree() == 2) && w->degree() == 2)
546  && (m_pOR->angle(e->adjSource()) == m_pOR->angle(e->adjTarget())) && //no uturns
548  m_length[arc] = 0;
549  m_type[arc] = ConstraintEdgeType::FixToZeroArc;
550  //we make fixtozero arcs as expensive as possible
551  m_cost[arc] = m_doubleBendCost;
552  }
553  }
554 }
555 
556 //
557 // insert arcs required for respecting vertex sizes
558 // and position of attached generalizations
559 // vertices are represented by tight cages
560 template<class ATYPE>
562  const NodeArray<ATYPE>& sizeOrig, const MinimumEdgeDistances<ATYPE>& minDist) {
563  // set the length of all basic arcs corresponding to inner edge segments
564  // to 0
565  setBasicArcsZeroLength(PG);
566 
567  // segments in constraint graph are sides sMin and sMax; other two side
568  // are sides in which adjacency entries run in direction m_arcDir and
569  // m_oppArcDir
570  OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
571  OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
572 
573  for (node v : PG.nodes) {
574  if (PG.expandAdj(v) == nullptr) {
575  continue;
576  }
577 
579  resetGenMergerLengths(PG, PG.expandAdj(v));
580 
581  } else // high/low-degree expander
582  {
583  ATYPE size = sizeOrig[v];
584  const OrthoRep::VertexInfoUML& vi = *m_pOR->cageInfo(v);
585 
586  adjEntry cornerDir = vi.m_corner[static_cast<int>(m_arcDir)];
587  adjEntry cornerOppDir = vi.m_corner[static_cast<int>(m_oppArcDir)];
588  adjEntry cornerMin = vi.m_corner[static_cast<int>(dirMin)];
589  adjEntry cornerMax = vi.m_corner[static_cast<int>(dirMax)];
590 
591  adjEntry adj = cornerDir, last = cornerMax->faceCyclePred();
592  if (adj != last) {
593  m_length[m_edgeToBasicArc[adj]] = minDist.epsilon(v, m_arcDir, 0);
594  m_length[m_edgeToBasicArc[last]] = minDist.epsilon(v, m_arcDir, 1);
595  int i = 0;
596  for (adj = adj->faceCycleSucc(); adj != last; adj = adj->faceCycleSucc()) {
598  i++;
599  }
600  m_length[m_edgeToBasicArc[adj]] = minDist.delta(v, m_arcDir, i);
601  }
602  }
603 
604  adj = cornerOppDir, last = cornerMin->faceCyclePred();
605  if (adj != last) {
606  m_length[m_edgeToBasicArc[adj]] = minDist.epsilon(v, m_oppArcDir, 0);
607  m_length[m_edgeToBasicArc[last]] = minDist.epsilon(v, m_oppArcDir, 1);
608  int i = 0;
609  for (adj = adj->faceCycleSucc(); adj != last; adj = adj->faceCycleSucc()) {
611  i++;
612  }
613  m_length[m_edgeToBasicArc[adj]] = minDist.delta(v, m_oppArcDir, i);
614  }
615  }
616 
617 
618  // insert arcs for respecting vertex size / position of generalizations
619  node vMin = m_pathNode[cornerDir->theNode()];
620  node vMax = m_pathNode[cornerOppDir->theNode()];
621 
622  const OrthoRep::SideInfoUML& sDir = vi.m_side[static_cast<int>(m_arcDir)];
623  const OrthoRep::SideInfoUML& sOppDir = vi.m_side[static_cast<int>(m_oppArcDir)];
624 
625  // any attached generalizations ?
626  if (sDir.m_adjGen == nullptr && sOppDir.m_adjGen == nullptr) {
627  //check for single edge case => special treatment
628  //generic case could handle all numbers
629 
630  if (sDir.totalAttached() == 1 || sOppDir.totalAttached() == 1) {
631  //first, insert a new center node and connect it
632  ATYPE lenMin = size / 2;
633  ATYPE lenMax = size - lenMin;
634  node vCenter = newNode();
635  setExtra(vCenter, cornerDir->theNode(), lenMin);
636 
637  edge e1 = newEdge(vMin, vCenter);
638  m_length[e1] = lenMin;
639  m_cost[e1] = m_vertexArcCost;
641  edge e2 = newEdge(vCenter, vMax);
642  m_length[e2] = lenMax;
643  m_cost[e2] = m_vertexArcCost;
645 
646  if (sDir.totalAttached() == 1) {
647  //then, insert a moveable node connecting center
648  //and outgoing segment
649  node vBungee = newNode();
650  //+1 should fix the fixzerolength problem
651  setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v, m_arcDir, 0));
652 
653  edge eToBungee = newEdge(vMin, vBungee);
654  m_type[eToBungee] = ConstraintEdgeType::MedianArc;
655  //BasicArc; // XXX: is this ok?
656  m_cost[eToBungee] = 0; // XXX: what about this?
657  m_length[eToBungee] = minDist.epsilon(v, m_arcDir, 0);
658 
659  edge eBungeeCenter = newEdge(vBungee, vCenter);
660  //bungee, center and outgoing segment may build column if in the middle
661  m_type[eBungeeCenter] = ConstraintEdgeType::MedianArc;
662  m_cost[eBungeeCenter] = m_bungeeCost; // XXX: what about this?
663  m_length[eBungeeCenter] = 0;
664 
665  //attention: pathnode construct works only if degree 1
666  edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerDir->twinNode()]);
667  //bungee, center and outgoing segment may build column if in the middle
668  m_type[eBungeeOut] = ConstraintEdgeType::MedianArc;
669  m_cost[eBungeeOut] = m_bungeeCost; // XXX: what about this?
670  m_length[eBungeeOut] = 0;
671 #if 0
672  //connect outgoing segment and "right" segment, maybe obsolete
673  edge eFromOut = newEdge(m_pathNode[cornerDir->twinNode()], vMax);
674  m_type[eFromOut] = ConstraintEdgeType::BasicArc; // XXX
675  m_cost[eFromOut] = 0; // XXX
676  m_length[eFromOut] = minDist.epsilon(v,m_arcDir,1);
677 #endif
678  }
679  if (sOppDir.totalAttached() == 1 && m_pathNode[cornerOppDir->twinNode()] != vMin) {
680  //then, insert a moveable node connecting center
681  //and outgoing segment
682  node vBungee = newNode();
683  //+1 for not fixzerolength
684  setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v, m_oppArcDir, 0));
685 
686  edge eToBungee = newEdge(vMin, vBungee);
687  m_type[eToBungee] = ConstraintEdgeType::MedianArc;
688  //BasicArc; // XXX: is this ok?
689  m_cost[eToBungee] = 0; // XXX: what about this?
690  m_length[eToBungee] = minDist.epsilon(v, m_oppArcDir, 0);
691 
692  edge eBungeeCenter = newEdge(vBungee, vCenter);
693  //bungee, center and outgoing segment may build column if in the middle
694  m_type[eBungeeCenter] = ConstraintEdgeType::MedianArc;
695  m_cost[eBungeeCenter] = m_bungeeCost; // XXX: what about this?
696  m_length[eBungeeCenter] = 0;
697 
698  //attention: pathnode construct works only if degree 1, sometimes not at all
699  edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerOppDir->twinNode()]);
700  //bungee, center and outgoing segment may build column if in the middle
701  m_type[eBungeeOut] = ConstraintEdgeType::MedianArc;
702  m_cost[eBungeeOut] = m_bungeeCost; // XXX: what about this?
703  m_length[eBungeeOut] = 0;
704 #if 0
705  //connect outgoing segment and "right" segment, maybe obsolete
706  edge eFromOut = newEdge(m_pathNode[cornerOppDir->twinNode()], vMax);
707  m_type[eFromOut] = ConstraintEdgeType::BasicArc; // XXX
708  m_cost[eFromOut] = 0; // XXX
709  m_length[eFromOut] = minDist.epsilon(v,m_oppArcDir,0);
710 #endif
711  }
712  } else {
713  // no, only one arc for vertex size + routing channels
714  edge e = newEdge(vMin, vMax);
715  m_length[e] = size;
716  m_cost[e] = 2 * m_vertexArcCost;
718  }
719  } else {
720  // yes, then two arcs for each side with an attached generalization
721  ATYPE lenMin = size / 2;
722  ATYPE lenMax = size - lenMin;
723 
724 #if 0
725  ATYPE len = size/2;
726 #endif
727 
728  if (sDir.m_adjGen != nullptr) {
729  node vCenter = m_pathNode[sDir.m_adjGen->theNode()];
730  edge e1 = newEdge(vMin, vCenter);
731  m_length[e1] = lenMin;
732  m_cost[e1] = m_vertexArcCost;
734  edge e2 = newEdge(vCenter, vMax);
735  m_length[e2] = lenMax;
736  m_cost[e2] = m_vertexArcCost;
738  } else {
739  if (sDir.totalAttached() == 1) {
740  node vCenter = newNode();
741  //m_pathNode[sOppDir.m_adjGen->theNode()]; //newNode();
742  setExtra(vCenter, cornerDir->theNode(), lenMin);
743 
744  edge e1 = newEdge(vMin, vCenter);
745  m_length[e1] = lenMin;
746  m_cost[e1] = m_vertexArcCost;
748  edge e2 = newEdge(vCenter, vMax);
749  m_length[e2] = lenMax;
750  m_cost[e2] = m_vertexArcCost;
752 
753  //then, insert a moveable node connecting center
754  //and outgoing segment
755  node vBungee = newNode();
756  //+1 for not fixzerolength
757  setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v, m_arcDir, 0));
758 
759  edge eToBungee = newEdge(vMin, vBungee);
760  m_type[eToBungee] = ConstraintEdgeType::MedianArc;
761  //BasicArc; // XXX: is this ok?
762  m_cost[eToBungee] = 0; // XXX: what about this?
763  m_length[eToBungee] = minDist.epsilon(v, m_arcDir, 0);
764 
765  edge eBungeeCenter = newEdge(vBungee, vCenter);
766  //bungee, center and outgoing segment may build column if in the middle
767  m_type[eBungeeCenter] = ConstraintEdgeType::MedianArc;
768  m_cost[eBungeeCenter] = m_bungeeCost; // XXX: what about this?
769  m_length[eBungeeCenter] = 0;
770 
771  //attention: pathnode construct works only if degree 1
772  edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerDir->twinNode()]);
773  //bungee, center and outgoing segment may build column if in the middle
774  m_type[eBungeeOut] = ConstraintEdgeType::MedianArc;
775  m_cost[eBungeeOut] = m_bungeeCost; // XXX: what about this?
776  m_length[eBungeeOut] = 0;
777  }
778  }
779  if (sOppDir.m_adjGen != nullptr) {
780  node vCenter = m_pathNode[sOppDir.m_adjGen->theNode()];
781  edge e1 = newEdge(vMin, vCenter);
782  m_length[e1] = lenMin;
783  m_cost[e1] = m_vertexArcCost;
785  edge e2 = newEdge(vCenter, vMax);
786  m_length[e2] = lenMax;
787  m_cost[e2] = m_vertexArcCost;
789  } else {
790  //special case single edge to middle position
791  if (sOppDir.totalAttached() == 1 && m_pathNode[cornerOppDir->twinNode()] != vMin) {
792  node vCenter = newNode();
793  //m_pathNode[sDir.m_adjGen->theNode()];//newNode();
794  setExtra(vCenter, cornerDir->theNode(), lenMin);
795 
796  edge e1 = newEdge(vMin, vCenter);
797  m_length[e1] = lenMin;
798  m_cost[e1] = m_vertexArcCost;
800  edge e2 = newEdge(vCenter, vMax);
801  m_length[e2] = lenMax;
802  m_cost[e2] = m_vertexArcCost;
804  //then, insert a moveable node connecting center
805  //and outgoing segment
806  node vBungee = newNode();
807  //+1 for not fixzerolength
808  setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v, m_oppArcDir, 0));
809 
810  edge eToBungee = newEdge(vMin, vBungee);
811  m_type[eToBungee] = ConstraintEdgeType::MedianArc;
812  //BasicArc; // XXX: is this ok?
813  m_cost[eToBungee] = 0; // XXX: what about this?
814  m_length[eToBungee] = minDist.epsilon(v, m_oppArcDir, 0);
815 
816  edge eBungeeCenter = newEdge(vBungee, vCenter);
817  //bungee, center and outgoing segment may build column if in the middle
818  m_type[eBungeeCenter] = ConstraintEdgeType::MedianArc;
819  m_cost[eBungeeCenter] = m_bungeeCost; // XXX: what about this?
820  m_length[eBungeeCenter] = 0;
821 
822  //attention: pathnode construct works only if degree 1
823  edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerOppDir->twinNode()]);
824  //bungee, center and outgoing segment may build column if in the middle
825  m_type[eBungeeOut] = ConstraintEdgeType::MedianArc;
826  m_cost[eBungeeOut] = m_bungeeCost; // XXX: what about this?
827  m_length[eBungeeOut] = 0;
828  }
829  }
830  }
831 
832  // set cost of edges on the cage boundary to 0
833  setBoundaryCosts(cornerDir, cornerOppDir);
834  }
835  }
836 #if 0
837  if (m_arcDir == OrthoDir::East) {
838  writeGML("eastvertexsizeinserted.gml");
839  } else {
840  writeGML("northvertexsizeinserted.gml");
841  }
842 #endif
843 }
844 
845 // computes the total costs for coordintes given by pos, i.e.,
846 // the sum of the weighted lengths of edges in the constraint graph.
847 template<class ATYPE>
849  ATYPE c = 0;
850  for (edge e : edges) {
851  c += cost(e) * (pos[e->target()] - pos[e->source()]);
852  }
853 
854  return c;
855 }
856 
857 //
858 // insertion of visibility arcs
859 
860 // checks if intervals on the sweep line are in correct order
861 template<class ATYPE>
863  if (sweepLine.empty()) {
864  return true;
865  }
866 
867  ListConstIterator<Interval> it = sweepLine.begin();
868 
869  if ((*it).m_high < (*it).m_low) {
870  return false;
871  }
872 
873  ATYPE x = (*it).m_low;
874 
875  for (++it; it.valid(); ++it) {
876  if ((*it).m_high < (*it).m_low) {
877  return false;
878  }
879  if ((*it).m_high > x) {
880  return false;
881  }
882  x = (*it).m_low;
883  }
884 
885  return true;
886 }
887 
888 template<class ATYPE>
890  const NodeArray<ATYPE>& posDir, const NodeArray<ATYPE>& posOrthDir) {
891  MinimumEdgeDistances<ATYPE> minDist(PG, m_sep);
892 
893  for (node v : PG.nodes) {
894  if (PG.expandAdj(v) == nullptr) {
895  continue;
896  }
897 
898  for (int d = 0; d < 4; ++d) {
899  minDist.delta(v, OrthoDir(d), 0) = m_sep; //currentSeparation;
900  minDist.delta(v, OrthoDir(d), 1) = m_sep; //currentSeparation;
901  }
902  }
903 
904  insertVisibilityArcs(PG, posDir, posOrthDir, minDist);
905 }
906 
907 // inserts arcs connecting segments which can see each other in a drawing
908 // of the associated planarized representation PG which is given by
909 // posDir and posOppDir.
910 
911 //ersetze mindist.delta durch min(m_sep, mindist.delta) fuer skalierung
912 template<class ATYPE>
914  const NodeArray<ATYPE>& posDir, const NodeArray<ATYPE>& posOrthDir,
915  const MinimumEdgeDistances<ATYPE>& minDist) {
916  OrthoDir segDir = OrthoRep::prevDir(m_arcDir);
917  OrthoDir segOppDir = OrthoRep::nextDir(m_arcDir);
918 
919  // list of visibility arcs which have to be inserted
920  SListPure<Tuple2<node, node>> visibArcs;
921 
922  // lower and upper bound of segments
923  NodeArray<ATYPE> low(getGraph()), lowReal(getGraph()), high(getGraph());
924  NodeArray<ATYPE> segPos(getGraph(), 0); // position of segments
925  NodeArray<int> topNum(getGraph() /*,0*/); // secondary sorting criteria for segments
926 
927  // compute position and lower/upper bound of segments
928  // We have to take care that segments cannot be shifted one upon the other,
929  // e.g., if we have two segments (l1,h1) and (l2,h2) with l2 > h2 and
930  // the distance l2-h2 is smaller than separation, the segments can see
931  // each other. We do this by enlarging the lower bound of all segments
932  // by separation if this lower bound is realized by a bend.
933  //
934  // Note: Be careful at segments attached at a vertex which are closer
935  // than separation to each other. Possible solution: Remove visibility
936  // arcs of segments which are connected by orthogonal segments to the
937  // same vertex and bend in opposite directions.
938  for (node v : nodes) {
939  //special case nodes
940  if (m_path[v].empty()) {
941  continue;
942  }
943 
944  SListConstIterator<node> it = m_path[v].begin();
945 
946  segPos[v] = posDir[*it];
947  low[v] = high[v] = posOrthDir[*it];
948  node nodeLow = *it;
949  for (++it; it.valid(); ++it) {
950  ATYPE x = posOrthDir[*it];
951  if (x < low[v]) {
952  low[v] = x;
953  nodeLow = *it;
954  }
955  if (x > high[v]) {
956  high[v] = x;
957  }
958  }
959  lowReal[v] = low[v];
960  Graph::NodeType typeLow = PG.typeOf(nodeLow);
962 #if 0
963  bool subtractSep = true;
964  if (nodeLow->degree() == 2) {
965  adjEntry adjFound = nullptr;
966  for(adjEntry adj : nodeLow->adjEntries) {
967  if(m_pOR->direction(adj) == m_arcDir || m_pOR->direction(adj) == m_oppArcDir) {
968  adjFound = adj;
969  break;
970  }
971  }
972  if (adjFound) {
973  for(adjEntry adj2 = adjFound->faceCycleSucc();
974  m_pOR->direction(adj2) == m_pOR->direction(adjFound);
975  adj2 = adj2->twin()->faceCycleSucc()) ;
976  if(posDir[adjFound->theNode()] == posDir[adj2->twinNode()])
977  subtractSep = false;
978  }
979  }
980  if (subtractSep)
981  low[v] -= m_sep;
982 #else
983  low[v] -= m_sep;
984 #endif
985  }
986  }
987 
988  // correct "-= m_sep" ...
989  OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
990  OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
991  bool isCaseA = (m_arcDir == OrthoDir::East || m_arcDir == OrthoDir::South);
992  const int angleAtMin = (m_arcDir == OrthoDir::East || m_arcDir == OrthoDir::South) ? 3 : 1;
993  const int angleAtMax = (m_arcDir == OrthoDir::East || m_arcDir == OrthoDir::South) ? 1 : 3;
994 
995  for (node v : PG.nodes) {
996  if (PG.expandAdj(v) == nullptr) {
997  continue;
998  }
999  const OrthoRep::VertexInfoUML& vi = *m_pOR->cageInfo(v);
1000 
1001  // int i = 0;
1002  adjEntry adj;
1003 
1004  for (adj = isCaseA ? vi.m_corner[static_cast<int>(dirMin)]->faceCycleSucc()->faceCycleSucc()
1005  : vi.m_corner[static_cast<int>(dirMin)]->faceCycleSucc();
1006  m_pOR->direction((isCaseA) ? adj : adj->faceCycleSucc())
1007  == dirMin; //m_pOR->direction(adj) == dirMin;
1008  adj = adj->faceCycleSucc()) {
1009  adjEntry adjCross = adj->cyclicPred();
1010  adjEntry adjTwin = adjCross->twin();
1011 
1012  adjEntry adjPred = adj->faceCyclePred();
1013  ATYPE delta = (isCaseA)
1014  ? min(abs(posOrthDir[adjPred->theNode()] - posOrthDir[adjPred->twinNode()]), m_sep)
1015  : min(abs(posOrthDir[adj->theNode()] - posOrthDir[adj->twinNode()]), m_sep);
1016  ATYPE boundary = (isCaseA)
1017  ? min(posOrthDir[adjPred->theNode()], posOrthDir[adjPred->twinNode()])
1018  : min(posOrthDir[adj->theNode()], posOrthDir[adj->twinNode()]);
1019 
1020  if (PG.typeOf(adjCross->theEdge()) == Graph::EdgeType::generalization) {
1021  if (isCaseA) {
1023  && m_pOR->angle(adjTwin) == 2) {
1024  node s1 = m_pathNode[adjTwin->theNode()];
1025  node s2 = m_pathNode[adjTwin->cyclicSucc()->twinNode()];
1026  low[s1] = lowReal[s1] - delta; // minDist.delta(v,dirMin,i);
1027  low[s2] = lowReal[s2] - delta; //minDist.delta(v,dirMin,i);
1028  }
1029  // ++i;
1030  } else {
1031  // ++i;
1033  && m_pOR->angle(adjTwin->cyclicPred()) == 2) {
1034  node s1 = m_pathNode[adjTwin->theNode()];
1035  node s2 = m_pathNode[adjTwin->cyclicPred()->twinNode()];
1036  low[s1] = lowReal[s1] - delta; //minDist.delta(v,dirMin,i);
1037  low[s2] = lowReal[s2] - delta; //minDist.delta(v,dirMin,i);
1038  }
1039  }
1040  continue;
1041  }
1042 
1043  //we save the current direction and stop if we run in opposite
1044  OrthoDir runDir = m_pOR->direction(adjCross);
1045  // if -> while
1046  while (PG.typeOf(adjTwin->theNode()) == Graph::NodeType::dummy
1047  && adjTwin->theNode()->degree() == 2 && m_pOR->angle(adjTwin) == angleAtMin) {
1048  // We handle the case if an edge segment adjacent to a vertex
1049  // is separated by less than separation from edge segments above.
1050  node s = m_edgeToBasicArc[adjCross]->source();
1051  if (lowReal[s] != low[s]) {
1052  if (low[s] >= boundary) { // nothing to do?
1053  break;
1054  }
1055  low[s] = boundary;
1056 #if 0
1057  low[s] += m_sep - delta; //minDist.delta(v,dirMin,i);
1058 #endif
1059 
1060  // If the compaction has eliminated bends, we can have the situation
1061  // that segment s has length 0 and the next segment s' (following the
1062  // edge) is at the same position (the edge arc has length 0).
1063  // In this case, the low-value of s' must be lowered (low[s'] := lowReal[s']
1064  // is approproate). The same situation can appear several times in a
1065  // row.
1066  //collect chains of segments compacted to zero length
1067  for (;;) { //while(true/*lowReal[s] == high[s]*/) {
1068  do {
1069  adjCross = adjCross->faceCycleSucc();
1070  } while (m_pOR->direction(adjCross) == segDir
1071  || m_pOR->direction(adjCross) == segOppDir);
1072 
1073  if (adjCross->theNode()->degree() != 2) { // no longer a bend point?
1074  break;
1075  }
1076 
1077  node sNext = m_edgeToBasicArc[adjCross]->opposite(s);
1078 
1079  if (segPos[sNext] != segPos[s]) {
1080  break;
1081  }
1082 
1083  low[sNext] = lowReal[sNext]; //?
1084  s = sNext;
1085  }
1086  }
1087 
1088  adjTwin = adjCross->twin(); // update of twin for while
1089  //check if we have to stop
1090  if (runDir != m_pOR->direction(adjCross)) {
1091  break;
1092  }
1093  }
1094  }
1095 
1096  // i = 0;
1097  for (adj = isCaseA ? vi.m_corner[static_cast<int>(dirMax)]->faceCycleSucc()
1098  : vi.m_corner[static_cast<int>(dirMax)]->faceCycleSucc()->faceCycleSucc();
1099  m_pOR->direction((isCaseA) ? adj->faceCycleSucc() : adj)
1100  == dirMax; // m_pOR->direction(adj) == dirMax;
1101  adj = adj->faceCycleSucc()) {
1102  adjEntry adjCross = adj->cyclicPred();
1103  adjEntry adjTwin = adjCross->twin();
1104 
1105 #if 0
1106  ATYPE delta = -posOrthDir[adj->twinNode()] + posOrthDir[adj->theNode()];
1107 #endif
1108  adjEntry adjPred = adj->faceCyclePred();
1109  ATYPE delta = (isCaseA)
1110  ? min(abs(posOrthDir[adj->twinNode()] - posOrthDir[adj->theNode()]), m_sep)
1111  : min(abs(posOrthDir[adjPred->theNode()] - posOrthDir[adjPred->twinNode()]),
1112  m_sep);
1113  ATYPE boundary = (isCaseA)
1114  ? min(posOrthDir[adj->twinNode()], posOrthDir[adj->theNode()])
1115  : min(posOrthDir[adjPred->theNode()], posOrthDir[adjPred->twinNode()]);
1116 
1117  if (PG.typeOf(adjCross->theEdge()) == Graph::EdgeType::generalization) {
1118  if (isCaseA) {
1119  // ++i;
1121  && m_pOR->angle(adjTwin->cyclicPred()) == 2) {
1122  node s1 = m_pathNode[adjTwin->theNode()];
1123  node s2 = m_pathNode[adjTwin->cyclicPred()->twinNode()];
1124  low[s1] = lowReal[s1] - delta; //minDist.delta(v,dirMax,i);
1125  low[s2] = lowReal[s2] - delta; //minDist.delta(v,dirMax,i);
1126  }
1127  } else {
1129  && m_pOR->angle(adjTwin) == 2) {
1130  node s1 = m_pathNode[adjTwin->theNode()];
1131  node s2 = m_pathNode[adjTwin->cyclicSucc()->twinNode()];
1132  low[s1] = lowReal[s1] - delta; //minDist.delta(v,dirMax,i);
1133  low[s2] = lowReal[s2] - delta; //minDist.delta(v,dirMax,i);
1134  }
1135  // ++i;
1136  }
1137  continue;
1138  }
1139 
1140 
1141  //we save the current direction and stop if we run in opposite
1142  OrthoDir runDir = m_pOR->direction(adjCross);
1143  // if -> while
1144  while (PG.typeOf(adjTwin->theNode()) == Graph::NodeType::dummy
1145  && adjTwin->theNode()->degree() == 2 && m_pOR->angle(adjTwin) == angleAtMax) {
1146  node s = m_edgeToBasicArc[adjCross]->target();
1147  if (lowReal[s] != low[s]) {
1148  if (low[s] >= boundary) { // nothing to do?
1149  break;
1150  }
1151  low[s] = boundary;
1152 #if 0
1153  low[s] += m_sep - delta; //minDist.delta(v,dirMax,i);
1154 #endif
1155 
1156  // If the compaction has eliminated bends, we can have the situation
1157  // that segment s has length 0 and the next segment s' (following the
1158  // edge) is at the same position (the edge arc has length 0).
1159  // In this case, the low-value of s' must be lowered (low[s'] := lowReal[s']
1160  // is approproate). The same situation can appear several times in a
1161  // row.
1162  //collect chains of segments compacted to zero length
1163  for (;;) /*lowReal[s] == high[s]*/
1164  {
1165  do {
1166  adjCross = adjCross->faceCycleSucc();
1167  } while (m_pOR->direction(adjCross) == segDir
1168  || m_pOR->direction(adjCross) == segOppDir);
1169 
1170  if (adjCross->theNode()->degree() != 2) { // no longer a bend point?
1171  break;
1172  }
1173 
1174  node sNext = m_edgeToBasicArc[adjCross]->opposite(s);
1175 
1176  if (segPos[sNext] != segPos[s]) {
1177  break;
1178  }
1179 
1180  low[sNext] = lowReal[sNext]; //was: low[s]
1181  s = sNext;
1182  }
1183  }
1184 
1185  adjTwin = adjCross->twin(); // update of twin for while
1186 
1187  //check if we have to stop
1188  if (runDir != m_pOR->direction(adjCross)) {
1189  break;
1190  }
1191  }
1192  }
1193  }
1194 
1195  // compute topological numbering of segments as second sorting criteria
1196  // in order to process overlapping segments in the order imposed by the
1197  // embedding
1198  computeTopologicalSegmentNum(topNum);
1199 
1200 
1201  // sort segments
1202  SegmentComparer cmpBySegPos(segPos, topNum);
1203  List<node> sortedPathNodes;
1204  allNodes(sortedPathNodes);
1205  sortedPathNodes.quicksort(cmpBySegPos);
1206 
1207  // add segments in the order given by sortedPathNodes to sweep line
1208  List<Interval> sweepLine;
1209 
1210  ListIterator<node> itV;
1211  for (itV = sortedPathNodes.begin(); itV.valid(); ++itV) {
1212  //special case nodes
1213  if (m_path[*itV].empty()) {
1214  continue;
1215  }
1216  OGDF_HEAVY_ASSERT(checkSweepLine(sweepLine));
1217 
1218  node v = *itV;
1220  for (it = sweepLine.begin(); it.valid(); ++it) {
1221  if ((*it).m_low < high[v]) {
1222  break;
1223  }
1224  }
1225 
1226  if (!it.valid()) {
1227  sweepLine.pushBack(Interval(v, low[v], high[v]));
1228  continue;
1229  }
1230 
1231  if ((*it).m_high <= low[v]) {
1232  sweepLine.insertBefore(Interval(v, low[v], high[v]), it);
1233  continue;
1234  }
1235 
1236  ListIterator<Interval> itUp = it, itSucc;
1237  // we store if itUp will be deleted in order not to
1238  // access the deleted iterator later
1239  bool isItUpDel = (((*itUp).m_low >= low[v]) && ((*itUp).m_high <= high[v]));
1240 
1241  for (; it.valid() && (*it).m_low >= low[v]; it = itSucc) {
1242  itSucc = it.succ();
1243  if ((*it).m_high <= high[v]) {
1244  visibArcs.pushBack(Tuple2<node, node>((*it).m_pathNode, v));
1245  sweepLine.del(it);
1246  }
1247  }
1248 
1249  if (it == itUp && (*it).m_high > high[v]) {
1250  node w = (*it).m_pathNode;
1251  sweepLine.insertAfter(Interval(w, (*it).m_low, low[v]), it);
1252  (*it).m_low = high[v];
1253  sweepLine.insertAfter(Interval(v, low[v], high[v]), it);
1254  visibArcs.pushBack(Tuple2<node, node>(w, v));
1255 
1256  } else {
1257  if ((!isItUpDel) && itUp != it && (*itUp).m_low < high[v]) {
1258  (*itUp).m_low = high[v];
1259  visibArcs.pushBack(Tuple2<node, node>((*itUp).m_pathNode, v));
1260  }
1261  if (it.valid()) {
1262  if ((*it).m_high > low[v]) {
1263  (*it).m_high = low[v];
1264  visibArcs.pushBack(Tuple2<node, node>((*it).m_pathNode, v));
1265  }
1266  sweepLine.insertBefore(Interval(v, low[v], high[v]), it);
1267 
1268  } else {
1269  sweepLine.pushBack(Interval(v, low[v], high[v]));
1270  }
1271  }
1272  }
1273 
1274  // remove all arcs from visibArcs that are already in the constraint graph
1275  removeRedundantVisibArcs(visibArcs);
1276 
1277  // compute original adjacency entry corresponding to a segment
1278  // We use this in order to omit visibility arcs between segments which
1279  // belong to the same edge if they can see each other from the same side
1280  // of the edge; if they see each other from different sides the arc is
1281  // essential!
1282  NodeArray<adjEntry> correspEdge(getGraph(), nullptr);
1283 
1284  for (node v : PG.nodes) {
1285  node seg = m_pathNode[v];
1286  for (adjEntry adj : v->adjEntries) {
1287  if (m_pOR->direction(adj) != segDir) {
1288  continue;
1289  }
1290  edge eAdj = adj->theEdge();
1291  edge eOrig = PG.original(eAdj);
1292  if (eOrig == nullptr) {
1293  continue;
1294  }
1295  if (adj == eAdj->adjSource()) {
1296  correspEdge[seg] = eOrig->adjSource();
1297  } else {
1298  correspEdge[seg] = eOrig->adjTarget();
1299  }
1300  }
1301  }
1302 
1303  // remove visibility arcs between ...
1304  SListIterator<Tuple2<node, node>> itT, itTSucc, itTPred;
1305  for (itT = visibArcs.begin(); itT.valid(); itT = itTSucc) {
1306  itTSucc = itT.succ();
1307  node v = (*itT).x1(), w = (*itT).x2();
1308 
1309  // remove arcs which connect segments belonging to the same edge
1310  if (correspEdge[v] && (correspEdge[v] == correspEdge[w])) {
1311  if (itTPred.valid()) {
1312  visibArcs.delSucc(itTPred);
1313  } else {
1314  visibArcs.popFront();
1315  }
1316  }
1317 
1318  else {
1319  itTPred = itT;
1320  }
1321  }
1322 
1323 
1324  for (itT = visibArcs.begin(); itT.valid(); ++itT) {
1325  //CHECK if
1326  node v = (*itT).x1(), w = (*itT).x2();
1327  if (!(m_extraNode[v] || m_extraNode[w])) {
1328  //CHECK if
1329  node boundRepresentant1 = m_path[v].front();
1330  node boundRepresentant2 = m_path[w].front();
1331  node en1 = m_pPR->expandedNode(boundRepresentant1);
1332  node en2 = m_pPR->expandedNode(boundRepresentant2);
1333  //do not insert visibility in cages
1334  if (!((en1 && en2) && (en1 == en2))) {
1335  edge e = newEdge(v, w);
1336 
1337  //hier vielleicht multiedges abfangen: length auf max(min(sep, dists), minDist.sep)
1338 
1339  m_length[e] = max(m_sep, minDist.separation()); //m_sep;
1340  m_cost[e] = 0;
1342 #if 0
1343  writeGML("visibilityinserted.gml");
1344 #endif
1345  }
1346  }
1347  }
1348 
1349  OGDF_HEAVY_ASSERT(checkSweepLine(sweepLine));
1350 }
1351 
1352 // performs feasibility test for position assignment pos, i.e., checks if
1353 // the segment positions given by pos fulfill the constraints in the
1354 // compaction constraint graph
1355 template<class ATYPE>
1357  for (edge e : getGraph().edges) {
1358  node v = m_path[e->source()].front();
1359  node w = m_path[e->target()].front();
1360  if (pos[w] - pos[v] < length(e)) {
1361  std::cout << "feasibility check failed for edge " << e << std::endl;
1362  std::cout << " representatives: " << v << ", " << w << std::endl;
1363  std::cout << " length: " << length(e) << std::endl;
1364  std::cout << " actual distance: " << pos[w] - pos[v] << std::endl;
1365  std::cout << " type of " << e << ": ";
1366  switch (m_type[e]) {
1368  std::cout << "basic arc" << std::endl;
1369  break;
1371  std::cout << "vertex-size arc" << std::endl;
1372  break;
1374  std::cout << "visibility arc" << std::endl;
1375  break;
1377  std::cout << "median arc" << std::endl;
1378  break;
1380  std::cout << "reducible arc" << std::endl;
1381  break;
1383  std::cout << "fixtozero arc" << std::endl;
1384  }
1385  return false;
1386  }
1387  }
1388 
1389  return true;
1390 }
1391 
1392 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::CommonCompactionConstraintGraphBase::m_extraNode
NodeArray< bool > m_extraNode
Node does not represent drawing node as we dont have positions we save a drawing representant and an ...
Definition: CommonCompactionConstraintGraphBase.h:75
ogdf::CompactionConstraintGraphBase::m_align
bool m_align
Definition: CompactionConstraintGraph.h:100
Graph.h
Includes declaration of graph class.
ogdf::CompactionConstraintGraph::m_doubleBendCost
int m_doubleBendCost
try to minimize double bends
Definition: CompactionConstraintGraph.h:270
ogdf::CompactionConstraintGraph::Interval::operator<<
friend std::ostream & operator<<(std::ostream &os, const Interval &interval)
output operator
Definition: CompactionConstraintGraph.h:212
ogdf::CompactionConstraintGraphBase::m_pathToEdge
NodeArray< edge > m_pathToEdge
save the (single!) edge (segment) for a pathNode
Definition: CompactionConstraintGraph.h:96
ogdf::CompactionConstraintGraphBase::m_edgeCost
int m_edgeCost[2]
Definition: CompactionConstraintGraph.h:87
exceptions.h
Definition of exception classes.
ogdf::PlanRep
Planarized representations (of a connected component) of a graph.
Definition: PlanRep.h:69
ogdf::ConstraintEdgeType::BasicArc
@ BasicArc
ogdf::CompactionConstraintGraph::setBoundaryCosts
void setBoundaryCosts(adjEntry cornerDir, adjEntry cornerOppDir)
Definition: CompactionConstraintGraph.h:394
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::OrthoRep::VertexInfoUML
Further information about the cages of vertices in UML diagrams.
Definition: OrthoRep.h:264
ogdf::CommonCompactionConstraintGraphBase::m_extraRep
NodeArray< node > m_extraRep
existing representant of extranodes position anchor
Definition: CommonCompactionConstraintGraphBase.h:76
ogdf::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:166
ogdf::OrthoDir
OrthoDir
Definition: OrthoRep.h:56
ogdf::CompactionConstraintGraph::isFeasible
bool isFeasible(const NodeArray< ATYPE > &pos)
Performs feasibility test for position assignment pos, i.e., checks if the segment positions given by...
Definition: CompactionConstraintGraph.h:1356
ogdf::Tuple2
Tuples of two elements (2-tuples).
Definition: tuples.h:49
ogdf::CompactionConstraintGraph::checkSweepLine
bool checkSweepLine(const List< Interval > &sweepLine) const
Definition: CompactionConstraintGraph.h:862
ogdf::AdjElement::cyclicPred
adjEntry cyclicPred() const
Returns the cyclic predecessor in the adjacency list.
Definition: Graph_d.h:358
ogdf::OrthoRep::SideInfoUML::m_adjGen
adjEntry m_adjGen
Definition: OrthoRep.h:231
ogdf::CompactionConstraintGraph::length
ATYPE length(edge e) const
Returns length of edge e.
Definition: CompactionConstraintGraph.h:142
ogdf::CompactionConstraintGraph::SegmentComparer
Comparer class used for sorting segments by increasing position (given by segPos) such that two overl...
Definition: CompactionConstraintGraph.h:223
OGDF_AUGMENT_COMPARER
#define OGDF_AUGMENT_COMPARER(type)
Add this macro to your class to turn it into a full comparer.
Definition: comparer.h:183
ogdf::MinimumEdgeDistances::separation
ATYPE separation() const
Definition: MinimumEdgeDistances.h:83
OGDF_HEAVY_ASSERT
#define OGDF_HEAVY_ASSERT(expr)
Assert condition expr when using heavy debugging. See OGDF_ASSERT.
Definition: basic.h:55
ogdf::SListIteratorBase
Encapsulates a pointer to an ogdf::SList element.
Definition: SList.h:50
ogdf::RoutingChannel::overhang
ATYPE overhang() const
Definition: RoutingChannel.h:67
ogdf::OrthoRep::SideInfoUML
Information about a side of a vertex in UML diagrams.
Definition: OrthoRep.h:228
ogdf::CompactionConstraintGraph::m_centerPriority
bool m_centerPriority
should centering be more expensive than generalizations
Definition: CompactionConstraintGraph.h:274
ogdf::PlanRep::expandAdj
adjEntry expandAdj(node v) const
Returns the adjacency entry of a node of an expanded face.
Definition: PlanRep.h:161
CommonCompactionConstraintGraphBase.h
Declares ogdf::CommonCompactionConstraintGraphBase.
ogdf::OrthoDir::South
@ South
ogdf::ListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: List.h:153
ogdf::MinimumEdgeDistances::epsilon
const ATYPE & epsilon(node v, OrthoDir s, int i) const
Definition: MinimumEdgeDistances.h:67
ogdf::CompactionConstraintGraph::m_length
EdgeArray< ATYPE > m_length
length of an edge
Definition: CompactionConstraintGraph.h:257
ogdf::CompactionConstraintGraph::m_vertexArcCost
int m_vertexArcCost
get small cages
Definition: CompactionConstraintGraph.h:267
ogdf::CompactionConstraintGraph::centerPriority
void centerPriority(bool b)
Sets centerPriority (center single edges?)
Definition: CompactionConstraintGraph.h:151
ogdf::CompactionConstraintGraph::SegmentComparer::compare
int compare(const node &x, const node &y) const
Definition: CompactionConstraintGraph.h:230
ogdf::CompactionConstraintGraph::Interval::m_high
ATYPE m_high
lower and upper bound
Definition: CompactionConstraintGraph.h:208
ogdf::CompactionConstraintGraph::m_bungeeCost
int m_bungeeCost
middle position distance penalty
Definition: CompactionConstraintGraph.h:268
ogdf::SListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: SList.h:134
ogdf::AdjElement::twin
adjEntry twin() const
Returns the corresponding adjacency element associated with the same edge.
Definition: Graph_d.h:172
ogdf::List::insertAfter
iterator insertAfter(const E &x, iterator it)
Inserts element x after it.
Definition: List.h:1572
PlanRep.h
Declaration of a base class for planar representations of graphs and cluster graphs.
ogdf::CompactionConstraintGraph::m_MedianArcCost
int m_MedianArcCost
draw merger gen at median of incoming generalizations
Definition: CompactionConstraintGraph.h:269
ogdf::Graph::NodeType::generalizationMerger
@ generalizationMerger
ogdf::AdjElement::faceCyclePred
adjEntry faceCyclePred() const
Returns the cyclic predecessor in face.
Definition: Graph_d.h:215
ogdf::CompactionConstraintGraphBase::pathToOriginal
edge pathToOriginal(node v)
Definition: CompactionConstraintGraph.h:80
ogdf::SListPure::begin
iterator begin()
Returns an iterator to the first element of the list.
Definition: SList.h:344
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::AlgorithmFailureException
Exception thrown when an algorithm realizes an internal bug that prevents it from continuing.
Definition: exceptions.h:247
ogdf::CompactionConstraintGraph::areMulti
bool areMulti(edge e1, edge e2) const
Return PG result for flowcompaction.
ogdf::ListIteratorBase::succ
ListIteratorBase< E, isConst, isReverse > succ() const
Returns successor iterator.
Definition: List.h:174
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:160
ogdf::Graph::nodes
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition: Graph_d.h:932
ogdf::CompactionConstraintGraphBase::alignmentArc
bool alignmentArc(edge e) const
Returns if arc is important for alignment. These are the arcs representing node to gen....
Definition: CompactionConstraintGraph.h:78
ogdf::CompactionConstraintGraph::CompactionConstraintGraph
CompactionConstraintGraph(const OrthoRep &OR, const PlanRep &PG, OrthoDir arcDir, ATYPE sep, int costGen=1, int costAssoc=1, bool align=false)
Construction.
Definition: CompactionConstraintGraph.h:123
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:283
ogdf::CompactionConstraintGraph::setMinimumSeparation
void setMinimumSeparation(const PlanRep &PG, const NodeArray< int > &coord, const MinimumEdgeDistances< ATYPE > &minDist)
Sets min separation for multi edge original.
ogdf::CompactionConstraintGraphBase::m_verticalGen
EdgeArray< bool > m_verticalGen
generalization that runs vertical relative to hierarchy
Definition: CompactionConstraintGraph.h:90
OrthoRep.h
Declaration of orthogonal representation of planar graphs.
ogdf::CompactionConstraintGraph::setExtra
void setExtra(node v, node rep, ATYPE ofs)
Node v has no representation in drawing, only internal representation.
Definition: CompactionConstraintGraph.h:286
ogdf::SListPure::delSucc
void delSucc(iterator itBefore)
Removes the succesor of itBefore.
Definition: SList.h:554
OGDF_THROW
#define OGDF_THROW(CLASS)
Replacement for throw.
Definition: exceptions.h:74
ogdf::OrthoRep
Orthogonal representation of an embedded graph.
Definition: OrthoRep.h:225
SList.h
Declaration of singly linked lists and iterators.
ogdf::CompactionConstraintGraph::insertVisibilityArcs
void insertVisibilityArcs(const PlanRep &PG, const NodeArray< ATYPE > &posDir, const NodeArray< ATYPE > &posOppDir)
Inserts arcs connecting segments which can see each other in a drawing of the associated planarized r...
Definition: CompactionConstraintGraph.h:889
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
MinimumEdgeDistances.h
Declaration of class MinimumEdgeDistances which maintains minimum distances between attached edges at...
ogdf::PlanRep::typeOf
Graph::NodeType typeOf(node v) const
Returns the type of node v.
Definition: PlanRep.h:200
ogdf::CompactionConstraintGraph::SegmentComparer::SegmentComparer
SegmentComparer(const NodeArray< ATYPE > &segPos, const NodeArray< int > &secSort)
Definition: CompactionConstraintGraph.h:225
ogdf::CompactionConstraintGraph::extraOfs
ATYPE extraOfs(node v) const
Returns extraNode position, change to save mem, only need some entries.
Definition: CompactionConstraintGraph.h:145
ogdf::CompactionConstraintGraph::c_doubleBendFactor
static const int c_doubleBendFactor
double bends cost factor*vertexArcCost
Definition: CompactionConstraintGraph.h:279
ogdf::ConstraintEdgeType::MedianArc
@ MedianArc
inserted to replace some reducible in fixzerolength
ogdf::CompactionConstraintGraphBase
Class implementing template-parameter-independent behaviour of ogdf::CompactionConstraintGraph.
Definition: CompactionConstraintGraph.h:59
ogdf::Graph::EdgeType::generalization
@ generalization
ogdf::SListPure
Singly linked lists.
Definition: SList.h:52
ogdf::OrthoRep::nextDir
static OrthoDir nextDir(OrthoDir d)
Returns the next OrthoDir (in a clockwise manner)
Definition: OrthoRep.h:395
ogdf::CompactionConstraintGraph::SegmentComparer::m_pSec
const NodeArray< int > * m_pSec
Definition: CompactionConstraintGraph.h:244
ogdf::CompactionConstraintGraph::setBasicArcsZeroLength
void setBasicArcsZeroLength(const PlanRep &PG)
Definition: CompactionConstraintGraph.h:535
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::ConstraintEdgeType::VisibilityArc
@ VisibilityArc
ogdf::CompactionConstraintGraph::computeTotalCosts
ATYPE computeTotalCosts(const NodeArray< ATYPE > &pos) const
Computes the total costs for coordintes given by pos, i.e., the sum of the weighted lengths of edges ...
Definition: CompactionConstraintGraph.h:848
ogdf::List
Doubly linked lists (maintaining the length of the list).
Definition: DfsMakeBiconnected.h:40
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::CompactionConstraintGraphBase::CompactionConstraintGraphBase
CompactionConstraintGraphBase(const OrthoRep &OR, const PlanRep &PG, OrthoDir arcDir, int costGen=1, int costAssoc=1, bool align=false)
Construction.
ogdf::EdgeElement::adjSource
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition: Graph_d.h:407
ogdf::Graph::NodeType::generalizationExpander
@ generalizationExpander
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:869
ogdf::CompactionConstraintGraphBase::align
void align(bool b)
Triggers alignment (=>some special edge handling to support al.)
Definition: CompactionConstraintGraph.h:74
ogdf::CompactionConstraintGraphBase::verticalGen
bool verticalGen(edge e) const
Returns true if e is vertical edge in PlanRepUML hierarchy.
Definition: CompactionConstraintGraph.h:65
ogdf::CommonCompactionConstraintGraphBase
Base class for ogdf::CompactionConstraintGraphBase.
Definition: CommonCompactionConstraintGraphBase.h:59
ogdf::CompactionConstraintGraph::Interval::m_pathNode
node m_pathNode
corresponding segment
Definition: CompactionConstraintGraph.h:209
ogdf::Graph::NodeType
NodeType
The type of nodes.
Definition: Graph_d.h:912
ogdf::OrthoRep::VertexInfoUML::m_side
SideInfoUML m_side[4]
Definition: OrthoRep.h:267
ogdf::CompactionConstraintGraph::c_MedianFactor
static const int c_MedianFactor
median arcs cost factor*vertexArcCost
Definition: CompactionConstraintGraph.h:280
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::ConstraintEdgeType::FixToZeroArc
@ FixToZeroArc
can be compacted to zero length, can be fixed
ogdf::AdjElement::cyclicSucc
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition: Graph_d.h:354
ogdf::CompactionConstraintGraph::Interval
Represents an interval on the sweep line.
Definition: CompactionConstraintGraph.h:201
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:410
ogdf::CompactionConstraintGraph::insertVertexSizeArcs
void insertVertexSizeArcs(const PlanRep &PG, const NodeArray< ATYPE > &sizeOrig, const RoutingChannel< ATYPE > &rc)
Inserts arcs for respecting sizes of vertices and achieving desired placement of generalizations if v...
Definition: CompactionConstraintGraph.h:428
ogdf::OrthoRep::VertexInfoUML::m_corner
adjEntry m_corner[4]
Definition: OrthoRep.h:270
ogdf::OrthoRep::SideInfoUML::totalAttached
int totalAttached() const
Definition: OrthoRep.h:245
ogdf::CompactionConstraintGraph::m_extraOfs
NodeArray< ATYPE > m_extraOfs
offset of extra node to its rep, should change this
Definition: CompactionConstraintGraph.h:259
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
ogdf::ConstraintEdgeType::ReducibleArc
@ ReducibleArc
can be compacted to zero length
ogdf::List::del
void del(iterator it)
Removes it from the list.
Definition: List.h:1611
basic.h
Basic declarations, included by all source files.
ogdf::SListIteratorBase::succ
SListIteratorBase< E, isConst > succ() const
Returns successor iterator.
Definition: SList.h:152
ogdf::CompactionConstraintGraphBase::m_alignmentArc
EdgeArray< bool > m_alignmentArc
Basic arcs that have to be short for alignment (node to gen expander)
Definition: CompactionConstraintGraph.h:94
ogdf::AdjElement::faceCycleSucc
adjEntry faceCycleSucc() const
Returns the cyclic successor in face.
Definition: Graph_d.h:212
ogdf::CompactionConstraintGraph::m_sep
ATYPE m_sep
Definition: CompactionConstraintGraph.h:255
ogdf::OrthoDir::East
@ East
ogdf::CompactionConstraintGraphBase::insertPathVertices
void insertPathVertices(const PlanRep &PG)
ogdf::CompactionConstraintGraph::Interval::m_low
ATYPE m_low
Definition: CompactionConstraintGraph.h:208
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
List.h
Declaration of doubly linked lists and iterators.
ogdf::CompactionConstraintGraph::separation
ATYPE separation() const
Returns the separation value.
Definition: CompactionConstraintGraph.h:194
ogdf::MinimumEdgeDistances::delta
const ATYPE & delta(node v, OrthoDir s, int i) const
Definition: MinimumEdgeDistances.h:50
ogdf::CompactionConstraintGraphBase::dfsInsertPathVertex
void dfsInsertPathVertex(node v, node pathVertex, NodeArray< bool > &visited, const NodeArray< node > &genOpposite)
ogdf::SListPure::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: SList.h:481
ogdf::CompactionConstraintGraph::resetGenMergerLengths
void resetGenMergerLengths(const PlanRep &PG, adjEntry adjFirst)
Definition: CompactionConstraintGraph.h:326
ogdf::ListIteratorBase
Encapsulates a pointer to a list element.
Definition: List.h:51
ogdf::CompactionConstraintGraph::c_bungeeFactor
static const int c_bungeeFactor
Definition: CompactionConstraintGraph.h:278
RoutingChannel.h
Declaration of class RoutingChannel which maintains required size of routing channels and separation,...
ogdf::CompactionConstraintGraphBase::m_verticalArc
EdgeArray< bool > m_verticalArc
arc corresponding to such an edge
Definition: CompactionConstraintGraph.h:91
ogdf::MinimumEdgeDistances
Maintains input sizes for improvement compaction (deltas and epsilons)
Definition: EdgeRouter.h:49
ogdf::CompactionConstraintGraphBase::verticalArc
bool verticalArc(edge e) const
Returns true if e is basic arc of vertical edge in PlanRepUML hierarchy.
Definition: CompactionConstraintGraph.h:69
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::CompactionConstraintGraph
Represents a constraint graph used for compaction.
Definition: CompactionConstraintGraph.h:120
ogdf::OrthoRep::prevDir
static OrthoDir prevDir(OrthoDir d)
Returns the previous OrthoDir (in a clockwise manner)
Definition: OrthoRep.h:400
ogdf::ConstraintEdgeType::VertexSizeArc
@ VertexSizeArc
ogdf::sync_plan::internal::to_string
std::string to_string(const std::function< std::ostream &(std::ostream &)> &func)
comparer.h
Declarations for Comparer objects.
ogdf::CompactionConstraintGraph::SegmentComparer::m_pPos
const NodeArray< ATYPE > * m_pPos
Definition: CompactionConstraintGraph.h:243
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
tuples.h
Declaration and implementation of class Tuple2, Tuple3 and Tuple4.
ogdf::SListPure::popFront
void popFront()
Removes the first element from the list.
Definition: SList.h:531
ogdf::Graph::NodeType::dummy
@ dummy
ogdf::CompactionConstraintGraph::centerPriority
bool centerPriority()
Gets centerPriority (center single edges?)
Definition: CompactionConstraintGraph.h:148
ogdf::CompactionConstraintGraph::m_genToMedian
bool m_genToMedian
draw outgoing generalization from merger above ingoing gen.
Definition: CompactionConstraintGraph.h:271
ogdf::CompactionConstraintGraph::initializeCosts
void initializeCosts()
Definition: CompactionConstraintGraph.h:292
ogdf::CompactionConstraintGraphBase::insertBasicArcs
void insertBasicArcs(const PlanRep &PG)
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::GraphCopyBase::original
const Graph & original() const
Returns a reference to the original graph.
Definition: GraphCopy.h:105
ogdf::CompactionConstraintGraph::getLengthString
virtual string getLengthString(edge e) const override
Definition: CompactionConstraintGraph.h:247
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::List::insertBefore
iterator insertBefore(const E &x, iterator it)
Inserts element x before it.
Definition: List.h:1566
ogdf::CompactionConstraintGraph::Interval::Interval
Interval(node v, ATYPE low, ATYPE high)
Definition: CompactionConstraintGraph.h:202
ogdf::RoutingChannel
Maintains input sizes for constructive compaction (size of routing channels, separation,...
Definition: RoutingChannel.h:47
ogdf::CompactionConstraintGraph::c_vertexArcFactor
static const int c_vertexArcFactor
Definition: CompactionConstraintGraph.h:277