Code

moving trunk for module inkscape
[inkscape.git] / src / removeoverlap / removeoverlap.cpp
1 /** \file
2  * Interface between Inkscape code (SPItem) and remove-overlaps function.
3  */
4 /*
5 * Authors:
6 *   Tim Dwyer <tgdwyer@gmail.com>
7 *
8 * Copyright (C) 2005 Authors
9 *
10 * Released under GNU GPL.  Read the file 'COPYING' for more information.
11 */
12 #include "util/glib-list-iterators.h"
13 #include "sp-item.h"
14 #include "sp-item-transform.h"
15 #include "removeoverlap/generate-constraints.h"
16 #include "removeoverlap/remove_rectangle_overlap.h"
18 /**
19 * Takes a list of inkscape items and moves them as little as possible
20 * such that rectangular bounding boxes are separated by at least xGap
21 * horizontally and yGap vertically
22 */
23 void removeoverlap(GSList const *const items, double const xGap, double const yGap) {
24         if(!items) {
25                 return;
26         }
28         using Inkscape::Util::GSListConstIterator;
29         std::list<SPItem *> selected;
30         selected.insert<GSListConstIterator<SPItem *> >(selected.end(), items, NULL);
31         if (selected.empty()) return;
32         int n=selected.size();
34         //Check 2 or more selected objects
35         if (n < 2) return;
37         Rectangle **rs = new Rectangle*[n];
38         int i=0;
40         NR::Point const gap(xGap, yGap);
41         for (std::list<SPItem *>::iterator it(selected.begin());
42                 it != selected.end();
43                 ++it)
44         {
45                 using NR::X; using NR::Y;
46                 NR::Rect const item_box(sp_item_bbox_desktop(*it));
47                 
48                 /* The current algorithm requires widths & heights to be strictly positive. */
49                 NR::Point min(item_box.min());
50                 NR::Point max(item_box.max());
51                 for (unsigned d = 0; d < 2; ++d) {
52                         double const minsize = 1; // arbitrary positive number
53                         if (max[d] - min[d] + gap[d] < minsize) {
54                                 double const mid = .5 * (min[d] + max[d]);
55                                 min[d] = mid - .5*minsize;
56                                 max[d] = mid + .5*minsize;
57                         } else {
58                                 min[d] -= .5*gap[d];
59                                 max[d] += .5*gap[d];
60                         }
61                 }
62                 rs[i++] = new Rectangle(min[X], max[X],
63                                         min[Y], max[Y]);
64         }
65         removeRectangleOverlap(rs, n, 0.0, 0.0);
66         i=0;
67         for (std::list<SPItem *>::iterator it(selected.begin());
68                 it != selected.end();
69                 ++it)
70         {
71                 NR::Rect const item_box(sp_item_bbox_desktop(*it));
72                 Rectangle *r = rs[i++];
73                 NR::Point const curr(item_box.midpoint());
74                 NR::Point const dest(r->getCentreX(),
75                                      r->getCentreY());
76                 sp_item_move_rel(*it, NR::translate(dest - curr));
77                 delete r;
78         }
79         delete [] rs;
80 }