Code

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