Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
compound_constraints.cpp
Go to the documentation of this file.
1/*
2 * vim: ts=4 sw=4 et tw=0 wm=0
3 *
4 * libcola - A library providing force-directed network layout using the
5 * stress-majorization method subject to separation constraints.
6 *
7 * Copyright (C) 2006-2008 Monash University
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 * See the file LICENSE.LGPL distributed with the library.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * Author(s): Tim Dwyer
20 * Michael Wybrow
21*/
22
23#include <algorithm>
24#include <climits>
25#include <sstream>
26
27#include <libvpsc/variable.h>
28#include <libvpsc/constraint.h>
29#include <libvpsc/assertions.h>
30
31#include "libcola/cola.h"
33#include "libcola/exceptions.h"
34
35using std::vector;
36using vpsc::XDIM;
37using vpsc::YDIM;
38
39namespace cola {
40
42 const VariableIDMap& idMap, bool forward)
43{
44 varIndex = idMap.mappingForVariable(varIndex, forward);
45}
46
47//-----------------------------------------------------------------------------
48// BoundaryConstraint code
49//-----------------------------------------------------------------------------
50
51class Offset : public SubConstraintInfo
52{
53 public:
54 Offset(unsigned ind, double offset) :
56 distOffset(offset)
57 {
58 }
59 double distOffset;
60};
61
62
64 : CompoundConstraint(dim),
65 position(0),
66 variable(nullptr)
67{
68}
69
70
72{
73 if (dim == _primaryDim)
74 {
76 }
77}
78
79
80void BoundaryConstraint::addShape(const unsigned int index,
81 const double offset)
82{
83 _subConstraintInfo.push_back(new Offset(index, offset));
84}
85
86
88{
89 fprintf(fp, " BoundaryConstraint *boundary%llu = "
90 "new BoundaryConstraint(vpsc::%cDIM);\n",
91 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y');
92 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
93 o != _subConstraintInfo.end(); ++o)
94 {
95 Offset *info = static_cast<Offset *> (*o);
96 fprintf(fp, " boundary%llu->addShape(%u, %g);\n",
97 (unsigned long long) this, info->varIndex, info->distOffset);
98 }
99 fprintf(fp, " ccs.push_back(boundary%llu);\n\n",
100 (unsigned long long) this);
101}
102
103
104std::string BoundaryConstraint::toString(void) const
105{
106 std::ostringstream stream;
107 stream << "BoundaryConstraint(";
108 stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
109 stream << "): {";
110 bool first = true;
111 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
112 o != _subConstraintInfo.end(); ++o)
113 {
114 Offset *info = static_cast<Offset *> (*o);
115 if (!first)
116 {
117 stream << ", ";
118 }
119 stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")";
120 first = false;
121 }
122 stream << "}";
123 return stream.str();
124}
125
126
128 vpsc::Variables& vars)
129{
130 if (dim == _primaryDim)
131 {
132 // Just one variable is generated, associated with the position
133 // of the boundary. This variable can float freely.
134 variable = new vpsc::Variable(vars.size(), position, freeWeight);
135 vars.push_back(variable);
136 }
137}
138
139
142 vpsc::Rectangles& bbs)
143{
144 COLA_UNUSED(bbs);
145 if (dim == _primaryDim)
146 {
147 COLA_ASSERT(variable != nullptr);
148 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
149 o != _subConstraintInfo.end(); ++o)
150 {
151 Offset *info = static_cast<Offset *> (*o);
152 assertValidVariableIndex(vars, info->varIndex);
153 vpsc::Constraint *constraint = nullptr;
154 if (info->distOffset < 0)
155 {
156 // Constrain the objects with negative offsets to be
157 // to the left of the boundary.
158 constraint = new vpsc::Constraint(vars[info->varIndex],
159 variable, -info->distOffset);
160 }
161 else
162 {
163 // Constrain the objects with positive offsets to be
164 // to the right of the boundary.
165 constraint = new vpsc::Constraint(variable,
166 vars[info->varIndex], info->distOffset);
167 }
168 constraint->creator = this;
169 cs.push_back(constraint);
170 }
171 }
172}
173
174
177{
178 SubConstraintAlternatives alternatives;
179
180 Offset *info = static_cast<Offset *>
182
183 assertValidVariableIndex(vs[_primaryDim], info->varIndex);
184 if (info->distOffset < 0)
185 {
186 // Constrain the objects with negative offsets to be
187 // to the left of the boundary.
189 vs[_primaryDim][info->varIndex], variable, -info->distOffset);
190 alternatives.push_back(SubConstraint(_primaryDim, constraint));
191 }
192 else
193 {
194 // Constrain the objects with positive offsets to be
195 // to the right of the boundary.
197 variable, vs[_primaryDim][info->varIndex], info->distOffset);
198 alternatives.push_back(SubConstraint(_primaryDim, constraint));
199 }
200
201 //fprintf(stderr, "===== BOUNDARYLINE ALTERNATIVES -======\n");
202 return alternatives;
203}
204
205
206
207//-----------------------------------------------------------------------------
208// AlignmentConstraint code
209//-----------------------------------------------------------------------------
210
212 : CompoundConstraint(dim),
213 indicator(nullptr),
214 variable(nullptr),
215 _position(position),
216 _isFixed(false)
217{
218}
219
220
221void AlignmentConstraint::addShape(const unsigned int index,
222 const double offset)
223{
224 _subConstraintInfo.push_back(new Offset(index, offset));
225}
226
227
229{
230 if (dim == _primaryDim)
231 {
233 }
234}
235
236
238{
239 _position = pos;
240 _isFixed = true;
241}
242
243
245{
246 _isFixed = false;
247}
248
249
251{
252 return _position;
253}
254
256{
257 return _isFixed;
258}
259
261 vpsc::Variables& vars)
262{
263 if (dim == _primaryDim)
264 {
265 // Variable representing the position of a guideline.
266 variable = new vpsc::Variable(vars.size(), _position, freeWeight);
267 if (_isFixed)
268 {
270 variable->weight = 100000;
271 }
272 vars.push_back(variable);
273 }
274}
275
276
279 vpsc::Rectangles& bbs)
280{
281 COLA_UNUSED(bbs);
282 if (dim == _primaryDim)
283 {
284 COLA_ASSERT(variable != nullptr);
285 // Constrain each object to be offset from the guideline by
286 // some exact amount.
287 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
288 o != _subConstraintInfo.end(); ++o)
289 {
290 Offset *info = static_cast<Offset *> (*o);
291 assertValidVariableIndex(vars, info->varIndex);
292 vpsc::Constraint *constraint = new vpsc::Constraint(
293 variable, vars[info->varIndex], info->distOffset, true);
294 constraint->creator = this;
295 cs.push_back(constraint);
296 }
297 }
298}
299
301 const std::vector<double>& offsets, bool forward)
302{
303 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
304 o != _subConstraintInfo.end(); ++o)
305 {
306 Offset *info = static_cast<Offset *> (*o);
307 if (offsets[info->varIndex] == 0)
308 {
309 continue;
310 }
311
312 if (forward)
313 {
314 info->distOffset -= offsets[info->varIndex];
315 }
316 else
317 {
318 info->distOffset += offsets[info->varIndex];
319 }
320 }
321}
322
324{
325 fprintf(fp, " AlignmentConstraint *alignment%llu = "
326 "new AlignmentConstraint(vpsc::%cDIM, %g);\n",
327 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
328 _position);
329 if (_isFixed)
330 {
331 fprintf(fp, " alignment%llu->fixPos(%g);\n",
332 (unsigned long long) this, _position);
333 }
334 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
335 o != _subConstraintInfo.end(); ++o)
336 {
337 Offset *info = static_cast<Offset *> (*o);
338 fprintf(fp, " alignment%llu->addShape(%u, %g);\n",
339 (unsigned long long) this, info->varIndex, info->distOffset);
340 }
341 fprintf(fp, " ccs.push_back(alignment%llu);\n\n",
342 (unsigned long long) this);
343}
344
345
346std::string AlignmentConstraint::toString(void) const
347{
348 std::ostringstream stream;
349 stream << "AlignmentConstraint(";
350 stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
351 stream << ", pos: " << _position;
352 if (_isFixed)
353 {
354 stream << ", fixed: true";
355 }
356#if 0
357 // TODO: buggy. Not the right value.
358 if (variable)
359 {
360 stream << ", varInd: " << variable->id;
361 }
362#endif
363 stream << "): {";
364 bool first = true;
365 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
366 o != _subConstraintInfo.end(); ++o)
367 {
368 Offset *info = static_cast<Offset *> (*o);
369 if (!first)
370 {
371 stream << ", ";
372 }
373 stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")";
374 first = false;
375 }
376 stream << "}";
377 return stream.str();
378}
379
380
383{
384 SubConstraintAlternatives alternatives;
385
386 Offset *info = static_cast<Offset *>
388
389 assertValidVariableIndex(vs[_primaryDim], info->varIndex);
390 vpsc::Constraint constraint(variable, vs[_primaryDim][info->varIndex],
391 info->distOffset, true);
392 alternatives.push_back(SubConstraint(_primaryDim, constraint));
393
394 //fprintf(stderr, "===== ALIGN ALTERNATIVES -======\n");
395 return alternatives;
396}
397
398
399//-----------------------------------------------------------------------------
400// SeparationConstraint code
401//-----------------------------------------------------------------------------
402
403
404class VarIndexPair : public SubConstraintInfo
405{
406 public:
407 VarIndexPair(unsigned ind1, unsigned ind2)
408 : SubConstraintInfo(ind1),
409 lConstraint(nullptr),
410 rConstraint(nullptr),
411 varIndex2(ind2)
412 {
413 }
414 VarIndexPair(AlignmentConstraint *l, AlignmentConstraint *r)
415 : SubConstraintInfo(0),
416 lConstraint(l),
417 rConstraint(r),
418 varIndex2(0)
419 {
420 }
421 unsigned indexL(void) const
422 {
423 return (lConstraint) ?
424 (unsigned) lConstraint->variable->id : varIndex;
425 }
426 unsigned indexR(void) const
427 {
428 return (rConstraint) ?
429 (unsigned) rConstraint->variable->id : varIndex2;
430 }
431 void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward)
432 {
433 varIndex = idMap.mappingForVariable(varIndex, forward);
434 varIndex2 = idMap.mappingForVariable(varIndex2, forward);
435 }
436
437 AlignmentConstraint *lConstraint;
438 AlignmentConstraint *rConstraint;
439 unsigned varIndex2;
440};
441
442
444 unsigned l, unsigned r, double g, bool equality)
445 : CompoundConstraint(dim),
446 gap(g),
447 equality(equality),
448 vpscConstraint(nullptr)
449{
450 _subConstraintInfo.push_back(new VarIndexPair(l, r));
451}
452
453
456 bool equality)
457 : CompoundConstraint(dim),
458 gap(g),
459 equality(equality)
460{
461 COLA_ASSERT(l);
462 COLA_ASSERT(r);
463
464 _subConstraintInfo.push_back(new VarIndexPair(l, r));
465}
466
467
469{
470 assert(_subConstraintInfo.size() == 1);
471 VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front();
472 if (varIndexPair->lConstraint && varIndexPair->rConstraint)
473 {
474 fprintf(fp, " SeparationConstraint *separation%llu = "
475 "new SeparationConstraint(vpsc::%cDIM, alignment%llu, "
476 "alignment%llu, %g, %s);\n",
477 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
478 (unsigned long long) varIndexPair->lConstraint,
479 (unsigned long long) varIndexPair->rConstraint, gap,
480 (equality) ? "true" : "false");
481 }
482 else
483 {
484 fprintf(fp, " SeparationConstraint *separation%llu = "
485 "new SeparationConstraint(vpsc::%cDIM, %u, %u, %g, %s);\n",
486 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
487 varIndexPair->indexL(), varIndexPair->indexR(), gap,
488 (equality) ? "true" : "false");
489 }
490 fprintf(fp, " ccs.push_back(separation%llu);\n\n",
491 (unsigned long long) this);
492}
493
494
495std::string SeparationConstraint::toString(void) const
496{
497 std::ostringstream stream;
498 stream << "SeparationConstraint(";
499 stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
500 stream << ", sep: " << gap;
501 stream << ", equality: " << ((equality) ? "true" : "false");
502 stream << "): {";
503 VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front();
504 if (varIndexPair->lConstraint && varIndexPair->rConstraint)
505 {
506 stream << "(alignment: " << varIndexPair->indexL() << "), ";
507 stream << "(alignment: " << varIndexPair->indexR() << "), ";
508 }
509 else
510 {
511 stream << "(rect: " << varIndexPair->indexL() << "), ";
512 stream << "(rect: " << varIndexPair->indexR() << "), ";
513 }
514 stream << "}";
515 return stream.str();
516}
517
518
520 vpsc::Variables& vars)
521{
522 COLA_UNUSED(dim);
523 COLA_UNUSED(vars);
524
525 // No additional variables are required!
526}
527
528
531{
532 SubConstraintAlternatives alternatives;
533
534 VarIndexPair *info = static_cast<VarIndexPair *>
536
537 assertValidVariableIndex(vs[_primaryDim], info->indexL());
538 assertValidVariableIndex(vs[_primaryDim], info->indexR());
539 vpsc::Constraint constraint(vs[_primaryDim][info->indexL()],
540 vs[_primaryDim][info->indexR()], gap, equality);
541 alternatives.push_back(SubConstraint(_primaryDim, constraint));
542
543 //fprintf(stderr, "===== SEPARATION ALTERNATIVES -======\n");
544 return alternatives;
545}
546
547
550 vpsc::Rectangles& bbs)
551{
552 COLA_UNUSED(bbs);
553 if (dim == _primaryDim)
554 {
555 VarIndexPair *info =
556 static_cast<VarIndexPair *> (_subConstraintInfo.front());
557
558 unsigned left = info->indexL();
559 unsigned right = info->indexR();
563 new vpsc::Constraint(vs[left], vs[right], gap, equality);
564 vpscConstraint->creator = this;
565 cs.push_back(vpscConstraint);
566 }
567}
568
569
570unsigned SeparationConstraint::left(void) const
571{
572 VarIndexPair *info =
573 static_cast<VarIndexPair *> (_subConstraintInfo.front());
574
575 return info->indexL();
576}
577
578
579unsigned SeparationConstraint::right(void) const
580{
581 VarIndexPair *info =
582 static_cast<VarIndexPair *> (_subConstraintInfo.front());
583
584 return info->indexR();
585}
586
587
589{
590 this->gap = gap;
591 if (vpscConstraint != nullptr)
592 {
594 }
595}
596
597
598//-----------------------------------------------------------------------------
599// OrthogonalEdgeConstraint code
600//-----------------------------------------------------------------------------
601
603 unsigned l, unsigned r)
604 : CompoundConstraint(dim),
605 left(l),
606 right(r),
607 vpscConstraint(nullptr)
608{
609}
610
611
613 vpsc::Variables& vars)
614{
615 COLA_UNUSED(dim);
616 COLA_UNUSED(vars);
617
618 // No additional variables are required!
619}
620
621
623{
624 fprintf(fp, " /* OrthogonalEdgeConstraint *orthogonal%llu = nullptr; */\n\n",
625 (unsigned long long) this);
626}
627
628
630{
631 std::ostringstream stream;
632 stream << "OrthogonalEdgeConstraint()";
633 return stream.str();
634}
635
636
637
640 vpsc::Variables vs[])
641{
642 COLA_UNUSED(vs);
643
644 // XXX: What to do here?
647}
648
649
651 const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
652 vpsc::Rectangles& bbs)
653{
654 COLA_UNUSED(bbs);
655 if (dim == _primaryDim)
656 {
659 vpscConstraint = new vpsc::Constraint(vs[left], vs[right], 0, true);
660 vpscConstraint->creator = this;
661 cs.push_back(vpscConstraint);
662 }
663}
664
665
667 const vpsc::Rectangles& rs, vector<vpsc::Variable*> const & vars,
668 vector<vpsc::Constraint*> & cs)
669{
672 double lBound, rBound, pos;
673 if (k == vpsc::HORIZONTAL)
674 {
675 lBound = rs[left]->getCentreY();
676 rBound = rs[right]->getCentreY();
677 pos = rs[left]->getCentreX();
678 }
679 else
680 {
681 lBound = rs[left]->getCentreX();
682 rBound = rs[right]->getCentreX();
683 pos = rs[left]->getCentreY();
684 }
685 double minBound = std::min(lBound, rBound);
686 double maxBound = std::max(lBound, rBound);
687 for (unsigned i = 0; i < rs.size(); ++i)
688 {
689 if (i==left || i==right) continue;
690 vpsc::Rectangle *r = rs[i];
691 if (r->allowOverlap()) continue;
692 double l, rMin, rMax, rCentre;
693 rectBounds(k, r, rMin, rMax, rCentre, l);
694 if ( ((rMin >= minBound) && (rMin <= maxBound)) ||
695 ((rMax >= minBound) && (rMax <= maxBound)))
696 {
697 double g = l / 2;
698 if (rCentre < pos)
699 {
700 cs.push_back(new vpsc::Constraint(vars[i], vars[left], g));
701 }
702 else
703 {
704 cs.push_back(new vpsc::Constraint(vars[left], vars[i], g));
705 }
706 }
707 }
708}
709
710
712 vpsc::Rectangle const *r, double& cmin, double& cmax,
713 double& centre, double & l) const
714{
715 if (k == vpsc::HORIZONTAL)
716 {
717 cmin = r->getMinY();
718 cmax = r->getMaxY();
719 centre = r->getCentreX();
720 l = r->width();
721 }
722 else
723 {
724 cmin = r->getMinX();
725 cmax = r->getMaxX();
726 centre = r->getCentreY();
727 l = r->height();
728 }
729}
730
731
732//-----------------------------------------------------------------------------
733// MultiSeparationConstraint code
734//-----------------------------------------------------------------------------
735
736class AlignmentPair : public SubConstraintInfo
737{
738 public:
739 AlignmentPair(AlignmentConstraint *ac1, AlignmentConstraint *ac2)
741 alignment1(ac1),
742 alignment2(ac2)
743 {
744 }
745 AlignmentConstraint *alignment1;
746 AlignmentConstraint *alignment2;
747};
748
749
751 double minSep, bool equality)
752 : CompoundConstraint(dim),
753 indicator(nullptr),
754 sep(minSep),
755 equality(equality)
756{
757}
758
759
762{
763 _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2));
764}
765
766
768{
769 fprintf(fp, " MultiSeparationConstraint *multiSep%llu = "
770 "new MultiSeparationConstraint(vpsc::%cDIM, %g, %s);\n",
771 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', sep,
772 (equality) ? "true" : "false");
773 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
774 o != _subConstraintInfo.end(); ++o)
775 {
776 AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
777 fprintf(fp, " multiSep%llu->addAlignmentPair("
778 "alignment%llu, alignment%llu);\n",
779 (unsigned long long) this,
780 (unsigned long long) pair->alignment1,
781 (unsigned long long) pair->alignment2);
782 }
783 fprintf(fp, " ccs.push_back(multiSep%llu);\n\n",
784 (unsigned long long) this);
785}
786
787
789{
790 std::ostringstream stream;
791 stream << "MultiSeparationConstraint(";
792 stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
793 stream << ", sep: " << sep;
794 stream << ", equality: " << ((equality) ? "true" : "false");
795 stream << "): {";
796 bool first = true;
797 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
798 o != _subConstraintInfo.end(); ++o)
799 {
800 if (!first)
801 {
802 stream << ", ";
803 }
804 AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
805 stream << "(alignment: " << pair->alignment1->variable->id
806 << ", alignment: " << pair->alignment2->variable->id << ")";
807 first = false;
808 }
809 stream << "}";
810 return stream.str();
811}
812
813
815 vpsc::Variables& vars)
816{
817 COLA_UNUSED(dim);
818 COLA_UNUSED(vars);
819
820 // No additional variables are required!
821}
822
823
826 vpsc::Variables vs[])
827{
828 COLA_UNUSED(vs);
829
830 SubConstraintAlternatives alternatives;
831
832 AlignmentPair *info = static_cast<AlignmentPair *>
834
835 AlignmentConstraint *c1 = info->alignment1;
836 AlignmentConstraint *c2 = info->alignment2;
837 if (!c1->variable || !c2->variable)
838 {
839 throw InvalidConstraint(this);
840 }
841 vpsc::Constraint constraint(c1->variable, c2->variable, sep, equality);
842 alternatives.push_back(SubConstraint(_primaryDim, constraint));
843
844 //fprintf(stderr, "===== MULTI SEPARATION ALTERNATIVES -======\n");
845 return alternatives;
846}
847
848
850{
851 this->sep = sep;
852}
853
854
856 const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& gcs,
857 vpsc::Rectangles& bbs)
858{
859 COLA_UNUSED(vs);
860 COLA_UNUSED(bbs);
861
862 if (dim == _primaryDim)
863 {
864 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
865 o != _subConstraintInfo.end(); ++o)
866 {
867 AlignmentPair *info = static_cast<AlignmentPair *> (*o);
868 AlignmentConstraint *c1 = info->alignment1;
869 AlignmentConstraint *c2 = info->alignment2;
870 if (!c1->variable || !c2->variable)
871 {
872 throw InvalidConstraint(this);
873 }
875 c1->variable, c2->variable, sep, equality);
876 c->creator = this;
877 gcs.push_back(c);
878 cs.push_back(c);
879 }
880 }
881}
882
883
884//-----------------------------------------------------------------------------
885// DistributionConstraint code
886//-----------------------------------------------------------------------------
887
889 : CompoundConstraint(dim),
890 indicator(nullptr)
891{
892}
893
894
897{
898 _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2));
899}
900
901
903 vpsc::Variables& vars)
904{
905 COLA_UNUSED(dim);
906 COLA_UNUSED(vars);
907
908 // No additional variables are required!
909}
910
911
913{
914 this->sep = sep;
915}
916
917
919{
920 fprintf(fp, " DistributionConstraint *distribution%llu = "
921 "new DistributionConstraint(vpsc::%cDIM);\n",
922 (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y');
923 fprintf(fp, " distribution%llu->setSeparation(%g);\n",
924 (unsigned long long) this, sep);
925 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
926 o != _subConstraintInfo.end(); ++o)
927 {
928 AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
929 fprintf(fp, " distribution%llu->addAlignmentPair("
930 "alignment%llu, alignment%llu);\n",
931 (unsigned long long) this,
932 (unsigned long long) pair->alignment1,
933 (unsigned long long) pair->alignment2);
934 }
935 fprintf(fp, " ccs.push_back(distribution%llu);\n\n",
936 (unsigned long long) this);
937}
938
939
940std::string DistributionConstraint::toString(void) const
941{
942 std::ostringstream stream;
943 stream << "DistributionConstraint(";
944 stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
945 stream << ", sep: " << sep;
946 stream << "): {";
947 bool first = true;
948 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
949 o != _subConstraintInfo.end(); ++o)
950 {
951 if (!first)
952 {
953 stream << ", ";
954 }
955 AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
956 stream << "(alignment: " << pair->alignment1->variable->id
957 << ", alignment: " << pair->alignment2->variable->id << ")";
958 first = false;
959 }
960 stream << "}";
961 return stream.str();
962}
963
964
967{
968 COLA_UNUSED(vs);
969
970 SubConstraintAlternatives alternatives;
971
972 AlignmentPair *info = static_cast<AlignmentPair *>
974 AlignmentConstraint *c1 = info->alignment1;
975 AlignmentConstraint *c2 = info->alignment2;
976 if (!c1->variable || !c2->variable)
977 {
978 throw InvalidConstraint(this);
979 }
980 vpsc::Constraint constraint(c1->variable, c2->variable, sep, true);
981 alternatives.push_back(SubConstraint(_primaryDim, constraint));
982
983 //fprintf(stderr, "===== DISTRIBUTION ALTERNATIVES -======\n");
984 return alternatives;
985}
986
987
989 const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& gcs,
990 vpsc::Rectangles& bbs)
991{
992 COLA_UNUSED(vars);
993 COLA_UNUSED(bbs);
994
995 if (dim == _primaryDim)
996 {
997 cs.clear();
998 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
999 o != _subConstraintInfo.end(); ++o)
1000 {
1001 AlignmentPair *info = static_cast<AlignmentPair *> (*o);
1002 AlignmentConstraint *c1 = info->alignment1;
1003 AlignmentConstraint *c2 = info->alignment2;
1004 if (!c1->variable || !c2->variable)
1005 {
1006 throw InvalidConstraint(this);
1007 }
1009 c1->variable, c2->variable, sep, true);
1010 c->creator = this;
1011 gcs.push_back(c);
1012 cs.push_back(c);
1013#if 0
1014 // The following was an experiment to allow variable distributions
1015 // solved by optimisation rather than satisfying constraints
1016 if(isVariable) {
1017 // set second derivatives of:
1018 // (u + g - v)^2 = g^2 + 2gu + u^2 - 2gv - 2uv + v^2
1019 (*Q)[make_pair(c1->variable->id,c1->variable->id)]+=w;
1020 (*Q)[make_pair(c2->variable->id,c2->variable->id)]+=w;
1021 (*Q)[make_pair(variable->id,variable->id)]+=w;
1022 (*Q)[make_pair(c1->variable->id,c2->variable->id)]-=w;
1023 (*Q)[make_pair(c2->variable->id,c1->variable->id)]-=w;
1024 (*Q)[make_pair(c1->variable->id,variable->id)]+=w;
1025 (*Q)[make_pair(variable->id,c1->variable->id)]+=w;
1026 (*Q)[make_pair(c2->variable->id,variable->id)]-=w;
1027 (*Q)[make_pair(variable->id,c2->variable->id)]-=w;
1028 }
1029#endif
1030 }
1031 }
1032}
1033
1034
1035//-----------------------------------------------------------------------------
1036// FixedRelativeConstraint code
1037//-----------------------------------------------------------------------------
1038
1039class RelativeOffset : public SubConstraintInfo
1040{
1041 public:
1042 RelativeOffset(unsigned indL, unsigned indR, vpsc::Dim dim,
1043 double offset)
1044 : SubConstraintInfo(indL),
1045 varIndex2(indR),
1046 dim(dim),
1047 distOffset(offset)
1048 {
1049 }
1050 void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward)
1051 {
1052 varIndex = idMap.mappingForVariable(varIndex, forward);
1053 varIndex2 = idMap.mappingForVariable(varIndex2, forward);
1054 }
1055
1056 unsigned varIndex2;
1057 vpsc::Dim dim;
1058 double distOffset;
1059};
1060
1061
1063 std::vector<unsigned> shapeIds, const bool fixedPosition)
1064 : CompoundConstraint(vpsc::XDIM),
1065 m_fixed_position(fixedPosition),
1066 m_shape_vars(shapeIds)
1067{
1069
1070 // Make sure that m_shape_vars doesn't contain duplicates.
1071 std::sort(m_shape_vars.begin(), m_shape_vars.end());
1072 std::vector<unsigned>::iterator last =
1073 std::unique(m_shape_vars.begin(), m_shape_vars.end());
1074 m_shape_vars.erase(last, m_shape_vars.end());
1075
1076 unsigned firstId = UINT_MAX;
1077 COLA_ASSERT(m_shape_vars.size() >= 2);
1078 for (std::vector<unsigned>::iterator it = m_shape_vars.begin();
1079 it != m_shape_vars.end(); ++it)
1080 {
1081 COLA_ASSERT(*it < rs.size());
1082
1083 if (it == m_shape_vars.begin())
1084 {
1085 firstId = *it;
1086 }
1087 else
1088 {
1089 unsigned thisId = *it;
1090 _subConstraintInfo.push_back(
1091 new RelativeOffset(firstId, thisId, vpsc::XDIM,
1092 rs[thisId]->getCentreX() - rs[firstId]->getCentreX()));
1093 _subConstraintInfo.push_back(
1094 new RelativeOffset(firstId, thisId, vpsc::YDIM,
1095 rs[thisId]->getCentreY() - rs[firstId]->getCentreY()));
1096 }
1097 }
1098}
1099
1101 const VariableIDMap& idMap, bool forward)
1102{
1104
1105 // We need to map variables in m_shape_vars too,
1106 // since this is used in generateVariables().
1107 for (size_t i = 0; i < m_shape_vars.size(); ++i)
1108 {
1109 m_shape_vars[i] = idMap.mappingForVariable(m_shape_vars[i], forward);
1110 }
1111}
1112
1113
1114
1116 vpsc::Variables& vars)
1117{
1118 COLA_UNUSED(dim);
1119 COLA_UNUSED(vars);
1120
1121 // No additional variables are required!
1122
1123 // Fix shape positions if required.
1124 if (m_fixed_position)
1125 {
1126 for (std::vector<unsigned>::iterator it = m_shape_vars.begin();
1127 it != m_shape_vars.end(); ++it)
1128 {
1129 vars[*it]->fixedDesiredPosition = true;
1130 vars[*it]->weight = 100000;
1131 }
1132 }
1133}
1134
1135
1137{
1138 fprintf(fp, " std::vector<unsigned> fixedRelativeSet%llu;\n",
1139 (unsigned long long) this);
1140 for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin();
1141 it != m_shape_vars.end(); ++it)
1142 {
1143 fprintf(fp, " fixedRelativeSet%llu.push_back(%u);\n",
1144 (unsigned long long) this, *it);
1145 }
1146 fprintf(fp, " FixedRelativeConstraint *fixedRelative%llu = "
1147 "new FixedRelativeConstraint(rs, fixedRelativeSet%llu, %s);\n",
1148 (unsigned long long) this, (unsigned long long) this,
1149 (m_fixed_position) ? "true" : "false");
1150 fprintf(fp, " ccs.push_back(fixedRelative%llu);\n\n",
1151 (unsigned long long) this);
1152}
1153
1154
1156{
1157 std::ostringstream stream;
1158 stream << "FixedRelativeConstraint(";
1159 stream << "fixedPos: " << ((m_fixed_position) ? "true" : "false");
1160 stream << "): {";
1161 bool first = true;
1162 for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin();
1163 it != m_shape_vars.end(); ++it)
1164 {
1165 if (!first)
1166 {
1167 stream << ", ";
1168 }
1169 stream << "(rect: " << *it << ")";
1170 first = false;
1171 }
1172 stream << "}";
1173 return stream.str();
1174}
1175
1176
1179{
1180 COLA_UNUSED(vs);
1181
1182 SubConstraintAlternatives alternatives;
1183
1184 RelativeOffset *offset = static_cast<RelativeOffset *>
1186
1187 vpsc::Dim dim = offset->dim;
1188 vpsc::Constraint constraint(vs[dim][offset->varIndex],
1189 vs[dim][offset->varIndex2], offset->distOffset, true);
1190 alternatives.push_back(SubConstraint(dim, constraint));
1191
1192 //fprintf(stderr, "===== FixedRelativeConstraint ALTERNATIVES -======\n");
1193 return alternatives;
1194}
1195
1196
1198 const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& ccs,
1199 vpsc::Rectangles& bbs)
1200{
1201 COLA_UNUSED(vars);
1202 COLA_UNUSED(bbs);
1203
1204 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
1205 o != _subConstraintInfo.end(); ++o)
1206 {
1207 RelativeOffset *offset = static_cast<RelativeOffset *> (*o);
1208 if (dim != offset->dim)
1209 {
1210 continue;
1211 }
1212
1213 assertValidVariableIndex(vars, offset->varIndex);
1214 assertValidVariableIndex(vars, offset->varIndex2);
1216 new vpsc::Constraint(vars[offset->varIndex],
1217 vars[offset->varIndex2], offset->distOffset, true);
1218 c->creator = this;
1219 ccs.push_back(c);
1220 }
1221}
1222
1223
1224//-----------------------------------------------------------------------------
1225// PageBoundaryConstraint code
1226//-----------------------------------------------------------------------------
1227
1228class PageBoundaryShapeOffsets : public SubConstraintInfo
1229{
1230 public:
1231 PageBoundaryShapeOffsets(unsigned ind, double xOffset, double yOffset) :
1233 {
1234 halfDim[0] = xOffset;
1235 halfDim[1] = yOffset;
1236 }
1237 double halfDim[2]; // half width and height values;
1238};
1239
1240
1242 double yLow, double yHigh, double weight)
1243 : CompoundConstraint(vpsc::HORIZONTAL)
1244{
1245 COLA_ASSERT(xLow < xHigh);
1246 COLA_ASSERT(yLow < yHigh);
1247
1248 leftMargin[vpsc::XDIM] = xLow;
1249 rightMargin[vpsc::XDIM] = xHigh;
1250 leftMargin[vpsc::YDIM] = yLow;
1251 rightMargin[vpsc::YDIM] = yHigh;
1252
1253 for (unsigned i = 0; i < 2; ++i)
1254 {
1257 leftWeight[i] = weight;
1258 rightWeight[i] = weight;
1259 vl[i] = nullptr;
1260 vr[i] = nullptr;
1261 }
1262}
1263
1264
1265void PageBoundaryConstraints::addShape(unsigned id, double halfW, double halfH)
1266{
1267 _subConstraintInfo.push_back(new PageBoundaryShapeOffsets(id, halfW, halfH));
1268}
1269
1270
1272{
1273 fprintf(fp, " PageBoundaryConstraints *pageBoundary%llu = "
1274 "new PageBoundaryConstraints(%g, %g, %g, %g, %g);\n",
1275 (unsigned long long) this, leftMargin[vpsc::XDIM],
1278 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
1279 o != _subConstraintInfo.end(); ++o)
1280 {
1281 PageBoundaryShapeOffsets *offsets =
1282 static_cast<PageBoundaryShapeOffsets *> (*o);
1283 fprintf(fp, " pageBoundary%llu->addShape(%u, %g, %g);\n",
1284 (unsigned long long) this, offsets->varIndex,
1285 offsets->halfDim[XDIM], offsets->halfDim[YDIM]);
1286 }
1287 fprintf(fp, " ccs.push_back(pageBoundary%llu);\n\n",
1288 (unsigned long long) this);
1289}
1290
1291
1293{
1294 std::ostringstream stream;
1295 stream << "PageBoundaryConstraints(";
1296 stream << "xLow: " << leftMargin[vpsc::XDIM];
1297 stream << ", xHigh: " << rightMargin[vpsc::XDIM];
1298 stream << ", yLow: " << leftMargin[vpsc::YDIM];
1299 stream << ", yHigh: " << rightMargin[vpsc::YDIM];
1300 stream << ", weight: " << leftWeight[0];
1301 stream << "): {";
1302 bool first = true;
1303 for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
1304 o != _subConstraintInfo.end(); ++o)
1305 {
1306 if (!first)
1307 {
1308 stream << ", ";
1309 }
1310 PageBoundaryShapeOffsets *offsets =
1311 static_cast<PageBoundaryShapeOffsets *> (*o);
1312 stream << "(rect: " << offsets->varIndex;
1313 stream << ", halfWidth: " << offsets->halfDim[XDIM];
1314 stream << ", halfHeight: " << offsets->halfDim[YDIM];
1315 stream <<")";
1316 first = false;
1317 }
1318 stream << "}";
1319 return stream.str();
1320}
1321
1324{
1325 COLA_UNUSED(vs);
1326
1327 // Page boundary constraints do not need to be evaluated at the
1328 // time of makeFeasible, so we return an empty list here.
1331}
1332
1333
1335{
1336 if (vl[dim])
1337 {
1338 actualLeftMargin[dim] = vl[dim]->finalPosition;
1339 }
1340
1341 if (vr[dim])
1342 {
1343 actualRightMargin[dim] = vr[dim]->finalPosition;
1344 }
1345}
1346
1347
1349{
1350 return actualLeftMargin[dim];
1351}
1352
1353
1355{
1356 return actualRightMargin[dim];
1357}
1358
1359
1361 vpsc::Variables& vars)
1362{
1363 // create 2 dummy vars, based on the dimension we are in
1364 if (leftWeight[dim])
1365 {
1366 vars.push_back(vl[dim] = new vpsc::Variable(vars.size(),
1367 leftMargin[dim], leftWeight[dim]));
1368 vl[dim]->fixedDesiredPosition = true;
1369 }
1370
1371 if (rightWeight[dim])
1372 {
1373 vars.push_back(vr[dim] = new vpsc::Variable(vars.size(),
1374 rightMargin[dim], rightWeight[dim]));
1375 vr[dim]->fixedDesiredPosition = true;
1376 }
1377}
1378
1379
1381 const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
1382 vpsc::Rectangles& bbs)
1383{
1384 COLA_UNUSED(bbs);
1385 // For each of the "real" variables, create a constraint that puts
1386 // that var between our two new dummy vars, depending on the dimension.
1387 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
1388 o != _subConstraintInfo.end(); ++o)
1389 {
1390 PageBoundaryShapeOffsets *info =
1391 static_cast<PageBoundaryShapeOffsets *> (*o);
1392 assertValidVariableIndex(vs, info->varIndex);
1393 if (vl[dim])
1394 {
1395 vpsc::Constraint *constraint = new vpsc::Constraint(vl[dim],
1396 vs[info->varIndex], info->halfDim[dim]);
1397 constraint->creator = this;
1398 cs.push_back(constraint);
1399 }
1400
1401 if (vr[dim])
1402 {
1403 vpsc::Constraint *constraint = new vpsc::Constraint(
1404 vs[info->varIndex], vr[dim], info->halfDim[dim]);
1405 constraint->creator = this;
1406 cs.push_back(constraint);
1407 }
1408 }
1409}
1410
1411
1412//-----------------------------------------------------------------------------
1413// Support code
1414//-----------------------------------------------------------------------------
1415
1416
1417struct GenerateVariables
1418{
1419 GenerateVariables(const vpsc::Dim dim, vpsc::Variables& vars)
1420 : dim(dim),
1421 vars(vars)
1422 {
1423 }
1424 void operator() (CompoundConstraint *c)
1425 {
1426 c->generateVariables(dim, vars);
1427 }
1428
1429 const vpsc::Dim dim;
1430 vpsc::Variables& vars;
1431};
1432
1433
1434struct GenerateSeparationConstraints
1435{
1436 GenerateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables& vars,
1438 : dim(dim),
1439 vars(vars),
1440 cs(cs),
1441 bbs(bbs)
1442 {
1443 }
1444 void operator() (CompoundConstraint *c)
1445 {
1446 c->generateSeparationConstraints(dim, vars, cs, bbs);
1447 }
1448 const vpsc::Dim dim;
1449 vpsc::Variables& vars;
1451 vpsc::Rectangles& bbs;
1452};
1453
1454
1456 const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& cs,
1457 vpsc::Rectangles& bbs)
1458{
1459 for_each(ccs.begin(), ccs.end(),
1460 GenerateVariables(dim, vars));
1461 for_each(ccs.begin(), ccs.end(),
1462 GenerateSeparationConstraints(dim, vars, cs, bbs));
1463}
1464
1465
1467 vpsc::Variables& vars)
1468{
1469 for_each(ccs.begin(), ccs.end(),
1470 GenerateVariables(dim, vars));
1471}
1472
1473
1475 unsigned int priority) :
1476 _primaryDim(primaryDim),
1477 _secondaryDim((vpsc::Dim) ((primaryDim + 1) % 2)),
1478 _priority(priority),
1479 _combineSubConstraints(false),
1480 _currSubConstraintIndex(0)
1481{
1482}
1483
1484
1486{
1487 // Free memory from the subConstraintInfo list.
1488 for_each(_subConstraintInfo.begin(), _subConstraintInfo.end(), delete_object());
1489 _subConstraintInfo.clear();
1490}
1491
1492
1494{
1495 return _primaryDim;
1496}
1497
1498
1499unsigned int CompoundConstraint::priority(void) const
1500{
1501 return _priority;
1502}
1503
1504
1506{
1507 COLA_UNUSED(fp);
1508
1509 // Do nothing. Subclasses can implement this.
1510}
1511
1513 bool forward)
1514{
1515 for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
1516 o != _subConstraintInfo.end(); ++o)
1517 {
1518 (*o)->updateVarIDsWithMapping(idMap, forward);
1519 }
1520}
1521
1522
1523std::list<unsigned> CompoundConstraint::subConstraintObjIndexes(void) const
1524{
1525 std::list<unsigned> idList;
1526 for (size_t i = 0; i < _subConstraintInfo.size(); ++i)
1527 {
1528 idList.push_back(_subConstraintInfo[i]->varIndex);
1529 }
1530 return idList;
1531}
1532
1533
1538
1539
1541{
1542 for (size_t i = 0; i < _subConstraintInfo.size(); ++i)
1543 {
1544 _subConstraintInfo[i]->satisfied = false;
1545 }
1547}
1548
1549
1551{
1552 _subConstraintInfo[_currSubConstraintIndex]->satisfied = satisfiable;
1553
1555}
1556
1557
1559 const unsigned index)
1560{
1561 if (index >= vars.size())
1562 {
1564 }
1565}
1566
1567
1572
1573
1575 const vpsc::Constraint *c)
1576 : leftVarIndex(c->left->id),
1577 rightVarIndex(c->right->id),
1578 separation(c->gap),
1579 equality(c->equality),
1580 cc((CompoundConstraint *)c->creator)
1581{
1582}
1583
1584// Variable mapping.
1585
1589
1593
1594typedef std::pair<unsigned, unsigned> IDPair;
1595typedef std::list<IDPair> IDPairList;
1596
1598 const unsigned to)
1599{
1600 bool found = false;
1601 for (IDPairList::iterator it = m_mapping.begin(); it != m_mapping.end();
1602 ++it)
1603 {
1604 IDPair& ids = *it;
1605
1606 if (ids.first == from)
1607 {
1608 found = true;
1609 break;
1610 }
1611 }
1612
1613 if (!found)
1614 {
1615 m_mapping.push_back(std::make_pair(from, to));
1616 return true;
1617 }
1618 //fprintf(stderr, "VariableIDMap: mapping already exists for var %u\n", from);
1619 return false;
1620}
1621
1623{
1624 fprintf(fp, " cola::VariableIDMap idMap;\n");
1625 for (IDPairList::const_iterator it = m_mapping.begin();
1626 it != m_mapping.end(); ++it)
1627 {
1628 fprintf(fp, " idMap.addMappingForVariable(%u, %u);\n",
1629 it->first, it->second);
1630 }
1631 fprintf(fp, " \n");
1632}
1633
1634unsigned VariableIDMap::mappingForVariable(const unsigned var,
1635 bool forward) const
1636{
1637 for (IDPairList::const_iterator it = m_mapping.begin();
1638 it != m_mapping.end(); ++it)
1639 {
1640 const IDPair& ids = *it;
1641
1642 if (forward)
1643 {
1644 if (ids.first == var)
1645 {
1646 return ids.second;
1647 }
1648 }
1649 else // (!forward)
1650 {
1651 if (ids.second == var)
1652 {
1653 return ids.first;
1654 }
1655 }
1656 }
1657
1658 //fprintf(stderr, "Warning: mapping not found for var %u\n", var);
1659
1660 // Just return original variable index.
1661 return var;
1662}
1663
1665{
1666 m_mapping.clear();
1667}
1668
1669
1670} // namespace cola
1671
An alignment constraint specifies a alignment line that a set of nodes must be constrained to by an e...
void printCreationCode(FILE *fp) const
void fixPos(double pos)
Mark the alignment as ideally having a fixed position.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &cs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
void addShape(const unsigned int index, const double offset)
Mark a node as being part of this alignment constraint.
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
void updateShapeOffsetsForDifferentCentres(const std::vector< double > &offsets, bool forward=true)
void unfixPos(void)
Mark the alignment as not having a fixed position.
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
bool isFixed(void) const
Indicates if the alignment position is marked as fixed.
void updatePosition(const vpsc::Dim dim)
Implemented by the compound constraint to send position information back to the interface.
std::string toString(void) const
Returns a textual description of the compound constraint.
AlignmentConstraint(const vpsc::Dim dim, double position=0.0)
Constructs a new AlignmentConstraint in the specified dimension.
void updatePosition(const vpsc::Dim dim)
Implemented by the compound constraint to send position information back to the interface.
double position
Holds the position of the boundary line, once layout is complete.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &cs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
std::string toString(void) const
Returns a textual description of the compound constraint.
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
void addShape(const unsigned int index, const double offset)
Mark a node as being part of this boundary constraint.
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
void printCreationCode(FILE *fp) const
BoundaryConstraint(const vpsc::Dim dim)
Constructs a new BoundaryConstraint in the specified dimension.
An abstract base class for all high-level compound constraints.
unsigned int priority(void) const
void assertValidVariableIndex(const vpsc::Variables &vars, const unsigned index)
virtual bool subConstraintsRemaining(void) const
CompoundConstraint(vpsc::Dim primaryDim, unsigned int priority=DEFAULT_CONSTRAINT_PRIORITY)
virtual void printCreationCode(FILE *fp) const
virtual void updateVarIDsWithMapping(const VariableIDMap &idMap, bool forward=true)
std::list< unsigned > subConstraintObjIndexes(void) const
SubConstraintInfoList _subConstraintInfo
virtual void markAllSubConstraintsAsInactive(void)
virtual void markCurrSubConstraintAsActive(const bool satisfiable)
bool shouldCombineSubConstraints(void) const
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
DistributionConstraint(const vpsc::Dim dim)
Constructs a new empty DistributionConstraint with a minimum or exact spacing.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &gcs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
void addAlignmentPair(AlignmentConstraint *ac1, AlignmentConstraint *ac2)
Mark a pair of alignment constraints as being part of this distribution constraint.
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
void setSeparation(double sep)
Alter the exact spacing between each pair of alignment constraints.
std::string toString(void) const
Returns a textual description of the compound constraint.
std::vector< unsigned > m_shape_vars
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
FixedRelativeConstraint(const vpsc::Rectangles &rs, std::vector< unsigned > shapeIds, const bool fixedPosition=false)
Constructs a new FixedRelativeConstraint between a set of nodes, optionally with a fixed position.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &gcs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
void updateVarIDsWithMapping(const VariableIDMap &idMap, bool forward=true)
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
std::string toString(void) const
Returns a textual description of the compound constraint.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vs, vpsc::Constraints &gcs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
MultiSeparationConstraint(const vpsc::Dim dim, double minSep=0, bool equality=false)
Constructs a new empty MultiSeparationConstraint with a minimum or exact spacing.
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
void addAlignmentPair(AlignmentConstraint *ac1, AlignmentConstraint *ac2)
Mark a pair of alignment constraints as being part of this multi separation constraint.
void setSeparation(double sep)
Alter the minimum or exact spacing between each pair of alignment constraints.
std::string toString(void) const
Returns a textual description of the compound constraint.
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
OrthogonalEdgeConstraint(const vpsc::Dim dim, unsigned l, unsigned r)
void rectBounds(const vpsc::Dim k, vpsc::Rectangle const *r, double &cmin, double &cmax, double &centre, double &l) const
void generateTopologyConstraints(const vpsc::Dim k, vpsc::Rectangles const &rs, std::vector< vpsc::Variable * > const &vars, std::vector< vpsc::Constraint * > &cs)
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
std::string toString(void) const
Returns a textual description of the compound constraint.
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &gcs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
void updatePosition(const vpsc::Dim dim)
Implemented by the compound constraint to send position information back to the interface.
double getActualRightMargin(const vpsc::Dim dim)
double getActualLeftMargin(const vpsc::Dim dim)
PageBoundaryConstraints(double xLow, double xHigh, double yLow, double yHigh, double weight=100.0)
Constructs a new PageBoundaryConstraints object with given page boundary positions and weight.
std::string toString(void) const
Returns a textual description of the compound constraint.
void addShape(unsigned index, double halfW, double halfH)
Mark a node as being contained within this page boundary.
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
void generateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &bbs)
Implemented by the compound constraint to generate the low-level separation constraints in the given ...
void generateVariables(const vpsc::Dim dim, vpsc::Variables &vars)
Implemented by the compound constraint to generate any additional required variables in the given dim...
std::string toString(void) const
Returns a textual description of the compound constraint.
SubConstraintAlternatives getCurrSubConstraintAlternatives(vpsc::Variables vs[])
SeparationConstraint(const vpsc::Dim dim, unsigned l, unsigned r, double g, bool equality=false)
Constructs a new SeparationConstraint between two nodes in the specified dimension.
void printCreationCode(FILE *fp) const
virtual void updateVarIDsWithMapping(const VariableIDMap &idMap, bool forward)
UnsatisfiableConstraintInfo(const vpsc::Constraint *c)
Holds a mapping between two sets of Variable indices.
std::list< std::pair< unsigned, unsigned > > m_mapping
unsigned mappingForVariable(const unsigned var, bool forward=true) const
bool addMappingForVariable(const unsigned from, const unsigned to)
Adds a mapping between a pair of variables.
void printCreationCode(FILE *fp) const
A constraint determines a minimum or exact spacing required between two Variable objects.
Definition constraint.h:45
double gap
The minimum or exact distance to separate the variables by.
Definition constraint.h:106
A rectangle represents a fixed-size shape in the diagram that may be moved to prevent overlaps and sa...
Definition rectangle.h:78
bool allowOverlap()
Definition rectangle.h:203
double getCentreY() const
Definition rectangle.h:131
double getMaxX() const
Definition rectangle.h:108
double height() const
Definition rectangle.h:140
double getCentreX() const
Definition rectangle.h:130
double width() const
Definition rectangle.h:139
double getMaxY() const
Definition rectangle.h:109
double getMinY() const
Definition rectangle.h:111
double getMinX() const
Definition rectangle.h:110
A variable is comprised of an ideal position, final position and a weight.
Definition variable.h:45
bool fixedDesiredPosition
Definition variable.h:60
double weight
Definition variable.h:54
double finalPosition
Definition variable.h:53
const double w
Definition conic-4.cpp:19
vector< vpsc::Rectangle * > rs
double c[8][4]
double offset
libcola: Force-directed network layout subject to separation constraints library.
Definition box.cpp:25
std::vector< CompoundConstraint * > CompoundConstraints
A vector of pointers to CompoundConstraint objects.
static const double freeWeight
void generateVariablesAndConstraints(CompoundConstraints &ccs, const vpsc::Dim dim, vpsc::Variables &vars, vpsc::Constraints &cs, vpsc::Rectangles &bbs)
Generate all the variables and constraints for a collection of CompoundConstraints.
void generateVariables(CompoundConstraints &ccs, const vpsc::Dim dim, vpsc::Variables &vars)
Generate just all the variables for a collection of CompoundConstraints.
std::pair< unsigned, unsigned > IDPair
std::list< IDPair > IDPairList
std::list< SubConstraint > SubConstraintAlternatives
libvpsc: Variable Placement with Separation Constraints quadratic program solver library.
Dim
Indicates the x- or y-dimension.
Definition rectangle.h:41
@ HORIZONTAL
The x-dimension (0).
Definition rectangle.h:43
@ XDIM
The x-dimension (0).
Definition rectangle.h:45
@ YDIM
The y-dimension (1).
Definition rectangle.h:49
std::vector< vpsc::Variable * > Variables
A vector of pointers to Variable objects.
std::vector< vpsc::Constraint * > Constraints
A vector of pointers to Constraint objects.
std::vector< Rectangle * > Rectangles
A vector of pointers to Rectangle objects.
Definition rectangle.h:246
unsigned long weight
Definition quantize.cpp:37
int index