Adaptagrams
rectangle.h
1 /*
2  * vim: ts=4 sw=4 et tw=0 wm=0
3  *
4  * libvpsc - A solver for the problem of Variable Placement with
5  * Separation Constraints.
6  *
7  * Copyright (C) 2005-2010 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 */
21 
22 /*
23  * Functions to automatically generate constraints for the
24  * rectangular node overlap removal problem.
25  *
26  */
27 #ifndef VPSC_RECTANGLE_H
28 #define VPSC_RECTANGLE_H
29 
30 #include <iostream>
31 #include <vector>
32 #include <set>
33 #include <cassert>
34 #include <cmath>
35 
36 #include "libvpsc/assertions.h"
37 
38 namespace vpsc {
39 
41 enum Dim {
45  XDIM = 0,
47  VERTICAL = 1,
49  YDIM = 1,
50  // The dimension is not set.
51  UNSET = 2
52 };
53 
54 inline Dim conjugate(Dim d) {
55  return static_cast<Dim>(!d);
56 }
57 /* records the positions and sides through which a particular line intersects with a rectangle
58  */
59 struct RectangleIntersections {
60  bool intersects, top, bottom, left, right;
61  double topX, topY, bottomX, bottomY, leftX, leftY, rightX, rightY;
62  RectangleIntersections()
63  : intersects(false),top(false),bottom(false),left(false),right(false),
64  topX(0),topY(0),bottomX(0),bottomY(0),leftX(0),leftY(0),rightX(0),rightY(0) {}
65  int countIntersections() {
66  return left+right+top+bottom;
67  }
68  void printIntersections(void);
69  // Of the stored intersections, this returns the one closest to the
70  // specified point
71  void nearest(double x, double y, double & xi, double & yi);
72 };
73 
78 class Rectangle {
79 public:
90  Rectangle(double x, double X, double y, double Y,
91  bool allowOverlap = false);
92  Rectangle(Rectangle const &Other)
93  : minX(Other.minX)
94  , maxX(Other.maxX)
95  , minY(Other.minY)
96  , maxY(Other.maxY)
97  , overlap(Other.overlap) { }
98  Rectangle();
99  bool isValid(void) const;
100  Rectangle unionWith(const Rectangle& rhs) const;
101  /*
102  * reset the dimensions in one axis
103  * @param d axis (0==X, 1==Y)
104  * @param x min value
105  * @param X max value
106  */
107  void reset(const unsigned d, double x, double X);
108  double getMaxX() const { return maxX+xBorder; }
109  double getMaxY() const { return maxY+yBorder; }
110  double getMinX() const { return minX-xBorder; }
111  double getMinY() const { return minY-yBorder; }
112  /*
113  * @param d axis: 0=horizontal 1=vertical
114  */
115  double getMinD(unsigned const d) const {
116  COLA_ASSERT(d==0||d==1);
117  return ( d == 0 ? getMinX() : getMinY() );
118  }
119  /*
120  * @param d axis: 0=horizontal 1=vertical
121  */
122  double getMaxD(unsigned const d) const {
123  COLA_ASSERT(d==0||d==1);
124  return ( d == 0 ? getMaxX() : getMaxY() );
125  }
126  void setMinD(unsigned const d, const double val)
127  { if ( d == 0) { minX = val; } else { minY = val; } }
128  void setMaxD(unsigned const d, const double val)
129  { if ( d == 0) { maxX = val; } else { maxY = val; } }
130  double getCentreX() const { return getMinX()+width()/2.0; }
131  double getCentreY() const { return getMinY()+height()/2.0; }
132  /*
133  * @param d axis: 0=horizontal 1=vertical
134  */
135  double getCentreD(unsigned const d) const {
136  COLA_ASSERT(d==0||d==1);
137  return getMinD(d)+length(d)/2.0;
138  }
139  double width() const { return getMaxX()-getMinX(); }
140  double height() const { return getMaxY()-getMinY(); }
141  /*
142  * @param d axis: 0=width 1=height
143  * @return width or height
144  */
145  double length(unsigned const d) const {
146  COLA_ASSERT(d==0||d==1);
147  return ( d == 0 ? width() : height() );
148  }
149  void set_width(double w) { maxX = minX + w - 2.0*xBorder; }
150  void set_height(double h) { maxY = minY + h - 2.0*yBorder; }
151  void moveCentreD(const unsigned d, double p) {
152  COLA_ASSERT(d==0||d==1);
153  if(d == 0) { moveCentreX(p);
154  } else { moveCentreY(p); }
155  }
156  void moveCentreX(double x) {
157  moveMinX(x-width()/2.0);
158  }
159  void moveCentreY(double y) {
160  moveMinY(y-height()/2.0);
161  }
162  void moveCentre(double x, double y) {
163  moveCentreX(x);
164  moveCentreY(y);
165  }
166  void moveMinX(double x) {
167  double w=width();
168  minX=x+xBorder;
169  maxX=x+w-xBorder;
170  COLA_ASSERT(fabs(width()-w)<1e-9);
171  }
172  void moveMinY(double y) {
173  double h=height();
174  maxY=y+h-yBorder;
175  minY=y+yBorder;
176  COLA_ASSERT(fabs(height()-h)<1e-9);
177  }
178  double overlapD(const unsigned d, Rectangle* r) {
179  if(d==0) {
180  return overlapX(r);
181  } else {
182  return overlapY(r);
183  }
184  }
185  double overlapX(Rectangle *r) const {
186  double ux=getCentreX(), vx=r->getCentreX();
187  if (ux <= vx && r->getMinX() < getMaxX())
188  return getMaxX() - r->getMinX();
189  if (vx <= ux && getMinX() < r->getMaxX())
190  return r->getMaxX() - getMinX();
191  return 0;
192  }
193  double overlapY(Rectangle *r) const {
194  double uy=getCentreY(), vy=r->getCentreY();
195  if (uy <= vy && r->getMinY() < getMaxY()) {
196  return getMaxY() - r->getMinY();
197  }
198  if (vy <= uy && getMinY() < r->getMaxY()) {
199  return r->getMaxY() - getMinY();
200  }
201  return 0;
202  }
203  bool allowOverlap() {
204  return overlap;
205  }
206  void offset(double dx, double dy) {
207  minX += dx;
208  maxX += dx;
209  minY += dy;
210  maxY += dy;
211  }
212  // returns the intersections between the line segment from (x1,y1)
213  // to (x2,y2) and this rectangle. Any intersections points with
214  // sides are reported, lines coincident with a side are considered not
215  // to intersect.
216  void lineIntersections(double x1, double y1, double x2, double y2, RectangleIntersections &ri) const;
217  bool inside(double x, double y) const {
218  return x>getMinX() && x<getMaxX() && y>getMinY() && y<getMaxY();
219  }
220  // checks if line segment is strictly overlapping.
221  // That is, if any point on the line is inside the rectangle.
222  bool overlaps(double x1, double y1, double x2, double y2);
223  // p1=(x1,y1),p2=(x2,y2) are points on the boundary. Puts the shortest
224  // path round the outside of the rectangle from p1 to p2 into xs, ys.
225  void routeAround(double x1, double y1, double x2, double y2,
226  std::vector<double> &xs, std::vector<double> &ys);
227  /*
228  * xBorder and yBorder can be set to add a border to the boundary of the
229  * rectangle. In other words, the size of the rectangle returned by the
230  * getters (getMinX, getMaxX, etc) will be slightly larger than the
231  * internal representation. This is useful in situations where we need the
232  * size considered in one axis to be slightly different to that considered
233  * in the other axis for example, to avoid numerical precision problems in
234  * the axis-by-axis overlap removal process.
235  */
236  static double xBorder,yBorder;
237  static void setXBorder(double x) {xBorder=x;}
238  static void setYBorder(double y) {yBorder=y;}
239 
240 private:
241  double minX,maxX,minY,maxY;
242  bool overlap;
243 };
244 
246 typedef std::vector<Rectangle*> Rectangles;
247 
248 std::ostream& operator<<(std::ostream& os, vpsc::Rectangle const &r);
249 
250 class Variable;
251 typedef std::vector<Variable *> Variables;
252 class Constraint;
253 typedef std::vector<Constraint *> Constraints;
254 
255 void generateXConstraints(const Rectangles& rs, const Variables& vars,
256  Constraints& cs, const bool useNeighbourLists);
257 void generateYConstraints(const Rectangles& rs, const Variables& vars,
258  Constraints& cs);
259 
268 void removeoverlaps(Rectangles& rs);
269 
289 void removeoverlaps(Rectangles& rs, const std::set<unsigned>& fixed,
290  bool thirdPass = true);
291 
292 // Useful for assertions:
293 bool noRectangleOverlaps(const Rectangles& rs);
294 
295 struct delete_object
296 {
297  template <typename T>
298  void operator()(T *ptr){ delete ptr;}
299 };
300 
301 } // namespace vpsc
302 #endif // VPSC_RECTANGLE_H
A variable is comprised of an ideal position, final position and a weight.
Definition: variable.h:44
The x-dimension (0).
Definition: rectangle.h:45
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
std::vector< Rectangle * > Rectangles
A vector of pointers to Rectangle objects.
Definition: rectangle.h:246
A constraint determines a minimum or exact spacing required between two Variable objects.
Definition: constraint.h:44
void removeoverlaps(Rectangles &rs)
Uses VPSC to remove overlaps between rectangles.
Definition: rectangle.cpp:563
A rectangle represents a fixed-size shape in the diagram that may be moved to prevent overlaps and sa...
Definition: rectangle.h:78
The y-dimension (1).
Definition: rectangle.h:47
The x-dimension (0).
Definition: rectangle.h:43
Dim
Indicates the x- or y-dimension.
Definition: rectangle.h:41
The y-dimension (1).
Definition: rectangle.h:49