diff options
Diffstat (limited to 'include/2geom/interval.h')
-rw-r--r-- | include/2geom/interval.h | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/include/2geom/interval.h b/include/2geom/interval.h new file mode 100644 index 0000000..11c8f28 --- /dev/null +++ b/include/2geom/interval.h @@ -0,0 +1,245 @@ +/** + * \file + * \brief Simple closed interval class + *//* + * Copyright 2007 Michael Sloan <mgsloan@gmail.com> + * + * Original Rect/Range code by: + * Lauris Kaplinski <lauris@kaplinski.com> + * Nathan Hurst <njh@mail.csse.monash.edu.au> + * bulia byak <buliabyak@users.sf.net> + * MenTaLguY <mental@rydia.net> + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, output to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + */ +#ifndef LIB2GEOM_SEEN_INTERVAL_H +#define LIB2GEOM_SEEN_INTERVAL_H + +#include <boost/none.hpp> +#include <boost/operators.hpp> +#include <2geom/coord.h> +#include <2geom/math-utils.h> +#include <2geom/generic-interval.h> +#include <2geom/int-interval.h> + +namespace Geom { + +/** + * @brief Range of real numbers that is never empty. + * + * Intervals are closed ranges \f$[a, b]\f$, which means they include their endpoints. + * To use them as open ranges, you can use the interiorContains() methods. + * + * @ingroup Primitives + */ +class Interval + : public GenericInterval<Coord> +{ + typedef GenericInterval<Coord> Base; +public: + /// @name Create intervals. + /// @{ + /** @brief Create an interval that contains only zero. */ + Interval() {} + /** @brief Create an interval that contains a single point. */ + explicit Interval(Coord u) : Base(u) {} + /** @brief Create an interval that contains all points between @c u and @c v. */ + Interval(Coord u, Coord v) : Base(u,v) {} + /** @brief Convert from integer interval */ + Interval(IntInterval const &i) : Base(i.min(), i.max()) {} + Interval(Base const &b) : Base(b) {} + + /** @brief Create an interval containing a range of values. + * The resulting interval will contain all values from the given range. + * The return type of iterators must be convertible to Coord. The given range + * must not be empty. For potentially empty ranges, see OptInterval. + * @param start Beginning of the range + * @param end End of the range + * @return Interval that contains all values from [start, end). */ + template <typename InputIterator> + static Interval from_range(InputIterator start, InputIterator end) { + Interval result = Base::from_range(start, end); + return result; + } + /** @brief Create an interval from a C-style array of values it should contain. */ + static Interval from_array(Coord const *c, unsigned n) { + Interval result = from_range(c, c+n); + return result; + } + /// @} + + /// @name Inspect contained values. + /// @{ + /// Check whether both endpoints are finite. + bool isFinite() const { + return std::isfinite(min()) && std::isfinite(max()); + } + /** @brief Map the interval [0,1] onto this one. + * This method simply performs 1D linear interpolation between endpoints. */ + Coord valueAt(Coord t) const { + return lerp(t, min(), max()); + } + /** @brief Compute a time value that maps to the given value. + * The supplied value does not need to be in the interval for this method to work. */ + Coord timeAt(Coord v) const { + return (v - min()) / extent(); + } + /// Find closest time in [0,1] that maps to the given value. */ + Coord nearestTime(Coord v) const { + if (v <= min()) return 0; + if (v >= max()) return 1; + return timeAt(v); + } + /// @} + + /// @name Test coordinates and other intervals for inclusion. + /// @{ + /** @brief Check whether the interior of the interval includes this number. + * Interior means all numbers in the interval except its ends. */ + bool interiorContains(Coord val) const { return min() < val && val < max(); } + /** @brief Check whether the interior of the interval includes the given interval. + * Interior means all numbers in the interval except its ends. */ + bool interiorContains(Interval const &val) const { return min() < val.min() && val.max() < max(); } + /// Check whether the number is contained in the union of the interior and the lower boundary. + bool lowerContains(Coord val) const { return min() <= val && val < max(); } + /// Check whether the given interval is contained in the union of the interior and the lower boundary. + bool lowerContains(Interval const &val) const { return min() <= val.min() && val.max() < max(); } + /// Check whether the number is contained in the union of the interior and the upper boundary. + bool upperContains(Coord val) { return min() < val && val <= max(); } + /// Check whether the given interval is contained in the union of the interior and the upper boundary. + bool upperContains(Interval const &val) const { return min() < val.min() && val.max() <= max(); } + /** @brief Check whether the interiors of the intervals have any common elements. + * A single point in common is not considered an intersection. */ + bool interiorIntersects(Interval const &val) const { + return std::max(min(), val.min()) < std::min(max(), val.max()); + } + /// @} + + /// @name Operators + /// @{ + // IMPL: ScalableConcept + /** @brief Scale an interval */ + Interval &operator*=(Coord s) { + using std::swap; + _b[0] *= s; + _b[1] *= s; + if(s < 0) swap(_b[0], _b[1]); + return *this; + } + /** @brief Scale an interval by the inverse of the specified value */ + Interval &operator/=(Coord s) { + using std::swap; + _b[0] /= s; + _b[1] /= s; + if(s < 0) swap(_b[0], _b[1]); + return *this; + } + /** @brief Multiply two intervals. + * Product is defined as the set of points that can be obtained by multiplying + * any value from the second operand by any value from the first operand: + * \f$S = \{x \in A, y \in B: x * y\}\f$ */ + Interval &operator*=(Interval const &o) { + // TODO implement properly + Coord mn = min(), mx = max(); + expandTo(mn * o.min()); + expandTo(mn * o.max()); + expandTo(mx * o.min()); + expandTo(mx * o.max()); + return *this; + } + bool operator==(IntInterval const &ii) const { + return min() == Coord(ii.min()) && max() == Coord(ii.max()); + } + bool operator==(Interval const &other) const { + return Base::operator==(other); + } + /// @} + + /// @name Rounding to integer values + /// @{ + /** @brief Return the smallest integer interval which contains this one. */ + IntInterval roundOutwards() const { + IntInterval ret(floor(min()), ceil(max())); + return ret; + } + /** @brief Return the largest integer interval which is contained in this one. */ + OptIntInterval roundInwards() const { + IntCoord u = ceil(min()), v = floor(max()); + if (u > v) { OptIntInterval e; return e; } + IntInterval ret(u, v); + return ret; + } + /// @} +}; + +/** + * @brief Range of real numbers that can be empty. + * @ingroup Primitives + */ +class OptInterval + : public GenericOptInterval<Coord> +{ + typedef GenericOptInterval<Coord> Base; +public: + using Base::Base; + using Base::operator==; + using Base::operator!=; + + OptInterval(Base const &b) : Base(b) {} + + /** @brief Promote from IntInterval. */ + OptInterval(IntInterval const &i) : Base(Interval(i)) {} + /** @brief Promote from OptIntInterval. */ + OptInterval(OptIntInterval const &i) : Base() { + if (i) *this = Interval(*i); + } +}; + +// functions required for Python bindings +inline Interval unify(Interval const &a, Interval const &b) +{ + Interval r = a | b; + return r; +} +inline OptInterval intersect(Interval const &a, Interval const &b) +{ + OptInterval r = a & b; + return r; +} + +} // end namespace Geom + +#endif //SEEN_INTERVAL_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |