Code

30dbbaf9eda76e775062a718e3856fc2a53f46df
[inkscape.git] / src / removeoverlap / remove_rectangle_overlap.cpp
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         }