diff options
| author | Ted Gould <ted@gould.cx> | 2010-03-26 04:34:25 +0000 |
|---|---|---|
| committer | Ted Gould <ted@gould.cx> | 2010-03-26 04:34:25 +0000 |
| commit | 9e023a3aa964a0d3fa1e31e46d33657367ba68aa (patch) | |
| tree | 33f1392a340737e4eeefca6fd031f96c29befd2b /src/removeoverlap.cpp | |
| parent | Installing the pkgconfig file (diff) | |
| parent | Adding in shape-record.h (diff) | |
| download | inkscape-9e023a3aa964a0d3fa1e31e46d33657367ba68aa.tar.gz inkscape-9e023a3aa964a0d3fa1e31e46d33657367ba68aa.zip | |
Merge from trunk
(bzr r8254.1.53)
Diffstat (limited to 'src/removeoverlap.cpp')
| -rw-r--r-- | src/removeoverlap.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/removeoverlap.cpp b/src/removeoverlap.cpp new file mode 100644 index 000000000..975b4becb --- /dev/null +++ b/src/removeoverlap.cpp @@ -0,0 +1,84 @@ +/** \file + * Interface between Inkscape code (SPItem) and remove-overlaps function. + */ +/* +* Authors: +* Tim Dwyer <tgdwyer@gmail.com> +* +* Copyright (C) 2005 Authors +* +* Released under GNU LGPL. Read the file 'COPYING' for more information. +*/ +#include "util/glib-list-iterators.h" +#include "sp-item.h" +#include "sp-item-transform.h" +#include "libvpsc/generate-constraints.h" +#include "libvpsc/remove_rectangle_overlap.h" +#include <utility> + +using vpsc::Rectangle; + +namespace { + struct Record { + SPItem *item; + Geom::Point midpoint; + Rectangle *vspc_rect; + + Record() {} + Record(SPItem *i, Geom::Point m, Rectangle *r) + : item(i), midpoint(m), vspc_rect(r) {} + }; +} + +/** +* Takes a list of inkscape items and moves them as little as possible +* such that rectangular bounding boxes are separated by at least xGap +* horizontally and yGap vertically +*/ +void removeoverlap(GSList const *const items, double const xGap, double const yGap) { + using Inkscape::Util::GSListConstIterator; + std::list<SPItem *> selected; + selected.insert<GSListConstIterator<SPItem *> >(selected.end(), items, NULL); + std::vector<Record> records; + std::vector<Rectangle *> rs; + + Geom::Point const gap(xGap, yGap); + for (std::list<SPItem *>::iterator it(selected.begin()); + it != selected.end(); + ++it) + { + using Geom::X; using Geom::Y; + Geom::OptRect item_box(sp_item_bbox_desktop(*it)); + if (item_box) { + Geom::Point min(item_box->min() - .5*gap); + Geom::Point max(item_box->max() + .5*gap); + // A negative gap is allowed, but will lead to problems when the gap is larger than + // the bounding box (in either X or Y direction, or both); min will have become max + // now, which cannot be handled by Rectangle() which is called below. And how will + // removeRectangleOverlap handle such a case? + // That's why we will enforce some boundaries on min and max here: + if (max[X] < min[X]) { + min[X] = max[X] = (min[X] + max[X])/2; + } + if (max[Y] < min[Y]) { + min[Y] = max[Y] = (min[Y] + max[Y])/2; + } + Rectangle *vspc_rect = new Rectangle(min[X], max[X], min[Y], max[Y]); + records.push_back(Record(*it, item_box->midpoint(), vspc_rect)); + rs.push_back(vspc_rect); + } + } + if (!rs.empty()) { + removeRectangleOverlap(rs.size(), &rs[0], 0.0, 0.0); + } + for ( std::vector<Record>::iterator it = records.begin(); + it != records.end(); + ++it ) + { + Geom::Point const curr = it->midpoint; + Geom::Point const dest(it->vspc_rect->getCentreX(), + it->vspc_rect->getCentreY()); + sp_item_move_rel(it->item, Geom::Translate(dest - curr)); + delete it->vspc_rect; + } +} |
