00001
00002
00003
00004
00005
00006
00007
00008
00046 #ifdef _MSC_VER
00047 #pragma once
00048 #endif
00049
00050
00051 #ifndef OGDF_COMP_CONSTR_GRAPH_H
00052 #define OGDF_COMP_CONSTR_GRAPH_H
00053
00054
00055 #include <ogdf/orthogonal/OrthoRep.h>
00056 #include <ogdf/internal/orthogonal/RoutingChannel.h>
00057 #include <ogdf/orthogonal/MinimumEdgeDistances.h>
00058
00059
00060 namespace ogdf {
00061
00062
00063
00064 enum ConstraintEdgeType {
00065 cetBasicArc,
00066 cetVertexSizeArc,
00067 cetVisibilityArc,
00068 cetFixToZeroArc,
00069 cetReducibleArc,
00070 cetMedianArc
00071 };
00072
00073
00074
00075
00076
00077
00078 class CompactionConstraintGraphBase : protected Graph
00079 {
00080 public:
00081
00082
00083 void writeGML(const char *fileName) const ;
00084 void writeGML(ostream &os) const;
00085
00086 void writeGML(const char *fileName, NodeArray<bool> one) const ;
00087 void writeGML(ostream &os, NodeArray<bool> one) const;
00088
00089
00090 edge basicArc(edge e) const {
00091 return m_edgeToBasicArc[e];
00092 }
00093
00094
00095
00096
00097
00098 bool verticalGen(edge e) const {return m_verticalGen[e];}
00099
00100
00101 bool verticalArc(edge e) const {return m_verticalArc[e];}
00102
00103 bool onBorder(edge e) const {return m_border[e]>0;}
00104
00105 bool fixOnBorder(edge e) const {return (m_border[e] == 2);}
00106
00107
00108 void align(bool b) {m_align = b;}
00109
00110
00111
00112 bool alignmentArc(edge e) const {return m_alignmentArc[e];}
00113
00114 const PlanRep& getPlanRep() const {return *m_pPR;}
00115
00116 edge pathToOriginal(node v) {return m_pathToEdge[v];}
00117
00118 protected:
00119
00120 CompactionConstraintGraphBase(const OrthoRep &OR,
00121 const PlanRep &PG,
00122 OrthoDir arcDir,
00123 int costGen = 1,
00124 int costAssoc = 1, bool align = false);
00125
00126
00127 void computeTopologicalSegmentNum(NodeArray<int> &topNum);
00128
00129
00130
00131 void removeRedundantVisibArcs(SListPure<Tuple2<node,node> > &visibArcs);
00132
00133 const OrthoRep *m_pOR;
00134 const PlanRep *m_pPR;
00135 OrthoDir m_arcDir;
00136 OrthoDir m_oppArcDir;
00137
00138 int m_edgeCost[2];
00139
00140 NodeArray<SListPure<node> > m_path;
00141 NodeArray<node> m_pathNode;
00142 EdgeArray<edge> m_edgeToBasicArc;
00143
00144 EdgeArray<int> m_cost;
00145 EdgeArray<ConstraintEdgeType> m_type;
00146
00147
00148 EdgeArray<bool> m_verticalGen;
00149 EdgeArray<bool> m_verticalArc;
00150 EdgeArray<int> m_border;
00151
00152
00153 EdgeArray<bool> m_alignmentArc;
00154
00155 NodeArray<edge> m_pathToEdge;
00156 NodeArray<edge> m_originalEdge;
00157
00158
00159
00160 void embed();
00161
00162 virtual void writeLength(ostream &os, edge e) const = 0;
00163
00164 private:
00165
00166
00167 bool m_align;
00168
00169 void insertPathVertices(const PlanRep &PG);
00170 void dfsInsertPathVertex(
00171 node v,
00172 node pathVertex,
00173 NodeArray<bool> &visited,
00174 const NodeArray<node> &genOpposite);
00175
00176 void insertBasicArcs(const PlanRep &PG);
00177
00178 node m_superSource;
00179 node m_superSink;
00180 SList<node> m_sources;
00181 SList<node> m_sinks;
00182
00183
00184 };
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 template<class ATYPE>
00197 class CompactionConstraintGraph : public CompactionConstraintGraphBase
00198 {
00199 public:
00200
00201 CompactionConstraintGraph(const OrthoRep &OR,
00202 const PlanRep &PG,
00203 OrthoDir arcDir,
00204 ATYPE sep,
00205 int costGen = 1,
00206 int costAssoc = 1,
00207 bool align = false) :
00208 CompactionConstraintGraphBase(OR, PG, arcDir, costGen, costAssoc, align),
00209 m_length((Graph&)*this, sep), m_extraNode((Graph&)*this, false),
00210 m_extraOfs((Graph&)*this, 0), m_extraRep((Graph&)*this, 0)
00211 {
00212 OGDF_ASSERT(&(const Graph &)PG == &(const Graph &)OR);
00213 m_sep = sep;
00214
00215 m_centerPriority = true;
00216 m_genToMedian = true;
00217 initializeCosts();
00218
00219 }
00220
00221
00222 void writeGML(const char *fileName) const ;
00223 void writeGML(ostream &os) const;
00224
00225
00226
00227 const Graph &getGraph() const { return (Graph&)*this; }
00228 Graph &getGraph() { return (Graph&)*this; }
00229
00230
00231 const OrthoRep &getOrthoRep() const {
00232 return *m_pOR;
00233 }
00234
00235
00236
00237
00238 const SListPure<node> &nodesIn(node v) const {
00239 return m_path[v];
00240 }
00241
00242
00243
00244 node pathNodeOf(node v) const {
00245 return m_pathNode[v];
00246 }
00247
00248
00249
00250 ATYPE length(edge e) const {
00251 return m_length[e];
00252 }
00253
00254
00255
00256 int cost(edge e) const {
00257 return m_cost[e];
00258 }
00259
00260
00261
00262 ConstraintEdgeType typeOf(edge e) const {
00263 return m_type[e];
00264 }
00265
00266
00267 bool extraNode(node v) const {
00268 return m_extraNode[v];
00269 }
00270
00271 ATYPE extraOfs(node v) const {
00272 return m_extraOfs[v];
00273 }
00274
00275 node extraRep(node v) const {
00276 return m_extraRep[v];
00277 }
00278
00279
00280 bool centerPriority() {return m_centerPriority;}
00281 void centerPriority(bool b) { m_centerPriority = b;}
00282
00283
00284
00285 ATYPE computeTotalCosts(const NodeArray<ATYPE> &pos) const;
00286
00287
00288
00289
00290
00291
00292 void insertVertexSizeArcs(const PlanRep &PG,
00293 const NodeArray<ATYPE> &sizeOrig,
00294 const RoutingChannel<ATYPE> &rc);
00295
00296
00297
00298
00299
00300
00301 void insertVertexSizeArcs(
00302 const PlanRep &PG,
00303 const NodeArray<ATYPE> &sizeOrig,
00304 const MinimumEdgeDistances<ATYPE> &minDist);
00305
00306
00307
00308
00309 void insertVisibilityArcs(
00310 const PlanRep &PG,
00311 const NodeArray<ATYPE> &posDir,
00312
00313 const NodeArray<ATYPE> &posOppDir);
00314
00315
00316 void insertVisibilityArcs(
00317 const PlanRep &PG,
00318 const NodeArray<ATYPE> &posDir,
00319 const NodeArray<ATYPE> &posOrthDir,
00320 const MinimumEdgeDistances<ATYPE> &minDist);
00321
00322
00323
00324 void setMinimumSeparation(const PlanRep &PG,
00325 const NodeArray<int> coord,
00326 const MinimumEdgeDistances<ATYPE> &minDist);
00327
00328
00329
00330
00331 void embed() {
00332 CompactionConstraintGraphBase::embed();
00333 }
00334
00335
00336
00337
00338
00339
00340 bool isFeasible(const NodeArray<ATYPE> &pos);
00341
00342
00343 ATYPE separation() const {return m_sep;}
00344
00345
00346 bool areMulti(edge e1, edge e2) const;
00347
00348
00349 private:
00350
00351
00352
00353
00354 struct Interval
00355 {
00356 Interval(node v, ATYPE low, ATYPE high) {
00357 m_low = low;
00358 m_high = high;
00359 m_pathNode = v;
00360 }
00361
00362 ATYPE m_low, m_high;
00363 node m_pathNode;
00364
00365
00366 friend ostream &operator<<(ostream &os,
00367 const Interval &interval)
00368 {
00369 os << "[" << interval.m_low << "," << interval.m_high <<
00370 ";" << interval.m_pathNode << "]";
00371 return os;
00372 }
00373
00374 };
00375
00376
00377
00378
00379
00380
00381
00382
00383 class SegmentComparer
00384 {
00385 public:
00386 SegmentComparer(const NodeArray<ATYPE> &segPos,
00387 const NodeArray<int> &secSort) {
00388 m_pPos = &segPos;
00389 m_pSec = &secSort;
00390 }
00391
00392 int compare(const node &x, const node &y) const {
00393 ATYPE d = (*m_pPos)[x] - (*m_pPos)[y];
00394 if (d < 0)
00395 return -1;
00396 else if (d > 0)
00397 return 1;
00398 else
00399 return (*m_pSec)[x] - (*m_pSec)[y];
00400 }
00401
00402 OGDF_AUGMENT_COMPARER(node)
00403 private:
00404 const NodeArray<ATYPE> *m_pPos;
00405 const NodeArray<int> *m_pSec;
00406 };
00407
00408 virtual void writeLength(ostream &os, edge e) const {
00409 os << m_length[e];
00410 }
00411
00412 void setBasicArcsZeroLength(const PlanRep &PG);
00413 void resetGenMergerLengths(const PlanRep &PG, adjEntry adjFirst);
00414 void setBoundaryCosts(adjEntry cornerDir,adjEntry cornerOppDir);
00415
00416 bool checkSweepLine(const List<Interval> &sweepLine);
00417
00418 ATYPE m_sep;
00419
00420 EdgeArray<ATYPE> m_length;
00421
00422 NodeArray<bool> m_extraNode;
00423
00424 NodeArray<ATYPE> m_extraOfs;
00425 NodeArray<node> m_extraRep;
00426
00427
00428
00429
00430
00431
00432
00433 int m_vertexArcCost;
00434 int m_bungeeCost;
00435 int m_MedianArcCost;
00436 int m_doubleBendCost;
00437 bool m_genToMedian;
00438
00439
00440 bool m_centerPriority;
00441
00442
00443 static const int c_vertexArcFactor;
00444 static const int c_bungeeFactor;
00445 static const int c_doubleBendFactor;
00446 static const int c_MedianFactor;
00447
00448
00449 protected:
00450
00451 void setExtra(node v, node rep, ATYPE ofs)
00452 {m_extraNode[v] = true; m_extraRep[v] = rep; m_extraOfs[v] = ofs;}
00453
00454 void initializeCosts()
00455 {
00456
00457
00458
00459
00460
00461 int costGen = m_edgeCost[Graph::generalization];
00462
00463 m_vertexArcCost = c_vertexArcFactor*costGen;
00464 if (m_centerPriority)
00465 m_bungeeCost = c_bungeeFactor*costGen+1;
00466 else
00467 m_bungeeCost = c_bungeeFactor*4+1;
00468
00469 m_MedianArcCost = c_MedianFactor*m_vertexArcCost;
00470 m_doubleBendCost = c_doubleBendFactor*m_vertexArcCost;
00471 }
00472 };
00473
00474
00475
00476 template<class ATYPE>
00477 const int CompactionConstraintGraph<ATYPE>::c_vertexArcFactor = 20;
00478 template<class ATYPE>
00479 const int CompactionConstraintGraph<ATYPE>::c_bungeeFactor = 20;
00480 template<class ATYPE>
00481 const int CompactionConstraintGraph<ATYPE>::c_doubleBendFactor = 20;
00482
00483 template<class ATYPE>
00484 const int CompactionConstraintGraph<ATYPE>::c_MedianFactor = 10*c_doubleBendFactor;
00485
00486
00487
00488
00489
00490
00491
00492 }
00493
00494 #include <ogdf/planarity/PlanRep.h>
00495
00496 namespace ogdf {
00497
00498
00499
00500 template<class ATYPE>
00501 void CompactionConstraintGraph<ATYPE>::resetGenMergerLengths(
00502 const PlanRep &PG,
00503 adjEntry adjFirst)
00504 {
00505 adjEntry adj = adjFirst;
00506 int faceSize = 0;
00507
00508 do {
00509 if ((m_pOR->direction(adj) == m_arcDir ||
00510 m_pOR->direction(adj) == m_oppArcDir) &&
00511 (PG.typeOf(adj->theNode()) == Graph::dummy ||
00512 PG.typeOf(adj->twinNode()) == Graph::dummy))
00513 {
00514 m_length[m_edgeToBasicArc[adj]] = 0;
00515 }
00516
00517 adj = adj->faceCycleSucc();
00518 faceSize++;
00519 } while(adj != adjFirst);
00520
00521
00522
00523
00524
00525 if (m_genToMedian)
00526 {
00527 if ((m_pOR->direction(adjFirst) == m_arcDir) ||
00528 (m_pOR->direction(adjFirst) == m_oppArcDir) )
00529 {
00530 int numIncoming = faceSize - 3;
00531 int median = (numIncoming / 2) + 1;
00532
00533
00534 node upper = m_pathNode[adjFirst->theNode()];
00535 if (PG.typeOf(adjFirst->theNode()) != Graph::generalizationMerger)
00536 OGDF_THROW(AlgorithmFailureException);
00537 node vMin;
00538 if (m_pOR->direction(adjFirst) == m_arcDir)
00539 vMin = adjFirst->faceCyclePred()->theNode();
00540 else vMin = adjFirst->faceCycleSucc()->theNode();
00541 adj = adjFirst->faceCycleSucc();
00542 for (int i = 0; i < median; i++)
00543 adj = adj->faceCycleSucc();
00544 node lower = m_pathNode[adj->theNode()];
00545 node vCenter = newNode();
00546 setExtra(vCenter, vMin, 0);
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 edge e1 = newEdge(vCenter,upper);
00557 m_length[e1] = 0;
00558 m_cost[e1] = m_MedianArcCost;
00559 m_type[e1] = cetMedianArc;
00560
00561 edge e2 = newEdge(vCenter,lower);
00562 m_length[e2] = 0;
00563 m_cost[e2] = m_MedianArcCost;
00564 m_type[e2] = cetMedianArc;
00565 }
00566 }
00567
00568 }
00569
00570
00571
00572 template<class ATYPE>
00573 void CompactionConstraintGraph<ATYPE>::setBoundaryCosts(
00574 adjEntry cornerDir,
00575 adjEntry cornerOppDir)
00576 {
00577
00578
00579
00580
00581
00582
00583
00584
00585 adjEntry adj;
00586 for (adj = cornerDir; m_pOR->direction(adj) == m_arcDir; adj = adj->faceCycleSucc())
00587 {
00588 m_cost[m_edgeToBasicArc[adj]] = 0;
00589
00590 if (m_pathNode[adj->twin()->cyclicSucc()->theNode()] &&
00591 (m_pOR->direction(adj->faceCycleSucc()) == m_arcDir)
00592 )
00593 m_originalEdge[m_pathNode[adj->twin()->cyclicSucc()->theNode()]] =
00594 m_pPR->original(adj->twin()->cyclicSucc()->theEdge());
00595
00596 }
00597 for (adj = cornerOppDir; m_pOR->direction(adj) == m_oppArcDir; adj = adj->faceCycleSucc())
00598 {
00599 m_cost[m_edgeToBasicArc[adj]] = 0;
00600
00601 if (m_pathNode[adj->twin()->cyclicSucc()->theNode()])
00602 m_originalEdge[m_pathNode[adj->twin()->cyclicSucc()->theNode()]] =
00603 m_pPR->original(adj->twin()->cyclicSucc()->theEdge());
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612 template<class ATYPE>
00613 void CompactionConstraintGraph<ATYPE>::insertVertexSizeArcs(
00614 const PlanRep &PG,
00615 const NodeArray<ATYPE> &sizeOrig,
00616 const RoutingChannel<ATYPE> &rc)
00617 {
00618
00619
00620
00621
00622 OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
00623 OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
00624
00625 const ATYPE overhang = rc.overhang();
00626
00627 node v;
00628 forall_nodes(v,PG)
00629 {
00630 if (PG.expandAdj(v) == 0) continue;
00631
00632 if(PG.typeOf(v) == Graph::generalizationMerger)
00633 {
00634 resetGenMergerLengths(PG,PG.expandAdj(v));
00635
00636 }
00637 else
00638 {
00639 ATYPE size = sizeOrig[v];
00640
00641 const OrthoRep::VertexInfoUML &vi = *m_pOR->cageInfo(v);
00642
00643
00644 ATYPE rcMin = overhang + rc(v,dirMin);
00645 ATYPE rcMax = overhang + rc(v,dirMax);
00646
00647 adjEntry cornerDir = vi.m_corner[m_arcDir];
00648 adjEntry cornerOppDir = vi.m_corner[m_oppArcDir];
00649 adjEntry cornerMin = vi.m_corner[dirMin];
00650 adjEntry cornerMax = vi.m_corner[dirMax];
00651
00652
00653 setBoundaryCosts(cornerDir,cornerOppDir);
00654
00655 const OrthoRep::SideInfoUML &sDir = vi.m_side[m_arcDir];
00656 const OrthoRep::SideInfoUML &sOppDir = vi.m_side[m_oppArcDir];
00657
00658
00659 if(sDir.totalAttached() > 0) {
00660 m_length[m_edgeToBasicArc[cornerDir]] = rcMin;
00661 m_length[m_edgeToBasicArc[cornerMax->faceCyclePred()]] = rcMax;
00662 } else {
00663
00664 m_length[m_edgeToBasicArc[cornerDir]] = 0;
00665 delEdge(m_edgeToBasicArc[cornerDir]);
00666 }
00667
00668 if(sOppDir.totalAttached() > 0) {
00669 m_length[m_edgeToBasicArc[cornerOppDir]] = rcMax;
00670 m_length[m_edgeToBasicArc[cornerMin->faceCyclePred()]] = rcMin;
00671 } else {
00672
00673 m_length[m_edgeToBasicArc[cornerOppDir]] = 0;
00674 delEdge(m_edgeToBasicArc[cornerOppDir]);
00675 }
00676
00677
00678
00679 node vMin = m_pathNode[cornerDir->theNode()];
00680 node vMax = m_pathNode[cornerOppDir->theNode()];
00681
00682
00683 if (sDir.m_adjGen == 0 && sOppDir.m_adjGen == 0)
00684 {
00685
00686 edge e = newEdge(vMin,vMax);
00687 m_length[e] = rcMin + size + rcMax - 2*overhang;
00688 m_cost [e] = 2*m_vertexArcCost;
00689 m_type [e] = cetVertexSizeArc;
00690
00691 } else {
00692
00693 ATYPE minHalf = size/2;
00694 ATYPE maxHalf = size - minHalf;
00695 ATYPE lenMin = rcMin + minHalf - overhang;
00696 ATYPE lenMax = maxHalf + rcMax - overhang;
00697
00698 if (sDir.m_adjGen != 0) {
00699 node vCenter = m_pathNode[sDir.m_adjGen->theNode()];
00700 edge e1 = newEdge(vMin,vCenter);
00701 m_length[e1] = lenMin;
00702 m_cost [e1] = m_vertexArcCost;
00703 m_type [e1] = cetVertexSizeArc;
00704 edge e2 = newEdge(vCenter,vMax);
00705 m_length[e2] = lenMax;
00706 m_cost [e2] = m_vertexArcCost;
00707 m_type [e2] = cetVertexSizeArc;
00708 }
00709
00710 if (sOppDir.m_adjGen != 0) {
00711 node vCenter = m_pathNode[sOppDir.m_adjGen->theNode()];
00712 edge e1 = newEdge(vMin,vCenter);
00713 m_length[e1] = lenMin;
00714 m_cost [e1] = m_vertexArcCost;
00715 m_type [e1] = cetVertexSizeArc;
00716 edge e2 = newEdge(vCenter,vMax);
00717 m_length[e2] = lenMax;
00718 m_cost [e2] = m_vertexArcCost;
00719 m_type [e2] = cetVertexSizeArc;
00720 }
00721
00722 }
00723
00724 }
00725 }
00726 }
00727
00728
00729 template<class ATYPE>
00730 void CompactionConstraintGraph<ATYPE>::setBasicArcsZeroLength(
00731 const PlanRep &PG)
00732 {
00733 edge e;
00734 forall_edges(e,PG)
00735 {
00736 edge arc = m_edgeToBasicArc[e];
00737 if (arc == 0) continue;
00738
00739 node v = e->source();
00740 node w = e->target();
00741 if ( ((PG.typeOf(v) == Graph::dummy) && (PG.typeOf(w) == Graph::dummy) &&
00742 (v->degree() == 2) && w->degree() == 2) &&
00743 (m_pOR->angle(e->adjSource()) == m_pOR->angle(e->adjTarget()) ) &&
00744 (PG.typeOf(e) != Graph::generalization)
00745 )
00746 {
00747 m_length[arc] = 0;
00748 m_type[arc] = cetFixToZeroArc;
00749
00750 m_cost[arc] = m_doubleBendCost;
00751 }
00752 }
00753 }
00754
00755
00756
00757
00758
00759
00760
00761 template<class ATYPE>
00762 void CompactionConstraintGraph<ATYPE>::insertVertexSizeArcs(
00763 const PlanRep &PG,
00764 const NodeArray<ATYPE> &sizeOrig,
00765 const MinimumEdgeDistances<ATYPE> &minDist)
00766 {
00767
00768
00769 setBasicArcsZeroLength(PG);
00770
00771
00772
00773
00774 OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
00775 OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
00776
00777 node v;
00778 forall_nodes(v,PG)
00779 {
00780 if (PG.expandAdj(v) == 0) continue;
00781
00782 if(PG.typeOf(v) == Graph::generalizationMerger)
00783 {
00784 resetGenMergerLengths(PG,PG.expandAdj(v));
00785
00786 }
00787 else
00788 {
00789 ATYPE size = sizeOrig[v];
00790 const OrthoRep::VertexInfoUML &vi = *m_pOR->cageInfo(v);
00791
00792 adjEntry cornerDir = vi.m_corner[m_arcDir];
00793 adjEntry cornerOppDir = vi.m_corner[m_oppArcDir];
00794 adjEntry cornerMin = vi.m_corner[dirMin];
00795 adjEntry cornerMax = vi.m_corner[dirMax];
00796
00797 adjEntry adj = cornerDir, last = cornerMax->faceCyclePred();
00798 if(adj != last) {
00799 m_length[m_edgeToBasicArc[adj]] = minDist.epsilon(v,m_arcDir,0);
00800 m_length[m_edgeToBasicArc[last]] = minDist.epsilon(v,m_arcDir,1);
00801 int i = 0;
00802 for(adj = adj->faceCycleSucc(); adj != last; adj = adj->faceCycleSucc()) {
00803 if (PG.typeOf(adj->cyclicPred()->theEdge()) == Graph::generalization)
00804 i++;
00805 m_length[m_edgeToBasicArc[adj]] = minDist.delta(v,m_arcDir,i);
00806 }
00807 }
00808
00809 adj = cornerOppDir, last = cornerMin->faceCyclePred();
00810 if(adj != last) {
00811 m_length[m_edgeToBasicArc[adj]] = minDist.epsilon(v,m_oppArcDir,0);
00812 m_length[m_edgeToBasicArc[last]] = minDist.epsilon(v,m_oppArcDir,1);
00813 int i = 0;
00814 for(adj = adj->faceCycleSucc(); adj != last; adj = adj->faceCycleSucc()) {
00815 if (PG.typeOf(adj->cyclicPred()->theEdge()) == Graph::generalization)
00816 i++;
00817 m_length[m_edgeToBasicArc[adj]] = minDist.delta(v,m_oppArcDir,i);
00818 }
00819 }
00820
00821
00822
00823 node vMin = m_pathNode[cornerDir->theNode()];
00824 node vMax = m_pathNode[cornerOppDir->theNode()];
00825
00826 const OrthoRep::SideInfoUML &sDir = vi.m_side[m_arcDir];
00827 const OrthoRep::SideInfoUML &sOppDir = vi.m_side[m_oppArcDir];
00828
00829
00830 if (sDir.m_adjGen == 0 && sOppDir.m_adjGen == 0)
00831 {
00832
00833
00834
00835 if ((sDir.totalAttached() == 1) || (sOppDir.totalAttached() == 1))
00836 {
00837
00838 ATYPE lenMin = size/2;
00839 ATYPE lenMax = size - lenMin;
00840 node vCenter = newNode();
00841 setExtra(vCenter, cornerDir->theNode(), lenMin);
00842
00843 edge e1 = newEdge(vMin,vCenter);
00844 m_length[e1] = lenMin;
00845
00846 m_cost[e1] = m_vertexArcCost;
00847 m_type[e1] = cetVertexSizeArc;
00848 edge e2 = newEdge(vCenter,vMax);
00849 m_length[e2] = lenMax;
00850 m_cost[e2] = m_vertexArcCost;
00851 m_type[e2] = cetVertexSizeArc;
00852
00853 if (sDir.totalAttached() == 1)
00854 {
00855
00856
00857
00858 node vBungee = newNode();
00859
00860 setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v,m_arcDir,0) );
00861
00862 edge eToBungee = newEdge(vMin, vBungee);
00863 m_type[eToBungee] = cetMedianArc;
00864 m_cost[eToBungee] = 0;
00865 m_length[eToBungee] = minDist.epsilon(v,m_arcDir,0);
00866
00867 edge eBungeeCenter = newEdge(vBungee, vCenter);
00868
00869 m_type[eBungeeCenter] = cetMedianArc;
00870 m_cost[eBungeeCenter] = m_bungeeCost;
00871 m_length[eBungeeCenter] = 0;
00872
00873
00874 edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerDir->twinNode()]);
00875 if (m_pathNode[cornerDir->twinNode()] == vMin) exit(1);
00876
00877 m_type[eBungeeOut] = cetMedianArc;
00878 m_cost[eBungeeOut] = m_bungeeCost;
00879 m_length[eBungeeOut] = 0;
00880
00881
00882
00883
00884
00885
00886
00887 }
00888 if ( (sOppDir.totalAttached() == 1) && !(m_pathNode[cornerOppDir->twinNode()] == vMin) )
00889 {
00890
00891
00892
00893 node vBungee = newNode();
00894
00895 setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v,m_oppArcDir,0) );
00896
00897 edge eToBungee = newEdge(vMin, vBungee);
00898 m_type[eToBungee] = cetMedianArc;
00899 m_cost[eToBungee] = 0;
00900 m_length[eToBungee] = minDist.epsilon(v,m_oppArcDir,0);
00901
00902 edge eBungeeCenter = newEdge(vBungee, vCenter);
00903
00904 m_type[eBungeeCenter] = cetMedianArc;
00905 m_cost[eBungeeCenter] = m_bungeeCost;
00906 m_length[eBungeeCenter] = 0;
00907
00908
00909 edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerOppDir->twinNode()]);
00910
00911 m_type[eBungeeOut] = cetMedianArc;
00912 m_cost[eBungeeOut] = m_bungeeCost;
00913 m_length[eBungeeOut] = 0;
00914
00915
00916
00917
00918
00919
00920
00921 }
00922 }
00923 else
00924 {
00925
00926 edge e = newEdge(vMin,vMax);
00927 m_length[e] = size;
00928 m_cost[e] = 2*m_vertexArcCost;
00929 m_type[e] = cetVertexSizeArc;
00930 }
00931
00932
00933 } else {
00934
00935 ATYPE lenMin = size/2;
00936 ATYPE lenMax = size - lenMin;
00937
00938
00939
00940 if (sDir.m_adjGen != 0) {
00941 node vCenter = m_pathNode[sDir.m_adjGen->theNode()];
00942 edge e1 = newEdge(vMin,vCenter);
00943 m_length[e1] = lenMin;
00944 m_cost [e1] = m_vertexArcCost;
00945 m_type [e1] = cetVertexSizeArc;
00946 edge e2 = newEdge(vCenter,vMax);
00947 m_length[e2] = lenMax;
00948 m_cost [e2] = m_vertexArcCost;
00949 m_type [e2] = cetVertexSizeArc;
00950 }
00951 else
00952 {
00953 if (sDir.totalAttached() == 1)
00954 {
00955 node vCenter = newNode();
00956 setExtra(vCenter, cornerDir->theNode(), lenMin);
00957
00958 edge e1 = newEdge(vMin,vCenter);
00959 m_length[e1] = lenMin;
00960 m_cost[e1] = m_vertexArcCost;
00961 m_type[e1] = cetVertexSizeArc;
00962 edge e2 = newEdge(vCenter,vMax);
00963 m_length[e2] = lenMax;
00964 m_cost[e2] = m_vertexArcCost;
00965 m_type[e2] = cetVertexSizeArc;
00966
00967
00968
00969 node vBungee = newNode();
00970
00971 setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v,m_arcDir,0) );
00972
00973 edge eToBungee = newEdge(vMin, vBungee);
00974 m_type[eToBungee] = cetMedianArc;
00975 m_cost[eToBungee] = 0;
00976 m_length[eToBungee] = minDist.epsilon(v,m_arcDir,0);
00977
00978 edge eBungeeCenter = newEdge(vBungee, vCenter);
00979
00980 m_type[eBungeeCenter] = cetMedianArc;
00981 m_cost[eBungeeCenter] = m_bungeeCost;
00982 m_length[eBungeeCenter] = 0;
00983
00984
00985 edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerDir->twinNode()]);
00986
00987 m_type[eBungeeOut] = cetMedianArc;
00988 m_cost[eBungeeOut] = m_bungeeCost;
00989 m_length[eBungeeOut] = 0;
00990
00991 }
00992 }
00993 if (sOppDir.m_adjGen != 0) {
00994 node vCenter = m_pathNode[sOppDir.m_adjGen->theNode()];
00995 edge e1 = newEdge(vMin,vCenter);
00996 m_length[e1] = lenMin;
00997 m_cost [e1] = m_vertexArcCost;
00998 m_type [e1] = cetVertexSizeArc;
00999 edge e2 = newEdge(vCenter,vMax);
01000 m_length[e2] = lenMax;
01001 m_cost [e2] = m_vertexArcCost;
01002 m_type [e2] = cetVertexSizeArc;
01003 }
01004 else
01005 {
01006
01007 if ( (sOppDir.totalAttached() == 1) && !(m_pathNode[cornerOppDir->twinNode()] == vMin) )
01008 {
01009 node vCenter = newNode();
01010 setExtra(vCenter, cornerDir->theNode(), lenMin);
01011
01012 edge e1 = newEdge(vMin,vCenter);
01013 m_length[e1] = lenMin;
01014 m_cost[e1] = m_vertexArcCost;
01015 m_type[e1] = cetVertexSizeArc;
01016 edge e2 = newEdge(vCenter,vMax);
01017 m_length[e2] = lenMax;
01018 m_cost[e2] = m_vertexArcCost;
01019 m_type[e2] = cetVertexSizeArc;
01020
01021
01022 node vBungee = newNode();
01023
01024 setExtra(vBungee, cornerDir->theNode(), minDist.epsilon(v,m_oppArcDir,0) );
01025
01026 edge eToBungee = newEdge(vMin, vBungee);
01027 m_type[eToBungee] = cetMedianArc;
01028 m_cost[eToBungee] = 0;
01029 m_length[eToBungee] = minDist.epsilon(v,m_oppArcDir,0);
01030
01031 edge eBungeeCenter = newEdge(vBungee, vCenter);
01032
01033 m_type[eBungeeCenter] = cetMedianArc;
01034 m_cost[eBungeeCenter] = m_bungeeCost;
01035 m_length[eBungeeCenter] = 0;
01036
01037
01038 edge eBungeeOut = newEdge(vBungee, m_pathNode[cornerOppDir->twinNode()]);
01039
01040 m_type[eBungeeOut] = cetMedianArc;
01041 m_cost[eBungeeOut] = m_bungeeCost;
01042 m_length[eBungeeOut] = 0;
01043
01044 }
01045 }
01046
01047 }
01048
01049
01050 setBoundaryCosts(cornerDir,cornerOppDir);
01051
01052 }
01053 }
01054
01055
01056
01057 }
01058
01059
01060
01061
01062 template<class ATYPE>
01063 ATYPE CompactionConstraintGraph<ATYPE>::computeTotalCosts(
01064 const NodeArray<ATYPE> &pos) const
01065 {
01066 ATYPE c = 0;
01067
01068 edge e;
01069 forall_edges(e,*this)
01070 {
01071 c += cost(e) * (pos[e->target()] - pos[e->source()]);
01072 }
01073
01074 return c;
01075 }
01076
01077
01078
01079
01080
01081
01082 template<class ATYPE>
01083 bool CompactionConstraintGraph<ATYPE>::checkSweepLine(const List<Interval> &sweepLine)
01084 {
01085 if (sweepLine.empty())
01086 return true;
01087
01088 ListConstIterator<Interval> it = sweepLine.begin();
01089
01090 if((*it).m_high < (*it).m_low)
01091 return false;
01092
01093 ATYPE x = (*it).m_low;
01094
01095 for(++it; it.valid(); ++it) {
01096 if((*it).m_high < (*it).m_low)
01097 return false;
01098 if ((*it).m_high > x)
01099 return false;
01100 x = (*it).m_low;
01101 }
01102
01103 return true;
01104 }
01105
01106
01107 template<class ATYPE>
01108 void CompactionConstraintGraph<ATYPE>::insertVisibilityArcs(
01109 const PlanRep &PG,
01110 const NodeArray<ATYPE> &posDir,
01111 const NodeArray<ATYPE> &posOrthDir
01112 )
01113 {
01114 MinimumEdgeDistances<ATYPE> minDist(PG, m_sep);
01115
01116 node v;
01117 forall_nodes(v,PG)
01118 {
01119 if(PG.expandAdj(v) == 0) continue;
01120
01121 for(int d = 0; d < 4; ++d) {
01122 minDist.delta(v,OrthoDir(d),0) = m_sep;
01123 minDist.delta(v,OrthoDir(d),1) = m_sep;
01124 }
01125 }
01126
01127 insertVisibilityArcs(PG,posDir,posOrthDir,minDist);
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137 template<class ATYPE>
01138 void CompactionConstraintGraph<ATYPE>::insertVisibilityArcs(
01139 const PlanRep &PG,
01140 const NodeArray<ATYPE> &posDir,
01141 const NodeArray<ATYPE> &posOrthDir,
01142 const MinimumEdgeDistances<ATYPE> &minDist)
01143 {
01144 OrthoDir segDir = OrthoRep::prevDir(m_arcDir);
01145 OrthoDir segOppDir = OrthoRep::nextDir(m_arcDir);
01146
01147
01148 SListPure<Tuple2<node,node> > visibArcs;
01149
01150
01151 NodeArray<ATYPE> low(getGraph()), lowReal(getGraph()), high(getGraph());
01152 NodeArray<ATYPE> segPos(getGraph(), 0);
01153 NodeArray<int> topNum(getGraph());
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 node v;
01167 forall_nodes(v,*this) {
01168
01169
01170 if (m_path[v].empty()) continue;
01171
01172 SListConstIterator<node> it = m_path[v].begin();
01173
01174 segPos[v] = posDir[*it];
01175 low[v] = high[v] = posOrthDir[*it];
01176 node nodeLow = *it;
01177 for(++it; it.valid(); ++it) {
01178 ATYPE x = posOrthDir[*it];
01179 if (x < low [v]) {
01180 low [v] = x;
01181 nodeLow = *it;
01182 }
01183 if (x > high[v]) high[v] = x;
01184 }
01185 lowReal[v] = low[v];
01186 Graph::NodeType typeLow = PG.typeOf(nodeLow);
01187 if(typeLow == Graph::dummy || typeLow == Graph::generalizationExpander) {
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 low[v] -= m_sep;
01205 }
01206 }
01207
01208
01209 OrthoDir dirMin = OrthoRep::prevDir(m_arcDir);
01210 OrthoDir dirMax = OrthoRep::nextDir(m_arcDir);
01211 bool isCaseA = (m_arcDir == odEast || m_arcDir == odSouth);
01212 const int angleAtMin = (m_arcDir == odEast || m_arcDir == odSouth) ? 3 : 1;
01213 const int angleAtMax = (m_arcDir == odEast || m_arcDir == odSouth) ? 1 : 3;
01214 forall_nodes(v,PG)
01215 {
01216 if(PG.expandAdj(v) == 0) continue;
01217 const OrthoRep::VertexInfoUML &vi = *m_pOR->cageInfo(v);
01218
01219 int i = 0;
01220 adjEntry adj;
01221
01222 for (adj = (isCaseA) ? vi.m_corner[dirMin]->faceCycleSucc()->faceCycleSucc() : vi.m_corner[dirMin]->faceCycleSucc();
01223 m_pOR->direction((isCaseA) ? adj : adj->faceCycleSucc()) == dirMin;
01224 adj = adj->faceCycleSucc())
01225 {
01226 adjEntry adjCross = adj->cyclicPred();
01227 adjEntry adjTwin = adjCross->twin();
01228
01229 adjEntry adjPred = adj->faceCyclePred();
01230 ATYPE delta = (isCaseA) ?
01231 min(abs(posOrthDir[adjPred->theNode()] - posOrthDir[adjPred->twinNode()]), m_sep) :
01232 min(abs(posOrthDir[adj->theNode()] - posOrthDir[adj->twinNode()]), m_sep);
01233 ATYPE boundary = (isCaseA) ?
01234 min(posOrthDir[adjPred->theNode()], posOrthDir[adjPred->twinNode()]) :
01235 min(posOrthDir[adj->theNode()], posOrthDir[adj->twinNode()]);
01236
01237 if (PG.typeOf(adjCross->theEdge()) == Graph::generalization)
01238 {
01239 if (isCaseA) {
01240 if(PG.typeOf(adjTwin->theNode()) == Graph::generalizationExpander &&
01241 m_pOR->angle(adjTwin) == 2)
01242 {
01243 node s1 = m_pathNode[adjTwin->theNode()];
01244 node s2 = m_pathNode[adjTwin->cyclicSucc()->twinNode()];
01245 low[s1] = lowReal[s1] - delta;
01246 low[s2] = lowReal[s2] - delta;
01247 }
01248 ++i;
01249 } else {
01250 ++i;
01251 if(PG.typeOf(adjTwin->theNode()) == Graph::generalizationExpander &&
01252 m_pOR->angle(adjTwin->cyclicPred()) == 2)
01253 {
01254 node s1 = m_pathNode[adjTwin->theNode()];
01255 node s2 = m_pathNode[adjTwin->cyclicPred()->twinNode()];
01256 low[s1] = lowReal[s1] - delta;
01257 low[s2] = lowReal[s2] - delta;
01258 }
01259 }
01260 continue;
01261 }
01262
01263
01264 OrthoDir runDir = m_pOR->direction(adjCross);
01265
01266 while (PG.typeOf(adjTwin->theNode()) == Graph::dummy &&
01267 adjTwin->theNode()->degree() == 2 &&
01268 m_pOR->angle(adjTwin) == angleAtMin)
01269 {
01270
01271
01272 node s = m_edgeToBasicArc[adjCross]->source();
01273 if(lowReal[s] != low[s])
01274 {
01275 if(low[s] >= boundary)
01276 break;
01277 low[s] = boundary;
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287 for( ; ; ) {
01288 do {
01289 adjCross = adjCross->faceCycleSucc();
01290 } while(m_pOR->direction(adjCross) == segDir ||
01291 m_pOR->direction(adjCross) == segOppDir);
01292
01293 if(adjCross->theNode()->degree() != 2)
01294 break;
01295
01296 node sNext = m_edgeToBasicArc[adjCross]->opposite(s);
01297
01298 if(segPos[sNext] != segPos[s])
01299 break;
01300
01301 low[sNext] = lowReal[sNext];
01302 s = sNext;
01303 }
01304 }
01305
01306 adjTwin = adjCross->twin();
01307
01308 if (runDir != m_pOR->direction(adjCross)) break;
01309 }
01310 }
01311
01312 i = 0;
01313 for (adj = (isCaseA) ? vi.m_corner[dirMax]->faceCycleSucc() : vi.m_corner[dirMax]->faceCycleSucc()->faceCycleSucc();
01314 m_pOR->direction((isCaseA) ? adj->faceCycleSucc() : adj) == dirMax;
01315 adj = adj->faceCycleSucc())
01316 {
01317 adjEntry adjCross = adj->cyclicPred();
01318 adjEntry adjTwin = adjCross->twin();
01319
01320
01321 adjEntry adjPred = adj->faceCyclePred();
01322 ATYPE delta = (isCaseA) ?
01323 min(abs(posOrthDir[adj->twinNode()] - posOrthDir[adj->theNode()]), m_sep) :
01324 min(abs(posOrthDir[adjPred->theNode()] - posOrthDir[adjPred->twinNode()]), m_sep);
01325 ATYPE boundary = (isCaseA) ?
01326 min(posOrthDir[adj->twinNode()], posOrthDir[adj->theNode()]) :
01327 min(posOrthDir[adjPred->theNode()], posOrthDir[adjPred->twinNode()]);
01328
01329 if (PG.typeOf(adjCross->theEdge()) == Graph::generalization)
01330 {
01331 if (isCaseA) {
01332 ++i;
01333 if(PG.typeOf(adjTwin->theNode()) == Graph::generalizationExpander &&
01334 m_pOR->angle(adjTwin->cyclicPred()) == 2)
01335 {
01336 node s1 = m_pathNode[adjTwin->theNode()];
01337 node s2 = m_pathNode[adjTwin->cyclicPred()->twinNode()];
01338 low[s1] = lowReal[s1] - delta;
01339 low[s2] = lowReal[s2] - delta;
01340 }
01341 } else {
01342 if(PG.typeOf(adjTwin->theNode()) == Graph::generalizationExpander &&
01343 m_pOR->angle(adjTwin) == 2)
01344 {
01345 node s1 = m_pathNode[adjTwin->theNode()];
01346 node s2 = m_pathNode[adjTwin->cyclicSucc()->twinNode()];
01347 low[s1] = lowReal[s1] - delta;
01348 low[s2] = lowReal[s2] - delta;
01349 }
01350 ++i;
01351 }
01352 continue;
01353 }
01354
01355
01356
01357 OrthoDir runDir = m_pOR->direction(adjCross);
01358
01359 while (PG.typeOf(adjTwin->theNode()) == Graph::dummy &&
01360 adjTwin->theNode()->degree() == 2 &&
01361 m_pOR->angle(adjTwin) == angleAtMax)
01362 {
01363 node s = m_edgeToBasicArc[adjCross]->target();
01364 if(lowReal[s] != low[s])
01365 {
01366 if(low[s] >= boundary)
01367 break;
01368 low[s] = boundary;
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 for( ; ; )
01379 {
01380 do
01381 {
01382 adjCross = adjCross->faceCycleSucc();
01383 } while(m_pOR->direction(adjCross) == segDir ||
01384 m_pOR->direction(adjCross) == segOppDir);
01385
01386 if(adjCross->theNode()->degree() != 2)
01387 break;
01388
01389 node sNext = m_edgeToBasicArc[adjCross]->opposite(s);
01390
01391 if(segPos[sNext] != segPos[s])
01392 break;
01393
01394 low[sNext] = lowReal[sNext];
01395 s = sNext;
01396 }
01397 }
01398
01399 adjTwin = adjCross->twin();
01400
01401
01402 if (runDir != m_pOR->direction(adjCross)) break;
01403 }
01404 }
01405 }
01406
01407
01408
01409
01410 computeTopologicalSegmentNum(topNum);
01411
01412
01413
01414 SegmentComparer cmpBySegPos(segPos,topNum);
01415 List<node> sortedPathNodes;
01416 allNodes(sortedPathNodes);
01417 sortedPathNodes.quicksort(cmpBySegPos);
01418
01419
01420 List<Interval> sweepLine;
01421
01422 ListIterator<node> itV;
01423 for(itV = sortedPathNodes.begin(); itV.valid(); ++itV)
01424 {
01425
01426 if (m_path[*itV].empty()) continue;
01427 OGDF_ASSERT_IF(dlExtendedChecking,checkSweepLine(sweepLine));
01428
01429 node v = *itV;
01430 ListIterator<Interval> it;
01431 for(it = sweepLine.begin(); it.valid(); ++it) {
01432 if ((*it).m_low < high[v])
01433 break;
01434 }
01435
01436 if (!it.valid()) {
01437 sweepLine.pushBack(Interval(v,low[v],high[v]));
01438 continue;
01439 }
01440
01441 if((*it).m_high <= low[v]) {
01442 sweepLine.insertBefore(Interval(v,low[v],high[v]),it);
01443 continue;
01444 }
01445
01446 ListIterator<Interval> itUp = it, itSucc;
01447
01448
01449 bool isItUpDel = ( ((*itUp).m_low >= low[v]) && ((*itUp).m_high <= high[v]) );
01450
01451 for(; it.valid() && (*it).m_low >= low[v]; it = itSucc) {
01452 itSucc = it.succ();
01453 if ((*it).m_high <= high[v]) {
01454 visibArcs.pushBack(Tuple2<node,node>((*it).m_pathNode,v));
01455 sweepLine.del(it);
01456 }
01457 }
01458
01459 if (it == itUp && (*it).m_high > high[v]) {
01460 node w = (*it).m_pathNode;
01461 sweepLine.insertAfter(Interval(w,(*it).m_low,low[v]),it);
01462 (*it).m_low = high[v];
01463 sweepLine.insertAfter(Interval(v,low[v],high[v]),it);
01464 visibArcs.pushBack(Tuple2<node,node>(w,v));
01465
01466 } else {
01467 if ( (!isItUpDel) && itUp != it && (*itUp).m_low < high[v]) {
01468 (*itUp).m_low = high[v];
01469 visibArcs.pushBack(Tuple2<node,node>((*itUp).m_pathNode,v));
01470 }
01471 if (it.valid()) {
01472 if ((*it).m_high > low[v]) {
01473 (*it).m_high = low[v];
01474 visibArcs.pushBack(Tuple2<node,node>((*it).m_pathNode,v));
01475 }
01476 sweepLine.insertBefore(Interval(v,low[v],high[v]),it);
01477
01478 } else {
01479 sweepLine.pushBack(Interval(v,low[v],high[v]));
01480 }
01481 }
01482
01483 }
01484
01485
01486 removeRedundantVisibArcs(visibArcs);
01487
01488
01489
01490
01491
01492
01493 NodeArray<adjEntry> correspEdge(getGraph(),0);
01494 forall_nodes(v,PG) {
01495 node seg = m_pathNode[v];
01496 adjEntry adj;
01497 forall_adj(adj,v) {
01498 if(m_pOR->direction(adj) != segDir) continue;
01499 edge eAdj = adj->theEdge();
01500 edge eOrig = PG.original(eAdj);
01501 if (eOrig == 0) continue;
01502 if (adj == eAdj->adjSource())
01503 correspEdge[seg] = eOrig->adjSource();
01504 else
01505 correspEdge[seg] = eOrig->adjTarget();
01506 }
01507 }
01508
01509
01510 SListIterator<Tuple2<node,node> > itT, itTSucc, itTPred;
01511 for(itT = visibArcs.begin(); itT.valid(); itT = itTSucc) {
01512 itTSucc = itT.succ();
01513 node v = (*itT).x1(), w = (*itT).x2();
01514
01515
01516 if (correspEdge[v] && (correspEdge[v] == correspEdge[w]))
01517 {
01518 if (itTPred.valid())
01519 visibArcs.delSucc(itTPred);
01520 else
01521 visibArcs.popFront();
01522 }
01523
01524 else
01525 itTPred = itT;
01526 }
01527
01528
01529
01530 for(itT = visibArcs.begin(); itT.valid(); ++itT) {
01531
01532 node v = (*itT).x1(), w = (*itT).x2();
01533 if (!(m_extraNode[v] || m_extraNode[w]))
01534 {
01535
01536 node boundRepresentant1 = m_path[v].front();
01537 node boundRepresentant2 = m_path[w].front();
01538 node en1 = m_pPR->expandedNode(boundRepresentant1);
01539 node en2 = m_pPR->expandedNode(boundRepresentant2);
01540
01541 if (!( ( en1 && en2 ) && ( en1 == en2) ))
01542 {
01543 edge e = newEdge(v,w);
01544
01545
01546
01547 m_length[e] = max(m_sep, minDist.separation());
01548 m_cost [e] = 0;
01549 m_type [e] = cetVisibilityArc;
01550
01551
01552 }
01553 }
01554 }
01555
01556 OGDF_ASSERT_IF(dlExtendedChecking,checkSweepLine(sweepLine));
01557
01558 }
01559
01560
01561
01562
01563
01564
01565 template<class ATYPE>
01566 bool CompactionConstraintGraph<ATYPE>::isFeasible(
01567 const NodeArray<ATYPE> &pos)
01568 {
01569 edge e;
01570 forall_edges(e, getGraph()) {
01571 node v = m_path[e->source()].front();
01572 node w = m_path[e->target()].front();;
01573 if (pos[w] - pos[v] < length(e)) {
01574 cout << "feasibility check failed for edge " << e << endl;
01575 cout << " representatives: " << v << ", " << w << endl;
01576 cout << " length: " << length(e) << endl;
01577 cout << " actual distance: " << pos[w] - pos[v] << endl;
01578 cout << " type of " << e << ": ";
01579 switch(m_type[e]) {
01580 case cetBasicArc: cout << "basic arc" << endl;
01581 break;
01582 case cetVertexSizeArc: cout << "vertex-size arc" << endl;
01583 break;
01584 case cetVisibilityArc: cout << "visibility arc" << endl;
01585 break;
01586 case cetMedianArc: cout << "median arc" << endl;
01587 break;
01588 case cetReducibleArc: cout << "reducible arc" <<endl;
01589 break;
01590 case cetFixToZeroArc: cout << "fixtozero arc" <<endl;
01591
01592 }
01593 return false;
01594 }
01595 }
01596
01597 return true;
01598 }
01599
01600
01601 template<class ATYPE>
01602 void CompactionConstraintGraph<ATYPE>::writeGML(const char *filename) const
01603 {
01604 ofstream os(filename);
01605 writeGML(os);
01606 }
01607
01608 template<class ATYPE>
01609 void CompactionConstraintGraph<ATYPE>::writeGML(ostream &os) const
01610 {
01611 const Graph &G = *this;
01612
01613 NodeArray<int> id(getGraph());
01614 int nextId = 0;
01615
01616 os.setf(ios::showpoint);
01617 os.precision(10);
01618
01619 os << "Creator \"ogdf::CompactionConstraintGraphBase::writeGML\"\n";
01620 os << "directed 1\n";
01621
01622 os << "graph [\n";
01623
01624 node v;
01625 forall_nodes(v,G) {
01626 os << "node [\n";
01627
01628 os << "id " << (id[v] = nextId++) << "\n";
01629
01630 if (m_extraNode[v])
01631 {
01632 os << "label \"" << "0" << "\"\n";
01633 }
01634 else
01635 {
01636 os << "label \"" << m_pPR->expandedNode(m_path[v].front()) << "\"\n";
01637 }
01638
01639 os << "graphics [\n";
01640 os << "x 0.0\n";
01641 os << "y 0.0\n";
01642 os << "w 30.0\n";
01643 os << "h 30.0\n";
01644 if (m_extraNode[v])
01645 os << "fill \"#00FFFF\"\n";
01646 else
01647 os << "fill \"#FFFF00\"\n";
01648 os << "]\n";
01649
01650 os << "]\n";
01651 }
01652
01653
01654 edge e;
01655 forall_edges(e,G) {
01656 os << "edge [\n";
01657
01658 os << "source " << id[e->source()] << "\n";
01659 os << "target " << id[e->target()] << "\n";
01660
01661
01662
01663
01664
01665
01666
01667
01668 os << "graphics [\n";
01669
01670 os << "type \"line\"\n";
01671 os << "arrow \"last\"\n";
01672 switch(m_type[e])
01673 {
01674 case cetBasicArc:
01675 os << "fill \"#FF0000\"\n";
01676 break;
01677 case cetVertexSizeArc:
01678 os << "fill \"#0000FF\"\n";
01679 break;
01680 case cetVisibilityArc:
01681 os << "fill \"#00FF00\"\n";
01682 break;
01683 case cetReducibleArc:
01684 os << "fill \"#FF0000\"\n";
01685 break;
01686 case cetFixToZeroArc:
01687 os << "fill \"#AF00FF\"\n";
01688 break;
01689 case cetMedianArc:
01690 os << "fill \"#FF00FF\"\n";
01691 break;
01692 }
01693
01694 os << "]\n";
01695
01696
01697
01698
01699
01700
01701
01702 os << "]\n";
01703 }
01704
01705 os << "]\n";
01706 }
01707
01708
01709 }
01710
01711
01712 #endif