1 #include <iostream>
2 #include <cassert>
3 #include "generate-constraints.h"
4 #include "solve_VPSC.h"
5 #include "variable.h"
6 #include "constraint.h"
7 #ifdef RECTANGLE_OVERLAP_LOGGING
8 #include <fstream>
9 #include "blocks.h"
10 using std::ios;
11 using std::ofstream;
12 using std::endl;
13 #endif
15 #define EXTRA_GAP 0.0001
17 double Rectangle::xBorder=0;
18 double Rectangle::yBorder=0;
19 /**
20 * Takes an array of n rectangles and moves them as little as possible
21 * such that rectangles are separated by at least xBorder horizontally
22 * and yBorder vertically
23 *
24 * Works in three passes:
25 * 1) removes some overlap horizontally
26 * 2) removes remaining overlap vertically
27 * 3) a last horizontal pass removes all overlap starting from original
28 * x-positions - this corrects the case where rectangles were moved
29 * too much in the first pass.
30 */
31 void removeRectangleOverlap(Rectangle *rs[], int n, double xBorder, double yBorder) {
32 assert(0 <= n);
33 try {
34 // The extra gap avoids numerical imprecision problems
35 Rectangle::setXBorder(xBorder+EXTRA_GAP);
36 Rectangle::setYBorder(yBorder+EXTRA_GAP);
37 double *ws=new double[n];
38 for(int i=0;i<n;i++) {
39 ws[i]=1;
40 }
41 Variable **vs;
42 Constraint **cs;
43 double *oldX = new double[n];
44 int m=generateXConstraints(rs,ws,n,vs,cs,true);
45 for(int i=0;i<n;i++) {
46 oldX[i]=vs[i]->desiredPosition;
47 }
48 VPSC vpsc_x(vs,n,cs,m);
49 #ifdef RECTANGLE_OVERLAP_LOGGING
50 ofstream f(LOGFILE,ios::app);
51 f<<"Calling VPSC: Horizontal pass 1"<<endl;
52 f.close();
53 #endif
54 vpsc_x.solve();
55 for(int i=0;i<n;i++) {
56 rs[i]->moveCentreX(vs[i]->position());
57 delete vs[i];
58 }
59 delete [] vs;
60 for(int i = 0; i < m; ++i) {
61 delete cs[i];
62 }
63 delete [] cs;
64 // Removing the extra gap here ensures things that were moved to be adjacent to
65 // one another above are not considered overlapping
66 Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP);
67 m=generateYConstraints(rs,ws,n,vs,cs);
68 VPSC vpsc_y(vs,n,cs,m);
69 #ifdef RECTANGLE_OVERLAP_LOGGING
70 f.open(LOGFILE,ios::app);
71 f<<"Calling VPSC: Vertical pass"<<endl;
72 f.close();
73 #endif
74 vpsc_y.solve();
75 for(int i=0;i<n;i++) {
76 rs[i]->moveCentreY(vs[i]->position());
77 rs[i]->moveCentreX(oldX[i]);
78 delete vs[i];
79 }
80 delete [] vs;
81 delete [] oldX;
82 for(int i = 0; i < m; ++i) {
83 delete cs[i];
84 }
85 delete [] cs;
86 Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP);
87 m=generateXConstraints(rs,ws,n,vs,cs,false);
88 VPSC vpsc_x2(vs,n,cs,m);
89 #ifdef RECTANGLE_OVERLAP_LOGGING
90 f.open(LOGFILE,ios::app);
91 f<<"Calling VPSC: Horizontal pass 2"<<endl;
92 f.close();
93 #endif
94 vpsc_x2.solve();
95 for(int i=0;i<n;i++) {
96 rs[i]->moveCentreX(vs[i]->position());
97 delete vs[i];
98 }
99 delete [] vs;
100 for(int i = 0; i < m; ++i) {
101 delete cs[i];
102 }
103 delete [] cs;
104 delete [] ws;
105 } catch (char *str) {
106 std::cerr<<str<<std::endl;
107 for(int i=0;i<n;i++) {
108 std::cerr << *rs[i]<<std::endl;
109 }
110 }
111 }