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