Code

(no commit message)
[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 #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         }