Adaptagrams
topology_constraints.h
1 /*
2  * vim: ts=4 sw=4 et tw=0 wm=0
3  *
4  * libtopology - Classes used in generating and managing topology constraints.
5  *
6  * Copyright (C) 2007-2010 Monash University
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  * See the file LICENSE.LGPL distributed with the library.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Author(s): Tim Dwyer
19 */
20 
21 /*
22  * Classes used in generating and managing topology constraints, i.e.
23  * constraints of the form (e.g.) \f$w_x + \frac{1}{2}\mathrm{width}(w) \le u_x
24  * + (v_x - u_x) \frac {(w_y-u_y)}{(v_y-u_y)}\f$ where (u,v) is an edge segment
25  * and w is a node constrained to lie to the left of that segment. Right-,
26  * above- and below-of constraints are similarly defined.
27  */
28 #ifndef TOPOLOGY_CONSTRAINTS_H
29 #define TOPOLOGY_CONSTRAINTS_H
30 #include "libcola/commondefs.h"
31 #include "libtopology/topology_graph.h"
32 #include <valarray>
33 #include <vector>
34 #include <map>
35 #include <list>
36 namespace vpsc {
37  class Constraint;
38  class Variable;
39  typedef std::vector<Constraint*> Constraints;
40  typedef std::vector<Variable*> Variables;
41 }
42 namespace cola {
43  struct SparseMap;
44  class RootCluster;
45 }
46 /*
47  * namespace for classes used in generating and solving forces and constraints
48  * associated with topology preserving layout.
49  */
50 namespace topology {
51  class StraightConstraint;
52  class Edge;
53  /*
54  * A constraint between three variables \f$u,v,w\f$ where \f$w\f$ is
55  * required to be to one side of the line between \f$u,v\f$. That is, e.g.
56  * if we require \f$w\f$ to be some minimum distance \f$g\f$ to the left of
57  * the parameterised distance \f$p\f$ along the line \f$(u,v)\f$ we have:
58  * \f[ w + g\le u + p*(v - u) \f] Right-of constraints are similar.
59  */
60  class TriConstraint {
61  public:
62  // A TriConstraint is associated with the positions of 3 nodes
63  const Node *u, *v, *w;
64  // p is the parameter for the constraint line, g is the offset constant
65  double p, g;
66  /*
67  * determines direction of inequality, w to the left of uv or to the
68  * right
69  */
70  bool leftOf;
71  vpsc::Dim scanDim;
72  TriConstraint(vpsc::Dim dim, const Node *u, const Node *v, const Node *w,
73  double p, double g, bool left);
74  /*
75  * @return the maximum move we can make along the line from initial to
76  * desired positions without violating this constraint
77  */
78  double maxSafeAlpha() const;
79  /*
80  * amount of slack at current positions of variables
81  */
82  double slackAtInitial() const;
83  /*
84  * amount of slack at desired positions of variables
85  */
86  double slackAtFinal() const;
87  /*
88  * checks initial positions
89  */
90  bool assertFeasible() const;
91  private:
92  double slack(const double, const double, const double) const;
93  };
94  class TopologyConstraint {
95  public:
96  TriConstraint* c;
97  vpsc::Dim scanDim;
98  /*
99  * depending on the type of constraint (i.e. whether it is a constraint
100  * between a segment and a node or between two segments) we either
101  * split the segment (creating a new bend EdgePoint) or merge
102  * the segment with its neighbour (removing an EdgePoint).
103  */
104  virtual void satisfy() = 0;
106  virtual std::string toString() const = 0;
107  virtual unsigned getEdgeID() const = 0;
108  virtual ~TopologyConstraint() {
109  delete c;
110  }
111  /*
112  * checks the underlying TriConstraint to ensure that it is feasible
113  * at the initial positions of its constituent variables. Note that
114  * these initial positions must be up-to-date before hand.
115  */
116  bool assertFeasible() const;
117  protected:
118  TopologyConstraint(vpsc::Dim dim) : c(nullptr), scanDim(dim) { }
119  };
120  /*
121  * A constraint around a bend point that becomes active when the bend
122  * goes straight
123  */
124  class BendConstraint : public TopologyConstraint {
125  public:
126  EdgePoint* bendPoint;
127  /*
128  * create a constraint between the two segments joined by this
129  * EdgePoint such that the constraint is activated when the segments
130  * are aligned.
131  * @param bendPoint the articulation point
132  */
133  BendConstraint(EdgePoint* bendPoint, vpsc::Dim dim);
134  void satisfy();
135  std::string toString() const;
136  unsigned getEdgeID() const;
137  };
138  /*
139  * A constraint between a Node and a Segment that is activated when
140  * the Node wants to move through the Segment to create a bend point
141  */
142  class StraightConstraint : public TopologyConstraint {
143  public:
144  Segment* segment;
145  Node* node;
146  EdgePoint::RectIntersect ri;
147  const double pos;
148  /*
149  * create a constraint between a segment and one corner of a node such
150  * that the constraint is activated when the segment needs to be bent
151  * (divided into two new segments)
152  * @param s the segment
153  * @param node the node
154  * @param ri the vertex of the node causing this constraint
155  * @param scanPos the position of the scan line along which the
156  * constraint lies
157  * @param segmentPos the ratio (s->start,scanPos)/(s->start,s->end)
158  */
159  StraightConstraint(Segment* s, vpsc::Dim dim,
160  Node* node, const EdgePoint::RectIntersect ri,
161  const double scanPos, const double segmentPos,
162  const bool nodeLeft);
163  void satisfy();
164  std::string toString() const;
165  unsigned getEdgeID() const {
166  return segment->edge->id;
167  }
168  };
169  /*
170  * Define a topology over a diagram by generating a set of
171  * TopologyConstraint
172  */
173  class TopologyConstraints {
174  public:
175  const size_t n;
176  /*
177  * @param dim HORIZONTAL or VERTICAL
178  * @param nodes topology nodes
179  * @param edges topology edges
180  * @param vs canonical list of variables to feed into constraint
181  * solver, this must include all the variables
182  * associated with nodes (ie. vs.size()>=nodes.size()) though they
183  * do not have to appear in the same order.
184  * @param cs constraints on variables, list will be appended with
185  * automatically generated non-overlap constraints
186  */
187  TopologyConstraints(
188  const vpsc::Dim dim,
189  Nodes& nodes,
190  Edges& edges,
191  cola::RootCluster* clusterHierarchy,
192  vpsc::Variables& vs,
193  vpsc::Constraints& cs);
194  ~TopologyConstraints();
195  bool solve();
196  void constraints(std::vector<TopologyConstraint*> & ts) const;
197  void computeForces(std::valarray<double>& g, cola::SparseMap& h);
198  bool assertFeasible() const;
199  void printInstance(std::valarray<double>& g) const;
200  bool noOverlaps() const;
201  private:
202  Nodes& nodes;
203  Edges& edges;
204  cola::RootCluster* clusters;
205  vpsc::Variables& vs;
206  vpsc::Constraints& cs;
207  vpsc::Dim dim;
208  };
209  /*
210  * The following just copies variables in ns into vs. May be useful
211  * in calling the TopologyConstraints constructor if you're not interested
212  * in constructing your own list of variables in advance.
213  * @param ns source list of nodes
214  * @param vs target list (we expect this to be 0 and resize to ns.size())
215  */
216  void getVariables(Nodes& ns, vpsc::Variables& vs);
217  /*
218  * Details new dimensions for a given rectangle.
219  */
220  struct ResizeInfo {
221  const Node* orig;
222  const vpsc::Rectangle* targetRect;
223  ResizeInfo(Node* v, const vpsc::Rectangle* target)
224  : orig(v),
225  targetRect(target),
226  lhsNode(nullptr),
227  rhsNode(nullptr) { };
228  Node *lhsNode, *rhsNode;
229  };
230  typedef std::map<unsigned, ResizeInfo> ResizeMap;
231  void applyResizes(Nodes& nodes, Edges& edges,
232  cola::RootCluster *clusters, ResizeMap& resizes,
235  /*
236  * compute the p-stress over a set of edge paths:
237  * \f[
238  * \sigma = \sum_{e \in E} \left( d_e - \sum_{s \in S(e)} |s| \right)^2
239  * \f]
240  */
241  double computeStress(const Edges& es);
242 } // namespace topology
243 #endif // TOPOLOGY_CONSTRAINTS_H
libtopology: Extensions for topology preservation for libcola and libavoid libraries.
Definition: shape.h:41
ProjectionResult solve(vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &rs, unsigned debugLevel=0)
Constructs a solver and attempts to solve the passed constraints on the passed vars.
std::pair< unsigned, unsigned > Edge
Edges are simply a pair of indices to entries in the Node vector.
Definition: cola.h:68
libvpsc: Variable Placement with Separation Constraints quadratic program solver library.
Definition: assertions.h:61
std::vector< Variable * > Variables
A vector of pointers to Variable objects.
Definition: constraint.h:38
std::vector< Constraint * > Constraints
A vector of pointers to Constraint objects.
Definition: constraint.h:125
Holds the cluster hierarchy specification for a diagram.
Definition: cluster.h:172
std::vector< Node * > Nodes
A vector of pointers to Node objects.
Definition: topology_graph.h:82
A rectangle represents a fixed-size shape in the diagram that may be moved to prevent overlaps and sa...
Definition: rectangle.h:78
std::vector< Edge * > Edges
A vector of pointers to Edge objects.
Definition: topology_graph.h:533
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