Adaptagrams
cluster.h
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 #ifndef COLA_CLUSTER_H
24 #define COLA_CLUSTER_H
25 
26 #include <cstdio>
27 
28 #include "libvpsc/rectangle.h"
29 #include "libvpsc/variable.h"
30 
31 #include "libcola/compound_constraints.h"
32 #include "libcola/commondefs.h"
33 #include "libcola/box.h"
34 #include "libcola/shapepair.h"
35 
36 namespace cola {
37 
38 class Cluster;
39 typedef std::vector<Cluster *> Clusters;
40 typedef std::vector<Clusters> ClustersList;
41 
50 class Cluster
51 {
52  public:
53  Cluster();
54 
55 // To prevent C++ objects from being destroyed in garbage collected languages
56 // when the libraries are called from SWIG, we hide the declarations of the
57 // destructors and prevent generation of default destructors.
58 #ifndef SWIG
59  virtual ~Cluster();
60 #endif
61  virtual void computeBoundary(const vpsc::Rectangles& rs) = 0;
62  virtual void computeBoundingRect(const vpsc::Rectangles& rs);
63 
69  virtual void addChildNode(unsigned index);
75  void addChildCluster(Cluster *cluster);
76 
77  virtual cola::Box padding(void) const
78  {
79  return cola::Box();
80  }
81  virtual cola::Box margin(void) const
82  {
83  return cola::Box();
84  }
85 
86  void setDesiredBounds(const vpsc::Rectangle bounds);
87  void unsetDesiredBounds();
88  void createVars(const vpsc::Dim dim, const vpsc::Rectangles& rs,
89  vpsc::Variables& vars);
90  virtual void printCreationCode(FILE *fp) const = 0;
91  virtual void countContainedNodes(std::vector<unsigned>& counts);
92  virtual bool clusterIsFromFixedRectangle(void) const;
93  virtual void outputToSVG(FILE *fp) const = 0;
94 
95  // Returns the total area covered by contents of this cluster
96  // (not including space between nodes/clusters).
97  double area(const vpsc::Rectangles& rs);
98 
99  // Sets bounds based on the finalPositions of vMin and vMax.
100  //
101  void updateBounds(const vpsc::Dim dim);
102 
103  virtual void computeVarRect(vpsc::Variables& vs, size_t dim);
104 
105  vpsc::Rectangle bounds;
106  vpsc::Rectangle varRect;
107  vpsc::Variable *vXMin, *vXMax, *vYMin, *vYMax;
108 
109  // This will be the id of the left/bottom boundary,
110  // and the right/top will be clusterVarId + 1.
111  unsigned clusterVarId;
112 
113  double varWeight;
114  double internalEdgeWeightFactor;
115  std::set<unsigned> nodes;
116  std::vector<Cluster*> clusters;
117  std::valarray<double> hullX, hullY;
118 
119  protected:
120  void recPathToCluster(RootCluster *rootCluster,
121  Clusters currentPath);
122  bool includesAllNodesFrom(const Cluster *rhs) const;
123 
124  // The following are for handling the generation of the correct
125  // set of non-overlap constraints in the case overlapping clusters
126  // (i.e., multiple inheritence). 1) We need to exclude the overlapping
127  // clusters from having non-overlap constraints. 2) We replace nodes
128  // with multiple parent clusters when enforcing non-overlap with their
129  // siblings and instead inforce non-overlap with the other clusters
130  // they are part of, since otherwise there is nothing stopping the
131  // other siblings of each cluster from overlapping each other. 3) We
132  // also need to enforce overlap still between the set of nodes replaced
133  // from each cluster in this way, since they may now be part of some
134  // new set.
135  std::set<ShapePair> m_cluster_cluster_overlap_exceptions;
136  std::map<unsigned, Cluster *> m_overlap_replacement_map;
137  std::set<unsigned> m_nodes_replaced_with_clusters;
138 
139  private:
140  friend class ConstrainedFDLayout;
141  friend class RootCluster;
142 
143  bool desiredBoundsSet;
144  vpsc::Rectangle desiredBounds;
145 
146  vpsc::Variable *vMin, *vMax;
147 };
148 
149 
172 class RootCluster : public Cluster
173 {
174  public:
175  RootCluster();
176  void computeBoundary(const vpsc::Rectangles& rs);
177  // There are just shapes at the top level, so
178  // effectively no clusters in the diagram scene.
179  bool flat(void) const
180  {
181  return clusters.empty();
182  }
183  virtual void printCreationCode(FILE *fp) const;
184  virtual void outputToSVG(FILE *fp) const;
185 
193  bool allowsMultipleParents(void) const;
194 
200  void setAllowsMultipleParents(const bool value);
201  private:
202  void calculateClusterPathsToEachNode(size_t nodesCount);
203 
204  friend class ConstrainedFDLayout;
205  friend class Cluster;
206 
207  bool m_allows_multiple_parents;
208 
209  std::vector<ClustersList> m_cluster_vectors_leading_to_nodes;
210 };
211 
219 {
220  public:
236  RectangularCluster(unsigned rectIndex);
237 
248  void setMargin(double margin);
260  void setMargin(const cola::Box margin);
266  cola::Box margin(void) const;
267 
277  void setPadding(double padding);
288  void setPadding(const cola::Box padding);
294  cola::Box padding(void) const;
295 
296 #ifndef SWIG
297  virtual ~RectangularCluster();
298 #endif
299  void computeBoundary(const vpsc::Rectangles& rs);
300  virtual void countContainedNodes(std::vector<unsigned>& counts);
301  virtual void printCreationCode(FILE *fp) const;
302  virtual void outputToSVG(FILE *fp) const;
303  virtual void computeBoundingRect(const vpsc::Rectangles& rs);
304  virtual void addChildNode(unsigned index);
305  inline vpsc::Rectangle *getMinEdgeRect(const vpsc::Dim dim)
306  {
307  if (minEdgeRect[dim])
308  {
309  delete minEdgeRect[dim];
310  }
311  minEdgeRect[dim] = new vpsc::Rectangle(bounds);
312 
313  // Set the Min and Max positions to be the min minus an offset.
314  double edgePosition = minEdgeRect[dim]->getMinD(dim);
315  minEdgeRect[dim]->setMinD(dim, edgePosition - m_margin.min(dim));
316  minEdgeRect[dim]->setMaxD(dim, edgePosition);
317 
318  return minEdgeRect[dim];
319  }
320 
321  inline vpsc::Rectangle *getMaxEdgeRect(const vpsc::Dim dim)
322  {
323  if (maxEdgeRect[dim])
324  {
325  delete maxEdgeRect[dim];
326  }
327  maxEdgeRect[dim] = new vpsc::Rectangle(bounds);
328 
329  // Set the Min and Max positions to be the max plus an offset.
330  double edgePosition = maxEdgeRect[dim]->getMaxD(dim);
331  maxEdgeRect[dim]->setMaxD(dim, edgePosition + m_margin.max(dim));
332  maxEdgeRect[dim]->setMinD(dim, edgePosition);
333 
334  return maxEdgeRect[dim];
335  }
336  virtual bool clusterIsFromFixedRectangle(void) const;
337  int rectangleIndex(void) const;
338 
339  // For fixed sized clusters based on a rectangle, this method
340  // generates the constraints that attach the cluster edges to the
341  // centre position of the relevant rectangle.
342  void generateFixedRectangleConstraints(
343  cola::CompoundConstraints& idleConstraints,
344  vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const;
345 
346  private:
347  vpsc::Rectangle *minEdgeRect[2];
348  vpsc::Rectangle *maxEdgeRect[2];
349  int m_rectangle_index;
350  Box m_margin;
351  Box m_padding;
352 };
353 
358 class ConvexCluster : public Cluster
359 {
360  public:
361  void computeBoundary(const vpsc::Rectangles& rs);
362  virtual void printCreationCode(FILE *fp) const;
363  virtual void outputToSVG(FILE *fp) const;
364 
365  std::valarray<unsigned> hullRIDs;
366  std::valarray<unsigned char> hullCorners;
367 };
368 
369 
370 } // namespace cola
371 #endif // COLA_CLUSTER_H
cola::Box margin(void) const
Returns the margin box for this cluster.
Definition: cluster.cpp:265
A variable is comprised of an ideal position, final position and a weight.
Definition: variable.h:44
void addChildCluster(Cluster *cluster)
Mark a cluster as being a sub-cluster of this cluster.
Definition: cluster.cpp:708
RectangularCluster()
A rectangular cluster of variable size that contains its children.
Definition: cluster.cpp:212
void setMargin(double margin)
Sets the margin size for this cluster.
Definition: cluster.cpp:259
cola::Box padding(void) const
Returns the padding box for this cluster.
Definition: cluster.cpp:283
A box consisting of four edge values for representing padding or margins for rectangles.
Definition: box.h:37
std::vector< Variable * > Variables
A vector of pointers to Variable objects.
Definition: constraint.h:38
Defines a rectangular cluster, either variable-sized with floating sides or a fixed size based on a p...
Definition: cluster.h:218
std::vector< Rectangle * > Rectangles
A vector of pointers to Rectangle objects.
Definition: rectangle.h:246
Holds the cluster hierarchy specification for a diagram.
Definition: cluster.h:172
void setAllowsMultipleParents(const bool value)
Definition: cluster.cpp:623
bool allowsMultipleParents(void) const
Definition: cluster.cpp:618
virtual void addChildNode(unsigned index)
Mark a rectangle as being a child of this cluster.
Definition: cluster.cpp:448
A rectangle represents a fixed-size shape in the diagram that may be moved to prevent overlaps and sa...
Definition: rectangle.h:78
A cluster defines a hierarchical partitioning over the nodes which should be kept disjoint by the lay...
Definition: cluster.h:50
libcola: Force-directed network layout subject to separation constraints library. ...
Definition: box.cpp:25
Dim
Indicates the x- or y-dimension.
Definition: rectangle.h:41
Implements a constrained force-directed layout algorithm.
Definition: cola.h:622
Defines a cluster that will be treated as a convex boundary around the child nodes and clusters...
Definition: cluster.h:358
void setPadding(double padding)
Sets the padding size for this cluster.
Definition: cluster.cpp:277
std::vector< CompoundConstraint * > CompoundConstraints
A vector of pointers to CompoundConstraint objects.
Definition: compound_constraints.h:259
virtual void addChildNode(unsigned index)
Mark a rectangle as being a child of this cluster.
Definition: cluster.cpp:703