diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2016-03-14 16:37:50 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2016-03-14 16:37:50 +0000 |
| commit | b8d22beef5345210ad27cdc2685083aeae6f8f3b (patch) | |
| tree | d69b8bfd19d3627a8425a1b265c2abf229b05354 /src/2geom/pathvector.cpp | |
| parent | fixes for update to trunk (diff) | |
| parent | "Relative to" option for node alignment. (diff) | |
| download | inkscape-b8d22beef5345210ad27cdc2685083aeae6f8f3b.tar.gz inkscape-b8d22beef5345210ad27cdc2685083aeae6f8f3b.zip | |
update to trunk
(bzr r13708.1.39)
Diffstat (limited to 'src/2geom/pathvector.cpp')
| -rw-r--r-- | src/2geom/pathvector.cpp | 111 |
1 files changed, 101 insertions, 10 deletions
diff --git a/src/2geom/pathvector.cpp b/src/2geom/pathvector.cpp index bff201c71..28ab26237 100644 --- a/src/2geom/pathvector.cpp +++ b/src/2geom/pathvector.cpp @@ -35,6 +35,7 @@ #include <2geom/path.h> #include <2geom/pathvector.h> #include <2geom/svg-path-writer.h> +#include <2geom/sweeper.h> namespace Geom { @@ -133,19 +134,96 @@ void PathVector::snapEnds(Coord precision) } } -std::vector<PVIntersection> PathVector::intersect(PathVector const &other, Coord precision) const -{ - typedef PathVectorTime PVPos; - std::vector<PVIntersection> result; - for (std::size_t i = 0; i < size(); ++i) { - for (std::size_t j = 0; j < other.size(); ++j) { - std::vector<PathIntersection> xs = (*this)[i].intersect(other[j], precision); - for (std::size_t k = 0; k < xs.size(); ++k) { - PVIntersection pvx(PVPos(i, xs[k].first), PVPos(j, xs[k].second), xs[k].point()); - result.push_back(pvx); +// sweepline optimization +// this is very similar to CurveIntersectionSweepSet in path.cpp +// should probably be merged +class PathIntersectionSweepSet { +public: + struct PathRecord { + boost::intrusive::list_member_hook<> _hook; + Path const *path; + std::size_t index; + unsigned which; + + PathRecord(Path const &p, std::size_t i, unsigned w) + : path(&p) + , index(i) + , which(w) + {} + }; + + typedef std::vector<PathRecord>::iterator ItemIterator; + + PathIntersectionSweepSet(std::vector<PVIntersection> &result, + PathVector const &a, PathVector const &b, Coord precision) + : _result(result) + , _precision(precision) + { + _records.reserve(a.size() + b.size()); + for (std::size_t i = 0; i < a.size(); ++i) { + _records.push_back(PathRecord(a[i], i, 0)); + } + for (std::size_t i = 0; i < b.size(); ++i) { + _records.push_back(PathRecord(b[i], i, 1)); + } + } + + std::vector<PathRecord> &items() { return _records; } + + Interval itemBounds(ItemIterator ii) { + OptRect r = ii->path->boundsFast(); + return (*r)[X]; + } + + void addActiveItem(ItemIterator ii) { + unsigned w = ii->which; + unsigned ow = (ii->which + 1) % 2; + + for (ActivePathList::iterator i = _active[ow].begin(); i != _active[ow].end(); ++i) { + if (!ii->path->boundsFast().intersects(i->path->boundsFast())) continue; + std::vector<PathIntersection> px = ii->path->intersect(*i->path, _precision); + for (std::size_t k = 0; k < px.size(); ++k) { + PathVectorTime tw(ii->index, px[k].first), tow(i->index, px[k].second); + _result.push_back(PVIntersection( + w == 0 ? tw : tow, + w == 0 ? tow : tw, + px[k].point())); } } + _active[w].push_back(*ii); + } + + void removeActiveItem(ItemIterator ii) { + ActivePathList &apl = _active[ii->which]; + apl.erase(apl.iterator_to(*ii)); } + +private: + typedef boost::intrusive::list + < PathRecord + , boost::intrusive::member_hook + < PathRecord + , boost::intrusive::list_member_hook<> + , &PathRecord::_hook + > + > ActivePathList; + + std::vector<PVIntersection> &_result; + std::vector<PathRecord> _records; + ActivePathList _active[2]; + Coord _precision; +}; + +std::vector<PVIntersection> PathVector::intersect(PathVector const &other, Coord precision) const +{ + std::vector<PVIntersection> result; + + PathIntersectionSweepSet pisset(result, *this, other, precision); + Sweeper<PathIntersectionSweepSet> sweeper(pisset); + sweeper.process(); + + std::sort(result.begin(), result.end()); + return result; } @@ -153,6 +231,7 @@ int PathVector::winding(Point const &p) const { int wind = 0; for (const_iterator i = begin(); i != end(); ++i) { + if (!i->boundsFast().contains(p)) continue; wind += i->winding(p); } return wind; @@ -201,6 +280,18 @@ std::vector<PathVectorTime> PathVector::allNearestTimes(Point const &p, Coord *d return retval; } +std::vector<Point> PathVector::nodes() const +{ + std::vector<Point> result; + for (size_type i = 0; i < size(); ++i) { + size_type path_size = (*this)[i].size_closed(); + for (size_type j = 0; j < path_size; ++j) { + result.push_back((*this)[i][j].initialPoint()); + } + } + return result; +} + PathVectorTime PathVector::_factorTime(Coord t) const { PathVectorTime ret; |
