Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
cluster.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-2014 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 "libvpsc/assertions.h"
24#include "libcola/commondefs.h"
25#include "libcola/cola.h"
26#include "libcola/convex_hull.h"
27#include "libcola/cluster.h"
28
31using namespace std;
32
33namespace cola {
34
36 : bounds(),
37 clusterVarId(0),
38 varWeight(0.0001),
39 internalEdgeWeightFactor(1.),
40 desiredBoundsSet(false),
41 desiredBounds()
42{
43 // XXX We use a really low weight here until we properly set the source
44 // of the variable value back in updatePositions() type manner.
45 varWeight = 0.0000001;
46}
47
49{
50 for_each(clusters.begin(), clusters.end(), delete_object());
51 clusters.clear();
52}
53
59
61{
62 desiredBoundsSet=false;
63}
64
65
66// Checks to see if the shape at the given index is contained within this
67// cluster or its child clusters.
68//
69void Cluster::countContainedNodes(std::vector<unsigned>& counts)
70{
71 vector<unsigned> invalidNodes;
72 for (set<unsigned>::iterator it = nodes.begin(); it != nodes.end(); ++it)
73 {
74 unsigned nodeIndex = *it;
75 if (nodeIndex < counts.size())
76 {
77 // Node index is valid, increase count.
78 counts[*it] += 1;
79 }
80 else
81 {
82 fprintf(stderr, "Warning: Invalid node index %u specified in "
83 "cluster. Ignoring...\n", nodeIndex);
84 invalidNodes.push_back(nodeIndex);
85 }
86 }
87 for (size_t i = 0; i < invalidNodes.size(); ++i)
88 {
89 nodes.erase(invalidNodes[i]);
90 }
91
92 for (vector<Cluster*>::const_iterator i = clusters.begin();
93 i != clusters.end(); ++i)
94 {
95 (*i)->countContainedNodes(counts);
96 }
97}
98
100{
102 for (vector<Cluster*>::const_iterator i = clusters.begin();
103 i != clusters.end(); ++i)
104 {
105 (*i)->computeBoundingRect(rs);
106 vpsc::Rectangle rectangle =
107 (*i)->margin().rectangleByApplyingBox((*i)->bounds);
108 bounds = bounds.unionWith(rectangle);
109 }
110 for (set<unsigned>::const_iterator i = nodes.begin();
111 i != nodes.end(); ++i)
112 {
113 vpsc::Rectangle* r=rs[*i];
114 bounds = bounds.unionWith(*r);
115 }
117}
118
120{
121 if ((clusterVarId > 0) && (vars.size() > clusterVarId))
122 {
123 varRect.setMinD(dim, vars[clusterVarId]->finalPosition);
124 varRect.setMaxD(dim, vars[clusterVarId + 1]->finalPosition);
125 }
126
127 for (vector<Cluster*>::const_iterator i = clusters.begin();
128 i != clusters.end(); ++i)
129 {
130 (*i)->computeVarRect(vars, dim);
131 }
132}
133
135{
136 return false;
137}
138
140{
141 unsigned n = 4 * nodes.size();
142 valarray<double> X(n);
143 valarray<double> Y(n);
144 unsigned pctr = 0;
145 vector<unsigned> nodesVector(nodes.begin(), nodes.end());
146 for (size_t i = 0; i < nodesVector.size(); ++i)
147 {
148 vpsc::Rectangle* r=rs[nodesVector[i]];
149 // Bottom Right
150 X[pctr]=r->getMaxX();
151 Y[pctr++]=r->getMinY();
152 // Top Right
153 X[pctr]=r->getMaxX();
154 Y[pctr++]=r->getMaxY();
155 // Top Left
156 X[pctr]=r->getMinX();
157 Y[pctr++]=r->getMaxY();
158 // Bottom Left
159 X[pctr]=r->getMinX();
160 Y[pctr++]=r->getMinY();
161 }
162 /*
163 for(unsigned i=0;i<n;i++) {
164 printf("X[%d]=%f, Y[%d]=%f;\n",i,X[i],i,Y[i]);
165 }
166 */
167 vector<unsigned> hull;
168 hull::convex(X,Y,hull);
169 hullX.resize(hull.size());
170 hullY.resize(hull.size());
171 hullRIDs.resize(hull.size());
172 hullCorners.resize(hull.size());
173 for (unsigned j=0;j<hull.size();j++)
174 {
175 hullX[j]=X[hull[j]];
176 hullY[j]=Y[hull[j]];
177 hullRIDs[j]=nodesVector[hull[j]/4];
178 hullCorners[j]=hull[j]%4;
179 }
180}
181
182
184{
185 fprintf(fp, " ConvexCluster *cluster%llu = new ConvexCluster();\n",
186 (unsigned long long) this);
187 for(set<unsigned>::const_iterator i = nodes.begin();
188 i != nodes.end(); ++i)
189 {
190 fprintf(fp, " cluster%llu->addChildNode(%u);\n",
191 (unsigned long long) this, *i);
192 }
193 for(vector<Cluster *>::const_iterator i = clusters.begin();
194 i != clusters.end(); ++i)
195 {
196 (*i)->printCreationCode(fp);
197 fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
198 (unsigned long long) this, (unsigned long long) *i);
199 }
200}
201
202void ConvexCluster::outputToSVG(FILE *fp) const
203{
204 for(vector<Cluster *>::const_iterator i = clusters.begin();
205 i != clusters.end(); ++i)
206 {
207 (*i)->outputToSVG(fp);
208 }
209}
210
211
213 : Cluster(),
214 m_rectangle_index(-1),
215 m_margin(0),
216 m_padding(0)
217{
218 minEdgeRect[vpsc::XDIM] = nullptr;
219 minEdgeRect[vpsc::YDIM] = nullptr;
220 maxEdgeRect[vpsc::XDIM] = nullptr;
221 maxEdgeRect[vpsc::YDIM] = nullptr;
222}
223
225 : Cluster(),
226 m_rectangle_index(rectIndex),
227 m_margin(0),
228 m_padding(0)
229{
230 minEdgeRect[vpsc::XDIM] = nullptr;
231 minEdgeRect[vpsc::YDIM] = nullptr;
232 maxEdgeRect[vpsc::XDIM] = nullptr;
233 maxEdgeRect[vpsc::YDIM] = nullptr;
234}
235
237{
238 for (size_t dim = 0; dim < 2; ++dim)
239 {
240 if (minEdgeRect[dim])
241 {
242 delete minEdgeRect[dim];
243 minEdgeRect[dim] = nullptr;
244 }
245 if (maxEdgeRect[dim])
246 {
247 delete maxEdgeRect[dim];
248 maxEdgeRect[dim] = nullptr;
249 }
250 }
251}
252
257
258
263
264
266{
267 return m_margin;
268}
269
270
272{
274}
275
276
278{
280}
281
282
284{
285 return m_padding;
286}
287
288
289void RectangularCluster::countContainedNodes(std::vector<unsigned>& counts)
290{
291 if (m_rectangle_index >= 0)
292 {
293 // This cluster is the shape in question.
294 counts[m_rectangle_index] += 1;
295 }
297}
298
299
301 cola::CompoundConstraints& idleConstraints,
302 vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const
303{
304 COLA_UNUSED(vars);
305
306 if (m_rectangle_index < 0)
307 {
308 // Not based on a Rectangle.
309 return;
310 }
311
312 double halfWidth = rc[m_rectangle_index]->width() / 2;
313 double halfHeight = rc[m_rectangle_index]->height() / 2;
314
317 m_rectangle_index, halfWidth, true);
318 idleConstraints.push_back(sc);
320 m_rectangle_index, clusterVarId + 1, halfWidth, true);
321 idleConstraints.push_back(sc);
322
324 clusterVarId, m_rectangle_index, halfHeight, true);
325 idleConstraints.push_back(sc);
327 m_rectangle_index, clusterVarId + 1, halfHeight, true);
328 idleConstraints.push_back(sc);
329}
330
331
333{
334 double xMin=DBL_MAX, xMax=-DBL_MAX, yMin=DBL_MAX, yMax=-DBL_MAX;
335 for (std::set<unsigned>::iterator it = nodes.begin();
336 it != nodes.end(); ++it)
337 {
338 xMin=std::min(xMin,rs[*it]->getMinX());
339 xMax=std::max(xMax,rs[*it]->getMaxX());
340 yMin=std::min(yMin,rs[*it]->getMinY());
341 yMax=std::max(yMax,rs[*it]->getMaxY());
342 }
343 hullX.resize(4);
344 hullY.resize(4);
345 hullX[3]=xMin;
346 hullY[3]=yMin;
347 hullX[2]=xMin;
348 hullY[2]=yMax;
349 hullX[1]=xMax;
350 hullY[1]=yMax;
351 hullX[0]=xMax;
352 hullY[0]=yMin;
353}
354
355
357{
358 fprintf(fp, " RectangularCluster *cluster%llu = "
359 "new RectangularCluster(",
360 (unsigned long long) this);
361 if (m_rectangle_index != -1)
362 {
363 fprintf(fp, "%d", m_rectangle_index);
364 }
365 fprintf(fp, ");\n");
366 if (!m_margin.empty())
367 {
368 fprintf(fp, " cluster%llu->setMargin(",
369 (unsigned long long) this);
371 fprintf(fp, ");\n");
372 }
373 if (!m_padding.empty())
374 {
375 fprintf(fp, " cluster%llu->setPadding(",
376 (unsigned long long) this);
378 fprintf(fp, ");\n");
379 }
380 for(set<unsigned>::const_iterator i = nodes.begin();
381 i != nodes.end(); ++i)
382 {
383 fprintf(fp, " cluster%llu->addChildNode(%u);\n",
384 (unsigned long long) this, *i);
385 }
386 for(vector<Cluster *>::const_iterator i = clusters.begin();
387 i != clusters.end(); ++i)
388 {
389 (*i)->printCreationCode(fp);
390 fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
391 (unsigned long long) this, (unsigned long long) *i);
392 }
393}
394
396{
397 double rounding = 4;
398 if (varRect.isValid())
399 {
400 fprintf(fp, "<rect id=\"cluster-%llu-r\" x=\"%g\" y=\"%g\" width=\"%g\" "
401 "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
402 "fill: green; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n",
403 (unsigned long long) this, varRect.getMinX(), varRect.getMinY(),
405 varRect.getMaxY() - varRect.getMinY(), rounding, rounding);
406 }
407 else
408 {
409 fprintf(fp, "<rect id=\"cluster-%llu\" x=\"%g\" y=\"%g\" width=\"%g\" "
410 "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
411 "fill: red; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n",
412 (unsigned long long) this, bounds.getMinX(), bounds.getMinY(),
414 bounds.getMaxY() - bounds.getMinY(), rounding, rounding);
415 }
416
417 for(vector<Cluster *>::const_iterator i = clusters.begin();
418 i != clusters.end(); ++i)
419 {
420 (*i)->outputToSVG(fp);
421 }
422}
423
424
425
427{
428 return m_rectangle_index;
429}
430
432{
433 return (m_rectangle_index >= 0);
434}
435
437{
439 {
440 // For bounds, just use this shape's rectangle.
442 }
443 else
444 {
446 }
447}
449{
450 if ((m_rectangle_index == (int) index) && (m_rectangle_index > 0))
451 {
452 fprintf(stderr, "Warning: ignoring cluster (%u) added as child of "
453 "itself.\n", index);
454 return;
455 }
457}
458
459
461 : m_allows_multiple_parents(false)
462{
463}
464
465void Cluster::recPathToCluster(RootCluster *rootCluster, Clusters currentPath)
466{
467 // Reset cluster-cluster overlap exceptions.
471
472 // Add this cluster to the path.
473 currentPath.push_back(this);
474
475 // Recusively all on each child cluster.
476 for (unsigned i = 0; i < clusters.size(); ++i)
477 {
478 clusters[i]->recPathToCluster(rootCluster, currentPath);
479 }
480
481 // And store the path to each child node.
482 for (std::set<unsigned>::iterator it = nodes.begin();
483 it != nodes.end(); ++it)
484 {
485 rootCluster->m_cluster_vectors_leading_to_nodes[*it].
486 push_back(currentPath);
487 }
488}
489
490
492{
494 m_cluster_vectors_leading_to_nodes.resize(nodesCount);
495
496 recPathToCluster(this, Clusters());
497
498 for (unsigned i = 0; i < m_cluster_vectors_leading_to_nodes.size(); ++i)
499 {
500 size_t paths = m_cluster_vectors_leading_to_nodes[i].size();
501 for (size_t j = 1; j < paths; ++j)
502 {
503 for (size_t k = 0; k < j; ++k)
504 {
505 // For each pair of paths.
506
507 // Find the lowest common ancestor by finding where the two
508 // paths from the root cluster to node i diverge.
511 size_t lcaIndex = 0;
512 while ((lcaIndex < pathJ.size()) &&
513 (lcaIndex < pathK.size()) &&
514 (pathJ[lcaIndex] == pathK[lcaIndex]))
515 {
516 ++lcaIndex;
517 }
518 COLA_ASSERT(lcaIndex > 0);
519
520 // lcaIndex will be the clusters/nodes that need to overlap
521 // due to these two paths to node i.
522 size_t lcaChildJIndex = i;
523 size_t lcaChildKIndex = i;
524 Cluster *lcaChildJCluster = nullptr;
525 Cluster *lcaChildKCluster = nullptr;
526
527 // lcaIndex < path{J,K}.size() means the child J or K of
528 // the lca is a Cluster. At least one of them will always
529 // be a cluster.
530 COLA_ASSERT((lcaIndex < pathJ.size()) ||
531 (lcaIndex < pathK.size()));
532 if (lcaIndex < pathJ.size())
533 {
534 lcaChildJCluster = pathJ[lcaIndex];
535 lcaChildJIndex = lcaChildJCluster->clusterVarId;
536 }
537 if (lcaIndex < pathK.size())
538 {
539 lcaChildKCluster = pathK[lcaIndex];
540 lcaChildKIndex = lcaChildKCluster->clusterVarId;
541 }
542
543 // We want to exclude the overlapping children of the lca
544 // from having non-overlap constraints generated for them
545 // (siblings of a particular cluster usually have
546 // non-overlap constraints generated for them).
547 Cluster *lcaCluster = pathJ[lcaIndex - 1];
548 lcaCluster->m_cluster_cluster_overlap_exceptions.insert(
549 ShapePair(lcaChildJIndex, lcaChildKIndex));
550
551 if (lcaChildJCluster)
552 {
553 // In cluster J, replace node i with cluster K for the
554 // purpose of non-overlap with siblings, and remember
555 // this replacement so we can still generate non-overlap
556 // constraints between multiple nodes that are children
557 // of the same overlapping clusters.
558 lcaChildJCluster->m_overlap_replacement_map[i] =
559 lcaChildKCluster;
560 lcaChildJCluster->m_nodes_replaced_with_clusters.insert(i);
561 }
562
563 if (lcaChildKCluster)
564 {
565 // In cluster K, replace node i with cluster J for the
566 // purpose of non-overlap with siblings, and remember
567 // this replacement so we can still generate non-overlap
568 // constraints between multiple nodes that are children
569 // of the same overlapping clusters.
570 lcaChildKCluster->m_overlap_replacement_map[i] =
571 lcaChildJCluster;
572 lcaChildKCluster->m_nodes_replaced_with_clusters.insert(i);
573 }
574 }
575 }
576 }
577}
578
579
581{
582 for (unsigned i = 0; i < clusters.size(); ++i)
583 {
584 clusters[i]->computeBoundary(rs);
585 }
586}
587
589{
590 fprintf(fp, " RootCluster *cluster%llu = new RootCluster();\n",
591 (unsigned long long) this);
592 for(set<unsigned>::const_iterator i = nodes.begin();
593 i != nodes.end(); ++i)
594 {
595 fprintf(fp, " cluster%llu->addChildNode(%u);\n",
596 (unsigned long long) this, *i);
597 }
598 for(vector<Cluster *>::const_iterator i = clusters.begin();
599 i != clusters.end(); ++i)
600 {
601 (*i)->printCreationCode(fp);
602 fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
603 (unsigned long long) this, (unsigned long long) *i);
604 }
605}
606
607void RootCluster::outputToSVG(FILE *fp) const
608{
609 for(vector<Cluster *>::const_iterator i = clusters.begin();
610 i != clusters.end(); ++i)
611 {
612 (*i)->outputToSVG(fp);
613 }
614
615}
616
617
622
624{
626}
627
629{
630 if (dim == vpsc::HORIZONTAL)
631 {
634 }
635 else
636 {
639 }
640 for (unsigned i=0; i < clusters.size(); ++i)
641 {
642 clusters[i]->updateBounds(dim);
643 }
644}
645
646
648 vpsc::Variables& vars)
649{
650 for (vector<Cluster*>::iterator i = clusters.begin();
651 i != clusters.end(); ++i)
652 {
653 (*i)->createVars(dim, rs, vars);
654 }
655 if (dim==vpsc::HORIZONTAL)
656 {
657 double desiredMinX = bounds.getMinX(), desiredMaxX = bounds.getMaxX();
659 {
660 desiredMinX = desiredBounds.getMinX();
661 desiredMaxX = desiredBounds.getMaxX();
662 }
663 clusterVarId = vars.size();
664 vars.push_back(vXMin = new vpsc::Variable(
665 vars.size(), desiredMinX, varWeight));
666 vars.push_back(vXMax = new vpsc::Variable(
667 vars.size(), desiredMaxX, varWeight));
668 }
669 else
670 {
671 double desiredMinY = bounds.getMinY(), desiredMaxY = bounds.getMaxY();
673 {
674 desiredMinY = desiredBounds.getMinY();
675 desiredMaxY = desiredBounds.getMaxY();
676 }
677 clusterVarId = vars.size();
678 vars.push_back(vYMin = new vpsc::Variable(
679 vars.size(), desiredMinY, varWeight));
680 vars.push_back(vYMax = new vpsc::Variable(
681 vars.size(), desiredMaxY, varWeight));
682 }
683}
684
685// Returns the total area covered by contents of this cluster (not
686// including space between nodes/clusters).
687//
689{
690 double a = 0;
691 for (set<unsigned>::iterator i = nodes.begin(); i != nodes.end(); ++i)
692 {
693 vpsc::Rectangle *r = rs[*i];
694 a += r->width() * r->height();
695 }
696 for (Clusters::iterator i = clusters.begin(); i!= clusters.end(); ++i)
697 {
698 a += (*i)->area(rs);
699 }
700 return a;
701}
702
704{
705 this->nodes.insert(index);
706}
707
709{
710 if (cluster == this)
711 {
712 fprintf(stderr, "Warning: ignoring cluster added as child of itself.\n");
713 return;
714 }
715 this->clusters.push_back(cluster);
716}
717
718
719} // namespace cola
int margin
Definition canvas.cpp:166
Geom::IntRect bounds
Definition canvas.cpp:182
A box consisting of four edge values for representing padding or margins for rectangles.
Definition box.h:38
bool empty(void) const
Definition box.cpp:56
void outputCode(FILE *fp) const
Definition box.cpp:64
vpsc::Rectangle rectangleByApplyingBox(const vpsc::Rectangle rectangle) const
Definition box.cpp:79
A cluster defines a hierarchical partitioning over the nodes which should be kept disjoint by the lay...
Definition cluster.h:51
vpsc::Variable * vMin
Definition cluster.h:146
vpsc::Variable * vYMax
Definition cluster.h:107
void updateBounds(const vpsc::Dim dim)
Definition cluster.cpp:628
vpsc::Variable * vYMin
Definition cluster.h:107
vpsc::Rectangle varRect
Definition cluster.h:106
void addChildCluster(Cluster *cluster)
Mark a cluster as being a sub-cluster of this cluster.
Definition cluster.cpp:708
vpsc::Variable * vMax
Definition cluster.h:146
std::set< unsigned > m_nodes_replaced_with_clusters
Definition cluster.h:137
vpsc::Variable * vXMax
Definition cluster.h:107
void recPathToCluster(RootCluster *rootCluster, Clusters currentPath)
Definition cluster.cpp:465
std::map< unsigned, Cluster * > m_overlap_replacement_map
Definition cluster.h:136
std::vector< Cluster * > clusters
Definition cluster.h:116
virtual void countContainedNodes(std::vector< unsigned > &counts)
Definition cluster.cpp:69
double varWeight
Definition cluster.h:113
vpsc::Rectangle bounds
Definition cluster.h:105
virtual cola::Box padding(void) const
Definition cluster.h:77
double area(const vpsc::Rectangles &rs)
Definition cluster.cpp:688
std::valarray< double > hullY
Definition cluster.h:117
virtual void addChildNode(unsigned index)
Mark a rectangle as being a child of this cluster.
Definition cluster.cpp:703
bool desiredBoundsSet
Definition cluster.h:143
void unsetDesiredBounds()
Definition cluster.cpp:60
std::set< ShapePair > m_cluster_cluster_overlap_exceptions
Definition cluster.h:135
vpsc::Rectangle desiredBounds
Definition cluster.h:144
virtual ~Cluster()
Definition cluster.cpp:48
virtual void computeBoundingRect(const vpsc::Rectangles &rs)
Definition cluster.cpp:99
std::valarray< double > hullX
Definition cluster.h:117
vpsc::Variable * vXMin
Definition cluster.h:107
std::set< unsigned > nodes
Definition cluster.h:115
void setDesiredBounds(const vpsc::Rectangle bounds)
Definition cluster.cpp:54
unsigned clusterVarId
Definition cluster.h:111
virtual void computeVarRect(vpsc::Variables &vs, size_t dim)
Definition cluster.cpp:119
virtual bool clusterIsFromFixedRectangle(void) const
Definition cluster.cpp:134
void createVars(const vpsc::Dim dim, const vpsc::Rectangles &rs, vpsc::Variables &vars)
Definition cluster.cpp:647
void computeBoundary(const vpsc::Rectangles &rs)
Definition cluster.cpp:139
virtual void outputToSVG(FILE *fp) const
Definition cluster.cpp:202
virtual void printCreationCode(FILE *fp) const
Definition cluster.cpp:183
std::valarray< unsigned > hullRIDs
Definition cluster.h:365
std::valarray< unsigned char > hullCorners
Definition cluster.h:366
cola::Box padding(void) const
Returns the padding box for this cluster.
Definition cluster.cpp:283
virtual void printCreationCode(FILE *fp) const
Definition cluster.cpp:356
virtual void computeBoundingRect(const vpsc::Rectangles &rs)
Definition cluster.cpp:436
virtual void outputToSVG(FILE *fp) const
Definition cluster.cpp:395
RectangularCluster()
A rectangular cluster of variable size that contains its children.
Definition cluster.cpp:212
virtual void countContainedNodes(std::vector< unsigned > &counts)
Definition cluster.cpp:289
void setMargin(double margin)
Sets the margin size for this cluster.
Definition cluster.cpp:259
virtual bool clusterIsFromFixedRectangle(void) const
Definition cluster.cpp:431
vpsc::Rectangle * maxEdgeRect[2]
Definition cluster.h:348
void setPadding(double padding)
Sets the padding size for this cluster.
Definition cluster.cpp:277
virtual void addChildNode(unsigned index)
Mark a rectangle as being a child of this cluster.
Definition cluster.cpp:448
vpsc::Rectangle * minEdgeRect[2]
Definition cluster.h:347
void computeBoundary(const vpsc::Rectangles &rs)
Definition cluster.cpp:332
void generateFixedRectangleConstraints(cola::CompoundConstraints &idleConstraints, vpsc::Rectangles &rc, vpsc::Variables(&vars)[2]) const
Definition cluster.cpp:300
cola::Box margin(void) const
Returns the margin box for this cluster.
Definition cluster.cpp:265
virtual ~RectangularCluster()
Definition cluster.cpp:236
int rectangleIndex(void) const
Definition cluster.cpp:426
Holds the cluster hierarchy specification for a diagram.
Definition cluster.h:173
void computeBoundary(const vpsc::Rectangles &rs)
Definition cluster.cpp:580
virtual void outputToSVG(FILE *fp) const
Definition cluster.cpp:607
virtual void printCreationCode(FILE *fp) const
Definition cluster.cpp:588
void calculateClusterPathsToEachNode(size_t nodesCount)
Definition cluster.cpp:491
std::vector< ClustersList > m_cluster_vectors_leading_to_nodes
Definition cluster.h:209
bool allowsMultipleParents(void) const
Returns true if this cluster hierarchy allows multiple parents, otherwise returns false.
Definition cluster.cpp:618
bool m_allows_multiple_parents
Definition cluster.h:207
void setAllowsMultipleParents(const bool value)
Set whether the cluster hierarchy should allow multiple parents.
Definition cluster.cpp:623
A separation constraint specifies a simple horizontal or vertical spacing constraint between 2 nodes ...
A rectangle represents a fixed-size shape in the diagram that may be moved to prevent overlaps and sa...
Definition rectangle.h:78
void setMaxD(unsigned const d, const double val)
Definition rectangle.h:128
double getMaxX() const
Definition rectangle.h:108
double height() const
Definition rectangle.h:140
Rectangle unionWith(const Rectangle &rhs) const
Definition rectangle.cpp:81
bool isValid(void) const
Definition rectangle.cpp:76
void setMinD(unsigned const d, const double val)
Definition rectangle.h:126
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
double finalPosition
Definition variable.h:53
vector< vpsc::Rectangle * > rs
RectangularCluster rc
vector< vector< Point > > paths
Definition metro.cpp:36
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.
std::vector< Cluster * > Clusters
Definition cluster.h:39
void convex(const unsigned n, const double *X, const double *Y, vector< unsigned > &h)
STL namespace.
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.
void generateXConstraints(const Rectangles &rs, const Variables &vars, Constraints &cs, const bool useNeighbourLists)
void generateYConstraints(const Rectangles &rs, const Variables &vars, Constraints &cs)
std::vector< Rectangle * > Rectangles
A vector of pointers to Rectangle objects.
Definition rectangle.h:246
int index