summaryrefslogtreecommitdiffstats
path: root/src/2geom/pathvector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/2geom/pathvector.cpp')
-rw-r--r--src/2geom/pathvector.cpp214
1 files changed, 145 insertions, 69 deletions
diff --git a/src/2geom/pathvector.cpp b/src/2geom/pathvector.cpp
index fc0ad75c4..36364de9b 100644
--- a/src/2geom/pathvector.cpp
+++ b/src/2geom/pathvector.cpp
@@ -1,12 +1,11 @@
-/*
- * PathVector - std::vector containing Geom::Path
- * This file provides a set of operations that can be performed on PathVector,
- * e.g. an affine transform.
- *
+/** @file
+ * @brief PathVector - a sequence of subpaths
+ *//*
* Authors:
- * Johan Engelen <goejendaagh@zonnet.nl>
+ * Johan Engelen <goejendaagh@zonnet.nl>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
*
- * Copyright 2008 authors
+ * Copyright 2008-2014 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,9 +31,6 @@
* the specific language governing rights and limitations.
*/
-#ifndef SEEN_GEOM_PATHVECTOR_CPP
-#define SEEN_GEOM_PATHVECTOR_CPP
-
#include <2geom/pathvector.h>
#include <2geom/path.h>
@@ -42,104 +38,184 @@
namespace Geom {
-// TODO: see which of these functions can be inlined for optimization
+//PathVector &PathVector::operator+=(PathVector const &other);
+
+PathVector::size_type PathVector::curveCount() const
+{
+ size_type n = 0;
+ for (const_iterator it = begin(); it != end(); ++it) {
+ n += it->size_default();
+ }
+ return n;
+}
+
+void PathVector::reverse(bool reverse_paths)
+{
+ if (reverse_paths) {
+ std::reverse(begin(), end());
+ }
+ for (iterator i = begin(); i != end(); ++i) {
+ *i = i->reversed();
+ }
+}
-/**
- * Reverses all Paths and the order of paths in the vector as well
- **/
-PathVector reverse_paths_and_order (PathVector const & path_in)
+PathVector PathVector::reversed(bool reverse_paths) const
{
- PathVector path_out;
- for (PathVector::const_reverse_iterator it = path_in.rbegin(); it != path_in.rend(); ++it) {
- path_out.push_back( (*it).reverse() );
+ PathVector ret;
+ for (const_iterator i = begin(); i != end(); ++i) {
+ ret.push_back(i->reversed());
+ }
+ if (reverse_paths) {
+ std::reverse(ret.begin(), ret.end());
}
- return path_out;
+ return ret;
}
-OptRect bounds_fast( PathVector const& pv )
+Path &PathVector::pathAt(Coord t, Coord *rest)
+{
+ return const_cast<Path &>(static_cast<PathVector const*>(this)->pathAt(t, rest));
+}
+Path const &PathVector::pathAt(Coord t, Coord *rest) const
+{
+ Position pos = _getPosition(t);
+ if (rest) {
+ *rest = Coord(pos.curve_index) + pos.t;
+ }
+ return at(pos.path_index);
+}
+Curve const &PathVector::curveAt(Coord t, Coord *rest) const
+{
+ Position pos = _getPosition(t);
+ if (rest) {
+ *rest = pos.t;
+ }
+ return at(pos.path_index).at(pos.curve_index);
+}
+Coord PathVector::valueAt(Coord t, Dim2 d) const
+{
+ Position pos = _getPosition(t);
+ return at(pos.path_index).at(pos.curve_index).valueAt(pos.t, d);
+}
+Point PathVector::pointAt(Coord t) const
+{
+ Position pos = _getPosition(t);
+ return at(pos.path_index).at(pos.curve_index).pointAt(pos.t);
+}
+
+OptRect PathVector::boundsFast() const
{
- typedef PathVector::const_iterator const_iterator;
-
OptRect bound;
- if (pv.empty()) return bound;
-
- bound = (pv.begin())->boundsFast();
- for (const_iterator it = ++(pv.begin()); it != pv.end(); ++it)
- {
+ if (empty()) return bound;
+
+ bound = front().boundsFast();
+ for (const_iterator it = ++begin(); it != end(); ++it) {
bound.unionWith(it->boundsFast());
}
return bound;
}
-OptRect bounds_exact( PathVector const& pv )
+OptRect PathVector::boundsExact() const
{
- typedef PathVector::const_iterator const_iterator;
-
OptRect bound;
- if (pv.empty()) return bound;
-
- bound = (pv.begin())->boundsExact();
- for (const_iterator it = ++(pv.begin()); it != pv.end(); ++it)
- {
+ if (empty()) return bound;
+
+ bound = front().boundsExact();
+ for (const_iterator it = ++begin(); it != end(); ++it) {
bound.unionWith(it->boundsExact());
}
return bound;
}
-/* Note: undefined for empty pathvectors or pathvectors with empty paths.
- * */
-boost::optional<PathVectorPosition> nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared)
+std::vector<PVIntersection> PathVector::intersect(PathVector const &other, Coord precision) const
{
- boost::optional<PathVectorPosition> retval;
-
- double mindsq = infinity();
- unsigned int i = 0;
- for (Geom::PathVector::const_iterator pit = path_in.begin(); pit != path_in.end(); ++pit) {
- double dsq;
- double t = pit->nearestPoint(_point, &dsq);
- //std::cout << t << "," << dsq << std::endl;
- if (dsq < mindsq) {
- mindsq = dsq;
- retval = PathVectorPosition(i, t);
+ typedef PathVectorPosition 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]);
+ 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);
+ }
}
+ }
+ return result;
+}
- ++i;
+int PathVector::winding(Point const &p) const
+{
+ int wind = 0;
+ for (const_iterator i = begin(); i != end(); ++i) {
+ wind += i->winding(p);
}
+ return wind;
+}
- if (distance_squared) {
- *distance_squared = mindsq;
+boost::optional<PathVectorPosition> PathVector::nearestPosition(Point const &p, Coord *dist) const
+{
+ boost::optional<Position> retval;
+
+ Coord mindist = infinity();
+ for (size_type i = 0; i < size(); ++i) {
+ Coord d;
+ PathPosition pos = (*this)[i].nearestPosition(p, &d);
+ if (d < mindist) {
+ mindist = d;
+ retval = Position(i, pos.curve_index, pos.t);
+ }
+ }
+
+ if (dist) {
+ *dist = mindist;
}
return retval;
}
-std::vector<PathVectorPosition> allNearestPoints(PathVector const & path_in, Point const& _point, double *distance_squared)
+std::vector<PathVectorPosition> PathVector::allNearestPositions(Point const &p, Coord *dist) const
{
- std::vector<PathVectorPosition> retval;
-
- double mindsq = infinity();
- unsigned int i = 0;
- for (Geom::PathVector::const_iterator pit = path_in.begin(); pit != path_in.end(); ++pit) {
- double dsq;
- double t = pit->nearestPoint(_point, &dsq);
- if (dsq < mindsq) {
- mindsq = dsq;
- retval.push_back(PathVectorPosition(i, t));
+ std::vector<Position> retval;
+
+ Coord mindist = infinity();
+ for (size_type i = 0; i < size(); ++i) {
+ Coord d;
+ PathPosition pos = (*this)[i].nearestPosition(p, &d);
+ if (d < mindist) {
+ mindist = d;
+ retval.clear();
+ }
+ if (d <= mindist) {
+ retval.push_back(Position(i, pos.curve_index, pos.t));
}
-
- ++i;
}
- if (distance_squared) {
- *distance_squared = mindsq;
+ if (dist) {
+ *dist = mindist;
}
return retval;
+}
+PathVectorPosition PathVector::_getPosition(Coord t) const
+{
+ Position ret;
+ Coord rest = 0;
+ ret.t = modf(t, &rest);
+ ret.curve_index = rest;
+ for (; ret.path_index < size(); ++ret.path_index) {
+ unsigned s = _data.at(ret.path_index).size_default();
+ if (s > ret.curve_index) break;
+ // special case for the last point
+ if (s == ret.curve_index && ret.path_index + 1 == size()) {
+ --ret.curve_index;
+ ret.t = 1;
+ break;
+ }
+ ret.curve_index -= s;
+ }
+ return ret;
}
} // namespace Geom
-#endif // SEEN_GEOM_PATHVECTOR_CPP
-
/*
Local Variables:
mode:c++