Code

c640fb407ad308185562dcd1074715a6e55b60b7
[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 LGPL.  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 "libvpsc/generate-constraints.h"
16 #include "libvpsc/remove_rectangle_overlap.h"
18 using vpsc::Rectangle;
20 /**
21 * Takes a list of inkscape items and moves them as little as possible
22 * such that rectangular bounding boxes are separated by at least xGap
23 * horizontally and yGap vertically
24 */
25 void removeoverlap(GSList const *const items, double const xGap, double const yGap) {
26         if(!items) {
27                 return;
28         }
30         using Inkscape::Util::GSListConstIterator;
31         std::list<SPItem *> selected;
32         selected.insert<GSListConstIterator<SPItem *> >(selected.end(), items, NULL);
33         if (selected.empty()) return;
34         int n=selected.size();
36         //Check 2 or more selected objects
37         if (n < 2) return;
39         Rectangle **rs = new Rectangle*[n];
40         int i=0;
42         NR::Point const gap(xGap, yGap);
43         for (std::list<SPItem *>::iterator it(selected.begin());
44                 it != selected.end();
45                 ++it)
46         {
47                 using NR::X; using NR::Y;
48                 NR::Rect const item_box(sp_item_bbox_desktop(*it));
49                 
50                 /* The current algorithm requires widths & heights to be strictly positive. */
51                 NR::Point min(item_box.min());
52                 NR::Point max(item_box.max());
53                 for (unsigned d = 0; d < 2; ++d) {
54                         double const minsize = 1; // arbitrary positive number
55                         if (max[d] - min[d] + gap[d] < minsize) {
56                                 double const mid = .5 * (min[d] + max[d]);
57                                 min[d] = mid - .5*minsize;
58                                 max[d] = mid + .5*minsize;
59                         } else {
60                                 min[d] -= .5*gap[d];
61                                 max[d] += .5*gap[d];
62                         }
63                 }
64                 rs[i++] = new Rectangle(min[X], max[X],
65                                         min[Y], max[Y]);
66         }
67         removeRectangleOverlap(n, rs, 0.0, 0.0);
68         i=0;
69         for (std::list<SPItem *>::iterator it(selected.begin());
70                 it != selected.end();
71                 ++it)
72         {
73                 NR::Rect const item_box(sp_item_bbox_desktop(*it));
74                 Rectangle *r = rs[i++];
75                 NR::Point const curr(item_box.midpoint());
76                 NR::Point const dest(r->getCentreX(),
77                                      r->getCentreY());
78                 sp_item_move_rel(*it, NR::translate(dest - curr));
79                 delete r;
80         }
81         delete [] rs;
82 }