c640fb407ad308185562dcd1074715a6e55b60b7
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));
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 }